mac80211: allow drivers to request DTIM period
Some features require knowing the DTIM period
before associating. This implements the ability
to wait for a beacon in mac80211 before assoc
to provide this value. It is optional since
most likely not all drivers will need this.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index cf8d721..b6c163a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -870,6 +870,11 @@
ieee80211_led_assoc(local, 1);
+ if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
+ bss_conf->dtim_period = bss->dtim_period;
+ else
+ bss_conf->dtim_period = 0;
+
bss_conf->assoc = 1;
/*
* For now just always ask the driver to update the basic rateset
@@ -1751,7 +1756,8 @@
if (wk->sdata != sdata)
continue;
- if (wk->type != IEEE80211_WORK_ASSOC)
+ if (wk->type != IEEE80211_WORK_ASSOC &&
+ wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
continue;
if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN))
@@ -2086,6 +2092,8 @@
struct sk_buff *skb)
{
struct ieee80211_mgmt *mgmt;
+ struct ieee80211_rx_status *rx_status;
+ struct ieee802_11_elems elems;
u16 status;
if (!skb) {
@@ -2093,6 +2101,19 @@
return WORK_DONE_DESTROY;
}
+ if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) {
+ mutex_lock(&wk->sdata->u.mgd.mtx);
+ rx_status = (void *) skb->cb;
+ ieee802_11_parse_elems(skb->data + 24 + 12, skb->len - 24 - 12, &elems);
+ ieee80211_rx_bss_info(wk->sdata, (void *)skb->data, skb->len, rx_status,
+ &elems, true);
+ mutex_unlock(&wk->sdata->u.mgd.mtx);
+
+ wk->type = IEEE80211_WORK_ASSOC;
+ /* not really done yet */
+ return WORK_DONE_REQUEUE;
+ }
+
mgmt = (void *)skb->data;
status = le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -2206,10 +2227,14 @@
if (req->prev_bssid)
memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN);
- wk->type = IEEE80211_WORK_ASSOC;
wk->chan = req->bss->channel;
wk->sdata = sdata;
wk->done = ieee80211_assoc_done;
+ if (!bss->dtim_period &&
+ sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
+ wk->type = IEEE80211_WORK_ASSOC_BEACON_WAIT;
+ else
+ wk->type = IEEE80211_WORK_ASSOC;
if (req->use_mfp) {
ifmgd->mfp = IEEE80211_MFP_REQUIRED;
@@ -2257,7 +2282,8 @@
if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
wk->type != IEEE80211_WORK_AUTH &&
- wk->type != IEEE80211_WORK_ASSOC)
+ wk->type != IEEE80211_WORK_ASSOC &&
+ wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
continue;
if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))