Index: sys/dev/acpi/ehci_acpi.c =================================================================== RCS file: /cvsroot/src/sys/dev/acpi/ehci_acpi.c,v retrieving revision 1.7 diff -u -p -r1.7 ehci_acpi.c --- sys/dev/acpi/ehci_acpi.c 7 Aug 2021 16:19:09 -0000 1.7 +++ sys/dev/acpi/ehci_acpi.c 22 Dec 2021 06:29:21 -0000 @@ -98,7 +98,6 @@ ehci_acpi_attach(device_t parent, device 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 @@ ehci_acpi_attach(device_t parent, device 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); Index: sys/dev/pci/ehci_pci.c =================================================================== RCS file: /cvsroot/src/sys/dev/pci/ehci_pci.c,v retrieving revision 1.72 diff -u -p -r1.72 ehci_pci.c --- sys/dev/pci/ehci_pci.c 7 Aug 2021 16:19:14 -0000 1.72 +++ sys/dev/pci/ehci_pci.c 22 Dec 2021 06:29:21 -0000 @@ -144,7 +144,22 @@ ehci_pci_attach(device_t parent, device_ 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); Index: sys/dev/usb/ehci.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/ehci.c,v retrieving revision 1.295 diff -u -p -r1.295 ehci.c --- sys/dev/usb/ehci.c 21 Dec 2021 10:16:05 -0000 1.295 +++ sys/dev/usb/ehci.c 22 Dec 2021 06:29:22 -0000 @@ -489,6 +489,25 @@ ehci_init(ehci_softc_t *sc) 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 @@ ehci_init(ehci_softc_t *sc) 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,19 @@ ehci_init(ehci_softc_t *sc) 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"); + + /* Drop the config_pending reference from attach. */ + goto fail1; + } DPRINTF("flsize=%jd", sc->sc_flsize, 0, 0, 0); sc->sc_flist = KERNADDR(&sc->sc_fldma, 0); @@ -529,7 +555,10 @@ ehci_init(ehci_softc_t *sc) 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 +576,12 @@ ehci_init(ehci_softc_t *sc) * 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 +624,7 @@ ehci_init(ehci_softc_t *sc) sqh = ehci_alloc_sqh(sc); if (sqh == NULL) { err = ENOMEM; - goto bad1; + goto fail2; } /* Fill the QH */ sqh->qh.qh_endp = @@ -618,6 +648,7 @@ ehci_init(ehci_softc_t *sc) /* Point to async list */ sc->sc_async_head = sqh; + EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH); callout_init(&sc->sc_tmo_intrlist, CALLOUT_MPSAFE); @@ -641,7 +672,8 @@ ehci_init(ehci_softc_t *sc) } if (hcr) { aprint_error("%s: run timeout\n", device_xname(sc->sc_dev)); - return EIO; + err = EIO; + goto fail3; } /* Enable interrupts */ @@ -650,12 +682,25 @@ ehci_init(ehci_softc_t *sc) 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,9 +2045,10 @@ ehci_open(struct usbd_pipe *pipe) 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); + sizeof(usb_device_request_t), 0, USBMALLOC_COHERENT, + &epipe->ctrl.reqdma); #ifdef EHCI_DEBUG if (err) printf("ehci_open: usb_allocmem()=%d\n", err); @@ -2798,7 +2844,7 @@ ehci_alloc_sqh(ehci_softc_t *sc) 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 +2900,7 @@ ehci_alloc_sqtd(ehci_softc_t *sc) 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 +3160,7 @@ ehci_alloc_itd(ehci_softc_t *sc) 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); Index: sys/dev/usb/ehcivar.h =================================================================== RCS file: /cvsroot/src/sys/dev/usb/ehcivar.h,v retrieving revision 1.48 diff -u -p -r1.48 ehcivar.h --- sys/dev/usb/ehcivar.h 15 Mar 2020 07:56:19 -0000 1.48 +++ sys/dev/usb/ehcivar.h 22 Dec 2021 06:29:22 -0000 @@ -171,6 +171,7 @@ typedef struct ehci_softc { bus_space_tag_t iot; bus_space_handle_t ioh; bus_size_t sc_size; + bus_dma_tag_t sc_dmatag; /* for control data structures */ u_int sc_offs; /* offset to operational regs */ int sc_flags; /* misc flags */ #define EHCIF_DROPPED_INTR_WORKAROUND 0x01