Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/acpi acpi: ehci: Don't assume that a transaction tra...



details:   https://anonhg.NetBSD.org/src/rev/ae89f03fb27d
branches:  trunk
changeset: 1029155:ae89f03fb27d
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Fri Dec 24 00:27:22 2021 +0000

description:
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.

diffstat:

 sys/dev/acpi/ehci_acpi.c |  113 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 110 insertions(+), 3 deletions(-)

diffs (157 lines):

diff -r 1126fb4375be -r ae89f03fb27d sys/dev/acpi/ehci_acpi.c
--- a/sys/dev/acpi/ehci_acpi.c  Fri Dec 24 00:24:49 2021 +0000
+++ b/sys/dev/acpi/ehci_acpi.c  Fri Dec 24 00:27:22 2021 +0000
@@ -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_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 @@
        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 @@
        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 @@
 
        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;
+}



Home | Main Index | Thread Index | Old Index