diff mbox series

[RESEND,v3,04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

Message ID 1599726112-4439-4-git-send-email-chunfeng.yun@mediatek.com
State Superseded
Headers show
Series [RESEND,v3,01/11] usb: early: convert to readl_poll_timeout_atomic() | expand

Commit Message

Chunfeng Yun (云春峰) Sept. 10, 2020, 8:21 a.m. UTC
Use readl_poll_timeout_atomic() to simplify code

Cc: Mathias Nyman <mathias.nyman@linux.intel.com>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>

---
v2~v3: no changes
---
 drivers/usb/host/xhci-rcar.c | 43 ++++++++++++-------------------------------
 1 file changed, 12 insertions(+), 31 deletions(-)

-- 
1.9.1

Comments

Chunfeng Yun (云春峰) Sept. 11, 2020, 2:33 a.m. UTC | #1
On Thu, 2020-09-10 at 14:12 +0100, Daniel Thompson wrote:
> On Thu, Sep 10, 2020 at 04:21:45PM +0800, Chunfeng Yun wrote:

> > Use readl_poll_timeout_atomic() to simplify code

> > 

> > Cc: Mathias Nyman <mathias.nyman@linux.intel.com>

> > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>

> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>

> > ---

> > v2~v3: no changes

> > ---

> >  drivers/usb/host/xhci-rcar.c | 43 ++++++++++++-------------------------------

> >  1 file changed, 12 insertions(+), 31 deletions(-)

> > 

> > diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c

> > index c1025d3..74f836f 100644

> > --- a/drivers/usb/host/xhci-rcar.c

> > +++ b/drivers/usb/host/xhci-rcar.c

> > @@ -6,6 +6,7 @@

> >   */

> >  

> >  #include <linux/firmware.h>

> > +#include <linux/iopoll.h>

> >  #include <linux/module.h>

> >  #include <linux/platform_device.h>

> >  #include <linux/of.h>

> > @@ -127,8 +128,7 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> >  	void __iomem *regs = hcd->regs;

> >  	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);

> >  	const struct firmware *fw;

> > -	int retval, index, j, time;

> > -	int timeout = 10000;

> > +	int retval, index, j;

> >  	u32 data, val, temp;

> >  	u32 quirks = 0;

> >  	const struct soc_device_attribute *attr;

> > @@ -166,32 +166,19 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> >  		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;

> >  		writel(temp, regs + RCAR_USB3_DL_CTRL);

> >  

> > -		for (time = 0; time < timeout; time++) {

> > -			val = readl(regs + RCAR_USB3_DL_CTRL);

> > -			if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0)

> > -				break;

> > -			udelay(1);

> > -		}

> > -		if (time == timeout) {

> > -			retval = -ETIMEDOUT;

> > +		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,

> > +				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),

> > +				1, 10000);

> > +		if (retval < 0)

> >  			break;

> > -		}

> >  	}

> >  

> >  	temp = readl(regs + RCAR_USB3_DL_CTRL);

> >  	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;

> >  	writel(temp, regs + RCAR_USB3_DL_CTRL);

> >  

> > -	for (time = 0; time < timeout; time++) {

> > -		val = readl(regs + RCAR_USB3_DL_CTRL);

> > -		if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) {

> > -			retval = 0;

> > -			break;

> > -		}

> > -		udelay(1);

> > -	}

> > -	if (time == timeout)

> > -		retval = -ETIMEDOUT;

> > +	retval = readl_poll_timeout_atomic((regs + RCAR_USB3_DL_CTRL),

> > +			val, (val & RCAR_USB3_DL_CTRL_FW_SUCCESS), 1, 10000);

> 

> Directly assigning to retval at this point will clobber a previous

> -ETIMEDOUT error.

> 

> In other words if there is a timeout waiting for FW_SET_DATA0, but not for

> DW_SUCCESS, then we will return the wrong return value.

Yes, agree with you, but seems I keep its original logic unchanged.

Hi Yoshihiro,

  What do think about Daniel's suggestion? should I fix it up?

> 

> 

> Daniel.

> 

> 

> >  

> >  	release_firmware(fw);

> >  

> > @@ -200,18 +187,12 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> >  

> >  static bool xhci_rcar_wait_for_pll_active(struct usb_hcd *hcd)

