diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00mac.c')
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 75 | 
1 files changed, 61 insertions, 14 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index abbd857ec75..235e037e650 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -273,16 +273,24 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,  	mutex_init(&intf->beacon_skb_mutex);  	intf->beacon = entry; -	if (vif->type == NL80211_IFTYPE_AP) -		memcpy(&intf->bssid, vif->addr, ETH_ALEN); -	memcpy(&intf->mac, vif->addr, ETH_ALEN); -  	/*  	 * The MAC adddress must be configured after the device  	 * has been initialized. Otherwise the device can reset  	 * the MAC registers. +	 * The BSSID address must only be configured in AP mode, +	 * however we should not send an empty BSSID address for +	 * STA interfaces at this time, since this can cause +	 * invalid behavior in the device.  	 */ -	rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL); +	memcpy(&intf->mac, vif->addr, ETH_ALEN); +	if (vif->type == NL80211_IFTYPE_AP) { +		memcpy(&intf->bssid, vif->addr, ETH_ALEN); +		rt2x00lib_config_intf(rt2x00dev, intf, vif->type, +				      intf->mac, intf->bssid); +	} else { +		rt2x00lib_config_intf(rt2x00dev, intf, vif->type, +				      intf->mac, NULL); +	}  	/*  	 * Some filters depend on the current working mode. We can force @@ -346,9 +354,11 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)  	/*  	 * Some configuration parameters (e.g. channel and antenna values) can  	 * only be set when the radio is enabled, but do require the RX to -	 * be off. +	 * be off. During this period we should keep link tuning enabled, +	 * if for any reason the link tuner must be reset, this will be +	 * handled by rt2x00lib_config().  	 */ -	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); +	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);  	/*  	 * When we've just turned on the radio, we want to reprogram @@ -366,7 +376,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)  	rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant);  	/* Turn RX back on */ -	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); +	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);  	return 0;  } @@ -430,12 +440,36 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,  }  EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); +static void rt2x00mac_set_tim_iter(void *data, u8 *mac, +				   struct ieee80211_vif *vif) +{ +	struct rt2x00_intf *intf = vif_to_intf(vif); + +	if (vif->type != NL80211_IFTYPE_AP && +	    vif->type != NL80211_IFTYPE_ADHOC && +	    vif->type != NL80211_IFTYPE_MESH_POINT && +	    vif->type != NL80211_IFTYPE_WDS) +		return; + +	spin_lock(&intf->lock); +	intf->delayed_flags |= DELAYED_UPDATE_BEACON; +	spin_unlock(&intf->lock); +} +  int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,  		      bool set)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; -	rt2x00lib_beacondone(rt2x00dev); +	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		return 0; + +	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, +						   rt2x00mac_set_tim_iter, +						   rt2x00dev); + +	/* queue work to upodate the beacon template */ +	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);  	return 0;  }  EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); @@ -539,6 +573,22 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  EXPORT_SYMBOL_GPL(rt2x00mac_set_key);  #endif /* CONFIG_RT2X00_LIB_CRYPTO */ +void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	__set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); +	rt2x00link_stop_tuner(rt2x00dev); +} +EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); + +void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	__clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); +	rt2x00link_start_tuner(rt2x00dev); +} +EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete); +  int rt2x00mac_get_stats(struct ieee80211_hw *hw,  			struct ieee80211_low_level_stats *stats)  { @@ -562,7 +612,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	struct rt2x00_intf *intf = vif_to_intf(vif); -	int update_bssid = 0;  	/*  	 * mac80211 might be calling this function while we are trying @@ -577,10 +626,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,  	 * conf->bssid can be NULL if coming from the internal  	 * beacon update routine.  	 */ -	if (changes & BSS_CHANGED_BSSID) { -		update_bssid = 1; +	if (changes & BSS_CHANGED_BSSID)  		memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); -	}  	spin_unlock(&intf->lock); @@ -592,7 +639,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,  	 */  	if (changes & BSS_CHANGED_BSSID)  		rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, -				      update_bssid ? bss_conf->bssid : NULL); +				      bss_conf->bssid);  	/*  	 * Update the beacon.  |