21
21
#include "gpiolib.h"
22
22
#include "gpiolib-acpi.h"
23
23
24
- #define QUIRK_NO_EDGE_EVENTS_ON_BOOT 0x01l
25
- #define QUIRK_NO_WAKEUP 0x02l
26
-
27
24
static int run_edge_events_on_boot = -1 ;
28
25
module_param (run_edge_events_on_boot , int , 0444 );
29
26
MODULE_PARM_DESC (run_edge_events_on_boot ,
30
27
"Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto" );
31
28
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
+ };
36
39
37
40
/**
38
41
* 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)
202
205
acpi_gpiochip_request_irq (acpi_gpio , event );
203
206
}
204
207
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
+
205
259
/* Always returns AE_OK so that we keep looping over the resources */
206
260
static acpi_status acpi_gpiochip_alloc_event (struct acpi_resource * ares ,
207
261
void * context )
@@ -289,7 +343,7 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
289
343
event -> handle = evt_handle ;
290
344
event -> handler = handler ;
291
345
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 ) ;
293
347
event -> pin = pin ;
294
348
event -> desc = desc ;
295
349
@@ -1328,7 +1382,9 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = {
1328
1382
DMI_MATCH (DMI_SYS_VENDOR , "MINIX" ),
1329
1383
DMI_MATCH (DMI_PRODUCT_NAME , "Z83-4" ),
1330
1384
},
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
+ },
1332
1388
},
1333
1389
{
1334
1390
/*
@@ -1341,50 +1397,82 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = {
1341
1397
DMI_MATCH (DMI_SYS_VENDOR , "Wortmann_AG" ),
1342
1398
DMI_MATCH (DMI_PRODUCT_NAME , "TERRA_PAD_1061" ),
1343
1399
},
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
+ },
1345
1403
},
1346
1404
{
1347
1405
/*
1348
- * Various HP X2 10 Cherry Trail models use an external
1349
- * embedded-controller connected via I2C + an ACPI GPIO
1350
- * event handler. The embedded controller generates various
1351
- * spurious wakeup events when suspended. So disable wakeup
1352
- * for its handler (it uses the only ACPI GPIO event handler).
1353
- * This breaks wakeup when opening the lid, the user needs
1406
+ * HP X2 10 models with Cherry Trail SoC + TI PMIC use an
1407
+ * external embedded-controller connected via I2C + an ACPI GPIO
1408
+ * event handler on INT33FF:01 pin 0, causing spurious wakeups.
1409
+ * When suspending by closing the LID, the power to the USB
1410
+ * keyboard is turned off, causing INT0002 ACPI events to
1411
+ * trigger once the XHCI controller notices the keyboard is
1412
+ * gone. So INT0002 events cause spurious wakeups too. Ignoring
1413
+ * EC wakes breaks wakeup when opening the lid, the user needs
1354
1414
* to press the power-button to wakeup the system. The
1355
1415
* alternative is suspend simply not working, which is worse.
1356
1416
*/
1357
1417
.matches = {
1358
1418
DMI_MATCH (DMI_SYS_VENDOR , "HP" ),
1359
1419
DMI_MATCH (DMI_PRODUCT_NAME , "HP x2 Detachable 10-p0XX" ),
1360
1420
},
1361
- .driver_data = (void * )QUIRK_NO_WAKEUP ,
1421
+ .driver_data = & (struct acpi_gpiolib_dmi_quirk ) {
1422
+ .ignore_wake = "INT33FF:01@0,INT0002:00@2" ,
1423
+ },
1424
+ },
1425
+ {
1426
+ /*
1427
+ * HP X2 10 models with Bay Trail SoC + AXP288 PMIC use an
1428
+ * external embedded-controller connected via I2C + an ACPI GPIO
1429
+ * event handler on INT33FC:02 pin 28, causing spurious wakeups.
1430
+ */
1431
+ .matches = {
1432
+ DMI_MATCH (DMI_SYS_VENDOR , "Hewlett-Packard" ),
1433
+ DMI_MATCH (DMI_PRODUCT_NAME , "HP Pavilion x2 Detachable" ),
1434
+ DMI_MATCH (DMI_BOARD_NAME , "815D" ),
1435
+ },
1436
+ .driver_data = & (struct acpi_gpiolib_dmi_quirk ) {
1437
+ .ignore_wake = "INT33FC:02@28" ,
1438
+ },
1439
+ },
1440
+ {
1441
+ /*
1442
+ * HP X2 10 models with Cherry Trail SoC + AXP288 PMIC use an
1443
+ * external embedded-controller connected via I2C + an ACPI GPIO
1444
+ * event handler on INT33FF:01 pin 0, causing spurious wakeups.
1445
+ */
1446
+ .matches = {
1447
+ DMI_MATCH (DMI_SYS_VENDOR , "HP" ),
1448
+ DMI_MATCH (DMI_PRODUCT_NAME , "HP Pavilion x2 Detachable" ),
1449
+ DMI_MATCH (DMI_BOARD_NAME , "813E" ),
1450
+ },
1451
+ .driver_data = & (struct acpi_gpiolib_dmi_quirk ) {
1452
+ .ignore_wake = "INT33FF:01@0" ,
1453
+ },
1362
1454
},
1363
1455
{} /* Terminating entry */
1364
1456
};
1365
1457
1366
1458
static int acpi_gpio_setup_params (void )
1367
1459
{
1460
+ const struct acpi_gpiolib_dmi_quirk * quirk = NULL ;
1368
1461
const struct dmi_system_id * id ;
1369
- long quirks = 0 ;
1370
1462
1371
1463
id = dmi_first_match (gpiolib_acpi_quirks );
1372
1464
if (id )
1373
- quirks = ( long ) id -> driver_data ;
1465
+ quirk = id -> driver_data ;
1374
1466
1375
1467
if (run_edge_events_on_boot < 0 ) {
1376
- if (quirks & QUIRK_NO_EDGE_EVENTS_ON_BOOT )
1468
+ if (quirk && quirk -> no_edge_events_on_boot )
1377
1469
run_edge_events_on_boot = 0 ;
1378
1470
else
1379
1471
run_edge_events_on_boot = 1 ;
1380
1472
}
1381
1473
1382
- if (honor_wakeup < 0 ) {
1383
- if (quirks & QUIRK_NO_WAKEUP )
1384
- honor_wakeup = 0 ;
1385
- else
1386
- honor_wakeup = 1 ;
1387
- }
1474
+ if (ignore_wake == NULL && quirk && quirk -> ignore_wake )
1475
+ ignore_wake = quirk -> ignore_wake ;
1388
1476
1389
1477
return 0 ;
1390
1478
}
0 commit comments