Skip to content

Commit 2ccb21f

Browse files
jwrdegoedelinusw
authored andcommitted
gpiolib: acpi: Rework honor_wakeup option into an ignore_wake option
Commit aa23ca3 ("gpiolib: acpi: Add honor_wakeup module-option + quirk mechanism") was added to deal with spurious wakeups on one specific model of the HP x2 10 series. The approach taken there was to add a bool controlling wakeup support for all ACPI GPIO events. This was sufficient for the specific HP x2 10 model the commit was trying to fix, but in the mean time other models have turned up which need a similar workaround to avoid spurious wakeups from suspend, but only for one of the pins on which the ACPI tables request ACPI GPIO events. Since the honor_wakeup option was added to be able to ignore wake events, the name was perhaps not the best, this commit renames it to ignore_wake and changes it to a string with the following format: gpiolib_acpi.ignore_wake=controller@pin[,controller@pin[,...]] This allows working around spurious wakeup issues on a per pin basis. This commit also reworks the existing quirk for the HP x2 10 so that it functions as before. Note: -This removes the honor_wakeup parameter. This has only been upstream for a short time and to the best of my knowledge there are no users using this module parameter. -The controller@pin[,controller@pin[,...]] syntax is based on an existing kernel module parameter using the same controller@pin format. That version uses ';' as separator, but in practice that is problematic because grub2 cannot handle this without taking special care to escape the ';', so here we are using a ',' as separator instead which does not have this issue. Fixes: aa23ca3 ("gpiolib: acpi: Add honor_wakeup module-option + quirk mechanism") Signed-off-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected] Acked-by: Mika Westerberg <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Signed-off-by: Linus Walleij <[email protected]>
1 parent efaa87f commit 2ccb21f

File tree

1 file changed

+76
-20
lines changed

1 file changed

+76
-20
lines changed

drivers/gpio/gpiolib-acpi.c

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,21 @@
2121
#include "gpiolib.h"
2222
#include "gpiolib-acpi.h"
2323

24-
#define QUIRK_NO_EDGE_EVENTS_ON_BOOT 0x01l
25-
#define QUIRK_NO_WAKEUP 0x02l
26-
2724
static int run_edge_events_on_boot = -1;
2825
module_param(run_edge_events_on_boot, int, 0444);
2926
MODULE_PARM_DESC(run_edge_events_on_boot,
3027
"Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto");
3128

32-
static int honor_wakeup = -1;
33-
module_param(honor_wakeup, int, 0444);
34-
MODULE_PARM_DESC(honor_wakeup,
35-
"Honor the ACPI wake-capable flag: 0=no, 1=yes, -1=auto");
29+
static char *ignore_wake;
30+
module_param(ignore_wake, charp, 0444);
31+
MODULE_PARM_DESC(ignore_wake,
32+
"controller@pin combos on which to ignore the ACPI wake flag "
33+
"ignore_wake=controller@pin[,controller@pin[,...]]");
34+
35+
struct acpi_gpiolib_dmi_quirk {
36+
bool no_edge_events_on_boot;
37+
char *ignore_wake;
38+
};
3639

3740
/**
3841
* struct acpi_gpio_event - ACPI GPIO event handler data
@@ -202,6 +205,57 @@ static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio)
202205
acpi_gpiochip_request_irq(acpi_gpio, event);
203206
}
204207

208+
static bool acpi_gpio_in_ignore_list(const char *controller_in, int pin_in)
209+
{
210+
const char *controller, *pin_str;
211+
int len, pin;
212+
char *endp;
213+
214+
controller = ignore_wake;
215+
while (controller) {
216+
pin_str = strchr(controller, '@');
217+
if (!pin_str)
218+
goto err;
219+
220+
len = pin_str - controller;
221+
if (len == strlen(controller_in) &&
222+
strncmp(controller, controller_in, len) == 0) {
223+
pin = simple_strtoul(pin_str + 1, &endp, 10);
224+
if (*endp != 0 && *endp != ',')
225+
goto err;
226+
227+
if (pin == pin_in)
228+
return true;
229+
}
230+
231+
controller = strchr(controller, ',');
232+
if (controller)
233+
controller++;
234+
}
235+
236+
return false;
237+
err:
238+
pr_err_once("Error invalid value for gpiolib_acpi.ignore_wake: %s\n",
239+
ignore_wake);
240+
return false;
241+
}
242+
243+
static bool acpi_gpio_irq_is_wake(struct device *parent,
244+
struct acpi_resource_gpio *agpio)
245+
{
246+
int pin = agpio->pin_table[0];
247+
248+
if (agpio->wake_capable != ACPI_WAKE_CAPABLE)
249+
return false;
250+
251+
if (acpi_gpio_in_ignore_list(dev_name(parent), pin)) {
252+
dev_info(parent, "Ignoring wakeup on pin %d\n", pin);
253+
return false;
254+
}
255+
256+
return true;
257+
}
258+
205259
/* Always returns AE_OK so that we keep looping over the resources */
206260
static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
207261
void *context)
@@ -289,7 +343,7 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
289343
event->handle = evt_handle;
290344
event->handler = handler;
291345
event->irq = irq;
292-
event->irq_is_wake = honor_wakeup && agpio->wake_capable == ACPI_WAKE_CAPABLE;
346+
event->irq_is_wake = acpi_gpio_irq_is_wake(chip->parent, agpio);
293347
event->pin = pin;
294348
event->desc = desc;
295349

@@ -1328,7 +1382,9 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = {
13281382
DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
13291383
DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
13301384
},
1331-
.driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT,
1385+
.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
1386+
.no_edge_events_on_boot = true,
1387+
},
13321388
},
13331389
{
13341390
/*
@@ -1341,7 +1397,9 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = {
13411397
DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"),
13421398
DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"),
13431399
},
1344-
.driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT,
1400+
.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
1401+
.no_edge_events_on_boot = true,
1402+
},
13451403
},
13461404
{
13471405
/*
@@ -1360,33 +1418,31 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = {
13601418
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
13611419
DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
13621420
},
1363-
.driver_data = (void *)QUIRK_NO_WAKEUP,
1421+
.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
1422+
.ignore_wake = "INT33FF:01@0,INT0002:00@2",
1423+
},
13641424
},
13651425
{} /* Terminating entry */
13661426
};
13671427

13681428
static int acpi_gpio_setup_params(void)
13691429
{
1430+
const struct acpi_gpiolib_dmi_quirk *quirk = NULL;
13701431
const struct dmi_system_id *id;
1371-
long quirks = 0;
13721432

13731433
id = dmi_first_match(gpiolib_acpi_quirks);
13741434
if (id)
1375-
quirks = (long)id->driver_data;
1435+
quirk = id->driver_data;
13761436

13771437
if (run_edge_events_on_boot < 0) {
1378-
if (quirks & QUIRK_NO_EDGE_EVENTS_ON_BOOT)
1438+
if (quirk && quirk->no_edge_events_on_boot)
13791439
run_edge_events_on_boot = 0;
13801440
else
13811441
run_edge_events_on_boot = 1;
13821442
}
13831443

1384-
if (honor_wakeup < 0) {
1385-
if (quirks & QUIRK_NO_WAKEUP)
1386-
honor_wakeup = 0;
1387-
else
1388-
honor_wakeup = 1;
1389-
}
1444+
if (ignore_wake == NULL && quirk && quirk->ignore_wake)
1445+
ignore_wake = quirk->ignore_wake;
13901446

13911447
return 0;
13921448
}

0 commit comments

Comments
 (0)