Re: [PATCH] USB: DCW3: GADGET: Set Correct Max Speed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

John Youn <John.Youn@xxxxxxxxxxxx> writes:
> On 11/6/2015 9:55 AM, Felipe Balbi wrote:
>> 
>> Hi,
>> 
>> "McCauley, Ben" <Ben.McCauley@xxxxxxxxxx> writes:
>>> Felipe,
>>>
>>>  -----Original Message-----
>>>  From: Felipe Balbi [mailto:balbi@xxxxxx]
>>>  Sent: Friday, November 06, 2015 10:06 AM
>>>  To: McCauley, Ben <Ben.McCauley@xxxxxxxxxx>
>>>  Cc: linux-usb@xxxxxxxxxxxxxxx; Schroeder, Jay <Jay.Schroeder@xxxxxxxxxx>
>>> Subject: Re: [PATCH] USB: DCW3: GADGET: Set Correct Max Speed
>>>>
>>>>
>>>> Hi,
>>>>
>>>> "McCauley, Ben" <Ben.McCauley@xxxxxxxxxx> writes:
>>>>> The max speed was always being set to USB_SUPER_SPEED even when the
>>>>> phy was only capable of HIGH_SPEED. This
>>>>
>>>> this statement is untrue
>>>>
>>>>> uses the value set for the phy to set the max for the gadget. It
>>>>> resolves an issue with Window PCs where they report that using a
>>>>> USB3.0 port would result in better performance even when connecting
>>>>> through a 3.0 port.
>>>>
>>>> man, who gave you this kernel ? Which kernel version are you using ?
>>>> Have you even tested mainline ?
>>>
>>> This Kernel is from http://omapzoom.org/?p=kernel/omap.git;a=shortlog;h=refs/heads/p-ti-linux-3.14.y-common
>>> at branch  "development/omapzoom/glsdk-7.-2.00.02".
>>> I have not tested it on main line.
>> 
>> seems like you should be talking to your FAE or using TI's e2e forum for
>> this.
>> 
>>>>> Signed-off-by: McCauley, Ben <ben.mccauley@xxxxxxxxxx>
>>>>> ---
>>>>>
>>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>>> index 1eaf31c..0a388e3 100644
>>>>> --- a/drivers/usb/dwc3/gadget.c
>>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>>> @@ -2899,7 +2899,7 @@
>>>>
>>>> which kernel are you using ? This file is 2868 lines, so you're patching outside
>>>> the file.
>>>>
>>>>>         }
>>>>>
>>>>>         dwc->gadget.ops                 = &dwc3_gadget_ops;
>>>>> -       dwc->gadget.max_speed           = USB_SPEED_SUPER;
>>>>> +       dwc->gadget.max_speed           = dwc->maximum_speed;
>>>>
>>>> this is corrected at dwc3_gadget_start():
>> 
>> and I see that in that kernel, this is corrected at
>> dwc3_gadget_restart() instead.
>> 
>>>>       /**
>>>>        * WORKAROUND: DWC3 revision < 2.20a have an issue
>>>>        * which would cause metastability state on Run/Stop
>>>>        * bit if we try to force the IP to USB2-only mode.
>>>>        *
>>>>        * Because of that, we cannot configure the IP to any
>>>>        * speed other than the SuperSpeed
>>>>        *
>>>>        * Refers to:
>>>>        *
>>>>        * STAR#9000525659: Clock Domain Crossing on DCTL in
>>>>        * USB 2.0 Mode
>>>>        */
>>>>       if (dwc->revision < DWC3_REVISION_220A) {
>>>>               reg |= DWC3_DCFG_SUPERSPEED;
>>>>       } else {
>>>>               switch (dwc->maximum_speed) {
>>>>               case USB_SPEED_LOW:
>>>>                       reg |= DWC3_DSTS_LOWSPEED;
>>>>                       break;
>>>>               case USB_SPEED_FULL:
>>>>                       reg |= DWC3_DSTS_FULLSPEED1;
>>>>                       break;
>>>>               case USB_SPEED_HIGH:
>>>>                       reg |= DWC3_DSTS_HIGHSPEED;
>>>>                       break;
>>>>               case USB_SPEED_SUPER:   /* FALLTHROUGH */
>>>>               case USB_SPEED_UNKNOWN: /* FALTHROUGH */
>>>>               default:
>>>>                       reg |= DWC3_DSTS_SUPERSPEED;
>>>>               }
>>>>       }
>>>>
>>>
>>> I am on 3.14 LTS though even on 4.3 I do not see dwc->gadget.max_speed
>>> being updated to reflect the actual max speed as set in
>>> drivers/usb/dwc3/core.c [dwc3_probe()]. dwc->gadget.max_speed is used
>>> in a number of locations to determine what response is sent to the
>>> host.
>>>
>>> dwc3_gadget_start() only appears to set the max speed to the register
>>> and not update the gadget.
>> 
>> but the IP _is_ super-speed capable. Max speed should only be used to
>> determine if $this gadget can run with $this controller; speed, instead,
>> is used for all sorts of different things and _that_ is updated on
>> Connection Done IRQ.
>> 
>> Can you point one place where you think it's wrong ? And, please, refer
>> to mainline code. We can't support a v3.14 kernel which might contain a
>> ton of additions which are not in mainline (for example, mainline
>> doesn't have a dwc3_gadget_restart() function).
>> 
>
>
> Hi Felipe,
>
> There are 3 related speed settings which may be confusing the
> matter.
>
> dwc->maximum_speed
>
> A user-supplied parameter that determines how to program the
> DCFG.speed. This is the code you're referring to above.
>
> gadget->speed
>
> The current connected speed of the gadget. Used in various ways
> by the upper layer.
>
> gadget->max_speed
>
> Reports the maximum speed supported by the gadget.
>
> This is used by upper layer to determine which BOS descriptors to
> send and the settings within those descriptors. It's also used to
> set the bcdUSB appropriately.

no, bcdUSB will be set to 0x0210 if max_speed == SUPER & speed == HIGH:

		case USB_DT_DEVICE:
			cdev->desc.bNumConfigurations =
				count_configs(cdev, USB_DT_DEVICE);
			cdev->desc.bMaxPacketSize0 =
				cdev->gadget->ep0->maxpacket;
			if (gadget_is_superspeed(gadget)) {
				if (gadget->speed >= USB_SPEED_SUPER) {
					cdev->desc.bcdUSB = cpu_to_le16(0x0300);
					cdev->desc.bMaxPacketSize0 = 9;
				} else {
					cdev->desc.bcdUSB = cpu_to_le16(0x0210);
				}
			} else {
				cdev->desc.bcdUSB = cpu_to_le16(0x0200);
			}


> Ben is talking about setting the gadget->max_speed, which is
> hard-coded in dwc3 to USB_SPEED_SUPER.
>
> For this core, the maximum supported speed may not actually be
> super speed. Many customers choose to use the 3.0 core in
> 2.0-only mode with a HS phy.

yeah, I got all that. But we still have the problem of metastability for
anything <2.20a. For those cores, we just cannot mess around with any of
these settings (STAR 9000525659, if you wanna check).

> And with the 3.1 core, it my be integrated in a system that is
> HS-only, SS (gen1), or SSP (gen2) capable. So the
> gadget->max_speed needs to be set correctly based on some
> user-defined or detected value.
>
> We have a similar change in our local tree for 3.1, except we set
> it based on GHWPARAMS3.SSPHY_INTERFACE. But I think it makes
> sense to set it from dwc->maximum_speed as well, for testing or
> to override it.

My other fear is about people setting this wrongly and later complaining
that it's not working. I would very much prefer your patch which detects
whether SSPHY_INTERFACE is around, however that won't always be correct.

I just noticed that in our USB2-only SoC (AM437x), SSPHY_INTERFACE is
set to 1 even though this SoC does _not_ have any USB3
capabilities.

	GHWPARAMS3 = 0x10420085

I actually tested this problem as listed above and connected my
USB2-only SoC to a windows box (both USB2 and USB3 hosts) and did not
see any such error messages. Any ideas why you have problems an I don't ?

Maybe, all we have to do is avoid adding a SuperSpeed USB Capability
descriptor if we didn't negotiate for superspeed. All the rest can
remain the same:

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 8b14c2a13ac5..672ae6bfcad8 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -547,9 +547,8 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
 static int bos_desc(struct usb_composite_dev *cdev)
 {
 	struct usb_ext_cap_descriptor	*usb_ext;
-	struct usb_ss_cap_descriptor	*ss_cap;
-	struct usb_dcd_config_params	dcd_config_params;
 	struct usb_bos_descriptor	*bos = cdev->req->buf;
+	struct usb_gadget		*gadget = cdev->gadget;
 
 	bos->bLength = USB_DT_BOS_SIZE;
 	bos->bDescriptorType = USB_DT_BOS;
@@ -569,33 +568,38 @@ static int bos_desc(struct usb_composite_dev *cdev)
 	usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
 	usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT);
 
-	/*
-	 * The Superspeed USB Capability descriptor shall be implemented by all
-	 * SuperSpeed devices.
-	 */
-	ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
-	bos->bNumDeviceCaps++;
-	le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
-	ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
-	ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
-	ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
-	ss_cap->bmAttributes = 0; /* LTM is not supported yet */
-	ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
+	if (gadget->speed >= USB_SPEED_SUPER) {
+		struct usb_ss_cap_descriptor	*ss_cap;
+		struct usb_dcd_config_params	dcd_config_params;
+
+		/*
+		 * The Superspeed USB Capability descriptor shall be implemented
+		 * by all SuperSpeed devices.
+		 */
+		ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
+		bos->bNumDeviceCaps++;
+		le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
+		ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
+		ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
+		ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
+		ss_cap->bmAttributes = 0; /* LTM is not supported yet */
+		ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
 				USB_FULL_SPEED_OPERATION |
 				USB_HIGH_SPEED_OPERATION |
 				USB_5GBPS_OPERATION);
-	ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
+		ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
 
-	/* Get Controller configuration */
-	if (cdev->gadget->ops->get_config_params)
-		cdev->gadget->ops->get_config_params(&dcd_config_params);
-	else {
+		/* Get Controller configuration */
 		dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT;
 		dcd_config_params.bU2DevExitLat =
 			cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
+
+		if (cdev->gadget->ops->get_config_params)
+			cdev->gadget->ops->get_config_params(&dcd_config_params);
+
+		ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
+		ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
 	}
-	ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
-	ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
 
 	return le16_to_cpu(bos->wTotalLength);
 }

Can you see if this solves the issue you're having ?

-- 
balbi

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux