diff options
Diffstat (limited to 'net/mac80211/util.c')
| -rw-r--r-- | net/mac80211/util.c | 151 | 
1 files changed, 118 insertions, 33 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d3fe2d237485..ddeb1b998383 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -799,6 +799,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)  		qparam.uapsd = false; +		local->tx_conf[queue] = qparam;  		drv_conf_tx(local, queue, &qparam);  	} @@ -1016,9 +1017,10 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,  }  struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, -					  u8 *dst, +					  u8 *dst, u32 ratemask,  					  const u8 *ssid, size_t ssid_len, -					  const u8 *ie, size_t ie_len) +					  const u8 *ie, size_t ie_len, +					  bool directed)  {  	struct ieee80211_local *local = sdata->local;  	struct sk_buff *skb; @@ -1035,14 +1037,20 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,  		return NULL;  	} -	chan = ieee80211_frequency_to_channel( -		local->hw.conf.channel->center_freq); +	/* +	 * Do not send DS Channel parameter for directed probe requests +	 * in order to maximize the chance that we get a response.  Some +	 * badly-behaved APs don't respond when this parameter is included. +	 */ +	if (directed) +		chan = 0; +	else +		chan = ieee80211_frequency_to_channel( +			local->hw.conf.channel->center_freq);  	buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,  					   local->hw.conf.channel->band, -					   sdata->rc_rateidx_mask -					   [local->hw.conf.channel->band], -					   chan); +					   ratemask, chan);  	skb = ieee80211_probereq_get(&local->hw, &sdata->vif,  				     ssid, ssid_len, @@ -1062,11 +1070,13 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,  void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,  			      const u8 *ssid, size_t ssid_len, -			      const u8 *ie, size_t ie_len) +			      const u8 *ie, size_t ie_len, +			      u32 ratemask, bool directed)  {  	struct sk_buff *skb; -	skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len); +	skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, +					ie, ie_len, directed);  	if (skb)  		ieee80211_tx_skb(sdata, skb);  } @@ -1123,7 +1133,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)  	struct ieee80211_hw *hw = &local->hw;  	struct ieee80211_sub_if_data *sdata;  	struct sta_info *sta; -	int res; +	int res, i;  #ifdef CONFIG_PM  	if (local->suspended) @@ -1146,27 +1156,37 @@ int ieee80211_reconfig(struct ieee80211_local *local)  	}  #endif -	/* restart hardware */ -	if (local->open_count) { -		/* -		 * Upon resume hardware can sometimes be goofy due to -		 * various platform / driver / bus issues, so restarting -		 * the device may at times not work immediately. Propagate -		 * the error. -		 */ -		res = drv_start(local); -		if (res) { -			WARN(local->suspended, "Hardware became unavailable " -			     "upon resume. This could be a software issue " -			     "prior to suspend or a hardware issue.\n"); -			return res; -		} +	/* setup fragmentation threshold */ +	drv_set_frag_threshold(local, hw->wiphy->frag_threshold); + +	/* setup RTS threshold */ +	drv_set_rts_threshold(local, hw->wiphy->rts_threshold); + +	/* reset coverage class */ +	drv_set_coverage_class(local, hw->wiphy->coverage_class); + +	/* everything else happens only if HW was up & running */ +	if (!local->open_count) +		goto wake_up; -		ieee80211_led_radio(local, true); -		ieee80211_mod_tpt_led_trig(local, -					   IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); +	/* +	 * Upon resume hardware can sometimes be goofy due to +	 * various platform / driver / bus issues, so restarting +	 * the device may at times not work immediately. Propagate +	 * the error. +	 */ +	res = drv_start(local); +	if (res) { +		WARN(local->suspended, "Hardware became unavailable " +		     "upon resume. This could be a software issue " +		     "prior to suspend or a hardware issue.\n"); +		return res;  	} +	ieee80211_led_radio(local, true); +	ieee80211_mod_tpt_led_trig(local, +				   IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); +  	/* add interfaces */  	list_for_each_entry(sdata, &local->interfaces, list) {  		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && @@ -1190,11 +1210,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)  	}  	mutex_unlock(&local->sta_mtx); -	/* setup fragmentation threshold */ -	drv_set_frag_threshold(local, hw->wiphy->frag_threshold); - -	/* setup RTS threshold */ -	drv_set_rts_threshold(local, hw->wiphy->rts_threshold); +	/* reconfigure tx conf */ +	for (i = 0; i < hw->queues; i++) +		drv_conf_tx(local, i, &local->tx_conf[i]);  	/* reconfigure hardware */  	ieee80211_hw_config(local, ~0); @@ -1321,6 +1339,33 @@ int ieee80211_reconfig(struct ieee80211_local *local)  	return 0;  } +void ieee80211_resume_disconnect(struct ieee80211_vif *vif) +{ +	struct ieee80211_sub_if_data *sdata; +	struct ieee80211_local *local; +	struct ieee80211_key *key; + +	if (WARN_ON(!vif)) +		return; + +	sdata = vif_to_sdata(vif); +	local = sdata->local; + +	if (WARN_ON(!local->resuming)) +		return; + +	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) +		return; + +	sdata->flags |= IEEE80211_SDATA_DISCONNECT_RESUME; + +	mutex_lock(&local->key_mtx); +	list_for_each_entry(key, &sdata->key_list, list) +		key->flags |= KEY_FLAG_TAINTED; +	mutex_unlock(&local->key_mtx); +} +EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect); +  static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,  			  enum ieee80211_smps_mode *smps_mode)  { @@ -1437,3 +1482,43 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)  	return pos;  } + +static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata, +					    int rssi_min_thold, +					    int rssi_max_thold) +{ +	trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold); + +	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) +		return; + +	/* +	 * Scale up threshold values before storing it, as the RSSI averaging +	 * algorithm uses a scaled up value as well. Change this scaling +	 * factor if the RSSI averaging algorithm changes. +	 */ +	sdata->u.mgd.rssi_min_thold = rssi_min_thold*16; +	sdata->u.mgd.rssi_max_thold = rssi_max_thold*16; +} + +void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, +				    int rssi_min_thold, +				    int rssi_max_thold) +{ +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + +	WARN_ON(rssi_min_thold == rssi_max_thold || +		rssi_min_thold > rssi_max_thold); + +	_ieee80211_enable_rssi_reports(sdata, rssi_min_thold, +				       rssi_max_thold); +} +EXPORT_SYMBOL(ieee80211_enable_rssi_reports); + +void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) +{ +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + +	_ieee80211_enable_rssi_reports(sdata, 0, 0); +} +EXPORT_SYMBOL(ieee80211_disable_rssi_reports);  |