diff options
author | Sujith Manoharan <c_manoha@qca.qualcomm.com> | 2013-08-13 23:41:18 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-08-15 16:08:04 -0400 |
commit | 6f38482eb0630e0be304d5c4fa0e2e5c0a701e91 (patch) | |
tree | 6dbbcc9ef6347ac4e9d9b5d94b12abe4bcf86e78 /drivers/net/wireless/ath | |
parent | a5525d9c8246cad653858044ccfd8a16143e84f6 (diff) |
ath9k: Fix RX beacon processing
Make sure that chained descriptors are handled correctly
before the packet is parsed to determine if it is a beacon.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 48 |
1 files changed, 22 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 823b4111e282..090c27e756b8 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -1037,13 +1037,28 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
1037 | #endif | 1037 | #endif |
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr) | ||
1041 | { | ||
1042 | struct ath_hw *ah = sc->sc_ah; | ||
1043 | struct ath_common *common = ath9k_hw_common(ah); | ||
1044 | |||
1045 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
1046 | RX_STAT_INC(rx_beacons); | ||
1047 | if (!is_zero_ether_addr(common->curbssid) && | ||
1048 | ether_addr_equal(hdr->addr3, common->curbssid)) | ||
1049 | return true; | ||
1050 | } | ||
1051 | |||
1052 | return false; | ||
1053 | } | ||
1054 | |||
1040 | /* | 1055 | /* |
1041 | * For Decrypt or Demic errors, we only mark packet status here and always push | 1056 | * For Decrypt or Demic errors, we only mark packet status here and always push |
1042 | * up the frame up to let mac80211 handle the actual error case, be it no | 1057 | * up the frame up to let mac80211 handle the actual error case, be it no |
1043 | * decryption key or real decryption error. This let us keep statistics there. | 1058 | * decryption key or real decryption error. This let us keep statistics there. |
1044 | */ | 1059 | */ |
1045 | static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | 1060 | static int ath9k_rx_skb_preprocess(struct ath_softc *sc, |
1046 | struct ieee80211_hdr *hdr, | 1061 | struct sk_buff *skb, |
1047 | struct ath_rx_status *rx_stats, | 1062 | struct ath_rx_status *rx_stats, |
1048 | struct ieee80211_rx_status *rx_status, | 1063 | struct ieee80211_rx_status *rx_status, |
1049 | bool *decrypt_error, u64 tsf) | 1064 | bool *decrypt_error, u64 tsf) |
@@ -1051,6 +1066,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | |||
1051 | struct ieee80211_hw *hw = sc->hw; | 1066 | struct ieee80211_hw *hw = sc->hw; |
1052 | struct ath_hw *ah = sc->sc_ah; | 1067 | struct ath_hw *ah = sc->sc_ah; |
1053 | struct ath_common *common = ath9k_hw_common(ah); | 1068 | struct ath_common *common = ath9k_hw_common(ah); |
1069 | struct ieee80211_hdr *hdr; | ||
1054 | bool discard_current = sc->rx.discard_next; | 1070 | bool discard_current = sc->rx.discard_next; |
1055 | 1071 | ||
1056 | /* | 1072 | /* |
@@ -1083,6 +1099,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | |||
1083 | if (rx_stats->rs_more) | 1099 | if (rx_stats->rs_more) |
1084 | return 0; | 1100 | return 0; |
1085 | 1101 | ||
1102 | hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len); | ||
1103 | |||
1086 | ath9k_process_tsf(rx_stats, rx_status, tsf); | 1104 | ath9k_process_tsf(rx_stats, rx_status, tsf); |
1087 | ath_debug_stat_rx(sc, rx_stats); | 1105 | ath_debug_stat_rx(sc, rx_stats); |
1088 | 1106 | ||
@@ -1105,6 +1123,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | |||
1105 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) | 1123 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) |
1106 | return -EINVAL; | 1124 | return -EINVAL; |
1107 | 1125 | ||
1126 | rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr); | ||
1127 | |||
1108 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) | 1128 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) |
1109 | return -EINVAL; | 1129 | return -EINVAL; |
1110 | 1130 | ||
@@ -1198,24 +1218,6 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc, | |||
1198 | } | 1218 | } |
1199 | } | 1219 | } |
1200 | 1220 | ||
1201 | static bool ath9k_is_mybeacon(struct ath_softc *sc, struct sk_buff *skb) | ||
1202 | { | ||
1203 | struct ath_hw *ah = sc->sc_ah; | ||
1204 | struct ath_common *common = ath9k_hw_common(ah); | ||
1205 | struct ieee80211_hdr *hdr; | ||
1206 | |||
1207 | hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len); | ||
1208 | |||
1209 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
1210 | RX_STAT_INC(rx_beacons); | ||
1211 | if (!is_zero_ether_addr(common->curbssid) && | ||
1212 | ether_addr_equal(hdr->addr3, common->curbssid)) | ||
1213 | return true; | ||
1214 | } | ||
1215 | |||
1216 | return false; | ||
1217 | } | ||
1218 | |||
1219 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1221 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
1220 | { | 1222 | { |
1221 | struct ath_buf *bf; | 1223 | struct ath_buf *bf; |
@@ -1225,7 +1227,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1225 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 1227 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
1226 | struct ath_common *common = ath9k_hw_common(ah); | 1228 | struct ath_common *common = ath9k_hw_common(ah); |
1227 | struct ieee80211_hw *hw = sc->hw; | 1229 | struct ieee80211_hw *hw = sc->hw; |
1228 | struct ieee80211_hdr *hdr; | ||
1229 | int retval; | 1230 | int retval; |
1230 | struct ath_rx_status rs; | 1231 | struct ath_rx_status rs; |
1231 | enum ath9k_rx_qtype qtype; | 1232 | enum ath9k_rx_qtype qtype; |
@@ -1269,15 +1270,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1269 | else | 1270 | else |
1270 | hdr_skb = skb; | 1271 | hdr_skb = skb; |
1271 | 1272 | ||
1272 | rs.is_mybeacon = ath9k_is_mybeacon(sc, hdr_skb); | ||
1273 | |||
1274 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + | ||
1275 | ah->caps.rx_status_len); | ||
1276 | |||
1277 | rxs = IEEE80211_SKB_RXCB(hdr_skb); | 1273 | rxs = IEEE80211_SKB_RXCB(hdr_skb); |
1278 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); | 1274 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); |
1279 | 1275 | ||
1280 | retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs, | 1276 | retval = ath9k_rx_skb_preprocess(sc, hdr_skb, &rs, rxs, |
1281 | &decrypt_error, tsf); | 1277 | &decrypt_error, tsf); |
1282 | if (retval) | 1278 | if (retval) |
1283 | goto requeue_drop_frag; | 1279 | goto requeue_drop_frag; |