mac80211: Reimplement WME using ->select_queue().

The only behavior change is that we do not drop packets under any
circumstances.  If that is absolutely needed, we could easily add it
back.

With cleanups and help from Johannes Berg.

Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index c74607e..f1a83d4 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -114,7 +114,7 @@
 	if (res)
 		return res;
 
-	netif_start_queue(local->mdev);
+	netif_tx_start_all_queues(local->mdev);
 
 	return 0;
 }
@@ -375,7 +375,7 @@
 		queue_work(local->hw.workqueue, &ifsta->work);
 	}
 
-	netif_start_queue(dev);
+	netif_tx_start_all_queues(dev);
 
 	return 0;
  err_del_interface:
@@ -400,7 +400,7 @@
 	/*
 	 * Stop TX on this interface first.
 	 */
-	netif_stop_queue(dev);
+	netif_tx_stop_all_queues(dev);
 
 	/*
 	 * Now delete all active aggregation sessions.
@@ -554,7 +554,6 @@
 int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
-	struct netdev_queue *txq;
 	struct sta_info *sta;
 	struct ieee80211_sub_if_data *sdata;
 	u16 start_seq_num = 0;
@@ -619,11 +618,6 @@
 			(unsigned long)&sta->timer_to_tid[tid];
 	init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
 
-	/* ensure that TX flow won't interrupt us
-	 * until the end of the call to requeue function */
-	txq = netdev_get_tx_queue(local->mdev, 0);
-	spin_lock_bh(&txq->lock);
-
 	/* create a new queue for this aggregation */
 	ret = ieee80211_ht_agg_queue_add(local, sta, tid);
 
@@ -650,7 +644,7 @@
 		/* No need to requeue the packets in the agg queue, since we
 		 * held the tx lock: no packet could be enqueued to the newly
 		 * allocated queue */
-		 ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
+		ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "BA request denied - HW unavailable for"
 					" tid %d\n", tid);
@@ -661,7 +655,6 @@
 
 	/* Will put all the packets in the new SW queue */
 	ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
-	spin_unlock_bh(&txq->lock);
 	spin_unlock_bh(&sta->lock);
 
 	/* send an addBA request */
@@ -687,7 +680,6 @@
 err_unlock_queue:
 	kfree(sta->ampdu_mlme.tid_tx[tid]);
 	sta->ampdu_mlme.tid_tx[tid] = NULL;
-	spin_unlock_bh(&txq->lock);
 	ret = -EBUSY;
 err_unlock_sta:
 	spin_unlock_bh(&sta->lock);
@@ -812,7 +804,6 @@
 void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
-	struct netdev_queue *txq;
 	struct sta_info *sta;
 	u8 *state;
 	int agg_queue;
@@ -844,8 +835,9 @@
 	state = &sta->ampdu_mlme.tid_state_tx[tid];
 
 	/* NOTE: no need to use sta->lock in this state check, as
-	 * ieee80211_stop_tx_ba_session will let only
-	 * one stop call to pass through per sta/tid */
+	 * ieee80211_stop_tx_ba_session will let only one stop call to
+	 * pass through per sta/tid
+	 */
 	if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
@@ -860,19 +852,14 @@
 
 	agg_queue = sta->tid_to_tx_q[tid];
 
-	/* avoid ordering issues: we are the only one that can modify
-	 * the content of the qdiscs */
-	txq = netdev_get_tx_queue(local->mdev, 0);
-	spin_lock_bh(&txq->lock);
-	/* remove the queue for this aggregation */
 	ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
-	spin_unlock_bh(&txq->lock);
 
-	/* we just requeued the all the frames that were in the removed
-	 * queue, and since we might miss a softirq we do netif_schedule_queue.
-	 * ieee80211_wake_queue is not used here as this queue is not
-	 * necessarily stopped */
-	netif_schedule_queue(txq);
+	/* We just requeued the all the frames that were in the
+	 * removed queue, and since we might miss a softirq we do
+	 * netif_schedule_queue.  ieee80211_wake_queue is not used
+	 * here as this queue is not necessarily stopped
+	 */
+	netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue));
 	spin_lock_bh(&sta->lock);
 	*state = HT_AGG_STATE_IDLE;
 	sta->ampdu_mlme.addba_req_num[tid] = 0;
@@ -1660,17 +1647,12 @@
 	 * We use the number of queues for feature tests (QoS, HT) internally
 	 * so restrict them appropriately.
 	 */
-#ifdef CONFIG_MAC80211_QOS
 	if (hw->queues > IEEE80211_MAX_QUEUES)
 		hw->queues = IEEE80211_MAX_QUEUES;
 	if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES)
 		hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES;
 	if (hw->queues < 4)
 		hw->ampdu_queues = 0;
-#else
-	hw->queues = 1;
-	hw->ampdu_queues = 0;
-#endif
 
 	mdev = alloc_netdev_mq(sizeof(struct wireless_dev),
 			       "wmaster%d", ether_setup,
@@ -1754,7 +1736,7 @@
 		goto fail_wep;
 	}
 
-	ieee80211_install_qdisc(local->mdev);
+	local->mdev->select_queue = ieee80211_select_queue;
 
 	/* add one default STA interface */
 	result = ieee80211_if_add(local, "wlan%d", NULL,
@@ -1852,23 +1834,11 @@
 
 	ret = rc80211_pid_init();
 	if (ret)
-		goto out;
-
-	ret = ieee80211_wme_register();
-	if (ret) {
-		printk(KERN_DEBUG "ieee80211_init: failed to "
-		       "initialize WME (err=%d)\n", ret);
-		goto out_cleanup_pid;
-	}
+		return ret;
 
 	ieee80211_debugfs_netdev_init();
 
 	return 0;
-
- out_cleanup_pid:
-	rc80211_pid_exit();
- out:
-	return ret;
 }
 
 static void __exit ieee80211_exit(void)
@@ -1884,7 +1854,6 @@
 	if (mesh_allocated)
 		ieee80211s_stop();
 
-	ieee80211_wme_unregister();
 	ieee80211_debugfs_netdev_exit();
 }