Skip to content

Commit

Permalink
x86/amd_node, platform/x86/amd/hsmp: Have HSMP use SMN through AMD_NODE
Browse files Browse the repository at this point in the history
The HSMP interface is just an SMN interface with different offsets.

Define an HSMP wrapper in the SMN code and have the HSMP platform driver
use that rather than a local solution.

Also, remove the "root" member from AMD_NB, since there are no more
users of it.

Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Carlos Bilbao <carlos.bilbao@kernel.org>
Acked-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20250130-wip-x86-amd-nb-cleanup-v4-1-b5cc997e471b@amd.com
  • Loading branch information
Yazen Ghannam authored and Borislav Petkov (AMD) committed Feb 17, 2025
1 parent e3cd859 commit 735049b
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 34 deletions.
1 change: 0 additions & 1 deletion arch/x86/include/asm/amd_nb.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ struct amd_l3_cache {
};

struct amd_northbridge {
struct pci_dev *root;
struct pci_dev *misc;
struct pci_dev *link;
struct amd_l3_cache l3_cache;
Expand Down
13 changes: 13 additions & 0 deletions arch/x86/include/asm/amd_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,20 @@ static inline u16 amd_num_nodes(void)
return topology_amd_nodes_per_pkg() * topology_max_packages();
}

#ifdef CONFIG_AMD_NODE
int __must_check amd_smn_read(u16 node, u32 address, u32 *value);
int __must_check amd_smn_write(u16 node, u32 address, u32 value);

/* Should only be used by the HSMP driver. */
int __must_check amd_smn_hsmp_rdwr(u16 node, u32 address, u32 *value, bool write);
#else
static inline int __must_check amd_smn_read(u16 node, u32 address, u32 *value) { return -ENODEV; }
static inline int __must_check amd_smn_write(u16 node, u32 address, u32 value) { return -ENODEV; }

static inline int __must_check amd_smn_hsmp_rdwr(u16 node, u32 address, u32 *value, bool write)
{
return -ENODEV;
}
#endif /* CONFIG_AMD_NODE */

#endif /*_ASM_X86_AMD_NODE_H_*/
1 change: 0 additions & 1 deletion arch/x86/kernel/amd_nb.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ static int amd_cache_northbridges(void)
amd_northbridges.nb = nb;

