diff options
| author | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-11 14:36:25 +0100 | 
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-11 14:36:25 +0100 | 
| commit | a8931ef380c92d121ae74ecfb03b2d63f72eea6f (patch) | |
| tree | 980fb6b019e11e6cb1ece55b7faff184721a8053 /drivers/net/wireless/rt2x00/rt2x00dev.c | |
| parent | 90574d0a4d4b73308ae54a2a57a4f3f1fa98e984 (diff) | |
| parent | e5a5816f7875207cb0a0a7032e39a4686c5e10a4 (diff) | |
| download | olio-linux-3.10-a8931ef380c92d121ae74ecfb03b2d63f72eea6f.tar.xz olio-linux-3.10-a8931ef380c92d121ae74ecfb03b2d63f72eea6f.zip  | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00dev.c')
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 59 | 
1 files changed, 35 insertions, 24 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index f8fe7a139a8..c997d4f28ab 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -75,7 +75,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev)  	rt2x00lib_reset_link_tuner(rt2x00dev); -	queue_delayed_work(rt2x00dev->hw->workqueue, +	queue_delayed_work(rt2x00dev->workqueue,  			   &rt2x00dev->link.work, LINK_TUNE_INTERVAL);  } @@ -114,6 +114,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)  		return status;  	rt2x00leds_led_radio(rt2x00dev, true); +	rt2x00led_led_activity(rt2x00dev, true);  	__set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags); @@ -136,14 +137,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)  		return;  	/* -	 * Stop all scheduled work. -	 */ -	if (work_pending(&rt2x00dev->intf_work)) -		cancel_work_sync(&rt2x00dev->intf_work); -	if (work_pending(&rt2x00dev->filter_work)) -		cancel_work_sync(&rt2x00dev->filter_work); - -	/*  	 * Stop the TX queues.  	 */  	ieee80211_stop_queues(rt2x00dev->hw); @@ -157,6 +150,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)  	 * Disable radio.  	 */  	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF); +	rt2x00led_led_activity(rt2x00dev, false);  	rt2x00leds_led_radio(rt2x00dev, false);  } @@ -396,8 +390,8 @@ static void rt2x00lib_link_tuner(struct work_struct *work)  	 * Increase tuner counter, and reschedule the next link tuner run.  	 */  	rt2x00dev->link.count++; -	queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, -			   LINK_TUNE_INTERVAL); +	queue_delayed_work(rt2x00dev->workqueue, +			   &rt2x00dev->link.work, LINK_TUNE_INTERVAL);  }  static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) @@ -431,6 +425,15 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,  	spin_unlock(&intf->lock); +	/* +	 * It is possible the radio was disabled while the work had been +	 * scheduled. If that happens we should return here immediately, +	 * note that in the spinlock protected area above the delayed_flags +	 * have been cleared correctly. +	 */ +	if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) +		return; +  	if (delayed_flags & DELAYED_UPDATE_BEACON) {  		skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);  		if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, @@ -439,7 +442,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,  	}  	if (delayed_flags & DELAYED_CONFIG_ERP) -		rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf); +		rt2x00lib_config_erp(rt2x00dev, intf, &conf);  	if (delayed_flags & DELAYED_LED_ASSOC)  		rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); @@ -481,11 +484,11 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)  	if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))  		return; -	ieee80211_iterate_active_interfaces(rt2x00dev->hw, -					    rt2x00lib_beacondone_iter, -					    rt2x00dev); +	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, +						   rt2x00lib_beacondone_iter, +						   rt2x00dev); -	queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); +	queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work);  }  EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -505,7 +508,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	 * Update TX statistics.  	 */  	rt2x00dev->link.qual.tx_success += success; -	rt2x00dev->link.qual.tx_failed += txdesc->retry + fail; +	rt2x00dev->link.qual.tx_failed += fail;  	/*  	 * Initialize TX status @@ -1030,8 +1033,10 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)  	 * Initialize the device.  	 */  	status = rt2x00dev->ops->lib->initialize(rt2x00dev); -	if (status) -		goto exit; +	if (status) { +		rt2x00queue_uninitialize(rt2x00dev); +		return status; +	}  	__set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags); @@ -1041,11 +1046,6 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)  	rt2x00rfkill_register(rt2x00dev);  	return 0; - -exit: -	rt2x00lib_uninitialize(rt2x00dev); - -	return status;  }  int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) @@ -1131,6 +1131,10 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)  	/*  	 * Initialize configuration work.  	 */ +	rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib"); +	if (!rt2x00dev->workqueue) +		goto exit; +  	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);  	INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);  	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); @@ -1191,6 +1195,13 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)  	rt2x00leds_unregister(rt2x00dev);  	/* +	 * Stop all queued work. Note that most tasks will already be halted +	 * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize(). +	 */ +	flush_workqueue(rt2x00dev->workqueue); +	destroy_workqueue(rt2x00dev->workqueue); + +	/*  	 * Free ieee80211_hw memory.  	 */  	rt2x00lib_remove_hw(rt2x00dev);  |