aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0043-x86-MCE-AMD-EDAC-mce_amd-Support-non-uniform-MCA-ban.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0043-x86-MCE-AMD-EDAC-mce_amd-Support-non-uniform-MCA-ban.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0043-x86-MCE-AMD-EDAC-mce_amd-Support-non-uniform-MCA-ban.patch311
1 files changed, 311 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0043-x86-MCE-AMD-EDAC-mce_amd-Support-non-uniform-MCA-ban.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0043-x86-MCE-AMD-EDAC-mce_amd-Support-non-uniform-MCA-ban.patch
new file mode 100644
index 00000000..e1733724
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0043-x86-MCE-AMD-EDAC-mce_amd-Support-non-uniform-MCA-ban.patch
@@ -0,0 +1,311 @@
+From 138fc4242a6f7dacfa329d112108b7d43e9c8d47 Mon Sep 17 00:00:00 2001
+From: Yazen Ghannam <yazen.ghannam@amd.com>
+Date: Thu, 16 Dec 2021 16:29:05 +0000
+Subject: [PATCH 43/86] x86/MCE/AMD, EDAC/mce_amd: Support non-uniform MCA bank
+ type enumeration
+
+commit 91f75eb481cfaee5c4ed8fb5214bf2fbfa04bd7b upstream
+
+AMD systems currently lay out MCA bank types such that the type of bank
+number "i" is either the same across all CPUs or is Reserved/Read-as-Zero.
+
+For example:
+
+ Bank # | CPUx | CPUy
+ 0 LS LS
+ 1 RAZ UMC
+ 2 CS CS
+ 3 SMU RAZ
+
+Future AMD systems will lay out MCA bank types such that the type of
+bank number "i" may be different across CPUs.
+
+For example:
+
+ Bank # | CPUx | CPUy
+ 0 LS LS
+ 1 RAZ UMC
+ 2 CS NBIO
+ 3 SMU RAZ
+
+Change the structures that cache MCA bank types to be per-CPU and update
+smca_get_bank_type() to handle this change.
+
+Move some SMCA-specific structures to amd.c from mce.h, since they no
+longer need to be global.
+
+Break out the "count" for bank types from struct smca_hwid, since this
+should provide a per-CPU count rather than a system-wide count.
+
+Apply the "const" qualifier to the struct smca_hwid_mcatypes array. The
+values in this array should not change at runtime.
+
+Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20211216162905.4132657-3-yazen.ghannam@amd.com
+Signed-off-by: Zhaolong Zhang <zhaolong.zhang@windriver.com>
+---
+ arch/x86/include/asm/mce.h | 18 +-------
+ arch/x86/kernel/cpu/mce/amd.c | 59 +++++++++++++++----------
+ drivers/edac/mce_amd.c | 11 +----
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
+ 4 files changed, 39 insertions(+), 51 deletions(-)
+
+diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
+index 85eae8570cc4..f686ed9723e0 100644
+--- a/arch/x86/include/asm/mce.h
++++ b/arch/x86/include/asm/mce.h
+@@ -341,22 +341,6 @@ enum smca_bank_types {
+ N_SMCA_BANK_TYPES
+ };
+
+-#define HWID_MCATYPE(hwid, mcatype) (((hwid) << 16) | (mcatype))
+-
+-struct smca_hwid {
+- unsigned int bank_type; /* Use with smca_bank_types for easy indexing. */
+- u32 hwid_mcatype; /* (hwid,mcatype) tuple */
+- u8 count; /* Number of instances. */
+-};
+-
+-struct smca_bank {
+- struct smca_hwid *hwid;
+- u32 id; /* Value of MCA_IPID[InstanceId]. */
+- u8 sysfs_id; /* Value used for sysfs name. */
+-};
+-
+-extern struct smca_bank smca_banks[MAX_NR_BANKS];
+-
+ extern const char *smca_get_long_name(enum smca_bank_types t);
+ extern bool amd_mce_is_memory_error(struct mce *m);
+
+@@ -364,7 +348,7 @@ extern int mce_threshold_create_device(unsigned int cpu);
+ extern int mce_threshold_remove_device(unsigned int cpu);
+
+ void mce_amd_feature_init(struct cpuinfo_x86 *c);
+-enum smca_bank_types smca_get_bank_type(unsigned int bank);
++enum smca_bank_types smca_get_bank_type(unsigned int cpu, unsigned int bank);
+ #else
+
+ static inline int mce_threshold_create_device(unsigned int cpu) { return 0; };
+diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c
+index 2f94c1da79e3..628e5bb7f241 100644
+--- a/arch/x86/kernel/cpu/mce/amd.c
++++ b/arch/x86/kernel/cpu/mce/amd.c
+@@ -71,6 +71,22 @@ static const char * const smca_umc_block_names[] = {
+ "misc_umc"
+ };
+
++#define HWID_MCATYPE(hwid, mcatype) (((hwid) << 16) | (mcatype))
++
++struct smca_hwid {
++ unsigned int bank_type; /* Use with smca_bank_types for easy indexing. */
++ u32 hwid_mcatype; /* (hwid,mcatype) tuple */
++};
++
++struct smca_bank {
++ const struct smca_hwid *hwid;
++ u32 id; /* Value of MCA_IPID[InstanceId]. */
++ u8 sysfs_id; /* Value used for sysfs name. */
++};
++
++static DEFINE_PER_CPU_READ_MOSTLY(struct smca_bank[MAX_NR_BANKS], smca_banks);
++static DEFINE_PER_CPU_READ_MOSTLY(u8[N_SMCA_BANK_TYPES], smca_bank_counts);
++
+ struct smca_bank_name {
+ const char *name; /* Short name for sysfs */
+ const char *long_name; /* Long name for pretty-printing */
+@@ -126,14 +142,14 @@ const char *smca_get_long_name(enum smca_bank_types t)
+ }
+ EXPORT_SYMBOL_GPL(smca_get_long_name);
+
+-enum smca_bank_types smca_get_bank_type(unsigned int bank)
++enum smca_bank_types smca_get_bank_type(unsigned int cpu, unsigned int bank)
+ {
+ struct smca_bank *b;
+
+ if (bank >= MAX_NR_BANKS)
+ return N_SMCA_BANK_TYPES;
+
+- b = &smca_banks[bank];
++ b = &per_cpu(smca_banks, cpu)[bank];
+ if (!b->hwid)
+ return N_SMCA_BANK_TYPES;
+
+@@ -141,7 +157,7 @@ enum smca_bank_types smca_get_bank_type(unsigned int bank)
+ }
+ EXPORT_SYMBOL_GPL(smca_get_bank_type);
+
+-static struct smca_hwid smca_hwid_mcatypes[] = {
++static const struct smca_hwid smca_hwid_mcatypes[] = {
+ /* { bank_type, hwid_mcatype } */
+
+ /* Reserved type */
+@@ -202,9 +218,6 @@ static struct smca_hwid smca_hwid_mcatypes[] = {
+ { SMCA_GMI_PHY, HWID_MCATYPE(0x269, 0x0) },
+ };
+
+-struct smca_bank smca_banks[MAX_NR_BANKS];
+-EXPORT_SYMBOL_GPL(smca_banks);
+-
+ /*
+ * In SMCA enabled processors, we can have multiple banks for a given IP type.
+ * So to define a unique name for each bank, we use a temp c-string to append
+@@ -260,8 +273,9 @@ static void smca_set_misc_banks_map(unsigned int bank, unsigned int cpu)
+
+ static void smca_configure(unsigned int bank, unsigned int cpu)
+ {
++ u8 *bank_counts = this_cpu_ptr(smca_bank_counts);
++ const struct smca_hwid *s_hwid;
+ unsigned int i, hwid_mcatype;
+- struct smca_hwid *s_hwid;
+ u32 high, low;
+ u32 smca_config = MSR_AMD64_SMCA_MCx_CONFIG(bank);
+
+@@ -297,10 +311,6 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
+
+ smca_set_misc_banks_map(bank, cpu);
+
+- /* Return early if this bank was already initialized. */
+- if (smca_banks[bank].hwid && smca_banks[bank].hwid->hwid_mcatype != 0)
+- return;
+-
+ if (rdmsr_safe(MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) {
+ pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
+ return;
+@@ -311,10 +321,11 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
+
+ for (i = 0; i < ARRAY_SIZE(smca_hwid_mcatypes); i++) {
+ s_hwid = &smca_hwid_mcatypes[i];
++
+ if (hwid_mcatype == s_hwid->hwid_mcatype) {
+- smca_banks[bank].hwid = s_hwid;
+- smca_banks[bank].id = low;
+- smca_banks[bank].sysfs_id = s_hwid->count++;
++ this_cpu_ptr(smca_banks)[bank].hwid = s_hwid;
++ this_cpu_ptr(smca_banks)[bank].id = low;
++ this_cpu_ptr(smca_banks)[bank].sysfs_id = bank_counts[s_hwid->bank_type]++;
+ break;
+ }
+ }
+@@ -600,7 +611,7 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
+
+ bool amd_filter_mce(struct mce *m)
+ {
+- enum smca_bank_types bank_type = smca_get_bank_type(m->bank);
++ enum smca_bank_types bank_type = smca_get_bank_type(m->extcpu, m->bank);
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+
+ /* See Family 17h Models 10h-2Fh Erratum #1114. */
+@@ -638,7 +649,7 @@ static void disable_err_thresholding(struct cpuinfo_x86 *c, unsigned int bank)
+ } else if (c->x86 == 0x17 &&
+ (c->x86_model >= 0x10 && c->x86_model <= 0x2F)) {
+
+- if (smca_get_bank_type(bank) != SMCA_IF)
++ if (smca_get_bank_type(smp_processor_id(), bank) != SMCA_IF)
+ return;
+
+ msrs[0] = MSR_AMD64_SMCA_MCx_MISC(bank);
+@@ -706,7 +717,7 @@ bool amd_mce_is_memory_error(struct mce *m)
+ u8 xec = (m->status >> 16) & 0x1f;
+
+ if (mce_flags.smca)
+- return smca_get_bank_type(m->bank) == SMCA_UMC && xec == 0x0;
++ return smca_get_bank_type(m->extcpu, m->bank) == SMCA_UMC && xec == 0x0;
+
+ return m->bank == 4 && xec == 0x8;
+ }
+@@ -1022,7 +1033,7 @@ static struct kobj_type threshold_ktype = {
+ .release = threshold_block_release,
+ };
+
+-static const char *get_name(unsigned int bank, struct threshold_block *b)
++static const char *get_name(unsigned int cpu, unsigned int bank, struct threshold_block *b)
+ {
+ enum smca_bank_types bank_type;
+
+@@ -1033,7 +1044,7 @@ static const char *get_name(unsigned int bank, struct threshold_block *b)
+ return th_names[bank];
+ }
+
+- bank_type = smca_get_bank_type(bank);
++ bank_type = smca_get_bank_type(cpu, bank);
+ if (bank_type >= N_SMCA_BANK_TYPES)
+ return NULL;
+
+@@ -1043,12 +1054,12 @@ static const char *get_name(unsigned int bank, struct threshold_block *b)
+ return NULL;
+ }
+
+- if (smca_banks[bank].hwid->count == 1)
++ if (per_cpu(smca_bank_counts, cpu)[bank_type] == 1)
+ return smca_get_name(bank_type);
+
+ snprintf(buf_mcatype, MAX_MCATYPE_NAME_LEN,
+- "%s_%x", smca_get_name(bank_type),
+- smca_banks[bank].sysfs_id);
++ "%s_%u", smca_get_name(bank_type),
++ per_cpu(smca_banks, cpu)[bank].sysfs_id);
+ return buf_mcatype;
+ }
+
+@@ -1104,7 +1115,7 @@ static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb
+ else
+ tb->blocks = b;
+
+- err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(bank, b));
++ err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(cpu, bank, b));
+ if (err)
+ goto out_free;
+ recurse:
+@@ -1159,7 +1170,7 @@ static int threshold_create_bank(struct threshold_bank **bp, unsigned int cpu,
+ struct device *dev = this_cpu_read(mce_device);
+ struct amd_northbridge *nb = NULL;
+ struct threshold_bank *b = NULL;
+- const char *name = get_name(bank, NULL);
++ const char *name = get_name(cpu, bank, NULL);
+ int err = 0;
+
+ if (!dev)
+diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
+index cfd3f7ae9251..cc5c63feb26a 100644
+--- a/drivers/edac/mce_amd.c
++++ b/drivers/edac/mce_amd.c
+@@ -1166,20 +1166,13 @@ static void decode_mc6_mce(struct mce *m)
+ /* Decode errors according to Scalable MCA specification */
+ static void decode_smca_error(struct mce *m)
+ {
+- struct smca_hwid *hwid;
+- enum smca_bank_types bank_type;
++ enum smca_bank_types bank_type = smca_get_bank_type(m->extcpu, m->bank);
+ const char *ip_name;
+ u8 xec = XEC(m->status, xec_mask);
+
+- if (m->bank >= ARRAY_SIZE(smca_banks))
++ if (bank_type >= N_SMCA_BANK_TYPES)
+ return;
+
+- hwid = smca_banks[m->bank].hwid;
+- if (!hwid)
+- return;
+-
+- bank_type = hwid->bank_type;
+-
+ if (bank_type == SMCA_RESERVED) {
+ pr_emerg(HW_ERR "Bank %d is reserved.\n", m->bank);
+ return;
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+index 6660327c7c50..ceabb3f89a76 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+@@ -2566,7 +2566,7 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
+ * and error occurred in DramECC (Extended error code = 0) then only
+ * process the error, else bail out.
+ */
+- if (!m || !((smca_get_bank_type(m->bank) == SMCA_UMC_V2) &&
++ if (!m || !((smca_get_bank_type(m->extcpu, m->bank) == SMCA_UMC_V2) &&
+ (XEC(m->status, 0x3f) == 0x0)))
+ return NOTIFY_DONE;
+
+--
+2.37.3
+