rt2x00: Implement flush callback
authorIvo van Doorn <ivdoorn@gmail.com>
Thu, 4 Nov 2010 19:40:11 +0000 (20:40 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 15 Nov 2010 18:26:04 +0000 (13:26 -0500)
Implement a basic flush callback function, which simply loops
over all TX queues and waits until all frames have been transmitted
and the status reports have been gathered.

At this moment we don't support dropping any frames during the
flush, but mac80211 will only send 'false' for this argument anyway,
so this is not important at this time.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Helmut Schaa <helmut.schaa@googlemail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c

index c94aa1e5d089cc786ab9b1625e22e41ca450cef0..bc1ae1ebfdb0ced4922f7dc655db9cb9c5c71053 100644 (file)
@@ -1612,6 +1612,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
        .get_tsf                = rt2400pci_get_tsf,
        .tx_last_beacon         = rt2400pci_tx_last_beacon,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
 };
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
index b69e55fedda990a1c12d1db368dfd3ef5dbbddb3..54754150250b2e2f1a192f2842899ad01c9a6e21 100644 (file)
@@ -1909,6 +1909,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
        .get_tsf                = rt2500pci_get_tsf,
        .tx_last_beacon         = rt2500pci_tx_last_beacon,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
 };
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
index f20ab79b2817e61bb491226aa7b4f32da778f4ed..478c4f127ce601bc4be0d128ce19f4ff3e9703ec 100644 (file)
@@ -1801,6 +1801,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
        .bss_info_changed       = rt2x00mac_bss_info_changed,
        .conf_tx                = rt2x00mac_conf_tx,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
 };
 
 static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
index 2c12b598be508c3697cac1fb08632b68e54a2ab5..6dc61b7710b9d494da3dcb1ef021e02ed41399e3 100644 (file)
@@ -943,6 +943,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
        .get_tsf                = rt2800_get_tsf,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
        .ampdu_action           = rt2800_ampdu_action,
+       .flush                  = rt2x00mac_flush,
 };
 
 static const struct rt2800_ops rt2800pci_rt2800_ops = {
index 3f44131baeeeba8ece63dbdee0dd56b9c84a40b6..04dfedc70f85be0c449e82406682e2eb2d72c6f8 100644 (file)
@@ -508,6 +508,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
        .get_tsf                = rt2800_get_tsf,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
        .ampdu_action           = rt2800_ampdu_action,
+       .flush                  = rt2x00mac_flush,
 };
 
 static const struct rt2800_ops rt2800usb_rt2800_ops = {
index 94fe589acfaabff06eac097fe7e3ae3e2f7ea310..42bd3a96f23b8fac6f847a61e04325b8a1c10be5 100644 (file)
@@ -1133,6 +1133,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
                      const struct ieee80211_tx_queue_params *params);
 void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
+void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
 
 /*
  * Driver allocation handlers.
index c3c206a97d54c608da497256a7fcadd44293d9df..283a8d9874ee251a0ba0e1b8d0dfa1ca1e7d6068 100644 (file)
@@ -719,3 +719,41 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
        wiphy_rfkill_set_hw_state(hw->wiphy, !active);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
+
+void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct data_queue *queue;
+       unsigned int i = 0;
+
+       ieee80211_stop_queues(hw);
+
+       /*
+        * Run over all queues to kick them, this will force
+        * any pending frames to be transmitted.
+        */
+       tx_queue_for_each(rt2x00dev, queue) {
+               rt2x00dev->ops->lib->kick_tx_queue(queue);
+       }
+
+       /**
+        * All queues have been kicked, now wait for each queue
+        * to become empty. With a bit of luck, we only have to wait
+        * for the first queue to become empty, because while waiting
+        * for the that queue, the other queues will have transmitted
+        * all their frames as well (since they were already kicked).
+        */
+       tx_queue_for_each(rt2x00dev, queue) {
+               for (i = 0; i < 10; i++) {
+                       if (rt2x00queue_empty(queue))
+                               break;
+                       msleep(100);
+               }
+
+               if (!rt2x00queue_empty(queue))
+                       WARNING(rt2x00dev, "Failed to flush queue %d", queue->qid);
+       }
+
+       ieee80211_wake_queues(hw);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_flush);
index fba9ee11873bb8c7b59aef74233b09221af7a4bf..f01bff7656bc2a5a866fd56e5f9fa1b75955ae65 100644 (file)
@@ -2824,6 +2824,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .conf_tx                = rt61pci_conf_tx,
        .get_tsf                = rt61pci_get_tsf,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
 };
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
index 3c86f0075aed08b288dafd4798a9f3b47d8b6bc3..dcb9211c4771ebe0cc34eaf8db2705e5127fb9e5 100644 (file)
@@ -2264,6 +2264,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
        .conf_tx                = rt73usb_conf_tx,
        .get_tsf                = rt73usb_get_tsf,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
 };
 
 static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {