Thread (8 messages) 8 messages, 4 authors, 2017-01-11

Re: [PATCH] intel_idle: work around errate VLP52 on Baytrail CPUs

From: Len Brown <lenb@kernel.org>
Date: 2016-12-27 20:37:28

quoted
quoted
On Mon, Dec 19, 2016 at 7:19 PM, Jochen Hein [off-list ref] wrote:
quoted
There are frequent hangs on Baytrail CPUs according to
https://bugzilla.kernel.org/show_bug.cgi?id=109051.
This patch works around the errata by disabling C6.

According to the discussion in the bug and private mail it might be
useful to include the workaround in mainline.

Signed-off-by: Jochen Hein <redacted>
Cc: stable@vger.kernel.org
--- linux-4.7.5/drivers/idle/intel_idle.c.orig  2016-09-24 10:10:18.000000000 +0200
+++ linux-4.7.5/drivers/idle/intel_idle.c       2016-10-16 07:36:51.142862573 +0200
@@ -1210,6 +1210,34 @@

 }
 /*
+ * byt_idle_state_table_update(void)
+ *
+ * On BYT, we have errata VLP52 and disable C6.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=109051A
+ * http://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/pentium-n3520-j2850-celeron-n2920-n2820-n2815-n2806-j1850-j1750-spec-update.pdf
+ * VLP52 EOI Transactions May Not be Sent if Software Enters Core C6 During an Interrupt Service Routine.
+
+Problem:
+If core C6 is entered after the start of an interrupt service routine but before a write
+to the APIC EOI (End of Interrupt) register, and the core is woken up by an event
+other than a fixed interrupt source the core may drop the EOI transaction the next
+time APIC EOI register is written and further interrupts from the same or lower
+priority level will be blocked.
+
+Implication:
+EOI transactions may be lost and interrupts may be blocked when core C6 is used
+during interrupt service routines.
Exactly how is it possible for Linux to enter idle and issue an MWAIT
from _within_ an interrupt handler?
quoted
quoted
quoted
+Workaround:
+It is possible for the firmware to contain a workaround for this erratum.
+ */
+static void byt_idle_state_table_update(void)
+{
+       printk(PREFIX "byt_idle_state_table_update reached\n");
+       byt_cstates[1].disabled = 1;    /* C6N-BYT */
+       byt_cstates[2].disabled = 1;    /* C6S-BYT */
+}
+/*
  * sklh_idle_state_table_update(void)
  *
  * On SKL-H (model 0x5e) disable C8 and C9 if:
@@ -1264,6 +1292,10 @@
        case 0x3e: /* IVT */
                ivt_idle_state_table_update();
                break;
+       case 0x37: /* BYT */
+               printk(PREFIX "intel_idle_state_table_update BYT 0x37 reached\n");
+               byt_idle_state_table_update();
+               break;
If the right strategy were to disable C6 for all of BYT, then the
right implementation
would be to delete those states from byt_cstates[], rather than for a
routine to mark
them as disabled.  Note that a user can not later enable a state that is marked
as disabled here, it is never registered with cpuidle, and thus the effect
is exactly the same as if the entry were never in the table in the first place.
quoted
quoted
quoted
        case 0x5c: /* BXT */
                bxt_idle_state_table_update();
                break;
thanks,
Len Brown, Intel Open Source Technology Center
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help