Re: [PATCH v2 2/3] usb: dwc3: qcom: Configure wakeup interrupts and set genpd active wakeup flag

From: Stephen Boyd
Date: Fri Jul 10 2020 - 02:12:38 EST


Quoting Sandeep Maheswaram (2020-07-08 12:10:16)
> configure interrupts based on hs_phy_flag. Set genpd active wakeup flag

Please capitalize the start of a sentence. What is 'hs_phy_flag'?

> for usb gdsc if wakeup capable devices are connected.

This tells us what is happening in the code but doesn't tell us the
important part, i.e. _why_ this patch is important. Why do we need to
set the genpd active wakeup flag? Why configure interrupt based on
hs_phy_flag, whatever that is.

>
> Signed-off-by: Sandeep Maheswaram <sanm@xxxxxxxxxxxxxx>
> ---
> drivers/usb/dwc3/dwc3-qcom.c | 73 ++++++++++++++++++++++++++++++++++----------
> 1 file changed, 57 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
> index 1dfd024..8902670 100644
> --- a/drivers/usb/dwc3/dwc3-qcom.c
> +++ b/drivers/usb/dwc3/dwc3-qcom.c
> @@ -192,21 +194,34 @@ static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom)
>
> static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
> {
> + struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
> +
> if (qcom->hs_phy_irq) {
> disable_irq_wake(qcom->hs_phy_irq);
> disable_irq_nosync(qcom->hs_phy_irq);
> }
> + if (dwc->hs_phy_flags & PHY_MODE_USB_HOST_LS) {
> + if (qcom->dp_hs_phy_irq) {
> + disable_irq_wake(qcom->dp_hs_phy_irq);
> + disable_irq_nosync(qcom->dp_hs_phy_irq);
> + }
> + } else if (dwc->hs_phy_flags & PHY_MODE_USB_HOST_HS) {
> + if (qcom->dm_hs_phy_irq) {
> + disable_irq_wake(qcom->dm_hs_phy_irq);
> + disable_irq_nosync(qcom->dm_hs_phy_irq);
> + }
> + } else {
>
> - if (qcom->dp_hs_phy_irq) {
> - disable_irq_wake(qcom->dp_hs_phy_irq);
> - disable_irq_nosync(qcom->dp_hs_phy_irq);
> - }
> + if (qcom->dp_hs_phy_irq) {
> + disable_irq_wake(qcom->dp_hs_phy_irq);
> + disable_irq_nosync(qcom->dp_hs_phy_irq);
> + }
>
> - if (qcom->dm_hs_phy_irq) {
> - disable_irq_wake(qcom->dm_hs_phy_irq);
> - disable_irq_nosync(qcom->dm_hs_phy_irq);
> + if (qcom->dm_hs_phy_irq) {
> + disable_irq_wake(qcom->dm_hs_phy_irq);
> + disable_irq_nosync(qcom->dm_hs_phy_irq);
> + }
> }
> -

I liked the newline. Please keep it.

> if (qcom->ss_phy_irq) {
> disable_irq_wake(qcom->ss_phy_irq);
> disable_irq_nosync(qcom->ss_phy_irq);
> @@ -215,21 +230,34 @@ static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
>
> static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
> {
> + struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
> +
> if (qcom->hs_phy_irq) {
> enable_irq(qcom->hs_phy_irq);
> enable_irq_wake(qcom->hs_phy_irq);
> }
> + if (dwc->hs_phy_flags & PHY_MODE_USB_HOST_LS) {
> + if (qcom->dp_hs_phy_irq) {
> + enable_irq(qcom->dp_hs_phy_irq);
> + enable_irq_wake(qcom->dp_hs_phy_irq);
> + }
> + } else if (dwc->hs_phy_flags & PHY_MODE_USB_HOST_HS) {
> + if (qcom->dm_hs_phy_irq) {
> + enable_irq(qcom->dm_hs_phy_irq);
> + enable_irq_wake(qcom->dm_hs_phy_irq);
> + }
> + } else {
>
> - if (qcom->dp_hs_phy_irq) {
> - enable_irq(qcom->dp_hs_phy_irq);
> - enable_irq_wake(qcom->dp_hs_phy_irq);
> - }
> + if (qcom->dp_hs_phy_irq) {
> + enable_irq(qcom->dp_hs_phy_irq);
> + enable_irq_wake(qcom->dp_hs_phy_irq);
> + }
>
> - if (qcom->dm_hs_phy_irq) {
> - enable_irq(qcom->dm_hs_phy_irq);
> - enable_irq_wake(qcom->dm_hs_phy_irq);
> + if (qcom->dm_hs_phy_irq) {
> + enable_irq(qcom->dm_hs_phy_irq);
> + enable_irq_wake(qcom->dm_hs_phy_irq);
> + }
> }
> -
> if (qcom->ss_phy_irq) {
> enable_irq(qcom->ss_phy_irq);
> enable_irq_wake(qcom->ss_phy_irq);

Can we use the wakeup irq support code in the kernel here? That would be
preferred to having the driver enable and disable irq wake at various
times when the irq is enabled and disabled (which is also odd by the
way). Why can't we request the irqs and leave them enabled all the time?
Also it seems like the binding should have 'wakeup-source' in it (see
Documentation/devicetree/bindings/power/wakeup-source.txt for more
info).

> @@ -240,6 +268,14 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
> {
> u32 val;
> int i;
> + struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
> + struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci);
> + struct generic_pm_domain *genpd;
> +
> + genpd = pd_to_genpd(qcom->dev->pm_domain);
> +
> + if (genpd && usb_wakeup_enabled_descendants(hcd->self.root_hub))

Feels like a comment would be good to explain why wakeup enabled
descendants matters here.

> + genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
>
> if (qcom->is_suspended)
> return 0;
> @@ -261,6 +297,11 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
> {
> int ret;
> int i;
> + struct generic_pm_domain *genpd;
> +
> + genpd = pd_to_genpd(qcom->dev->pm_domain);

This does container_of() so it can't return NULL.

> + if (genpd)

So this check is wrong?

> + genpd->flags &= !GENPD_FLAG_ACTIVE_WAKEUP;