Patchwork [v3] powerpc/usb: fix bug of CPU hang when missing USB PHY clock

login
register
mail settings
Submitter Shengzhou Liu
Date Sept. 18, 2012, 8:52 a.m.
Message ID <1347958359-20153-1-git-send-email-Shengzhou.Liu@freescale.com>
Download mbox | patch
Permalink /patch/184666/
State Superseded
Headers show

Comments

Shengzhou Liu - Sept. 18, 2012, 8:52 a.m.
when missing USB PHY clock, kernel booting up will hang during USB
initialization. We should check USBGP[PHY_CLK_VALID] bit to avoid
CPU hanging in this case.

Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
---
v3 change: no check for UTMI PHY.
v2 change: use spin_event_timeout() instead.

 drivers/usb/host/ehci-fsl.c |   57 +++++++++++++++++++++++++++++-------------
 drivers/usb/host/ehci-fsl.h |    1 +
 include/linux/fsl_devices.h |    1 +
 3 files changed, 41 insertions(+), 18 deletions(-)
Greg KH - Sept. 21, 2012, 4:43 p.m.
On Tue, Sep 18, 2012 at 04:52:39PM +0800, Shengzhou Liu wrote:
> when missing USB PHY clock, kernel booting up will hang during USB
> initialization. We should check USBGP[PHY_CLK_VALID] bit to avoid
> CPU hanging in this case.
> 
> Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
> ---
> v3 change: no check for UTMI PHY.
> v2 change: use spin_event_timeout() instead.
> 
>  drivers/usb/host/ehci-fsl.c |   57 +++++++++++++++++++++++++++++-------------
>  drivers/usb/host/ehci-fsl.h |    1 +
>  include/linux/fsl_devices.h |    1 +
>  3 files changed, 41 insertions(+), 18 deletions(-)

This is already applied, right?

greg k-h
Kumar Gala - Sept. 22, 2012, 2:39 p.m.
On Sep 21, 2012, at 11:43 AM, Greg KH wrote:

> On Tue, Sep 18, 2012 at 04:52:39PM +0800, Shengzhou Liu wrote:
>> when missing USB PHY clock, kernel booting up will hang during USB
>> initialization. We should check USBGP[PHY_CLK_VALID] bit to avoid
>> CPU hanging in this case.
>> 
>> Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
>> ---
>> v3 change: no check for UTMI PHY.
>> v2 change: use spin_event_timeout() instead.
>> 
>> drivers/usb/host/ehci-fsl.c |   57 +++++++++++++++++++++++++++++-------------
>> drivers/usb/host/ehci-fsl.h |    1 +
>> include/linux/fsl_devices.h |    1 +
>> 3 files changed, 41 insertions(+), 18 deletions(-)
> 
> This is already applied, right?
> 
> greg k-h

It appears that v2 of the patch is applied to your usb-next branch.

in drivers/usb/host/ehci-fsl.c

V2:
@@ -262,23 +266,34 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
        case FSL_USB2_PHY_NONE:
                break;
        }
