Module Name:    src
Committed By:   jmcneill
Date:           Fri Dec 24 00:27:22 UTC 2021

Modified Files:
        src/sys/dev/acpi: ehci_acpi.c

Log Message:
acpi: ehci: Don't assume that a transaction translator is available.

Look for companion controllers using the rules in ACPI 6.3 section 9.14.1
"USB 2.0 Host Controllers and _UPC and _PLD", and only assume TT is
present if we can't find a USB 1.1 companion.


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/acpi/ehci_acpi.c

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.8 src/sys/dev/acpi/ehci_acpi.c:1.9
--- src/sys/dev/acpi/ehci_acpi.c:1.8	Wed Dec 22 21:45:02 2021
+++ src/sys/dev/acpi/ehci_acpi.c	Fri Dec 24 00:27:22 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: ehci_acpi.c,v 1.8 2021/12/22 21:45:02 skrll Exp $ */
+/* $NetBSD: ehci_acpi.c,v 1.9 2021/12/24 00:27:22 jmcneill 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.8 2021/12/22 21:45:02 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci_acpi.c,v 1.9 2021/12/24 00:27:22 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -69,6 +69,8 @@ static void	ehci_acpi_attach(device_t, d
 
 static void	ehci_acpi_init(struct ehci_softc *);
 
+static int	ehci_acpi_num_companions(struct acpi_attach_args *);
+
 CFATTACH_DECL2_NEW(ehci_acpi, sizeof(struct ehci_acpi_softc),
 	ehci_acpi_match, ehci_acpi_attach, NULL,
 	ehci_activate, NULL, ehci_childdet);
@@ -94,12 +96,13 @@ ehci_acpi_attach(device_t parent, device
 	int error;
 	void *ih;
 
+	acpi_claim_childdevs(self, aa->aa_node);
+
 	asc->sc_handle = aa->aa_node->ad_handle;
 
 	sc->sc_dev = self;
 	sc->sc_bus.ub_hcpriv = sc;
 	sc->sc_bus.ub_revision = USBREV_2_0;
-	sc->sc_flags = EHCIF_ETTF;
 	sc->sc_vendor_init = ehci_acpi_init;
 
 	rv = acpi_resource_parse(sc->sc_dev, asc->sc_handle, "_CRS",
@@ -107,6 +110,10 @@ ehci_acpi_attach(device_t parent, device
 	if (ACPI_FAILURE(rv))
 		return;
 
+	sc->sc_ncomp = ehci_acpi_num_companions(aa);
+	if (sc->sc_ncomp == 0) {
+		sc->sc_flags = EHCIF_ETTF;
+	}
 	mem = acpi_res_mem(&res, 0);
 	if (mem == NULL) {
 		aprint_error_dev(self, "couldn't find mem resource\n");
@@ -174,3 +181,103 @@ ehci_acpi_init(struct ehci_softc *sc)
 
 	acpi_usb_post_reset(asc->sc_handle);
 }
+
+static int
+ehci_acpi_port_has_companion(struct acpi_devnode *portad, ACPI_INTEGER portno)
+{
+	struct acpi_devnode *ad;
+	ACPI_BUFFER portbuf, buf;
+	ACPI_OBJECT *portobj, *obj;
+	ACPI_OBJECT *portpld, *pld;
+	ACPI_STATUS rv;
+	int ncomp = 0;
+
+	rv = acpi_eval_struct(portad->ad_handle, "_PLD", &portbuf);
+	if (ACPI_FAILURE(rv)) {
+		return 0;
+	}
+	portobj = portbuf.Pointer;
+	if (portobj->Type != ACPI_TYPE_PACKAGE ||
+	    portobj->Package.Count == 0 ||
+	    portobj->Package.Elements[0].Type != ACPI_TYPE_BUFFER) {
+		return 0;
+	}
+	portpld = &portobj->Package.Elements[0];
+
+	/*
+	 * Look through all ACPI device nodes and try to find another
+	 * one that matches our _PLD. If we have a match, it means we
+	 * have a companion controller somewhere.
+	 */
+	SIMPLEQ_FOREACH(ad, &acpi_softc->sc_head, ad_list) {
+		if (ad == portad) {
+			continue;
+		}
+		rv = acpi_eval_struct(ad->ad_handle, "_PLD", &buf);
+		if (ACPI_FAILURE(rv)) {
+			continue;
+		}
+		obj = buf.Pointer;
+		if (obj->Type == ACPI_TYPE_PACKAGE &&
+		    obj->Package.Count != 0 &&
+		    obj->Package.Elements[0].Type == ACPI_TYPE_BUFFER) {
+			pld = &obj->Package.Elements[0];
+			if (memcmp(pld->Buffer.Pointer, portpld->Buffer.Pointer,
+			    pld->Buffer.Length) == 0) {
+				aprint_verbose_dev(portad->ad_device,
+				    "companion port: %s\n", acpi_name(ad->ad_handle));
+				ncomp = 1;
+			}
+		}
+		ACPI_FREE(buf.Pointer);
+		if (ncomp != 0) {
+			break;
+		}
+	}
+
+	ACPI_FREE(portbuf.Pointer);
+
+	return ncomp;
+}
+
+static int
+ehci_acpi_num_companion_ports(struct acpi_devnode *hubad)
+{
+	struct acpi_devnode *ad;
+	ACPI_STATUS rv;
+	ACPI_INTEGER val;
+	int ncomp = 0;
+
+	/* Look for child ports with _ADR != 0 */
+	SIMPLEQ_FOREACH(ad, &hubad->ad_child_head, ad_child_list) {
+		rv = acpi_eval_integer(ad->ad_handle, "_ADR", &val);
+		if (ACPI_SUCCESS(rv) && val != 0) {
+			ncomp += ehci_acpi_port_has_companion(ad, val);
+		}
+	}
+
+	return ncomp;
+}
+
+static int
+ehci_acpi_num_companions(struct acpi_attach_args *aa)
+{
+	struct acpi_devnode *ad;
+	ACPI_STATUS rv;
+	ACPI_INTEGER val;
+	int ncomp = 0;
+
+	/* Look for a child node with _ADR 0 that represents our root hub. */
+	SIMPLEQ_FOREACH(ad, &aa->aa_node->ad_child_head, ad_child_list) {
+		rv = acpi_eval_integer(ad->ad_handle, "_ADR", &val);
+		if (ACPI_SUCCESS(rv) && val == 0) {
+			/*
+			 * Count the number of ports on this hub.
+			 */
+			ncomp = ehci_acpi_num_companion_ports(ad);
+			break;
+		}
+	}
+
+	return ncomp;
+}

Reply via email to