Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ice: fix missing dpll notifications for SW pins

The SMA/U.FL pin redesign (commit 2dd5d03c77e2 ("ice: redesign dpll
sma/u.fl pins control")) introduced software-controlled pins that wrap
backing CGU input/output pins, but never updated the notification and
data paths to propagate pin events to these SW wrappers.

The periodic work sends dpll_pin_change_ntf() only for direct CGU input
pins. SW pins that wrap these inputs never receive change or phase
offset notifications, so userspace consumers such as synce4l monitoring
SMA pins via dpll netlink never learn about state transitions or phase
offset updates. Similarly, ice_dpll_phase_offset_get() reads the SW
pin's own phase_offset field which is never updated; the PPS monitor
writes to the backing CGU input's field instead.

Fix by introducing ice_dpll_pin_ntf(), a wrapper around
dpll_pin_change_ntf() that also notifies any registered SMA/U.FL pin
whose backing CGU input matches. Replace all direct
dpll_pin_change_ntf() calls in the periodic notification paths with
this wrapper. Fix ice_dpll_phase_offset_get() to return the backing
CGU input's phase_offset for input-direction SW pins.

Fixes: 2dd5d03c77e2 ("ice: redesign dpll sma/u.fl pins control")
Signed-off-by: Petr Oros <poros@redhat.com>
Tested-by: Alexander Nowlin <alexander.nowlin@intel.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Ivan Vecera <ivecera@redhat.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20260427-jk-iwl-net-petr-oros-fixes-v1-10-cdcb48303fd8@intel.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Petr Oros and committed by
Paolo Abeni
1a41b58f 620055cb

+36 -11
+36 -11
drivers/net/ethernet/intel/ice/ice_dpll.c
··· 1963 1963 d->active_input == p->input->pin)) 1964 1964 *phase_offset = d->phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR; 1965 1965 else if (d->phase_offset_monitor_period) 1966 - *phase_offset = p->phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR; 1966 + *phase_offset = (p->input && 1967 + p->direction == DPLL_PIN_DIRECTION_INPUT ? 1968 + p->input->phase_offset : 1969 + p->phase_offset) * ICE_DPLL_PHASE_OFFSET_FACTOR; 1967 1970 else 1968 1971 *phase_offset = 0; 1969 1972 mutex_unlock(&pf->dplls.lock); ··· 2661 2658 } 2662 2659 2663 2660 /** 2661 + * ice_dpll_pin_ntf - notify pin change including any SW pin wrappers 2662 + * @dplls: pointer to dplls struct 2663 + * @pin: the dpll_pin that changed 2664 + * 2665 + * Send a change notification for @pin and for any registered SMA/U.FL pin 2666 + * whose backing CGU input matches @pin. 2667 + */ 2668 + static void ice_dpll_pin_ntf(struct ice_dplls *dplls, struct dpll_pin *pin) 2669 + { 2670 + dpll_pin_change_ntf(pin); 2671 + for (int i = 0; i < ICE_DPLL_PIN_SW_NUM; i++) { 2672 + if (dplls->sma[i].pin && dplls->sma[i].input && 2673 + dplls->sma[i].input->pin == pin) 2674 + dpll_pin_change_ntf(dplls->sma[i].pin); 2675 + if (dplls->ufl[i].pin && dplls->ufl[i].input && 2676 + dplls->ufl[i].input->pin == pin) 2677 + dpll_pin_change_ntf(dplls->ufl[i].pin); 2678 + } 2679 + } 2680 + 2681 + /** 2664 2682 * ice_dpll_notify_changes - notify dpll subsystem about changes 2665 2683 * @d: pointer do dpll 2666 2684 * ··· 2689 2665 */ 2690 2666 static void ice_dpll_notify_changes(struct ice_dpll *d) 2691 2667 { 2668 + struct ice_dplls *dplls = &d->pf->dplls; 2692 2669 bool pin_notified = false; 2693 2670 2694 2671 if (d->prev_dpll_state != d->dpll_state) { ··· 2698 2673 } 2699 2674 if (d->prev_input != d->active_input) { 2700 2675 if (d->prev_input) 2701 - dpll_pin_change_ntf(d->prev_input); 2676 + ice_dpll_pin_ntf(dplls, d->prev_input); 2702 2677 d->prev_input = d->active_input; 2703 2678 if (d->active_input) { 2704 - dpll_pin_change_ntf(d->active_input); 2679 + ice_dpll_pin_ntf(dplls, d->active_input); 2705 2680 pin_notified = true; 2706 2681 } 2707 2682 } 2708 2683 if (d->prev_phase_offset != d->phase_offset) { 2709 2684 d->prev_phase_offset = d->phase_offset; 2710 2685 if (!pin_notified && d->active_input) 2711 - dpll_pin_change_ntf(d->active_input); 2686 + ice_dpll_pin_ntf(dplls, d->active_input); 2712 2687 } 2713 2688 } 2714 2689 ··· 2737 2712 2738 2713 /** 2739 2714 * ice_dpll_pins_notify_mask - notify dpll subsystem about bulk pin changes 2715 + * @dplls: pointer to dplls struct 2740 2716 * @pins: array of ice_dpll_pin pointers registered within dpll subsystem 2741 2717 * @pin_num: number of pins 2742 2718 * @phase_offset_ntf_mask: bitmask of pin indexes to notify ··· 2747 2721 * 2748 2722 * Context: Must be called while pf->dplls.lock is released. 2749 2723 */ 2750 - static void ice_dpll_pins_notify_mask(struct ice_dpll_pin *pins, 2724 + static void ice_dpll_pins_notify_mask(struct ice_dplls *dplls, 2725 + struct ice_dpll_pin *pins, 2751 2726 u8 pin_num, 2752 2727 u32 phase_offset_ntf_mask) 2753 2728 { 2754 - int i = 0; 2755 - 2756 - for (i = 0; i < pin_num; i++) 2757 - if (phase_offset_ntf_mask & (1 << i)) 2758 - dpll_pin_change_ntf(pins[i].pin); 2729 + for (int i = 0; i < pin_num; i++) 2730 + if (phase_offset_ntf_mask & BIT(i)) 2731 + ice_dpll_pin_ntf(dplls, pins[i].pin); 2759 2732 } 2760 2733 2761 2734 /** ··· 2930 2905 ice_dpll_notify_changes(de); 2931 2906 ice_dpll_notify_changes(dp); 2932 2907 if (phase_offset_ntf) 2933 - ice_dpll_pins_notify_mask(d->inputs, d->num_inputs, 2908 + ice_dpll_pins_notify_mask(d, d->inputs, d->num_inputs, 2934 2909 phase_offset_ntf); 2935 2910 2936 2911 resched: