If USB transfers aren't completed in order, the stack cannot recover.

So don't try to continue when this happen and make it clear what the
problem is.  Currently the kernel panic in many different ways or
worse enters an infinite loop sometimes after that happened.

ok?

Index: usbdi.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdi.c,v
retrieving revision 1.97
diff -u -p -r1.97 usbdi.c
--- usbdi.c     3 Feb 2018 13:37:37 -0000       1.97
+++ usbdi.c     28 Apr 2018 08:18:18 -0000
@@ -769,13 +769,11 @@ usb_transfer_complete(struct usbd_xfer *
 
        if (!pipe->repeat) {
                /* Remove request from queue. */
+               KASSERT(xfer == SIMPLEQ_FIRST(&pipe->queue));
+               SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
 #ifdef DIAGNOSTIC
-               if (xfer != SIMPLEQ_FIRST(&pipe->queue))
-                       printf("usb_transfer_complete: bad dequeue %p != %p\n",
-                           xfer, SIMPLEQ_FIRST(&pipe->queue));
                xfer->busy_free = XFER_FREE;
 #endif
-               SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
        }
        DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n",
            pipe->repeat, SIMPLEQ_FIRST(&pipe->queue)));

Reply via email to