]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
EDAC/{skx_common,i10nm}: Move RRL handling to common code
authorQiuxu Zhuo <qiuxu.zhuo@intel.com>
Thu, 21 May 2026 07:31:09 +0000 (15:31 +0800)
committerTony Luck <tony.luck@intel.com>
Fri, 29 May 2026 15:34:12 +0000 (08:34 -0700)
Move RRL (Retry Read error Log)  handling from i10nm_edac to skx_common
so it can be shared across EDAC drivers (e.g. imh_edac).

- Move RRL enable/disable and log dumping helpers to skx_common
  to avoid code duplication and enable reuse by other drivers.

- Export skx_enable_rrl() and skx_show_rrl()
  so common RRL handling can be used by i10nm_edac and imh_edac.

No functional change intended.

Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Tested-by: Yi Lai <yi1.lai@intel.com>
Link: https://patch.msgid.link/20260521073112.3881223-6-qiuxu.zhuo@intel.com
drivers/edac/i10nm_base.c
drivers/edac/skx_common.c
drivers/edac/skx_common.h

index fe148f1f2319d5bcd140309d4a7662a3fc858d3a..2e21eefbb4f5df5fa38d1fce3e97d43b444f1870 100644 (file)
@@ -183,191 +183,6 @@ static struct reg_rrl gnr_reg_rrl_ddr = {
        .cecnt_widths   = {4, 4, 4, 4, 4, 4, 4, 4},
 };
 
