Steve, can you test this diff for me and tell me if it fixes anything for you.
I'll also be attending BSDCan to give a talk, see you there! Index: dsdt.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v retrieving revision 1.205 diff -u -p -r1.205 dsdt.c --- dsdt.c 12 Dec 2013 20:56:01 -0000 1.205 +++ dsdt.c 12 Apr 2014 10:45:02 -0000 @@ -736,72 +736,58 @@ static long global_lock_count = 0; void acpi_glk_enter(void) { - acpi_acquire_glk(&acpi_softc->sc_facs->global_lock); -} - -void -acpi_glk_leave(void) -{ - int x; - - if (acpi_release_glk(&acpi_softc->sc_facs->global_lock)) { - /* - * If pending, notify the BIOS that the lock was released - * by the OSPM. No locking is needed because nobody outside - * the ACPI thread is touching this register. - */ - x = acpi_read_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0); - x |= ACPI_PM1_GBL_RLS; - acpi_write_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0, x); - } -} - -void -aml_lockfield(struct aml_scope *scope, struct aml_value *field) -{ int st = 0; - if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON) - return; - - /* If lock is already ours, just continue */ + /* If lock is already ours, just continue. */ if (global_lock_count++) return; - /* Spin to acquire lock */ + /* Spin to acquire the lock. */ while (!st) { st = acpi_acquire_glk(&acpi_softc->sc_facs->global_lock); /* XXX - yield/delay? */ } - - return; } void -aml_unlockfield(struct aml_scope *scope, struct aml_value *field) +acpi_glk_leave(void) { - int st, x, s; + int st, x; - if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON) - return; - - /* If we are the last ones, turn out the lights */ + /* If we are the last one, turn out the lights. */ if (--global_lock_count) return; - /* Release lock */ st = acpi_release_glk(&acpi_softc->sc_facs->global_lock); if (!st) return; - /* Signal others if someone waiting */ - s = spltty(); + /* + * If pending, notify the BIOS that the lock was released by + * OSPM. No locking is needed because nobody outside the ACPI + * thread is supposed to touch this register. + */ x = acpi_read_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0); x |= ACPI_PM1_GBL_RLS; acpi_write_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0, x); - splx(s); +} + +void +aml_lockfield(struct aml_scope *scope, struct aml_value *field) +{ + if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON) + return; + + acpi_glk_enter(); +} + +void +aml_unlockfield(struct aml_scope *scope, struct aml_value *field) +{ + if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON) + return; - return; + acpi_glk_leave(); } /* Index: acpiec.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpiec.c,v retrieving revision 1.48 diff -u -p -r1.48 acpiec.c --- acpiec.c 2 Jul 2013 18:37:47 -0000 1.48 +++ acpiec.c 12 Apr 2014 10:45:03 -0000 @@ -34,6 +34,7 @@ int acpiec_match(struct device *, void *, void *); void acpiec_attach(struct device *, struct device *, void *); +int acpiec_activate(struct device *, int); u_int8_t acpiec_status(struct acpiec_softc *); u_int8_t acpiec_read_data(struct acpiec_softc *); @@ -54,6 +55,7 @@ int acpiec_getregister(const u_int8_t * void acpiec_wait(struct acpiec_softc *, u_int8_t, u_int8_t); void acpiec_sci_event(struct acpiec_softc *); +void acpiec_clear_events(struct acpiec_softc *); void acpiec_get_events(struct acpiec_softc *); @@ -82,7 +84,8 @@ void acpiec_unlock(struct acpiec_softc int acpiec_reg(struct acpiec_softc *); struct cfattach acpiec_ca = { - sizeof(struct acpiec_softc), acpiec_match, acpiec_attach + sizeof(struct acpiec_softc), acpiec_match, acpiec_attach, + NULL, acpiec_activate }; struct cfdriver acpiec_cd = { @@ -296,6 +299,8 @@ acpiec_attach(struct device *parent, str acpi_set_gpehandler(sc->sc_acpi, sc->sc_gpe, acpiec_gpehandler, sc, 1); #endif + + acpiec_clear_events(sc); if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_GLK", 0, NULL, &res)) sc->sc_glk = 0; @@ -307,6 +312,20 @@ acpiec_attach(struct device *parent, str printf("\n"); } +int +acpiec_activate(struct device *self, int act) +{ + struct acpiec_softc *sc = (struct acpiec_softc *)self; + + + switch (act) { + case DVACT_RESUME: + acpiec_clear_events(sc); + break; + } + return (0); +} + void acpiec_get_events(struct acpiec_softc *sc) { @@ -552,4 +571,18 @@ acpiec_unlock(struct acpiec_softc *sc) } sc->sc_ecbusy = 0; +} + +void +acpiec_clear_events(struct acpiec_softc *sc) +{ + int i; + + for (i = 0; i < 100; i++) { + acpiec_write_cmd(sc, EC_CMD_QR); + sc->sc_gotsci = 0; + if ((acpiec_status(sc) & EC_STAT_SCI_EVT) != EC_STAT_SCI_EVT) { + break; + } + } }