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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox