[linux] 01/02: ACPI / EC: Use busy polling mode when GPE is not enabled

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Mon Mar 13 20:27:20 UTC 2017


This is an automated email from the git hooks/post-receive script.

carnil pushed a commit to branch sid
in repository linux.

commit 11c12948995995f9d7674b17a8c6f107d083fff7
Author: Salvatore Bonaccorso <carnil at debian.org>
Date:   Mon Mar 13 07:33:18 2017 +0100

    ACPI / EC: Use busy polling mode when GPE is not enabled
    
    Thanks: Jakobus Schurz <jakobus.schurz at gmail.com>
    Closes: #846792
---
 debian/changelog                                   |   4 +
 ...-busy-polling-mode-when-GPE-is-not-enable.patch | 167 +++++++++++++++++++++
 debian/patches/series                              |   1 +
 3 files changed, 172 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 201946f..26d596d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -144,6 +144,10 @@ linux (4.9.14-1) UNRELEASED; urgency=medium
     - timer/hrtimer: check properly for a running timer
   * tty: n_hdlc: get rid of racy n_hdlc.tbuf (CVE-2017-2636)
 
+  [ Salvatore Bonaccorso ]
+  * ACPI / EC: Use busy polling mode when GPE is not enabled.
+    Thanks to Jakobus Schurz <jakobus.schurz at gmail.com> (Closes: #846792)
+
  -- Ben Hutchings <ben at decadent.org.uk>  Wed, 01 Mar 2017 15:42:54 +0000
 
 linux (4.9.13-1) unstable; urgency=medium
diff --git a/debian/patches/bugfix/all/ACPI-EC-Use-busy-polling-mode-when-GPE-is-not-enable.patch b/debian/patches/bugfix/all/ACPI-EC-Use-busy-polling-mode-when-GPE-is-not-enable.patch
new file mode 100644
index 0000000..ad94bb5
--- /dev/null
+++ b/debian/patches/bugfix/all/ACPI-EC-Use-busy-polling-mode-when-GPE-is-not-enable.patch
@@ -0,0 +1,167 @@
+From: Lv Zheng <lv.zheng at intel.com>
+Date: Fri, 20 Jan 2017 16:42:48 +0800
+Subject: ACPI / EC: Use busy polling mode when GPE is not enabled
+Origin: https://git.kernel.org/linus/c3a696b6e8f8f75f9f75e556a9f9f6472eae2655
+Bug: https://bugzilla.kernel.org/show_bug.cgi?id=191561
+Bug-Debian: https://bugs.debian.org/846792
+
+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 at gmail.com>
+Tested-by: Chen Yu <yu.c.chen at intel.com>
+Signed-off-by: Lv Zheng <lv.zheng at intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+---
+ drivers/acpi/ec.c       | 62 ++++++++++++++++++++++++-------------------------
+ drivers/acpi/internal.h |  4 ++--
+ 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)
+ 
+ static int ec_guard(struct acpi_ec *ec)
+ {
+-	unsigned long guard = usecs_to_jiffies(ec_polling_guard);
++	unsigned long guard = usecs_to_jiffies(ec->polling_guard);
+ 	unsigned long timeout = ec->timestamp + guard;
+ 
+ 	/* Ensure guarding period before polling EC status */
+ 	do {
+-		if (ec_busy_polling) {
++		if (ec->busy_polling) {
+ 			/* Perform busy polling */
+ 			if (ec_transaction_completed(ec))
+ 				return 0;
+@@ -973,6 +973,28 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
+ 	spin_unlock_irqrestore(&ec->lock, flags);
+ }
+ 
++static void acpi_ec_enter_noirq(struct acpi_ec *ec)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&ec->lock, flags);
++	ec->busy_polling = true;
++	ec->polling_guard = 0;
++	ec_log_drv("interrupt blocked");
++	spin_unlock_irqrestore(&ec->lock, flags);
++}
++
++static void acpi_ec_leave_noirq(struct acpi_ec *ec)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&ec->lock, flags);
++	ec->busy_polling = ec_busy_polling;
++	ec->polling_guard = ec_polling_guard;
++	ec_log_drv("interrupt unblocked");
++	spin_unlock_irqrestore(&ec->lock, flags);
++}
++
+ void acpi_ec_block_transactions(void)
+ {
+ 	struct acpi_ec *ec = first_ec;
+@@ -1253,7 +1275,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
+ 	if (function != ACPI_READ && function != ACPI_WRITE)
+ 		return AE_BAD_PARAMETER;
+ 
+-	if (ec_busy_polling || bits > 8)
++	if (ec->busy_polling || bits > 8)
+ 		acpi_ec_burst_enable(ec);
+ 
+ 	for (i = 0; i < bytes; ++i, ++address, ++value)
+@@ -1261,7 +1283,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
+ 			acpi_ec_read(ec, address, value) :
+ 			acpi_ec_write(ec, address, *value);
+ 
+-	if (ec_busy_polling || bits > 8)
++	if (ec->busy_polling || bits > 8)
+ 		acpi_ec_burst_disable(ec);
+ 
+ 	switch (result) {
+@@ -1304,6 +1326,8 @@ static struct acpi_ec *acpi_ec_alloc(void)
+ 	spin_lock_init(&ec->lock);
+ 	INIT_WORK(&ec->work, acpi_ec_event_handler);
+ 	ec->timestamp = jiffies;
++	ec->busy_polling = true;
++	ec->polling_guard = 0;
+ 	return ec;
+ }
+ 
+@@ -1365,6 +1389,7 @@ static int ec_install_handlers(struct acpi_ec *ec, bool handle_events)
+ 	acpi_ec_start(ec, false);
+ 
+ 	if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
++		acpi_ec_enter_noirq(ec);
+ 		status = acpi_install_address_space_handler(ec->handle,
+ 							    ACPI_ADR_SPACE_EC,
+ 							    &acpi_ec_space_handler,
+@@ -1404,6 +1429,7 @@ static int ec_install_handlers(struct acpi_ec *ec, bool handle_events)
+ 		/* This is not fatal as we can poll EC events */
+ 		if (ACPI_SUCCESS(status)) {
+ 			set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
++			acpi_ec_leave_noirq(ec);
+ 			if (test_bit(EC_FLAGS_STARTED, &ec->flags) &&
+ 			    ec->reference_count >= 1)
+ 				acpi_ec_enable_gpe(ec, true);
+@@ -1786,34 +1812,6 @@ int __init acpi_ec_ecdt_probe(void)
+ }
+ 
+ #ifdef CONFIG_PM_SLEEP
+-static void acpi_ec_enter_noirq(struct acpi_ec *ec)
+-{
+-	unsigned long flags;
+-
+-	if (ec == first_ec) {
+-		spin_lock_irqsave(&ec->lock, flags);
+-		ec->saved_busy_polling = ec_busy_polling;
+-		ec->saved_polling_guard = ec_polling_guard;
+-		ec_busy_polling = true;
+-		ec_polling_guard = 0;
+-		ec_log_drv("interrupt blocked");
+-		spin_unlock_irqrestore(&ec->lock, flags);
+-	}
+-}
+-
+-static void acpi_ec_leave_noirq(struct acpi_ec *ec)
+-{
+-	unsigned long flags;
+-
+-	if (ec == first_ec) {
+-		spin_lock_irqsave(&ec->lock, flags);
+-		ec_busy_polling = ec->saved_busy_polling;
+-		ec_polling_guard = ec->saved_polling_guard;
+-		ec_log_drv("interrupt unblocked");
+-		spin_unlock_irqrestore(&ec->lock, flags);
+-	}
+-}
+-
+ static int acpi_ec_suspend_noirq(struct device *dev)
+ {
+ 	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 {
+ 	struct work_struct work;
+ 	unsigned long timestamp;
+ 	unsigned long nr_pending_queries;
+-	bool saved_busy_polling;
+-	unsigned int saved_polling_guard;
++	bool busy_polling;
++	unsigned int polling_guard;
+ };
+ 
+ extern struct acpi_ec *first_ec;
+-- 
+2.11.0
+
diff --git a/debian/patches/series b/debian/patches/series
index f25eebe..7156e7f 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -82,6 +82,7 @@ bugfix/all/media-dvb-usb-dibusb-mc-common-add-module_license.patch
 bugfix/all/media-dvb-usb-don-t-use-stack-for-firmware-load.patch
 bugfix/all/media-dvb-usb-don-t-use-stack-for-reset-either.patch
 bugfix/all/kbuild-include-addtree-remove-quotes-before-matching-path.patch
+bugfix/all/ACPI-EC-Use-busy-polling-mode-when-GPE-is-not-enable.patch
 
 # Miscellaneous features
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list