Skip to content

Commit

Permalink
mac80211: unify scan and work mutexes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Aug 16, 2010
1 parent c240879 commit a1699b7
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 43 deletions.
4 changes: 2 additions & 2 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions net/mac80211/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
8 changes: 4 additions & 4 deletions net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
30 changes: 15 additions & 15 deletions net/mac80211/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -267,15 +267,15 @@ 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;
}

was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
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;
}

Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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;
}
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
Expand Down
35 changes: 15 additions & 20 deletions net/mac80211/work.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/*
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -1057,27 +1052,27 @@ 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;
wk->type = IEEE80211_WORK_ABORT;
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,
Expand Down Expand Up @@ -1163,15 +1158,15 @@ 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;
found = true;
break;
}
}
mutex_unlock(&local->work_mtx);
mutex_unlock(&local->mtx);

if (!found)
return -ENOENT;
Expand Down

0 comments on commit a1699b7

Please sign in to comment.