[U-Boot] [PATCH 1/4] usb: xhci: Set accurate add context flags when updating hub attributes

If a USB 3.0 hub is plugged into the root port of the xHC, the xHCI driver will issue a 'Configure Endpoint' command to the xHC for it to update its internal data structure for this hub device. The hub attributes are in the slot context so we need tell xHC to update the slot context by setting the add context flags of the input control context to only cover the slot context.
At present the add context flags is or'ed with the slot context bit, but it should really be accurately set to the slot context, as the variable that holds the value of the add context flags comes from whatever was set in the last command execution, which may contain additional contexts that 'Configure Endpoint' command should not touch. Some xHC implementations like x86 don't complain such, but it was observed on Renesas RCar Gen3 platform that the RCar xHC complains with a 'TRB error' completion codes as the response.
Reported-by: Marek Vasut marek.vasut@gmail.com Signed-off-by: Bin Meng bmeng.cn@gmail.com Tested-by: Marek Vasut marek.vasut@gmail.com Tested-by: Matthias Blankertz matthias.blankertz@cetitec.com ---
drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3adb002..565948c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1424,7 +1424,7 @@ static int xhci_update_hub_device(struct udevice *dev, struct usb_device *udev)
ctrl_ctx = xhci_get_input_control_ctx(in_ctx); /* Initialize the input context control */ - ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); + ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); ctrl_ctx->drop_flags = 0;
xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);

Per xHCI spec chapter 6.2.2 table 6-7, as input, software shall initialize the dev_state field to '0'. Though this does not seem to cause any issue with most xHC implementations, let's do this to conform with the spec.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Tested-by: Marek Vasut marek.vasut@gmail.com Tested-by: Matthias Blankertz matthias.blankertz@cetitec.com ---
drivers/usb/host/xhci.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 565948c..8c1126e 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1452,6 +1452,7 @@ static int xhci_update_hub_device(struct udevice *dev, struct usb_device *udev) think_time = (think_time / 666) - 1; if (udev->speed == USB_SPEED_HIGH) slot_ctx->tt_info |= cpu_to_le32(TT_THINK_TIME(think_time)); + slot_ctx->dev_state = 0;
return xhci_configure_endpoints(udev, false); }

If a full speed hub connects to a high speed hub which supports MTT, the MTT field of its slot context will be set to 1 when xHCI driver setups an xHCI virtual device in xhci_setup_addressable_virt_dev(). Once usb core fetch its hub descriptor, and need to update the xHC's internal data structures for the device, the HUB field of its slot context will be set to 1 too, meanwhile MTT is also set before, this will cause configure endpoint command fail. In the case, we should clear MTT to 0 for full speed hub according to section 6.2.2.
This keeps in sync with Linux kernel commit: 096b110: usb: xhci: fix config fail of FS hub behind a HS hub with MTT
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
drivers/usb/host/xhci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8c1126e..f9c6bbb 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1435,8 +1435,15 @@ static int xhci_update_hub_device(struct udevice *dev, struct usb_device *udev)
/* Update hub related fields */ slot_ctx->dev_info |= cpu_to_le32(DEV_HUB); - if (hub->tt.multi && udev->speed == USB_SPEED_HIGH) + /* + * refer to section 6.2.2: MTT should be 0 for full speed hub, + * but it may be already set to 1 when setup an xHCI virtual + * device, so clear it anyway. + */ + if (hub->tt.multi) slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); + else if (udev->speed == USB_SPEED_FULL) + slot_ctx->dev_info &= cpu_to_le32(~DEV_MTT); slot_ctx->dev_info2 |= cpu_to_le32(XHCI_MAX_PORTS(udev->maxchild)); /* * Set TT think time - convert from ns to FS bit times.

In xhci_set_configuration(), 'Context Entries' field in the slot context was cleared with mask LAST_CTX_MASK, but it should have taken the endianness into consideration.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f9c6bbb..9ded14c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -536,7 +536,7 @@ static int xhci_set_configuration(struct usb_device *udev) /* slot context */ xhci_slot_copy(ctrl, in_ctx, out_ctx); slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - slot_ctx->dev_info &= ~(LAST_CTX_MASK); + slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK)); slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0);
xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0);

On 05/24/2018 08:40 AM, Bin Meng wrote:
If a USB 3.0 hub is plugged into the root port of the xHC, the xHCI driver will issue a 'Configure Endpoint' command to the xHC for it to update its internal data structure for this hub device. The hub attributes are in the slot context so we need tell xHC to update the slot context by setting the add context flags of the input control context to only cover the slot context.
At present the add context flags is or'ed with the slot context bit, but it should really be accurately set to the slot context, as the variable that holds the value of the add context flags comes from whatever was set in the last command execution, which may contain additional contexts that 'Configure Endpoint' command should not touch. Some xHC implementations like x86 don't complain such, but it was observed on Renesas RCar Gen3 platform that the RCar xHC complains with a 'TRB error' completion codes as the response.
Reported-by: Marek Vasut marek.vasut@gmail.com Signed-off-by: Bin Meng bmeng.cn@gmail.com Tested-by: Marek Vasut marek.vasut@gmail.com Tested-by: Matthias Blankertz matthias.blankertz@cetitec.com
Applied all, thanks!
participants (2)
-
Bin Meng
-
Marek Vasut