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>
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
- musb->context.otg_interfsel = musb_readl(musb->mregs,
- OTG_INTERFSEL);
+ if (musb) {
+ musb->context.otg_interfsel = musb_readl(musb->mregs,
+ OTG_INTERFSEL);
- omap2430_low_level_exit(musb);
- usb_phy_set_suspend(musb->xceiv, 1);
+ omap2430_low_level_exit(musb);
+ usb_phy_set_suspend(musb->xceiv, 1);
+ }
return 0;
}
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
- omap2430_low_level_init(musb);
- musb_writel(musb->mregs, OTG_INTERFSEL,
- musb->context.otg_interfsel);
+ if (musb) {
+ omap2430_low_level_init(musb);
+ musb_writel(musb->mregs, OTG_INTERFSEL,
+ musb->context.otg_interfsel);
- usb_phy_set_suspend(musb->xceiv, 0);
+ usb_phy_set_suspend(musb->xceiv, 0);
+ }
return 0;
}