mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org
Cc: stable-review@kernel.org, torvalds@linux-foundation.org,
	akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk,
	"Alexey Starikovskiy" <astarikovskiy@suse.de>,
	"Len Brown" <len.brown@intel.com>,
	"François Valenduc" <francois.valenduc@tvcablenet.be>
Subject: [17/29] ACPI: EC: Accelerate query execution
Date: Fri, 22 Jan 2010 16:10:01 -0800	[thread overview]
Message-ID: <20100123001112.394557014@mini.kroah.org> (raw)
In-Reply-To: <20100123001145.GA7391@kroah.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 6611 bytes --]

2.6.32-stable review patch.  If anyone has any objections, please let us know.

------------------

From: Alexey Starikovskiy <astarikovskiy@suse.de>

commit a62e8f1978f49e52f87a711ff6711b323d4b12ff upstream.

Split EC query handling into acknowledge and execution phase.
This allows much smaller pending query lattency and lowers chances
of EC going "wild" and losing events.

Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14858

Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
Cc: François Valenduc <francois.valenduc@tvcablenet.be>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/acpi/ec.c |  122 ++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 77 insertions(+), 45 deletions(-)

--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -201,14 +201,13 @@ unlock:
 	spin_unlock_irqrestore(&ec->curr_lock, flags);
 }
 
-static void acpi_ec_gpe_query(void *ec_cxt);
+static int acpi_ec_sync_query(struct acpi_ec *ec);
 
-static int ec_check_sci(struct acpi_ec *ec, u8 state)
+static int ec_check_sci_sync(struct acpi_ec *ec, u8 state)
 {
 	if (state & ACPI_EC_FLAG_SCI) {
 		if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
-			return acpi_os_execute(OSL_EC_BURST_HANDLER,
-				acpi_ec_gpe_query, ec);
+			return acpi_ec_sync_query(ec);
 	}
 	return 0;
 }
@@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(
 {
 	unsigned long tmp;
 	int ret = 0;
-	pr_debug(PREFIX "transaction start\n");
-	/* disable GPE during transaction if storm is detected */
-	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
-		acpi_disable_gpe(NULL, ec->gpe);
-	}
 	if (EC_FLAGS_MSI)
 		udelay(ACPI_EC_MSI_UDELAY);
 	/* start transaction */
@@ -269,16 +263,6 @@ static int acpi_ec_transaction_unlocked(
 	spin_lock_irqsave(&ec->curr_lock, tmp);
 	ec->curr = NULL;
 	spin_unlock_irqrestore(&ec->curr_lock, tmp);
-	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
-		/* check if we received SCI during transaction */
-		ec_check_sci(ec, acpi_ec_read_status(ec));
-		/* it is safe to enable GPE outside of transaction */
-		acpi_enable_gpe(NULL, ec->gpe);
-	} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
-		pr_info(PREFIX "GPE storm detected, "
-			"transactions will use polling mode\n");
-		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
-	}
 	return ret;
 }
 
@@ -321,7 +305,24 @@ static int acpi_ec_transaction(struct ac
 		status = -ETIME;
 		goto end;
 	}
+	pr_debug(PREFIX "transaction start\n");
+	/* disable GPE during transaction if storm is detected */
+	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+		acpi_disable_gpe(NULL, ec->gpe);
+	}
+
 	status = acpi_ec_transaction_unlocked(ec, t);
+
+	/* check if we received SCI during transaction */
+	ec_check_sci_sync(ec, acpi_ec_read_status(ec));
+	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+		/* it is safe to enable GPE outside of transaction */
+		acpi_enable_gpe(NULL, ec->gpe);
+	} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
+		pr_info(PREFIX "GPE storm detected, "
+			"transactions will use polling mode\n");
+		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
+	}
 end:
 	if (ec->global_lock)
 		acpi_release_global_lock(glk);
