In ehci_check_qh_intr don't treat a short control transfer as done if the
status phase is still inflight. Let the hardware complete it. PR/48358: Repeated low-speed USB control transfers returning short data fail on EHCI PR/46696: uhub disables port where USB keyboard attached
This commit is contained in:
parent
144626538e
commit
04f7636d4c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ehci.c,v 1.220 2013/12/01 07:28:47 skrll Exp $ */
|
||||
/* $NetBSD: ehci.c,v 1.221 2013/12/01 07:34:16 skrll Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004-2012 The NetBSD Foundation, Inc.
|
||||
|
@ -53,7 +53,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.220 2013/12/01 07:28:47 skrll Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.221 2013/12/01 07:34:16 skrll Exp $");
|
||||
|
||||
#include "ohci.h"
|
||||
#include "uhci.h"
|
||||
|
@ -839,9 +839,26 @@ ehci_check_qh_intr(ehci_softc_t *sc, struct ehci_xfer *ex)
|
|||
/* Any kind of error makes the xfer done. */
|
||||
if (status & EHCI_QTD_HALTED)
|
||||
goto done;
|
||||
/* We want short packets, and it is short: it's done */
|
||||
if (EHCI_QTD_GET_BYTES(status) != 0)
|
||||
/* Handle short packets */
|
||||
if (EHCI_QTD_GET_BYTES(status) != 0) {
|
||||
usbd_pipe_handle pipe = ex->xfer.pipe;
|
||||
usb_endpoint_descriptor_t *ed =
|
||||
pipe->endpoint->edesc;
|
||||
uint8_t xt = UE_GET_XFERTYPE(ed->bmAttributes);
|
||||
|
||||
/*
|
||||
* If we get here for a control transfer then
|
||||
* we need to let the hardware complete the
|
||||
* status phase. That is, we're not done
|
||||
* quite yet.
|
||||
*
|
||||
* Otherwise, we're done.
|
||||
*/
|
||||
if (xt == UE_CONTROL) {
|
||||
break;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
DPRINTFN(12, ("ehci_check_intr: ex=%p std=%p still active\n",
|
||||
ex, ex->sqtdstart));
|
||||
|
|
Loading…
Reference in New Issue