* Time the connection can be idle before we probe
* it to see if we can still talk to the AP.
*/
-#define IEEE80211_CONNECTION_IDLE_TIME (2 * HZ)
+#define IEEE80211_CONNECTION_IDLE_TIME (30 * HZ)
/*
* Time we wait for a probe response after sending
* a probe request because of beacon loss or for
* checking the connection still works.
*/
-#define IEEE80211_PROBE_WAIT (HZ / 5)
+#define IEEE80211_PROBE_WAIT (HZ / 2)
#define TMR_RUNNING_TIMER 0
#define TMR_RUNNING_CHANSW 1
mgmt->u.deauth.reason_code = cpu_to_le16(reason);
if (stype == IEEE80211_STYPE_DEAUTH)
- cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, cookie);
+ if (cookie)
+ __cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
+ else
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
else
- cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len, cookie);
+ if (cookie)
+ __cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
+ else
+ cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
}
}
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_bss *bss,
+ struct ieee80211_mgd_work *wk,
u32 bss_info_changed)
{
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_bss *bss = wk->bss;
bss_info_changed |= BSS_CHANGED_ASSOC;
/* set timing information */
bss->cbss.capability, bss->has_erp_value, bss->erp_value);
sdata->u.mgd.associated = bss;
+ sdata->u.mgd.old_associate_work = wk;
memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
/* just to be sure */
ieee80211_recalc_ps(local, -1);
mutex_unlock(&local->iflist_mtx);
- netif_tx_start_all_queues(sdata->dev);
+ netif_start_queue(sdata->dev);
netif_carrier_on(sdata->dev);
}
return RX_MGMT_NONE;
}
-static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+ bool deauth)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
ifmgd->associated = NULL;
memset(ifmgd->bssid, 0, ETH_ALEN);
+ if (deauth) {
+ kfree(ifmgd->old_associate_work);
+ ifmgd->old_associate_work = NULL;
+ } else {
+ struct ieee80211_mgd_work *wk = ifmgd->old_associate_work;
+
+ wk->state = IEEE80211_MGD_STATE_IDLE;
+ list_add(&wk->list, &ifmgd->work_list);
+ }
+
/*
* we need to commit the associated = NULL change because the
* scan code uses that to determine whether this iface should
* time -- we don't want the scan code to enable queues.
*/
- netif_tx_stop_all_queues(sdata->dev);
+ netif_stop_queue(sdata->dev);
netif_carrier_off(sdata->dev);
rcu_read_lock();
sdata->dev->name, bssid, reason_code);
if (!wk) {
- ieee80211_set_disassoc(sdata);
+ ieee80211_set_disassoc(sdata, true);
} else {
list_del(&wk->list);
kfree(wk);
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
- printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
- sdata->dev->name, reason_code);
+ printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
+ sdata->dev->name, mgmt->sa, reason_code);
- ieee80211_set_disassoc(sdata);
+ ieee80211_set_disassoc(sdata, false);
return RX_MGMT_CFG80211_DISASSOC;
}
if (status_code != WLAN_STATUS_SUCCESS) {
printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
sdata->dev->name, status_code);
- list_del(&wk->list);
- kfree(wk);
+ wk->state = IEEE80211_MGD_STATE_IDLE;
return RX_MGMT_CFG80211_ASSOC;
}
* ieee80211_set_associated() will tell the driver */
bss_conf->aid = aid;
bss_conf->assoc_capability = capab_info;
- ieee80211_set_associated(sdata, wk->bss, changed);
+ /* this will take ownership of wk */
+ ieee80211_set_associated(sdata, wk, changed);
/*
* Start timer to probe the connection to the AP now.
ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
mod_beacon_timer(sdata);
- kfree(wk);
return RX_MGMT_CFG80211_ASSOC;
}
/* direct probe may be part of the association flow */
if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
- printk(KERN_DEBUG "%s direct probe responded\n",
+ printk(KERN_DEBUG "%s: direct probe responded\n",
sdata->dev->name);
wk->tries = 0;
wk->state = IEEE80211_MGD_STATE_AUTH;
/* no action */
break;
case RX_MGMT_CFG80211_DEAUTH:
- cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len,
- NULL);
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
break;
case RX_MGMT_CFG80211_DISASSOC:
- cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len,
- NULL);
+ cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
break;
default:
WARN(1, "unexpected: %d", rma);
cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len);
break;
case RX_MGMT_CFG80211_DEAUTH:
- cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, NULL);
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
break;
default:
WARN(1, "unexpected: %d", rma);
printk(KERN_DEBUG "No probe response from AP %pM"
" after %dms, disconnecting.\n",
bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
- ieee80211_set_disassoc(sdata);
+ ieee80211_set_disassoc(sdata, true);
mutex_unlock(&ifmgd->mtx);
/*
* must be outside lock due to cfg80211,
}
}
- list_for_each_entry(wk, &ifmgd->work_list, list) {
- if (wk->state != IEEE80211_MGD_STATE_IDLE) {
- anybusy = true;
- break;
- }
- }
ieee80211_recalc_idle(local);
- if (!anybusy) {
- mutex_unlock(&ifmgd->mtx);
-
- if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
- ieee80211_queue_delayed_work(&local->hw,
- &local->scan_work,
- round_jiffies_relative(0));
- return;
- }
-
list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) {
if (time_is_after_jiffies(wk->timeout)) {
/*
}
}
+ list_for_each_entry(wk, &ifmgd->work_list, list) {
+ if (wk->state != IEEE80211_MGD_STATE_IDLE) {
+ anybusy = true;
+ break;
+ }
+ }
+ if (!anybusy &&
+ test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
+ ieee80211_queue_delayed_work(&local->hw,
+ &local->scan_work,
+ round_jiffies_relative(0));
+
mutex_unlock(&ifmgd->mtx);
list_for_each_entry_safe(wk, tmp, &free_work, list) {
struct ieee80211_mgd_work *wk;
const u8 *bssid = NULL;
- printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
- sdata->dev->name, req->reason_code);
-
mutex_lock(&ifmgd->mtx);
if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
bssid = req->bss->bssid;
- ieee80211_set_disassoc(sdata);
+ ieee80211_set_disassoc(sdata, true);
} else list_for_each_entry(wk, &ifmgd->work_list, list) {
if (&wk->bss->cbss == req->bss) {
bssid = req->bss->bssid;
mutex_unlock(&ifmgd->mtx);
+ printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
+ sdata->dev->name, bssid, req->reason_code);
+
ieee80211_send_deauth_disassoc(sdata, bssid,
IEEE80211_STYPE_DEAUTH, req->reason_code,
cookie);
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
- sdata->dev->name, req->reason_code);
-
mutex_lock(&ifmgd->mtx);
/*
return -ENOLINK;
}
- ieee80211_set_disassoc(sdata);
+ printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
+ sdata->dev->name, req->bss->bssid, req->reason_code);
+
+ ieee80211_set_disassoc(sdata, false);
mutex_unlock(&ifmgd->mtx);