summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChangwoo Min <changwoo@igalia.com>2026-01-08 14:32:12 +0900
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2026-01-09 21:44:46 +0100
commit380ff27af25e49e2cb2ff8fd0ecd7c95be2976ee (patch)
tree65e0ab8aaf514046d3f688fc372d83805db6b600
parentd29b900cf412c31f18bab67d04db619f64acb43d (diff)
PM: EM: Add dump to get-perf-domains in the EM YNL spec
Add dump to get-perf-domains, so that a user can fetch either information about a specific performance domain with do or information about all performance domains with dump. Share the reply format of do and dump using perf-domain-attrs, so remove perf-domains. The YNL spec, autogenerated files, and the do implementation are updated, and the dump implementation is added. Suggested-by: Donald Hunter <donald.hunter@gmail.com> Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> Reviewed-by: Donald Hunter <donald.hunter@gmail.com> Signed-off-by: Changwoo Min <changwoo@igalia.com> Link: https://patch.msgid.link/20260108053212.642478-5-changwoo@igalia.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--Documentation/netlink/specs/dev-energymodel.yaml25
-rw-r--r--include/uapi/linux/dev_energymodel.h7
-rw-r--r--kernel/power/em_netlink.c68
-rw-r--r--kernel/power/em_netlink_autogen.c16
-rw-r--r--kernel/power/em_netlink_autogen.h2
5 files changed, 80 insertions, 38 deletions
diff --git a/Documentation/netlink/specs/dev-energymodel.yaml b/Documentation/netlink/specs/dev-energymodel.yaml
index af8b8f72f722..11faabfdfbe8 100644
--- a/Documentation/netlink/specs/dev-energymodel.yaml
+++ b/Documentation/netlink/specs/dev-energymodel.yaml
@@ -43,16 +43,6 @@ definitions:
attribute-sets:
-
- name: perf-domains
- doc: >-
- Information on all the performance domains.
- attributes:
- -
- name: perf-domain
- type: nest
- nested-attributes: perf-domain
- multi-attr: true
- -
name: perf-domain
doc: >-
Information on a single performance domains.
@@ -133,12 +123,21 @@ operations:
list:
-
name: get-perf-domains
- attribute-set: perf-domains
+ attribute-set: perf-domain
doc: Get the list of information for all performance domains.
do:
- reply:
+ request:
attributes:
- - perf-domain
+ - perf-domain-id
+ reply:
+ attributes: &perf-domain-attrs
+ - pad
+ - perf-domain-id
+ - flags
+ - cpus
+ dump:
+ reply:
+ attributes: *perf-domain-attrs
-
name: get-perf-table
attribute-set: perf-table
diff --git a/include/uapi/linux/dev_energymodel.h b/include/uapi/linux/dev_energymodel.h
index 3399967e1f93..355d8885c9a0 100644
--- a/include/uapi/linux/dev_energymodel.h
+++ b/include/uapi/linux/dev_energymodel.h
@@ -37,13 +37,6 @@ enum dev_energymodel_perf_domain_flags {
};
enum {
- DEV_ENERGYMODEL_A_PERF_DOMAINS_PERF_DOMAIN = 1,
-
- __DEV_ENERGYMODEL_A_PERF_DOMAINS_MAX,
- DEV_ENERGYMODEL_A_PERF_DOMAINS_MAX = (__DEV_ENERGYMODEL_A_PERF_DOMAINS_MAX - 1)
-};
-
-enum {
DEV_ENERGYMODEL_A_PERF_DOMAIN_PAD = 1,
DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID,
DEV_ENERGYMODEL_A_PERF_DOMAIN_FLAGS,
diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
index b6edb018c65a..5a611d3950fd 100644
--- a/kernel/power/em_netlink.c
+++ b/kernel/power/em_netlink.c
@@ -18,6 +18,13 @@
#include "em_netlink_autogen.h"
/*************************** Command encoding ********************************/
+struct dump_ctx {
+ int idx;
+ int start;
+ struct sk_buff *skb;
+ struct netlink_callback *cb;
+};
+
static int __em_nl_get_pd_size(struct em_perf_domain *pd, void *data)
{
int nr_cpus, msg_sz, cpus_sz;
@@ -43,14 +50,8 @@ static int __em_nl_get_pd(struct em_perf_domain *pd, void *data)
{
struct sk_buff *msg = data;
struct cpumask *cpumask;
- struct nlattr *entry;
int cpu;
- entry = nla_nest_start(msg,
- DEV_ENERGYMODEL_A_PERF_DOMAINS_PERF_DOMAIN);
- if (!entry)
- goto out_cancel_nest;
-
if (nla_put_u32(msg, DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID,
pd->id))
goto out_cancel_nest;
@@ -66,26 +67,50 @@ static int __em_nl_get_pd(struct em_perf_domain *pd, void *data)
goto out_cancel_nest;
}
- nla_nest_end(msg, entry);
-
return 0;
out_cancel_nest:
- nla_nest_cancel(msg, entry);
-
return -EMSGSIZE;
}
+static int __em_nl_get_pd_for_dump(struct em_perf_domain *pd, void *data)
+{
+ const struct genl_info *info;
+ struct dump_ctx *ctx = data;
+ void *hdr;
+ int ret;
+
+ if (ctx->idx++ < ctx->start)
+ return 0;
+
+ info = genl_info_dump(ctx->cb);
+ hdr = genlmsg_iput(ctx->skb, info);
+ if (!hdr) {
+ genlmsg_cancel(ctx->skb, hdr);
+ return -EMSGSIZE;
+ }
+
+ ret = __em_nl_get_pd(pd, ctx->skb);
+ genlmsg_end(ctx->skb, hdr);
+ return ret;
+}
+
int dev_energymodel_nl_get_perf_domains_doit(struct sk_buff *skb,
struct genl_info *info)
{
+ int id, ret = -EMSGSIZE, msg_sz = 0;
+ int cmd = info->genlhdr->cmd;
+ struct em_perf_domain *pd;
struct sk_buff *msg;
void *hdr;
- int cmd = info->genlhdr->cmd;
- int ret = -EMSGSIZE, msg_sz = 0;
- for_each_em_perf_domain(__em_nl_get_pd_size, &msg_sz);
+ if (!info->attrs[DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID])
+ return -EINVAL;
+ id = nla_get_u32(info->attrs[DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID]);
+ pd = em_perf_domain_get_by_id(id);
+
+ __em_nl_get_pd_size(pd, &msg_sz);
msg = genlmsg_new(msg_sz, GFP_KERNEL);
if (!msg)
return -ENOMEM;
@@ -94,10 +119,9 @@ int dev_energymodel_nl_get_perf_domains_doit(struct sk_buff *skb,
if (!hdr)
goto out_free_msg;
- ret = for_each_em_perf_domain(__em_nl_get_pd, msg);
+ ret = __em_nl_get_pd(pd, msg);
if (ret)
goto out_cancel_msg;
-
genlmsg_end(msg, hdr);
return genlmsg_reply(msg, info);
@@ -106,10 +130,22 @@ out_cancel_msg:
genlmsg_cancel(msg, hdr);
out_free_msg:
nlmsg_free(msg);
-
return ret;
}
+int dev_energymodel_nl_get_perf_domains_dumpit(struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct dump_ctx ctx = {
+ .idx = 0,
+ .start = cb->args[0],
+ .skb = skb,
+ .cb = cb,
+ };
+
+ return for_each_em_perf_domain(__em_nl_get_pd_for_dump, &ctx);
+}
+
static struct em_perf_domain *__em_nl_get_pd_table_id(struct nlattr **attrs)
{
struct em_perf_domain *pd;
diff --git a/kernel/power/em_netlink_autogen.c b/kernel/power/em_netlink_autogen.c
index 44acef0e7df2..fedd473e4244 100644
--- a/kernel/power/em_netlink_autogen.c
+++ b/kernel/power/em_netlink_autogen.c
@@ -11,6 +11,11 @@
#include <uapi/linux/dev_energymodel.h>
+/* DEV_ENERGYMODEL_CMD_GET_PERF_DOMAINS - do */
+static const struct nla_policy dev_energymodel_get_perf_domains_nl_policy[DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID + 1] = {
+ [DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID] = { .type = NLA_U32, },
+};
+
/* DEV_ENERGYMODEL_CMD_GET_PERF_TABLE - do */
static const struct nla_policy dev_energymodel_get_perf_table_nl_policy[DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID + 1] = {
[DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID] = { .type = NLA_U32, },
@@ -19,9 +24,16 @@ static const struct nla_policy dev_energymodel_get_perf_table_nl_policy[DEV_ENER
/* Ops table for dev_energymodel */
static const struct genl_split_ops dev_energymodel_nl_ops[] = {
{
+ .cmd = DEV_ENERGYMODEL_CMD_GET_PERF_DOMAINS,
+ .doit = dev_energymodel_nl_get_perf_domains_doit,
+ .policy = dev_energymodel_get_perf_domains_nl_policy,
+ .maxattr = DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID,
+ .flags = GENL_CMD_CAP_DO,
+ },
+ {
.cmd = DEV_ENERGYMODEL_CMD_GET_PERF_DOMAINS,
- .doit = dev_energymodel_nl_get_perf_domains_doit,
- .flags = GENL_CMD_CAP_DO,
+ .dumpit = dev_energymodel_nl_get_perf_domains_dumpit,
+ .flags = GENL_CMD_CAP_DUMP,
},
{
.cmd = DEV_ENERGYMODEL_CMD_GET_PERF_TABLE,
diff --git a/kernel/power/em_netlink_autogen.h b/kernel/power/em_netlink_autogen.h
index f7e4bddcbd53..5caf2f7e18a5 100644
--- a/kernel/power/em_netlink_autogen.h
+++ b/kernel/power/em_netlink_autogen.h
@@ -14,6 +14,8 @@
int dev_energymodel_nl_get_perf_domains_doit(struct sk_buff *skb,
struct genl_info *info);
+int dev_energymodel_nl_get_perf_domains_dumpit(struct sk_buff *skb,
+ struct netlink_callback *cb);
int dev_energymodel_nl_get_perf_table_doit(struct sk_buff *skb,
struct genl_info *info);