Re: Lost IAA and EHCI reclaim problems

Alan Stern <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
On Sun, 19 Aug 2007, David Brownell wrote:

> On Sunday 19 August 2007, Alan Stern wrote:
> > Dave:
> > 
> > I just read through your old iaa_watchdog patch, and there are several 
> > things about it (maybe about the pre-patch code too) that seem strange.
> > 
> > Management of the reclaim list is wrong.  Every qh that was added 
> > before the IAA doorbell bit was set should get unlinked when 
> > end_unlink_async() runs, whereas qhs added after the IAAD bit should 
> > cause another IAA cycle.  However end_unlink_async() never changes
> > more than one qh's state to QH_STATE_IDLE.
> 
> The pessimistic assumption is that only one QH will be removed per
> doorbell.  I don't see how that would be "wrong"...

I see.  You've got this funny QH_STATE_UNLINK_WAIT, meaning that
someone wants to unlink the qh but the IAAD is already in use.  From
there qhs go one at a time into QH_STATE_UNLINK.  Not how I would have
done it, but okay.

BTW, what's the funny test for qh == ehci->async doing there in 
start_unlink_async()?  Why would you ever want to unlink the dummy qh 
pointed to by ehci->async?


> > The iaa_watchdog routine seems to assume that STS_IAA gets set properly
> > and the interrupt is never delivered.
> 
> That is, assumes that the hardware behaves correctly.

Apart from not delivering the interrupt.  But it seems strange for a 
watchdog routine to assume that the hardware behaves correctly; after 
all, the whole point of that code is to recover from hardware bugs!

> > Isn't it likely that some controllers may fail to set STS_IAA at all?
> 
> I wouldn't think so; but of course if you *knew* of such a controller
> it wouldn't be likely ... it'd be a certainty!

The attachment in comment #12 of Bugzilla #8692 shows IAAD set, IAA 
clear, and lots of qhs in the reclaim list.  QED  :-)


> > Here's a somewhat unrelated question that came up earlier:  When an
> > async transfer stops because of an error the endpoint queue has to be
> > restarted, presumably by setting qh->hw_current to point to the first
> > qtd in the next URB.  But the driver never does this.  How does a
> > stopped queue get restarted?  Does it go through an unlink cycle first?
> 
> It's been a long time since I touched that code, so details are fuzzy...
> 
> But the basic notion is that there's only one routine scanning a QH and
> removing TDs from it -- qh_completions() is its name.  This ensures that
> there are no little races of the type ISTR the original OHCI code suffered
> from, with one routine fighting another.
> 
> A comment at the top of qh_completions() says that it leaves HALT (error)
> status set until the queue is completely scrubbed.  A QH that's halted like
> that, or else is in QH_STATE_IDLE, can safely be scanned and modified even
> after the hardware's view of the queue head.  Otherwise the TD queue only
> get modified by removing completed TDs (before the head) or by adding new
> ones (after the tail).
> 
> A QH that's getting that "scrub everything" treatment should always get
> reactivated using qh_refresh(), and thence qh_update().  And if it's
> in that mode, the qh_completions() loop doesn't stop when it gets to
> an active TD ... it keeps scanning to the end of the list, processing
> pending unlinks (in queue order, once).
> 
> Now, I seem to recall that there were two refresh modes.  One was where
> the QH overlay was partially completed ... e.g. TD at list head was
> for 8 packets, and 3 of them were processed already, but an URB after
> this one got unlinked.  In that case the important part is clearing the
> overlay bits that said "be a NOP for now".  The other mode was where
> that overlay was no longer valid, in which case it invalidates the
> overlay so that the next QTD is read.  Both require careful attention
> to the text in 4.10 regarding operation of queue heads.
> 
> Now, in the error case you asked about, the overlay became invalid.
> 
> So 4.10.2 needs to come into play ... it ignores hw_current when both
> ACTIVE and HALT bits are cleared.  That's ensured by qh_update(); at
> the very end it scrubs those bits.  Which makes the HC fetch from
> the qh->hw_next field, and then normally process that QTD and update
> the overlay.  Tadaa!

But exactly where is the relevant call to qh_refresh()?  There's a 
comment near the end of qh_completions() which says:

	/* restore original state; caller must unlink or relink */

If stopped != 0 and state == QH_STATE_LINKED, as they would be in this 
case, the code goes on to call unlink_async().  And there's nothing in 
scan_async() -- the caller -- to relink qh.

Doesn't this mean that qh really does end up going through an
unnecessary unlink cycle?

Alan Stern


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.