Re: [PATCH v6 2/3] RAS/AMD/ATL: Translate UMC normalized address to DRAM address using PRM

From: Borislav Petkov

Date: Tue Jun 30 2026 - 01:34:04 EST


On Mon, Jun 29, 2026 at 11:07:30AM -0400, Yazen Ghannam wrote:
> @@ -210,7 +210,8 @@ static int __init amd_atl_init(void)
>
> /* Increment this module's recount so that it can't be easily unloaded. */
> __module_get(THIS_MODULE);
> - amd_atl_register_decoder(convert_umc_mca_addr_to_sys_addr);
> + amd_atl_register_decoder(convert_umc_mca_addr_to_sys_addr,
> + convert_umc_mca_addr_to_dram_addr);

This thing with passing in a function pointer from mce_amd was a hack back
then. Now we're doing this here and we're passing in another pointer too.
Yeah, let's rip it out and have users of the decoding library call the library
directly.

Oh, and let's shorten those function names somewhat:
amd_convert_umc_mca_addr_to_dram_addr is an unreadable mouthful.

Diff ontop:

---

diff --git a/drivers/ras/amd/atl/core.c b/drivers/ras/amd/atl/core.c
index 3d622e6a6cc5..96189915b47e 100644
--- a/drivers/ras/amd/atl/core.c
+++ b/drivers/ras/amd/atl/core.c
@@ -192,6 +192,18 @@ static const struct x86_cpu_id amd_atl_cpuids[] = {
};
MODULE_DEVICE_TABLE(x86cpu, amd_atl_cpuids);

+unsigned long amd_convert_umc_addr_to_sys_addr(struct atl_err *err)
+{
+ return convert_umc_mca_addr_to_sys_addr(err);
+}
+EXPORT_SYMBOL_GPL(amd_convert_umc_addr_to_sys_addr);
+
+int amd_convert_umc_addr_to_dram_addr(struct atl_err *err, struct atl_dram_addr *dram_addr)
+{
+ return convert_umc_mca_addr_to_dram_addr(err, dram_addr);
+}
+EXPORT_SYMBOL_GPL(amd_convert_umc_addr_to_dram_addr);
+
static int __init amd_atl_init(void)
{
int ret;
@@ -210,24 +222,12 @@ static int __init amd_atl_init(void)

/* Increment this module's recount so that it can't be easily unloaded. */
__module_get(THIS_MODULE);
- amd_atl_register_decoder(convert_umc_mca_addr_to_sys_addr,
- convert_umc_mca_addr_to_dram_addr);

pr_info("AMD Address Translation Library initialized\n");
return 0;
}

-/*
- * Exit function is only needed for testing and debug. Module unload must be
- * forced to override refcount check.
- */
-static void __exit amd_atl_exit(void)
-{
- amd_atl_unregister_decoder();
-}
-
module_init(amd_atl_init);
-module_exit(amd_atl_exit);

MODULE_DESCRIPTION("AMD Address Translation Library");
MODULE_LICENSE("GPL");
diff --git a/drivers/ras/amd/atl/umc.c b/drivers/ras/amd/atl/umc.c
index b48c0fe97bf2..f8470d74a9b0 100644
--- a/drivers/ras/amd/atl/umc.c
+++ b/drivers/ras/amd/atl/umc.c
@@ -318,7 +318,7 @@ static void _retire_row_mi300(struct atl_err *a_err)
a_err->addr &= ~MI300_UMC_MCA_COL;
a_err->addr |= FIELD_PREP(MI300_UMC_MCA_COL, col);

- addr = amd_convert_umc_mca_addr_to_sys_addr(a_err);
+ addr = amd_convert_umc_addr_to_sys_addr(a_err);
if (IS_ERR_VALUE(addr))
continue;

diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
index 582aa2b93e81..011de2c257b1 100644
--- a/drivers/ras/ras.c
+++ b/drivers/ras/ras.c
@@ -10,51 +10,6 @@
#include <linux/ras.h>
#include <linux/uuid.h>

