aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2017-01-20 03:42:48 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-01-30 06:12:52 -0500
commitc3a696b6e8f8f75f9f75e556a9f9f6472eae2655 (patch)
treefd6a1a2545ada67bb777a9663947e340212abb9a
parent4c237371f290d1ed3b2071dd43554362137b1cce (diff)
ACPI / EC: Use busy polling mode when GPE is not enabled
When GPE is not enabled, it is not efficient to use the wait polling mode as it introduces an unexpected scheduler delay. So before the GPE handler is installed, this patch uses busy polling mode for all EC(s) and the logic can be applied to non boot EC(s) during the suspend/resume process. Link: https://bugzilla.kernel.org/show_bug.cgi?id=191561 Tested-by: Jakobus Schurz <jakobus.schurz@gmail.com> 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.c62
-rw-r--r--drivers/acpi/internal.h4
2 files changed, 32 insertions, 34 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 6a32cd4ec9da..c24235d8fb52 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -704,12 +704,12 @@ static void start_transaction(struct acpi_ec *ec)
704 704
705static int ec_guard(struct acpi_ec *ec) 705static int ec_guard(struct acpi_ec *ec)
706{ 706{
707 unsigned long guard = usecs_to_jiffies(ec_polling_guard); 707 unsigned long guard = usecs_to_jiffies(ec->polling_guard);
708 unsigned long timeout = ec->timestamp + guard; 708 unsigned long timeout = ec->timestamp + guard;
709 709
710 /* Ensure guarding period before polling EC status */ 710 /* Ensure guarding period before polling EC status */
711 do { 711 do {
712 if (ec_busy_polling) { 712 if (ec->busy_polling) {
713 /* Perform busy polling */ 713 /* Perform busy polling */
714 if (ec_transaction_completed(ec)) 714 if (ec_transaction_completed(ec))
715 return 0; 715 return 0;
@@ -973,6 +973,28 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
973 spin_unlock_irqrestore(&ec->lock, flags); 973 spin_unlock_irqrestore(&ec->lock, flags);
974} 974}
975 975
976static void acpi_ec_enter_noirq(struct acpi_ec *ec)
977{
978 unsigned long flags;
979
980 spin_lock_irqsave(&ec->lock, flags);
981 ec->busy_polling = true;
982 ec->polling_guard = 0;
983 ec_log_drv("interrupt blocked");
984 spin_unlock_irqrestore(&ec->lock, flags);
985}
986
987static void acpi_ec_leave_noirq(struct acpi_ec *ec)
988{
989 unsigned long flags;
990
991 spin_lock_irqsave(&ec->lock, flags);
992 ec->busy_polling = ec_busy_polling;
993 ec->polling_guard = ec_polling_guard;
994 ec_log_drv("interrupt unblocked");
995 spin_unlock_irqrestore(&ec->lock, flags);
996}
997
976void acpi_ec_block_transactions(void) 998void acpi_ec_block_transactions(void)
977{ 999{
978 struct acpi_ec *ec = first_ec; 1000 struct acpi_ec *ec = first_ec;
@@ -1253,7 +1275,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
1253 if (function != ACPI_READ && function != ACPI_WRITE) 1275 if (function != ACPI_READ && function != ACPI_WRITE)
1254 return AE_BAD_PARAMETER; 1276 return AE_BAD_PARAMETER;
1255 1277
1256 if (ec_busy_polling || bits > 8) 1278 if (ec->busy_polling || bits > 8)
1257 acpi_ec_burst_enable(ec); 1279 acpi_ec_burst_enable(ec);
1258 1280
1259 for (i = 0; i < bytes; ++i, ++address, ++value) 1281 for (i = 0; i < bytes; ++i, ++address, ++value)
@@ -1261,7 +1283,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
1261 acpi_ec_read(ec, address, value) : 1283 acpi_ec_read(ec, address, value) :
1262 acpi_ec_write(ec, address, *value); 1284 acpi_ec_write(ec, address, *value);
1263 1285
1264 if (ec_busy_polling || bits > 8) 1286 if (ec->busy_polling || bits > 8)
1265 acpi_ec_burst_disable(ec); 1287 acpi_ec_burst_disable(ec);
1266 1288
1267 switch (result) { 1289 switch (result) {
@@ -1304,6 +1326,8 @@ static struct acpi_ec *acpi_ec_alloc(void)
1304 spin_lock_init(&ec->lock); 1326 spin_lock_init(&ec->lock);
1305 INIT_WORK(&ec->work, acpi_ec_event_handler); 1327 INIT_WORK(&ec->work, acpi_ec_event_handler);
1306 ec->timestamp = jiffies; 1328 ec->timestamp = jiffies;
1329 ec->busy_polling = true;
1330 ec->polling_guard = 0;
1307 return ec; 1331 return ec;
1308} 1332}
1309 1333
@@ -1365,6 +1389,7 @@ static int ec_install_handlers(struct acpi_ec *ec, bool handle_events)
1365 acpi_ec_start(ec, false); 1389 acpi_ec_start(ec, false);
1366 1390
1367 if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { 1391 if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
1392 acpi_ec_enter_noirq(ec);
1368 status = acpi_install_address_space_handler(ec->handle, 1393 status = acpi_install_address_space_handler(ec->handle,
1369 ACPI_ADR_SPACE_EC, 1394 ACPI_ADR_SPACE_EC,
1370 &acpi_ec_space_handler, 1395 &acpi_ec_space_handler,
@@ -1404,6 +1429,7 @@ static int ec_install_handlers(struct acpi_ec *ec, bool handle_events)
1404 /* This is not fatal as we can poll EC events */ 1429 /* This is not fatal as we can poll EC events */
1405 if (ACPI_SUCCESS(status)) { 1430 if (ACPI_SUCCESS(status)) {
1406 set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags); 1431 set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
1432 acpi_ec_leave_noirq(ec);
1407 if (test_bit(EC_FLAGS_STARTED, &ec->flags) && 1433 if (test_bit(EC_FLAGS_STARTED, &ec->flags) &&
1408 ec->reference_count >= 1) 1434 ec->reference_count >= 1)
1409 acpi_ec_enable_gpe(ec, true); 1435 acpi_ec_enable_gpe(ec, true);
@@ -1786,34 +1812,6 @@ error:
1786} 1812}
1787 1813
1788#ifdef CONFIG_PM_SLEEP 1814#ifdef CONFIG_PM_SLEEP
1789static void acpi_ec_enter_noirq(struct acpi_ec *ec)
1790{
1791 unsigned long flags;
1792
1793 if (ec == first_ec) {
1794 spin_lock_irqsave(&ec->lock, flags);
1795 ec->saved_busy_polling = ec_busy_polling;
1796 ec->saved_polling_guard = ec_polling_guard;
1797 ec_busy_polling = true;
1798 ec_polling_guard = 0;
1799 ec_log_drv("interrupt blocked");
1800 spin_unlock_irqrestore(&ec->lock, flags);
1801 }
1802}
1803
1804static void acpi_ec_leave_noirq(struct acpi_ec *ec)
1805{
1806 unsigned long flags;
1807
1808 if (ec == first_ec) {
1809 spin_lock_irqsave(&ec->lock, flags);
1810 ec_busy_polling = ec->saved_busy_polling;
1811 ec_polling_guard = ec->saved_polling_guard;
1812 ec_log_drv("interrupt unblocked");
1813 spin_unlock_irqrestore(&ec->lock, flags);
1814 }
1815}
1816
1817static int acpi_ec_suspend_noirq(struct device *dev) 1815static int acpi_ec_suspend_noirq(struct device *dev)
1818{ 1816{
1819 struct acpi_ec *ec = 1817 struct acpi_ec *ec =
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 0c452265c111..219b90bc0922 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -172,8 +172,8 @@ struct acpi_ec {
172 struct work_struct work; 172 struct work_struct work;
173 unsigned long timestamp; 173 unsigned long timestamp;
174 unsigned long nr_pending_queries; 174 unsigned long nr_pending_queries;
175 bool saved_busy_polling; 175 bool busy_polling;
176 unsigned int saved_polling_guard; 176 unsigned int polling_guard;
177}; 177};
178 178
179extern struct acpi_ec *first_ec; 179extern struct acpi_ec *first_ec;