Re: [PATCH v2] usb: host: xhci-plat: fix possible kernel oops while resuming

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

 



On 6/30/23 11:48 PM, Sergey Shtylyov wrote:

> If this driver enables the xHC clocks while resuming from sleep, it calls
> clk_prepare_enable() without checking for errors and blithely goes on to
> read/write the xHC's registers -- which, with the xHC not being clocked,
> at least on ARM32 usually causes an imprecise external abort exceptions
> which cause kernel oops.  Currently, the chips for which the driver does
> the clock dance on suspend/resume seem to be the Broadcom STB SoCs, based
> on ARM32 CPUs, as it seems...
> 
> Found by Linux Verification Center (linuxtesting.org) with the Svace static
> analysis tool.
> 
> Fixes: 8bd954c56197 ("usb: host: xhci-plat: suspend and resume clocks")
> Signed-off-by: Sergey Shtylyov <s.shtylyov@xxxxxx>
> 
> ---
> This patch is against the 'usb-linus' branch of Greg KH's 'usb.git' repo...
> 
> Changes in version 2:
> - fixed up the error path for clk_prepare_enable() calls in xhci_plat_resume().

   Scratch that, still not correct enough...
 
>  drivers/usb/host/xhci-plat.c |   21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
> 
> Index: usb/drivers/usb/host/xhci-plat.c
> ===================================================================
> --- usb.orig/drivers/usb/host/xhci-plat.c
> +++ usb/drivers/usb/host/xhci-plat.c
> @@ -470,23 +470,36 @@ static int __maybe_unused xhci_plat_resu
>  	int ret;
>  
>  	if (!device_may_wakeup(dev) && (xhci->quirks & XHCI_SUSPEND_RESUME_CLKS)) {
> -		clk_prepare_enable(xhci->clk);
> -		clk_prepare_enable(xhci->reg_clk);
> +		ret = clk_prepare_enable(xhci->clk);
> +		if (ret)
> +			return ret;
> +
> +		ret = clk_prepare_enable(xhci->reg_clk);
> +		if (ret)
> +			goto disable_clk;
>  	}
>  
>  	ret = xhci_priv_resume_quirk(hcd);
>  	if (ret)
> -		return ret;
> +		goto disable_reg_clk;
>  
>  	ret = xhci_resume(xhci, 0);
>  	if (ret)
> -		return ret;
> +		goto disable_reg_clk;
>  
>  	pm_runtime_disable(dev);
>  	pm_runtime_set_active(dev);
>  	pm_runtime_enable(dev);
>  
>  	return 0;
> +
> +disable_reg_clk:
> +	clk_disable_unprepare(xhci->reg_clk);
> +
> +disable_clk:
> +	clk_disable_unprepare(xhci->clk);
> +
> +	return ret;
>  }
[...]

   Grr, the error path is still incorrect here -- it should've checked
xhci->quirks/etc. before calling the clock disable/unprepare... :-(

MBR, Sergey



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

  Powered by Linux