Commit f042e9cb authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Felipe Balbi

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: default avatarGeorge Cherian <george.cherian@ti.com>
Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 53185b3a
...@@ -868,9 +868,15 @@ static int dsps_suspend(struct device *dev) ...@@ -868,9 +868,15 @@ static int dsps_suspend(struct device *dev)
struct dsps_glue *glue = dev_get_drvdata(dev); struct dsps_glue *glue = dev_get_drvdata(dev);
const struct dsps_musb_wrapper *wrp = glue->wrp; const struct dsps_musb_wrapper *wrp = glue->wrp;
struct musb *musb = platform_get_drvdata(glue->musb); struct musb *musb = platform_get_drvdata(glue->musb);
void __iomem *mbase = musb->ctrl_base; void __iomem *mbase;
del_timer_sync(&glue->timer); del_timer_sync(&glue->timer);
if (!musb)
/* This can happen if the musb device is in -EPROBE_DEFER */
return 0;
mbase = musb->ctrl_base;
glue->context.control = dsps_readl(mbase, wrp->control); glue->context.control = dsps_readl(mbase, wrp->control);
glue->context.epintr = dsps_readl(mbase, wrp->epintr_set); glue->context.epintr = dsps_readl(mbase, wrp->epintr_set);
glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set); glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set);
...@@ -887,8 +893,12 @@ static int dsps_resume(struct device *dev) ...@@ -887,8 +893,12 @@ static int dsps_resume(struct device *dev)
struct dsps_glue *glue = dev_get_drvdata(dev); struct dsps_glue *glue = dev_get_drvdata(dev);
const struct dsps_musb_wrapper *wrp = glue->wrp; const struct dsps_musb_wrapper *wrp = glue->wrp;
struct musb *musb = platform_get_drvdata(glue->musb); struct musb *musb = platform_get_drvdata(glue->musb);
void __iomem *mbase = musb->ctrl_base; void __iomem *mbase;
if (!musb)
return 0;
mbase = musb->ctrl_base;
dsps_writel(mbase, wrp->control, glue->context.control); dsps_writel(mbase, wrp->control, glue->context.control);
dsps_writel(mbase, wrp->epintr_set, glue->context.epintr); dsps_writel(mbase, wrp->epintr_set, glue->context.epintr);
dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr); dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment