Merge tag 'edac_updates_for_v7.4_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras
Merge commit. Changes below are compared with the first parent: 303bff36.
Changes
14 files changed · +567 −24
| File | Status | Add | Del | Content |
|---|---|---|---|---|
| MAINTAINERS | modified | +20 | −6 | View file |
| arch/x86/include/asm/mce.h | modified | +5 | −0 | View file |
| arch/x86/include/asm/msr-index.h | modified | +2 | −0 | View file |
| drivers/base/cacheinfo.c | modified | +17 | −0 | View file |
| drivers/edac/Kconfig | modified | +22 | −0 | View file |
| drivers/edac/Makefile | modified | +4 | −1 | View file |
| drivers/edac/bluefield_edac.c | modified | +2 | −2 | View file |
| drivers/edac/dummy_edac.c | added | +191 | −0 | View file |
| drivers/edac/i10nm_base.c | modified | +2 | −0 | View file |
| drivers/edac/ie31200_edac.c | modified | +3 | −1 | View file |
| drivers/edac/intel-bff.c | added | +295 | −0 | View file |
| drivers/edac/loongson_edac.c | modified | +2 | −2 | View file |
| drivers/edac/skx_base.c | modified | +1 | −1 | View file |
| include/linux/cacheinfo.h | modified | +1 | −11 | View file |
Only the first 600 diff lines are shown. Download the complete patch.
MAINTAINERS
View filediff --git a/MAINTAINERS b/MAINTAINERS
index 56c38a9..83aa851 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2076,8 +2076,7 @@ S: Supported
F: arch/arm64/boot/dts/apm/
APPLIED MICRO (APM) X-GENE SOC EDAC
-M: Khuong Dinh <[email protected]>
-S: Supported
+S: Orphan
F: Documentation/devicetree/bindings/edac/apm,xgene-edac.yaml
F: drivers/edac/xgene_edac.c
@@ -9450,6 +9449,11 @@ L: [email protected]
S: Orphan
F: drivers/edac/i3000_edac.c
+EDAC-I3200
+S: Orphan
+F: drivers/edac/i3200_edac.c
+
EDAC-I5000
S: Maintained
@@ -9474,9 +9478,8 @@ S: Maintained
F: drivers/edac/i7core_edac.c
EDAC-I82975X
-M: "Arvind R." <[email protected]>
-S: Maintained
+S: Orphan
F: drivers/edac/i82975x_edac.c
EDAC-IE31200
@@ -9487,11 +9490,17 @@ F: drivers/edac/ie31200_edac.c
EDAC-IGEN6
M: Tony Luck <[email protected]>
-R: Qiuxu Zhuo <[email protected]>
+R: Qiuxu Zhuo <[email protected]>
S: Maintained
F: drivers/edac/igen6_edac.c
+EDAC-INTEL-BFF-RESET
+M: Tony Luck <[email protected]>
+S: Maintained
+F: drivers/edac/intel-bff.c
+
EDAC-MPC85XX
S: Orphan
@@ -9526,7 +9535,7 @@ F: drivers/edac/qcom_edac.c
EDAC-SBRIDGE
M: Tony Luck <[email protected]>
-R: Qiuxu Zhuo <[email protected]>
+R: Qiuxu Zhuo <[email protected]>
S: Maintained
F: drivers/edac/sb_edac.c
@@ -9543,6 +9552,11 @@ L: [email protected]
S: Odd Fixes
F: drivers/edac/ti_edac.c
+EDAC-X38
+S: Orphan
+F: drivers/edac/x38_edac.c
+
EDIROL UA-101/UA-1000 DRIVER
M: Clemens Ladisch <[email protected]>
arch/x86/include/asm/mce.h
View filediff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index e575b70..9995176 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -13,6 +13,7 @@
#define MCG_CTL_P BIT_ULL(8) /* MCG_CTL register available */
#define MCG_EXT_P BIT_ULL(9) /* Extended registers available */
#define MCG_CMCI_P BIT_ULL(10) /* CMCI supported */
+#define MCG_TES_P BIT_ULL(11) /* Threshold-based error status supported */
#define MCG_SEAM_NR BIT_ULL(12) /* MCG_STATUS_SEAM_NR supported */
#define MCG_EXT_CNT_MASK 0xff0000 /* Number of Extended registers */
#define MCG_EXT_CNT_SHIFT 16
@@ -41,6 +42,10 @@
#define MCI_STATUS_PCC BIT_ULL(57) /* processor context corrupt */
#define MCI_STATUS_S BIT_ULL(56) /* Signaled machine check */
#define MCI_STATUS_AR BIT_ULL(55) /* Action required */
+#define MCI_STATUS_TES_MASK GENMASK_ULL(54, 53)
+#define MCI_STATUS_TES(s) FIELD_GET(MCI_STATUS_TES_MASK, s)
+#define MCI_STATUS_TES_GREEN 1 /* Threshold-based errors below threshold */
+#define MCI_STATUS_TES_YELLOW 2 /* Threshold-based errors above threshold */
#define MCI_STATUS_CEC_SHIFT 38 /* Corrected Error Count */
#define MCI_STATUS_CEC_MASK GENMASK_ULL(52,38)
#define MCI_STATUS_CEC(c) (((c) & MCI_STATUS_CEC_MASK) >> MCI_STATUS_CEC_SHIFT)
arch/x86/include/asm/msr-index.h
View filediff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 3a8e51a..1787fbb 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -114,6 +114,8 @@
#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS BIT(MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT)
#define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT 5
#define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT BIT(MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT)
+#define MSR_IA32_CORE_CAPS_BFF_RESET_BIT 9
+#define MSR_IA32_CORE_CAPS_BFF_RESET BIT(MSR_IA32_CORE_CAPS_BFF_RESET_BIT)
#define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
#define NHM_C3_AUTO_DEMOTE (1UL << 25)
drivers/base/cacheinfo.c
View filediff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index 7a47a39..eb8a907 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -38,6 +38,23 @@ struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu)
return ci_cacheinfo(cpu);
}
+/**
+ * get_cpu_cacheinfo_id - Return the cache ID for a CPU and cache level
+ * @cpu: CPU number
+ * @level: Cache level
+ *
+ * The caller must hold the cpuhp lock.
+ *
+ * Return: Cache ID on success, or -1 if no matching cache exists.
+ */
+int get_cpu_cacheinfo_id(int cpu, int level)
+{
+ struct cacheinfo *ci = get_cpu_cacheinfo_level(cpu, level);
+
+ return ci ? ci->id : -1;
+}
+EXPORT_SYMBOL_GPL(get_cpu_cacheinfo_id);
+
static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf,
struct cacheinfo *sib_leaf)
{
drivers/edac/Kconfig
View filediff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index a44b85c..4c70729 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -280,6 +280,19 @@ config EDAC_IMH
first used on the Diamond Rapids servers but may appear on
others in the future.
+config EDAC_INTEL_BFF_RESET
+ tristate "Intel bitfix filter reset driver"
+ depends on X86_64 && X86_MCE_INTEL
+ help
+ Support for Intel systems that implement bitfix filters to
+ suppress repeated logging and signaling of the same corrected
+ error. Those filters can become clogged with transient errors
+ over time. Clearing the filter may make space for additional
+ hard errors.
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel_bff.
+
config EDAC_PND2
tristate "Intel Pondicherry2"
depends on PCI && X86_64 && X86_MCE_INTEL
@@ -581,4 +594,13 @@ config EDAC_VERSALNET
and other system errors from various IP subsystems like RPU, NOCs,
HNICX, PL on the AMD Versal NET DDR memory controller.
+config EDAC_DUMMY
+ tristate "Dummy EDAC driver"
+ default n
+ help
+ A dummy EDAC driver is useful for testing purposes in a VM when one
+ doesn't have all the hardware needed to test aspects of the EDAC
+ subsystem code.
+
+ You definitely wanna say N here.
endif # EDAC
drivers/edac/Makefile
View filediff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index a375343..4020ea6 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -35,7 +35,7 @@ obj-$(CONFIG_EDAC_I7300) += i7300_edac.o
obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o
obj-$(CONFIG_EDAC_SBRIDGE) += sb_edac.o
obj-$(CONFIG_EDAC_PND2) += pnd2_edac.o
-obj-$(CONFIG_EDAC_IGEN6) += igen6_edac.o
+obj-$(CONFIG_EDAC_IGEN6) += igen6_edac.o
obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
@@ -66,6 +66,8 @@ obj-$(CONFIG_EDAC_I10NM) += i10nm_edac.o skx_edac_common.o
imh_edac-y := imh_base.o
obj-$(CONFIG_EDAC_IMH) += imh_edac.o skx_edac_common.o
+obj-$(CONFIG_EDAC_INTEL_BFF_RESET) += intel-bff.o
+
obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o
obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o
@@ -91,3 +93,4 @@ obj-$(CONFIG_EDAC_VERSAL) += versal_edac.o
obj-$(CONFIG_EDAC_LOONGSON) += loongson_edac.o
obj-$(CONFIG_EDAC_VERSALNET) += versalnet_edac.o
obj-$(CONFIG_EDAC_CORTEX_A72) += a72_edac.o
+obj-$(CONFIG_EDAC_DUMMY) += dummy_edac.o
drivers/edac/bluefield_edac.c
View filediff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c
index ae3bb7a..472fc87 100644
--- a/drivers/edac/bluefield_edac.c
+++ b/drivers/edac/bluefield_edac.c
@@ -472,8 +472,8 @@ static void bluefield_edac_mc_remove(struct platform_device *pdev)
}
static const struct acpi_device_id bluefield_mc_acpi_ids[] = {
- {"MLNXBF08", 0},
- {}
+ { .id = "MLNXBF08" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, bluefield_mc_acpi_ids);
drivers/edac/dummy_edac.c
View filediff --git a/drivers/edac/dummy_edac.c b/drivers/edac/dummy_edac.c
new file mode 100644
index 0000000..193f561
--- /dev/null
+++ b/drivers/edac/dummy_edac.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Dummy EDAC driver
+ *
+ * A minimal EDAC device driver that registers its own platform device
+ * unconditionally, so it probes successfully on any system -- including
+ * VMs and guests that have no real ECC-capable cache/memory hardware
+ * exposed to them. Useful for exercising the EDAC core, sysfs interface,
+ * and userspace tooling (edac-utils, mcelog, etc.) without needing the
+ * physical hardware the "real" drivers depend on.
+ *
+ * Modeled after drivers/edac/a72_edac.c (Cortex A72 EDAC L1/L2 cache
+ * error detection), but with all of the hardware-specific bits (system
+ * register reads, SMP cross-calls, devicetree compatible matching)
+ * replaced by a software-only error source that can be poked from
+ * debugfs or left to generate nothing at all.
+ */
+
+#include <linux/cpu.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "edac_module.h"
+
+#define DRVNAME "dummy-edac"
+#define MESSAGE_SIZE 64
+
+/*
+ * Simulated "error syndrome". In real hardware drivers this would be
+ * read out of a per-CPU system/MMIO register. Here userspace (via
+ * debugfs) or nothing at all drives it, which is exactly the point:
+ * the driver has no dependency on any physical error source.
+ */
+struct dummy_edac_priv {
+ struct dentry *debugfs_dir;
+ atomic_t inject_ce;
+ atomic_t inject_ue;
+};
+
+static void dummy_edac_check(struct edac_device_ctl_info *edac_ctl)
+{
+ struct dummy_edac_priv *priv = edac_ctl->pvt_info;
+ int cpu = raw_smp_processor_id();
+ char msg[MESSAGE_SIZE];
+
+ if (atomic_xchg(&priv->inject_ce, 0)) {
+ snprintf(msg, MESSAGE_SIZE,
+ "simulated correctable error on CPU %d", cpu);
+ edac_device_handle_ce(edac_ctl, cpu, 0, msg);
+ }
+
+ if (atomic_xchg(&priv->inject_ue, 0)) {
+ snprintf(msg, MESSAGE_SIZE,
+ "simulated uncorrectable error on CPU %d", cpu);
+ edac_device_handle_ue(edac_ctl, cpu, 0, msg);
+ }
+}
+
+/*
+ * debugfs knobs so you can drive the driver from userspace inside the
+ * guest, e.g.:
+ * echo 1 > /sys/kernel/debug/dummy-edac/inject_ce
+ * echo 1 > /sys/kernel/debug/dummy-edac/inject_ue
+ */
+static int inject_ce_set(void *data, u64 val)
+{
+ struct dummy_edac_priv *priv = data;
+
+ if (val)
+ atomic_set(&priv->inject_ce, 1);
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(inject_ce_fops, NULL, inject_ce_set, "%llu\n");
+
+static int inject_ue_set(void *data, u64 val)
+{
+ struct dummy_edac_priv *priv = data;
+
+ if (val)
+ atomic_set(&priv->inject_ue, 1);
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(inject_ue_fops, NULL, inject_ue_set, "%llu\n");
+
+static int dummy_edac_probe(struct platform_device *pdev)
+{
+ struct edac_device_ctl_info *edac_ctl;
+ struct dummy_edac_priv *priv;
+ struct device *dev = &pdev->dev;
+ int rc;
+
+ edac_ctl = edac_device_alloc_ctl_info(sizeof(*priv), "cpu",
+ num_possible_cpus(), "L", 1, 1,
+ edac_device_alloc_index());
+ if (!edac_ctl)
+ return -ENOMEM;
+
+ priv = edac_ctl->pvt_info;
+ atomic_set(&priv->inject_ce, 0);
+ atomic_set(&priv->inject_ue, 0);
+
+ edac_ctl->edac_check = dummy_edac_check;
+ edac_ctl->dev = dev;
+ edac_ctl->mod_name = dev_name(dev);
+ edac_ctl->dev_name = dev_name(dev);
+ edac_ctl->ctl_name = DRVNAME;
+ /* Poll fairly slowly; this is a software source, not real hardware. */
+ edac_ctl->poll_msec = 1000;
+ dev_set_drvdata(dev, edac_ctl);
+
+ rc = edac_device_add_device(edac_ctl);
+ if (rc)
+ goto out_dev;
+
+ priv->debugfs_dir = debugfs_create_dir(DRVNAME, NULL);
+ debugfs_create_file_unsafe("inject_ce", 0200, priv->debugfs_dir,
+ priv, &inject_ce_fops);
+ debugfs_create_file_unsafe("inject_ue", 0200, priv->debugfs_dir,
+ priv, &inject_ue_fops);
+
+ return 0;
+
+out_dev:
+ edac_device_free_ctl_info(edac_ctl);
+
+ return rc;
+}
+
+static void dummy_edac_remove(struct platform_device *pdev)
+{
+ struct edac_device_ctl_info *edac_ctl = dev_get_drvdata(&pdev->dev);
+ struct dummy_edac_priv *priv = edac_ctl->pvt_info;
+
+ debugfs_remove_recursive(priv->debugfs_dir);
+ edac_device_del_device(edac_ctl->dev);
+ edac_device_free_ctl_info(edac_ctl);
+}
+
+static struct platform_driver dummy_edac_driver = {
+ .probe = dummy_edac_probe,
+ .remove = dummy_edac_remove,
+ .driver = {
+ .name = DRVNAME,
+ },
+};
+
+/*
+ * No devicetree/ACPI match table, and no scan of CPU nodes for a "compatible"
+ * + enable property: simply register a platform device unconditionally so
+ * probe() always runs. There is nothing here that depends on the underlying
+ * platform actually exposing the corresponding hardware, so it loads fine
+ * under QEMU/KVM, containers-with-a-kernel, or any other guest environment.
+ */
+static struct platform_device *dummy_pdev;
+
+static int __init dummy_edac_driver_init(void)
+{
+ int rc;
+
+ dummy_pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
+ if (IS_ERR(dummy_pdev)) {
+ pr_err(DRVNAME ": failed to register dummy platform device\n");
+ return PTR_ERR(dummy_pdev);
+ }
+
+ rc = platform_driver_register(&dummy_edac_driver);
+ if (rc) {
+ platform_device_unregister(dummy_pdev);
+ return rc;
+ }
+
+ pr_info("Loading %s\n", DRVNAME);
+
+ return 0;
+}
+
+static void __exit dummy_edac_driver_exit(void)
+{
+ platform_driver_unregister(&dummy_edac_driver);
+ platform_device_unregister(dummy_pdev);
+
+ pr_info("Removing %s\n", DRVNAME);
+}
+
+module_init(dummy_edac_driver_init);
+module_exit(dummy_edac_driver_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Dummy EDAC driver for testing without real ECC hardware");
drivers/edac/i10nm_base.c
View filediff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
index fa1853f..87e541c 100644
--- a/drivers/edac/i10nm_base.c
+++ b/drivers/edac/i10nm_base.c
@@ -479,6 +479,7 @@ static struct pci_dev *get_gnr_mdev(struct skx_dev *d, int logical_idx, int *phy
if (mdev) {
if (logical == logical_idx) {
*physical_idx = i;
+ skx_set_mc_mapping(d, i, logical_idx);
return mdev;
}
@@ -634,6 +635,7 @@ static int i10nm_get_ddr_munits(void)
mbase = ioremap(base + off, size);
if (!mbase) {
+ pci_dev_put(mdev);
i10nm_printk(KERN_ERR, "Failed to ioremap 0x%llx\n",
base + off);
return -ENODEV;
drivers/edac/ie31200_edac.c
View filediff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
index 6f5fdf4..88af77e 100644
--- a/drivers/edac/ie31200_edac.c
+++ b/drivers/edac/ie31200_edac.c
@@ -660,7 +660,9 @@ static int ie31200_init_one(struct pci_dev *pdev,
if (pci_enable_device(pdev) < 0)
return -EIO;
rc = ie31200_probe1(pdev, (struct res_config *)ent->driver_data);
- if (rc == 0 && !mci_pdev)
+ if (rc)
+ pci_disable_device(pdev);
+ else if (!mci_pdev)
mci_pdev = pci_dev_get(pdev);
return rc;
drivers/edac/intel-bff.c
View filediff --git a/drivers/edac/intel-bff.c b/drivers/edac/intel-bff.c
new file mode 100644
index 0000000..adf2ec3
--- /dev/null
+++ b/drivers/edac/intel-bff.c
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2026 Intel Corporation. */
+
+/*
+ * Intel driver to reset bitfix filters when they overflow.
+ *
+ * Each bitfix filter has limited slots to track corrected errors.
+ * These slots can be filled by transient corrected errors (e.g.,
+ * bit flips from particle strikes) that don't represent permanent
+ * hardware defects.
+ *
+ * When the filter overflows (yellow status), reset it to reclaim
+ * slots occupied by transient corrected errors. If the overflow
+ * repeats frequently after reset, it indicates persistent hardware
+ * defects that need attention: the system should be scheduled for
+ * servicing.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/cacheinfo.h>
+#include <linux/cleanup.h>
+#include <linux/cpufeature.h>
+#include <linux/cpuhplock.h>
+#include <linux/device-id/x86_cpu.h>
+#include <linux/errno.h>
+#include <linux/gfp_types.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/topology.h>
+#include <linux/types.h>
+#include <linux/xarray.h>
+
+#include <asm/cpu_device_id.h>
+#include <asm/cpufeatures.h>
+#include <asm/intel-family.h>
+#include <asm/mce.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
+
+/*
+ * A 10-minute observation period helps distinguish between:
+ *
+ * - A long-term accumulation of transient corrected errors
+ * (filter stays clear after reset).
+ *
+ * - Permanent defects (filter overflows again quickly).
+ */
+#define BFF_OVERFLOW_INTERVAL secs_to_jiffies(10 * 60)
+
+/* Intel bitfix filter control register defines */
+#define MSR_MC0_BFF_CTL 0x000006c0
+#define MSR_MCx_BFF_CTL(x) (MSR_MC0_BFF_CTL + (x))
+#define MCI_BFF_RESET BIT_ULL(0)
+
+/* Machine check bank hardware unit types */
+enum bff_bank_type {
+ BFF_BANK_NONE = 0,
+ BFF_BANK_DCU,
+ BFF_BANK_DTLB,
+ BFF_BANK_MLC,
+ BFF_BANK_CCF,
+ BFF_BANK_HSF,
+ BFF_BANK_IOCACHE,
+};
+
+/*
+ * Mapping from machine check bank numbers on Diamond Rapids CPU, that are
+ * supported by a bitfix filter, to hardware unit type.
+ */
+static const enum bff_bank_type dmr_mcbanks[MAX_NR_BANKS] = {
+ [1] = BFF_BANK_DCU,
+ [2] = BFF_BANK_DTLB,
+ [3] = BFF_BANK_MLC,
+ [6] = BFF_BANK_CCF,
+ [13] = BFF_BANK_HSF,
+ [17] = BFF_BANK_IOCACHE
+};
+
+static const struct x86_cpu_id bff_cpu_ids[] __initconst = {
+ X86_MATCH_VFM(INTEL_DIAMONDRAPIDS_X, dmr_mcbanks),
+ {}
+};
+MODULE_DEVICE_TABLE(x86cpu, bff_cpu_ids);
+
+static const enum bff_bank_type *bff_bank_types;
+
+static DEFINE_XARRAY(bff_bank_xa);
+
+/* Diamond Rapids maps APICID[2] to the IMH instance within a socket. */
+#define APICID_IMH_NUM GENMASK(2, 2)
+#define IMH_NUM(apicid) FIELD_GET(APICID_IMH_NUM, apicid)
+#define NUM_IMH_PER_SOCKET 2
+
+static void bff_set_imh_id(struct mce *mce, unsigned long *id)
+{
+ int imh_num;
+
+ imh_num = NUM_IMH_PER_SOCKET * topology_physical_package_id(mce->extcpu) +
+ IMH_NUM(mce->apicid);
+
+ *id |= imh_num;
+}
+
+static bool bff_set_cache_id(int cpu, int level, unsigned long *id)
+{
+ int cacheid;
+
+ guard(cpus_read_lock)();
+
+ cacheid = get_cpu_cacheinfo_id(cpu, level);
+ if (cacheid == -1) {
+ pr_warn("Could not get L%d cache id for CPU %d\n", level, cpu);
+ return false;
+ }
+
+ *id |= cacheid;
+
+ return true;
+}
+
+/*
+ * Cache IDs are only unique within a cache level.
+ * Include the MCA bank number so each BFF-capable hardware
+ * resource has a unique tracking ID.
+ */
+#define BFF_ID_BANK_FIELD GENMASK(63, 32)
+
+static unsigned long bff_get_id(struct mce *mce)
+{
+ unsigned long id = FIELD_PREP(BFF_ID_BANK_FIELD, mce->bank);
+
+ switch (bff_bank_types[mce->bank]) {
+ case BFF_BANK_DCU:
+ case BFF_BANK_DTLB:
This diff is incomplete. Download the complete patch.
drivers/edac/loongson_edac.c
View fileThis diff is incomplete. Download the complete patch.
drivers/edac/skx_base.c
View fileThis diff is incomplete. Download the complete patch.
include/linux/cacheinfo.h
View fileThis diff is incomplete. Download the complete patch.