+
+       if ((pdata->controller_ver) && ((phy_mode == FSL_USB2_PHY_ULPI) ||
+                       (phy_mode == FSL_USB2_PHY_UTMI))) {

V3:

@@ -262,23 +266,33 @@  static void ehci_fsl_setup_phy(struct usb_hcd *hcd,

 	case FSL_USB2_PHY_NONE:
 		break;
 	}

+
+	if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) {
+		/* check PHY_CLK_VALID to get phy clk valid */


- k
Greg KH - Sept. 22, 2012, 2:48 p.m.
On Sat, Sep 22, 2012 at 09:39:15AM -0500, Kumar Gala wrote:
> 
> On Sep 21, 2012, at 11:43 AM, Greg KH wrote:
> 
> > On Tue, Sep 18, 2012 at 04:52:39PM +0800, Shengzhou Liu wrote:
> >> when missing USB PHY clock, kernel booting up will hang during USB
> >> initialization. We should check USBGP[PHY_CLK_VALID] bit to avoid
> >> CPU hanging in this case.
> >> 
> >> Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
> >> ---
> >> v3 change: no check for UTMI PHY.
> >> v2 change: use spin_event_timeout() instead.
> >> 
> >> drivers/usb/host/ehci-fsl.c |   57 +++++++++++++++++++++++++++++-------------
> >> drivers/usb/host/ehci-fsl.h |    1 +
> >> include/linux/fsl_devices.h |    1 +
> >> 3 files changed, 41 insertions(+), 18 deletions(-)
> > 
> > This is already applied, right?
> > 
> > greg k-h
> 
> It appears that v2 of the patch is applied to your usb-next branch.
> 
> in drivers/usb/host/ehci-fsl.c
> 
> V2:
> @@ -262,23 +266,34 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
>         case FSL_USB2_PHY_NONE:
>                 break;
>         }
> +
> +       if ((pdata->controller_ver) && ((phy_mode == FSL_USB2_PHY_ULPI) ||
> +                       (phy_mode == FSL_USB2_PHY_UTMI))) {
> 
> V3:
> 
> @@ -262,23 +266,33 @@  static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
> 
>  	case FSL_USB2_PHY_NONE:
>  		break;
>  	}
> 
> +
> +	if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) {
> +		/* check PHY_CLK_VALID to get phy clk valid */

Ok, can someone please make the incremental patch that I need to apply
here and send it to me?

thanks,

greg k-h
Liu Shengzhou-B36685 - Sept. 24, 2012, 2:44 p.m.
> -----Original Message-----

> From: Greg KH [mailto:greg@kroah.com]

> Sent: 2012年9月22日 22:49

> To: Kumar Gala

> Cc: Liu Shengzhou-B36685; linuxppc-dev@lists.ozlabs.org; linux-

> usb@vger.kernel.org

> Subject: Re: [PATCH v3] powerpc/usb: fix bug of CPU hang when missing

> USB PHY clock

> 

> On Sat, Sep 22, 2012 at 09:39:15AM -0500, Kumar Gala wrote:

> >

> > On Sep 21, 2012, at 11:43 AM, Greg KH wrote:

> >

> > > On Tue, Sep 18, 2012 at 04:52:39PM +0800, Shengzhou Liu wrote:

> > >> when missing USB PHY clock, kernel booting up will hang during USB

> > >> initialization. We should check USBGP[PHY_CLK_VALID] bit to avoid

> > >> CPU hanging in this case.

> > >>

> > >> Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>

> > >> ---

> > >> v3 change: no check for UTMI PHY.

> > >> v2 change: use spin_event_timeout() instead.

> > >>

> > >> drivers/usb/host/ehci-fsl.c |   57 +++++++++++++++++++++++++++++--

> -----------

> > >> drivers/usb/host/ehci-fsl.h |    1 +

> > >> include/linux/fsl_devices.h |    1 +

> > >> 3 files changed, 41 insertions(+), 18 deletions(-)

> > >

> > > This is already applied, right?

> > >

> > > greg k-h

> >

> > It appears that v2 of the patch is applied to your usb-next branch.

> >

> > in drivers/usb/host/ehci-fsl.c

> >

> > V2:

> > @@ -262,23 +266,34 @@ static void ehci_fsl_setup_phy(struct usb_hcd

> *hcd,

> >         case FSL_USB2_PHY_NONE:

> >                 break;

> >         }

> > +

> > +       if ((pdata->controller_ver) && ((phy_mode ==

> FSL_USB2_PHY_ULPI) ||

> > +                       (phy_mode == FSL_USB2_PHY_UTMI))) {

> >

> > V3:

> >

> > @@ -262,23 +266,33 @@  static void ehci_fsl_setup_phy(struct usb_hcd

> *hcd,

> >

> >  	case FSL_USB2_PHY_NONE:

> >  		break;

> >  	}

> >

> > +

> > +	if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) {

> > +		/* check PHY_CLK_VALID to get phy clk valid */

> 

> Ok, can someone please make the incremental patch that I need to apply

> here and send it to me?

> 

> thanks,

> 

> greg k-h


Hi greg,

I have sent the below incremental patch to you, please squash it into the previous patch v2, which had been applied in your usb-next branch. 
http://patchwork.ozlabs.org/patch/186443/

Thanks,
Shengzhou
Greg KH - Sept. 24, 2012, 5:27 p.m.
On Mon, Sep 24, 2012 at 02:44:19PM +0000, Liu Shengzhou-B36685 wrote:
> 
> > -----Original Message-----
> > From: Greg KH [mailto:greg@kroah.com]
> > Sent: 2012年9月22日 22:49
> > To: Kumar Gala
> > Cc: Liu Shengzhou-B36685; linuxppc-dev@lists.ozlabs.org; linux-
> > usb@vger.kernel.org
> > Subject: Re: [PATCH v3] powerpc/usb: fix bug of CPU hang when missing
> > USB PHY clock
> > 
> > On Sat, Sep 22, 2012 at 09:39:15AM -0500, Kumar Gala wrote:
> > >
> > > On Sep 21, 2012, at 11:43 AM, Greg KH wrote:
> > >
> > > > On Tue, Sep 18, 2012 at 04:52:39PM +0800, Shengzhou Liu wrote:
> > > >> when missing USB PHY clock, kernel booting up will hang during USB
> > > >> initialization. We should check USBGP[PHY_CLK_VALID] bit to avoid
> > > >> CPU hanging in this case.
> > > >>
> > > >> Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
> > > >> ---
> > > >> v3 change: no check for UTMI PHY.
> > > >> v2 change: use spin_event_timeout() instead.
> > > >>
> > > >> drivers/usb/host/ehci-fsl.c |   57 +++++++++++++++++++++++++++++--
> > -----------
> > > >> drivers/usb/host/ehci-fsl.h |    1 +
> > > >> include/linux/fsl_devices.h |    1 +
> > > >> 3 files changed, 41 insertions(+), 18 deletions(-)
> > > >
> > > > This is already applied, right?
> > > >
> > > > greg k-h
> > >
> > > It appears that v2 of the patch is applied to your usb-next branch.
> > >
> > > in drivers/usb/host/ehci-fsl.c
> > >
> > > V2:
> > > @@ -262,23 +266,34 @@ static void ehci_fsl_setup_phy(struct usb_hcd
> > *hcd,
> > >         case FSL_USB2_PHY_NONE:
> > >                 break;
> > >         }
> > > +
> > > +       if ((pdata->controller_ver) && ((phy_mode ==
> > FSL_USB2_PHY_ULPI) ||
> > > +                       (phy_mode == FSL_USB2_PHY_UTMI))) {
> > >
> > > V3:
> > >
> > > @@ -262,23 +266,33 @@  static void ehci_fsl_setup_phy(struct usb_hcd
> > *hcd,
> > >
> > >  	case FSL_USB2_PHY_NONE:
> > >  		break;
> > >  	}
> > >
> > > +
> > > +	if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) {
> > > +		/* check PHY_CLK_VALID to get phy clk valid */
> > 
> > Ok, can someone please make the incremental patch that I need to apply
> > here and send it to me?
> > 
> > thanks,
> > 
> > greg k-h
> 
> Hi greg,
> 
> I have sent the below incremental patch to you, please squash it into the previous patch v2, which had been applied in your usb-next branch. 
> http://patchwork.ozlabs.org/patch/186443/

Given that this is a git tree, "squashing" patches does not work at all.
I'll just apply it as-is.

thanks,

greg k-h

Patch

diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index b7451b2..9bfde82 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -210,11 +210,11 @@  static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
 	usb_put_hcd(hcd);
 }
 
-static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
+static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
 			       enum fsl_usb2_phy_modes phy_mode,
 			       unsigned int port_offset)
 {
-	u32 portsc, temp;
+	u32 portsc;
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	void __iomem *non_ehci = hcd->regs;
 	struct device *dev = hcd->self.controller;
@@ -232,9 +232,15 @@  static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
 	case FSL_USB2_PHY_ULPI:
 		if (pdata->controller_ver) {
 			/* controller version 1.6 or above */
-			temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
-			out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
-				USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL);
+			setbits32(non_ehci + FSL_SOC_USB_CTRL,
+					ULPI_PHY_CLK_SEL);
+			/*
+			 * Due to controller issue of PHY_CLK_VALID in ULPI
+			 * mode, we set USB_CTRL_USB_EN before checking
+			 * PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work.
+			 */
+			clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
+					UTMI_PHY_EN, USB_CTRL_USB_EN);
 		}
 		portsc |= PORT_PTS_ULPI;
 		break;
