Early initialization of acpiec if ECDT table exists
authorjordan <jordan@openbsd.org>
Tue, 27 Jul 2010 05:17:36 +0000 (05:17 +0000)
committerjordan <jordan@openbsd.org>
Tue, 27 Jul 2010 05:17:36 +0000 (05:17 +0000)
Fixes hang when booting thinkpads while docked
ok deraadt

sys/dev/acpi/acpi.c
sys/dev/acpi/acpiec.c

index 95bd0bf..bdad367 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.189 2010/07/26 17:25:44 deraadt Exp $ */
+/* $OpenBSD: acpi.c,v 1.190 2010/07/27 05:17:36 jordan Exp $ */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -2127,6 +2127,10 @@ acpi_foundec(struct aml_node *node, void *arg)
        if (strcmp(dev, ACPI_DEV_ECD))
                return 0;
 
+       /* Check if we're already attached */
+       if (sc->sc_ec && sc->sc_ec->sc_devnode == node->parent)
+               return 0;
+
        memset(&aaa, 0, sizeof(aaa));
        aaa.aaa_iot = sc->sc_iot;
        aaa.aaa_memt = sc->sc_memt;
index abe76b6..3467947 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpiec.c,v 1.34 2010/07/23 20:21:58 jordan Exp $ */
+/* $OpenBSD: acpiec.c,v 1.35 2010/07/27 05:17:36 jordan Exp $ */
 /*
  * Copyright (c) 2006 Can Erkin Acar <canacar@openbsd.org>
  *
@@ -245,6 +245,11 @@ acpiec_match(struct device *parent, void *match, void *aux)
 {
        struct acpi_attach_args *aa = aux;
        struct cfdata           *cf = match;
+       struct acpi_ecdt        *ecdt = aa->aaa_table;
+
+       /* Check for early ECDT table attach */
+       if (ecdt && !memcmp(ecdt->hdr.signature, ECDT_SIG, sizeof(ECDT_SIG) - 1))
+               return (1);
 
        /* sanity */
        return (acpi_matchhids(aa, acpiec_hids, cf->cf_driver->cd_name));
@@ -384,6 +389,25 @@ acpiec_getcrs(struct acpiec_softc *sc, struct acpi_attach_args *aa)
        char                    *buf;
        int                     size, ret;
        int64_t                 gpe;
+       struct acpi_ecdt        *ecdt = aa->aaa_table;
+       extern struct aml_node   aml_root;
+
+       /* Check if this is ECDT initialization */
+       if (ecdt) {
+               /* Get GPE, Data and Control segments */
+               sc->sc_gpe = ecdt->gpe_bit;
+
+               ctype = ecdt->ec_control.address_space_id;
+               ec_sc = ecdt->ec_control.address;
+
+               dtype = ecdt->ec_data.address_space_id;
+               ec_data = ecdt->ec_data.address;
+
+               /* Get devnode from header */
+               sc->sc_devnode = aml_searchname(&aml_root, ecdt->ec_id);
+
+               goto ecdtdone;
+       }
 
        if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_GPE", 0, NULL, &gpe)) {
                dnprintf(10, "%s: no _GPE\n", DEVNAME(sc));
@@ -439,6 +463,7 @@ acpiec_getcrs(struct acpiec_softc *sc, struct acpi_attach_args *aa)
        aml_freevalue(&res);
 
        /* XXX: todo - validate _CRS checksum? */
+ecdtdone:
 
        dnprintf(10, "%s: Data: 0x%x, S/C: 0x%x\n",
            DEVNAME(sc), ec_data, ec_sc);