Skip to content

Commit

Permalink
ar9170: cancel led worker properly on exit
Browse files Browse the repository at this point in the history
"[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>
  • Loading branch information
Christian Lamparter authored and John W. Linville committed Jun 3, 2009
1 parent 66d0081 commit 6d7db19
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions drivers/net/wireless/ath/ar9170/led.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static void ar9170_update_leds(struct work_struct *work)

mutex_lock(&ar->mutex);
for (i = 0; i < AR9170_NUM_LEDS; i++)
if (ar->leds[i].toggled) {
if (ar->leds[i].registered && ar->leds[i].toggled) {
led_val |= 1 << i;

tmp = 70 + 200 / (ar->leds[i].toggled);
Expand All @@ -101,6 +101,9 @@ static void ar9170_led_brightness_set(struct led_classdev *led,
struct ar9170_led *arl = container_of(led, struct ar9170_led, l);
struct ar9170 *ar = arl->ar;

if (unlikely(!arl->registered))
return ;

if (arl->last_state != !!brightness) {
arl->toggled++;
arl->last_state = !!brightness;
Expand Down Expand Up @@ -139,13 +142,14 @@ void ar9170_unregister_leds(struct ar9170 *ar)
{
int i;

cancel_delayed_work_sync(&ar->led_work);

for (i = 0; i < AR9170_NUM_LEDS; i++)
if (ar->leds[i].registered) {
led_classdev_unregister(&ar->leds[i].l);
ar->leds[i].registered = false;
ar->leds[i].toggled = 0;
}

cancel_delayed_work_sync(&ar->led_work);
}

int ar9170_register_leds(struct ar9170 *ar)
Expand Down

0 comments on commit 6d7db19

Please sign in to comment.