All of lore.kernel.org
 help / color / mirror / Atom feed
From: Erwan Velu <erwanaliasr1@gmail.com>
To: platform-driver-x86@vger.kernel.org
Cc: "Naveen Krishna Chatradhi" <naveenkrishna.chatradhi@amd.com>,
	"Carlos Bilbao" <carlos.bilbao@kernel.org>,
	"Hans de Goede" <hansg@kernel.org>,
	"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 1/4] platform/x86/amd/hsmp: Move per-socket sysfs attributes to common code
Date: Wed,  7 Oct 2026 14:59:05 +0200	[thread overview]
Message-ID: <20261007125908.321186-2-erwanaliasr1@gmail.com> (raw)
In-Reply-To: <20261007125908.321186-1-erwanaliasr1@gmail.com>

From: Erwan Velu <e.velu@criteo.com>

The per-socket telemetry attributes (c0_residency_input, ddr_max_bw,
pwr_current_active_freq_limit, ...) are implemented in acpi.c, so only
the ACPI driver can expose them, although they are plain HSMP messages
the platform driver can send as well.

Move them to a new sysfs.c in hsmp_common and export the attribute
groups as hsmp_sock_groups, so they can be shared by both drivers. The
ACPI driver keeps exposing them on its socket devices via dev_groups.

No functional change.

Assisted-by: claude-opus-5-5
Signed-off-by: Erwan Velu <e.velu@criteo.com>
---
 drivers/platform/x86/amd/hsmp/Makefile |   2 +-
 drivers/platform/x86/amd/hsmp/acpi.c   | 321 +----------------------
 drivers/platform/x86/amd/hsmp/hsmp.h   |   1 +
 drivers/platform/x86/amd/hsmp/sysfs.c  | 338 +++++++++++++++++++++++++
 4 files changed, 341 insertions(+), 321 deletions(-)
 create mode 100644 drivers/platform/x86/amd/hsmp/sysfs.c

diff --git a/drivers/platform/x86/amd/hsmp/Makefile b/drivers/platform/x86/amd/hsmp/Makefile
index ce8342e71f50..21fc1d185550 100644
--- a/drivers/platform/x86/amd/hsmp/Makefile
+++ b/drivers/platform/x86/amd/hsmp/Makefile
@@ -5,7 +5,7 @@
 #
 
 obj-$(CONFIG_AMD_HSMP)			+= hsmp_common.o
-hsmp_common-y				:= hsmp.o
+hsmp_common-y				:= hsmp.o sysfs.o
 hsmp_common-$(CONFIG_HWMON)		+= hwmon.o
 obj-$(CONFIG_AMD_HSMP_PLAT)		+= amd_hsmp.o
 amd_hsmp-y				:= plat.o
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index ddd7a04ee753..d76979baffa8 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -12,9 +12,6 @@
 #include <asm/amd/hsmp.h>
 
 #include <linux/acpi.h>
-#include <linux/array_size.h>
-#include <linux/bits.h>
-#include <linux/bitfield.h>
 #include <linux/cleanup.h>
 #include <linux/device.h>
 #include <linux/dev_printk.h>
@@ -27,7 +24,6 @@
 #include <linux/rwsem.h>
 #include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/sysfs.h>
 #include <linux/topology.h>
 #include <linux/uuid.h>
 
@@ -55,11 +51,6 @@ static struct hsmp_plat_device *hsmp_pdev;
  */
 static struct kref hsmp_acpi_sock_kref;
 
-struct hsmp_sys_attr {
-	struct device_attribute dattr;
-	u32 msg_id;
-};
-
 static int amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
 			      u32 *value, bool write)
 {
@@ -270,252 +261,6 @@ static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)
 	return 0;
 }
 