> >  {

> > -	int timeout = 1000;

> > +	int retval;

> >  	u32 val, mask = RCAR_USB3_AXH_STA_PLL_ACTIVE_MASK;

> >  

> > -	while (timeout > 0) {

> > -		val = readl(hcd->regs + RCAR_USB3_AXH_STA);

> > -		if ((val & mask) == mask)

> > -			return true;

> > -		udelay(1);

> > -		timeout--;

> > -	}

> > -

> > -	return false;

> > +	retval = readl_poll_timeout_atomic(hcd->regs + RCAR_USB3_AXH_STA,

> > +			val, ((val & mask) == mask), 1, 1000);

> > +	return !!retval;

> 

> This function returns a bool so !! is either wrong or redundant... I

> think in this case it is wrong and should be a single ! .

Yes, will fix it

Thanks a lot
> 

> 

> Daniel.
Chunfeng Yun (云春峰) Sept. 11, 2020, 4:12 a.m. UTC | #2
On Fri, 2020-09-11 at 03:13 +0000, Yoshihiro Shimoda wrote:
> Hi Daniel, Chunfeng,

> 

> > From: Chunfeng Yun, Sent: Friday, September 11, 2020 11:33 AM

> > 

> > On Thu, 2020-09-10 at 14:12 +0100, Daniel Thompson wrote:

> > > On Thu, Sep 10, 2020 at 04:21:45PM +0800, Chunfeng Yun wrote:

> > > > Use readl_poll_timeout_atomic() to simplify code

> > > >

> > > > Cc: Mathias Nyman <mathias.nyman@linux.intel.com>

> > > > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>

> > > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>

> > > > ---

> > > > v2~v3: no changes

> > > > ---

> > > >  drivers/usb/host/xhci-rcar.c | 43 ++++++++++++-------------------------------

> > > >  1 file changed, 12 insertions(+), 31 deletions(-)

> > > >

> > > > diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c

> > > > index c1025d3..74f836f 100644

> > > > --- a/drivers/usb/host/xhci-rcar.c

> > > > +++ b/drivers/usb/host/xhci-rcar.c

> > > > @@ -6,6 +6,7 @@

> > > >   */

> > > >

> > > >  #include <linux/firmware.h>

> > > > +#include <linux/iopoll.h>

> > > >  #include <linux/module.h>

> > > >  #include <linux/platform_device.h>

> > > >  #include <linux/of.h>

> > > > @@ -127,8 +128,7 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> > > >  	void __iomem *regs = hcd->regs;

> > > >  	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);

> > > >  	const struct firmware *fw;

> > > > -	int retval, index, j, time;

> > > > -	int timeout = 10000;

> > > > +	int retval, index, j;

> > > >  	u32 data, val, temp;

> > > >  	u32 quirks = 0;

> > > >  	const struct soc_device_attribute *attr;

> > > > @@ -166,32 +166,19 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> > > >  		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;

> > > >  		writel(temp, regs + RCAR_USB3_DL_CTRL);

> > > >

> > > > -		for (time = 0; time < timeout; time++) {

> > > > -			val = readl(regs + RCAR_USB3_DL_CTRL);

> > > > -			if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0)

> > > > -				break;

> > > > -			udelay(1);

> > > > -		}

> > > > -		if (time == timeout) {

> > > > -			retval = -ETIMEDOUT;

> > > > +		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,

> > > > +				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),

> > > > +				1, 10000);

> > > > +		if (retval < 0)

How about free firmware and return error number here ? instead of break

> > > >  			break;

> > > > -		}

> > > >  	}

> > > >

> > > >  	temp = readl(regs + RCAR_USB3_DL_CTRL);

> > > >  	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;

> > > >  	writel(temp, regs + RCAR_USB3_DL_CTRL);

> > > >

> > > > -	for (time = 0; time < timeout; time++) {

> > > > -		val = readl(regs + RCAR_USB3_DL_CTRL);

> > > > -		if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) {

> > > > -			retval = 0;

> > > > -			break;

> > > > -		}

> > > > -		udelay(1);

> > > > -	}

> > > > -	if (time == timeout)

> > > > -		retval = -ETIMEDOUT;

> > > > +	retval = readl_poll_timeout_atomic((regs + RCAR_USB3_DL_CTRL),

> > > > +			val, (val & RCAR_USB3_DL_CTRL_FW_SUCCESS), 1, 10000);

> > >

> > > Directly assigning to retval at this point will clobber a previous

> > > -ETIMEDOUT error.

