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.

Reply via email to