@@ -247,9 +253,7 @@  static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
 	case FSL_USB2_PHY_UTMI:
 		if (pdata->controller_ver) {
 			/* controller version 1.6 or above */
-			temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
-			out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
-				UTMI_PHY_EN | USB_CTRL_USB_EN);
+			setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
 			mdelay(FSL_UTMI_PHY_DLY);  /* Delay for UTMI PHY CLK to
 						become stable - 10ms*/
 		}
@@ -262,23 +266,33 @@  static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
 	case FSL_USB2_PHY_NONE:
 		break;
 	}
+
+	if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) {
+		/* check PHY_CLK_VALID to get phy clk valid */
+		if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
+				PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) {
+			printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
+			return -EINVAL;
+		}
+	}
+
 	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
+
+	if (phy_mode != FSL_USB2_PHY_ULPI)
+		setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN);
+
+	return 0;
 }
 
-static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
+static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 {
 	struct usb_hcd *hcd = ehci_to_hcd(ehci);
 	struct fsl_usb2_platform_data *pdata;
 	void __iomem *non_ehci = hcd->regs;
-	u32 temp;
 
 	pdata = hcd->self.controller->platform_data;
 
-	/* Enable PHY interface in the control reg. */
 	if (pdata->have_sysif_regs) {
-		temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
-		out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
-
 		/*
 		* Turn on cache snooping hardware, since some PowerPC platforms
 		* wholly rely on hardware to deal with cache coherent
@@ -293,7 +307,8 @@  static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 
 	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
 			(pdata->operating_mode == FSL_USB2_DR_OTG))
-		ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
+		if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
+			return -EINVAL;
 
 	if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
 		unsigned int chip, rev, svr;
@@ -307,9 +322,12 @@  static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 			ehci->has_fsl_port_bug = 1;
 
 		if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
-			ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
+			if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
+				return -EINVAL;
+
 		if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
-			ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1);
+			if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1))
+				return -EINVAL;
 	}
 
 	if (pdata->have_sysif_regs) {
@@ -322,12 +340,15 @@  static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 #endif
 		out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
 	}
+
+	return 0;
 }
 
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 {
-	ehci_fsl_usb_setup(ehci);
+	if (ehci_fsl_usb_setup(ehci))
+		return -EINVAL;
 	ehci_port_power(ehci, 0);
 
 	return 0;
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 8840368..dbd292e 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -61,4 +61,5 @@ 
 #define PLL_RESET               (1<<8)
 #define UTMI_PHY_EN             (1<<9)
 #define ULPI_PHY_CLK_SEL        (1<<10)
+#define PHY_CLK_VALID		(1<<17)
 #endif				/* _EHCI_FSL_H */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 15be561..700bf31 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -19,6 +19,7 @@ 
 
 #define FSL_UTMI_PHY_DLY	10	/*As per P1010RM, delay for UTMI
 				PHY CLK to become stable - 10ms*/
+#define FSL_USB_PHY_CLK_TIMEOUT	10000	/* uSec */
 #define FSL_USB_VER_OLD		0
 #define FSL_USB_VER_1_6		1
 #define FSL_USB_VER_2_2		2