forked from mirrors/linux
		
	mac80211: add VHT support for IBSS
Add VHT support for IBSS. Drivers could activate this feature by setting NL80211_EXT_FEATURE_VHT_IBSS flag. Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
		
							parent
							
								
									76bed0f43b
								
							
						
					
					
						commit
						abcff6ef01
					
				
					 5 changed files with 80 additions and 11 deletions
				
			
		| 
						 | 
					@ -252,8 +252,6 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bw != sta->sta.bandwidth)
 | 
					 | 
				
			||||||
		changed = true;
 | 
					 | 
				
			||||||
	sta->sta.bandwidth = bw;
 | 
						sta->sta.bandwidth = bw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sta->cur_max_bandwidth =
 | 
						sta->cur_max_bandwidth =
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,6 +188,16 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
 | 
							pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
 | 
				
			||||||
						 chandef, 0);
 | 
											 chandef, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* add VHT capability and information IEs */
 | 
				
			||||||
 | 
							if (chandef->width != NL80211_CHAN_WIDTH_20 &&
 | 
				
			||||||
 | 
							    chandef->width != NL80211_CHAN_WIDTH_40 &&
 | 
				
			||||||
 | 
							    sband->vht_cap.vht_supported) {
 | 
				
			||||||
 | 
								pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
 | 
				
			||||||
 | 
												 sband->vht_cap.cap);
 | 
				
			||||||
 | 
								pos = ieee80211_ie_build_vht_oper(pos, &sband->vht_cap,
 | 
				
			||||||
 | 
												  chandef);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (local->hw.queues >= IEEE80211_NUM_ACS)
 | 
						if (local->hw.queues >= IEEE80211_NUM_ACS)
 | 
				
			||||||
| 
						 | 
					@ -415,6 +425,11 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
					NL80211_CHAN_WIDTH_20_NOHT);
 | 
										NL80211_CHAN_WIDTH_20_NOHT);
 | 
				
			||||||
		chandef.width = sdata->u.ibss.chandef.width;
 | 
							chandef.width = sdata->u.ibss.chandef.width;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case NL80211_CHAN_WIDTH_80:
 | 
				
			||||||
 | 
						case NL80211_CHAN_WIDTH_160:
 | 
				
			||||||
 | 
							chandef = sdata->u.ibss.chandef;
 | 
				
			||||||
 | 
							chandef.chan = cbss->channel;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		/* fall back to 20 MHz for unsupported modes */
 | 
							/* fall back to 20 MHz for unsupported modes */
 | 
				
			||||||
		cfg80211_chandef_create(&chandef, cbss->channel,
 | 
							cfg80211_chandef_create(&chandef, cbss->channel,
 | 
				
			||||||
| 
						 | 
					@ -1026,24 +1041,40 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		/* we both use HT */
 | 
							/* we both use HT */
 | 
				
			||||||
		struct ieee80211_ht_cap htcap_ie;
 | 
							struct ieee80211_ht_cap htcap_ie;
 | 
				
			||||||
		struct cfg80211_chan_def chandef;
 | 
							struct cfg80211_chan_def chandef;
 | 
				
			||||||
 | 
							enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ieee80211_ht_oper_to_chandef(channel,
 | 
							ieee80211_ht_oper_to_chandef(channel,
 | 
				
			||||||
					     elems->ht_operation,
 | 
										     elems->ht_operation,
 | 
				
			||||||
					     &chandef);
 | 
										     &chandef);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
 | 
							memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * fall back to HT20 if we don't use or use
 | 
					 | 
				
			||||||
		 * the other extension channel
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		if (chandef.center_freq1 != sdata->u.ibss.chandef.center_freq1)
 | 
					 | 
				
			||||||
			htcap_ie.cap_info &=
 | 
					 | 
				
			||||||
				cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
 | 
							rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
 | 
				
			||||||
								   &htcap_ie,
 | 
													   &htcap_ie,
 | 
				
			||||||
								   sta);
 | 
													   sta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (elems->vht_operation && elems->vht_cap_elem &&
 | 
				
			||||||
 | 
							    sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20 &&
 | 
				
			||||||
 | 
							    sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_40) {
 | 
				
			||||||
 | 
								/* we both use VHT */
 | 
				
			||||||
 | 
								struct ieee80211_vht_cap cap_ie;
 | 
				
			||||||
 | 
								struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								ieee80211_vht_oper_to_chandef(channel,
 | 
				
			||||||
 | 
											      elems->vht_operation,
 | 
				
			||||||
 | 
											      &chandef);
 | 
				
			||||||
 | 
								memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
 | 
				
			||||||
 | 
								ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
 | 
				
			||||||
 | 
												    &cap_ie, sta);
 | 
				
			||||||
 | 
								if (memcmp(&cap, &sta->sta.vht_cap, sizeof(cap)))
 | 
				
			||||||
 | 
									rates_updated |= true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (bw != sta->sta.bandwidth)
 | 
				
			||||||
 | 
								rates_updated |= true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!cfg80211_chandef_compatible(&sdata->u.ibss.chandef,
 | 
				
			||||||
 | 
											 &chandef))
 | 
				
			||||||
 | 
								WARN_ON_ONCE(1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sta && rates_updated) {
 | 
						if (sta && rates_updated) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1960,6 +1960,9 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo);
 | 
				
			||||||