for (i = 0; i < amd_northbridges.num; i++) {
node_to_amd_nb(i)->root = amd_node_get_root(i);
node_to_amd_nb(i)->misc = amd_node_get_func(i, 3);

/*
Expand Down
9 changes: 9 additions & 0 deletions arch/x86/kernel/amd_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ static DEFINE_MUTEX(smn_mutex);
#define SMN_INDEX_OFFSET 0x60
#define SMN_DATA_OFFSET 0x64

#define HSMP_INDEX_OFFSET 0xc4
#define HSMP_DATA_OFFSET 0xc8

/*
* 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
Expand Down Expand Up @@ -179,6 +182,12 @@ int __must_check amd_smn_write(u16 node, u32 address, u32 value)
}
EXPORT_SYMBOL_GPL(amd_smn_write);

int __must_check amd_smn_hsmp_rdwr(u16 node, u32 address, u32 *value, bool write)
{
return __amd_smn_rw(HSMP_INDEX_OFFSET, HSMP_DATA_OFFSET, node, address, value, write);
}
EXPORT_SYMBOL_GPL(amd_smn_hsmp_rdwr);

static int amd_cache_roots(void)
{
u16 node, num_nodes = amd_num_nodes();
Expand Down
2 changes: 1 addition & 1 deletion drivers/platform/x86/amd/hsmp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ config AMD_HSMP
tristate

menu "AMD HSMP Driver"
depends on AMD_NB || COMPILE_TEST
depends on AMD_NODE || COMPILE_TEST

config AMD_HSMP_ACPI
tristate "AMD HSMP ACPI device driver"
Expand Down
7 changes: 4 additions & 3 deletions drivers/platform/x86/amd/hsmp/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <asm/amd_hsmp.h>
#include <asm/amd_nb.h>

#include <linux/acpi.h>
#include <linux/device.h>
Expand All @@ -24,6 +23,8 @@

#include <uapi/asm-generic/errno-base.h>

#include <asm/amd_node.h>

#include "hsmp.h"

#define DRIVER_NAME "amd_hsmp"
Expand Down Expand Up @@ -321,8 +322,8 @@ static int hsmp_acpi_probe(struct platform_device *pdev)
return -ENOMEM;

if (!hsmp_pdev->is_probed) {
hsmp_pdev->num_sockets = amd_nb_num();
if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS)
hsmp_pdev->num_sockets = amd_num_nodes();
if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES)
return -ENODEV;

hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets,
Expand Down
1 change: 0 additions & 1 deletion drivers/platform/x86/amd/hsmp/hsmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
*/

#include <asm/amd_hsmp.h>
#include <asm/amd_nb.h>

#include <linux/acpi.h>
#include <linux/delay.h>
Expand Down
3 changes: 0 additions & 3 deletions drivers/platform/x86/amd/hsmp/hsmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@

#define HSMP_ATTR_GRP_NAME_SIZE 10

#define MAX_AMD_SOCKETS 8

#define HSMP_CDEV_NAME "hsmp_cdev"
#define HSMP_DEVNODE_NAME "hsmp"

Expand All @@ -41,7 +39,6 @@ struct hsmp_socket {
void __iomem *virt_base_addr;
struct semaphore hsmp_sem;
char name[HSMP_ATTR_GRP_NAME_SIZE];
struct pci_dev *root;
struct device *dev;
u16 sock_ind;
int (*amd_hsmp_rdwr)(struct hsmp_socket *sock, u32 off, u32 *val, bool rw);
Expand Down
36 changes: 12 additions & 24 deletions drivers/platform/x86/amd/hsmp/plat.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <asm/amd_hsmp.h>
#include <asm/amd_nb.h>

#include <linux/build_bug.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/sysfs.h>

#include <asm/amd_node.h>

#include "hsmp.h"

#define DRIVER_NAME "amd_hsmp"
Expand All @@ -34,28 +36,12 @@
#define SMN_HSMP_MSG_RESP 0x0010980
#define SMN_HSMP_MSG_DATA 0x00109E0

#define HSMP_INDEX_REG 0xc4
#define HSMP_DATA_REG 0xc8

static struct hsmp_plat_device *hsmp_pdev;

static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,
u32 *value, bool write)
{
int ret;

if (!sock->root)
return -ENODEV;

ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG,
sock->mbinfo.base_addr + offset);
if (ret)
return ret;

ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value)
: pci_read_config_dword(sock->root, HSMP_DATA_REG, value));

return ret;
return amd_smn_hsmp_rdwr(sock->sock_ind, sock->mbinfo.base_addr + offset, value, write);
}

static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj,
Expand Down Expand Up @@ -95,7 +81,12 @@ static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
* Static array of 8 + 1(for NULL) elements is created below
* to create sysfs groups for sockets.
* is_bin_visible function is used to show / hide the necessary groups.
*
* Validate the maximum number against MAX_AMD_NUM_NODES. If this changes,
* then the attributes and groups below must be adjusted.
*/
static_assert(MAX_AMD_NUM_NODES == 8);

#define HSMP_BIN_ATTR(index, _list) \
static const struct bin_attribute attr##index = { \
.attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \
Expand Down Expand Up @@ -159,10 +150,7 @@ static int init_platform_device(struct device *dev)
int ret, i;

for (i = 0; i < hsmp_pdev->num_sockets; i++) {
if (!node_to_amd_nb(i))
return -ENODEV;
sock = &hsmp_pdev->sock[i];
sock->root = node_to_amd_nb(i)->root;
sock->sock_ind = i;
sock->dev = dev;
sock->mbinfo.base_addr = SMN_HSMP_BASE;
Expand Down Expand Up @@ -305,11 +293,11 @@ static int __init hsmp_plt_init(void)
return -ENOMEM;

/*
* amd_nb_num() returns number of SMN/DF interfaces present in the system
* amd_num_nodes() returns number of SMN/DF interfaces present in the system
* if we have N SMN/DF interfaces that ideally means N sockets
*/
hsmp_pdev->num_sockets = amd_nb_num();
if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS)
hsmp_pdev->num_sockets = amd_num_nodes();
if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES)
return ret;

ret = platform_driver_register(&amd_hsmp_driver);
Expand Down

0 comments on commit 735049b

Please sign in to comment.