-static void enable_rrl(struct skx_imc *imc, int chan, struct reg_rrl *rrl,
-                      int rrl_set, bool enable, u32 *rrl_ctl)
-{
-       enum rrl_source_type source = rrl->sources[rrl_set];
-       u32 offset = rrl->offsets[rrl_set][0], v;
-       u8 width = rrl->widths[0];
-       bool first, scrub;
-
-       /* First or last read error. */
-       first = (source == RRL_SRC_FRE_SCRUB || source == RRL_SRC_FRE_DEMAND);
-       /* Patrol scrub or on-demand read error. */
-       scrub = (source == RRL_SRC_FRE_SCRUB || source == RRL_SRC_LRE_SCRUB);
-
-       v = skx_read_imc_reg(imc, chan, offset, width);
-
-       if (enable) {
-               /* Save default configurations. */
-               *rrl_ctl = v;
-               v &= ~rrl->uc_mask;
-
-               if (first)
-                       v |= rrl->noover_mask;
-               else
-                       v &= ~rrl->noover_mask;
-
-               if (scrub)
-                       v |= rrl->en_patspr_mask;
-               else
-                       v &= ~rrl->en_patspr_mask;
-
-               v |= rrl->en_mask;
-       } else {
-               /* Restore default configurations. */
-               if (*rrl_ctl & rrl->uc_mask)
-                       v |= rrl->uc_mask;
-
-               if (first) {
-                       if (!(*rrl_ctl & rrl->noover_mask))
-                               v &= ~rrl->noover_mask;
-               } else {
-                       if (*rrl_ctl & rrl->noover_mask)
-                               v |= rrl->noover_mask;
-               }
-
-               if (scrub) {
-                       if (!(*rrl_ctl & rrl->en_patspr_mask))
-                               v &= ~rrl->en_patspr_mask;
-               } else {
-                       if (*rrl_ctl & rrl->en_patspr_mask)
-                               v |= rrl->en_patspr_mask;
-               }
-
-               if (!(*rrl_ctl & rrl->en_mask))
-                       v &= ~rrl->en_mask;
-       }
-
-       skx_write_imc_reg(imc, chan, offset, width, v);
-}
-
-static void enable_rrls(struct skx_imc *imc, int chan, struct reg_rrl *rrl,
-                       bool enable, u32 *rrl_ctl)
-{
-       for (int i = 0; i < rrl->set_num; i++)
-               enable_rrl(imc, chan, rrl, i, enable, rrl_ctl + i);
-}
-
-static void enable_rrls_ddr(struct skx_imc *imc, bool enable)
-{
-       struct reg_rrl *rrl_ddr = res_cfg->reg_rrl_ddr;
-       int i, chan_num = res_cfg->ddr_chan_num;
-       struct skx_channel *chan = imc->chan;
-
-       if (!imc->mbase)
-               return;
-
-       for (i = 0; i < chan_num; i++)
-               enable_rrls(imc, i, rrl_ddr, enable, chan[i].rrl_ctl[0]);
-}
-
-static void enable_rrls_hbm(struct skx_imc *imc, bool enable)
-{
-       struct reg_rrl **rrl_hbm = res_cfg->reg_rrl_hbm;
-       int i, chan_num = res_cfg->hbm_chan_num;
-       struct skx_channel *chan = imc->chan;
-
-       if (!imc->mbase || !imc->hbm_mc || !rrl_hbm[0] || !rrl_hbm[1])
-               return;
-
-       for (i = 0; i < chan_num; i++) {
-               enable_rrls(imc, i, rrl_hbm[0], enable, chan[i].rrl_ctl[0]);
-               enable_rrls(imc, i, rrl_hbm[1], enable, chan[i].rrl_ctl[1]);
-       }
-}
-
-static void enable_retry_rd_err_log(bool enable)
-{
-       struct skx_dev *d;
-       int i, imc_num;
-
-       edac_dbg(2, "\n");
-
-       list_for_each_entry(d, i10nm_edac_list, list) {
-               imc_num  = res_cfg->ddr_imc_num;
-               for (i = 0; i < imc_num; i++)
-                       enable_rrls_ddr(&d->imc[i], enable);
-
-               imc_num += res_cfg->hbm_imc_num;
-               for (; i < imc_num; i++)
-                       enable_rrls_hbm(&d->imc[i], enable);
-       }
-}
-
-static void show_retry_rd_err_log(struct decoded_addr *res, char *msg,
-                                 int len, bool scrub_err)
-{
-       int i, j, n, ch = res->channel, pch = res->cs & 1;
-       struct skx_imc *imc = &res->dev->imc[res->imc];
-       u64 log, corr, status_mask;
-       struct reg_rrl *rrl;
-       bool scrub;
-       u32 offset;
-       u8 width;
-
-       if (!imc->mbase)
-               return;
-
-       rrl = imc->hbm_mc ? res_cfg->reg_rrl_hbm[pch] : res_cfg->reg_rrl_ddr;
-
-       if (!rrl)
-               return;
-
-       status_mask = rrl->over_mask | rrl->uc_mask | rrl->v_mask;
-
-       n = scnprintf(msg, len, " retry_rd_err_log[");
-       for (i = 0; i < rrl->set_num; i++) {
-               scrub = (rrl->sources[i] == RRL_SRC_FRE_SCRUB || rrl->sources[i] == RRL_SRC_LRE_SCRUB);
-               if (scrub_err != scrub)
-                       continue;
-
-               for (j = 0; j < rrl->reg_num && len - n > 0; j++) {
-                       offset = rrl->offsets[i][j];
-                       width = rrl->widths[j];
-                       log = skx_read_imc_reg(imc, ch, offset, width);
-
-                       if (width == 4)
-                               n += scnprintf(msg + n, len - n, "%.8llx ", log);
-                       else
-                               n += scnprintf(msg + n, len - n, "%.16llx ", log);
-
-                       /* Clear RRL status if RRL in Linux control mode. */
-                       if (res_cfg->rrl_ctrl_mode == RRL_CTRL_LINUX && !j && (log & status_mask))
-                               skx_write_imc_reg(imc, ch, offset, width, log & ~status_mask);
-               }
-       }
-
-       /* Move back one space. */
-       n--;
-       n += scnprintf(msg + n, len - n, "]");
-
-       if (len - n > 0) {
-               n += scnprintf(msg + n, len - n, " correrrcnt[");
-               for (i = 0; i < rrl->cecnt_num && len - n > 0; i++) {
-                       offset = rrl->cecnt_offsets[i];
-                       width = rrl->cecnt_widths[i];
-                       corr = skx_read_imc_reg(imc, ch, offset, width);
-
-                       /* CPUs {ICX,SPR} encode two counters per 4-byte CORRERRCNT register. */
-                       if (res_cfg->type <= SPR) {
-                               n += scnprintf(msg + n, len - n, "%.4llx %.4llx ",
-                                             corr & 0xffff, corr >> 16);
-                       } else {
-                       /* CPUs {GNR} encode one counter per CORRERRCNT register. */
-                               if (width == 4)
-                                       n += scnprintf(msg + n, len - n, "%.8llx ", corr);
-                               else
-                                       n += scnprintf(msg + n, len - n, "%.16llx ", corr);
-                       }
-               }
-
-               /* Move back one space. */
-               n--;
-               n += scnprintf(msg + n, len - n, "]");
-       }
-}
-
 static struct pci_dev *pci_get_dev_wrapper(int dom, unsigned int bus,
                                           unsigned int dev, unsigned int fun)
 {
@@ -1209,9 +1024,9 @@ static int __init i10nm_init(void)
 
        res_cfg->rrl_ctrl_mode = retry_rd_err_log;
        if (retry_rd_err_log && res_cfg->reg_rrl_ddr) {
-               skx_set_show_rrl(show_retry_rd_err_log);
+               skx_set_show_rrl(skx_show_rrl);
                if (retry_rd_err_log == RRL_CTRL_LINUX)
-                       enable_retry_rd_err_log(true);
+                       skx_enable_rrl(true);
        }
 
        skx_set_decode(i10nm_mc_decode);
@@ -1232,7 +1047,7 @@ static void __exit i10nm_exit(void)
 
        if (retry_rd_err_log && res_cfg->reg_rrl_ddr) {
                if (retry_rd_err_log == RRL_CTRL_LINUX)
-                       enable_retry_rd_err_log(false);
+                       skx_enable_rrl(false);
                skx_set_show_rrl(NULL);
        }
 
index 2cdef2e69d71e6e047d615e3862095d544da7c2a..f769a354ea45a8527987921d353cbe3ad9722131 100644 (file)
@@ -102,6 +102,192 @@ void skx_write_imc_reg(struct skx_imc *imc, int chan, u32 offset, u8 width, u64
 }
 EXPORT_SYMBOL_GPL(skx_write_imc_reg);
 
+static void enable_rrl(struct skx_imc *imc, int chan, struct reg_rrl *rrl,
+                      int rrl_set, bool enable, u32 *rrl_ctl)
+{
+       enum rrl_source_type source = rrl->sources[rrl_set];
+       u32 offset = rrl->offsets[rrl_set][0], v;
+       u8 width = rrl->widths[0];
+       bool first, scrub;
+
+       /* First or last read error. */
+       first = (source == RRL_SRC_FRE_SCRUB || source == RRL_SRC_FRE_DEMAND);
+       /* Patrol scrub or on-demand read error. */
+       scrub = (source == RRL_SRC_FRE_SCRUB || source == RRL_SRC_LRE_SCRUB);
+
+       v = skx_read_imc_reg(imc, chan, offset, width);
+
+       if (enable) {
+               /* Save default configurations. */
+               *rrl_ctl = v;
+               v &= ~rrl->uc_mask;
+
+               if (first)
+                       v |= rrl->noover_mask;
+               else
+                       v &= ~rrl->noover_mask;
+
+               if (scrub)
+                       v |= rrl->en_patspr_mask;
+               else
+                       v &= ~rrl->en_patspr_mask;
+
+               v |= rrl->en_mask;
+       } else {
+               /* Restore default configurations. */
+               if (*rrl_ctl & rrl->uc_mask)
+                       v |= rrl->uc_mask;
+
+               if (first) {
+                       if (!(*rrl_ctl & rrl->noover_mask))
+                               v &= ~rrl->noover_mask;
+               } else {
+                       if (*rrl_ctl & rrl->noover_mask)
+                               v |= rrl->noover_mask;
+               }
+
+               if (scrub) {
+                       if (!(*rrl_ctl & rrl->en_patspr_mask))
+                               v &= ~rrl->en_patspr_mask;
+               } else {
+                       if (*rrl_ctl & rrl->en_patspr_mask)
+                               v |= rrl->en_patspr_mask;
+               }
+
+               if (!(*rrl_ctl & rrl->en_mask))
+                       v &= ~rrl->en_mask;
+       }
+
+       skx_write_imc_reg(imc, chan, offset, width, v);
+}
+
+static void enable_rrls(struct skx_imc *imc, int chan, struct reg_rrl *rrl,
+                       bool enable, u32 *rrl_ctl)
+{
+       for (int i = 0; i < rrl->set_num; i++)
+               enable_rrl(imc, chan, rrl, i, enable, rrl_ctl + i);
+}
+
+static void enable_rrls_ddr(struct skx_imc *imc, bool enable)
+{
+       struct reg_rrl *rrl_ddr = skx_res_cfg->reg_rrl_ddr;
+       int i, chan_num = skx_res_cfg->ddr_chan_num;
+       struct skx_channel *chan = imc->chan;
+
+       if (!imc->mbase)
+               return;
+
+       for (i = 0; i < chan_num; i++)
+               enable_rrls(imc, i, rrl_ddr, enable, chan[i].rrl_ctl[0]);
+}
+
+static void enable_rrls_hbm(struct skx_imc *imc, bool enable)
+{
+       struct reg_rrl **rrl_hbm = skx_res_cfg->reg_rrl_hbm;
+       int i, chan_num = skx_res_cfg->hbm_chan_num;
+       struct skx_channel *chan = imc->chan;
+
+       if (!imc->mbase || !imc->hbm_mc || !rrl_hbm[0] || !rrl_hbm[1])
+               return;
+
+       for (i = 0; i < chan_num; i++) {
+               enable_rrls(imc, i, rrl_hbm[0], enable, chan[i].rrl_ctl[0]);
+               enable_rrls(imc, i, rrl_hbm[1], enable, chan[i].rrl_ctl[1]);
+       }
+}
+
+void skx_enable_rrl(bool enable)
+{
+       struct skx_dev *d;
+       int i, imc_num;
+
+       edac_dbg(2, "\n");
+
+       list_for_each_entry(d, &dev_edac_list, list) {
+               imc_num  = skx_res_cfg->ddr_imc_num;
+               for (i = 0; i < imc_num; i++)
+                       enable_rrls_ddr(&d->imc[i], enable);
+
+               imc_num += skx_res_cfg->hbm_imc_num;
+               for (; i < imc_num; i++)
+                       enable_rrls_hbm(&d->imc[i], enable);
+       }
+}
+EXPORT_SYMBOL_GPL(skx_enable_rrl);
+
+void skx_show_rrl(struct decoded_addr *res, char *msg, int len, bool scrub_err)
+{
+       int i, j, n, ch = res->channel, pch = res->cs & 1;
+       struct skx_imc *imc = &res->dev->imc[res->imc];
+       u64 log, corr, status_mask;
+       struct reg_rrl *rrl;
+       bool scrub;
+       u32 offset;
+       u8 width;
+
+       if (!imc->mbase)
+               return;
+
+       rrl = imc->hbm_mc ? skx_res_cfg->reg_rrl_hbm[pch] : skx_res_cfg->reg_rrl_ddr;
+
+       if (!rrl)
+               return;
+
+       status_mask = rrl->over_mask | rrl->uc_mask | rrl->v_mask;
+
+       n = scnprintf(msg, len, " retry_rd_err_log[");
+       for (i = 0; i < rrl->set_num; i++) {
+               scrub = (rrl->sources[i] == RRL_SRC_FRE_SCRUB || rrl->sources[i] == RRL_SRC_LRE_SCRUB);
+               if (scrub_err != scrub)
+                       continue;
+
+               for (j = 0; j < rrl->reg_num && len - n > 0; j++) {
+                       offset = rrl->offsets[i][j];
+                       width = rrl->widths[j];
+                       log = skx_read_imc_reg(imc, ch, offset, width);
+
+                       if (width == 4)
+                               n += scnprintf(msg + n, len - n, "%.8llx ", log);
+                       else
+                               n += scnprintf(msg + n, len - n, "%.16llx ", log);
+
+                       /* Clear RRL status if RRL in Linux control mode. */
+                       if (skx_res_cfg->rrl_ctrl_mode == RRL_CTRL_LINUX && !j && (log & status_mask))
+                               skx_write_imc_reg(imc, ch, offset, width, log & ~status_mask);
+               }
+       }
+
+       /* Move back one space. */
+       n--;
+       n += scnprintf(msg + n, len - n, "]");
+
+       if (len - n > 0) {
+               n += scnprintf(msg + n, len - n, " correrrcnt[");
+               for (i = 0; i < rrl->cecnt_num && len - n > 0; i++) {
+                       offset = rrl->cecnt_offsets[i];
+                       width = rrl->cecnt_widths[i];
+                       corr = skx_read_imc_reg(imc, ch, offset, width);
+
+                       /* CPUs {ICX,SPR} encode two counters per 4-byte CORRERRCNT register. */
+                       if (skx_res_cfg->type <= SPR) {
+                               n += scnprintf(msg + n, len - n, "%.4llx %.4llx ",
+                                             corr & 0xffff, corr >> 16);
+                       } else {
+                       /* CPUs {GNR} encode one counter per CORRERRCNT register. */
+                               if (width == 4)
+                                       n += scnprintf(msg + n, len - n, "%.8llx ", corr);
+                               else
+                                       n += scnprintf(msg + n, len - n, "%.16llx ", corr);
+                       }
+               }
+
+               /* Move back one space. */
+               n--;
+               n += scnprintf(msg + n, len - n, "]");
+       }
+}
+EXPORT_SYMBOL_GPL(skx_show_rrl);
+
 int skx_adxl_get(void)
 {
        const char * const *names;
index 4091431356d612b25ffc3e33b8be265ec399727a..eea2d95cc0ac615953e9dfa40a38fdc8a1d64ee6 100644 (file)
@@ -344,6 +344,8 @@ int skx_adxl_get(void);
 void skx_adxl_put(void);
 void skx_set_decode(skx_decode_f decode);
 void skx_set_show_rrl(skx_show_rrl_f rrl);
+void skx_show_rrl(struct decoded_addr *res, char *msg, int len, bool scrub_err);
+void skx_enable_rrl(bool enable);
 void skx_set_mem_cfg(bool mem_cfg_2lm);
 void skx_set_res_cfg(struct res_config *cfg);
 void skx_init_mc_mapping(struct skx_dev *d);