diff options
author | Vladimir Zapolskiy <vladimir.zapolskiy@nokia.com> | 2011-12-23 11:37:18 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-04-10 12:11:43 -0400 |
commit | afb76df140823c57738598a876cd1d6568cd57c7 (patch) | |
tree | f7f80a22b1d2b4ac5bad7b20ed61423a7c6964d3 | |
parent | ecb07797ffc1c2aaa2e58d1ba1b5deea44ea5b9e (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.c | 20 |
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 | } |