> > >

> > > In other words if there is a timeout waiting for FW_SET_DATA0, but not for

> > > DW_SUCCESS, then we will return the wrong return value.

> 

> Thank you for your comment! I didn't realized this.

> 

> > Yes, agree with you, but seems I keep its original logic unchanged.

> > Hi Yoshihiro,

> > 

> >   What do think about Daniel's suggestion? should I fix it up?

> 

> I think you should fix it up like below:

> 

> if (readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,

> 		val, val & RCAR_USB3_DL_CTRL_FW_SUCCESS, 1, 10000) < 0)

> 	retval = -ETIMEOUT;	/* Overwrite retval if timeout occurred */


readl_poll_timeout_atomic() only return -ETIMEOUT error number, so this
likes what I did, doesn't fix it.

> 

> Otherwise, the xhci_rcar_download_firmware() cannot return -ETIMEDOUT if

> timeout happened on the previous poll [1].

> 

> [1]

> +		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,

> +				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),

> +				1, 10000);

> 

> Best regards,

> Yoshihiro Shimoda

>
Yoshihiro Shimoda Sept. 11, 2020, 4:57 a.m. UTC | #3
Hi Chunfeng,

> From: Chunfeng Yun, Sent: Friday, September 11, 2020 1:13 PM

> 

> On Fri, 2020-09-11 at 03:13 +0000, Yoshihiro Shimoda wrote:

> > Hi Daniel, Chunfeng,

> >

> > > From: Chunfeng Yun, Sent: Friday, September 11, 2020 11:33 AM

> > >

> > > On Thu, 2020-09-10 at 14:12 +0100, Daniel Thompson wrote:

> > > > On Thu, Sep 10, 2020 at 04:21:45PM +0800, Chunfeng Yun wrote:

> > > > > Use readl_poll_timeout_atomic() to simplify code

> > > > >

> > > > > Cc: Mathias Nyman <mathias.nyman@linux.intel.com>

> > > > > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>

> > > > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>

> > > > > ---

> > > > > v2~v3: no changes

> > > > > ---

> > > > >  drivers/usb/host/xhci-rcar.c | 43 ++++++++++++-------------------------------

> > > > >  1 file changed, 12 insertions(+), 31 deletions(-)

> > > > >

> > > > > diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c

> > > > > index c1025d3..74f836f 100644

> > > > > --- a/drivers/usb/host/xhci-rcar.c

> > > > > +++ b/drivers/usb/host/xhci-rcar.c

> > > > > @@ -6,6 +6,7 @@

> > > > >   */

> > > > >

> > > > >  #include <linux/firmware.h>

> > > > > +#include <linux/iopoll.h>

> > > > >  #include <linux/module.h>

> > > > >  #include <linux/platform_device.h>

> > > > >  #include <linux/of.h>

> > > > > @@ -127,8 +128,7 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> > > > >  	void __iomem *regs = hcd->regs;

> > > > >  	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);

> > > > >  	const struct firmware *fw;

> > > > > -	int retval, index, j, time;

> > > > > -	int timeout = 10000;

> > > > > +	int retval, index, j;

> > > > >  	u32 data, val, temp;

> > > > >  	u32 quirks = 0;

> > > > >  	const struct soc_device_attribute *attr;

> > > > > @@ -166,32 +166,19 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> > > > >  		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;

> > > > >  		writel(temp, regs + RCAR_USB3_DL_CTRL);

> > > > >

> > > > > -		for (time = 0; time < timeout; time++) {

> > > > > -			val = readl(regs + RCAR_USB3_DL_CTRL);

> > > > > -			if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0)

> > > > > -				break;

> > > > > -			udelay(1);

> > > > > -		}

> > > > > -		if (time == timeout) {

> > > > > -			retval = -ETIMEDOUT;

> > > > > +		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,

> > > > > +				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),

> > > > > +				1, 10000);

> > > > > +		if (retval < 0)

> How about free firmware and return error number here ? instead of break


I think clearing CTRL_ENABLE code below is needed.
And, I think this patch should not change a lot of things...

> > > > >  			break;

> > > > > -		}

> > > > >  	}

> > > > >

> > > > >  	temp = readl(regs + RCAR_USB3_DL_CTRL);

> > > > >  	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;

> > > > >  	writel(temp, regs + RCAR_USB3_DL_CTRL);

> > > > >

