Re: [Intel-wired-lan] [PATCH net-next 05/12] dpll: Add notifier chain for dpll events

2026-01-09 Thread Vadim Fedorenko

On 08/01/2026 18:23, Ivan Vecera wrote:

From: Petr Oros 

Currently, the DPLL subsystem reports events (creation, deletion, changes)
to userspace via Netlink. However, there is no mechanism for other kernel
components to be notified of these events directly.

Add a raw notifier chain to the DPLL core protected by dpll_lock. This
allows other kernel subsystems or drivers to register callbacks and
receive notifications when DPLL devices or pins are created, deleted,
or modified.

Define the following:
- Registration helpers: {,un}register_dpll_notifier()
- Event types: DPLL_DEVICE_CREATED, DPLL_PIN_CREATED, etc.
- Context structures: dpll_{device,pin}_notifier_info  to pass relevant
   data to the listeners.

The notification chain is invoked alongside the existing Netlink event
generation to ensure in-kernel listeners are kept in sync with the
subsystem state.

Co-developed-by: Ivan Vecera 
Signed-off-by: Ivan Vecera 
Signed-off-by: Petr Oros 


LGTM, Thanks!

Reviewed-by: Vadim Fedorenko 


[Intel-wired-lan] [PATCH net-next 05/12] dpll: Add notifier chain for dpll events

2026-01-08 Thread Ivan Vecera
From: Petr Oros 

Currently, the DPLL subsystem reports events (creation, deletion, changes)
to userspace via Netlink. However, there is no mechanism for other kernel
components to be notified of these events directly.

Add a raw notifier chain to the DPLL core protected by dpll_lock. This
allows other kernel subsystems or drivers to register callbacks and
receive notifications when DPLL devices or pins are created, deleted,
or modified.

Define the following:
- Registration helpers: {,un}register_dpll_notifier()
- Event types: DPLL_DEVICE_CREATED, DPLL_PIN_CREATED, etc.
- Context structures: dpll_{device,pin}_notifier_info  to pass relevant
  data to the listeners.

The notification chain is invoked alongside the existing Netlink event
generation to ensure in-kernel listeners are kept in sync with the
subsystem state.

Co-developed-by: Ivan Vecera 
Signed-off-by: Ivan Vecera 
Signed-off-by: Petr Oros 
---
 drivers/dpll/dpll_core.c| 57 +
 drivers/dpll/dpll_core.h|  4 +++
 drivers/dpll/dpll_netlink.c |  6 
 include/linux/dpll.h| 29 +++
 4 files changed, 96 insertions(+)

diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index 23d04a9d022d7..4efa7fbd8f21f 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -23,6 +23,8 @@ DEFINE_MUTEX(dpll_lock);
 DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
 DEFINE_XARRAY_FLAGS(dpll_pin_xa, XA_FLAGS_ALLOC);
 
+static RAW_NOTIFIER_HEAD(dpll_notifier_chain);
+
 static u32 dpll_device_xa_id;
 static u32 dpll_pin_xa_id;
 
@@ -46,6 +48,39 @@ struct dpll_pin_registration {
void *cookie;
 };
 
+static int call_dpll_notifiers(unsigned long action, void *info)
+{
+   lockdep_assert_held(&dpll_lock);
+   return raw_notifier_call_chain(&dpll_notifier_chain, action, info);
+}
+
+void dpll_device_notify(struct dpll_device *dpll, unsigned long action)
+{
+   struct dpll_device_notifier_info info = {
+   .dpll = dpll,
+   .id = dpll->id,
+   .idx = dpll->device_idx,
+   .clock_id = dpll->clock_id,
+   .type = dpll->type,
+   };
+
+   call_dpll_notifiers(action, &info);
+}
+
+void dpll_pin_notify(struct dpll_pin *pin, unsigned long action)
+{
+   struct dpll_pin_notifier_info info = {
+   .pin = pin,
+   .id = pin->id,
+   .idx = pin->pin_idx,
+   .clock_id = pin->clock_id,
+   .fwnode = pin->fwnode,
+   .prop = &pin->prop,
+   };
+
+   call_dpll_notifiers(action, &info);
+}
+
 struct dpll_device *dpll_device_get_by_id(int id)
 {
if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
@@ -543,6 +578,28 @@ void dpll_netdev_pin_clear(struct net_device *dev)
 }
 EXPORT_SYMBOL(dpll_netdev_pin_clear);
 
+int register_dpll_notifier(struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(&dpll_lock);
+   ret = raw_notifier_chain_register(&dpll_notifier_chain, nb);
+   mutex_unlock(&dpll_lock);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(register_dpll_notifier);
+
+int unregister_dpll_notifier(struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(&dpll_lock);
+   ret = raw_notifier_chain_unregister(&dpll_notifier_chain, nb);
+   mutex_unlock(&dpll_lock);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(unregister_dpll_notifier);
+
 /**
  * dpll_pin_get - find existing or create new dpll pin
  * @clock_id: clock_id of creator
diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
index d3e17ff0ecef0..b7b4bb251f739 100644
--- a/drivers/dpll/dpll_core.h
+++ b/drivers/dpll/dpll_core.h
@@ -91,4 +91,8 @@ struct dpll_pin_ref *dpll_xa_ref_dpll_first(struct xarray 
*xa_refs);
 extern struct xarray dpll_device_xa;
 extern struct xarray dpll_pin_xa;
 extern struct mutex dpll_lock;
+
+void dpll_device_notify(struct dpll_device *dpll, unsigned long action);
+void dpll_pin_notify(struct dpll_pin *pin, unsigned long action);
+
 #endif
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 64944f601ee5a..fe9c3d9073f0f 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -742,17 +742,20 @@ dpll_device_event_send(enum dpll_cmd event, struct 
dpll_device *dpll)
 
 int dpll_device_create_ntf(struct dpll_device *dpll)
 {
+   dpll_device_notify(dpll, DPLL_DEVICE_CREATED);
return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF, dpll);
 }
 
 int dpll_device_delete_ntf(struct dpll_device *dpll)
 {
+   dpll_device_notify(dpll, DPLL_DEVICE_DELETED);
return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll);
 }
 
 static int
 __dpll_device_change_ntf(struct dpll_device *dpll)
 {
+   dpll_device_notify(dpll, DPLL_DEVICE_CHANGED);
return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll);
 }
 
@@ -810,16 +813,19 @@ dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin 
*pin)
 
 int dpll_pin_create_n