Skip to content

Commit c3a696b

Browse files
Lv Zhengrafaeljw
authored andcommitted
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 <[email protected]> Tested-by: Chen Yu <[email protected]> Signed-off-by: Lv Zheng <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 4c23737 commit c3a696b

File tree

2 files changed

+32
-34
lines changed

2 files changed

+32
-34
lines changed

drivers/acpi/ec.c

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -704,12 +704,12 @@ static void start_transaction(struct acpi_ec *ec)
704704

705705
static int ec_guard(struct acpi_ec *ec)
706706
{
707-
unsigned long guard = usecs_to_jiffies(ec_polling_guard);
707+
unsigned long guard = usecs_to_jiffies(ec->polling_guard);
708708
unsigned long timeout = ec->timestamp + guard;
709709

710710
/* Ensure guarding period before polling EC status */
711711
do {
712-
if (ec_busy_polling) {
712+
if (ec->busy_polling) {
713713
/* Perform busy polling */
714714
if (ec_transaction_completed(ec))
715715
return 0;
@@ -973,6 +973,28 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
973973
spin_unlock_irqrestore(&ec->lock, flags);
974974
}
975975

976+
static 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+
987+
static 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+
976998
void acpi_ec_block_transactions(void)
977999
{
9781000
struct acpi_ec *ec = first_ec;
@@ -1253,15 +1275,15 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
12531275
if (function != ACPI_READ && function != ACPI_WRITE)
12541276
return AE_BAD_PARAMETER;
12551277

1256-
if (ec_busy_polling || bits > 8)
1278+
if (ec->busy_polling || bits > 8)
12571279
acpi_ec_burst_enable(ec);
12581280

12591281
for (i = 0; i < bytes; ++i, ++address, ++value)
12601282
result = (function == ACPI_READ) ?
12611283
acpi_ec_read(ec, address, value) :
12621284
acpi_ec_write(ec, address, *value);
12631285

1264-
if (ec_busy_polling || bits > 8)
1286+
if (ec->busy_polling || bits > 8)
12651287
acpi_ec_burst_disable(ec);
12661288

12671289
switch (result) {
@@ -1304,6 +1326,8 @@ static struct acpi_ec *acpi_ec_alloc(void)
13041326
spin_lock_init(&ec->lock);
13051327
INIT_WORK(&ec->work, acpi_ec_event_handler);
13061328
ec->timestamp = jiffies;
1329+
ec->busy_polling = true;
1330+
ec->polling_guard = 0;
13071331
return ec;
13081332
}
13091333

@@ -1365,6 +1389,7 @@ static int ec_install_handlers(struct acpi_ec *ec, bool handle_events)
13651389
acpi_ec_start(ec, false);
13661390

13671391
if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
1392+
acpi_ec_enter_noirq(ec);
13681393
status = acpi_install_address_space_handler(ec->handle,
13691394
ACPI_ADR_SPACE_EC,
13701395
&acpi_ec_space_handler,
@@ -1404,6 +1429,7 @@ static int ec_install_handlers(struct acpi_ec *ec, bool handle_events)
14041429
/* This is not fatal as we can poll EC events */
14051430
if (ACPI_SUCCESS(status)) {
14061431
set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
1432+
acpi_ec_leave_noirq(ec);
14071433
if (test_bit(EC_FLAGS_STARTED, &ec->flags) &&
14081434
ec->reference_count >= 1)
14091435
acpi_ec_enable_gpe(ec, true);
@@ -1786,34 +1812,6 @@ int __init acpi_ec_ecdt_probe(void)
17861812
}
17871813

17881814
#ifdef CONFIG_PM_SLEEP
1789-
static 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-
1804-
static 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-
18171815
static int acpi_ec_suspend_noirq(struct device *dev)
18181816
{
18191817
struct acpi_ec *ec =

drivers/acpi/internal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ struct acpi_ec {
172172
struct work_struct work;
173173
unsigned long timestamp;
174174
unsigned long nr_pending_queries;
175-
bool saved_busy_polling;
176-
unsigned int saved_polling_guard;
175+
bool busy_polling;
176+
unsigned int polling_guard;
177177
};
178178

179179
extern struct acpi_ec *first_ec;

0 commit comments

Comments
 (0)