X86 platform drivers
 help / color / mirror / Atom feed
From: Mario Limonciello <mario.limonciello@amd.com>
To: Suma Hegde <suma.hegde@amd.com>, platform-driver-x86@vger.kernel.org
Cc: ilpo.jarvinen@linux.intel.com, hdegoede@redhat.com,
	Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
Subject: Re: [PATCH 2/3] platform/x86/amd/hsmp: Split the ACPI and non-ACPI code
Date: Tue, 23 Apr 2024 12:13:32 -0500	[thread overview]
Message-ID: <f9729073-311e-455c-9b2e-4e9eb48be2a4@amd.com> (raw)
In-Reply-To: <20240423091434.2063246-3-suma.hegde@amd.com>

On 4/23/2024 04:14, Suma Hegde wrote:
> HSMP driver is supported on ACPI as well as non-ACPI based platforms.
> Making it dependent on ACPI in Kconfig, causes it to be compiled only on
> systems which have ACPI enabled.
> Remove this dependency by seggregating acpi specific code into
segregating
> hsmp-acpi.c file.
> This ensures that HSMP can be compiled with or without
> ACPI enabled.
> 
> Also create hsmp/ directory with Kconfig and Makefile
> to keep hsmp related files.
> 
> Signed-off-by: Suma Hegde <suma.hegde@amd.com>
> Reviewed-by: Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
> ---
>   MAINTAINERS                                |   2 +-
>   drivers/platform/x86/amd/Kconfig           |  14 +-
>   drivers/platform/x86/amd/Makefile          |   3 +-
>   drivers/platform/x86/amd/hsmp/Kconfig      |  17 ++
>   drivers/platform/x86/amd/hsmp/Makefile     |   9 +
>   drivers/platform/x86/amd/hsmp/hsmp-acpi.c  | 219 ++++++++++++++
>   drivers/platform/x86/amd/{ => hsmp}/hsmp.c | 324 +++------------------
>   drivers/platform/x86/amd/hsmp/hsmp.h       |  82 ++++++
>   8 files changed, 377 insertions(+), 293 deletions(-)
>   create mode 100644 drivers/platform/x86/amd/hsmp/Kconfig
>   create mode 100644 drivers/platform/x86/amd/hsmp/Makefile
>   create mode 100644 drivers/platform/x86/amd/hsmp/hsmp-acpi.c
>   rename drivers/platform/x86/amd/{ => hsmp}/hsmp.c (72%)
>   create mode 100644 drivers/platform/x86/amd/hsmp/hsmp.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ebf03f5f0619..bdc390ddcc4b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -999,7 +999,7 @@ S:	Maintained
>   F:	Documentation/arch/x86/amd_hsmp.rst
>   F:	arch/x86/include/asm/amd_hsmp.h
>   F:	arch/x86/include/uapi/asm/amd_hsmp.h
> -F:	drivers/platform/x86/amd/hsmp.c
> +F:	drivers/platform/x86/amd/hsmp/
>   
>   AMD IOMMU (AMD-VI)
>   M:	Joerg Roedel <joro@8bytes.org>
> diff --git a/drivers/platform/x86/amd/Kconfig b/drivers/platform/x86/amd/Kconfig
> index f88682d36447..c2f16ccebec4 100644
> --- a/drivers/platform/x86/amd/Kconfig
> +++ b/drivers/platform/x86/amd/Kconfig
> @@ -5,19 +5,7 @@
>   
>   source "drivers/platform/x86/amd/pmf/Kconfig"
>   source "drivers/platform/x86/amd/pmc/Kconfig"
> -
> -config AMD_HSMP
> -	tristate "AMD HSMP Driver"
> -	depends on AMD_NB && X86_64 && ACPI
> -	help
> -	  The driver provides a way for user space tools to monitor and manage
> -	  system management functionality on EPYC server CPUs from AMD.
> -
> -	  Host System Management Port (HSMP) interface is a mailbox interface
> -	  between the x86 core and the System Management Unit (SMU) firmware.
> -
> -	  If you choose to compile this driver as a module the module will be
> -	  called amd_hsmp.
> +source "drivers/platform/x86/amd/hsmp/Kconfig"
>   
>   config AMD_WBRF
>   	bool "AMD Wifi RF Band mitigations (WBRF)"
> diff --git a/drivers/platform/x86/amd/Makefile b/drivers/platform/x86/amd/Makefile
> index dcec0a46f8af..f0b2fe81c685 100644
> --- a/drivers/platform/x86/amd/Makefile
> +++ b/drivers/platform/x86/amd/Makefile
> @@ -5,7 +5,6 @@
>   #
>   
>   obj-$(CONFIG_AMD_PMC)		+= pmc/
> -amd_hsmp-y			:= hsmp.o
> -obj-$(CONFIG_AMD_HSMP)		+= amd_hsmp.o
> +obj-$(CONFIG_AMD_HSMP)		+= hsmp/
>   obj-$(CONFIG_AMD_PMF)		+= pmf/
>   obj-$(CONFIG_AMD_WBRF)		+= wbrf.o
> diff --git a/drivers/platform/x86/amd/hsmp/Kconfig b/drivers/platform/x86/amd/hsmp/Kconfig
> new file mode 100644
> index 000000000000..26096f901c22
> --- /dev/null
> +++ b/drivers/platform/x86/amd/hsmp/Kconfig
> @@ -0,0 +1,17 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# AMD HSMP driver
> +#
> +
> +config AMD_HSMP
> +	tristate "AMD HSMP Driver"
> +	depends on AMD_NB && X86_64
> +	help
> +	  The driver provides a way for user space tools to monitor and manage
> +	  system management functionality on EPYC server CPUs from AMD.
> +
> +	  Host System Management Port (HSMP) interface is a mailbox interface
> +	  between the x86 core and the System Management Unit (SMU) firmware.
> +
> +	  If you choose to compile this driver as a module the module will be
> +	  called amd_hsmp.
> diff --git a/drivers/platform/x86/amd/hsmp/Makefile b/drivers/platform/x86/amd/hsmp/Makefile
> new file mode 100644
> index 000000000000..0e5e4cc68145
> --- /dev/null
> +++ b/drivers/platform/x86/amd/hsmp/Makefile
> @@ -0,0 +1,9 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Makefile for linux/drivers/platform/x86/amd/hsmp
> +# AMD Host System Management Port
> +#
> +
> +amd_hsmp-y			:= hsmp.o
> +amd_hsmp-$(CONFIG_ACPI)		+= hsmp-acpi.o
> +obj-$(CONFIG_AMD_HSMP)		+= amd_hsmp.o
> diff --git a/drivers/platform/x86/amd/hsmp/hsmp-acpi.c b/drivers/platform/x86/amd/hsmp/hsmp-acpi.c
> new file mode 100644
> index 000000000000..90aa1bdbf7f1
> --- /dev/null
> +++ b/drivers/platform/x86/amd/hsmp/hsmp-acpi.c
> @@ -0,0 +1,219 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * AMD HSMP Platform Driver
> + * Copyright (c) 2024, AMD.
> + * All Rights Reserved.
> + *
> + * This file provides ACPI parsing implementation for HSMP interface
> + */
> +
> +#include "hsmp.h"
> +
> +/* These are the strings specified in ACPI table */
> +#define MSG_IDOFF_STR           "MsgIdOffset"
> +#define MSG_ARGOFF_STR          "MsgArgOffset"
> +#define MSG_RESPOFF_STR         "MsgRspOffset"
> +
> +/* This is the UUID used for HSMP */
> +static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd,
> +						0xa6, 0x9f, 0x4e, 0xa2,
> +						0x87, 0x1f, 0xc2, 0xf6);
> +
> +static inline bool is_acpi_hsmp_uuid(union acpi_object *obj)
> +{
> +	if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE)
> +		return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid);
> +
> +	return false;
> +}
> +
> +static acpi_status hsmp_resource(struct acpi_resource *res, void *data)
> +{
> +	struct hsmp_socket *sock = data;
> +	struct resource r;
> +
> +	switch (res->type) {
> +	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
> +		if (!acpi_dev_resource_memory(res, &r))
> +			return AE_ERROR;
> +		if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE))
> +			return AE_ERROR;
> +		sock->mbinfo.base_addr = r.start;
> +		sock->mbinfo.size = resource_size(&r);
> +		break;
> +	case ACPI_RESOURCE_TYPE_END_TAG:
> +		break;
> +	default:
> +		return AE_ERROR;
> +	}
> +
> +	return AE_OK;
> +}
> +
> +static int hsmp_read_acpi_crs(struct hsmp_socket *sock)
> +{
> +	acpi_status status;
> +
> +	status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS,
> +				     hsmp_resource, sock);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n",
> +			acpi_format_exception(status));
> +		return -EINVAL;
> +	}
> +	if (!sock->mbinfo.base_addr || !sock->mbinfo.size)
> +		return -EINVAL;
> +
> +	/* The mapped region should be un cached */
> +	sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr,
> +					       sock->mbinfo.size);
> +	if (!sock->virt_base_addr) {
> +		dev_err(sock->dev, "Failed to ioremap MP1 base address\n");
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +static int hsmp_read_acpi_dsd(struct hsmp_socket *sock)
> +{
> +	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object *guid, *mailbox_package;
> +	union acpi_object *dsd;
> +	acpi_status status;
> +	int ret = 0;
> +	int j;
> +
> +	status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL,
> +					    &buf, ACPI_TYPE_PACKAGE);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n",
> +			acpi_format_exception(status));
> +		return -ENODEV;
> +	}
> +
> +	dsd = buf.pointer;
> +
> +	/* HSMP _DSD property should contain 2 objects.
> +	 * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER
> +	 * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE
> +	 *    This mailbox object contains 3 more acpi objects of type
> +	 *    ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets
> +	 *    these packages inturn contain 2 acpi objects of type
> +	 *    ACPI_TYPE_STRING and ACPI_TYPE_INTEGER
> +	 */
> +	if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) {
> +		ret = -EINVAL;
> +		goto free_buf;
> +	}
> +
> +	guid = &dsd->package.elements[0];
> +	mailbox_package = &dsd->package.elements[1];
> +	if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) {
> +		dev_err(sock->dev, "Invalid hsmp _DSD table data\n");
> +		ret = -EINVAL;
> +		goto free_buf;
> +	}
> +
> +	for (j = 0; j < mailbox_package->package.count; j++) {
> +		union acpi_object *msgobj, *msgstr, *msgint;
> +
> +		msgobj	= &mailbox_package->package.elements[j];
> +		msgstr	= &msgobj->package.elements[0];
> +		msgint	= &msgobj->package.elements[1];
> +
> +		/* package should have 1 string and 1 integer object */
> +		if (msgobj->type != ACPI_TYPE_PACKAGE ||
> +		    msgstr->type != ACPI_TYPE_STRING ||
> +		    msgint->type != ACPI_TYPE_INTEGER) {
> +			ret = -EINVAL;
> +			goto free_buf;
> +		}
> +
> +		if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR,
> +			     msgstr->string.length)) {
> +			sock->mbinfo.msg_id_off = msgint->integer.value;
> +		} else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR,
> +				    msgstr->string.length)) {
> +			sock->mbinfo.msg_resp_off =  msgint->integer.value;
> +		} else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR,
> +				    msgstr->string.length)) {
> +			sock->mbinfo.msg_arg_off = msgint->integer.value;
> +		} else {
> +			ret = -ENOENT;
> +			goto free_buf;
> +		}
> +	}
> +
> +	if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off ||
> +	    !sock->mbinfo.msg_arg_off)
> +		ret = -EINVAL;
> +
> +free_buf:
> +	ACPI_FREE(buf.pointer);
> +	return ret;
> +}
> +
> +int init_acpi(struct hsmp_plat_device *plat_dev, struct device *dev)
> +{
> +	struct hsmp_socket *sock;
> +	u16 sock_ind;
> +	int ret;
> +
> +	plat_dev->is_acpi_device = true;
> +
> +	ret = hsmp_get_uid(dev, &sock_ind);
> +	if (ret)
> +		return ret;
> +	if (sock_ind >= plat_dev->num_sockets)
> +		return -EINVAL;
> +
> +	sock = &plat_dev->sock[sock_ind];
> +
> +	sock->sock_ind		= sock_ind;
> +	sock->dev		= dev;
> +
> +	sema_init(&sock->hsmp_sem, 1);
> +
> +	/* Read MP1 base address from CRS method */
> +	ret = hsmp_read_acpi_crs(sock);
> +	if (ret)
> +		return ret;
> +
> +	/* Read mailbox offsets from DSD table */
> +	return hsmp_read_acpi_dsd(sock);
> +}
> +
> +int check_acpi_support(struct device *dev, const struct acpi_device_id *amd_hsmp_acpi_ids)
> +{
> +	struct acpi_device *adev;
> +
> +	adev = ACPI_COMPANION(dev);
> +	if (adev && !acpi_match_device_ids(adev, amd_hsmp_acpi_ids))
> +		return 0;
> +
> +	return -ENODEV;
> +}
> +
> +int hsmp_get_uid(struct device *dev, u16 *sock_ind)
> +{
> +	char *uid;
> +
> +	/*
> +	 * UID (ID00, ID01..IDXX) is used for differentiating sockets,
> +	 * read it and strip the "ID" part of it and convert the remaining
> +	 * bytes to integer.
> +	 */
> +	uid = acpi_device_uid(ACPI_COMPANION(dev));
> +
> +	return kstrtou16(uid + 2, 10, sock_ind);
> +}
> +
> +void amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
> +			u32 *value, bool write)
> +{
> +	if (write)
> +		iowrite32(*value, sock->virt_base_addr + offset);
> +	else
> +		*value = ioread32(sock->virt_base_addr + offset);
> +}
> diff --git a/drivers/platform/x86/amd/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c
> similarity index 72%
> rename from drivers/platform/x86/amd/hsmp.c
> rename to drivers/platform/x86/amd/hsmp/hsmp.c
> index 807a5066dacc..1df2b34ddbbd 100644
> --- a/drivers/platform/x86/amd/hsmp.c
> +++ b/drivers/platform/x86/amd/hsmp/hsmp.c
> @@ -10,18 +10,10 @@
>   #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>   
>   #include <asm/amd_hsmp.h>
> -#include <asm/amd_nb.h>
> -#include <linux/delay.h>
> -#include <linux/io.h>
> -#include <linux/miscdevice.h>
> -#include <linux/module.h>
> -#include <linux/pci.h>
> -#include <linux/platform_device.h>
> -#include <linux/semaphore.h>
> -#include <linux/acpi.h>
> +#include "hsmp.h"
>   
>   #define DRIVER_NAME		"amd_hsmp"
> -#define DRIVER_VERSION		"2.2"
> +#define DRIVER_VERSION		"2.3"
>   #define ACPI_HSMP_DEVICE_HID	"AMDI0097"
>   
>   /* HSMP Status / Error codes */
> @@ -55,44 +47,8 @@
>   #define HSMP_DEVNODE_NAME	"hsmp"
>   #define HSMP_METRICS_TABLE_NAME	"metrics_bin"
>   
> -#define HSMP_ATTR_GRP_NAME_SIZE	10
> -
> -/* These are the strings specified in ACPI table */
> -#define MSG_IDOFF_STR		"MsgIdOffset"
> -#define MSG_ARGOFF_STR		"MsgArgOffset"
> -#define MSG_RESPOFF_STR		"MsgRspOffset"
> -
>   #define MAX_AMD_SOCKETS 8
>   
> -struct hsmp_mbaddr_info {
> -	u32 base_addr;
> -	u32 msg_id_off;
> -	u32 msg_resp_off;
> -	u32 msg_arg_off;
> -	u32 size;
> -};
> -
> -struct hsmp_socket {
> -	struct bin_attribute hsmp_attr;
> -	struct hsmp_mbaddr_info mbinfo;
> -	void __iomem *metric_tbl_addr;
> -	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;
> -};
> -
> -struct hsmp_plat_device {
> -	struct miscdevice hsmp_device;
> -	struct hsmp_socket *sock;
> -	u32 proto_ver;
> -	u16 num_sockets;
> -	bool is_acpi_device;
> -	bool is_probed;
> -};
> -
>   static struct hsmp_plat_device plat_dev;
>   
>   static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,
> @@ -114,15 +70,6 @@ static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,
>   	return ret;
>   }
>   
> -static void amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
> -			       u32 *value, bool write)
> -{
> -	if (write)
> -		iowrite32(*value, sock->virt_base_addr + offset);
> -	else
> -		*value = ioread32(sock->virt_base_addr + offset);
> -}
> -
>   static int amd_hsmp_rdwr(struct hsmp_socket *sock, u32 offset,
>   			 u32 *value, bool write)
>   {
> @@ -321,6 +268,22 @@ static int hsmp_test(u16 sock_ind, u32 value)
>   	return ret;
>   }
>   
> +static int hsmp_cache_proto_ver(u16 sock_ind)
> +{
> +	struct hsmp_message msg = { 0 };
> +	int ret;
> +
> +	msg.msg_id	= HSMP_GET_PROTO_VER;
> +	msg.sock_ind	= sock_ind;
> +	msg.response_sz = hsmp_msg_desc_table[HSMP_GET_PROTO_VER].response_sz;
> +
> +	ret = hsmp_send_message(&msg);
> +	if (!ret)
> +		plat_dev.proto_ver = msg.args[0];
> +
> +	return ret;
> +}
> +
>   static long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
>   {
>   	int __user *arguser = (int  __user *)arg;
> @@ -383,181 +346,6 @@ static const struct file_operations hsmp_fops = {
>   	.compat_ioctl	= hsmp_ioctl,
>   };
>   
> -/* This is the UUID used for HSMP */
> -static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd,
> -						0xa6, 0x9f, 0x4e, 0xa2,
> -						0x87, 0x1f, 0xc2, 0xf6);
> -
> -static inline bool is_acpi_hsmp_uuid(union acpi_object *obj)
> -{
> -	if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE)
> -		return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid);
> -
> -	return false;
> -}
> -
> -static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind)
> -{
> -	char *uid;
> -
> -	/*
> -	 * UID (ID00, ID01..IDXX) is used for differentiating sockets,
> -	 * read it and strip the "ID" part of it and convert the remaining
> -	 * bytes to integer.
> -	 */
> -	uid = acpi_device_uid(ACPI_COMPANION(dev));
> -
> -	return kstrtou16(uid + 2, 10, sock_ind);
> -}
> -
> -static acpi_status hsmp_resource(struct acpi_resource *res, void *data)
> -{
> -	struct hsmp_socket *sock = data;
> -	struct resource r;
> -
> -	switch (res->type) {
> -	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
> -		if (!acpi_dev_resource_memory(res, &r))
> -			return AE_ERROR;
> -		if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE))
> -			return AE_ERROR;
> -		sock->mbinfo.base_addr = r.start;
> -		sock->mbinfo.size = resource_size(&r);
> -		break;
> -	case ACPI_RESOURCE_TYPE_END_TAG:
> -		break;
> -	default:
> -		return AE_ERROR;
> -	}
> -
> -	return AE_OK;
> -}
> -
> -static int hsmp_read_acpi_dsd(struct hsmp_socket *sock)
> -{
> -	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
> -	union acpi_object *guid, *mailbox_package;
> -	union acpi_object *dsd;
> -	acpi_status status;
> -	int ret = 0;
> -	int j;
> -
> -	status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL,
> -					    &buf, ACPI_TYPE_PACKAGE);
> -	if (ACPI_FAILURE(status)) {
> -		dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n",
> -			acpi_format_exception(status));
> -		return -ENODEV;
> -	}
> -
> -	dsd = buf.pointer;
> -
> -	/* HSMP _DSD property should contain 2 objects.
> -	 * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER
> -	 * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE
> -	 *    This mailbox object contains 3 more acpi objects of type
> -	 *    ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets
> -	 *    these packages inturn contain 2 acpi objects of type
> -	 *    ACPI_TYPE_STRING and ACPI_TYPE_INTEGER
> -	 */
> -	if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) {
> -		ret = -EINVAL;
> -		goto free_buf;
> -	}
> -
> -	guid = &dsd->package.elements[0];
> -	mailbox_package = &dsd->package.elements[1];
> -	if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) {
> -		dev_err(sock->dev, "Invalid hsmp _DSD table data\n");
> -		ret = -EINVAL;
> -		goto free_buf;
> -	}
> -
> -	for (j = 0; j < mailbox_package->package.count; j++) {
> -		union acpi_object *msgobj, *msgstr, *msgint;
> -
> -		msgobj	= &mailbox_package->package.elements[j];
> -		msgstr	= &msgobj->package.elements[0];
> -		msgint	= &msgobj->package.elements[1];
> -
> -		/* package should have 1 string and 1 integer object */
> -		if (msgobj->type != ACPI_TYPE_PACKAGE ||
> -		    msgstr->type != ACPI_TYPE_STRING ||
> -		    msgint->type != ACPI_TYPE_INTEGER) {
> -			ret = -EINVAL;
> -			goto free_buf;
> -		}
> -
> -		if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR,
> -			     msgstr->string.length)) {
> -			sock->mbinfo.msg_id_off = msgint->integer.value;
> -		} else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR,
> -				    msgstr->string.length)) {
> -			sock->mbinfo.msg_resp_off =  msgint->integer.value;
> -		} else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR,
> -				    msgstr->string.length)) {
> -			sock->mbinfo.msg_arg_off = msgint->integer.value;
> -		} else {
> -			ret = -ENOENT;
> -			goto free_buf;
> -		}
> -	}
> -
> -	if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off ||
> -	    !sock->mbinfo.msg_arg_off)
> -		ret = -EINVAL;
> -
> -free_buf:
> -	ACPI_FREE(buf.pointer);
> -	return ret;
> -}
> -
> -static int hsmp_read_acpi_crs(struct hsmp_socket *sock)
> -{
> -	acpi_status status;
> -
> -	status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS,
> -				     hsmp_resource, sock);
> -	if (ACPI_FAILURE(status)) {
> -		dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n",
> -			acpi_format_exception(status));
> -		return -EINVAL;
> -	}
> -	if (!sock->mbinfo.base_addr || !sock->mbinfo.size)
> -		return -EINVAL;
> -
> -	/* The mapped region should be un cached */
> -	sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr,
> -					       sock->mbinfo.size);
> -	if (!sock->virt_base_addr) {
> -		dev_err(sock->dev, "Failed to ioremap MP1 base address\n");
> -		return -ENOMEM;
> -	}
> -
> -	return 0;
> -}
> -
> -/* Parse the ACPI table to read the data */
> -static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)
> -{
> -	struct hsmp_socket *sock = &plat_dev.sock[sock_ind];
> -	int ret;
> -
> -	sock->sock_ind		= sock_ind;
> -	sock->dev		= dev;
> -	plat_dev.is_acpi_device	= true;
> -
> -	sema_init(&sock->hsmp_sem, 1);
> -
> -	/* Read MP1 base address from CRS method */
> -	ret = hsmp_read_acpi_crs(sock);
> -	if (ret)
> -		return ret;
> -
> -	/* Read mailbox offsets from DSD table */
> -	return hsmp_read_acpi_dsd(sock);
> -}
> -
>   static ssize_t hsmp_metric_tbl_read(struct file *filp, struct kobject *kobj,
>   				    struct bin_attribute *bin_attr, char *buf,
>   				    loff_t off, size_t count)
> @@ -670,8 +458,15 @@ static int hsmp_create_non_acpi_sysfs_if(struct device *dev)
>   {
>   	const struct attribute_group **hsmp_attr_grps;
>   	struct attribute_group *attr_grp;
> +	int ret;
>   	u16 i;
>   
> +	ret = hsmp_cache_proto_ver(0);
> +	if (ret) {
> +		dev_err(dev, "Failed to read HSMP protocol version\n");
> +		return ret;
> +	}
> +
>   	hsmp_attr_grps = devm_kcalloc(dev, plat_dev.num_sockets + 1,
>   				      sizeof(*hsmp_attr_grps),
>   				      GFP_KERNEL);
> @@ -706,12 +501,18 @@ static int hsmp_create_acpi_sysfs_if(struct device *dev)
>   	if (!attr_grp)
>   		return -ENOMEM;
>   
> -	attr_grp->is_bin_visible = hsmp_is_sock_attr_visible;
> -
>   	ret = hsmp_get_uid(dev, &sock_ind);
>   	if (ret)
>   		return ret;
>   
> +	ret = hsmp_cache_proto_ver(sock_ind);
> +	if (ret) {
> +		dev_err(dev, "Failed to read HSMP protocol version\n");
> +		return ret;
> +	}
> +
> +	attr_grp->is_bin_visible = hsmp_is_sock_attr_visible;
> +
>   	ret = hsmp_create_attr_list(attr_grp, dev, sock_ind);
>   	if (ret)
>   		return ret;
> @@ -719,22 +520,6 @@ static int hsmp_create_acpi_sysfs_if(struct device *dev)
>   	return devm_device_add_group(dev, attr_grp);
>   }
>   
> -static int hsmp_cache_proto_ver(u16 sock_ind)
> -{
> -	struct hsmp_message msg = { 0 };
> -	int ret;
> -
> -	msg.msg_id	= HSMP_GET_PROTO_VER;
> -	msg.sock_ind	= sock_ind;
> -	msg.response_sz = hsmp_msg_desc_table[HSMP_GET_PROTO_VER].response_sz;
> -
> -	ret = hsmp_send_message(&msg);
> -	if (!ret)
> -		plat_dev.proto_ver = msg.args[0];
> -
> -	return ret;
> -}
> -
>   static inline bool is_f1a_m0h(void)
>   {
>   	if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F)
> @@ -791,8 +576,6 @@ MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids);
>   
>   static int hsmp_pltdrv_probe(struct platform_device *pdev)
>   {
> -	struct acpi_device *adev;
> -	u16 sock_ind = 0;
>   	int ret;
>   
>   	/*
> @@ -809,46 +592,33 @@ static int hsmp_pltdrv_probe(struct platform_device *pdev)
>   		if (!plat_dev.sock)
>   			return -ENOMEM;
>   	}
> -	adev = ACPI_COMPANION(&pdev->dev);
> -	if (adev && !acpi_match_device_ids(adev, amd_hsmp_acpi_ids)) {
> -		ret = hsmp_get_uid(&pdev->dev, &sock_ind);
> -		if (ret)
> -			return ret;
> -		if (sock_ind >= plat_dev.num_sockets)
> -			return -EINVAL;
> -		ret = hsmp_parse_acpi_table(&pdev->dev, sock_ind);
> +
> +	ret = check_acpi_support(&pdev->dev, amd_hsmp_acpi_ids);
> +	if (!ret) {
> +		ret = init_acpi(&plat_dev, &pdev->dev);
>   		if (ret) {
> -			dev_err(&pdev->dev, "Failed to parse ACPI table\n");
> +			dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n");
>   			return ret;
>   		}
> -		/* Test the hsmp interface */
> -		ret = hsmp_test(sock_ind, 0xDEADBEEF);
> +
> +		ret = hsmp_create_acpi_sysfs_if(&pdev->dev);
>   		if (ret) {
> -			dev_err(&pdev->dev, "HSMP test message failed on Fam:%x model:%x\n",
> -				boot_cpu_data.x86, boot_cpu_data.x86_model);
> -			dev_err(&pdev->dev, "Is HSMP disabled in BIOS ?\n");
> +			dev_err(&pdev->dev, "Failed to create HSMP sysfs interface\n");
>   			return ret;
>   		}
>   	} else {
>   		ret = init_platform_device(&pdev->dev);
>   		if (ret) {
> -			dev_err(&pdev->dev, "Failed to init HSMP mailbox\n");
> +			dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n");
>   			return ret;
>   		}
> -	}
> -
> -	ret = hsmp_cache_proto_ver(sock_ind);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to read HSMP protocol version\n");
> -		return ret;
> -	}
>   
> -	if (plat_dev.is_acpi_device)
> -		ret = hsmp_create_acpi_sysfs_if(&pdev->dev);
> -	else
>   		ret = hsmp_create_non_acpi_sysfs_if(&pdev->dev);
> -	if (ret)
> -		dev_err(&pdev->dev, "Failed to create HSMP sysfs interface\n");
> +		if (ret) {
> +			dev_err(&pdev->dev, "Failed to create HSMP sysfs interface\n");
> +			return ret;
> +		}
> +	}
>   
>   	if (!plat_dev.is_probed) {
>   		plat_dev.hsmp_device.name	= HSMP_CDEV_NAME;
> diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h
> new file mode 100644
> index 000000000000..23629ccb1fb0
> --- /dev/null
> +++ b/drivers/platform/x86/amd/hsmp/hsmp.h
> @@ -0,0 +1,82 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * AMD HSMP Platform Driver
> + * Copyright (c) 2024, AMD.
> + * All Rights Reserved.
> + *
> + * This file provides a header implementation for HSMP interface
> + */
> +
> +#ifndef _HSMP_H
> +#define _HSMP_H
> +
> +#include <asm/amd_nb.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/platform_device.h>
> +#include <linux/semaphore.h>
> +#include <linux/acpi.h>
> +#include <linux/miscdevice.h>
> +
> +#define HSMP_ATTR_GRP_NAME_SIZE 10
> +
> +struct hsmp_mbaddr_info {
> +	u32 base_addr;
> +	u32 msg_id_off;
> +	u32 msg_resp_off;
> +	u32 msg_arg_off;
> +	u32 size;
> +};
> +
> +struct hsmp_socket {
> +	struct bin_attribute hsmp_attr;
> +	struct hsmp_mbaddr_info mbinfo;
> +	void __iomem *metric_tbl_addr;
> +	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;
> +};
> +
> +struct hsmp_plat_device {
> +	struct miscdevice hsmp_device;
> +	struct hsmp_socket *sock;
> +	u32 proto_ver;
> +	u16 num_sockets;
> +	bool is_acpi_device;
> +	bool is_probed;
> +};
> +
> +#ifdef CONFIG_ACPI
> +int hsmp_get_uid(struct device *dev, u16 *sock_ind);
> +void amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
> +			u32 *value, bool write);
> +int check_acpi_support(struct device *dev, const struct acpi_device_id *amd_hsmp_acpi_ids);
> +int init_acpi(struct hsmp_plat_device *plat_dev, struct device *dev);
> +#else
> +static inline void amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
> +				      u32 *value, bool write)
> +{
> +}
> +
> +static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind)
> +{
> +	return -ENODEV;
> +}
> +
> +static inline int check_acpi_support(struct device *dev,
> +				     const struct acpi_device_id *amd_hsmp_acpi_ids)
> +{
> +	return -ENODEV;
> +}
> +
> +static inline int init_acpi(struct hsmp_plat_device *plat_dev, struct device *dev)
> +{
> +	return -ENODEV;
> +}
> +#endif
> +#endif


  reply	other threads:[~2024-04-23 17:13 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-23  9:14 [PATCH 0/3] platform/x86/amd/hsmp: ACPI, Non-ACPI code split and other misc changes Suma Hegde
2024-04-23  9:14 ` [PATCH 1/3] platform/x86/amd/hsmp: Check HSMP support on AMD family of processors Suma Hegde
2024-04-23 17:11   ` Mario Limonciello
2024-04-25 10:03     ` Hegde, Suma
2024-04-23  9:14 ` [PATCH 2/3] platform/x86/amd/hsmp: Split the ACPI and non-ACPI code Suma Hegde
2024-04-23 17:13   ` Mario Limonciello [this message]
2024-04-23  9:14 ` [PATCH 3/3] platform/x86/amd/hsmp: Make HSMP as default m Suma Hegde
2024-04-23 17:17   ` Mario Limonciello
2024-04-25  6:59     ` Hegde, Suma
2024-04-23 17:07 ` [PATCH 0/3] platform/x86/amd/hsmp: ACPI, Non-ACPI code split and other misc changes Mario Limonciello
2024-04-29  8:50   ` Hans de Goede

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f9729073-311e-455c-9b2e-4e9eb48be2a4@amd.com \
    --to=mario.limonciello@amd.com \
    --cc=hdegoede@redhat.com \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=naveenkrishna.chatradhi@amd.com \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=suma.hegde@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox