[RFC PATCH v2 3/5] x86/amd_nb: Add amd_nb_set_cache() for external NB cache registration
From: Lin Wang
Date: Thu Apr 23 2026 - 02:06:47 EST
Several subsystems (EDAC, MCE decode, ATL) consume the NB cache through
node_to_amd_nb() and amd_nb_num(). On Hygon Family 0x18, the AMD
enumeration path in amd_cache_northbridges() cannot discover DF nodes
because Hygon uses platform-assigned PCI slots rather than the fixed
00:18..1f layout.
Hygon therefore needs to populate the NB cache from its own enumeration
module (hygon_node.c) without adding Hygon-specific code or includes
into amd_nb.c.
Add amd_nb_set_cache() as a vendor-neutral data registration interface:
the caller builds a struct amd_northbridge[] array, populates the
mandatory misc and link device pointers, and transfers ownership to the
NB layer. AMD-only legacy features (GART, L3 Index Disable, flags)
remain inactive for non-AMD callers because amd_cache_northbridges()
-- which sets those features -- is now guarded to AMD-only.
This keeps amd_nb.c free of any vendor-specific headers, defines, or
branch logic, while allowing non-AMD vendors to satisfy the existing
amd_nb consumer contracts.
No functional change for AMD systems.
Signed-off-by: Lin Wang <wanglin@xxxxxxxxxxxxxx>
---
arch/x86/include/asm/amd/nb.h | 7 +++++++
arch/x86/kernel/amd_nb.c | 22 ++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/arch/x86/include/asm/amd/nb.h b/arch/x86/include/asm/amd/nb.h
index ddb5108cf46c..0f10911c08d5 100644
--- a/arch/x86/include/asm/amd/nb.h
+++ b/arch/x86/include/asm/amd/nb.h
@@ -47,6 +47,7 @@ struct amd_northbridge_info {
u16 amd_nb_num(void);
bool amd_nb_has_feature(unsigned int feature);
struct amd_northbridge *node_to_amd_nb(int node);
+int amd_nb_set_cache(struct amd_northbridge *nb, u16 num);
static inline bool amd_gart_present(void)
{
@@ -69,6 +70,12 @@ static inline struct amd_northbridge *node_to_amd_nb(int node)
{
return NULL;
}
+
+static inline int amd_nb_set_cache(struct amd_northbridge *nb, u16 num)
+{
+ return -ENODEV;
+}
+
#define amd_gart_present(x) false
#endif
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 5d364540673d..8a066cf0f747 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -58,6 +58,25 @@ struct amd_northbridge *node_to_amd_nb(int node)
}
EXPORT_SYMBOL_GPL(node_to_amd_nb);
+/*
+ * Register a pre-built NB cache from a vendor-specific module (e.g. Hygon).
+ * Must be called at most once, before any amd_nb consumer is active.
+ * Returns -EBUSY if the cache is already populated.
+ */
+int amd_nb_set_cache(struct amd_northbridge *nb, u16 num)
+{
+ if (!nb || !num)
+ return -EINVAL;
+
+ if (amd_northbridges.num)
+ return -EBUSY;
+
+ amd_northbridges.nb = nb;
+ amd_northbridges.num = num;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(amd_nb_set_cache);
+
static int amd_cache_northbridges(void)
{
struct amd_northbridge *nb;
@@ -66,6 +85,9 @@ static int amd_cache_northbridges(void)
if (amd_northbridges.num)
return 0;
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ return -ENODEV;
+
amd_northbridges.num = amd_num_nodes();
nb = kzalloc_objs(struct amd_northbridge, amd_northbridges.num);
--
2.43.0