aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c73
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: