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:
mentor 2008-05-03 03:40:27 +00:00
parent 2ecfeab07e
commit 1b318d3853
3 changed files with 117 additions and 120 deletions

View File

@ -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,17 +6633,16 @@ 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) &&
@ -6640,7 +6650,8 @@ ath_rx_tasklet(TQUEUE_ARG data)
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 "
"skb that is self-linked. "
"This may be a driver bug.\n", "This may be a driver bug.\n",
__func__); __func__);
bf = NULL; bf = NULL;
@ -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); }
/* If a node is found, dispatch, else, dispatch to all. */
if (ni) {
type = ieee80211_input(ni->ni_vap, ni, skb,
rs->rs_rssi, bf->bf_tsf);
ieee80211_unref_node(&ni); ieee80211_unref_node(&ni);
} else { } else {
struct ieee80211vap *vap; 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) { TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
type = ieee80211_input(vap, NULL, bf->bf_skb, rs->rs_rssi, bf->bf_tsf); 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;

View File

@ -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) !=

View File

@ -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 */