Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-6-1]: src/sys/dev/usb Pull up following revision(s) (requested by...



details:   https://anonhg.NetBSD.org/src/rev/824256f6fa44
branches:  netbsd-6-1
changeset: 775864:824256f6fa44
user:      riz <riz%NetBSD.org@localhost>
date:      Thu Sep 26 01:57:22 2013 +0000

description:
Pull up following revision(s) (requested by skrll in ticket #950):
        sys/dev/usb/uhci.c: revision 1.255
        sys/dev/usb/uhci.c: revision 1.256
        sys/dev/usb/ehci.c: revision 1.205
        sys/dev/usb/uhci.c: revision 1.258
Add missed byteswap ops for BE machines in block added in rev 1.223.
Call usb_syncmem() against descriptors more strictly.
(not sure if the previous ones were fatal though)
Deal with control transfers better by
        - removing the UHCI_PTR_VF flag for the setup and status stages
          which means they are scheduled less aggressively.  Some devices
          appear to require this (blymn@ has one).  The flag was
          introduced as a performance improvement for bulk transfers.
        - Checking for short reads and making sure the status stage runs
          if they're encountered.
PR/47522 Enumeration of LUFA/Atmel devices on UHCI fails
Thanks to jak@ and blymn@ for testing and mlelstv@ for comments.

diffstat:

 sys/dev/usb/ehci.c |   13 ++--
 sys/dev/usb/uhci.c |  147 +++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 105 insertions(+), 55 deletions(-)

diffs (272 lines):

diff -r 8b6db4bbe4f7 -r 824256f6fa44 sys/dev/usb/ehci.c
--- a/sys/dev/usb/ehci.c        Mon Sep 23 14:28:03 2013 +0000
+++ b/sys/dev/usb/ehci.c        Thu Sep 26 01:57:22 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ehci.c,v 1.183 2011/12/23 00:51:43 jakllsch Exp $ */
+/*     $NetBSD: ehci.c,v 1.183.8.1 2013/09/26 01:57:22 riz Exp $ */
 
 /*
  * Copyright (c) 2004-2008 The NetBSD Foundation, Inc.
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.183 2011/12/23 00:51:43 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.183.8.1 2013/09/26 01:57:22 riz Exp $");
 
 #include "ohci.h"
 #include "uhci.h"
@@ -763,7 +763,11 @@
            lsqtd->offs + offsetof(ehci_qtd_t, qtd_status),
            sizeof(lsqtd->qtd.qtd_status),
            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-       if (le32toh(lsqtd->qtd.qtd_status) & EHCI_QTD_ACTIVE) {
+       status = le32toh(lsqtd->qtd.qtd_status);
+       usb_syncmem(&lsqtd->dma,
+           lsqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+           sizeof(lsqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD);
+       if (status & EHCI_QTD_ACTIVE) {
                DPRINTFN(12, ("ehci_check_intr: active ex=%p\n", ex));
                for (sqtd = ex->sqtdstart; sqtd != lsqtd; sqtd=sqtd->nextqtd) {
                        usb_syncmem(&sqtd->dma,
@@ -786,9 +790,6 @@
                }
                DPRINTFN(12, ("ehci_check_intr: ex=%p std=%p still active\n",
                              ex, ex->sqtdstart));
-               usb_syncmem(&lsqtd->dma,
-                   lsqtd->offs + offsetof(ehci_qtd_t, qtd_status),
-                   sizeof(lsqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD);
                return;
        }
  done:
diff -r 8b6db4bbe4f7 -r 824256f6fa44 sys/dev/usb/uhci.c
--- a/sys/dev/usb/uhci.c        Mon Sep 23 14:28:03 2013 +0000
+++ b/sys/dev/usb/uhci.c        Thu Sep 26 01:57:22 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uhci.c,v 1.242 2011/12/23 00:51:46 jakllsch Exp $      */
+/*     $NetBSD: uhci.c,v 1.242.8.1 2013/09/26 01:57:22 riz Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $       */
 
 /*
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.242 2011/12/23 00:51:46 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.242.8.1 2013/09/26 01:57:22 riz Exp $");
 
 #include "opt_usb.h"
 
@@ -1102,6 +1102,7 @@
 uhci_remove_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh)
 {
        uhci_soft_qh_t *pqh;
+       uint32_t elink;
 
        SPLUSBCHECK;
 
@@ -1125,7 +1126,10 @@
        usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
            sizeof(sqh->qh.qh_elink),
            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-       if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
+       elink = le32toh(sqh->qh.qh_elink);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink), BUS_DMASYNC_PREREAD);
+       if (!(elink & UHCI_PTR_T)) {
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
                usb_syncmem(&sqh->dma,
                    sqh->offs + offsetof(uhci_qh_t, qh_elink),
@@ -1175,6 +1179,7 @@
 uhci_remove_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh)
 {
        uhci_soft_qh_t *pqh;
+       uint32_t elink;
 
        SPLUSBCHECK;
 
@@ -1183,7 +1188,10 @@
        usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
            sizeof(sqh->qh.qh_elink),
            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-       if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
+       elink = le32toh(sqh->qh.qh_elink);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink), BUS_DMASYNC_PREREAD);
+       if (!(elink & UHCI_PTR_T)) {
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
                usb_syncmem(&sqh->dma,
                    sqh->offs + offsetof(uhci_qh_t, qh_elink),
@@ -1421,54 +1429,89 @@
                return;
        }
 #endif
+       usb_syncmem(&lstd->dma,
+           lstd->offs + offsetof(uhci_td_t, td_status),
+           sizeof(lstd->td.td_status),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+       status = le32toh(lstd->td.td_status);
+       usb_syncmem(&lstd->dma,
+           lstd->offs + offsetof(uhci_td_t, td_status),
+           sizeof(lstd->td.td_status),
+           BUS_DMASYNC_PREREAD);
+
+       /* If the last TD is not marked active we can complete */
+       if (!(status & UHCI_TD_ACTIVE)) {
+ done:
+               DPRINTFN(12, ("uhci_check_intr: ii=%p done\n", ii));
+               callout_stop(&ii->xfer->timeout_handle);
+               uhci_idone(ii);
+               return;
+       }
+
        /*
         * If the last TD is still active we need to check whether there
         * is an error somewhere in the middle, or whether there was a
         * short packet (SPD and not ACTIVE).
         */
-       usb_syncmem(&lstd->dma,
-           lstd->offs + offsetof(uhci_td_t, td_status),
-           sizeof(lstd->td.td_status),
-           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-       if (le32toh(lstd->td.td_status) & UHCI_TD_ACTIVE) {
-               DPRINTFN(12, ("uhci_check_intr: active ii=%p\n", ii));
-               for (std = ii->stdstart; std != lstd; std = std->link.std) {
-                       usb_syncmem(&std->dma,
-                           std->offs + offsetof(uhci_td_t, td_status),
-                           sizeof(std->td.td_status),
-                           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-                       status = le32toh(std->td.td_status);
-                       usb_syncmem(&std->dma,
-                           std->offs + offsetof(uhci_td_t, td_status),
-                           sizeof(std->td.td_status), BUS_DMASYNC_PREREAD);
-                       /* If there's an active TD the xfer isn't done. */
-                       if (status & UHCI_TD_ACTIVE)
-                               break;
-                       /* Any kind of error makes the xfer done. */
-                       if (status & UHCI_TD_STALLED)
-                               goto done;
-                       /* We want short packets, and it is short: it's done */
-                       usb_syncmem(&std->dma,
-                           std->offs + offsetof(uhci_td_t, td_token),
-                           sizeof(std->td.td_token),
-                           BUS_DMASYNC_POSTWRITE);
-                       if ((status & UHCI_TD_SPD) &&
-                             UHCI_TD_GET_ACTLEN(status) <
-                             UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token)))
-                               goto done;
+       DPRINTFN(12, ("uhci_check_intr: active ii=%p\n", ii));
+       for (std = ii->stdstart; std != lstd; std = std->link.std) {
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+               status = le32toh(std->td.td_status);
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status), BUS_DMASYNC_PREREAD);
+
+               /* If there's an active TD the xfer isn't done. */
+               if (status & UHCI_TD_ACTIVE) {
+                       DPRINTFN(12, ("%s: ii=%p std=%p still active\n",
+                           __func__, ii, std));
+                       return;
                }
-               DPRINTFN(12, ("uhci_check_intr: ii=%p std=%p still active\n",
-                             ii, ii->stdstart));
-               usb_syncmem(&lstd->dma,
-                   lstd->offs + offsetof(uhci_td_t, td_status),
-                   sizeof(lstd->td.td_status),
-                   BUS_DMASYNC_PREREAD);
-               return;
+
+               /* Any kind of error makes the xfer done. */
+               if (status & UHCI_TD_STALLED)
+                       goto done;
+
+               /*
+                * If the data phase of a control transfer is short, we need
+                * to complete the status stage
+                */
+               usbd_xfer_handle xfer = ii->xfer;
+               usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc;
+               uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes);
+
+               if ((status & UHCI_TD_SPD) && xfertype == UE_CONTROL) {
+                       struct uhci_pipe *upipe =
+                           (struct uhci_pipe *)xfer->pipe;
+                       uhci_soft_qh_t *sqh = upipe->u.ctl.sqh;
+                       uhci_soft_td_t *stat = upipe->u.ctl.stat;
+
+                       DPRINTFN(12, ("%s: ii=%p std=%p control status"
+                           "phase needs completion\n", __func__, ii,
+                           ii->stdstart));
+
+                       sqh->qh.qh_elink =
+                           htole32(stat->physaddr | UHCI_PTR_TD);
+                       usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+                           BUS_DMASYNC_PREWRITE);
+                       break;
+               }
+
+               /* We want short packets, and it is short: it's done */
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_token),
+                   sizeof(std->td.td_token),
+                   BUS_DMASYNC_POSTWRITE);
+
+               if ((status & UHCI_TD_SPD) &&
+                       UHCI_TD_GET_ACTLEN(status) <
+                       UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token))) {
+                       goto done;
+               }
        }
