diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b5f1bba7ffe1..3acb70b73e22 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2375,31 +2375,27 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2375 | switch (mgmt->u.action.u.ht_smps.action) { | 2375 | switch (mgmt->u.action.u.ht_smps.action) { |
2376 | case WLAN_HT_ACTION_SMPS: { | 2376 | case WLAN_HT_ACTION_SMPS: { |
2377 | struct ieee80211_supported_band *sband; | 2377 | struct ieee80211_supported_band *sband; |
2378 | u8 smps; | 2378 | enum ieee80211_smps_mode smps_mode; |
2379 | 2379 | ||
2380 | /* convert to HT capability */ | 2380 | /* convert to HT capability */ |
2381 | switch (mgmt->u.action.u.ht_smps.smps_control) { | 2381 | switch (mgmt->u.action.u.ht_smps.smps_control) { |
2382 | case WLAN_HT_SMPS_CONTROL_DISABLED: | 2382 | case WLAN_HT_SMPS_CONTROL_DISABLED: |
2383 | smps = WLAN_HT_CAP_SM_PS_DISABLED; | 2383 | smps_mode = IEEE80211_SMPS_OFF; |
2384 | break; | 2384 | break; |
2385 | case WLAN_HT_SMPS_CONTROL_STATIC: | 2385 | case WLAN_HT_SMPS_CONTROL_STATIC: |
2386 | smps = WLAN_HT_CAP_SM_PS_STATIC; | 2386 | smps_mode = IEEE80211_SMPS_STATIC; |
2387 | break; | 2387 | break; |
2388 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: | 2388 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: |
2389 | smps = WLAN_HT_CAP_SM_PS_DYNAMIC; | 2389 | smps_mode = IEEE80211_SMPS_DYNAMIC; |
2390 | break; | 2390 | break; |
2391 | default: | 2391 | default: |
2392 | goto invalid; | 2392 | goto invalid; |
2393 | } | 2393 | } |
2394 | smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
2395 | 2394 | ||
2396 | /* if no change do nothing */ | 2395 | /* if no change do nothing */ |
2397 | if ((rx->sta->sta.ht_cap.cap & | 2396 | if (rx->sta->sta.smps_mode == smps_mode) |
2398 | IEEE80211_HT_CAP_SM_PS) == smps) | ||
2399 | goto handled; | 2397 | goto handled; |
2400 | 2398 | rx->sta->sta.smps_mode = smps_mode; | |
2401 | rx->sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS; | ||
2402 | rx->sta->sta.ht_cap.cap |= smps; | ||
2403 | 2399 | ||
2404 | sband = rx->local->hw.wiphy->bands[status->band]; | 2400 | sband = rx->local->hw.wiphy->bands[status->band]; |
2405 | 2401 | ||
@@ -2410,26 +2406,21 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2410 | case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { | 2406 | case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { |
2411 | struct ieee80211_supported_band *sband; | 2407 | struct ieee80211_supported_band *sband; |
2412 | u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; | 2408 | u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; |
2413 | bool old_40mhz, new_40mhz; | 2409 | enum ieee80211_sta_rx_bandwidth new_bw; |
2414 | 2410 | ||
2415 | /* If it doesn't support 40 MHz it can't change ... */ | 2411 | /* If it doesn't support 40 MHz it can't change ... */ |
2416 | if (!rx->sta->supports_40mhz) | 2412 | if (!(rx->sta->sta.ht_cap.cap & |
2413 | IEEE80211_HT_CAP_SUP_WIDTH_20_40)) | ||
2417 | goto handled; | 2414 | goto handled; |
2418 | 2415 | ||
2419 | old_40mhz = rx->sta->sta.ht_cap.cap & | 2416 | if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) |
2420 | IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 2417 | new_bw = IEEE80211_STA_RX_BW_20; |
2421 | new_40mhz = chanwidth == IEEE80211_HT_CHANWIDTH_ANY; | 2418 | else |
2419 | new_bw = ieee80211_sta_cur_vht_bw(rx->sta); | ||
2422 | 2420 | ||
2423 | if (old_40mhz == new_40mhz) | 2421 | if (rx->sta->sta.bandwidth == new_bw) |
2424 | goto handled; | 2422 | goto handled; |
2425 | 2423 | ||
2426 | if (new_40mhz) | ||
2427 | rx->sta->sta.ht_cap.cap |= | ||
2428 | IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
2429 | else | ||
2430 | rx->sta->sta.ht_cap.cap &= | ||
2431 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
2432 | |||
2433 | sband = rx->local->hw.wiphy->bands[status->band]; | 2424 | sband = rx->local->hw.wiphy->bands[status->band]; |
2434 | 2425 | ||
2435 | rate_control_rate_update(local, sband, rx->sta, | 2426 | rate_control_rate_update(local, sband, rx->sta, |
@@ -2441,6 +2432,37 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2441 | } | 2432 | } |
2442 | 2433 | ||
2443 | break; | 2434 | break; |
2435 | case WLAN_CATEGORY_VHT: | ||
2436 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
2437 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | ||
2438 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
2439 | sdata->vif.type != NL80211_IFTYPE_AP && | ||
2440 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
2441 | break; | ||
2442 | |||
2443 | /* verify action code is present */ | ||
2444 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
2445 | goto invalid; | ||
2446 | |||
2447 | switch (mgmt->u.action.u.vht_opmode_notif.action_code) { | ||
2448 | case WLAN_VHT_ACTION_OPMODE_NOTIF: { | ||
2449 | u8 opmode; | ||
2450 | |||
2451 | /* verify opmode is present */ | ||
2452 | if (len < IEEE80211_MIN_ACTION_SIZE + 2) | ||
2453 | goto invalid; | ||
2454 | |||
2455 | opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; | ||
2456 | |||
2457 | ieee80211_vht_handle_opmode(rx->sdata, rx->sta, | ||
2458 | opmode, status->band, | ||
2459 | false); | ||
2460 | goto handled; | ||
2461 | } | ||
2462 | default: | ||
2463 | break; | ||
2464 | } | ||
2465 | break; | ||
2444 | case WLAN_CATEGORY_BACK: | 2466 | case WLAN_CATEGORY_BACK: |
2445 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 2467 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
2446 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | 2468 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && |
@@ -2692,8 +2714,9 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2692 | return RX_DROP_MONITOR; | 2714 | return RX_DROP_MONITOR; |
2693 | break; | 2715 | break; |
2694 | case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): | 2716 | case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): |
2695 | /* process only for ibss */ | 2717 | /* process only for ibss and mesh */ |
2696 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 2718 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
2719 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
2697 | return RX_DROP_MONITOR; | 2720 | return RX_DROP_MONITOR; |
2698 | break; | 2721 | break; |
2699 | default: | 2722 | default: |