Module Name: src Committed By: skrll Date: Mon Jan 11 22:24:58 UTC 2016
Modified Files: src/sys/dev/usb [nick-nhusb]: ehci.c Log Message: Fix active control transfer aborts - need to run through the entire TD chain from start to finish and not just on any data phase. To generate a diff of this commit: cvs rdiff -u -r1.234.2.78 -r1.234.2.79 src/sys/dev/usb/ehci.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/ehci.c diff -u src/sys/dev/usb/ehci.c:1.234.2.78 src/sys/dev/usb/ehci.c:1.234.2.79 --- src/sys/dev/usb/ehci.c:1.234.2.78 Sun Jan 10 16:06:07 2016 +++ src/sys/dev/usb/ehci.c Mon Jan 11 22:24:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.234.2.78 2016/01/10 16:06:07 skrll Exp $ */ +/* $NetBSD: ehci.c,v 1.234.2.79 2016/01/11 22:24:58 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.234.2.78 2016/01/10 16:06:07 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.79 2016/01/11 22:24:58 skrll Exp $"); #include "ohci.h" #include "uhci.h" @@ -3215,7 +3215,7 @@ ehci_abort_xfer(struct usbd_xfer *xfer, struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); ehci_softc_t *sc = EHCI_XFER2SC(xfer); ehci_soft_qh_t *sqh = epipe->sqh; - ehci_soft_qtd_t *sqtd; + ehci_soft_qtd_t *sqtd, *fsqtd, *lsqtd; ehci_physaddr_t cur; uint32_t qhstatus; int hit; @@ -3273,7 +3273,15 @@ ehci_abort_xfer(struct usbd_xfer *xfer, sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status), sizeof(sqh->qh.qh_qtd.qtd_status), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - for (sqtd = exfer->ex_sqtdstart; ; sqtd = sqtd->nextqtd) { + + if (exfer->ex_type == EX_CTRL) { + fsqtd = exfer->ex_setup; + lsqtd = exfer->ex_status; + } else { + fsqtd = exfer->ex_sqtdstart; + lsqtd = exfer->ex_sqtdend; + } + for (sqtd = fsqtd; sqtd != lsqtd; sqtd = sqtd->nextqtd) { usb_syncmem(&sqtd->dma, sqtd->offs + offsetof(ehci_qtd_t, qtd_status), sizeof(sqtd->qtd.qtd_status), @@ -3283,8 +3291,6 @@ ehci_abort_xfer(struct usbd_xfer *xfer, sqtd->offs + offsetof(ehci_qtd_t, qtd_status), sizeof(sqtd->qtd.qtd_status), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - if (sqtd == exfer->ex_sqtdend) - break; } /* @@ -3311,10 +3317,8 @@ ehci_abort_xfer(struct usbd_xfer *xfer, BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); cur = EHCI_LINK_ADDR(le32toh(sqh->qh.qh_curqtd)); hit = 0; - for (sqtd = exfer->ex_sqtdstart; ; sqtd = sqtd->nextqtd) { + for (sqtd = fsqtd; sqtd != lsqtd; sqtd = sqtd->nextqtd) { hit |= cur == sqtd->physaddr; - if (sqtd == exfer->ex_sqtdend) - break; } sqtd = sqtd->nextqtd; /* Zap curqtd register if hardware pointed inside the xfer. */