aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2013-08-10 14:04:15 +0000
committerFelix Fietkau <nbd@openwrt.org>2013-08-10 14:04:15 +0000
commit4c1bfdf69de4eef149daff20f2991b1734529956 (patch)
tree734a9d78ac2e63d7fe49a6da2c3e60192cfbd804
parent7254772e91955d8454ad64e66145fb119826df5d (diff)
downloadupstream-4c1bfdf69de4eef149daff20f2991b1734529956.tar.gz
upstream-4c1bfdf69de4eef149daff20f2991b1734529956.tar.bz2
upstream-4c1bfdf69de4eef149daff20f2991b1734529956.zip
ath9k: fix an rx descriptor processing race condition
Signed-off-by: Felix Fietkau <nbd@openwrt.org> Backport of r37746 git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@37747 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--package/mac80211/patches/556-ath9k_fix_rx_race.patch82
-rw-r--r--package/mac80211/patches/560-ath9k_tx_queueing_rework.patch12
2 files changed, 88 insertions, 6 deletions
diff --git a/package/mac80211/patches/556-ath9k_fix_rx_race.patch b/package/mac80211/patches/556-ath9k_fix_rx_race.patch
new file mode 100644
index 0000000000..69030d27a3
--- /dev/null
+++ b/package/mac80211/patches/556-ath9k_fix_rx_race.patch
@@ -0,0 +1,82 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -79,10 +79,6 @@ struct ath_config {
+ sizeof(struct ath_buf_state)); \
+ } while (0)
+
+-#define ATH_RXBUF_RESET(_bf) do { \
+- (_bf)->bf_stale = false; \
+- } while (0)
+-
+ /**
+ * enum buffer_type - Buffer type flags
+ *
+@@ -317,6 +313,7 @@ struct ath_rx {
+ struct ath_descdma rxdma;
+ struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
+
++ struct ath_buf *buf_hold;
+ struct sk_buff *frag;
+
+ u32 ampdu_ref;
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -42,8 +42,6 @@ static void ath_rx_buf_link(struct ath_s
+ struct ath_desc *ds;
+ struct sk_buff *skb;
+
+- ATH_RXBUF_RESET(bf);
+-
+ ds = bf->bf_desc;
+ ds->ds_link = 0; /* link to null */
+ ds->ds_data = bf->bf_buf_addr;
+@@ -70,6 +68,14 @@ static void ath_rx_buf_link(struct ath_s
+ sc->rx.rxlink = &ds->ds_link;
+ }
+
++static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf)
++{
++ if (sc->rx.buf_hold)
++ ath_rx_buf_link(sc, sc->rx.buf_hold);
++
++ sc->rx.buf_hold = bf;
++}
++
+ static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
+ {
+ /* XXX block beacon interrupts */
+@@ -117,7 +123,6 @@ static bool ath_rx_edma_buf_link(struct
+
+ skb = bf->bf_mpdu;
+
+- ATH_RXBUF_RESET(bf);
+ memset(skb->data, 0, ah->caps.rx_status_len);
+ dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+ ah->caps.rx_status_len, DMA_TO_DEVICE);
+@@ -432,6 +437,7 @@ int ath_startrecv(struct ath_softc *sc)
+ if (list_empty(&sc->rx.rxbuf))
+ goto start_recv;
+
++ sc->rx.buf_hold = NULL;
+ sc->rx.rxlink = NULL;
+ list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
+ ath_rx_buf_link(sc, bf);
+@@ -677,6 +683,9 @@ static struct ath_buf *ath_get_next_rx_b
+ }
+
+ bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
++ if (bf == sc->rx.buf_hold)
++ return NULL;
++
+ ds = bf->bf_desc;
+
+ /*
+@@ -1391,7 +1400,7 @@ requeue:
+ if (edma) {
+ ath_rx_edma_buf_link(sc, qtype);
+ } else {
+- ath_rx_buf_link(sc, bf);
++ ath_rx_buf_relink(sc, bf);
+ ath9k_hw_rxena(ah);
+ }
+ } while (1);
diff --git a/package/mac80211/patches/560-ath9k_tx_queueing_rework.patch b/package/mac80211/patches/560-ath9k_tx_queueing_rework.patch
index 814bca81a6..c5bcbbedfc 100644
--- a/package/mac80211/patches/560-ath9k_tx_queueing_rework.patch
+++ b/package/mac80211/patches/560-ath9k_tx_queueing_rework.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -137,7 +137,8 @@ int ath_descdma_setup(struct ath_softc *
+@@ -133,7 +133,8 @@ int ath_descdma_setup(struct ath_softc *
#define ATH_AGGR_ENCRYPTDELIM 10
/* minimum h/w qdepth to be sustained to maximize aggregation */
#define ATH_AGGR_MIN_QDEPTH 2
@@ -10,7 +10,7 @@
#define IEEE80211_SEQ_SEQ_SHIFT 4
#define IEEE80211_SEQ_MAX 4096
-@@ -174,12 +175,6 @@ int ath_descdma_setup(struct ath_softc *
+@@ -170,12 +171,6 @@ int ath_descdma_setup(struct ath_softc *
#define ATH_TX_COMPLETE_POLL_INT 1000
@@ -23,7 +23,7 @@
#define ATH_TXFIFO_DEPTH 8
struct ath_txq {
int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
-@@ -212,8 +207,9 @@ struct ath_frame_info {
+@@ -208,8 +203,9 @@ struct ath_frame_info {
int framelen;
enum ath9k_key_type keytype;
u8 keyix;
@@ -34,7 +34,7 @@
};
struct ath_buf_state {
-@@ -241,6 +237,7 @@ struct ath_buf {
+@@ -237,6 +233,7 @@ struct ath_buf {
struct ath_atx_tid {
struct list_head list;
struct sk_buff_head buf_q;
@@ -42,7 +42,7 @@
struct ath_node *an;
struct ath_atx_ac *ac;
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
-@@ -268,6 +265,7 @@ struct ath_node {
+@@ -264,6 +261,7 @@ struct ath_node {
u8 mpdudensity;
bool sleeping;
@@ -50,7 +50,7 @@
#if defined(CPTCFG_MAC80211_DEBUGFS) && defined(CPTCFG_ATH9K_DEBUGFS)
struct dentry *node_stat;
-@@ -367,6 +365,7 @@ void ath9k_release_buffered_frames(struc
+@@ -364,6 +362,7 @@ void ath9k_release_buffered_frames(struc
/********/
struct ath_vif {