On 17/10/19(Thu) 18:53, Stefan Sperling wrote: > My USB scanner works again in 6.6 \o/ > Thanks to whoever fixed it. I have no idea when and how it happened but > since a few releases back it has always been failed with some I/O error. > But now it just works again as it once did (apart from a weird Xsane > bug where it scans only part of the page which I will ignore for now; > the 'scanimage' command scans as expected). > > So I scanned an image and tried to print it. > The default image format produced by scanimage is .pnm, and when I queued > several megabytes of pnm data with lpr my printer started printing page > after page of garbage. > So I turned the printer off and was surprised to see that doing so > made the whole machine hang hard. Nothing even on serial console. > > I can reliably reproduce this. With an XHCI_DEBUG kernel I see the > following messages scoll by very fast on the serial console: > > xhci_abort_xfer: already done > usbd_abort_pipe: pipe=0xffff800000e84000 xfer=0xfffffd811f8da1e0 > (methods=0xffffffff81efb9f8) > xhci_abort_xfer: xfer=0xfffffd811f8da1e0 status=NORMAL_COMPLETION > err=CANCELLED actlen=23 len=64 idx=-1 > xhci_abort_xfer: already done > usbd_abort_pipe: pipe=0xffff800000e84000 xfer=0xfffffd811f8da1e0 > (methods=0xffffffff81efb9f8) > xhci_abort_xfer: xfer=0xfffffd811f8da1e0 status=NORMAL_COMPLETION > err=CANCELLED actlen=23 len=64 idx=-1 > xhci_abort_xfer: already done > usbd_abort_pipe: pipe=0xffff800000e84000 xfer=0xfffffd811f8da1e0 > (methods=0xffffffff81efb9f8) > xhci_abort_xfer: xfer=0xfffffd811f8da1e0 status=NORMAL_COMPLETION > err=CANCELLED actlen=23 len=64 idx=-1 > xhci_abort_xfer: already done > usbd_abort_pipe: pipe=0xffff800000e84000 xfer=0xfffffd811f8da1e0 > (methods=0xffffffff81efb9f8) > xhci_abort_xfer: xfer=0xfffffd811f8da1e0 status=NORMAL_COMPLETION > err=CANCELLED actlen=23 len=64 idx=-1 > xhci_abort_xfer: already done > > Here is the loop we are in at that point, in usbdi.c's usbd_abort_pipe: > > while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) { > DPRINTFN(2,("%s: pipe=%p xfer=%p (methods=%p)\n", __func__, > pipe, xfer, pipe->methods)); > /* Make the HC abort it (and invoke the callback). */ > pipe->methods->abort(xfer); > /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ > } > > > Note how this will keep looping forever if the xfer is never taken off > the queue. I don't understand internal USB stack interface contracts > (does anyone, really?) but assuming that the abort method is always > expected to dequeue the transfer by calling the usb_transfer_complete() > function, then the following patch allows this loop to exit when I turn > off my printer while it is printing.
The question here is how an `xfer' with a status of NORMAL_COMPLETION can be found in the pipe's queue? The operations are like - *hci driver is notified that a USB transfer is finish - dequeue it and set `xter->status' to USBD_NORMAL_COMPLETION - call usb_transfer_complete() that should dequeue the `xfer' from the pipe. The fact that the whole USB stack use the USBD_* status value as return code makes it complicated to understand 8) But that's the question we should answer.