Commit a1699b75 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

mac80211: unify scan and work mutexes

Having both scan and work mutexes is not just
a bit too fine grained, it also creates issues
when there's code that needs both since they
then need to be acquired in the right order,
which can be hard to do.

Therefore, use just a single mutex for both.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c240879f
...@@ -634,7 +634,6 @@ struct ieee80211_local { ...@@ -634,7 +634,6 @@ struct ieee80211_local {
/* /*
* work stuff, potentially off-channel (in the future) * work stuff, potentially off-channel (in the future)
*/ */
struct mutex work_mtx;
struct list_head work_list; struct list_head work_list;
struct timer_list work_timer; struct timer_list work_timer;
struct work_struct work_work; struct work_struct work_work;
...@@ -746,9 +745,10 @@ struct ieee80211_local { ...@@ -746,9 +745,10 @@ struct ieee80211_local {
*/ */
struct mutex key_mtx; struct mutex key_mtx;
/* mutex for scan and work locking */
struct mutex mtx;
/* Scanning and BSS list */ /* Scanning and BSS list */
struct mutex scan_mtx;
unsigned long scanning; unsigned long scanning;
struct cfg80211_ssid scan_ssid; struct cfg80211_ssid scan_ssid;
struct cfg80211_scan_request *int_scan_req; struct cfg80211_scan_request *int_scan_req;
......
...@@ -482,7 +482,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, ...@@ -482,7 +482,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
__hw_addr_init(&local->mc_list); __hw_addr_init(&local->mc_list);
mutex_init(&local->iflist_mtx); mutex_init(&local->iflist_mtx);
mutex_init(&local->scan_mtx); mutex_init(&local->mtx);
mutex_init(&local->key_mtx); mutex_init(&local->key_mtx);
spin_lock_init(&local->filter_lock); spin_lock_init(&local->filter_lock);
...@@ -791,7 +791,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) ...@@ -791,7 +791,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_local *local = hw_to_local(hw);
mutex_destroy(&local->iflist_mtx); mutex_destroy(&local->iflist_mtx);
mutex_destroy(&local->scan_mtx); mutex_destroy(&local->mtx);
wiphy_free(local->hw.wiphy); wiphy_free(local->hw.wiphy);
} }
......
...@@ -1751,7 +1751,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ...@@ -1751,7 +1751,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_work *wk; struct ieee80211_work *wk;
mutex_lock(&local->work_mtx); mutex_lock(&local->mtx);
list_for_each_entry(wk, &local->work_list, list) { list_for_each_entry(wk, &local->work_list, list) {
if (wk->sdata != sdata) if (wk->sdata != sdata)
continue; continue;
...@@ -1783,7 +1783,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ...@@ -1783,7 +1783,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
free_work(wk); free_work(wk);
break; break;
} }
mutex_unlock(&local->work_mtx); mutex_unlock(&local->mtx);
cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
} }
...@@ -2275,7 +2275,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, ...@@ -2275,7 +2275,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&ifmgd->mtx); mutex_unlock(&ifmgd->mtx);
mutex_lock(&local->work_mtx); mutex_lock(&local->mtx);
list_for_each_entry(wk, &local->work_list, list) { list_for_each_entry(wk, &local->work_list, list) {
if (wk->sdata != sdata) if (wk->sdata != sdata)
continue; continue;
...@@ -2294,7 +2294,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, ...@@ -2294,7 +2294,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
free_work(wk); free_work(wk);
break; break;
} }
mutex_unlock(&local->work_mtx); mutex_unlock(&local->mtx);
/* /*
* If somebody requests authentication and we haven't * If somebody requests authentication and we haven't
......
...@@ -255,7 +255,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -255,7 +255,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
trace_api_scan_completed(local, aborted); trace_api_scan_completed(local, aborted);
mutex_lock(&local->scan_mtx); mutex_lock(&local->mtx);
/* /*
* It's ok to abort a not-yet-running scan (that * It's ok to abort a not-yet-running scan (that
...@@ -267,7 +267,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -267,7 +267,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
aborted = true; aborted = true;
if (WARN_ON(!local->scan_req)) { if (WARN_ON(!local->scan_req)) {
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
return; return;
} }
...@@ -275,7 +275,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -275,7 +275,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
ieee80211_queue_delayed_work(&local->hw, ieee80211_queue_delayed_work(&local->hw,
&local->scan_work, 0); &local->scan_work, 0);
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
return; return;
} }
...@@ -291,7 +291,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -291,7 +291,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
local->scan_channel = NULL; local->scan_channel = NULL;
/* we only have to protect scan_req and hw/sw scan */ /* we only have to protect scan_req and hw/sw scan */
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
if (was_hw_scan) if (was_hw_scan)
...@@ -639,15 +639,15 @@ void ieee80211_scan_work(struct work_struct *work) ...@@ -639,15 +639,15 @@ void ieee80211_scan_work(struct work_struct *work)
struct ieee80211_sub_if_data *sdata = local->scan_sdata; struct ieee80211_sub_if_data *sdata = local->scan_sdata;
unsigned long next_delay = 0; unsigned long next_delay = 0;
mutex_lock(&local->scan_mtx); mutex_lock(&local->mtx);
if (!sdata || !local->scan_req) { if (!sdata || !local->scan_req) {
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
return; return;
} }
if (local->hw_scan_req) { if (local->hw_scan_req) {
int rc = drv_hw_scan(local, sdata, local->hw_scan_req); int rc = drv_hw_scan(local, sdata, local->hw_scan_req);
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
if (rc) if (rc)
ieee80211_scan_completed(&local->hw, true); ieee80211_scan_completed(&local->hw, true);
return; return;
...@@ -661,14 +661,14 @@ void ieee80211_scan_work(struct work_struct *work) ...@@ -661,14 +661,14 @@ void ieee80211_scan_work(struct work_struct *work)
local->scan_sdata = NULL; local->scan_sdata = NULL;
rc = __ieee80211_start_scan(sdata, req); rc = __ieee80211_start_scan(sdata, req);
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
if (rc) if (rc)
ieee80211_scan_completed(&local->hw, true); ieee80211_scan_completed(&local->hw, true);
return; return;
} }
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
/* /*
* Avoid re-scheduling when the sdata is going away. * Avoid re-scheduling when the sdata is going away.
...@@ -711,9 +711,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, ...@@ -711,9 +711,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
{ {
int res; int res;
mutex_lock(&sdata->local->scan_mtx); mutex_lock(&sdata->local->mtx);
res = __ieee80211_start_scan(sdata, req); res = __ieee80211_start_scan(sdata, req);
mutex_unlock(&sdata->local->scan_mtx); mutex_unlock(&sdata->local->mtx);
return res; return res;
} }
...@@ -726,7 +726,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, ...@@ -726,7 +726,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
int ret = -EBUSY; int ret = -EBUSY;
enum ieee80211_band band; enum ieee80211_band band;
mutex_lock(&local->scan_mtx); mutex_lock(&local->mtx);
/* busy scanning */ /* busy scanning */
if (local->scan_req) if (local->scan_req)
...@@ -761,7 +761,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, ...@@ -761,7 +761,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
unlock: unlock:
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
return ret; return ret;
} }
...@@ -775,10 +775,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) ...@@ -775,10 +775,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
* Only call this function when a scan can't be * Only call this function when a scan can't be
* queued -- mostly at suspend under RTNL. * queued -- mostly at suspend under RTNL.
*/ */
mutex_lock(&local->scan_mtx); mutex_lock(&local->mtx);
abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
(!local->scanning && local->scan_req); (!local->scanning && local->scan_req);
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
if (abortscan) if (abortscan)
ieee80211_scan_completed(&local->hw, true); ieee80211_scan_completed(&local->hw, true);
......
...@@ -43,7 +43,7 @@ enum work_action { ...@@ -43,7 +43,7 @@ enum work_action {
/* utils */ /* utils */
static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) static inline void ASSERT_WORK_MTX(struct ieee80211_local *local)
{ {
WARN_ON(!mutex_is_locked(&local->work_mtx)); lockdep_assert_held(&local->mtx);
} }
/* /*
...@@ -757,7 +757,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, ...@@ -757,7 +757,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
mgmt = (struct ieee80211_mgmt *) skb->data; mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control); fc = le16_to_cpu(mgmt->frame_control);
mutex_lock(&local->work_mtx); mutex_lock(&local->mtx);
list_for_each_entry(wk, &local->work_list, list) { list_for_each_entry(wk, &local->work_list, list) {
const u8 *bssid = NULL; const u8 *bssid = NULL;
...@@ -833,7 +833,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, ...@@ -833,7 +833,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
WARN(1, "unexpected: %d", rma); WARN(1, "unexpected: %d", rma);
} }
mutex_unlock(&local->work_mtx); mutex_unlock(&local->mtx);
if (rma != WORK_ACT_DONE) if (rma != WORK_ACT_DONE)
goto out; goto out;
...@@ -845,9 +845,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, ...@@ -845,9 +845,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
case WORK_DONE_REQUEUE: case WORK_DONE_REQUEUE:
synchronize_rcu(); synchronize_rcu();
wk->started = false; /* restart */ wk->started = false; /* restart */
mutex_lock(&local->work_mtx); mutex_lock(&local->mtx);
list_add_tail(&wk->list, &local->work_list); list_add_tail(&wk->list, &local->work_list);
mutex_unlock(&local->work_mtx); mutex_unlock(&local->mtx);
} }
out: out:
...@@ -890,7 +890,7 @@ static void ieee80211_work_work(struct work_struct *work) ...@@ -890,7 +890,7 @@ static void ieee80211_work_work(struct work_struct *work)
ieee80211_recalc_idle(local); ieee80211_recalc_idle(local);
mutex_lock(&local->work_mtx); mutex_lock(&local->mtx);
list_for_each_entry_safe(wk, tmp, &local->work_list, list) { list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
bool started = wk->started; bool started = wk->started;
...@@ -995,17 +995,13 @@ static void ieee80211_work_work(struct work_struct *work) ...@@ -995,17 +995,13 @@ static void ieee80211_work_work(struct work_struct *work)
run_again(local, jiffies + HZ/2); run_again(local, jiffies + HZ/2);
} }
mutex_lock(&local->scan_mtx);
if (list_empty(&local->work_list) && local->scan_req && if (list_empty(&local->work_list) && local->scan_req &&
!local->scanning) !local->scanning)
ieee80211_queue_delayed_work(&local->hw, ieee80211_queue_delayed_work(&local->hw,
&local->scan_work, &local->scan_work,
round_jiffies_relative(0)); round_jiffies_relative(0));
mutex_unlock(&local->scan_mtx); mutex_unlock(&local->mtx);
mutex_unlock(&local->work_mtx);
ieee80211_recalc_idle(local); ieee80211_recalc_idle(local);
...@@ -1035,16 +1031,15 @@ void ieee80211_add_work(struct ieee80211_work *wk) ...@@ -1035,16 +1031,15 @@ void ieee80211_add_work(struct ieee80211_work *wk)
wk->started = false; wk->started = false;
local = wk->sdata->local; local = wk->sdata->local;
mutex_lock(&local->work_mtx); mutex_lock(&local->mtx);
list_add_tail(&wk->list, &local->work_list); list_add_tail(&wk->list, &local->work_list);
mutex_unlock(&local->work_mtx); mutex_unlock(&local->mtx);
ieee80211_queue_work(&local->hw, &local->work_work); ieee80211_queue_work(&local->hw, &local->work_work);
} }
void ieee80211_work_init(struct ieee80211_local *local) void ieee80211_work_init(struct ieee80211_local *local)
{ {
mutex_init(&local->work_mtx);
INIT_LIST_HEAD(&local->work_list); INIT_LIST_HEAD(&local->work_list);
setup_timer(&local->work_timer, ieee80211_work_timer, setup_timer(&local->work_timer, ieee80211_work_timer,
(unsigned long)local); (unsigned long)local);
...@@ -1057,7 +1052,7 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) ...@@ -1057,7 +1052,7 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_work *wk; struct ieee80211_work *wk;
mutex_lock(&local->work_mtx); mutex_lock(&local->mtx);
list_for_each_entry(wk, &local->work_list, list) { list_for_each_entry(wk, &local->work_list, list) {
if (wk->sdata != sdata) if (wk->sdata != sdata)
continue; continue;
...@@ -1065,19 +1060,19 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) ...@@ -1065,19 +1060,19 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
wk->started = true; wk->started = true;
wk->timeout = jiffies; wk->timeout = jiffies;
} }
mutex_unlock(&local->work_mtx); mutex_unlock(&local->mtx);
/* run cleanups etc. */ /* run cleanups etc. */
ieee80211_work_work(&local->work_work); ieee80211_work_work(&local->work_work);
mutex_lock(&local->work_mtx); mutex_lock(&local->mtx);
list_for_each_entry(wk, &local->work_list, list) { list_for_each_entry(wk, &local->work_list, list) {
if (wk->sdata != sdata) if (wk->sdata != sdata)
continue; continue;
WARN_ON(1); WARN_ON(1);
break; break;
} }
mutex_unlock(&local->work_mtx); mutex_unlock(&local->mtx);
} }
ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
...@@ -1163,7 +1158,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, ...@@ -1163,7 +1158,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
struct ieee80211_work *wk, *tmp; struct ieee80211_work *wk, *tmp;
bool found = false; bool found = false;
mutex_lock(&local->work_mtx); mutex_lock(&local->mtx);
list_for_each_entry_safe(wk, tmp, &local->work_list, list) { list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
if ((unsigned long) wk == cookie) { if ((unsigned long) wk == cookie) {
wk->timeout = jiffies; wk->timeout = jiffies;
...@@ -1171,7 +1166,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, ...@@ -1171,7 +1166,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
break; break;
} }
} }
mutex_unlock(&local->work_mtx); mutex_unlock(&local->mtx);
if (!found) if (!found)
return -ENOENT; return -ENOENT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment