Skip to content

Commit 4810b76

Browse files
captain5050namhyung
authored andcommitted
perf hwmon_pmu: Add hwmon filename parser
hwmon filenames have a specific encoding that will be used to give a config value. The encoding is described in: Documentation/hwmon/sysfs-interface.rst Add a function to parse the filename into consituent enums/ints that will then be amenable to config encoding. Note, things are done this way to allow mapping names to config and back without the use of hash/dynamic lookup tables. Signed-off-by: Ian Rogers <[email protected]> Cc: Ravi Bangoria <[email protected]> Cc: Yoshihiro Furudera <[email protected]> Cc: Howard Chu <[email protected]> Cc: Ze Gao <[email protected]> Cc: Changbin Du <[email protected]> Cc: Junhao He <[email protected]> Cc: Weilin Wang <[email protected]> Cc: James Clark <[email protected]> Cc: Oliver Upton <[email protected]> Cc: Athira Jajeev <[email protected]> [namhyung: add #include <linux/string.h> for strlcpy()] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Namhyung Kim <[email protected]>
1 parent f4db95b commit 4810b76

File tree

3 files changed

+257
-0
lines changed

3 files changed

+257
-0
lines changed

tools/perf/util/Build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ perf-util-y += pmu.o
8383
perf-util-y += pmus.o
8484
perf-util-y += pmu-flex.o
8585
perf-util-y += pmu-bison.o
86+
perf-util-y += hwmon_pmu.o
8687
perf-util-y += tool_pmu.o
8788
perf-util-y += svghelper.o
8889
perf-util-$(CONFIG_LIBTRACEEVENT) += trace-event-info.o

tools/perf/util/hwmon_pmu.c

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2+
#include "debug.h"
3+
#include "hwmon_pmu.h"
4+
#include <assert.h>
5+
#include <stddef.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
#include <linux/kernel.h>
9+
#include <linux/string.h>
10+
11+
/** Strings that correspond to enum hwmon_type. */
12+
static const char * const hwmon_type_strs[HWMON_TYPE_MAX] = {
13+
NULL,
14+
"cpu",
15+
"curr",
16+
"energy",
17+
"fan",
18+
"humidity",
19+
"in",
20+
"intrusion",
21+
"power",
22+
"pwm",
23+
"temp",
24+
};
25+
#define LONGEST_HWMON_TYPE_STR "intrusion"
26+
27+
/** Strings that correspond to enum hwmon_item. */
28+
static const char * const hwmon_item_strs[HWMON_ITEM__MAX] = {
29+
NULL,
30+
"accuracy",
31+
"alarm",
32+
"auto_channels_temp",
33+
"average",
34+
"average_highest",
35+
"average_interval",
36+
"average_interval_max",
37+
"average_interval_min",
38+
"average_lowest",
39+
"average_max",
40+
"average_min",
41+
"beep",
42+
"cap",
43+
"cap_hyst",
44+
"cap_max",
45+
"cap_min",
46+
"crit",
47+
"crit_hyst",
48+
"div",
49+
"emergency",
50+
"emergency_hist",
51+
"enable",
52+
"fault",
53+
"freq",
54+
"highest",
55+
"input",
56+
"label",
57+
"lcrit",
58+
"lcrit_hyst",
59+
"lowest",
60+
"max",
61+
"max_hyst",
62+
"min",
63+
"min_hyst",
64+
"mod",
65+
"offset",
66+
"pulses",
67+
"rated_max",
68+
"rated_min",
69+
"reset_history",
70+
"target",
71+
"type",
72+
"vid",
73+
};
74+
#define LONGEST_HWMON_ITEM_STR "average_interval_max"
75+
76+
static int hwmon_strcmp(const void *a, const void *b)
77+
{
78+
const char *sa = a;
79+
const char * const *sb = b;
80+
81+
return strcmp(sa, *sb);
82+
}
83+
84+
bool parse_hwmon_filename(const char *filename,
85+
enum hwmon_type *type,
86+
int *number,
87+
enum hwmon_item *item,
88+
bool *alarm)
89+
{
90+
char fn_type[24];
91+
const char **elem;
92+
const char *fn_item = NULL;
93+
size_t fn_item_len;
94+
95+
assert(strlen(LONGEST_HWMON_TYPE_STR) < sizeof(fn_type));
96+
strlcpy(fn_type, filename, sizeof(fn_type));
97+
for (size_t i = 0; fn_type[i] != '\0'; i++) {
98+
if (fn_type[i] >= '0' && fn_type[i] <= '9') {
99+
fn_type[i] = '\0';
100+
*number = strtoul(&filename[i], (char **)&fn_item, 10);
101+
if (*fn_item == '_')
102+
fn_item++;
103+
break;
104+
}
105+
if (fn_type[i] == '_') {
106+
fn_type[i] = '\0';
107+
*number = -1;
108+
fn_item = &filename[i + 1];
109+
break;
110+
}
111+
}
112+
if (fn_item == NULL || fn_type[0] == '\0' || (item != NULL && fn_item[0] == '\0')) {
113+
pr_debug("hwmon_pmu: not a hwmon file '%s'\n", filename);
114+
return false;
115+
}
116+
elem = bsearch(&fn_type, hwmon_type_strs + 1, ARRAY_SIZE(hwmon_type_strs) - 1,
117+
sizeof(hwmon_type_strs[0]), hwmon_strcmp);
118+
if (!elem) {
119+
pr_debug("hwmon_pmu: not a hwmon type '%s' in file name '%s'\n",
120+
fn_type, filename);
121+
return false;
122+
}
123+
124+
*type = elem - &hwmon_type_strs[0];
125+
if (!item)
126+
return true;
127+
128+
*alarm = false;
129+
fn_item_len = strlen(fn_item);
130+
if (fn_item_len > 6 && !strcmp(&fn_item[fn_item_len - 6], "_alarm")) {
131+
assert(strlen(LONGEST_HWMON_ITEM_STR) < sizeof(fn_type));
132+
strlcpy(fn_type, fn_item, fn_item_len - 5);
133+
fn_item = fn_type;
134+
*alarm = true;
135+
}
136+
elem = bsearch(fn_item, hwmon_item_strs + 1, ARRAY_SIZE(hwmon_item_strs) - 1,
137+
sizeof(hwmon_item_strs[0]), hwmon_strcmp);
138+
if (!elem) {
139+
pr_debug("hwmon_pmu: not a hwmon item '%s' in file name '%s'\n",
140+
fn_item, filename);
141+
return false;
142+
}
143+
*item = elem - &hwmon_item_strs[0];
144+
return true;
145+
}

tools/perf/util/hwmon_pmu.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2+
#ifndef __HWMON_PMU_H
3+
#define __HWMON_PMU_H
4+
5+
#include <stdbool.h>
6+
7+
/**
8+
* enum hwmon_type:
9+
*
10+
* As described in Documentation/hwmon/sysfs-interface.rst hwmon events are
11+
* defined over multiple files of the form <type><num>_<item>. This enum
12+
* captures potential <type> values.
13+
*
14+
* This enum is exposed for testing.
15+
*/
16+
enum hwmon_type {
17+
HWMON_TYPE_NONE,
18+
19+
HWMON_TYPE_CPU,
20+
HWMON_TYPE_CURR,
21+
HWMON_TYPE_ENERGY,
22+
HWMON_TYPE_FAN,
23+
HWMON_TYPE_HUMIDITY,
24+
HWMON_TYPE_IN,
25+
HWMON_TYPE_INTRUSION,
26+
HWMON_TYPE_POWER,
27+
HWMON_TYPE_PWM,
28+
HWMON_TYPE_TEMP,
29+
30+
HWMON_TYPE_MAX
31+
};
32+
33+
/**
34+
* enum hwmon_item:
35+
*
36+
* Similar to enum hwmon_type but describes the item part of a a sysfs filename.
37+
*
38+
* This enum is exposed for testing.
39+
*/
40+
enum hwmon_item {
41+
HWMON_ITEM_NONE,
42+
43+
HWMON_ITEM_ACCURACY,
44+
HWMON_ITEM_ALARM,
45+
HWMON_ITEM_AUTO_CHANNELS_TEMP,
46+
HWMON_ITEM_AVERAGE,
47+
HWMON_ITEM_AVERAGE_HIGHEST,
48+
HWMON_ITEM_AVERAGE_INTERVAL,
49+
HWMON_ITEM_AVERAGE_INTERVAL_MAX,
50+
HWMON_ITEM_AVERAGE_INTERVAL_MIN,
51+
HWMON_ITEM_AVERAGE_LOWEST,
52+
HWMON_ITEM_AVERAGE_MAX,
53+
HWMON_ITEM_AVERAGE_MIN,
54+
HWMON_ITEM_BEEP,
55+
HWMON_ITEM_CAP,
56+
HWMON_ITEM_CAP_HYST,
57+
HWMON_ITEM_CAP_MAX,
58+
HWMON_ITEM_CAP_MIN,
59+
HWMON_ITEM_CRIT,
60+
HWMON_ITEM_CRIT_HYST,
61+
HWMON_ITEM_DIV,
62+
HWMON_ITEM_EMERGENCY,
63+
HWMON_ITEM_EMERGENCY_HIST,
64+
HWMON_ITEM_ENABLE,
65+
HWMON_ITEM_FAULT,
66+
HWMON_ITEM_FREQ,
67+
HWMON_ITEM_HIGHEST,
68+
HWMON_ITEM_INPUT,
69+
HWMON_ITEM_LABEL,
70+
HWMON_ITEM_LCRIT,
71+
HWMON_ITEM_LCRIT_HYST,
72+
HWMON_ITEM_LOWEST,
73+
HWMON_ITEM_MAX,
74+
HWMON_ITEM_MAX_HYST,
75+
HWMON_ITEM_MIN,
76+
HWMON_ITEM_MIN_HYST,
77+
HWMON_ITEM_MOD,
78+
HWMON_ITEM_OFFSET,
79+
HWMON_ITEM_PULSES,
80+
HWMON_ITEM_RATED_MAX,
81+
HWMON_ITEM_RATED_MIN,
82+
HWMON_ITEM_RESET_HISTORY,
83+
HWMON_ITEM_TARGET,
84+
HWMON_ITEM_TYPE,
85+
HWMON_ITEM_VID,
86+
87+
HWMON_ITEM__MAX,
88+
};
89+
90+
/**
91+
* parse_hwmon_filename() - Parse filename into constituent parts.
92+
*
93+
* @filename: To be parsed, of the form <type><number>_<item>.
94+
* @type: The type defined from the parsed file name.
95+
* @number: The number of the type, for example there may be more than 1 fan.
96+
* @item: A hwmon <type><number> may have multiple associated items.
97+
* @alarm: Is the filename for an alarm value?
98+
*
99+
* An example of a hwmon filename is "temp1_input". The type is temp for a
100+
* temperature value. The number is 1. The item within the file is an input
101+
* value - the temperature itself. This file doesn't contain an alarm value.
102+
*
103+
* Exposed for testing.
104+
*/
105+
bool parse_hwmon_filename(const char *filename,
106+
enum hwmon_type *type,
107+
int *number,
108+
enum hwmon_item *item,
109+
bool *alarm);
110+
111+
#endif /* __HWMON_PMU_H */

0 commit comments

Comments
 (0)