Files
Ivan VeceraandJakub Kicinski 2c1bd78dc8 dpll: use pin owner's dpll ref for pin-level attribute reporting
Commit c191b319f2 ("dpll: allow registering FW-identified pin with a
different DPLL") relaxed dpll_pin_register() to let fwnode-identified pins
register with DPLLs from a different driver. This allows, for example, the
ICE driver to register a zl3073x-created pin with its TXC DPLL using
ice_dpll_txclk_ops, which lack frequency_get and phase_adjust_get
callbacks.

After such cross-driver registration, the pin's dpll_refs xarray contains
refs from both drivers. dpll_cmd_pin_get_one() calls
dpll_xa_ref_dpll_first() which returns the ref with the lowest DPLL id.
When the foreign DPLL (e.g. ICE TXC) has a lower id than the owner DPLL
(e.g. zl3073x), the foreign ops are used for reporting. Since those ops
lack callbacks like frequency_get, pin-level attributes are silently
omitted from the netlink response.

For example, a zl3073x output pin that should report frequency and
phase-adjust shows neither:

Before:
  # dpll pin show id 45
  pin id 45:
    module-name: zl3073x
    clock-id: 3427468959636104019
    board-label: 156M25_NAC0_CLKREF_SYNC
    package-label: OUT3
    type: synce-eth-port
    capabilities: 0x0
    phase-adjust-min: -2147483648
    phase-adjust-max: 2147483647
    phase-adjust-gran: 800
    parent-device:
      ...

After:
  # dpll pin show id 19
  pin id 19:
    module-name: zl3073x
    clock-id: 15964355450360090479
    board-label: 156M25_NAC0_CLKREF_SYNC
    package-label: OUT3
    type: synce-eth-port
    frequency: 156250000 Hz
    frequency-supported:
      156250000 Hz
    capabilities: 0x0
    phase-adjust-min: -2147483648
    phase-adjust-max: 2147483647
    phase-adjust-gran: 800
    phase-adjust: 0
    parent-device:
      ...

Fix this by:

1. Adding dpll_pin_own_dpll_ref_first() helper that returns the first ref
   whose DPLL matches the pin's (module, clock_id) tuple -- i.e. the DPLL
   from the driver that created the pin and has the complete set of ops.
   Return NULL if no owner ref is found.

2. Using dpll_pin_own_dpll_ref_first() in dpll_cmd_pin_get_one() with a
   fallback to dpll_xa_ref_dpll_first() for pin-on-pin child pins whose
   dpll_refs all point to a different driver's DPLLs.

3. Using dpll_pin_own_dpll_ref_first() in SET operations
   (dpll_pin_freq_set, dpll_pin_esync_set, dpll_pin_ref_sync_state_set,
   dpll_pin_phase_adj_set) returning -ENODEV if no owner ref exists.
   Replacing the validation loops that rejected the entire operation when
   any ref's ops lacked the required callback -- instead validate only the
   owner refs so that foreign DPLLs with incomplete ops no longer block
   SET operations.

4. Guarding all SET and rollback xa_for_each loops against NULL set
   callbacks so that foreign refs without the operation are safely skipped
   instead of causing a NULL pointer dereference.

Fixes: c191b319f2 ("dpll: allow registering FW-identified pin with a different DPLL")
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Acked-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20260714125945.1823269-1-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-07-24 16:15:19 -07:00
..
2026-06-13 13:24:31 -07:00
2026-04-30 16:21:49 +02:00