[PATCH for 6.19 4/4] PM: EM: Add dump to get-perf-domains in the EM YNL spec

Changwoo Min posted 4 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH for 6.19 4/4] PM: EM: Add dump to get-perf-domains in the EM YNL spec
Posted by Changwoo Min 1 month, 2 weeks ago
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. 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>
Signed-off-by: Changwoo Min <changwoo@igalia.com>
---
 .../netlink/specs/dev-energymodel.yaml        | 12 ++++
 include/uapi/linux/dev_energymodel.h          |  3 +-
 kernel/power/em_netlink.c                     | 58 +++++++++++++++++--
 kernel/power/em_netlink_autogen.c             | 16 ++++-
 kernel/power/em_netlink_autogen.h             |  2 +
 5 files changed, 82 insertions(+), 9 deletions(-)

diff --git a/Documentation/netlink/specs/dev-energymodel.yaml b/Documentation/netlink/specs/dev-energymodel.yaml
index af8b8f72f722..1843e68faacf 100644
--- a/Documentation/netlink/specs/dev-energymodel.yaml
+++ b/Documentation/netlink/specs/dev-energymodel.yaml
@@ -47,6 +47,11 @@ attribute-sets:
     doc: >-
       Information on all the performance domains.
     attributes:
+      -
+        name: perf-domain-id
+        type: u32
+        doc: >-
+          A unique ID number for each performance domain.
       -
         name: perf-domain
         type: nest
@@ -136,6 +141,13 @@ operations:
       attribute-set: perf-domains
       doc: Get the list of information for all performance domains.
       do:
+        request:
+          attributes:
+            - perf-domain-id
+        reply:
+          attributes:
+            - perf-domain
+      dump:
         reply:
           attributes:
             - perf-domain
diff --git a/include/uapi/linux/dev_energymodel.h b/include/uapi/linux/dev_energymodel.h
index 3399967e1f93..e8e133b5a797 100644
--- a/include/uapi/linux/dev_energymodel.h
+++ b/include/uapi/linux/dev_energymodel.h
@@ -37,7 +37,8 @@ enum dev_energymodel_perf_domain_flags {
 };
 
 enum {
-	DEV_ENERGYMODEL_A_PERF_DOMAINS_PERF_DOMAIN = 1,
+	DEV_ENERGYMODEL_A_PERF_DOMAINS_PERF_DOMAIN_ID = 1,
+	DEV_ENERGYMODEL_A_PERF_DOMAINS_PERF_DOMAIN,
 
 	__DEV_ENERGYMODEL_A_PERF_DOMAINS_MAX,
 	DEV_ENERGYMODEL_A_PERF_DOMAINS_MAX = (__DEV_ENERGYMODEL_A_PERF_DOMAINS_MAX - 1)
diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
index b6edb018c65a..9412f1666007 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;
@@ -76,16 +83,44 @@ static int __em_nl_get_pd(struct em_perf_domain *pd, void *data)
 	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_DOMAINS_PERF_DOMAIN_ID])
+		return -EINVAL;
+
+	id = nla_get_u32(info->attrs[DEV_ENERGYMODEL_A_PERF_DOMAINS_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 +129,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 +140,22 @@ int dev_energymodel_nl_get_perf_domains_doit(struct sk_buff *skb,
 	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..16a59200c6a4 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_DOMAINS_PERF_DOMAIN_ID + 1] = {
+	[DEV_ENERGYMODEL_A_PERF_DOMAINS_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, },
@@ -18,10 +23,17 @@ 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_DOMAINS_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);
 
-- 
2.52.0
Re: [PATCH for 6.19 4/4] PM: EM: Add dump to get-perf-domains in the EM YNL spec
Posted by Donald Hunter 1 month ago
Changwoo Min <changwoo@igalia.com> writes:

> 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. 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>
> Signed-off-by: Changwoo Min <changwoo@igalia.com>
> ---
>  .../netlink/specs/dev-energymodel.yaml        | 12 ++++
>  include/uapi/linux/dev_energymodel.h          |  3 +-
>  kernel/power/em_netlink.c                     | 58 +++++++++++++++++--
>  kernel/power/em_netlink_autogen.c             | 16 ++++-
>  kernel/power/em_netlink_autogen.h             |  2 +
>  5 files changed, 82 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/netlink/specs/dev-energymodel.yaml b/Documentation/netlink/specs/dev-energymodel.yaml
> index af8b8f72f722..1843e68faacf 100644
> --- a/Documentation/netlink/specs/dev-energymodel.yaml
> +++ b/Documentation/netlink/specs/dev-energymodel.yaml
> @@ -47,6 +47,11 @@ attribute-sets:
>      doc: >-
>        Information on all the performance domains.
>      attributes:
> +      -
> +        name: perf-domain-id
> +        type: u32
> +        doc: >-
> +          A unique ID number for each performance domain.
>        -
>          name: perf-domain
>          type: nest
> @@ -136,6 +141,13 @@ operations:
>        attribute-set: perf-domains

I think this can be changed to 'perf-domain' and you could remove
the 'perf-domains' attribute-set.

>        doc: Get the list of information for all performance domains.
>        do:
> +        request:
> +          attributes:
> +            - perf-domain-id
> +        reply:
> +          attributes:
> +            - perf-domain

If you use 'perf-domain' then the reply attributes would be:

  reply:
    attributes: &perf-domain-attrs
      - pad
      - perf-domain-id
      - flags
      - cpus

> +      dump:
>          reply:
>            attributes:
>              - perf-domain

You can then change the dump reply to be:

  dump:
    reply:
      attributes: *perf-domain-attrs

The dump reply for multiple perf domains would then look like this, no
need for the 'perf-domains' wrapper:

[{'perf-domain-id': ...,
  'flags': ...,
  'cpus': [1, 2, 3]},
 {'perf-domain-id': ...,
  'flags': ...,
  'cpus': [1, 2, 3]}]
Re: [PATCH for 6.19 4/4] PM: EM: Add dump to get-perf-domains in the EM YNL spec
Posted by Changwoo Min 1 month ago
Hi Donald,

On 1/5/26 8:19 PM, Donald Hunter wrote:
> Changwoo Min <changwoo@igalia.com> writes:
> 
>> 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. 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>
>> Signed-off-by: Changwoo Min <changwoo@igalia.com>
>> ---
>>   .../netlink/specs/dev-energymodel.yaml        | 12 ++++
>>   include/uapi/linux/dev_energymodel.h          |  3 +-
>>   kernel/power/em_netlink.c                     | 58 +++++++++++++++++--
>>   kernel/power/em_netlink_autogen.c             | 16 ++++-
>>   kernel/power/em_netlink_autogen.h             |  2 +
>>   5 files changed, 82 insertions(+), 9 deletions(-)
>>
>> diff --git a/Documentation/netlink/specs/dev-energymodel.yaml b/Documentation/netlink/specs/dev-energymodel.yaml
>> index af8b8f72f722..1843e68faacf 100644
>> --- a/Documentation/netlink/specs/dev-energymodel.yaml
>> +++ b/Documentation/netlink/specs/dev-energymodel.yaml
>> @@ -47,6 +47,11 @@ attribute-sets:
>>       doc: >-
>>         Information on all the performance domains.
>>       attributes:
>> +      -
>> +        name: perf-domain-id
>> +        type: u32
>> +        doc: >-
>> +          A unique ID number for each performance domain.
>>         -
>>           name: perf-domain
>>           type: nest
>> @@ -136,6 +141,13 @@ operations:
>>         attribute-set: perf-domains
> 
> I think this can be changed to 'perf-domain' and you could remove
> the 'perf-domains' attribute-set.
> 
>>         doc: Get the list of information for all performance domains.
>>         do:
>> +        request:
>> +          attributes:
>> +            - perf-domain-id
>> +        reply:
>> +          attributes:
>> +            - perf-domain
> 
> If you use 'perf-domain' then the reply attributes would be:
> 
>    reply:
>      attributes: &perf-domain-attrs
>        - pad
>        - perf-domain-id
>        - flags
>        - cpus
> 
>> +      dump:
>>           reply:
>>             attributes:
>>               - perf-domain
> 
> You can then change the dump reply to be:
> 
>    dump:
>      reply:
>        attributes: *perf-domain-attrs
> 
> The dump reply for multiple perf domains would then look like this, no
> need for the 'perf-domains' wrapper:
> 
> [{'perf-domain-id': ...,
>    'flags': ...,
>    'cpus': [1, 2, 3]},
>   {'perf-domain-id': ...,
>    'flags': ...,
>    'cpus': [1, 2, 3]}]
> 

Thank you for the suggestion. I will send v2 soon with your suggested 
changes.

Regards,
Changwoo Min