Linux seems to permit GPE re-assignment (at least from what I can tell, the code is a bit convoluted). In the Surface Book AML, Microsoft provides an _L50 method as well as a _GPE method on the EC object that also returns 0x50. This makes no sense, since EC GPEs must be edge-triggered (and an _Lxx method indicates a level-triggered GPE). What happens now is that we ignore the second GPE registration, meaning all EC GPEs get ignored.
This diff removes the -EBUSY return in that situation, allowing the second (and, I suppose, subsequent) GPEs to be registered properly. With this diff, and another one not yet posted, I can get the EC on the Surface Book to actually generate events, which means we can support the buttons and other events on this machine. I am still not 100% convinced this is the right way to go. I have not yet unravelled all the Linux GPE code, but I'd like to see if the diff below breaks anyone, in case I decide to go this way. I have discussed this with kettenis@ and we can't come up with anything better at the moment. Testing appreciated, look for "GPE xxx already enabled" in your dmesgs. -ml Index: acpi.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpi.c,v retrieving revision 1.345 diff -u -p -a -u -r1.345 acpi.c --- acpi.c 25 Jun 2018 22:33:24 -0000 1.345 +++ acpi.c 26 Jun 2018 03:36:10 -0000 @@ -2186,10 +2186,9 @@ acpi_set_gpehandler(struct acpi_softc *s ptbl = acpi_find_gpe(sc, gpe); if (ptbl == NULL || handler == NULL) return -EINVAL; - if (ptbl->handler != NULL) { - dnprintf(10, "error: GPE %.2x already enabled\n", gpe); - return -EBUSY; - } + if (ptbl->handler != NULL) + printf("%s: GPE %.2x already enabled\n", DEVNAME(sc), gpe); + dnprintf(50, "Adding GPE handler %.2x (%s)\n", gpe, edge ? "edge" : "level"); ptbl->handler = handler; ptbl->arg = arg;