Skip to content

Commit

Permalink
platform/x86/amd/hsmp: Create separate ACPI, plat and common drivers
Browse files Browse the repository at this point in the history
Separate the probes for HSMP ACPI and platform device drivers.

Provide a Kconfig option to choose between ACPI or the platform device
based driver. The common code which is the core part of the HSMP driver
maintained at hsmp.c is guarded by AMD_HSMP config and is selected by
these two driver configs. This will be built into separate hsmp_common.ko
module and acpi as hsmp_acpi and plat as amd_hsmp respectively.

Also add "|| COMPILE_TEST" clause in Kconfig to get build coverage for
HSMP.

Signed-off-by: Suma Hegde <suma.hegde@amd.com>
Reviewed-by: Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
Link: https://lore.kernel.org/r/20241021111428.2676884-8-suma.hegde@amd.com
[ij: Fixed doc to use pre-formatted text for the ACPI dump.]
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
  • Loading branch information
Suma Hegde authored and Ilpo Järvinen committed Oct 25, 2024
1 parent 8e75dff commit 7d3135d
Show file tree
Hide file tree
Showing 8 changed files with 348 additions and 215 deletions.
67 changes: 62 additions & 5 deletions Documentation/arch/x86/amd_hsmp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
AMD HSMP interface
============================================

Newer Fam19h EPYC server line of processors from AMD support system
management functionality via HSMP (Host System Management Port).
Newer Fam19h(model 0x00-0x1f, 0x30-0x3f, 0x90-0x9f, 0xa0-0xaf),
Fam1Ah(model 0x00-0x1f) EPYC server line of processors from AMD support
system management functionality via HSMP (Host System Management Port).

The Host System Management Port (HSMP) is an interface to provide
OS-level software with access to system management functions via a
Expand All @@ -16,14 +17,25 @@ More details on the interface can be found in chapter
Eg: https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/programmer-references/55898_B1_pub_0_50.zip


HSMP interface is supported on EPYC server CPU models only.
HSMP interface is supported on EPYC line of server CPUs and MI300A (APU).


HSMP device
============================================

amd_hsmp driver under the drivers/platforms/x86/ creates miscdevice
/dev/hsmp to let user space programs run hsmp mailbox commands.
amd_hsmp driver under drivers/platforms/x86/amd/hsmp/ has separate driver files
for ACPI object based probing, platform device based probing and for the common
code for these two drivers.

Kconfig option CONFIG_AMD_HSMP_PLAT compiles plat.c and creates amd_hsmp.ko.
Kconfig option CONFIG_AMD_HSMP_ACPI compiles acpi.c and creates hsmp_acpi.ko.
Selecting any of these two configs automatically selects CONFIG_AMD_HSMP. This
compiles common code hsmp.c and creates hsmp_common.ko module.

Both the ACPI and plat drivers create the miscdevice /dev/hsmp to let
user space programs run hsmp mailbox commands.

The ACPI object format supported by the driver is defined below.

$ ls -al /dev/hsmp
crw-r--r-- 1 root root 10, 123 Jan 21 21:41 /dev/hsmp
Expand Down Expand Up @@ -59,6 +71,51 @@ Note: lseek() is not supported as entire metrics table is read.
Metrics table definitions will be documented as part of Public PPR.
The same is defined in the amd_hsmp.h header.

ACPI device object format
=========================
The ACPI object format expected from the amd_hsmp driver
for socket with ID00 is given below::

Device(HSMP)
{
Name(_HID, "AMDI0097")
Name(_UID, "ID00")
Name(HSE0, 0x00000001)
Name(RBF0, ResourceTemplate()
{
Memory32Fixed(ReadWrite, 0xxxxxxx, 0x00100000)
})
Method(_CRS, 0, NotSerialized)
{
Return(RBF0)
}
Method(_STA, 0, NotSerialized)
{
If(LEqual(HSE0, One))
{
Return(0x0F)
}
Else
{
Return(Zero)
}
}
Name(_DSD, Package(2)
{
Buffer(0x10)
{
0x9D, 0x61, 0x4D, 0xB7, 0x07, 0x57, 0xBD, 0x48,
0xA6, 0x9F, 0x4E, 0xA2, 0x87, 0x1F, 0xC2, 0xF6
},
Package(3)
{
Package(2) {"MsgIdOffset", 0x00010934},
Package(2) {"MsgRspOffset", 0x00010980},
Package(2) {"MsgArgOffset", 0x000109E0}
}
})
}


An example
==========
Expand Down
2 changes: 1 addition & 1 deletion drivers/platform/x86/amd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
#

obj-$(CONFIG_AMD_PMC) += pmc/
obj-y += hsmp/
obj-$(CONFIG_AMD_HSMP) += hsmp/
obj-$(CONFIG_AMD_PMF) += pmf/
obj-$(CONFIG_AMD_WBRF) += wbrf.o
36 changes: 33 additions & 3 deletions drivers/platform/x86/amd/hsmp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,44 @@
#

config AMD_HSMP
tristate "AMD HSMP Driver"
depends on AMD_NB && X86_64 && ACPI
tristate

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

