Source-Changes-HG archive

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

[src/trunk]: src/sys/dev Three fixes



details:   https://anonhg.NetBSD.org/src/rev/dc5a83ded578
branches:  trunk
changeset: 1029139:dc5a83ded578
user:      skrll <skrll%NetBSD.org@localhost>
date:      Wed Dec 22 21:45:02 2021 +0000

description:
Three fixes

- pass the 64bit DMA tag if the HCCPARAMS says ehci supports it and the
  64bit DMA tag is available/valid.  This should help with the
  "cannot create xfer" error on 64bit systems.

- restrict the control structure memory allocation to the low 4GB
  (CTRLDSSEGMENT was always set to zero anyway)

- if ehci_init fails then tidyup before returning the error.

diffstat:

 sys/dev/acpi/ehci_acpi.c |  27 ++++++++++++---
 sys/dev/pci/ehci_pci.c   |  21 ++++++++++-
 sys/dev/usb/ehci.c       |  79 +++++++++++++++++++++++++++++++++++++----------
 sys/dev/usb/ehcivar.h    |   3 +-
 4 files changed, 102 insertions(+), 28 deletions(-)

diffs (truncated from 317 to 300 lines):

diff -r 46e9eff0a166 -r dc5a83ded578 sys/dev/acpi/ehci_acpi.c
--- a/sys/dev/acpi/ehci_acpi.c  Wed Dec 22 21:36:40 2021 +0000
+++ b/sys/dev/acpi/ehci_acpi.c  Wed Dec 22 21:45:02 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ehci_acpi.c,v 1.7 2021/08/07 16:19:09 thorpej Exp $ */
+/* $NetBSD: ehci_acpi.c,v 1.8 2021/12/22 21:45:02 skrll Exp $ */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci_acpi.c,v 1.7 2021/08/07 16:19:09 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci_acpi.c,v 1.8 2021/12/22 21:45:02 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -98,7 +98,6 @@
 
        sc->sc_dev = self;
        sc->sc_bus.ub_hcpriv = sc;
-       sc->sc_bus.ub_dmatag = aa->aa_dmat;
        sc->sc_bus.ub_revision = USBREV_2_0;
        sc->sc_flags = EHCIF_ETTF;
        sc->sc_vendor_init = ehci_acpi_init;
@@ -125,25 +124,41 @@
        error = bus_space_map(sc->iot, mem->ar_base, mem->ar_length, 0, &sc->ioh);
        if (error) {
                aprint_error_dev(self, "couldn't map registers\n");
-               return;
+               goto done;
        }
 
        /* Disable interrupts */
        sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
        EOWRITE4(sc, EHCI_USBINTR, 0);
 
+       const uint32_t hccparams = EREAD4(sc, EHCI_HCCPARAMS);
+       if (EHCI_HCC_64BIT(hccparams)) {
+               aprint_verbose_dev(self, "64-bit DMA");
+               if (BUS_DMA_TAG_VALID(aa->aa_dmat64)) {
+                       aprint_verbose("\n");
+                       sc->sc_bus.ub_dmatag = aa->aa_dmat64;
+               } else {
+                       aprint_verbose(" - limited\n");
+                       sc->sc_bus.ub_dmatag = aa->aa_dmat;
+               }
+       } else {
+               aprint_verbose_dev(self, "32-bit DMA\n");
+               sc->sc_bus.ub_dmatag = aa->aa_dmat;
+       }
+
        ih = acpi_intr_establish(self,
            (uint64_t)(uintptr_t)aa->aa_node->ad_handle,
            IPL_USB, true, ehci_intr, sc, device_xname(self));
        if (ih == NULL) {
                aprint_error_dev(self, "couldn't establish interrupt\n");
-               return;
+               goto done;
        }
 
        error = ehci_init(sc);
        if (error) {
                aprint_error_dev(self, "init failed, error = %d\n", error);
-               return;
+               acpi_intr_disestablish(ih);
+               goto done;
        }
 
        sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint, CFARGS_NONE);
