From 6193d6997c90535af8f8491fc0019f785a3322b0 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 10 Aug 2011 11:01:57 +0200 Subject: 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 |[] (sysfs_find_dirent+0x4/0x60) from [] (sysfs_get_dirent+0x28/0x78) |[] (sysfs_get_dirent+0x28/0x78) from [] (sysfs_unmerge_group+0x1c/0x90) |[] (sysfs_unmerge_group+0x1c/0x90) from [] (dpm_sysfs_remove+0x14/0x3c) |[] (dpm_sysfs_remove+0x14/0x3c) from [] (device_del+0x40/0x1b4) |[] (device_del+0x40/0x1b4) from [] (device_unregister+0xc/0x18) |[] (device_unregister+0xc/0x18) from [] (musb_free+0x24/0x88 [musb_hdrc]) |[] (musb_free+0x24/0x88 [musb_hdrc]) from [] (musb_probe+0xb50/0xe3c [musb_hdrc]) |[] (musb_probe+0xb50/0xe3c [musb_hdrc]) from [] (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 Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/usb') 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); } /* -- cgit v1.2.3-59-g8ed1b