diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00dev.c')
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 22 | 
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e1fb2a8569b..edd317fa7c0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -465,6 +465,23 @@ static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)  	return NULL;  } +static void rt2x00lib_sleep(struct work_struct *work) +{ +	struct rt2x00_dev *rt2x00dev = +	    container_of(work, struct rt2x00_dev, sleep_work); + +	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) +		return; + +	/* +	 * Check again is powersaving is enabled, to prevent races from delayed +	 * work execution. +	 */ +	if (!test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags)) +		rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf, +				 IEEE80211_CONF_CHANGE_PS); +} +  static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,  				      struct sk_buff *skb,  				      struct rxdone_entry_desc *rxdesc) @@ -512,8 +529,7 @@ static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,  	cam |= (tim_ie->bitmap_ctrl & 0x01);  	if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags)) -		rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf, -				 IEEE80211_CONF_CHANGE_PS); +		queue_work(rt2x00dev->workqueue, &rt2x00dev->sleep_work);  }  static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, @@ -1141,6 +1157,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)  	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);  	INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); +	INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);  	/*  	 * Let the driver probe the device to detect the capabilities. @@ -1197,6 +1214,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)  	 */  	cancel_work_sync(&rt2x00dev->intf_work);  	cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); +	cancel_work_sync(&rt2x00dev->sleep_work);  	if (rt2x00_is_usb(rt2x00dev)) {  		del_timer_sync(&rt2x00dev->txstatus_timer);  		cancel_work_sync(&rt2x00dev->rxdone_work);  |