K 10 svn:author V 7 iedowse K 8 svn:date V 27 2004-11-09T20:51:32.000000Z K 7 svn:log V 1523 Attempt to fix a number of race conditions in the handling of transfer timeouts that typically cause a transfer to be completed twice, resulting in panics and page faults: o A transfer completion interrupt could arrive while an abort_task event was set up, so the transfer would be aborted after it had completed. This is very easy to reproduce. Fix this by setting the transfer status to USBD_TIMEOUT before scheduling the abort_task so that the transfer completion code will ignore it. o The transfer completion code could execute concurrently with the timeout callout, leaving the callout blocked (e.g. waiting for Giant) while the transfer completion code runs. In this case, callout_stop() does not prevent the callout from running, so again the timeout code would run after the transfer was complete. Handle this case by checking the return value from callout_stop(), and ignoring the transfer if the callout could not be removed. o Finally, protect against a timeout callout occurring while a transfer is being aborted by another process. Here we arrange for the timeout processing to ignore the transfer, and use callout_drain() to ensure that the callout has really gone before completing the transfer. This was tested by repeatedly performing USB transfers with a timeout set to approximately the same as the normal transfer completion time. In the PR below, apparently this occurred by accident with a particular printer and the default timeout. PR: kern/71491 END