On Fri, Oct 30, 2015 at 11:15:05AM -0400, Alan Stern wrote: > On Fri, 30 Oct 2015, Peter Chen wrote: > > > After reading spec at 4.8.2: > > > > Software must not remove an active queue head from the schedule. > > Software should first deactivate all active qTDs, wait for the > > queue head to go inactive, then remove the queue head from the > > asynchronous list. > > > > But current software removes an active queue head first, then > > deactivates qTDs for the unlinked queue head. What's possible > > harm if we deactivates qTDs first, then unlink the queue head > > directly without waiting. > > Right, that's the relevant part of the spec. > > > > [In practice it's not feasible to wait for an active QH to become > > > inactive before removing it, for several reasons. For one, the QH may > > > _never_ become inactive (if the endpoint NAKs indefinitely). > > > > Yes, > > > > > For > > > another, the procedure given in the spec (deactivate the qTDs on the > > > queue) is racy, since the controller can perform a new overlay or > > > writeback at any time.] > > > > > > > But that queue head will be unlinked soon, software (or controller) will > > not use a new overlay or a new writeback, isn't it? > > You don't know that. Until the controller sees that the QH has been > unlinked, it can do a new overlay or writeback at any time. Don't > forget that the controller keeps an on-chip cached copy of the QH. So > we could have a race like this: > > Initially the QH is marked active, both in RAM and in the > controller's cache. The next qTD in the queue is marked > active. > > The driver sees that the QH in RAM is active. It decides to > follow the recommendation in the spec. > > But before the driver can do anything, the controller finishes > the current transfer. It marks the QH inactive in its cache > and writes the cached QH back to RAM. > > Next, the controller seeing that the QH is inactive, reads the > next qTD into its cache and performs an overlay. This marks > the cached version of the QH as active again. > > The driver marks the qTDs inactive and waits for the QH to become > inactive. Since the QH in RAM is already marked inactive, the > driver doesn't have to wait long. It removes the QH from the > async list. > > The controller writes the cached QH back to RAM, so now the QH > in RAM is active again. But it has already been removed from > the list! > > Other races of the same general sort are also possible. > Hi Alan, After a discussion with IC engineer, a brief idea like below: - Delete the QH from the asynclist directly, Issue the first IAA routine, this is we do now. - During the first IAA interrupt, judge if asynclistaddr is next address of the QH we want to remove, if it does not, issue the second IAA routine, else, we consider the controller will not process the removed QH any more, so it is safe to remove. - If the controller still handles the QH previous than the one we want to remove , issue IAA again. -- Best Regards, Peter Chen -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html