Redux: this new version will apply with -current

This patch will allow acpiec to initialize earlier if a ECDT table is
found.  This fixes a lockup if booting on some Thinkpads while docked.
 
You can tell if your system supports ECDT by scanning the ACPI tables
line in dmesg.  There should be a line like this:
acpi0: tables DSDT FACP SSDT ECDT TCPA APIC MCFG HPET SLIC BOOT ASF! SSDT SSDT 
SSDT SSDT
 
ECDT will be one of the entries if the early initialization is supported.
 
If scanning dmesg, acpiec0 will now also initialize earlier (near acpitimer
and acpimadt) instead of after acpiprt. 

Index: acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpi.c,v
retrieving revision 1.187
diff -u -p -u -p -b -r1.187 acpi.c
--- acpi.c      22 Jul 2010 14:19:47 -0000      1.187
+++ acpi.c      24 Jul 2010 05:52:03 -0000
@@ -2123,6 +2123,10 @@ acpi_foundec(struct aml_node *node, void
        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: acpiec.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpiec.c,v
retrieving revision 1.34
diff -u -p -u -p -b -r1.34 acpiec.c
--- acpiec.c    23 Jul 2010 20:21:58 -0000      1.34
+++ acpiec.c    24 Jul 2010 05:52:04 -0000
@@ -245,6 +245,11 @@ acpiec_match(struct device *parent, void
 {
        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, s
        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, s
        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);

Reply via email to