mirror of https://github.com/proski/madwifi
Tidy RX queue processing code:
* Formatting * Add a function to remove SKB from ath_buf. * Call aforementioned function early if we are accepting a frame, so that there's not chance the data can get stomped on by DMA. We should probably do this for ignored frames as well, but I got fed up trying to sort out the stack of goto. * Remove some KASSERT for skb users, as the SKB are always copied. git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@3594 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
parent
2ecfeab07e
commit
1b318d3853
219
ath/if_ath.c
219
ath/if_ath.c
|
@ -180,6 +180,7 @@ static void ath_node_free(struct ieee80211_node *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static u_int8_t ath_node_getrssi(const struct ieee80211_node *);
|
static u_int8_t ath_node_getrssi(const struct ieee80211_node *);
|
||||||
|
static struct sk_buff *ath_rxbuf_take_skb(struct ath_softc *, struct ath_buf *);
|
||||||
static int ath_rxbuf_init(struct ath_softc *, struct ath_buf *);
|
static int ath_rxbuf_init(struct ath_softc *, struct ath_buf *);
|
||||||
static void ath_recv_mgmt(struct ieee80211vap *, struct ieee80211_node *,
|
static void ath_recv_mgmt(struct ieee80211vap *, struct ieee80211_node *,
|
||||||
struct sk_buff *, int, int, u_int64_t);
|
struct sk_buff *, int, int, u_int64_t);
|
||||||
|
@ -6334,22 +6335,34 @@ ath_alloc_skb(u_int size, u_int align)
|
||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct sk_buff *
|
||||||
|
ath_rxbuf_take_skb(struct ath_softc *sc, struct ath_buf *bf) {
|
||||||
|
struct sk_buff *skb = bf->bf_skb;
|
||||||
|
bf->bf_skb = NULL;
|
||||||
|
KASSERT(bf->bf_skbaddr, ("bf->bf_skbaddr is 0"));
|
||||||
|
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
|
||||||
|
sc->sc_rxbufsize, BUS_DMA_FROMDEVICE);
|
||||||
|
bf->bf_skbaddr = 0;
|
||||||
|
return skb;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
|
ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
|
||||||
{
|
{
|
||||||
struct ath_hal *ah = sc->sc_ah;
|
struct ath_hal *ah = sc->sc_ah;
|
||||||
struct ath_desc *ds = NULL;
|
struct ath_desc *ds = NULL;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
|
||||||
/* NB: I'm being cautious by unmapping and releasing the SKB every
|
/* NB: I'm being cautious by unmapping and releasing the SKB every
|
||||||
* time.
|
* time.
|
||||||
* XXX: I could probably keep rolling, but the DMA map/unmap logic
|
* XXX: I could probably keep rolling, but the DMA map/unmap logic
|
||||||
* doesn't seem clean enough and cycling the skb through the free
|
* doesn't seem clean enough and cycling the skb through the free
|
||||||
* function and slab allocator seems to scrub any un-reset values. */
|
* function and slab allocator seems to scrub any un-reset values. */
|
||||||
if (bf->bf_skb != NULL) {
|
if (bf->bf_skb != NULL) {
|
||||||
KASSERT(bf->bf_skbaddr, ("bf->bf_skbaddr is 0"));
|
skb = ath_rxbuf_take_skb(sc, bf);
|
||||||
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
|
ieee80211_dev_kfree_skb(&skb);
|
||||||
sc->sc_rxbufsize, BUS_DMA_FROMDEVICE);
|
|
||||||
ieee80211_dev_kfree_skb(&bf->bf_skb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bf->bf_skb) {
|
if (!bf->bf_skb) {
|
||||||
/* NB: Always use the same size for buffer allocations so that
|
/* NB: Always use the same size for buffer allocations so that
|
||||||
* dynamically adding a monitor mode VAP to a running driver
|
* dynamically adding a monitor mode VAP to a running driver
|
||||||
|
@ -6364,15 +6377,13 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
|
||||||
__func__, size);
|
__func__, size);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Reserve space for the header.
|
/* Reserve space for the header. */
|
||||||
*/
|
|
||||||
skb_reserve(bf->bf_skb, IEEE80211_MON_MAXHDROOM);
|
skb_reserve(bf->bf_skb, IEEE80211_MON_MAXHDROOM);
|
||||||
/*
|
|
||||||
* Cache-line-align. This is important (for the
|
/* Cache-line-align. This is important (for the
|
||||||
* 5210 at least) as not doing so causes bogus data
|
* 5210 at least) as not doing so causes bogus data
|
||||||
* in rx'd frames.
|
* in RX'd frames. */
|
||||||
*/
|
|
||||||
offset = ((unsigned long)bf->bf_skb->data) % sc->sc_cachelsz;
|
offset = ((unsigned long)bf->bf_skb->data) % sc->sc_cachelsz;
|
||||||
if (offset != 0)
|
if (offset != 0)
|
||||||
skb_reserve(bf->bf_skb, sc->sc_cachelsz - offset);
|
skb_reserve(bf->bf_skb, sc->sc_cachelsz - offset);
|
||||||
|
@ -6612,8 +6623,8 @@ ath_rx_tasklet(TQUEUE_ARG data)
|
||||||
struct ath_desc *ds;
|
struct ath_desc *ds;
|
||||||
struct ath_rx_status *rs;
|
struct ath_rx_status *rs;
|
||||||
struct ieee80211_node *ni;
|
struct ieee80211_node *ni;
|
||||||
|
struct sk_buff* skb;
|
||||||
unsigned int len, phyerr, mic_fail = 0;
|
unsigned int len, phyerr, mic_fail = 0;
|
||||||
int is_mcast = 0;
|
|
||||||
int type = -1; /* undefined */
|
int type = -1; /* undefined */
|
||||||
int init_ret = 0;
|
int init_ret = 0;
|
||||||
int bf_processed = 0;
|
int bf_processed = 0;
|
||||||
|
@ -6622,27 +6633,27 @@ ath_rx_tasklet(TQUEUE_ARG data)
|
||||||
|
|
||||||
DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s started...\n", __func__);
|
DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s started...\n", __func__);
|
||||||
do {
|
do {
|
||||||
/*
|
/* Get next RX buffer pending processing by RX tasklet...
|
||||||
* Get next rx buffer pending processing by rx tasklet...
|
|
||||||
*
|
*
|
||||||
* Descriptors are now processed at in the first-level interrupt
|
* Descriptors are now processed at in the first-level interrupt
|
||||||
* handler to support U-APSD trigger search. This must also be done
|
* handler to support U-APSD trigger search. This must also be
|
||||||
* even when U-APSD is not active to support other error handling
|
* done even when U-APSD is not active to support other error
|
||||||
* that requires immediate attention. We check bf_status to find
|
* handling that requires immediate attention. We check
|
||||||
* out if the bf's descriptors have been processed by the interrupt
|
* bf_status to find out if the bf's descriptors have been
|
||||||
* handler and are ready for this tasklet to consume them. We
|
* processed by the interrupt handler and are ready for this
|
||||||
* also never process/remove the self-linked entry at the end
|
* tasklet to consume them. We also never process/remove the
|
||||||
*/
|
* self-linked entry at the end. */
|
||||||
ATH_RXBUF_LOCK_IRQ(sc);
|
ATH_RXBUF_LOCK_IRQ(sc);
|
||||||
bf = STAILQ_FIRST(&sc->sc_rxbuf);
|
bf = STAILQ_FIRST(&sc->sc_rxbuf);
|
||||||
if (bf && (bf->bf_status & ATH_BUFSTATUS_RXDESC_DONE) &&
|
if (bf && (bf->bf_status & ATH_BUFSTATUS_RXDESC_DONE) &&
|
||||||
(bf->bf_desc->ds_link != bf->bf_daddr))
|
(bf->bf_desc->ds_link != bf->bf_daddr))
|
||||||
STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list);
|
STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list);
|
||||||
else {
|
else {
|
||||||
if(bf && (bf->bf_status & ATH_BUFSTATUS_RXDESC_DONE))
|
if (bf && (bf->bf_status & ATH_BUFSTATUS_RXDESC_DONE))
|
||||||
EPRINTF(sc, "Warning: %s detected a non-empty skb that is self-linked. "
|
EPRINTF(sc, "Warning: %s detected a non-empty "
|
||||||
"This may be a driver bug.\n",
|
"skb that is self-linked. "
|
||||||
__func__);
|
"This may be a driver bug.\n",
|
||||||
|
__func__);
|
||||||
bf = NULL;
|
bf = NULL;
|
||||||
}
|
}
|
||||||
ATH_RXBUF_UNLOCK_IRQ(sc);
|
ATH_RXBUF_UNLOCK_IRQ(sc);
|
||||||
|
@ -6651,8 +6662,6 @@ ath_rx_tasklet(TQUEUE_ARG data)
|
||||||
|
|
||||||
bf_processed++;
|
bf_processed++;
|
||||||
ds = bf->bf_desc;
|
ds = bf->bf_desc;
|
||||||
is_mcast = (((const struct ieee80211_frame*)bf->bf_skb->data)->i_addr1[0] & 0x01) ||
|
|
||||||
(((const struct ieee80211_frame*)bf->bf_skb->data)->i_addr3[0] & 0x01);
|
|
||||||
|
|
||||||
#ifdef AR_DEBUG
|
#ifdef AR_DEBUG
|
||||||
if (sc->sc_debug & ATH_DEBUG_RECV_DESC)
|
if (sc->sc_debug & ATH_DEBUG_RECV_DESC)
|
||||||
|
@ -6665,24 +6674,20 @@ ath_rx_tasklet(TQUEUE_ARG data)
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
goto rx_next;
|
goto rx_next;
|
||||||
if (rs->rs_more) {
|
if (rs->rs_more) {
|
||||||
/*
|
/* Frame spans multiple descriptors; this
|
||||||
* Frame spans multiple descriptors; this
|
|
||||||
* cannot happen yet as we don't support
|
* cannot happen yet as we don't support
|
||||||
* jumbograms. If not in monitor mode,
|
* jumbograms. If not in monitor mode,
|
||||||
* discard the frame.
|
* discard the frame. */
|
||||||
*/
|
|
||||||
#ifndef ERROR_FRAMES
|
#ifndef ERROR_FRAMES
|
||||||
/*
|
/* Enable this if you want to see
|
||||||
* Enable this if you want to see
|
* error frames in Monitor mode. */
|
||||||
* error frames in Monitor mode.
|
|
||||||
*/
|
|
||||||
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
|
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
|
||||||
sc->sc_stats.ast_rx_toobig++;
|
sc->sc_stats.ast_rx_toobig++;
|
||||||
errors++;
|
errors++;
|
||||||
goto rx_next;
|
goto rx_next;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* fall thru for monitor mode handling... */
|
/* Fall through for monitor mode handling... */
|
||||||
} else if (rs->rs_status != 0) {
|
} else if (rs->rs_status != 0) {
|
||||||
errors++;
|
errors++;
|
||||||
if (rs->rs_status & HAL_RXERR_CRC)
|
if (rs->rs_status & HAL_RXERR_CRC)
|
||||||
|
@ -6695,16 +6700,14 @@ ath_rx_tasklet(TQUEUE_ARG data)
|
||||||
sc->sc_stats.ast_rx_phy[phyerr]++;
|
sc->sc_stats.ast_rx_phy[phyerr]++;
|
||||||
}
|
}
|
||||||
if (rs->rs_status & HAL_RXERR_DECRYPT) {
|
if (rs->rs_status & HAL_RXERR_DECRYPT) {
|
||||||
/*
|
/* Decrypt error. If the error occurred
|
||||||
* Decrypt error. If the error occurred
|
|
||||||
* because there was no hardware key, then
|
* because there was no hardware key, then
|
||||||
* let the frame through so the upper layers
|
* let the frame through so the upper layers
|
||||||
* can process it. This is necessary for 5210
|
* can process it. This is necessary for 5210
|
||||||
* parts which have no way to setup a ``clear''
|
* parts which have no way to setup a ``clear''
|
||||||
* key cache entry.
|
* key cache entry.
|
||||||
*
|
*
|
||||||
* XXX do key cache faulting
|
* XXX: Do key cache faulting. */
|
||||||
*/
|
|
||||||
if (rs->rs_keyix == HAL_RXKEYIX_INVALID)
|
if (rs->rs_keyix == HAL_RXKEYIX_INVALID)
|
||||||
goto rx_accept;
|
goto rx_accept;
|
||||||
sc->sc_stats.ast_rx_badcrypt++;
|
sc->sc_stats.ast_rx_badcrypt++;
|
||||||
|
@ -6722,24 +6725,25 @@ ath_rx_tasklet(TQUEUE_ARG data)
|
||||||
}
|
}
|
||||||
rx_accept:
|
rx_accept:
|
||||||
skb_accepted++;
|
skb_accepted++;
|
||||||
/*
|
|
||||||
* Sync and unmap the frame. At this point we're
|
/* Sync and unmap the frame. At this point we're committed
|
||||||
* committed to passing the sk_buff somewhere so
|
* to passing the sk_buff somewhere so clear bf_skb; this means
|
||||||
* clear buf_skb; this means a new sk_buff must be
|
* a new sk_buff must be allocated when the RX descriptor is
|
||||||
* allocated when the rx descriptor is setup again
|
* setup again to receive another frame.
|
||||||
* to receive another frame.
|
* NB: Meta-data (rs, noise, tsf) in the ath_buf is still
|
||||||
*/
|
* used. */
|
||||||
bus_dma_sync_single(sc->sc_bdev,
|
bus_dma_sync_single(sc->sc_bdev,
|
||||||
bf->bf_skbaddr, len, BUS_DMA_FROMDEVICE);
|
bf->bf_skbaddr, len, BUS_DMA_FROMDEVICE);
|
||||||
|
skb = ath_rxbuf_take_skb(sc, bf);
|
||||||
|
|
||||||
sc->sc_stats.ast_ant_rx[rs->rs_antenna]++;
|
sc->sc_stats.ast_ant_rx[rs->rs_antenna]++;
|
||||||
sc->sc_devstats.rx_packets++;
|
sc->sc_devstats.rx_packets++;
|
||||||
sc->sc_devstats.rx_bytes += len;
|
sc->sc_devstats.rx_bytes += len;
|
||||||
|
|
||||||
skb_put(bf->bf_skb, len);
|
skb_put(skb, len);
|
||||||
bf->bf_skb->protocol = __constant_htons(ETH_P_CONTROL);
|
skb->protocol = __constant_htons(ETH_P_CONTROL);
|
||||||
|
|
||||||
ath_capture(dev, bf, bf->bf_skb, bf->bf_tsf, 0 /* RX */);
|
ath_capture(dev, bf, skb, bf->bf_tsf, 0 /* RX */);
|
||||||
|
|
||||||
/* Finished monitor mode handling, now reject error frames
|
/* Finished monitor mode handling, now reject error frames
|
||||||
* before passing to other VAPs. Ignore MIC failures here, as
|
* before passing to other VAPs. Ignore MIC failures here, as
|
||||||
|
@ -6747,22 +6751,22 @@ rx_accept:
|
||||||
if (rs->rs_status & ~(HAL_RXERR_MIC | HAL_RXERR_DECRYPT))
|
if (rs->rs_status & ~(HAL_RXERR_MIC | HAL_RXERR_DECRYPT))
|
||||||
goto rx_next;
|
goto rx_next;
|
||||||
|
|
||||||
/* remove the CRC */
|
/* Remove the CRC. */
|
||||||
skb_trim(bf->bf_skb, bf->bf_skb->len - IEEE80211_CRC_LEN);
|
skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
|
||||||
|
|
||||||
if (mic_fail) {
|
if (mic_fail) {
|
||||||
/* Ignore control frames which are reported with MIC
|
/* Ignore control frames which are reported with MIC
|
||||||
* error. */
|
* error. */
|
||||||
if ((((struct ieee80211_frame *)bf->bf_skb->data)->i_fc[0] &
|
if ((((struct ieee80211_frame *)skb->data)->i_fc[0] &
|
||||||
IEEE80211_FC0_TYPE_MASK) ==
|
IEEE80211_FC0_TYPE_MASK) ==
|
||||||
IEEE80211_FC0_TYPE_CTL)
|
IEEE80211_FC0_TYPE_CTL)
|
||||||
goto drop_micfail;
|
goto drop_micfail;
|
||||||
|
|
||||||
ni = ieee80211_find_rxnode(ic, (const struct
|
ni = ieee80211_find_rxnode(ic, (const struct
|
||||||
ieee80211_frame_min *)bf->bf_skb->data);
|
ieee80211_frame_min *)skb->data);
|
||||||
if (ni) {
|
if (ni) {
|
||||||
if (ni->ni_table)
|
if (ni->ni_table)
|
||||||
ieee80211_check_mic(ni, bf->bf_skb);
|
ieee80211_check_mic(ni, skb);
|
||||||
ieee80211_unref_node(&ni);
|
ieee80211_unref_node(&ni);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6783,17 +6787,16 @@ drop_micfail:
|
||||||
|
|
||||||
/* Normal receive. */
|
/* Normal receive. */
|
||||||
if (IFF_DUMPPKTS(sc, ATH_DEBUG_RECV))
|
if (IFF_DUMPPKTS(sc, ATH_DEBUG_RECV))
|
||||||
ieee80211_dump_pkt(ic, bf->bf_skb->data, bf->bf_skb->len,
|
ieee80211_dump_pkt(ic, skb->data, skb->len,
|
||||||
sc->sc_hwmap[rs->rs_rate].ieeerate,
|
sc->sc_hwmap[rs->rs_rate].ieeerate,
|
||||||
rs->rs_rssi);
|
rs->rs_rssi);
|
||||||
|
|
||||||
{
|
{
|
||||||
struct ieee80211_frame * wh =
|
struct ieee80211_frame * wh =
|
||||||
(struct ieee80211_frame *) bf->bf_skb->data;
|
(struct ieee80211_frame *)skb->data;
|
||||||
|
|
||||||
/* only print beacons */
|
/* Only print beacons. */
|
||||||
|
if ((skb->len >= sizeof(struct ieee80211_frame)) &&
|
||||||
if ((bf->bf_skb->len >= sizeof(struct ieee80211_frame)) &&
|
|
||||||
((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)
|
((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)
|
||||||
== IEEE80211_FC0_TYPE_MGT) &&
|
== IEEE80211_FC0_TYPE_MGT) &&
|
||||||
((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
|
((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
|
||||||
|
@ -6812,69 +6815,64 @@ drop_micfail:
|
||||||
* are on-channel. */
|
* are on-channel. */
|
||||||
if (!sc->sc_scanning && !(ic->ic_flags & IEEE80211_F_SCAN))
|
if (!sc->sc_scanning && !(ic->ic_flags & IEEE80211_F_SCAN))
|
||||||
ATH_RSSI_LPF(sc->sc_halstats.ns_avgrssi, rs->rs_rssi);
|
ATH_RSSI_LPF(sc->sc_halstats.ns_avgrssi, rs->rs_rssi);
|
||||||
KASSERT((atomic_read(&bf->bf_skb->users) == 1),
|
|
||||||
("BAD starting skb reference count!"));
|
/* Locate the node for sender, track state, and then pass the
|
||||||
/*
|
* (referenced) node up to the 802.11 layer for its use. If
|
||||||
* Locate the node for sender, track state, and then
|
* the sender is unknown spam the frame; it'll be dropped
|
||||||
* pass the (referenced) node up to the 802.11 layer
|
* where it's not wanted. */
|
||||||
* for its use. If the sender is unknown spam the
|
if ((rs->rs_keyix != HAL_RXKEYIX_INVALID) &&
|
||||||
* frame; it'll be dropped where it's not wanted.
|
|
||||||
*/
|
|
||||||
if (rs->rs_keyix != HAL_RXKEYIX_INVALID &&
|
|
||||||
(ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) {
|
(ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) {
|
||||||
/* Fast path: node is present in the key map;
|
/* Fast path: node is present in the key map;
|
||||||
* grab a reference for processing the frame. */
|
* grab a reference for processing the frame. */
|
||||||
ni = ieee80211_ref_node(ni);
|
ni = ieee80211_ref_node(ni);
|
||||||
type = ieee80211_input(ni->ni_vap, ni, bf->bf_skb, rs->rs_rssi, bf->bf_tsf);
|
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/* No key index or no entry, do a lookup and
|
||||||
* No key index or no entry, do a lookup and
|
* add the node to the mapping table if possible. */
|
||||||
* add the node to the mapping table if possible.
|
|
||||||
*/
|
|
||||||
ni = ieee80211_find_rxnode(ic,
|
ni = ieee80211_find_rxnode(ic,
|
||||||
(const struct ieee80211_frame_min *)bf->bf_skb->data);
|
(const struct ieee80211_frame_min *)skb->data);
|
||||||
if (ni != NULL) {
|
if (ni != NULL) {
|
||||||
ieee80211_keyix_t keyix;
|
/* If the station has a key cache slot assigned
|
||||||
type = ieee80211_input(ni->ni_vap, ni, bf->bf_skb, rs->rs_rssi, bf->bf_tsf);
|
* update the key->node mapping table. */
|
||||||
/*
|
ieee80211_keyix_t keyix =
|
||||||
* If the station has a key cache slot assigned
|
ni->ni_ucastkey.wk_keyix;
|
||||||
* update the key->node mapping table.
|
if ((keyix != IEEE80211_KEYIX_NONE) &&
|
||||||
*/
|
(sc->sc_keyixmap[keyix] == NULL))
|
||||||
keyix = ni->ni_ucastkey.wk_keyix;
|
sc->sc_keyixmap[keyix] =
|
||||||
if (keyix != IEEE80211_KEYIX_NONE &&
|
ieee80211_ref_node(ni);
|
||||||
sc->sc_keyixmap[keyix] == NULL)
|
}
|
||||||
sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni);
|
}
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
} else {
|
/* If a node is found, dispatch, else, dispatch to all. */
|
||||||
struct ieee80211vap * vap;
|
if (ni) {
|
||||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
|
type = ieee80211_input(ni->ni_vap, ni, skb,
|
||||||
type = ieee80211_input(vap, NULL, bf->bf_skb, rs->rs_rssi, bf->bf_tsf);
|
rs->rs_rssi, bf->bf_tsf);
|
||||||
}
|
ieee80211_unref_node(&ni);
|
||||||
|
} else {
|
||||||
|
struct ieee80211vap *vap;
|
||||||
|
/* Create a new SKB copy for each VAP except the last
|
||||||
|
* one, which gets the original SKB. */
|
||||||
|
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
|
||||||
|
type = ieee80211_input(vap, NULL, skb,
|
||||||
|
rs->rs_rssi, bf->bf_tsf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KASSERT((atomic_read(&bf->bf_skb->users) == 1),
|
|
||||||
("ieee80211_input changed skb reference count!"));
|
|
||||||
|
|
||||||
if (sc->sc_diversity) {
|
if (sc->sc_diversity) {
|
||||||
/*
|
/* When using hardware fast diversity, change the default RX
|
||||||
* When using hardware fast diversity, change the default rx
|
* antenna if RX diversity chooses the other antenna 3
|
||||||
* antenna if rx diversity chooses the other antenna 3
|
* times in a row. */
|
||||||
* times in a row.
|
|
||||||
*/
|
|
||||||
if (sc->sc_defant != rs->rs_antenna) {
|
if (sc->sc_defant != rs->rs_antenna) {
|
||||||
if (++sc->sc_rxotherant >= 3)
|
if (++sc->sc_rxotherant >= 3)
|
||||||
ath_setdefantenna(sc, rs->rs_antenna);
|
ath_setdefantenna(sc, rs->rs_antenna);
|
||||||
} else
|
} else
|
||||||
sc->sc_rxotherant = 0;
|
sc->sc_rxotherant = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc->sc_softled) {
|
if (sc->sc_softled) {
|
||||||
/*
|
/* Blink for any data frame. Otherwise do a
|
||||||
* Blink for any data frame. Otherwise do a
|
|
||||||
* heartbeat-style blink when idle. The latter
|
* heartbeat-style blink when idle. The latter
|
||||||
* is mainly for station mode where we depend on
|
* is mainly for station mode where we depend on
|
||||||
* periodic beacon frames to trigger the poll event.
|
* periodic beacon frames to trigger the poll event. */
|
||||||
*/
|
|
||||||
if (type == IEEE80211_FC0_TYPE_DATA) {
|
if (type == IEEE80211_FC0_TYPE_DATA) {
|
||||||
sc->sc_rxrate = rs->rs_rate;
|
sc->sc_rxrate = rs->rs_rate;
|
||||||
ath_led_event(sc, ATH_LED_RX);
|
ath_led_event(sc, ATH_LED_RX);
|
||||||
|
@ -6883,10 +6881,10 @@ drop_micfail:
|
||||||
}
|
}
|
||||||
rx_next:
|
rx_next:
|
||||||
KASSERT(bf != NULL, ("null bf"));
|
KASSERT(bf != NULL, ("null bf"));
|
||||||
KASSERT(bf->bf_skb != NULL, ("null bf->bf_skb"));
|
|
||||||
|
|
||||||
if (0 != (init_ret = ath_rxbuf_init(sc, bf))) {
|
if ((init_ret = ath_rxbuf_init(sc, bf)) != 0) {
|
||||||
EPRINTF(sc, "Failed to reinitialize rxbuf: %d. Lost an RX buffer!\n", init_ret);
|
EPRINTF(sc, "Failed to reinitialize rxbuf: %d. "
|
||||||
|
"Lost an RX buffer!\n", init_ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6895,6 +6893,7 @@ rx_next:
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
|
||||||
ATH_RXBUF_UNLOCK_IRQ(sc);
|
ATH_RXBUF_UNLOCK_IRQ(sc);
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
if (sc->sc_useintmit)
|
if (sc->sc_useintmit)
|
||||||
ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
|
ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
|
||||||
if (!bf_processed)
|
if (!bf_processed)
|
||||||
|
@ -8514,7 +8513,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||||
/* ath_capture modifies skb data; must be last process
|
/* ath_capture modifies skb data; must be last process
|
||||||
* in TX path. */
|
* in TX path. */
|
||||||
tskb = skb->next;
|
tskb = skb->next;
|
||||||
DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture/free skb %p\n",
|
DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n",
|
||||||
bf->bf_skb);
|
bf->bf_skb);
|
||||||
ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */);
|
ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */);
|
||||||
skb = tskb;
|
skb = tskb;
|
||||||
|
@ -8524,7 +8523,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||||
* extra buffers */
|
* extra buffers */
|
||||||
for (i = 0; i < bf->bf_numdescff; i++) {
|
for (i = 0; i < bf->bf_numdescff; i++) {
|
||||||
tskb = skb->next;
|
tskb = skb->next;
|
||||||
DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture/free skb %p\n",
|
DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n",
|
||||||
skb);
|
skb);
|
||||||
ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */);
|
ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */);
|
||||||
skb = tskb;
|
skb = tskb;
|
||||||
|
|
|
@ -213,7 +213,7 @@ ieee80211_input(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null,
|
||||||
u_int8_t *bssid;
|
u_int8_t *bssid;
|
||||||
u_int16_t rxseq;
|
u_int16_t rxseq;
|
||||||
|
|
||||||
/* initialize ni as in the previous API */
|
/* Initialize ni as in the previous API. */
|
||||||
if (ni_or_null == NULL) {
|
if (ni_or_null == NULL) {
|
||||||
/* This function does not 'own' vap->iv_bss, so we cannot
|
/* This function does not 'own' vap->iv_bss, so we cannot
|
||||||
* guarantee its existence during the following call, hence
|
* guarantee its existence during the following call, hence
|
||||||
|
@ -224,11 +224,10 @@ ieee80211_input(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null,
|
||||||
KASSERT(ni != NULL, ("null node"));
|
KASSERT(ni != NULL, ("null node"));
|
||||||
ni->ni_inact = ni->ni_inact_reload;
|
ni->ni_inact = ni->ni_inact_reload;
|
||||||
type = -1; /* undefined */
|
type = -1; /* undefined */
|
||||||
/*
|
|
||||||
* In monitor mode, send everything directly to bpf.
|
/* In monitor mode, send everything directly to bpf.
|
||||||
* Also do not process frames w/o i_addr2 any further.
|
* Also do not process frames w/o i_addr2 any further.
|
||||||
* XXX may want to include the CRC
|
* XXX: may want to include the CRC. */
|
||||||
*/
|
|
||||||
if (vap->iv_opmode == IEEE80211_M_MONITOR)
|
if (vap->iv_opmode == IEEE80211_M_MONITOR)
|
||||||
goto out;
|
goto out;
|
||||||
if (original_skb->len < sizeof(struct ieee80211_frame_min)) {
|
if (original_skb->len < sizeof(struct ieee80211_frame_min)) {
|
||||||
|
@ -252,12 +251,10 @@ ieee80211_input(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null,
|
||||||
ieee80211_skb_copy_noderef(original_skb, skb);
|
ieee80211_skb_copy_noderef(original_skb, skb);
|
||||||
original_skb = NULL; /* protect caller's skb */
|
original_skb = NULL; /* protect caller's skb */
|
||||||
|
|
||||||
/*
|
/* Bit of a cheat here, we use a pointer for a 3-address
|
||||||
* Bit of a cheat here, we use a pointer for a 3-address
|
|
||||||
* frame format but don't reference fields past outside
|
* frame format but don't reference fields past outside
|
||||||
* ieee80211_frame_min w/o first validating the data is
|
* ieee80211_frame_min w/o first validating the data is
|
||||||
* present.
|
* present. */
|
||||||
*/
|
|
||||||
wh = (struct ieee80211_frame *)skb->data;
|
wh = (struct ieee80211_frame *)skb->data;
|
||||||
|
|
||||||
if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
|
if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
|
||||||
|
|
|
@ -294,7 +294,8 @@ struct ieee80211com {
|
||||||
struct net_device *ic_dev; /* associated device */
|
struct net_device *ic_dev; /* associated device */
|
||||||
ieee80211com_lock_t ic_comlock; /* state update lock */
|
ieee80211com_lock_t ic_comlock; /* state update lock */
|
||||||
ieee80211com_lock_t ic_vapslock; /* vap state machine lock */
|
ieee80211com_lock_t ic_vapslock; /* vap state machine lock */
|
||||||
TAILQ_HEAD(, ieee80211vap) ic_vaps; /* list of vap instances */
|
TAILQ_HEAD(ieee80211vap_headtype,
|
||||||
|
ieee80211vap) ic_vaps; /* list of vap instances */
|
||||||
enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */
|
enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */
|
||||||
enum ieee80211_opmode ic_opmode; /* operation mode */
|
enum ieee80211_opmode ic_opmode; /* operation mode */
|
||||||
struct ifmedia ic_media; /* interface media config */
|
struct ifmedia ic_media; /* interface media config */
|
||||||
|
|
Loading…
Reference in New Issue