aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2013-04-07 18:04:11 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-10 14:10:33 -0400
commit723e711356b5a8a95728a890e254e8b0d47b55cf (patch)
tree23f3c8856b72438a40b7bbbb47283a5ca1eb54b3 /drivers
parent2e1cd495466d14c7d92e10d709f27161afe44b15 (diff)
ath9k: fix handling of broken descriptors
As the comment in ath_get_next_rx_buf indicates, if a descriptor with the done bit set follows one with the done bit cleared, both descriptors should be discarded, however the driver is not doing that yet. To fix this, use the rs->rs_more flag as an indicator that the following frame should be discarded. This also helps with the split buffer case: if the first part of the frame is discarded, the following parts need to be discarded as well, since they contain no valid header or usable data. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c24
2 files changed, 20 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index a56b2416e2f9..86d35726edb4 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -311,6 +311,7 @@ struct ath_rx_edma {
311struct ath_rx { 311struct ath_rx {
312 u8 defant; 312 u8 defant;
313 u8 rxotherant; 313 u8 rxotherant;
314 bool discard_next;
314 u32 *rxlink; 315 u32 *rxlink;
315 u32 num_pkts; 316 u32 num_pkts;
316 unsigned int rxfilter; 317 unsigned int rxfilter;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 3d0f02ddcf5b..c593a3e0cd95 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -727,6 +727,13 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
727 ret = ath9k_hw_rxprocdesc(ah, tds, &trs); 727 ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
728 if (ret == -EINPROGRESS) 728 if (ret == -EINPROGRESS)
729 return NULL; 729 return NULL;
730
731 /*
732 * mark descriptor as zero-length and set the 'more'
733 * flag to ensure that both buffers get discarded
734 */
735 rs->rs_datalen = 0;
736 rs->rs_more = true;
730 } 737 }
731 738
732 list_del(&bf->list); 739 list_del(&bf->list);
@@ -933,14 +940,20 @@ static void ath9k_process_rssi(struct ath_common *common,
933 * up the frame up to let mac80211 handle the actual error case, be it no 940 * up the frame up to let mac80211 handle the actual error case, be it no
934 * decryption key or real decryption error. This let us keep statistics there. 941 * decryption key or real decryption error. This let us keep statistics there.
935 */ 942 */
936static int ath9k_rx_skb_preprocess(struct ath_common *common, 943static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
937 struct ieee80211_hw *hw,
938 struct ieee80211_hdr *hdr, 944 struct ieee80211_hdr *hdr,
939 struct ath_rx_status *rx_stats, 945 struct ath_rx_status *rx_stats,
940 struct ieee80211_rx_status *rx_status, 946 struct ieee80211_rx_status *rx_status,
941 bool *decrypt_error) 947 bool *decrypt_error)
942{ 948{
943 struct ath_hw *ah = common->ah; 949 struct ieee80211_hw *hw = sc->hw;
950 struct ath_hw *ah = sc->sc_ah;
951 struct ath_common *common = ath9k_hw_common(ah);
952 bool discard_current = sc->rx.discard_next;
953
954 sc->rx.discard_next = rx_stats->rs_more;
955 if (discard_current)
956 return -EINVAL;
944 957
945 /* 958 /*
946 * everything but the rate is checked here, the rate check is done 959 * everything but the rate is checked here, the rate check is done
@@ -966,6 +979,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
966 if (rx_stats->rs_moreaggr) 979 if (rx_stats->rs_moreaggr)
967 rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; 980 rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
968 981
982 sc->rx.discard_next = false;
969 return 0; 983 return 0;
970} 984}
971 985
@@ -1243,8 +1257,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
1243 } 1257 }
1244 } 1258 }
1245 1259
1246 retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, 1260 retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
1247 rxs, &decrypt_error); 1261 &decrypt_error);
1248 if (retval) 1262 if (retval)
1249 goto requeue_drop_frag; 1263 goto requeue_drop_frag;
1250 1264