-#if IS_ENABLED(CONFIG_AMD_ATL)
-/*
- * Once set, this function pointer should never be unset.
- *
- * The library module will set this pointer if it successfully loads. The module
- * should not be unloaded except for testing and debug purposes.
- */
-static unsigned long (*amd_atl_umc_na_to_spa)(struct atl_err *err);
-
-static int (*amd_atl_umc_na_to_dram_addr)(struct atl_err *err, struct atl_dram_addr *dram_addr);
-
-void amd_atl_register_decoder(unsigned long (*f1)(struct atl_err *),
- int (*f2)(struct atl_err *, struct atl_dram_addr *))
-{
- amd_atl_umc_na_to_spa = f1;
- amd_atl_umc_na_to_dram_addr = f2;
-}
-EXPORT_SYMBOL_GPL(amd_atl_register_decoder);
-
-void amd_atl_unregister_decoder(void)
-{
- amd_atl_umc_na_to_spa = NULL;
- amd_atl_umc_na_to_dram_addr = NULL;
-}
-EXPORT_SYMBOL_GPL(amd_atl_unregister_decoder);
-
-unsigned long amd_convert_umc_mca_addr_to_sys_addr(struct atl_err *err)
-{
- if (!amd_atl_umc_na_to_spa)
- return -EINVAL;
-
- return amd_atl_umc_na_to_spa(err);
-}
-EXPORT_SYMBOL_GPL(amd_convert_umc_mca_addr_to_sys_addr);
-
-int amd_convert_umc_mca_addr_to_dram_addr(struct atl_err *err, struct atl_dram_addr *dram_addr)
-{
- if (!amd_atl_umc_na_to_dram_addr)
- return -EINVAL;
-
- return amd_atl_umc_na_to_dram_addr(err, dram_addr);
-}
-EXPORT_SYMBOL_GPL(amd_convert_umc_mca_addr_to_dram_addr);
-#endif /* CONFIG_AMD_ATL */
-
#define CREATE_TRACE_POINTS
#define TRACE_INCLUDE_PATH ../../include/ras
#include <ras/ras_event.h>
diff --git a/include/linux/ras.h b/include/linux/ras.h
index 1e82a94b0db0..ce2327229515 100644
--- a/include/linux/ras.h
+++ b/include/linux/ras.h
@@ -52,18 +52,14 @@ struct atl_dram_addr {
} __packed;

#if IS_ENABLED(CONFIG_AMD_ATL)
-void amd_atl_register_decoder(unsigned long (*f1)(struct atl_err *),
- int (*f2)(struct atl_err *, struct atl_dram_addr *));
-void amd_atl_unregister_decoder(void);
void amd_retire_dram_row(struct atl_err *err);
-unsigned long amd_convert_umc_mca_addr_to_sys_addr(struct atl_err *err);
-int amd_convert_umc_mca_addr_to_dram_addr(struct atl_err *err, struct atl_dram_addr *dram_addr);
+unsigned long amd_convert_umc_addr_to_sys_addr(struct atl_err *err);
+int amd_convert_umc_addr_to_dram_addr(struct atl_err *err, struct atl_dram_addr *dram_addr);
#else
static inline void amd_retire_dram_row(struct atl_err *err) { }
static inline unsigned long
-amd_convert_umc_mca_addr_to_sys_addr(struct atl_err *err) { return -EINVAL; }
-static inline int amd_convert_umc_mca_addr_to_dram_addr(struct atl_err *err,
- struct atl_dram_addr *dram_addr)
+amd_convert_umc_addr_to_sys_addr(struct atl_err *err) { return -EINVAL; }
+static inline int amd_convert_umc_addr_to_dram_addr(struct atl_err *err, struct atl_dram_addr *dram_addr)
{
return -EINVAL;
}

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette