This is a note to let you know that I've just added the patch titled
ath9k: fix invalid descriptor discarding
to the 3.13-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ath9k-fix-invalid-descriptor-discarding.patch
and it can be found in the queue-3.13 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <[email protected]> know about it.
>From b7b146c9c9a0248cc57da71244f672ebc54bbef1 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <[email protected]>
Date: Mon, 24 Feb 2014 22:26:06 +0100
Subject: ath9k: fix invalid descriptor discarding
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From: Felix Fietkau <[email protected]>
commit b7b146c9c9a0248cc57da71244f672ebc54bbef1 upstream.
Only set sc->rx.discard_next to rx_stats->rs_more when actually
discarding the current descriptor.
Also, fix a detection of broken descriptors:
First the code checks if the current descriptor is not done.
Then it checks if the next descriptor is done.
Add a check that afterwards checks the first descriptor again, because
it might have been completed in the mean time.
This fixes a regression introduced in
commit 723e711356b5a8a95728a890e254e8b0d47b55cf
"ath9k: fix handling of broken descriptors"
Reported-by: Marco André Dinis <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/ath/ath9k/recv.c | 70 +++++++++++++++++-----------------
1 file changed, 35 insertions(+), 35 deletions(-)
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -733,11 +733,18 @@ static struct ath_rxbuf *ath_get_next_rx
return NULL;
/*
- * mark descriptor as zero-length and set the 'more'
- * flag to ensure that both buffers get discarded
+ * Re-check previous descriptor, in case it has been filled
+ * in the mean time.
*/
- rs->rs_datalen = 0;
- rs->rs_more = true;
+ ret = ath9k_hw_rxprocdesc(ah, ds, rs);
+ if (ret == -EINPROGRESS) {
+ /*
+ * mark descriptor as zero-length and set the 'more'
+ * flag to ensure that both buffers get discarded
+ */
+ rs->rs_datalen = 0;
+ rs->rs_more = true;
+ }
}
list_del(&bf->list);
@@ -1166,32 +1173,32 @@ static int ath9k_rx_skb_preprocess(struc
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_hdr *hdr;
bool discard_current = sc->rx.discard_next;
- int ret = 0;
/*
* Discard corrupt descriptors which are marked in
* ath_get_next_rx_buf().
*/
- sc->rx.discard_next = rx_stats->rs_more;
if (discard_current)
- return -EINVAL;
+ goto corrupt;
+
+ sc->rx.discard_next = false;
/*
* Discard zero-length packets.
*/
if (!rx_stats->rs_datalen) {
RX_STAT_INC(rx_len_err);
- return -EINVAL;
+ goto corrupt;
}
- /*
- * rs_status follows rs_datalen so if rs_datalen is too large
- * we can take a hint that hardware corrupted it, so ignore
- * those frames.
- */
+ /*
+ * rs_status follows rs_datalen so if rs_datalen is too large
+ * we can take a hint that hardware corrupted it, so ignore
+ * those frames.
+ */
if (rx_stats->rs_datalen > (common->rx_bufsize -
ah->caps.rx_status_len)) {
RX_STAT_INC(rx_len_err);
- return -EINVAL;
+ goto corrupt;
}
/* Only use status info from the last fragment */
@@ -1205,10 +1212,8 @@ static int ath9k_rx_skb_preprocess(struc
* This is different from the other corrupt descriptor
* condition handled above.
*/
- if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) {
- ret = -EINVAL;
- goto exit;
- }
+ if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC)
+ goto corrupt;
hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
@@ -1224,18 +1229,15 @@ static int ath9k_rx_skb_preprocess(struc
if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
RX_STAT_INC(rx_spectral);
- ret = -EINVAL;
- goto exit;
+ return -EINVAL;
}
/*
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
*/
- if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
- ret = -EINVAL;
- goto exit;
- }
+ if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
+ return -EINVAL;
rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr);
if (rx_stats->is_mybeacon) {
@@ -1246,15 +1248,11 @@ static int ath9k_rx_skb_preprocess(struc
/*
* This shouldn't happen, but have a safety check anyway.
*/
- if (WARN_ON(!ah->curchan)) {
- ret = -EINVAL;
- goto exit;
- }
+ if (WARN_ON(!ah->curchan))
+ return -EINVAL;
- if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
- ret =-EINVAL;
- goto exit;
- }
+ if (ath9k_process_rate(common, hw, rx_stats, rx_status))
+ return -EINVAL;
ath9k_process_rssi(common, hw, rx_stats, rx_status);
@@ -1269,9 +1267,11 @@ static int ath9k_rx_skb_preprocess(struc
sc->rx.num_pkts++;
#endif
-exit:
- sc->rx.discard_next = false;
- return ret;
+ return 0;
+
+corrupt:
+ sc->rx.discard_next = rx_stats->rs_more;
+ return -EINVAL;
}
static void ath9k_rx_skb_postprocess(struct ath_common *common,
Patches currently in stable-queue which might be from [email protected] are
queue-3.13/ath9k-fix-ps-poll-responses-under-a-mpdu-sessions.patch
queue-3.13/mac80211-send-control-port-protocol-frames-to-the-vo-queue.patch
queue-3.13/ath9k-fix-invalid-descriptor-discarding.patch
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html