rt2x00: Don't queue ieee80211 work after USB removal

This prevents the rt2x00 driver from queueing ieee80211 work after the  
USB card has been removed, preventing a kernel panic.

Signed-off-by: Sean Cross <sean@chumby.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Sean Cross
2009-11-05 20:22:03 +01:00
committed by John W. Linville
parent 143d40f3ab
commit 66f84d6594
3 changed files with 17 additions and 7 deletions

View File

@@ -815,6 +815,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
mutex_init(&rt2x00dev->csr_mutex); mutex_init(&rt2x00dev->csr_mutex);
set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
/* /*
* Make room for rt2x00_intf inside the per-interface * Make room for rt2x00_intf inside the per-interface
* structure ieee80211_vif. * structure ieee80211_vif.
@@ -871,8 +873,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
rt2x00leds_register(rt2x00dev); rt2x00leds_register(rt2x00dev);
rt2x00debug_register(rt2x00dev); rt2x00debug_register(rt2x00dev);
set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
return 0; return 0;
exit: exit:

View File

@@ -362,6 +362,7 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
rt2x00link_reset_tuner(rt2x00dev, false); rt2x00link_reset_tuner(rt2x00dev, false);
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
ieee80211_queue_delayed_work(rt2x00dev->hw, ieee80211_queue_delayed_work(rt2x00dev->hw,
&link->work, LINK_TUNE_INTERVAL); &link->work, LINK_TUNE_INTERVAL);
} }
@@ -469,6 +470,8 @@ static void rt2x00link_tuner(struct work_struct *work)
* Increase tuner counter, and reschedule the next link tuner run. * Increase tuner counter, and reschedule the next link tuner run.
*/ */
link->count++; link->count++;
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
ieee80211_queue_delayed_work(rt2x00dev->hw, ieee80211_queue_delayed_work(rt2x00dev->hw,
&link->work, LINK_TUNE_INTERVAL); &link->work, LINK_TUNE_INTERVAL);
} }

View File

@@ -47,6 +47,8 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
(requesttype == USB_VENDOR_REQUEST_IN) ? (requesttype == USB_VENDOR_REQUEST_IN) ?
usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0); usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return -ENODEV;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) { for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
status = usb_control_msg(usb_dev, pipe, request, requesttype, status = usb_control_msg(usb_dev, pipe, request, requesttype,
@@ -60,9 +62,11 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
* -ENODEV: Device has disappeared, no point continuing. * -ENODEV: Device has disappeared, no point continuing.
* All other errors: Try again. * All other errors: Try again.
*/ */
else if (status == -ENODEV) else if (status == -ENODEV) {
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
break; break;
} }
}
ERROR(rt2x00dev, ERROR(rt2x00dev,
"Vendor Request 0x%02x failed for offset 0x%04x with error %d.\n", "Vendor Request 0x%02x failed for offset 0x%04x with error %d.\n",
@@ -161,6 +165,9 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
{ {
unsigned int i; unsigned int i;
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return -ENODEV;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) { for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2x00usb_register_read_lock(rt2x00dev, offset, reg); rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
if (!rt2x00_get_field32(*reg, field)) if (!rt2x00_get_field32(*reg, field))