Author: wmb
Date: 2010-01-16 21:02:47 +0100 (Sat, 16 Jan 2010)
New Revision: 1676
Modified:
dev/usb2/device/net/ax8817x.fth
dev/usb2/device/net/ethernet.fth
dev/usb2/hcd/control.fth
dev/usb2/hcd/ehci/bulk.fth
dev/usb2/hcd/ehci/qhtd.fth
Log:
OLPC trac 9423 - Fixed the longstanding problem with losing the first receive
packet with USB Ethernet devices. The problem was much deeper, involving data
toggle mismatches in the EHCI driver when the driver is re-opened and a new
bulk-in ring is established.
Modified: dev/usb2/device/net/ax8817x.fth
===================================================================
--- dev/usb2/device/net/ax8817x.fth 2010-01-15 02:48:23 UTC (rev 1675)
+++ dev/usb2/device/net/ax8817x.fth 2010-01-16 20:02:47 UTC (rev 1676)
@@ -168,8 +168,9 @@
\ I increase the loop count in case the partner is slow in negotiating.
\ And if there's no connection at all, let's not wait too long.
ax-mii-sw
- d# 2000 0 do 1 ax-mii@ 4 and ?leave 1 ms loop
+ d# 3000 0 do 1 ax-mii@ h# 20 and ?leave 1 ms loop
ax-mii-hw
+ d# 10 ms \ Just in case the link status bit isn't ready just yet
;
: select-phy ( -- )
Modified: dev/usb2/device/net/ethernet.fth
===================================================================
--- dev/usb2/device/net/ethernet.fth 2010-01-15 02:48:23 UTC (rev 1675)
+++ dev/usb2/device/net/ethernet.fth 2010-01-16 20:02:47 UTC (rev 1676)
@@ -147,14 +147,10 @@
headers
-\ This loopback test is a reliability improvement. The AX88772,
-\ and perhaps other chips, sometimes loses the first received
-\ packet. That's annoying, as the first packet is often a
-\ reply that we care about, thus causing a timeout and retry.
-\ We work around that by sending ourselves a few loopback packets
-\ until we receive one. In most cases, the first loopback packet
-\ is received correctly, and if not, the second one is okay.
-\ We try 5 times just to be safe, exiting as soon as we "win".
+\ This loopback code is here just in case it might be useful later.
+\ It was originally written as a workaround for a first-packet lossage
+\ problem, but the problem was eventually tracked down to a data toggle
+\ issue in the EHCI layer.
0 value scratch-buf
: clear-rx ( -- )
@@ -181,7 +177,6 @@
clear-rx
5 0 do try-loopback? ?leave loop
}loopback
- d# 20 ms \ Settling time after switching back
scratch-buf d# 2000 free-mem
;
@@ -190,8 +185,6 @@
link-up? 0= if
." Network not connected." cr
- end-bulk-in
- free-buf
true exit
then
@@ -199,7 +192,6 @@
inbuf /inbuf bulk-in-pipe begin-bulk-in
start-mac
- loopback-test
false
;
Modified: dev/usb2/hcd/control.fth
===================================================================
--- dev/usb2/hcd/control.fth 2010-01-15 02:48:23 UTC (rev 1675)
+++ dev/usb2/hcd/control.fth 2010-01-16 20:02:47 UTC (rev 1676)
@@ -78,6 +78,9 @@
: set-config ( cfg -- usberr )
>r 0 0 0 r> DR_DEVICE DR_OUT or SET_CONFIGURATION control-set
+ \ Setting the configuration initializes the endpoint's bulk data toggles
+ 0 bulk-out-pipe target di-out-data!
+ 0 bulk-in-pipe target di-in-data!
;
: set-interface ( alt intf -- usberr )
Modified: dev/usb2/hcd/ehci/bulk.fth
===================================================================
--- dev/usb2/hcd/ehci/bulk.fth 2010-01-15 02:48:23 UTC (rev 1675)
+++ dev/usb2/hcd/ehci/bulk.fth 2010-01-16 20:02:47 UTC (rev 1676)
@@ -207,19 +207,26 @@
r> swap attach-qtds ( )
;
-: make-ring ( /buf #bufs -- qh qtd )
- 2dup * alloc&map ( /buf #bufs va pa )
- dup 4 pick 4 pick alloc-ring-qhqtds ( /buf #bufs va pa qh qtd )
- >r >r ( /buf #bufs va pa r: qtd qh )
- r@ >qh-buf-pa l! r@ >qh-buf l! ( /buf #bufs )
- r@ >qh-#bufs l! r@ >qh-/buf l! ( r: qtd qh )
+: make-ring ( /buf #bufs in? -- qh qtd )
+ -rot ( in? /buf #bufs )
+ 2dup * alloc&map ( in? /buf #bufs va pa )
+ dup 4 pick 4 pick alloc-ring-qhqtds ( in? /buf #bufs va pa qh qtd )
+ >r >r ( in? /buf #bufs va pa r: qtd qh )
+ r@ >qh-buf-pa l! r@ >qh-buf l! ( in? /buf #bufs )
+ r@ >qh-#bufs l! r@ >qh-/buf l! ( in? r: qtd qh )
- \ Start bulk in transaction
- r@ pt-bulk fill-qh ( r: qtd qh )
+ r@ pt-bulk fill-qh ( in? r: qtd qh )
- \ Let the QH keep track of the data toggle
+ \ Let the QH keep track of the data toggle on an ongoing basis ...
r@ >hcqh-endp-char dup le-l@ QH_TD_TOGGLE invert and swap le-l!
+ \ But we have to initialize it here based on the last state
+ r@ >hcqh-overlay >hcqtd-token ( in? token-adr r: qtd qh )
+ dup le-l@ ( in? token-adr token-val r: qtd qh )
+ rot if bulk-in-data@ else bulk-out-data@ then ( token-adr token-val toggle r: qtd qh )
+ or ( token-adr token-val' r: qtd qh )
+ swap le-l! ( r: qtd qh )
+
r> r> ( qh qtd )
2dup link-ring ( qh qtd )
over insert-qh ( qh qtd )
@@ -282,7 +289,7 @@
dup to bulk-out-pipe ( /buf #bufs pipe )
set-bulk-vars ( /buf #bufs )
- make-ring ( qh qtd )
+ false make-ring ( qh qtd )
to bulk-out-qtd to bulk-out-qh ( )
bulk-out-timeout bulk-out-qh >qh-timeout l! ( )
;
@@ -294,7 +301,7 @@
dup to bulk-in-pipe ( /buf #bufs pipe )
set-bulk-vars ( /buf #bufs )
- make-ring ( qh qtd )
+ true make-ring ( qh qtd )
dup activate-in-ring ( qh qtd )
to bulk-in-qtd to bulk-in-qh ( )
bulk-in-timeout bulk-in-qh >qh-timeout l! ( )
@@ -359,8 +366,10 @@
dup >qtd-/buf l@ d# 16 << ( qtd token_word )
TD_STAT_ACTIVE or TD_C_ERR3 or TD_PID_IN or ( qtd token_word' )
- \ Maybe unnecessary based on using dt in QH
- bulk-in-data@ or toggle-bulk-in-data ( qtd token_word' )
+ \ We need not adjust the data toggle here, as the controller handles
+ \ it automatically while the queue is active. We set it initially
+ \ when creating the the queue head, and save it for later after
+ \ detaching the queue head.
over >hcqtd-token le-l! ( qtd )
more-qtds? while ( qtd )
Modified: dev/usb2/hcd/ehci/qhtd.fth
===================================================================
--- dev/usb2/hcd/ehci/qhtd.fth 2010-01-15 02:48:23 UTC (rev 1675)
+++ dev/usb2/hcd/ehci/qhtd.fth 2010-01-16 20:02:47 UTC (rev 1676)
@@ -244,7 +244,8 @@
\ operations, where ping transactions can help significantly.
\ (I'm not sure this matters, as the overlay will overwrite it).
- TD_TOGGLE_DATA1 TD_STAT_OUT or swap >hcqtd-token le-l! ( )
+ \ The data toggle will be set later
+ TD_STAT_OUT swap >hcqtd-token le-l! ( )
;
: link-qhqtds ( qtd.v qtd.p #qtds qh -- )