config AMD_HSMP_ACPI
tristate "AMD HSMP ACPI device driver"
depends on ACPI
select AMD_HSMP
help
Host System Management Port (HSMP) interface is a mailbox interface
between the x86 core and the System Management Unit (SMU) firmware.
The driver provides a way for user space tools to monitor and manage
system management functionality on EPYC server CPUs from AMD.
system management functionality on EPYC and MI300A server CPUs
from AMD.

This option supports ACPI based probing.
You may enable this, if your platform BIOS provides an ACPI object
as described in amd_hsmp.rst document.

If you choose to compile this driver as a module the module will be
called hsmp_acpi.

config AMD_HSMP_PLAT
tristate "AMD HSMP platform device driver"
select AMD_HSMP
help
Host System Management Port (HSMP) interface is a mailbox interface
between the x86 core and the System Management Unit (SMU) firmware.
The driver provides a way for user space tools to monitor and manage
system management functionality on EPYC and MI300A server CPUs
from AMD.

This option supports platform device based probing.
You may enable this, if your platform BIOS does not provide
HSMP ACPI object.

If you choose to compile this driver as a module the module will be
called amd_hsmp.

endmenu
8 changes: 6 additions & 2 deletions drivers/platform/x86/amd/hsmp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@
# AMD HSMP Driver
#

obj-$(CONFIG_AMD_HSMP) += amd_hsmp.o
amd_hsmp-objs := hsmp.o plat.o acpi.o
obj-$(CONFIG_AMD_HSMP) += hsmp_common.o
hsmp_common-objs := hsmp.o
obj-$(CONFIG_AMD_HSMP_PLAT) += amd_hsmp.o
amd_hsmp-objs := plat.o
obj-$(CONFIG_AMD_HSMP_ACPI) += hsmp_acpi.o
hsmp_acpi-objs := acpi.o
82 changes: 79 additions & 3 deletions drivers/platform/x86/amd/hsmp/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,26 @@

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <asm/amd_nb.h>

#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/dev_printk.h>
#include <linux/ioport.h>
#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/sysfs.h>
#include <linux/uuid.h>

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

#include "hsmp.h"

#define DRIVER_NAME "amd_hsmp"
#define DRIVER_VERSION "2.3"
#define ACPI_HSMP_DEVICE_HID "AMDI0097"

/* These are the strings specified in ACPI table */
#define MSG_IDOFF_STR "MsgIdOffset"
#define MSG_ARGOFF_STR "MsgArgOffset"
Expand Down Expand Up @@ -200,7 +208,6 @@ static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)
sock->sock_ind = sock_ind;
sock->dev = dev;
sock->amd_hsmp_rdwr = amd_hsmp_acpi_rdwr;
hsmp_pdev.is_acpi_device = true;

sema_init(&sock->hsmp_sem, 1);

Expand All @@ -213,7 +220,7 @@ static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)
return hsmp_read_acpi_dsd(sock);
}

int hsmp_create_acpi_sysfs_if(struct device *dev)
static int hsmp_create_acpi_sysfs_if(struct device *dev)
{
struct attribute_group *attr_grp;
u16 sock_ind;
Expand All @@ -236,7 +243,7 @@ int hsmp_create_acpi_sysfs_if(struct device *dev)
return devm_device_add_group(dev, attr_grp);
}

int init_acpi(struct device *dev)
static int init_acpi(struct device *dev)
{
u16 sock_ind;
int ret;
Expand Down Expand Up @@ -270,3 +277,72 @@ int init_acpi(struct device *dev)

return ret;
}

static const struct acpi_device_id amd_hsmp_acpi_ids[] = {
{ACPI_HSMP_DEVICE_HID, 0},
{}
};
MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids);

static int hsmp_acpi_probe(struct platform_device *pdev)
{
int ret;

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)
return -ENODEV;

hsmp_pdev.sock = devm_kcalloc(&pdev->dev, hsmp_pdev.num_sockets,
sizeof(*hsmp_pdev.sock),
GFP_KERNEL);
if (!hsmp_pdev.sock)
return -ENOMEM;
}

ret = init_acpi(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n");
return ret;
}

ret = hsmp_create_acpi_sysfs_if(&pdev->dev);
if (ret)
dev_err(&pdev->dev, "Failed to create HSMP sysfs interface\n");

if (!hsmp_pdev.is_probed) {
ret = hsmp_misc_register(&pdev->dev);
if (ret)
return ret;
hsmp_pdev.is_probed = true;
}

return 0;
}

static void hsmp_acpi_remove(struct platform_device *pdev)
{
/*
* We register only one misc_device even on multi-socket system.
* So, deregister should happen only once.
*/
if (hsmp_pdev.is_probed) {
hsmp_misc_deregister();
hsmp_pdev.is_probed = false;
}
}

static struct platform_driver amd_hsmp_driver = {
.probe = hsmp_acpi_probe,
.remove = hsmp_acpi_remove,
.driver = {
.name = DRIVER_NAME,
.acpi_match_table = amd_hsmp_acpi_ids,
},
};

module_platform_driver(amd_hsmp_driver);

MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
Loading

0 comments on commit 7d3135d

Please sign in to comment.