ath9k: use separate HW queue for each channel context

Use seperate tx queue for each AC in each channel context and expose
these information to mac80211 to avoid stopping one channel context
leads to stopping the entire traffic for that AC even on other contexts.

Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index a422c20..d4927c9 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -156,7 +156,8 @@
 static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
 			     struct sk_buff *skb)
 {
-	int q;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	int q, hw_queue;
 
 	q = skb_get_queue_mapping(skb);
 	if (txq == sc->tx.uapsdq)
@@ -168,9 +169,10 @@
 	if (WARN_ON(--txq->pending_frames < 0))
 		txq->pending_frames = 0;
 
+	hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
 	if (txq->stopped &&
 	    txq->pending_frames < sc->tx.txq_max_pending[q]) {
-		ieee80211_wake_queue(sc->hw, q);
+		ieee80211_wake_queue(sc->hw, hw_queue);
 		txq->stopped = false;
 	}
 }
@@ -2191,7 +2193,7 @@
 	struct ath_atx_tid *tid = NULL;
 	struct ath_buf *bf;
 	bool queue;
-	int q;
+	int q, hw_queue;
 	int ret;
 
 	if (vif)
@@ -2211,12 +2213,13 @@
 	 */
 
 	q = skb_get_queue_mapping(skb);
+	hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
 
 	ath_txq_lock(sc, txq);
 	if (txq == sc->tx.txq_map[q] &&
 	    ++txq->pending_frames > sc->tx.txq_max_pending[q] &&
 	    !txq->stopped) {
-		ieee80211_stop_queue(sc->hw, q);
+		ieee80211_stop_queue(sc->hw, hw_queue);
 		txq->stopped = true;
 	}