public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH iproute2-next 0/2] dpll: phase unit display and frequency monitoring
@ 2026-04-28 15:21 Ivan Vecera
  2026-04-28 15:21 ` [PATCH iproute2-next 1/2] dpll: add ps unit to phase-related pin attributes Ivan Vecera
  2026-04-28 15:21 ` [PATCH iproute2-next 2/2] dpll: add frequency monitoring support Ivan Vecera
  0 siblings, 2 replies; 7+ messages in thread
From: Ivan Vecera @ 2026-04-28 15:21 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern, Stephen Hemminger, Petr Oros

This series improves dpll pin output formatting and adds support for
the frequency monitoring feature.

Patch 1 adds picosecond unit to phase-adjust-min, phase-adjust-max
and phase-adjust attributes. It also introduces the DPLL_PR_PHASE_OFFSET
macro that properly formats phase-offset as fractional picoseconds by
dividing the raw kernel value by DPLL_PHASE_OFFSET_DIVIDER.

Patch 2 adds support for the new frequency monitoring feature including
the DPLL_A_FREQUENCY_MONITOR device attribute and
DPLL_A_PIN_MEASURED_FREQUENCY pin attribute. The measured frequency is
displayed as fractional Hz using the DPLL_PR_MEASURED_FREQUENCY macro
since the kernel reports the value in millihertz. It also refactors
phase-offset-monitor parsing into a shared helper.

Tested on EDS2 development board with zl3073x DPLL:

  # dpll pin show package-label REF0P
  pin id 196:
    module-name: zl3073x
    clock-id: 13709406750444215013
    board-label: SyncE IN M1 CLK1
    package-label: REF0P
    type: synce-eth-port
    frequency: 125000000 Hz
    measured-frequency: 124999326.000 Hz
    frequency-supported:
      2500000 Hz
      25000000 Hz
      125000000 Hz
    capabilities: 0x6 state-can-change priority-can-change
    phase-adjust-min: -2147483648 ps
    phase-adjust-max: 2147483647 ps
    phase-adjust: 0 ps
    parent-device:
      id 14 direction input prio 10 state selectable phase-offset 0.000 ps
      id 15 direction input prio 0 state connected phase-offset 323.000 ps

Ivan Vecera (2):
  dpll: add ps unit to phase-related pin attributes
  dpll: add frequency monitoring support

 bash-completion/dpll |  4 +-
 dpll/dpll.c          | 89 +++++++++++++++++++++++++++++++++++---------
 man/man8/dpll.8      | 19 +++++++++-
 3 files changed, 90 insertions(+), 22 deletions(-)

-- 
2.53.0


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

* [PATCH iproute2-next 1/2] dpll: add ps unit to phase-related pin attributes
  2026-04-28 15:21 [PATCH iproute2-next 0/2] dpll: phase unit display and frequency monitoring Ivan Vecera
