aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ibss.c6
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/iface.c4
-rw-r--r--net/mac80211/main.c8
-rw-r--r--net/mac80211/mesh.c10
-rw-r--r--net/mac80211/mesh_hwmp.c4
-rw-r--r--net/mac80211/mlme.c48
-rw-r--r--net/mac80211/pm.c4
-rw-r--r--net/mac80211/scan.c8
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/mac80211/util.c41
11 files changed, 92 insertions, 49 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 6e3cca6..920ec87 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -781,7 +781,7 @@ static void ieee80211_ibss_timer(unsigned long data)
}
set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
- queue_work(local->hw.workqueue, &ifibss->work);
+ ieee80211_queue_work(&local->hw, &ifibss->work);
}
#ifdef CONFIG_PM
@@ -853,7 +853,7 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
case IEEE80211_STYPE_PROBE_REQ:
case IEEE80211_STYPE_AUTH:
skb_queue_tail(&sdata->u.ibss.skb_queue, skb);
- queue_work(local->hw.workqueue, &sdata->u.ibss.work);
+ ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
return RX_QUEUED;
}
@@ -912,7 +912,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_idle(sdata->local);
set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
- queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work);
return 0;
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index aec6853..316825b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -614,6 +614,12 @@ struct ieee80211_local {
const struct ieee80211_ops *ops;
+ /*
+ * private workqueue to mac80211. mac80211 makes this accessible
+ * via ieee80211_queue_work()
+ */
+ struct workqueue_struct *workqueue;
+
unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
/* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
spinlock_t queue_stop_reason_lock;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index a83087f..8c1284d 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -312,7 +312,7 @@ static int ieee80211_open(struct net_device *dev)
* to fix this.
*/
if (sdata->vif.type == NL80211_IFTYPE_STATION)
- queue_work(local->hw.workqueue, &sdata->u.mgd.work);
+ ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
netif_tx_start_all_queues(dev);
@@ -551,7 +551,7 @@ static int ieee80211_stop(struct net_device *dev)
ieee80211_led_radio(local, false);
- flush_workqueue(local->hw.workqueue);
+ flush_workqueue(local->workqueue);
tasklet_disable(&local->tx_pending_tasklet);
tasklet_disable(&local->tasklet);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 5e76dd1..22e0738 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -821,9 +821,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (hw->queues > IEEE80211_MAX_QUEUES)
hw->queues = IEEE80211_MAX_QUEUES;
- local->hw.workqueue =
+ local->workqueue =
create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
- if (!local->hw.workqueue) {
+ if (!local->workqueue) {
result = -ENOMEM;
goto fail_workqueue;
}
@@ -913,7 +913,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
sta_info_stop(local);
fail_sta_info:
debugfs_hw_del(local);
- destroy_workqueue(local->hw.workqueue);
+ destroy_workqueue(local->workqueue);
fail_workqueue:
wiphy_unregister(local->hw.wiphy);
fail_wiphy_register:
@@ -955,7 +955,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
skb_queue_purge(&local->skb_queue);
skb_queue_purge(&local->skb_queue_unreliable);
- destroy_workqueue(local->hw.workqueue);
+ destroy_workqueue(local->workqueue);
wiphy_unregister(local->hw.wiphy);
ieee80211_wep_free(local);
ieee80211_led_exit(local);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 9a38269..2f4f518 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -54,7 +54,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
return;
}
- queue_work(local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
}
/**
@@ -357,7 +357,7 @@ static void ieee80211_mesh_path_timer(unsigned long data)
return;
}
- queue_work(local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
}
struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
@@ -471,7 +471,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local;
ifmsh->housekeeping = true;
- queue_work(local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED);
}
@@ -619,7 +619,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list)
if (ieee80211_vif_is_mesh(&sdata->vif))
- queue_work(local->hw.workqueue, &sdata->u.mesh.work);
+ ieee80211_queue_work(local->hw.workqueue, &sdata->u.mesh.work);
rcu_read_unlock();
}
@@ -692,7 +692,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
skb_queue_tail(&ifmsh->skb_queue, skb);
- queue_work(local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
return RX_QUEUED;
}
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index e93c37e..11ab71a 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -660,14 +660,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
spin_unlock(&ifmsh->mesh_preq_queue_lock);
if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
- queue_work(sdata->local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work);
else if (time_before(jiffies, ifmsh->last_preq)) {
/* avoid long wait if did not send preqs for a long time
* and jiffies wrapped around
*/
ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
- queue_work(sdata->local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work);
} else
mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
min_preq_int_jiff(sdata));
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ee83125..0779ba1 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -565,7 +565,7 @@ static void ieee80211_chswitch_timer(unsigned long data)
return;
}
- queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
+ ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
}
void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
@@ -597,7 +597,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
sdata->local->csa_channel = new_ch;
if (sw_elem->count <= 1) {
- queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
+ ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
} else {
ieee80211_stop_queues_by_reason(&sdata->local->hw,
IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -763,7 +763,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
if (local->quiescing || local->suspended)
return;
- queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
+ ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
}
/* MLME */
@@ -950,7 +950,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
* due to work needing to be done. Hence, queue the STAs work
* again for that.
*/
- queue_work(local->hw.workqueue, &ifmgd->work);
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
return RX_MGMT_CFG80211_AUTH_TO;
}
@@ -995,7 +995,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
* due to work needing to be done. Hence, queue the STAs work
* again for that.
*/
- queue_work(local->hw.workqueue, &ifmgd->work);
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
return RX_MGMT_CFG80211_AUTH_TO;
}
@@ -1124,7 +1124,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata,
* due to work needing to be done. Hence, queue the STAs work
* again for that.
*/
- queue_work(local->hw.workqueue, &ifmgd->work);
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
return RX_MGMT_CFG80211_ASSOC_TO;
}
@@ -1232,8 +1232,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
- queue_work(sdata->local->hw.workqueue,
- &sdata->u.mgd.beacon_loss_work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
}
EXPORT_SYMBOL(ieee80211_beacon_loss);
@@ -1888,7 +1887,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
case IEEE80211_STYPE_DISASSOC:
case IEEE80211_STYPE_ACTION:
skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
- queue_work(local->hw.workqueue, &sdata->u.mgd.work);
+ ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
return RX_QUEUED;
}
@@ -2026,7 +2025,7 @@ static void ieee80211_sta_timer(unsigned long data)
return;
}
- queue_work(local->hw.workqueue, &ifmgd->work);
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
}
static void ieee80211_sta_work(struct work_struct *work)
@@ -2051,13 +2050,11 @@ static void ieee80211_sta_work(struct work_struct *work)
return;
/*
- * Nothing should have been stuffed into the workqueue during
- * the suspend->resume cycle. If this WARN is seen then there
- * is a bug with either the driver suspend or something in
- * mac80211 stuffing into the workqueue which we haven't yet
- * cleared during mac80211's suspend cycle.
+ * ieee80211_queue_work() should have picked up most cases,
+ * here we'll pick the the rest.
*/
- if (WARN_ON(local->suspended))
+ if (WARN(local->suspended, "STA MLME work scheduled while "
+ "going to suspend\n"))
return;
ifmgd = &sdata->u.mgd;
@@ -2113,9 +2110,9 @@ static void ieee80211_sta_work(struct work_struct *work)
mutex_unlock(&ifmgd->mtx);
if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
- queue_delayed_work(local->hw.workqueue,
- &local->scan_work,
- round_jiffies_relative(0));
+ ieee80211_queue_delayed_work(&local->hw,
+ &local->scan_work,
+ round_jiffies_relative(0));
return;
}
@@ -2196,8 +2193,7 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
if (local->quiescing)
return;
- queue_work(sdata->local->hw.workqueue,
- &sdata->u.mgd.beacon_loss_work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
}
static void ieee80211_sta_conn_mon_timer(unsigned long data)
@@ -2210,7 +2206,7 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data)
if (local->quiescing)
return;
- queue_work(local->hw.workqueue, &ifmgd->monitor_work);
+ ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
}
static void ieee80211_sta_monitor_work(struct work_struct *work)
@@ -2229,10 +2225,10 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
IEEE80211_STA_CONNECTION_POLL);
/* let's probe the connection once */
- queue_work(sdata->local->hw.workqueue,
+ ieee80211_queue_work(&sdata->local->hw,
&sdata->u.mgd.monitor_work);
/* and do all the other regular work too */
- queue_work(sdata->local->hw.workqueue,
+ ieee80211_queue_work(&sdata->local->hw,
&sdata->u.mgd.work);
}
}
@@ -2393,7 +2389,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
list_add(&wk->list, &sdata->u.mgd.work_list);
mutex_unlock(&ifmgd->mtx);
- queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
return 0;
}
@@ -2467,7 +2463,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
else
ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
- queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
err = 0;
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 3320f7d..a5d2f1f 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -26,7 +26,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
/* make quiescing visible to timers everywhere */
mb();
- flush_workqueue(local->hw.workqueue);
+ flush_workqueue(local->workqueue);
/* Don't try to run timers while suspended. */
del_timer_sync(&local->sta_cleanup);
@@ -117,7 +117,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
* shouldn't be doing (or cancel everything in the
* stop callback) that but better safe than sorry.
*/
- flush_workqueue(local->hw.workqueue);
+ flush_workqueue(local->workqueue);
local->suspended = true;
/* need suspended to be visible before quiescing is false */
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 4573100..244f53f 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -385,8 +385,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
spin_unlock_bh(&local->filter_lock);
/* TODO: start scan as soon as all nullfunc frames are ACKed */
- queue_delayed_work(local->hw.workqueue, &local->scan_work,
- IEEE80211_CHANNEL_TIME);
+ ieee80211_queue_delayed_work(&local->hw,
+ &local->scan_work,
+ IEEE80211_CHANNEL_TIME);
return 0;
}
@@ -715,8 +716,7 @@ void ieee80211_scan_work(struct work_struct *work)
}
} while (next_delay == 0);
- queue_delayed_work(local->hw.workqueue, &local->scan_work,
- next_delay);
+ ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
}
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 4e1b2ba..7cffaa0 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1400,7 +1400,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
ieee80211_stop_queues_by_reason(&local->hw,
IEEE80211_QUEUE_STOP_REASON_PS);
- queue_work(local->hw.workqueue,
+ ieee80211_queue_work(&local->hw,
&local->dynamic_ps_disable_work);
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 8502936..e55d57f 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -511,6 +511,46 @@ void ieee80211_iterate_active_interfaces_atomic(
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
+/*
+ * Nothing should have been stuffed into the workqueue during
+ * the suspend->resume cycle. If this WARN is seen then there
+ * is a bug with either the driver suspend or something in
+ * mac80211 stuffing into the workqueue which we haven't yet
+ * cleared during mac80211's suspend cycle.
+ */
+static bool ieee80211_can_queue_work(struct ieee80211_local *local)
+{
+ if (WARN(local->suspended, "queueing ieee80211 work while "
+ "going to suspend\n"))
+ return false;
+
+ return true;
+}
+
+void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+
+ if (!ieee80211_can_queue_work(local))
+ return;
+
+ queue_work(local->workqueue, work);
+}
+EXPORT_SYMBOL(ieee80211_queue_work);
+
+void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
+ struct delayed_work *dwork,
+ unsigned long delay)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+
+ if (!ieee80211_can_queue_work(local))
+ return;
+
+ queue_delayed_work(local->workqueue, dwork, delay);
+}
+EXPORT_SYMBOL(ieee80211_queue_delayed_work);
+
void ieee802_11_parse_elems(u8 *start, size_t len,
struct ieee802_11_elems *elems)
{
@@ -1114,3 +1154,4 @@ int ieee80211_reconfig(struct ieee80211_local *local)
#endif
return 0;
}
+