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

Reply via email to