]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
dpll: zl3073x: use struct_group to partition states
authorIvan Vecera <ivecera@redhat.com>
Sun, 15 Mar 2026 17:42:19 +0000 (18:42 +0100)
committerJakub Kicinski <kuba@kernel.org>
Wed, 18 Mar 2026 02:05:12 +0000 (19:05 -0700)
Organize the zl3073x_out, zl3073x_ref, and zl3073x_synth structures
using struct_group() to partition fields into semantic groups:

  * cfg:  mutable configuration written to HW via state_set
  * inv:  invariant fields set once during state_fetch
  * stat: read-only status

This enables group-level operations in place of field-by-field copies:

  * state_set validates invariants haven't changed (WARN_ON + -EINVAL)
  * state_set short-circuits when cfg is unchanged
  * state_set copy entire groups in a single assignment instead of
    enumerating each field

Add kernel doc for zl3073x_out_state_set and zl3073x_ref_state_set
documenting the new invariant validation and short-circuit semantics.

Remove forward declaration of zl3073x_synth_state_set().

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Link: https://patch.msgid.link/20260315174224.399074-2-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/dpll/zl3073x/out.c
drivers/dpll/zl3073x/out.h
drivers/dpll/zl3073x/ref.c
drivers/dpll/zl3073x/ref.h
drivers/dpll/zl3073x/synth.h

index 86829a0c1c022f44e2f7c9071c35d55a52268dde..eb5628aebcee8ee7350cc5fd878e77836e66eba1 100644 (file)
@@ -106,12 +106,32 @@ const struct zl3073x_out *zl3073x_out_state_get(struct zl3073x_dev *zldev,
        return &zldev->out[index];
 }
 
+/**
+ * zl3073x_out_state_set - commit output state changes to hardware
+ * @zldev: pointer to zl3073x_dev structure
+ * @index: output index to set state for
+ * @out: desired output state
+ *
+ * Validates that invariant fields have not been modified, skips the HW
+ * write if the mutable configuration is unchanged, and otherwise writes
+ * only the changed cfg fields to hardware via the mailbox interface.
+ *
+ * Return: 0 on success, -EINVAL if invariants changed, <0 on HW error
+ */
 int zl3073x_out_state_set(struct zl3073x_dev *zldev, u8 index,
                          const struct zl3073x_out *out)
 {
        struct zl3073x_out *dout = &zldev->out[index];
        int rc;
 
+       /* Reject attempts to change invariant fields (set at fetch only) */
+       if (WARN_ON(memcmp(&dout->inv, &out->inv, sizeof(out->inv))))
+               return -EINVAL;
+
+       /* Skip HW write if configuration hasn't changed */
+       if (!memcmp(&dout->cfg, &out->cfg, sizeof(out->cfg)))
+               return 0;
+
        guard(mutex)(&zldev->multiop_lock);
 
        /* Read output configuration into mailbox */
@@ -146,12 +166,7 @@ int zl3073x_out_state_set(struct zl3073x_dev *zldev, u8 index,
                return rc;
 
        /* After successful commit store new state */
-       dout->div = out->div;
-       dout->width = out->width;
-       dout->esync_n_period = out->esync_n_period;
-       dout->esync_n_width = out->esync_n_width;
-       dout->mode = out->mode;
-       dout->phase_comp = out->phase_comp;
+       dout->cfg = out->cfg;
 
        return 0;
 }
index 318f9bb8da3a064abe48711ba7e12830e482ab66..edf40432bba5f072958a5912965dfec3c83fa189 100644 (file)
@@ -4,6 +4,7 @@
 #define _ZL3073X_OUT_H
 
 #include <linux/bitfield.h>
+#include <linux/stddef.h>
 #include <linux/types.h>
 
 #include "regs.h"
@@ -17,17 +18,21 @@ struct zl3073x_dev;
  * @esync_n_period: embedded sync or n-pin period (for n-div formats)
  * @esync_n_width: embedded sync or n-pin pulse width
  * @phase_comp: phase compensation
- * @ctrl: output control
  * @mode: output mode
+ * @ctrl: output control
  */
 struct zl3073x_out {
-       u32     div;
-       u32     width;
-       u32     esync_n_period;
-       u32     esync_n_width;
-       s32     phase_comp;
-       u8      ctrl;
-       u8      mode;
+       struct_group(cfg, /* Config */
+               u32     div;
+               u32     width;
+               u32     esync_n_period;
+               u32     esync_n_width;
+               s32     phase_comp;
+               u8      mode;
+       );
+       struct_group(inv, /* Invariants */
+               u8      ctrl;
+       );
 };
 
 int zl3073x_out_state_fetch(struct zl3073x_dev *zldev, u8 index);
index 6b65e61039999b52cf2e8690614f950ab30e9684..8b4c4807bcc447b0f2bf23714863effb65ba2e8c 100644 (file)
@@ -73,14 +73,8 @@ int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index)
                struct zl3073x_ref *p_ref = ref - 1; /* P-pin counterpart*/
 
                /* Copy the shared items from the P-pin */
