diff options
| author | Christian Lamparter <chunkeey@googlemail.com> | 2010-05-25 23:58:47 +0200 | 
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2010-05-26 14:49:48 -0400 | 
| commit | 5001960016bb53a1075bd9d62d7c067cd38c5a68 (patch) | |
| tree | f08324c99732f7e53fc633926d3d1beacdaeae43 /drivers/net/wireless/ath/ar9170/usb.c | |
| parent | b578bb490fb605c23c20b63995f26d3ab2cfb6e0 (diff) | |
ar9170usb: fix read from freed driver context
Commit "ar9170: wait for asynchronous firmware loading"
introduced a bug, which is triggered by fatal errors
while the driver is initializing the device.
BUG: unable to handle kernel paging request at 6b6b6bf7
IP: [<c117b567>] kobject_put+0x7/0x70
*pde = 00000000
Oops: 0000 [#1] PREEMPT
last sysfs file: /sys/devices/platform/hdaps/position
Modules linked in: ar9170usb [...]
Pid: 6246, comm: firmware/ar9170 Not tainted 2.6.34-wl #54
EIP: 0060:[<c117b567>] EFLAGS: 00010206 CPU: 0
EIP is at kobject_put+0x7/0x70
EAX: 6b6b6bd7 EBX: f4d3d0e0 ECX: f5ba9124 EDX: f6af2a7c
ESI: 00000000 EDI: f4d3d0e0 EBP: 00000000 ESP: f5e98f9c
 DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068
Process firmware/ar9170 (pid: 6246)
Stack:
 c12532ed 00000246 f5bfaa70 f8487353 f4d3d0e0
Call Trace:
 [<c12532ed>] ? device_release_driver+0x1d/0x30
 [<f8487353>] ? ar9170_usb_firmware_failed+0x43/0x70 [ar9170usb]
 [<c125983c>] ? request_firmware_work_func+0x2c/0x70
 [<c1259810>] ? request_firmware_work_func+0x0/0x70
 [<c10413f4>] ? kthread+0x74/0x80
 [<c1041380>] ? kthread+0x0/0x80
 [<c1003136>] ? kernel_thread_helper+0x6/0x10
Code: 40 d3 f2 ff 85 c0 89 c3 74 0a ba 44 86 4c c1 e8 [...]
EIP: [<c117b567>] kobject_put+0x7/0x70 SS:ESP 0068:f5e98f9c
CR2: 000000006b6b6bf7
---[ end trace e81abb992434b410 ]---
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ar9170/usb.c')
| -rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 14 | 
1 files changed, 12 insertions, 2 deletions
| diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 82ab532a4923..a93dc18a45c3 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -739,17 +739,27 @@ err_out:  static void ar9170_usb_firmware_failed(struct ar9170_usb *aru)  {  	struct device *parent = aru->udev->dev.parent; +	struct usb_device *udev; + +	/* +	 * Store a copy of the usb_device pointer locally. +	 * This is because device_release_driver initiates +	 * ar9170_usb_disconnect, which in turn frees our +	 * driver context (aru). +	 */ +	udev = aru->udev;  	complete(&aru->firmware_loading_complete);  	/* unbind anything failed */  	if (parent)  		device_lock(parent); -	device_release_driver(&aru->udev->dev); + +	device_release_driver(&udev->dev);  	if (parent)  		device_unlock(parent); -	usb_put_dev(aru->udev); +	usb_put_dev(udev);  }  static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) | 
