From 6eeb0261e615e16f05444dd8678c3ab433e7d979 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Sat, 14 Sep 2013 14:46:39 +0000
Subject: [PATCH] ath9k: merge a fix for tx processing issues with aggregation

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

SVN-Revision: 37982
---
 .../mac80211/patches/300-pending_work.patch   | 100 ++++++++++--------
 1 file changed, 54 insertions(+), 46 deletions(-)

diff --git a/package/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch
index de70867c6b..f1a03c7f6b 100644
--- a/package/kernel/mac80211/patches/300-pending_work.patch
+++ b/package/kernel/mac80211/patches/300-pending_work.patch
@@ -573,7 +573,15 @@
  }
  
  static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
-@@ -380,7 +456,6 @@ static void ath_tx_complete_aggr(struct 
+@@ -323,6 +399,7 @@ static struct ath_buf* ath_clone_txbuf(s
+ 	tbf->bf_buf_addr = bf->bf_buf_addr;
+ 	memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
+ 	tbf->bf_state = bf->bf_state;
++	tbf->bf_state.stale = false;
+ 
+ 	return tbf;
+ }
+@@ -380,7 +457,6 @@ static void ath_tx_complete_aggr(struct 
  	struct ieee80211_tx_rate rates[4];
  	struct ath_frame_info *fi;
  	int nframes;
@@ -581,7 +589,7 @@
  	bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
  	int i, retries;
  	int bar_index = -1;
-@@ -406,7 +481,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -406,7 +482,7 @@ static void ath_tx_complete_aggr(struct 
  		while (bf) {
  			bf_next = bf->bf_next;
  
@@ -590,7 +598,7 @@
  				list_move_tail(&bf->list, &bf_head);
  
  			ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
-@@ -417,8 +492,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -417,8 +493,7 @@ static void ath_tx_complete_aggr(struct 
  	}
  
  	an = (struct ath_node *)sta->drv_priv;
@@ -600,7 +608,7 @@
  	seq_first = tid->seq_start;
  	isba = ts->ts_flags & ATH9K_TX_BA;
  
-@@ -430,7 +504,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -430,7 +505,7 @@ static void ath_tx_complete_aggr(struct 
  	 * Only BlockAcks have a TID and therefore normal Acks cannot be
  	 * checked
  	 */
@@ -609,7 +617,7 @@
  		txok = false;
  
  	isaggr = bf_isaggr(bf);
-@@ -466,7 +540,8 @@ static void ath_tx_complete_aggr(struct 
+@@ -466,7 +541,8 @@ static void ath_tx_complete_aggr(struct 
  		tx_info = IEEE80211_SKB_CB(skb);
  		fi = get_frame_info(skb);
  
@@ -619,7 +627,7 @@
  			/*
  			 * Outside of the current BlockAck window,
  			 * maybe part of a previous session
-@@ -499,7 +574,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -499,7 +575,7 @@ static void ath_tx_complete_aggr(struct 
  		 * not a holding desc.
  		 */
  		INIT_LIST_HEAD(&bf_head);
@@ -628,7 +636,7 @@
  			list_move_tail(&bf->list, &bf_head);
  
  		if (!txpending) {
-@@ -523,7 +598,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -523,7 +599,7 @@ static void ath_tx_complete_aggr(struct 
  				ieee80211_sta_eosp(sta);
  			}
  			/* retry the un-acked ones */
@@ -637,7 +645,7 @@
  				struct ath_buf *tbf;
  
  				tbf = ath_clone_txbuf(sc, bf_last);
-@@ -560,7 +635,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -560,7 +636,7 @@ static void ath_tx_complete_aggr(struct 
  		if (an->sleeping)
  			ieee80211_sta_set_buffered(sta, tid->tidno, true);
  
@@ -646,7 +654,7 @@
  		if (!an->sleeping) {
  			ath_tx_queue_tid(txq, tid);
  
-@@ -618,7 +693,7 @@ static void ath_tx_process_buffer(struct
+@@ -618,7 +694,7 @@ static void ath_tx_process_buffer(struct
  	} else
  		ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok);
  
@@ -655,7 +663,7 @@
  		ath_txq_schedule(sc, txq);
  }
  
-@@ -792,15 +867,20 @@ static int ath_compute_num_delims(struct
+@@ -792,15 +868,20 @@ static int ath_compute_num_delims(struct
  
  static struct ath_buf *
  ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
@@ -678,7 +686,7 @@
  		if (!skb)
  			break;
  
-@@ -808,13 +888,26 @@ ath_tx_get_tid_subframe(struct ath_softc
+@@ -808,13 +889,26 @@ ath_tx_get_tid_subframe(struct ath_softc
  		bf = fi->bf;
  		if (!fi->bf)
  			bf = ath_tx_setup_buffer(sc, txq, tid, skb);
@@ -706,7 +714,7 @@
  		bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
  		seqno = bf->bf_state.seqno;
  
-@@ -828,73 +921,52 @@ ath_tx_get_tid_subframe(struct ath_softc
+@@ -828,73 +922,52 @@ ath_tx_get_tid_subframe(struct ath_softc
  
  			INIT_LIST_HEAD(&bf_head);
  			list_add(&bf->list, &bf_head);
@@ -801,7 +809,7 @@
  		}
  
  		/* add padding for previous frame to aggregation length */
-@@ -912,22 +984,37 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+@@ -912,22 +985,37 @@ static enum ATH_AGGR_STATUS ath_tx_form_
  		bf->bf_next = NULL;
  
  		/* link buffers of this frame to the aggregate */
@@ -844,7 +852,7 @@
  #undef PADBYTES
  }
  
-@@ -999,7 +1086,7 @@ void ath_update_max_aggr_framelen(struct
+@@ -999,7 +1087,7 @@ void ath_update_max_aggr_framelen(struct
  }
  
  static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
@@ -853,7 +861,7 @@
  {
  	struct ath_hw *ah = sc->sc_ah;
  	struct sk_buff *skb;
-@@ -1008,6 +1095,7 @@ static void ath_buf_set_rate(struct ath_
+@@ -1008,6 +1096,7 @@ static void ath_buf_set_rate(struct ath_
  	const struct ieee80211_rate *rate;
  	struct ieee80211_hdr *hdr;
  	struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
@@ -861,7 +869,7 @@
  	int i;
  	u8 rix = 0;
  
-@@ -1030,7 +1118,17 @@ static void ath_buf_set_rate(struct ath_
+@@ -1030,7 +1119,17 @@ static void ath_buf_set_rate(struct ath_
  		rix = rates[i].idx;
  		info->rates[i].Tries = rates[i].count;
  
@@ -880,7 +888,7 @@
  			info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
  			info->flags |= ATH9K_TXDESC_RTSENA;
  		} else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-@@ -1123,6 +1221,8 @@ static void ath_tx_fill_desc(struct ath_
+@@ -1123,6 +1222,8 @@ static void ath_tx_fill_desc(struct ath_
  	struct ath_hw *ah = sc->sc_ah;
  	struct ath_buf *bf_first = NULL;
  	struct ath_tx_info info;
@@ -889,7 +897,7 @@
  
  	memset(&info, 0, sizeof(info));
  	info.is_first = true;
-@@ -1159,7 +1259,22 @@ static void ath_tx_fill_desc(struct ath_
+@@ -1159,7 +1260,22 @@ static void ath_tx_fill_desc(struct ath_
  				info.flags |= (u32) bf->bf_state.bfs_paprd <<
  					      ATH9K_TXDESC_PAPRD_S;
  
@@ -913,7 +921,7 @@
  		}
  
  		info.buf_addr[0] = bf->bf_buf_addr;
-@@ -1188,53 +1303,86 @@ static void ath_tx_fill_desc(struct ath_
+@@ -1188,53 +1304,86 @@ static void ath_tx_fill_desc(struct ath_
  	}
  }
  
@@ -1035,7 +1043,7 @@
  }
  
  int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-@@ -1258,6 +1406,9 @@ int ath_tx_aggr_start(struct ath_softc *
+@@ -1258,6 +1407,9 @@ int ath_tx_aggr_start(struct ath_softc *
  		an->mpdudensity = density;
  	}
  
@@ -1045,7 +1053,7 @@
  	txtid->active = true;
  	txtid->paused = true;
  	*ssn = txtid->seq_start = txtid->seq_next;
-@@ -1277,8 +1428,9 @@ void ath_tx_aggr_stop(struct ath_softc *
+@@ -1277,8 +1429,9 @@ void ath_tx_aggr_stop(struct ath_softc *
  
  	ath_txq_lock(sc, txq);
  	txtid->active = false;
@@ -1056,7 +1064,7 @@
  	ath_txq_unlock_complete(sc, txq);
  }
  
-@@ -1302,7 +1454,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
+@@ -1302,7 +1455,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
  
  		ath_txq_lock(sc, txq);
  
@@ -1065,7 +1073,7 @@
  
  		tid->sched = false;
  		list_del(&tid->list);
-@@ -1334,7 +1486,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
+@@ -1334,7 +1487,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
  		ath_txq_lock(sc, txq);
  		ac->clear_ps_filter = true;
  
@@ -1074,7 +1082,7 @@
  			ath_tx_queue_tid(txq, tid);
  			ath_txq_schedule(sc, txq);
  		}
-@@ -1359,7 +1511,7 @@ void ath_tx_aggr_resume(struct ath_softc
+@@ -1359,7 +1512,7 @@ void ath_tx_aggr_resume(struct ath_softc
  	tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
  	tid->paused = false;
  
@@ -1083,7 +1091,7 @@
  		ath_tx_queue_tid(txq, tid);
  		ath_txq_schedule(sc, txq);
  	}
-@@ -1379,6 +1531,7 @@ void ath9k_release_buffered_frames(struc
+@@ -1379,6 +1532,7 @@ void ath9k_release_buffered_frames(struc
  	struct ieee80211_tx_info *info;
  	struct list_head bf_q;
  	struct ath_buf *bf_tail = NULL, *bf;
@@ -1091,7 +1099,7 @@
  	int sent = 0;
  	int i;
  
-@@ -1394,15 +1547,15 @@ void ath9k_release_buffered_frames(struc
+@@ -1394,15 +1548,15 @@ void ath9k_release_buffered_frames(struc
  			continue;
  
  		ath_txq_lock(sc, tid->ac->txq);
@@ -1111,7 +1119,7 @@
  			bf->bf_state.bf_type &= ~BUF_AGGR;
  			if (bf_tail)
  				bf_tail->bf_next = bf;
-@@ -1412,7 +1565,7 @@ void ath9k_release_buffered_frames(struc
+@@ -1412,7 +1566,7 @@ void ath9k_release_buffered_frames(struc
  			sent++;
  			TX_STAT_INC(txq->axq_qnum, a_queued_hw);
  
@@ -1120,7 +1128,7 @@
  				ieee80211_sta_set_buffered(an->sta, i, false);
  		}
  		ath_txq_unlock_complete(sc, tid->ac->txq);
-@@ -1571,7 +1724,7 @@ static void ath_drain_txq_list(struct at
+@@ -1571,7 +1725,7 @@ static void ath_drain_txq_list(struct at
  	while (!list_empty(list)) {
  		bf = list_first_entry(list, struct ath_buf, list);
  
@@ -1129,7 +1137,7 @@
  			list_del(&bf->list);
  
  			ath_tx_return_buffer(sc, bf);
-@@ -1665,25 +1818,27 @@ void ath_tx_cleanupq(struct ath_softc *s
+@@ -1665,25 +1819,27 @@ void ath_tx_cleanupq(struct ath_softc *s
   */
  void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
  {
@@ -1162,7 +1170,7 @@
  			tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
  					       list);
  			list_del(&tid->list);
-@@ -1692,17 +1847,17 @@ void ath_txq_schedule(struct ath_softc *
+@@ -1692,17 +1848,17 @@ void ath_txq_schedule(struct ath_softc *
  			if (tid->paused)
  				continue;
  
@@ -1184,7 +1192,7 @@
  				break;
  		}
  
-@@ -1711,9 +1866,17 @@ void ath_txq_schedule(struct ath_softc *
+@@ -1711,9 +1867,17 @@ void ath_txq_schedule(struct ath_softc *
  			list_add_tail(&ac->list, &txq->axq_acq);
  		}
  
@@ -1204,7 +1212,7 @@
  	}
  
  	rcu_read_unlock();
-@@ -1792,57 +1955,6 @@ static void ath_tx_txqaddbuf(struct ath_
+@@ -1792,57 +1956,6 @@ static void ath_tx_txqaddbuf(struct ath_
  	}
  }
  
@@ -1262,7 +1270,7 @@
  static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
  			       struct ath_atx_tid *tid, struct sk_buff *skb)
  {
-@@ -1985,6 +2097,7 @@ static int ath_tx_prepare(struct ieee802
+@@ -1985,6 +2098,7 @@ static int ath_tx_prepare(struct ieee802
  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  	struct ieee80211_sta *sta = txctl->sta;
  	struct ieee80211_vif *vif = info->control.vif;
@@ -1270,7 +1278,7 @@
  	struct ath_softc *sc = hw->priv;
  	int frmlen = skb->len + FCS_LEN;
  	int padpos, padsize;
-@@ -1992,6 +2105,10 @@ static int ath_tx_prepare(struct ieee802
+@@ -1992,6 +2106,10 @@ static int ath_tx_prepare(struct ieee802
  	/* NOTE:  sta can be NULL according to net/mac80211.h */
  	if (sta)
  		txctl->an = (struct ath_node *)sta->drv_priv;
@@ -1281,7 +1289,7 @@
  
  	if (info->control.hw_key)
  		frmlen += info->control.hw_key->icv_len;
-@@ -2041,7 +2158,6 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -2041,7 +2159,6 @@ int ath_tx_start(struct ieee80211_hw *hw
  	struct ath_txq *txq = txctl->txq;
  	struct ath_atx_tid *tid = NULL;
  	struct ath_buf *bf;
@@ -1289,7 +1297,7 @@
  	int q;
  	int ret;
  
-@@ -2069,27 +2185,31 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -2069,27 +2186,31 @@ int ath_tx_start(struct ieee80211_hw *hw
  		ath_txq_unlock(sc, txq);
  		txq = sc->tx.uapsdq;
  		ath_txq_lock(sc, txq);
@@ -1332,7 +1340,7 @@
  		if (txctl->paprd)
  			dev_kfree_skb_any(skb);
  		else
-@@ -2142,7 +2262,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
+@@ -2142,7 +2263,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
  
  		bf->bf_lastbf = bf;
  		ath_set_rates(vif, NULL, bf);
@@ -1341,7 +1349,7 @@
  		duration += info.rates[0].PktDuration;
  		if (bf_tail)
  			bf_tail->bf_next = bf;
-@@ -2189,7 +2309,7 @@ static void ath_tx_complete(struct ath_s
+@@ -2189,7 +2310,7 @@ static void ath_tx_complete(struct ath_s
  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
  	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
  	struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
@@ -1350,7 +1358,7 @@
  	unsigned long flags;
  
  	ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
-@@ -2225,21 +2345,7 @@ static void ath_tx_complete(struct ath_s
+@@ -2225,21 +2346,7 @@ static void ath_tx_complete(struct ath_s
  	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
  
  	__skb_queue_tail(&txq->complete_q, skb);
@@ -1373,7 +1381,7 @@
  }
  
  static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
-@@ -2360,8 +2466,7 @@ static void ath_tx_processq(struct ath_s
+@@ -2360,8 +2467,7 @@ static void ath_tx_processq(struct ath_s
  
  		if (list_empty(&txq->axq_q)) {
  			txq->axq_link = NULL;
@@ -1383,7 +1391,7 @@
  			break;
  		}
  		bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
-@@ -2375,7 +2480,7 @@ static void ath_tx_processq(struct ath_s
+@@ -2375,7 +2481,7 @@ static void ath_tx_processq(struct ath_s
  		 * it with the STALE flag.
  		 */
  		bf_held = NULL;
@@ -1392,7 +1400,7 @@
  			bf_held = bf;
  			if (list_is_last(&bf_held->list, &txq->axq_q))
  				break;
-@@ -2399,7 +2504,7 @@ static void ath_tx_processq(struct ath_s
+@@ -2399,7 +2505,7 @@ static void ath_tx_processq(struct ath_s
  		 * however leave the last descriptor back as the holding
  		 * descriptor for hw.
  		 */
@@ -1401,7 +1409,7 @@
  		INIT_LIST_HEAD(&bf_head);
  		if (!list_is_singular(&lastbf->list))
  			list_cut_position(&bf_head,
-@@ -2470,7 +2575,7 @@ void ath_tx_edma_tasklet(struct ath_soft
+@@ -2470,7 +2576,7 @@ void ath_tx_edma_tasklet(struct ath_soft
  		}
  
  		bf = list_first_entry(fifo_list, struct ath_buf, list);
@@ -1410,7 +1418,7 @@
  			list_del(&bf->list);
  			ath_tx_return_buffer(sc, bf);
  			bf = list_first_entry(fifo_list, struct ath_buf, list);
-@@ -2492,7 +2597,7 @@ void ath_tx_edma_tasklet(struct ath_soft
+@@ -2492,7 +2598,7 @@ void ath_tx_edma_tasklet(struct ath_soft
  				ath_tx_txqaddbuf(sc, txq, &bf_q, true);
  			}
  		} else {
@@ -1419,7 +1427,7 @@
  			if (bf != lastbf)
  				list_cut_position(&bf_head, fifo_list,
  						  lastbf->list.prev);
-@@ -2583,6 +2688,7 @@ void ath_tx_node_init(struct ath_softc *
+@@ -2583,6 +2689,7 @@ void ath_tx_node_init(struct ath_softc *
  		tid->paused    = false;
  		tid->active	   = false;
  		__skb_queue_head_init(&tid->buf_q);
@@ -1427,7 +1435,7 @@
  		acno = TID_TO_WME_AC(tidno);
  		tid->ac = &an->ac[acno];
  	}
-@@ -2590,6 +2696,7 @@ void ath_tx_node_init(struct ath_softc *
+@@ -2590,6 +2697,7 @@ void ath_tx_node_init(struct ath_softc *
  	for (acno = 0, ac = &an->ac[acno];
  	     acno < IEEE80211_NUM_ACS; acno++, ac++) {
  		ac->sched    = false;
-- 
2.30.2