dpll: zl3073x: use struct_group to partition states

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>
This commit is contained in:
Ivan Vecera authored and Jakub Kicinski committed 2026-03-17 19:05:12 -07:00
1 parent bb8539e0e6
commit f327f5a811
5 files changed
+84 -49

No files matched your search

+21 -6
View 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;
}
+13 -8
View 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);
+23 -15
View 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;
}
+19 -12
View 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);
+8 -8
View 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