From: bigunclemax@gmail.com
Cc: bigunclemax@gmail.com, Bin Meng <bmeng.cn@gmail.com>,
Marek Vasut <marex@denx.de>, Tom Rini <trini@konsulko.com>,
Godfrey Mwangi <godmwan@microsoft.com>,
Janne Grunau <j@jannau.net>,
Mattijs Korpershoek <mkorpershoek@baylibre.com>,
Hector Martin <marcan@marcan.st>,
u-boot@lists.denx.de
Subject: [PATCH v1 0/1] USB xHCI wrong act_len calculation in case of using multipe TRB
Date: Fri, 21 Mar 2025 19:58:49 +0300 [thread overview]
Message-ID: <20250321165853.742837-1-bigunclemax@gmail.com> (raw)
From: Maksim Kiselev <bigunclemax@gmail.com>
Hello everyone!
I've encountered an issue where the actual length of received data is
calculated incorrectly in the case of a multiple TRB request.
Below, I'll try to describe the essence of the problem:
A USB-ethernet adapter ASIX ax88179 is connected to my board Li4pi,
and I'm sending a DHCP request to the server via dhpc command.
The response from the DHCP server always has the same length (0x168).
However, in some cases, I noticed that the received response had
an incorrect length and network subsystem is completely ingnore
incoming packets.
The problem turned out to be in the xhci_bulk_tx() function.
I added some debugging[1] to better understand what's happening.
Here's the log from a working case:
```
dev=000000057f786b90, pipe=c0010283, buffer=000000057f787540, length=20480
PUSH. trb_len: 0x5000
POP. trb_len: 0x4e98, comp_code: 0xd
udev->act_len: 0x168
```
And here's the log from a non-working case:
```
dev=000000057f78b610, pipe=c0010283, buffer=000000057f78bfc0, length=20480
PUSH. trb_len: 0x4040
PUSH. trb_len: 0xfc0
POP. trb_len: 0x3ed8, comp_code: 0xd
POP. trb_len: 0x0, comp_code: 0x1
udev->act_len: 0x1128
```
As you can see, in the second case, the buffer spans a 64KB boundary
(buffer=000000057f78bfc0 + 0x5000).
Therefore, it is split into two TRBs with lengths 0x4040 and 0xfc0.
Then, act_len is calculated as the difference between length and
trans_event.transfer_len:
```
0x5000 - 0x3ed8 = 0x1128
```
However, it seems that this is not entirely correct,
and act_len should be calculated as:
```
trb_buff_len - trans_event.transfer_len
(0x4040 - 0x3ed8 = 0x168)
```
0x168 is the correct length, which is the same as the length
obtained in the first case where network rx works fine.
Also I looked at the Linux xhci-ring code where urb->actual_length
calculated as:
[2]
```
requested = td->urb->transfer_buffer_length;
remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
```
[3]
```
td->urb->actual_length = requested - remaining;
```
Perhaps I missed something or misunderstood, so I would appreciate any help.
---
[1] Patch for debug output
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 89d2e54f20a..b1433a16a99 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -791,6 +791,8 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
trb_fields[2] = length_field;
trb_fields[3] = field | TRB_TYPE(TRB_NORMAL);
+ debug("PUSH. trb_len: 0x%x\n", trb_buff_len);
+
last_transfer_trb_addr = queue_trb(ctrl, ring, (num_trbs > 1), trb_fields);
--num_trbs;
@@ -816,6 +818,10 @@ again:
return -ETIMEDOUT;
}
+ debug("POP. trb_len: 0x%x, comp_code: 0x%x\n",
+ (int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len)),
+ GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len)));
+
if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer)) !=
(uintptr_t)last_transfer_trb_addr) {
available_length -=
@@ -831,6 +837,7 @@ again:
available_length -= first_trb_trimmed_sz;
record_transfer_result(udev, event, available_length);
+ debug("udev->act_len: 0x%x\n", udev->act_len);
xhci_acknowledge_event(ctrl);
xhci_inval_cache((uintptr_t)buffer, length);
xhci_dma_unmap(ctrl, buf_64, length);
[2] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/usb/host/xhci-ring.c?h=v6.14-rc7#n2346
[3] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/usb/host/xhci-ring.c?h=v6.14-rc7#n2413
Maksim Kiselev (1):
usb: xhci: fix calculation of act_len in case of using multipe TRB
drivers/usb/host/xhci-ring.c | 5 +++++
1 file changed, 5 insertions(+)
--
2.45.2
next reply other threads:[~2025-03-21 16:59 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-21 16:58 bigunclemax [this message]
2025-03-21 16:58 ` [PATCH v1 1/1] usb: xhci: fix calculation of act_len in case of using multipe TRB bigunclemax
2025-04-07 17:41 ` [PATCH v1 0/1] USB xHCI wrong act_len calculation " marcan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250321165853.742837-1-bigunclemax@gmail.com \
--to=bigunclemax@gmail.com \
--cc=bmeng.cn@gmail.com \
--cc=godmwan@microsoft.com \
--cc=j@jannau.net \
--cc=marcan@marcan.st \
--cc=marex@denx.de \
--cc=mkorpershoek@baylibre.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.