|
@@ -560,6 +560,22 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
|
|
return WORK_ACT_TIMEOUT;
|
|
return WORK_ACT_TIMEOUT;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static enum work_action __must_check
|
|
|
|
+ieee80211_assoc_beacon_wait(struct ieee80211_work *wk)
|
|
|
|
+{
|
|
|
|
+ if (wk->started)
|
|
|
|
+ return WORK_ACT_TIMEOUT;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Wait up to one beacon interval ...
|
|
|
|
+ * should this be more if we miss one?
|
|
|
|
+ */
|
|
|
|
+ printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
|
|
|
|
+ wk->sdata->name, wk->filter_ta);
|
|
|
|
+ wk->timeout = TU_TO_EXP_TIME(wk->assoc.bss->beacon_interval);
|
|
|
|
+ return WORK_ACT_NONE;
|
|
|
|
+}
|
|
|
|
+
|
|
static void ieee80211_auth_challenge(struct ieee80211_work *wk,
|
|
static void ieee80211_auth_challenge(struct ieee80211_work *wk,
|
|
struct ieee80211_mgmt *mgmt,
|
|
struct ieee80211_mgmt *mgmt,
|
|
size_t len)
|
|
size_t len)
|
|
@@ -709,6 +725,25 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk,
|
|
return WORK_ACT_DONE;
|
|
return WORK_ACT_DONE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static enum work_action __must_check
|
|
|
|
+ieee80211_rx_mgmt_beacon(struct ieee80211_work *wk,
|
|
|
|
+ struct ieee80211_mgmt *mgmt, size_t len)
|
|
|
|
+{
|
|
|
|
+ struct ieee80211_sub_if_data *sdata = wk->sdata;
|
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
|
+
|
|
|
|
+ ASSERT_WORK_MTX(local);
|
|
|
|
+
|
|
|
|
+ if (wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
|
|
|
|
+ return WORK_ACT_MISMATCH;
|
|
|
|
+
|
|
|
|
+ if (len < 24 + 12)
|
|
|
|
+ return WORK_ACT_NONE;
|
|
|
|
+
|
|
|
|
+ printk(KERN_DEBUG "%s: beacon received\n", sdata->name);
|
|
|
|
+ return WORK_ACT_DONE;
|
|
|
|
+}
|
|
|
|
+
|
|
static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
|
static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
|
struct sk_buff *skb)
|
|
struct sk_buff *skb)
|
|
{
|
|
{
|
|
@@ -731,6 +766,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
|
case IEEE80211_WORK_DIRECT_PROBE:
|
|
case IEEE80211_WORK_DIRECT_PROBE:
|
|
case IEEE80211_WORK_AUTH:
|
|
case IEEE80211_WORK_AUTH:
|
|
case IEEE80211_WORK_ASSOC:
|
|
case IEEE80211_WORK_ASSOC:
|
|
|
|
+ case IEEE80211_WORK_ASSOC_BEACON_WAIT:
|
|
bssid = wk->filter_ta;
|
|
bssid = wk->filter_ta;
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
@@ -745,6 +781,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
|
continue;
|
|
continue;
|
|
|
|
|
|
switch (fc & IEEE80211_FCTL_STYPE) {
|
|
switch (fc & IEEE80211_FCTL_STYPE) {
|
|
|
|
+ case IEEE80211_STYPE_BEACON:
|
|
|
|
+ rma = ieee80211_rx_mgmt_beacon(wk, mgmt, skb->len);
|
|
|
|
+ break;
|
|
case IEEE80211_STYPE_PROBE_RESP:
|
|
case IEEE80211_STYPE_PROBE_RESP:
|
|
rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len,
|
|
rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len,
|
|
rx_status);
|
|
rx_status);
|
|
@@ -916,6 +955,9 @@ static void ieee80211_work_work(struct work_struct *work)
|
|
case IEEE80211_WORK_REMAIN_ON_CHANNEL:
|
|
case IEEE80211_WORK_REMAIN_ON_CHANNEL:
|
|
rma = ieee80211_remain_on_channel_timeout(wk);
|
|
rma = ieee80211_remain_on_channel_timeout(wk);
|
|
break;
|
|
break;
|
|
|
|
+ case IEEE80211_WORK_ASSOC_BEACON_WAIT:
|
|
|
|
+ rma = ieee80211_assoc_beacon_wait(wk);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
|
|
wk->started = started;
|
|
wk->started = started;
|
|
@@ -1065,6 +1107,7 @@ ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
|
|
case IEEE80211_STYPE_PROBE_RESP:
|
|
case IEEE80211_STYPE_PROBE_RESP:
|
|
case IEEE80211_STYPE_ASSOC_RESP:
|
|
case IEEE80211_STYPE_ASSOC_RESP:
|
|
case IEEE80211_STYPE_REASSOC_RESP:
|
|
case IEEE80211_STYPE_REASSOC_RESP:
|
|
|
|
+ case IEEE80211_STYPE_BEACON:
|
|
skb_queue_tail(&local->work_skb_queue, skb);
|
|
skb_queue_tail(&local->work_skb_queue, skb);
|
|
ieee80211_queue_work(&local->hw, &local->work_work);
|
|
ieee80211_queue_work(&local->hw, &local->work_work);
|
|
return RX_QUEUED;
|
|
return RX_QUEUED;
|