Skip to content

Commit 511a4a5

Browse files
sumachidanandij-intel
authored andcommitted
platform/x86/amd/hsmp: acpi: Add sysfs files to display HSMP telemetry
Make frequently fetched telemetry available via sysfs. These parameters do not fit in hwmon sensor model, hence make them available via sysfs. Create following sysfs files per acpi device node. * c0_residency_input * prochot_status * smu_fw_version * protocol_version * ddr_max_bw(GB/s) * ddr_utilised_bw_input(GB/s) * ddr_utilised_bw_perc_input(%) * mclk_input(MHz) * fclk_input(MHz) * clk_fmax(MHz) * clk_fmin(MHz) * cclk_freq_limit_input(MHz) * pwr_current_active_freq_limit(MHz) * pwr_current_active_freq_limit_source Signed-off-by: Suma Hegde <[email protected]> Reviewed-by: Naveen Krishna Chatradhi <[email protected]> Reviewed-by: Ilpo Järvinen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ilpo Järvinen <[email protected]>
1 parent 92c025d commit 511a4a5

File tree

4 files changed

+308
-0
lines changed

4 files changed

+308
-0
lines changed

Documentation/arch/x86/amd_hsmp.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,28 @@ Note: lseek() is not supported as entire metrics table is read.
7171
Metrics table definitions will be documented as part of Public PPR.
7272
The same is defined in the amd_hsmp.h header.
7373

74+
2. HSMP telemetry sysfs files
75+
76+
Following sysfs files are available at /sys/devices/platform/AMDI0097:0X/.
77+
78+
* c0_residency_input: Percentage of cores in C0 state.
79+
* prochot_status: Reports 1 if the processor is at thermal threshold value,
80+
0 otherwise.
81+
* smu_fw_version: SMU firmware version.
82+
* protocol_version: HSMP interface version.
83+
* ddr_max_bw: Theoretical maximum DDR bandwidth in GB/s.
84+
* ddr_utilised_bw_input: Current utilized DDR bandwidth in GB/s.
85+
* ddr_utilised_bw_perc_input(%): Percentage of current utilized DDR bandwidth.
86+
* mclk_input: Memory clock in MHz.
87+
* fclk_input: Fabric clock in MHz.
88+
* clk_fmax: Maximum frequency of socket in MHz.
89+
* clk_fmin: Minimum frequency of socket in MHz.
90+
* cclk_freq_limit_input: Core clock frequency limit per socket in MHz.
91+
* pwr_current_active_freq_limit: Current active frequency limit of socket
92+
in MHz.
93+
* pwr_current_active_freq_limit_source: Source of current active frequency
94+
limit.
95+
7496
ACPI device object format
7597
=========================
7698
The ACPI object format expected from the amd_hsmp driver

drivers/platform/x86/amd/hsmp/acpi.c

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <asm/amd_hsmp.h>
1313

1414
#include <linux/acpi.h>
15+
#include <linux/array_size.h>
16+
#include <linux/bits.h>
17+
#include <linux/bitfield.h>
1518
#include <linux/device.h>
1619
#include <linux/dev_printk.h>
1720
#include <linux/ioport.h>
@@ -36,6 +39,11 @@
3639

3740
static struct hsmp_plat_device *hsmp_pdev;
3841

42+
struct hsmp_sys_attr {
43+
struct device_attribute dattr;
44+
u32 msg_id;
45+
};
46+
3947
static int amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
4048
u32 *value, bool write)
4149
{
@@ -243,6 +251,215 @@ static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
243251
return 0;
244252
}
245253

254+
static umode_t hsmp_is_sock_dev_attr_visible(struct kobject *kobj,
255+
struct attribute *attr, int id)
256+
{
257+
return attr->mode;
258+
}
259+
260+
#define to_hsmp_sys_attr(_attr) container_of(_attr, struct hsmp_sys_attr, dattr)
261+
262+
static ssize_t hsmp_msg_resp32_show(struct device *dev, struct device_attribute *attr,
263+
char *buf)
264+
{
265+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
266+
struct hsmp_socket *sock = dev_get_drvdata(dev);
267+
u32 data;
268+
int ret;
269+
270+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
271+
if (ret)
272+
return ret;
273+
274+
return sysfs_emit(buf, "%u\n", data);
275+
}
276+
277+
#define DDR_MAX_BW_MASK GENMASK(31, 20)
278+
#define DDR_UTIL_BW_MASK GENMASK(19, 8)
279+
#define DDR_UTIL_BW_PERC_MASK GENMASK(7, 0)
280+
#define FW_VER_MAJOR_MASK GENMASK(23, 16)
281+
#define FW_VER_MINOR_MASK GENMASK(15, 8)
282+
#define FW_VER_DEBUG_MASK GENMASK(7, 0)
283+
#define FMAX_MASK GENMASK(31, 16)
284+
#define FMIN_MASK GENMASK(15, 0)
285+
#define FREQ_LIMIT_MASK GENMASK(31, 16)
286+
#define FREQ_SRC_IND_MASK GENMASK(15, 0)
287+
288+
static ssize_t hsmp_ddr_max_bw_show(struct device *dev, struct device_attribute *attr,
289+
char *buf)
290+
{
291+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
292+
struct hsmp_socket *sock = dev_get_drvdata(dev);
293+
u32 data;
294+
int ret;
295+
296+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
297+
if (ret)
298+
return ret;
299+
300+
return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_MAX_BW_MASK, data));
301+
}
302+
303+
static ssize_t hsmp_ddr_util_bw_show(struct device *dev, struct device_attribute *attr,
304+
char *buf)
305+
{
306+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
307+
struct hsmp_socket *sock = dev_get_drvdata(dev);
308+
u32 data;
309+
int ret;
310+
311+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
312+
if (ret)
313+
return ret;
314+
315+
return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_UTIL_BW_MASK, data));
316+
}
317+
318+
static ssize_t hsmp_ddr_util_bw_perc_show(struct device *dev, struct device_attribute *attr,
319+
char *buf)
320+
{
321+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
322+
struct hsmp_socket *sock = dev_get_drvdata(dev);
323+
u32 data;
324+
int ret;
325+
326+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
327+
if (ret)
328+
return ret;
329+
330+
return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_UTIL_BW_PERC_MASK, data));
331+
}
332+
333+
static ssize_t hsmp_msg_fw_ver_show(struct device *dev, struct device_attribute *attr,
334+
char *buf)
335+
{
336+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
337+
struct hsmp_socket *sock = dev_get_drvdata(dev);
338+
u32 data;
339+
int ret;
340+
341+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
342+
if (ret)
343+
return ret;
344+
345+
return sysfs_emit(buf, "%lu.%lu.%lu\n",
346+
FIELD_GET(FW_VER_MAJOR_MASK, data),
347+
FIELD_GET(FW_VER_MINOR_MASK, data),
348+
FIELD_GET(FW_VER_DEBUG_MASK, data));
349+
}
350+
351+
static ssize_t hsmp_fclk_show(struct device *dev, struct device_attribute *attr,
352+
char *buf)
353+
{
354+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
355+
struct hsmp_socket *sock = dev_get_drvdata(dev);
356+
u32 data[2];
357+
int ret;
358+
359+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, data, 2);
360+
if (ret)
361+
return ret;
362+
363+
return sysfs_emit(buf, "%u\n", data[0]);
364+
}
365+
366+
static ssize_t hsmp_mclk_show(struct device *dev, struct device_attribute *attr,
367+
char *buf)
368+
{
369+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
370+
struct hsmp_socket *sock = dev_get_drvdata(dev);
371+
u32 data[2];
372+
int ret;
373+
374+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, data, 2);
375+
if (ret)
376+
return ret;
377+
378+
return sysfs_emit(buf, "%u\n", data[1]);
379+
}
380+
381+
static ssize_t hsmp_clk_fmax_show(struct device *dev, struct device_attribute *attr,
382+
char *buf)
383+
{
384+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
385+
struct hsmp_socket *sock = dev_get_drvdata(dev);
386+
u32 data;
387+
int ret;
388+
389+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
390+
if (ret)
391+
return ret;
392+
393+
return sysfs_emit(buf, "%lu\n", FIELD_GET(FMAX_MASK, data));
394+
}
395+
396+
static ssize_t hsmp_clk_fmin_show(struct device *dev, struct device_attribute *attr,
397+
char *buf)
398+
{
399+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
400+
struct hsmp_socket *sock = dev_get_drvdata(dev);
401+
u32 data;
402+
int ret;
403+
404+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
405+
if (ret)
406+
return ret;
407+
408+
return sysfs_emit(buf, "%lu\n", FIELD_GET(FMIN_MASK, data));
409+
}
410+
411+
static ssize_t hsmp_freq_limit_show(struct device *dev, struct device_attribute *attr,
412+
char *buf)
413+
{
414+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
415+
struct hsmp_socket *sock = dev_get_drvdata(dev);
416+
u32 data;
417+
int ret;
418+
419+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
420+
if (ret)
421+
return ret;
422+
423+
return sysfs_emit(buf, "%lu\n", FIELD_GET(FREQ_LIMIT_MASK, data));
424+
}
425+
426+
static const char * const freqlimit_srcnames[] = {
427+
"cHTC-Active",
428+
"PROCHOT",
429+
"TDC limit",
430+
"PPT Limit",
431+
"OPN Max",
432+
"Reliability Limit",
433+
"APML Agent",
434+
"HSMP Agent",
435+
};
436+
437+
static ssize_t hsmp_freq_limit_source_show(struct device *dev, struct device_attribute *attr,
438+
char *buf)
439+
{
440+
struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
441+
struct hsmp_socket *sock = dev_get_drvdata(dev);
442+
unsigned int index;
443+
int len = 0;
444+
u16 src_ind;
445+
u32 data;
446+
int ret;
447+
448+
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
449+
if (ret)
450+
return ret;
451+
452+
src_ind = FIELD_GET(FREQ_SRC_IND_MASK, data);
453+
for (index = 0; index < ARRAY_SIZE(freqlimit_srcnames); index++) {
454+
if (!src_ind)
455+
break;
456+
if (src_ind & 1)
457+
len += sysfs_emit_at(buf, len, "%s\n", freqlimit_srcnames[index]);
458+
src_ind >>= 1;
459+
}
460+
return len;
461+
}
462+
246463
static int init_acpi(struct device *dev)
247464
{
248465
u16 sock_ind;
@@ -285,6 +502,8 @@ static int init_acpi(struct device *dev)
285502
if (ret)
286503
dev_err(dev, "Failed to register HSMP sensors with hwmon\n");
287504

505+
dev_set_drvdata(dev, &hsmp_pdev->sock[sock_ind]);
506+
288507
return ret;
289508
}
290509

