Re: [PATCH] usb/chipidea: fix oops on memory allocation failure

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux