aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2009-06-01 16:49:25 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-06-03 14:05:15 -0400
commit6d7db193f2097d2f12fdc6b2300439a91a3196be (patch)
treed918f4737ac2093e5eaf5538d802571157db2e44 /drivers
parent66d008139c61d610f3ade9b46ad610e2cd277fb9 (diff)
ar9170: cancel led worker properly on exit
"[PATCH 3/4 v2] ar9170: fix LED power state handling" revealed a bug which can cause a ugly crash. The delayed worker is canceled before the LED class functions are unregistered... So, if something manages to update the LEDs while unregister routine is running the timer could fire _after_ the module has been unloaded. Signed-off-by: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ar9170/led.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c
index 3c8a5728920d..63fda6cd2101 100644
--- a/drivers/net/wireless/ath/ar9170/led.c
+++ b/drivers/net/wireless/ath/ar9170/led.c
@@ -74,7 +74,7 @@ static void ar9170_update_leds(struct work_struct *work)
74 74
75 mutex_lock(&ar->mutex); 75 mutex_lock(&ar->mutex);
76 for (i = 0; i < AR9170_NUM_LEDS; i++) 76 for (i = 0; i < AR9170_NUM_LEDS; i++)
77 if (ar->leds[i].toggled) { 77 if (ar->leds[i].registered && ar->leds[i].toggled) {
78 led_val |= 1 << i; 78 led_val |= 1 << i;
79 79
80 tmp = 70 + 200 / (ar->leds[i].toggled); 80 tmp = 70 + 200 / (ar->leds[i].toggled);
@@ -101,6 +101,9 @@ static void ar9170_led_brightness_set(struct led_classdev *led,
101 struct ar9170_led *arl = container_of(led, struct ar9170_led, l); 101 struct ar9170_led *arl = container_of(led, struct ar9170_led, l);
102 struct ar9170 *ar = arl->ar; 102 struct ar9170 *ar = arl->ar;
103 103
104 if (unlikely(!arl->registered))
105 return ;
106
104 if (arl->last_state != !!brightness) { 107 if (arl->last_state != !!brightness) {
105 arl->toggled++; 108 arl->toggled++;
106 arl->last_state = !!brightness; 109 arl->last_state = !!brightness;
@@ -139,13 +142,14 @@ void ar9170_unregister_leds(struct ar9170 *ar)
139{ 142{
140 int i; 143 int i;
141 144
142 cancel_delayed_work_sync(&ar->led_work);
143
144 for (i = 0; i < AR9170_NUM_LEDS; i++) 145 for (i = 0; i < AR9170_NUM_LEDS; i++)
145 if (ar->leds[i].registered) { 146 if (ar->leds[i].registered) {
146 led_classdev_unregister(&ar->leds[i].l); 147 led_classdev_unregister(&ar->leds[i].l);
147 ar->leds[i].registered = false; 148 ar->leds[i].registered = false;
149 ar->leds[i].toggled = 0;
148 } 150 }
151
152 cancel_delayed_work_sync(&ar->led_work);
149} 153}
150 154
151int ar9170_register_leds(struct ar9170 *ar) 155int ar9170_register_leds(struct ar9170 *ar)