diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 192 |
1 files changed, 122 insertions, 70 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c79e59f82fd9..2f9ed8b9c3f0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -75,6 +75,9 @@ enum rx_mgmt_action { | |||
75 | /* caller must call cfg80211_send_disassoc() */ | 75 | /* caller must call cfg80211_send_disassoc() */ |
76 | RX_MGMT_CFG80211_DISASSOC, | 76 | RX_MGMT_CFG80211_DISASSOC, |
77 | 77 | ||
78 | /* caller must tell cfg80211 about internal error */ | ||
79 | RX_MGMT_CFG80211_ASSOC_ERROR, | ||
80 | |||
78 | /* caller must call cfg80211_auth_timeout() & free work */ | 81 | /* caller must call cfg80211_auth_timeout() & free work */ |
79 | RX_MGMT_CFG80211_AUTH_TO, | 82 | RX_MGMT_CFG80211_AUTH_TO, |
80 | 83 | ||
@@ -202,7 +205,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
202 | ieee80211_hw_config(local, 0); | 205 | ieee80211_hw_config(local, 0); |
203 | 206 | ||
204 | rcu_read_lock(); | 207 | rcu_read_lock(); |
205 | sta = sta_info_get(local, bssid); | 208 | sta = sta_info_get(sdata, bssid); |
206 | if (sta) | 209 | if (sta) |
207 | rate_control_rate_update(local, sband, sta, | 210 | rate_control_rate_update(local, sband, sta, |
208 | IEEE80211_RC_HT_CHANGED); | 211 | IEEE80211_RC_HT_CHANGED); |
@@ -248,7 +251,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
248 | wk->ssid_len); | 251 | wk->ssid_len); |
249 | if (!skb) { | 252 | if (!skb) { |
250 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | 253 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " |
251 | "frame\n", sdata->dev->name); | 254 | "frame\n", sdata->name); |
252 | return; | 255 | return; |
253 | } | 256 | } |
254 | skb_reserve(skb, local->hw.extra_tx_headroom); | 257 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -282,7 +285,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
282 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 285 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
283 | memset(mgmt, 0, 24); | 286 | memset(mgmt, 0, 24); |
284 | memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN); | 287 | memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN); |
285 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 288 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
286 | memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN); | 289 | memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN); |
287 | 290 | ||
288 | if (!is_zero_ether_addr(wk->prev_bssid)) { | 291 | if (!is_zero_ether_addr(wk->prev_bssid)) { |
@@ -398,6 +401,14 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
398 | __le16 tmp; | 401 | __le16 tmp; |
399 | u32 flags = local->hw.conf.channel->flags; | 402 | u32 flags = local->hw.conf.channel->flags; |
400 | 403 | ||
404 | /* determine capability flags */ | ||
405 | |||
406 | if (ieee80211_disable_40mhz_24ghz && | ||
407 | sband->band == IEEE80211_BAND_2GHZ) { | ||
408 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
409 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
410 | } | ||
411 | |||
401 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 412 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
402 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 413 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
403 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | 414 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { |
@@ -413,17 +424,64 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
413 | break; | 424 | break; |
414 | } | 425 | } |
415 | 426 | ||
416 | tmp = cpu_to_le16(cap); | 427 | /* set SM PS mode properly */ |
417 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); | 428 | cap &= ~IEEE80211_HT_CAP_SM_PS; |
429 | /* new association always uses requested smps mode */ | ||
430 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { | ||
431 | if (ifmgd->powersave) | ||
432 | ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; | ||
433 | else | ||
434 | ifmgd->ap_smps = IEEE80211_SMPS_OFF; | ||
435 | } else | ||
436 | ifmgd->ap_smps = ifmgd->req_smps; | ||
437 | |||
438 | switch (ifmgd->ap_smps) { | ||
439 | case IEEE80211_SMPS_AUTOMATIC: | ||
440 | case IEEE80211_SMPS_NUM_MODES: | ||
441 | WARN_ON(1); | ||
442 | case IEEE80211_SMPS_OFF: | ||
443 | cap |= WLAN_HT_CAP_SM_PS_DISABLED << | ||
444 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
445 | break; | ||
446 | case IEEE80211_SMPS_STATIC: | ||
447 | cap |= WLAN_HT_CAP_SM_PS_STATIC << | ||
448 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
449 | break; | ||
450 | case IEEE80211_SMPS_DYNAMIC: | ||
451 | cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
452 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | /* reserve and fill IE */ | ||
457 | |||
458 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
418 | *pos++ = WLAN_EID_HT_CAPABILITY; | 459 | *pos++ = WLAN_EID_HT_CAPABILITY; |
419 | *pos++ = sizeof(struct ieee80211_ht_cap); | 460 | *pos++ = sizeof(struct ieee80211_ht_cap); |
420 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | 461 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); |
462 | |||
463 | /* capability flags */ | ||
464 | tmp = cpu_to_le16(cap); | ||
421 | memcpy(pos, &tmp, sizeof(u16)); | 465 | memcpy(pos, &tmp, sizeof(u16)); |
422 | pos += sizeof(u16); | 466 | pos += sizeof(u16); |
423 | /* TODO: needs a define here for << 2 */ | 467 | |
468 | /* AMPDU parameters */ | ||
424 | *pos++ = sband->ht_cap.ampdu_factor | | 469 | *pos++ = sband->ht_cap.ampdu_factor | |
425 | (sband->ht_cap.ampdu_density << 2); | 470 | (sband->ht_cap.ampdu_density << |
471 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
472 | |||
473 | /* MCS set */ | ||
426 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | 474 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); |
475 | pos += sizeof(sband->ht_cap.mcs); | ||
476 | |||
477 | /* extended capabilities */ | ||
478 | pos += sizeof(__le16); | ||
479 | |||
480 | /* BF capabilities */ | ||
481 | pos += sizeof(__le32); | ||
482 | |||
483 | /* antenna selection */ | ||
484 | pos += sizeof(u8); | ||
427 | } | 485 | } |
428 | 486 | ||
429 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 487 | 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, | |||
443 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 501 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); |
444 | if (!skb) { | 502 | if (!skb) { |
445 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | 503 | printk(KERN_DEBUG "%s: failed to allocate buffer for " |
446 | "deauth/disassoc frame\n", sdata->dev->name); | 504 | "deauth/disassoc frame\n", sdata->name); |
447 | return; | 505 | return; |
448 | } | 506 | } |
449 | skb_reserve(skb, local->hw.extra_tx_headroom); | 507 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -451,7 +509,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
451 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 509 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
452 | memset(mgmt, 0, 24); | 510 | memset(mgmt, 0, 24); |
453 | memcpy(mgmt->da, bssid, ETH_ALEN); | 511 | memcpy(mgmt->da, bssid, ETH_ALEN); |
454 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 512 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
455 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | 513 | memcpy(mgmt->bssid, bssid, ETH_ALEN); |
456 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); | 514 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); |
457 | skb_put(skb, 2); | 515 | skb_put(skb, 2); |
@@ -484,7 +542,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, | |||
484 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); | 542 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); |
485 | if (!skb) { | 543 | if (!skb) { |
486 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | 544 | printk(KERN_DEBUG "%s: failed to allocate buffer for " |
487 | "pspoll frame\n", sdata->dev->name); | 545 | "pspoll frame\n", sdata->name); |
488 | return; | 546 | return; |
489 | } | 547 | } |
490 | skb_reserve(skb, local->hw.extra_tx_headroom); | 548 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -499,7 +557,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, | |||
499 | pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); | 557 | pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); |
500 | 558 | ||
501 | memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); | 559 | memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); |
502 | memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN); | 560 | memcpy(pspoll->ta, sdata->vif.addr, ETH_ALEN); |
503 | 561 | ||
504 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 562 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
505 | ieee80211_tx_skb(sdata, skb); | 563 | ieee80211_tx_skb(sdata, skb); |
@@ -519,7 +577,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
519 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); | 577 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); |
520 | if (!skb) { | 578 | if (!skb) { |
521 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " | 579 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " |
522 | "frame\n", sdata->dev->name); | 580 | "frame\n", sdata->name); |
523 | return; | 581 | return; |
524 | } | 582 | } |
525 | skb_reserve(skb, local->hw.extra_tx_headroom); | 583 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -532,7 +590,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
532 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | 590 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); |
533 | nullfunc->frame_control = fc; | 591 | nullfunc->frame_control = fc; |
534 | memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); | 592 | memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); |
535 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | 593 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); |
536 | memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); | 594 | memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); |
537 | 595 | ||
538 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 596 | 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, | |||
940 | 998 | ||
941 | mutex_lock(&local->iflist_mtx); | 999 | mutex_lock(&local->iflist_mtx); |
942 | ieee80211_recalc_ps(local, -1); | 1000 | ieee80211_recalc_ps(local, -1); |
1001 | ieee80211_recalc_smps(local, sdata); | ||
943 | mutex_unlock(&local->iflist_mtx); | 1002 | mutex_unlock(&local->iflist_mtx); |
944 | 1003 | ||
945 | netif_start_queue(sdata->dev); | 1004 | netif_start_queue(sdata->dev); |
@@ -956,7 +1015,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
956 | wk->tries++; | 1015 | wk->tries++; |
957 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { | 1016 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { |
958 | printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", | 1017 | printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", |
959 | sdata->dev->name, wk->bss->cbss.bssid); | 1018 | sdata->name, wk->bss->cbss.bssid); |
960 | 1019 | ||
961 | /* | 1020 | /* |
962 | * Most likely AP is not in the range so remove the | 1021 | * Most likely AP is not in the range so remove the |
@@ -974,7 +1033,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
974 | } | 1033 | } |
975 | 1034 | ||
976 | printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", | 1035 | printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", |
977 | sdata->dev->name, wk->bss->cbss.bssid, | 1036 | sdata->name, wk->bss->cbss.bssid, |
978 | wk->tries); | 1037 | wk->tries); |
979 | 1038 | ||
980 | /* | 1039 | /* |
@@ -1001,7 +1060,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
1001 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { | 1060 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { |
1002 | printk(KERN_DEBUG "%s: authentication with AP %pM" | 1061 | printk(KERN_DEBUG "%s: authentication with AP %pM" |
1003 | " timed out\n", | 1062 | " timed out\n", |
1004 | sdata->dev->name, wk->bss->cbss.bssid); | 1063 | sdata->name, wk->bss->cbss.bssid); |
1005 | 1064 | ||
1006 | /* | 1065 | /* |
1007 | * Most likely AP is not in the range so remove the | 1066 | * Most likely AP is not in the range so remove the |
@@ -1019,7 +1078,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
1019 | } | 1078 | } |
1020 | 1079 | ||
1021 | printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", | 1080 | printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", |
1022 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); | 1081 | sdata->name, wk->bss->cbss.bssid, wk->tries); |
1023 | 1082 | ||
1024 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, | 1083 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, |
1025 | wk->bss->cbss.bssid, NULL, 0, 0); | 1084 | wk->bss->cbss.bssid, NULL, 0, 0); |
@@ -1078,7 +1137,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1078 | netif_carrier_off(sdata->dev); | 1137 | netif_carrier_off(sdata->dev); |
1079 | 1138 | ||
1080 | rcu_read_lock(); | 1139 | rcu_read_lock(); |
1081 | sta = sta_info_get(local, bssid); | 1140 | sta = sta_info_get(sdata, bssid); |
1082 | if (sta) | 1141 | if (sta) |
1083 | ieee80211_sta_tear_down_BA_sessions(sta); | 1142 | ieee80211_sta_tear_down_BA_sessions(sta); |
1084 | rcu_read_unlock(); | 1143 | rcu_read_unlock(); |
@@ -1115,7 +1174,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1115 | 1174 | ||
1116 | rcu_read_lock(); | 1175 | rcu_read_lock(); |
1117 | 1176 | ||
1118 | sta = sta_info_get(local, bssid); | 1177 | sta = sta_info_get(sdata, bssid); |
1119 | if (!sta) { | 1178 | if (!sta) { |
1120 | rcu_read_unlock(); | 1179 | rcu_read_unlock(); |
1121 | return; | 1180 | return; |
@@ -1139,7 +1198,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, | |||
1139 | if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) { | 1198 | if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) { |
1140 | printk(KERN_DEBUG "%s: association with AP %pM" | 1199 | printk(KERN_DEBUG "%s: association with AP %pM" |
1141 | " timed out\n", | 1200 | " timed out\n", |
1142 | sdata->dev->name, wk->bss->cbss.bssid); | 1201 | sdata->name, wk->bss->cbss.bssid); |
1143 | 1202 | ||
1144 | /* | 1203 | /* |
1145 | * Most likely AP is not in the range so remove the | 1204 | * Most likely AP is not in the range so remove the |
@@ -1157,7 +1216,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, | |||
1157 | } | 1216 | } |
1158 | 1217 | ||
1159 | printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", | 1218 | printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", |
1160 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); | 1219 | sdata->name, wk->bss->cbss.bssid, wk->tries); |
1161 | ieee80211_send_assoc(sdata, wk); | 1220 | ieee80211_send_assoc(sdata, wk); |
1162 | 1221 | ||
1163 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | 1222 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; |
@@ -1218,7 +1277,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1218 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1277 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1219 | if (beacon && net_ratelimit()) | 1278 | if (beacon && net_ratelimit()) |
1220 | printk(KERN_DEBUG "%s: detected beacon loss from AP " | 1279 | printk(KERN_DEBUG "%s: detected beacon loss from AP " |
1221 | "- sending probe request\n", sdata->dev->name); | 1280 | "- sending probe request\n", sdata->name); |
1222 | #endif | 1281 | #endif |
1223 | 1282 | ||
1224 | /* | 1283 | /* |
@@ -1275,7 +1334,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, | |||
1275 | struct ieee80211_mgd_work *wk) | 1334 | struct ieee80211_mgd_work *wk) |
1276 | { | 1335 | { |
1277 | wk->state = IEEE80211_MGD_STATE_IDLE; | 1336 | wk->state = IEEE80211_MGD_STATE_IDLE; |
1278 | printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); | 1337 | printk(KERN_DEBUG "%s: authenticated\n", sdata->name); |
1279 | } | 1338 | } |
1280 | 1339 | ||
1281 | 1340 | ||
@@ -1372,7 +1431,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1372 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 1431 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1373 | 1432 | ||
1374 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1433 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
1375 | sdata->dev->name, bssid, reason_code); | 1434 | sdata->name, bssid, reason_code); |
1376 | 1435 | ||
1377 | if (!wk) { | 1436 | if (!wk) { |
1378 | ieee80211_set_disassoc(sdata, true); | 1437 | ieee80211_set_disassoc(sdata, true); |
@@ -1407,7 +1466,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1407 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1466 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
1408 | 1467 | ||
1409 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1468 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
1410 | sdata->dev->name, mgmt->sa, reason_code); | 1469 | sdata->name, mgmt->sa, reason_code); |
1411 | 1470 | ||
1412 | ieee80211_set_disassoc(sdata, false); | 1471 | ieee80211_set_disassoc(sdata, false); |
1413 | ieee80211_recalc_idle(sdata->local); | 1472 | ieee80211_recalc_idle(sdata->local); |
@@ -1431,8 +1490,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1431 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 1490 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
1432 | u8 *pos; | 1491 | u8 *pos; |
1433 | u32 changed = 0; | 1492 | u32 changed = 0; |
1434 | int i, j; | 1493 | int i, j, err; |
1435 | bool have_higher_than_11mbit = false, newsta = false; | 1494 | bool have_higher_than_11mbit = false; |
1436 | u16 ap_ht_cap_flags; | 1495 | u16 ap_ht_cap_flags; |
1437 | 1496 | ||
1438 | /* | 1497 | /* |
@@ -1452,7 +1511,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1452 | 1511 | ||
1453 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | 1512 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " |
1454 | "status=%d aid=%d)\n", | 1513 | "status=%d aid=%d)\n", |
1455 | sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa, | 1514 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, |
1456 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | 1515 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
1457 | 1516 | ||
1458 | pos = mgmt->u.assoc_resp.variable; | 1517 | pos = mgmt->u.assoc_resp.variable; |
@@ -1466,7 +1525,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1466 | ms = tu * 1024 / 1000; | 1525 | ms = tu * 1024 / 1000; |
1467 | printk(KERN_DEBUG "%s: AP rejected association temporarily; " | 1526 | printk(KERN_DEBUG "%s: AP rejected association temporarily; " |
1468 | "comeback duration %u TU (%u ms)\n", | 1527 | "comeback duration %u TU (%u ms)\n", |
1469 | sdata->dev->name, tu, ms); | 1528 | sdata->name, tu, ms); |
1470 | wk->timeout = jiffies + msecs_to_jiffies(ms); | 1529 | wk->timeout = jiffies + msecs_to_jiffies(ms); |
1471 | if (ms > IEEE80211_ASSOC_TIMEOUT) | 1530 | if (ms > IEEE80211_ASSOC_TIMEOUT) |
1472 | run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); | 1531 | run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); |
@@ -1475,49 +1534,37 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1475 | 1534 | ||
1476 | if (status_code != WLAN_STATUS_SUCCESS) { | 1535 | if (status_code != WLAN_STATUS_SUCCESS) { |
1477 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", | 1536 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", |
1478 | sdata->dev->name, status_code); | 1537 | sdata->name, status_code); |
1479 | wk->state = IEEE80211_MGD_STATE_IDLE; | 1538 | wk->state = IEEE80211_MGD_STATE_IDLE; |
1480 | return RX_MGMT_CFG80211_ASSOC; | 1539 | return RX_MGMT_CFG80211_ASSOC; |
1481 | } | 1540 | } |
1482 | 1541 | ||
1483 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1542 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
1484 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " | 1543 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " |
1485 | "set\n", sdata->dev->name, aid); | 1544 | "set\n", sdata->name, aid); |
1486 | aid &= ~(BIT(15) | BIT(14)); | 1545 | aid &= ~(BIT(15) | BIT(14)); |
1487 | 1546 | ||
1488 | if (!elems.supp_rates) { | 1547 | if (!elems.supp_rates) { |
1489 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 1548 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", |
1490 | sdata->dev->name); | 1549 | sdata->name); |
1491 | return RX_MGMT_NONE; | 1550 | return RX_MGMT_NONE; |
1492 | } | 1551 | } |
1493 | 1552 | ||
1494 | printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); | 1553 | printk(KERN_DEBUG "%s: associated\n", sdata->name); |
1495 | ifmgd->aid = aid; | 1554 | ifmgd->aid = aid; |
1496 | 1555 | ||
1497 | rcu_read_lock(); | 1556 | sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); |
1498 | |||
1499 | /* Add STA entry for the AP */ | ||
1500 | sta = sta_info_get(local, wk->bss->cbss.bssid); | ||
1501 | if (!sta) { | 1557 | if (!sta) { |
1502 | newsta = true; | 1558 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" |
1503 | 1559 | " the AP\n", sdata->name); | |
1504 | rcu_read_unlock(); | 1560 | return RX_MGMT_CFG80211_ASSOC_ERROR; |
1505 | |||
1506 | sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); | ||
1507 | if (!sta) { | ||
1508 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" | ||
1509 | " the AP\n", sdata->dev->name); | ||
1510 | return RX_MGMT_NONE; | ||
1511 | } | ||
1512 | |||
1513 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | ||
1514 | WLAN_STA_ASSOC_AP); | ||
1515 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | ||
1516 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | ||
1517 | |||
1518 | rcu_read_lock(); | ||
1519 | } | 1561 | } |
1520 | 1562 | ||
1563 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | ||
1564 | WLAN_STA_ASSOC_AP); | ||
1565 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | ||
1566 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | ||
1567 | |||
1521 | rates = 0; | 1568 | rates = 0; |
1522 | basic_rates = 0; | 1569 | basic_rates = 0; |
1523 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1570 | 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, | |||
1580 | if (elems.wmm_param) | 1627 | if (elems.wmm_param) |
1581 | set_sta_flags(sta, WLAN_STA_WME); | 1628 | set_sta_flags(sta, WLAN_STA_WME); |
1582 | 1629 | ||
1583 | if (newsta) { | 1630 | err = sta_info_insert(sta); |
1584 | int err = sta_info_insert(sta); | 1631 | sta = NULL; |
1585 | if (err) { | 1632 | if (err) { |
1586 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | 1633 | printk(KERN_DEBUG "%s: failed to insert STA entry for" |
1587 | " the AP (error %d)\n", sdata->dev->name, err); | 1634 | " the AP (error %d)\n", sdata->name, err); |
1588 | rcu_read_unlock(); | 1635 | return RX_MGMT_CFG80211_ASSOC_ERROR; |
1589 | return RX_MGMT_NONE; | ||
1590 | } | ||
1591 | } | 1636 | } |
1592 | 1637 | ||
1593 | rcu_read_unlock(); | ||
1594 | |||
1595 | if (elems.wmm_param) | 1638 | if (elems.wmm_param) |
1596 | ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, | 1639 | ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, |
1597 | elems.wmm_param_len); | 1640 | elems.wmm_param_len); |
@@ -1679,7 +1722,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1679 | 1722 | ||
1680 | ASSERT_MGD_MTX(ifmgd); | 1723 | ASSERT_MGD_MTX(ifmgd); |
1681 | 1724 | ||
1682 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | 1725 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) |
1683 | return; /* ignore ProbeResp to foreign address */ | 1726 | return; /* ignore ProbeResp to foreign address */ |
1684 | 1727 | ||
1685 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 1728 | 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, | |||
1694 | /* direct probe may be part of the association flow */ | 1737 | /* direct probe may be part of the association flow */ |
1695 | if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) { | 1738 | if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) { |
1696 | printk(KERN_DEBUG "%s: direct probe responded\n", | 1739 | printk(KERN_DEBUG "%s: direct probe responded\n", |
1697 | sdata->dev->name); | 1740 | sdata->name); |
1698 | wk->tries = 0; | 1741 | wk->tries = 0; |
1699 | wk->state = IEEE80211_MGD_STATE_AUTH; | 1742 | wk->state = IEEE80211_MGD_STATE_AUTH; |
1700 | WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE); | 1743 | 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, | |||
1787 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1830 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1788 | if (net_ratelimit()) { | 1831 | if (net_ratelimit()) { |
1789 | printk(KERN_DEBUG "%s: cancelling probereq poll due " | 1832 | printk(KERN_DEBUG "%s: cancelling probereq poll due " |
1790 | "to a received beacon\n", sdata->dev->name); | 1833 | "to a received beacon\n", sdata->name); |
1791 | } | 1834 | } |
1792 | #endif | 1835 | #endif |
1793 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; | 1836 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; |
@@ -1865,7 +1908,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1865 | 1908 | ||
1866 | rcu_read_lock(); | 1909 | rcu_read_lock(); |
1867 | 1910 | ||
1868 | sta = sta_info_get(local, bssid); | 1911 | sta = sta_info_get(sdata, bssid); |
1869 | if (WARN_ON(!sta)) { | 1912 | if (WARN_ON(!sta)) { |
1870 | rcu_read_unlock(); | 1913 | rcu_read_unlock(); |
1871 | return; | 1914 | return; |
@@ -2036,6 +2079,10 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
2036 | case RX_MGMT_CFG80211_DEAUTH: | 2079 | case RX_MGMT_CFG80211_DEAUTH: |
2037 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | 2080 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); |
2038 | break; | 2081 | break; |
2082 | case RX_MGMT_CFG80211_ASSOC_ERROR: | ||
2083 | /* an internal error -- pretend timeout for now */ | ||
2084 | cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); | ||
2085 | break; | ||
2039 | default: | 2086 | default: |
2040 | WARN(1, "unexpected: %d", rma); | 2087 | WARN(1, "unexpected: %d", rma); |
2041 | } | 2088 | } |
@@ -2336,6 +2383,11 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2336 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; | 2383 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; |
2337 | 2384 | ||
2338 | mutex_init(&ifmgd->mtx); | 2385 | mutex_init(&ifmgd->mtx); |
2386 | |||
2387 | if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) | ||
2388 | ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC; | ||
2389 | else | ||
2390 | ifmgd->req_smps = IEEE80211_SMPS_OFF; | ||
2339 | } | 2391 | } |
2340 | 2392 | ||
2341 | /* scan finished notification */ | 2393 | /* scan finished notification */ |
@@ -2563,7 +2615,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2563 | mutex_unlock(&ifmgd->mtx); | 2615 | mutex_unlock(&ifmgd->mtx); |
2564 | 2616 | ||
2565 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 2617 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", |
2566 | sdata->dev->name, bssid, req->reason_code); | 2618 | sdata->name, bssid, req->reason_code); |
2567 | 2619 | ||
2568 | ieee80211_send_deauth_disassoc(sdata, bssid, | 2620 | ieee80211_send_deauth_disassoc(sdata, bssid, |
2569 | IEEE80211_STYPE_DEAUTH, req->reason_code, | 2621 | IEEE80211_STYPE_DEAUTH, req->reason_code, |
@@ -2594,7 +2646,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2594 | } | 2646 | } |
2595 | 2647 | ||
2596 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 2648 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", |
2597 | sdata->dev->name, req->bss->bssid, req->reason_code); | 2649 | sdata->name, req->bss->bssid, req->reason_code); |
2598 | 2650 | ||
2599 | ieee80211_set_disassoc(sdata, false); | 2651 | ieee80211_set_disassoc(sdata, false); |
2600 | 2652 | ||