802.11: clean up/fix HT support
This patch cleans up a number of things:
 * the unusable definition of the HT capabilities/HT information
   information elements
 * variable names that are hard to understand
 * mac80211: move ieee80211_handle_ht to ht.c and remove the unused
             enable_ht parameter
 * mac80211: fix bug with MCS rate 32 in ieee80211_handle_ht
 * mac80211: fix bug with casting the result of ieee80211_bss_get_ie
             to an information element _contents_ rather than the
             whole element, add size checking (another out-of-bounds
             access bug fixed!)
 * mac80211: remove some unused return values in favour of BUG_ON
             checking
 * a few minor other things
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
			
			
This commit is contained in:
		
				
					committed by
					
						 John W. Linville
						John W. Linville
					
				
			
			
				
	
			
			
			
						parent
						
							40333e4fb4
						
					
				
				
					commit
					d9fe60dea7
				
			| @@ -232,100 +232,6 @@ int ieee80211_hw_config(struct ieee80211_local *local) | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * ieee80211_handle_ht should be used only after legacy configuration | ||||
|  * has been determined namely band, as ht configuration depends upon | ||||
|  * the hardware's HT abilities for a _specific_ band. | ||||
|  */ | ||||
| u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | ||||
| 			   struct ieee80211_ht_info *req_ht_cap, | ||||
| 			   struct ieee80211_ht_bss_info *req_bss_cap) | ||||
| { | ||||
| 	struct ieee80211_conf *conf = &local->hw.conf; | ||||
| 	struct ieee80211_supported_band *sband; | ||||
| 	struct ieee80211_ht_info ht_conf; | ||||
| 	struct ieee80211_ht_bss_info ht_bss_conf; | ||||
| 	u32 changed = 0; | ||||
| 	int i; | ||||
| 	u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS; | ||||
| 	u8 tx_mcs_set_cap; | ||||
|  | ||||
| 	sband = local->hw.wiphy->bands[conf->channel->band]; | ||||
|  | ||||
| 	memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); | ||||
| 	memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); | ||||
|  | ||||
| 	/* HT is not supported */ | ||||
| 	if (!sband->ht_info.ht_supported) { | ||||
| 		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	/* disable HT */ | ||||
| 	if (!enable_ht) { | ||||
| 		if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) | ||||
| 			changed |= BSS_CHANGED_HT; | ||||
| 		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | ||||
| 		conf->ht_conf.ht_supported = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) | ||||
| 		changed |= BSS_CHANGED_HT; | ||||
|  | ||||
| 	conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; | ||||
| 	ht_conf.ht_supported = 1; | ||||
|  | ||||
| 	ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; | ||||
| 	ht_conf.cap &= ~(IEEE80211_HT_CAP_SM_PS); | ||||
| 	ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_SM_PS; | ||||
| 	ht_bss_conf.primary_channel = req_bss_cap->primary_channel; | ||||
| 	ht_bss_conf.bss_cap = req_bss_cap->bss_cap; | ||||
| 	ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; | ||||
|  | ||||
| 	ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; | ||||
| 	ht_conf.ampdu_density = req_ht_cap->ampdu_density; | ||||
|  | ||||
| 	/* Bits 96-100 */ | ||||
| 	tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12]; | ||||
|  | ||||
| 	/* configure suppoerted Tx MCS according to requested MCS | ||||
| 	 * (based in most cases on Rx capabilities of peer) and self | ||||
| 	 * Tx MCS capabilities (as defined by low level driver HW | ||||
| 	 * Tx capabilities) */ | ||||
| 	if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED)) | ||||
| 		goto check_changed; | ||||
|  | ||||
| 	/* Counting from 0 therfore + 1 */ | ||||
| 	if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF) | ||||
| 		max_tx_streams = ((tx_mcs_set_cap & | ||||
| 				IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1; | ||||
|  | ||||
| 	for (i = 0; i < max_tx_streams; i++) | ||||
| 		ht_conf.supp_mcs_set[i] = | ||||
| 			sband->ht_info.supp_mcs_set[i] & | ||||
| 					req_ht_cap->supp_mcs_set[i]; | ||||
|  | ||||
| 	if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM) | ||||
| 		for (i = IEEE80211_SUPP_MCS_SET_UEQM; | ||||
| 		     i < IEEE80211_SUPP_MCS_SET_LEN; i++) | ||||
| 			ht_conf.supp_mcs_set[i] = | ||||
| 				sband->ht_info.supp_mcs_set[i] & | ||||
| 					req_ht_cap->supp_mcs_set[i]; | ||||
|  | ||||
| check_changed: | ||||
| 	/* if bss configuration changed store the new one */ | ||||
| 	if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || | ||||
| 	    memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { | ||||
| 		changed |= BSS_CHANGED_HT; | ||||
| 		memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); | ||||
| 		memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); | ||||
| 	} | ||||
| out: | ||||
| 	return changed; | ||||
| } | ||||
|  | ||||
| void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | ||||
| 				      u32 changed) | ||||
| { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user