|
@@ -1037,13 +1037,28 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr)
|
|
|
+{
|
|
|
+ struct ath_hw *ah = sc->sc_ah;
|
|
|
+ struct ath_common *common = ath9k_hw_common(ah);
|
|
|
+
|
|
|
+ if (ieee80211_is_beacon(hdr->frame_control)) {
|
|
|
+ RX_STAT_INC(rx_beacons);
|
|
|
+ if (!is_zero_ether_addr(common->curbssid) &&
|
|
|
+ ether_addr_equal(hdr->addr3, common->curbssid))
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* For Decrypt or Demic errors, we only mark packet status here and always push
|
|
|
* up the frame up to let mac80211 handle the actual error case, be it no
|
|
|
* decryption key or real decryption error. This let us keep statistics there.
|
|
|
*/
|
|
|
static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|
|
- struct ieee80211_hdr *hdr,
|
|
|
+ struct sk_buff *skb,
|
|
|
struct ath_rx_status *rx_stats,
|
|
|
struct ieee80211_rx_status *rx_status,
|
|
|
bool *decrypt_error, u64 tsf)
|
|
@@ -1051,6 +1066,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|
|
struct ieee80211_hw *hw = sc->hw;
|
|
|
struct ath_hw *ah = sc->sc_ah;
|
|
|
struct ath_common *common = ath9k_hw_common(ah);
|
|
|
+ struct ieee80211_hdr *hdr;
|
|
|
bool discard_current = sc->rx.discard_next;
|
|
|
|
|
|
/*
|
|
@@ -1083,6 +1099,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|
|
if (rx_stats->rs_more)
|
|
|
return 0;
|
|
|
|
|
|
+ hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
|
|
|
+
|
|
|
ath9k_process_tsf(rx_stats, rx_status, tsf);
|
|
|
ath_debug_stat_rx(sc, rx_stats);
|
|
|
|
|
@@ -1105,6 +1123,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|
|
if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr);
|
|
|
+
|
|
|
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
|
|
|
return -EINVAL;
|
|
|
|
|
@@ -1198,24 +1218,6 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static bool ath9k_is_mybeacon(struct ath_softc *sc, struct sk_buff *skb)
|
|
|
-{
|
|
|
- struct ath_hw *ah = sc->sc_ah;
|
|
|
- struct ath_common *common = ath9k_hw_common(ah);
|
|
|
- struct ieee80211_hdr *hdr;
|
|
|
-
|
|
|
- hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
|
|
|
-
|
|
|
- if (ieee80211_is_beacon(hdr->frame_control)) {
|
|
|
- RX_STAT_INC(rx_beacons);
|
|
|
- if (!is_zero_ether_addr(common->curbssid) &&
|
|
|
- ether_addr_equal(hdr->addr3, common->curbssid))
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|
|
{
|
|
|
struct ath_buf *bf;
|
|
@@ -1225,7 +1227,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|
|
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
|
|
struct ath_common *common = ath9k_hw_common(ah);
|
|
|
struct ieee80211_hw *hw = sc->hw;
|
|
|
- struct ieee80211_hdr *hdr;
|
|
|
int retval;
|
|
|
struct ath_rx_status rs;
|
|
|
enum ath9k_rx_qtype qtype;
|
|
@@ -1269,15 +1270,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|
|
else
|
|
|
hdr_skb = skb;
|
|
|
|
|
|
- rs.is_mybeacon = ath9k_is_mybeacon(sc, hdr_skb);
|
|
|
-
|
|
|
- hdr = (struct ieee80211_hdr *) (hdr_skb->data +
|
|
|
- ah->caps.rx_status_len);
|
|
|
-
|
|
|
rxs = IEEE80211_SKB_RXCB(hdr_skb);
|
|
|
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
|
|
|
|
|
|
- retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
|
|
|
+ retval = ath9k_rx_skb_preprocess(sc, hdr_skb, &rs, rxs,
|
|
|
&decrypt_error, tsf);
|
|
|
if (retval)
|
|
|
goto requeue_drop_frag;
|