> > > > > -	for (time = 0; time < timeout; time++) {

> > > > > -		val = readl(regs + RCAR_USB3_DL_CTRL);

> > > > > -		if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) {

> > > > > -			retval = 0;

> > > > > -			break;

> > > > > -		}

> > > > > -		udelay(1);

> > > > > -	}

> > > > > -	if (time == timeout)

> > > > > -		retval = -ETIMEDOUT;

> > > > > +	retval = readl_poll_timeout_atomic((regs + RCAR_USB3_DL_CTRL),

> > > > > +			val, (val & RCAR_USB3_DL_CTRL_FW_SUCCESS), 1, 10000);

> > > >

> > > > Directly assigning to retval at this point will clobber a previous

> > > > -ETIMEDOUT error.

> > > >

> > > > In other words if there is a timeout waiting for FW_SET_DATA0, but not for

> > > > DW_SUCCESS, then we will return the wrong return value.

> >

> > Thank you for your comment! I didn't realized this.

> >

> > > Yes, agree with you, but seems I keep its original logic unchanged.

> > > Hi Yoshihiro,

> > >

> > >   What do think about Daniel's suggestion? should I fix it up?

> >

> > I think you should fix it up like below:

> >

> > if (readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,

> > 		val, val & RCAR_USB3_DL_CTRL_FW_SUCCESS, 1, 10000) < 0)

> > 	retval = -ETIMEOUT;	/* Overwrite retval if timeout occurred */

> 

> readl_poll_timeout_atomic() only return -ETIMEOUT error number, so this

> likes what I did, doesn't fix it.


readl_poll_timeout_atomic() returns 0 if timeout doesn't happen.
So, when my suggestion code runs, the retval is not overwritten if
the readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL...) returns 0.

Best regards,
Yoshihiro Shimoda
Chunfeng Yun (云春峰) Sept. 11, 2020, 9:27 a.m. UTC | #4
On Fri, 2020-09-11 at 09:34 +0100, Daniel Thompson wrote:
> On Fri, Sep 11, 2020 at 10:33:21AM +0800, Chunfeng Yun wrote:

> > On Thu, 2020-09-10 at 14:12 +0100, Daniel Thompson wrote:

> > > On Thu, Sep 10, 2020 at 04:21:45PM +0800, Chunfeng Yun wrote:

> > > > Use readl_poll_timeout_atomic() to simplify code

> > > > 

> > > > Cc: Mathias Nyman <mathias.nyman@linux.intel.com>

> > > > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>

> > > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>

> > > > ---

> > > > v2~v3: no changes

> > > > ---

> > > >  drivers/usb/host/xhci-rcar.c | 43 ++++++++++++-------------------------------

> > > >  1 file changed, 12 insertions(+), 31 deletions(-)

> > > > 

> > > > diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c

> > > > index c1025d3..74f836f 100644

> > > > --- a/drivers/usb/host/xhci-rcar.c

> > > > +++ b/drivers/usb/host/xhci-rcar.c

> > > > @@ -6,6 +6,7 @@

> > > >   */

> > > >  

> > > >  #include <linux/firmware.h>

> > > > +#include <linux/iopoll.h>

> > > >  #include <linux/module.h>

> > > >  #include <linux/platform_device.h>

> > > >  #include <linux/of.h>

> > > > @@ -127,8 +128,7 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> > > >  	void __iomem *regs = hcd->regs;

> > > >  	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);

> > > >  	const struct firmware *fw;

> > > > -	int retval, index, j, time;

> > > > -	int timeout = 10000;

> > > > +	int retval, index, j;

> > > >  	u32 data, val, temp;

> > > >  	u32 quirks = 0;

> > > >  	const struct soc_device_attribute *attr;

> > > > @@ -166,32 +166,19 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> > > >  		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;

> > > >  		writel(temp, regs + RCAR_USB3_DL_CTRL);

> > > >  

> > > > -		for (time = 0; time < timeout; time++) {

> > > > -			val = readl(regs + RCAR_USB3_DL_CTRL);

> > > > -			if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0)

> > > > -				break;

> > > > -			udelay(1);

> > > > -		}

> > > > -		if (time == timeout) {

> > > > -			retval = -ETIMEDOUT;

> > > > +		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,

> > > > +				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),

> > > > +				1, 10000);

> > > > +		if (retval < 0)

> > > >  			break;

> > > > -		}

> > > >  	}

> > > >  

> > > >  	temp = readl(regs + RCAR_USB3_DL_CTRL);

> > > >  	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;

> > > >  	writel(temp, regs + RCAR_USB3_DL_CTRL);

> > > >  

> > > > -	for (time = 0; time < timeout; time++) {

> > > > -		val = readl(regs + RCAR_USB3_DL_CTRL);

> > > > -		if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) {

> > > > -			retval = 0;

Here will set it 0 too

> > > > -			break;

> > > > -		}

> > > > -		udelay(1);

> > > > -	}

> > > > -	if (time == timeout)

> > > > -		retval = -ETIMEDOUT;

> > > > +	retval = readl_poll_timeout_atomic((regs + RCAR_USB3_DL_CTRL),

> > > > +			val, (val & RCAR_USB3_DL_CTRL_FW_SUCCESS), 1, 10000);

> > > 

> > > Directly assigning to retval at this point will clobber a previous

> > > -ETIMEDOUT error.

> > > 

> > > In other words if there is a timeout waiting for FW_SET_DATA0, but not for

> > > DW_SUCCESS, then we will return the wrong return value.

> >

> > Yes, agree with you, but seems I keep its original logic unchanged.

> 

> I disagree.

> 

> Your patch does not preserve the original logic. Your patch explicitly

> sets retval to zero if the second loop succeeds. The original code does

> not do this. As a result there is a change of return code for one of the

> error paths.

> 

> 

> Daniel.
Yoshihiro Shimoda Sept. 11, 2020, 9:58 a.m. UTC | #5
Hi Chunfeng,

> From: Daniel Thompson, Sent: Friday, September 11, 2020 6:49 PM
> 
> On Fri, Sep 11, 2020 at 05:27:22PM +0800, Chunfeng Yun wrote:
> > On Fri, 2020-09-11 at 09:34 +0100, Daniel Thompson wrote:
> > > On Fri, Sep 11, 2020 at 10:33:21AM +0800, Chunfeng Yun wrote:
> > > > On Thu, 2020-09-10 at 14:12 +0100, Daniel Thompson wrote:
> > > > > On Thu, Sep 10, 2020 at 04:21:45PM +0800, Chunfeng Yun wrote:
> > > > > > Use readl_poll_timeout_atomic() to simplify code
> > > > > >
> > > > > > Cc: Mathias Nyman <mathias.nyman@linux.intel.com>
> > > > > > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> > > > > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > > > > > ---
> > > > > > v2~v3: no changes
> > > > > > ---
> > > > > >  drivers/usb/host/xhci-rcar.c | 43 ++++++++++++-------------------------------
> > > > > >  1 file changed, 12 insertions(+), 31 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
> > > > > > index c1025d3..74f836f 100644
> > > > > > --- a/drivers/usb/host/xhci-rcar.c
> > > > > > +++ b/drivers/usb/host/xhci-rcar.c
> > > > > > @@ -6,6 +6,7 @@
> > > > > >   */
> > > > > >
> > > > > >  #include <linux/firmware.h>
> > > > > > +#include <linux/iopoll.h>
> > > > > >  #include <linux/module.h>
> > > > > >  #include <linux/platform_device.h>
> > > > > >  #include <linux/of.h>
> > > > > > @@ -127,8 +128,7 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
> > > > > >  	void __iomem *regs = hcd->regs;
> > > > > >  	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
> > > > > >  	const struct firmware *fw;
> > > > > > -	int retval, index, j, time;
> > > > > > -	int timeout = 10000;
> > > > > > +	int retval, index, j;
> > > > > >  	u32 data, val, temp;
> > > > > >  	u32 quirks = 0;
> > > > > >  	const struct soc_device_attribute *attr;
> > > > > > @@ -166,32 +166,19 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
> > > > > >  		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;
> > > > > >  		writel(temp, regs + RCAR_USB3_DL_CTRL);
> > > > > >
> > > > > > -		for (time = 0; time < timeout; time++) {
> > > > > > -			val = readl(regs + RCAR_USB3_DL_CTRL);
> > > > > > -			if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0)
> > > > > > -				break;
> > > > > > -			udelay(1);
> > > > > > -		}
> > > > > > -		if (time == timeout) {
> > > > > > -			retval = -ETIMEDOUT;
> > > > > > +		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,
> > > > > > +				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),
> > > > > > +				1, 10000);
> > > > > > +		if (retval < 0)
> > > > > >  			break;
> > > > > > -		}
> > > > > >  	}
> > > > > >
> > > > > >  	temp = readl(regs + RCAR_USB3_DL_CTRL);
> > > > > >  	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;
> > > > > >  	writel(temp, regs + RCAR_USB3_DL_CTRL);
> > > > > >
> > > > > > -	for (time = 0; time < timeout; time++) {
> > > > > > -		val = readl(regs + RCAR_USB3_DL_CTRL);
> > > > > > -		if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) {
> > > > > > -			retval = 0;
> > Here will set it 0 too
> 
> Doh...
> 
> Thanks.

Ah, now I also understood your patch was logically unchanged.
Thanks!

Best regards,
Yoshihiro Shimoda
Chunfeng Yun (云春峰) Sept. 11, 2020, 11:46 a.m. UTC | #6
On Fri, 2020-09-11 at 04:57 +0000, Yoshihiro Shimoda wrote:
> Hi Chunfeng,

> 

> > From: Chunfeng Yun, Sent: Friday, September 11, 2020 1:13 PM

> > 

> > On Fri, 2020-09-11 at 03:13 +0000, Yoshihiro Shimoda wrote:

> > > Hi Daniel, Chunfeng,

> > >

> > > > From: Chunfeng Yun, Sent: Friday, September 11, 2020 11:33 AM

> > > >

> > > > On Thu, 2020-09-10 at 14:12 +0100, Daniel Thompson wrote:

> > > > > On Thu, Sep 10, 2020 at 04:21:45PM +0800, Chunfeng Yun wrote:

> > > > > > Use readl_poll_timeout_atomic() to simplify code

> > > > > >

> > > > > > Cc: Mathias Nyman <mathias.nyman@linux.intel.com>

> > > > > > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>

> > > > > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>

> > > > > > ---

> > > > > > v2~v3: no changes

> > > > > > ---

> > > > > >  drivers/usb/host/xhci-rcar.c | 43 ++++++++++++-------------------------------

> > > > > >  1 file changed, 12 insertions(+), 31 deletions(-)

> > > > > >

> > > > > > diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c

> > > > > > index c1025d3..74f836f 100644

> > > > > > --- a/drivers/usb/host/xhci-rcar.c

> > > > > > +++ b/drivers/usb/host/xhci-rcar.c

> > > > > > @@ -6,6 +6,7 @@

> > > > > >   */

> > > > > >

> > > > > >  #include <linux/firmware.h>

> > > > > > +#include <linux/iopoll.h>

> > > > > >  #include <linux/module.h>

> > > > > >  #include <linux/platform_device.h>

> > > > > >  #include <linux/of.h>

> > > > > > @@ -127,8 +128,7 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> > > > > >  	void __iomem *regs = hcd->regs;

> > > > > >  	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);

