linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/10] PM: EM: Add netlink support for the energy model
@ 2025-10-14  0:10 Changwoo Min
  2025-10-14  0:10 ` [PATCH v5 01/10] PM: EM: Assign a unique ID when creating a performance domain Changwoo Min
                   ` (10 more replies)
  0 siblings, 11 replies; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

Addressed all the comments from Lukasz and rebased the code to the head
of the linus tree.

There is a need to access the energy model from the userspace. One such
example is the sched_ext schedulers [1]. The userspace part of the
sched_ext schedules could feed the (post-processed) energy-model
information to the BPF part of the scheduler.

Currently, debugfs is the only way to read the energy model from userspace;
however, it lacks proper notification mechanisms when a performance domain
and its associated energy model change.

This patch set introduces a generic netlink for the energy model, as
discussed in [2]. It allows a userspace program to read the performance
domain and its energy model. It notifies the userspace program when a
performance domain is created or deleted or its energy model is updated
through a multicast interface.

Specifically, it supports two commands:
  - EM_CMD_GET_PDS: Get the list of information for all performance
    domains.
  - EM_CMD_GET_PD_TABLE: Get the energy model table of a performance
    domain.

Also, it supports three notification events:
  - EM_CMD_PD_CREATED: When a performance domain is created.
  - EM_CMD_PD_DELETED: When a performance domain is deleted.
  - EM_CMD_PD_UPDATED: When the energy model table of a performance domain
    is updated.

This can be tested using the tool, tools/net/ynl/pyynl/cli.py, for example,
with the following commands:

  $> tools/net/ynl/pyynl/cli.py \
     --spec Documentation/netlink/specs/em.yaml \
     --do get-pds
  $> tools/net/ynl/pyynl/cli.py \
     --spec Documentation/netlink/specs/em.yaml \
     --do get-pd-table --json '{"pd-id": 0}'
  $> tools/net/ynl/pyynl/cli.py \
     --spec Documentation/netlink/specs/em.yaml \
     --subscribe event  --sleep 10

[1] https://lwn.net/Articles/922405/
[2] https://lore.kernel.org/lkml/a82423bc-8c38-4d57-93da-c4f20011cc92@arm.com/
[3] https://lore.kernel.org/lkml/202506140306.tuIoz8rN-lkp@intel.com/#t

ChangeLog v4 -> v5:
  - Rebase the code to the head of the linus tree.
  - Remove the redundant em_check_capacity_update() call from
    em_dev_register_pd_no_update().
  - Move patch 3 ("PM: EM: Add an iterator and accessor for the
    performance domain") after patch 5 ("PM: EM: Add a skeleton code for
    netlink notification").
  - Move the declaration of for_each_em_perf_domain() and
    em_perf_domain_get_by_id() from energy_model.h to em_netlink.h.
  - Fix a typo in patch 7 ("PM: EM: Implement
    em_nl_get_pd_table_doit()") and change the variable declaration
    order in em_nl_get_pd_table_doit() following the reverse Christmas
    tree order.
  - Remove the empty skeleton code of em_notify_pd_created/updated() from
    patch 8 ("PM: EM: Implement em_notify_pd_deleted()") and introduce
    them later where they are actually implemented.
  - Change the return type of em_notify_pd_created/updated/deleted()
    from int to void, since we don't check it anyway.

ChangeLog v3 -> v4:
  - Move patches [3-5] to the first.
  - Remove the ending period (".") from all of the patch subjects.
  - Rebase the code to v6.17-rc4.

ChangeLog v2 -> v3:
  - Properly initialize a return variable in
    em_notify_pd_created/updated() at an error path (09/10), reported by
    the kernel test robot [3].
  - Remove redundant initialization of a return variable in
    em_notify_pd_deleted() at an error path (08/10).

ChangeLog v1 -> v2:
  - Use YNL to generate boilerplate code. Overhaul the naming conventions
    (command, event, notification, attribute) to follow the typical
    conventions of other YNL-based netlink implementations.
  - Calculate the exact message size instead of using NLMSG_GOODSIZE
    when allocating a message (genlmsg_new). This avoids the reallocation
    of a message.
  - Remove an unnecessary function, em_netlink_exit(), and initialize the
    netlink (em_netlink_init) at em_netlink.c without touching energy_model.c.

Changwoo Min (10):
  PM: EM: Assign a unique ID when creating a performance domain
  PM: EM: Expose the ID of a performance domain via debugfs
  PM: EM: Add em.yaml and autogen files
  PM: EM: Add a skeleton code for netlink notification
  PM: EM: Add an iterator and accessor for the performance domain
  PM: EM: Implement em_nl_get_pds_doit()
  PM: EM: Implement em_nl_get_pd_table_doit()
  PM: EM: Implement em_notify_pd_deleted()
  PM: EM: Implement em_notify_pd_created/updated()
  PM: EM: Notify an event when the performance domain changes

 Documentation/netlink/specs/em.yaml | 113 ++++++++++
 MAINTAINERS                         |   3 +
 include/linux/energy_model.h        |   4 +
 include/uapi/linux/energy_model.h   |  62 ++++++
 kernel/power/Makefile               |   5 +-
 kernel/power/em_netlink.c           | 311 ++++++++++++++++++++++++++++
 kernel/power/em_netlink.h           |  39 ++++
 kernel/power/em_netlink_autogen.c   |  48 +++++
 kernel/power/em_netlink_autogen.h   |  23 ++
 kernel/power/energy_model.c         |  83 +++++++-
 10 files changed, 689 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/netlink/specs/em.yaml
 create mode 100644 include/uapi/linux/energy_model.h
 create mode 100644 kernel/power/em_netlink.c
 create mode 100644 kernel/power/em_netlink.h
 create mode 100644 kernel/power/em_netlink_autogen.c
 create mode 100644 kernel/power/em_netlink_autogen.h

-- 
2.51.0


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v5 01/10] PM: EM: Assign a unique ID when creating a performance domain
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  8:41   ` Lukasz Luba
  2025-10-14  0:10 ` [PATCH v5 02/10] PM: EM: Expose the ID of a performance domain via debugfs Changwoo Min
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

It is necessary to refer to a specific performance domain from a
userspace. For example, the energy model of a particular performance
domain is updated.

To this end, assign a unique ID to each performance domain to address it,
and manage them in a global linked list to look up a specific one by
matching ID. IDA is used for ID assignment, and the mutex is used to
protect the global list from concurrent access.

Note that the mutex (em_pd_list_mutex) is not supposed to hold while
holding em_pd_mutex to avoid ABBA deadlock.

Signed-off-by: Changwoo Min <changwoo@igalia.com>
---
 include/linux/energy_model.h |  4 ++++
 kernel/power/energy_model.c  | 30 +++++++++++++++++++++++++++++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h
index 61d50571ad88..43aa6153dc57 100644
--- a/include/linux/energy_model.h
+++ b/include/linux/energy_model.h
@@ -54,6 +54,8 @@ struct em_perf_table {
 /**
  * struct em_perf_domain - Performance domain
  * @em_table:		Pointer to the runtime modifiable em_perf_table
+ * @node:		node in	em_pd_list (in energy_model.c)
+ * @id:			A unique ID number for each performance domain
  * @nr_perf_states:	Number of performance states
  * @min_perf_state:	Minimum allowed Performance State index
  * @max_perf_state:	Maximum allowed Performance State index
@@ -71,6 +73,8 @@ struct em_perf_table {
  */
 struct em_perf_domain {
 	struct em_perf_table __rcu *em_table;
+	struct list_head node;
+	int id;
 	int nr_perf_states;
 	int min_perf_state;
 	int max_perf_state;
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index 5f17d2e8e954..2047b546ad11 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -23,6 +23,16 @@
  */
 static DEFINE_MUTEX(em_pd_mutex);
 
+/*
+ * Manage performance domains with IDs. One can iterate the performance domains
+ * through the list and pick one with their associated ID. The mutex serializes
+ * the list access. When holding em_pd_list_mutex, em_pd_mutex should not be
+ * taken to avoid potential deadlock.
+ */
+static DEFINE_IDA(em_pd_ida);
+static LIST_HEAD(em_pd_list);
+static DEFINE_MUTEX(em_pd_list_mutex);
+
 static void em_cpufreq_update_efficiencies(struct device *dev,
 					   struct em_perf_state *table);
 static void em_check_capacity_update(void);
@@ -396,7 +406,7 @@ static int em_create_pd(struct device *dev, int nr_states,
 	struct em_perf_table *em_table;
 	struct em_perf_domain *pd;
 	struct device *cpu_dev;
-	int cpu, ret, num_cpus;
+	int cpu, ret, num_cpus, id;
 
 	if (_is_cpu_device(dev)) {
 		num_cpus = cpumask_weight(cpus);
@@ -420,6 +430,13 @@ static int em_create_pd(struct device *dev, int nr_states,
 
 	pd->nr_perf_states = nr_states;
 
+	INIT_LIST_HEAD(&pd->node);
+
+	id = ida_alloc(&em_pd_ida, GFP_KERNEL);
+	if (id < 0)
+		return -ENOMEM;
+	pd->id = id;
+
 	em_table = em_table_alloc(pd);
 	if (!em_table)
 		goto free_pd;
@@ -444,6 +461,7 @@ static int em_create_pd(struct device *dev, int nr_states,
 	kfree(em_table);
 free_pd:
 	kfree(pd);
+	ida_free(&em_pd_ida, id);
 	return -EINVAL;
 }
 
@@ -660,6 +678,10 @@ int em_dev_register_pd_no_update(struct device *dev, unsigned int nr_states,
 unlock:
 	mutex_unlock(&em_pd_mutex);
 
+	mutex_lock(&em_pd_list_mutex);
+	list_add_tail(&dev->em_pd->node, &em_pd_list);
+	mutex_unlock(&em_pd_list_mutex);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(em_dev_register_pd_no_update);
@@ -678,6 +700,10 @@ void em_dev_unregister_perf_domain(struct device *dev)
 	if (_is_cpu_device(dev))
 		return;
 
+	mutex_lock(&em_pd_list_mutex);
+	list_del_init(&dev->em_pd->node);
+	mutex_unlock(&em_pd_list_mutex);
+
 	/*
 	 * The mutex separates all register/unregister requests and protects
 	 * from potential clean-up/setup issues in the debugfs directories.
@@ -689,6 +715,8 @@ void em_dev_unregister_perf_domain(struct device *dev)
 	em_table_free(rcu_dereference_protected(dev->em_pd->em_table,
 						lockdep_is_held(&em_pd_mutex)));
 
+	ida_free(&em_pd_ida, dev->em_pd->id);
+
 	kfree(dev->em_pd);
 	dev->em_pd = NULL;
 	mutex_unlock(&em_pd_mutex);
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 02/10] PM: EM: Expose the ID of a performance domain via debugfs
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
  2025-10-14  0:10 ` [PATCH v5 01/10] PM: EM: Assign a unique ID when creating a performance domain Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  0:10 ` [PATCH v5 03/10] PM: EM: Add em.yaml and autogen files Changwoo Min
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

For ease of debugging, let's expose the assigned ID of a performance
domain through debugfs (e.g., /sys/kernel/debug/energy_model/cpu0/id).

Signed-off-by: Changwoo Min <changwoo@igalia.com>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
---
 kernel/power/energy_model.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index 2047b546ad11..756debf5406a 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -126,6 +126,16 @@ static int em_debug_flags_show(struct seq_file *s, void *unused)
 }
 DEFINE_SHOW_ATTRIBUTE(em_debug_flags);
 
+static int em_debug_id_show(struct seq_file *s, void *unused)
+{
+	struct em_perf_domain *pd = s->private;
+
+	seq_printf(s, "%d\n", pd->id);
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(em_debug_id);
+
 static void em_debug_create_pd(struct device *dev)
 {
 	struct em_dbg_info *em_dbg;
@@ -142,6 +152,8 @@ static void em_debug_create_pd(struct device *dev)
 	debugfs_create_file("flags", 0444, d, dev->em_pd,
 			    &em_debug_flags_fops);
 
+	debugfs_create_file("id", 0444, d, dev->em_pd, &em_debug_id_fops);
+
 	em_dbg = devm_kcalloc(dev, dev->em_pd->nr_perf_states,
 			      sizeof(*em_dbg), GFP_KERNEL);
 	if (!em_dbg)
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 03/10] PM: EM: Add em.yaml and autogen files
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
  2025-10-14  0:10 ` [PATCH v5 01/10] PM: EM: Assign a unique ID when creating a performance domain Changwoo Min
  2025-10-14  0:10 ` [PATCH v5 02/10] PM: EM: Expose the ID of a performance domain via debugfs Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  0:10 ` [PATCH v5 04/10] PM: EM: Add a skeleton code for netlink notification Changwoo Min
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

Add a generic netlink spec in YAML format and autogenerate boilerplate
code using ynl-regen.sh to introduce a generic netlink for the energy
model. It allows a userspace program to read the performance domain and
its energy model. It notifies the userspace program when a performance
domain is created or deleted or its energy model is updated through a
multicast interface.

Specifically, it supports two commands:
  - EM_CMD_GET_PDS: Get the list of information for all performance
    domains.
  - EM_CMD_GET_PD_TABLE: Get the energy model table of a performance
    domain.

Also, it supports three notification events:
  - EM_CMD_PD_CREATED: When a performance domain is created.
  - EM_CMD_PD_DELETED: When a performance domain is deleted.
  - EM_CMD_PD_UPDATED: When the energy model table of a performance domain
    is updated.

Finally, update MAINTAINERS to include new files.

Signed-off-by: Changwoo Min <changwoo@igalia.com>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
---
 Documentation/netlink/specs/em.yaml | 113 ++++++++++++++++++++++++++++
 MAINTAINERS                         |   3 +
 include/uapi/linux/energy_model.h   |  62 +++++++++++++++
 kernel/power/em_netlink_autogen.c   |  48 ++++++++++++
 kernel/power/em_netlink_autogen.h   |  23 ++++++
 5 files changed, 249 insertions(+)
 create mode 100644 Documentation/netlink/specs/em.yaml
 create mode 100644 include/uapi/linux/energy_model.h
 create mode 100644 kernel/power/em_netlink_autogen.c
 create mode 100644 kernel/power/em_netlink_autogen.h

diff --git a/Documentation/netlink/specs/em.yaml b/Documentation/netlink/specs/em.yaml
new file mode 100644
index 000000000000..9905ca482325
--- /dev/null
+++ b/Documentation/netlink/specs/em.yaml
@@ -0,0 +1,113 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+
+name: em
+
+doc: |
+  Energy model netlink interface to notify its changes.
+
+protocol: genetlink
+
+uapi-header: linux/energy_model.h
+
+attribute-sets:
+  -
+    name: pds
+    attributes:
+      -
+        name: pd
+        type: nest
+        nested-attributes: pd
+        multi-attr: true
+  -
+    name: pd
+    attributes:
+      -
+        name: pad
+        type: pad
+      -
+        name: pd-id
+        type: u32
+      -
+        name: flags
+        type: u64
+      -
+        name: cpus
+        type: string
+  -
+    name: pd-table
+    attributes:
+      -
+        name: pd-id
+        type: u32
+      -
+        name: ps
+        type: nest
+        nested-attributes: ps
+        multi-attr: true
+  -
+    name: ps
+    attributes:
+      -
+        name: pad
+        type: pad
+      -
+        name: performance
+        type: u64
+      -
+        name: frequency
+        type: u64
+      -
+        name: power
+        type: u64
+      -
+        name: cost
+        type: u64
+      -
+        name: flags
+        type: u64
+
+operations:
+  list:
+    -
+      name: get-pds
+      attribute-set: pds
+      doc: Get the list of information for all performance domains.
+      do:
+        reply:
+          attributes:
+            - pd
+    -
+      name: get-pd-table
+      attribute-set: pd-table
+      doc: Get the energy model table of a performance domain.
+      do:
+        request:
+          attributes:
+            - pd-id
+        reply:
+          attributes:
+            - pd-id
+            - ps
+    -
+      name: pd-created
+      doc: A performance domain is created.
+      notify: get-pd-table
+      mcgrp: event
+    -
+      name: pd-updated
+      doc: A performance domain is updated.
+      notify: get-pd-table
+      mcgrp: event
+    -
+      name: pd-deleted
+      doc: A performance domain is deleted.
+      attribute-set: pd-table
+      event:
+        attributes:
+            - pd-id
+      mcgrp: event
+
+mcast-groups:
+  list:
+    -
+      name: event
diff --git a/MAINTAINERS b/MAINTAINERS
index 46126ce2f968..babd7088fc1c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9180,6 +9180,9 @@ S:	Maintained
 F:	kernel/power/energy_model.c
 F:	include/linux/energy_model.h
 F:	Documentation/power/energy-model.rst
+F:	Documentation/netlink/specs/em.yaml
+F:	include/uapi/linux/energy_model.h
+F:	kernel/power/em_netlink_autogen.*
 
 EPAPR HYPERVISOR BYTE CHANNEL DEVICE DRIVER
 M:	Laurentiu Tudor <laurentiu.tudor@nxp.com>
diff --git a/include/uapi/linux/energy_model.h b/include/uapi/linux/energy_model.h
new file mode 100644
index 000000000000..4ec4c0eabbbb
--- /dev/null
+++ b/include/uapi/linux/energy_model.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/*	Documentation/netlink/specs/em.yaml */
+/* YNL-GEN uapi header */
+
+#ifndef _UAPI_LINUX_ENERGY_MODEL_H
+#define _UAPI_LINUX_ENERGY_MODEL_H
+
+#define EM_FAMILY_NAME		"em"
+#define EM_FAMILY_VERSION	1
+
+enum {
+	EM_A_PDS_PD = 1,
+
+	__EM_A_PDS_MAX,
+	EM_A_PDS_MAX = (__EM_A_PDS_MAX - 1)
+};
+
+enum {
+	EM_A_PD_PAD = 1,
+	EM_A_PD_PD_ID,
+	EM_A_PD_FLAGS,
+	EM_A_PD_CPUS,
+
+	__EM_A_PD_MAX,
+	EM_A_PD_MAX = (__EM_A_PD_MAX - 1)
+};
+
+enum {
+	EM_A_PD_TABLE_PD_ID = 1,
+	EM_A_PD_TABLE_PS,
+
+	__EM_A_PD_TABLE_MAX,
+	EM_A_PD_TABLE_MAX = (__EM_A_PD_TABLE_MAX - 1)
+};
+
+enum {
+	EM_A_PS_PAD = 1,
+	EM_A_PS_PERFORMANCE,
+	EM_A_PS_FREQUENCY,
+	EM_A_PS_POWER,
+	EM_A_PS_COST,
+	EM_A_PS_FLAGS,
+
+	__EM_A_PS_MAX,
+	EM_A_PS_MAX = (__EM_A_PS_MAX - 1)
+};
+
+enum {
+	EM_CMD_GET_PDS = 1,
+	EM_CMD_GET_PD_TABLE,
+	EM_CMD_PD_CREATED,
+	EM_CMD_PD_UPDATED,
+	EM_CMD_PD_DELETED,
+
+	__EM_CMD_MAX,
+	EM_CMD_MAX = (__EM_CMD_MAX - 1)
+};
+
+#define EM_MCGRP_EVENT	"event"
+
+#endif /* _UAPI_LINUX_ENERGY_MODEL_H */
diff --git a/kernel/power/em_netlink_autogen.c b/kernel/power/em_netlink_autogen.c
new file mode 100644
index 000000000000..a7a09ab1d1c2
--- /dev/null
+++ b/kernel/power/em_netlink_autogen.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+/* Do not edit directly, auto-generated from: */
+/*	Documentation/netlink/specs/em.yaml */
+/* YNL-GEN kernel source */
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include "em_netlink_autogen.h"
+
+#include <uapi/linux/energy_model.h>
+
+/* EM_CMD_GET_PD_TABLE - do */
+static const struct nla_policy em_get_pd_table_nl_policy[EM_A_PD_TABLE_PD_ID + 1] = {
+	[EM_A_PD_TABLE_PD_ID] = { .type = NLA_U32, },
+};
+
+/* Ops table for em */
+static const struct genl_split_ops em_nl_ops[] = {
+	{
+		.cmd	= EM_CMD_GET_PDS,
+		.doit	= em_nl_get_pds_doit,
+		.flags	= GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd		= EM_CMD_GET_PD_TABLE,
+		.doit		= em_nl_get_pd_table_doit,
+		.policy		= em_get_pd_table_nl_policy,
+		.maxattr	= EM_A_PD_TABLE_PD_ID,
+		.flags		= GENL_CMD_CAP_DO,
+	},
+};
+
+static const struct genl_multicast_group em_nl_mcgrps[] = {
+	[EM_NLGRP_EVENT] = { "event", },
+};
+
+struct genl_family em_nl_family __ro_after_init = {
+	.name		= EM_FAMILY_NAME,
+	.version	= EM_FAMILY_VERSION,
+	.netnsok	= true,
+	.parallel_ops	= true,
+	.module		= THIS_MODULE,
+	.split_ops	= em_nl_ops,
+	.n_split_ops	= ARRAY_SIZE(em_nl_ops),
+	.mcgrps		= em_nl_mcgrps,
+	.n_mcgrps	= ARRAY_SIZE(em_nl_mcgrps),
+};
diff --git a/kernel/power/em_netlink_autogen.h b/kernel/power/em_netlink_autogen.h
new file mode 100644
index 000000000000..78ce609641f1
--- /dev/null
+++ b/kernel/power/em_netlink_autogen.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/*	Documentation/netlink/specs/em.yaml */
+/* YNL-GEN kernel header */
+
+#ifndef _LINUX_EM_GEN_H
+#define _LINUX_EM_GEN_H
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include <uapi/linux/energy_model.h>
+
+int em_nl_get_pds_doit(struct sk_buff *skb, struct genl_info *info);
+int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info);
+
+enum {
+	EM_NLGRP_EVENT,
+};
+
+extern struct genl_family em_nl_family;
+
+#endif /* _LINUX_EM_GEN_H */
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 04/10] PM: EM: Add a skeleton code for netlink notification
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
                   ` (2 preceding siblings ...)
  2025-10-14  0:10 ` [PATCH v5 03/10] PM: EM: Add em.yaml and autogen files Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  8:43   ` Lukasz Luba
  2025-10-14  0:10 ` [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain Changwoo Min
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

Add a boilerplate code for netlink notification to register the new
protocol family. Also, initialize and register the netlink during booting.
The initialization is called at the postcore level, which is late enough
after the generic netlink is initialized.

Finally, update MAINTAINERS to include new files.

Signed-off-by: Changwoo Min <changwoo@igalia.com>
---
 MAINTAINERS               |  2 +-
 kernel/power/Makefile     |  5 ++++-
 kernel/power/em_netlink.c | 35 +++++++++++++++++++++++++++++++++++
 kernel/power/em_netlink.h | 16 ++++++++++++++++
 4 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 kernel/power/em_netlink.c
 create mode 100644 kernel/power/em_netlink.h

diff --git a/MAINTAINERS b/MAINTAINERS
index babd7088fc1c..bc2c08e6f0ac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9182,7 +9182,7 @@ F:	include/linux/energy_model.h
 F:	Documentation/power/energy-model.rst
 F:	Documentation/netlink/specs/em.yaml
 F:	include/uapi/linux/energy_model.h
-F:	kernel/power/em_netlink_autogen.*
+F:	kernel/power/em_netlink*.*
 
 EPAPR HYPERVISOR BYTE CHANNEL DEVICE DRIVER
 M:	Laurentiu Tudor <laurentiu.tudor@nxp.com>
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 874ad834dc8d..284a760aade7 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -21,4 +21,7 @@ obj-$(CONFIG_PM_WAKELOCKS)	+= wakelock.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
 
-obj-$(CONFIG_ENERGY_MODEL)	+= energy_model.o
+obj-$(CONFIG_ENERGY_MODEL)	+= em.o
+em-y				:= energy_model.o
+em-$(CONFIG_NET)		+= em_netlink_autogen.o em_netlink.o
+
diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
new file mode 100644
index 000000000000..f3fbfeff29a4
--- /dev/null
+++ b/kernel/power/em_netlink.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Generic netlink for energy model.
+ *
+ * Copyright (c) 2025 Valve Corporation.
+ * Author: Changwoo Min <changwoo@igalia.com>
+ */
+
+#define pr_fmt(fmt) "energy_model: " fmt
+
+#include <linux/energy_model.h>
+#include <net/sock.h>
+#include <net/genetlink.h>
+#include <uapi/linux/energy_model.h>
+
+#include "em_netlink.h"
+#include "em_netlink_autogen.h"
+
+int em_nl_get_pds_doit(struct sk_buff *skb, struct genl_info *info)
+{
+	return -EOPNOTSUPP;
+}
+
+int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
+{
+	return -EOPNOTSUPP;
+}
+
+static int __init em_netlink_init(void)
+{
+	return genl_register_family(&em_nl_family);
+}
+postcore_initcall(em_netlink_init);
+
diff --git a/kernel/power/em_netlink.h b/kernel/power/em_netlink.h
new file mode 100644
index 000000000000..acd186c92d6b
--- /dev/null
+++ b/kernel/power/em_netlink.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * Generic netlink for energy model.
+ *
+ * Copyright (c) 2025 Valve Corporation.
+ * Author: Changwoo Min <changwoo@igalia.com>
+ */
+#ifndef _EM_NETLINK_H
+#define _EM_NETLINK_H
+
+#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_NET)
+#else
+#endif
+
+#endif /* _EM_NETLINK_H */
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
                   ` (3 preceding siblings ...)
  2025-10-14  0:10 ` [PATCH v5 04/10] PM: EM: Add a skeleton code for netlink notification Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  8:45   ` Lukasz Luba
  2025-10-15  4:49   ` kernel test robot
  2025-10-14  0:10 ` [PATCH v5 06/10] PM: EM: Implement em_nl_get_pds_doit() Changwoo Min
                   ` (5 subsequent siblings)
  10 siblings, 2 replies; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

Add an iterator function (for_each_em_perf_domain) that iterates all the
performance domains in the global list. A passed callback function (cb) is
called for each performance domain.

Additionally, add a lookup function (em_perf_domain_get_by_id) that
searches for a performance domain by matching the ID in the global list.

Signed-off-by: Changwoo Min <changwoo@igalia.com>
---
 kernel/power/em_netlink.h   | 14 ++++++++++++++
 kernel/power/energy_model.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/kernel/power/em_netlink.h b/kernel/power/em_netlink.h
index acd186c92d6b..8114b018c73b 100644
--- a/kernel/power/em_netlink.h
+++ b/kernel/power/em_netlink.h
@@ -10,7 +10,21 @@
 #define _EM_NETLINK_H
 
 #if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_NET)
+int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
+			    void *data);
+struct em_perf_domain *em_perf_domain_get_by_id(int id);
 #else
+static inline
+int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
+			    void *data)
+{
+	return -EINVAL;
+}
+static inline
+struct em_perf_domain *em_perf_domain_get_by_id(int id)
+{
+	return NULL;
+}
 #endif
 
 #endif /* _EM_NETLINK_H */
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index 756debf5406a..43a243f9cfa2 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -17,6 +17,8 @@
 #include <linux/sched/topology.h>
 #include <linux/slab.h>
 
+#include "em_netlink.h"
+
 /*
  * Mutex serializing the registrations of performance domains and letting
  * callbacks defined by drivers sleep.
@@ -998,3 +1000,37 @@ void em_rebuild_sched_domains(void)
 	 */
 	schedule_work(&rebuild_sd_work);
 }
+
+int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
+			    void *data)
+{
+	struct em_perf_domain *pd;
+
+	lockdep_assert_not_held(&em_pd_mutex);
+	guard(mutex)(&em_pd_list_mutex);
+
+	list_for_each_entry(pd, &em_pd_list, node) {
+		int ret;
+
+		ret = cb(pd, data);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+struct em_perf_domain *em_perf_domain_get_by_id(int id)
+{
+	struct em_perf_domain *pd;
+
+	lockdep_assert_not_held(&em_pd_mutex);
+	guard(mutex)(&em_pd_list_mutex);
+
+	list_for_each_entry(pd, &em_pd_list, node) {
+		if (pd->id == id)
+			return pd;
+	}
+
+	return NULL;
+}
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 06/10] PM: EM: Implement em_nl_get_pds_doit()
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
                   ` (4 preceding siblings ...)
  2025-10-14  0:10 ` [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  0:10 ` [PATCH v5 07/10] PM: EM: Implement em_nl_get_pd_table_doit() Changwoo Min
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

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>
---
 kernel/power/em_netlink.c | 82 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 1 deletion(-)

diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
index f3fbfeff29a4..31b27c6fe3c9 100644
--- a/kernel/power/em_netlink.c
+++ b/kernel/power/em_netlink.c
@@ -17,9 +17,89 @@
 #include "em_netlink.h"
 #include "em_netlink_autogen.h"
 
+#define EM_A_PD_CPUS_LEN		256
+
+/*************************** Command encoding ********************************/
+static int __em_nl_get_pd_size(struct em_perf_domain *pd, void *data)
+{
+	char cpus_buf[EM_A_PD_CPUS_LEN];
+	int *tot_msg_sz = data;
+	int msg_sz, cpus_sz;
+
+	cpus_sz = snprintf(cpus_buf, sizeof(cpus_buf), "%*pb",
+			   cpumask_pr_args(to_cpumask(pd->cpus)));
+
+	msg_sz = nla_total_size(0) +			/* EM_A_PDS_PD */
+		 nla_total_size(sizeof(u32)) +		/* EM_A_PD_PD_ID */
+		 nla_total_size_64bit(sizeof(u64)) +	/* EM_A_PD_FLAGS */
+		 nla_total_size(cpus_sz);		/* EM_A_PD_CPUS */
+
+	*tot_msg_sz += nlmsg_total_size(genlmsg_msg_size(msg_sz));
+	return 0;
+}
+
+static int __em_nl_get_pd(struct em_perf_domain *pd, void *data)
+{
+	char cpus_buf[EM_A_PD_CPUS_LEN];
+	struct sk_buff *msg = data;
+	struct nlattr *entry;
+
+	entry = nla_nest_start(msg, EM_A_PDS_PD);
+	if (!entry)
+		goto out_cancel_nest;
+
+	if (nla_put_u32(msg, EM_A_PD_PD_ID, pd->id))
+		goto out_cancel_nest;
+
+	if (nla_put_u64_64bit(msg, EM_A_PD_FLAGS, pd->flags, EM_A_PD_PAD))
+		goto out_cancel_nest;
+
+	snprintf(cpus_buf, sizeof(cpus_buf), "%*pb",
+		 cpumask_pr_args(to_cpumask(pd->cpus)));
+	if (nla_put_string(msg, EM_A_PD_CPUS, cpus_buf))
+		goto out_cancel_nest;
+
+	nla_nest_end(msg, entry);
+
+	return 0;
+
+out_cancel_nest:
+	nla_nest_cancel(msg, entry);
+
+	return -EMSGSIZE;
+}
+
 int em_nl_get_pds_doit(struct sk_buff *skb, struct genl_info *info)
 {
-	return -EOPNOTSUPP;
+	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);
+
+	msg = genlmsg_new(msg_sz, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put_reply(msg, info, &em_nl_family, 0, cmd);
+	if (!hdr)
+		goto out_free_msg;
+
+	ret = for_each_em_perf_domain(__em_nl_get_pd, msg);
+	if (ret)
+		goto out_cancel_msg;
+
+	genlmsg_end(msg, hdr);
+
+	return genlmsg_reply(msg, info);
+
+out_cancel_msg:
+	genlmsg_cancel(msg, hdr);
+out_free_msg:
+	nlmsg_free(msg);
+
+	return ret;
 }
 
 int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 07/10] PM: EM: Implement em_nl_get_pd_table_doit()
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
                   ` (5 preceding siblings ...)
  2025-10-14  0:10 ` [PATCH v5 06/10] PM: EM: Implement em_nl_get_pds_doit() Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  0:10 ` [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted() Changwoo Min
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

When a userspace requests EM_CMD_GET_PD_TABLE with an ID of a performance
domain, the kernel reports back the energy model table of the specified
performance domain. The message format of the response is as follows:

EM_A_PD_TABLE_PD_ID (NLA_U32)
EM_A_PD_TABLE_PS (NLA_NESTED)*
    EM_A_PS_PERFORMANCE (NLA_U64)
    EM_A_PS_FREQUENCY (NLA_U64)
    EM_A_PS_POWER (NLA_U64)
    EM_A_PS_COST (NLA_U64)
    EM_A_PS_FLAGS (NLA_U64)

where EM_A_PD_TABLE_PS can be repeated as many times as there are
performance states (struct em_perf_state).

Signed-off-by: Changwoo Min <changwoo@igalia.com>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
---
 kernel/power/em_netlink.c | 108 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 107 insertions(+), 1 deletion(-)

diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
index 31b27c6fe3c9..2addc143401b 100644
--- a/kernel/power/em_netlink.c
+++ b/kernel/power/em_netlink.c
@@ -102,9 +102,115 @@ int em_nl_get_pds_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
+static struct em_perf_domain *__em_nl_get_pd_table_id(struct nlattr **attrs)
+{
+	struct em_perf_domain *pd;
+	int id;
+
+	if (!attrs[EM_A_PD_TABLE_PD_ID])
+		return NULL;
+
+	id = nla_get_u32(attrs[EM_A_PD_TABLE_PD_ID]);
+	pd = em_perf_domain_get_by_id(id);
+	return pd;
+}
+
+static int __em_nl_get_pd_table_size(const struct em_perf_domain *pd)
+{
+	int id_sz, ps_sz;
+
+	id_sz = nla_total_size(sizeof(u32));		/* EM_A_PD_TABLE_PD_ID */
+	ps_sz = nla_total_size(0) +			/* EM_A_PD_TABLE_PS */
+		nla_total_size_64bit(sizeof(u64)) +	/* EM_A_PS_PERFORMANCE */
+		nla_total_size_64bit(sizeof(u64)) +	/* EM_A_PS_FREQUENCY */
+		nla_total_size_64bit(sizeof(u64)) +	/* EM_A_PS_POWER */
+		nla_total_size_64bit(sizeof(u64)) +	/* EM_A_PS_COST */
+		nla_total_size_64bit(sizeof(u64));	/* EM_A_PS_FLAGS */
+	ps_sz *= pd->nr_perf_states;
+
+	return nlmsg_total_size(genlmsg_msg_size(id_sz + ps_sz));
+}
+
+static int __em_nl_get_pd_table(struct sk_buff *msg, const struct em_perf_domain *pd)
+{
+	struct em_perf_state *table, *ps;
+	struct nlattr *entry;
+	int i;
+
+	if (nla_put_u32(msg, EM_A_PD_TABLE_PD_ID, pd->id))
+		goto out_err;
+
+	rcu_read_lock();
+	table = em_perf_state_from_pd((struct em_perf_domain *)pd);
+
+	for (i = 0; i < pd->nr_perf_states; i++) {
+		ps = &table[i];
+
+		entry = nla_nest_start(msg, EM_A_PD_TABLE_PS);
+		if (!entry)
+			goto out_unlock_ps;
+
+		if (nla_put_u64_64bit(msg, EM_A_PS_PERFORMANCE,
+				      ps->performance, EM_A_PS_PAD))
+			goto out_cancel_ps_nest;
+		if (nla_put_u64_64bit(msg, EM_A_PS_FREQUENCY,
+				      ps->frequency, EM_A_PS_PAD))
+			goto out_cancel_ps_nest;
+		if (nla_put_u64_64bit(msg, EM_A_PS_POWER,
+				      ps->power, EM_A_PS_PAD))
+			goto out_cancel_ps_nest;
+		if (nla_put_u64_64bit(msg, EM_A_PS_COST,
+				      ps->cost, EM_A_PS_PAD))
+			goto out_cancel_ps_nest;
+		if (nla_put_u64_64bit(msg, EM_A_PS_FLAGS,
+				      ps->flags, EM_A_PS_PAD))
+			goto out_cancel_ps_nest;
+
+		nla_nest_end(msg, entry);
+	}
+	rcu_read_unlock();
+	return 0;
+
+out_cancel_ps_nest:
+	nla_nest_cancel(msg, entry);
+out_unlock_ps:
+	rcu_read_unlock();
+out_err:
+	return -EMSGSIZE;
+}
+
 int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
 {
-	return -EOPNOTSUPP;
+	int cmd = info->genlhdr->cmd;
+	int msg_sz, ret = -EMSGSIZE;
+	struct em_perf_domain *pd;
+	struct sk_buff *msg;
+	void *hdr;
+
+	pd = __em_nl_get_pd_table_id(info->attrs);
+	if (!pd)
+		return -EINVAL;
+
+	msg_sz = __em_nl_get_pd_table_size(pd);
+
+	msg = genlmsg_new(msg_sz, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put_reply(msg, info, &em_nl_family, 0, cmd);
+	if (!hdr)
+		goto out_free_msg;
+
+	ret = __em_nl_get_pd_table(msg, pd);
+	if (ret)
+		goto out_free_msg;
+
+	genlmsg_end(msg, hdr);
+	return genlmsg_reply(msg, info);
+
+out_free_msg:
+	nlmsg_free(msg);
+	return ret;
 }
 
 static int __init em_netlink_init(void)
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted()
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
                   ` (6 preceding siblings ...)
  2025-10-14  0:10 ` [PATCH v5 07/10] PM: EM: Implement em_nl_get_pd_table_doit() Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  8:47   ` Lukasz Luba
  2025-10-15  4:16   ` kernel test robot
  2025-10-14  0:10 ` [PATCH v5 09/10] PM: EM: Implement em_notify_pd_created/updated() Changwoo Min
                   ` (2 subsequent siblings)
  10 siblings, 2 replies; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

Add the event notification infrastructure and implement the event
notification for when a performance domain is deleted (EM_CMD_PD_DELETED).

The event contains the ID of the performance domain (EM_A_PD_TABLE_PD_ID)
so the userspace can identify the changed performance domain for further
processing.

Signed-off-by: Changwoo Min <changwoo@igalia.com>
---
 kernel/power/em_netlink.c | 46 +++++++++++++++++++++++++++++++++++++++
 kernel/power/em_netlink.h |  3 +++
 2 files changed, 49 insertions(+)

diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
index 2addc143401b..90ae6f1c9c9a 100644
--- a/kernel/power/em_netlink.c
+++ b/kernel/power/em_netlink.c
@@ -213,6 +213,52 @@ int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
+
+/**************************** Event encoding *********************************/
+static int __em_notify_pd_deleted_size(const struct em_perf_domain *pd)
+{
+	int id_sz = nla_total_size(sizeof(u32)); /* EM_A_PD_TABLE_PD_ID */
+
+	return nlmsg_total_size(genlmsg_msg_size(id_sz));
+}
+
+void em_notify_pd_deleted(const struct em_perf_domain *pd)
+{
+	struct sk_buff *msg;
+	int ret = -EMSGSIZE;
+	void *hdr;
+	int msg_sz;
+
+	if (!genl_has_listeners(&em_nl_family, &init_net, EM_NLGRP_EVENT))
+		return;
+
+	msg_sz = __em_notify_pd_deleted_size(pd);
+
+	msg = genlmsg_new(msg_sz, GFP_KERNEL);
+	if (!msg)
+		return;
+
+	hdr = genlmsg_put(msg, 0, 0, &em_nl_family, 0, EM_CMD_PD_DELETED);
+	if (!hdr)
+		goto out_free_msg;
+
+	if (nla_put_u32(msg, EM_A_PD_TABLE_PD_ID, pd->id)) {
+		ret = -EMSGSIZE;
+		goto out_free_msg;
+	}
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast(&em_nl_family, msg, 0, EM_NLGRP_EVENT, GFP_KERNEL);
+
+	return;
+
+out_free_msg:
+	nlmsg_free(msg);
+	return;
+}
+
+/**************************** Initialization *********************************/
 static int __init em_netlink_init(void)
 {
 	return genl_register_family(&em_nl_family);
diff --git a/kernel/power/em_netlink.h b/kernel/power/em_netlink.h
index 8114b018c73b..d56e5865e1ed 100644
--- a/kernel/power/em_netlink.h
+++ b/kernel/power/em_netlink.h
@@ -13,6 +13,7 @@
 int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
 			    void *data);
 struct em_perf_domain *em_perf_domain_get_by_id(int id);
+void em_notify_pd_deleted(const struct em_perf_domain *pd);
 #else
 static inline
 int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
@@ -25,6 +26,8 @@ struct em_perf_domain *em_perf_domain_get_by_id(int id)
 {
 	return NULL;
 }
+
+static inline void em_notify_pd_deleted(const struct em_perf_domain *pd) {}
 #endif
 
 #endif /* _EM_NETLINK_H */
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 09/10] PM: EM: Implement em_notify_pd_created/updated()
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
                   ` (7 preceding siblings ...)
  2025-10-14  0:10 ` [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted() Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  8:48   ` Lukasz Luba
  2025-10-14  0:10 ` [PATCH v5 10/10] PM: EM: Notify an event when the performance domain changes Changwoo Min
  2025-10-14  8:54 ` [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Lukasz Luba
  10 siblings, 1 reply; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

Implement two event notifications when a performance domain is created
(EM_CMD_PD_CREATED) and updated (EM_CMD_PD_UPDATED). The message format
of these two event notifications is the same as EM_CMD_GET_PD_TABLE --
containing the performance domain's ID and its energy model table.

Signed-off-by: Changwoo Min <changwoo@igalia.com>
---
 kernel/power/em_netlink.c | 44 +++++++++++++++++++++++++++++++++++++++
 kernel/power/em_netlink.h |  6 ++++++
 2 files changed, 50 insertions(+)

diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
index 90ae6f1c9c9a..2c55c758de6b 100644
--- a/kernel/power/em_netlink.c
+++ b/kernel/power/em_netlink.c
@@ -215,6 +215,50 @@ int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
 
 
 /**************************** Event encoding *********************************/
+static void __em_notify_pd_table(const struct em_perf_domain *pd, int ntf_type)
+{
+	struct sk_buff *msg;
+	int msg_sz, ret = -EMSGSIZE;
+	void *hdr;
+
+	if (!genl_has_listeners(&em_nl_family, &init_net, EM_NLGRP_EVENT))
+		return;
+
+	msg_sz = __em_nl_get_pd_table_size(pd);
+
+	msg = genlmsg_new(msg_sz, GFP_KERNEL);
+	if (!msg)
+		return;
+
+	hdr = genlmsg_put(msg, 0, 0, &em_nl_family, 0, ntf_type);
+	if (!hdr)
+		goto out_free_msg;
+
+	ret = __em_nl_get_pd_table(msg, pd);
+	if (ret)
+		goto out_free_msg;
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast(&em_nl_family, msg, 0, EM_NLGRP_EVENT, GFP_KERNEL);
+
+	return;
+
+out_free_msg:
+	nlmsg_free(msg);
+	return;
+}
+
+void em_notify_pd_created(const struct em_perf_domain *pd)
+{
+	__em_notify_pd_table(pd, EM_CMD_PD_CREATED);
+}
+
+void em_notify_pd_updated(const struct em_perf_domain *pd)
+{
+	__em_notify_pd_table(pd, EM_CMD_PD_UPDATED);
+}
+
 static int __em_notify_pd_deleted_size(const struct em_perf_domain *pd)
 {
 	int id_sz = nla_total_size(sizeof(u32)); /* EM_A_PD_TABLE_PD_ID */
diff --git a/kernel/power/em_netlink.h b/kernel/power/em_netlink.h
index d56e5865e1ed..583d7f1c3939 100644
--- a/kernel/power/em_netlink.h
+++ b/kernel/power/em_netlink.h
@@ -13,7 +13,9 @@
 int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
 			    void *data);
 struct em_perf_domain *em_perf_domain_get_by_id(int id);
+void em_notify_pd_created(const struct em_perf_domain *pd);
 void em_notify_pd_deleted(const struct em_perf_domain *pd);
+void em_notify_pd_updated(const struct em_perf_domain *pd);
 #else
 static inline
 int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
@@ -27,7 +29,11 @@ struct em_perf_domain *em_perf_domain_get_by_id(int id)
 	return NULL;
 }
 
+static inline void em_notify_pd_created(const struct em_perf_domain *pd) {}
+
 static inline void em_notify_pd_deleted(const struct em_perf_domain *pd) {}
+
+static inline void em_notify_pd_updated(const struct em_perf_domain *pd) {}
 #endif
 
 #endif /* _EM_NETLINK_H */
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 10/10] PM: EM: Notify an event when the performance domain changes
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
                   ` (8 preceding siblings ...)
  2025-10-14  0:10 ` [PATCH v5 09/10] PM: EM: Implement em_notify_pd_created/updated() Changwoo Min
@ 2025-10-14  0:10 ` Changwoo Min
  2025-10-14  8:54 ` [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Lukasz Luba
  10 siblings, 0 replies; 22+ messages in thread
From: Changwoo Min @ 2025-10-14  0:10 UTC (permalink / raw)
  To: lukasz.luba, rafael, len.brown, pavel
  Cc: christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel, Changwoo Min

Send an event to userspace when a performance domain is created or deleted,
or its energy model is updated.

Signed-off-by: Changwoo Min <changwoo@igalia.com>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
---
 kernel/power/energy_model.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index 43a243f9cfa2..92c12b5983ed 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -352,6 +352,8 @@ int em_dev_update_perf_domain(struct device *dev,
 	em_table_free(old_table);
 
 	mutex_unlock(&em_pd_mutex);
+
+	em_notify_pd_updated(pd);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(em_dev_update_perf_domain);
@@ -696,6 +698,7 @@ int em_dev_register_pd_no_update(struct device *dev, unsigned int nr_states,
 	list_add_tail(&dev->em_pd->node, &em_pd_list);
 	mutex_unlock(&em_pd_list_mutex);
 
+	em_notify_pd_created(dev->em_pd);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(em_dev_register_pd_no_update);
@@ -718,6 +721,8 @@ void em_dev_unregister_perf_domain(struct device *dev)
 	list_del_init(&dev->em_pd->node);
 	mutex_unlock(&em_pd_list_mutex);
 
+	em_notify_pd_deleted(dev->em_pd);
+
 	/*
 	 * The mutex separates all register/unregister requests and protects
 	 * from potential clean-up/setup issues in the debugfs directories.
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 01/10] PM: EM: Assign a unique ID when creating a performance domain
  2025-10-14  0:10 ` [PATCH v5 01/10] PM: EM: Assign a unique ID when creating a performance domain Changwoo Min
@ 2025-10-14  8:41   ` Lukasz Luba
  0 siblings, 0 replies; 22+ messages in thread
From: Lukasz Luba @ 2025-10-14  8:41 UTC (permalink / raw)
  To: Changwoo Min
  Cc: christian.loehle, tj, pavel, len.brown, rafael, kernel-dev,
	linux-pm, sched-ext, linux-kernel



On 10/14/25 01:10, Changwoo Min wrote:
> It is necessary to refer to a specific performance domain from a
> userspace. For example, the energy model of a particular performance
> domain is updated.
> 
> To this end, assign a unique ID to each performance domain to address it,
> and manage them in a global linked list to look up a specific one by
> matching ID. IDA is used for ID assignment, and the mutex is used to
> protect the global list from concurrent access.
> 
> Note that the mutex (em_pd_list_mutex) is not supposed to hold while
> holding em_pd_mutex to avoid ABBA deadlock.
> 
> Signed-off-by: Changwoo Min <changwoo@igalia.com>
> ---
>   include/linux/energy_model.h |  4 ++++
>   kernel/power/energy_model.c  | 30 +++++++++++++++++++++++++++++-
>   2 files changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h
> index 61d50571ad88..43aa6153dc57 100644
> --- a/include/linux/energy_model.h
> +++ b/include/linux/energy_model.h
> @@ -54,6 +54,8 @@ struct em_perf_table {
>   /**
>    * struct em_perf_domain - Performance domain
>    * @em_table:		Pointer to the runtime modifiable em_perf_table
> + * @node:		node in	em_pd_list (in energy_model.c)
> + * @id:			A unique ID number for each performance domain
>    * @nr_perf_states:	Number of performance states
>    * @min_perf_state:	Minimum allowed Performance State index
>    * @max_perf_state:	Maximum allowed Performance State index
> @@ -71,6 +73,8 @@ struct em_perf_table {
>    */
>   struct em_perf_domain {
>   	struct em_perf_table __rcu *em_table;
> +	struct list_head node;
> +	int id;
>   	int nr_perf_states;
>   	int min_perf_state;
>   	int max_perf_state;
> diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
> index 5f17d2e8e954..2047b546ad11 100644
> --- a/kernel/power/energy_model.c
> +++ b/kernel/power/energy_model.c
> @@ -23,6 +23,16 @@
>    */
>   static DEFINE_MUTEX(em_pd_mutex);
>   
> +/*
> + * Manage performance domains with IDs. One can iterate the performance domains
> + * through the list and pick one with their associated ID. The mutex serializes
> + * the list access. When holding em_pd_list_mutex, em_pd_mutex should not be
> + * taken to avoid potential deadlock.
> + */
> +static DEFINE_IDA(em_pd_ida);
> +static LIST_HEAD(em_pd_list);
> +static DEFINE_MUTEX(em_pd_list_mutex);
> +
>   static void em_cpufreq_update_efficiencies(struct device *dev,
>   					   struct em_perf_state *table);
>   static void em_check_capacity_update(void);
> @@ -396,7 +406,7 @@ static int em_create_pd(struct device *dev, int nr_states,
>   	struct em_perf_table *em_table;
>   	struct em_perf_domain *pd;
>   	struct device *cpu_dev;
> -	int cpu, ret, num_cpus;
> +	int cpu, ret, num_cpus, id;
>   
>   	if (_is_cpu_device(dev)) {
>   		num_cpus = cpumask_weight(cpus);
> @@ -420,6 +430,13 @@ static int em_create_pd(struct device *dev, int nr_states,
>   
>   	pd->nr_perf_states = nr_states;
>   
> +	INIT_LIST_HEAD(&pd->node);
> +
> +	id = ida_alloc(&em_pd_ida, GFP_KERNEL);
> +	if (id < 0)
> +		return -ENOMEM;
> +	pd->id = id;
> +
>   	em_table = em_table_alloc(pd);
>   	if (!em_table)
>   		goto free_pd;
> @@ -444,6 +461,7 @@ static int em_create_pd(struct device *dev, int nr_states,
>   	kfree(em_table);
>   free_pd:
>   	kfree(pd);
> +	ida_free(&em_pd_ida, id);
>   	return -EINVAL;
>   }
>   
> @@ -660,6 +678,10 @@ int em_dev_register_pd_no_update(struct device *dev, unsigned int nr_states,
>   unlock:
>   	mutex_unlock(&em_pd_mutex);
>   
> +	mutex_lock(&em_pd_list_mutex);
> +	list_add_tail(&dev->em_pd->node, &em_pd_list);
> +	mutex_unlock(&em_pd_list_mutex);
> +
>   	return ret;
>   }
>   EXPORT_SYMBOL_GPL(em_dev_register_pd_no_update);
> @@ -678,6 +700,10 @@ void em_dev_unregister_perf_domain(struct device *dev)
>   	if (_is_cpu_device(dev))
>   		return;
>   
> +	mutex_lock(&em_pd_list_mutex);
> +	list_del_init(&dev->em_pd->node);
> +	mutex_unlock(&em_pd_list_mutex);
> +
>   	/*
>   	 * The mutex separates all register/unregister requests and protects
>   	 * from potential clean-up/setup issues in the debugfs directories.
> @@ -689,6 +715,8 @@ void em_dev_unregister_perf_domain(struct device *dev)
>   	em_table_free(rcu_dereference_protected(dev->em_pd->em_table,
>   						lockdep_is_held(&em_pd_mutex)));
>   
> +	ida_free(&em_pd_ida, dev->em_pd->id);
> +
>   	kfree(dev->em_pd);
>   	dev->em_pd = NULL;
>   	mutex_unlock(&em_pd_mutex);

LGTM,

Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 04/10] PM: EM: Add a skeleton code for netlink notification
  2025-10-14  0:10 ` [PATCH v5 04/10] PM: EM: Add a skeleton code for netlink notification Changwoo Min
@ 2025-10-14  8:43   ` Lukasz Luba
  0 siblings, 0 replies; 22+ messages in thread
From: Lukasz Luba @ 2025-10-14  8:43 UTC (permalink / raw)
  To: Changwoo Min
  Cc: christian.loehle, tj, pavel, len.brown, rafael, kernel-dev,
	linux-pm, sched-ext, linux-kernel



On 10/14/25 01:10, Changwoo Min wrote:
> Add a boilerplate code for netlink notification to register the new
> protocol family. Also, initialize and register the netlink during booting.
> The initialization is called at the postcore level, which is late enough
> after the generic netlink is initialized.
> 
> Finally, update MAINTAINERS to include new files.
> 
> Signed-off-by: Changwoo Min <changwoo@igalia.com>
> ---
>   MAINTAINERS               |  2 +-
>   kernel/power/Makefile     |  5 ++++-
>   kernel/power/em_netlink.c | 35 +++++++++++++++++++++++++++++++++++
>   kernel/power/em_netlink.h | 16 ++++++++++++++++
>   4 files changed, 56 insertions(+), 2 deletions(-)
>   create mode 100644 kernel/power/em_netlink.c
>   create mode 100644 kernel/power/em_netlink.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index babd7088fc1c..bc2c08e6f0ac 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -9182,7 +9182,7 @@ F:	include/linux/energy_model.h
>   F:	Documentation/power/energy-model.rst
>   F:	Documentation/netlink/specs/em.yaml
>   F:	include/uapi/linux/energy_model.h
> -F:	kernel/power/em_netlink_autogen.*
> +F:	kernel/power/em_netlink*.*
>   
>   EPAPR HYPERVISOR BYTE CHANNEL DEVICE DRIVER
>   M:	Laurentiu Tudor <laurentiu.tudor@nxp.com>
> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> index 874ad834dc8d..284a760aade7 100644
> --- a/kernel/power/Makefile
> +++ b/kernel/power/Makefile
> @@ -21,4 +21,7 @@ obj-$(CONFIG_PM_WAKELOCKS)	+= wakelock.o
>   
>   obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
>   
> -obj-$(CONFIG_ENERGY_MODEL)	+= energy_model.o
> +obj-$(CONFIG_ENERGY_MODEL)	+= em.o
> +em-y				:= energy_model.o
> +em-$(CONFIG_NET)		+= em_netlink_autogen.o em_netlink.o
> +
> diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
> new file mode 100644
> index 000000000000..f3fbfeff29a4
> --- /dev/null
> +++ b/kernel/power/em_netlink.c
> @@ -0,0 +1,35 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + *
> + * Generic netlink for energy model.
> + *
> + * Copyright (c) 2025 Valve Corporation.
> + * Author: Changwoo Min <changwoo@igalia.com>
> + */
> +
> +#define pr_fmt(fmt) "energy_model: " fmt
> +
> +#include <linux/energy_model.h>
> +#include <net/sock.h>
> +#include <net/genetlink.h>
> +#include <uapi/linux/energy_model.h>
> +
> +#include "em_netlink.h"
> +#include "em_netlink_autogen.h"
> +
> +int em_nl_get_pds_doit(struct sk_buff *skb, struct genl_info *info)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
> +int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
> +static int __init em_netlink_init(void)
> +{
> +	return genl_register_family(&em_nl_family);
> +}
> +postcore_initcall(em_netlink_init);
> +
> diff --git a/kernel/power/em_netlink.h b/kernel/power/em_netlink.h
> new file mode 100644
> index 000000000000..acd186c92d6b
> --- /dev/null
> +++ b/kernel/power/em_netlink.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + *
> + * Generic netlink for energy model.
> + *
> + * Copyright (c) 2025 Valve Corporation.
> + * Author: Changwoo Min <changwoo@igalia.com>
> + */
> +#ifndef _EM_NETLINK_H
> +#define _EM_NETLINK_H
> +
> +#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_NET)
> +#else
> +#endif
> +
> +#endif /* _EM_NETLINK_H */


LGTM,

Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain
  2025-10-14  0:10 ` [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain Changwoo Min
@ 2025-10-14  8:45   ` Lukasz Luba
  2025-10-15  4:49   ` kernel test robot
  1 sibling, 0 replies; 22+ messages in thread
From: Lukasz Luba @ 2025-10-14  8:45 UTC (permalink / raw)
  To: Changwoo Min
  Cc: christian.loehle, tj, pavel, len.brown, rafael, kernel-dev,
	linux-pm, sched-ext, linux-kernel



On 10/14/25 01:10, Changwoo Min wrote:
> Add an iterator function (for_each_em_perf_domain) that iterates all the
> performance domains in the global list. A passed callback function (cb) is
> called for each performance domain.
> 
> Additionally, add a lookup function (em_perf_domain_get_by_id) that
> searches for a performance domain by matching the ID in the global list.
> 
> Signed-off-by: Changwoo Min <changwoo@igalia.com>
> ---
>   kernel/power/em_netlink.h   | 14 ++++++++++++++
>   kernel/power/energy_model.c | 36 ++++++++++++++++++++++++++++++++++++
>   2 files changed, 50 insertions(+)
> 
> diff --git a/kernel/power/em_netlink.h b/kernel/power/em_netlink.h
> index acd186c92d6b..8114b018c73b 100644
> --- a/kernel/power/em_netlink.h
> +++ b/kernel/power/em_netlink.h
> @@ -10,7 +10,21 @@
>   #define _EM_NETLINK_H
>   
>   #if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_NET)
> +int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
> +			    void *data);
> +struct em_perf_domain *em_perf_domain_get_by_id(int id);
>   #else
> +static inline
> +int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
> +			    void *data)
> +{
> +	return -EINVAL;
> +}
> +static inline
> +struct em_perf_domain *em_perf_domain_get_by_id(int id)
> +{
> +	return NULL;
> +}
>   #endif
>   
>   #endif /* _EM_NETLINK_H */
> diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
> index 756debf5406a..43a243f9cfa2 100644
> --- a/kernel/power/energy_model.c
> +++ b/kernel/power/energy_model.c
> @@ -17,6 +17,8 @@
>   #include <linux/sched/topology.h>
>   #include <linux/slab.h>
>   
> +#include "em_netlink.h"
> +
>   /*
>    * Mutex serializing the registrations of performance domains and letting
>    * callbacks defined by drivers sleep.
> @@ -998,3 +1000,37 @@ void em_rebuild_sched_domains(void)
>   	 */
>   	schedule_work(&rebuild_sd_work);
>   }
> +
> +int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
> +			    void *data)
> +{
> +	struct em_perf_domain *pd;
> +
> +	lockdep_assert_not_held(&em_pd_mutex);
> +	guard(mutex)(&em_pd_list_mutex);
> +
> +	list_for_each_entry(pd, &em_pd_list, node) {
> +		int ret;
> +
> +		ret = cb(pd, data);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +struct em_perf_domain *em_perf_domain_get_by_id(int id)
> +{
> +	struct em_perf_domain *pd;
> +
> +	lockdep_assert_not_held(&em_pd_mutex);
> +	guard(mutex)(&em_pd_list_mutex);
> +
> +	list_for_each_entry(pd, &em_pd_list, node) {
> +		if (pd->id == id)
> +			return pd;
> +	}
> +
> +	return NULL;
> +}



LGTM,

Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted()
  2025-10-14  0:10 ` [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted() Changwoo Min
@ 2025-10-14  8:47   ` Lukasz Luba
  2025-10-15  4:16   ` kernel test robot
  1 sibling, 0 replies; 22+ messages in thread
From: Lukasz Luba @ 2025-10-14  8:47 UTC (permalink / raw)
  To: Changwoo Min
  Cc: christian.loehle, tj, pavel, len.brown, rafael, kernel-dev,
	linux-pm, sched-ext, linux-kernel



On 10/14/25 01:10, Changwoo Min wrote:
> Add the event notification infrastructure and implement the event
> notification for when a performance domain is deleted (EM_CMD_PD_DELETED).
> 
> The event contains the ID of the performance domain (EM_A_PD_TABLE_PD_ID)
> so the userspace can identify the changed performance domain for further
> processing.
> 
> Signed-off-by: Changwoo Min <changwoo@igalia.com>
> ---
>   kernel/power/em_netlink.c | 46 +++++++++++++++++++++++++++++++++++++++
>   kernel/power/em_netlink.h |  3 +++
>   2 files changed, 49 insertions(+)
> 
> diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
> index 2addc143401b..90ae6f1c9c9a 100644
> --- a/kernel/power/em_netlink.c
> +++ b/kernel/power/em_netlink.c
> @@ -213,6 +213,52 @@ int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
>   	return ret;
>   }
>   
> +
> +/**************************** Event encoding *********************************/
> +static int __em_notify_pd_deleted_size(const struct em_perf_domain *pd)
> +{
> +	int id_sz = nla_total_size(sizeof(u32)); /* EM_A_PD_TABLE_PD_ID */
> +
> +	return nlmsg_total_size(genlmsg_msg_size(id_sz));
> +}
> +
> +void em_notify_pd_deleted(const struct em_perf_domain *pd)
> +{
> +	struct sk_buff *msg;
> +	int ret = -EMSGSIZE;
> +	void *hdr;
> +	int msg_sz;
> +
> +	if (!genl_has_listeners(&em_nl_family, &init_net, EM_NLGRP_EVENT))
> +		return;
> +
> +	msg_sz = __em_notify_pd_deleted_size(pd);
> +
> +	msg = genlmsg_new(msg_sz, GFP_KERNEL);
> +	if (!msg)
> +		return;
> +
> +	hdr = genlmsg_put(msg, 0, 0, &em_nl_family, 0, EM_CMD_PD_DELETED);
> +	if (!hdr)
> +		goto out_free_msg;
> +
> +	if (nla_put_u32(msg, EM_A_PD_TABLE_PD_ID, pd->id)) {
> +		ret = -EMSGSIZE;
> +		goto out_free_msg;
> +	}
> +
> +	genlmsg_end(msg, hdr);
> +
> +	genlmsg_multicast(&em_nl_family, msg, 0, EM_NLGRP_EVENT, GFP_KERNEL);
> +
> +	return;
> +
> +out_free_msg:
> +	nlmsg_free(msg);
> +	return;
> +}
> +
> +/**************************** Initialization *********************************/
>   static int __init em_netlink_init(void)
>   {
>   	return genl_register_family(&em_nl_family);
> diff --git a/kernel/power/em_netlink.h b/kernel/power/em_netlink.h
> index 8114b018c73b..d56e5865e1ed 100644
> --- a/kernel/power/em_netlink.h
> +++ b/kernel/power/em_netlink.h
> @@ -13,6 +13,7 @@
>   int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
>   			    void *data);
>   struct em_perf_domain *em_perf_domain_get_by_id(int id);
> +void em_notify_pd_deleted(const struct em_perf_domain *pd);
>   #else
>   static inline
>   int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
> @@ -25,6 +26,8 @@ struct em_perf_domain *em_perf_domain_get_by_id(int id)
>   {
>   	return NULL;
>   }
> +
> +static inline void em_notify_pd_deleted(const struct em_perf_domain *pd) {}
>   #endif
>   
>   #endif /* _EM_NETLINK_H */


LGTM,

Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 09/10] PM: EM: Implement em_notify_pd_created/updated()
  2025-10-14  0:10 ` [PATCH v5 09/10] PM: EM: Implement em_notify_pd_created/updated() Changwoo Min
@ 2025-10-14  8:48   ` Lukasz Luba
  0 siblings, 0 replies; 22+ messages in thread
From: Lukasz Luba @ 2025-10-14  8:48 UTC (permalink / raw)
  To: Changwoo Min
  Cc: christian.loehle, tj, pavel, len.brown, rafael, kernel-dev,
	linux-pm, sched-ext, linux-kernel



On 10/14/25 01:10, Changwoo Min wrote:
> Implement two event notifications when a performance domain is created
> (EM_CMD_PD_CREATED) and updated (EM_CMD_PD_UPDATED). The message format
> of these two event notifications is the same as EM_CMD_GET_PD_TABLE --
> containing the performance domain's ID and its energy model table.
> 
> Signed-off-by: Changwoo Min <changwoo@igalia.com>
> ---
>   kernel/power/em_netlink.c | 44 +++++++++++++++++++++++++++++++++++++++
>   kernel/power/em_netlink.h |  6 ++++++
>   2 files changed, 50 insertions(+)
> 
> diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
> index 90ae6f1c9c9a..2c55c758de6b 100644
> --- a/kernel/power/em_netlink.c
> +++ b/kernel/power/em_netlink.c
> @@ -215,6 +215,50 @@ int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
>   
>   
>   /**************************** Event encoding *********************************/
> +static void __em_notify_pd_table(const struct em_perf_domain *pd, int ntf_type)
> +{
> +	struct sk_buff *msg;
> +	int msg_sz, ret = -EMSGSIZE;
> +	void *hdr;
> +
> +	if (!genl_has_listeners(&em_nl_family, &init_net, EM_NLGRP_EVENT))
> +		return;
> +
> +	msg_sz = __em_nl_get_pd_table_size(pd);
> +
> +	msg = genlmsg_new(msg_sz, GFP_KERNEL);
> +	if (!msg)
> +		return;
> +
> +	hdr = genlmsg_put(msg, 0, 0, &em_nl_family, 0, ntf_type);
> +	if (!hdr)
> +		goto out_free_msg;
> +
> +	ret = __em_nl_get_pd_table(msg, pd);
> +	if (ret)
> +		goto out_free_msg;
> +
> +	genlmsg_end(msg, hdr);
> +
> +	genlmsg_multicast(&em_nl_family, msg, 0, EM_NLGRP_EVENT, GFP_KERNEL);
> +
> +	return;
> +
> +out_free_msg:
> +	nlmsg_free(msg);
> +	return;
> +}
> +
> +void em_notify_pd_created(const struct em_perf_domain *pd)
> +{
> +	__em_notify_pd_table(pd, EM_CMD_PD_CREATED);
> +}
> +
> +void em_notify_pd_updated(const struct em_perf_domain *pd)
> +{
> +	__em_notify_pd_table(pd, EM_CMD_PD_UPDATED);
> +}
> +
>   static int __em_notify_pd_deleted_size(const struct em_perf_domain *pd)
>   {
>   	int id_sz = nla_total_size(sizeof(u32)); /* EM_A_PD_TABLE_PD_ID */
> diff --git a/kernel/power/em_netlink.h b/kernel/power/em_netlink.h
> index d56e5865e1ed..583d7f1c3939 100644
> --- a/kernel/power/em_netlink.h
> +++ b/kernel/power/em_netlink.h
> @@ -13,7 +13,9 @@
>   int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
>   			    void *data);
>   struct em_perf_domain *em_perf_domain_get_by_id(int id);
> +void em_notify_pd_created(const struct em_perf_domain *pd);
>   void em_notify_pd_deleted(const struct em_perf_domain *pd);
> +void em_notify_pd_updated(const struct em_perf_domain *pd);
>   #else
>   static inline
>   int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
> @@ -27,7 +29,11 @@ struct em_perf_domain *em_perf_domain_get_by_id(int id)
>   	return NULL;
>   }
>   
> +static inline void em_notify_pd_created(const struct em_perf_domain *pd) {}
> +
>   static inline void em_notify_pd_deleted(const struct em_perf_domain *pd) {}
> +
> +static inline void em_notify_pd_updated(const struct em_perf_domain *pd) {}
>   #endif
>   
>   #endif /* _EM_NETLINK_H */



Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 00/10] PM: EM: Add netlink support for the energy model
  2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
                   ` (9 preceding siblings ...)
  2025-10-14  0:10 ` [PATCH v5 10/10] PM: EM: Notify an event when the performance domain changes Changwoo Min
@ 2025-10-14  8:54 ` Lukasz Luba
  10 siblings, 0 replies; 22+ messages in thread
From: Lukasz Luba @ 2025-10-14  8:54 UTC (permalink / raw)
  To: Changwoo Min
  Cc: christian.loehle, tj, pavel, len.brown, rafael, kernel-dev,
	linux-pm, sched-ext, linux-kernel



On 10/14/25 01:10, Changwoo Min wrote:
> Addressed all the comments from Lukasz and rebased the code to the head
> of the linus tree.
> 
> There is a need to access the energy model from the userspace. One such
> example is the sched_ext schedulers [1]. The userspace part of the
> sched_ext schedules could feed the (post-processed) energy-model
> information to the BPF part of the scheduler.
> 
> Currently, debugfs is the only way to read the energy model from userspace;
> however, it lacks proper notification mechanisms when a performance domain
> and its associated energy model change.
> 
> This patch set introduces a generic netlink for the energy model, as
> discussed in [2]. It allows a userspace program to read the performance
> domain and its energy model. It notifies the userspace program when a
> performance domain is created or deleted or its energy model is updated
> through a multicast interface.
> 
> Specifically, it supports two commands:
>    - EM_CMD_GET_PDS: Get the list of information for all performance
>      domains.
>    - EM_CMD_GET_PD_TABLE: Get the energy model table of a performance
>      domain.
> 
> Also, it supports three notification events:
>    - EM_CMD_PD_CREATED: When a performance domain is created.
>    - EM_CMD_PD_DELETED: When a performance domain is deleted.
>    - EM_CMD_PD_UPDATED: When the energy model table of a performance domain
>      is updated.
> 
> This can be tested using the tool, tools/net/ynl/pyynl/cli.py, for example,
> with the following commands:
> 
>    $> tools/net/ynl/pyynl/cli.py \
>       --spec Documentation/netlink/specs/em.yaml \
>       --do get-pds
>    $> tools/net/ynl/pyynl/cli.py \
>       --spec Documentation/netlink/specs/em.yaml \
>       --do get-pd-table --json '{"pd-id": 0}'
>    $> tools/net/ynl/pyynl/cli.py \
>       --spec Documentation/netlink/specs/em.yaml \
>       --subscribe event  --sleep 10
> 
> [1] https://lwn.net/Articles/922405/
> [2] https://lore.kernel.org/lkml/a82423bc-8c38-4d57-93da-c4f20011cc92@arm.com/
> [3] https://lore.kernel.org/lkml/202506140306.tuIoz8rN-lkp@intel.com/#t

Thank you Changwoo, it looks good.

The patches can go now into some PM testing branches so we can check the
integration/testing in wider configurations.

Regards,
Lukasz

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted()
  2025-10-14  0:10 ` [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted() Changwoo Min
  2025-10-14  8:47   ` Lukasz Luba
@ 2025-10-15  4:16   ` kernel test robot
  2025-10-20 17:48     ` Rafael J. Wysocki
  1 sibling, 1 reply; 22+ messages in thread
From: kernel test robot @ 2025-10-15  4:16 UTC (permalink / raw)
  To: Changwoo Min, lukasz.luba, rafael, len.brown, pavel
  Cc: llvm, oe-kbuild-all, christian.loehle, tj, kernel-dev, linux-pm,
	sched-ext, linux-kernel, Changwoo Min

Hi Changwoo,

kernel test robot noticed the following build warnings:

[auto build test WARNING on amd-pstate/linux-next]
[also build test WARNING on amd-pstate/bleeding-edge linus/master v6.18-rc1 next-20251014]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Changwoo-Min/PM-EM-Assign-a-unique-ID-when-creating-a-performance-domain/20251014-082420
base:   https://git.kernel.org/pub/scm/linux/kernel/git/superm1/linux.git linux-next
patch link:    https://lore.kernel.org/r/20251014001055.772422-9-changwoo%40igalia.com
patch subject: [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted()
config: i386-buildonly-randconfig-004-20251015 (https://download.01.org/0day-ci/archive/20251015/202510151223.THlBK6QR-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251015/202510151223.THlBK6QR-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510151223.THlBK6QR-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> kernel/power/em_netlink.c:228:6: warning: variable 'ret' set but not used [-Wunused-but-set-variable]
     228 |         int ret = -EMSGSIZE;
         |             ^
   1 warning generated.


vim +/ret +228 kernel/power/em_netlink.c

   224	
   225	void em_notify_pd_deleted(const struct em_perf_domain *pd)
   226	{
   227		struct sk_buff *msg;
 > 228		int ret = -EMSGSIZE;
   229		void *hdr;
   230		int msg_sz;
   231	
   232		if (!genl_has_listeners(&em_nl_family, &init_net, EM_NLGRP_EVENT))
   233			return;
   234	
   235		msg_sz = __em_notify_pd_deleted_size(pd);
   236	
   237		msg = genlmsg_new(msg_sz, GFP_KERNEL);
   238		if (!msg)
   239			return;
   240	
   241		hdr = genlmsg_put(msg, 0, 0, &em_nl_family, 0, EM_CMD_PD_DELETED);
   242		if (!hdr)
   243			goto out_free_msg;
   244	
   245		if (nla_put_u32(msg, EM_A_PD_TABLE_PD_ID, pd->id)) {
   246			ret = -EMSGSIZE;
   247			goto out_free_msg;
   248		}
   249	
   250		genlmsg_end(msg, hdr);
   251	
   252		genlmsg_multicast(&em_nl_family, msg, 0, EM_NLGRP_EVENT, GFP_KERNEL);
   253	
   254		return;
   255	
   256	out_free_msg:
   257		nlmsg_free(msg);
   258		return;
   259	}
   260	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain
  2025-10-14  0:10 ` [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain Changwoo Min
  2025-10-14  8:45   ` Lukasz Luba
@ 2025-10-15  4:49   ` kernel test robot
  2025-10-20 17:44     ` Rafael J. Wysocki
  1 sibling, 1 reply; 22+ messages in thread
From: kernel test robot @ 2025-10-15  4:49 UTC (permalink / raw)
  To: Changwoo Min, lukasz.luba, rafael, len.brown, pavel
  Cc: oe-kbuild-all, christian.loehle, tj, kernel-dev, linux-pm,
	sched-ext, linux-kernel, Changwoo Min

Hi Changwoo,

kernel test robot noticed the following build errors:

[auto build test ERROR on amd-pstate/linux-next]
[also build test ERROR on amd-pstate/bleeding-edge linus/master v6.18-rc1 next-20251014]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Changwoo-Min/PM-EM-Assign-a-unique-ID-when-creating-a-performance-domain/20251014-082420
base:   https://git.kernel.org/pub/scm/linux/kernel/git/superm1/linux.git linux-next
patch link:    https://lore.kernel.org/r/20251014001055.772422-6-changwoo%40igalia.com
patch subject: [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain
config: i386-buildonly-randconfig-001-20251015 (https://download.01.org/0day-ci/archive/20251015/202510151232.UNZ2J7TZ-lkp@intel.com/config)
compiler: gcc-13 (Debian 13.3.0-16) 13.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251015/202510151232.UNZ2J7TZ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510151232.UNZ2J7TZ-lkp@intel.com/

All errors (new ones prefixed by >>):

>> kernel/power/energy_model.c:1003:5: error: redefinition of 'for_each_em_perf_domain'
    1003 | int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
         |     ^~~~~~~~~~~~~~~~~~~~~~~
   In file included from kernel/power/energy_model.c:20:
   kernel/power/em_netlink.h:18:5: note: previous definition of 'for_each_em_perf_domain' with type 'int(int (*)(struct em_perf_domain *, void *), void *)'
      18 | int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
         |     ^~~~~~~~~~~~~~~~~~~~~~~
>> kernel/power/energy_model.c:1022:24: error: redefinition of 'em_perf_domain_get_by_id'
    1022 | struct em_perf_domain *em_perf_domain_get_by_id(int id)
         |                        ^~~~~~~~~~~~~~~~~~~~~~~~
   kernel/power/em_netlink.h:24:24: note: previous definition of 'em_perf_domain_get_by_id' with type 'struct em_perf_domain *(int)'
      24 | struct em_perf_domain *em_perf_domain_get_by_id(int id)
         |                        ^~~~~~~~~~~~~~~~~~~~~~~~


vim +/for_each_em_perf_domain +1003 kernel/power/energy_model.c

  1002	
> 1003	int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
  1004				    void *data)
  1005	{
  1006		struct em_perf_domain *pd;
  1007	
  1008		lockdep_assert_not_held(&em_pd_mutex);
  1009		guard(mutex)(&em_pd_list_mutex);
  1010	
  1011		list_for_each_entry(pd, &em_pd_list, node) {
  1012			int ret;
  1013	
  1014			ret = cb(pd, data);
  1015			if (ret)
  1016				return ret;
  1017		}
  1018	
  1019		return 0;
  1020	}
  1021	
> 1022	struct em_perf_domain *em_perf_domain_get_by_id(int id)

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain
  2025-10-15  4:49   ` kernel test robot
@ 2025-10-20 17:44     ` Rafael J. Wysocki
  2025-10-20 21:35       ` Changwoo Min
  0 siblings, 1 reply; 22+ messages in thread
From: Rafael J. Wysocki @ 2025-10-20 17:44 UTC (permalink / raw)
  To: kernel test robot, Changwoo Min
  Cc: lukasz.luba, rafael, len.brown, pavel, oe-kbuild-all,
	christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel

On Wed, Oct 15, 2025 at 6:50 AM kernel test robot <lkp@intel.com> wrote:
>
> Hi Changwoo,
>
> kernel test robot noticed the following build errors:
>
> [auto build test ERROR on amd-pstate/linux-next]
> [also build test ERROR on amd-pstate/bleeding-edge linus/master v6.18-rc1 next-20251014]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Changwoo-Min/PM-EM-Assign-a-unique-ID-when-creating-a-performance-domain/20251014-082420
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/superm1/linux.git linux-next
> patch link:    https://lore.kernel.org/r/20251014001055.772422-6-changwoo%40igalia.com
> patch subject: [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain
> config: i386-buildonly-randconfig-001-20251015 (https://download.01.org/0day-ci/archive/20251015/202510151232.UNZ2J7TZ-lkp@intel.com/config)
> compiler: gcc-13 (Debian 13.3.0-16) 13.3.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251015/202510151232.UNZ2J7TZ-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202510151232.UNZ2J7TZ-lkp@intel.com/
>
> All errors (new ones prefixed by >>):
>
> >> kernel/power/energy_model.c:1003:5: error: redefinition of 'for_each_em_perf_domain'
>     1003 | int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
>          |     ^~~~~~~~~~~~~~~~~~~~~~~
>    In file included from kernel/power/energy_model.c:20:
>    kernel/power/em_netlink.h:18:5: note: previous definition of 'for_each_em_perf_domain' with type 'int(int (*)(struct em_perf_domain *, void *), void *)'
>       18 | int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
>          |     ^~~~~~~~~~~~~~~~~~~~~~~
> >> kernel/power/energy_model.c:1022:24: error: redefinition of 'em_perf_domain_get_by_id'
>     1022 | struct em_perf_domain *em_perf_domain_get_by_id(int id)
>          |                        ^~~~~~~~~~~~~~~~~~~~~~~~
>    kernel/power/em_netlink.h:24:24: note: previous definition of 'em_perf_domain_get_by_id' with type 'struct em_perf_domain *(int)'
>       24 | struct em_perf_domain *em_perf_domain_get_by_id(int id)
>          |                        ^~~~~~~~~~~~~~~~~~~~~~~~
>

Please update the patch to address this report and resend it, thanks!

> vim +/for_each_em_perf_domain +1003 kernel/power/energy_model.c
>
>   1002
> > 1003  int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
>   1004                              void *data)
>   1005  {
>   1006          struct em_perf_domain *pd;
>   1007
>   1008          lockdep_assert_not_held(&em_pd_mutex);
>   1009          guard(mutex)(&em_pd_list_mutex);
>   1010
>   1011          list_for_each_entry(pd, &em_pd_list, node) {
>   1012                  int ret;
>   1013
>   1014                  ret = cb(pd, data);
>   1015                  if (ret)
>   1016                          return ret;
>   1017          }
>   1018
>   1019          return 0;
>   1020  }
>   1021
> > 1022  struct em_perf_domain *em_perf_domain_get_by_id(int id)
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted()
  2025-10-15  4:16   ` kernel test robot
@ 2025-10-20 17:48     ` Rafael J. Wysocki
  0 siblings, 0 replies; 22+ messages in thread
From: Rafael J. Wysocki @ 2025-10-20 17:48 UTC (permalink / raw)
  To: kernel test robot, Changwoo Min
  Cc: lukasz.luba, rafael, len.brown, pavel, llvm, oe-kbuild-all,
	christian.loehle, tj, kernel-dev, linux-pm, sched-ext,
	linux-kernel

On Wed, Oct 15, 2025 at 6:17 AM kernel test robot <lkp@intel.com> wrote:
>
> Hi Changwoo,
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on amd-pstate/linux-next]
> [also build test WARNING on amd-pstate/bleeding-edge linus/master v6.18-rc1 next-20251014]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Changwoo-Min/PM-EM-Assign-a-unique-ID-when-creating-a-performance-domain/20251014-082420
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/superm1/linux.git linux-next
> patch link:    https://lore.kernel.org/r/20251014001055.772422-9-changwoo%40igalia.com
> patch subject: [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted()
> config: i386-buildonly-randconfig-004-20251015 (https://download.01.org/0day-ci/archive/20251015/202510151223.THlBK6QR-lkp@intel.com/config)
> compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251015/202510151223.THlBK6QR-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202510151223.THlBK6QR-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> >> kernel/power/em_netlink.c:228:6: warning: variable 'ret' set but not used [-Wunused-but-set-variable]
>      228 |         int ret = -EMSGSIZE;
>          |             ^
>    1 warning generated.
>

Please update the patch to address this report and resend it, thanks!

> vim +/ret +228 kernel/power/em_netlink.c
>
>    224
>    225  void em_notify_pd_deleted(const struct em_perf_domain *pd)
>    226  {
>    227          struct sk_buff *msg;
>  > 228          int ret = -EMSGSIZE;
>    229          void *hdr;
>    230          int msg_sz;
>    231
>    232          if (!genl_has_listeners(&em_nl_family, &init_net, EM_NLGRP_EVENT))
>    233                  return;
>    234
>    235          msg_sz = __em_notify_pd_deleted_size(pd);
>    236
>    237          msg = genlmsg_new(msg_sz, GFP_KERNEL);
>    238          if (!msg)
>    239                  return;
>    240
>    241          hdr = genlmsg_put(msg, 0, 0, &em_nl_family, 0, EM_CMD_PD_DELETED);
>    242          if (!hdr)
>    243                  goto out_free_msg;
>    244
>    245          if (nla_put_u32(msg, EM_A_PD_TABLE_PD_ID, pd->id)) {
>    246                  ret = -EMSGSIZE;
>    247                  goto out_free_msg;
>    248          }
>    249
>    250          genlmsg_end(msg, hdr);
>    251
>    252          genlmsg_multicast(&em_nl_family, msg, 0, EM_NLGRP_EVENT, GFP_KERNEL);
>    253
>    254          return;
>    255
>    256  out_free_msg:
>    257          nlmsg_free(msg);
>    258          return;
>    259  }
>    260
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain
  2025-10-20 17:44     ` Rafael J. Wysocki
@ 2025-10-20 21:35       ` Changwoo Min
  0 siblings, 0 replies; 22+ messages in thread
From: Changwoo Min @ 2025-10-20 21:35 UTC (permalink / raw)
  To: Rafael J. Wysocki, kernel test robot
  Cc: lukasz.luba, len.brown, pavel, oe-kbuild-all, christian.loehle,
	tj, kernel-dev, linux-pm, sched-ext, linux-kernel

Hi Rafael,

On 10/21/25 02:44, Rafael J. Wysocki wrote:
> On Wed, Oct 15, 2025 at 6:50 AM kernel test robot <lkp@intel.com> wrote:
>>
>> Hi Changwoo,
>>
>> kernel test robot noticed the following build errors:
>>
>> [auto build test ERROR on amd-pstate/linux-next]
>> [also build test ERROR on amd-pstate/bleeding-edge linus/master v6.18-rc1 next-20251014]
>> [If your patch is applied to the wrong git tree, kindly drop us a note.
>> And when submitting patch, we suggest to use '--base' as documented in
>> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>>
>> url:    https://github.com/intel-lab-lkp/linux/commits/Changwoo-Min/PM-EM-Assign-a-unique-ID-when-creating-a-performance-domain/20251014-082420
>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/superm1/linux.git linux-next
>> patch link:    https://lore.kernel.org/r/20251014001055.772422-6-changwoo%40igalia.com
>> patch subject: [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain
>> config: i386-buildonly-randconfig-001-20251015 (https://download.01.org/0day-ci/archive/20251015/202510151232.UNZ2J7TZ-lkp@intel.com/config)
>> compiler: gcc-13 (Debian 13.3.0-16) 13.3.0
>> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251015/202510151232.UNZ2J7TZ-lkp@intel.com/reproduce)
>>
>> If you fix the issue in a separate patch/commit (i.e. not just a new version of
>> the same patch/commit), kindly add following tags
>> | Reported-by: kernel test robot <lkp@intel.com>
>> | Closes: https://lore.kernel.org/oe-kbuild-all/202510151232.UNZ2J7TZ-lkp@intel.com/
>>
>> All errors (new ones prefixed by >>):
>>
>>>> kernel/power/energy_model.c:1003:5: error: redefinition of 'for_each_em_perf_domain'
>>      1003 | int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
>>           |     ^~~~~~~~~~~~~~~~~~~~~~~
>>     In file included from kernel/power/energy_model.c:20:
>>     kernel/power/em_netlink.h:18:5: note: previous definition of 'for_each_em_perf_domain' with type 'int(int (*)(struct em_perf_domain *, void *), void *)'
>>        18 | int for_each_em_perf_domain(int (*cb)(struct em_perf_domain*, void *),
>>           |     ^~~~~~~~~~~~~~~~~~~~~~~
>>>> kernel/power/energy_model.c:1022:24: error: redefinition of 'em_perf_domain_get_by_id'
>>      1022 | struct em_perf_domain *em_perf_domain_get_by_id(int id)
>>           |                        ^~~~~~~~~~~~~~~~~~~~~~~~
>>     kernel/power/em_netlink.h:24:24: note: previous definition of 'em_perf_domain_get_by_id' with type 'struct em_perf_domain *(int)'
>>        24 | struct em_perf_domain *em_perf_domain_get_by_id(int id)
>>           |                        ^~~~~~~~~~~~~~~~~~~~~~~~
>>
> 
> Please update the patch to address this report and resend it, thanks!

Sure, I will send v6 with these two fixes in.

Regards,
Changwoo Min

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2025-10-20 21:35 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-14  0:10 [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Changwoo Min
2025-10-14  0:10 ` [PATCH v5 01/10] PM: EM: Assign a unique ID when creating a performance domain Changwoo Min
2025-10-14  8:41   ` Lukasz Luba
2025-10-14  0:10 ` [PATCH v5 02/10] PM: EM: Expose the ID of a performance domain via debugfs Changwoo Min
2025-10-14  0:10 ` [PATCH v5 03/10] PM: EM: Add em.yaml and autogen files Changwoo Min
2025-10-14  0:10 ` [PATCH v5 04/10] PM: EM: Add a skeleton code for netlink notification Changwoo Min
2025-10-14  8:43   ` Lukasz Luba
2025-10-14  0:10 ` [PATCH v5 05/10] PM: EM: Add an iterator and accessor for the performance domain Changwoo Min
2025-10-14  8:45   ` Lukasz Luba
2025-10-15  4:49   ` kernel test robot
2025-10-20 17:44     ` Rafael J. Wysocki
2025-10-20 21:35       ` Changwoo Min
2025-10-14  0:10 ` [PATCH v5 06/10] PM: EM: Implement em_nl_get_pds_doit() Changwoo Min
2025-10-14  0:10 ` [PATCH v5 07/10] PM: EM: Implement em_nl_get_pd_table_doit() Changwoo Min
2025-10-14  0:10 ` [PATCH v5 08/10] PM: EM: Implement em_notify_pd_deleted() Changwoo Min
2025-10-14  8:47   ` Lukasz Luba
2025-10-15  4:16   ` kernel test robot
2025-10-20 17:48     ` Rafael J. Wysocki
2025-10-14  0:10 ` [PATCH v5 09/10] PM: EM: Implement em_notify_pd_created/updated() Changwoo Min
2025-10-14  8:48   ` Lukasz Luba
2025-10-14  0:10 ` [PATCH v5 10/10] PM: EM: Notify an event when the performance domain changes Changwoo Min
2025-10-14  8:54 ` [PATCH v5 00/10] PM: EM: Add netlink support for the energy model Lukasz Luba

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).