On Wed, 28 Mar 2007, David Brownell wrote:

> On Wednesday 28 March 2007 2:29 am, Pandita, Vikram wrote:
> > 
> > > (**) 8.5.1 in the USB 2.0 spec says that after a NYET handshake,
> > > "the host controller must return to using a PING token until the
> > > endpoint indicates it has space".
> > > 
> > > Clearly, the HDRC did not issue any PINGs ... it just went right
> > > to the status handshake.  Fishy, and quite possibly something
> > 
> > The PING flow-control is only for the OUT tokens.
> > So Host should send PING only if next OUT token is to be sent.
> 
> That "must" language is unambiguous:  PING "must" be sent.
> There is no "should" in that paragraph of the spec.
> 
> Read it this way:  the host must send PING until it reports
> that the next data token may be sent to that endpoint.  The
> fact that it will be a zero length packet is irrelevant, as
> is the fact that this is a control endpoint (the data stage
> works like normal BULK data, where that can't happen) so it
> will be an IN token; in either case, the FIFO may still not
> be ready.

That's not right.  Here's what the spec says (section 8.5.1):

        High-speed devices must support an improved NAK mechanism for Bulk
        OUT and Control endpoints and transactions.  Control endpoints
        must support this protocol for an OUT transaction in the data and
        status stages.

The PING protocol is not supported for IN transactions in control 
transfers -- i.e., not for the status stage of an OUT transfer.  You could 
probably deduce this from Figure 8-27, but I have never been able to 
figure out those baroque state transition diagrams.

> > The IN token has no restriction and the device should NAK the IN token
> > till it can process the next IN token. 
> > So the HDRC flow looks ok. Do you agree?
> 
> Clearly not.  This is another case where Mentor hasn't paid
> very close attention to the relevant specs.  Although in
> this case the workaround should be simple ... it's not like
> the bizarre way their OTG state machine works!

I disagree; the trace shows that the MUSBHDRC behaved correctly.  The 
question is why did the net2280 send back the STALL?

> > > the net2280 interpreted as "wrong" (ergo the STALL).  I'd guess
> > > the RTL from Mentor is triggering the "tx data was ACKed" IRQ
> > > too early ... treating the NYET as an ACK.

NYET _is_ supposed to be treated much like an ACK when it is received in
response to an OUT data packet.  That is, it indicates that the data was
received correctly, but the endpoint is not ready to accept another OUT
transaction.

> > > An experiment you could try:  before starting the status stage
> > > of an ep0 OUT transfer, stick a udelay(50) or somesuch.  Then
> > > compare what the HDRC is doing.  With luck, the net2280 only
> > > cares about that illegal state in a small window, and the udelay
> > > will get past it...
> > > 
> > > - Dave
> > 
> > When I enable all the logging in the code on Host side (which is lot of
> > unnecessary logs) I see that the test case passes.
> 
> Then I consider the experiment made, the hypothesis proven.  What
> remains is turning it into a workaround on the HDRC side.

The workaround belongs on the net2280 side, since that's where the error
occurs.  It could be that there is a mistake in the parenthesization of
one tricky statement.  (I blush to admit that I was the last person to
change that particular line of code.)  Vikram, does this untested patch
improve your situation?

Alan Stern



Index: usb-2.6/drivers/usb/gadget/net2280.c
===================================================================
--- usb-2.6.orig/drivers/usb/gadget/net2280.c
+++ usb-2.6/drivers/usb/gadget/net2280.c
@@ -2200,16 +2200,16 @@ static void handle_ep_small (struct net2
                                }
                                mode = 2;
                        /* an extra OUT token is an error */
-                       } else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
-                                       && req
-                                       && req->req.actual == req->req.length)
-                                       || (ep->responded && !req)) {
-                               ep->dev->protocol_stall = 1;
-                               set_halt (ep);
-                               ep->stopped = 1;
-                               if (req)
-                                       done (ep, req, -EOVERFLOW);
-                               req = NULL;
+                       } else if (t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) {
+                               if ((req && req->req.actual == req->req.length)
+                                               || (!req && ep->responded)) {
+                                       ep->dev->protocol_stall = 1;
+                                       set_halt(ep);
+                                       ep->stopped = 1;
+                                       if (req)
+                                               done(ep, req, -EOVERFLOW);
+                                       req = NULL;
+                               }
                        }
                }
        }


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to