-               ref->config = p_ref->config;
-               ref->esync_n_div = p_ref->esync_n_div;
-               ref->freq_base = p_ref->freq_base;
-               ref->freq_mult = p_ref->freq_mult;
-               ref->freq_ratio_m = p_ref->freq_ratio_m;
-               ref->freq_ratio_n = p_ref->freq_ratio_n;
-               ref->phase_comp = p_ref->phase_comp;
-               ref->sync_ctrl = p_ref->sync_ctrl;
+               ref->cfg = p_ref->cfg;
+               ref->inv = p_ref->inv;
 
                return 0; /* Finish - no non-shared items for now */
        }
@@ -154,12 +148,32 @@ zl3073x_ref_state_get(struct zl3073x_dev *zldev, u8 index)
        return &zldev->ref[index];
 }
 
+/**
+ * zl3073x_ref_state_set - commit input reference state changes to hardware
+ * @zldev: pointer to zl3073x_dev structure
+ * @index: input reference index to set state for
+ * @ref: desired reference state
+ *
+ * Validates that invariant fields have not been modified, skips the HW
+ * write if the mutable configuration is unchanged, and otherwise writes
+ * only the changed cfg fields to hardware via the mailbox interface.
+ *
+ * Return: 0 on success, -EINVAL if invariants changed, <0 on HW error
+ */
 int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
                          const struct zl3073x_ref *ref)
 {
        struct zl3073x_ref *dref = &zldev->ref[index];
        int rc;
 
+       /* Reject attempts to change invariant fields (set at init only) */
+       if (WARN_ON(memcmp(&dref->inv, &ref->inv, sizeof(ref->inv))))
+               return -EINVAL;
+
+       /* Skip HW write if configuration hasn't changed */
+       if (!memcmp(&dref->cfg, &ref->cfg, sizeof(ref->cfg)))
+               return 0;
+
        guard(mutex)(&zldev->multiop_lock);
 
        /* Read reference configuration into mailbox */
@@ -207,13 +221,7 @@ int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
                return rc;
 
        /* After successful commit store new state */
-       dref->freq_base = ref->freq_base;
-       dref->freq_mult = ref->freq_mult;
-       dref->freq_ratio_m = ref->freq_ratio_m;
-       dref->freq_ratio_n = ref->freq_ratio_n;
-       dref->esync_n_div = ref->esync_n_div;
-       dref->sync_ctrl = ref->sync_ctrl;
-       dref->phase_comp = ref->phase_comp;
+       dref->cfg = ref->cfg;
 
        return 0;
 }
index 0d8618f5ce8df55600f03f0a5d6972371bd74902..ab3a816c291089caf8f3b065bec36b5b3732c9e6 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/math64.h>
+#include <linux/stddef.h>
 #include <linux/types.h>
 
 #include "regs.h"
@@ -13,28 +14,34 @@ struct zl3073x_dev;
 
 /**
  * struct zl3073x_ref - input reference state
- * @ffo: current fractional frequency offset
  * @phase_comp: phase compensation
  * @esync_n_div: divisor for embedded sync or n-divided signal formats
  * @freq_base: frequency base
  * @freq_mult: frequnecy multiplier
  * @freq_ratio_m: FEC mode multiplier
  * @freq_ratio_n: FEC mode divisor
- * @config: reference config
  * @sync_ctrl: reference sync control
+ * @config: reference config
+ * @ffo: current fractional frequency offset
  * @mon_status: reference monitor status
  */
 struct zl3073x_ref {
-       s64     ffo;
-       u64     phase_comp;
-       u32     esync_n_div;
-       u16     freq_base;
-       u16     freq_mult;
-       u16     freq_ratio_m;
-       u16     freq_ratio_n;
-       u8      config;
-       u8      sync_ctrl;
-       u8      mon_status;
+       struct_group(cfg, /* Configuration */
+               u64     phase_comp;
+               u32     esync_n_div;
+               u16     freq_base;
+               u16     freq_mult;
+               u16     freq_ratio_m;
+               u16     freq_ratio_n;
+               u8      sync_ctrl;
+       );
+       struct_group(inv, /* Invariants */
+               u8      config;
+       );
+       struct_group(stat, /* Status */
+               s64     ffo;
+               u8      mon_status;
+       );
 };
 
 int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index);
index 6c55eb8a888c2c152a18164387fa2a02cffae9ba..89e13ea2e6d941063a4bc270d3999f3233aa9758 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/math64.h>
+#include <linux/stddef.h>
 #include <linux/types.h>
 
 #include "regs.h"
@@ -20,11 +21,13 @@ struct zl3073x_dev;
  * @ctrl: synth control
  */
 struct zl3073x_synth {
-       u32     freq_mult;
-       u16     freq_base;
-       u16     freq_m;
-       u16     freq_n;
-       u8      ctrl;
+       struct_group(inv, /* Invariants */
+               u32     freq_mult;
+               u16     freq_base;
+               u16     freq_m;
+               u16     freq_n;
+               u8      ctrl;
+       );
 };
 
 int zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 synth_id);
@@ -32,9 +35,6 @@ int zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 synth_id);
 const struct zl3073x_synth *zl3073x_synth_state_get(struct zl3073x_dev *zldev,
                                                    u8 synth_id);
 
-int zl3073x_synth_state_set(struct zl3073x_dev *zldev, u8 synth_id,
-                           const struct zl3073x_synth *synth);
-
 /**
  * zl3073x_synth_dpll_get - get DPLL ID the synth is driven by
  * @synth: pointer to synth state