- done:
-       DPRINTFN(12, ("uhci_check_intr: ii=%p done\n", ii));
-       callout_stop(&ii->xfer->timeout_handle);
-       uhci_idone(ii);
 }
 
 /* Called at splusb() */
@@ -1830,6 +1873,7 @@
                    uhci_soft_td_t *stdend)
 {
        uhci_soft_td_t *p;
+       uint32_t td_link;
 
        /*
         * to avoid race condition with the controller which may be looking
@@ -1841,8 +1885,13 @@
                    p->offs + offsetof(uhci_td_t, td_link),
                    sizeof(p->td.td_link),
                    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-               if ((p->td.td_link & UHCI_PTR_T) == 0) {
-                       p->td.td_link = UHCI_PTR_T;
+               td_link = le32toh(p->td.td_link);
+               usb_syncmem(&p->dma,
+                   p->offs + offsetof(uhci_td_t, td_link),
+                   sizeof(p->td.td_link),
+                   BUS_DMASYNC_PREREAD);
+               if ((td_link & UHCI_PTR_T) == 0) {
+                       p->td.td_link = htole32(UHCI_PTR_T);
                        usb_syncmem(&p->dma,
                            p->offs + offsetof(uhci_td_t, td_link),
                            sizeof(p->td.td_link),
@@ -2420,7 +2469,7 @@
                        return (err);
                next = data;
                dataend->link.std = stat;
-               dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_VF | UHCI_PTR_TD);
+               dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_TD);
                usb_syncmem(&dataend->dma,
                    dataend->offs + offsetof(uhci_td_t, td_link),
                    sizeof(dataend->td.td_link),
@@ -2434,7 +2483,7 @@
        usb_syncmem(&upipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREWRITE);
 
        setup->link.std = next;
-       setup->td.td_link = htole32(next->physaddr | UHCI_PTR_VF | UHCI_PTR_TD);
+       setup->td.td_link = htole32(next->physaddr | UHCI_PTR_TD);
        setup->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls |
                UHCI_TD_ACTIVE);
        setup->td.td_token = htole32(UHCI_TD_SETUP(sizeof *req, endpt, addr));



Home | Main Index | Thread Index | Old Index