diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2014-10-13 05:04:21 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2014-10-23 10:55:43 -0400 |
commit | f042e9cbae607c323e3de86fc714b7306774a151 (patch) | |
tree | 044837b38ff147b6ea10bb739046d6d0ae15542c /drivers/usb/musb/musb_dsps.c | |
parent | 53185b3a441a6cc9bb3f57e924342d249138dcd6 (diff) |
usb: musb: musb_dsps: fix NULL pointer in suspend
So testing managed to configure musb in DMA mode but not load the
matching cppi41 driver for DMA. This results in
|musb-hdrc musb-hdrc.0.auto: Failed to request rx1.
|musb-hdrc musb-hdrc.0.auto: musb_init_controller failed with status -517
|platform musb-hdrc.0.auto: Driver musb-hdrc requests probe deferral
which is "okay". Once the driver is loaded we re-try probing and
everyone is happy. Until then if you try suspend say
echo mem > /sys/power/state
then you go boom
|Unable to handle kernel NULL pointer dereference at virtual address 000003a4
|pgd = cf50c000
|[000003a4] *pgd=8f6a3831, *pte=00000000, *ppte=00000000
|Internal error: Oops: 17 [#1] ARM
|PC is at dsps_suspend+0x18/0x9c [musb_dsps]
|LR is at dsps_suspend+0x18/0x9c [musb_dsps]
|pc : [<bf08e268>] lr : [<bf08e268>] psr: a0000013
|sp : cbd97e00 ip : c0af4394 fp : 00000000
|r10: c0831d90 r9 : 00000002 r8 : cf6da410
|r7 : c03ba4dc r6 : bf08f224 r5 : 00000000 r4 : cbc5fcd0
|r3 : bf08e250 r2 : bf08f264 r1 : cf6da410 r0 : 00000000
|[<bf08e268>] (dsps_suspend [musb_dsps]) from [<c03ba508>] (platform_pm_suspend+0x2c/0x54)
|Code: e1a04000 e9900041 e2800010 eb4caa8e (e59053a4)
because platform_get_drvdata(glue->musb) returns a NULL pointer as long as the
device is not fully probed.
Tested-by: George Cherian <george.cherian@ti.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/musb/musb_dsps.c')
-rw-r--r-- | drivers/usb/musb/musb_dsps.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index b18f8d5e4f98..48bc09e7b83b 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c | |||
@@ -868,9 +868,15 @@ static int dsps_suspend(struct device *dev) | |||
868 | struct dsps_glue *glue = dev_get_drvdata(dev); | 868 | struct dsps_glue *glue = dev_get_drvdata(dev); |
869 | const struct dsps_musb_wrapper *wrp = glue->wrp; | 869 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
870 | struct musb *musb = platform_get_drvdata(glue->musb); | 870 | struct musb *musb = platform_get_drvdata(glue->musb); |
871 | void __iomem *mbase = musb->ctrl_base; | 871 | void __iomem *mbase; |
872 | 872 | ||
873 | del_timer_sync(&glue->timer); | 873 | del_timer_sync(&glue->timer); |
874 | |||
875 | if (!musb) | ||
876 | /* This can happen if the musb device is in -EPROBE_DEFER */ | ||
877 | return 0; | ||
878 | |||
879 | mbase = musb->ctrl_base; | ||
874 | glue->context.control = dsps_readl(mbase, wrp->control); | 880 | glue->context.control = dsps_readl(mbase, wrp->control); |
875 | glue->context.epintr = dsps_readl(mbase, wrp->epintr_set); | 881 | glue->context.epintr = dsps_readl(mbase, wrp->epintr_set); |
876 | glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set); | 882 | glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set); |
@@ -887,8 +893,12 @@ static int dsps_resume(struct device *dev) | |||
887 | struct dsps_glue *glue = dev_get_drvdata(dev); | 893 | struct dsps_glue *glue = dev_get_drvdata(dev); |
888 | const struct dsps_musb_wrapper *wrp = glue->wrp; | 894 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
889 | struct musb *musb = platform_get_drvdata(glue->musb); | 895 | struct musb *musb = platform_get_drvdata(glue->musb); |
890 | void __iomem *mbase = musb->ctrl_base; | 896 | void __iomem *mbase; |
897 | |||
898 | if (!musb) | ||
899 | return 0; | ||
891 | 900 | ||
901 | mbase = musb->ctrl_base; | ||
892 | dsps_writel(mbase, wrp->control, glue->context.control); | 902 | dsps_writel(mbase, wrp->control, glue->context.control); |
893 | dsps_writel(mbase, wrp->epintr_set, glue->context.epintr); | 903 | dsps_writel(mbase, wrp->epintr_set, glue->context.epintr); |
894 | dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr); | 904 | dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr); |