aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Zapolskiy <vladimir.zapolskiy@nokia.com>2011-12-23 11:37:18 -0500
committerFelipe Balbi <balbi@ti.com>2012-04-10 12:11:43 -0400
commitafb76df140823c57738598a876cd1d6568cd57c7 (patch)
treef7f80a22b1d2b4ac5bad7b20ed61423a7c6964d3
parentecb07797ffc1c2aaa2e58d1ba1b5deea44ea5b9e (diff)
usb: musb: fix oops on omap2430 module unload
This change prevents runtime suspend and resume actual execution, if omap2430 controller driver is loaded after musb-hdrc, and therefore the controller isn't initialized properly. The problem is reproducible with 3.1.y and 3.2 kernels. Kernel configuration of musb: % cat .config | egrep 'MUSB|GADGET' CONFIG_USB_MUSB_HDRC=y # CONFIG_USB_MUSB_TUSB6010 is not set CONFIG_USB_MUSB_OMAP2PLUS=m # CONFIG_USB_MUSB_AM35X is not set CONFIG_MUSB_PIO_ONLY=y CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set # CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 CONFIG_USB_GADGET_MUSB_HDRC=m CONFIG_USB_GADGET_DUALSPEED=y CONFIG_USB_GADGETFS=m # CONFIG_USB_MIDI_GADGET is not set Fixes the following oops on module unloading: Unable to handle kernel NULL pointer dereference at virtual address 00000220 ----8<---- [<bf162088>] (omap2430_runtime_resume+0x24/0x54 [omap2430]) from [<c0302e34>] (pm_generic_runtime_resume+0x3c/0x50) [<c0302e34>] (pm_generic_runtime_resume+0x3c/0x50) from [<c0031a24>] (_od_runtime_resume+0x28/0x2c) [<c0031a24>] (_od_runtime_resume+0x28/0x2c) from [<c0306cb0>] (__rpm_callback+0x60/0xa0) [<c0306cb0>] (__rpm_callback+0x60/0xa0) from [<c0307f2c>] (rpm_resume+0x3fc/0x6e4) [<c0307f2c>] (rpm_resume+0x3fc/0x6e4) from [<c030851c>] (__pm_runtime_resume+0x5c/0x90) [<c030851c>] (__pm_runtime_resume+0x5c/0x90) from [<c02fd0dc>] (__device_release_driver+0x2c/0xd0) [<c02fd0dc>] (__device_release_driver+0x2c/0xd0) from [<c02fda18>] (driver_detach+0xe8/0xf4) [<c02fda18>] (driver_detach+0xe8/0xf4) from [<c02fcf88>] (bus_remove_driver+0xa0/0x104) [<c02fcf88>] (bus_remove_driver+0xa0/0x104) from [<c02fde54>] (driver_unregister+0x60/0x80) [<c02fde54>] (driver_unregister+0x60/0x80) from [<c02ff2d4>] (platform_driver_unregister+0x1c/0x20) [<c02ff2d4>] (platform_driver_unregister+0x1c/0x20) from [<bf162928>] (omap2430_exit+0x14/0x1c [omap2430]) [<bf162928>] (omap2430_exit+0x14/0x1c [omap2430]) from [<c007d8bc>] (sys_delete_module+0x1f4/0x264) [<c007d8bc>] (sys_delete_module+0x1f4/0x264) from [<c000f000>] (ret_fast_syscall+0x0/0x30) Signed-off-by: Vladimir Zapolskiy <vladimir.zapolskiy@nokia.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: stable@vger.kernel.org # 3.1 Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/musb/omap2430.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 2ae0bb309994..11b571ec22f2 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -491,11 +491,13 @@ static int omap2430_runtime_suspend(struct device *dev)
491 struct omap2430_glue *glue = dev_get_drvdata(dev); 491 struct omap2430_glue *glue = dev_get_drvdata(dev);
492 struct musb *musb = glue_to_musb(glue); 492 struct musb *musb = glue_to_musb(glue);
493 493
494 musb->context.otg_interfsel = musb_readl(musb->mregs, 494 if (musb) {
495 OTG_INTERFSEL); 495 musb->context.otg_interfsel = musb_readl(musb->mregs,
496 OTG_INTERFSEL);
496 497
497 omap2430_low_level_exit(musb); 498 omap2430_low_level_exit(musb);
498 usb_phy_set_suspend(musb->xceiv, 1); 499 usb_phy_set_suspend(musb->xceiv, 1);
500 }
499 501
500 return 0; 502 return 0;
501} 503}
@@ -505,11 +507,13 @@ static int omap2430_runtime_resume(struct device *dev)
505 struct omap2430_glue *glue = dev_get_drvdata(dev); 507 struct omap2430_glue *glue = dev_get_drvdata(dev);
506 struct musb *musb = glue_to_musb(glue); 508 struct musb *musb = glue_to_musb(glue);
507 509
508 omap2430_low_level_init(musb); 510 if (musb) {
509 musb_writel(musb->mregs, OTG_INTERFSEL, 511 omap2430_low_level_init(musb);
510 musb->context.otg_interfsel); 512 musb_writel(musb->mregs, OTG_INTERFSEL,
513 musb->context.otg_interfsel);
511 514
512 usb_phy_set_suspend(musb->xceiv, 0); 515 usb_phy_set_suspend(musb->xceiv, 0);
516 }
513 517
514 return 0; 518 return 0;
515} 519}