public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] dpll: add pin operational state
@ 2026-04-28 15:49 Ivan Vecera
  2026-04-28 15:49 ` [PATCH net-next 1/2] " Ivan Vecera
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Ivan Vecera @ 2026-04-28 15:49 UTC (permalink / raw)
  To: netdev
  Cc: Arkadiusz Kubalewski, David S. Miller, Donald Hunter,
	Eric Dumazet, Jakub Kicinski, Jiri Pirko, Jonathan Corbet,
	Michal Schmidt, Paolo Abeni, Pasi Vaananen, Petr Oros,
	Prathosh Satish, Shuah Khan, Simon Horman, Vadim Fedorenko,
	linux-doc, linux-kernel

Add pin operational state (operstate) to the DPLL subsystem to
separate administrative intent from actual hardware status.

Currently pin-state mixes what the user requested (connected,
selectable, disconnected) with what the hardware is actually doing.
This makes it difficult to diagnose situations where a user sets
a pin as selectable or connected but the hardware cannot use it
due to signal issues.

The new operstate attribute is reported inside the pin-parent-device
nest alongside the existing state and is read-only. Defined values:

  - active: pin is qualified and actively used by the DPLL
  - standby: pin is qualified but not actively used by the DPLL
  - no-signal: pin does not have a valid signal
  - qual-failed: pin signal failed qualification checks

Patch 1 adds the operstate enum, netlink attribute and the
operstate_on_dpll_get callback to the DPLL subsystem. It also
updates Documentation/driver-api/dpll.rst to describe the
separation between admin state and operational state.

Patch 2 implements the callback for ZL3073x input pins using the
reference monitor status register. It also refactors the existing
state_on_dpll_get to return purely administrative state and switches
periodic monitoring to track operstate changes.

Ivan Vecera (2):
  dpll: add pin operational state
  dpll: zl3073x: implement pin operational state reporting

 Documentation/driver-api/dpll.rst     |  38 +++++----
 Documentation/netlink/specs/dpll.yaml |  31 ++++++++
 drivers/dpll/dpll_netlink.c           |  27 +++++++
 drivers/dpll/dpll_nl.c                |   3 +-
 drivers/dpll/dpll_nl.h                |   2 +-
 drivers/dpll/zl3073x/dpll.c           | 108 +++++++++++++++++---------
 drivers/dpll/zl3073x/regs.h           |   9 ++-
 include/linux/dpll.h                  |   6 ++
 include/uapi/linux/dpll.h             |  23 ++++++
 9 files changed, 192 insertions(+), 55 deletions(-)


base-commit: 1f5ffc672165ff851063a5fd044b727ab2517ae3
-- 
2.53.0


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

* [PATCH net-next 1/2] dpll: add pin operational state
  2026-04-28 15:49 [PATCH net-next 0/2] dpll: add pin operational state Ivan Vecera
@ 2026-04-28 15:49 ` Ivan Vecera
  2026-04-29  8:55   ` Jiri Pirko
                     ` (2 more replies)
  2026-04-28 15:49 ` [PATCH net-next 2/2] dpll: zl3073x: implement pin operational state reporting Ivan Vecera
  2026-04-30 14:30 ` [PATCH net-next 0/2] dpll: add pin operational state patchwork-bot+netdevbpf
  2 siblings, 3 replies; 9+ messages in thread
From: Ivan Vecera @ 2026-04-28 15:49 UTC (permalink / raw)
  To: netdev
  Cc: Arkadiusz Kubalewski, David S. Miller, Donald Hunter,
	Eric Dumazet, Jakub Kicinski, Jiri Pirko, Jonathan Corbet,
	Michal Schmidt, Paolo Abeni, Pasi Vaananen, Petr Oros,
	Prathosh Satish, Shuah Khan, Simon Horman, Vadim Fedorenko,
	linux-doc, linux-kernel

Add pin-operstate enum and operstate_on_dpll_get callback to report
the actual hardware status of a pin with respect to its parent DPLL
device. Unlike pin-state (which reflects administrative intent set
by the user), operstate reflects what the hardware is actually doing.

Defined operational states:
  - active: pin is qualified and actively used by the DPLL
  - standby: pin is qualified but not actively used by the DPLL
  - no-signal: pin does not have a valid signal
  - qual-failed: pin signal failed qualification

The operstate is reported inside the pin-parent-device nested
attribute alongside the existing state and phase-offset attributes.

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
 Documentation/driver-api/dpll.rst     | 38 ++++++++++++++++-----------
 Documentation/netlink/specs/dpll.yaml | 31 ++++++++++++++++++++++
 drivers/dpll/dpll_netlink.c           | 27 +++++++++++++++++++
 drivers/dpll/dpll_nl.c                |  3 ++-
 drivers/dpll/dpll_nl.h                |  2 +-
 include/linux/dpll.h                  |  6 +++++
 include/uapi/linux/dpll.h             | 23 ++++++++++++++++
 7 files changed, 113 insertions(+), 17 deletions(-)

diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-api/dpll.rst
index 93c191b2d0898..37eaef785e304 100644
--- a/Documentation/driver-api/dpll.rst
+++ b/Documentation/driver-api/dpll.rst
@@ -65,35 +65,43 @@ request, where user provides attributes that result in single pin match.
 Pin selection
 =============
 
-In general, selected pin (the one which signal is driving the dpll
-device) can be obtained from ``DPLL_A_PIN_STATE`` attribute, and only
-one pin shall be in ``DPLL_PIN_STATE_CONNECTED`` state for any dpll
-device.
+Pin state (``DPLL_A_PIN_STATE``) reflects the administrative intent set
+by the user. Pin operational state (``DPLL_A_PIN_OPERSTATE``) reflects
+what the hardware is actually doing with the pin.
 
 Pin selection can be done either manually or automatically, depending
 on hardware capabilities and active dpll device work mode
 (``DPLL_A_MODE`` attribute). The consequence is that there are
-differences for each mode in terms of available pin states, as well as
-for the states the user can request for a dpll device.
+differences for each mode in terms of available pin states the user can
+request for a dpll device.
 
-In manual mode (``DPLL_MODE_MANUAL``) the user can request or receive
-one of following pin states:
+In manual mode (``DPLL_MODE_MANUAL``) the user can request one of
+following pin states:
 
-- ``DPLL_PIN_STATE_CONNECTED`` - the pin is used to drive dpll device
-- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not used to drive dpll
+- ``DPLL_PIN_STATE_CONNECTED`` - the pin is selected to drive dpll
   device
+- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not selected to drive
+  dpll device
 
-In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request or
-receive one of following pin states:
+In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request one of
+following pin states:
 
 - ``DPLL_PIN_STATE_SELECTABLE`` - the pin shall be considered as valid
   input for automatic selection algorithm
 - ``DPLL_PIN_STATE_DISCONNECTED`` - the pin shall be not considered as
   a valid input for automatic selection algorithm
 
-In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can only receive
-pin state ``DPLL_PIN_STATE_CONNECTED`` once automatic selection
-algorithm locks a dpll device with one of the inputs.
+The actual hardware status of a pin is reported via the operational
+state (``DPLL_A_PIN_OPERSTATE``) attribute nested under the parent
+device:
+
+- ``DPLL_PIN_OPERSTATE_ACTIVE`` - pin is qualified and actively used
+  by the DPLL
+- ``DPLL_PIN_OPERSTATE_STANDBY`` - pin is qualified but not actively
+  used by the DPLL
+- ``DPLL_PIN_OPERSTATE_NO_SIGNAL`` - pin does not have a valid signal
+- ``DPLL_PIN_OPERSTATE_QUAL_FAILED`` - pin signal failed qualification
+  checks
 
 Shared pins
 ===========
diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml
index 40465a3d7fc20..c45de70a47ce6 100644
--- a/Documentation/netlink/specs/dpll.yaml
+++ b/Documentation/netlink/specs/dpll.yaml
@@ -212,6 +212,27 @@ definitions:
         name: selectable
         doc: pin enabled for automatic input selection
     render-max: true
+  -
+    type: enum
+    name: pin-operstate
+    doc: |
+      defines possible operational states of a pin with respect to its
+      parent DPLL device, valid values for DPLL_A_PIN_OPERSTATE attribute
+    entries:
+      -
+        name: active
+        doc: pin is qualified and actively used by the DPLL
+        value: 1
+      -
+        name: standby
+        doc: pin is qualified but not actively used by the DPLL
+      -
+        name: no-signal
+        doc: pin does not have a valid signal
+      -
+        name: qual-failed
+        doc: pin signal failed qualification (e.g. frequency or phase monitor)
+    render-max: true
   -
     type: flags
     name: pin-capabilities
@@ -488,6 +509,14 @@ attribute-sets:
           Value of (DPLL_A_PIN_MEASURED_FREQUENCY %
           DPLL_PIN_MEASURED_FREQUENCY_DIVIDER) is a fractional part
           of a measured frequency value.
+      -
+        name: operstate
+        type: u32
+        enum: pin-operstate
+        doc: |
+          Operational state of the pin with respect to its parent DPLL
+          device. Unlike state (which reflects the administrative intent),
+          operstate reflects the actual hardware status.
 
   -
     name: pin-parent-device
@@ -501,6 +530,8 @@ attribute-sets:
         name: prio
       -
         name: state
+      -
+        name: operstate
       -
         name: phase-offset
   -
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index af7ce62ec55ca..05cf946b4be5e 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -324,6 +324,30 @@ dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin,
 	return 0;
 }
 
+static int
+dpll_msg_add_pin_operstate(struct sk_buff *msg, struct dpll_pin *pin,
+			   struct dpll_pin_ref *ref,
+			   struct netlink_ext_ack *extack)
+{
+	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
+	struct dpll_device *dpll = ref->dpll;
+	enum dpll_pin_operstate operstate;
+	int ret;
+
+	if (!ops->operstate_on_dpll_get)
+		return 0;
+	ret = ops->operstate_on_dpll_get(pin,
+					  dpll_pin_on_dpll_priv(dpll, pin),
+					  dpll, dpll_priv(dpll),
+					  &operstate, extack);
+	if (ret)
+		return ret;
+	if (nla_put_u32(msg, DPLL_A_PIN_OPERSTATE, operstate))
+		return -EMSGSIZE;
+
+	return 0;
+}
+
 static int
 dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
 			   struct dpll_pin_ref *ref,
@@ -650,6 +674,9 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
 		if (ret)
 			goto nest_cancel;
 		ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack);
+		if (ret)
+			goto nest_cancel;
+		ret = dpll_msg_add_pin_operstate(msg, pin, ref, extack);
 		if (ret)
 			goto nest_cancel;
 		ret = dpll_msg_add_pin_prio(msg, pin, ref, extack);
diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c
index 1e652340a5d73..58235845fa3d5 100644
--- a/drivers/dpll/dpll_nl.c
+++ b/drivers/dpll/dpll_nl.c
@@ -12,11 +12,12 @@
 #include <uapi/linux/dpll.h>
 
 /* Common nested types */
-const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1] = {
+const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + 1] = {
 	[DPLL_A_PIN_PARENT_ID] = { .type = NLA_U32, },
 	[DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
 	[DPLL_A_PIN_PRIO] = { .type = NLA_U32, },
 	[DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3),
+	[DPLL_A_PIN_OPERSTATE] = NLA_POLICY_RANGE(NLA_U32, 1, 4),
 	[DPLL_A_PIN_PHASE_OFFSET] = { .type = NLA_S64, },
 };
 
diff --git a/drivers/dpll/dpll_nl.h b/drivers/dpll/dpll_nl.h
index 7419679b69779..fa8280e3dd14c 100644
--- a/drivers/dpll/dpll_nl.h
+++ b/drivers/dpll/dpll_nl.h
@@ -13,7 +13,7 @@
 #include <uapi/linux/dpll.h>
 
 /* Common nested types */
-extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1];
+extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + 1];
 extern const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1];
 extern const struct nla_policy dpll_reference_sync_nl_policy[DPLL_A_PIN_STATE + 1];
 
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index b7277a8b484d2..b6f16c884b99e 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -85,6 +85,12 @@ struct dpll_pin_ops {
 				 const struct dpll_device *dpll,
 				 void *dpll_priv, enum dpll_pin_state *state,
 				 struct netlink_ext_ack *extack);
