On 3/17/2015 2:54 AM, Mian Yousaf Kaukab wrote:
> From: Gregory Herrero <[email protected]>
> 
> When suspending usb bus, phy driver may disable controller power.
> In this case, registers need to be saved on suspend and restored
> on resume.
> 
> Signed-off-by: Gregory Herrero <[email protected]>
> ---
>  drivers/usb/dwc2/core.c | 382 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/dwc2/core.h |  84 +++++++++++
>  2 files changed, 466 insertions(+)
> 
> diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
> index d5197d4..bf62d30 100644
> --- a/drivers/usb/dwc2/core.c
> +++ b/drivers/usb/dwc2/core.c
> @@ -56,6 +56,388 @@
>  #include "core.h"
>  #include "hcd.h"
>  
> +#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
> +/**
> + * dwc2_backup_host_registers() - Backup controller host registers.
> + * When suspending usb bus, registers needs to be backuped
> + * if controller power is disabled once suspended.
> + *
> + * @hsotg: Programming view of the DWC_otg controller
> + */
> +static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
> +{
> +     struct dwc2_hregs_backup *hr;
> +     int i;
> +
> +     dev_dbg(hsotg->dev, "%s\n", __func__);
> +
> +     /* Backup Host regs */
> +     hr = hsotg->hr_backup;
> +     if (!hr) {
> +             hr = kmalloc(sizeof(*hr), GFP_KERNEL);
> +             if (!hr) {
> +                     dev_err(hsotg->dev, "%s: can't allocate host regs\n",
> +                                     __func__);
> +                     return -ENOMEM;
> +             }
> +
> +             hsotg->hr_backup = hr;
> +     }
> +     hr->hcfg = readl(hsotg->regs + HCFG);
> +     hr->haintmsk = readl(hsotg->regs + HAINTMSK);
> +     for (i = 0; i < hsotg->core_params->host_channels; ++i)
> +             hr->hcintmsk[i] = readl(hsotg->regs + HCINTMSK(i));
> +
> +     hr->hprt0 = readl(hsotg->regs + HPRT0);
> +     hr->hfir = readl(hsotg->regs + HFIR);
> +     return 0;
> +}
> +
> +/**
> + * dwc2_restore_host_registers() - Restore controller host registers.
> + * When resuming usb bus, device registers needs to be restored
> + * if controller power were disabled.
> + *
> + * @hsotg: Programming view of the DWC_otg controller
> + */
> +static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
> +{
> +     struct dwc2_hregs_backup *hr;
> +     int i;
> +
> +     dev_dbg(hsotg->dev, "%s\n", __func__);
> +
> +     /* Restore host regs */
> +     hr = hsotg->hr_backup;
> +     if (!hr) {
> +             dev_err(hsotg->dev, "%s: no host registers to restore\n",
> +                             __func__);
> +             return -EINVAL;
> +     }
> +
> +     writel(hr->hcfg, hsotg->regs + HCFG);
> +     writel(hr->haintmsk, hsotg->regs + HAINTMSK);
> +
> +     for (i = 0; i < hsotg->core_params->host_channels; ++i)
> +             writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i));
> +
> +     writel(hr->hprt0, hsotg->regs + HPRT0);
> +     writel(hr->hfir, hsotg->regs + HFIR);
> +
> +     kfree(hsotg->hr_backup);

Should NULL this out otherwise you will reuse free'd memory.

Maybe better, you could just free this on remove. Just reuse the
same buffer each time.

Same with device/global registers.


John

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to