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;
+ }
+ }
}