-static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj,
-					 const struct bin_attribute *bin_attr, char *buf,
-					 loff_t off, size_t count)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-
-	/*
-	 * metrics_bin is a sysfs binary attribute and is capped at PAGE_SIZE.
-	 * It can therefore only carry the protocol version 6 metric table
-	 * (struct hsmp_metric_table).  The larger tables defined from protocol
-	 * version 7 onwards do not fit; userspace on those systems must read
-	 * the snapshot through HSMP_IOCTL_GET_TELEMETRY_DATA on /dev/hsmp.
-	 * Surface the unsupported case here as -EOPNOTSUPP rather than
-	 * silently truncating the snapshot.
-	 */
-	if (hsmp_pdev->proto_ver != HSMP_PROTO_VER6)
-		return -EOPNOTSUPP;
-
-	return hsmp_metric_tbl_read(sock, buf, count);
-}
-
-static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
-					 const struct bin_attribute *battr, int id)
-{
-	/*
-	 * Keep metrics_bin visible on protocol version 7 and later as well,
-	 * so that userspace which expects the file to exist gets a clear
-	 * -EOPNOTSUPP from the read handler instead of -ENOENT, and is
-	 * pointed at HSMP_IOCTL_GET_TELEMETRY_DATA as the supported path.
-	 */
-	if (hsmp_pdev->proto_ver >= HSMP_PROTO_VER6)
-		return battr->attr.mode;
-
-	return 0;
-}
-
-static umode_t hsmp_is_sock_dev_attr_visible(struct kobject *kobj,
-					     struct attribute *attr, int id)
-{
-	return attr->mode;
-}
-
-#define to_hsmp_sys_attr(_attr) container_of(_attr, struct hsmp_sys_attr, dattr)
-
-static ssize_t hsmp_msg_resp32_show(struct device *dev, struct device_attribute *attr,
-				    char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data;
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%u\n", data);
-}
-
-#define DDR_MAX_BW_MASK		GENMASK(31, 20)
-#define DDR_UTIL_BW_MASK	GENMASK(19, 8)
-#define DDR_UTIL_BW_PERC_MASK	GENMASK(7, 0)
-#define FW_VER_MAJOR_MASK	GENMASK(23, 16)
-#define FW_VER_MINOR_MASK	GENMASK(15, 8)
-#define FW_VER_DEBUG_MASK	GENMASK(7, 0)
-#define FMAX_MASK		GENMASK(31, 16)
-#define FMIN_MASK		GENMASK(15, 0)
-#define FREQ_LIMIT_MASK		GENMASK(31, 16)
-#define FREQ_SRC_IND_MASK	GENMASK(15, 0)
-
-static ssize_t hsmp_ddr_max_bw_show(struct device *dev, struct device_attribute *attr,
-				    char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data;
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_MAX_BW_MASK, data));
-}
-
-static ssize_t hsmp_ddr_util_bw_show(struct device *dev, struct device_attribute *attr,
-				     char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data;
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_UTIL_BW_MASK, data));
-}
-
-static ssize_t hsmp_ddr_util_bw_perc_show(struct device *dev, struct device_attribute *attr,
-					  char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data;
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_UTIL_BW_PERC_MASK, data));
-}
-
-static ssize_t hsmp_msg_fw_ver_show(struct device *dev, struct device_attribute *attr,
-				    char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data;
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%lu.%lu.%lu\n",
-			  FIELD_GET(FW_VER_MAJOR_MASK, data),
-			  FIELD_GET(FW_VER_MINOR_MASK, data),
-			  FIELD_GET(FW_VER_DEBUG_MASK, data));
-}
-
-static ssize_t hsmp_fclk_show(struct device *dev, struct device_attribute *attr,
-			      char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data[2];
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, data, 2);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%u\n", data[0]);
-}
-
-static ssize_t hsmp_mclk_show(struct device *dev, struct device_attribute *attr,
-			      char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data[2];
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, data, 2);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%u\n", data[1]);
-}
-
-static ssize_t hsmp_clk_fmax_show(struct device *dev, struct device_attribute *attr,
-				  char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data;
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%lu\n", FIELD_GET(FMAX_MASK, data));
-}
-
-static ssize_t hsmp_clk_fmin_show(struct device *dev, struct device_attribute *attr,
-				  char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data;
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%lu\n", FIELD_GET(FMIN_MASK, data));
-}
-
-static ssize_t hsmp_freq_limit_show(struct device *dev, struct device_attribute *attr,
-				    char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	u32 data;
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
-	if (ret)
-		return ret;
-
-	return sysfs_emit(buf, "%lu\n", FIELD_GET(FREQ_LIMIT_MASK, data));
-}
-
-static const char * const freqlimit_srcnames[] = {
-	"cHTC-Active",
-	"PROCHOT",
-	"TDC limit",
-	"PPT Limit",
-	"OPN Max",
-	"Reliability Limit",
-	"APML Agent",
-	"HSMP Agent",
-};
-
-static ssize_t hsmp_freq_limit_source_show(struct device *dev, struct device_attribute *attr,
-					   char *buf)
-{
-	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
-	struct hsmp_socket *sock = dev_get_drvdata(dev);
-	unsigned int index;
-	int len = 0;
-	u16 src_ind;
-	u32 data;
-	int ret;
-
-	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
-	if (ret)
-		return ret;
-
-	src_ind = FIELD_GET(FREQ_SRC_IND_MASK, data);
-	for (index = 0; index < ARRAY_SIZE(freqlimit_srcnames); index++) {
-		if (!src_ind)
-			break;
-		if (src_ind & 1)
-			len += sysfs_emit_at(buf, len, "%s\n", freqlimit_srcnames[index]);
-		src_ind >>= 1;
-	}
-	return len;
-}
-
 /*
  * Bring up one ACPI HSMP socket: parse its ACPI table, run the mailbox
  * handshake and register its sysfs/hwmon interfaces.
@@ -572,70 +317,6 @@ static int init_acpi(struct device *dev)
 	return 0;
 }
 
-static const struct bin_attribute  hsmp_metric_tbl_attr = {
-	.attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444},
-	.read = hsmp_metric_tbl_acpi_read,
-	.size = sizeof(struct hsmp_metric_table),
-};
-
-static const struct bin_attribute *hsmp_attr_list[] = {
-	&hsmp_metric_tbl_attr,
-	NULL
-};
-
-#define HSMP_DEV_ATTR(_name, _msg_id, _show, _mode)	\
-static struct hsmp_sys_attr hattr_##_name = {		\
-	.dattr = __ATTR(_name, _mode, _show, NULL),	\
-	.msg_id = _msg_id,				\
-}
-
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444);
-HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444);
-HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444);
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444);
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444);
-HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444);
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444);
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_perc_show, 0444);
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444);
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444);
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444);
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444);
-HSMP_DEV_ATTR(pwr_current_active_freq_limit, HSMP_GET_SOCKET_FREQ_LIMIT,
-	      hsmp_freq_limit_show, 0444);
-HSMP_DEV_ATTR(pwr_current_active_freq_limit_source, HSMP_GET_SOCKET_FREQ_LIMIT,
-	      hsmp_freq_limit_source_show, 0444);
-
-static struct attribute *hsmp_dev_attr_list[] = {
-	&hattr_c0_residency_input.dattr.attr,
-	&hattr_prochot_status.dattr.attr,
-	&hattr_smu_fw_version.dattr.attr,
-	&hattr_protocol_version.dattr.attr,
-	&hattr_cclk_freq_limit_input.dattr.attr,
-	&hattr_ddr_max_bw.dattr.attr,
-	&hattr_ddr_utilised_bw_input.dattr.attr,
-	&hattr_ddr_utilised_bw_perc_input.dattr.attr,
-	&hattr_fclk_input.dattr.attr,
-	&hattr_mclk_input.dattr.attr,
-	&hattr_clk_fmax.dattr.attr,
-	&hattr_clk_fmin.dattr.attr,
-	&hattr_pwr_current_active_freq_limit.dattr.attr,
-	&hattr_pwr_current_active_freq_limit_source.dattr.attr,
-	NULL
-};
-
-static const struct attribute_group hsmp_attr_grp = {
-	.bin_attrs = hsmp_attr_list,
-	.attrs = hsmp_dev_attr_list,
-	.is_bin_visible = hsmp_is_sock_attr_visible,
-	.is_visible = hsmp_is_sock_dev_attr_visible,
-};
-
-static const struct attribute_group *hsmp_groups[] = {
-	&hsmp_attr_grp,
-	NULL
-};
-
 static const struct acpi_device_id amd_hsmp_acpi_ids[] = {
 	{ACPI_HSMP_DEVICE_HID, 0},
 	{}
@@ -793,7 +474,7 @@ static struct platform_driver amd_hsmp_driver = {
 	.driver		= {
 		.name	= DRIVER_NAME,
 		.acpi_match_table = amd_hsmp_acpi_ids,
-		.dev_groups = hsmp_groups,
+		.dev_groups = hsmp_sock_groups,
 	},
 };
 
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h
index 8dbff16a87b1..692721e2e6d3 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.h
+++ b/drivers/platform/x86/amd/hsmp/hsmp.h
@@ -80,6 +80,7 @@ int hsmp_create_sensor(struct device *dev, u16 sock_ind);
 static inline int hsmp_create_sensor(struct device *dev, u16 sock_ind) { return 0; }
 #endif
 int hsmp_msg_get_nargs(u16 sock_ind, u32 msg_id, u32 *data, u8 num_args);
+extern const struct attribute_group *hsmp_sock_groups[];
 
 /*
  * Gates the HSMP data plane: hsmp_send_message() takes it for read; probe and
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
new file mode 100644
index 000000000000..b1db3b4d77b9
--- /dev/null
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD HSMP sysfs support
+ * Copyright (c) 2024, AMD.
+ * All Rights Reserved.
+ *
+ * This file provides the per-socket sysfs attributes of the HSMP interface.
+ */
+
+#include <asm/amd/hsmp.h>
+
+#include <linux/array_size.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+
+#include "hsmp.h"
+
+struct hsmp_sys_attr {
+	struct device_attribute dattr;
+	u32 msg_id;
+};
+
+static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj,
+					 const struct bin_attribute *bin_attr, char *buf,
+					 loff_t off, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+
+	/*
+	 * metrics_bin is a sysfs binary attribute and is capped at PAGE_SIZE.
+	 * It can therefore only carry the protocol version 6 metric table
+	 * (struct hsmp_metric_table).  The larger tables defined from protocol
+	 * version 7 onwards do not fit; userspace on those systems must read
+	 * the snapshot through HSMP_IOCTL_GET_TELEMETRY_DATA on /dev/hsmp.
+	 * Surface the unsupported case here as -EOPNOTSUPP rather than
+	 * silently truncating the snapshot.
+	 */
+	if (get_hsmp_pdev()->proto_ver != HSMP_PROTO_VER6)
+		return -EOPNOTSUPP;
+
+	return hsmp_metric_tbl_read(sock, buf, count);
+}
+
+static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
+					 const struct bin_attribute *battr, int id)
+{
+	/*
+	 * Keep metrics_bin visible on protocol version 7 and later as well,
+	 * so that userspace which expects the file to exist gets a clear
+	 * -EOPNOTSUPP from the read handler instead of -ENOENT, and is
+	 * pointed at HSMP_IOCTL_GET_TELEMETRY_DATA as the supported path.
+	 */
+	if (get_hsmp_pdev()->proto_ver >= HSMP_PROTO_VER6)
+		return battr->attr.mode;
+
+	return 0;
+}
+
+static umode_t hsmp_is_sock_dev_attr_visible(struct kobject *kobj,
+					     struct attribute *attr, int id)
+{
+	return attr->mode;
+}
+
+#define to_hsmp_sys_attr(_attr) container_of(_attr, struct hsmp_sys_attr, dattr)
+
+static ssize_t hsmp_msg_resp32_show(struct device *dev, struct device_attribute *attr,
+				    char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", data);
+}
+
+#define DDR_MAX_BW_MASK		GENMASK(31, 20)
+#define DDR_UTIL_BW_MASK	GENMASK(19, 8)
+#define DDR_UTIL_BW_PERC_MASK	GENMASK(7, 0)
+#define FW_VER_MAJOR_MASK	GENMASK(23, 16)
+#define FW_VER_MINOR_MASK	GENMASK(15, 8)
+#define FW_VER_DEBUG_MASK	GENMASK(7, 0)
+#define FMAX_MASK		GENMASK(31, 16)
+#define FMIN_MASK		GENMASK(15, 0)
+#define FREQ_LIMIT_MASK		GENMASK(31, 16)
+#define FREQ_SRC_IND_MASK	GENMASK(15, 0)
+
+static ssize_t hsmp_ddr_max_bw_show(struct device *dev, struct device_attribute *attr,
+				    char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_MAX_BW_MASK, data));
+}
+
+static ssize_t hsmp_ddr_util_bw_show(struct device *dev, struct device_attribute *attr,
+				     char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_UTIL_BW_MASK, data));
+}
+
+static ssize_t hsmp_ddr_util_bw_perc_show(struct device *dev, struct device_attribute *attr,
+					  char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_UTIL_BW_PERC_MASK, data));
+}
+
+static ssize_t hsmp_msg_fw_ver_show(struct device *dev, struct device_attribute *attr,
+				    char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu.%lu.%lu\n",
+			  FIELD_GET(FW_VER_MAJOR_MASK, data),
+			  FIELD_GET(FW_VER_MINOR_MASK, data),
+			  FIELD_GET(FW_VER_DEBUG_MASK, data));
+}
+
+static ssize_t hsmp_fclk_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data[2];
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, data, 2);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", data[0]);
+}
+
+static ssize_t hsmp_mclk_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data[2];
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, data, 2);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", data[1]);
+}
+
+static ssize_t hsmp_clk_fmax_show(struct device *dev, struct device_attribute *attr,
+				  char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu\n", FIELD_GET(FMAX_MASK, data));
+}
+
+static ssize_t hsmp_clk_fmin_show(struct device *dev, struct device_attribute *attr,
+				  char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu\n", FIELD_GET(FMIN_MASK, data));
+}
+
+static ssize_t hsmp_freq_limit_show(struct device *dev, struct device_attribute *attr,
+				    char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu\n", FIELD_GET(FREQ_LIMIT_MASK, data));
+}
+
+static const char * const freqlimit_srcnames[] = {
+	"cHTC-Active",
+	"PROCHOT",
+	"TDC limit",
+	"PPT Limit",
+	"OPN Max",
+	"Reliability Limit",
+	"APML Agent",
+	"HSMP Agent",
+};
+
+static ssize_t hsmp_freq_limit_source_show(struct device *dev, struct device_attribute *attr,
+					   char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = dev_get_drvdata(dev);
+	unsigned int index;
+	int len = 0;
+	u16 src_ind;
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	src_ind = FIELD_GET(FREQ_SRC_IND_MASK, data);
+	for (index = 0; index < ARRAY_SIZE(freqlimit_srcnames); index++) {
+		if (!src_ind)
+			break;
+		if (src_ind & 1)
+			len += sysfs_emit_at(buf, len, "%s\n", freqlimit_srcnames[index]);
+		src_ind >>= 1;
+	}
+	return len;
+}
+
+static const struct bin_attribute  hsmp_metric_tbl_attr = {
+	.attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444},
+	.read = hsmp_metric_tbl_acpi_read,
+	.size = sizeof(struct hsmp_metric_table),
+};
+
+static const struct bin_attribute *hsmp_attr_list[] = {
+	&hsmp_metric_tbl_attr,
+	NULL
+};
+
+#define HSMP_DEV_ATTR(_name, _msg_id, _show, _mode)	\
+static struct hsmp_sys_attr hattr_##_name = {		\
+	.dattr = __ATTR(_name, _mode, _show, NULL),	\
+	.msg_id = _msg_id,				\
+}
+
+HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444);
+HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444);
+HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_perc_show, 0444);
+HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444);
+HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444);
+HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444);
+HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444);
+HSMP_DEV_ATTR(pwr_current_active_freq_limit, HSMP_GET_SOCKET_FREQ_LIMIT,
+	      hsmp_freq_limit_show, 0444);
+HSMP_DEV_ATTR(pwr_current_active_freq_limit_source, HSMP_GET_SOCKET_FREQ_LIMIT,
+	      hsmp_freq_limit_source_show, 0444);
+
+static struct attribute *hsmp_dev_attr_list[] = {
+	&hattr_c0_residency_input.dattr.attr,
+	&hattr_prochot_status.dattr.attr,
+	&hattr_smu_fw_version.dattr.attr,
+	&hattr_protocol_version.dattr.attr,
+	&hattr_cclk_freq_limit_input.dattr.attr,
+	&hattr_ddr_max_bw.dattr.attr,
+	&hattr_ddr_utilised_bw_input.dattr.attr,
+	&hattr_ddr_utilised_bw_perc_input.dattr.attr,
+	&hattr_fclk_input.dattr.attr,
+	&hattr_mclk_input.dattr.attr,
+	&hattr_clk_fmax.dattr.attr,
+	&hattr_clk_fmin.dattr.attr,
+	&hattr_pwr_current_active_freq_limit.dattr.attr,
+	&hattr_pwr_current_active_freq_limit_source.dattr.attr,
+	NULL
+};
+
+static const struct attribute_group hsmp_attr_grp = {
+	.bin_attrs = hsmp_attr_list,
+	.attrs = hsmp_dev_attr_list,
+	.is_bin_visible = hsmp_is_sock_attr_visible,
+	.is_visible = hsmp_is_sock_dev_attr_visible,
+};
+
+/*
+ * Per-socket attribute groups. Every show/read handler expects the drvdata of
+ * the device carrying the group to be the struct hsmp_socket it reports on.
+ */
+const struct attribute_group *hsmp_sock_groups[] = {
+	&hsmp_attr_grp,
+	NULL
+};
+EXPORT_SYMBOL_NS_GPL(hsmp_sock_groups, "AMD_HSMP");
-- 
2.53.0


  reply	other threads:[~2026-10-07 12:59 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-07 12:59 [PATCH 0/4] platform/x86/amd/hsmp: Unify per-socket sysfs metrics Erwan Velu
2026-10-07 12:59 ` Erwan Velu [this message]
2026-10-07 12:59 ` [PATCH 2/4] platform/x86/amd/hsmp: Add /sys/devices/amd_hsmp socket devices Erwan Velu
2026-10-07 12:59 ` [PATCH 3/4] platform/x86/amd/hsmp: Expose socket attributes from the platform driver Erwan Velu
2026-10-07 12:59 ` [PATCH 4/4] platform/x86/amd/hsmp: Add pwr_current_active_freq_limit_source_raw Erwan Velu

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=20261007125908.321186-2-erwanaliasr1@gmail.com \
    --to=erwanaliasr1@gmail.com \
    --cc=carlos.bilbao@kernel.org \
    --cc=hansg@kernel.org \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=naveenkrishna.chatradhi@amd.com \
    --cc=platform-driver-x86@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.