@ 2026-04-28 15:21 ` Ivan Vecera
  2026-05-01 10:20   ` Petr Oros
  2026-04-28 15:21 ` [PATCH iproute2-next 2/2] dpll: add frequency monitoring support Ivan Vecera
  1 sibling, 1 reply; 7+ messages in thread
From: Ivan Vecera @ 2026-04-28 15:21 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern, Stephen Hemminger, Petr Oros

Display phase-adjust-min, phase-adjust-max and phase-adjust values
with ps unit. Add DPLL_PR_PHASE_OFFSET macro that properly formats
phase-offset as fractional picoseconds by dividing the raw kernel
value by DPLL_PHASE_OFFSET_DIVIDER.

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
 dpll/dpll.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/dpll/dpll.c b/dpll/dpll.c
index b6ba3283e0ba..e8056ff6a24b 100644
--- a/dpll/dpll.c
+++ b/dpll/dpll.c
@@ -410,6 +410,21 @@ static __s64 mnl_attr_get_sint(const struct nlattr *attr)
 		}                                                              \
 	} while (0)
 
+/* Phase offset - JSON prints raw sub-ps value, FP prints fractional ps */
+#define DPLL_PR_PHASE_OFFSET(tb, attr_id)                                      \
+	do {                                                                   \
+		if (tb[attr_id]) {                                             \
+			__s64 val = mnl_attr_get_sint(tb[attr_id]);            \
+			lldiv_t d = lldiv(llabs(val),                          \
+					  DPLL_PHASE_OFFSET_DIVIDER);	       \
+			print_s64(PRINT_JSON, "phase-offset", NULL, val);      \
+			print_string(PRINT_FP, NULL, " phase-offset %s",       \
+				     val < 0 ? "-" : "");                      \
+			print_s64(PRINT_FP, NULL, "%lld.", d.quot);            \
+			print_s64(PRINT_FP, NULL, "%03lld ps", d.rem);         \
+		}                                                              \
+	} while (0)
+
 /* Generic version with custom format */
 #define DPLL_PR_ENUM_STR_FMT(tb, attr_id, name, format_str, name_func)         \
 	do {                                                                   \
@@ -1507,8 +1522,7 @@ static void dpll_pin_print_parent_devices(struct nlattr *attr)
 				 " prio %u");
 		DPLL_PR_ENUM_STR_FMT(tb_parent, DPLL_A_PIN_STATE, "state",
 				     " state %s", dpll_pin_state_name);
-		DPLL_PR_SINT_FMT(tb_parent, DPLL_A_PIN_PHASE_OFFSET,
-				 "phase-offset", " phase-offset %" PRId64);
+		DPLL_PR_PHASE_OFFSET(tb_parent, DPLL_A_PIN_PHASE_OFFSET);
 
 		print_nl();
 		close_json_object();
@@ -1592,10 +1606,13 @@ static void dpll_pin_print_attrs(struct nlattr **tb)
 
 	dpll_pin_print_capabilities(tb[DPLL_A_PIN_CAPABILITIES]);
 
-	DPLL_PR_INT(tb, DPLL_A_PIN_PHASE_ADJUST_MIN, "phase-adjust-min");
-	DPLL_PR_INT(tb, DPLL_A_PIN_PHASE_ADJUST_MAX, "phase-adjust-max");
+	DPLL_PR_INT_FMT(tb, DPLL_A_PIN_PHASE_ADJUST_MIN, "phase-adjust-min",
+			"  phase-adjust-min: %d ps\n");
+	DPLL_PR_INT_FMT(tb, DPLL_A_PIN_PHASE_ADJUST_MAX, "phase-adjust-max",
+			"  phase-adjust-max: %d ps\n");
 	DPLL_PR_UINT(tb, DPLL_A_PIN_PHASE_ADJUST_GRAN, "phase-adjust-gran");
-	DPLL_PR_INT(tb, DPLL_A_PIN_PHASE_ADJUST, "phase-adjust");
+	DPLL_PR_INT_FMT(tb, DPLL_A_PIN_PHASE_ADJUST, "phase-adjust",
+			"  phase-adjust: %d ps\n");
 
 	if (json || !tb[DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT])
 		DPLL_PR_SINT(tb, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET,
-- 
2.53.0


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

* [PATCH iproute2-next 2/2] dpll: add frequency monitoring support
  2026-04-28 15:21 [PATCH iproute2-next 0/2] dpll: phase unit display and frequency monitoring Ivan Vecera
  2026-04-28 15:21 ` [PATCH iproute2-next 1/2] dpll: add ps unit to phase-related pin attributes Ivan Vecera
@ 2026-04-28 15:21 ` Ivan Vecera
  2026-05-01 10:20   ` Petr Oros
  2026-05-02 18:29   ` David Ahern
  1 sibling, 2 replies; 7+ messages in thread
From: Ivan Vecera @ 2026-04-28 15:21 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern, Stephen Hemminger, Petr Oros

Add support for the new frequency monitoring feature from the kernel
patch series "dpll: add actual frequency monitoring feature". This
includes:

- DPLL_A_FREQUENCY_MONITOR device attribute (enable/disable)
- DPLL_A_PIN_MEASURED_FREQUENCY pin attribute displayed as fractional Hz
  using DPLL_PR_MEASURED_FREQUENCY macro (kernel reports in mHz)
- device set: frequency-monitor { enable | disable }
- Refactor phase-offset-monitor to use new dpll_parse_attr_feature_state
  helper shared with frequency-monitor
- Update man page and bash-completion

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
 bash-completion/dpll |  4 +--
 dpll/dpll.c          | 62 ++++++++++++++++++++++++++++++++++----------
 man/man8/dpll.8      | 19 ++++++++++++--
 3 files changed, 68 insertions(+), 17 deletions(-)

diff --git a/bash-completion/dpll b/bash-completion/dpll
index 542b99c2fce2..7ddcf529d429 100644
--- a/bash-completion/dpll
+++ b/bash-completion/dpll
@@ -100,7 +100,7 @@ _dpll_device()
                     COMPREPLY=( $( compgen -W "automatic manual" -- "$cur" ) )
                     return 0
                     ;;
-                phase-offset-monitor)
+                phase-offset-monitor|frequency-monitor)
                     COMPREPLY=( $( compgen -W "enable disable true false 0 1" -- "$cur" ) )
                     return 0
                     ;;
@@ -110,7 +110,7 @@ _dpll_device()
                     ;;
                 *)
                     COMPREPLY=( $( compgen -W "id mode phase-offset-monitor \
-                        phase-offset-avg-factor" -- "$cur" ) )
+                        phase-offset-avg-factor frequency-monitor" -- "$cur" ) )
                     return 0
                     ;;
             esac
diff --git a/dpll/dpll.c b/dpll/dpll.c
index e8056ff6a24b..6d8c0cbb8a34 100644
--- a/dpll/dpll.c
+++ b/dpll/dpll.c
@@ -313,6 +313,26 @@ static int dpll_parse_attr_str(struct dpll *dpll, struct nlmsghdr *nlh,
 	return 0;
 }
 
+static int dpll_parse_attr_feature_state(struct dpll *dpll,
+					struct nlmsghdr *nlh,
+					const char *arg_name, int attr_id)
+{
+	const char *str = dpll_argv_next(dpll);
+	bool val;
+
+	if (!str) {
+		pr_err("%s requires an argument\n", arg_name);
+		return -EINVAL;
+	}
+	if (str_to_bool(str, &val)) {
+		pr_err("invalid %s value: %s (use enable/disable)\n",
+		       arg_name, str);
+		return -EINVAL;
+	}
+	mnl_attr_put_u32(nlh, attr_id, val ? 1 : 0);
+	return 0;
+}
+
 static int dpll_parse_attr_enum(struct dpll *dpll, struct nlmsghdr *nlh,
 				const char *arg_name, int attr_id,
 				int (*parse_func)(struct dpll *, __u32 *))
@@ -425,6 +445,21 @@ static __s64 mnl_attr_get_sint(const struct nlattr *attr)
 		}                                                              \
 	} while (0)
 
+/* Measured frequency - JSON prints raw mHz value, FP prints fractional Hz */
+#define DPLL_PR_MEASURED_FREQUENCY(tb, attr_id)                                \
+	do {                                                                   \
+		if (tb[attr_id]) {                                             \
+			__u64 val = mnl_attr_get_u64(tb[attr_id]);             \
+			lldiv_t d = lldiv(val,                                 \
+				DPLL_PIN_MEASURED_FREQUENCY_DIVIDER);           \
+			print_lluint(PRINT_JSON, "measured-frequency",         \
+				     NULL, val);                                \
+			print_s64(PRINT_FP, NULL,                              \
+				  "  measured-frequency: %lld.", d.quot);       \
+			print_s64(PRINT_FP, NULL, "%03lld Hz\n", d.rem);       \
+		}                                                              \
+	} while (0)
+
 /* Generic version with custom format */
 #define DPLL_PR_ENUM_STR_FMT(tb, attr_id, name, format_str, name_func)         \
 	do {                                                                   \
@@ -657,6 +692,7 @@ static void cmd_device_help(void)
 	pr_err("       dpll device set id DEVICE_ID [ mode { automatic | manual } ]\n");
 	pr_err("                                    [ phase-offset-monitor { enable | disable } ]\n");
 	pr_err("                                    [ phase-offset-avg-factor NUM ]\n");
+	pr_err("                                    [ frequency-monitor { enable | disable } ]\n");
 	pr_err("       dpll device id-get [ module-name NAME ] [ clock-id ID ] [ type TYPE ]\n");
 }
 
@@ -1058,6 +1094,10 @@ static void dpll_device_print_attrs(const struct nlmsghdr *nlh,
 			     str_enable_disable);
 	DPLL_PR_UINT(tb, DPLL_A_PHASE_OFFSET_AVG_FACTOR,
 		     "phase-offset-avg-factor");
+	DPLL_PR_ENUM_STR_FMT(tb, DPLL_A_FREQUENCY_MONITOR,
+			     "frequency-monitor",
+			     "  frequency-monitor: %s\n",
+			     str_enable_disable);
 }
 
 /* Netlink callback - device get (single device) */
@@ -1219,25 +1259,20 @@ static int cmd_device_set(struct dpll *dpll)
 						 dpll_parse_mode))
 				return -EINVAL;
 		} else if (dpll_argv_match(dpll, "phase-offset-monitor")) {
-			const char *str = dpll_argv_next(dpll);
-			bool val;
-
-			if (!str) {
-				pr_err("phase-offset-monitor requires an argument\n");
-				return -EINVAL;
-			}
-			if (str_to_bool(str, &val)) {
-				pr_err("invalid phase-offset-monitor value: %s (use enable/disable)\n",
-				       str);
+			if (dpll_parse_attr_feature_state(dpll, nlh,
+							  "phase-offset-monitor",
+							  DPLL_A_PHASE_OFFSET_MONITOR))
 				return -EINVAL;
-			}
-			mnl_attr_put_u32(nlh, DPLL_A_PHASE_OFFSET_MONITOR,
-					 val ? 1 : 0);
 		} else if (dpll_argv_match(dpll, "phase-offset-avg-factor")) {
 			if (dpll_parse_attr_u32(dpll, nlh,
 						"phase-offset-avg-factor",
 						DPLL_A_PHASE_OFFSET_AVG_FACTOR))
 				return -EINVAL;
+		} else if (dpll_argv_match(dpll, "frequency-monitor")) {
+			if (dpll_parse_attr_feature_state(dpll, nlh,
+							  "frequency-monitor",
+							  DPLL_A_FREQUENCY_MONITOR))
+				return -EINVAL;
 		} else {
 			pr_err("unknown option: %s\n", dpll_argv(dpll));
 			return -EINVAL;
@@ -1601,6 +1636,7 @@ static void dpll_pin_print_attrs(struct nlattr **tb)
 	DPLL_PR_ENUM_STR(tb, DPLL_A_PIN_TYPE, "type", dpll_pin_type_name);
 	DPLL_PR_U64_FMT(tb, DPLL_A_PIN_FREQUENCY, "frequency",
 			"  frequency: %" PRIu64 " Hz\n");
+	DPLL_PR_MEASURED_FREQUENCY(tb, DPLL_A_PIN_MEASURED_FREQUENCY);
 
 	dpll_pin_print_freq_supported(tb[DPLL_A_PIN_FREQUENCY_SUPPORTED]);
 
diff --git a/man/man8/dpll.8 b/man/man8/dpll.8
index 89f17af74923..59ec4208f251 100644
--- a/man/man8/dpll.8
+++ b/man/man8/dpll.8
@@ -111,7 +111,7 @@ Temperature (if supported)
 Type (PPS or EEC)
 .RE
 
-.SS dpll device set id ID [ mode { automatic | manual } ] [ phase-offset-monitor { enable | disable } ] [ phase-offset-avg-factor FACTOR ]
+.SS dpll device set id ID [ mode { automatic | manual } ] [ phase-offset-monitor { enable | disable } ] [ phase-offset-avg-factor FACTOR ] [ frequency-monitor { enable | disable } ]
 
 Configure DPLL device parameters.
 
@@ -140,6 +140,14 @@ When enabled, the kernel continuously measures and reports phase differences.
 Set the averaging factor (1-255) applied to phase offset calculations.
 Higher values provide smoother but slower-responding measurements.
 
+.TP
+.BI frequency-monitor " { enable | disable | true | false | 0 | 1 }"
+Enable or disable frequency monitoring on the device. When enabled, the
+kernel continuously measures and reports actual pin frequencies, which can
+be read via the
+.B measured-frequency
+field in pin show output.
+
 .SS dpll device id-get [ module-name NAME ] [ clock-id ID ] [ type TYPE ]
 
 Retrieve the device ID based on identifying attributes. Useful for scripting
@@ -233,7 +241,9 @@ Board label (hardware label from device tree or ACPI)
 .IP \[bu]
 Pin type (mux, ext, synce-eth-port, int-oscillator, gnss)
 .IP \[bu]
-Frequency and supported frequency ranges
+Configured frequency and supported frequency ranges
+.IP \[bu]
+Measured frequency in Hz (when frequency monitoring is enabled)
 .IP \[bu]
 Capabilities (state-can-change, priority-can-change, direction-can-change)
 .IP \[bu]
@@ -372,6 +382,11 @@ Press Ctrl+C to stop monitoring.
 .B dpll device set id 0 phase-offset-monitor enable
 .fi
 
+.SS Enable frequency monitoring on device 0
+.nf
+.B dpll device set id 0 frequency-monitor enable
+.fi
+
 .SS Show all EEC devices
 .nf
 .B dpll device show type eec
-- 
2.53.0


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

* Re: [PATCH iproute2-next 1/2] dpll: add ps unit to phase-related pin attributes
  2026-04-28 15:21 ` [PATCH iproute2-next 1/2] dpll: add ps unit to phase-related pin attributes Ivan Vecera
