summaryrefslogtreecommitdiffstats
path: root/net/mac80211/work.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-20 21:04:44 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-20 21:04:44 -0700
commitf8965467f366fd18f01feafb5db10512d7b4422c (patch)
tree3706a9cd779859271ca61b85c63a1bc3f82d626e /net/mac80211/work.c
parenta26272e5200765691e67d6780e52b32498fdb659 (diff)
parent2ec8c6bb5d8f3a62a79f463525054bae1e3d4487 (diff)
downloadlinux-f8965467f366fd18f01feafb5db10512d7b4422c.tar.bz2
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits) qlcnic: adding co maintainer ixgbe: add support for active DA cables ixgbe: dcb, do not tag tc_prio_control frames ixgbe: fix ixgbe_tx_is_paused logic ixgbe: always enable vlan strip/insert when DCB is enabled ixgbe: remove some redundant code in setting FCoE FIP filter ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp ixgbe: fix header len when unsplit packet overflows to data buffer ipv6: Never schedule DAD timer on dead address ipv6: Use POSTDAD state ipv6: Use state_lock to protect ifa state ipv6: Replace inet6_ifaddr->dead with state cxgb4: notify upper drivers if the device is already up when they load cxgb4: keep interrupts available when the ports are brought down cxgb4: fix initial addition of MAC address cnic: Return SPQ credit to bnx2x after ring setup and shutdown. cnic: Convert cnic_local_flags to atomic ops. can: Fix SJA1000 command register writes on SMP systems bridge: fix build for CONFIG_SYSFS disabled ARCNET: Limit com20020 PCI ID matches for SOHARD cards ... Fix up various conflicts with pcmcia tree drivers/net/ {pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and wireless/orinoco/spectrum_cs.c} and feature removal (Documentation/feature-removal-schedule.txt). Also fix a non-content conflict due to pm_qos_requirement getting renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c
Diffstat (limited to 'net/mac80211/work.c')
-rw-r--r--net/mac80211/work.c62
1 files changed, 50 insertions, 12 deletions
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 15e1ba931b87..be3d4a698692 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -33,6 +33,7 @@
#define IEEE80211_MAX_PROBE_TRIES 5
enum work_action {
+ WORK_ACT_MISMATCH,
WORK_ACT_NONE,
WORK_ACT_TIMEOUT,
WORK_ACT_DONE,
@@ -213,15 +214,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 */
@@ -575,7 +586,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;
@@ -626,6 +637,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.
@@ -681,6 +695,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;
@@ -695,7 +715,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;
@@ -742,7 +762,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.
@@ -752,6 +782,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:
@@ -920,11 +953,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);