aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2015-05-15 02:16:48 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-05-15 19:51:18 -0400
commit15de603b04b229b5582fd148fd851801a79472cc (patch)
treef2b270eaea5d3b28860a20f49e97885c66139591
parentd8d031a605bff183b76611e0d18e2ca7021fb99f (diff)
ACPI / EC: Add module params for polling modes.
We have 2 polling modes in the EC driver: 1. busy polling: originally used for the MSI quirks. udelay() is used to perform register access guarding. 2. wait polling: normal code path uses wait_event_timeout() and it can be woken up as soon as the transaction is completed in the interrupt mode. It also contains the register acces guarding logic in case the interrupt doesn't arrive and the EC driver is about to advance the transaction in task context (the polling mode). The wait polling is useful for interrupt mode to allow other tasks to use the CPU during the wait. But for the polling mode, the busy polling takes less time than the wait polling, because if no interrupt arrives, the wait polling has to wait the minimal HZ interval. We have a new use case for using the busy polling mode. Some GPIO drivers initialize PIN configuration which cause a GPIO multiplexed EC GPE to be disabled out of the GPE register's control. Busy polling mode is useful here as it takes less time than the wait polling. But the guarding logic prevents it from responding even faster. We should spinning around the EC status rather than spinning around the nop execution lasted a determined period. This patch introduces 2 module params for the polling mode switch and the guard time, so that users can use the busy polling mode without the guarding in case the guarding is not necessary. This is an example to use the 2 module params for this purpose: acpi.ec_busy_polling acpi.ec_polling_guard=0 We've tested the patch on a test platform. The platform suffers from such kind of the GPIO PIN issue. The GPIO driver resets all PIN configuration and after that, EC interrupt cannot arrive because of the multiplexing. Then the platform suffers from a long delay carried out by the wait_event_timeout() as all further EC transactions will run in the polling mode. We switched the EC driver to use the busy polling mechanism instead of the wait timeout polling mechanism and the delay is still high: [ 44.283005] calling PNP0C0B:00+ @ 1305, parent: platform [ 44.417548] call PNP0C0B:00+ returned 0 after 131323 usecs And this patch can significantly reduce the delay: [ 44.502625] calling PNP0C0B:00+ @ 1308, parent: platform [ 44.503760] call PNP0C0B:00+ returned 0 after 1103 usecs Tested-by: Chen Yu <yu.c.chen@intel.com> Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/ec.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index a521b6b3797e..846e0617eb9b 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -92,6 +92,14 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
92module_param(ec_delay, uint, 0644); 92module_param(ec_delay, uint, 0644);
93MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); 93MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
94 94
95static bool ec_busy_polling __read_mostly;
96module_param(ec_busy_polling, bool, 0644);
97MODULE_PARM_DESC(ec_busy_polling, "Use busy polling to advance EC transaction");
98
99static unsigned int ec_polling_guard __read_mostly = ACPI_EC_UDELAY_POLL;
100module_param(ec_polling_guard, uint, 0644);
101MODULE_PARM_DESC(ec_polling_guard, "Guard time(us) between EC accesses in polling modes");
102
95/* 103/*
96 * If the number of false interrupts per one transaction exceeds 104 * If the number of false interrupts per one transaction exceeds
97 * this threshold, will think there is a GPE storm happened and 105 * this threshold, will think there is a GPE storm happened and
@@ -128,7 +136,6 @@ static void advance_transaction(struct acpi_ec *ec);
128struct acpi_ec *boot_ec, *first_ec; 136struct acpi_ec *boot_ec, *first_ec;
129EXPORT_SYMBOL(first_ec); 137EXPORT_SYMBOL(first_ec);
130 138
131static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
132static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ 139static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
133static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ 140static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
134static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ 141static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
@@ -504,11 +511,11 @@ static void start_transaction(struct acpi_ec *ec)
504 511
505static int ec_guard(struct acpi_ec *ec) 512static int ec_guard(struct acpi_ec *ec)
506{ 513{
507 unsigned long guard = usecs_to_jiffies(ACPI_EC_UDELAY_POLL); 514 unsigned long guard = usecs_to_jiffies(ec_polling_guard);
508 unsigned long timeout = ec->timestamp + guard; 515 unsigned long timeout = ec->timestamp + guard;
509 516
510 do { 517 do {
511 if (EC_FLAGS_MSI) { 518 if (ec_busy_polling) {
512 /* Perform busy polling */ 519 /* Perform busy polling */
513 if (ec_transaction_completed(ec)) 520 if (ec_transaction_completed(ec))
514 return 0; 521 return 0;
@@ -985,7 +992,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
985 if (function != ACPI_READ && function != ACPI_WRITE) 992 if (function != ACPI_READ && function != ACPI_WRITE)
986 return AE_BAD_PARAMETER; 993 return AE_BAD_PARAMETER;
987 994
988 if (EC_FLAGS_MSI || bits > 8) 995 if (ec_busy_polling || bits > 8)
989 acpi_ec_burst_enable(ec); 996 acpi_ec_burst_enable(ec);
990 997
991 for (i = 0; i < bytes; ++i, ++address, ++value) 998 for (i = 0; i < bytes; ++i, ++address, ++value)
@@ -993,7 +1000,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
993 acpi_ec_read(ec, address, value) : 1000 acpi_ec_read(ec, address, value) :
994 acpi_ec_write(ec, address, *value); 1001 acpi_ec_write(ec, address, *value);
995 1002
996 if (EC_FLAGS_MSI || bits > 8) 1003 if (ec_busy_polling || bits > 8)
997 acpi_ec_burst_disable(ec); 1004 acpi_ec_burst_disable(ec);
998 1005
999 switch (result) { 1006 switch (result) {
@@ -1262,11 +1269,11 @@ static int ec_validate_ecdt(const struct dmi_system_id *id)
1262 return 0; 1269 return 0;
1263} 1270}
1264 1271
1265/* MSI EC needs special treatment, enable it */ 1272/* EC firmware needs special polling mode, enable it */
1266static int ec_flag_msi(const struct dmi_system_id *id) 1273static int ec_use_busy_polling(const struct dmi_system_id *id)
1267{ 1274{
1268 pr_debug("Detected MSI hardware, enabling workarounds.\n"); 1275 pr_debug("Detected the EC firmware requiring busy polling mode.\n");
1269 EC_FLAGS_MSI = 1; 1276 ec_busy_polling = 1;
1270 EC_FLAGS_VALIDATE_ECDT = 1; 1277 EC_FLAGS_VALIDATE_ECDT = 1;
1271 return 0; 1278 return 0;
1272} 1279}
@@ -1313,27 +1320,27 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {
1313 DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), 1320 DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
1314 DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL}, 1321 DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL},
1315 { 1322 {
1316 ec_flag_msi, "MSI hardware", { 1323 ec_use_busy_polling, "MSI hardware", {
1317 DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star")}, NULL}, 1324 DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star")}, NULL},
1318 { 1325 {
1319 ec_flag_msi, "MSI hardware", { 1326 ec_use_busy_polling, "MSI hardware", {
1320 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star")}, NULL}, 1327 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star")}, NULL},
1321 { 1328 {
1322 ec_flag_msi, "MSI hardware", { 1329 ec_use_busy_polling, "MSI hardware", {
1323 DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL}, 1330 DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL},
1324 { 1331 {
1325 ec_flag_msi, "MSI hardware", { 1332 ec_use_busy_polling, "MSI hardware", {
1326 DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL}, 1333 DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL},
1327 { 1334 {
1328 ec_flag_msi, "Quanta hardware", { 1335 ec_use_busy_polling, "Quanta hardware", {
1329 DMI_MATCH(DMI_SYS_VENDOR, "Quanta"), 1336 DMI_MATCH(DMI_SYS_VENDOR, "Quanta"),
1330 DMI_MATCH(DMI_PRODUCT_NAME, "TW8/SW8/DW8"),}, NULL}, 1337 DMI_MATCH(DMI_PRODUCT_NAME, "TW8/SW8/DW8"),}, NULL},
1331 { 1338 {
1332 ec_flag_msi, "Quanta hardware", { 1339 ec_use_busy_polling, "Quanta hardware", {
1333 DMI_MATCH(DMI_SYS_VENDOR, "Quanta"), 1340 DMI_MATCH(DMI_SYS_VENDOR, "Quanta"),
1334 DMI_MATCH(DMI_PRODUCT_NAME, "TW9/SW9"),}, NULL}, 1341 DMI_MATCH(DMI_PRODUCT_NAME, "TW9/SW9"),}, NULL},
1335 { 1342 {
1336 ec_flag_msi, "Clevo W350etq", { 1343 ec_use_busy_polling, "Clevo W350etq", {
1337 DMI_MATCH(DMI_SYS_VENDOR, "CLEVO CO."), 1344 DMI_MATCH(DMI_SYS_VENDOR, "CLEVO CO."),
1338 DMI_MATCH(DMI_PRODUCT_NAME, "W35_37ET"),}, NULL}, 1345 DMI_MATCH(DMI_PRODUCT_NAME, "W35_37ET"),}, NULL},
1339 { 1346 {