Skip to content

dpll: add device reset command with resync and holdover types - #7

Open
ivecera wants to merge 4 commits into
mainfrom
reset-resync
Open

dpll: add device reset command with resync and holdover types#7
ivecera wants to merge 4 commits into
mainfrom
reset-resync

Conversation

@ivecera

@ivecera ivecera commented Aug 7, 2026

Copy link
Copy Markdown
Owner

When an OCXO cold starts at power-up, its output frequency drifts by
10-20 ppm and takes 100-300 seconds to stabilize. If the DPLL begins
locking before the oscillator settles, it acquires a poor lock and
recovery is slow.

A re-synchronization is much more convenient than a full device restart
because it preserves clock I/O, holdover state, and all other device
settings. The DPLL simply re-locks to its currently selected input
reference.

This series adds a generic DPLL_CMD_DEVICE_RESET netlink command with
a reset type attribute. Two reset types are defined:

  • DPLL_RESET_TYPE_RESYNC: forces fast lock re-convergence without
    affecting inputs, outputs or other device settings.

  • DPLL_RESET_TYPE_HOLDOVER: clears the holdover filter and storage,
    resetting any accumulated holdover state.

The zl3073x driver implements resync using the hardware's fast lock
mechanism and holdover reset using the self-clearing clear_ho bit in
the dpll_cmd register (B Series and later chips only).

@ivecera
ivecera marked this pull request as ready for review August 7, 2026 14:15
ivecera pushed a commit that referenced this pull request Aug 11, 2026
In test_ringbuffer()'s out_free cleanup loop, the check
`!rb_threads[cpu]` only catches NULL entries and misses entries that
hold an ERR_PTR.

rb_threads[] is static, so unassigned slots are NULL. But when
kthread_run_on_cpu() fails for a cpu, it stores ERR_PTR(-ENOMEM) (or
-EINTR) in rb_threads[cpu] before the creation loop jumps to out_free.
That entry is non-NULL, so the old `!ptr` check does not break, and the
cleanup proceeds to call kthread_stop() on the ERR_PTR. kthread_stop()
then dereferences the bogus pointer, crashing the kernel during the
late_initcall self-test.

crash logs:
  BUG: kernel NULL pointer dereference, address: 000000000000001c
  Oops: 0002 [#1] SMP NOPTI
  CPU: 1 PID: 1 Comm: swapper/0 Not tainted 7.2.0-rc6-dirty #7 PREEMPT(lazy)
  RIP: 0010:kthread_stop+0x2e/0x220
  RBX: fffffffffffffff4
  CR2: 000000000000001c
  Call Trace:
   <TASK>
   test_ringbuffer+0x1ec/0x650
   do_one_initcall+0x6c/0x2c0
   kernel_init_freeable+0x21d/0x420
   kernel_init+0x15/0x1c0
   ret_from_fork+0x21b/0x320
   </TASK>
  Kernel panic - not syncing: Fatal exception

Cc: stable@vger.kernel.org
Fixes: 64ed3a0 ("ring-buffer: make use of the helper function kthread_run_on_cpu()")
Link: https://patch.msgid.link/20260807154145.2846521-2-sh_def@163.com
Signed-off-by: Hui Su <sh_def@163.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Add DPLL_CMD_DEVICE_RESET netlink command with DPLL_A_RESET_TYPE
attribute. The first reset type is DPLL_RESET_TYPE_RESYNC which
forces the DPLL to re-lock to its currently selected input reference
without affecting inputs, outputs or other device settings.

This is useful for recovery from OCXO cold-start conditions where the
PLL may have acquired a poor lock while the oscillator frequency was
still settling.

Add .reset callback to struct dpll_device_ops for driver
implementations.

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
@ivecera
ivecera force-pushed the reset-resync branch 3 times, most recently from 23f9d15 to cb66a4c Compare August 19, 2026 12:34
Implement the .reset callback for the ZL3073X DPLL driver. The resync
operation triggers fast lock re-convergence by setting the force_en bit
in the dpll_fast_lock_ctrl mailbox register, waiting for the DPLL to
enter the FAST_LOCK state, then restoring the original register value.

Generalize zl3073x_poll_zero_u8() into zl3073x_poll_u8() that accepts
an expected value parameter. The original function becomes an inline
wrapper.

Cache the dpll_fast_lock_ctrl register in struct zl3073x_chan and
commit changes through the existing zl3073x_chan_state_set() path.

Before triggering fast lock, verify that a qualified input reference
is selected, as the hardware requires a valid input to exit holdover
and enter the fast lock state.

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Add DPLL_RESET_TYPE_HOLDOVER to the reset type enum. This type clears
the DPLL holdover filter and storage, resetting any accumulated
holdover state.

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Implement DPLL_RESET_TYPE_HOLDOVER by writing the self-clearing
clear_ho bit in the dpll_cmd register. This clears the holdover
filter, holdover storage and ho_ready status.

The clear_ho command is only available on B Series and later chips.
Add ZL3073X_FLAG_HO_CLEAR chip flag to gate the feature and return
-EOPNOTSUPP on older variants.

Log the actual time spent waiting for the self-clear so the timeout
constant can be tuned after testing on real hardware.

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
@ivecera ivecera changed the title dpll: add device reset command with resync type dpll: add device reset command with resync and holdover types Aug 20, 2026
@ivecera
ivecera requested a review from orosp August 20, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant