Skip to contentSkip to conversation

acpi: Avoid dropping rapid hotkey events (or other GPEs) on Asus EeePC

PATCH In review Alan Jenkins 7 participants 29 messages Jul 15, 2008 – Aug 13, 2008 1 message not in the archive ACPI

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 acpi: Avoid dropping rapid hotkey events (or other GPEs) on Asus EeePC

It looks like this EC clears the SMI_EVT bit after every query, even if there are more events pending. The workaround is to repeatedly query the EC until it reports that no events remain.

This fixes a regression in 2.6.26 (from 2.6.25.3). Initially reported as "Asus Eee PC hotkeys stop working if pressed quickly" in bugzilla
<http://bugzilla.kernel.org/show_bug.cgi?id=11089>.

The regression was caused by a recently added check for interrupt storms. The Eee PC triggers this check and switches to polling. When multiple events arrive between polling intervals, only one is fetched from the EC. This causes erroneous behaviour; ultimately events stop being delivered altogether when the EC buffer overflows.

---

drivers/acpi/ec.c +13 -5
index 5622aee..2b4c5a2 100644
@@ -459,14 +459,10 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_gpe_run_handler(struct acpi_ec *ec, u8 value)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
 	struct acpi_ec_query_handler *handler, copy;
 
-	if (!ec || acpi_ec_query(ec, &value))
-		return;
 	mutex_lock(&ec->lock);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
@@ -484,6 +480,18 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	u8 value = 0;
+
+	if (!ec)
+		return;
+
+	while (!acpi_ec_query(ec, &value))
+		acpi_ec_gpe_run_handler(ec, value);
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	acpi_status status = AE_OK;
#1 lore raw

Hi Alan,

Thanks for the patch, ACK.

Regards,
Alex.

Quoted 58 lines · Alan Jenkins

It looks like this EC clears the SMI_EVT bit after every query, even if there are more events pending. The workaround is to repeatedly query the EC until it reports that no events remain.

This fixes a regression in 2.6.26 (from 2.6.25.3). Initially reported as "Asus Eee PC hotkeys stop working if pressed quickly" in bugzilla
<http://bugzilla.kernel.org/show_bug.cgi?id=11089>.

The regression was caused by a recently added check for interrupt storms. The Eee PC triggers this check and switches to polling. When multiple events arrive between polling intervals, only one is fetched from the EC. This causes erroneous behaviour; ultimately events stop being delivered altogether when the EC buffer overflows.

---

drivers/acpi/ec.c +13 -5
index 5622aee..2b4c5a2 100644
@@ -459,14 +459,10 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_gpe_run_handler(struct acpi_ec *ec, u8 value)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
 	struct acpi_ec_query_handler *handler, copy;
 
-	if (!ec || acpi_ec_query(ec, &value))
-		return;
 	mutex_lock(&ec->lock);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
@@ -484,6 +480,18 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	u8 value = 0;
+
+	if (!ec)
+		return;
+
+	while (!acpi_ec_query(ec, &value))
+		acpi_ec_gpe_run_handler(ec, value);
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	acpi_status status = AE_OK;
#2 lore raw
Quoted 1 line · Alexey Starikovskiy

Thanks for the patch, ACK.

This one fixes a potentially bad problem, since we could ignore more than just hot key EC events by accident. Maybe it should go to -stable?

Quoted 53 lines
Quoted 52 lines · Alan Jenkins

It looks like this EC clears the SMI_EVT bit after every query, even if there are more events pending. The workaround is to repeatedly query the EC until it reports that no events remain.

This fixes a regression in 2.6.26 (from 2.6.25.3). Initially reported as "Asus Eee PC hotkeys stop working if pressed quickly" in bugzilla
<http://bugzilla.kernel.org/show_bug.cgi?id=11089>.

The regression was caused by a recently added check for interrupt storms. The Eee PC triggers this check and switches to polling. When multiple events arrive between polling intervals, only one is fetched from the EC. This causes erroneous behaviour; ultimately events stop being delivered altogether when the EC buffer overflows.

---

drivers/acpi/ec.c +12 -3
index 5622aee..2b4c5a2 100644
@@ -459,14 +459,10 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
  EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 -static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_gpe_run_handler(struct acpi_ec *ec, u8 value)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
 	struct acpi_ec_query_handler *handler, copy;
 -	if (!ec || acpi_ec_query(ec, &value))
-		return;
 	mutex_lock(&ec->lock);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
@@ -484,6 +480,18 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	mutex_unlock(&ec->lock);
 }
 +static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	u8 value = 0;
+
+	if (!ec)
+		return;
+
+	while (!acpi_ec_query(ec, &value))
+		acpi_ec_gpe_run_handler(ec, value);
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	acpi_status status = AE_OK;
Signature · 4 lines
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh
#3 lore raw
Quoted 5 lines · Henrique de Moraes Holschuh
Quoted 1 line · Alexey Starikovskiy

Thanks for the patch, ACK.

This one fixes a potentially bad problem, since we could ignore more than just hot key EC events by accident. Maybe it should go to -stable?

I vote for it

Regards,
Alex.

#4 lore raw
Quoted 8 lines · Alexey Starikovskiy
Quoted 5 lines · Henrique de Moraes Holschuh
Quoted 1 line · Alexey Starikovskiy

Thanks for the patch, ACK.

This one fixes a potentially bad problem, since we could ignore more than just hot key EC events by accident. Maybe it should go to -stable?

I vote for it

Well, in that case, it would be best to tack a Cc: [email protected] git footer to it right away, I think.

IMHO, it would also be nice if the commit message made it more clear that the issue it solves can affect much more serious ACPI events than just hot key presses.

Signature · 4 lines
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh
#5 lore raw
Quoted 14 lines · Henrique de Moraes Holschuh
Quoted 11 lines · Alexey Starikovskiy
Quoted 7 lines · Henrique de Moraes Holschuh
Quoted 2 lines · Alexey Starikovskiy

Thanks for the patch, ACK.

This one fixes a potentially bad problem, since we could ignore more than just hot key EC events by accident. Maybe it should go to -stable?

I vote for it

Quoted 8 lines

Well, in that case, it would be best to tack a Cc: [email protected] git footer to it right away, I think.

IMHO, it would also be nice if the commit message made it more clear that the issue it solves can affect much more serious ACPI events than just hot key presses.

Actually Alexey has another patch in bugzilla (#10919) which resolves this issue in a better way. It avoids polling altogether, which is good because it means you get events immediately. My laptop has backlight adjustment hotkeys with hardware autorepeat, so it looks really jerky with polling.

So I think I should withdraw my patch and leave this to Alexey. I've tested his fix on my laptop and it works fine. It needs some more work though - e.g. at the moment it spams the kernel log.

Thanks,
Alan

#6 lore raw
Quoted 5 lines · Alan Jenkins

Actually Alexey has another patch in bugzilla (#10919) which resolves this issue in a better way. It avoids polling altogether, which is good because it means you get events immediately. My laptop has backlight adjustment hotkeys with hardware autorepeat, so it looks really jerky with polling.

We need to get ALL pending events from the EC, whether in polling mode or in interrupt mode (and we must make sure that we ARE going to queue any new interrupt before we stop checking for an empty pending event queue, otherwise there is a small window where a new event might get queued, and we are still masking the GPE and don't notice it). As long as the fix does that, it is all I care :-)

Signature · 4 lines
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh
#7 lore raw
Quoted 9 lines · Henrique de Moraes Holschuh
Quoted 6 lines · Alan Jenkins

Actually Alexey has another patch in bugzilla (#10919) which resolves this issue in a better way. It avoids polling altogether, which is good because it means you get events immediately. My laptop has backlight adjustment hotkeys with hardware autorepeat, so it looks really jerky with polling.

Quoted 9 lines

We need to get ALL pending events from the EC, whether in polling mode or in interrupt mode

(and we must make sure that we ARE going to queue any new interrupt before we stop checking for an empty pending event queue, otherwise there is a small window where a new event might get queued, and we are still masking the GPE and don't notice it). As long as the fix does that, it is all I care :-)

OK, I forgot about that. I need to do some reading on kernel programming, workqueues in particular, and redo my patch again. Sorry, Alexey! AFAICS there's still this (very) small window where events could be dropped.

Alan

#8 lore raw

cover acpi: GPE fixes

Here's what I came up with -

1. I was fighting against EC_FLAGS_QUERY_PENDING. This was used to ignore multiple successive GPE interrupts and treat them as a single GPE instead. That's the exact opposite of what we want to do. Let's get rid of it.

2. Then we can apply my original patch to fix GPE polling on the Asus EeePC, by repeatedly querying for GPEs until there are none left.

3. Finally, if I'm right then we now know how to handle "GPE interrupt storms". Some EC's are raising multiple interrupts before we acknowledge them. but they're just telling us how many events are pending. There's no harm in that, so we don't ever need to disable GPE interrupts. Let's get rid of GPE polling mode. (Code mainly stolen from Alexey).

Patch 3 would benefit from wider testing. Fortunately there are several open bugs about GPEs so it should be easy to find testers :-).

Alan

#9 lore raw

Re: [PATCH 0/3] acpi: GPE fixes

Quoted 6 lines · Alan Jenkins

Here's what I came up with -

1. I was fighting against EC_FLAGS_QUERY_PENDING. This was used to ignore multiple successive GPE interrupts and treat them as a single GPE instead. That's the exact opposite of what we want to do. Let's get rid of it.

Quoted 8 lines

2. Then we can apply my original patch to fix GPE polling on the Asus EeePC, by repeatedly querying for GPEs until there are none left.

3. Finally, if I'm right then we now know how to handle "GPE interrupt storms". Some EC's are raising multiple interrupts before we acknowledge them. but they're just telling us how many events are pending. There's no harm in that, so we don't ever need to disable GPE interrupts. Let's get rid of GPE polling mode. (Code mainly stolen from Alexey).

Hi,

I have seen the "GPE storm" message before but it had no apparent side-effects. Your patches do not seem to change this, although the message is now gone. Thanks! (I have an Acer Aspire 5720 laptop.)

Vegard

Signature · 4 lines
"The animistic metaphor of the bug that maliciously sneaked in while
the programmer was not looking is intellectually dishonest as it
disguises that the error is the programmer's own creation."
	-- E. W. Dijkstra, EWD1036

A message that is not in the archive (sent off-list or not yet received): [email protected]

#11 lore raw

PATCH 1/3 acpi: Rip out EC_FLAGS_QUERY_PENDING (prevent race condition)

From: Alan Jenkins <[email protected]>

If several GPE interrupts arrive at a time, then perform an equal number of queries in the workqueue. It doesn't matter if there are excess interrupts; the queries will just come back with nothing.

This won't fix anything, because it still switches to polling GPEs if more than five interrupts arrive at a time. But it simplifies the code, and makes it easier to modify further without introducing race conditions.

drivers/acpi/ec.c +2 -7
index 5622aee..8e4b1a4 100644
@@ -77,7 +77,6 @@ enum ec_event {
 
 enum {
 	EC_FLAGS_WAIT_GPE = 0,		/* Don't check status until GPE arrives */
-	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
 	EC_FLAGS_GPE_MODE,		/* Expect GPE to be sent for status change */
 	EC_FLAGS_NO_GPE,		/* Don't use GPE mode */
 	EC_FLAGS_RESCHEDULE_POLL	/* Re-schedule poll */
@@ -230,8 +229,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
 			       "finish-write timeout, command = %d\n", command);
 			goto end;
 		}
-	} else if (command == ACPI_EC_COMMAND_QUERY)
-		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+	}
 
 	for (; rdata_len > 0; --rdata_len) {
 		result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
@@ -502,7 +508,7 @@ static u32 acpi_ec_gpe_handler(void *data)
 		wake_up(&ec->wait);
 
 	if (state & ACPI_EC_FLAG_SCI) {
-		if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
+		if (ec->handlers_installed)
 			status = acpi_os_execute(OSL_EC_BURST_HANDLER,
 				acpi_ec_gpe_query, ec);
 	} else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
@@ -665,7 +671,6 @@ static struct acpi_ec *make_acpi_ec(void)
 	struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
 	if (!ec)
 		return NULL;
-	ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
 	mutex_init(&ec->lock);
 	init_waitqueue_head(&ec->wait);
 	INIT_LIST_HEAD(&ec->list);
@@ -858,8 +863,6 @@ static int acpi_ec_start(struct acpi_device *device)
 
 	ret = ec_install_handlers(ec);
 
-	/* EC is fully operational, allow queries */
-	clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
 	ec_schedule_ec_poll(ec);
 	return ret;
 }
#12 lore raw

Re: [PATCH 1/3] acpi: Rip out EC_FLAGS_QUERY_PENDING (prevent race condition)

Alan,

I don't think this is very good idea -- now every interrupt will add a new entry to workqueue, and given the rate of this interrupt, it could be become quite long.

Your second patch is redundant if you add queue entry for each interrupt, and as it does not require any investments into memory, I like it more.

Also, it is very cool to rip of things you don't care for, but that essentially reverts a fix done for 9998, so at least, you should ask these people if you broke their setups.

Regards,
Alex.

Quoted 63 lines · Alan Jenkins

From: Alan Jenkins <[email protected]>

If several GPE interrupts arrive at a time, then perform an equal number of queries in the workqueue. It doesn't matter if there are excess interrupts; the queries will just come back with nothing.

This won't fix anything, because it still switches to polling GPEs if more than five interrupts arrive at a time. But it simplifies the code, and makes it easier to modify further without introducing race conditions.

drivers/acpi/ec.c +2 -7
index 5622aee..8e4b1a4 100644
@@ -77,7 +77,6 @@ enum ec_event {
 
 enum {
 	EC_FLAGS_WAIT_GPE = 0,		/* Don't check status until GPE arrives */
-	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
 	EC_FLAGS_GPE_MODE,		/* Expect GPE to be sent for status change */
 	EC_FLAGS_NO_GPE,		/* Don't use GPE mode */
 	EC_FLAGS_RESCHEDULE_POLL	/* Re-schedule poll */
@@ -230,8 +229,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
 			       "finish-write timeout, command = %d\n", command);
 			goto end;
 		}
-	} else if (command == ACPI_EC_COMMAND_QUERY)
-		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+	}
 
 	for (; rdata_len > 0; --rdata_len) {
 		result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
@@ -502,7 +508,7 @@ static u32 acpi_ec_gpe_handler(void *data)
 		wake_up(&ec->wait);
 
 	if (state & ACPI_EC_FLAG_SCI) {
-		if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
+		if (ec->handlers_installed)
 			status = acpi_os_execute(OSL_EC_BURST_HANDLER,
 				acpi_ec_gpe_query, ec);
 	} else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
@@ -665,7 +671,6 @@ static struct acpi_ec *make_acpi_ec(void)
 	struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
 	if (!ec)
 		return NULL;
-	ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
 	mutex_init(&ec->lock);
 	init_waitqueue_head(&ec->wait);
 	INIT_LIST_HEAD(&ec->list);
@@ -858,8 +863,6 @@ static int acpi_ec_start(struct acpi_device *device)
 
 	ret = ec_install_handlers(ec);
 
-	/* EC is fully operational, allow queries */
-	clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
 	ec_schedule_ec_poll(ec);
 	return ret;
 }
#13 lore raw

Re: [PATCH 1/3] acpi: Rip out EC_FLAGS_QUERY_PENDING (prevent race condition)

Quoted 1 line · Alexey Starikovskiy

Alan,

Thanks for your robust response. Sorry for not discussing this more in the first place. I wanted to write the code that fixes my system first, and post it as soon as possible. I think I missed a flag to say "this post is not an immediate request for submission".

Quoted 4 lines

I don't think this is very good idea -- now every interrupt will add a new entry to workqueue,
and given the rate of this interrupt, it could be become quite long.

I confess I gave up too quickly on the synchronisation issues and resorted to brute force. Patch #1 is preventing a narrow race:

- acpi_ec_write_cmd() (QUERY)
- EC writes 0 (no event) to input buffer
- new event arrives, triggering a GPE interrupt which is ignored because QUERY_PENDING is set.
- QUERY_PENDING is cleared (but too late).

Now we ignored an event, which will be delayed until the next GPE interrupt.

The original reason for patch #1 was to stop patch #2 driving me insane. If you apply the second patch on it's own, you break EC_FLAGS_QUERY_PENDING. It gets cleared as soon as the _first_ query command is submitted. It works, but it means the flag no longer has a clearly defined meaning. I tried to fix that by only clearing it once the loop has finished - and then realised I was widening a pre-existing race condition.

As you say, I took the easy way out and pushed it all into the workqueue. So the workqueue ends up as a buffer of GPE occurrences. I did look at reducing the memory usage while avoiding race conditions, but I couldn't find a reasonable solution. But I looked at it again now and I have a better solution:

...

    /* moved here from acpi_ec_transaction_unlocked() */
    clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);

    while (acpi_ec_query(ec, &value) == 0)
        acpi_ec_gpe_run_handler(ec, value);
}

The PENDING flag then reflects whether or not there's an item on the workqueue. Does that make sense?

Quoted 4 lines

Your second patch is redundant if you add queue entry for each interrupt, and as it does not
require any investments into memory, I like it more.

It's not quite redundant with the first patch. We still have GPE polling mode - patch #1 doesn't affect that. In polling mode, it's essential to query all the pending events - otherwise, if they arrive more frequently than the polling interval then you will inevitably drop events.

Patch #2 is also required to fix my buggy hardware. My laptop's EC buffers multiple events, but clears SCI_EVT after every query. This caused problems in polling mode; with multiple events between polling intervals only one gets queried - and after a while the buffer overflows and it breaks completely.

Quoted 4 lines

Also, it is very cool to rip of things you don't care for, but that essentially reverts a fix done for 9998,
so at least, you should ask these people if you broke their setups.

I assume you're referring to the "would benefit from wider testing" patch #3. Thanks for identifying the bugzilla entry - I had difficulty separating the different entries on GPEs. I'm optimistic that we can fix all these crazy buffering EC's without having to disable GPE interrupts.

The reason I like my proposed fix is that it makes the code simple enough that I can understand it, without making any assumptions about how many interrupts arrive per GPE. The EC can be broken in lots of ways, so long as:

1. We receive interrupts when one or more GPE's are pending.
2. We don't get a constant interrupt storm.

I don't think I missed anything. Is there anything else I should check before I try to get testing?

Thanks
Alan

#14 lore raw

Re: [PATCH 1/3] acpi: Rip out EC_FLAGS_QUERY_PENDING (prevent race condition)

Quoted 9 lines · Alan Jenkins
    /* moved here from acpi_ec_transaction_unlocked() */
    clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);

    while (acpi_ec_query(ec, &value) == 0)
        acpi_ec_gpe_run_handler(ec, value);
}

The PENDING flag then reflects whether or not there's an item on the workqueue. Does that make sense?

Yes, this is what the flag was made for -- to guard workqueue from being filled up.

Quoted 10 lines
Quoted 5 lines

Your second patch is redundant if you add queue entry for each interrupt, and as it does not
require any investments into memory, I like it more.

It's not quite redundant with the first patch. We still have GPE polling mode - patch #1 doesn't affect that. In polling mode, it's essential to query all the pending events - otherwise, if they arrive more frequently than the polling interval then you will inevitably drop events.

I meant that if we have patch #3, which drops poll mode, we only need one of the first two, not both. And in this case I like #2 more than #1.

Quoted 6 lines

Patch #2 is also required to fix my buggy hardware. My laptop's EC buffers multiple events, but clears SCI_EVT after every query. This caused problems in polling mode; with multiple events between polling intervals only one gets queried - and after a while the buffer overflows and it breaks completely.

I fully agree here, it would be great to make sure that EC buffers are empty.

Quoted 8 lines
Quoted 4 lines

Also, it is very cool to rip of things you don't care for, but that essentially reverts a fix done for 9998,
so at least, you should ask these people if you broke their setups.

I assume you're referring to the "would benefit from wider testing" patch #3. Thanks for identifying the bugzilla entry - I had difficulty separating the different entries on GPEs. I'm optimistic that we can fix all these crazy buffering EC's without having to disable GPE interrupts.

I would say, we should test pair of #2 and #3, or your original patch + my patch. I still like the option to not have any new interrupts until I'm done with current one -- much like the PENDING bit.

Quoted 11 lines

The reason I like my proposed fix is that it makes the code simple enough that I can understand it, without making any assumptions about how many interrupts arrive per GPE. The EC can be broken in lots of ways, so long as:

1. We receive interrupts when one or more GPE's are pending.
2. We don't get a constant interrupt storm.

I don't think I missed anything. Is there anything else I should check before I try to get testing?

Well, there is Keith Packard with concern that either high number of interrupts or long spins on polling status register could push battery life down the drain... One more argument to disable GPE until we service previous.

Regards,
Alex.

#15 lore raw

Re: [PATCH 1/3] acpi: Rip out EC_FLAGS_QUERY_PENDING (prevent race condition)

Quoted 57 lines · Alexey Starikovskiy
Quoted 9 lines · Alan Jenkins
    /* moved here from acpi_ec_transaction_unlocked() */
    clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);

    while (acpi_ec_query(ec, &value) == 0)
        acpi_ec_gpe_run_handler(ec, value);
}

The PENDING flag then reflects whether or not there's an item on the workqueue. Does that make sense?

Yes, this is what the flag was made for -- to guard workqueue from being filled up.

Quoted 10 lines
Quoted 5 lines

Your second patch is redundant if you add queue entry for each interrupt, and as it does not
require any investments into memory, I like it more.

It's not quite redundant with the first patch. We still have GPE polling mode - patch #1 doesn't affect that. In polling mode, it's essential to query all the pending events - otherwise, if they arrive more frequently than the polling interval then you will inevitably drop events.

I meant that if we have patch #3, which drops poll mode, we only need one of the first two, not both. And in this case I like #2 more than #1.

Quoted 6 lines

Patch #2 is also required to fix my buggy hardware. My laptop's EC buffers multiple events, but clears SCI_EVT after every query. This caused problems in polling mode; with multiple events between polling intervals only one gets queried - and after a while the buffer overflows and it breaks completely.

I fully agree here, it would be great to make sure that EC buffers are empty.

Quoted 9 lines
Quoted 4 lines

Also, it is very cool to rip of things you don't care for, but that essentially reverts a fix done for 9998,
so at least, you should ask these people if you broke their setups.

I assume you're referring to the "would benefit from wider testing" patch #3. Thanks for identifying the bugzilla entry - I had difficulty separating the different entries on GPEs. I'm optimistic that we can fix all these crazy buffering EC's without having to disable GPE interrupts.

I would say, we should test pair of #2 and #3, or your original patch
+ my patch.
I still like the option to not have any new interrupts until I'm done with current one --
much like the PENDING bit.

Quoted 11 lines

The reason I like my proposed fix is that it makes the code simple enough that I can understand it, without making any assumptions about how many interrupts arrive per GPE. The EC can be broken in lots of ways, so long as:

1. We receive interrupts when one or more GPE's are pending.
2. We don't get a constant interrupt storm.

I don't think I missed anything. Is there anything else I should check before I try to get testing?

Quoted 7 lines

Well, there is Keith Packard with concern that either high number of interrupts or long
spins on polling status register could push battery life down the drain...
One more argument to disable GPE until we service previous. Regards,
Alex.

Ah, the powertop argument. Disabling interrupts is a nice safety blanket, but it means you end up polling the status register during queries. I think the interrupts are better for battery life. The excess interrupts happen all at once, so they don't wake the CPU up more frequently, they just keep it awake slightly longer.

I'm convinced that emptying the EC buffer will reduce the number of interrupts, even for the reporter of #9998. I'll ask them to test this patchset, then respin it to fix the mess I made of EC_FLAGS_QUERY_PENDING. As I mentioned earlier I've worked out how to avoid my theoretical race without causing increased memory usage.

Thanks
Alan

#16 lore raw

PATCH 2/3 acpi: Avoid dropping rapid GPEs on Asus EeePC and others

In reply to a message not in the archive

From: Alan Jenkins <[email protected]>

Fix regression "Asus Eee PC hotkeys stop working if pressed quickly",
<http://bugzilla.kernel.org/show_bug.cgi?id=11089>. More important notifications e.g. battery level may also be affected.

It looks like this EC clears the SCI_EVT bit after every query, but there may be more events buffered. Therefore we should repeatedly query the EC until it reports that no events remain.

The regression was caused by a recently added check for GPE interrupt storms. The Eee PC triggers this check and switches to polling GPEs. When multiple events arrive between polling intervals, only one was fetched from the EC. This caused erroneous behaviour; ultimately events stop being delivered altogether when the EC buffer overflows.

drivers/acpi/ec.c +13 -5
index 9ca71df..e764011 100644
@@ -457,14 +457,10 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_gpe_run_handler(struct acpi_ec *ec, u8 value)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
 	struct acpi_ec_query_handler *handler, copy;
 
-	if (!ec || acpi_ec_query(ec, &value))
-		return;
 	mutex_lock(&ec->lock);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
@@ -482,6 +478,18 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	u8 value = 0;
+
+	if (!ec)
+		return;
+
+	while (acpi_ec_query(ec, &value) == 0)
+		acpi_ec_gpe_run_handler(ec, value);
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	acpi_status status = AE_OK;
#17 lore raw

PATCH 3/3 acpi: remove GPE polling

In reply to a message not in the archive

From: Alan Jenkins <[email protected]>

This should fix "[regression] display dimming is slow and laggy",
<http://bugzilla.kernel.org/show_bug.cgi?id=10919>. It has a similar effect on my Asus EeePC.

Much of this is stolen from Alexey Starikovskiy's fix (see Bugzilla). But the previous two GPE fixes should have avoided the need to disable GPE interrupts.

drivers/acpi/ec.c +1 -32
index e764011..1088903 100644
@@ -79,7 +79,6 @@ enum {
 	EC_FLAGS_WAIT_GPE = 0,		/* Don't check status until GPE arrives */
 	EC_FLAGS_GPE_MODE,		/* Expect GPE to be sent for status change */
 	EC_FLAGS_NO_GPE,		/* Don't use GPE mode */
-	EC_FLAGS_RESCHEDULE_POLL	/* Re-schedule poll */
 };
 
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
@@ -105,7 +104,6 @@ static struct acpi_ec {
 	wait_queue_head_t wait;
 	struct list_head list;
 	struct delayed_work work;
-	atomic_t irq_count;
 	u8 handlers_installed;
 } *boot_ec, *first_ec;
 
@@ -154,24 +152,14 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
 	return 0;
 }
 
-static void ec_schedule_ec_poll(struct acpi_ec *ec)
-{
-	if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags))
-		schedule_delayed_work(&ec->work,
-				      msecs_to_jiffies(ACPI_EC_DELAY));
-}
-
 static void ec_switch_to_poll_mode(struct acpi_ec *ec)
 {
 	set_bit(EC_FLAGS_NO_GPE, &ec->flags);
 	clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
-	acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
-	set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
 }
 
 static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
 {
-	atomic_set(&ec->irq_count, 0);
 	if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
 	    likely(!force_poll)) {
 		if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
@@ -184,7 +172,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
 				pr_info(PREFIX "missing confirmations, "
 						"switch off interrupt mode.\n");
 			ec_switch_to_poll_mode(ec);
-			ec_schedule_ec_poll(ec);
 			return 0;
 		}
 	} else {
@@ -497,12 +484,6 @@ static u32 acpi_ec_gpe_handler(void *data)
 	u8 state = acpi_ec_read_status(ec);
 
 	pr_debug(PREFIX "~~~> interrupt\n");
-	atomic_inc(&ec->irq_count);
-	if (atomic_read(&ec->irq_count) > 5) {
-		pr_err(PREFIX "GPE storm detected, disabling EC GPE\n");
-		ec_switch_to_poll_mode(ec);
-		goto end;
-	}
 	clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
 	if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
 		wake_up(&ec->wait);
@@ -519,10 +500,8 @@ static u32 acpi_ec_gpe_handler(void *data)
 			pr_info(PREFIX "non-query interrupt received,"
 				" switching to interrupt mode\n");
 		set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
-		clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
 	}
-end:
-	ec_schedule_ec_poll(ec);
+
 	return ACPI_SUCCESS(status) ?
 	    ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
 }
@@ -530,7 +509,6 @@ end:
 static void do_ec_poll(struct work_struct *work)
 {
 	struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work);
-	atomic_set(&ec->irq_count, 0);
 	(void)acpi_ec_gpe_handler(ec);
 }
 
@@ -675,7 +653,6 @@ static struct acpi_ec *make_acpi_ec(void)
 	init_waitqueue_head(&ec->wait);
 	INIT_LIST_HEAD(&ec->list);
 	INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll);
-	atomic_set(&ec->irq_count, 0);
 	return ec;
 }
 
@@ -714,15 +691,8 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
 	return AE_CTRL_TERMINATE;
 }
 
-static void ec_poll_stop(struct acpi_ec *ec)
-{
-	clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
-	cancel_delayed_work(&ec->work);
-}
-
 static void ec_remove_handlers(struct acpi_ec *ec)
 {
-	ec_poll_stop(ec);
 	if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
 				ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
 		pr_err(PREFIX "failed to remove space handler\n");
@@ -863,7 +833,6 @@ static int acpi_ec_start(struct acpi_device *device)
 
 	ret = ec_install_handlers(ec);
 
-	ec_schedule_ec_poll(ec);
 	return ret;
 }
 
#18 lore raw
In reply to Alan Jenkins

Hi Alan,

Could you please test if your patch works with the last patch in #10919?

Thanks,
Alex.

Quoted 58 lines · Alan Jenkins

It looks like this EC clears the SMI_EVT bit after every query, even if there are more events pending. The workaround is to repeatedly query the EC until it reports that no events remain.

This fixes a regression in 2.6.26 (from 2.6.25.3). Initially reported as "Asus Eee PC hotkeys stop working if pressed quickly" in bugzilla
<http://bugzilla.kernel.org/show_bug.cgi?id=11089>.

The regression was caused by a recently added check for interrupt storms. The Eee PC triggers this check and switches to polling. When multiple events arrive between polling intervals, only one is fetched from the EC. This causes erroneous behaviour; ultimately events stop being delivered altogether when the EC buffer overflows.

---

drivers/acpi/ec.c +13 -5
index 5622aee..2b4c5a2 100644
@@ -459,14 +459,10 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_gpe_run_handler(struct acpi_ec *ec, u8 value)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
 	struct acpi_ec_query_handler *handler, copy;
 
-	if (!ec || acpi_ec_query(ec, &value))
-		return;
 	mutex_lock(&ec->lock);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
@@ -484,6 +480,18 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	u8 value = 0;
+
+	if (!ec)
+		return;
+
+	while (!acpi_ec_query(ec, &value))
+		acpi_ec_gpe_run_handler(ec, value);
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	acpi_status status = AE_OK;
#19 lore raw
Quoted 6 lines · Alexey Starikovskiy

Hi Alan,

Could you please test if your patch works with the last patch in #10919?

Thanks,
Alex.

Vacuously so.

My patch still applies, but #10919 makes it obsolete. My patch fixed a bug that shows up in polling mode. #10919 kills polling mode.

I've tested v2.6.26 + #10919 and it works fine (except for spamming the kernel log - please read my Bugzilla comment).

It appears that interrupt mode suffered from a race which is very similar to my original problem. If two GPE interrupts arrive before the workqueue runs, then the second interrupt will be ignored because EC_FLAGS_QUERY_PENDING is still set. This will happen with any EC if interrupts are very close together, right?

I think my patch also fixes this theoretical problem. But I'd rather you took over on this. I was already confused by ec.c in v2.6.26, and with #10919 I understand it even less. E.g. why is ec_switch_to_poll_mode() still present; what does it do now do_ec_poll() is removed?

I'm happy to work on this with you, but I'd need to be able understand the code first :-(.

Alan

#20 lore raw
Quoted 10 lines · Alan Jenkins
Quoted 6 lines · Alexey Starikovskiy

Hi Alan,

Could you please test if your patch works with the last patch in #10919?

Thanks,
Alex.

Vacuously so.

My patch still applies, but #10919 makes it obsolete.

Not so, there are two polls in ec.c, first is poll for change in status register, which gave the name to the mode, and still exists; the other is for event in embedded controller, which was introduced to properly solve #9998, and part of it is removed by patch in #10919.

Quoted 8 lines

My patch fixed a
bug that shows up in polling mode. #10919 kills polling mode.

I've tested v2.6.26 + #10919 and it works fine (except for spamming the kernel log - please read my Bugzilla comment).

Quoted 5 lines

It appears that interrupt mode suffered from a race which is very similar to my original problem. If two GPE interrupts arrive before the workqueue runs, then the second interrupt will be ignored because EC_FLAGS_QUERY_PENDING is still set. This will happen with any EC if interrupts are very close together, right?

The notion of queue in embedded controller is new, it was never mentioned in ACPI spec, so the driver was written with assumption that new query interrupt should not arrive before we service previous one. There is even a chart in how interrupts should occur near the EC query command...

Quoted 2 lines

I think my patch also fixes this theoretical problem.

I think, this is not a theoretical problem, but the problem we've tried to solve in #9998, #10724, and so on.

Quoted 5 lines

But I'd rather
you took over on this. I was already confused by ec.c in v2.6.26, and with #10919 I understand it even less. E.g. why is ec_switch_to_poll_mode() still present; what does it do now do_ec_poll() is removed?

See above, I still disable EC GPE for the time than we have pending query, so we better not wait for it to check the status register

Quoted 3 lines

I'm happy to work on this with you, but I'd need to be able understand the code first :-(.

Well, with this patch of yours, I guess, we will not have too many problems in EC left :-)

Quoted 2 lines

Alan

Thanks again,
Alex.

Tested-by
#21 lore raw
Quoted 48 lines · Alexey Starikovskiy
Quoted 11 lines · Alan Jenkins
Quoted 7 lines · Alexey Starikovskiy

Hi Alan,

Could you please test if your patch works with the last patch in #10919?

Thanks,
Alex.

Vacuously so.

My patch still applies, but #10919 makes it obsolete.

Not so, there are two polls in ec.c, first is poll for change in status register,
which gave the name to the mode, and still exists; the other is for event in embedded controller, which was introduced to properly solve #9998, and part of
it is removed by patch in #10919.

Quoted 8 lines

My patch fixed a
bug that shows up in polling mode. #10919 kills polling mode.

I've tested v2.6.26 + #10919 and it works fine (except for spamming the kernel log - please read my Bugzilla comment).

Quoted 5 lines

It appears that interrupt mode suffered from a race which is very similar to my original problem. If two GPE interrupts arrive before the workqueue runs, then the second interrupt will be ignored because EC_FLAGS_QUERY_PENDING is still set. This will happen with any EC if interrupts are very close together, right?

The notion of queue in embedded controller is new, it was never mentioned in
ACPI spec, so the driver was written with assumption that new query interrupt should
not arrive before we service previous one. There is even a chart in how interrupts
should occur near the EC query command...

Quoted 2 lines

I think my patch also fixes this theoretical problem.

I think, this is not a theoretical problem, but the problem we've tried to solve in
#9998, #10724, and so on.

Quoted 5 lines

But I'd rather
you took over on this. I was already confused by ec.c in v2.6.26, and with #10919 I understand it even less. E.g. why is ec_switch_to_poll_mode() still present; what does it do now do_ec_poll() is removed?

Quoted 8 lines

See above, I still disable EC GPE for the time than we have pending query,
so we better not wait for it to check the status register

Quoted 3 lines

I'm happy to work on this with you, but I'd need to be able understand the code first :-(.

Well, with this patch of yours, I guess, we will not have too many problems in EC left :-)

OK, I'm happy now.

However, I'm now worried that I broke the semantics for EC_FLAGS_QUERY_PENDING. In my patch it gets cleared after the first query, even though I'm running queries in a loop until nothing is left. It doesn't cause a problem in my patch, but it's unclean and might cause confusion later on. It'd be better to clear it after the loop has completed.

Can I fix my patch? If you ACK the new code below, then I'll resend with a proper changelog, S-o-B, CC's from the -mm mail (including [email protected]) and grovel to akpm, etc.

You're latest (quieter) work still applies on top and works fine.

Thanks
Alan

---

From: Alan Jenkins <[email protected]>

drivers/acpi/ec.c +16 -7
index 5622aee..2a42392 100644
@@ -230,8 +230,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
 			       "finish-write timeout, command = %d\n", command);
 			goto end;
 		}
-	} else if (command == ACPI_EC_COMMAND_QUERY)
-		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+	}
 
 	for (; rdata_len > 0; --rdata_len) {
 		result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
@@ -459,14 +458,10 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_gpe_run_handler(struct acpi_ec *ec, u8 value)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
 	struct acpi_ec_query_handler *handler, copy;
 
-	if (!ec || acpi_ec_query(ec, &value))
-		return;
 	mutex_lock(&ec->lock);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
@@ -484,6 +479,20 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	u8 value = 0;
+
+	if (!ec)
+		return;
+
+	while (acpi_ec_query(ec, &value) != 0)
+		acpi_ec_gpe_run_handler(ec, value);
+
+	clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	acpi_status status = AE_OK;
#22 lore raw
Quoted 54 lines · Alan Jenkins
Quoted 45 lines · Alexey Starikovskiy
Quoted 11 lines · Alan Jenkins
Quoted 7 lines · Alexey Starikovskiy

Hi Alan,

Could you please test if your patch works with the last patch in #10919?

Thanks,
Alex.

Vacuously so.

My patch still applies, but #10919 makes it obsolete.

Not so, there are two polls in ec.c, first is poll for change in status register,
which gave the name to the mode, and still exists; the other is for event in embedded controller, which was introduced to properly solve #9998, and part of
it is removed by patch in #10919.

Quoted 11 lines

My patch fixed a
bug that shows up in polling mode. #10919 kills polling mode. I've tested v2.6.26 + #10919 and it works fine (except for spamming the kernel log - please read my Bugzilla comment).

It appears that interrupt mode suffered from a race which is very similar to my original problem. If two GPE interrupts arrive before the workqueue runs, then the second interrupt will be ignored because EC_FLAGS_QUERY_PENDING is still set. This will happen with any EC if interrupts are very close together, right?

The notion of queue in embedded controller is new, it was never mentioned in
ACPI spec, so the driver was written with assumption that new query interrupt should
not arrive before we service previous one. There is even a chart in how interrupts
should occur near the EC query command...

Quoted 1 line

I think my patch also fixes this theoretical problem.

I think, this is not a theoretical problem, but the problem we've tried to solve in
#9998, #10724, and so on.

Quoted 5 lines

But I'd rather
you took over on this. I was already confused by ec.c in v2.6.26, and with #10919 I understand it even less. E.g. why is ec_switch_to_poll_mode() still present; what does it do now do_ec_poll() is removed?

Quoted 7 lines

See above, I still disable EC GPE for the time than we have pending query,
so we better not wait for it to check the status register

Quoted 2 lines

I'm happy to work on this with you, but I'd need to be able understand the code first :-(.

Well, with this patch of yours, I guess, we will not have too many problems in EC left :-)

Quoted 7 lines

OK, I'm happy now.

However, I'm now worried that I broke the semantics for
EC_FLAGS_QUERY_PENDING. In my patch it gets cleared after the first
query, even though I'm running queries in a loop until nothing is left. It doesn't cause a problem in my patch, but it's unclean and might cause confusion later on. It'd be better to clear it after the loop has
completed.

Right.

Quoted 4 lines

Can I fix my patch? If you ACK the new code below, then I'll resend with a proper changelog, S-o-B, CC's from the -mm mail (including [email protected]) and grovel to akpm, etc.

ACK

Quoted 2 lines

You're latest (quieter) work still applies on top and works fine.

Good.

Quoted 3 lines

Thanks
Alan

Thanks,
Alex.

Quoted 60 lines

---

From: Alan Jenkins <[email protected]>

drivers/acpi/ec.c +16 -7
index 5622aee..2a42392 100644
@@ -230,8 +230,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
 			       "finish-write timeout, command = %d\n", command);
 			goto end;
 		}
-	} else if (command == ACPI_EC_COMMAND_QUERY)
-		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+	}
 
 	for (; rdata_len > 0; --rdata_len) {
 		result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
@@ -459,14 +458,10 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_gpe_run_handler(struct acpi_ec *ec, u8 value)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
 	struct acpi_ec_query_handler *handler, copy;
 
-	if (!ec || acpi_ec_query(ec, &value))
-		return;
 	mutex_lock(&ec->lock);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
@@ -484,6 +479,20 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	u8 value = 0;
+
+	if (!ec)
+		return;
+
+	while (acpi_ec_query(ec, &value) != 0)
+		acpi_ec_gpe_run_handler(ec, value);
+
+	clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	acpi_status status = AE_OK;
#23 lore raw

Did this get fixed yet?

I have an patch in -mm which I just restored (I had to tempdrop it because the acpi tree was busted for some time). But it seems to be old.

http://bugzilla.kernel.org/show_bug.cgi?id=10919 is marked "resolved" but the reporter (Maximilian) seems to think otherwise. 2.6.26.x is, afaik, still unfixed, as is 2.6.27-rc.

Thanks.

#24 lore raw
Quoted 10 lines · Andrew Morton

Did this get fixed yet?

I have an patch in -mm which I just restored (I had to tempdrop it because the acpi tree was busted for some time). But it seems to be old.

http://bugzilla.kernel.org/show_bug.cgi?id=10919 is marked "resolved" but the reporter (Maximilian) seems to think otherwise. 2.6.26.x is, afaik, still unfixed, as is 2.6.27-rc.

That's correct. I think this specific patch should go in 2.6.27 and 2.6.26-stable. No objections have been raised so far.

I still need this patch to make my brightness and volume control keys usable in 2.6.27-rc3. (They auto-repeat fast enough to trigger the bug). This is true even after applying the latest patches from bug 10919 (#25 + #27).

I think the 10919 fix makes it harder to reproduce, but it definitely still happens. I guess this is because the polling-driven EC transactions add 1ms delays between each byte. The slower timings leave a window where the buggy behaviour of my EC can make a difference. (It has been seen to clear the "pending event" bit after a single event is read, despite having more events pending).

There are more serious consequences of this bug. After a while it can confuse the EC enough to cause lockups or reboots during boot, or after pressing a single hotkey. This bad state is preserved over reboots, even into known good kernels. Fortunately the badness clears when power is removed for a long enough period. For a while I was worried that something had physically burnt out.

Thanks
Alan

#25 lore raw
Quoted 11 lines · On Wed, 13 Aug 2008 11:21:10 +0100 Alan Jenkins <[email protected]>…
Quoted 10 lines · Andrew Morton

Did this get fixed yet?

I have an patch in -mm which I just restored (I had to tempdrop it because the acpi tree was busted for some time). But it seems to be old.

http://bugzilla.kernel.org/show_bug.cgi?id=10919 is marked "resolved" but the reporter (Maximilian) seems to think otherwise. 2.6.26.x is, afaik, still unfixed, as is 2.6.27-rc.

Quoted 8 lines

That's correct. I think this specific patch should go in 2.6.27 and 2.6.26-stable. No objections have been raised so far.

I still need this patch to make my brightness and volume control keys usable in 2.6.27-rc3. (They auto-repeat fast enough to trigger the bug). This is true even after applying the latest patches from bug 10919 (#25 + #27).

Confusing. Please send the patch which you think we should apply.

Quoted 7 lines

I think the 10919 fix makes it harder to reproduce, but it definitely still happens. I guess this is because the polling-driven EC transactions add 1ms delays between each byte. The slower timings leave a window where the buggy behaviour of my EC can make a difference. (It has been seen to clear the "pending event" bit after a single event is read, despite having more events pending).

Quoted 6 lines

There are more serious consequences of this bug. After a while it can confuse the EC enough to cause lockups or reboots during boot, or after pressing a single hotkey. This bad state is preserved over reboots, even into known good kernels. Fortunately the badness clears when power is removed for a long enough period. For a while I was worried that something had physically burnt out.

Oh gad. And there's no workaround?

#26 lore raw
Quoted 44 lines · Andrew Morton
Quoted 13 lines · On Wed, 13 Aug 2008 11:21:10 +0100 Alan Jenkins <[email protected]>…
Quoted 11 lines · Andrew Morton

Did this get fixed yet?

I have an patch in -mm which I just restored (I had to tempdrop it because the acpi tree was busted for some time). But it seems to be old.

http://bugzilla.kernel.org/show_bug.cgi?id=10919 is marked "resolved" but the reporter (Maximilian) seems to think otherwise. 2.6.26.x is, afaik, still unfixed, as is 2.6.27-rc.

Quoted 9 lines

That's correct. I think this specific patch should go in 2.6.27 and 2.6.26-stable. No objections have been raised so far.

I still need this patch to make my brightness and volume control keys usable in 2.6.27-rc3. (They auto-repeat fast enough to trigger the bug). This is true even after applying the latest patches from bug 10919 (#25 + #27).

Confusing. Please send the patch which you think we should apply.

Quoted 7 lines

I think the 10919 fix makes it harder to reproduce, but it definitely still happens. I guess this is because the polling-driven EC transactions add 1ms delays between each byte. The slower timings leave a window where the buggy behaviour of my EC can make a difference. (It has been seen to clear the "pending event" bit after a single event is read, despite having more events pending).

Quoted 7 lines

There are more serious consequences of this bug. After a while it can confuse the EC enough to cause lockups or reboots during boot, or after pressing a single hotkey. This bad state is preserved over reboots, even into known good kernels. Fortunately the badness clears when power is removed for a long enough period. For a while I was worried that something had physically burnt out.

Quoted 2 lines

Oh gad. And there's no workaround?

Sorry, that was confusing.

The patch in currently in -mm _is_ the workaround for this damage. It was not initially obvious just how important it was :-). I've re-attached it as requested.

10919, "laggy hotkeys" is just what it says; ACPI EC events are slower because of polling. It appears to be a more cosmetic issue which is orthogonal to the _dropping_ of events.

Thanks
Alan

It looks like this EC clears the SMI_EVT bit after every query, even if there are more events pending. The workaround is to repeatedly query the EC until it reports that no events remain.

This fixes a regression in 2.6.26 (from 2.6.25.3). Initially reported as "Asus Eee PC hotkeys stop working if pressed quickly" in bugzilla
<http://bugzilla.kernel.org/show_bug.cgi?id=11089>.

The regression was caused by a recently added check for interrupt storms. The Eee PC triggers this check and switches to polling. When multiple events arrive between polling intervals, only one is fetched from the EC. This causes erroneous behaviour; ultimately events stop being delivered altogether when the EC buffer overflows.

---

drivers/acpi/ec.c +13 -5
index 5622aee..2b4c5a2 100644
@@ -459,14 +459,10 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_gpe_run_handler(struct acpi_ec *ec, u8 value)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
 	struct acpi_ec_query_handler *handler, copy;
 
-	if (!ec || acpi_ec_query(ec, &value))
-		return;
 	mutex_lock(&ec->lock);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
@@ -484,6 +480,18 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	u8 value = 0;
+
+	if (!ec)
+		return;
+
+	while (!acpi_ec_query(ec, &value))
+		acpi_ec_gpe_run_handler(ec, value);
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	acpi_status status = AE_OK;
#27 lore raw
In reply to Andrew Morton

[Dupe apology: CC'd to [email protected], with the right address this time]

Quoted 44 lines · Andrew Morton
Quoted 13 lines · On Wed, 13 Aug 2008 11:21:10 +0100 Alan Jenkins <[email protected]>…
Quoted 11 lines · Andrew Morton

Did this get fixed yet?

I have an patch in -mm which I just restored (I had to tempdrop it because the acpi tree was busted for some time). But it seems to be old.

http://bugzilla.kernel.org/show_bug.cgi?id=10919 is marked "resolved" but the reporter (Maximilian) seems to think otherwise. 2.6.26.x is, afaik, still unfixed, as is 2.6.27-rc.

Quoted 9 lines

That's correct. I think this specific patch should go in 2.6.27 and 2.6.26-stable. No objections have been raised so far.

I still need this patch to make my brightness and volume control keys usable in 2.6.27-rc3. (They auto-repeat fast enough to trigger the bug). This is true even after applying the latest patches from bug 10919 (#25 + #27).

Confusing. Please send the patch which you think we should apply.

Quoted 7 lines

I think the 10919 fix makes it harder to reproduce, but it definitely still happens. I guess this is because the polling-driven EC transactions add 1ms delays between each byte. The slower timings leave a window where the buggy behaviour of my EC can make a difference. (It has been seen to clear the "pending event" bit after a single event is read, despite having more events pending).

Quoted 7 lines

There are more serious consequences of this bug. After a while it can confuse the EC enough to cause lockups or reboots during boot, or after pressing a single hotkey. This bad state is preserved over reboots, even into known good kernels. Fortunately the badness clears when power is removed for a long enough period. For a while I was worried that something had physically burnt out.

Quoted 2 lines

Oh gad. And there's no workaround?

Sorry, that was confusing.

The patch in currently in -mm _is_ the workaround for this damage. It was not initially obvious just how important it was :-). I've re-attached it as requested.

10919, "laggy hotkeys" is just what it says; ACPI EC events are slower because of polling. It appears to be a more cosmetic issue which is orthogonal to the _dropping_ of events.

Thanks
Alan

It looks like this EC clears the SMI_EVT bit after every query, even if there are more events pending. The workaround is to repeatedly query the EC until it reports that no events remain.

This fixes a regression in 2.6.26 (from 2.6.25.3). Initially reported as "Asus Eee PC hotkeys stop working if pressed quickly" in bugzilla
<http://bugzilla.kernel.org/show_bug.cgi?id=11089>.

The regression was caused by a recently added check for interrupt storms. The Eee PC triggers this check and switches to polling. When multiple events arrive between polling intervals, only one is fetched from the EC. This causes erroneous behaviour; ultimately events stop being delivered altogether when the EC buffer overflows.

---

drivers/acpi/ec.c +13 -5
index 5622aee..2b4c5a2 100644
@@ -459,14 +459,10 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_gpe_run_handler(struct acpi_ec *ec, u8 value)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
 	struct acpi_ec_query_handler *handler, copy;
 
-	if (!ec || acpi_ec_query(ec, &value))
-		return;
 	mutex_lock(&ec->lock);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
@@ -484,6 +480,18 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	u8 value = 0;
+
+	if (!ec)
+		return;
+
+	while (!acpi_ec_query(ec, &value))
+		acpi_ec_gpe_run_handler(ec, value);
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	acpi_status status = AE_OK;
#28 lore raw
Quoted 4 lines · Alan Jenkins

[Dupe apology: CC'd to [email protected], with the right address this time]

Quoted 1 line · Andrew Morton

On Wed, 13 Aug 2008 11:21:10 +0100 Alan Jenkins

Quoted 43 lines · <[email protected]> wrote:
Quoted 28 lines
Quoted 11 lines
Quoted 9 lines · Andrew Morton

Did this get fixed yet?

I have an patch in -mm which I just restored (I had to tempdrop it because the acpi tree was busted for some time). But it seems to be old.

http://bugzilla.kernel.org/show_bug.cgi?id=10919 is marked "resolved" but the reporter (Maximilian) seems to think otherwise. 2.6.26.x is, afaik, still unfixed, as is 2.6.27-rc.

Quoted 7 lines

That's correct. I think this specific patch should go in 2.6.27 and 2.6.26-stable. No objections have been raised so far.

I still need this patch to make my brightness and volume control keys usable in 2.6.27-rc3. (They auto-repeat fast enough to trigger the bug). This is true even after applying the latest patches from bug 10919 (#25 + #27).

Confusing. Please send the patch which you think we should apply.

Quoted 7 lines

I think the 10919 fix makes it harder to reproduce, but it definitely still happens. I guess this is because the polling-driven EC transactions add 1ms delays between each byte. The slower timings leave a window where the buggy behaviour of my EC can make a difference. (It has been seen to clear the "pending event" bit after a single event is read, despite having more events pending).

Quoted 8 lines
Quoted 6 lines

There are more serious consequences of this bug. After a while it can confuse the EC enough to cause lockups or reboots during boot, or after pressing a single hotkey. This bad state is preserved over reboots, even into known good kernels. Fortunately the badness clears when power is removed for a long enough period. For a while I was worried that something had physically burnt out.

Oh gad. And there's no workaround?

Sorry, that was confusing.

The patch in currently in -mm _is_ the workaround for this damage. It was not initially obvious just how important it was :-). I've re-attached it as requested.

Quoted 6 lines

10919, "laggy hotkeys" is just what it says; ACPI EC events are slower because of polling. It appears to be a more cosmetic issue which is orthogonal to the _dropping_ of events.

Thanks
Alan

This patch doesn't fix my problem (bug 10919), it only changes it a bit. When I press the dimming key and hold it pressed the display should dim up/down step by step as long as I hold the key pressed (that's how it has always been).
I'm now running a 2.6.27-rc3 kernel with your patch applied and the display does dim as described below.
When I press the dimming key first the display brightness doesn't change at all, then it jumps multiple steps, stays there for a short while and again jumps some steps till it reaches the end of the dimming interval. It looks like the key presses (assuming holding down the key does generate multiple key presses) get queued up, then all processed all at once, then again queued up...

Maxi

#29 lore raw
Quoted 76 lines · Maximilian Engelhardt
Quoted 6 lines · Alan Jenkins

[Dupe apology: CC'd to [email protected], with the right address this time]

Quoted 2 lines · Andrew Morton

On Wed, 13 Aug 2008 11:21:10 +0100 Alan Jenkins

Quoted 45 lines · <[email protected]> wrote:
Quoted 30 lines
Quoted 12 lines
Quoted 10 lines · Andrew Morton

Did this get fixed yet?

I have an patch in -mm which I just restored (I had to tempdrop it because the acpi tree was busted for some time). But it seems to be old.

http://bugzilla.kernel.org/show_bug.cgi?id=10919 is marked "resolved" but the reporter (Maximilian) seems to think otherwise. 2.6.26.x is, afaik, still unfixed, as is 2.6.27-rc.

Quoted 8 lines

That's correct. I think this specific patch should go in 2.6.27 and 2.6.26-stable. No objections have been raised so far.

I still need this patch to make my brightness and volume control keys usable in 2.6.27-rc3. (They auto-repeat fast enough to trigger the bug). This is true even after applying the latest patches from bug 10919 (#25 + #27).

Confusing. Please send the patch which you think we should apply.

Quoted 7 lines

I think the 10919 fix makes it harder to reproduce, but it definitely still happens. I guess this is because the polling-driven EC transactions add 1ms delays between each byte. The slower timings leave a window where the buggy behaviour of my EC can make a difference. (It has been seen to clear the "pending event" bit after a single event is read, despite having more events pending).

Quoted 9 lines
Quoted 7 lines

There are more serious consequences of this bug. After a while it can confuse the EC enough to cause lockups or reboots during boot, or after pressing a single hotkey. This bad state is preserved over reboots, even into known good kernels. Fortunately the badness clears when power is removed for a long enough period. For a while I was worried that something had physically burnt out.

Oh gad. And there's no workaround?

Sorry, that was confusing.

The patch in currently in -mm _is_ the workaround for this damage. It was not initially obvious just how important it was :-). I've re-attached it as requested.

Quoted 7 lines

10919, "laggy hotkeys" is just what it says; ACPI EC events are slower because of polling. It appears to be a more cosmetic issue which is orthogonal to the _dropping_ of events.

Thanks
Alan

This patch doesn't fix my problem (bug 10919), it only changes it a bit. When I press the dimming key and hold it pressed the display should dim up/down step by step as long as I hold the key pressed (that's how it has always been).
I'm now running a 2.6.27-rc3 kernel with your patch applied and the display does dim as described below.
When I press the dimming key first the display brightness doesn't change at all, then it jumps multiple steps, stays there for a short while and again jumps some steps till it reaches the end of the dimming interval. It looks like the key presses (assuming holding down the key does generate multiple key presses) get queued up, then all processed all at once, then again queued up...

Quoted 2 lines

Maxi

This is expected behaviour - I can explain it in detail if that helps. I see the same on my laptop, though perhaps it is more annoying on yours.

The patch I've submitted here is not intended to fix #10919. You said the patch at <http://bugzilla.kernel.org/show_bug.cgi?id=10919#c21>
worked for you, and I think the approach there is the way forward for this "laggy" issue. However I don't know if it will be ready for this kernel release. I pointed out a cosmetic issue with it to Alexey but haven't heard anything since.

Alan