]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
x86/amd_nb: Move SMN access code to a new amd_node driver
authorMario Limonciello <mario.limonciello@amd.com>
Fri, 6 Dec 2024 16:12:03 +0000 (16:12 +0000)
committerBorislav Petkov (AMD) <bp@alien8.de>
Wed, 8 Jan 2025 09:59:44 +0000 (10:59 +0100)
SMN access was bolted into amd_nb mostly as convenience.  This has
limitations though that require incurring tech debt to keep it working.

Move SMN access to the newly introduced AMD Node driver.

Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Acked-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> # pdx86
Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> # PMF, PMC
Link: https://lore.kernel.org/r/20241206161210.163701-11-yazen.ghannam@amd.com
16 files changed:
MAINTAINERS
arch/x86/include/asm/amd_nb.h
arch/x86/include/asm/amd_node.h
arch/x86/kernel/amd_nb.c
arch/x86/kernel/amd_node.c
arch/x86/pci/fixup.c
drivers/edac/Kconfig
drivers/edac/amd64_edac.c
drivers/hwmon/Kconfig
drivers/hwmon/k10temp.c
drivers/platform/x86/amd/pmc/Kconfig
drivers/platform/x86/amd/pmc/pmc.c
drivers/platform/x86/amd/pmf/Kconfig
drivers/platform/x86/amd/pmf/core.c
drivers/ras/amd/atl/Kconfig
drivers/ras/amd/atl/internal.h

index 290989ab9f7224335c40aca6bc4849b41f805a53..27a5bc2fc49baa210605b8fcd739adc2a4113b63 100644 (file)
@@ -1122,6 +1122,7 @@ S:        Supported
 F:     drivers/i2c/busses/i2c-amd-asf-plat.c
 
 AMD NODE DRIVER
+M:     Mario Limonciello <mario.limonciello@amd.com>
 M:     Yazen Ghannam <yazen.ghannam@amd.com>
 L:     linux-kernel@vger.kernel.org
 S:     Supported
index 094c3be81a8df17877c054f5f91c5e1d8ca0fd1b..5e0333534abc008c63afdcb435a8975e9d0668c2 100644 (file)
@@ -21,9 +21,6 @@ extern int amd_numa_init(void);
 extern int amd_get_subcaches(int);
 extern int amd_set_subcaches(int, unsigned long);
 
-int __must_check amd_smn_read(u16 node, u32 address, u32 *value);
-int __must_check amd_smn_write(u16 node, u32 address, u32 value);
-
 struct amd_l3_cache {
        unsigned indices;
        u8       subcaches[4];
index 419a0ad13ef271b9457c83bf13aa132925e6ee49..113ad3e8ee40ae8f6966eebfdb5b7b2e638ee7d8 100644 (file)
@@ -30,4 +30,7 @@ static inline u16 amd_num_nodes(void)
        return topology_amd_nodes_per_pkg() * topology_max_packages();
 }
 
+int __must_check amd_smn_read(u16 node, u32 address, u32 *value);
+int __must_check amd_smn_write(u16 node, u32 address, u32 value);
+
 #endif /*_ASM_X86_AMD_NODE_H_*/
index e335d89ddad7188d22a85e298a3871e1b9dfdd9f..11fac09e3a8cb55e082764e6c5aa706c02df7d4d 100644 (file)
@@ -15,9 +15,6 @@
 #include <linux/pci_ids.h>
 #include <asm/amd_nb.h>
 
-/* Protect the PCI config register pairs used for SMN. */
-static DEFINE_MUTEX(smn_mutex);
-
 static u32 *flush_words;
 
 static const struct pci_device_id amd_nb_misc_ids[] = {
@@ -59,92 +56,6 @@ struct amd_northbridge *node_to_amd_nb(int node)
 }
 EXPORT_SYMBOL_GPL(node_to_amd_nb);
 
-/*
- * SMN accesses may fail in ways that are difficult to detect here in the called
- * functions amd_smn_read() and amd_smn_write(). Therefore, callers must do
- * their own checking based on what behavior they expect.
- *
- * For SMN reads, the returned value may be zero if the register is Read-as-Zero.
- * Or it may be a "PCI Error Response", e.g. all 0xFFs. The "PCI Error Response"
- * can be checked here, and a proper error code can be returned.
- *
- * But the Read-as-Zero response cannot be verified here. A value of 0 may be
- * correct in some cases, so callers must check that this correct is for the
- * register/fields they need.
- *
- * For SMN writes, success can be determined through a "write and read back"
- * However, this is not robust when done here.
- *
- * Possible issues:
- *
- * 1) Bits that are "Write-1-to-Clear". In this case, the read value should
- *    *not* match the write value.
- *
- * 2) Bits that are "Read-as-Zero"/"Writes-Ignored". This information cannot be
- *    known here.
- *
- * 3) Bits that are "Reserved / Set to 1". Ditto above.
- *
- * Callers of amd_smn_write() should do the "write and read back" check
- * themselves, if needed.
- *
- * For #1, they can see if their target bits got cleared.
- *
- * For #2 and #3, they can check if their target bits got set as intended.
- *
- * This matches what is done for RDMSR/WRMSR. As long as there's no #GP, then
- * the operation is considered a success, and the caller does their own
- * checking.
- */
-static int __amd_smn_rw(u16 node, u32 address, u32 *value, bool write)
-{
-       struct pci_dev *root;
-       int err = -ENODEV;
-
-       if (node >= amd_northbridges.num)
-               goto out;
-
-       root = node_to_amd_nb(node)->root;
-       if (!root)
-               goto out;
-
-       mutex_lock(&smn_mutex);
-
-       err = pci_write_config_dword(root, 0x60, address);
-       if (err) {
-               pr_warn("Error programming SMN address 0x%x.\n", address);
-               goto out_unlock;
-       }
-
-       err = (write ? pci_write_config_dword(root, 0x64, *value)
-                    : pci_read_config_dword(root, 0x64, value));
-
-out_unlock:
-       mutex_unlock(&smn_mutex);
-
-out:
-       return err;
-}
-
-int __must_check amd_smn_read(u16 node, u32 address, u32 *value)
-{
-       int err = __amd_smn_rw(node, address, value, false);
-
-       if (PCI_POSSIBLE_ERROR(*value)) {
-               err = -ENODEV;
-               *value = 0;
-       }
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(amd_smn_read);
-
-int __must_check amd_smn_write(u16 node, u32 address, u32 value)
-{
-       return __amd_smn_rw(node, address, &value, true);
-}
-EXPORT_SYMBOL_GPL(amd_smn_write);
-
 static int amd_cache_northbridges(void)
 {
        struct amd_northbridge *nb;
index 4eea8c7d809040e0aa309443365f8793b3e2f3bb..95e5ca0acc905f1c23217ba619022f63e3fa966a 100644 (file)
@@ -8,6 +8,7 @@
  * Author: Yazen Ghannam <Yazen.Ghannam@amd.com>
  */
 
+#include <asm/amd_nb.h>
 #include <asm/amd_node.h>
 
 /*
@@ -88,3 +89,92 @@ struct pci_dev *amd_node_get_root(u16 node)
        pci_dbg(root, "is root for AMD node %u\n", node);
        return root;
 }
+
+/* Protect the PCI config register pairs used for SMN. */
+static DEFINE_MUTEX(smn_mutex);
+
+/*
+ * SMN accesses may fail in ways that are difficult to detect here in the called
+ * functions amd_smn_read() and amd_smn_write(). Therefore, callers must do
+ * their own checking based on what behavior they expect.
+ *
+ * For SMN reads, the returned value may be zero if the register is Read-as-Zero.
+ * Or it may be a "PCI Error Response", e.g. all 0xFFs. The "PCI Error Response"
+ * can be checked here, and a proper error code can be returned.
+ *
+ * But the Read-as-Zero response cannot be verified here. A value of 0 may be
+ * correct in some cases, so callers must check that this correct is for the
+ * register/fields they need.
+ *
+ * For SMN writes, success can be determined through a "write and read back"
+ * However, this is not robust when done here.
+ *
+ * Possible issues:
+ *
+ * 1) Bits that are "Write-1-to-Clear". In this case, the read value should
+ *    *not* match the write value.
+ *
+ * 2) Bits that are "Read-as-Zero"/"Writes-Ignored". This information cannot be
+ *    known here.
+ *
+ * 3) Bits that are "Reserved / Set to 1". Ditto above.
+ *
+ * Callers of amd_smn_write() should do the "write and read back" check
+ * themselves, if needed.
+ *
+ * For #1, they can see if their target bits got cleared.
+ *
+ * For #2 and #3, they can check if their target bits got set as intended.
+ *
+ * This matches what is done for RDMSR/WRMSR. As long as there's no #GP, then
+ * the operation is considered a success, and the caller does their own
+ * checking.
+ */
+static int __amd_smn_rw(u16 node, u32 address, u32 *value, bool write)
+{
+       struct pci_dev *root;
+       int err = -ENODEV;
+
+       if (node >= amd_nb_num())
+               goto out;
+
+       root = node_to_amd_nb(node)->root;
+       if (!root)
+               goto out;
+
+       mutex_lock(&smn_mutex);
+
+       err = pci_write_config_dword(root, 0x60, address);
+       if (err) {
+               pr_warn("Error programming SMN address 0x%x.\n", address);
+               goto out_unlock;
+       }
+
+       err = (write ? pci_write_config_dword(root, 0x64, *value)
+                    : pci_read_config_dword(root, 0x64, value));
+
+out_unlock:
+       mutex_unlock(&smn_mutex);
+
+out:
+       return err;
+}
+
+int __must_check amd_smn_read(u16 node, u32 address, u32 *value)
+{
+       int err = __amd_smn_rw(node, address, value, false);
+
+       if (PCI_POSSIBLE_ERROR(*value)) {
+               err = -ENODEV;
+               *value = 0;
+       }
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(amd_smn_read);
+
+int __must_check amd_smn_write(u16 node, u32 address, u32 value)
+{
+       return __amd_smn_rw(node, address, &value, true);
+}
+EXPORT_SYMBOL_GPL(amd_smn_write);
index 0681ecfe34300e54fceb17965340bcdbbb2e5d7f..592fb9d97e773c339f7f6b04e6992140c1bdb5ed 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/pci.h>
 #include <linux/suspend.h>
 #include <linux/vgaarb.h>
-#include <asm/amd_nb.h>
+#include <asm/amd_node.h>
 #include <asm/hpet.h>
 #include <asm/pci_x86.h>
 
@@ -828,7 +828,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7910, rs690_fix_64bit_dma);
 
 #endif
 
-#ifdef CONFIG_AMD_NB
+#ifdef CONFIG_AMD_NODE
 
 #define AMD_15B8_RCC_DEV2_EPF0_STRAP2                                  0x10136008
 #define AMD_15B8_RCC_DEV2_EPF0_STRAP2_NO_SOFT_RESET_DEV2_F0_MASK       0x00000080L
index 06f7b43a6f7884a8ffe8b27cf60bd2d0c507510c..cb97d7bdae31ad41d15cae23bf652f157a2883f3 100644 (file)
@@ -78,6 +78,7 @@ config EDAC_GHES
 config EDAC_AMD64
        tristate "AMD64 (Opteron, Athlon64)"
        depends on AMD_NB && EDAC_DECODE_MCE
+       depends on AMD_NODE
        imply AMD_ATL
        help
          Support for error detection and correction of DRAM ECC errors on
index ddfbdb66b794d78d6bbff978bfa520a7b55c542f..29465088639ce55647a92df3221cbb479cf52234 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/ras.h>
 #include "amd64_edac.h"
 #include <asm/amd_nb.h>
+#include <asm/amd_node.h>
 
 static struct edac_pci_ctl_info *pci_ctl;
 
index dd376602f3f19c6f258651afeffbe1bb5d9b6b72..ea13ea482a631d2d285b8003d227d5486e7208b9 100644 (file)
@@ -324,7 +324,7 @@ config SENSORS_K8TEMP
 
 config SENSORS_K10TEMP
        tristate "AMD Family 10h+ temperature sensor"
-       depends on X86 && PCI && AMD_NB
+       depends on X86 && PCI && AMD_NODE
        help
          If you say yes here you get support for the temperature
          sensor(s) inside your CPU. Supported are later revisions of
index cefa8cd184c8bbd06906bb8ed4f5811f0a0a02af..d0b4cc9a5011073b81c09a1931d4df9d1297ced7 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
-#include <asm/amd_nb.h>
+#include <asm/amd_node.h>
 #include <asm/processor.h>
 
 MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor");
index 94f9563d8be78831a6add10744ff952e50b80a81..eeffdafd686e7df43a593c6eb031eb4c594d7f92 100644 (file)
@@ -5,7 +5,7 @@
 
 config AMD_PMC
        tristate "AMD SoC PMC driver"
-       depends on ACPI && PCI && RTC_CLASS && AMD_NB
+       depends on ACPI && PCI && RTC_CLASS && AMD_NODE
        depends on SUSPEND
        select SERIO
        help
index 26b878ee519181467b8bc5620a1c1bf54ee54de8..941b7753dd78e3afd919b38f1e45fc9a6034a26b 100644 (file)
@@ -10,7 +10,6 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <asm/amd_nb.h>
 #include <linux/acpi.h>
 #include <linux/bitfield.h>
 #include <linux/bits.h>
@@ -28,6 +27,8 @@
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 
+#include <asm/amd_node.h>
+
 #include "pmc.h"
 
 /* SMU communication registers */
index 99d67cdbd91e5eda9cfa87493dc542503730291f..25b8f7ae3abde50d9a34ffdcc3b2f102567c4850 100644 (file)
@@ -7,7 +7,7 @@ config AMD_PMF
        tristate "AMD Platform Management Framework"
        depends on ACPI && PCI
        depends on POWER_SUPPLY
-       depends on AMD_NB
+       depends on AMD_NODE
        select ACPI_PLATFORM_PROFILE
        depends on TEE && AMDTEE
        depends on AMD_SFH_HID
index 06a97c533cb8524e64fe2376d78247749f9716b3..7f88f3121cf5dc4c430234569e017e4ad2ff1889 100644 (file)
@@ -8,13 +8,13 @@
  * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
  */
 
-#include <asm/amd_nb.h>
 #include <linux/debugfs.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
+#include <asm/amd_node.h>
 #include "pmf.h"
 
 /* PMF-SMU communication registers */
index 551680073e431a0d65c45f9f485016314439ee40..6e03942cd7daea943e32ffccea0ce346a5b9eee9 100644 (file)
@@ -10,6 +10,7 @@
 config AMD_ATL
        tristate "AMD Address Translation Library"
        depends on AMD_NB && X86_64 && RAS
+       depends on AMD_NODE
        depends on MEMORY_FAILURE
        default N
        help
index 143d04c779a821fb52a1e186cea3b265204c8b3e..f9be26d253484616595fdc2e67103e1adbe3a4b9 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/ras.h>
 
 #include <asm/amd_nb.h>
+#include <asm/amd_node.h>
 
 #include "reg_fields.h"