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 b5f1bba7ffe..3acb70b73e2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2375,31 +2375,27 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  		switch (mgmt->u.action.u.ht_smps.action) {  		case WLAN_HT_ACTION_SMPS: {  			struct ieee80211_supported_band *sband; -			u8 smps; +			enum ieee80211_smps_mode smps_mode;  			/* convert to HT capability */  			switch (mgmt->u.action.u.ht_smps.smps_control) {  			case WLAN_HT_SMPS_CONTROL_DISABLED: -				smps = WLAN_HT_CAP_SM_PS_DISABLED; +				smps_mode = IEEE80211_SMPS_OFF;  				break;  			case WLAN_HT_SMPS_CONTROL_STATIC: -				smps = WLAN_HT_CAP_SM_PS_STATIC; +				smps_mode = IEEE80211_SMPS_STATIC;  				break;  			case WLAN_HT_SMPS_CONTROL_DYNAMIC: -				smps = WLAN_HT_CAP_SM_PS_DYNAMIC; +				smps_mode = IEEE80211_SMPS_DYNAMIC;  				break;  			default:  				goto invalid;  			} -			smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;  			/* if no change do nothing */ -			if ((rx->sta->sta.ht_cap.cap & -					IEEE80211_HT_CAP_SM_PS) == smps) +			if (rx->sta->sta.smps_mode == smps_mode)  				goto handled; - -			rx->sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS; -			rx->sta->sta.ht_cap.cap |= smps; +			rx->sta->sta.smps_mode = smps_mode;  			sband = rx->local->hw.wiphy->bands[status->band]; @@ -2410,26 +2406,21 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  		case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {  			struct ieee80211_supported_band *sband;  			u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; -			bool old_40mhz, new_40mhz; +			enum ieee80211_sta_rx_bandwidth new_bw;  			/* If it doesn't support 40 MHz it can't change ... */ -			if (!rx->sta->supports_40mhz) +			if (!(rx->sta->sta.ht_cap.cap & +					IEEE80211_HT_CAP_SUP_WIDTH_20_40))  				goto handled; -			old_40mhz = rx->sta->sta.ht_cap.cap & -					IEEE80211_HT_CAP_SUP_WIDTH_20_40; -			new_40mhz = chanwidth == IEEE80211_HT_CHANWIDTH_ANY; +			if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) +				new_bw = IEEE80211_STA_RX_BW_20; +			else +				new_bw = ieee80211_sta_cur_vht_bw(rx->sta); -			if (old_40mhz == new_40mhz) +			if (rx->sta->sta.bandwidth == new_bw)  				goto handled; -			if (new_40mhz) -				rx->sta->sta.ht_cap.cap |= -					IEEE80211_HT_CAP_SUP_WIDTH_20_40; -			else -				rx->sta->sta.ht_cap.cap &= -					~IEEE80211_HT_CAP_SUP_WIDTH_20_40; -  			sband = rx->local->hw.wiphy->bands[status->band];  			rate_control_rate_update(local, sband, rx->sta, @@ -2441,6 +2432,37 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  		}  		break; +	case WLAN_CATEGORY_VHT: +		if (sdata->vif.type != NL80211_IFTYPE_STATION && +		    sdata->vif.type != NL80211_IFTYPE_MESH_POINT && +		    sdata->vif.type != NL80211_IFTYPE_AP_VLAN && +		    sdata->vif.type != NL80211_IFTYPE_AP && +		    sdata->vif.type != NL80211_IFTYPE_ADHOC) +			break; + +		/* verify action code is present */ +		if (len < IEEE80211_MIN_ACTION_SIZE + 1) +			goto invalid; + +		switch (mgmt->u.action.u.vht_opmode_notif.action_code) { +		case WLAN_VHT_ACTION_OPMODE_NOTIF: { +			u8 opmode; + +			/* verify opmode is present */ +			if (len < IEEE80211_MIN_ACTION_SIZE + 2) +				goto invalid; + +			opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; + +			ieee80211_vht_handle_opmode(rx->sdata, rx->sta, +						    opmode, status->band, +						    false); +			goto handled; +		} +		default: +			break; +		} +		break;  	case WLAN_CATEGORY_BACK:  		if (sdata->vif.type != NL80211_IFTYPE_STATION &&  		    sdata->vif.type != NL80211_IFTYPE_MESH_POINT && @@ -2692,8 +2714,9 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)  			return RX_DROP_MONITOR;  		break;  	case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): -		/* process only for ibss */ -		if (sdata->vif.type != NL80211_IFTYPE_ADHOC) +		/* process only for ibss and mesh */ +		if (sdata->vif.type != NL80211_IFTYPE_ADHOC && +		    sdata->vif.type != NL80211_IFTYPE_MESH_POINT)  			return RX_DROP_MONITOR;  		break;  	default:  |