Skip to content

Commit d8eef04

Browse files
multics69rafaeljw
authored andcommitted
PM: EM: Implement em_nl_get_pds_doit()
When a userspace requests EM_CMD_GET_PDS, the kernel responds with information on all performance domains. The message format of the response is as follows: EM_A_PDS_PD (NLA_NESTED)* EM_A_PD_PD_ID (NLA_U32) EM_A_PD_FLAGS (NLA_U64) EM_A_PD_CPUS (NLA_STRING) where EM_A_PDS_PD can be repeated as many times as there are performance domains, and EM_A_PD_CPUS is a hexadecimal string representing a CPU bitmask. Signed-off-by: Changwoo Min <changwoo@igalia.com> Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> Link: https://patch.msgid.link/20251020220914.320832-7-changwoo@igalia.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 7928339 commit d8eef04

1 file changed

Lines changed: 81 additions & 1 deletion

File tree

kernel/power/em_netlink.c

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,89 @@
1717
#include "em_netlink.h"
1818
#include "em_netlink_autogen.h"
1919

20+
#define EM_A_PD_CPUS_LEN 256
21+
22+
/*************************** Command encoding ********************************/
23+
static int __em_nl_get_pd_size(struct em_perf_domain *pd, void *data)
24+
{
25+
char cpus_buf[EM_A_PD_CPUS_LEN];
26+
int *tot_msg_sz = data;
27+
int msg_sz, cpus_sz;
28+
29+
cpus_sz = snprintf(cpus_buf, sizeof(cpus_buf), "%*pb",
30+
cpumask_pr_args(to_cpumask(pd->cpus)));
31+
32+
msg_sz = nla_total_size(0) + /* EM_A_PDS_PD */
33+
nla_total_size(sizeof(u32)) + /* EM_A_PD_PD_ID */
34+
nla_total_size_64bit(sizeof(u64)) + /* EM_A_PD_FLAGS */
35+
nla_total_size(cpus_sz); /* EM_A_PD_CPUS */
36+
37+
*tot_msg_sz += nlmsg_total_size(genlmsg_msg_size(msg_sz));
38+
return 0;
39+
}
40+
41+
static int __em_nl_get_pd(struct em_perf_domain *pd, void *data)
42+
{
43+
char cpus_buf[EM_A_PD_CPUS_LEN];
44+
struct sk_buff *msg = data;
45+
struct nlattr *entry;
46+
47+
entry = nla_nest_start(msg, EM_A_PDS_PD);
48+
if (!entry)
49+
goto out_cancel_nest;
50+
51+
if (nla_put_u32(msg, EM_A_PD_PD_ID, pd->id))
52+
goto out_cancel_nest;
53+
54+
if (nla_put_u64_64bit(msg, EM_A_PD_FLAGS, pd->flags, EM_A_PD_PAD))
55+
goto out_cancel_nest;
56+
57+
snprintf(cpus_buf, sizeof(cpus_buf), "%*pb",
58+
cpumask_pr_args(to_cpumask(pd->cpus)));
59+
if (nla_put_string(msg, EM_A_PD_CPUS, cpus_buf))
60+
goto out_cancel_nest;
61+
62+
nla_nest_end(msg, entry);
63+
64+
return 0;
65+
66+
out_cancel_nest:
67+
nla_nest_cancel(msg, entry);
68+
69+
return -EMSGSIZE;
70+
}
71+
2072
int em_nl_get_pds_doit(struct sk_buff *skb, struct genl_info *info)
2173
{
22-
return -EOPNOTSUPP;
74+
struct sk_buff *msg;
75+
void *hdr;
76+
int cmd = info->genlhdr->cmd;
77+
int ret = -EMSGSIZE, msg_sz = 0;
78+
79+
for_each_em_perf_domain(__em_nl_get_pd_size, &msg_sz);
80+
81+
msg = genlmsg_new(msg_sz, GFP_KERNEL);
82+
if (!msg)
83+
return -ENOMEM;
84+
85+
hdr = genlmsg_put_reply(msg, info, &em_nl_family, 0, cmd);
86+
if (!hdr)
87+
goto out_free_msg;
88+
89+
ret = for_each_em_perf_domain(__em_nl_get_pd, msg);
90+
if (ret)
91+
goto out_cancel_msg;
92+
93+
genlmsg_end(msg, hdr);
94+
95+
return genlmsg_reply(msg, info);
96+
97+
out_cancel_msg:
98+
genlmsg_cancel(msg, hdr);
99+
out_free_msg:
100+
nlmsg_free(msg);
101+
102+
return ret;
23103
}
24104

25105
int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)

0 commit comments

Comments
 (0)