|
@@ -75,6 +75,9 @@ enum rx_mgmt_action {
|
|
/* caller must call cfg80211_send_disassoc() */
|
|
/* caller must call cfg80211_send_disassoc() */
|
|
RX_MGMT_CFG80211_DISASSOC,
|
|
RX_MGMT_CFG80211_DISASSOC,
|
|
|
|
|
|
|
|
+ /* caller must tell cfg80211 about internal error */
|
|
|
|
+ RX_MGMT_CFG80211_ASSOC_ERROR,
|
|
|
|
+
|
|
/* caller must call cfg80211_auth_timeout() & free work */
|
|
/* caller must call cfg80211_auth_timeout() & free work */
|
|
RX_MGMT_CFG80211_AUTH_TO,
|
|
RX_MGMT_CFG80211_AUTH_TO,
|
|
|
|
|
|
@@ -202,7 +205,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
|
|
ieee80211_hw_config(local, 0);
|
|
ieee80211_hw_config(local, 0);
|
|
|
|
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
- sta = sta_info_get(local, bssid);
|
|
|
|
|
|
+ sta = sta_info_get(sdata, bssid);
|
|
if (sta)
|
|
if (sta)
|
|
rate_control_rate_update(local, sband, sta,
|
|
rate_control_rate_update(local, sband, sta,
|
|
IEEE80211_RC_HT_CHANGED);
|
|
IEEE80211_RC_HT_CHANGED);
|
|
@@ -248,7 +251,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
|
|
wk->ssid_len);
|
|
wk->ssid_len);
|
|
if (!skb) {
|
|
if (!skb) {
|
|
printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
|
|
printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
|
|
- "frame\n", sdata->dev->name);
|
|
|
|
|
|
+ "frame\n", sdata->name);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
skb_reserve(skb, local->hw.extra_tx_headroom);
|
|
skb_reserve(skb, local->hw.extra_tx_headroom);
|
|
@@ -282,7 +285,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
|
|
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
|
|
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
|
|
memset(mgmt, 0, 24);
|
|
memset(mgmt, 0, 24);
|
|
memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN);
|
|
memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN);
|
|
- memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
|
|
|
|
|
|
+ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
|
|
memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN);
|
|
memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN);
|
|
|
|
|
|
if (!is_zero_ether_addr(wk->prev_bssid)) {
|
|
if (!is_zero_ether_addr(wk->prev_bssid)) {
|
|
@@ -398,6 +401,14 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
|
|
__le16 tmp;
|
|
__le16 tmp;
|
|
u32 flags = local->hw.conf.channel->flags;
|
|
u32 flags = local->hw.conf.channel->flags;
|
|
|
|
|
|
|
|
+ /* determine capability flags */
|
|
|
|
+
|
|
|
|
+ if (ieee80211_disable_40mhz_24ghz &&
|
|
|
|
+ sband->band == IEEE80211_BAND_2GHZ) {
|
|
|
|
+ cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
|
|
|
+ cap &= ~IEEE80211_HT_CAP_SGI_40;
|
|
|
|
+ }
|
|
|
|
+
|
|
switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
|
|
switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
|
|
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
|
|
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
|
|
if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
|
|
if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
|
|
@@ -413,17 +424,64 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- tmp = cpu_to_le16(cap);
|
|
|
|
- pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
|
|
|
|
|
|
+ /* set SM PS mode properly */
|
|
|
|
+ cap &= ~IEEE80211_HT_CAP_SM_PS;
|
|
|
|
+ /* new association always uses requested smps mode */
|
|
|
|
+ if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
|
|
|
|
+ if (ifmgd->powersave)
|
|
|
|
+ ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC;
|
|
|
|
+ else
|
|
|
|
+ ifmgd->ap_smps = IEEE80211_SMPS_OFF;
|
|
|
|
+ } else
|
|
|
|
+ ifmgd->ap_smps = ifmgd->req_smps;
|
|
|
|
+
|
|
|
|
+ switch (ifmgd->ap_smps) {
|
|
|
|
+ case IEEE80211_SMPS_AUTOMATIC:
|
|
|
|
+ case IEEE80211_SMPS_NUM_MODES:
|
|
|
|
+ WARN_ON(1);
|
|
|
|
+ case IEEE80211_SMPS_OFF:
|
|
|
|
+ cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
|
|
|
|
+ IEEE80211_HT_CAP_SM_PS_SHIFT;
|
|
|
|
+ break;
|
|
|
|
+ case IEEE80211_SMPS_STATIC:
|
|
|
|
+ cap |= WLAN_HT_CAP_SM_PS_STATIC <<
|
|
|
|
+ IEEE80211_HT_CAP_SM_PS_SHIFT;
|
|
|
|
+ break;
|
|
|
|
+ case IEEE80211_SMPS_DYNAMIC:
|
|
|
|
+ cap |= WLAN_HT_CAP_SM_PS_DYNAMIC <<
|
|
|
|
+ IEEE80211_HT_CAP_SM_PS_SHIFT;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* reserve and fill IE */
|
|
|
|
+
|
|
|
|
+ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
|
|
*pos++ = WLAN_EID_HT_CAPABILITY;
|
|
*pos++ = WLAN_EID_HT_CAPABILITY;
|
|
*pos++ = sizeof(struct ieee80211_ht_cap);
|
|
*pos++ = sizeof(struct ieee80211_ht_cap);
|
|
memset(pos, 0, sizeof(struct ieee80211_ht_cap));
|
|
memset(pos, 0, sizeof(struct ieee80211_ht_cap));
|
|
|
|
+
|
|
|
|
+ /* capability flags */
|
|
|
|
+ tmp = cpu_to_le16(cap);
|
|
memcpy(pos, &tmp, sizeof(u16));
|
|
memcpy(pos, &tmp, sizeof(u16));
|
|
pos += sizeof(u16);
|
|
pos += sizeof(u16);
|
|
- /* TODO: needs a define here for << 2 */
|
|
|
|
|
|
+
|
|
|
|
+ /* AMPDU parameters */
|
|
*pos++ = sband->ht_cap.ampdu_factor |
|
|
*pos++ = sband->ht_cap.ampdu_factor |
|
|
- (sband->ht_cap.ampdu_density << 2);
|
|
|
|
|
|
+ (sband->ht_cap.ampdu_density <<
|
|
|
|
+ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
|
|
|
|
+
|
|
|
|
+ /* MCS set */
|
|
memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
|
|
memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
|
|
|
|
+ pos += sizeof(sband->ht_cap.mcs);
|
|
|
|
+
|
|
|
|
+ /* extended capabilities */
|
|
|
|
+ pos += sizeof(__le16);
|
|
|
|
+
|
|
|
|
+ /* BF capabilities */
|
|
|
|
+ pos += sizeof(__le32);
|
|
|
|
+
|
|
|
|
+ /* antenna selection */
|
|
|
|
+ pos += sizeof(u8);
|
|
}
|
|
}
|
|
|
|
|
|
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
@@ -443,7 +501,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
|
|
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
|
|
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
|
|
if (!skb) {
|
|
if (!skb) {
|
|
printk(KERN_DEBUG "%s: failed to allocate buffer for "
|
|
printk(KERN_DEBUG "%s: failed to allocate buffer for "
|
|
- "deauth/disassoc frame\n", sdata->dev->name);
|
|
|
|
|
|
+ "deauth/disassoc frame\n", sdata->name);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
skb_reserve(skb, local->hw.extra_tx_headroom);
|
|
skb_reserve(skb, local->hw.extra_tx_headroom);
|
|
@@ -451,7 +509,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
|
|
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
|
|
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
|
|
memset(mgmt, 0, 24);
|
|
memset(mgmt, 0, 24);
|
|
memcpy(mgmt->da, bssid, ETH_ALEN);
|
|
memcpy(mgmt->da, bssid, ETH_ALEN);
|
|
- memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
|
|
|
|
|
|
+ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
|
|
memcpy(mgmt->bssid, bssid, ETH_ALEN);
|
|
memcpy(mgmt->bssid, bssid, ETH_ALEN);
|
|
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
|
|
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
|
|
skb_put(skb, 2);
|
|
skb_put(skb, 2);
|
|
@@ -484,7 +542,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local,
|
|
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
|
|
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
|
|
if (!skb) {
|
|
if (!skb) {
|
|
printk(KERN_DEBUG "%s: failed to allocate buffer for "
|
|
printk(KERN_DEBUG "%s: failed to allocate buffer for "
|
|
- "pspoll frame\n", sdata->dev->name);
|
|
|
|
|
|
+ "pspoll frame\n", sdata->name);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
skb_reserve(skb, local->hw.extra_tx_headroom);
|
|
skb_reserve(skb, local->hw.extra_tx_headroom);
|
|
@@ -499,7 +557,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local,
|
|
pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
|
|
pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
|
|
|
|
|
|
memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
|
|
memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
|
|
- memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN);
|
|
|
|
|
|
+ memcpy(pspoll->ta, sdata->vif.addr, ETH_ALEN);
|
|
|
|
|
|
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
ieee80211_tx_skb(sdata, skb);
|
|
ieee80211_tx_skb(sdata, skb);
|
|
@@ -519,7 +577,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
|
|
skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
|
|
skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
|
|
if (!skb) {
|
|
if (!skb) {
|
|
printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
|
|
printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
|
|
- "frame\n", sdata->dev->name);
|
|
|
|
|
|
+ "frame\n", sdata->name);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
skb_reserve(skb, local->hw.extra_tx_headroom);
|
|
skb_reserve(skb, local->hw.extra_tx_headroom);
|
|
@@ -532,7 +590,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
|
|
fc |= cpu_to_le16(IEEE80211_FCTL_PM);
|
|
fc |= cpu_to_le16(IEEE80211_FCTL_PM);
|
|
nullfunc->frame_control = fc;
|
|
nullfunc->frame_control = fc;
|
|
memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN);
|
|
memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN);
|
|
- memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
|
|
|
|
|
|
+ memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
|
|
memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN);
|
|
memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN);
|
|
|
|
|
|
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
@@ -940,6 +998,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
mutex_lock(&local->iflist_mtx);
|
|
mutex_lock(&local->iflist_mtx);
|
|
ieee80211_recalc_ps(local, -1);
|
|
ieee80211_recalc_ps(local, -1);
|
|
|
|
+ ieee80211_recalc_smps(local, sdata);
|
|
mutex_unlock(&local->iflist_mtx);
|
|
mutex_unlock(&local->iflist_mtx);
|
|
|
|
|
|
netif_start_queue(sdata->dev);
|
|
netif_start_queue(sdata->dev);
|
|
@@ -956,7 +1015,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
|
|
wk->tries++;
|
|
wk->tries++;
|
|
if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
|
|
if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
|
|
printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
|
|
printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
|
|
- sdata->dev->name, wk->bss->cbss.bssid);
|
|
|
|
|
|
+ sdata->name, wk->bss->cbss.bssid);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Most likely AP is not in the range so remove the
|
|
* Most likely AP is not in the range so remove the
|
|
@@ -974,7 +1033,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
|
|
}
|
|
}
|
|
|
|
|
|
printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
|
|
printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
|
|
- sdata->dev->name, wk->bss->cbss.bssid,
|
|
|
|
|
|
+ sdata->name, wk->bss->cbss.bssid,
|
|
wk->tries);
|
|
wk->tries);
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1001,7 +1060,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
|
|
if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
|
|
if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
|
|
printk(KERN_DEBUG "%s: authentication with AP %pM"
|
|
printk(KERN_DEBUG "%s: authentication with AP %pM"
|
|
" timed out\n",
|
|
" timed out\n",
|
|
- sdata->dev->name, wk->bss->cbss.bssid);
|
|
|
|
|
|
+ sdata->name, wk->bss->cbss.bssid);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Most likely AP is not in the range so remove the
|
|
* Most likely AP is not in the range so remove the
|
|
@@ -1019,7 +1078,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
|
|
}
|
|
}
|
|
|
|
|
|
printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
|
|
printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
|
|
- sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
|
|
|
|
|
|
+ sdata->name, wk->bss->cbss.bssid, wk->tries);
|
|
|
|
|
|
ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
|
|
ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
|
|
wk->bss->cbss.bssid, NULL, 0, 0);
|
|
wk->bss->cbss.bssid, NULL, 0, 0);
|
|
@@ -1078,7 +1137,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
|
netif_carrier_off(sdata->dev);
|
|
netif_carrier_off(sdata->dev);
|
|
|
|
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
- sta = sta_info_get(local, bssid);
|
|
|
|
|
|
+ sta = sta_info_get(sdata, bssid);
|
|
if (sta)
|
|
if (sta)
|
|
ieee80211_sta_tear_down_BA_sessions(sta);
|
|
ieee80211_sta_tear_down_BA_sessions(sta);
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
@@ -1115,7 +1174,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
|
|
|
|
- sta = sta_info_get(local, bssid);
|
|
|
|
|
|
+ sta = sta_info_get(sdata, bssid);
|
|
if (!sta) {
|
|
if (!sta) {
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
return;
|
|
return;
|
|
@@ -1139,7 +1198,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata,
|
|
if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) {
|
|
if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) {
|
|
printk(KERN_DEBUG "%s: association with AP %pM"
|
|
printk(KERN_DEBUG "%s: association with AP %pM"
|
|
" timed out\n",
|
|
" timed out\n",
|
|
- sdata->dev->name, wk->bss->cbss.bssid);
|
|
|
|
|
|
+ sdata->name, wk->bss->cbss.bssid);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Most likely AP is not in the range so remove the
|
|
* Most likely AP is not in the range so remove the
|
|
@@ -1157,7 +1216,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata,
|
|
}
|
|
}
|
|
|
|
|
|
printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n",
|
|
printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n",
|
|
- sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
|
|
|
|
|
|
+ sdata->name, wk->bss->cbss.bssid, wk->tries);
|
|
ieee80211_send_assoc(sdata, wk);
|
|
ieee80211_send_assoc(sdata, wk);
|
|
|
|
|
|
wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
|
|
wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
|
|
@@ -1218,7 +1277,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
|
|
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
|
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
|
if (beacon && net_ratelimit())
|
|
if (beacon && net_ratelimit())
|
|
printk(KERN_DEBUG "%s: detected beacon loss from AP "
|
|
printk(KERN_DEBUG "%s: detected beacon loss from AP "
|
|
- "- sending probe request\n", sdata->dev->name);
|
|
|
|
|
|
+ "- sending probe request\n", sdata->name);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1275,7 +1334,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
|
|
struct ieee80211_mgd_work *wk)
|
|
struct ieee80211_mgd_work *wk)
|
|
{
|
|
{
|
|
wk->state = IEEE80211_MGD_STATE_IDLE;
|
|
wk->state = IEEE80211_MGD_STATE_IDLE;
|
|
- printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
|
|
|
|
|
|
+ printk(KERN_DEBUG "%s: authenticated\n", sdata->name);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1372,7 +1431,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
|
|
reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
|
|
reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
|
|
|
|
|
|
printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
|
|
printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
|
|
- sdata->dev->name, bssid, reason_code);
|
|
|
|
|
|
+ sdata->name, bssid, reason_code);
|
|
|
|
|
|
if (!wk) {
|
|
if (!wk) {
|
|
ieee80211_set_disassoc(sdata, true);
|
|
ieee80211_set_disassoc(sdata, true);
|
|
@@ -1407,7 +1466,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
|
|
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
|
|
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
|
|
|
|
|
|
printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
|
|
printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
|
|
- sdata->dev->name, mgmt->sa, reason_code);
|
|
|
|
|
|
+ sdata->name, mgmt->sa, reason_code);
|
|
|
|
|
|
ieee80211_set_disassoc(sdata, false);
|
|
ieee80211_set_disassoc(sdata, false);
|
|
ieee80211_recalc_idle(sdata->local);
|
|
ieee80211_recalc_idle(sdata->local);
|
|
@@ -1431,8 +1490,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
|
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
|
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
|
u8 *pos;
|
|
u8 *pos;
|
|
u32 changed = 0;
|
|
u32 changed = 0;
|
|
- int i, j;
|
|
|
|
- bool have_higher_than_11mbit = false, newsta = false;
|
|
|
|
|
|
+ int i, j, err;
|
|
|
|
+ bool have_higher_than_11mbit = false;
|
|
u16 ap_ht_cap_flags;
|
|
u16 ap_ht_cap_flags;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1452,7 +1511,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
|
|
printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
|
|
"status=%d aid=%d)\n",
|
|
"status=%d aid=%d)\n",
|
|
- sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa,
|
|
|
|
|
|
+ sdata->name, reassoc ? "Rea" : "A", mgmt->sa,
|
|
capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
|
|
capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
|
|
|
|
|
|
pos = mgmt->u.assoc_resp.variable;
|
|
pos = mgmt->u.assoc_resp.variable;
|
|
@@ -1466,7 +1525,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
|
ms = tu * 1024 / 1000;
|
|
ms = tu * 1024 / 1000;
|
|
printk(KERN_DEBUG "%s: AP rejected association temporarily; "
|
|
printk(KERN_DEBUG "%s: AP rejected association temporarily; "
|
|
"comeback duration %u TU (%u ms)\n",
|
|
"comeback duration %u TU (%u ms)\n",
|
|
- sdata->dev->name, tu, ms);
|
|
|
|
|
|
+ sdata->name, tu, ms);
|
|
wk->timeout = jiffies + msecs_to_jiffies(ms);
|
|
wk->timeout = jiffies + msecs_to_jiffies(ms);
|
|
if (ms > IEEE80211_ASSOC_TIMEOUT)
|
|
if (ms > IEEE80211_ASSOC_TIMEOUT)
|
|
run_again(ifmgd, jiffies + msecs_to_jiffies(ms));
|
|
run_again(ifmgd, jiffies + msecs_to_jiffies(ms));
|
|
@@ -1475,49 +1534,37 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
if (status_code != WLAN_STATUS_SUCCESS) {
|
|
if (status_code != WLAN_STATUS_SUCCESS) {
|
|
printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
|
|
printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
|
|
- sdata->dev->name, status_code);
|
|
|
|
|
|
+ sdata->name, status_code);
|
|
wk->state = IEEE80211_MGD_STATE_IDLE;
|
|
wk->state = IEEE80211_MGD_STATE_IDLE;
|
|
return RX_MGMT_CFG80211_ASSOC;
|
|
return RX_MGMT_CFG80211_ASSOC;
|
|
}
|
|
}
|
|
|
|
|
|
if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
|
|
if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
|
|
printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
|
|
printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
|
|
- "set\n", sdata->dev->name, aid);
|
|
|
|
|
|
+ "set\n", sdata->name, aid);
|
|
aid &= ~(BIT(15) | BIT(14));
|
|
aid &= ~(BIT(15) | BIT(14));
|
|
|
|
|
|
if (!elems.supp_rates) {
|
|
if (!elems.supp_rates) {
|
|
printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
|
|
printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
|
|
- sdata->dev->name);
|
|
|
|
|
|
+ sdata->name);
|
|
return RX_MGMT_NONE;
|
|
return RX_MGMT_NONE;
|
|
}
|
|
}
|
|
|
|
|
|
- printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
|
|
|
|
|
|
+ printk(KERN_DEBUG "%s: associated\n", sdata->name);
|
|
ifmgd->aid = aid;
|
|
ifmgd->aid = aid;
|
|
|
|
|
|
- rcu_read_lock();
|
|
|
|
-
|
|
|
|
- /* Add STA entry for the AP */
|
|
|
|
- sta = sta_info_get(local, wk->bss->cbss.bssid);
|
|
|
|
|
|
+ sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL);
|
|
if (!sta) {
|
|
if (!sta) {
|
|
- newsta = true;
|
|
|
|
-
|
|
|
|
- rcu_read_unlock();
|
|
|
|
-
|
|
|
|
- sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL);
|
|
|
|
- if (!sta) {
|
|
|
|
- printk(KERN_DEBUG "%s: failed to alloc STA entry for"
|
|
|
|
- " the AP\n", sdata->dev->name);
|
|
|
|
- return RX_MGMT_NONE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
|
|
|
|
- WLAN_STA_ASSOC_AP);
|
|
|
|
- if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
|
|
|
|
- set_sta_flags(sta, WLAN_STA_AUTHORIZED);
|
|
|
|
-
|
|
|
|
- rcu_read_lock();
|
|
|
|
|
|
+ printk(KERN_DEBUG "%s: failed to alloc STA entry for"
|
|
|
|
+ " the AP\n", sdata->name);
|
|
|
|
+ return RX_MGMT_CFG80211_ASSOC_ERROR;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
|
|
|
|
+ WLAN_STA_ASSOC_AP);
|
|
|
|
+ if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
|
|
|
|
+ set_sta_flags(sta, WLAN_STA_AUTHORIZED);
|
|
|
|
+
|
|
rates = 0;
|
|
rates = 0;
|
|
basic_rates = 0;
|
|
basic_rates = 0;
|
|
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
|
|
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
|
|
@@ -1580,18 +1627,14 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
|
if (elems.wmm_param)
|
|
if (elems.wmm_param)
|
|
set_sta_flags(sta, WLAN_STA_WME);
|
|
set_sta_flags(sta, WLAN_STA_WME);
|
|
|
|
|
|
- if (newsta) {
|
|
|
|
- int err = sta_info_insert(sta);
|
|
|
|
- if (err) {
|
|
|
|
- printk(KERN_DEBUG "%s: failed to insert STA entry for"
|
|
|
|
- " the AP (error %d)\n", sdata->dev->name, err);
|
|
|
|
- rcu_read_unlock();
|
|
|
|
- return RX_MGMT_NONE;
|
|
|
|
- }
|
|
|
|
|
|
+ err = sta_info_insert(sta);
|
|
|
|
+ sta = NULL;
|
|
|
|
+ if (err) {
|
|
|
|
+ printk(KERN_DEBUG "%s: failed to insert STA entry for"
|
|
|
|
+ " the AP (error %d)\n", sdata->name, err);
|
|
|
|
+ return RX_MGMT_CFG80211_ASSOC_ERROR;
|
|
}
|
|
}
|
|
|
|
|
|
- rcu_read_unlock();
|
|
|
|
-
|
|
|
|
if (elems.wmm_param)
|
|
if (elems.wmm_param)
|
|
ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
|
|
ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
|
|
elems.wmm_param_len);
|
|
elems.wmm_param_len);
|
|
@@ -1679,7 +1722,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
ASSERT_MGD_MTX(ifmgd);
|
|
ASSERT_MGD_MTX(ifmgd);
|
|
|
|
|
|
- if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
|
|
|
|
|
|
+ if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
|
|
return; /* ignore ProbeResp to foreign address */
|
|
return; /* ignore ProbeResp to foreign address */
|
|
|
|
|
|
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
|
|
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
|
|
@@ -1694,7 +1737,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
|
|
/* direct probe may be part of the association flow */
|
|
/* direct probe may be part of the association flow */
|
|
if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
|
|
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);
|
|
|
|
|
|
+ sdata->name);
|
|
wk->tries = 0;
|
|
wk->tries = 0;
|
|
wk->state = IEEE80211_MGD_STATE_AUTH;
|
|
wk->state = IEEE80211_MGD_STATE_AUTH;
|
|
WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE);
|
|
WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE);
|
|
@@ -1787,7 +1830,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
|
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
|
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
|
if (net_ratelimit()) {
|
|
if (net_ratelimit()) {
|
|
printk(KERN_DEBUG "%s: cancelling probereq poll due "
|
|
printk(KERN_DEBUG "%s: cancelling probereq poll due "
|
|
- "to a received beacon\n", sdata->dev->name);
|
|
|
|
|
|
+ "to a received beacon\n", sdata->name);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
|
|
ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
|
|
@@ -1865,7 +1908,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
|
|
|
|
- sta = sta_info_get(local, bssid);
|
|
|
|
|
|
+ sta = sta_info_get(sdata, bssid);
|
|
if (WARN_ON(!sta)) {
|
|
if (WARN_ON(!sta)) {
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
return;
|
|
return;
|
|
@@ -2036,6 +2079,10 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
|
case RX_MGMT_CFG80211_DEAUTH:
|
|
case RX_MGMT_CFG80211_DEAUTH:
|
|
cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
|
|
cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
|
|
break;
|
|
break;
|
|
|
|
+ case RX_MGMT_CFG80211_ASSOC_ERROR:
|
|
|
|
+ /* an internal error -- pretend timeout for now */
|
|
|
|
+ cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
WARN(1, "unexpected: %d", rma);
|
|
WARN(1, "unexpected: %d", rma);
|
|
}
|
|
}
|
|
@@ -2336,6 +2383,11 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
|
|
ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
|
|
ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
|
|
|
|
|
|
mutex_init(&ifmgd->mtx);
|
|
mutex_init(&ifmgd->mtx);
|
|
|
|
+
|
|
|
|
+ if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
|
|
|
|
+ ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
|
|
|
|
+ else
|
|
|
|
+ ifmgd->req_smps = IEEE80211_SMPS_OFF;
|
|
}
|
|
}
|
|
|
|
|
|
/* scan finished notification */
|
|
/* scan finished notification */
|
|
@@ -2563,7 +2615,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
|
mutex_unlock(&ifmgd->mtx);
|
|
mutex_unlock(&ifmgd->mtx);
|
|
|
|
|
|
printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
|
|
printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
|
|
- sdata->dev->name, bssid, req->reason_code);
|
|
|
|
|
|
+ sdata->name, bssid, req->reason_code);
|
|
|
|
|
|
ieee80211_send_deauth_disassoc(sdata, bssid,
|
|
ieee80211_send_deauth_disassoc(sdata, bssid,
|
|
IEEE80211_STYPE_DEAUTH, req->reason_code,
|
|
IEEE80211_STYPE_DEAUTH, req->reason_code,
|
|
@@ -2594,7 +2646,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
|
|
}
|
|
}
|
|
|
|
|
|
printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
|
|
printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
|
|
- sdata->dev->name, req->bss->bssid, req->reason_code);
|
|
|
|
|
|
+ sdata->name, req->bss->bssid, req->reason_code);
|
|
|
|
|
|
ieee80211_set_disassoc(sdata, false);
|
|
ieee80211_set_disassoc(sdata, false);
|
|
|
|
|