[rt2x00-users] [PATCH] rt2x00: Don't queue ieee80211 work after USB removal
Sean Cross
sean at chumby.com
Sat Oct 31 03:00:47 UTC 2009
On Oct 30, 2009, at Fri 30, 5:51 PM, Ivo van Doorn wrote:
>> #include <linux/kernel.h>
>> #include <linux/module.h>
>>
>> @@ -362,8 +363,9 @@
>>
>> rt2x00link_reset_tuner(rt2x00dev, false);
>>
>> - ieee80211_queue_delayed_work(rt2x00dev->hw,
>> - &link->work, LINK_TUNE_INTERVAL);
>> + if(test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
>> + ieee80211_queue_delayed_work(rt2x00dev->hw,
>> + &link->work, LINK_TUNE_INTERVAL);
>> }
>>
>> void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
>> @@ -469,8 +471,10 @@
>> * Increase tuner counter, and reschedule the next link tuner run.
>> */
>> link->count++;
>> - ieee80211_queue_delayed_work(rt2x00dev->hw,
>> - &link->work, LINK_TUNE_INTERVAL);
>> +
>> + if(test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
>> + ieee80211_queue_delayed_work(rt2x00dev->hw,
>> + &link->work, LINK_TUNE_INTERVAL);
>> }
>
> Actually these 2 changes are incorrec, what happens when the device
> disapears between scheduling
> and starting the thread? Wouldn't that cause the same error you are
> trying to fix? Wouldn't checking
> the flag at the start of the thread be more meaningful?
Perhaps it does make more sense to test for DEVICE_STATE_PRESENT in
rt2x00link_start_tuner, just so rt2x00link_reset_tuner() isn't called
on a card that is no longer present.
But the timing issue I'm seeing is something like this:
1) Card is removed
2) ENODEV messages start getting received.
3) Something decides to start the tuner.
4) link->work gets queued to happen sometime in the future.
5) The USB system finally decides to unload the driver. I think
rt2x00usb_disconnect() gets called here.
6) link->work gets run, but as the device has been unloaded, the
delayed_work is no longer valid, so a KP occurs.
The root cause is that link->work is suddenly no longer valid, so the
flag can't get checked at the start of the thread. Since I think
ENODEV will get returned before rt2x00link_start_tuner() is called, I
believe this is a valid method of catching the removal.
Sean
More information about the users
mailing list