@@ -443,7 +444,7 @@ int ec_transaction(u8 command,
 
 EXPORT_SYMBOL(ec_transaction);
 
-static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
+static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
 {
 	int result;
 	u8 d;
@@ -452,20 +453,16 @@ static int acpi_ec_query(struct acpi_ec 
 				.wlen = 0, .rlen = 1};
 	if (!ec || !data)
 		return -EINVAL;
-
 	/*
 	 * Query the EC to find out which _Qxx method we need to evaluate.
 	 * Note that successful completion of the query causes the ACPI_EC_SCI
 	 * bit to be cleared (and thus clearing the interrupt source).
 	 */
-
-	result = acpi_ec_transaction(ec, &t);
+	result = acpi_ec_transaction_unlocked(ec, &t);
 	if (result)
 		return result;
-
 	if (!d)
 		return -ENODATA;
-
 	*data = d;
 	return 0;
 }
@@ -509,43 +506,78 @@ void acpi_ec_remove_query_handler(struct
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_run(void *cxt)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
-	struct acpi_ec_query_handler *handler, copy;
-
-	if (!ec || acpi_ec_query(ec, &value))
+	struct acpi_ec_query_handler *handler = cxt;
+	if (!handler)
 		return;
-	mutex_lock(&ec->lock);
+	pr_debug(PREFIX "start query execution\n");
+	if (handler->func)
+		handler->func(handler->data);
+	else if (handler->handle)
+		acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
+	pr_debug(PREFIX "stop query execution\n");
+	kfree(handler);
+}
+
+static int acpi_ec_sync_query(struct acpi_ec *ec)
+{
+	u8 value = 0;
+	int status;
+	struct acpi_ec_query_handler *handler, *copy;
+	if ((status = acpi_ec_query_unlocked(ec, &value)))
+		return status;
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
 			/* have custom handler for this bit */
-			memcpy(&copy, handler, sizeof(copy));
-			mutex_unlock(&ec->lock);
-			if (copy.func) {
-				copy.func(copy.data);
-			} else if (copy.handle) {
-				acpi_evaluate_object(copy.handle, NULL, NULL, NULL);
-			}
-			return;
+			copy = kmalloc(sizeof(*handler), GFP_KERNEL);
+			if (!copy)
+				return -ENOMEM;
+			memcpy(copy, handler, sizeof(*copy));
+			pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value);
+			return acpi_os_execute(OSL_GPE_HANDLER,
+				acpi_ec_run, copy);
 		}
 	}
+	return 0;
+}
+
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	if (!ec)
+		return;
+	mutex_lock(&ec->lock);
+	acpi_ec_sync_query(ec);
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt);
+
+static int ec_check_sci(struct acpi_ec *ec, u8 state)
+{
+	if (state & ACPI_EC_FLAG_SCI) {
+		if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
+			pr_debug(PREFIX "push gpe query to the queue\n");
+			return acpi_os_execute(OSL_NOTIFY_HANDLER,
+				acpi_ec_gpe_query, ec);
+		}
+	}
+	return 0;
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	struct acpi_ec *ec = data;
-	u8 status;
 
 	pr_debug(PREFIX "~~~> interrupt\n");
-	status = acpi_ec_read_status(ec);
 