+	int (*operstate_on_dpll_get)(const struct dpll_pin *pin,
+				     void *pin_priv,
+				     const struct dpll_device *dpll,
+				     void *dpll_priv,
+				     enum dpll_pin_operstate *operstate,
+				     struct netlink_ext_ack *extack);
 	int (*state_on_pin_set)(const struct dpll_pin *pin, void *pin_priv,
 				const struct dpll_pin *parent_pin,
 				void *parent_pin_priv,
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index 871685f7c353b..cb363cccf2e2a 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -178,6 +178,28 @@ enum dpll_pin_state {
 	DPLL_PIN_STATE_MAX = (__DPLL_PIN_STATE_MAX - 1)
 };
 
+/**
+ * enum dpll_pin_operstate - defines possible operational states of a pin with
+ *   respect to its parent DPLL device, valid values for DPLL_A_PIN_OPERSTATE
+ *   attribute
+ * @DPLL_PIN_OPERSTATE_ACTIVE: pin is qualified and actively used by the DPLL
+ * @DPLL_PIN_OPERSTATE_STANDBY: pin is qualified but not actively used by the
+ *   DPLL
+ * @DPLL_PIN_OPERSTATE_NO_SIGNAL: pin does not have a valid signal
+ * @DPLL_PIN_OPERSTATE_QUAL_FAILED: pin signal failed qualification (e.g.
+ *   frequency or phase monitor)
+ */
+enum dpll_pin_operstate {
+	DPLL_PIN_OPERSTATE_ACTIVE = 1,
+	DPLL_PIN_OPERSTATE_STANDBY,
+	DPLL_PIN_OPERSTATE_NO_SIGNAL,
+	DPLL_PIN_OPERSTATE_QUAL_FAILED,
+
+	/* private: */
+	__DPLL_PIN_OPERSTATE_MAX,
+	DPLL_PIN_OPERSTATE_MAX = (__DPLL_PIN_OPERSTATE_MAX - 1)
+};
+
 /**
  * enum dpll_pin_capabilities - defines possible capabilities of a pin, valid
  *   flags on DPLL_A_PIN_CAPABILITIES attribute
@@ -257,6 +279,7 @@ enum dpll_a_pin {
 	DPLL_A_PIN_PHASE_ADJUST_GRAN,
 	DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT,
 	DPLL_A_PIN_MEASURED_FREQUENCY,
+	DPLL_A_PIN_OPERSTATE,
 
 	__DPLL_A_PIN_MAX,
 	DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1)
-- 
2.53.0


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

* [PATCH net-next 2/2] dpll: zl3073x: implement pin operational state reporting
  2026-04-28 15:49 [PATCH net-next 0/2] dpll: add pin operational state Ivan Vecera
  2026-04-28 15:49 ` [PATCH net-next 1/2] " Ivan Vecera
@ 2026-04-28 15:49 ` Ivan Vecera
  2026-04-30 11:58   ` Petr Oros
  2026-04-30 14:21   ` Paolo Abeni
  2026-04-30 14:30 ` [PATCH net-next 0/2] dpll: add pin operational state patchwork-bot+netdevbpf
  2 siblings, 2 replies; 9+ messages in thread
From: Ivan Vecera @ 2026-04-28 15:49 UTC (permalink / raw)
  To: netdev
  Cc: Arkadiusz Kubalewski, David S. Miller, Donald Hunter,
	Eric Dumazet, Jakub Kicinski, Jiri Pirko, Jonathan Corbet,
	Michal Schmidt, Paolo Abeni, Pasi Vaananen, Petr Oros,
	Prathosh Satish, Shuah Khan, Simon Horman, Vadim Fedorenko,
	linux-doc, linux-kernel

Implement operstate_on_dpll_get callback for input pins to report
the actual hardware status:

  - active: pin is the currently locked reference
  - standby: signal is valid but pin is not actively used
  - no-signal: reference monitor reports Loss of Signal (LOS)
  - qual-failed: reference monitor reports a qualification failure
    (SCM, CFM, GST, PFM, eSync or Split-XO)

Separate administrative state (state_on_dpll_get) from operational
state: admin state now reports purely the user-requested intent
(connected in reflock mode, selectable in auto mode).

Switch periodic monitoring to track operstate changes instead of
the mixed admin/oper state that was previously reported.

Add ref_mon_status bit definitions to regs.h.

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
 drivers/dpll/zl3073x/dpll.c | 108 ++++++++++++++++++++++++------------
 drivers/dpll/zl3073x/regs.h |   9 ++-
 2 files changed, 79 insertions(+), 38 deletions(-)

diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
index c95e93ef3ab04..6fd718696de0d 100644
--- a/drivers/dpll/zl3073x/dpll.c
+++ b/drivers/dpll/zl3073x/dpll.c
@@ -38,7 +38,7 @@
  * @prio: pin priority <0, 14>
  * @esync_control: embedded sync is controllable
  * @phase_gran: phase adjustment granularity
- * @pin_state: last saved pin state
+ * @operstate: last saved operational state
  * @phase_offset: last saved pin phase offset
  * @freq_offset: last saved fractional frequency offset
  * @measured_freq: last saved measured frequency
@@ -55,7 +55,7 @@ struct zl3073x_dpll_pin {
 	u8			prio;
 	bool			esync_control;
 	s32			phase_gran;
-	enum dpll_pin_state	pin_state;
+	enum dpll_pin_operstate	operstate;
 	s64			phase_offset;
 	s64			freq_offset;
 	u32			measured_freq;
@@ -500,46 +500,41 @@ zl3073x_dpll_input_pin_phase_adjust_set(const struct dpll_pin *dpll_pin,
 }
 
 /**
- * zl3073x_dpll_ref_state_get - get status for given input pin
+ * zl3073x_dpll_ref_operstate_get - get operational state for input pin
  * @pin: pointer to pin
- * @state: place to store status
+ * @operstate: place to store operational state
  *
- * Checks current status for the given input pin and stores the value
- * to @state.
+ * Returns the actual hardware state of the pin: whether it is actively
+ * used by the DPLL, has no signal, failed qualification, or is simply
+ * not in use.
  *
  * Return: 0 on success, <0 on error
  */
 static int
-zl3073x_dpll_ref_state_get(struct zl3073x_dpll_pin *pin,
-			   enum dpll_pin_state *state)
+zl3073x_dpll_ref_operstate_get(struct zl3073x_dpll_pin *pin,
+			       enum dpll_pin_operstate *operstate)
 {
 	struct zl3073x_dpll *zldpll = pin->dpll;
 	struct zl3073x_dev *zldev = zldpll->dev;
-	const struct zl3073x_chan *chan;
-	u8 ref;
-
-	chan = zl3073x_chan_state_get(zldev, zldpll->id);
-	ref = zl3073x_input_pin_ref_get(pin->id);
+	const struct zl3073x_ref *ref;
+	u8 ref_id;
 
-	/* Check if the pin reference is connected */
-	if (ref == zl3073x_dpll_connected_ref_get(zldpll)) {
-		*state = DPLL_PIN_STATE_CONNECTED;
-		return 0;
-	}
+	ref_id = zl3073x_input_pin_ref_get(pin->id);
 
-	/* If the DPLL is running in automatic mode and the reference is
-	 * selectable and its monitor does not report any error then report
-	 * pin as selectable.
-	 */
-	if (zl3073x_chan_mode_get(chan) == ZL_DPLL_MODE_REFSEL_MODE_AUTO &&
-	    zl3073x_dev_ref_is_status_ok(zldev, ref) &&
-	    zl3073x_chan_ref_is_selectable(chan, ref)) {
-		*state = DPLL_PIN_STATE_SELECTABLE;
+	/* Check if this pin is the currently locked reference */
+	if (ref_id == zl3073x_dpll_connected_ref_get(zldpll)) {
+		*operstate = DPLL_PIN_OPERSTATE_ACTIVE;
 		return 0;
 	}
 
-	/* Otherwise report the pin as disconnected */
-	*state = DPLL_PIN_STATE_DISCONNECTED;
+	/* Check reference monitor status */
+	ref = zl3073x_ref_state_get(zldev, ref_id);
+	if (ref->mon_status & ZL_REF_MON_STATUS_LOS)
+		*operstate = DPLL_PIN_OPERSTATE_NO_SIGNAL;
+	else if (!zl3073x_ref_is_status_ok(ref))
+		*operstate = DPLL_PIN_OPERSTATE_QUAL_FAILED;
+	else
+		*operstate = DPLL_PIN_OPERSTATE_STANDBY;
 
 	return 0;
 }
@@ -551,10 +546,48 @@ zl3073x_dpll_input_pin_state_on_dpll_get(const struct dpll_pin *dpll_pin,
 					 void *dpll_priv,
 					 enum dpll_pin_state *state,
 					 struct netlink_ext_ack *extack)
+{
+	struct zl3073x_dpll *zldpll = dpll_priv;
+	struct zl3073x_dpll_pin *pin = pin_priv;
+	const struct zl3073x_chan *chan;
+	u8 mode, ref;
+
+	chan = zl3073x_chan_state_get(zldpll->dev, zldpll->id);
+	ref = zl3073x_input_pin_ref_get(pin->id);
+	mode = zl3073x_chan_mode_get(chan);
+
+	switch (mode) {
+	case ZL_DPLL_MODE_REFSEL_MODE_REFLOCK:
+		if (ref == zl3073x_chan_ref_get(chan))
+			*state = DPLL_PIN_STATE_CONNECTED;
+		else
+			*state = DPLL_PIN_STATE_DISCONNECTED;
+		break;
+	case ZL_DPLL_MODE_REFSEL_MODE_AUTO:
+		if (zl3073x_chan_ref_is_selectable(chan, ref))
+			*state = DPLL_PIN_STATE_SELECTABLE;
+		else
+			*state = DPLL_PIN_STATE_DISCONNECTED;
+		break;
+	default:
+		*state = DPLL_PIN_STATE_DISCONNECTED;
+		break;
+	}
+
+	return 0;
+}
+
+static int
+zl3073x_dpll_input_pin_operstate_on_dpll_get(const struct dpll_pin *dpll_pin,
+					     void *pin_priv,
+					     const struct dpll_device *dpll,
+					     void *dpll_priv,
+					     enum dpll_pin_operstate *operstate,
+					     struct netlink_ext_ack *extack)
 {
 	struct zl3073x_dpll_pin *pin = pin_priv;
 
-	return zl3073x_dpll_ref_state_get(pin, state);
+	return zl3073x_dpll_ref_operstate_get(pin, operstate);
 }
 
 static int
@@ -1248,6 +1281,7 @@ static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = {
 	.frequency_get = zl3073x_dpll_input_pin_frequency_get,
 	.frequency_set = zl3073x_dpll_input_pin_frequency_set,
 	.measured_freq_get = zl3073x_dpll_input_pin_measured_freq_get,
+	.operstate_on_dpll_get = zl3073x_dpll_input_pin_operstate_on_dpll_get,
 	.phase_offset_get = zl3073x_dpll_input_pin_phase_offset_get,
 	.phase_adjust_get = zl3073x_dpll_input_pin_phase_adjust_get,
 	.phase_adjust_set = zl3073x_dpll_input_pin_phase_adjust_set,
@@ -1663,7 +1697,7 @@ zl3073x_dpll_pin_phase_offset_check(struct zl3073x_dpll_pin *pin)
 	 * 2) For other pins use appropriate ref_phase register if the phase
 	 *    monitor feature is enabled.
 	 */
-	if (pin->pin_state == DPLL_PIN_STATE_CONNECTED)
+	if (pin->operstate == DPLL_PIN_OPERSTATE_ACTIVE)
 		reg = ZL_REG_DPLL_PHASE_ERR_DATA(zldpll->id);
 	else if (zldpll->phase_monitor)
 		reg = ZL_REG_REF_PHASE(ref_id);
@@ -1828,7 +1862,7 @@ zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll)
 	}
 
 	list_for_each_entry(pin, &zldpll->pins, list) {
-		enum dpll_pin_state state;
+		enum dpll_pin_operstate operstate;
 		bool pin_changed = false;
 
 		/* Output pins change checks are not necessary because output
@@ -1837,18 +1871,18 @@ zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll)
 		if (!zl3073x_dpll_is_input_pin(pin))
 			continue;
 
-		rc = zl3073x_dpll_ref_state_get(pin, &state);
+		rc = zl3073x_dpll_ref_operstate_get(pin, &operstate);
 		if (rc) {
 			dev_err(dev,
-				"Failed to get %s on DPLL%u state: %pe\n",
+				"Failed to get %s on DPLL%u oper state: %pe\n",
 				pin->label, zldpll->id, ERR_PTR(rc));
 			return;
 		}
 
-		if (state != pin->pin_state) {
-			dev_dbg(dev, "%s state changed: %u->%u\n", pin->label,
-				pin->pin_state, state);
-			pin->pin_state = state;
+		if (operstate != pin->operstate) {
+			dev_dbg(dev, "%s oper state changed: %u->%u\n",
+				pin->label, pin->operstate, operstate);
+			pin->operstate = operstate;
 			pin_changed = true;
 		}
 
diff --git a/drivers/dpll/zl3073x/regs.h b/drivers/dpll/zl3073x/regs.h
index d425dc67250fe..8015808bdf548 100644
--- a/drivers/dpll/zl3073x/regs.h
+++ b/drivers/dpll/zl3073x/regs.h
@@ -98,7 +98,14 @@
 
 #define ZL_REG_REF_MON_STATUS(_idx)					\
 	ZL_REG_IDX(_idx, 2, 0x02, 1, ZL3073X_NUM_REFS, 1)
-#define ZL_REF_MON_STATUS_OK			0 /* all bits zeroed */
+#define ZL_REF_MON_STATUS_OK			0
+#define ZL_REF_MON_STATUS_LOS			BIT(0)
+#define ZL_REF_MON_STATUS_SCM			BIT(1)
+#define ZL_REF_MON_STATUS_CFM			BIT(2)
+#define ZL_REF_MON_STATUS_GST			BIT(3)
+#define ZL_REF_MON_STATUS_PFM			BIT(4)
+#define ZL_REF_MON_STATUS_ESYNC			BIT(6)
+#define ZL_REF_MON_STATUS_SPLIT_XO		BIT(7)
 
 #define ZL_REG_DPLL_MON_STATUS(_idx)					\
 	ZL_REG_IDX(_idx, 2, 0x10, 1, ZL3073X_MAX_CHANNELS, 1)
-- 
2.53.0


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

* Re: [PATCH net-next 1/2] dpll: add pin operational state
  2026-04-28 15:49 ` [PATCH net-next 1/2] " Ivan Vecera
@ 2026-04-29  8:55   ` Jiri Pirko
  2026-04-29 10:45   ` Vadim Fedorenko
  2026-04-30 11:58   ` Petr Oros
  2 siblings, 0 replies; 9+ messages in thread
From: Jiri Pirko @ 2026-04-29  8:55 UTC (permalink / raw)
  To: Ivan Vecera
  Cc: netdev, Arkadiusz Kubalewski, David S. Miller, Donald Hunter,
	Eric Dumazet, Jakub Kicinski, Jonathan Corbet, Michal Schmidt,
	Paolo Abeni, Pasi Vaananen, Petr Oros, Prathosh Satish,
	Shuah Khan, Simon Horman, Vadim Fedorenko, linux-doc,
	linux-kernel

Tue, Apr 28, 2026 at 05:49:06PM +0200, ivecera@redhat.com wrote:
>Add pin-operstate enum and operstate_on_dpll_get callback to report
>the actual hardware status of a pin with respect to its parent DPLL
>device. Unlike pin-state (which reflects administrative intent set
>by the user), operstate reflects what the hardware is actually doing.
>
>Defined operational states:
>  - active: pin is qualified and actively used by the DPLL
>  - standby: pin is qualified but not actively used by the DPLL
>  - no-signal: pin does not have a valid signal
>  - qual-failed: pin signal failed qualification
>
>The operstate is reported inside the pin-parent-device nested
>attribute alongside the existing state and phase-offset attributes.
>
>Signed-off-by: Ivan Vecera <ivecera@redhat.com>

Looks great.

Reviewed-by: Jiri Pirko <jiri@nvidia.com>

Thanks!

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

* Re: [PATCH net-next 1/2] dpll: add pin operational state
  2026-04-28 15:49 ` [PATCH net-next 1/2] " Ivan Vecera
  2026-04-29  8:55   ` Jiri Pirko
@ 2026-04-29 10:45   ` Vadim Fedorenko
  2026-04-30 11:58   ` Petr Oros
  2 siblings, 0 replies; 9+ messages in thread
From: Vadim Fedorenko @ 2026-04-29 10:45 UTC (permalink / raw)
  To: Ivan Vecera, netdev
  Cc: Arkadiusz Kubalewski, David S. Miller, Donald Hunter,
	Eric Dumazet, Jakub Kicinski, Jiri Pirko, Jonathan Corbet,
	Michal Schmidt, Paolo Abeni, Pasi Vaananen, Petr Oros,
	Prathosh Satish, Shuah Khan, Simon Horman, linux-doc,
	linux-kernel

On 28/04/2026 16:49, Ivan Vecera wrote:
> Add pin-operstate enum and operstate_on_dpll_get callback to report
> the actual hardware status of a pin with respect to its parent DPLL
> device. Unlike pin-state (which reflects administrative intent set
> by the user), operstate reflects what the hardware is actually doing.
> 
> Defined operational states:
>    - active: pin is qualified and actively used by the DPLL
>    - standby: pin is qualified but not actively used by the DPLL
>    - no-signal: pin does not have a valid signal
>    - qual-failed: pin signal failed qualification
> 
> The operstate is reported inside the pin-parent-device nested
> attribute alongside the existing state and phase-offset attributes.
> 
> Signed-off-by: Ivan Vecera <ivecera@redhat.com>

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>

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

* Re: [PATCH net-next 1/2] dpll: add pin operational state
  2026-04-28 15:49 ` [PATCH net-next 1/2] " Ivan Vecera
  2026-04-29  8:55   ` Jiri Pirko
  2026-04-29 10:45   ` Vadim Fedorenko
@ 2026-04-30 11:58   ` Petr Oros
  2 siblings, 0 replies; 9+ messages in thread
From: Petr Oros @ 2026-04-30 11:58 UTC (permalink / raw)
  To: Ivan Vecera, netdev
  Cc: Arkadiusz Kubalewski, David S. Miller, Donald Hunter,
	Eric Dumazet, Jakub Kicinski, Jiri Pirko, Jonathan Corbet,
	Michal Schmidt, Paolo Abeni, Pasi Vaananen, Prathosh Satish,
	Shuah Khan, Simon Horman, Vadim Fedorenko, linux-doc,
	linux-kernel


On 4/28/26 17:49, Ivan Vecera wrote:
> Add pin-operstate enum and operstate_on_dpll_get callback to report
> the actual hardware status of a pin with respect to its parent DPLL
> device. Unlike pin-state (which reflects administrative intent set
> by the user), operstate reflects what the hardware is actually doing.
>
> Defined operational states:
>    - active: pin is qualified and actively used by the DPLL
>    - standby: pin is qualified but not actively used by the DPLL
>    - no-signal: pin does not have a valid signal
>    - qual-failed: pin signal failed qualification
>
> The operstate is reported inside the pin-parent-device nested
> attribute alongside the existing state and phase-offset attributes.
>
> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
> ---
>   Documentation/driver-api/dpll.rst     | 38 ++++++++++++++++-----------
>   Documentation/netlink/specs/dpll.yaml | 31 ++++++++++++++++++++++
>   drivers/dpll/dpll_netlink.c           | 27 +++++++++++++++++++
>   drivers/dpll/dpll_nl.c                |  3 ++-
>   drivers/dpll/dpll_nl.h                |  2 +-
>   include/linux/dpll.h                  |  6 +++++
>   include/uapi/linux/dpll.h             | 23 ++++++++++++++++
>   7 files changed, 113 insertions(+), 17 deletions(-)
>
> diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-api/dpll.rst
> index 93c191b2d0898..37eaef785e304 100644
> --- a/Documentation/driver-api/dpll.rst
> +++ b/Documentation/driver-api/dpll.rst
> @@ -65,35 +65,43 @@ request, where user provides attributes that result in single pin match.
>   Pin selection
>   =============
>   
> -In general, selected pin (the one which signal is driving the dpll
> -device) can be obtained from ``DPLL_A_PIN_STATE`` attribute, and only
> -one pin shall be in ``DPLL_PIN_STATE_CONNECTED`` state for any dpll
> -device.
> +Pin state (``DPLL_A_PIN_STATE``) reflects the administrative intent set
> +by the user. Pin operational state (``DPLL_A_PIN_OPERSTATE``) reflects
> +what the hardware is actually doing with the pin.
>   
>   Pin selection can be done either manually or automatically, depending
>   on hardware capabilities and active dpll device work mode
>   (``DPLL_A_MODE`` attribute). The consequence is that there are
> -differences for each mode in terms of available pin states, as well as
> -for the states the user can request for a dpll device.
> +differences for each mode in terms of available pin states the user can
> +request for a dpll device.
>   
> -In manual mode (``DPLL_MODE_MANUAL``) the user can request or receive
> -one of following pin states:
> +In manual mode (``DPLL_MODE_MANUAL``) the user can request one of
> +following pin states:
>   
> -- ``DPLL_PIN_STATE_CONNECTED`` - the pin is used to drive dpll device
> -- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not used to drive dpll
> +- ``DPLL_PIN_STATE_CONNECTED`` - the pin is selected to drive dpll
>     device
> +- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not selected to drive
> +  dpll device
>   
> -In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request or
> -receive one of following pin states:
> +In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request one of
> +following pin states:
>   
>   - ``DPLL_PIN_STATE_SELECTABLE`` - the pin shall be considered as valid
>     input for automatic selection algorithm
>   - ``DPLL_PIN_STATE_DISCONNECTED`` - the pin shall be not considered as
>     a valid input for automatic selection algorithm
>   
> -In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can only receive
> -pin state ``DPLL_PIN_STATE_CONNECTED`` once automatic selection
> -algorithm locks a dpll device with one of the inputs.
> +The actual hardware status of a pin is reported via the operational
> +state (``DPLL_A_PIN_OPERSTATE``) attribute nested under the parent
> +device:
> +
> +- ``DPLL_PIN_OPERSTATE_ACTIVE`` - pin is qualified and actively used
> +  by the DPLL
> +- ``DPLL_PIN_OPERSTATE_STANDBY`` - pin is qualified but not actively
> +  used by the DPLL
> +- ``DPLL_PIN_OPERSTATE_NO_SIGNAL`` - pin does not have a valid signal
> +- ``DPLL_PIN_OPERSTATE_QUAL_FAILED`` - pin signal failed qualification
> +  checks
>   
>   Shared pins
>   ===========
> diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml
> index 40465a3d7fc20..c45de70a47ce6 100644
> --- a/Documentation/netlink/specs/dpll.yaml
> +++ b/Documentation/netlink/specs/dpll.yaml
> @@ -212,6 +212,27 @@ definitions:
>           name: selectable
>           doc: pin enabled for automatic input selection
>       render-max: true
> +  -
> +    type: enum
> +    name: pin-operstate
> +    doc: |
> +      defines possible operational states of a pin with respect to its
> +      parent DPLL device, valid values for DPLL_A_PIN_OPERSTATE attribute
> +    entries:
> +      -
> +        name: active
> +        doc: pin is qualified and actively used by the DPLL
> +        value: 1
> +      -
> +        name: standby
> +        doc: pin is qualified but not actively used by the DPLL
> +      -
> +        name: no-signal
> +        doc: pin does not have a valid signal
> +      -
> +        name: qual-failed
> +        doc: pin signal failed qualification (e.g. frequency or phase monitor)
> +    render-max: true
>     -
>       type: flags
>       name: pin-capabilities
> @@ -488,6 +509,14 @@ attribute-sets:
>             Value of (DPLL_A_PIN_MEASURED_FREQUENCY %
>             DPLL_PIN_MEASURED_FREQUENCY_DIVIDER) is a fractional part
>             of a measured frequency value.
> +      -
> +        name: operstate
> +        type: u32
> +        enum: pin-operstate
> +        doc: |
> +          Operational state of the pin with respect to its parent DPLL
> +          device. Unlike state (which reflects the administrative intent),
> +          operstate reflects the actual hardware status.
>   
>     -
>       name: pin-parent-device
> @@ -501,6 +530,8 @@ attribute-sets:
>           name: prio
>         -
>           name: state
> +      -
> +        name: operstate
>         -
>           name: phase-offset
>     -
> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
> index af7ce62ec55ca..05cf946b4be5e 100644
> --- a/drivers/dpll/dpll_netlink.c
> +++ b/drivers/dpll/dpll_netlink.c
> @@ -324,6 +324,30 @@ dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin,
>   	return 0;
>   }
>   
> +static int
> +dpll_msg_add_pin_operstate(struct sk_buff *msg, struct dpll_pin *pin,
> +			   struct dpll_pin_ref *ref,
> +			   struct netlink_ext_ack *extack)
> +{
> +	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
> +	struct dpll_device *dpll = ref->dpll;
> +	enum dpll_pin_operstate operstate;
> +	int ret;
> +
> +	if (!ops->operstate_on_dpll_get)
> +		return 0;
> +	ret = ops->operstate_on_dpll_get(pin,
> +					  dpll_pin_on_dpll_priv(dpll, pin),
> +					  dpll, dpll_priv(dpll),
> +					  &operstate, extack);
> +	if (ret)
> +		return ret;
> +	if (nla_put_u32(msg, DPLL_A_PIN_OPERSTATE, operstate))
> +		return -EMSGSIZE;
> +
> +	return 0;
> +}
> +
>   static int
>   dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
>   			   struct dpll_pin_ref *ref,
> @@ -650,6 +674,9 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
>   		if (ret)
>   			goto nest_cancel;
>   		ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack);
> +		if (ret)
> +			goto nest_cancel;
> +		ret = dpll_msg_add_pin_operstate(msg, pin, ref, extack);
>   		if (ret)
>   			goto nest_cancel;
>   		ret = dpll_msg_add_pin_prio(msg, pin, ref, extack);
> diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c
> index 1e652340a5d73..58235845fa3d5 100644
> --- a/drivers/dpll/dpll_nl.c
> +++ b/drivers/dpll/dpll_nl.c
> @@ -12,11 +12,12 @@
>   #include <uapi/linux/dpll.h>
>   
>   /* Common nested types */
> -const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1] = {
> +const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + 1] = {
>   	[DPLL_A_PIN_PARENT_ID] = { .type = NLA_U32, },
>   	[DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
>   	[DPLL_A_PIN_PRIO] = { .type = NLA_U32, },
>   	[DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3),
> +	[DPLL_A_PIN_OPERSTATE] = NLA_POLICY_RANGE(NLA_U32, 1, 4),
>   	[DPLL_A_PIN_PHASE_OFFSET] = { .type = NLA_S64, },
>   };
>   
> diff --git a/drivers/dpll/dpll_nl.h b/drivers/dpll/dpll_nl.h
> index 7419679b69779..fa8280e3dd14c 100644
> --- a/drivers/dpll/dpll_nl.h
> +++ b/drivers/dpll/dpll_nl.h
> @@ -13,7 +13,7 @@
>   #include <uapi/linux/dpll.h>
>   
>   /* Common nested types */
> -extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1];
> +extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + 1];
>   extern const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1];
>   extern const struct nla_policy dpll_reference_sync_nl_policy[DPLL_A_PIN_STATE + 1];
>   
> diff --git a/include/linux/dpll.h b/include/linux/dpll.h
> index b7277a8b484d2..b6f16c884b99e 100644
> --- a/include/linux/dpll.h
> +++ b/include/linux/dpll.h
> @@ -85,6 +85,12 @@ struct dpll_pin_ops {
>   				 const struct dpll_device *dpll,
>   				 void *dpll_priv, enum dpll_pin_state *state,
>   				 struct netlink_ext_ack *extack);
> +	int (*operstate_on_dpll_get)(const struct dpll_pin *pin,
> +				     void *pin_priv,
> +				     const struct dpll_device *dpll,
> +				     void *dpll_priv,
> +				     enum dpll_pin_operstate *operstate,
> +				     struct netlink_ext_ack *extack);
>   	int (*state_on_pin_set)(const struct dpll_pin *pin, void *pin_priv,
>   				const struct dpll_pin *parent_pin,
>   				void *parent_pin_priv,
> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
> index 871685f7c353b..cb363cccf2e2a 100644
> --- a/include/uapi/linux/dpll.h
> +++ b/include/uapi/linux/dpll.h
> @@ -178,6 +178,28 @@ enum dpll_pin_state {
>   	DPLL_PIN_STATE_MAX = (__DPLL_PIN_STATE_MAX - 1)
>   };
>   
> +/**
> + * enum dpll_pin_operstate - defines possible operational states of a pin with
> + *   respect to its parent DPLL device, valid values for DPLL_A_PIN_OPERSTATE
> + *   attribute
> + * @DPLL_PIN_OPERSTATE_ACTIVE: pin is qualified and actively used by the DPLL
> + * @DPLL_PIN_OPERSTATE_STANDBY: pin is qualified but not actively used by the
> + *   DPLL
> + * @DPLL_PIN_OPERSTATE_NO_SIGNAL: pin does not have a valid signal
> + * @DPLL_PIN_OPERSTATE_QUAL_FAILED: pin signal failed qualification (e.g.
> + *   frequency or phase monitor)
> + */
> +enum dpll_pin_operstate {
> +	DPLL_PIN_OPERSTATE_ACTIVE = 1,
> +	DPLL_PIN_OPERSTATE_STANDBY,
> +	DPLL_PIN_OPERSTATE_NO_SIGNAL,
> +	DPLL_PIN_OPERSTATE_QUAL_FAILED,
> +
> +	/* private: */
> +	__DPLL_PIN_OPERSTATE_MAX,
> +	DPLL_PIN_OPERSTATE_MAX = (__DPLL_PIN_OPERSTATE_MAX - 1)
> +};
> +
>   /**
>    * enum dpll_pin_capabilities - defines possible capabilities of a pin, valid
>    *   flags on DPLL_A_PIN_CAPABILITIES attribute
> @@ -257,6 +279,7 @@ enum dpll_a_pin {
>   	DPLL_A_PIN_PHASE_ADJUST_GRAN,
>   	DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT,
>   	DPLL_A_PIN_MEASURED_FREQUENCY,
> +	DPLL_A_PIN_OPERSTATE,
>   
>   	__DPLL_A_PIN_MAX,
>   	DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1)

Reviewed-by: Petr Oros <poros@redhat.com>



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

* Re: [PATCH net-next 2/2] dpll: zl3073x: implement pin operational state reporting
  2026-04-28 15:49 ` [PATCH net-next 2/2] dpll: zl3073x: implement pin operational state reporting Ivan Vecera
@ 2026-04-30 11:58   ` Petr Oros
  2026-04-30 14:21   ` Paolo Abeni
  1 sibling, 0 replies; 9+ messages in thread
From: Petr Oros @ 2026-04-30 11:58 UTC (permalink / raw)
  To: Ivan Vecera, netdev
  Cc: Arkadiusz Kubalewski, David S. Miller, Donald Hunter,
	Eric Dumazet, Jakub Kicinski, Jiri Pirko, Jonathan Corbet,
	Michal Schmidt, Paolo Abeni, Pasi Vaananen, Prathosh Satish,
	Shuah Khan, Simon Horman, Vadim Fedorenko, linux-doc,
	linux-kernel


On 4/28/26 17:49, Ivan Vecera wrote:
> Implement operstate_on_dpll_get callback for input pins to report
> the actual hardware status:
>
>    - active: pin is the currently locked reference
>    - standby: signal is valid but pin is not actively used
>    - no-signal: reference monitor reports Loss of Signal (LOS)
>    - qual-failed: reference monitor reports a qualification failure
>      (SCM, CFM, GST, PFM, eSync or Split-XO)
>
> Separate administrative state (state_on_dpll_get) from operational
> state: admin state now reports purely the user-requested intent
> (connected in reflock mode, selectable in auto mode).
>
> Switch periodic monitoring to track operstate changes instead of
> the mixed admin/oper state that was previously reported.
>
> Add ref_mon_status bit definitions to regs.h.
>
> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
> ---
>   drivers/dpll/zl3073x/dpll.c | 108 ++++++++++++++++++++++++------------
>   drivers/dpll/zl3073x/regs.h |   9 ++-
>   2 files changed, 79 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
> index c95e93ef3ab04..6fd718696de0d 100644
> --- a/drivers/dpll/zl3073x/dpll.c
> +++ b/drivers/dpll/zl3073x/dpll.c
> @@ -38,7 +38,7 @@
>    * @prio: pin priority <0, 14>
>    * @esync_control: embedded sync is controllable
>    * @phase_gran: phase adjustment granularity
> - * @pin_state: last saved pin state
> + * @operstate: last saved operational state
>    * @phase_offset: last saved pin phase offset
>    * @freq_offset: last saved fractional frequency offset
>    * @measured_freq: last saved measured frequency
> @@ -55,7 +55,7 @@ struct zl3073x_dpll_pin {
>   	u8			prio;
>   	bool			esync_control;
>   	s32			phase_gran;
> -	enum dpll_pin_state	pin_state;
> +	enum dpll_pin_operstate	operstate;
>   	s64			phase_offset;
>   	s64			freq_offset;
>   	u32			measured_freq;
> @@ -500,46 +500,41 @@ zl3073x_dpll_input_pin_phase_adjust_set(const struct dpll_pin *dpll_pin,
>   }
>   
>   /**
> - * zl3073x_dpll_ref_state_get - get status for given input pin
> + * zl3073x_dpll_ref_operstate_get - get operational state for input pin
>    * @pin: pointer to pin
> - * @state: place to store status
> + * @operstate: place to store operational state
>    *
> - * Checks current status for the given input pin and stores the value
> - * to @state.
> + * Returns the actual hardware state of the pin: whether it is actively
> + * used by the DPLL, has no signal, failed qualification, or is simply
> + * not in use.
>    *
>    * Return: 0 on success, <0 on error
>    */
>   static int
> -zl3073x_dpll_ref_state_get(struct zl3073x_dpll_pin *pin,
> -			   enum dpll_pin_state *state)
> +zl3073x_dpll_ref_operstate_get(struct zl3073x_dpll_pin *pin,
> +			       enum dpll_pin_operstate *operstate)
>   {
>   	struct zl3073x_dpll *zldpll = pin->dpll;
>   	struct zl3073x_dev *zldev = zldpll->dev;
> -	const struct zl3073x_chan *chan;
> -	u8 ref;
> -
> -	chan = zl3073x_chan_state_get(zldev, zldpll->id);
> -	ref = zl3073x_input_pin_ref_get(pin->id);
> +	const struct zl3073x_ref *ref;
> +	u8 ref_id;
>   
> -	/* Check if the pin reference is connected */
> -	if (ref == zl3073x_dpll_connected_ref_get(zldpll)) {
> -		*state = DPLL_PIN_STATE_CONNECTED;
> -		return 0;
> -	}
> +	ref_id = zl3073x_input_pin_ref_get(pin->id);
>   
> -	/* If the DPLL is running in automatic mode and the reference is
> -	 * selectable and its monitor does not report any error then report
> -	 * pin as selectable.
> -	 */
> -	if (zl3073x_chan_mode_get(chan) == ZL_DPLL_MODE_REFSEL_MODE_AUTO &&
> -	    zl3073x_dev_ref_is_status_ok(zldev, ref) &&
> -	    zl3073x_chan_ref_is_selectable(chan, ref)) {
> -		*state = DPLL_PIN_STATE_SELECTABLE;
> +	/* Check if this pin is the currently locked reference */
> +	if (ref_id == zl3073x_dpll_connected_ref_get(zldpll)) {
> +		*operstate = DPLL_PIN_OPERSTATE_ACTIVE;
>   		return 0;
>   	}
>   
> -	/* Otherwise report the pin as disconnected */
> -	*state = DPLL_PIN_STATE_DISCONNECTED;
> +	/* Check reference monitor status */
> +	ref = zl3073x_ref_state_get(zldev, ref_id);
> +	if (ref->mon_status & ZL_REF_MON_STATUS_LOS)
> +		*operstate = DPLL_PIN_OPERSTATE_NO_SIGNAL;
> +	else if (!zl3073x_ref_is_status_ok(ref))
> +		*operstate = DPLL_PIN_OPERSTATE_QUAL_FAILED;
> +	else
> +		*operstate = DPLL_PIN_OPERSTATE_STANDBY;
>   
>   	return 0;
>   }
> @@ -551,10 +546,48 @@ zl3073x_dpll_input_pin_state_on_dpll_get(const struct dpll_pin *dpll_pin,
>   					 void *dpll_priv,
>   					 enum dpll_pin_state *state,
>   					 struct netlink_ext_ack *extack)
> +{
> +	struct zl3073x_dpll *zldpll = dpll_priv;
> +	struct zl3073x_dpll_pin *pin = pin_priv;
> +	const struct zl3073x_chan *chan;
> +	u8 mode, ref;
> +
> +	chan = zl3073x_chan_state_get(zldpll->dev, zldpll->id);
> +	ref = zl3073x_input_pin_ref_get(pin->id);
> +	mode = zl3073x_chan_mode_get(chan);
> +
> +	switch (mode) {
> +	case ZL_DPLL_MODE_REFSEL_MODE_REFLOCK:
> +		if (ref == zl3073x_chan_ref_get(chan))
> +			*state = DPLL_PIN_STATE_CONNECTED;
> +		else
> +			*state = DPLL_PIN_STATE_DISCONNECTED;
> +		break;
> +	case ZL_DPLL_MODE_REFSEL_MODE_AUTO:
> +		if (zl3073x_chan_ref_is_selectable(chan, ref))
> +			*state = DPLL_PIN_STATE_SELECTABLE;
> +		else
> +			*state = DPLL_PIN_STATE_DISCONNECTED;
> +		break;
> +	default:
> +		*state = DPLL_PIN_STATE_DISCONNECTED;
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +zl3073x_dpll_input_pin_operstate_on_dpll_get(const struct dpll_pin *dpll_pin,
> +					     void *pin_priv,
> +					     const struct dpll_device *dpll,
> +					     void *dpll_priv,
> +					     enum dpll_pin_operstate *operstate,
> +					     struct netlink_ext_ack *extack)
>   {
>   	struct zl3073x_dpll_pin *pin = pin_priv;
>   
> -	return zl3073x_dpll_ref_state_get(pin, state);
> +	return zl3073x_dpll_ref_operstate_get(pin, operstate);
>   }
>   
>   static int
> @@ -1248,6 +1281,7 @@ static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = {
>   	.frequency_get = zl3073x_dpll_input_pin_frequency_get,
>   	.frequency_set = zl3073x_dpll_input_pin_frequency_set,
>   	.measured_freq_get = zl3073x_dpll_input_pin_measured_freq_get,
> +	.operstate_on_dpll_get = zl3073x_dpll_input_pin_operstate_on_dpll_get,
>   	.phase_offset_get = zl3073x_dpll_input_pin_phase_offset_get,
>   	.phase_adjust_get = zl3073x_dpll_input_pin_phase_adjust_get,
>   	.phase_adjust_set = zl3073x_dpll_input_pin_phase_adjust_set,
> @@ -1663,7 +1697,7 @@ zl3073x_dpll_pin_phase_offset_check(struct zl3073x_dpll_pin *pin)
>   	 * 2) For other pins use appropriate ref_phase register if the phase
>   	 *    monitor feature is enabled.
>   	 */
> -	if (pin->pin_state == DPLL_PIN_STATE_CONNECTED)
> +	if (pin->operstate == DPLL_PIN_OPERSTATE_ACTIVE)
>   		reg = ZL_REG_DPLL_PHASE_ERR_DATA(zldpll->id);
>   	else if (zldpll->phase_monitor)
>   		reg = ZL_REG_REF_PHASE(ref_id);
> @@ -1828,7 +1862,7 @@ zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll)
>   	}
>   
>   	list_for_each_entry(pin, &zldpll->pins, list) {
> -		enum dpll_pin_state state;
> +		enum dpll_pin_operstate operstate;
>   		bool pin_changed = false;
>   
>   		/* Output pins change checks are not necessary because output
> @@ -1837,18 +1871,18 @@ zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll)
>   		if (!zl3073x_dpll_is_input_pin(pin))
>   			continue;
>   
> -		rc = zl3073x_dpll_ref_state_get(pin, &state);
> +		rc = zl3073x_dpll_ref_operstate_get(pin, &operstate);
>   		if (rc) {
>   			dev_err(dev,
> -				"Failed to get %s on DPLL%u state: %pe\n",
> +				"Failed to get %s on DPLL%u oper state: %pe\n",
>   				pin->label, zldpll->id, ERR_PTR(rc));
>   			return;
>   		}
>   
> -		if (state != pin->pin_state) {
> -			dev_dbg(dev, "%s state changed: %u->%u\n", pin->label,
> -				pin->pin_state, state);
> -			pin->pin_state = state;
> +		if (operstate != pin->operstate) {
> +			dev_dbg(dev, "%s oper state changed: %u->%u\n",
> +				pin->label, pin->operstate, operstate);
> +			pin->operstate = operstate;
>   			pin_changed = true;
>   		}
>   
> diff --git a/drivers/dpll/zl3073x/regs.h b/drivers/dpll/zl3073x/regs.h
> index d425dc67250fe..8015808bdf548 100644
> --- a/drivers/dpll/zl3073x/regs.h
> +++ b/drivers/dpll/zl3073x/regs.h
> @@ -98,7 +98,14 @@
>   
>   #define ZL_REG_REF_MON_STATUS(_idx)					\
>   	ZL_REG_IDX(_idx, 2, 0x02, 1, ZL3073X_NUM_REFS, 1)
> -#define ZL_REF_MON_STATUS_OK			0 /* all bits zeroed */
> +#define ZL_REF_MON_STATUS_OK			0
> +#define ZL_REF_MON_STATUS_LOS			BIT(0)
> +#define ZL_REF_MON_STATUS_SCM			BIT(1)
> +#define ZL_REF_MON_STATUS_CFM			BIT(2)
> +#define ZL_REF_MON_STATUS_GST			BIT(3)
> +#define ZL_REF_MON_STATUS_PFM			BIT(4)
> +#define ZL_REF_MON_STATUS_ESYNC			BIT(6)
> +#define ZL_REF_MON_STATUS_SPLIT_XO		BIT(7)
>   
>   #define ZL_REG_DPLL_MON_STATUS(_idx)					\
>   	ZL_REG_IDX(_idx, 2, 0x10, 1, ZL3073X_MAX_CHANNELS, 1)

Reviewed-by: Petr Oros <poros@redhat.com>



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

* Re: [PATCH net-next 2/2] dpll: zl3073x: implement pin operational state reporting
  2026-04-28 15:49 ` [PATCH net-next 2/2] dpll: zl3073x: implement pin operational state reporting Ivan Vecera
  2026-04-30 11:58   ` Petr Oros
@ 2026-04-30 14:21   ` Paolo Abeni
  1 sibling, 0 replies; 9+ messages in thread
From: Paolo Abeni @ 2026-04-30 14:21 UTC (permalink / raw)
  To: Ivan Vecera, netdev
  Cc: Arkadiusz Kubalewski, David S. Miller, Donald Hunter,
	Eric Dumazet, Jakub Kicinski, Jiri Pirko, Jonathan Corbet,
	Michal Schmidt, Pasi Vaananen, Petr Oros, Prathosh Satish,
	Shuah Khan, Simon Horman, Vadim Fedorenko, linux-doc,
	linux-kernel

On 4/28/26 5:49 PM, Ivan Vecera wrote:
> @@ -1828,7 +1862,7 @@ zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll)
>  	}

Sashiko says:

---
Will input pin operational state changes fail to generate netlink
notifications when the DPLL channel is in FREERUN or HOLDOVER modes?
---

but such modes can not generate any real notification as explicitly
documented in a previous comment.

/P


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

* Re: [PATCH net-next 0/2] dpll: add pin operational state
  2026-04-28 15:49 [PATCH net-next 0/2] dpll: add pin operational state Ivan Vecera
  2026-04-28 15:49 ` [PATCH net-next 1/2] " Ivan Vecera
  2026-04-28 15:49 ` [PATCH net-next 2/2] dpll: zl3073x: implement pin operational state reporting Ivan Vecera
@ 2026-04-30 14:30 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 9+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-04-30 14:30 UTC (permalink / raw)
  To: Ivan Vecera
  Cc: netdev, arkadiusz.kubalewski, davem, donald.hunter, edumazet,
	kuba, jiri, corbet, mschmidt, pabeni, pvaanane, poros,
	Prathosh.Satish, skhan, horms, vadim.fedorenko, linux-doc,
	linux-kernel

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Tue, 28 Apr 2026 17:49:05 +0200 you wrote:
> Add pin operational state (operstate) to the DPLL subsystem to
> separate administrative intent from actual hardware status.
> 
> Currently pin-state mixes what the user requested (connected,
> selectable, disconnected) with what the hardware is actually doing.
> This makes it difficult to diagnose situations where a user sets
> a pin as selectable or connected but the hardware cannot use it
> due to signal issues.
> 
> [...]

Here is the summary with links:
  - [net-next,1/2] dpll: add pin operational state
    https://git.kernel.org/netdev/net-next/c/781c8893a5da
  - [net-next,2/2] dpll: zl3073x: implement pin operational state reporting
    https://git.kernel.org/netdev/net-next/c/c53f8f8dce77

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2026-04-30 14:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28 15:49 [PATCH net-next 0/2] dpll: add pin operational state Ivan Vecera
2026-04-28 15:49 ` [PATCH net-next 1/2] " Ivan Vecera
2026-04-29  8:55   ` Jiri Pirko
2026-04-29 10:45   ` Vadim Fedorenko
2026-04-30 11:58   ` Petr Oros
2026-04-28 15:49 ` [PATCH net-next 2/2] dpll: zl3073x: implement pin operational state reporting Ivan Vecera
2026-04-30 11:58   ` Petr Oros
2026-04-30 14:21   ` Paolo Abeni
2026-04-30 14:30 ` [PATCH net-next 0/2] dpll: add pin operational state patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox