diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index cd5dcc3d8c2b..0a762a9ba4df 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -398,6 +398,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
398 | __le16 tmp; | 398 | __le16 tmp; |
399 | u32 flags = local->hw.conf.channel->flags; | 399 | u32 flags = local->hw.conf.channel->flags; |
400 | 400 | ||
401 | /* determine capability flags */ | ||
402 | |||
401 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 403 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
402 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 404 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
403 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | 405 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { |
@@ -413,17 +415,64 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
413 | break; | 415 | break; |
414 | } | 416 | } |
415 | 417 | ||
416 | tmp = cpu_to_le16(cap); | 418 | /* set SM PS mode properly */ |
417 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); | 419 | cap &= ~IEEE80211_HT_CAP_SM_PS; |
420 | /* new association always uses requested smps mode */ | ||
421 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { | ||
422 | if (ifmgd->powersave) | ||
423 | ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; | ||
424 | else | ||
425 | ifmgd->ap_smps = IEEE80211_SMPS_OFF; | ||
426 | } else | ||
427 | ifmgd->ap_smps = ifmgd->req_smps; | ||
428 | |||
429 | switch (ifmgd->ap_smps) { | ||
430 | case IEEE80211_SMPS_AUTOMATIC: | ||
431 | case IEEE80211_SMPS_NUM_MODES: | ||
432 | WARN_ON(1); | ||
433 | case IEEE80211_SMPS_OFF: | ||
434 | cap |= WLAN_HT_CAP_SM_PS_DISABLED << | ||
435 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
436 | break; | ||
437 | case IEEE80211_SMPS_STATIC: | ||
438 | cap |= WLAN_HT_CAP_SM_PS_STATIC << | ||
439 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
440 | break; | ||
441 | case IEEE80211_SMPS_DYNAMIC: | ||
442 | cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
443 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
444 | break; | ||
445 | } | ||
446 | |||
447 | /* reserve and fill IE */ | ||
448 | |||
449 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
418 | *pos++ = WLAN_EID_HT_CAPABILITY; | 450 | *pos++ = WLAN_EID_HT_CAPABILITY; |
419 | *pos++ = sizeof(struct ieee80211_ht_cap); | 451 | *pos++ = sizeof(struct ieee80211_ht_cap); |
420 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | 452 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); |
453 | |||
454 | /* capability flags */ | ||
455 | tmp = cpu_to_le16(cap); | ||
421 | memcpy(pos, &tmp, sizeof(u16)); | 456 | memcpy(pos, &tmp, sizeof(u16)); |
422 | pos += sizeof(u16); | 457 | pos += sizeof(u16); |
423 | /* TODO: needs a define here for << 2 */ | 458 | |
459 | /* AMPDU parameters */ | ||
424 | *pos++ = sband->ht_cap.ampdu_factor | | 460 | *pos++ = sband->ht_cap.ampdu_factor | |
425 | (sband->ht_cap.ampdu_density << 2); | 461 | (sband->ht_cap.ampdu_density << |
462 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
463 | |||
464 | /* MCS set */ | ||
426 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | 465 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); |
466 | pos += sizeof(sband->ht_cap.mcs); | ||
467 | |||
468 | /* extended capabilities */ | ||
469 | pos += sizeof(__le16); | ||
470 | |||
471 | /* BF capabilities */ | ||
472 | pos += sizeof(__le32); | ||
473 | |||
474 | /* antenna selection */ | ||
475 | pos += sizeof(u8); | ||
427 | } | 476 | } |
428 | 477 | ||
429 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 478 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
@@ -932,6 +981,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
932 | 981 | ||
933 | mutex_lock(&local->iflist_mtx); | 982 | mutex_lock(&local->iflist_mtx); |
934 | ieee80211_recalc_ps(local, -1); | 983 | ieee80211_recalc_ps(local, -1); |
984 | ieee80211_recalc_smps(local, sdata); | ||
935 | mutex_unlock(&local->iflist_mtx); | 985 | mutex_unlock(&local->iflist_mtx); |
936 | 986 | ||
937 | netif_start_queue(sdata->dev); | 987 | netif_start_queue(sdata->dev); |
@@ -2327,6 +2377,11 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2327 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; | 2377 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; |
2328 | 2378 | ||
2329 | mutex_init(&ifmgd->mtx); | 2379 | mutex_init(&ifmgd->mtx); |
2380 | |||
2381 | if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) | ||
2382 | ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC; | ||
2383 | else | ||
2384 | ifmgd->req_smps = IEEE80211_SMPS_OFF; | ||
2330 | } | 2385 | } |
2331 | 2386 | ||
2332 | /* scan finished notification */ | 2387 | /* scan finished notification */ |