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: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Johannes Berg 2010-07-30 16:46:07 +02:00 committed by John W. Linville
parent c240879f34
commit a1699b75a1
5 changed files with 38 additions and 43 deletions

View File

@ -634,7 +634,6 @@ struct ieee80211_local {
/*
* work stuff, potentially off-channel (in the future)
*/
struct mutex work_mtx;
struct list_head work_list;
struct timer_list work_timer;
struct work_struct work_work;
@ -746,9 +745,10 @@ struct ieee80211_local {
*/
struct mutex key_mtx;
/* mutex for scan and work locking */
struct mutex mtx;
/* Scanning and BSS list */
struct mutex scan_mtx;
unsigned long scanning;
struct cfg80211_ssid scan_ssid;
struct cfg80211_scan_request *int_scan_req;

View File

@ -482,7 +482,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
__hw_addr_init(&local->mc_list);
mutex_init(&local->iflist_mtx);
mutex_init(&local->scan_mtx);
mutex_init(&local->mtx);
mutex_init(&local->key_mtx);
spin_lock_init(&local->filter_lock);
@ -791,7 +791,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
struct ieee80211_local *local = hw_to_local(hw);
mutex_destroy(&local->iflist_mtx);
mutex_destroy(&local->scan_mtx);
mutex_destroy(&local->mtx);
wiphy_free(local->hw.wiphy);
}

View File

@ -1751,7 +1751,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_work *wk;
mutex_lock(&local->work_mtx);
mutex_lock(&local->mtx);
list_for_each_entry(wk, &local->work_list, list) {
if (wk->sdata != sdata)
continue;
@ -1783,7 +1783,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
free_work(wk);
break;
}
mutex_unlock(&local->work_mtx);
mutex_unlock(&local->mtx);
cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
}
@ -2275,7 +2275,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&ifmgd->mtx);
mutex_lock(&local->work_mtx);
mutex_lock(&local->mtx);
list_for_each_entry(wk, &local->work_list, list) {
if (wk->sdata != sdata)
continue;
@ -2294,7 +2294,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
free_work(wk);
break;
}
mutex_unlock(&local->work_mtx);
mutex_unlock(&local->mtx);
/*
* If somebody requests authentication and we haven't

View File

@ -255,7 +255,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool 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
@ -267,7 +267,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
aborted = true;
if (WARN_ON(!local->scan_req)) {
mutex_unlock(&local->scan_mtx);
mutex_unlock(&local->mtx);
return;
}
@ -275,7 +275,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
ieee80211_queue_delayed_work(&local->hw,
&local->scan_work, 0);
mutex_unlock(&local->scan_mtx);
mutex_unlock(&local->mtx);
return;
}
@ -291,7 +291,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
local->scan_channel = NULL;
/* 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);
if (was_hw_scan)
@ -639,15 +639,15 @@ void ieee80211_scan_work(struct work_struct *work)
struct ieee80211_sub_if_data *sdata = local->scan_sdata;
unsigned long next_delay = 0;
mutex_lock(&local->scan_mtx);
mutex_lock(&local->mtx);
if (!sdata || !local->scan_req) {
mutex_unlock(&local->scan_mtx);
mutex_unlock(&local->mtx);
return;
}
if (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)
ieee80211_scan_completed(&local->hw, true);
return;
@ -661,14 +661,14 @@ void ieee80211_scan_work(struct work_struct *work)
local->scan_sdata = NULL;
rc = __ieee80211_start_scan(sdata, req);
mutex_unlock(&local->scan_mtx);
mutex_unlock(&local->mtx);
if (rc)
ieee80211_scan_completed(&local->hw, true);
return;
}
mutex_unlock(&local->scan_mtx);
mutex_unlock(&local->mtx);
/*
* Avoid re-scheduling when the sdata is going away.
@ -711,9 +711,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
{
int res;
mutex_lock(&sdata->local->scan_mtx);
mutex_lock(&sdata->local->mtx);
res = __ieee80211_start_scan(sdata, req);
mutex_unlock(&sdata->local->scan_mtx);
mutex_unlock(&sdata->local->mtx);
return res;
}
@ -726,7 +726,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
int ret = -EBUSY;
enum ieee80211_band band;
mutex_lock(&local->scan_mtx);
mutex_lock(&local->mtx);
/* busy scanning */
if (local->scan_req)
@ -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);
unlock:
mutex_unlock(&local->scan_mtx);
mutex_unlock(&local->mtx);
return ret;
}
@ -775,10 +775,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
* Only call this function when a scan can't be
* queued -- mostly at suspend under RTNL.
*/
mutex_lock(&local->scan_mtx);
mutex_lock(&local->mtx);
abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
(!local->scanning && local->scan_req);
mutex_unlock(&local->scan_mtx);
mutex_unlock(&local->mtx);
if (abortscan)
ieee80211_scan_completed(&local->hw, true);

View File

@ -43,7 +43,7 @@ enum work_action {
/* utils */
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,
mgmt = (struct ieee80211_mgmt *) skb->data;
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) {
const u8 *bssid = NULL;
@ -833,7 +833,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
WARN(1, "unexpected: %d", rma);
}
mutex_unlock(&local->work_mtx);
mutex_unlock(&local->mtx);
if (rma != WORK_ACT_DONE)
goto out;
@ -845,9 +845,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
case WORK_DONE_REQUEUE:
synchronize_rcu();
wk->started = false; /* restart */
mutex_lock(&local->work_mtx);
mutex_lock(&local->mtx);
list_add_tail(&wk->list, &local->work_list);
mutex_unlock(&local->work_mtx);
mutex_unlock(&local->mtx);
}
out:
@ -890,7 +890,7 @@ static void ieee80211_work_work(struct work_struct *work)
ieee80211_recalc_idle(local);
mutex_lock(&local->work_mtx);
mutex_lock(&local->mtx);
list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
bool started = wk->started;
@ -995,17 +995,13 @@ static void ieee80211_work_work(struct work_struct *work)
run_again(local, jiffies + HZ/2);
}
mutex_lock(&local->scan_mtx);
if (list_empty(&local->work_list) && local->scan_req &&
!local->scanning)
ieee80211_queue_delayed_work(&local->hw,
&local->scan_work,
round_jiffies_relative(0));
mutex_unlock(&local->scan_mtx);
mutex_unlock(&local->work_mtx);
mutex_unlock(&local->mtx);
ieee80211_recalc_idle(local);
@ -1035,16 +1031,15 @@ void ieee80211_add_work(struct ieee80211_work *wk)
wk->started = false;
local = wk->sdata->local;
mutex_lock(&local->work_mtx);
mutex_lock(&local->mtx);
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);
}
void ieee80211_work_init(struct ieee80211_local *local)
{
mutex_init(&local->work_mtx);
INIT_LIST_HEAD(&local->work_list);
setup_timer(&local->work_timer, ieee80211_work_timer,
(unsigned long)local);
@ -1057,7 +1052,7 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local;
struct ieee80211_work *wk;
mutex_lock(&local->work_mtx);
mutex_lock(&local->mtx);
list_for_each_entry(wk, &local->work_list, list) {
if (wk->sdata != sdata)
continue;
@ -1065,19 +1060,19 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
wk->started = true;
wk->timeout = jiffies;
}
mutex_unlock(&local->work_mtx);
mutex_unlock(&local->mtx);
/* run cleanups etc. */
ieee80211_work_work(&local->work_work);
mutex_lock(&local->work_mtx);
mutex_lock(&local->mtx);
list_for_each_entry(wk, &local->work_list, list) {
if (wk->sdata != sdata)
continue;
WARN_ON(1);
break;
}
mutex_unlock(&local->work_mtx);
mutex_unlock(&local->mtx);
}
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,
struct ieee80211_work *wk, *tmp;
bool found = false;
mutex_lock(&local->work_mtx);
mutex_lock(&local->mtx);
list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
if ((unsigned long) wk == cookie) {
wk->timeout = jiffies;
@ -1171,7 +1166,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
break;
}
}
mutex_unlock(&local->work_mtx);
mutex_unlock(&local->mtx);
if (!found)
return -ENOENT;