> -----Original Message-----
> From: Loktionov, Aleksandr <[email protected]>
> Sent: Tuesday, March 24, 2026 9:13 AM
> To: Nitka, Grzegorz <[email protected]>; [email protected]
> Cc: Vecera, Ivan <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]; Kitszel,
> Przemyslaw <[email protected]>; [email protected];
> [email protected]; [email protected]; Kubalewski,
> Arkadiusz <[email protected]>; [email protected];
> [email protected]; [email protected];
> [email protected]; Nguyen, Anthony L
> <[email protected]>; [email protected];
> [email protected]
> Subject: RE: [Intel-wired-lan] [PATCH v3 net-next 8/8] ice: add TX reference
> clock (tx_clk) control for E825 devices
> 
> 
> 
> > -----Original Message-----
> > From: Intel-wired-lan <[email protected]> On Behalf
> > Of Grzegorz Nitka
> > Sent: Monday, March 23, 2026 11:22 PM
> > To: [email protected]
> > Cc: Vecera, Ivan <[email protected]>; [email protected];
> > [email protected]; [email protected]; [email protected]; Kitszel,
> > Przemyslaw <[email protected]>; [email protected];
> > [email protected]; [email protected]; Kubalewski,
> > Arkadiusz <[email protected]>; [email protected];
> > [email protected]; [email protected];
> > [email protected]; Nguyen, Anthony L
> > <[email protected]>; [email protected];
> [email protected]
> > Subject: [Intel-wired-lan] [PATCH v3 net-next 8/8] ice: add TX
> > reference clock (tx_clk) control for E825 devices
> >
> > Add full support for selecting and controlling the TX SERDES reference
> > clock on E825C hardware. E825C devicede supports selecting among
> > multiple SERDES transmit reference clock sources (ENET, SyncE, EREF0),
> > but imposes several routing constraints: on some paths a reference
> > must be enabled on both PHY complexes, and ports sharing a PHY must
> > coordinate usage so that a reference is not disabled while still in
> > active use. Until now the driver did not expose this domain through
> > the DPLL API, nor did it provide a coherent control layer for
> > enabling, switching, or tracking TX reference clocks.
> >
> > This patch implements full TX reference clock management for E825
> > devices. Compared to previous iterations, the logic is now separated
> > into a dedicated module (ice_txclk.c) which encapsulates all clock-
> > selection rules, cross‑PHY dependencies, and the bookkeeping needed to
> > ensure safe transitions. This allows the DPLL layer and the PTP code
> > to remain focused on their respective roles.
> >
> > Key additions:
> >
> >   * A new txclk control module (`ice_txclk.c`) implementing:
> >       - software usage tracking for each reference clock per PHY,
> >       - peer‑PHY enable rules (SyncE required on both PHYs when used
> > on
> >         PHY0, EREF0 required on both when used on PHY1),
> >       - safe disabling of unused reference clocks after switching,
> >       - a single, driver‑internal entry point for clock changes.
> >
> >   * Integration with the DPLL pin ops:
> >       - pin‑set now calls into `ice_txclk_set_clk()` to request a
> >         hardware switch,
> >       - pin‑get reports the current SERDES reference by reading back
> > the
> >         active selector (`ice_get_serdes_ref_sel_e825c()`).
> >
> >   * Wiring the requested reference clock into Auto‑Negotiation restart
> >     through the already‑extended `ice_aq_set_link_restart_an()`.
> >
> >   * After each link-up the driver verifies the effective hardware
> > state
> >     (`ice_txclk_verify()`) and updates its per‑PHY usage bitmaps,
> >     correcting the requested/active state if the FW or AN flow applied
> > a
> >     different reference.
> >
> >   * PTP PF initialization now seeds the ENET reference clock as
> > enabled
> >     by default for its port.
> >
> > All reference clock transitions are serialized through the DPLL lock,
> > and usage information is shared across all PFs belonging to the same
> > E825C controller PF. This ensures that concurrent changes are
> > coordinated and that shared PHYs never see an unexpected disable.
> >
> > With this patch, E825 devices gain full userspace‑driven TXC reference
> > clock selection via the DPLL subsystem, enabling complete SyncE
> > support, precise multi‑clock setups, and predictable clock routing
> > behavior.
> >
> > Reviewed-by: Arkadiusz Kubalewski <[email protected]>
> > Signed-off-by: Grzegorz Nitka <[email protected]>
> > ---
> >  drivers/net/ethernet/intel/ice/Makefile     |   2 +-
> >  drivers/net/ethernet/intel/ice/ice_dpll.c   |  53 ++++-
> >  drivers/net/ethernet/intel/ice/ice_ptp.c    |  22 ++
> >  drivers/net/ethernet/intel/ice/ice_ptp.h    |   7 +
> >  drivers/net/ethernet/intel/ice/ice_ptp_hw.c |  37 +++
> > drivers/net/ethernet/intel/ice/ice_ptp_hw.h |  27 +++
> > drivers/net/ethernet/intel/ice/ice_txclk.c  | 237 ++++++++++++++++++++
> > drivers/net/ethernet/intel/ice/ice_txclk.h  |  41 ++++
> >  8 files changed, 414 insertions(+), 12 deletions(-)  create mode
> > 100644 drivers/net/ethernet/intel/ice/ice_txclk.c
> >  create mode 100644 drivers/net/ethernet/intel/ice/ice_txclk.h
> >
> > diff --git a/drivers/net/ethernet/intel/ice/Makefile
> > b/drivers/net/ethernet/intel/ice/Makefile
> > index 38db476ab2ec..95fd0c49800f 100644
> > --- a/drivers/net/ethernet/intel/ice/Makefile
> > +++ b/drivers/net/ethernet/intel/ice/Makefile
> > @@ -54,7 +54,7 @@ ice-$(CONFIG_PCI_IOV) +=  \
> >     ice_vf_mbx.o            \
> >     ice_vf_vsi_vlan_ops.o   \
> >     ice_vf_lib.o
> > -ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o ice_dpll.o
> > ice_tspll.o ice_cpi.o
> > +ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o ice_dpll.o
> > +ice_tspll.o ice_cpi.o ice_txclk.o
> >  ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o
> >  ice-$(CONFIG_RFS_ACCEL) += ice_arfs.o
> >  ice-$(CONFIG_XDP_SOCKETS) += ice_xsk.o
> > diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c
> > b/drivers/net/ethernet/intel/ice/ice_dpll.c
> > index 72518fd1398d..ac0bfc2f0f0e 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_dpll.c
> > +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
> > @@ -4,6 +4,7 @@
> >  #include "ice.h"
> >  #include "ice_lib.h"
> >  #include "ice_trace.h"
> > +#include "ice_txclk.h"
> >  #include <linux/dpll.h>
> >  #include <linux/property.h>
> >
> > @@ -2538,7 +2539,9 @@ ice_dpll_rclk_state_on_pin_get(const struct
> > dpll_pin *pin, void *pin_priv,
> >   *
> >   * Dpll subsystem callback, set a state of a Tx reference clock pin
> >   *
> > + * Context: Acquires and releases pf->dplls.lock
> >   * Return:
> > + * * 0 - success
> >   * * negative - failure
> >   */
> >  static int
> > @@ -2547,11 +2550,24 @@ ice_dpll_txclk_state_on_dpll_set(const struct
> > dpll_pin *pin, void *pin_priv,
> >                              void *dpll_priv, enum dpll_pin_state
> > state,
> >                              struct netlink_ext_ack *extack)
> >  {
> > -   /*
> > -    * TODO: set HW accordingly to selected TX reference clock.
> > -    * To be added in the follow up patches.
> > -    */
> > -   return -EOPNOTSUPP;
> > +   struct ice_dpll_pin *p = pin_priv;
> > +   struct ice_pf *pf = p->pf;
> > +   enum ice_e825c_ref_clk new_clk;
> > +   int ret = 0;
> > +
> > +   if (ice_dpll_is_reset(pf, extack))
> > +           return -EBUSY;
> > +
> > +   mutex_lock(&pf->dplls.lock);
> > +   new_clk = (state == DPLL_PIN_STATE_DISCONNECTED) ?
> > ICE_REF_CLK_ENET :
> > +                   p->tx_ref_src;
> > +   if (new_clk == pf->ptp.port.tx_clk)
> > +           goto unlock;
> > +
> > +   ret = ice_txclk_set_clk(pf, new_clk);
> > +unlock:
> > +   mutex_unlock(&pf->dplls.lock);
> > +   return ret;
> >  }
> >
> >  /**
> > @@ -2565,8 +2581,10 @@ ice_dpll_txclk_state_on_dpll_set(const struct
> > dpll_pin *pin, void *pin_priv,
> >   *
> >   * dpll subsystem callback, get a state of a TX clock reference pin.
> >   *
> > + * Context: Acquires and releases pf->dplls.lock
> >   * Return:
> >   * * 0 - success
> > + * * negative - failure
> >   */
> >  static int
> >  ice_dpll_txclk_state_on_dpll_get(const struct dpll_pin *pin, void
> > *pin_priv, @@ -2575,13 +2593,26 @@
> > ice_dpll_txclk_state_on_dpll_get(const struct dpll_pin *pin, void
> > *pin_priv,
> >                              enum dpll_pin_state *state,
> >                              struct netlink_ext_ack *extack)
> >  {
> > -   /*
> > -    * TODO: query HW status to determine if the TX reference is
> > selected.
> > -    * To be added in the follow up patches.
> > -    */
> > -   *state = DPLL_PIN_STATE_DISCONNECTED;
> > +   struct ice_dpll_pin *p = pin_priv;
> > +   enum ice_e825c_ref_clk clk;
> > +   struct ice_pf *pf = p->pf;
> > +   int ret;
> >
> > -   return 0;
> > +   if (ice_dpll_is_reset(pf, extack))
> > +           return -EBUSY;
> > +
> > +   mutex_lock(&pf->dplls.lock);
> > +   ret = ice_get_serdes_ref_sel_e825c(&pf->hw, pf-
> > >ptp.port.port_num,
> > +                                      &clk);
> > +   if (ret)
> > +           goto unlock;
> > +
> > +   *state = (clk == p->tx_ref_src) ? DPLL_PIN_STATE_CONNECTED :
> > +                   DPLL_PIN_STATE_DISCONNECTED;
> > +unlock:
> > +   mutex_unlock(&pf->dplls.lock);
> > +
> > +   return ret;
> >  }
> >
> >  static const struct dpll_pin_ops ice_dpll_rclk_ops = { diff --git
> > a/drivers/net/ethernet/intel/ice/ice_ptp.c
> > b/drivers/net/ethernet/intel/ice/ice_ptp.c
> > index 094e96219f45..84b1fa00bc52 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_ptp.c
> > +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
> > @@ -4,6 +4,7 @@
> >  #include "ice.h"
> >  #include "ice_lib.h"
> >  #include "ice_trace.h"
> > +#include "ice_txclk.h"
> >
> >  static const char ice_pin_names[][64] = {
> >     "SDP0",
> > @@ -1325,6 +1326,10 @@ void ice_ptp_link_change(struct ice_pf *pf,
> > bool linkup)
> >                             return;
> >                     }
> >             }
> > +
> > +           if (linkup)
> > +                   ice_txclk_verify(pf);
> > +
> >             mutex_unlock(&pf->dplls.lock);
> >     }
> >
> > @@ -3079,6 +3084,7 @@ static int ice_ptp_setup_pf(struct ice_pf *pf)
> > {
> >     struct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(pf);
> >     struct ice_ptp *ptp = &pf->ptp;
> > +   u8 port_num, phy;
> >
> >     if (WARN_ON(!ctrl_ptp) || pf->hw.mac_type ==
> ICE_MAC_UNKNOWN)
> >             return -ENODEV;
> > @@ -3090,6 +3096,10 @@ static int ice_ptp_setup_pf(struct ice_pf *pf)
> >              &pf->adapter->ports.ports);
> >     mutex_unlock(&pf->adapter->ports.lock);
> >
> > +   port_num = ptp->port.port_num;
> > +   phy = port_num / pf->hw.ptp.ports_per_phy;
> > +   set_bit(port_num, &ctrl_ptp->tx_refclks[phy][pf-
> > >ptp.port.tx_clk]);
> > +
> >     return 0;
> >  }
> >
> > @@ -3290,6 +3300,7 @@ static void
> > ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf)
> >   */
> >  void ice_ptp_init(struct ice_pf *pf)
> >  {
> > +   enum ice_e825c_ref_clk tx_ref_clk;
> >     struct ice_ptp *ptp = &pf->ptp;
> >     struct ice_hw *hw = &pf->hw;
> >     int err;
> > @@ -3318,6 +3329,17 @@ void ice_ptp_init(struct ice_pf *pf)
> >                     goto err_exit;
> >     }
> >
> > +   ptp->port.tx_clk = ICE_REF_CLK_ENET;
> > +   ptp->port.tx_clk_req = ICE_REF_CLK_ENET;
> > +   if (hw->mac_type == ICE_MAC_GENERIC_3K_E825) {
> > +           err = ice_get_serdes_ref_sel_e825c(hw, ptp-
> > >port.port_num,
> > +                                              &tx_ref_clk);
> > +           if (!err) {
> > +                   ptp->port.tx_clk = tx_ref_clk;
> > +                   ptp->port.tx_clk_req = tx_ref_clk;
> > +           }
> > +   }
> > +
> >     err = ice_ptp_setup_pf(pf);
> >     if (err)
> >             goto err_exit;
> > diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h
> > b/drivers/net/ethernet/intel/ice/ice_ptp.h
> > index 8c44bd758a4f..8b385271ab36 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_ptp.h
> > +++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
> > @@ -144,6 +144,8 @@ struct ice_ptp_tx {
> >   * @link_up: indicates whether the link is up
> >   * @tx_fifo_busy_cnt: number of times the Tx FIFO was busy
> >   * @port_num: the port number this structure represents
> > + * @tx_clk: currently active Tx reference clock source
> > + * @tx_clk_req: requested Tx reference clock source (new target)
> >   */
> >  struct ice_ptp_port {
> >     struct list_head list_node;
> > @@ -153,6 +155,8 @@ struct ice_ptp_port {
> >     bool link_up;
> >     u8 tx_fifo_busy_cnt;
> >     u8 port_num;
> > +   enum ice_e825c_ref_clk tx_clk;
> > +   enum ice_e825c_ref_clk tx_clk_req;
> >  };
> >
> >  enum ice_ptp_tx_interrupt {
> > @@ -236,6 +240,7 @@ struct ice_ptp_pin_desc {
> >   * @info: structure defining PTP hardware capabilities
> >   * @clock: pointer to registered PTP clock device
> >   * @tstamp_config: hardware timestamping configuration
> > + * @tx_refclks: bitmaps table to store the information about TX
> > + reference clocks
> >   * @reset_time: kernel time after clock stop on reset
> >   * @tx_hwtstamp_good: number of completed Tx timestamp requests
> >   * @tx_hwtstamp_skipped: number of Tx time stamp requests skipped
> @@
> > -261,6 +266,8 @@ struct ice_ptp {
> >     struct ptp_clock_info info;
> >     struct ptp_clock *clock;
> >     struct kernel_hwtstamp_config tstamp_config;
> > +#define ICE_E825_MAX_PHYS 2
> > +   unsigned long tx_refclks[ICE_E825_MAX_PHYS][ICE_REF_CLK_MAX];
> >     u64 reset_time;
> >     u64 tx_hwtstamp_good;
> >     u32 tx_hwtstamp_skipped;
> > diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
> > b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
> > index 61c0a0d93ea8..c0720525ac49 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
> > +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
> > @@ -461,6 +461,43 @@ static int ice_read_phy_eth56g(struct ice_hw *hw,
> > u8 port, u32 addr, u32 *val)
> >     return err;
> >  }
> >
> > +/**
> > + * ice_get_serdes_ref_sel_e825c - Read current Tx ref clock source
> > + * @hw: pointer to the HW struct
> > + * @port: port number for which Tx reference clock is read
> > + * @clk: Tx reference clock value (output)
> > + *
> > + * Return: 0 on success, other error codes when failed to read from
> > PHY
> > +*/ int ice_get_serdes_ref_sel_e825c(struct ice_hw *hw, u8 port,
> > +                            enum ice_e825c_ref_clk *clk)
> > +{
> > +   u8 lane = port % hw->ptp.ports_per_phy;
> > +   u32 serdes_rx_nt, serdes_tx_nt;
> > +   u32 val;
> > +   int ret;
> > +
> > +   ret = ice_read_phy_eth56g(hw, port,
> > +                             SERDES_IP_IF_LN_FLXM_GENERAL(lane, 0),
> > +                             &val);
> > +   if (ret)
> > +           return ret;
> > +
> > +   serdes_rx_nt = FIELD_GET(CFG_ICTL_PCS_REF_SEL_RX_NT, val);
> > +   serdes_tx_nt = FIELD_GET(CFG_ICTL_PCS_REF_SEL_TX_NT, val);
> > +
> > +   if (serdes_tx_nt == REF_SEL_NT_SYNCE &&
> > +       serdes_rx_nt == REF_SEL_NT_SYNCE)
> > +           *clk = ICE_REF_CLK_SYNCE;
> > +   else if (serdes_tx_nt == REF_SEL_NT_EREF0 &&
> > +            serdes_rx_nt == REF_SEL_NT_EREF0)
> > +           *clk = ICE_REF_CLK_EREF0;
> > +   else
> > +           *clk = ICE_REF_CLK_ENET;
> > +
> > +   return 0;
> > +}
> > +
> >  /**
> >   * ice_phy_res_address_eth56g - Calculate a PHY port register address
> >   * @hw: pointer to the HW struct
> > diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
> > b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
> > index cbc9693179a1..820ba953ea01 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
> > +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
> > @@ -381,6 +381,8 @@ int ice_stop_phy_timer_eth56g(struct ice_hw *hw,
> > u8 port, bool soft_reset);  int ice_start_phy_timer_eth56g(struct
> > ice_hw *hw, u8 port);  int ice_phy_cfg_intr_eth56g(struct ice_hw *hw,
> > u8 port, bool ena, u8 threshold);  int
> > ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port);
> > +int ice_get_serdes_ref_sel_e825c(struct ice_hw *hw, u8 port,
> > +                            enum ice_e825c_ref_clk *clk);
> >
> >  #define ICE_ETH56G_NOMINAL_INCVAL  0x140000000ULL
> >  #define ICE_ETH56G_NOMINAL_PCS_REF_TUS     0x100000000ULL
> > @@ -790,4 +792,29 @@ static inline u64 ice_get_base_incval(struct
> > ice_hw *hw)
> >  #define PHY_PTP_1STEP_PD_DELAY_M   GENMASK(30, 1)
> >  #define PHY_PTP_1STEP_PD_DLY_V_M   BIT(31)
> >
> > +#define SERDES_IP_IF_LN_FLXM_GENERAL(n, m) \
> > +   (0x32B800 + (m) * 0x100000 + (n) * 0x8000)
> > +#define CFG_RESERVED0_1                         GENMASK(1, 0)
> > +#define CFG_ICTL_PCS_MODE_NT                    BIT(2)
> > +#define CFG_ICTL_PCS_RCOMP_SLAVE_EN_NT          BIT(3)
> > +#define CFG_ICTL_PCS_CMN_FORCE_PUP_A            BIT(4)
> > +#define CFG_ICTL_PCS_RCOMP_SLAVE_VALID_A        BIT(5)
> > +#define CFG_ICTL_PCS_REF_SEL_RX_NT              GENMASK(9, 6)
> > +#define REF_SEL_NT_ENET                         0
> > +#define REF_SEL_NT_EREF0                        1
> > +#define REF_SEL_NT_SYNCE                        2
> > +#define CFG_IDAT_DFX_OBS_DIG_                   GENMASK(11, 10)
> > +#define CFG_IRST_APB_MEM_B                      BIT(12)
> > +#define CFG_ICTL_PCS_DISCONNECT_NT              BIT(13)
> > +#define CFG_ICTL_PCS_ISOLATE_NT                 BIT(14)
> > +#define CFG_RESERVED15_15                       BIT(15)
> > +#define CFG_IRST_PCS_TSTBUS_B_A                 BIT(16)
> > +#define CFG_ICTL_PCS_REF_TERM_HIZ_EN_NT         BIT(17)
> > +#define CFG_RESERVED18_19                       GENMASK(19, 18)
> > +#define CFG_ICTL_PCS_SYNTHLCSLOW_FORCE_PUP_A    BIT(20)
> > +#define CFG_ICTL_PCS_SYNTHLCFAST_FORCE_PUP_A    BIT(21)
> > +#define CFG_RESERVED22_24                       GENMASK(24, 22)
> > +#define CFG_ICTL_PCS_REF_SEL_TX_NT              GENMASK(28, 25)
> > +#define CFG_RESERVED29_31                       GENMASK(31, 29)
> > +
> >  #endif /* _ICE_PTP_HW_H_ */
> > diff --git a/drivers/net/ethernet/intel/ice/ice_txclk.c
> > b/drivers/net/ethernet/intel/ice/ice_txclk.c
> > new file mode 100644
> > index 000000000000..125f5db4d092
> > --- /dev/null
> > +++ b/drivers/net/ethernet/intel/ice/ice_txclk.c
> > @@ -0,0 +1,237 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright (C) 2026 Intel Corporation */
> > +
> > +#include "ice.h"
> > +#include "ice_cpi.h"
> > +#include "ice_txclk.h"
> > +
> > +static struct ice_pf *ice_get_ctrl_pf(struct ice_pf *pf) {
> > +   return !pf->adapter ? NULL : pf->adapter->ctrl_pf; }
> Can legitimately return NULL
> So potential NULL pointer dereference in many places.

Aleks, thanks for your review!
Yes, good point.
I'll add NULL checker in the next iteration.
Also, I realized that ice_get_ctrl_pf function is also defined
in ice_ptp module. Will move it to the header file.

Thanks

Grzegorz
> > +
> > +#define ICE_PHY0   0
> > +#define ICE_PHY1   1
> > +
> 
> ...
> 
> > +/**
> > + * ice_txclk_disable_unused - Disable TX reference clock no longer in
> > +use
> > + * @pf: pointer to the PF structure
> > + * @ref_clk: TX reference clock source to evaluate for disabling
> > + *
> > + * Disable (from power-saving reasons) a TX reference clock after a
> > +clock
> > + * switch, provided that:
> > + *   - no port on the local PHY uses this clock, and
> > + *   - for SyncE: no port on PHY0 or PHY1 requires the clock,
> > depending on
> > + *     where it must remain enabled for routing.
> > + *   - for EREF0: same logic as above but inverted PHY roles.
> > + *
> > + * Some reference clocks must be enabled on both PHY complexes when
> > +used
> > + * (SyncE for PHY0, EREF0 for PHY1). The function therefore also
> > +attempts
> > + * to implicitly disable the peer PHY copy when no port requires it.
> > + *
> > + * Return: 0 on success or negative error code if disabling fails.
> > + */
> > +static int
> > +ice_txclk_disable_unused(struct ice_pf *pf, enum ice_e825c_ref_clk
> > +ref_clk) {
> > +   struct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);
> Can legitimately return NULL
> 
> > +   struct ice_hw *hw = &pf->hw;
> > +   int err = 0;
> > +   u8 cur_phy;
> > +
> > +   cur_phy = pf->ptp.port.port_num / hw->ptp.ports_per_phy;
> > +
> > +   if (ref_clk == ICE_REF_CLK_SYNCE) {
> > +           /* Don't disable SyncE clock if it's still in use on PHY
> > 0 */
> > +           if (ice_txclk_any_port_uses(ctrl_pf, ICE_PHY0, ref_clk))
> NULL pointer dereference.
> 
> > +                   return 0;
> > +           if (cur_phy == ICE_PHY0 &&
> > +               !ice_txclk_any_port_uses(ctrl_pf, ICE_PHY1,
> > ref_clk)) {
> > +                   err = ice_cpi_ena_dis_clk_ref(hw, ICE_PHY1,
> > ref_clk,
> > +                                                 false);
> > +                   if (err) {
> > +                           cur_phy = ICE_PHY1;
> > +                           goto err;
> > +                   }
> > +           }
> > +   } else if (ref_clk == ICE_REF_CLK_EREF0) {
> > +           /* Don't disable EREF0 clock if it's still in use on PHY
> > 1 */
> > +           if (ice_txclk_any_port_uses(ctrl_pf, ICE_PHY1, ref_clk))
> > +                   return 0;
> > +           if (cur_phy == ICE_PHY1 &&
> > +               !ice_txclk_any_port_uses(ctrl_pf, ICE_PHY0,
> > ref_clk)) {
> > +                   err = ice_cpi_ena_dis_clk_ref(hw, ICE_PHY0,
> > ref_clk,
> > +                                                 false);
> > +                   if (err) {
> > +                           cur_phy = ICE_PHY0;
> > +                           goto err;
> > +                   }
> > +           }
> > +   }
> 
> ...
> 
> > --
> > 2.39.3

Reply via email to