diff options
| -rw-r--r-- | package/mac80211/patches/300-pending_work.patch | 74 | 
1 files changed, 74 insertions, 0 deletions
| diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index 7558c3d1a..569bf7f06 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -1036,3 +1036,77 @@   		dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",   			MAJOR_VERSION_REQ, MINOR_VERSION_REQ);   		return -EINVAL; +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -516,8 +516,7 @@ static void ath_tx_complete_aggr(struct  + 		 * not a holding desc. + 		 */ + 		INIT_LIST_HEAD(&bf_head); +-		if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) || +-		    bf_next != NULL || !bf_last->bf_stale) ++		if (bf_next != NULL || !bf_last->bf_stale) + 			list_move_tail(&bf->list, &bf_head); +  + 		if (!txpending || (tid->state & AGGR_CLEANUP)) { +@@ -537,8 +536,7 @@ static void ath_tx_complete_aggr(struct  + 				!txfail); + 		} else { + 			/* retry the un-acked ones */ +-			if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && +-			    bf->bf_next == NULL && bf_last->bf_stale) { ++			if (bf->bf_next == NULL && bf_last->bf_stale) { + 				struct ath_buf *tbf; +  + 				tbf = ath_clone_txbuf(sc, bf_last); +@@ -2264,6 +2262,7 @@ void ath_tx_edma_tasklet(struct ath_soft + 	struct ath_txq *txq; + 	struct ath_buf *bf, *lastbf; + 	struct list_head bf_head; ++	struct list_head *fifo_list; + 	int status; +  + 	for (;;) { +@@ -2291,20 +2290,24 @@ void ath_tx_edma_tasklet(struct ath_soft +  + 		TX_STAT_INC(txq->axq_qnum, txprocdesc); +  +-		if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { ++		fifo_list = &txq->txq_fifo[txq->txq_tailidx]; ++		if (list_empty(fifo_list)) { + 			ath_txq_unlock(sc, txq); + 			return; + 		} +  +-		bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx], +-				      struct ath_buf, list); ++		bf = list_first_entry(fifo_list, struct ath_buf, list); ++		if (bf->bf_stale) { ++			list_del(&bf->list); ++			ath_tx_return_buffer(sc, bf); ++			bf = list_first_entry(fifo_list, struct ath_buf, list); ++		} ++ + 		lastbf = bf->bf_lastbf; +  + 		INIT_LIST_HEAD(&bf_head); +-		list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx], +-				  &lastbf->list); +- +-		if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { ++		if (list_is_last(&lastbf->list, fifo_list)) { ++			list_splice_tail_init(fifo_list, &bf_head); + 			INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); +  + 			if (!list_empty(&txq->axq_q)) { +@@ -2315,6 +2318,11 @@ void ath_tx_edma_tasklet(struct ath_soft + 				list_splice_tail_init(&txq->axq_q, &bf_q); + 				ath_tx_txqaddbuf(sc, txq, &bf_q, true); + 			} ++		} else { ++			lastbf->bf_stale = true; ++			if (bf != lastbf) ++				list_cut_position(&bf_head, fifo_list, ++						  lastbf->list.prev); + 		} +  + 		ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head); | 
