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