void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
 | 
					void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
 | 
				
			||||||
				  const struct ieee80211_ht_operation *ht_oper,
 | 
									  const struct ieee80211_ht_operation *ht_oper,
 | 
				
			||||||
				  struct cfg80211_chan_def *chandef);
 | 
									  struct cfg80211_chan_def *chandef);
 | 
				
			||||||
 | 
					void ieee80211_vht_oper_to_chandef(struct ieee80211_channel *control_chan,
 | 
				
			||||||
 | 
									   const struct ieee80211_vht_operation *oper,
 | 
				
			||||||
 | 
									   struct cfg80211_chan_def *chandef);
 | 
				
			||||||
u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c);
 | 
					u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int __must_check
 | 
					int __must_check
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -382,6 +382,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
 | 
						enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
 | 
				
			||||||
	struct ieee80211_supported_band *sband;
 | 
						struct ieee80211_supported_band *sband;
 | 
				
			||||||
	u32 rates, basic_rates = 0, changed = 0;
 | 
						u32 rates, basic_rates = 0, changed = 0;
 | 
				
			||||||
 | 
						enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sband = local->hw.wiphy->bands[band];
 | 
						sband = local->hw.wiphy->bands[band];
 | 
				
			||||||
	rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates);
 | 
						rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates);
 | 
				
			||||||
| 
						 | 
					@ -401,6 +402,9 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
					      elems->ht_cap_elem, sta))
 | 
										      elems->ht_cap_elem, sta))
 | 
				
			||||||
		changed |= IEEE80211_RC_BW_CHANGED;
 | 
							changed |= IEEE80211_RC_BW_CHANGED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bw != sta->sta.bandwidth)
 | 
				
			||||||
 | 
							changed |= IEEE80211_RC_BW_CHANGED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* HT peer is operating 20MHz-only */
 | 
						/* HT peer is operating 20MHz-only */
 | 
				
			||||||
	if (elems->ht_operation &&
 | 
						if (elems->ht_operation &&
 | 
				
			||||||
	    !(elems->ht_operation->ht_param &
 | 
						    !(elems->ht_operation->ht_param &
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2440,6 +2440,39 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
 | 
				
			||||||
	cfg80211_chandef_create(chandef, control_chan, channel_type);
 | 
						cfg80211_chandef_create(chandef, control_chan, channel_type);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ieee80211_vht_oper_to_chandef(struct ieee80211_channel *control_chan,
 | 
				
			||||||
 | 
									   const struct ieee80211_vht_operation *oper,
 | 
				
			||||||
 | 
									   struct cfg80211_chan_def *chandef)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!oper)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chandef->chan = control_chan;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (oper->chan_width) {
 | 
				
			||||||
 | 
						case IEEE80211_VHT_CHANWIDTH_USE_HT:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IEEE80211_VHT_CHANWIDTH_80MHZ:
 | 
				
			||||||
 | 
							chandef->width = NL80211_CHAN_WIDTH_80;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IEEE80211_VHT_CHANWIDTH_160MHZ:
 | 
				
			||||||
 | 
							chandef->width = NL80211_CHAN_WIDTH_160;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
 | 
				
			||||||
 | 
							chandef->width = NL80211_CHAN_WIDTH_80P80;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chandef->center_freq1 =
 | 
				
			||||||
 | 
							ieee80211_channel_to_frequency(oper->center_freq_seg1_idx,
 | 
				
			||||||
 | 
										       control_chan->band);
 | 
				
			||||||
 | 
						chandef->center_freq2 =
 | 
				
			||||||
 | 
							ieee80211_channel_to_frequency(oper->center_freq_seg2_idx,
 | 
				
			||||||
 | 
										       control_chan->band);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
 | 
					int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
 | 
				
			||||||
			     const struct ieee80211_supported_band *sband,
 | 
								     const struct ieee80211_supported_band *sband,
 | 
				
			||||||
			     const u8 *srates, int srates_len, u32 *rates)
 | 
								     const u8 *srates, int srates_len, u32 *rates)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue