Message ID | 1594235417-23066-2-git-send-email-sanm@codeaurora.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | usb: dwc3: Host wake up support from system suspend | expand |
Hi Sandeep, Thank you for the patch! Yet something to improve: [auto build test ERROR on balbi-usb/testing/next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Sandeep-Maheswaram/usb-dwc3-Host-wake-up-support-from-system-suspend/20200709-031939 base: https://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git testing/next config: i386-randconfig-a012-20200713 (attached as .config) compiler: gcc-9 (Debian 9.3.0-14) 9.3.0 reproduce (this is a W=1 build): # save the attached .config to linux build tree make W=1 ARCH=i386 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): ld: drivers/usb/dwc3/core.o: in function `dwc3_suspend_common': >> core.c:(.text+0x3f0f): undefined reference to `usb_hcd_is_primary_hcd' >> ld: core.c:(.text+0x40c7): undefined reference to `usb_wakeup_enabled_descendants' --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
On Mon, Jul 13, 2020 at 11:34:11PM +0800, kernel test robot wrote: > Hi Sandeep, > > Thank you for the patch! Yet something to improve: > > [auto build test ERROR on balbi-usb/testing/next] > [If your patch is applied to the wrong git tree, kindly drop us a note. > And when submitting patch, we suggest to use as documented in > https://git-scm.com/docs/git-format-patch] > > url: https://github.com/0day-ci/linux/commits/Sandeep-Maheswaram/usb-dwc3-Host-wake-up-support-from-system-suspend/20200709-031939 > base: https://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git testing/next > config: i386-randconfig-a012-20200713 (attached as .config) > compiler: gcc-9 (Debian 9.3.0-14) 9.3.0 > reproduce (this is a W=1 build): > # save the attached .config to linux build tree > make W=1 ARCH=i386 > > If you fix the issue, kindly add following tag as appropriate > Reported-by: kernel test robot <lkp@intel.com> > > All errors (new ones prefixed by >>): > > ld: drivers/usb/dwc3/core.o: in function `dwc3_suspend_common': > >> core.c:(.text+0x3f0f): undefined reference to `usb_hcd_is_primary_hcd' > >> ld: core.c:(.text+0x40c7): undefined reference to `usb_wakeup_enabled_descendants' The problem here seems to be that: CONFIG_USB_DWC3=y and CONFIG_USB=m Add a Kconfig condition that disallows usb_dwc3 to be builtin when the USB core is built as a module?
Hi Sandeep, On Thu, Jul 09, 2020 at 12:40:15AM +0530, Sandeep Maheswaram wrote: > Avoiding phy powerdown in host mode so that it can be wake up by devices. > Added need_phy_for_wakeup flag to distinugush resume path and hs_phy_flags > to check connection status and set phy mode and configure interrupts. > > Signed-off-by: Sandeep Maheswaram <sanm@codeaurora.org> > --- > drivers/usb/dwc3/core.c | 47 ++++++++++++++++++++++++++++++++++++++++------- > drivers/usb/dwc3/core.h | 2 ++ > 2 files changed, 42 insertions(+), 7 deletions(-) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 25c686a7..eb7c225 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -31,12 +31,14 @@ > #include <linux/usb/gadget.h> > #include <linux/usb/of.h> > #include <linux/usb/otg.h> > +#include <linux/usb/hcd.h> > > #include "core.h" > #include "gadget.h" > #include "io.h" > > #include "debug.h" > +#include "../host/xhci.h" > > #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */ > > @@ -1627,10 +1629,36 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc) > return ret; > } > > +static void dwc3_set_phy_speed_flags(struct dwc3 *dwc) > +{ > + > + int i, num_ports; > + u32 reg; > + struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci); > + struct xhci_hcd *xhci_hcd = hcd_to_xhci(hcd); > + > + dwc->hs_phy_flags &= ~(PHY_MODE_USB_HOST_HS | PHY_MODE_USB_HOST_LS); Where is hs_phy_flags initialized? As far as I can tell it isn't, hence when dwc3_set_phy_speed_flags() is executed the first time it is 0 (from devm_kzalloc()), and after the '&=' it is still 0. The next time it will have whatever value it was set to in the below loop, which is then cleared by the '&='. It seems you could as well just write 'dwc->hs_phy_flags = 0', which is clearer, unless the field is used in some other way that isn't obvious to me. > + > + reg = readl(&xhci_hcd->cap_regs->hcs_params1); > + > + num_ports = HCS_MAX_PORTS(reg); > + for (i = 0; i < num_ports; i++) { > + reg = readl(&xhci_hcd->op_regs->port_status_base + i * 0x04); > + if (reg & PORT_PE) { > + if (DEV_HIGHSPEED(reg) || DEV_FULLSPEED(reg)) > + dwc->hs_phy_flags |= PHY_MODE_USB_HOST_HS; > + else if (DEV_LOWSPEED(reg)) > + dwc->hs_phy_flags |= PHY_MODE_USB_HOST_LS; Is another entry for DEV_SUPERSPEED needed? > + } > + } > + phy_set_mode(dwc->usb2_generic_phy, dwc->hs_phy_flags); > +} > + > static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) > { > unsigned long flags; > u32 reg; > + struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci); > > switch (dwc->current_dr_role) { > case DWC3_GCTL_PRTCAP_DEVICE: > @@ -1643,9 +1671,12 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) > dwc3_core_exit(dwc); > break; > case DWC3_GCTL_PRTCAP_HOST: > + dwc3_set_phy_speed_flags(dwc); > if (!PMSG_IS_AUTO(msg)) { > - dwc3_core_exit(dwc); > - break; > + if (usb_wakeup_enabled_descendants(hcd->self.root_hub)) > + dwc->need_phy_for_wakeup = true; > + else > + dwc->need_phy_for_wakeup = false; > } > > /* Let controller to suspend HSPHY before PHY driver suspends */ > @@ -1705,11 +1736,13 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) > break; > case DWC3_GCTL_PRTCAP_HOST: > if (!PMSG_IS_AUTO(msg)) { > - ret = dwc3_core_init_for_resume(dwc); > - if (ret) > - return ret; > - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); > - break; > + if (!dwc->need_phy_for_wakeup) { > + ret = dwc3_core_init_for_resume(dwc); Before this patch we had the combo dwc3_core_exit() / dwc3_core_init_for_resume(), now it is only dwc3_core_init_for_resume() for !dwc->need_phy_for_wakeup. Doesn't this cause trouble with enable counts, e.g. with clk_bulk_prepare_enable() being called in dwc3_core_init_for_resume(), without the corresponding clk_bulk_disable_unprepare() calls in dwc3_core_exit()?
On Thu, Jul 09, 2020 at 12:40:15AM +0530, Sandeep Maheswaram wrote: > Avoiding phy powerdown in host mode so that it can be wake up by devices. > Added need_phy_for_wakeup flag to distinugush resume path and hs_phy_flags > to check connection status and set phy mode and configure interrupts. > > Signed-off-by: Sandeep Maheswaram <sanm@codeaurora.org> > --- > drivers/usb/dwc3/core.c | 47 ++++++++++++++++++++++++++++++++++++++++------- > drivers/usb/dwc3/core.h | 2 ++ > 2 files changed, 42 insertions(+), 7 deletions(-) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 25c686a7..eb7c225 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -31,12 +31,14 @@ > #include <linux/usb/gadget.h> > #include <linux/usb/of.h> > #include <linux/usb/otg.h> > +#include <linux/usb/hcd.h> > > #include "core.h" > #include "gadget.h" > #include "io.h" > > #include "debug.h" > +#include "../host/xhci.h" > > #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */ > > @@ -1627,10 +1629,36 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc) > return ret; > } > > +static void dwc3_set_phy_speed_flags(struct dwc3 *dwc) > +{ > + > + int i, num_ports; > + u32 reg; > + struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci); > + struct xhci_hcd *xhci_hcd = hcd_to_xhci(hcd); > + > + dwc->hs_phy_flags &= ~(PHY_MODE_USB_HOST_HS | PHY_MODE_USB_HOST_LS); > + > + reg = readl(&xhci_hcd->cap_regs->hcs_params1); > + > + num_ports = HCS_MAX_PORTS(reg); > + for (i = 0; i < num_ports; i++) { > + reg = readl(&xhci_hcd->op_regs->port_status_base + i * 0x04); > + if (reg & PORT_PE) { > + if (DEV_HIGHSPEED(reg) || DEV_FULLSPEED(reg)) > + dwc->hs_phy_flags |= PHY_MODE_USB_HOST_HS; > + else if (DEV_LOWSPEED(reg)) > + dwc->hs_phy_flags |= PHY_MODE_USB_HOST_LS; > + } > + } > + phy_set_mode(dwc->usb2_generic_phy, dwc->hs_phy_flags); > +} > + > static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) > { > unsigned long flags; > u32 reg; > + struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci); > > switch (dwc->current_dr_role) { > case DWC3_GCTL_PRTCAP_DEVICE: > @@ -1643,9 +1671,12 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) > dwc3_core_exit(dwc); > break; > case DWC3_GCTL_PRTCAP_HOST: > + dwc3_set_phy_speed_flags(dwc); > if (!PMSG_IS_AUTO(msg)) { > - dwc3_core_exit(dwc); > - break; > + if (usb_wakeup_enabled_descendants(hcd->self.root_hub)) > + dwc->need_phy_for_wakeup = true; > + else > + dwc->need_phy_for_wakeup = false; > } > > /* Let controller to suspend HSPHY before PHY driver suspends */ > @@ -1705,11 +1736,13 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) > break; > case DWC3_GCTL_PRTCAP_HOST: > if (!PMSG_IS_AUTO(msg)) { > - ret = dwc3_core_init_for_resume(dwc); > - if (ret) > - return ret; > - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); > - break; > + if (!dwc->need_phy_for_wakeup) { > + ret = dwc3_core_init_for_resume(dwc); > + if (ret) > + return ret; > + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); > + break; > + } > } > /* Restore GUSB2PHYCFG bits that were modified in suspend */ > reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index 013f42a..5367d510e 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -1094,6 +1094,8 @@ struct dwc3 { > struct phy *usb3_generic_phy; > > bool phys_ready; > + bool need_phy_for_wakeup; > + unsigned int hs_phy_flags; > > struct ulpi *ulpi; > bool ulpi_ready; Should this include a check for the 'wakeup-source' DT attribute as in xhci-mtk.c, to make wakeup support optional?
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 25c686a7..eb7c225 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -31,12 +31,14 @@ #include <linux/usb/gadget.h> #include <linux/usb/of.h> #include <linux/usb/otg.h> +#include <linux/usb/hcd.h> #include "core.h" #include "gadget.h" #include "io.h" #include "debug.h" +#include "../host/xhci.h" #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */ @@ -1627,10 +1629,36 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc) return ret; } +static void dwc3_set_phy_speed_flags(struct dwc3 *dwc) +{ + + int i, num_ports; + u32 reg; + struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci); + struct xhci_hcd *xhci_hcd = hcd_to_xhci(hcd); + + dwc->hs_phy_flags &= ~(PHY_MODE_USB_HOST_HS | PHY_MODE_USB_HOST_LS); + + reg = readl(&xhci_hcd->cap_regs->hcs_params1); + + num_ports = HCS_MAX_PORTS(reg); + for (i = 0; i < num_ports; i++) { + reg = readl(&xhci_hcd->op_regs->port_status_base + i * 0x04); + if (reg & PORT_PE) { + if (DEV_HIGHSPEED(reg) || DEV_FULLSPEED(reg)) + dwc->hs_phy_flags |= PHY_MODE_USB_HOST_HS; + else if (DEV_LOWSPEED(reg)) + dwc->hs_phy_flags |= PHY_MODE_USB_HOST_LS; + } + } + phy_set_mode(dwc->usb2_generic_phy, dwc->hs_phy_flags); +} + static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) { unsigned long flags; u32 reg; + struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci); switch (dwc->current_dr_role) { case DWC3_GCTL_PRTCAP_DEVICE: @@ -1643,9 +1671,12 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) dwc3_core_exit(dwc); break; case DWC3_GCTL_PRTCAP_HOST: + dwc3_set_phy_speed_flags(dwc); if (!PMSG_IS_AUTO(msg)) { - dwc3_core_exit(dwc); - break; + if (usb_wakeup_enabled_descendants(hcd->self.root_hub)) + dwc->need_phy_for_wakeup = true; + else + dwc->need_phy_for_wakeup = false; } /* Let controller to suspend HSPHY before PHY driver suspends */ @@ -1705,11 +1736,13 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) break; case DWC3_GCTL_PRTCAP_HOST: if (!PMSG_IS_AUTO(msg)) { - ret = dwc3_core_init_for_resume(dwc); - if (ret) - return ret; - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); - break; + if (!dwc->need_phy_for_wakeup) { + ret = dwc3_core_init_for_resume(dwc); + if (ret) + return ret; + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); + break; + } } /* Restore GUSB2PHYCFG bits that were modified in suspend */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 013f42a..5367d510e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1094,6 +1094,8 @@ struct dwc3 { struct phy *usb3_generic_phy; bool phys_ready; + bool need_phy_for_wakeup; + unsigned int hs_phy_flags; struct ulpi *ulpi; bool ulpi_ready;
Avoiding phy powerdown in host mode so that it can be wake up by devices. Added need_phy_for_wakeup flag to distinugush resume path and hs_phy_flags to check connection status and set phy mode and configure interrupts. Signed-off-by: Sandeep Maheswaram <sanm@codeaurora.org> --- drivers/usb/dwc3/core.c | 47 ++++++++++++++++++++++++++++++++++++++++------- drivers/usb/dwc3/core.h | 2 ++ 2 files changed, 42 insertions(+), 7 deletions(-)