diff -r 46e9eff0a166 -r dc5a83ded578 sys/dev/pci/ehci_pci.c
--- a/sys/dev/pci/ehci_pci.c    Wed Dec 22 21:36:40 2021 +0000
+++ b/sys/dev/pci/ehci_pci.c    Wed Dec 22 21:45:02 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ehci_pci.c,v 1.72 2021/08/07 16:19:14 thorpej Exp $    */
+/*     $NetBSD: ehci_pci.c,v 1.73 2021/12/22 21:45:02 skrll Exp $      */
 
 /*
  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.72 2021/08/07 16:19:14 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.73 2021/12/22 21:45:02 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -144,7 +144,22 @@
 
        sc->sc_pc = pc;
        sc->sc_tag = tag;
-       sc->sc.sc_bus.ub_dmatag = pa->pa_dmat;
+
+       const uint32_t hccparams = EREAD4(&sc->sc, EHCI_HCCPARAMS);
+
+       if (EHCI_HCC_64BIT(hccparams)) {
+               aprint_verbose_dev(self, "64-bit DMA");
+               if (pci_dma64_available(pa)) {
+                       sc->sc.sc_bus.ub_dmatag = pa->pa_dmat64;
+                       aprint_verbose("\n");
+               } else {
+                       aprint_verbose(" - limited\n");
+                       sc->sc.sc_bus.ub_dmatag = pa->pa_dmat;
+               }
+       } else {
+               aprint_verbose_dev(self, "32-bit DMA\n");
+               sc->sc.sc_bus.ub_dmatag = pa->pa_dmat;
+       }
 
        /* Disable interrupts, so we don't get any spurious ones. */
        sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
diff -r 46e9eff0a166 -r dc5a83ded578 sys/dev/usb/ehci.c
--- a/sys/dev/usb/ehci.c        Wed Dec 22 21:36:40 2021 +0000
+++ b/sys/dev/usb/ehci.c        Wed Dec 22 21:45:02 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ehci.c,v 1.296 2021/12/22 21:36:40 skrll Exp $ */
+/*     $NetBSD: ehci.c,v 1.297 2021/12/22 21:45:02 skrll Exp $ */
 
 /*
  * Copyright (c) 2004-2012,2016,2020 The NetBSD Foundation, Inc.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.296 2021/12/22 21:36:40 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.297 2021/12/22 21:45:02 skrll Exp $");
 
 #include "ohci.h"
 #include "uhci.h"
@@ -489,6 +489,25 @@
        sc->sc_bus.ub_usedma = true;
        sc->sc_bus.ub_dmaflags = USBMALLOC_MULTISEG;
 
+       /*
+        * The bus attachment code will possibly provide a 64bit DMA
+        * tag which we now limit to the bottom 4G range as
+        *
+        * - that's as much as ehci can address in its QH, TD, iTD, and siTD
+        *   structures; and
+        * - the driver doesn't currently set EHCI_CTRLDSSEGMENT to anything
+        *   other than 0.
+        */
+       bus_dma_tag_t ntag;
+       sc->sc_dmatag = sc->sc_bus.ub_dmatag;
+       err = bus_dmatag_subregion(sc->sc_bus.ub_dmatag, 0, UINT32_MAX,
+           &ntag, 0);
+       if (err == 0) {
+               sc->sc_dmatag = ntag;
+               aprint_normal_dev(sc->sc_dev, "Using DMA subregion for control"
+                   " data structures\n");
+       }
+
        /* Reset the controller */
        DPRINTF("resetting", 0, 0, 0, 0);
        EOWRITE4(sc, EHCI_USBCMD, 0);   /* Halt controller */
@@ -501,8 +520,9 @@
                        break;
        }
        if (hcr) {
-               aprint_error("%s: reset timeout\n", device_xname(sc->sc_dev));
-               return EIO;
+               aprint_error_dev(sc->sc_dev, "reset timeout\n");
+               err = EIO;
+               goto fail1;
        }
        if (sc->sc_vendor_init)
                sc->sc_vendor_init(sc);
@@ -515,13 +535,17 @@
        case 0: sc->sc_flsize = 1024; break;
        case 1: sc->sc_flsize = 512; break;
        case 2: sc->sc_flsize = 256; break;
-       case 3: return EIO;
+       case 3:
+               err = EIO;
+               goto fail1;
        }
        err = usb_allocmem(sc->sc_bus.ub_dmatag,
            sc->sc_flsize * sizeof(ehci_link_t),
            EHCI_FLALIGN_ALIGN, USBMALLOC_COHERENT, &sc->sc_fldma);
-       if (err)
-               return err;
+       if (err) {
+               aprint_error_dev(sc->sc_dev, "failed to allocate frame list\n");
+               goto fail1;
+       }
        DPRINTF("flsize=%jd", sc->sc_flsize, 0, 0, 0);
        sc->sc_flist = KERNADDR(&sc->sc_fldma, 0);
 
@@ -529,7 +553,10 @@
                sc->sc_flist[i] = EHCI_NULL;
        }
 
-       EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0));
+       KASSERT(BUS_ADDR_HI32(DMAADDR(&sc->sc_fldma, 0)) == 0);
+       uint32_t lo32 = BUS_ADDR_LO32(DMAADDR(&sc->sc_fldma, 0));
+
+       EOWRITE4(sc, EHCI_PERIODICLISTBASE, lo32);
 
        sc->sc_softitds = kmem_zalloc(sc->sc_flsize * sizeof(ehci_soft_itd_t *),
            KM_SLEEP);
@@ -547,11 +574,12 @@
         * Allocate the interrupt dummy QHs. These are arranged to give poll
         * intervals that are powers of 2 times 1ms.
         */
+       memset(sc->sc_islots, 0, sizeof(sc->sc_islots));
        for (i = 0; i < EHCI_INTRQHS; i++) {
                sqh = ehci_alloc_sqh(sc);
                if (sqh == NULL) {
                        err = ENOMEM;
-                       goto bad1;
+                       goto fail2;
                }
                sc->sc_islots[i].sqh = sqh;
        }
@@ -594,7 +622,7 @@
        sqh = ehci_alloc_sqh(sc);
        if (sqh == NULL) {
                err = ENOMEM;
-               goto bad1;
+               goto fail2;
        }
        /* Fill the QH */
        sqh->qh.qh_endp =
@@ -641,7 +669,8 @@
        }
        if (hcr) {
                aprint_error("%s: run timeout\n", device_xname(sc->sc_dev));
-               return EIO;
+               err = EIO;
+               goto fail3;
        }
 
        /* Enable interrupts */
@@ -650,12 +679,25 @@
 
        return 0;
 
-#if 0
- bad2:
+fail3:
        ehci_free_sqh(sc, sc->sc_async_head);
-#endif
- bad1:
+
+fail2:
+       for (i = 0; i < EHCI_INTRQHS; i++) {
+               sqh = sc->sc_islots[i].sqh;
+               if (sqh)
+                       ehci_free_sqh(sc, sqh);
+       }
+
+       kmem_free(sc->sc_softitds, sc->sc_flsize * sizeof(ehci_soft_itd_t *));
        usb_freemem(&sc->sc_fldma);
+
+fail1:
+       softint_disestablish(sc->sc_doorbell_si);
+       softint_disestablish(sc->sc_pcd_si);
+       mutex_destroy(&sc->sc_lock);
+       mutex_destroy(&sc->sc_intr_lock);
+
        return err;
 }
 
@@ -2000,6 +2042,7 @@
 
        switch (xfertype) {
        case UE_CONTROL:
+               /* we can use 64bit DMA for the reqdma buffer */
                err = usb_allocmem(sc->sc_bus.ub_dmatag,
                    sizeof(usb_device_request_t), 0, USBMALLOC_COHERENT,
                    &epipe->ctrl.reqdma);
@@ -2798,7 +2841,7 @@
                mutex_exit(&sc->sc_lock);
 
                usb_dma_t dma;
-               int err = usb_allocmem(sc->sc_bus.ub_dmatag,
+               int err = usb_allocmem(sc->sc_dmatag,
                    EHCI_SQH_SIZE * EHCI_SQH_CHUNK,
                    EHCI_PAGE_SIZE, USBMALLOC_COHERENT, &dma);
 
@@ -2854,7 +2897,7 @@
                mutex_exit(&sc->sc_lock);
 
                usb_dma_t dma;
-               int err = usb_allocmem(sc->sc_bus.ub_dmatag,
+               int err = usb_allocmem(sc->sc_dmatag,
                    EHCI_SQTD_SIZE * EHCI_SQTD_CHUNK,
                    EHCI_PAGE_SIZE, USBMALLOC_COHERENT, &dma);
 
@@ -3114,7 +3157,7 @@
                mutex_exit(&sc->sc_lock);
 
                usb_dma_t dma;
-               int err = usb_allocmem(sc->sc_bus.ub_dmatag,
+               int err = usb_allocmem(sc->sc_dmatag,
                    EHCI_ITD_SIZE * EHCI_ITD_CHUNK,
                    EHCI_PAGE_SIZE, USBMALLOC_COHERENT, &dma);
 



Home | Main Index | Thread Index | Old Index