From 68dd5b7a45d1935fcd32b786e8d3d3f7bb4bbfe7 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Fri, 9 Apr 2010 13:07:55 +0300 Subject: mac80211: check whether scan is in progress before queueing scan_work As scan_work is queued from work_work it needs to be checked if scan has been started during execution of work_work. Otherwise, when hw scan is used, the stack gets error about hw being busy with ongoing scan. This causes the stack to abort scan without notifying the driver about it. This leads to a situation where the hw is scanning and the stack thinks it's not. Then when the scan finishes, the stack will complain by warnings. Signed-off-by: Teemu Paasikivi Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/work.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'net/mac80211/work.c') diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 1e1ea3007b0..7bd8670379d 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -919,11 +919,16 @@ static void ieee80211_work_work(struct work_struct *work) run_again(local, jiffies + HZ/2); } - if (list_empty(&local->work_list) && local->scan_req) + 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); ieee80211_recalc_idle(local); -- cgit v1.2.3-70-g09d2 From 76f273640134f3eb8257179cd5b3bc6ba5fe4a96 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 28 Apr 2010 17:03:15 +0200 Subject: mac80211: fix supported rates IE if AP doesn't give us it's rates If AP do not provide us supported rates before assiociation, send all rates we are supporting instead of empty information element. v1 -> v2: Add comment. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- net/mac80211/work.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'net/mac80211/work.c') diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 7bd8670379d..4c7de72c27e 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -212,15 +212,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, sband = local->hw.wiphy->bands[wk->chan->band]; - /* - * Get all rates supported by the device and the AP as - * some APs don't like getting a superset of their rates - * in the association request (e.g. D-Link DAP 1353 in - * b-only mode)... - */ - rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, - wk->assoc.supp_rates_len, - sband, &rates); + if (wk->assoc.supp_rates_len) { + /* + * Get all rates supported by the device and the AP as + * some APs don't like getting a superset of their rates + * in the association request (e.g. D-Link DAP 1353 in + * b-only mode)... + */ + rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, + wk->assoc.supp_rates_len, + sband, &rates); + } else { + /* + * In case AP not provide any supported rates information + * before association, we send information element(s) with + * all rates that we support. + */ + rates = ~0; + rates_len = sband->n_bitrates; + } skb = alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + /* bit too much but doesn't matter */ -- cgit v1.2.3-70-g09d2 From b8d92c9c141ee3dc9b3537b1f0ffb4a54ea8d9b2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 11 May 2010 12:42:04 +0200 Subject: mac80211: don't process work item with wrong frame When we process a frame, we currently just match it to the work struct by the MAC addresses, and not by the work type. This means that we can end up doing the work for an association request item when (for whatever reason) we receive another frame type, for example a probe response. Processing the wrong type of frame will lead to completely invalid data being processed, and will lead to various problems like thinking the association was successful even if the AP never sent an assocation response. Fix this by making each processing function check that it is invoked for the right work struct type only and continue processing otherwise (and drop frames that we didn't expect). This bug was uncovered during the debugging for https://bugzilla.kernel.org/show_bug.cgi?id=15862 but doesn't seem to be the cause for any of the various problems reported there. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/work.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'net/mac80211/work.c') diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 1e1ea3007b0..b0ba58589ca 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -32,6 +32,7 @@ #define IEEE80211_MAX_PROBE_TRIES 5 enum work_action { + WORK_ACT_MISMATCH, WORK_ACT_NONE, WORK_ACT_TIMEOUT, WORK_ACT_DONE, @@ -574,7 +575,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, u16 auth_alg, auth_transaction, status_code; if (wk->type != IEEE80211_WORK_AUTH) - return WORK_ACT_NONE; + return WORK_ACT_MISMATCH; if (len < 24 + 6) return WORK_ACT_NONE; @@ -625,6 +626,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, struct ieee802_11_elems elems; u8 *pos; + if (wk->type != IEEE80211_WORK_ASSOC) + return WORK_ACT_MISMATCH; + /* * AssocResp and ReassocResp have identical structure, so process both * of them in this function. @@ -680,6 +684,12 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, ASSERT_WORK_MTX(local); + if (wk->type != IEEE80211_WORK_DIRECT_PROBE) + return WORK_ACT_MISMATCH; + + if (len < 24 + 12) + return WORK_ACT_NONE; + baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; if (baselen > len) return WORK_ACT_NONE; @@ -694,7 +704,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, struct ieee80211_rx_status *rx_status; struct ieee80211_mgmt *mgmt; struct ieee80211_work *wk; - enum work_action rma = WORK_ACT_NONE; + enum work_action rma; u16 fc; rx_status = (struct ieee80211_rx_status *) skb->cb; @@ -741,7 +751,17 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, break; default: WARN_ON(1); + rma = WORK_ACT_NONE; } + + /* + * We've either received an unexpected frame, or we have + * multiple work items and need to match the frame to the + * right one. + */ + if (rma == WORK_ACT_MISMATCH) + continue; + /* * We've processed this frame for that work, so it can't * belong to another work struct. @@ -751,6 +771,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, } switch (rma) { + case WORK_ACT_MISMATCH: + /* ignore this unmatched frame */ + break; case WORK_ACT_NONE: break; case WORK_ACT_DONE: -- cgit v1.2.3-70-g09d2