@@ -299,9 +518,52 @@ static const struct bin_attribute *hsmp_attr_list[] = {
299518
NULL
300519
};
301520

521+
#define HSMP_DEV_ATTR(_name, _msg_id, _show, _mode) \
522+
static struct hsmp_sys_attr hattr_##_name = { \
523+
.dattr = __ATTR(_name, _mode, _show, NULL), \
524+
.msg_id = _msg_id, \
525+
}
526+
527+
HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444);
528+
HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444);
529+
HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444);
530+
HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444);
531+
HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444);
532+
HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444);
533+
HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444);
534+
HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_perc_show, 0444);
535+
HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444);
536+
HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444);
537+
HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444);
538+
HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444);
539+
HSMP_DEV_ATTR(pwr_current_active_freq_limit, HSMP_GET_SOCKET_FREQ_LIMIT,
540+
hsmp_freq_limit_show, 0444);
541+
HSMP_DEV_ATTR(pwr_current_active_freq_limit_source, HSMP_GET_SOCKET_FREQ_LIMIT,
542+
hsmp_freq_limit_source_show, 0444);
543+
544+
static struct attribute *hsmp_dev_attr_list[] = {
545+
&hattr_c0_residency_input.dattr.attr,
546+
&hattr_prochot_status.dattr.attr,
547+
&hattr_smu_fw_version.dattr.attr,
548+
&hattr_protocol_version.dattr.attr,
549+
&hattr_cclk_freq_limit_input.dattr.attr,
550+
&hattr_ddr_max_bw.dattr.attr,
551+
&hattr_ddr_utilised_bw_input.dattr.attr,
552+
&hattr_ddr_utilised_bw_perc_input.dattr.attr,
553+
&hattr_fclk_input.dattr.attr,
554+
&hattr_mclk_input.dattr.attr,
555+
&hattr_clk_fmax.dattr.attr,
556+
&hattr_clk_fmin.dattr.attr,
557+
&hattr_pwr_current_active_freq_limit.dattr.attr,
558+
&hattr_pwr_current_active_freq_limit_source.dattr.attr,
559+
NULL
560+
};
561+
302562
static const struct attribute_group hsmp_attr_grp = {
303563
.bin_attrs_new = hsmp_attr_list,
564+
.attrs = hsmp_dev_attr_list,
304565
.is_bin_visible = hsmp_is_sock_attr_visible,
566+
.is_visible = hsmp_is_sock_dev_attr_visible,
305567
};
306568

307569
static const struct attribute_group *hsmp_groups[] = {

drivers/platform/x86/amd/hsmp/hsmp.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,29 @@ int hsmp_send_message(struct hsmp_message *msg)
228228
}
229229
EXPORT_SYMBOL_NS_GPL(hsmp_send_message, "AMD_HSMP");
230230

231+
int hsmp_msg_get_nargs(u16 sock_ind, u32 msg_id, u32 *data, u8 num_args)
232+
{
233+
struct hsmp_message msg = {};
234+
unsigned int i;
235+
int ret;
236+
237+
if (!data)
238+
return -EINVAL;
239+
msg.msg_id = msg_id;
240+
msg.sock_ind = sock_ind;
241+
msg.response_sz = num_args;
242+
243+
ret = hsmp_send_message(&msg);
244+
if (ret)
245+
return ret;
246+
247+
for (i = 0; i < num_args; i++)
248+
data[i] = msg.args[i];
249+
250+
return 0;
251+
}
252+
EXPORT_SYMBOL_NS_GPL(hsmp_msg_get_nargs, "AMD_HSMP");
253+
231254
int hsmp_test(u16 sock_ind, u32 value)
232255
{
233256
struct hsmp_message msg = { 0 };

drivers/platform/x86/amd/hsmp/hsmp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,5 @@ int hsmp_create_sensor(struct device *dev, u16 sock_ind);
6969
#else
7070
static inline int hsmp_create_sensor(struct device *dev, u16 sock_ind) { return 0; }
7171
#endif
72+
int hsmp_msg_get_nargs(u16 sock_ind, u32 msg_id, u32 *data, u8 num_args);
7273
#endif /* HSMP_H */

0 commit comments

Comments
 (0)