mac80211: dont allow fragmentation and requeuing on A-MPDU queues

There really is no reason for a driver to reject a frame on
an A-MPDU queue when it can stop that queue for any period
of time and is given frames one by one. Hence, disallow it
with a big warning and reduce mac80211-internal state.

Also add a warning when we try to fragment a frame destined
for an A-MPDU queue and drop it, the actual bug needs to be
fixed elsewhere but I'm not exactly sure how to yet.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Ron Rindjunsky <ron.rindjunsky@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ac9a4af..6268bbc 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -673,6 +673,16 @@
 	if (!(tx->flags & IEEE80211_TX_FRAGMENTED))
 		return TX_CONTINUE;
 
+	/*
+	 * Warn when submitting a fragmented A-MPDU frame and drop it.
+	 * This is an error and needs to be fixed elsewhere, but when
+	 * done needs to take care of monitor interfaces (injection)
+	 * etc.
+	 */
+	if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU ||
+		    IEEE80211_SKB_CB(tx->skb)->queue >= tx->local->hw.queues))
+		return TX_DROP;
+
 	first = tx->skb;
 
 	hdrlen = ieee80211_get_hdrlen(tx->fc);
@@ -1216,8 +1226,17 @@
 retry:
 	ret = __ieee80211_tx(local, skb, &tx);
 	if (ret) {
-		struct ieee80211_tx_stored_packet *store =
-			&local->pending_packet[info->queue];
+		struct ieee80211_tx_stored_packet *store;
+
+		/*
+		 * Since there are no fragmented frames on A-MPDU
+		 * queues, there's no reason for a driver to reject
+		 * a frame there, warn and drop it.
+		 */
+		if (WARN_ON(queue >= local->hw.queues))
+			goto drop;
+
+		store = &local->pending_packet[queue];
 
 		if (ret == IEEE80211_TX_FRAG_AGAIN)
 			skb = NULL;