NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/54070: urtwn(4) does not work on OHCI
The following reply was made to PR kern/54070; it has been noted by GNATS.
From: Andreas Gustafsson <gson%gson.org@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc:
Subject: Re: kern/54070: urtwn(4) does not work on OHCI
Date: Tue, 26 Nov 2019 16:42:26 +0200
Investigating this with a USB protocol analyzer showed that the
first USB bulk IN transfer processed by urtwn_rxeof() was correct,
but in the second transfer, the first 64 bytes were missing from
the data received by urtwn_rxeof() even though they were present
on the wire.
I believe what is happening is that the first transfer ends with a
zero-length packet, which is expected. The code path in the OHCI
driver that handles short transfers then resets the TD Queue Head
Pointer in the Endpoint Descriptor by writing the entire 32-bit word
containing it, which has the desired side effect of clearing the
Halted bit, but also the undesired side effect of clearing the
toggleCarry bit. If the first packet of the next transfer then
happens to have a data toggle of "1", it is considered to have a
toggle mismatch and is ignored, causing one packet's worth of data
(64 bytes) to be lost. The following packet then has the expected
toggle and the remainder of the transfer is received normally.
With the following patch, urtwn at ochi works much better. I intend
to commit it soon unless someone has a really good objection.
Index: ohci.c
===================================================================
RCS file: /bracket/repo/src/sys/dev/usb/ohci.c,v
retrieving revision 1.290
diff -u -r1.290 ohci.c
--- ohci.c 11 Aug 2019 22:55:03 -0000 1.290
+++ ohci.c 26 Nov 2019 14:04:32 -0000
@@ -1515,8 +1515,9 @@
ohci_soft_ed_t *sed = opipe->sed;
- /* clear halt and TD chain */
- sed->ed.ed_headp = HTOO32(p->physaddr);
+ /* clear halt and TD chain, preserving toggle carry */
+ sed->ed.ed_headp = HTOO32(p->physaddr |
+ (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY));
usb_syncmem(&sed->dma,
sed->offs + offsetof(ohci_ed_t, ed_headp),
sizeof(sed->ed.ed_headp),
--
Andreas Gustafsson, gson%gson.org@localhost
Home |
Main Index |
Thread Index |
Old Index