Module Name: src
Committed By: skrll
Date: Wed Dec 22 21:45:02 UTC 2021
Modified Files:
src/sys/dev/acpi: ehci_acpi.c
src/sys/dev/pci: ehci_pci.c
src/sys/dev/usb: ehci.c ehcivar.h
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/acpi/ehci_acpi.c
cvs rdiff -u -r1.72 -r1.73 src/sys/dev/pci/ehci_pci.c
cvs rdiff -u -r1.296 -r1.297 src/sys/dev/usb/ehci.c
cvs rdiff -u -r1.48 -r1.49 src/sys/dev/usb/ehcivar.h
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/acpi/ehci_acpi.c
diff -u src/sys/dev/acpi/ehci_acpi.c:1.7 src/sys/dev/acpi/ehci_acpi.c:1.8
--- src/sys/dev/acpi/ehci_acpi.c:1.7 Sat Aug 7 16:19:09 2021
+++ src/sys/dev/acpi/ehci_acpi.c Wed Dec 22 21:45:02 2021
@@ -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 @@ 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: src/sys/dev/pci/ehci_pci.c
diff -u src/sys/dev/pci/ehci_pci.c:1.72 src/sys/dev/pci/ehci_pci.c:1.73
--- src/sys/dev/pci/ehci_pci.c:1.72 Sat Aug 7 16:19:14 2021
+++ src/sys/dev/pci/ehci_pci.c Wed Dec 22 21:45:02 2021
@@ -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 @@ 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: src/sys/dev/usb/ehci.c
diff -u src/sys/dev/usb/ehci.c:1.296 src/sys/dev/usb/ehci.c:1.297
--- src/sys/dev/usb/ehci.c:1.296 Wed Dec 22 21:36:40 2021
+++ src/sys/dev/usb/ehci.c Wed Dec 22 21:45:02 2021
@@ -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 @@ 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,17 @@ 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");
+ goto fail1;
+ }
DPRINTF("flsize=%jd", sc->sc_flsize, 0, 0, 0);
sc->sc_flist = KERNADDR(&sc->sc_fldma, 0);
@@ -529,7 +553,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 +574,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 +622,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 =
@@ -641,7 +669,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 +679,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,6 +2042,7 @@ 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);
@@ -2798,7 +2841,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 +2897,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 +3157,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: src/sys/dev/usb/ehcivar.h
diff -u src/sys/dev/usb/ehcivar.h:1.48 src/sys/dev/usb/ehcivar.h:1.49
--- src/sys/dev/usb/ehcivar.h:1.48 Sun Mar 15 07:56:19 2020
+++ src/sys/dev/usb/ehcivar.h Wed Dec 22 21:45:02 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: ehcivar.h,v 1.48 2020/03/15 07:56:19 skrll Exp $ */
+/* $NetBSD: ehcivar.h,v 1.49 2021/12/22 21:45:02 skrll Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -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