After discussions with Theo we decided to walk the table where needed
instead of using the soft state variables.

Also adding all the Samsung models to the quirks table (as per the
Linux EC quirks table).


Index: acpiec.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpiec.c,v
retrieving revision 1.49
diff -u -p -r1.49 acpiec.c
--- acpiec.c    21 May 2014 02:14:07 -0000      1.49
+++ acpiec.c    10 Jun 2014 15:18:59 -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 = {
@@ -91,6 +94,34 @@ struct cfdriver acpiec_cd = {
 
 const char *acpiec_hids[] = { ACPI_DEV_ECD, 0 };
 
+/* needed by acpiec_clear_events */
+extern char *hw_vendor, *hw_prod;
+
+struct ec_quirks_description {
+       char *vendor;
+       char *prod;
+};
+
+static const struct ec_quirks_description ec_quirks[] = {
+       /*
+        * Header description:
+        *
+        * The entries define the machine model based on information
+        * from BIOS in the following order: VENDOR, PRODUCT
+        *
+        */
+
+       /* ThinkPad x120e */
+       { "LENOVO", "05962PU" },
+
+       /*
+        * All Samsung models require this according to Linux
+        * https://bugzilla.kernel.org/show_bug.cgi?id=44161
+        */
+       { "SAMSUNG ELECTRONICS CO., LTD.", NULL }
+};
+
+
 void
 acpiec_wait(struct acpiec_softc *sc, u_int8_t mask, u_int8_t val)
 {
@@ -274,6 +305,8 @@ acpiec_attach(struct device *parent, str
        struct acpi_attach_args *aa = aux;
        struct aml_value res;
 
+       int i;
+
        sc->sc_acpi = (struct acpi_softc *)parent;
        sc->sc_devnode = aa->aaa_node;
 
@@ -297,7 +330,16 @@ acpiec_attach(struct device *parent, str
        acpi_set_gpehandler(sc->sc_acpi, sc->sc_gpe, acpiec_gpehandler,
            sc, 1);
 #endif
-       
+
+       for (i = 0; i < nitems(ec_quirks); i++)
+               if ((!strcmp(hw_vendor, ec_quirks[i].vendor)) &&
+                   (ec_quirks[i].prod == NULL ||
+                   (!strcmp(hw_prod, ec_quirks[i].prod)))) {
+                       acpiec_clear_events(sc);
+                       break;
+               }
+
+
        if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_GLK", 0, NULL, &res))
                sc->sc_glk = 0;
        else if (res.type != AML_OBJTYPE_INTEGER)
@@ -308,6 +350,26 @@ acpiec_attach(struct device *parent, str
        printf("\n");
 }
 
+int
+acpiec_activate(struct device *self, int act)
+{
+       struct acpiec_softc *sc = (struct acpiec_softc *)self;
+       int i;
+
+       switch (act) {
+       case DVACT_RESUME:
+               for (i = 0; i < nitems(ec_quirks); i++)
+                       if ((!strcmp(hw_vendor, ec_quirks[i].vendor)) &&
+                           (ec_quirks[i].prod == NULL ||
+                           (!strcmp(hw_prod, ec_quirks[i].prod)))) {
+                               acpiec_clear_events(sc);
+                               break;
+               }
+               break;
+       }
+       return (0);
+}
+
 void
 acpiec_get_events(struct acpiec_softc *sc)
 {
@@ -553,4 +615,17 @@ 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;
+       }
 }

Reply via email to