diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2011-08-10 11:01:57 +0200 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-08-12 12:06:34 +0300 |
commit | 6193d6997c90535af8f8491fc0019f785a3322b0 (patch) | |
tree | 100c8582c33178cc0c76394eb5d667a281529c7c /drivers/usb | |
parent | bb8070c29ca87ac0aa24e04a1207cc932f62258f (diff) | |
download | lwn-6193d6997c90535af8f8491fc0019f785a3322b0.tar.gz lwn-6193d6997c90535af8f8491fc0019f785a3322b0.zip |
usb: musb: gadget: fix error path
In case one "forgot" to load the receiver i.e. doing
|modprobe omap2430
|modprobe musb_hdrc
he ends up with:
|musb-hdrc: version 6.0, ?dma?, otg (peripheral+host)
|HS USB OTG: no transceiver configured
|musb-hdrc musb-hdrc: musb_init_controller failed with status -19
|(NULL device *): gadget not registered.
|Unable to handle kernel NULL pointer dereference at virtual address 0000001c
|Internal error: Oops: 17 [#1] SMP
|[<c011383c>] (sysfs_find_dirent+0x4/0x60) from [<c01138c0>] (sysfs_get_dirent+0x28/0x78)
|[<c01138c0>] (sysfs_get_dirent+0x28/0x78) from [<c0115b78>] (sysfs_unmerge_group+0x1c/0x90)
|[<c0115b78>] (sysfs_unmerge_group+0x1c/0x90) from [<c0179ba4>] (dpm_sysfs_remove+0x14/0x3c)
|[<c0179ba4>] (dpm_sysfs_remove+0x14/0x3c) from [<c01742f8>] (device_del+0x40/0x1b4)
|[<c01742f8>] (device_del+0x40/0x1b4) from [<c0174478>] (device_unregister+0xc/0x18)
|[<c0174478>] (device_unregister+0xc/0x18) from [<bf0489b4>] (musb_free+0x24/0x88 [musb_hdrc])
|[<bf0489b4>] (musb_free+0x24/0x88 [musb_hdrc]) from [<bf057d18>] (musb_probe+0xb50/0xe3c [musb_hdrc])
|[<bf057d18>] (musb_probe+0xb50/0xe3c [musb_hdrc]) from [<c01779c4>] (platform_drv_probe+0x1c/0x24)
The problem is that musb_free() tries to figure out what was
initializued and what wasn't and clean up only the initialized part.
This works well for usb_del_gadget_udc() but device_unregister() can't
deal with it. Therefore we rely on the fact the we always have a parent
device and only then remove the device.
I broke this in 0f91349 ("usb: gadget: convert all users to the new udc
infrastructure")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 8c41a2e6ea77..e81820370d6f 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1856,6 +1856,7 @@ int __init musb_gadget_setup(struct musb *musb) return 0; err: + musb->g.dev.parent = NULL; device_unregister(&musb->g.dev); return status; } @@ -1863,7 +1864,8 @@ err: void musb_gadget_cleanup(struct musb *musb) { usb_del_gadget_udc(&musb->g); - device_unregister(&musb->g.dev); + if (musb->g.dev.parent) + device_unregister(&musb->g.dev); } /* |