-	advance_transaction(ec, status);
-	if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0)
+	advance_transaction(ec, acpi_ec_read_status(ec));
+	if (ec_transaction_done(ec) &&
+	    (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
 		wake_up(&ec->wait);
-	ec_check_sci(ec, status);
+		ec_check_sci(ec, acpi_ec_read_status(ec));
+	}
 	return ACPI_INTERRUPT_HANDLED;
 }
 



  parent reply	other threads:[~2010-01-23  0:19 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-23  0:11 [00/29] 2.6.32.6 stable review Greg KH
2010-01-23  0:09 ` [01/29] x86, msr/cpuid: Register enough minors for the MSR and CPUID drivers Greg KH
2010-01-23  0:09 ` [02/29] V4L/DVB (13900): gspca - sunplus: Fix bridge exchanges Greg KH
2010-01-23  0:09 ` [03/29] Staging: asus_oled: fix oops in 2.6.32.2 Greg KH
2010-01-23  0:09 ` [04/29] Staging: hv: fix smp problems in the hyperv core code Greg KH
2010-01-23  0:09 ` [05/29] tty: fix race in tty_fasync Greg KH
2010-01-23  0:09 ` [06/29] ecryptfs: use after free Greg KH
2010-01-23  0:09 ` [07/29] ecryptfs: initialize private persistent file before dereferencing pointer Greg KH
2010-01-23  0:09 ` [08/29] nozomi: quick fix for the close/close bug Greg KH
2010-01-23  0:09 ` [09/29] serial: 8250_pnp: use wildcard for serial Wacom tablets Greg KH
2010-01-23  0:09 ` [10/29] usb: serial: fix memory leak in generic driver Greg KH
2010-01-23  0:09 ` [11/29] USB: fix bitmask merge error Greg KH
2010-01-23  0:09 ` [12/29] USB: Dont use GFP_KERNEL while we cannot reset a storage device Greg KH
2010-01-23  0:09 ` [13/29] USB: EHCI: fix handling of unusual interrupt intervals Greg KH
2010-01-23  0:09 ` [14/29] USB: EHCI & UHCI: fix race between root-hub suspend and port resume Greg KH
2010-01-23  0:09 ` [15/29] USB: add missing delay during remote wakeup Greg KH
2010-01-23  0:10 ` [16/29] USB: add speed values for USB 3.0 and wireless controllers Greg KH
2010-01-23  0:10 ` Greg KH [this message]
2010-01-23  0:10 ` [18/29] ACPI: EC: Add wait for irq storm Greg KH
2010-01-23  0:10 ` [19/29] SCSI: enclosure: fix oops while iterating enclosure_status array Greg KH
2010-01-23  0:10 ` [20/29] drm/i915: Read the response after issuing DDC bus switch command Greg KH
2010-01-23  0:10 ` [21/29] drm/i915: try another possible DDC bus for the SDVO device with multiple outputs Greg KH
2010-01-23  0:10 ` [22/29] block: bdev_stack_limits wrapper Greg KH
2010-01-23  0:10 ` [23/29] DM: Fix device mapper topology stacking Greg KH
2010-01-23  0:10 ` [24/29] x86/PCI/PAT: return EINVAL for pci mmap WC request for !pat_enabled Greg KH
2010-01-23  0:10 ` [25/29] USB: fix usbstorage for 2770:915d delivers no FAT Greg KH
2010-01-23  2:43   ` [Stable-review] " Ben Hutchings
2010-01-23  6:05     ` Greg KH
2010-01-23  0:10 ` [26/29] vmalloc: remove BUG_ON due to racy counting of VM_LAZY_FREE Greg KH
2010-01-23  0:10 ` [27/29] perf timechart: Use tid not pid for COMM change Greg KH
2010-01-23  0:10 ` [28/29] perf events: Dont report side-band events on each cpu for per-task-per-cpu events Greg KH
2010-01-23 11:38   ` [Stable-review] " Stefan Bader
2010-01-23 15:33     ` Greg KH
2010-01-25 18:04     ` Greg KH
2010-01-23  0:10 ` [29/29] perf: Honour event state for aux stream data Greg KH
2010-01-24  7:21 ` [stable] [00/29] 2.6.32.6 stable review Andrew Morton
2010-01-24 16:29   ` Thomas Gleixner
2010-01-25  8:40     ` Ozan Çağlayan
2010-01-25 17:16       ` Greg KH
2010-01-25 17:39         ` Ozan Çağlayan
2010-01-25 17:46           ` Greg KH
2010-01-25 19:09             ` Greg KH
2010-01-25 18:22         ` Thomas Gleixner
2010-01-25 17:15     ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100123001112.394557014@mini.kroah.org \
    --to=gregkh@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=astarikovskiy@suse.de \
    --cc=francois.valenduc@tvcablenet.be \
    --cc=len.brown@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable-review@kernel.org \
    --cc=stable@kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome