diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 14 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_amd.c | 38 |
2 files changed, 23 insertions, 29 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index e9ffd6d9e32d..052b5e05c3c4 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -2255,8 +2255,6 @@ static struct bus_type mce_subsys = { DEFINE_PER_CPU(struct device *, mce_device); -void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); - static inline struct mce_bank *attr_to_bank(struct device_attribute *attr) { return container_of(attr, struct mce_bank, attr); @@ -2512,13 +2510,17 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: + mce_device_create(cpu); - if (threshold_cpu_callback) - threshold_cpu_callback(action, cpu); + + if (mce_threshold_create_device(cpu)) { + mce_device_remove(cpu); + return NOTIFY_BAD; + } + break; case CPU_DEAD: - if (threshold_cpu_callback) - threshold_cpu_callback(action, cpu); + mce_threshold_remove_device(cpu); mce_device_remove(cpu); mce_intel_hcpu_update(cpu); diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index e93580c82ef0..c33a3ee2e383 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -55,6 +55,8 @@ /* Threshold LVT offset is at MSR0xC0000410[15:12] */ #define SMCA_THR_LVT_OFF 0xF000 +static bool thresholding_en; + static const char * const th_names[] = { "load_store", "insn_fetch", @@ -1077,10 +1079,13 @@ free_out: per_cpu(threshold_banks, cpu)[bank] = NULL; } -static void threshold_remove_device(unsigned int cpu) +int mce_threshold_remove_device(unsigned int cpu) { unsigned int bank; + if (!thresholding_en) + return 0; + for (bank = 0; bank < mca_cfg.banks; ++bank) { if (!(per_cpu(bank_map, cpu) & (1 << bank))) continue; @@ -1088,15 +1093,19 @@ static void threshold_remove_device(unsigned int cpu) } kfree(per_cpu(threshold_banks, cpu)); per_cpu(threshold_banks, cpu) = NULL; + return 0; } /* create dir/files for all valid threshold banks */ -static int threshold_create_device(unsigned int cpu) +int mce_threshold_create_device(unsigned int cpu) { unsigned int bank; struct threshold_bank **bp; int err = 0; + if (!thresholding_en) + return 0; + bp = per_cpu(threshold_banks, cpu); if (bp) return 0; @@ -1117,40 +1126,23 @@ static int threshold_create_device(unsigned int cpu) } return err; err: - threshold_remove_device(cpu); + mce_threshold_remove_device(cpu); return err; } -/* get notified when a cpu comes on/off */ -static void -amd_64_threshold_cpu_callback(unsigned long action, unsigned int cpu) -{ - switch (action) { - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - threshold_create_device(cpu); - break; - case CPU_DEAD: - case CPU_DEAD_FROZEN: - threshold_remove_device(cpu); - break; - default: - break; - } -} - static __init int threshold_init_device(void) { unsigned lcpu = 0; /* to hit CPUs online before the notifier is up */ for_each_online_cpu(lcpu) { - int err = threshold_create_device(lcpu); + int err = mce_threshold_create_device(lcpu); if (err) return err; } - threshold_cpu_callback = amd_64_threshold_cpu_callback; + + thresholding_en = true; return 0; } |