diff --git a/ath/if_ath.c b/ath/if_ath.c index d04bda4..c9262b5 100644 --- a/ath/if_ath.c +++ b/ath/if_ath.c @@ -6795,25 +6795,10 @@ drop_micfail: rs->rs_rssi, bf->bf_tsf); ieee80211_unref_node(&ni); } else { - struct ieee80211vap *vap; - struct sk_buff *tskb; - /* 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) { - if (vap == TAILQ_LAST(&ic->ic_vaps, - ieee80211vap_headtype)) - tskb = skb; - else - tskb = skb_copy(skb, GFP_ATOMIC); - - if (!tskb) - /* XXX: Brilliant OOM handling. */ - vap->iv_devstats.tx_dropped++; - else - type = ieee80211_input(vap, NULL, skb, - rs->rs_rssi, bf->bf_tsf); - } + type = ieee80211_input_all(ic, skb, + rs->rs_rssi, bf->bf_tsf); } + skb = NULL; if (sc->sc_diversity) { /* When using hardware fast diversity, change the default RX diff --git a/net80211/ieee80211_input.c b/net80211/ieee80211_input.c index 824403e..e8fa999 100644 --- a/net80211/ieee80211_input.c +++ b/net80211/ieee80211_input.c @@ -194,7 +194,7 @@ iwspy_event(struct ieee80211vap *vap, struct ieee80211_node *ni, u_int rssi) * Context: softIRQ (tasklet) */ int -ieee80211_input(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null, +ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null, struct sk_buff *skb, int rssi, u_int64_t rtsf) { #define HAS_SEQ(type) ((type & 0x4) == 0) @@ -208,10 +208,14 @@ ieee80211_input(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null, struct llc *llc; #endif int hdrspace; - u_int8_t dir, type, subtype; + u_int8_t dir, type = -1, subtype; u_int8_t *bssid; u_int16_t rxseq; + if ((vap->iv_dev->flags & (IFF_RUNNING | IFF_UP)) != + (IFF_RUNNING | IFF_UP)) + goto out; + /* Initialize ni as in the previous API. */ if (ni_or_null == NULL) { /* This function does not 'own' vap->iv_bss, so we cannot @@ -222,7 +226,6 @@ ieee80211_input(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null, KASSERT(skb != NULL, ("null skb")); KASSERT(ni != NULL, ("null node")); ni->ni_inact = ni->ni_inact_reload; - type = -1; /* undefined */ /* In monitor mode, send everything directly to bpf. * Also do not process frames w/o i_addr2 any further. @@ -845,8 +848,49 @@ out: return type; #undef HAS_SEQ } -EXPORT_SYMBOL(ieee80211_input); +EXPORT_SYMBOL(ieee80211_input); +/* + * Context: softIRQ (tasklet) + */ +int +ieee80211_input_all(struct ieee80211com *ic, + struct sk_buff *skb, int rssi, u_int64_t rtsf) +{ + struct ieee80211vap *vap, *next_vap; + struct sk_buff *tskb = NULL; + int type = -1; /* Used to determine when to blinks LEDs. */ + + /* Create a new SKB copy for each VAP except the last + * one, which gets the original SKB. */ + vap = TAILQ_FIRST(&ic->ic_vaps); + while (vap) { + for (next_vap = TAILQ_NEXT(vap, iv_next); next_vap; + next_vap = TAILQ_NEXT(next_vap, iv_next)) { + if ((next_vap->iv_dev->flags & (IFF_RUNNING | IFF_UP)) + == (IFF_RUNNING | IFF_UP)) + break; + } + + if (!next_vap) { + tskb = skb; + skb = NULL; + } else + tskb = skb_copy(skb, GFP_ATOMIC); + + if (!tskb) + /* XXX: Brilliant OOM handling. */ + vap->iv_devstats.tx_dropped++; + else + type = ieee80211_input(vap, NULL, tskb, rssi, rtsf); + + vap = next_vap; + }; + + ieee80211_dev_kfree_skb(&skb); + return type; +} +EXPORT_SYMBOL(ieee80211_input_all); /* * Determines whether a frame should be accepted, based on information diff --git a/net80211/ieee80211_proto.h b/net80211/ieee80211_proto.h index ab2659a..433fa7b 100644 --- a/net80211/ieee80211_proto.h +++ b/net80211/ieee80211_proto.h @@ -65,6 +65,7 @@ void ieee80211_proto_vdetach(struct ieee80211vap *); struct ieee80211_node; struct ieee80211_channel *ieee80211_doth_findchan(struct ieee80211vap *, u_int8_t); int ieee80211_input(struct ieee80211vap *, struct ieee80211_node *, struct sk_buff *, int, u_int64_t); +int ieee80211_input_all(struct ieee80211com *, struct sk_buff *, int, u_int64_t); int ieee80211_setup_rates(struct ieee80211_node *, const u_int8_t *, const u_int8_t *, int); void ieee80211_saveie(u_int8_t **, const u_int8_t *);