@ 2026-05-01 10:20   ` Petr Oros
  0 siblings, 0 replies; 7+ messages in thread
From: Petr Oros @ 2026-05-01 10:20 UTC (permalink / raw)
  To: Ivan Vecera, netdev; +Cc: David Ahern, Stephen Hemminger


On 4/28/26 17:21, Ivan Vecera wrote:
> Display phase-adjust-min, phase-adjust-max and phase-adjust values
> with ps unit. Add DPLL_PR_PHASE_OFFSET macro that properly formats
> phase-offset as fractional picoseconds by dividing the raw kernel
> value by DPLL_PHASE_OFFSET_DIVIDER.
>
> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
> ---
>   dpll/dpll.c | 27 ++++++++++++++++++++++-----
>   1 file changed, 22 insertions(+), 5 deletions(-)
>
> diff --git a/dpll/dpll.c b/dpll/dpll.c
> index b6ba3283e0ba..e8056ff6a24b 100644
> --- a/dpll/dpll.c
> +++ b/dpll/dpll.c
> @@ -410,6 +410,21 @@ static __s64 mnl_attr_get_sint(const struct nlattr *attr)
>   		}                                                              \
>   	} while (0)
>   
> +/* Phase offset - JSON prints raw sub-ps value, FP prints fractional ps */
> +#define DPLL_PR_PHASE_OFFSET(tb, attr_id)                                      \
> +	do {                                                                   \
> +		if (tb[attr_id]) {                                             \
> +			__s64 val = mnl_attr_get_sint(tb[attr_id]);            \
> +			lldiv_t d = lldiv(llabs(val),                          \
> +					  DPLL_PHASE_OFFSET_DIVIDER);	       \
> +			print_s64(PRINT_JSON, "phase-offset", NULL, val);      \
> +			print_string(PRINT_FP, NULL, " phase-offset %s",       \
> +				     val < 0 ? "-" : "");                      \
> +			print_s64(PRINT_FP, NULL, "%lld.", d.quot);            \
> +			print_s64(PRINT_FP, NULL, "%03lld ps", d.rem);         \
> +		}                                                              \
> +	} while (0)
> +
>   /* Generic version with custom format */
>   #define DPLL_PR_ENUM_STR_FMT(tb, attr_id, name, format_str, name_func)         \
>   	do {                                                                   \
> @@ -1507,8 +1522,7 @@ static void dpll_pin_print_parent_devices(struct nlattr *attr)
>   				 " prio %u");
>   		DPLL_PR_ENUM_STR_FMT(tb_parent, DPLL_A_PIN_STATE, "state",
>   				     " state %s", dpll_pin_state_name);
> -		DPLL_PR_SINT_FMT(tb_parent, DPLL_A_PIN_PHASE_OFFSET,
> -				 "phase-offset", " phase-offset %" PRId64);
> +		DPLL_PR_PHASE_OFFSET(tb_parent, DPLL_A_PIN_PHASE_OFFSET);
>   
>   		print_nl();
>   		close_json_object();
> @@ -1592,10 +1606,13 @@ static void dpll_pin_print_attrs(struct nlattr **tb)
>   
>   	dpll_pin_print_capabilities(tb[DPLL_A_PIN_CAPABILITIES]);
>   
> -	DPLL_PR_INT(tb, DPLL_A_PIN_PHASE_ADJUST_MIN, "phase-adjust-min");
> -	DPLL_PR_INT(tb, DPLL_A_PIN_PHASE_ADJUST_MAX, "phase-adjust-max");
> +	DPLL_PR_INT_FMT(tb, DPLL_A_PIN_PHASE_ADJUST_MIN, "phase-adjust-min",
> +			"  phase-adjust-min: %d ps\n");
> +	DPLL_PR_INT_FMT(tb, DPLL_A_PIN_PHASE_ADJUST_MAX, "phase-adjust-max",
> +			"  phase-adjust-max: %d ps\n");
>   	DPLL_PR_UINT(tb, DPLL_A_PIN_PHASE_ADJUST_GRAN, "phase-adjust-gran");
> -	DPLL_PR_INT(tb, DPLL_A_PIN_PHASE_ADJUST, "phase-adjust");
> +	DPLL_PR_INT_FMT(tb, DPLL_A_PIN_PHASE_ADJUST, "phase-adjust",
> +			"  phase-adjust: %d ps\n");
>   
>   	if (json || !tb[DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT])
>   		DPLL_PR_SINT(tb, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET,
Reviewed-by: Petr Oros <poros@redhat.com>


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

* Re: [PATCH iproute2-next 2/2] dpll: add frequency monitoring support
  2026-04-28 15:21 ` [PATCH iproute2-next 2/2] dpll: add frequency monitoring support Ivan Vecera
