2019-10-29 15:17:15

by Roger Quadros

[permalink] [raw]
Subject: [PATCH] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host

Take into account gadget driver's speed limit when programming
controller speed.

Signed-off-by: Roger Quadros <[email protected]>
---
Hi Greg,

Please apply this for -rc.
Without this, g_audio is broken on cdns3 USB controller is
connected to a Super-Speed host.

cheers,
-roger

drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
index 40dad4e8d0dc..1c724c20d468 100644
--- a/drivers/usb/cdns3/gadget.c
+++ b/drivers/usb/cdns3/gadget.c
@@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
{
struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
unsigned long flags;
+ enum usb_device_speed max_speed = driver->max_speed;

spin_lock_irqsave(&priv_dev->lock, flags);
priv_dev->gadget_driver = driver;
+
+ /* limit speed if necessary */
+ max_speed = min(driver->max_speed, gadget->max_speed);
+
+ switch (max_speed) {
+ case USB_SPEED_FULL:
+ writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
+ writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
+ break;
+ case USB_SPEED_HIGH:
+ writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
+ break;
+ case USB_SPEED_SUPER:
+ break;
+ default:
+ dev_err(priv_dev->dev,
+ "invalid maximum_speed parameter %d\n",
+ max_speed);
+ /* fall through */
+ case USB_SPEED_UNKNOWN:
+ /* default to superspeed */
+ max_speed = USB_SPEED_SUPER;
+ break;
+ }
+
cdns3_gadget_config(priv_dev);
spin_unlock_irqrestore(&priv_dev->lock, flags);
return 0;
@@ -2570,12 +2596,7 @@ static int cdns3_gadget_start(struct cdns3 *cdns)
/* Check the maximum_speed parameter */
switch (max_speed) {
case USB_SPEED_FULL:
- writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
- writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
- break;
case USB_SPEED_HIGH:
- writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
- break;
case USB_SPEED_SUPER:
break;
default:
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


2019-10-30 06:37:55

by Peter Chen

[permalink] [raw]
Subject: Re: [PATCH] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host

On 19-10-29 17:15:14, Roger Quadros wrote:
> Take into account gadget driver's speed limit when programming
> controller speed.
>
> Signed-off-by: Roger Quadros <[email protected]>
> ---
> Hi Greg,
>
> Please apply this for -rc.
> Without this, g_audio is broken on cdns3 USB controller is
> connected to a Super-Speed host.
>
> cheers,
> -roger
>
> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
> 1 file changed, 26 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
> index 40dad4e8d0dc..1c724c20d468 100644
> --- a/drivers/usb/cdns3/gadget.c
> +++ b/drivers/usb/cdns3/gadget.c
> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
> {
> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
> unsigned long flags;
> + enum usb_device_speed max_speed = driver->max_speed;
>
> spin_lock_irqsave(&priv_dev->lock, flags);
> priv_dev->gadget_driver = driver;
> +
> + /* limit speed if necessary */
> + max_speed = min(driver->max_speed, gadget->max_speed);
> +
> + switch (max_speed) {
> + case USB_SPEED_FULL:
> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> + break;
> + case USB_SPEED_HIGH:
> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> + break;
> + case USB_SPEED_SUPER:
> + break;
> + default:
> + dev_err(priv_dev->dev,
> + "invalid maximum_speed parameter %d\n",
> + max_speed);
> + /* fall through */
> + case USB_SPEED_UNKNOWN:
> + /* default to superspeed */
> + max_speed = USB_SPEED_SUPER;
> + break;
> + }
> +
> cdns3_gadget_config(priv_dev);
> spin_unlock_irqrestore(&priv_dev->lock, flags);
> return 0;
> @@ -2570,12 +2596,7 @@ static int cdns3_gadget_start(struct cdns3 *cdns)
> /* Check the maximum_speed parameter */
> switch (max_speed) {
> case USB_SPEED_FULL:
> - writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
> - writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> - break;
> case USB_SPEED_HIGH:
> - writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> - break;
> case USB_SPEED_SUPER:
> break;
> default:

Just a small comment:

You could delete switch-case at cdns3_gadget_start, and just use
if() statement, eg:

max_speed = usb_get_maximum_speed(cdns->dev);
if (max_speed == USB_SPEED_UNKNOWN)
max_speed = USB_SPEED_SUPER;

Otherwise:

Acked-by: Peter Chen <[email protected]>

--

Thanks,
Peter Chen

2019-10-30 08:45:55

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host



On 30/10/2019 08:36, Peter Chen wrote:
> On 19-10-29 17:15:14, Roger Quadros wrote:
>> Take into account gadget driver's speed limit when programming
>> controller speed.
>>
>> Signed-off-by: Roger Quadros <[email protected]>
>> ---
>> Hi Greg,
>>
>> Please apply this for -rc.
>> Without this, g_audio is broken on cdns3 USB controller is
>> connected to a Super-Speed host.
>>
>> cheers,
>> -roger
>>
>> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>> index 40dad4e8d0dc..1c724c20d468 100644
>> --- a/drivers/usb/cdns3/gadget.c
>> +++ b/drivers/usb/cdns3/gadget.c
>> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
>> {
>> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
>> unsigned long flags;
>> + enum usb_device_speed max_speed = driver->max_speed;
>>
>> spin_lock_irqsave(&priv_dev->lock, flags);
>> priv_dev->gadget_driver = driver;
>> +
>> + /* limit speed if necessary */
>> + max_speed = min(driver->max_speed, gadget->max_speed);
>> +
>> + switch (max_speed) {
>> + case USB_SPEED_FULL:
>> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>> + break;
>> + case USB_SPEED_HIGH:
>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>> + break;
>> + case USB_SPEED_SUPER:
>> + break;
>> + default:
>> + dev_err(priv_dev->dev,
>> + "invalid maximum_speed parameter %d\n",
>> + max_speed);
>> + /* fall through */
>> + case USB_SPEED_UNKNOWN:
>> + /* default to superspeed */
>> + max_speed = USB_SPEED_SUPER;
>> + break;
>> + }
>> +
>> cdns3_gadget_config(priv_dev);
>> spin_unlock_irqrestore(&priv_dev->lock, flags);
>> return 0;
>> @@ -2570,12 +2596,7 @@ static int cdns3_gadget_start(struct cdns3 *cdns)
>> /* Check the maximum_speed parameter */
>> switch (max_speed) {
>> case USB_SPEED_FULL:
>> - writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
>> - writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>> - break;
>> case USB_SPEED_HIGH:
>> - writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>> - break;
>> case USB_SPEED_SUPER:
>> break;
>> default:
>
> Just a small comment:
>
> You could delete switch-case at cdns3_gadget_start, and just use
> if() statement, eg:
>
> max_speed = usb_get_maximum_speed(cdns->dev);
> if (max_speed == USB_SPEED_UNKNOWN)
> max_speed = USB_SPEED_SUPER;

But then it will not take care of bailing out for USB_SPEED_WIRELESS,
USB_SPEED_SUPER_PLUS and any future speeds.

>
> Otherwise:
>
> Acked-by: Peter Chen <[email protected]>
>

--
cheers,
-roger

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

2019-10-30 08:57:18

by Peter Chen

[permalink] [raw]
Subject: Re: [PATCH] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host

On 19-10-30 10:44:10, Roger Quadros wrote:
>
>
> On 30/10/2019 08:36, Peter Chen wrote:
> > On 19-10-29 17:15:14, Roger Quadros wrote:
> > > Take into account gadget driver's speed limit when programming
> > > controller speed.
> > >
> > > Signed-off-by: Roger Quadros <[email protected]>
> > > ---
> > > Hi Greg,
> > >
> > > Please apply this for -rc.
> > > Without this, g_audio is broken on cdns3 USB controller is
> > > connected to a Super-Speed host.
> > >
> > > cheers,
> > > -roger
> > >
> > > drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
> > > 1 file changed, 26 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
> > > index 40dad4e8d0dc..1c724c20d468 100644
> > > --- a/drivers/usb/cdns3/gadget.c
> > > +++ b/drivers/usb/cdns3/gadget.c
> > > @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
> > > {
> > > struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
> > > unsigned long flags;
> > > + enum usb_device_speed max_speed = driver->max_speed;
> > > spin_lock_irqsave(&priv_dev->lock, flags);
> > > priv_dev->gadget_driver = driver;
> > > +
> > > + /* limit speed if necessary */
> > > + max_speed = min(driver->max_speed, gadget->max_speed);
> > > +
> > > + switch (max_speed) {
> > > + case USB_SPEED_FULL:
> > > + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
> > > + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> > > + break;
> > > + case USB_SPEED_HIGH:
> > > + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> > > + break;
> > > + case USB_SPEED_SUPER:
> > > + break;
> > > + default:
> > > + dev_err(priv_dev->dev,
> > > + "invalid maximum_speed parameter %d\n",
> > > + max_speed);
> > > + /* fall through */
> > > + case USB_SPEED_UNKNOWN:
> > > + /* default to superspeed */
> > > + max_speed = USB_SPEED_SUPER;
> > > + break;
> > > + }
> > > +
> > > cdns3_gadget_config(priv_dev);
> > > spin_unlock_irqrestore(&priv_dev->lock, flags);
> > > return 0;
> > > @@ -2570,12 +2596,7 @@ static int cdns3_gadget_start(struct cdns3 *cdns)
> > > /* Check the maximum_speed parameter */
> > > switch (max_speed) {
> > > case USB_SPEED_FULL:
> > > - writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
> > > - writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> > > - break;
> > > case USB_SPEED_HIGH:
> > > - writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> > > - break;
> > > case USB_SPEED_SUPER:
> > > break;
> > > default:
> >
> > Just a small comment:
> >
> > You could delete switch-case at cdns3_gadget_start, and just use
> > if() statement, eg:
> >
> > max_speed = usb_get_maximum_speed(cdns->dev);
> > if (max_speed == USB_SPEED_UNKNOWN)
> > max_speed = USB_SPEED_SUPER;
>
> But then it will not take care of bailing out for USB_SPEED_WIRELESS,
> USB_SPEED_SUPER_PLUS and any future speeds.

This IP only supports FS/HS/SS. It doesn't a big issue, if you would
like to keep the code like your patch, it is also OK.

--

Thanks,
Peter Chen

2019-10-30 11:47:40

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host


Hi,

Roger Quadros <[email protected]> writes:

> Take into account gadget driver's speed limit when programming
> controller speed.
>
> Signed-off-by: Roger Quadros <[email protected]>
> ---
> Hi Greg,
>
> Please apply this for -rc.

if you want this in -rc, you should have a Fixes line there.

> Without this, g_audio is broken on cdns3 USB controller is
> connected to a Super-Speed host.
>
> cheers,
> -roger
>
> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
> 1 file changed, 26 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
> index 40dad4e8d0dc..1c724c20d468 100644
> --- a/drivers/usb/cdns3/gadget.c
> +++ b/drivers/usb/cdns3/gadget.c
> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
> {
> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
> unsigned long flags;
> + enum usb_device_speed max_speed = driver->max_speed;
>
> spin_lock_irqsave(&priv_dev->lock, flags);
> priv_dev->gadget_driver = driver;
> +
> + /* limit speed if necessary */
> + max_speed = min(driver->max_speed, gadget->max_speed);
> +
> + switch (max_speed) {
> + case USB_SPEED_FULL:
> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> + break;
> + case USB_SPEED_HIGH:
> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> + break;

seems like this can be simplified a little:

switch (max_speed) {
case USB_SPEED_FULL:
writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
/* fallthrough */
case USB_SPEED_HIGH:
writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
/* fallthrough */
case USB_SPEED_SUPER:
break;

[...]


--
balbi

2019-10-30 11:52:28

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host

On Wed, Oct 30, 2019 at 01:46:07PM +0200, Felipe Balbi wrote:
>
> Hi,
>
> Roger Quadros <[email protected]> writes:
>
> > Take into account gadget driver's speed limit when programming
> > controller speed.
> >
> > Signed-off-by: Roger Quadros <[email protected]>
> > ---
> > Hi Greg,
> >
> > Please apply this for -rc.
>
> if you want this in -rc, you should have a Fixes line there.

I agree, I can't take this for -rc as-is :(

2019-10-30 12:18:00

by Roger Quadros

[permalink] [raw]
Subject: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host

Take into account gadget driver's speed limit when programming
controller speed.

Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
Signed-off-by: Roger Quadros <[email protected]>
Acked-by: Peter Chen <[email protected]>
---

Changelog:
v2
- Add Fixes line

drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
index 40dad4e8d0dc..1c724c20d468 100644
--- a/drivers/usb/cdns3/gadget.c
+++ b/drivers/usb/cdns3/gadget.c
@@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
{
struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
unsigned long flags;
+ enum usb_device_speed max_speed = driver->max_speed;

spin_lock_irqsave(&priv_dev->lock, flags);
priv_dev->gadget_driver = driver;
+
+ /* limit speed if necessary */
+ max_speed = min(driver->max_speed, gadget->max_speed);
+
+ switch (max_speed) {
+ case USB_SPEED_FULL:
+ writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
+ writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
+ break;
+ case USB_SPEED_HIGH:
+ writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
+ break;
+ case USB_SPEED_SUPER:
+ break;
+ default:
+ dev_err(priv_dev->dev,
+ "invalid maximum_speed parameter %d\n",
+ max_speed);
+ /* fall through */
+ case USB_SPEED_UNKNOWN:
+ /* default to superspeed */
+ max_speed = USB_SPEED_SUPER;
+ break;
+ }
+
cdns3_gadget_config(priv_dev);
spin_unlock_irqrestore(&priv_dev->lock, flags);
return 0;
@@ -2570,12 +2596,7 @@ static int cdns3_gadget_start(struct cdns3 *cdns)
/* Check the maximum_speed parameter */
switch (max_speed) {
case USB_SPEED_FULL:
- writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
- writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
- break;
case USB_SPEED_HIGH:
- writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
- break;
case USB_SPEED_SUPER:
break;
default:
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

2019-10-30 13:32:05

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host

On Wed, Oct 30, 2019 at 02:16:07PM +0200, Roger Quadros wrote:
> Take into account gadget driver's speed limit when programming
> controller speed.
>
> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")

No need for "commit", doesn't the documentation say the correct format?
I haven't looked in a while...

I can edit it out this time...

greg k-h

2019-10-30 14:24:17

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host



On 30/10/2019 15:30, Greg KH wrote:
> On Wed, Oct 30, 2019 at 02:16:07PM +0200, Roger Quadros wrote:
>> Take into account gadget driver's speed limit when programming
>> controller speed.
>>
>> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
>
> No need for "commit", doesn't the documentation say the correct format?
> I haven't looked in a while...
>

Sorry, my bad.

> I can edit it out this time...

Thanks!
>
> greg k-h
>

--
cheers,
-roger

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

2019-10-31 08:57:35

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host


Hi,

Roger Quadros <[email protected]> writes:

> Take into account gadget driver's speed limit when programming
> controller speed.
>
> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
> Signed-off-by: Roger Quadros <[email protected]>
> Acked-by: Peter Chen <[email protected]>
> ---
>
> Changelog:
> v2
> - Add Fixes line
>
> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
> 1 file changed, 26 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
> index 40dad4e8d0dc..1c724c20d468 100644
> --- a/drivers/usb/cdns3/gadget.c
> +++ b/drivers/usb/cdns3/gadget.c
> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
> {
> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
> unsigned long flags;
> + enum usb_device_speed max_speed = driver->max_speed;
>
> spin_lock_irqsave(&priv_dev->lock, flags);
> priv_dev->gadget_driver = driver;
> +
> + /* limit speed if necessary */
> + max_speed = min(driver->max_speed, gadget->max_speed);
> +
> + switch (max_speed) {
> + case USB_SPEED_FULL:
> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> + break;
> + case USB_SPEED_HIGH:
> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
> + break;
> + case USB_SPEED_SUPER:
> + break;
> + default:
> + dev_err(priv_dev->dev,
> + "invalid maximum_speed parameter %d\n",
> + max_speed);
> + /* fall through */
> + case USB_SPEED_UNKNOWN:
> + /* default to superspeed */
> + max_speed = USB_SPEED_SUPER;
> + break;
> + }

I had suggested some simplification for this case statement.

--
balbi

2019-10-31 10:37:07

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host

Hi,

On 31/10/2019 10:55, Felipe Balbi wrote:
>
> Hi,
>
> Roger Quadros <[email protected]> writes:
>
>> Take into account gadget driver's speed limit when programming
>> controller speed.
>>
>> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
>> Signed-off-by: Roger Quadros <[email protected]>
>> Acked-by: Peter Chen <[email protected]>
>> ---
>>
>> Changelog:
>> v2
>> - Add Fixes line
>>
>> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>> index 40dad4e8d0dc..1c724c20d468 100644
>> --- a/drivers/usb/cdns3/gadget.c
>> +++ b/drivers/usb/cdns3/gadget.c
>> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
>> {
>> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
>> unsigned long flags;
>> + enum usb_device_speed max_speed = driver->max_speed;
>>
>> spin_lock_irqsave(&priv_dev->lock, flags);
>> priv_dev->gadget_driver = driver;
>> +
>> + /* limit speed if necessary */
>> + max_speed = min(driver->max_speed, gadget->max_speed);
>> +
>> + switch (max_speed) {
>> + case USB_SPEED_FULL:
>> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>> + break;
>> + case USB_SPEED_HIGH:
>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>> + break;
>> + case USB_SPEED_SUPER:
>> + break;
>> + default:
>> + dev_err(priv_dev->dev,
>> + "invalid maximum_speed parameter %d\n",
>> + max_speed);
>> + /* fall through */
>> + case USB_SPEED_UNKNOWN:
>> + /* default to superspeed */
>> + max_speed = USB_SPEED_SUPER;
>> + break;
>> + }
>
> I had suggested some simplification for this case statement.
>

oops, looks like Greg picked this already.

During more tests today I just observed that this patch causes
the following regression.

Connect EVM to Super-Speed host
Load g_audio. (this enumerates as HS which is fine)
unload g_audio
load g_zero (this enumerates at HS instead of SS).

This is because the speed limit that we set doesn't get cleared.

Now the bits are write only and there is a way to undo USB_CONF_SFORCE_FS
by writing USB_CONF_CFORCE_FS, however there is no corresponding bit
to clear USB_CONF_USB3DIS. Only way seems to be USB_CFG_SWRST which
is a bit harsh IMO.

Pawel,

could you please confirm what is the best way to undo the high-speed
limit?

--
cheers,
-roger
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

2019-10-31 10:57:58

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host


Hi,

Roger Quadros <[email protected]> writes:

> Hi,
>
> On 31/10/2019 10:55, Felipe Balbi wrote:
>>
>> Hi,
>>
>> Roger Quadros <[email protected]> writes:
>>
>>> Take into account gadget driver's speed limit when programming
>>> controller speed.
>>>
>>> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
>>> Signed-off-by: Roger Quadros <[email protected]>
>>> Acked-by: Peter Chen <[email protected]>
>>> ---
>>>
>>> Changelog:
>>> v2
>>> - Add Fixes line
>>>
>>> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
>>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>>> index 40dad4e8d0dc..1c724c20d468 100644
>>> --- a/drivers/usb/cdns3/gadget.c
>>> +++ b/drivers/usb/cdns3/gadget.c
>>> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
>>> {
>>> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
>>> unsigned long flags;
>>> + enum usb_device_speed max_speed = driver->max_speed;
>>>
>>> spin_lock_irqsave(&priv_dev->lock, flags);
>>> priv_dev->gadget_driver = driver;
>>> +
>>> + /* limit speed if necessary */
>>> + max_speed = min(driver->max_speed, gadget->max_speed);
>>> +
>>> + switch (max_speed) {
>>> + case USB_SPEED_FULL:
>>> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);

so this forces the controller to FS

>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);

and this disconnects in superspeed? What is this supposed to do?

>>> + break;
>>> + case USB_SPEED_HIGH:
>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>> + break;
>>> + case USB_SPEED_SUPER:
>>> + break;
>>> + default:
>>> + dev_err(priv_dev->dev,
>>> + "invalid maximum_speed parameter %d\n",
>>> + max_speed);
>>> + /* fall through */
>>> + case USB_SPEED_UNKNOWN:
>>> + /* default to superspeed */
>>> + max_speed = USB_SPEED_SUPER;
>>> + break;
>>> + }
>>
>> I had suggested some simplification for this case statement.
>>
>
> oops, looks like Greg picked this already.
>
> During more tests today I just observed that this patch causes
> the following regression.
>
> Connect EVM to Super-Speed host
> Load g_audio. (this enumerates as HS which is fine)
> unload g_audio
> load g_zero (this enumerates at HS instead of SS).
>
> This is because the speed limit that we set doesn't get cleared.
>
> Now the bits are write only and there is a way to undo USB_CONF_SFORCE_FS
> by writing USB_CONF_CFORCE_FS, however there is no corresponding bit
> to clear USB_CONF_USB3DIS. Only way seems to be USB_CFG_SWRST which
> is a bit harsh IMO.

Isn't bit 0 enough?

/* Reset USB device configuration. */
#define USB_CONF_CFGRST BIT(0)

Also, now that I look at this more carefully, you should move that code
to udc_set_speed().

--
balbi

2019-10-31 11:06:26

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host



On 31/10/2019 12:55, Felipe Balbi wrote:
>
> Hi,
>
> Roger Quadros <[email protected]> writes:
>
>> Hi,
>>
>> On 31/10/2019 10:55, Felipe Balbi wrote:
>>>
>>> Hi,
>>>
>>> Roger Quadros <[email protected]> writes:
>>>
>>>> Take into account gadget driver's speed limit when programming
>>>> controller speed.
>>>>
>>>> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
>>>> Signed-off-by: Roger Quadros <[email protected]>
>>>> Acked-by: Peter Chen <[email protected]>
>>>> ---
>>>>
>>>> Changelog:
>>>> v2
>>>> - Add Fixes line
>>>>
>>>> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
>>>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>>>> index 40dad4e8d0dc..1c724c20d468 100644
>>>> --- a/drivers/usb/cdns3/gadget.c
>>>> +++ b/drivers/usb/cdns3/gadget.c
>>>> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
>>>> {
>>>> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
>>>> unsigned long flags;
>>>> + enum usb_device_speed max_speed = driver->max_speed;
>>>>
>>>> spin_lock_irqsave(&priv_dev->lock, flags);
>>>> priv_dev->gadget_driver = driver;
>>>> +
>>>> + /* limit speed if necessary */
>>>> + max_speed = min(driver->max_speed, gadget->max_speed);
>>>> +
>>>> + switch (max_speed) {
>>>> + case USB_SPEED_FULL:
>>>> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
>
> so this forces the controller to FS

Right.

>
>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>
> and this disconnects in superspeed? What is this supposed to do?
>

It says "Disconnect USB device in SuperSpeed".

We were asked to set that bit to limit it to HS.

>>>> + break;
>>>> + case USB_SPEED_HIGH:
>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>>> + break;
>>>> + case USB_SPEED_SUPER:
>>>> + break;
>>>> + default:
>>>> + dev_err(priv_dev->dev,
>>>> + "invalid maximum_speed parameter %d\n",
>>>> + max_speed);
>>>> + /* fall through */
>>>> + case USB_SPEED_UNKNOWN:
>>>> + /* default to superspeed */
>>>> + max_speed = USB_SPEED_SUPER;
>>>> + break;
>>>> + }
>>>
>>> I had suggested some simplification for this case statement.
>>>
>>
>> oops, looks like Greg picked this already.
>>
>> During more tests today I just observed that this patch causes
>> the following regression.
>>
>> Connect EVM to Super-Speed host
>> Load g_audio. (this enumerates as HS which is fine)
>> unload g_audio
>> load g_zero (this enumerates at HS instead of SS).
>>
>> This is because the speed limit that we set doesn't get cleared.
>>
>> Now the bits are write only and there is a way to undo USB_CONF_SFORCE_FS
>> by writing USB_CONF_CFORCE_FS, however there is no corresponding bit
>> to clear USB_CONF_USB3DIS. Only way seems to be USB_CFG_SWRST which
>> is a bit harsh IMO.
>
> Isn't bit 0 enough?
>
> /* Reset USB device configuration. */
> #define USB_CONF_CFGRST BIT(0)

Probably not, as explanation of USB3DIS bit says,
"To connect disconnected device, CPU performs
software reset (CFG.SWRST)." which is bit 7. "Device software reset.

But I'll let Pawel comment on this.

>
> Also, now that I look at this more carefully, you should move that code
> to udc_set_speed().
>

Agreed. I'll revise the implementation to move it to udc_set_speed()
once I know how to undo the USB3DIS.

--
cheers,
-roger
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

2019-10-31 11:09:36

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host


Hi,

Roger Quadros <[email protected]> writes:
>>>>> Take into account gadget driver's speed limit when programming
>>>>> controller speed.
>>>>>
>>>>> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
>>>>> Signed-off-by: Roger Quadros <[email protected]>
>>>>> Acked-by: Peter Chen <[email protected]>
>>>>> ---
>>>>>
>>>>> Changelog:
>>>>> v2
>>>>> - Add Fixes line
>>>>>
>>>>> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
>>>>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>>>>
>>>>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>>>>> index 40dad4e8d0dc..1c724c20d468 100644
>>>>> --- a/drivers/usb/cdns3/gadget.c
>>>>> +++ b/drivers/usb/cdns3/gadget.c
>>>>> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
>>>>> {
>>>>> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
>>>>> unsigned long flags;
>>>>> + enum usb_device_speed max_speed = driver->max_speed;
>>>>>
>>>>> spin_lock_irqsave(&priv_dev->lock, flags);
>>>>> priv_dev->gadget_driver = driver;
>>>>> +
>>>>> + /* limit speed if necessary */
>>>>> + max_speed = min(driver->max_speed, gadget->max_speed);
>>>>> +
>>>>> + switch (max_speed) {
>>>>> + case USB_SPEED_FULL:
>>>>> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
>>
>> so this forces the controller to FS
>
> Right.
>
>>
>>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>
>> and this disconnects in superspeed? What is this supposed to do?
>>
>
> It says "Disconnect USB device in SuperSpeed".
>
> We were asked to set that bit to limit it to HS.

I wonder if by "Disconnect USB device in SuperSpeed" means tristating
the PIPE3 interface, therefore forcing RX.Detect to fail.

>>>>> + break;
>>>>> + case USB_SPEED_HIGH:
>>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>>>> + break;
>>>>> + case USB_SPEED_SUPER:
>>>>> + break;
>>>>> + default:
>>>>> + dev_err(priv_dev->dev,
>>>>> + "invalid maximum_speed parameter %d\n",
>>>>> + max_speed);
>>>>> + /* fall through */
>>>>> + case USB_SPEED_UNKNOWN:
>>>>> + /* default to superspeed */
>>>>> + max_speed = USB_SPEED_SUPER;
>>>>> + break;
>>>>> + }
>>>>
>>>> I had suggested some simplification for this case statement.
>>>>
>>>
>>> oops, looks like Greg picked this already.
>>>
>>> During more tests today I just observed that this patch causes
>>> the following regression.
>>>
>>> Connect EVM to Super-Speed host
>>> Load g_audio. (this enumerates as HS which is fine)
>>> unload g_audio
>>> load g_zero (this enumerates at HS instead of SS).
>>>
>>> This is because the speed limit that we set doesn't get cleared.
>>>
>>> Now the bits are write only and there is a way to undo USB_CONF_SFORCE_FS
>>> by writing USB_CONF_CFORCE_FS, however there is no corresponding bit
>>> to clear USB_CONF_USB3DIS. Only way seems to be USB_CFG_SWRST which
>>> is a bit harsh IMO.
>>
>> Isn't bit 0 enough?
>>
>> /* Reset USB device configuration. */
>> #define USB_CONF_CFGRST BIT(0)
>
> Probably not, as explanation of USB3DIS bit says,
> "To connect disconnected device, CPU performs
> software reset (CFG.SWRST)." which is bit 7. "Device software reset.

ouch

> But I'll let Pawel comment on this.

ok

>> Also, now that I look at this more carefully, you should move that code
>> to udc_set_speed().
>>
>
> Agreed. I'll revise the implementation to move it to udc_set_speed()
> once I know how to undo the USB3DIS.

Sure

--
balbi

2019-11-03 08:19:09

by Pawel Laszczak

[permalink] [raw]
Subject: RE: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host

Hi,

>>
>> Hi,
>>
>> Roger Quadros <[email protected]> writes:
>>
>>> Hi,
>>>
>>> On 31/10/2019 10:55, Felipe Balbi wrote:
>>>>
>>>> Hi,
>>>>
>>>> Roger Quadros <[email protected]> writes:
>>>>
>>>>> Take into account gadget driver's speed limit when programming
>>>>> controller speed.
>>>>>
>>>>> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
>>>>> Signed-off-by: Roger Quadros <[email protected]>
>>>>> Acked-by: Peter Chen <[email protected]>
>>>>> ---
>>>>>
>>>>> Changelog:
>>>>> v2
>>>>> - Add Fixes line
>>>>>
>>>>> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
>>>>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>>>>
>>>>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>>>>> index 40dad4e8d0dc..1c724c20d468 100644
>>>>> --- a/drivers/usb/cdns3/gadget.c
>>>>> +++ b/drivers/usb/cdns3/gadget.c
>>>>> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
>>>>> {
>>>>> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
>>>>> unsigned long flags;
>>>>> + enum usb_device_speed max_speed = driver->max_speed;
>>>>>
>>>>> spin_lock_irqsave(&priv_dev->lock, flags);
>>>>> priv_dev->gadget_driver = driver;
>>>>> +
>>>>> + /* limit speed if necessary */
>>>>> + max_speed = min(driver->max_speed, gadget->max_speed);
>>>>> +
>>>>> + switch (max_speed) {
>>>>> + case USB_SPEED_FULL:
>>>>> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
>>
>> so this forces the controller to FS
>
>Right.
>
>>
>>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>
>> and this disconnects in superspeed? What is this supposed to do?
>>
>
>It says "Disconnect USB device in SuperSpeed".
>
>We were asked to set that bit to limit it to HS.
>
>>>>> + break;
>>>>> + case USB_SPEED_HIGH:
>>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>>>> + break;
>>>>> + case USB_SPEED_SUPER:
>>>>> + break;
>>>>> + default:
>>>>> + dev_err(priv_dev->dev,
>>>>> + "invalid maximum_speed parameter %d\n",
>>>>> + max_speed);
>>>>> + /* fall through */
>>>>> + case USB_SPEED_UNKNOWN:
>>>>> + /* default to superspeed */
>>>>> + max_speed = USB_SPEED_SUPER;
>>>>> + break;
>>>>> + }
>>>>
>>>> I had suggested some simplification for this case statement.
>>>>
>>>
>>> oops, looks like Greg picked this already.
>>>
>>> During more tests today I just observed that this patch causes
>>> the following regression.
>>>
>>> Connect EVM to Super-Speed host
>>> Load g_audio. (this enumerates as HS which is fine)
>>> unload g_audio
>>> load g_zero (this enumerates at HS instead of SS).
>>>
>>> This is because the speed limit that we set doesn't get cleared.
>>>
>>> Now the bits are write only and there is a way to undo USB_CONF_SFORCE_FS
>>> by writing USB_CONF_CFORCE_FS, however there is no corresponding bit
>>> to clear USB_CONF_USB3DIS. Only way seems to be USB_CFG_SWRST which
>>> is a bit harsh IMO.
>>
>> Isn't bit 0 enough?
>>
>> /* Reset USB device configuration. */
>> #define USB_CONF_CFGRST BIT(0)
>
>Probably not, as explanation of USB3DIS bit says,
>"To connect disconnected device, CPU performs
>software reset (CFG.SWRST)." which is bit 7. "Device software reset.
>
>But I'll let Pawel comment on this.

Yes it's the only way to return back to SS mode.
The USB speed is detecting during connecting.
CFG.SWRST make reconnect.

Maybe it would be better to add SS support in g_audio function.

>>
>> Also, now that I look at this more carefully, you should move that code
>> to udc_set_speed().
>>
>
>Agreed. I'll revise the implementation to move it to udc_set_speed()
>once I know how to undo the USB3DIS.
>
>--
>cheers,
>-roger
>Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
>Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

2019-11-04 09:20:15

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host



On 03/11/2019 10:17, Pawel Laszczak wrote:
> Hi,
>
>>>
>>> Hi,
>>>
>>> Roger Quadros <[email protected]> writes:
>>>
>>>> Hi,
>>>>
>>>> On 31/10/2019 10:55, Felipe Balbi wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> Roger Quadros <[email protected]> writes:
>>>>>
>>>>>> Take into account gadget driver's speed limit when programming
>>>>>> controller speed.
>>>>>>
>>>>>> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
>>>>>> Signed-off-by: Roger Quadros <[email protected]>
>>>>>> Acked-by: Peter Chen <[email protected]>
>>>>>> ---
>>>>>>
>>>>>> Changelog:
>>>>>> v2
>>>>>> - Add Fixes line
>>>>>>
>>>>>> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
>>>>>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>>>>>> index 40dad4e8d0dc..1c724c20d468 100644
>>>>>> --- a/drivers/usb/cdns3/gadget.c
>>>>>> +++ b/drivers/usb/cdns3/gadget.c
>>>>>> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
>>>>>> {
>>>>>> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
>>>>>> unsigned long flags;
>>>>>> + enum usb_device_speed max_speed = driver->max_speed;
>>>>>>
>>>>>> spin_lock_irqsave(&priv_dev->lock, flags);
>>>>>> priv_dev->gadget_driver = driver;
>>>>>> +
>>>>>> + /* limit speed if necessary */
>>>>>> + max_speed = min(driver->max_speed, gadget->max_speed);
>>>>>> +
>>>>>> + switch (max_speed) {
>>>>>> + case USB_SPEED_FULL:
>>>>>> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
>>>
>>> so this forces the controller to FS
>>
>> Right.
>>
>>>
>>>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>>
>>> and this disconnects in superspeed? What is this supposed to do?
>>>
>>
>> It says "Disconnect USB device in SuperSpeed".
>>
>> We were asked to set that bit to limit it to HS.
>>
>>>>>> + break;
>>>>>> + case USB_SPEED_HIGH:
>>>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>>>>> + break;
>>>>>> + case USB_SPEED_SUPER:
>>>>>> + break;
>>>>>> + default:
>>>>>> + dev_err(priv_dev->dev,
>>>>>> + "invalid maximum_speed parameter %d\n",
>>>>>> + max_speed);
>>>>>> + /* fall through */
>>>>>> + case USB_SPEED_UNKNOWN:
>>>>>> + /* default to superspeed */
>>>>>> + max_speed = USB_SPEED_SUPER;
>>>>>> + break;
>>>>>> + }
>>>>>
>>>>> I had suggested some simplification for this case statement.
>>>>>
>>>>
>>>> oops, looks like Greg picked this already.
>>>>
>>>> During more tests today I just observed that this patch causes
>>>> the following regression.
>>>>
>>>> Connect EVM to Super-Speed host
>>>> Load g_audio. (this enumerates as HS which is fine)
>>>> unload g_audio
>>>> load g_zero (this enumerates at HS instead of SS).
>>>>
>>>> This is because the speed limit that we set doesn't get cleared.
>>>>
>>>> Now the bits are write only and there is a way to undo USB_CONF_SFORCE_FS
>>>> by writing USB_CONF_CFORCE_FS, however there is no corresponding bit
>>>> to clear USB_CONF_USB3DIS. Only way seems to be USB_CFG_SWRST which
>>>> is a bit harsh IMO.
>>>
>>> Isn't bit 0 enough?
>>>
>>> /* Reset USB device configuration. */
>>> #define USB_CONF_CFGRST BIT(0)
>>
>> Probably not, as explanation of USB3DIS bit says,
>> "To connect disconnected device, CPU performs
>> software reset (CFG.SWRST)." which is bit 7. "Device software reset.
>>
>> But I'll let Pawel comment on this.
>
> Yes it's the only way to return back to SS mode.
> The USB speed is detecting during connecting.
> CFG.SWRST make reconnect.

Can this be done as part of udc_start or udc_stop?

>
> Maybe it would be better to add SS support in g_audio function.

Not every gadget needs SS, so this is not the right way IMO.

>
>>>
>>> Also, now that I look at this more carefully, you should move that code
>>> to udc_set_speed().
>>>
>>
>> Agreed. I'll revise the implementation to move it to udc_set_speed()
>> once I know how to undo the USB3DIS.
>>


--
cheers,
-roger
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

2019-11-04 15:18:40

by Pawel Laszczak

[permalink] [raw]
Subject: RE: [PATCH v2] usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host

Hi,

>
>On 03/11/2019 10:17, Pawel Laszczak wrote:
>> Hi,
>>
>>>>
>>>> Hi,
>>>>
>>>> Roger Quadros <[email protected]> writes:
>>>>
>>>>> Hi,
>>>>>
>>>>> On 31/10/2019 10:55, Felipe Balbi wrote:
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> Roger Quadros <[email protected]> writes:
>>>>>>
>>>>>>> Take into account gadget driver's speed limit when programming
>>>>>>> controller speed.
>>>>>>>
>>>>>>> Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
>>>>>>> Signed-off-by: Roger Quadros <[email protected]>
>>>>>>> Acked-by: Peter Chen <[email protected]>
>>>>>>> ---
>>>>>>>
>>>>>>> Changelog:
>>>>>>> v2
>>>>>>> - Add Fixes line
>>>>>>>
>>>>>>> drivers/usb/cdns3/gadget.c | 31 ++++++++++++++++++++++++++-----
>>>>>>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>>>>>>> index 40dad4e8d0dc..1c724c20d468 100644
>>>>>>> --- a/drivers/usb/cdns3/gadget.c
>>>>>>> +++ b/drivers/usb/cdns3/gadget.c
>>>>>>> @@ -2338,9 +2338,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
>>>>>>> {
>>>>>>> struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
>>>>>>> unsigned long flags;
>>>>>>> + enum usb_device_speed max_speed = driver->max_speed;
>>>>>>>
>>>>>>> spin_lock_irqsave(&priv_dev->lock, flags);
>>>>>>> priv_dev->gadget_driver = driver;
>>>>>>> +
>>>>>>> + /* limit speed if necessary */
>>>>>>> + max_speed = min(driver->max_speed, gadget->max_speed);
>>>>>>> +
>>>>>>> + switch (max_speed) {
>>>>>>> + case USB_SPEED_FULL:
>>>>>>> + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
>>>>
>>>> so this forces the controller to FS
>>>
>>> Right.
>>>
>>>>
>>>>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>>>
>>>> and this disconnects in superspeed? What is this supposed to do?
>>>>
>>>
>>> It says "Disconnect USB device in SuperSpeed".
>>>
>>> We were asked to set that bit to limit it to HS.
>>>
>>>>>>> + break;
>>>>>>> + case USB_SPEED_HIGH:
>>>>>>> + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
>>>>>>> + break;
>>>>>>> + case USB_SPEED_SUPER:
>>>>>>> + break;
>>>>>>> + default:
>>>>>>> + dev_err(priv_dev->dev,
>>>>>>> + "invalid maximum_speed parameter %d\n",
>>>>>>> + max_speed);
>>>>>>> + /* fall through */
>>>>>>> + case USB_SPEED_UNKNOWN:
>>>>>>> + /* default to superspeed */
>>>>>>> + max_speed = USB_SPEED_SUPER;
>>>>>>> + break;
>>>>>>> + }
>>>>>>
>>>>>> I had suggested some simplification for this case statement.
>>>>>>
>>>>>
>>>>> oops, looks like Greg picked this already.
>>>>>
>>>>> During more tests today I just observed that this patch causes
>>>>> the following regression.
>>>>>
>>>>> Connect EVM to Super-Speed host
>>>>> Load g_audio. (this enumerates as HS which is fine)
>>>>> unload g_audio
>>>>> load g_zero (this enumerates at HS instead of SS).
>>>>>
>>>>> This is because the speed limit that we set doesn't get cleared.
>>>>>
>>>>> Now the bits are write only and there is a way to undo USB_CONF_SFORCE_FS
>>>>> by writing USB_CONF_CFORCE_FS, however there is no corresponding bit
>>>>> to clear USB_CONF_USB3DIS. Only way seems to be USB_CFG_SWRST which
>>>>> is a bit harsh IMO.
>>>>
>>>> Isn't bit 0 enough?
>>>>
>>>> /* Reset USB device configuration. */
>>>> #define USB_CONF_CFGRST BIT(0)
>>>
>>> Probably not, as explanation of USB3DIS bit says,
>>> "To connect disconnected device, CPU performs
>>> software reset (CFG.SWRST)." which is bit 7. "Device software reset.
>>>
>>> But I'll let Pawel comment on this.
>>
>> Yes it's the only way to return back to SS mode.
>> The USB speed is detecting during connecting.
>> CFG.SWRST make reconnect.
>
>Can this be done as part of udc_start or udc_stop?

I think that it should work in both cases, however because it finish with connection
so probably the better will be udc_start function.

>
>>
>> Maybe it would be better to add SS support in g_audio function.
>
>Not every gadget needs SS, so this is not the right way IMO.
>
>>
>>>>
>>>> Also, now that I look at this more carefully, you should move that code
>>>> to udc_set_speed().
>>>>
>>>
>>> Agreed. I'll revise the implementation to move it to udc_set_speed()
>>> once I know how to undo the USB3DIS.
>>>
>
>
>--
>cheers,
>-roger
>Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
>Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki