]> Pileus Git - ~andy/linux/blobdiff - net/mac80211/util.c
xen-netback: coalesce slots in TX path and fix regressions
[~andy/linux] / net / mac80211 / util.c
index 0f38f43ac62eac316434c60614694d41efed09ff..a7368870c8ee10cf7ee48dc764bc466974eac8ae 100644 (file)
@@ -453,7 +453,8 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
 }
 
 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
-                                   enum queue_stop_reason reason)
+                                    unsigned long queues,
+                                    enum queue_stop_reason reason)
 {
        struct ieee80211_local *local = hw_to_local(hw);
        unsigned long flags;
@@ -461,7 +462,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
 
        spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 
-       for (i = 0; i < hw->queues; i++)
+       for_each_set_bit(i, &queues, hw->queues)
                __ieee80211_stop_queue(hw, i, reason);
 
        spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
@@ -469,7 +470,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
 
 void ieee80211_stop_queues(struct ieee80211_hw *hw)
 {
-       ieee80211_stop_queues_by_reason(hw,
+       ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
                                        IEEE80211_QUEUE_STOP_REASON_DRIVER);
 }
 EXPORT_SYMBOL(ieee80211_stop_queues);
@@ -491,6 +492,7 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
 EXPORT_SYMBOL(ieee80211_queue_stopped);
 
 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
+                                    unsigned long queues,
                                     enum queue_stop_reason reason)
 {
        struct ieee80211_local *local = hw_to_local(hw);
@@ -499,7 +501,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 
        spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 
-       for (i = 0; i < hw->queues; i++)
+       for_each_set_bit(i, &queues, hw->queues)
                __ieee80211_wake_queue(hw, i, reason);
 
        spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
@@ -507,10 +509,42 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 
 void ieee80211_wake_queues(struct ieee80211_hw *hw)
 {
-       ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER);
+       ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
+                                       IEEE80211_QUEUE_STOP_REASON_DRIVER);
 }
 EXPORT_SYMBOL(ieee80211_wake_queues);
 
+void ieee80211_flush_queues(struct ieee80211_local *local,
+                           struct ieee80211_sub_if_data *sdata)
+{
+       u32 queues;
+
+       if (!local->ops->flush)
+               return;
+
+       if (sdata && local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) {
+               int ac;
+
+               queues = 0;
+
+               for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+                       queues |= BIT(sdata->vif.hw_queue[ac]);
+               if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
+                       queues |= BIT(sdata->vif.cab_queue);
+       } else {
+               /* all queues */
+               queues = BIT(local->hw.queues) - 1;
+       }
+
+       ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
+                                       IEEE80211_QUEUE_STOP_REASON_FLUSH);
+
+       drv_flush(local, queues, false);
+
+       ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
+                                       IEEE80211_QUEUE_STOP_REASON_FLUSH);
+}
+
 void ieee80211_iterate_active_interfaces(
        struct ieee80211_hw *hw, u32 iter_flags,
        void (*iterator)(void *data, u8 *mac,
@@ -1357,6 +1391,25 @@ void ieee80211_stop_device(struct ieee80211_local *local)
        drv_stop(local);
 }
 
+static void ieee80211_assign_chanctx(struct ieee80211_local *local,
+                                    struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_chanctx_conf *conf;
+       struct ieee80211_chanctx *ctx;
+
+       if (!local->use_chanctx)
+               return;
+
+       mutex_lock(&local->chanctx_mtx);
+       conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+                                        lockdep_is_held(&local->chanctx_mtx));
+       if (conf) {
+               ctx = container_of(conf, struct ieee80211_chanctx, conf);
+               drv_assign_vif_chanctx(local, sdata, ctx);
+       }
+       mutex_unlock(&local->chanctx_mtx);
+}
+
 int ieee80211_reconfig(struct ieee80211_local *local)
 {
        struct ieee80211_hw *hw = &local->hw;
@@ -1445,36 +1498,14 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        }
 
        list_for_each_entry(sdata, &local->interfaces, list) {
-               struct ieee80211_chanctx_conf *ctx_conf;
-
                if (!ieee80211_sdata_running(sdata))
                        continue;
-
-               mutex_lock(&local->chanctx_mtx);
-               ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
-                               lockdep_is_held(&local->chanctx_mtx));
-               if (ctx_conf) {
-                       ctx = container_of(ctx_conf, struct ieee80211_chanctx,
-                                          conf);
-                       drv_assign_vif_chanctx(local, sdata, ctx);
-               }
-               mutex_unlock(&local->chanctx_mtx);
+               ieee80211_assign_chanctx(local, sdata);
        }
 
        sdata = rtnl_dereference(local->monitor_sdata);
-       if (sdata && local->use_chanctx && ieee80211_sdata_running(sdata)) {
-               struct ieee80211_chanctx_conf *ctx_conf;
-
-               mutex_lock(&local->chanctx_mtx);
-               ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
-                               lockdep_is_held(&local->chanctx_mtx));
-               if (ctx_conf) {
-                       ctx = container_of(ctx_conf, struct ieee80211_chanctx,
-                                          conf);
-                       drv_assign_vif_chanctx(local, sdata, ctx);
-               }
-               mutex_unlock(&local->chanctx_mtx);
-       }
+       if (sdata && ieee80211_sdata_running(sdata))
+               ieee80211_assign_chanctx(local, sdata);
 
        /* add STAs back */
        mutex_lock(&local->sta_mtx);
@@ -1534,11 +1565,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                          BSS_CHANGED_IDLE |
                          BSS_CHANGED_TXPOWER;
 
-#ifdef CONFIG_PM
-               if (local->resuming && !reconfig_due_to_wowlan)
-                       sdata->vif.bss_conf = sdata->suspend_bss_conf;
-#endif
-
                switch (sdata->vif.type) {
                case NL80211_IFTYPE_STATION:
                        changed |= BSS_CHANGED_ASSOC |
@@ -1659,8 +1685,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                mutex_unlock(&local->sta_mtx);
        }
 
-       ieee80211_wake_queues_by_reason(hw,
-                       IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+       ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
+                                       IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
        /*
         * If this is for hw restart things are still running.
@@ -1678,28 +1704,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        mb();
        local->resuming = false;
 
-       list_for_each_entry(sdata, &local->interfaces, list) {
-               switch(sdata->vif.type) {
-               case NL80211_IFTYPE_STATION:
-                       ieee80211_sta_restart(sdata);
-                       break;
-               case NL80211_IFTYPE_ADHOC:
-                       ieee80211_ibss_restart(sdata);
-                       break;
-               case NL80211_IFTYPE_MESH_POINT:
-                       ieee80211_mesh_restart(sdata);
-                       break;
-               default:
-                       break;
-               }
-       }
-
        mod_timer(&local->sta_cleanup, jiffies + 1);
-
-       mutex_lock(&local->sta_mtx);
-       list_for_each_entry(sta, &local->sta_list, list)
-               mesh_plink_restart(sta);
-       mutex_unlock(&local->sta_mtx);
 #else
        WARN_ON(1);
 #endif