@ 2026-05-01 10:20   ` Petr Oros
  2026-05-02 18:29   ` David Ahern
  1 sibling, 0 replies; 7+ messages in thread
From: Petr Oros @ 2026-05-01 10:20 UTC (permalink / raw)
  To: Ivan Vecera, netdev; +Cc: David Ahern, Stephen Hemminger


On 4/28/26 17:21, Ivan Vecera wrote:
> Add support for the new frequency monitoring feature from the kernel
> patch series "dpll: add actual frequency monitoring feature". This
> includes:
>
> - DPLL_A_FREQUENCY_MONITOR device attribute (enable/disable)
> - DPLL_A_PIN_MEASURED_FREQUENCY pin attribute displayed as fractional Hz
>    using DPLL_PR_MEASURED_FREQUENCY macro (kernel reports in mHz)
> - device set: frequency-monitor { enable | disable }
> - Refactor phase-offset-monitor to use new dpll_parse_attr_feature_state
>    helper shared with frequency-monitor
> - Update man page and bash-completion
>
> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
> ---
>   bash-completion/dpll |  4 +--
>   dpll/dpll.c          | 62 ++++++++++++++++++++++++++++++++++----------
>   man/man8/dpll.8      | 19 ++++++++++++--
>   3 files changed, 68 insertions(+), 17 deletions(-)
>
> diff --git a/bash-completion/dpll b/bash-completion/dpll
> index 542b99c2fce2..7ddcf529d429 100644
> --- a/bash-completion/dpll
> +++ b/bash-completion/dpll
> @@ -100,7 +100,7 @@ _dpll_device()
>                       COMPREPLY=( $( compgen -W "automatic manual" -- "$cur" ) )
>                       return 0
>                       ;;
> -                phase-offset-monitor)
> +                phase-offset-monitor|frequency-monitor)
>                       COMPREPLY=( $( compgen -W "enable disable true false 0 1" -- "$cur" ) )
>                       return 0
>                       ;;
> @@ -110,7 +110,7 @@ _dpll_device()
>                       ;;
>                   *)
>                       COMPREPLY=( $( compgen -W "id mode phase-offset-monitor \
> -                        phase-offset-avg-factor" -- "$cur" ) )
> +                        phase-offset-avg-factor frequency-monitor" -- "$cur" ) )
>                       return 0
>                       ;;
>               esac
> diff --git a/dpll/dpll.c b/dpll/dpll.c
> index e8056ff6a24b..6d8c0cbb8a34 100644
> --- a/dpll/dpll.c
> +++ b/dpll/dpll.c
> @@ -313,6 +313,26 @@ static int dpll_parse_attr_str(struct dpll *dpll, struct nlmsghdr *nlh,
>   	return 0;
>   }
>   
> +static int dpll_parse_attr_feature_state(struct dpll *dpll,
> +					struct nlmsghdr *nlh,
> +					const char *arg_name, int attr_id)
> +{
> +	const char *str = dpll_argv_next(dpll);
> +	bool val;
> +
> +	if (!str) {
> +		pr_err("%s requires an argument\n", arg_name);
> +		return -EINVAL;
> +	}
> +	if (str_to_bool(str, &val)) {
> +		pr_err("invalid %s value: %s (use enable/disable)\n",
> +		       arg_name, str);
> +		return -EINVAL;
> +	}
> +	mnl_attr_put_u32(nlh, attr_id, val ? 1 : 0);
> +	return 0;
> +}
> +
>   static int dpll_parse_attr_enum(struct dpll *dpll, struct nlmsghdr *nlh,
>   				const char *arg_name, int attr_id,
>   				int (*parse_func)(struct dpll *, __u32 *))
> @@ -425,6 +445,21 @@ static __s64 mnl_attr_get_sint(const struct nlattr *attr)
>   		}                                                              \
>   	} while (0)
>   
> +/* Measured frequency - JSON prints raw mHz value, FP prints fractional Hz */
> +#define DPLL_PR_MEASURED_FREQUENCY(tb, attr_id)                                \
> +	do {                                                                   \
> +		if (tb[attr_id]) {                                             \
> +			__u64 val = mnl_attr_get_u64(tb[attr_id]);             \
> +			lldiv_t d = lldiv(val,                                 \
> +				DPLL_PIN_MEASURED_FREQUENCY_DIVIDER);           \
> +			print_lluint(PRINT_JSON, "measured-frequency",         \
> +				     NULL, val);                                \
> +			print_s64(PRINT_FP, NULL,                              \
> +				  "  measured-frequency: %lld.", d.quot);       \
> +			print_s64(PRINT_FP, NULL, "%03lld Hz\n", d.rem);       \
> +		}                                                              \
> +	} while (0)
> +
>   /* Generic version with custom format */
>   #define DPLL_PR_ENUM_STR_FMT(tb, attr_id, name, format_str, name_func)         \
>   	do {                                                                   \
> @@ -657,6 +692,7 @@ static void cmd_device_help(void)
>   	pr_err("       dpll device set id DEVICE_ID [ mode { automatic | manual } ]\n");
>   	pr_err("                                    [ phase-offset-monitor { enable | disable } ]\n");
>   	pr_err("                                    [ phase-offset-avg-factor NUM ]\n");
> +	pr_err("                                    [ frequency-monitor { enable | disable } ]\n");
>   	pr_err("       dpll device id-get [ module-name NAME ] [ clock-id ID ] [ type TYPE ]\n");
>   }
>   
> @@ -1058,6 +1094,10 @@ static void dpll_device_print_attrs(const struct nlmsghdr *nlh,
>   			     str_enable_disable);
>   	DPLL_PR_UINT(tb, DPLL_A_PHASE_OFFSET_AVG_FACTOR,
>   		     "phase-offset-avg-factor");
> +	DPLL_PR_ENUM_STR_FMT(tb, DPLL_A_FREQUENCY_MONITOR,
> +			     "frequency-monitor",
> +			     "  frequency-monitor: %s\n",
> +			     str_enable_disable);
>   }
>   
>   /* Netlink callback - device get (single device) */
> @@ -1219,25 +1259,20 @@ static int cmd_device_set(struct dpll *dpll)
>   						 dpll_parse_mode))
>   				return -EINVAL;
>   		} else if (dpll_argv_match(dpll, "phase-offset-monitor")) {
> -			const char *str = dpll_argv_next(dpll);
> -			bool val;
> -
> -			if (!str) {
> -				pr_err("phase-offset-monitor requires an argument\n");
> -				return -EINVAL;
> -			}
> -			if (str_to_bool(str, &val)) {
> -				pr_err("invalid phase-offset-monitor value: %s (use enable/disable)\n",
> -				       str);
> +			if (dpll_parse_attr_feature_state(dpll, nlh,
> +							  "phase-offset-monitor",
> +							  DPLL_A_PHASE_OFFSET_MONITOR))
>   				return -EINVAL;
> -			}
> -			mnl_attr_put_u32(nlh, DPLL_A_PHASE_OFFSET_MONITOR,
> -					 val ? 1 : 0);
>   		} else if (dpll_argv_match(dpll, "phase-offset-avg-factor")) {
>   			if (dpll_parse_attr_u32(dpll, nlh,
>   						"phase-offset-avg-factor",
>   						DPLL_A_PHASE_OFFSET_AVG_FACTOR))
>   				return -EINVAL;
> +		} else if (dpll_argv_match(dpll, "frequency-monitor")) {
> +			if (dpll_parse_attr_feature_state(dpll, nlh,
> +							  "frequency-monitor",
> +							  DPLL_A_FREQUENCY_MONITOR))
> +				return -EINVAL;
>   		} else {
>   			pr_err("unknown option: %s\n", dpll_argv(dpll));
>   			return -EINVAL;
> @@ -1601,6 +1636,7 @@ static void dpll_pin_print_attrs(struct nlattr **tb)
>   	DPLL_PR_ENUM_STR(tb, DPLL_A_PIN_TYPE, "type", dpll_pin_type_name);
>   	DPLL_PR_U64_FMT(tb, DPLL_A_PIN_FREQUENCY, "frequency",
>   			"  frequency: %" PRIu64 " Hz\n");
> +	DPLL_PR_MEASURED_FREQUENCY(tb, DPLL_A_PIN_MEASURED_FREQUENCY);
>   
>   	dpll_pin_print_freq_supported(tb[DPLL_A_PIN_FREQUENCY_SUPPORTED]);
>   
> diff --git a/man/man8/dpll.8 b/man/man8/dpll.8
> index 89f17af74923..59ec4208f251 100644
> --- a/man/man8/dpll.8
> +++ b/man/man8/dpll.8
> @@ -111,7 +111,7 @@ Temperature (if supported)
>   Type (PPS or EEC)
>   .RE
>   
> -.SS dpll device set id ID [ mode { automatic | manual } ] [ phase-offset-monitor { enable | disable } ] [ phase-offset-avg-factor FACTOR ]
> +.SS dpll device set id ID [ mode { automatic | manual } ] [ phase-offset-monitor { enable | disable } ] [ phase-offset-avg-factor FACTOR ] [ frequency-monitor { enable | disable } ]
>   
>   Configure DPLL device parameters.
>   
> @@ -140,6 +140,14 @@ When enabled, the kernel continuously measures and reports phase differences.
>   Set the averaging factor (1-255) applied to phase offset calculations.
>   Higher values provide smoother but slower-responding measurements.
>   
> +.TP
> +.BI frequency-monitor " { enable | disable | true | false | 0 | 1 }"
> +Enable or disable frequency monitoring on the device. When enabled, the
> +kernel continuously measures and reports actual pin frequencies, which can
> +be read via the
> +.B measured-frequency
> +field in pin show output.
> +
>   .SS dpll device id-get [ module-name NAME ] [ clock-id ID ] [ type TYPE ]
>   
>   Retrieve the device ID based on identifying attributes. Useful for scripting
> @@ -233,7 +241,9 @@ Board label (hardware label from device tree or ACPI)
>   .IP \[bu]
>   Pin type (mux, ext, synce-eth-port, int-oscillator, gnss)
>   .IP \[bu]
> -Frequency and supported frequency ranges
> +Configured frequency and supported frequency ranges
> +.IP \[bu]
> +Measured frequency in Hz (when frequency monitoring is enabled)
>   .IP \[bu]
>   Capabilities (state-can-change, priority-can-change, direction-can-change)
>   .IP \[bu]
> @@ -372,6 +382,11 @@ Press Ctrl+C to stop monitoring.
>   .B dpll device set id 0 phase-offset-monitor enable
>   .fi
>   
> +.SS Enable frequency monitoring on device 0
> +.nf
> +.B dpll device set id 0 frequency-monitor enable
> +.fi
> +
>   .SS Show all EEC devices
>   .nf
>   .B dpll device show type eec
Reviewed-by: Petr Oros <poros@redhat.com>


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

* Re: [PATCH iproute2-next 2/2] dpll: add frequency monitoring support
  2026-04-28 15:21 ` [PATCH iproute2-next 2/2] dpll: add frequency monitoring support Ivan Vecera
  2026-05-01 10:20   ` Petr Oros
@ 2026-05-02 18:29   ` David Ahern
  2026-05-03 15:11     ` Ivan Vecera
  1 sibling, 1 reply; 7+ messages in thread
From: David Ahern @ 2026-05-02 18:29 UTC (permalink / raw)
  To: Ivan Vecera, netdev; +Cc: Stephen Hemminger, Petr Oros

On 4/28/26 9:21 AM, Ivan Vecera wrote:
> diff --git a/man/man8/dpll.8 b/man/man8/dpll.8
> index 89f17af74923..59ec4208f251 100644
> --- a/man/man8/dpll.8
> +++ b/man/man8/dpll.8
> @@ -111,7 +111,7 @@ Temperature (if supported)
>  Type (PPS or EEC)
>  .RE
>  
> -.SS dpll device set id ID [ mode { automatic | manual } ] [ phase-offset-monitor { enable | disable } ] [ phase-offset-avg-factor FACTOR ]
> +.SS dpll device set id ID [ mode { automatic | manual } ] [ phase-offset-monitor { enable | disable } ] [ phase-offset-avg-factor FACTOR ] [ frequency-monitor { enable | disable } ]

very long line; please fix up.

Keep Petr reviewed by on patch 1.

Claude has some comments on the man page in general:

● I found three issues. Let me show them clearly:

  Issue 1 — Typo: "locked-ho-ack" should be "locked-ho-acq" (line 107)

  The man page description of device show output says locked-ho-ack but
the code (dpll_lock_status_name) returns locked-ho-acq
  (ACQuired, not ACKnowledge).

  Issue 2 — Wrong mode values in output description (lines 104–105)

  The "Output includes" section says:

  ▎ Operating mode (manual, automatic, holdover, freerun)

  But dpll_mode_map and DPLL_MODE_* only define manual and automatic.
Holdover and freerun are not DPLL modes — they are lock statuses.
   This should read (manual, automatic).

  Issue 3 — Undocumented but accepted alternate values for monitors
(lines 134, 144)

  The man page documents { enable | disable | true | false | 0 | 1 } for
phase-offset-monitor and frequency-monitor. The tool's own
  help text shows only { enable | disable } and the error message says
"use enable/disable". While str_to_bool technically accepts
  true/false/0/1, the canonical interface is enable | disable. The extra
forms in the man page are inconsistent with the help text.




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

* Re: [PATCH iproute2-next 2/2] dpll: add frequency monitoring support
  2026-05-02 18:29   ` David Ahern
@ 2026-05-03 15:11     ` Ivan Vecera
  0 siblings, 0 replies; 7+ messages in thread
From: Ivan Vecera @ 2026-05-03 15:11 UTC (permalink / raw)
  To: David Ahern, netdev; +Cc: Stephen Hemminger, Petr Oros

Hi David,

On 5/2/26 8:29 PM, David Ahern wrote:
> On 4/28/26 9:21 AM, Ivan Vecera wrote:
>> diff --git a/man/man8/dpll.8 b/man/man8/dpll.8
>> index 89f17af74923..59ec4208f251 100644
>> --- a/man/man8/dpll.8
>> +++ b/man/man8/dpll.8
>> @@ -111,7 +111,7 @@ Temperature (if supported)
>>   Type (PPS or EEC)
>>   .RE
>>   
>> -.SS dpll device set id ID [ mode { automatic | manual } ] [ phase-offset-monitor { enable | disable } ] [ phase-offset-avg-factor FACTOR ]
>> +.SS dpll device set id ID [ mode { automatic | manual } ] [ phase-offset-monitor { enable | disable } ] [ phase-offset-avg-factor FACTOR ] [ frequency-monitor { enable | disable } ]
> 
> very long line; please fix up.

Will fix in v2.

> 
> Keep Petr reviewed by on patch 1.
> 
> Claude has some comments on the man page in general:
> 
> ● I found three issues. Let me show them clearly:
> 
>    Issue 1 — Typo: "locked-ho-ack" should be "locked-ho-acq" (line 107)
> 
>    The man page description of device show output says locked-ho-ack but
> the code (dpll_lock_status_name) returns locked-ho-acq
>    (ACQuired, not ACKnowledge).
> 
>    Issue 2 — Wrong mode values in output description (lines 104–105)
> 
>    The "Output includes" section says:
> 
>    ▎ Operating mode (manual, automatic, holdover, freerun)
> 
>    But dpll_mode_map and DPLL_MODE_* only define manual and automatic.
> Holdover and freerun are not DPLL modes — they are lock statuses.
>     This should read (manual, automatic).
> 
>    Issue 3 — Undocumented but accepted alternate values for monitors
> (lines 134, 144)
> 
>    The man page documents { enable | disable | true | false | 0 | 1 } for
> phase-offset-monitor and frequency-monitor. The tool's own
>    help text shows only { enable | disable } and the error message says
> "use enable/disable". While str_to_bool technically accepts
>    true/false/0/1, the canonical interface is enable | disable. The extra
> forms in the man page are inconsistent with the help text.

Will send a separate fix for the dpll man page (non-next)...

Thanks,
Ivan


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

end of thread, other threads:[~2026-05-03 15:11 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28 15:21 [PATCH iproute2-next 0/2] dpll: phase unit display and frequency monitoring Ivan Vecera
2026-04-28 15:21 ` [PATCH iproute2-next 1/2] dpll: add ps unit to phase-related pin attributes Ivan Vecera
2026-05-01 10:20   ` Petr Oros
2026-04-28 15:21 ` [PATCH iproute2-next 2/2] dpll: add frequency monitoring support Ivan Vecera
2026-05-01 10:20   ` Petr Oros
2026-05-02 18:29   ` David Ahern
2026-05-03 15:11     ` Ivan Vecera

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