> > > > > >  	const struct firmware *fw;

> > > > > > -	int retval, index, j, time;

> > > > > > -	int timeout = 10000;

> > > > > > +	int retval, index, j;

> > > > > >  	u32 data, val, temp;

> > > > > >  	u32 quirks = 0;

> > > > > >  	const struct soc_device_attribute *attr;

> > > > > > @@ -166,32 +166,19 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)

> > > > > >  		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;

> > > > > >  		writel(temp, regs + RCAR_USB3_DL_CTRL);

> > > > > >

> > > > > > -		for (time = 0; time < timeout; time++) {

> > > > > > -			val = readl(regs + RCAR_USB3_DL_CTRL);

> > > > > > -			if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0)

> > > > > > -				break;

> > > > > > -			udelay(1);

> > > > > > -		}

> > > > > > -		if (time == timeout) {

> > > > > > -			retval = -ETIMEDOUT;

> > > > > > +		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,

> > > > > > +				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),

> > > > > > +				1, 10000);

> > > > > > +		if (retval < 0)

> > How about free firmware and return error number here ? instead of break

> 

> I think clearing CTRL_ENABLE code below is needed.

> And, I think this patch should not change a lot of things...

Ok, thanks

> 

> > > > > >  			break;

> > > > > > -		}

> > > > > >  	}

> > > > > >

> > > > > >  	temp = readl(regs + RCAR_USB3_DL_CTRL);

> > > > > >  	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;

> > > > > >  	writel(temp, regs + RCAR_USB3_DL_CTRL);

> > > > > >

> > > > > > -	for (time = 0; time < timeout; time++) {

> > > > > > -		val = readl(regs + RCAR_USB3_DL_CTRL);

> > > > > > -		if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) {

> > > > > > -			retval = 0;

> > > > > > -			break;

> > > > > > -		}

> > > > > > -		udelay(1);

> > > > > > -	}

> > > > > > -	if (time == timeout)

> > > > > > -		retval = -ETIMEDOUT;

> > > > > > +	retval = readl_poll_timeout_atomic((regs + RCAR_USB3_DL_CTRL),

> > > > > > +			val, (val & RCAR_USB3_DL_CTRL_FW_SUCCESS), 1, 10000);

> > > > >

> > > > > Directly assigning to retval at this point will clobber a previous

> > > > > -ETIMEDOUT error.

> > > > >

> > > > > In other words if there is a timeout waiting for FW_SET_DATA0, but not for

> > > > > DW_SUCCESS, then we will return the wrong return value.

> > >

> > > Thank you for your comment! I didn't realized this.

> > >

> > > > Yes, agree with you, but seems I keep its original logic unchanged.

> > > > Hi Yoshihiro,

> > > >

> > > >   What do think about Daniel's suggestion? should I fix it up?

> > >

> > > I think you should fix it up like below:

> > >

> > > if (readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,

> > > 		val, val & RCAR_USB3_DL_CTRL_FW_SUCCESS, 1, 10000) < 0)

> > > 	retval = -ETIMEOUT;	/* Overwrite retval if timeout occurred */

> > 

> > readl_poll_timeout_atomic() only return -ETIMEOUT error number, so this

> > likes what I did, doesn't fix it.

> 

> readl_poll_timeout_atomic() returns 0 if timeout doesn't happen.

> So, when my suggestion code runs, the retval is not overwritten if

> the readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL...) returns 0.

> 

> Best regards,

> Yoshihiro Shimoda

>
diff mbox series

Patch

diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index c1025d3..74f836f 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -6,6 +6,7 @@ 
  */
 
 #include <linux/firmware.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
@@ -127,8 +128,7 @@  static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
 	void __iomem *regs = hcd->regs;
 	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
 	const struct firmware *fw;
-	int retval, index, j, time;
-	int timeout = 10000;
+	int retval, index, j;
 	u32 data, val, temp;
 	u32 quirks = 0;
 	const struct soc_device_attribute *attr;
@@ -166,32 +166,19 @@  static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
 		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;
 		writel(temp, regs + RCAR_USB3_DL_CTRL);
 
-		for (time = 0; time < timeout; time++) {
-			val = readl(regs + RCAR_USB3_DL_CTRL);
-			if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0)
-				break;
-			udelay(1);
-		}
-		if (time == timeout) {
-			retval = -ETIMEDOUT;
+		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,
+				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),
+				1, 10000);
+		if (retval < 0)
 			break;
-		}
 	}
 
 	temp = readl(regs + RCAR_USB3_DL_CTRL);
 	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;
 	writel(temp, regs + RCAR_USB3_DL_CTRL);
 
-	for (time = 0; time < timeout; time++) {
-		val = readl(regs + RCAR_USB3_DL_CTRL);
-		if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) {
-			retval = 0;
-			break;
-		}
-		udelay(1);
-	}
-	if (time == timeout)
-		retval = -ETIMEDOUT;
+	retval = readl_poll_timeout_atomic((regs + RCAR_USB3_DL_CTRL),
+			val, (val & RCAR_USB3_DL_CTRL_FW_SUCCESS), 1, 10000);
 
 	release_firmware(fw);
 
@@ -200,18 +187,12 @@  static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
 
 static bool xhci_rcar_wait_for_pll_active(struct usb_hcd *hcd)
 {
-	int timeout = 1000;
+	int retval;
 	u32 val, mask = RCAR_USB3_AXH_STA_PLL_ACTIVE_MASK;
 
-	while (timeout > 0) {
-		val = readl(hcd->regs + RCAR_USB3_AXH_STA);
-		if ((val & mask) == mask)
-			return true;
-		udelay(1);
-		timeout--;
-	}
-
-	return false;
+	retval = readl_poll_timeout_atomic(hcd->regs + RCAR_USB3_AXH_STA,
+			val, ((val & mask) == mask), 1, 1000);
+	return !!retval;
 }
 
 /* This function needs to initialize a "phy" of usb before */