Re: [PATCH v2 1/3] EDAC/loongson: Encode node and MC info into mc_idx
Huacai Chen <[email protected]>
| Newsgroups | org.kernel.vger.linux-edac,dev.linux.lists.loongarch,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAAhV-H5F6JasjxgiDeDdsz64o186CoL1+EEkH6OJSHPZG0PDOQ@mail.gmail.com> |
Hi, Qunqin, On Wed, Aug 5, 2026 at 5:09 PM Qunqin Zhao <[email protected]> wrote: > > From: Wang Jinwei <[email protected]> > > On Loongson multi-node systems, memory controllers are distributed across > multiple nodes. Encode node and MC information into mc_idx so that sysfs > entries uniquely identify each controller. > > The driver gets mc-idx from ACPI _DSD property if firmware provides it. > If not, it falls back to edac_device_alloc_index() for legacy firmware > compatibility. > > The number of memory controllers per node (mcs-per-node) is obtained > from firmware via ACPI _DSD property, with a default of 4 for backward > compatibility. Validate that the firmware-provided value is non-zero to > prevent division by zero. The node and MC IDs are decoded from mc_idx: > node = mc_idx / mcs_per_node > mc = mc_idx % mcs_per_node > > Cc: Yulong Wang <[email protected]> > Cc: Dongyan Qian <[email protected]> > Cc: Chao Li <[email protected]> > Signed-off-by: Wang Jinwei <[email protected]> > Signed-off-by: Qunqin Zhao <[email protected]> > --- > drivers/edac/loongson_edac.c | 35 ++++++++++++++++++++++++++++++----- > 1 file changed, 30 insertions(+), 5 deletions(-) > > diff --git a/drivers/edac/loongson_edac.c b/drivers/edac/loongson_edac.c > index 38745800ed..abfc1e60e0 100644 > --- a/drivers/edac/loongson_edac.c > +++ b/drivers/edac/loongson_edac.c > @@ -9,6 +9,7 @@ > #include <linux/io-64-nonatomic-lo-hi.h> > #include <linux/module.h> > #include <linux/platform_device.h> > +#include <linux/property.h> > #include "edac_module.h" > > #define ECC_CS_COUNT_REG 0x18 > @@ -23,6 +24,8 @@ struct loongson_edac_pvt { > * register state. > */ > int last_ce_count; > + int mcs_per_node; > + bool mc_idx_valid; > }; > > static int read_ecc(struct mem_ctl_info *mci) > @@ -44,7 +47,8 @@ static int read_ecc(struct mem_ctl_info *mci) > static void edac_check(struct mem_ctl_info *mci) > { > struct loongson_edac_pvt *pvt = mci->pvt_info; > - int new, add; > + char other_detail[64] = {0}; > + int new, add, node, mc; > > new = read_ecc(mci); > add = new - pvt->last_ce_count; > @@ -52,8 +56,14 @@ static void edac_check(struct mem_ctl_info *mci) > if (add <= 0) > return; > > + if (pvt->mc_idx_valid) { > + node = mci->mc_idx / pvt->mcs_per_node; > + mc = mci->mc_idx % pvt->mcs_per_node; > + snprintf(other_detail, sizeof(other_detail), "node:%d mc:%d", node, mc); > + } > + > edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, add, > - 0, 0, 0, 0, 0, -1, "error", ""); > + 0, 0, 0, 0, 0, -1, "error", other_detail); > } > > static void dimm_config_init(struct mem_ctl_info *mci) > @@ -72,20 +82,26 @@ static void dimm_config_init(struct mem_ctl_info *mci) > dimm->grain = 8; > } > > -static void pvt_init(struct mem_ctl_info *mci, void __iomem *vbase) > +static void pvt_init(struct mem_ctl_info *mci, void __iomem *vbase, > + bool mc_idx_valid, int mcs_per_node) > { > struct loongson_edac_pvt *pvt = mci->pvt_info; > > pvt->ecc_base = vbase; > pvt->last_ce_count = read_ecc(mci); > + pvt->mc_idx_valid = mc_idx_valid; > + pvt->mcs_per_node = mcs_per_node; > } > > static int edac_probe(struct platform_device *pdev) > { > struct edac_mc_layer layers[2]; > struct mem_ctl_info *mci; > + struct device *dev = &pdev->dev; > void __iomem *vbase; > + u32 mcs_per_node, mc_idx_u32; Why do we need mc_idx_u32? The code in V1 doesn't work? > int ret; > + bool mc_idx_valid = true; > > vbase = devm_platform_ioremap_resource(pdev, 0); > if (IS_ERR(vbase)) > @@ -102,7 +118,6 @@ static int edac_probe(struct platform_device *pdev) > if (mci == NULL) > return -ENOMEM; > > - mci->mc_idx = edac_device_alloc_index(); > mci->mtype_cap = MEM_FLAG_RDDR4; > mci->edac_ctl_cap = EDAC_FLAG_NONE; > mci->edac_cap = EDAC_FLAG_NONE; > @@ -114,7 +129,17 @@ static int edac_probe(struct platform_device *pdev) > mci->error_desc.grain = 8; > mci->edac_check = edac_check; > > - pvt_init(mci, vbase); > + if (device_property_read_u32(dev, "mc-idx", &mc_idx_u32)) { > + mci->mc_idx = edac_device_alloc_index(); > + mc_idx_valid = false; > + } else { > + mci->mc_idx = mc_idx_u32; > + } > + > + if (device_property_read_u32(dev, "mc-per-node", &mcs_per_node) || mcs_per_node == 0) The property should also be mcs-per-node. Huacai > + mcs_per_node = 4; > + > + pvt_init(mci, vbase, mc_idx_valid, mcs_per_node); > dimm_config_init(mci); > > ret = edac_mc_add_mc(mci); > -- > 2.47.3 > >