2020-09-10 08:28:51

by Chunfeng Yun

[permalink] [raw]
Subject: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

Use readl_poll_timeout_atomic() to simplify code

Cc: Mathias Nyman <[email protected]>
Cc: Yoshihiro Shimoda <[email protected]>
Signed-off-by: Chunfeng Yun <[email protected]>
---
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);

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 */
--
1.9.1


2020-09-10 13:24:42

by Daniel Thompson

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

On Thu, Sep 10, 2020 at 04:21:45PM +0800, Chunfeng Yun wrote:
> Use readl_poll_timeout_atomic() to simplify code
>
> Cc: Mathias Nyman <[email protected]>
> Cc: Yoshihiro Shimoda <[email protected]>
> Signed-off-by: Chunfeng Yun <[email protected]>
> ---
> 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.


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 ! .


Daniel.

2020-09-10 21:50:27

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

Hi Chunfeng,

Thank you for the patch!

> From: Chunfeng Yun, Sent: Thursday, September 10, 2020 5:22 PM
>
> Use readl_poll_timeout_atomic() to simplify code
>
> Cc: Mathias Nyman <[email protected]>
> Cc: Yoshihiro Shimoda <[email protected]>
> Signed-off-by: Chunfeng Yun <[email protected]>
> ---
> 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);

Some parentheses are not needed like below:

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);

Likewise above:
retval = readl_poll_timeout_atomic(hcd->regs + RCAR_USB3_AXH_STA,
val, (val & mask) == mask, 1, 1000);

> + return !!retval;

This breaks the code. If I changed this to "return retval < 0 ? false : true;",
it works again.

Best regards,
Yoshihiro Shimoda

2020-09-11 02:24:42

by Chunfeng Yun

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

On Thu, 2020-09-10 at 12:56 +0000, Yoshihiro Shimoda wrote:
> Hi Chunfeng,
>
> Thank you for the patch!
>
> > From: Chunfeng Yun, Sent: Thursday, September 10, 2020 5:22 PM
> >
> > Use readl_poll_timeout_atomic() to simplify code
> >
> > Cc: Mathias Nyman <[email protected]>
> > Cc: Yoshihiro Shimoda <[email protected]>
> > Signed-off-by: Chunfeng Yun <[email protected]>
> > ---
> > 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);
>
> Some parentheses are not needed like below:
>
> retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,
> val, val & RCAR_USB3_DL_CTRL_FW_SUCCESS, 1, 10000);
>
Ok, will modify it

>
> > 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);
>
> Likewise above:
> retval = readl_poll_timeout_atomic(hcd->regs + RCAR_USB3_AXH_STA,
> val, (val & mask) == mask, 1, 1000);
>
> > + return !!retval;
>
> This breaks the code. If I changed this to "return retval < 0 ? false : true;",
> it works again.
Oops, my bad, will fix it

Thanks a lot

>
> Best regards,
> Yoshihiro Shimoda
>

2020-09-11 02:36:38

by Chunfeng Yun

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

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 <[email protected]>
> > Cc: Yoshihiro Shimoda <[email protected]>
> > Signed-off-by: Chunfeng Yun <[email protected]>
> > ---
> > 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.

2020-09-11 03:15:02

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

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 <[email protected]>
> > > Cc: Yoshihiro Shimoda <[email protected]>
> > > Signed-off-by: Chunfeng Yun <[email protected]>
> > > ---
> > > 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.

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 */

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

2020-09-11 04:18:36

by Chunfeng Yun

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

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 <[email protected]>
> > > > Cc: Yoshihiro Shimoda <[email protected]>
> > > > Signed-off-by: Chunfeng Yun <[email protected]>
> > > > ---
> > > > 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
>

2020-09-11 04:59:25

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

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 <[email protected]>
> > > > > Cc: Yoshihiro Shimoda <[email protected]>
> > > > > Signed-off-by: Chunfeng Yun <[email protected]>
> > > > > ---
> > > > > 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

2020-09-11 08:35:50

by Daniel Thompson

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

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 <[email protected]>
> > > Cc: Yoshihiro Shimoda <[email protected]>
> > > Signed-off-by: Chunfeng Yun <[email protected]>
> > > ---
> > > 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.

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.

2020-09-11 09:30:35

by Chunfeng Yun

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

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 <[email protected]>
> > > > Cc: Yoshihiro Shimoda <[email protected]>
> > > > Signed-off-by: Chunfeng Yun <[email protected]>
> > > > ---
> > > > 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.

2020-09-11 09:50:12

by Daniel Thompson

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

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 <[email protected]>
> > > > > Cc: Yoshihiro Shimoda <[email protected]>
> > > > > Signed-off-by: Chunfeng Yun <[email protected]>
> > > > > ---
> > > > > 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.


Daniel.


>
> > > > > - 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.
>

2020-09-11 10:01:54

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

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 <[email protected]>
> > > > > > Cc: Yoshihiro Shimoda <[email protected]>
> > > > > > Signed-off-by: Chunfeng Yun <[email protected]>
> > > > > > ---
> > > > > > 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

2020-09-11 11:51:33

by Chunfeng Yun

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 04/11] usb: xhci-rcar: convert to readl_poll_timeout_atomic()

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 <[email protected]>
> > > > > > Cc: Yoshihiro Shimoda <[email protected]>
> > > > > > Signed-off-by: Chunfeng Yun <[email protected]>
> > > > > > ---
> > > > > > 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
>