On Wed, Oct 16, 2013 at 01:45:15PM +0100, Russell King - ARM Linux wrote: > When CMA fails to initialize in v3.12-rc4, the chipidea driver oopses > the kernel while trying to remove and put the HCD which doesn't exist: > > WARNING: CPU: 0 PID: 6 at /home/rmk/git/linux-rmk/arch/arm/mm/dma-mapping.c:511 > __dma_alloc+0x200/0x240() > coherent pool not initialised! > Modules linked in: > CPU: 0 PID: 6 Comm: kworker/u2:0 Tainted: G W 3.12.0-rc4+ #56 > Workqueue: deferwq deferred_probe_work_func > Backtrace: > [<c001218c>] (dump_backtrace+0x0/0x10c) from [<c0012328>] (show_stack+0x18/0x1c) > r6:c05fd9cc r5:000001ff r4:00000000 r3:df86ad00 > [<c0012310>] (show_stack+0x0/0x1c) from [<c05f3a4c>] (dump_stack+0x70/0x8c) > [<c05f39dc>] (dump_stack+0x0/0x8c) from [<c00230a8>] (warn_slowpath_common+0x6c/0x8c) > r4:df883a60 r3:df86ad00 > [<c002303c>] (warn_slowpath_common+0x0/0x8c) from [<c002316c>] (warn_slowpath_fmt+0x38/0x40) > r8:ffffffff r7:00001000 r6:c083b808 r5:00000000 r4:df2efe80 > [<c0023134>] (warn_slowpath_fmt+0x0/0x40) from [<c00196bc>] (__dma_alloc+0x200/0x240) > r3:00000000 r2:c05fda00 > [<c00194bc>] (__dma_alloc+0x0/0x240) from [<c001982c>] (arm_dma_alloc+0x88/0xa0) > [<c00197a4>] (arm_dma_alloc+0x0/0xa0) from [<c03e2904>] (ehci_setup+0x1f4/0x438) > [<c03e2710>] (ehci_setup+0x0/0x438) from [<c03cbd60>] (usb_add_hcd+0x18c/0x664) > [<c03cbbd4>] (usb_add_hcd+0x0/0x664) from [<c03e89f4>] (host_start+0xf0/0x180) > [<c03e8904>] (host_start+0x0/0x180) from [<c03e7c34>] (ci_hdrc_probe+0x360/0x670 > ) > r6:df2ef410 r5:00000000 r4:df2c3010 r3:c03e8904 > [<c03e78d4>] (ci_hdrc_probe+0x0/0x670) from [<c0311044>] (platform_drv_probe+0x20/0x24) > [<c0311024>] (platform_drv_probe+0x0/0x24) from [<c030fcac>] (driver_probe_device+0x9c/0x234) > ... > ---[ end trace c88ccaf3969e8422 ]--- > Unable to handle kernel NULL pointer dereference at virtual address 00000028 > pgd = c0004000 > [00000028] *pgd=00000000 > Internal error: Oops: 17 [#1] SMP ARM > Modules linked in: > CPU: 0 PID: 6 Comm: kworker/u2:0 Tainted: G W 3.12.0-rc4+ #56 > Workqueue: deferwq deferred_probe_work_func > task: df86ad00 ti: df882000 task.ti: df882000 > PC is at usb_remove_hcd+0x10/0x150 > LR is at host_stop+0x1c/0x3c > pc : [<c03cacec>] lr : [<c03e88e4>] psr: 60000013 > sp : df883b50 ip : df883b78 fp : df883b74 > r10: c11f4c54 r9 : c0836450 r8 : df30c400 > r7 : fffffff4 r6 : df2ef410 r5 : 00000000 r4 : df2c3010 > r3 : 00000000 r2 : 00000000 r1 : df86b0a0 r0 : 00000000 > Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel > Control: 10c53c7d Table: 2f29404a DAC: 00000015 > Process kworker/u2:0 (pid: 6, stack limit = 0xdf882240) > Stack: (0xdf883b50 to 0xdf884000) > ... > Backtrace: > [<c03cacdc>] (usb_remove_hcd+0x0/0x150) from [<c03e88e4>] (host_stop+0x1c/0x3c) > r6:df2ef410 r5:00000000 r4:df2c3010 > [<c03e88c8>] (host_stop+0x0/0x3c) from [<c03e8aa0>] (ci_hdrc_host_destroy+0x1c/0x20) > r5:00000000 r4:df2c3010 > [<c03e8a84>] (ci_hdrc_host_destroy+0x0/0x20) from [<c03e7c80>] (ci_hdrc_probe+0x3ac/0x670) > [<c03e78d4>] (ci_hdrc_probe+0x0/0x670) from [<c0311044>] (platform_drv_probe+0x20/0x24) > [<c0311024>] (platform_drv_probe+0x0/0x24) from [<c030fcac>] (driver_probe_device+0x9c/0x234) > [<c030fc10>] (driver_probe_device+0x0/0x234) from [<c030ff28>] (__device_attach+0x44/0x48) > ... > ---[ end trace c88ccaf3969e8423 ]--- > > Fix this so at least we can continue booting and get to a shell prompt. > > Signed-off-by: Russell King <rmk+kernel@xxxxxxxxxxxxxxxx> > Tested-by: Russell King <rmk+kernel@xxxxxxxxxxxxxxxx> > --- > drivers/usb/chipidea/host.c | 6 ++++-- > 1 files changed, 4 insertions(+), 2 deletions(-) > > diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c > index 6f96795..64d7a6d 100644 > --- a/drivers/usb/chipidea/host.c > +++ b/drivers/usb/chipidea/host.c > @@ -100,8 +100,10 @@ static void host_stop(struct ci_hdrc *ci) > { > struct usb_hcd *hcd = ci->hcd; > > - usb_remove_hcd(hcd); > - usb_put_hcd(hcd); > + if (hcd) { > + usb_remove_hcd(hcd); > + usb_put_hcd(hcd); > + } > if (ci->platdata->reg_vbus) > regulator_disable(ci->platdata->reg_vbus); > } Thanks for pointing it, the regulator_disable may still be called but the regulator_enable is not called due to hcd's allocation is failed at this case. For this error, the driver should not call .stop if .start has failed. Below is my proposal fix for this problem: diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 42a0bd4..c1d05c4 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -270,16 +270,18 @@ static void host_stop(struct ci_hdrc *ci) { struct usb_hcd *hcd = ci->hcd; - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - if (ci->platdata->reg_vbus) - regulator_disable(ci->platdata->reg_vbus); + if (hcd) { + usb_remove_hcd(hcd); + usb_put_hcd(hcd); + if (ci->platdata->reg_vbus) + regulator_disable(ci->platdata->reg_vbus); + } } void ci_hdrc_host_destroy(struct ci_hdrc *ci) { - if (ci->role == CI_ROLE_HOST) + if (ci->role == CI_ROLE_HOST && ci->hcd) host_stop(ci); } -- Best Regards, Peter Chen -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html