LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH] x86, mce, amd: Enable interrupts by default if HW capable
@ 2015-01-23 22:35 Aravind Gopalakrishnan
  0 siblings, 0 replies; only message in thread
From: Aravind Gopalakrishnan @ 2015-01-23 22:35 UTC (permalink / raw)
  To: tony.luck, bp, mingo, tglx, hpa, x86, linux-kernel; +Cc: Aravind Gopalakrishnan

We setup APIC vectors for threshold errors if interrupt_capable.
However, we don't set interrupt_enable by default.
Re-working threshold_restart_bank() here so that the first time we
set up lvt_offset, we also set IntType to APIC.

If user wants to disable through sysfs, then that's fine too as
we will clear IntType if !tr->b->interrupt_enable

Also, we want to set IntType only if lvt_off_valid is true.
If not, then something is wrong (buggy BIOS maybe) and we'd rather
not have interrupts generated on overflow.

Misc other changes:
- lvt_interrupt_supported() says bank 4 supports APIC LVT always
  But, I looked at BKDG from K8 onwards and I am not seeing IntP
  bit(bit 60) set for any of them.
  - So, removing the bank = 4 check
  - msr_high_bits & BIT(28); will work anyway if bit is set

- We don't have to expose 'interrupt_enable' attribute if HW is
  not capable.
- Moving setting of b.threshold_limit to mce_amd_feature_init()
  - All other setup of struct threshold_block is done there anyway

- Fix comments/comment style issues

Testing details:
on Fam10h (does not have IntP set)
 - interrupt_enable attribute is not exposed.
on F15hM60h (IntP is set)
 - interrupt_enable is set by default
 - echo 0 > interrupt_enable clears IntType of respective register
 - Forcing error count to go over threshold_limit generates APIC
   interrupt and edac mce_amd catches it fine

Signed-off-by: Aravind Gopalakrishnan <aravind.gopalakrishnan@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 43 +++++++++++++-----------------------
 1 file changed, 15 insertions(+), 28 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index f1c3769..8b7dcc6 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -61,9 +61,7 @@ static DEFINE_PER_CPU(unsigned char, bank_map);	/* see which banks are on */
 
 static void amd_threshold_interrupt(void);
 
-/*
- * CPU Initialization
- */
+/* CPU Initialization */
 
 struct thresh_restart {
 	struct threshold_block	*b;
@@ -102,12 +100,6 @@ static const char * const bank4_names(struct threshold_block *b)
 static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits)
 {
 	/*
-	 * bank 4 supports APIC LVT interrupts implicitly since forever.
-	 */
-	if (bank == 4)
-		return true;
-
-	/*
 	 * IntP: interrupt present; if this bit is set, the thresholding
 	 * bank can generate APIC LVT interrupts
 	 */
@@ -161,23 +153,24 @@ static void threshold_restart_bank(void *_tr)
 		    (new_count & THRESHOLD_MAX);
 	}
 
-	/* clear IntType */
-	hi &= ~MASK_INT_TYPE_HI;
-
 	if (!tr->b->interrupt_capable)
 		goto done;
 
+	/* clear IntType */
+	if (!tr->b->interrupt_enable)
+		hi &= ~MASK_INT_TYPE_HI;
+
 	if (tr->set_lvt_off) {
 		if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) {
 			/* set new lvt offset */
 			hi &= ~MASK_LVTOFF_HI;
 			hi |= tr->lvt_off << 20;
+
+			/* set IntType */
+			hi |= INT_TYPE_APIC;
 		}
 	}
 
-	if (tr->b->interrupt_enable)
-		hi |= INT_TYPE_APIC;
-
  done:
 
 	hi |= MASK_COUNT_EN_HI;
@@ -192,7 +185,6 @@ static void mce_threshold_block_init(struct threshold_block *b, int offset)
 		.lvt_off		= offset,
 	};
 
-	b->threshold_limit		= THRESHOLD_MAX;
 	threshold_restart_bank(&tr);
 };
 
@@ -246,6 +238,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
 			b.block			= block;
 			b.address		= address;
 			b.interrupt_capable	= lvt_interrupt_supported(bank, high);
+			b.threshold_limit	= THRESHOLD_MAX;
 
 			if (!b.interrupt_capable)
 				goto init;
@@ -264,13 +257,9 @@ init:
 }
 
 /*
- * APIC Interrupt Handler
- */
-
-/*
- * threshold interrupt handler will service THRESHOLD_APIC_VECTOR.
+ * The threshold interrupt handler will service THRESHOLD_APIC_VECTOR.
  * the interrupt goes off when error_count reaches threshold_limit.
- * the handler will simply log mcelog w/ software defined bank number.
+ * the handler will simply call mcelog for error decoding
  */
 static void amd_threshold_interrupt(void)
 {
@@ -329,9 +318,7 @@ log:
 	wrmsrl(MSR_IA32_MCx_STATUS(bank), 0);
 }
 
-/*
- * Sysfs Interface
- */
+/* Sysfs Interface */
 
 struct threshold_attr {
 	struct attribute attr;
@@ -497,10 +484,10 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
 	b->interrupt_capable	= lvt_interrupt_supported(bank, high);
 	b->threshold_limit	= THRESHOLD_MAX;
 
-	if (b->interrupt_capable)
+	if (b->interrupt_capable) {
 		threshold_ktype.default_attrs[2] = &interrupt_enable.attr;
-	else
-		threshold_ktype.default_attrs[2] = NULL;
+		b->interrupt_enable = 1;
+	}
 
 	INIT_LIST_HEAD(&b->miscj);
 
-- 
2.1.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-01-23 22:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-23 22:35 [PATCH] x86, mce, amd: Enable interrupts by default if HW capable Aravind Gopalakrishnan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).