diff --git a/kernel-rt/debian/patches/ice-VDF/0001-ice-Auxbus-devices-driver-for-E822-TS.patch b/kernel-rt/debian/patches/ice-VDF/0001-ice-Auxbus-devices-driver-for-E822-TS.patch new file mode 100644 index 00000000..d0ad7896 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0001-ice-Auxbus-devices-driver-for-E822-TS.patch @@ -0,0 +1,684 @@ +From ba0d88d4ff54805aac7aec77cc5b05d0df9114da Mon Sep 17 00:00:00 2001 +From: Michal Michalik +Date: Thu, 27 Jul 2023 15:50:34 +0200 +Subject: [PATCH 01/36] ice: Auxbus devices & driver for E822 TS + +There is a problem in HW in E822-based devices leading to race +condition. +It might happen that, in order: +- PF0 (which owns the PHC) requests few timestamps, +- PF1 requests a timestamp, +- interrupt is being triggered and both PF0 and PF1 threads are woken +up, +- PF0 got one timestamp, still waiting for others so not going to sleep, +- PF1 gets it's timestamp, process it and go to sleep, +- PF1 requests a timestamp again, +- just before PF0 goes to sleep timestamp of PF1 appear, +- PF0 finishes all it's timestamps and go to sleep (PF1 also sleeping). +That leaves PF1 timestamp memory not read, which lead to blocking the +next interrupt from arriving. + +Fix it by adding auxiliary devices and only one driver to handle all the +timestamps for all PF's by PHC owner. In the past each PF requested it's +own timestamps and process it from the start till the end which causes +problem described above. Currently each PF requests the timestamps as +before, but the actual reading of the completed timestamps is being done +by the PTP auxiliary driver, which is registered by the PF which owns PHC. + +Additionally, the newly introduced auxiliary driver/devices for PTP clock +owner will be used for other features in all products (including E810). + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Signed-off-by: Michal Michalik +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit d938a8cca88a5f02f523f95fe3d2d1214f4b4a8d) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 12 + + .../net/ethernet/intel/ice/ice_hw_autogen.h | 1 + + drivers/net/ethernet/intel/ice/ice_main.c | 11 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 393 +++++++++++++++++- + drivers/net/ethernet/intel/ice/ice_ptp.h | 30 ++ + 5 files changed, 430 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index b9cd0113b859..0a3d76d184ba 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -671,6 +671,18 @@ static inline bool ice_vector_ch_enabled(struct ice_q_vector *qv) + return !!qv->ch; /* Enable it to run with TC */ + } + ++/** ++ * ice_ptp_pf_handles_tx_interrupt - Check if PF handles Tx interrupt ++ * @pf: Board private structure ++ * ++ * Return true if this PF should respond to the Tx timestamp interrupt ++ * indication in the miscellaneous OICR interrupt handler. ++ */ ++static inline bool ice_ptp_pf_handles_tx_interrupt(struct ice_pf *pf) ++{ ++ return pf->ptp.tx_interrupt_mode != ICE_PTP_TX_INTERRUPT_NONE; ++} ++ + /** + * ice_irq_dynamic_ena - Enable default interrupt generation settings + * @hw: pointer to HW struct +diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +index 531cc2194741..6756f3d51d14 100644 +--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h ++++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +@@ -231,6 +231,7 @@ + #define PFINT_SB_CTL 0x0016B600 + #define PFINT_SB_CTL_MSIX_INDX_M ICE_M(0x7FF, 0) + #define PFINT_SB_CTL_CAUSE_ENA_M BIT(30) ++#define PFINT_TSYN_MSK 0x0016C980 + #define QINT_RQCTL(_QRX) (0x00150000 + ((_QRX) * 4)) + #define QINT_RQCTL_MSIX_INDX_S 0 + #define QINT_RQCTL_MSIX_INDX_M ICE_M(0x7FF, 0) +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 8a6acb5a722e..39cb6ee52abe 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3190,7 +3190,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + if (oicr & PFINT_OICR_TSYN_TX_M) { + ena_mask &= ~PFINT_OICR_TSYN_TX_M; +- if (!hw->reset_ongoing) ++ if (!hw->reset_ongoing && ice_ptp_pf_handles_tx_interrupt(pf)) + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); + } + +@@ -7444,8 +7444,13 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + } + + /* configure PTP timestamping after VSI rebuild */ +- if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) +- ice_ptp_cfg_timestamp(pf, false); ++ if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) { ++ if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) ++ ice_ptp_cfg_timestamp(pf, false); ++ else if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) ++ /* for E82x PHC owner always need to have interrupts */ ++ ice_ptp_cfg_timestamp(pf, true); ++ } + + err = ice_vsi_rebuild_by_type(pf, ICE_VSI_SWITCHDEV_CTRL); + if (err) { +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 3648d3cccacc..e3012608c9dd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -255,6 +255,24 @@ ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin, + return ice_ptp_set_sma_e810t(info, pin, func); + } + ++/** ++ * ice_ptp_configure_tx_tstamp - Enable or disable Tx timestamp interrupt ++ * @pf: The PF pointer to search in ++ * @on: bool value for whether timestamp interrupt is enabled or disabled ++ */ ++static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on) ++{ ++ u32 val; ++ ++ /* Configure the Tx timestamp interrupt */ ++ val = rd32(&pf->hw, PFINT_OICR_ENA); ++ if (on) ++ val |= PFINT_OICR_TSYN_TX_M; ++ else ++ val &= ~PFINT_OICR_TSYN_TX_M; ++ wr32(&pf->hw, PFINT_OICR_ENA, val); ++} ++ + /** + * ice_set_tx_tstamp - Enable or disable Tx timestamping + * @pf: The PF pointer to search in +@@ -263,7 +281,6 @@ ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin, + static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) + { + struct ice_vsi *vsi; +- u32 val; + u16 i; + + vsi = ice_get_main_vsi(pf); +@@ -277,13 +294,8 @@ static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) + vsi->tx_rings[i]->ptp_tx = on; + } + +- /* Configure the Tx timestamp interrupt */ +- val = rd32(&pf->hw, PFINT_OICR_ENA); +- if (on) +- val |= PFINT_OICR_TSYN_TX_M; +- else +- val &= ~PFINT_OICR_TSYN_TX_M; +- wr32(&pf->hw, PFINT_OICR_ENA, val); ++ if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) ++ ice_ptp_configure_tx_tstamp(pf, on); + + pf->ptp.tstamp_config.tx_type = on ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + } +@@ -674,9 +686,6 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + int err; + u8 idx; + +- if (!tx->init) +- return; +- + ptp_port = container_of(tx, struct ice_ptp_port, tx); + pf = ptp_port_to_pf(ptp_port); + hw = &pf->hw; +@@ -774,6 +783,39 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + } + } + ++/** ++ * ice_ptp_tx_tstamp_owner - Process Tx timestamps for all ports on the device ++ * @pf: Board private structure ++ */ ++static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) ++{ ++ struct ice_ptp_port *port; ++ unsigned int i; ++ ++ mutex_lock(&pf->ptp.ports_owner.lock); ++ list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member) { ++ struct ice_ptp_tx *tx = &port->tx; ++ ++ if (!tx || !tx->init) ++ continue; ++ ++ ice_ptp_process_tx_tstamp(tx); ++ } ++ mutex_unlock(&pf->ptp.ports_owner.lock); ++ ++ for (i = 0; i < ICE_MAX_QUAD; i++) { ++ u64 tstamp_ready; ++ int err; ++ ++ /* Read the Tx ready status first */ ++ err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready); ++ if (err || tstamp_ready) ++ return ICE_TX_TSTAMP_WORK_PENDING; ++ } ++ ++ return ICE_TX_TSTAMP_WORK_DONE; ++} ++ + /** + * ice_ptp_tx_tstamp - Process Tx timestamps for this function. + * @tx: Tx tracking structure to initialize +@@ -2448,7 +2490,21 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) + */ + enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf) + { +- return ice_ptp_tx_tstamp(&pf->ptp.port.tx); ++ switch (pf->ptp.tx_interrupt_mode) { ++ case ICE_PTP_TX_INTERRUPT_NONE: ++ /* This device has the clock owner handle timestamps for it */ ++ return ICE_TX_TSTAMP_WORK_DONE; ++ case ICE_PTP_TX_INTERRUPT_SELF: ++ /* This device handles its own timestamps */ ++ return ice_ptp_tx_tstamp(&pf->ptp.port.tx); ++ case ICE_PTP_TX_INTERRUPT_ALL: ++ /* This device handles timestamps for all ports */ ++ return ice_ptp_tx_tstamp_owner(pf); ++ default: ++ WARN_ONCE(1, "Unexpected Tx timestamp interrupt mode %u\n", ++ pf->ptp.tx_interrupt_mode); ++ return ICE_TX_TSTAMP_WORK_DONE; ++ } + } + + static void ice_ptp_periodic_work(struct kthread_work *work) +@@ -2557,6 +2613,187 @@ void ice_ptp_reset(struct ice_pf *pf) + dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err); + } + ++/** ++ * ice_ptp_aux_dev_to_aux_pf - Get auxiliary PF handle for the auxiliary device ++ * @aux_dev: auxiliary device to get the auxiliary PF for ++ */ ++static struct ice_pf * ++ice_ptp_aux_dev_to_aux_pf(struct auxiliary_device *aux_dev) ++{ ++ struct ice_ptp_port *aux_port; ++ struct ice_ptp *aux_ptp; ++ ++ aux_port = container_of(aux_dev, struct ice_ptp_port, aux_dev); ++ aux_ptp = container_of(aux_port, struct ice_ptp, port); ++ ++ return container_of(aux_ptp, struct ice_pf, ptp); ++} ++ ++/** ++ * ice_ptp_aux_dev_to_owner_pf - Get PF handle for the auxiliary device ++ * @aux_dev: auxiliary device to get the PF for ++ */ ++static struct ice_pf * ++ice_ptp_aux_dev_to_owner_pf(struct auxiliary_device *aux_dev) ++{ ++ struct ice_ptp_port_owner *ports_owner; ++ struct auxiliary_driver *aux_drv; ++ struct ice_ptp *owner_ptp; ++ ++ if (!aux_dev->dev.driver) ++ return NULL; ++ ++ aux_drv = to_auxiliary_drv(aux_dev->dev.driver); ++ ports_owner = container_of(aux_drv, struct ice_ptp_port_owner, ++ aux_driver); ++ owner_ptp = container_of(ports_owner, struct ice_ptp, ports_owner); ++ return container_of(owner_ptp, struct ice_pf, ptp); ++} ++ ++/** ++ * ice_ptp_auxbus_probe - Probe auxiliary devices ++ * @aux_dev: PF's auxiliary device ++ * @id: Auxiliary device ID ++ */ ++static int ice_ptp_auxbus_probe(struct auxiliary_device *aux_dev, ++ const struct auxiliary_device_id *id) ++{ ++ struct ice_pf *owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev); ++ struct ice_pf *aux_pf = ice_ptp_aux_dev_to_aux_pf(aux_dev); ++ ++ if (WARN_ON(!owner_pf)) ++ return -ENODEV; ++ ++ INIT_LIST_HEAD(&aux_pf->ptp.port.list_member); ++ mutex_lock(&owner_pf->ptp.ports_owner.lock); ++ list_add(&aux_pf->ptp.port.list_member, ++ &owner_pf->ptp.ports_owner.ports); ++ mutex_unlock(&owner_pf->ptp.ports_owner.lock); ++ ++ return 0; ++} ++ ++/** ++ * ice_ptp_auxbus_remove - Remove auxiliary devices from the bus ++ * @aux_dev: PF's auxiliary device ++ */ ++static void ice_ptp_auxbus_remove(struct auxiliary_device *aux_dev) ++{ ++ struct ice_pf *owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev); ++ struct ice_pf *aux_pf = ice_ptp_aux_dev_to_aux_pf(aux_dev); ++ ++ mutex_lock(&owner_pf->ptp.ports_owner.lock); ++ list_del(&aux_pf->ptp.port.list_member); ++ mutex_unlock(&owner_pf->ptp.ports_owner.lock); ++} ++ ++/** ++ * ice_ptp_auxbus_shutdown ++ * @aux_dev: PF's auxiliary device ++ */ ++static void ice_ptp_auxbus_shutdown(struct auxiliary_device *aux_dev) ++{ ++ /* Doing nothing here, but handle to auxbus driver must be satisfied */ ++} ++ ++/** ++ * ice_ptp_auxbus_suspend ++ * @aux_dev: PF's auxiliary device ++ * @state: power management state indicator ++ */ ++static int ++ice_ptp_auxbus_suspend(struct auxiliary_device *aux_dev, pm_message_t state) ++{ ++ /* Doing nothing here, but handle to auxbus driver must be satisfied */ ++ return 0; ++} ++ ++/** ++ * ice_ptp_auxbus_resume ++ * @aux_dev: PF's auxiliary device ++ */ ++static int ice_ptp_auxbus_resume(struct auxiliary_device *aux_dev) ++{ ++ /* Doing nothing here, but handle to auxbus driver must be satisfied */ ++ return 0; ++} ++ ++/** ++ * ice_ptp_auxbus_create_id_table - Create auxiliary device ID table ++ * @pf: Board private structure ++ * @name: auxiliary bus driver name ++ */ ++static struct auxiliary_device_id * ++ice_ptp_auxbus_create_id_table(struct ice_pf *pf, const char *name) ++{ ++ struct auxiliary_device_id *ids; ++ ++ /* Second id left empty to terminate the array */ ++ ids = devm_kcalloc(ice_pf_to_dev(pf), 2, ++ sizeof(struct auxiliary_device_id), GFP_KERNEL); ++ if (!ids) ++ return NULL; ++ ++ snprintf(ids[0].name, sizeof(ids[0].name), "ice.%s", name); ++ ++ return ids; ++} ++ ++/** ++ * ice_ptp_register_auxbus_driver - Register PTP auxiliary bus driver ++ * @pf: Board private structure ++ */ ++static int ice_ptp_register_auxbus_driver(struct ice_pf *pf) ++{ ++ struct auxiliary_driver *aux_driver; ++ struct ice_ptp *ptp; ++ struct device *dev; ++ char *name; ++ int err; ++ ++ ptp = &pf->ptp; ++ dev = ice_pf_to_dev(pf); ++ aux_driver = &ptp->ports_owner.aux_driver; ++ INIT_LIST_HEAD(&ptp->ports_owner.ports); ++ mutex_init(&ptp->ports_owner.lock); ++ name = devm_kasprintf(dev, GFP_KERNEL, "ptp_aux_dev_%u_%u_clk%u", ++ pf->pdev->bus->number, PCI_SLOT(pf->pdev->devfn), ++ ice_get_ptp_src_clock_index(&pf->hw)); ++ ++ aux_driver->name = name; ++ aux_driver->shutdown = ice_ptp_auxbus_shutdown; ++ aux_driver->suspend = ice_ptp_auxbus_suspend; ++ aux_driver->remove = ice_ptp_auxbus_remove; ++ aux_driver->resume = ice_ptp_auxbus_resume; ++ aux_driver->probe = ice_ptp_auxbus_probe; ++ aux_driver->id_table = ice_ptp_auxbus_create_id_table(pf, name); ++ if (!aux_driver->id_table) ++ return -ENOMEM; ++ ++ err = auxiliary_driver_register(aux_driver); ++ if (err) { ++ devm_kfree(dev, aux_driver->id_table); ++ dev_err(dev, "Failed registering aux_driver, name <%s>\n", ++ name); ++ } ++ ++ return err; ++} ++ ++/** ++ * ice_ptp_unregister_auxbus_driver - Unregister PTP auxiliary bus driver ++ * @pf: Board private structure ++ */ ++static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf) ++{ ++ struct auxiliary_driver *aux_driver = &pf->ptp.ports_owner.aux_driver; ++ ++ auxiliary_driver_unregister(aux_driver); ++ devm_kfree(ice_pf_to_dev(pf), aux_driver->id_table); ++ ++ mutex_destroy(&pf->ptp.ports_owner.lock); ++} ++ + /** + * ice_ptp_prepare_for_reset - Prepare PTP for reset + * @pf: Board private structure +@@ -2635,7 +2872,15 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + /* Release the global hardware lock */ + ice_ptp_unlock(hw); + +- if (!ice_is_e810(hw)) { ++ if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) { ++ /* The clock owner for this device type handles the timestamp ++ * interrupt for all ports. ++ */ ++ ice_ptp_configure_tx_tstamp(pf, true); ++ ++ /* React on all quads interrupts for E82x */ ++ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f); ++ + /* Enable quad interrupts */ + err = ice_ptp_tx_ena_intr(pf, true, itr); + if (err) +@@ -2650,8 +2895,16 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + /* Store the PTP clock index for other PFs */ + ice_set_ptp_clock_index(pf); + +- return 0; ++ err = ice_ptp_register_auxbus_driver(pf); ++ if (err) { ++ dev_err(ice_pf_to_dev(pf), "Failed to register PTP auxbus driver"); ++ goto err_aux; ++ } + ++ return 0; ++err_aux: ++ ice_clear_ptp_clock_index(pf); ++ ptp_clock_unregister(pf->ptp.clock); + err_clk: + pf->ptp.clock = NULL; + err_exit: +@@ -2701,6 +2954,13 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + case ICE_PHY_E810: + return ice_ptp_init_tx_e810(pf, &ptp_port->tx); + case ICE_PHY_E822: ++ /* Non-owner PFs don't react to any interrupts on E82x, ++ * neither on own quad nor on others ++ */ ++ if (!ice_ptp_pf_handles_tx_interrupt(pf)) { ++ ice_ptp_configure_tx_tstamp(pf, false); ++ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0); ++ } + kthread_init_delayed_work(&ptp_port->ov_work, + ice_ptp_wait_for_offsets); + +@@ -2711,6 +2971,101 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + } + } + ++/** ++ * ice_ptp_release_auxbus_device ++ * @dev: device that utilizes the auxbus ++ */ ++static void ice_ptp_release_auxbus_device(struct device *dev) ++{ ++ /* Doing nothing here, but handle to auxbux device must be satisfied */ ++} ++ ++/** ++ * ice_ptp_create_auxbus_device - Create PTP auxiliary bus device ++ * @pf: Board private structure ++ */ ++static int ice_ptp_create_auxbus_device(struct ice_pf *pf) ++{ ++ struct auxiliary_device *aux_dev; ++ struct ice_ptp *ptp; ++ struct device *dev; ++ char *name; ++ int err; ++ u32 id; ++ ++ ptp = &pf->ptp; ++ id = ptp->port.port_num; ++ dev = ice_pf_to_dev(pf); ++ ++ aux_dev = &ptp->port.aux_dev; ++ ++ name = devm_kasprintf(dev, GFP_KERNEL, "ptp_aux_dev_%u_%u_clk%u", ++ pf->pdev->bus->number, PCI_SLOT(pf->pdev->devfn), ++ ice_get_ptp_src_clock_index(&pf->hw)); ++ ++ aux_dev->name = name; ++ aux_dev->id = id; ++ aux_dev->dev.release = ice_ptp_release_auxbus_device; ++ aux_dev->dev.parent = dev; ++ ++ err = auxiliary_device_init(aux_dev); ++ if (err) ++ goto aux_err; ++ ++ err = auxiliary_device_add(aux_dev); ++ if (err) { ++ auxiliary_device_uninit(aux_dev); ++ goto aux_err; ++ } ++ ++ return 0; ++aux_err: ++ dev_err(dev, "Failed to create PTP auxiliary bus device <%s>\n", name); ++ devm_kfree(dev, name); ++ return err; ++} ++ ++/** ++ * ice_ptp_remove_auxbus_device - Remove PTP auxiliary bus device ++ * @pf: Board private structure ++ */ ++static void ice_ptp_remove_auxbus_device(struct ice_pf *pf) ++{ ++ struct auxiliary_device *aux_dev = &pf->ptp.port.aux_dev; ++ ++ auxiliary_device_delete(aux_dev); ++ auxiliary_device_uninit(aux_dev); ++ ++ memset(aux_dev, 0, sizeof(*aux_dev)); ++} ++ ++/** ++ * ice_ptp_init_tx_interrupt_mode - Initialize device Tx interrupt mode ++ * @pf: Board private structure ++ * ++ * Initialize the Tx timestamp interrupt mode for this device. For most device ++ * types, each PF processes the interrupt and manages its own timestamps. For ++ * E822-based devices, only the clock owner processes the timestamps. Other ++ * PFs disable the interrupt and do not process their own timestamps. ++ */ ++static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf) ++{ ++ switch (pf->hw.phy_model) { ++ case ICE_PHY_E822: ++ /* E822 based PHY has the clock owner process the interrupt ++ * for all ports. ++ */ ++ if (ice_pf_src_tmr_owned(pf)) ++ pf->ptp.tx_interrupt_mode = ICE_PTP_TX_INTERRUPT_ALL; ++ else ++ pf->ptp.tx_interrupt_mode = ICE_PTP_TX_INTERRUPT_NONE; ++ break; ++ default: ++ /* other PHY types handle their own Tx interrupt */ ++ pf->ptp.tx_interrupt_mode = ICE_PTP_TX_INTERRUPT_SELF; ++ } ++} ++ + /** + * ice_ptp_init - Initialize PTP hardware clock support + * @pf: Board private structure +@@ -2731,6 +3086,8 @@ void ice_ptp_init(struct ice_pf *pf) + + ice_ptp_init_phy_model(hw); + ++ ice_ptp_init_tx_interrupt_mode(pf); ++ + /* If this function owns the clock hardware, it must allocate and + * configure the PTP clock device to represent it. + */ +@@ -2753,6 +3110,10 @@ void ice_ptp_init(struct ice_pf *pf) + if (err) + goto err; + ++ err = ice_ptp_create_auxbus_device(pf); ++ if (err) ++ goto err; ++ + dev_info(ice_pf_to_dev(pf), "PTP init successful\n"); + return; + +@@ -2781,6 +3142,8 @@ void ice_ptp_release(struct ice_pf *pf) + /* Disable timestamping for both Tx and Rx */ + ice_ptp_cfg_timestamp(pf, false); + ++ ice_ptp_remove_auxbus_device(pf); ++ + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); + + clear_bit(ICE_FLAG_PTP, pf->flags); +@@ -2804,5 +3167,7 @@ void ice_ptp_release(struct ice_pf *pf) + ptp_clock_unregister(pf->ptp.clock); + pf->ptp.clock = NULL; + ++ ice_ptp_unregister_auxbus_driver(pf); ++ + dev_info(ice_pf_to_dev(pf), "Removed PTP clock\n"); + } +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 995a57019ba7..d94c22329df0 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -157,7 +157,9 @@ struct ice_ptp_tx { + * ready for PTP functionality. It is used to track the port initialization + * and determine when the port's PHY offset is valid. + * ++ * @list_member: list member structure of auxiliary device + * @tx: Tx timestamp tracking for this port ++ * @aux_dev: auxiliary device associated with this port + * @ov_work: delayed work task for tracking when PHY offset is valid + * @ps_lock: mutex used to protect the overall PTP PHY start procedure + * @link_up: indicates whether the link is up +@@ -165,7 +167,9 @@ struct ice_ptp_tx { + * @port_num: the port number this structure represents + */ + struct ice_ptp_port { ++ struct list_head list_member; + struct ice_ptp_tx tx; ++ struct auxiliary_device aux_dev; + struct kthread_delayed_work ov_work; + struct mutex ps_lock; /* protects overall PTP PHY start procedure */ + bool link_up; +@@ -173,11 +177,35 @@ struct ice_ptp_port { + u8 port_num; + }; + ++enum ice_ptp_tx_interrupt { ++ ICE_PTP_TX_INTERRUPT_NONE = 0, ++ ICE_PTP_TX_INTERRUPT_SELF, ++ ICE_PTP_TX_INTERRUPT_ALL, ++}; ++ ++/** ++ * struct ice_ptp_port_owner - data used to handle the PTP clock owner info ++ * ++ * This structure contains data necessary for the PTP clock owner to correctly ++ * handle the timestamping feature for all attached ports. ++ * ++ * @aux_driver: the structure carring the auxiliary driver information ++ * @ports: list of porst handled by this port owner ++ * @lock: protect access to ports list ++ */ ++struct ice_ptp_port_owner { ++ struct auxiliary_driver aux_driver; ++ struct list_head ports; ++ struct mutex lock; ++}; ++ + #define GLTSYN_TGT_H_IDX_MAX 4 + + /** + * struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK ++ * @tx_interrupt_mode: the TX interrupt mode for the PTP clock + * @port: data for the PHY port initialization procedure ++ * @ports_owner: data for the auxiliary driver owner + * @work: delayed work function for periodic tasks + * @cached_phc_time: a cached copy of the PHC time for timestamp extension + * @cached_phc_jiffies: jiffies when cached_phc_time was last updated +@@ -197,7 +225,9 @@ struct ice_ptp_port { + * @late_cached_phc_updates: number of times cached PHC update is late + */ + struct ice_ptp { ++ enum ice_ptp_tx_interrupt tx_interrupt_mode; + struct ice_ptp_port port; ++ struct ice_ptp_port_owner ports_owner; + struct kthread_delayed_work work; + u64 cached_phc_time; + unsigned long cached_phc_jiffies; +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0002-ice-introduce-ice_pf_src_tmr_owned.patch b/kernel-rt/debian/patches/ice-VDF/0002-ice-introduce-ice_pf_src_tmr_owned.patch new file mode 100644 index 00000000..3078a79b --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0002-ice-introduce-ice_pf_src_tmr_owned.patch @@ -0,0 +1,95 @@ +From f6af978ef435067b4c9f5ff5e159f8b65d969268 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Fri, 8 Sep 2023 14:37:14 -0700 +Subject: [PATCH 02/36] ice: introduce ice_pf_src_tmr_owned + +Add ice_pf_src_tmr_owned() macro to check the function capability bit +indicating if the current function owns the PTP hardware clock. This is +slightly shorter than the more verbose access via +hw.func_caps.ts_func_info.src_tmr_owned. Use this where possible rather +than open coding its equivalent. + +Signed-off-by: Jacob Keller +Signed-off-by: Tony Nguyen +(cherry picked from commit 42d40bb21e332151da6fb689bf7d4af8195866ed) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 2 ++ + drivers/net/ethernet/intel/ice/ice_lib.c | 2 +- + drivers/net/ethernet/intel/ice/ice_main.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 6 +++--- + 4 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 0a3d76d184ba..54a98c4032b7 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -197,6 +197,8 @@ extern const char ice_drv_ver[]; + + #define ice_pf_to_dev(pf) (&((pf)->pdev->dev)) + ++#define ice_pf_src_tmr_owned(pf) ((pf)->hw.func_caps.ts_func_info.src_tmr_owned) ++ + enum ice_feature { + ICE_F_DSCP, + ICE_F_PHY_RCLK, +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index 632091487413..106ef843f4b5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -4010,7 +4010,7 @@ void ice_init_feature_support(struct ice_pf *pf) + if (ice_is_phy_rclk_in_netlist(&pf->hw)) + ice_set_feature_support(pf, ICE_F_PHY_RCLK); + /* If we don't own the timer - don't enable other caps */ +- if (!pf->hw.func_caps.ts_func_info.src_tmr_owned) ++ if (!ice_pf_src_tmr_owned(pf)) + break; + if (ice_is_cgu_in_netlist(&pf->hw)) + ice_set_feature_support(pf, ICE_F_CGU); +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 39cb6ee52abe..e957529b3fd6 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3200,7 +3200,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + ena_mask &= ~PFINT_OICR_TSYN_EVNT_M; + +- if (hw->func_caps.ts_func_info.src_tmr_owned) { ++ if (ice_pf_src_tmr_owned(pf)) { + /* Save EVENTs from GLTSYN register */ + pf->ptp.ext_ts_irq |= gltsyn_stat & + (GLTSYN_STAT_EVENT0_M | +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index e3012608c9dd..b1951357ba9f 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -448,7 +448,7 @@ static void ice_clear_ptp_clock_index(struct ice_pf *pf) + int err; + + /* Do not clear the index if we don't own the timer */ +- if (!hw->func_caps.ts_func_info.src_tmr_owned) ++ if (!ice_pf_src_tmr_owned(pf)) + return; + + tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc; +@@ -2538,7 +2538,7 @@ void ice_ptp_reset(struct ice_pf *pf) + if (test_bit(ICE_PFR_REQ, pf->state)) + goto pfr; + +- if (!hw->func_caps.ts_func_info.src_tmr_owned) ++ if (!ice_pf_src_tmr_owned(pf)) + goto reset_ts; + + err = ice_ptp_init_phc(hw); +@@ -3091,7 +3091,7 @@ void ice_ptp_init(struct ice_pf *pf) + /* If this function owns the clock hardware, it must allocate and + * configure the PTP clock device to represent it. + */ +- if (hw->func_caps.ts_func_info.src_tmr_owned) { ++ if (ice_pf_src_tmr_owned(pf)) { + err = ice_ptp_init_owner(pf); + if (err) + goto err; +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0003-ice-Re-enable-timestamping-correctly-after-reset.patch b/kernel-rt/debian/patches/ice-VDF/0003-ice-Re-enable-timestamping-correctly-after-reset.patch new file mode 100644 index 00000000..206d655f --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0003-ice-Re-enable-timestamping-correctly-after-reset.patch @@ -0,0 +1,93 @@ +From 3c155fbf8e2a0546302a01cc06e8ece18468148e Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Fri, 1 Dec 2023 10:08:42 -0800 +Subject: [PATCH 03/36] ice: Re-enable timestamping correctly after reset + +During reset, TX_TSYN interrupt should be processed as it may process +timestamps in brief moments before and after reset. +Timestamping should be enabled on VSIs at the end of reset procedure. +On ice_get_phy_tx_tstamp_ready error, interrupt should not be rearmed +because error only happens on resets. + +Reviewed-by: Jesse Brandeburg +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 1cc5b6eaad92d69fe4d84bbee5c12ee297d56296) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_main.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 19 ++++++++++--------- + 2 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index e957529b3fd6..d2f3b4374d14 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3190,7 +3190,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + if (oicr & PFINT_OICR_TSYN_TX_M) { + ena_mask &= ~PFINT_OICR_TSYN_TX_M; +- if (!hw->reset_ongoing && ice_ptp_pf_handles_tx_interrupt(pf)) ++ if (ice_ptp_pf_handles_tx_interrupt(pf)) + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); + } + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index b1951357ba9f..92459589f6ce 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -809,7 +809,9 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) + + /* Read the Tx ready status first */ + err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready); +- if (err || tstamp_ready) ++ if (err) ++ break; ++ else if (tstamp_ready) + return ICE_TX_TSTAMP_WORK_PENDING; + } + +@@ -2535,12 +2537,10 @@ void ice_ptp_reset(struct ice_pf *pf) + int err, itr = 1; + u64 time_diff; + +- if (test_bit(ICE_PFR_REQ, pf->state)) ++ if (test_bit(ICE_PFR_REQ, pf->state) || ++ !ice_pf_src_tmr_owned(pf)) + goto pfr; + +- if (!ice_pf_src_tmr_owned(pf)) +- goto reset_ts; +- + err = ice_ptp_init_phc(hw); + if (err) + goto err; +@@ -2584,10 +2584,6 @@ void ice_ptp_reset(struct ice_pf *pf) + goto err; + } + +-reset_ts: +- /* Restart the PHY timestamping block */ +- ice_ptp_reset_phy_timestamping(pf); +- + pfr: + /* Init Tx structures */ + if (ice_is_e810(&pf->hw)) { +@@ -2603,6 +2599,11 @@ void ice_ptp_reset(struct ice_pf *pf) + + set_bit(ICE_FLAG_PTP, pf->flags); + ++ /* Restart the PHY timestamping block */ ++ if (!test_bit(ICE_PFR_REQ, pf->state) && ++ ice_pf_src_tmr_owned(pf)) ++ ice_ptp_restart_all_phy(pf); ++ + /* Start periodic work going */ + kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0); + +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0004-ice-periodically-kick-Tx-timestamp-interrupt.patch b/kernel-rt/debian/patches/ice-VDF/0004-ice-periodically-kick-Tx-timestamp-interrupt.patch new file mode 100644 index 00000000..29d0c524 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0004-ice-periodically-kick-Tx-timestamp-interrupt.patch @@ -0,0 +1,121 @@ +From 214f06259ade960e3790b62f96bc1b75e5b76e79 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Fri, 1 Dec 2023 10:08:43 -0800 +Subject: [PATCH 04/36] ice: periodically kick Tx timestamp interrupt + +The E822 hardware for Tx timestamping keeps track of how many +outstanding timestamps are still in the PHY memory block. It will not +generate a new interrupt to the MAC until all of the timestamps in the +region have been read. + +If somehow all the available data is not read, but the driver has exited +its interrupt routine already, the PHY will not generate a new interrupt +even if new timestamp data is captured. Because no interrupt is +generated, the driver never processes the timestamp data. This state +results in a permanent failure for all future Tx timestamps. + +It is not clear how the driver and hardware could enter this state. +However, if it does, there is currently no recovery mechanism. + +Add a recovery mechanism via the periodic PTP work thread which invokes +ice_ptp_periodic_work(). Introduce a new check, +ice_ptp_maybe_trigger_tx_interrupt() which checks the PHY timestamp +ready bitmask. If any bits are set, trigger a software interrupt by +writing to PFINT_OICR. + +Once triggered, the main timestamp processing thread will read through +the PHY data and clear the outstanding timestamp data. Once cleared, new +data should trigger interrupts as expected. + +This should allow recovery from such a state rather than leaving the +device in a state where we cannot process Tx timestamps. + +It is possible that this function checks for timestamp data +simultaneously with the interrupt, and it might trigger additional +unnecessary interrupts. This will cause a small amount of additional +processing. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Andrii Staikov +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 712e876371f8350c446a33577cf4a0aedcd4742a) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 50 ++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 92459589f6ce..0d6c7215e0c1 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -2509,6 +2509,54 @@ enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf) + } + } + ++/** ++ * ice_ptp_maybe_trigger_tx_interrupt - Trigger Tx timstamp interrupt ++ * @pf: Board private structure ++ * ++ * The device PHY issues Tx timestamp interrupts to the driver for processing ++ * timestamp data from the PHY. It will not interrupt again until all ++ * current timestamp data is read. In rare circumstances, it is possible that ++ * the driver fails to read all outstanding data. ++ * ++ * To avoid getting permanently stuck, periodically check if the PHY has ++ * outstanding timestamp data. If so, trigger an interrupt from software to ++ * process this data. ++ */ ++static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf) ++{ ++ struct device *dev = ice_pf_to_dev(pf); ++ struct ice_hw *hw = &pf->hw; ++ bool trigger_oicr = false; ++ unsigned int i; ++ ++ if (ice_is_e810(hw)) ++ return; ++ ++ if (!ice_pf_src_tmr_owned(pf)) ++ return; ++ ++ for (i = 0; i < ICE_MAX_QUAD; i++) { ++ u64 tstamp_ready; ++ int err; ++ ++ err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready); ++ if (!err && tstamp_ready) { ++ trigger_oicr = true; ++ break; ++ } ++ } ++ ++ if (trigger_oicr) { ++ /* Trigger a software interrupt, to ensure this data ++ * gets processed. ++ */ ++ dev_dbg(dev, "PTP periodic task detected waiting timestamps. Triggering Tx timestamp interrupt now.\n"); ++ ++ wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); ++ ice_flush(hw); ++ } ++} ++ + static void ice_ptp_periodic_work(struct kthread_work *work) + { + struct ice_ptp *ptp = container_of(work, struct ice_ptp, work.work); +@@ -2520,6 +2568,8 @@ static void ice_ptp_periodic_work(struct kthread_work *work) + + err = ice_ptp_update_cached_phctime(pf); + ++ ice_ptp_maybe_trigger_tx_interrupt(pf); ++ + /* Run twice a second or reschedule if phc update failed */ + kthread_queue_delayed_work(ptp->kworker, &ptp->work, + msecs_to_jiffies(err ? 10 : 500)); +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0005-ice-PTP-Rename-macros-used-for-PHY-QUAD-port-definit.patch b/kernel-rt/debian/patches/ice-VDF/0005-ice-PTP-Rename-macros-used-for-PHY-QUAD-port-definit.patch new file mode 100644 index 00000000..a31b8b17 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0005-ice-PTP-Rename-macros-used-for-PHY-QUAD-port-definit.patch @@ -0,0 +1,81 @@ +From c25fc364d599195403ed9ba51ef8fa6ed3b642ff Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 26 Jul 2023 11:27:44 -0700 +Subject: [PATCH 05/36] ice: PTP: Rename macros used for PHY/QUAD port + definitions + +The ice_fill_phy_msg_e822 function uses several macros to specify the +correct address when sending a sideband message to the PHY block in +hardware. + +The names of these macros are fairly generic and confusing. Future +development is going to extend the driver to support new hardware families +which have different relationships between PHY and QUAD. Rename the macros +for clarity and to indicate that they are E822 specific. This also matches +closer to the hardware specification in the data sheet. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 64fd7de2469dd52a7f1517ce95ae22fcb391a8a1) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 8 ++++---- + drivers/net/ethernet/intel/ice/ice_type.h | 14 +++++++------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index a299af39a7c4..03c4aa995e8d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -294,9 +294,9 @@ ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset) + { + int phy_port, phy, quadtype; + +- phy_port = port % ICE_PORTS_PER_PHY; +- phy = port / ICE_PORTS_PER_PHY; +- quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_NUM_QUAD_TYPE; ++ phy_port = port % ICE_PORTS_PER_PHY_E822; ++ phy = port / ICE_PORTS_PER_PHY_E822; ++ quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E822; + + if (quadtype == 0) { + msg->msg_addr_low = P_Q0_L(P_0_BASE + offset, phy_port); +@@ -628,7 +628,7 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + + msg->dest_dev = rmn_0; + +- if ((quad % ICE_NUM_QUAD_TYPE) == 0) ++ if ((quad % ICE_QUADS_PER_PHY_E822) == 0) + addr = Q_0_BASE + offset; + else + addr = Q_1_BASE + offset; +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index 4cd131546aa9..bb5d8b681bc2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -909,13 +909,13 @@ struct ice_hw { + /* INTRL granularity in 1 us */ + u8 intrl_gran; + +-#define ICE_PHY_PER_NAC 1 +-#define ICE_MAX_QUAD 2 +-#define ICE_NUM_QUAD_TYPE 2 +-#define ICE_PORTS_PER_QUAD 4 +-#define ICE_PHY_0_LAST_QUAD 1 +-#define ICE_PORTS_PER_PHY 8 +-#define ICE_NUM_EXTERNAL_PORTS ICE_PORTS_PER_PHY ++#define ICE_PHY_PER_NAC_E822 1 ++#define ICE_MAX_QUAD 2 ++#define ICE_QUADS_PER_PHY_E822 2 ++#define ICE_PORTS_PER_PHY_E822 8 ++#define ICE_PORTS_PER_QUAD 4 ++#define ICE_PORTS_PER_PHY_E810 4 ++#define ICE_NUM_EXTERNAL_PORTS (ICE_MAX_QUAD * ICE_PORTS_PER_QUAD) + + /* Active package version (currently active) */ + struct ice_pkg_ver active_pkg_ver; +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0006-ice-PTP-move-quad-value-check-inside-ice_fill_phy_ms.patch b/kernel-rt/debian/patches/ice-VDF/0006-ice-PTP-move-quad-value-check-inside-ice_fill_phy_ms.patch new file mode 100644 index 00000000..0faf7dd3 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0006-ice-PTP-move-quad-value-check-inside-ice_fill_phy_ms.patch @@ -0,0 +1,80 @@ +From 13f48f4c94ad4d317e7c7ccaa188a11850a8aa32 Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 26 Jul 2023 11:27:45 -0700 +Subject: [PATCH 06/36] ice: PTP: move quad value check inside + ice_fill_phy_msg_e822 + +The callers of ice_fill_phy_msg_e822 check for whether the quad number is +within the expected range. Move this check inside the ice_fill_phy_msg_e822 +function instead of duplicating it twice. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit dd84744cf5ea967c8d53aae6b6a45703dbc5c5c4) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index 03c4aa995e8d..e024b88ce32b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -621,11 +621,14 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + * Fill a message buffer for accessing a register in a quad shared between + * multiple PHYs. + */ +-static void ++static int + ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + { + u32 addr; + ++ if (quad >= ICE_MAX_QUAD) ++ return -EINVAL; ++ + msg->dest_dev = rmn_0; + + if ((quad % ICE_QUADS_PER_PHY_E822) == 0) +@@ -635,6 +638,8 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + + msg->msg_addr_low = lower_16_bits(addr); + msg->msg_addr_high = upper_16_bits(addr); ++ ++ return 0; + } + + /** +@@ -653,10 +658,10 @@ ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- if (quad >= ICE_MAX_QUAD) +- return -EINVAL; ++ err = ice_fill_quad_msg_e822(&msg, quad, offset); ++ if (err) ++ return err; + +- ice_fill_quad_msg_e822(&msg, quad, offset); + msg.opcode = ice_sbq_msg_rd; + + err = ice_sbq_rw_reg(hw, &msg); +@@ -687,10 +692,10 @@ ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- if (quad >= ICE_MAX_QUAD) +- return -EINVAL; ++ err = ice_fill_quad_msg_e822(&msg, quad, offset); ++ if (err) ++ return err; + +- ice_fill_quad_msg_e822(&msg, quad, offset); + msg.opcode = ice_sbq_msg_wr; + msg.data = val; + +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0007-ice-remove-ptp_tx-ring-parameter-flag.patch b/kernel-rt/debian/patches/ice-VDF/0007-ice-remove-ptp_tx-ring-parameter-flag.patch new file mode 100644 index 00000000..a2e95af6 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0007-ice-remove-ptp_tx-ring-parameter-flag.patch @@ -0,0 +1,97 @@ +From 7dae9333af82f6c9e2db1940c3a10ae38dabea7b Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 21 Nov 2023 13:12:55 -0800 +Subject: [PATCH 07/36] ice: remove ptp_tx ring parameter flag + +Before performing a Tx timestamp in ice_stamp(), the driver checks a ptp_tx +ring variable to see if timestamping is enabled on that ring. This value is +set for all rings whenever userspace configures Tx timestamping. + +Ostensibly this was done to avoid wasting cycles checking other fields when +timestamping has not been enabled. However, for Tx timestamps we already +get an individual per-SKB flag indicating whether userspace wants to +request a timestamp on that packet. We do not gain much by also having +a separate flag to check for whether timestamping was enabled. + +In fact, the driver currently fails to restore the field after a PF reset. +Because of this, if a PF reset occurs, timestamps will be disabled. + +Since this flag doesn't add value in the hotpath, remove it and always +provide a timestamp if the SKB flag has been set. + +A following change will fix the reset path to properly restore user +timestamping configuration completely. + +This went unnoticed for some time because one of the most common +applications using Tx timestamps, ptp4l, will reconfigure the socket as +part of its fault recovery logic. + +Fixes: ea9b847cda64 ("ice: enable transmit timestamps for E810 devices") +Signed-off-by: Jacob Keller +Reviewed-by: Jesse Brandeburg +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 0ffb08b1a45bd6b7694e01da0e1d9e3e788418fb) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 14 -------------- + drivers/net/ethernet/intel/ice/ice_txrx.c | 3 --- + drivers/net/ethernet/intel/ice/ice_txrx.h | 1 - + 3 files changed, 18 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 0d6c7215e0c1..c03153bdb7c3 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -280,20 +280,6 @@ static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on) + */ + static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) + { +- struct ice_vsi *vsi; +- u16 i; +- +- vsi = ice_get_main_vsi(pf); +- if (!vsi) +- return; +- +- /* Set the timestamp enable flag for all the Tx rings */ +- ice_for_each_txq(vsi, i) { +- if (!vsi->tx_rings[i]) +- continue; +- vsi->tx_rings[i]->ptp_tx = on; +- } +- + if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) + ice_ptp_configure_tx_tstamp(pf, on); + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index 24c914015973..9170a3e8f088 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -2305,9 +2305,6 @@ ice_tstamp(struct ice_tx_ring *tx_ring, struct sk_buff *skb, + if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) + return; + +- if (!tx_ring->ptp_tx) +- return; +- + /* Tx timestamps cannot be sampled when doing TSO */ + if (first->tx_flags & ICE_TX_FLAGS_TSO) + return; +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h +index 407d4c320097..b28b9826bbcd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.h ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.h +@@ -381,7 +381,6 @@ struct ice_tx_ring { + #define ICE_TX_FLAGS_RING_VLAN_L2TAG2 BIT(2) + u8 flags; + u8 dcb_tc; /* Traffic class of ring */ +- u8 ptp_tx; + } ____cacheline_internodealigned_in_smp; + + static inline bool ice_ring_uses_build_skb(struct ice_rx_ring *ring) +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0008-ice-unify-logic-for-programming-PFINT_TSYN_MSK.patch b/kernel-rt/debian/patches/ice-VDF/0008-ice-unify-logic-for-programming-PFINT_TSYN_MSK.patch new file mode 100644 index 00000000..9b7c9ca9 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0008-ice-unify-logic-for-programming-PFINT_TSYN_MSK.patch @@ -0,0 +1,160 @@ +From 99007ca6255e2c35256bd97fa141705d301eb934 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 21 Nov 2023 13:12:56 -0800 +Subject: [PATCH 08/36] ice: unify logic for programming PFINT_TSYN_MSK + +Commit d938a8cca88a ("ice: Auxbus devices & driver for E822 TS") modified +how Tx timestamps are handled for E822 devices. On these devices, only the +clock owner handles reading the Tx timestamp data from firmware. To do +this, the PFINT_TSYN_MSK register is modified from the default value to one +which enables reacting to a Tx timestamp on all PHY ports. + +The driver currently programs PFINT_TSYN_MSK in different places depending +on whether the port is the clock owner or not. For the clock owner, the +PFINT_TSYN_MSK value is programmed during ice_ptp_init_owner just before +calling ice_ptp_tx_ena_intr to program the PHY ports. + +For the non-clock owner ports, the PFINT_TSYN_MSK is programmed during +ice_ptp_init_port. + +If a large enough device reset occurs, the PFINT_TSYN_MSK register will be +reset to the default value in which only the PHY associated directly with +the PF will cause the Tx timestamp interrupt to trigger. + +The driver lacks logic to reprogram the PFINT_TSYN_MSK register after a +device reset. For the E822 device, this results in the PF no longer +responding to interrupts for other ports. This results in failure to +deliver Tx timestamps to user space applications. + +Rename ice_ptp_configure_tx_tstamp to ice_ptp_cfg_tx_interrupt, and unify +the logic for programming PFINT_TSYN_MSK and PFINT_OICR_ENA into one place. +This function will program both registers according to the combination of +user configuration and device requirements. + +This ensures that PFINT_TSYN_MSK is always restored when we configure the +Tx timestamp interrupt. + +Fixes: d938a8cca88a ("ice: Auxbus devices & driver for E822 TS") +Signed-off-by: Jacob Keller +Reviewed-by: Jesse Brandeburg +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 7d606a1e2d0575b6c3a2600f43f90d1e409f9661) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 60 ++++++++++++++---------- + 1 file changed, 34 insertions(+), 26 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index c03153bdb7c3..b0bba866e8a2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -256,21 +256,42 @@ ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin, + } + + /** +- * ice_ptp_configure_tx_tstamp - Enable or disable Tx timestamp interrupt +- * @pf: The PF pointer to search in +- * @on: bool value for whether timestamp interrupt is enabled or disabled ++ * ice_ptp_cfg_tx_interrupt - Configure Tx timestamp interrupt for the device ++ * @pf: Board private structure ++ * ++ * Program the device to respond appropriately to the Tx timestamp interrupt ++ * cause. + */ +-static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on) ++static void ice_ptp_cfg_tx_interrupt(struct ice_pf *pf) + { ++ struct ice_hw *hw = &pf->hw; ++ bool enable; + u32 val; + ++ switch (pf->ptp.tx_interrupt_mode) { ++ case ICE_PTP_TX_INTERRUPT_ALL: ++ /* React to interrupts across all quads. */ ++ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f); ++ enable = true; ++ break; ++ case ICE_PTP_TX_INTERRUPT_NONE: ++ /* Do not react to interrupts on any quad. */ ++ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0); ++ enable = false; ++ break; ++ case ICE_PTP_TX_INTERRUPT_SELF: ++ default: ++ enable = pf->ptp.tstamp_config.tx_type == HWTSTAMP_TX_ON; ++ break; ++ } ++ + /* Configure the Tx timestamp interrupt */ +- val = rd32(&pf->hw, PFINT_OICR_ENA); +- if (on) ++ val = rd32(hw, PFINT_OICR_ENA); ++ if (enable) + val |= PFINT_OICR_TSYN_TX_M; + else + val &= ~PFINT_OICR_TSYN_TX_M; +- wr32(&pf->hw, PFINT_OICR_ENA, val); ++ wr32(hw, PFINT_OICR_ENA, val); + } + + /** +@@ -280,10 +301,9 @@ static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on) + */ + static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) + { +- if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) +- ice_ptp_configure_tx_tstamp(pf, on); +- + pf->ptp.tstamp_config.tx_type = on ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; ++ ++ ice_ptp_cfg_tx_interrupt(pf); + } + + /** +@@ -2909,15 +2929,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + /* Release the global hardware lock */ + ice_ptp_unlock(hw); + +- if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) { +- /* The clock owner for this device type handles the timestamp +- * interrupt for all ports. +- */ +- ice_ptp_configure_tx_tstamp(pf, true); +- +- /* React on all quads interrupts for E82x */ +- wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f); +- ++ if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ + err = ice_ptp_tx_ena_intr(pf, true, itr); + if (err) +@@ -2991,13 +3003,6 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + case ICE_PHY_E810: + return ice_ptp_init_tx_e810(pf, &ptp_port->tx); + case ICE_PHY_E822: +- /* Non-owner PFs don't react to any interrupts on E82x, +- * neither on own quad nor on others +- */ +- if (!ice_ptp_pf_handles_tx_interrupt(pf)) { +- ice_ptp_configure_tx_tstamp(pf, false); +- wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0); +- } + kthread_init_delayed_work(&ptp_port->ov_work, + ice_ptp_wait_for_offsets); + +@@ -3142,6 +3147,9 @@ void ice_ptp_init(struct ice_pf *pf) + /* Start the PHY timestamping block */ + ice_ptp_reset_phy_timestamping(pf); + ++ /* Configure initial Tx interrupt settings */ ++ ice_ptp_cfg_tx_interrupt(pf); ++ + set_bit(ICE_FLAG_PTP, pf->flags); + err = ice_ptp_init_work(pf, ptp); + if (err) +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0009-ice-PTP-Clean-up-timestamp-registers-correctly.patch b/kernel-rt/debian/patches/ice-VDF/0009-ice-PTP-Clean-up-timestamp-registers-correctly.patch new file mode 100644 index 00000000..76770529 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0009-ice-PTP-Clean-up-timestamp-registers-correctly.patch @@ -0,0 +1,147 @@ +From e5a65377977e338a8f7baf92892481acf1c62403 Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 26 Jul 2023 11:27:43 -0700 +Subject: [PATCH 09/36] ice: PTP: Clean up timestamp registers correctly + +E822 PHY TS registers should not be written and the only way to clean up +them is to reset QUAD memory. + +To ensure that the status bit for the timestamp index is cleared, ensure +that ice_clear_phy_tstamp implementations first read the timestamp out. +Implementations which can write the register continue to do so. + +Add a note to indicate this function should only be called on timestamps +which have their valid bit set. Update the dynamic debug messages to +reflect the actual action taken. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit be65a1a33bdee3912daac50aa6c5270ec9c37010) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 70 +++++++++++++-------- + 1 file changed, 45 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index e024b88ce32b..cd28430cfdda 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -759,29 +759,32 @@ ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + * @quad: the quad to read from + * @idx: the timestamp index to reset + * +- * Clear a timestamp, resetting its valid bit, from the PHY quad block that is +- * shared between the internal PHYs on the E822 devices. ++ * Read the timestamp out of the quad to clear its timestamp status bit from ++ * the PHY quad block that is shared between the internal PHYs of the E822 ++ * devices. ++ * ++ * Note that unlike E810, software cannot directly write to the quad memory ++ * bank registers. E822 relies on the ice_get_phy_tx_tstamp_ready() function ++ * to determine which timestamps are valid. Reading a timestamp auto-clears ++ * the valid bit. ++ * ++ * To directly clear the contents of the timestamp block entirely, discarding ++ * all timestamp data at once, software should instead use ++ * ice_ptp_reset_ts_memory_quad_e822(). ++ * ++ * This function should only be called on an idx whose bit is set according to ++ * ice_get_phy_tx_tstamp_ready(). + */ + static int + ice_clear_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx) + { +- u16 lo_addr, hi_addr; ++ u64 unused_tstamp; + int err; + +- lo_addr = (u16)TS_L(Q_REG_TX_MEMORY_BANK_START, idx); +- hi_addr = (u16)TS_H(Q_REG_TX_MEMORY_BANK_START, idx); +- +- err = ice_write_quad_reg_e822(hw, quad, lo_addr, 0); +- if (err) { +- ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, err %d\n", +- err); +- return err; +- } +- +- err = ice_write_quad_reg_e822(hw, quad, hi_addr, 0); ++ err = ice_read_phy_tstamp_e822(hw, quad, idx, &unused_tstamp); + if (err) { +- ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register, err %d\n", +- err); ++ ice_debug(hw, ICE_DBG_PTP, "Failed to read the timestamp register for quad %u, idx %u, err %d\n", ++ quad, idx, err); + return err; + } + +@@ -2816,28 +2819,39 @@ ice_read_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp) + * @lport: the lport to read from + * @idx: the timestamp index to reset + * +- * Clear a timestamp, resetting its valid bit, from the timestamp block of the +- * external PHY on the E810 device. ++ * Read the timestamp and then forcibly overwrite its value to clear the valid ++ * bit from the timestamp block of the external PHY on the E810 device. ++ * ++ * This function should only be called on an idx whose bit is set according to ++ * ice_get_phy_tx_tstamp_ready(). + */ + static int ice_clear_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx) + { + u32 lo_addr, hi_addr; ++ u64 unused_tstamp; + int err; + ++ err = ice_read_phy_tstamp_e810(hw, lport, idx, &unused_tstamp); ++ if (err) { ++ ice_debug(hw, ICE_DBG_PTP, "Failed to read the timestamp register for lport %u, idx %u, err %d\n", ++ lport, idx, err); ++ return err; ++ } ++ + lo_addr = TS_EXT(LOW_TX_MEMORY_BANK_START, lport, idx); + hi_addr = TS_EXT(HIGH_TX_MEMORY_BANK_START, lport, idx); + + err = ice_write_phy_reg_e810(hw, lo_addr, 0); + if (err) { +- ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, err %d\n", +- err); ++ ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register for lport %u, idx %u, err %d\n", ++ lport, idx, err); + return err; + } + + err = ice_write_phy_reg_e810(hw, hi_addr, 0); + if (err) { +- ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register, err %d\n", +- err); ++ ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register for lport %u, idx %u, err %d\n", ++ lport, idx, err); + return err; + } + +@@ -3519,9 +3533,15 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp) + * @block: the block to read from + * @idx: the timestamp index to reset + * +- * Clear a timestamp, resetting its valid bit, from the timestamp block. For +- * E822 devices, the block is the quad to clear from. For E810 devices, the +- * block is the logical port to clear from. ++ * Clear a timestamp from the timestamp block, discarding its value without ++ * returning it. This resets the memory status bit for the timestamp index ++ * allowing it to be reused for another timestamp in the future. ++ * ++ * For E822 devices, the block number is the PHY quad to clear from. For E810 ++ * devices, the block number is the logical port to clear from. ++ * ++ * This function must only be called on a timestamp index whose valid bit is ++ * set according to ice_get_phy_tx_tstamp_ready(). + */ + int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx) + { +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0010-ice-Use-PTP-auxbus-for-all-PHYs-restart-in-E822.patch b/kernel-rt/debian/patches/ice-VDF/0010-ice-Use-PTP-auxbus-for-all-PHYs-restart-in-E822.patch new file mode 100644 index 00000000..2a88fb45 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0010-ice-Use-PTP-auxbus-for-all-PHYs-restart-in-E822.patch @@ -0,0 +1,65 @@ +From e2a74a0a7dd399b0ee2ddd4889c609dedb85bfb5 Mon Sep 17 00:00:00 2001 +From: Michal Michalik +Date: Thu, 27 Jul 2023 15:50:35 +0200 +Subject: [PATCH 10/36] ice: Use PTP auxbus for all PHYs restart in E822 + +The E822 (and other devices based on the same PHY) is having issue while +setting the PHC timer - the PHY timers are drifting from the PHC. After +such a set all PHYs need to be restarted and resynchronised - do it +using auxiliary bus. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Michal Michalik +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit af3c5c8748e6d286d4f2dd9800f9d27f29b8e2ef) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index b0bba866e8a2..42eb1418eb90 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1496,6 +1496,24 @@ static void ice_ptp_reset_phy_timestamping(struct ice_pf *pf) + ice_ptp_port_phy_restart(&pf->ptp.port); + } + ++/** ++ * ice_ptp_restart_all_phy - Restart all PHYs to recalibrate timestamping ++ * @pf: Board private structure ++ */ ++static void ice_ptp_restart_all_phy(struct ice_pf *pf) ++{ ++ struct list_head *entry; ++ ++ list_for_each(entry, &pf->ptp.ports_owner.ports) { ++ struct ice_ptp_port *port = list_entry(entry, ++ struct ice_ptp_port, ++ list_member); ++ ++ if (port->link_up) ++ ice_ptp_port_phy_restart(port); ++ } ++} ++ + /** + * ice_ptp_adjfine - Adjust clock increment rate + * @info: the driver's PTP info structure +@@ -1933,9 +1951,9 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts) + /* Reenable periodic outputs */ + ice_ptp_enable_all_clkout(pf); + +- /* Recalibrate and re-enable timestamp block */ +- if (pf->ptp.port.link_up) +- ice_ptp_port_phy_restart(&pf->ptp.port); ++ /* Recalibrate and re-enable timestamp blocks for E822/E823 */ ++ if (hw->phy_model == ICE_PHY_E822) ++ ice_ptp_restart_all_phy(pf); + exit: + if (err) { + dev_err(ice_pf_to_dev(pf), "PTP failed to set time %d\n", err); +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0011-ice-Rename-E822-to-E82X.patch b/kernel-rt/debian/patches/ice-VDF/0011-ice-Rename-E822-to-E82X.patch new file mode 100644 index 00000000..5f259989 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0011-ice-Rename-E822-to-E82X.patch @@ -0,0 +1,2177 @@ +From ed199ec1c5886cf9830921b9380cf91ee216f26f Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Fri, 1 Dec 2023 10:08:44 -0800 +Subject: [PATCH 11/36] ice: Rename E822 to E82X + +When code is applicable for both E822 and E823 devices, rename it from +E822 to E82X. +ICE_PHY_PER_NAC_E822 was unused, so just remove it. + +Signed-off-by: Karol Kolacinski +Reviewed-by: Przemek Kitszel +Reviewed-by: Simon Horman +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit a39dd252d552ab3212fea55330081ee64a9e5573) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 48 +- + drivers/net/ethernet/intel/ice/ice_ptp.h | 2 +- + .../net/ethernet/intel/ice/ice_ptp_consts.h | 12 +- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 444 +++++++++--------- + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 48 +- + drivers/net/ethernet/intel/ice/ice_type.h | 7 +- + 6 files changed, 280 insertions(+), 281 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 42eb1418eb90..2e6e1fc84d11 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -7,7 +7,7 @@ + + #define E810_OUT_PROP_DELAY_NS 1 + +-#define UNKNOWN_INCVAL_E822 0x100000000ULL ++#define UNKNOWN_INCVAL_E82X 0x100000000ULL + + static const struct ptp_pin_desc ice_pin_desc_e810t[] = { + /* name idx func chan */ +@@ -987,7 +987,7 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + } + + /** +- * ice_ptp_init_tx_e822 - Initialize tracking for Tx timestamps ++ * ice_ptp_init_tx_e82x - Initialize tracking for Tx timestamps + * @pf: Board private structure + * @tx: the Tx tracking structure to initialize + * @port: the port this structure tracks +@@ -998,11 +998,11 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + * registers into chunks based on the port number. + */ + static int +-ice_ptp_init_tx_e822(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port) ++ice_ptp_init_tx_e82x(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port) + { + tx->block = port / ICE_PORTS_PER_QUAD; +- tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E822; +- tx->len = INDEX_PER_PORT_E822; ++ tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E82X; ++ tx->len = INDEX_PER_PORT_E82X; + tx->verify_cached = 0; + + return ice_ptp_alloc_tx_tracker(tx); +@@ -1205,10 +1205,10 @@ static u64 ice_base_incval(struct ice_pf *pf) + + if (ice_is_e810(hw)) + incval = ICE_PTP_NOMINAL_INCVAL_E810; +- else if (ice_e822_time_ref(hw) < NUM_ICE_TIME_REF_FREQ) +- incval = ice_e822_nominal_incval(ice_e822_time_ref(hw)); ++ else if (ice_e82x_time_ref(hw) < NUM_ICE_TIME_REF_FREQ) ++ incval = ice_e82x_nominal_incval(ice_e82x_time_ref(hw)); + else +- incval = UNKNOWN_INCVAL_E822; ++ incval = UNKNOWN_INCVAL_E82X; + + dev_dbg(ice_pf_to_dev(pf), "PTP: using base increment value of 0x%016llx\n", + incval); +@@ -1237,10 +1237,10 @@ static int ice_ptp_check_tx_fifo(struct ice_ptp_port *port) + + /* need to read FIFO state */ + if (offs == 0 || offs == 1) +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_FIFO01_STATUS, ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_FIFO01_STATUS, + &val); + else +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_FIFO23_STATUS, ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_FIFO23_STATUS, + &val); + + if (err) { +@@ -1268,7 +1268,7 @@ static int ice_ptp_check_tx_fifo(struct ice_ptp_port *port) + dev_dbg(ice_pf_to_dev(pf), + "Port %d Tx FIFO still not empty; resetting quad %d\n", + port->port_num, quad); +- ice_ptp_reset_ts_memory_quad_e822(hw, quad); ++ ice_ptp_reset_ts_memory_quad_e82x(hw, quad); + port->tx_fifo_busy_cnt = FIFO_OK; + return 0; + } +@@ -1313,8 +1313,8 @@ static void ice_ptp_wait_for_offsets(struct kthread_work *work) + + tx_err = ice_ptp_check_tx_fifo(port); + if (!tx_err) +- tx_err = ice_phy_cfg_tx_offset_e822(hw, port->port_num); +- rx_err = ice_phy_cfg_rx_offset_e822(hw, port->port_num); ++ tx_err = ice_phy_cfg_tx_offset_e82x(hw, port->port_num); ++ rx_err = ice_phy_cfg_rx_offset_e82x(hw, port->port_num); + if (tx_err || rx_err) { + /* Tx and/or Rx offset not yet configured, try again later */ + kthread_queue_delayed_work(pf->ptp.kworker, +@@ -1343,7 +1343,7 @@ ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port) + + kthread_cancel_delayed_work_sync(&ptp_port->ov_work); + +- err = ice_stop_phy_timer_e822(hw, port, true); ++ err = ice_stop_phy_timer_e82x(hw, port, true); + if (err) + dev_err(ice_pf_to_dev(pf), "PTP failed to set PHY port %d down, err %d\n", + port, err); +@@ -1386,7 +1386,7 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port) + ptp_port->tx_fifo_busy_cnt = 0; + + /* Start the PHY timer in Vernier mode */ +- err = ice_start_phy_timer_e822(hw, port); ++ err = ice_start_phy_timer_e82x(hw, port); + if (err) + goto out_unlock; + +@@ -1435,7 +1435,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + case ICE_PHY_E810: + /* Do not reconfigure E810 PHY */ + return; +- case ICE_PHY_E822: ++ case ICE_PHY_E82X: + ice_ptp_port_phy_restart(ptp_port); + return; + default: +@@ -1461,7 +1461,7 @@ static int ice_ptp_tx_ena_intr(struct ice_pf *pf, bool ena, u32 threshold) + ice_ptp_reset_ts_memory(hw); + + for (quad = 0; quad < ICE_MAX_QUAD; quad++) { +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, + &val); + if (err) + break; +@@ -1475,7 +1475,7 @@ static int ice_ptp_tx_ena_intr(struct ice_pf *pf, bool ena, u32 threshold) + val &= ~Q_REG_TX_MEM_GBL_CFG_INTR_ENA_M; + } + +- err = ice_write_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, ++ err = ice_write_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, + val); + if (err) + break; +@@ -1713,7 +1713,7 @@ static int ice_ptp_cfg_clkout(struct ice_pf *pf, unsigned int chan, + if (ice_is_e810(hw)) + start_time -= E810_OUT_PROP_DELAY_NS; + else +- start_time -= ice_e822_pps_delay(ice_e822_time_ref(hw)); ++ start_time -= ice_e82x_pps_delay(ice_e82x_time_ref(hw)); + + /* 2. Write TARGET time */ + wr32(hw, GLTSYN_TGT_L(chan, tmr_idx), lower_32_bits(start_time)); +@@ -1952,7 +1952,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts) + ice_ptp_enable_all_clkout(pf); + + /* Recalibrate and re-enable timestamp blocks for E822/E823 */ +- if (hw->phy_model == ICE_PHY_E822) ++ if (hw->phy_model == ICE_PHY_E82X) + ice_ptp_restart_all_phy(pf); + exit: + if (err) { +@@ -2665,7 +2665,7 @@ void ice_ptp_reset(struct ice_pf *pf) + } else { + kthread_init_delayed_work(&ptp->port.ov_work, + ice_ptp_wait_for_offsets); +- err = ice_ptp_init_tx_e822(pf, &ptp->port.tx, ++ err = ice_ptp_init_tx_e82x(pf, &ptp->port.tx, + ptp->port.port_num); + } + if (err) +@@ -3020,11 +3020,11 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + switch (hw->phy_model) { + case ICE_PHY_E810: + return ice_ptp_init_tx_e810(pf, &ptp_port->tx); +- case ICE_PHY_E822: ++ case ICE_PHY_E82X: + kthread_init_delayed_work(&ptp_port->ov_work, + ice_ptp_wait_for_offsets); + +- return ice_ptp_init_tx_e822(pf, &ptp_port->tx, ++ return ice_ptp_init_tx_e82x(pf, &ptp_port->tx, + ptp_port->port_num); + default: + return -ENODEV; +@@ -3111,7 +3111,7 @@ static void ice_ptp_remove_auxbus_device(struct ice_pf *pf) + static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf) + { + switch (pf->hw.phy_model) { +- case ICE_PHY_E822: ++ case ICE_PHY_E82X: + /* E822 based PHY has the clock owner process the interrupt + * for all ports. + */ +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index d94c22329df0..a3ae008a3539 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -147,7 +147,7 @@ struct ice_ptp_tx { + + /* Quad and port information for initializing timestamp blocks */ + #define INDEX_PER_QUAD 64 +-#define INDEX_PER_PORT_E822 16 ++#define INDEX_PER_PORT_E82X 16 + #define INDEX_PER_PORT_E810 64 + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h +index 4109aa3b2fcd..2c4dab0c48ab 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h +@@ -9,17 +9,17 @@ + */ + /* Constants defined for the PTP 1588 clock hardware. */ + +-/* struct ice_time_ref_info_e822 ++/* struct ice_time_ref_info_e82x + * + * E822 hardware can use different sources as the reference for the PTP + * hardware clock. Each clock has different characteristics such as a slightly + * different frequency, etc. + * + * This lookup table defines several constants that depend on the current time +- * reference. See the struct ice_time_ref_info_e822 for information about the ++ * reference. See the struct ice_time_ref_info_e82x for information about the + * meaning of each constant. + */ +-const struct ice_time_ref_info_e822 e822_time_ref[NUM_ICE_TIME_REF_FREQ] = { ++const struct ice_time_ref_info_e82x e822_time_ref[NUM_ICE_TIME_REF_FREQ] = { + /* ICE_TIME_REF_FREQ_25_000 -> 25 MHz */ + { + /* pll_freq */ +@@ -81,7 +81,7 @@ const struct ice_time_ref_info_e822 e822_time_ref[NUM_ICE_TIME_REF_FREQ] = { + }, + }; + +-const struct ice_cgu_pll_params_e822 e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = { ++const struct ice_cgu_pll_params_e82x e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = { + /* ICE_TIME_REF_FREQ_25_000 -> 25 MHz */ + { + /* refclk_pre_div */ +@@ -155,7 +155,7 @@ const struct ice_cgu_pll_params_e822 e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = { + }, + }; + +-/* struct ice_vernier_info_e822 ++/* struct ice_vernier_info_e82x + * + * E822 hardware calibrates the delay of the timestamp indication from the + * actual packet transmission or reception during the initialization of the +@@ -168,7 +168,7 @@ const struct ice_cgu_pll_params_e822 e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = { + * used by this link speed, and that the register should be cleared by writing + * 0. Other values specify the clock frequency in Hz. + */ +-const struct ice_vernier_info_e822 e822_vernier[NUM_ICE_PTP_LNK_SPD] = { ++const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD] = { + /* ICE_PTP_LNK_SPD_1G */ + { + /* tx_par_clk */ +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index cd28430cfdda..7337e7e710ed 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -284,19 +284,19 @@ static void ice_ptp_exec_tmr_cmd(struct ice_hw *hw) + */ + + /** +- * ice_fill_phy_msg_e822 - Fill message data for a PHY register access ++ * ice_fill_phy_msg_e82x - Fill message data for a PHY register access + * @msg: the PHY message buffer to fill in + * @port: the port to access + * @offset: the register offset + */ + static void +-ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset) ++ice_fill_phy_msg_e82x(struct ice_sbq_msg_input *msg, u8 port, u16 offset) + { + int phy_port, phy, quadtype; + +- phy_port = port % ICE_PORTS_PER_PHY_E822; +- phy = port / ICE_PORTS_PER_PHY_E822; +- quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E822; ++ phy_port = port % ICE_PORTS_PER_PHY_E82X; ++ phy = port / ICE_PORTS_PER_PHY_E82X; ++ quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E82X; + + if (quadtype == 0) { + msg->msg_addr_low = P_Q0_L(P_0_BASE + offset, phy_port); +@@ -315,7 +315,7 @@ ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset) + } + + /** +- * ice_is_64b_phy_reg_e822 - Check if this is a 64bit PHY register ++ * ice_is_64b_phy_reg_e82x - Check if this is a 64bit PHY register + * @low_addr: the low address to check + * @high_addr: on return, contains the high address of the 64bit register + * +@@ -323,7 +323,7 @@ ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset) + * represented as two 32bit registers. If it is, return the appropriate high + * register offset to use. + */ +-static bool ice_is_64b_phy_reg_e822(u16 low_addr, u16 *high_addr) ++static bool ice_is_64b_phy_reg_e82x(u16 low_addr, u16 *high_addr) + { + switch (low_addr) { + case P_REG_PAR_PCS_TX_OFFSET_L: +@@ -368,7 +368,7 @@ static bool ice_is_64b_phy_reg_e822(u16 low_addr, u16 *high_addr) + } + + /** +- * ice_is_40b_phy_reg_e822 - Check if this is a 40bit PHY register ++ * ice_is_40b_phy_reg_e82x - Check if this is a 40bit PHY register + * @low_addr: the low address to check + * @high_addr: on return, contains the high address of the 40bit value + * +@@ -377,7 +377,7 @@ static bool ice_is_64b_phy_reg_e822(u16 low_addr, u16 *high_addr) + * upper 32 bits in the high register. If it is, return the appropriate high + * register offset to use. + */ +-static bool ice_is_40b_phy_reg_e822(u16 low_addr, u16 *high_addr) ++static bool ice_is_40b_phy_reg_e82x(u16 low_addr, u16 *high_addr) + { + switch (low_addr) { + case P_REG_TIMETUS_L: +@@ -413,7 +413,7 @@ static bool ice_is_40b_phy_reg_e822(u16 low_addr, u16 *high_addr) + } + + /** +- * ice_read_phy_reg_e822 - Read a PHY register ++ * ice_read_phy_reg_e82x - Read a PHY register + * @hw: pointer to the HW struct + * @port: PHY port to read from + * @offset: PHY register offset to read +@@ -422,12 +422,12 @@ static bool ice_is_40b_phy_reg_e822(u16 low_addr, u16 *high_addr) + * Read a PHY register for the given port over the device sideband queue. + */ + static int +-ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val) ++ice_read_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 offset, u32 *val) + { + struct ice_sbq_msg_input msg = {0}; + int err; + +- ice_fill_phy_msg_e822(&msg, port, offset); ++ ice_fill_phy_msg_e82x(&msg, port, offset); + msg.opcode = ice_sbq_msg_rd; + + err = ice_sbq_rw_reg(hw, &msg); +@@ -443,7 +443,7 @@ ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val) + } + + /** +- * ice_read_64b_phy_reg_e822 - Read a 64bit value from PHY registers ++ * ice_read_64b_phy_reg_e82x - Read a 64bit value from PHY registers + * @hw: pointer to the HW struct + * @port: PHY port to read from + * @low_addr: offset of the lower register to read from +@@ -455,7 +455,7 @@ ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val) + * known to be two parts of a 64bit value. + */ + static int +-ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) ++ice_read_64b_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) + { + u32 low, high; + u16 high_addr; +@@ -464,20 +464,20 @@ ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) + /* Only operate on registers known to be split into two 32bit + * registers. + */ +- if (!ice_is_64b_phy_reg_e822(low_addr, &high_addr)) { ++ if (!ice_is_64b_phy_reg_e82x(low_addr, &high_addr)) { + ice_debug(hw, ICE_DBG_PTP, "Invalid 64b register addr 0x%08x\n", + low_addr); + return -EINVAL; + } + +- err = ice_read_phy_reg_e822(hw, port, low_addr, &low); ++ err = ice_read_phy_reg_e82x(hw, port, low_addr, &low); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read from low register 0x%08x\n, err %d", + low_addr, err); + return err; + } + +- err = ice_read_phy_reg_e822(hw, port, high_addr, &high); ++ err = ice_read_phy_reg_e82x(hw, port, high_addr, &high); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read from high register 0x%08x\n, err %d", + high_addr, err); +@@ -490,7 +490,7 @@ ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) + } + + /** +- * ice_write_phy_reg_e822 - Write a PHY register ++ * ice_write_phy_reg_e82x - Write a PHY register + * @hw: pointer to the HW struct + * @port: PHY port to write to + * @offset: PHY register offset to write +@@ -499,12 +499,12 @@ ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) + * Write a PHY register for the given port over the device sideband queue. + */ + static int +-ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val) ++ice_write_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 offset, u32 val) + { + struct ice_sbq_msg_input msg = {0}; + int err; + +- ice_fill_phy_msg_e822(&msg, port, offset); ++ ice_fill_phy_msg_e82x(&msg, port, offset); + msg.opcode = ice_sbq_msg_wr; + msg.data = val; + +@@ -519,7 +519,7 @@ ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val) + } + + /** +- * ice_write_40b_phy_reg_e822 - Write a 40b value to the PHY ++ * ice_write_40b_phy_reg_e82x - Write a 40b value to the PHY + * @hw: pointer to the HW struct + * @port: port to write to + * @low_addr: offset of the low register +@@ -529,7 +529,7 @@ ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val) + * it up into two chunks, the lower 8 bits and the upper 32 bits. + */ + static int +-ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) ++ice_write_40b_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + { + u32 low, high; + u16 high_addr; +@@ -538,7 +538,7 @@ ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + /* Only operate on registers known to be split into a lower 8 bit + * register and an upper 32 bit register. + */ +- if (!ice_is_40b_phy_reg_e822(low_addr, &high_addr)) { ++ if (!ice_is_40b_phy_reg_e82x(low_addr, &high_addr)) { + ice_debug(hw, ICE_DBG_PTP, "Invalid 40b register addr 0x%08x\n", + low_addr); + return -EINVAL; +@@ -547,14 +547,14 @@ ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + low = (u32)(val & P_REG_40B_LOW_M); + high = (u32)(val >> P_REG_40B_HIGH_S); + +- err = ice_write_phy_reg_e822(hw, port, low_addr, low); ++ err = ice_write_phy_reg_e82x(hw, port, low_addr, low); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write to low register 0x%08x\n, err %d", + low_addr, err); + return err; + } + +- err = ice_write_phy_reg_e822(hw, port, high_addr, high); ++ err = ice_write_phy_reg_e82x(hw, port, high_addr, high); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write to high register 0x%08x\n, err %d", + high_addr, err); +@@ -565,7 +565,7 @@ ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + } + + /** +- * ice_write_64b_phy_reg_e822 - Write a 64bit value to PHY registers ++ * ice_write_64b_phy_reg_e82x - Write a 64bit value to PHY registers + * @hw: pointer to the HW struct + * @port: PHY port to read from + * @low_addr: offset of the lower register to read from +@@ -577,7 +577,7 @@ ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + * a 64bit value. + */ + static int +-ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) ++ice_write_64b_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + { + u32 low, high; + u16 high_addr; +@@ -586,7 +586,7 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + /* Only operate on registers known to be split into two 32bit + * registers. + */ +- if (!ice_is_64b_phy_reg_e822(low_addr, &high_addr)) { ++ if (!ice_is_64b_phy_reg_e82x(low_addr, &high_addr)) { + ice_debug(hw, ICE_DBG_PTP, "Invalid 64b register addr 0x%08x\n", + low_addr); + return -EINVAL; +@@ -595,14 +595,14 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + low = lower_32_bits(val); + high = upper_32_bits(val); + +- err = ice_write_phy_reg_e822(hw, port, low_addr, low); ++ err = ice_write_phy_reg_e82x(hw, port, low_addr, low); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write to low register 0x%08x\n, err %d", + low_addr, err); + return err; + } + +- err = ice_write_phy_reg_e822(hw, port, high_addr, high); ++ err = ice_write_phy_reg_e82x(hw, port, high_addr, high); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write to high register 0x%08x\n, err %d", + high_addr, err); +@@ -613,7 +613,7 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + } + + /** +- * ice_fill_quad_msg_e822 - Fill message data for quad register access ++ * ice_fill_quad_msg_e82x - Fill message data for quad register access + * @msg: the PHY message buffer to fill in + * @quad: the quad to access + * @offset: the register offset +@@ -622,7 +622,7 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + * multiple PHYs. + */ + static int +-ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) ++ice_fill_quad_msg_e82x(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + { + u32 addr; + +@@ -631,7 +631,7 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + + msg->dest_dev = rmn_0; + +- if ((quad % ICE_QUADS_PER_PHY_E822) == 0) ++ if ((quad % ICE_QUADS_PER_PHY_E82X) == 0) + addr = Q_0_BASE + offset; + else + addr = Q_1_BASE + offset; +@@ -643,7 +643,7 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + } + + /** +- * ice_read_quad_reg_e822 - Read a PHY quad register ++ * ice_read_quad_reg_e82x - Read a PHY quad register + * @hw: pointer to the HW struct + * @quad: quad to read from + * @offset: quad register offset to read +@@ -653,12 +653,12 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + * shared between multiple PHYs. + */ + int +-ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) ++ice_read_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + { + struct ice_sbq_msg_input msg = {0}; + int err; + +- err = ice_fill_quad_msg_e822(&msg, quad, offset); ++ err = ice_fill_quad_msg_e82x(&msg, quad, offset); + if (err) + return err; + +@@ -677,7 +677,7 @@ ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + } + + /** +- * ice_write_quad_reg_e822 - Write a PHY quad register ++ * ice_write_quad_reg_e82x - Write a PHY quad register + * @hw: pointer to the HW struct + * @quad: quad to write to + * @offset: quad register offset to write +@@ -687,12 +687,12 @@ ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + * shared between multiple PHYs. + */ + int +-ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val) ++ice_write_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + { + struct ice_sbq_msg_input msg = {0}; + int err; + +- err = ice_fill_quad_msg_e822(&msg, quad, offset); ++ err = ice_fill_quad_msg_e82x(&msg, quad, offset); + if (err) + return err; + +@@ -710,7 +710,7 @@ ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + } + + /** +- * ice_read_phy_tstamp_e822 - Read a PHY timestamp out of the quad block ++ * ice_read_phy_tstamp_e82x - Read a PHY timestamp out of the quad block + * @hw: pointer to the HW struct + * @quad: the quad to read from + * @idx: the timestamp index to read +@@ -721,7 +721,7 @@ ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + * family of devices. + */ + static int +-ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) ++ice_read_phy_tstamp_e82x(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + { + u16 lo_addr, hi_addr; + u32 lo, hi; +@@ -730,14 +730,14 @@ ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + lo_addr = (u16)TS_L(Q_REG_TX_MEMORY_BANK_START, idx); + hi_addr = (u16)TS_H(Q_REG_TX_MEMORY_BANK_START, idx); + +- err = ice_read_quad_reg_e822(hw, quad, lo_addr, &lo); ++ err = ice_read_quad_reg_e82x(hw, quad, lo_addr, &lo); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read low PTP timestamp register, err %d\n", + err); + return err; + } + +- err = ice_read_quad_reg_e822(hw, quad, hi_addr, &hi); ++ err = ice_read_quad_reg_e82x(hw, quad, hi_addr, &hi); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read high PTP timestamp register, err %d\n", + err); +@@ -754,7 +754,7 @@ ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + } + + /** +- * ice_clear_phy_tstamp_e822 - Clear a timestamp from the quad block ++ * ice_clear_phy_tstamp_e82x - Clear a timestamp from the quad block + * @hw: pointer to the HW struct + * @quad: the quad to read from + * @idx: the timestamp index to reset +@@ -770,18 +770,18 @@ ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + * + * To directly clear the contents of the timestamp block entirely, discarding + * all timestamp data at once, software should instead use +- * ice_ptp_reset_ts_memory_quad_e822(). ++ * ice_ptp_reset_ts_memory_quad_e82x(). + * + * This function should only be called on an idx whose bit is set according to + * ice_get_phy_tx_tstamp_ready(). + */ + static int +-ice_clear_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx) ++ice_clear_phy_tstamp_e82x(struct ice_hw *hw, u8 quad, u8 idx) + { + u64 unused_tstamp; + int err; + +- err = ice_read_phy_tstamp_e822(hw, quad, idx, &unused_tstamp); ++ err = ice_read_phy_tstamp_e82x(hw, quad, idx, &unused_tstamp); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read the timestamp register for quad %u, idx %u, err %d\n", + quad, idx, err); +@@ -792,33 +792,33 @@ ice_clear_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx) + } + + /** +- * ice_ptp_reset_ts_memory_quad_e822 - Clear all timestamps from the quad block ++ * ice_ptp_reset_ts_memory_quad_e82x - Clear all timestamps from the quad block + * @hw: pointer to the HW struct + * @quad: the quad to read from + * + * Clear all timestamps from the PHY quad block that is shared between the + * internal PHYs on the E822 devices. + */ +-void ice_ptp_reset_ts_memory_quad_e822(struct ice_hw *hw, u8 quad) ++void ice_ptp_reset_ts_memory_quad_e82x(struct ice_hw *hw, u8 quad) + { +- ice_write_quad_reg_e822(hw, quad, Q_REG_TS_CTRL, Q_REG_TS_CTRL_M); +- ice_write_quad_reg_e822(hw, quad, Q_REG_TS_CTRL, ~(u32)Q_REG_TS_CTRL_M); ++ ice_write_quad_reg_e82x(hw, quad, Q_REG_TS_CTRL, Q_REG_TS_CTRL_M); ++ ice_write_quad_reg_e82x(hw, quad, Q_REG_TS_CTRL, ~(u32)Q_REG_TS_CTRL_M); + } + + /** +- * ice_ptp_reset_ts_memory_e822 - Clear all timestamps from all quad blocks ++ * ice_ptp_reset_ts_memory_e82x - Clear all timestamps from all quad blocks + * @hw: pointer to the HW struct + */ +-static void ice_ptp_reset_ts_memory_e822(struct ice_hw *hw) ++static void ice_ptp_reset_ts_memory_e82x(struct ice_hw *hw) + { + unsigned int quad; + + for (quad = 0; quad < ICE_MAX_QUAD; quad++) +- ice_ptp_reset_ts_memory_quad_e822(hw, quad); ++ ice_ptp_reset_ts_memory_quad_e82x(hw, quad); + } + + /** +- * ice_read_cgu_reg_e822 - Read a CGU register ++ * ice_read_cgu_reg_e82x - Read a CGU register + * @hw: pointer to the HW struct + * @addr: Register address to read + * @val: storage for register value read +@@ -827,7 +827,7 @@ static void ice_ptp_reset_ts_memory_e822(struct ice_hw *hw) + * applicable to E822 devices. + */ + static int +-ice_read_cgu_reg_e822(struct ice_hw *hw, u32 addr, u32 *val) ++ice_read_cgu_reg_e82x(struct ice_hw *hw, u32 addr, u32 *val) + { + struct ice_sbq_msg_input cgu_msg; + int err; +@@ -850,7 +850,7 @@ ice_read_cgu_reg_e822(struct ice_hw *hw, u32 addr, u32 *val) + } + + /** +- * ice_write_cgu_reg_e822 - Write a CGU register ++ * ice_write_cgu_reg_e82x - Write a CGU register + * @hw: pointer to the HW struct + * @addr: Register address to write + * @val: value to write into the register +@@ -859,7 +859,7 @@ ice_read_cgu_reg_e822(struct ice_hw *hw, u32 addr, u32 *val) + * applicable to E822 devices. + */ + static int +-ice_write_cgu_reg_e822(struct ice_hw *hw, u32 addr, u32 val) ++ice_write_cgu_reg_e82x(struct ice_hw *hw, u32 addr, u32 val) + { + struct ice_sbq_msg_input cgu_msg; + int err; +@@ -925,7 +925,7 @@ static const char *ice_clk_src_str(u8 clk_src) + } + + /** +- * ice_cfg_cgu_pll_e822 - Configure the Clock Generation Unit ++ * ice_cfg_cgu_pll_e82x - Configure the Clock Generation Unit + * @hw: pointer to the HW struct + * @clk_freq: Clock frequency to program + * @clk_src: Clock source to select (TIME_REF, or TCX0) +@@ -934,7 +934,7 @@ static const char *ice_clk_src_str(u8 clk_src) + * time reference, enabling the PLL which drives the PTP hardware clock. + */ + static int +-ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, ++ice_cfg_cgu_pll_e82x(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + enum ice_clk_src clk_src) + { + union tspll_ro_bwm_lf bwm_lf; +@@ -963,15 +963,15 @@ ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + return -EINVAL; + } + +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD9, &dw9.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD9, &dw9.val); + if (err) + return err; + +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD24, &dw24.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD24, &dw24.val); + if (err) + return err; + +- err = ice_read_cgu_reg_e822(hw, TSPLL_RO_BWM_LF, &bwm_lf.val); ++ err = ice_read_cgu_reg_e82x(hw, TSPLL_RO_BWM_LF, &bwm_lf.val); + if (err) + return err; + +@@ -986,43 +986,43 @@ ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + if (dw24.field.ts_pll_enable) { + dw24.field.ts_pll_enable = 0; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD24, dw24.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.val); + if (err) + return err; + } + + /* Set the frequency */ + dw9.field.time_ref_freq_sel = clk_freq; +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD9, dw9.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD9, dw9.val); + if (err) + return err; + + /* Configure the TS PLL feedback divisor */ +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD19, &dw19.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD19, &dw19.val); + if (err) + return err; + + dw19.field.tspll_fbdiv_intgr = e822_cgu_params[clk_freq].feedback_div; + dw19.field.tspll_ndivratio = 1; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD19, dw19.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD19, dw19.val); + if (err) + return err; + + /* Configure the TS PLL post divisor */ +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD22, &dw22.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD22, &dw22.val); + if (err) + return err; + + dw22.field.time1588clk_div = e822_cgu_params[clk_freq].post_pll_div; + dw22.field.time1588clk_sel_div2 = 0; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD22, dw22.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD22, dw22.val); + if (err) + return err; + + /* Configure the TS PLL pre divisor and clock source */ +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD24, &dw24.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD24, &dw24.val); + if (err) + return err; + +@@ -1030,21 +1030,21 @@ ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + dw24.field.tspll_fbdiv_frac = e822_cgu_params[clk_freq].frac_n_div; + dw24.field.time_ref_sel = clk_src; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD24, dw24.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.val); + if (err) + return err; + + /* Finally, enable the PLL */ + dw24.field.ts_pll_enable = 1; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD24, dw24.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.val); + if (err) + return err; + + /* Wait to verify if the PLL locks */ + usleep_range(1000, 5000); + +- err = ice_read_cgu_reg_e822(hw, TSPLL_RO_BWM_LF, &bwm_lf.val); ++ err = ice_read_cgu_reg_e82x(hw, TSPLL_RO_BWM_LF, &bwm_lf.val); + if (err) + return err; + +@@ -1064,18 +1064,18 @@ ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + } + + /** +- * ice_init_cgu_e822 - Initialize CGU with settings from firmware ++ * ice_init_cgu_e82x - Initialize CGU with settings from firmware + * @hw: pointer to the HW structure + * + * Initialize the Clock Generation Unit of the E822 device. + */ +-static int ice_init_cgu_e822(struct ice_hw *hw) ++static int ice_init_cgu_e82x(struct ice_hw *hw) + { + struct ice_ts_func_info *ts_info = &hw->func_caps.ts_func_info; + union tspll_cntr_bist_settings cntr_bist; + int err; + +- err = ice_read_cgu_reg_e822(hw, TSPLL_CNTR_BIST_SETTINGS, ++ err = ice_read_cgu_reg_e82x(hw, TSPLL_CNTR_BIST_SETTINGS, + &cntr_bist.val); + if (err) + return err; +@@ -1084,7 +1084,7 @@ static int ice_init_cgu_e822(struct ice_hw *hw) + cntr_bist.field.i_plllock_sel_0 = 0; + cntr_bist.field.i_plllock_sel_1 = 0; + +- err = ice_write_cgu_reg_e822(hw, TSPLL_CNTR_BIST_SETTINGS, ++ err = ice_write_cgu_reg_e82x(hw, TSPLL_CNTR_BIST_SETTINGS, + cntr_bist.val); + if (err) + return err; +@@ -1092,7 +1092,7 @@ static int ice_init_cgu_e822(struct ice_hw *hw) + /* Configure the CGU PLL using the parameters from the function + * capabilities. + */ +- err = ice_cfg_cgu_pll_e822(hw, ts_info->time_ref, ++ err = ice_cfg_cgu_pll_e82x(hw, ts_info->time_ref, + (enum ice_clk_src)ts_info->clk_src); + if (err) + return err; +@@ -1113,7 +1113,7 @@ static int ice_ptp_set_vernier_wl(struct ice_hw *hw) + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + int err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_WL, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_WL, + PTP_VERNIER_WL); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to set vernier window length for port %u, err %d\n", +@@ -1126,12 +1126,12 @@ static int ice_ptp_set_vernier_wl(struct ice_hw *hw) + } + + /** +- * ice_ptp_init_phc_e822 - Perform E822 specific PHC initialization ++ * ice_ptp_init_phc_e82x - Perform E822 specific PHC initialization + * @hw: pointer to HW struct + * + * Perform PHC initialization steps specific to E822 devices. + */ +-static int ice_ptp_init_phc_e822(struct ice_hw *hw) ++static int ice_ptp_init_phc_e82x(struct ice_hw *hw) + { + int err; + u32 regval; +@@ -1145,7 +1145,7 @@ static int ice_ptp_init_phc_e822(struct ice_hw *hw) + wr32(hw, PF_SB_REM_DEV_CTL, regval); + + /* Initialize the Clock Generation Unit */ +- err = ice_init_cgu_e822(hw); ++ err = ice_init_cgu_e82x(hw); + if (err) + return err; + +@@ -1154,7 +1154,7 @@ static int ice_ptp_init_phc_e822(struct ice_hw *hw) + } + + /** +- * ice_ptp_prep_phy_time_e822 - Prepare PHY port with initial time ++ * ice_ptp_prep_phy_time_e82x - Prepare PHY port with initial time + * @hw: pointer to the HW struct + * @time: Time to initialize the PHY port clocks to + * +@@ -1164,7 +1164,7 @@ static int ice_ptp_init_phc_e822(struct ice_hw *hw) + * units of nominal nanoseconds. + */ + static int +-ice_ptp_prep_phy_time_e822(struct ice_hw *hw, u32 time) ++ice_ptp_prep_phy_time_e82x(struct ice_hw *hw, u32 time) + { + u64 phy_time; + u8 port; +@@ -1177,14 +1177,14 @@ ice_ptp_prep_phy_time_e822(struct ice_hw *hw, u32 time) + + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + /* Tx case */ +- err = ice_write_64b_phy_reg_e822(hw, port, ++ err = ice_write_64b_phy_reg_e82x(hw, port, + P_REG_TX_TIMER_INC_PRE_L, + phy_time); + if (err) + goto exit_err; + + /* Rx case */ +- err = ice_write_64b_phy_reg_e822(hw, port, ++ err = ice_write_64b_phy_reg_e82x(hw, port, + P_REG_RX_TIMER_INC_PRE_L, + phy_time); + if (err) +@@ -1201,7 +1201,7 @@ ice_ptp_prep_phy_time_e822(struct ice_hw *hw, u32 time) + } + + /** +- * ice_ptp_prep_port_adj_e822 - Prepare a single port for time adjust ++ * ice_ptp_prep_port_adj_e82x - Prepare a single port for time adjust + * @hw: pointer to HW struct + * @port: Port number to be programmed + * @time: time in cycles to adjust the port Tx and Rx clocks +@@ -1216,7 +1216,7 @@ ice_ptp_prep_phy_time_e822(struct ice_hw *hw, u32 time) + * Negative adjustments are supported using 2s complement arithmetic. + */ + static int +-ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) ++ice_ptp_prep_port_adj_e82x(struct ice_hw *hw, u8 port, s64 time) + { + u32 l_time, u_time; + int err; +@@ -1225,23 +1225,23 @@ ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) + u_time = upper_32_bits(time); + + /* Tx case */ +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_TIMER_INC_PRE_L, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_TIMER_INC_PRE_L, + l_time); + if (err) + goto exit_err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_TIMER_INC_PRE_U, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_TIMER_INC_PRE_U, + u_time); + if (err) + goto exit_err; + + /* Rx case */ +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_TIMER_INC_PRE_L, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_TIMER_INC_PRE_L, + l_time); + if (err) + goto exit_err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_TIMER_INC_PRE_U, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_TIMER_INC_PRE_U, + u_time); + if (err) + goto exit_err; +@@ -1255,7 +1255,7 @@ ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) + } + + /** +- * ice_ptp_prep_phy_adj_e822 - Prep PHY ports for a time adjustment ++ * ice_ptp_prep_phy_adj_e82x - Prep PHY ports for a time adjustment + * @hw: pointer to HW struct + * @adj: adjustment in nanoseconds + * +@@ -1264,7 +1264,7 @@ ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) + * ADJ_TIME or ADJ_TIME_AT_TIME sync command. + */ + static int +-ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj) ++ice_ptp_prep_phy_adj_e82x(struct ice_hw *hw, s32 adj) + { + s64 cycles; + u8 port; +@@ -1281,7 +1281,7 @@ ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj) + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + int err; + +- err = ice_ptp_prep_port_adj_e822(hw, port, cycles); ++ err = ice_ptp_prep_port_adj_e82x(hw, port, cycles); + if (err) + return err; + } +@@ -1290,7 +1290,7 @@ ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj) + } + + /** +- * ice_ptp_prep_phy_incval_e822 - Prepare PHY ports for time adjustment ++ * ice_ptp_prep_phy_incval_e82x - Prepare PHY ports for time adjustment + * @hw: pointer to HW struct + * @incval: new increment value to prepare + * +@@ -1299,13 +1299,13 @@ ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj) + * issuing an INIT_INCVAL command. + */ + static int +-ice_ptp_prep_phy_incval_e822(struct ice_hw *hw, u64 incval) ++ice_ptp_prep_phy_incval_e82x(struct ice_hw *hw, u64 incval) + { + int err; + u8 port; + + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_TIMETUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_TIMETUS_L, + incval); + if (err) + goto exit_err; +@@ -1337,7 +1337,7 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) + int err; + + /* Tx case */ +- err = ice_read_64b_phy_reg_e822(hw, port, P_REG_TX_CAPTURE_L, tx_ts); ++ err = ice_read_64b_phy_reg_e82x(hw, port, P_REG_TX_CAPTURE_L, tx_ts); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read REG_TX_CAPTURE, err %d\n", + err); +@@ -1348,7 +1348,7 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) + (unsigned long long)*tx_ts); + + /* Rx case */ +- err = ice_read_64b_phy_reg_e822(hw, port, P_REG_RX_CAPTURE_L, rx_ts); ++ err = ice_read_64b_phy_reg_e82x(hw, port, P_REG_RX_CAPTURE_L, rx_ts); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_CAPTURE, err %d\n", + err); +@@ -1362,7 +1362,7 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) + } + + /** +- * ice_ptp_write_port_cmd_e822 - Prepare a single PHY port for a timer command ++ * ice_ptp_write_port_cmd_e82x - Prepare a single PHY port for a timer command + * @hw: pointer to HW struct + * @port: Port to which cmd has to be sent + * @cmd: Command to be sent to the port +@@ -1372,8 +1372,8 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) + * Do not use this function directly. If you want to configure exactly one + * port, use ice_ptp_one_port_cmd() instead. + */ +-static int +-ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) ++static int ice_ptp_write_port_cmd_e82x(struct ice_hw *hw, u8 port, ++ enum ice_ptp_tmr_cmd cmd) + { + u32 cmd_val, val; + u8 tmr_idx; +@@ -1403,7 +1403,7 @@ ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd + + /* Tx case */ + /* Read, modify, write */ +- err = ice_read_phy_reg_e822(hw, port, P_REG_TX_TMR_CMD, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_TX_TMR_CMD, &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_TMR_CMD, err %d\n", + err); +@@ -1414,7 +1414,7 @@ ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd + val &= ~TS_CMD_MASK; + val |= cmd_val; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_TMR_CMD, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_TMR_CMD, val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write back TX_TMR_CMD, err %d\n", + err); +@@ -1423,7 +1423,7 @@ ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd + + /* Rx case */ + /* Read, modify, write */ +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_TMR_CMD, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_TMR_CMD, &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_TMR_CMD, err %d\n", + err); +@@ -1434,7 +1434,7 @@ ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd + val &= ~TS_CMD_MASK; + val |= cmd_val; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_TMR_CMD, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_TMR_CMD, val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write back RX_TMR_CMD, err %d\n", + err); +@@ -1469,7 +1469,7 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + else + cmd = ICE_PTP_NOP; + +- err = ice_ptp_write_port_cmd_e822(hw, port, cmd); ++ err = ice_ptp_write_port_cmd_e82x(hw, port, cmd); + if (err) + return err; + } +@@ -1478,7 +1478,7 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + } + + /** +- * ice_ptp_port_cmd_e822 - Prepare all ports for a timer command ++ * ice_ptp_port_cmd_e82x - Prepare all ports for a timer command + * @hw: pointer to the HW struct + * @cmd: timer command to prepare + * +@@ -1486,14 +1486,14 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + * command. + */ + static int +-ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) ++ice_ptp_port_cmd_e82x(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + { + u8 port; + + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + int err; + +- err = ice_ptp_write_port_cmd_e822(hw, port, cmd); ++ err = ice_ptp_write_port_cmd_e82x(hw, port, cmd); + if (err) + return err; + } +@@ -1509,7 +1509,7 @@ ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + */ + + /** +- * ice_phy_get_speed_and_fec_e822 - Get link speed and FEC based on serdes mode ++ * ice_phy_get_speed_and_fec_e82x - Get link speed and FEC based on serdes mode + * @hw: pointer to HW struct + * @port: the port to read from + * @link_out: if non-NULL, holds link speed on success +@@ -1519,7 +1519,7 @@ ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + * algorithm. + */ + static int +-ice_phy_get_speed_and_fec_e822(struct ice_hw *hw, u8 port, ++ice_phy_get_speed_and_fec_e82x(struct ice_hw *hw, u8 port, + enum ice_ptp_link_spd *link_out, + enum ice_ptp_fec_mode *fec_out) + { +@@ -1528,7 +1528,7 @@ ice_phy_get_speed_and_fec_e822(struct ice_hw *hw, u8 port, + u32 serdes; + int err; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_LINK_SPEED, &serdes); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_LINK_SPEED, &serdes); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read serdes info\n"); + return err; +@@ -1585,18 +1585,18 @@ ice_phy_get_speed_and_fec_e822(struct ice_hw *hw, u8 port, + } + + /** +- * ice_phy_cfg_lane_e822 - Configure PHY quad for single/multi-lane timestamp ++ * ice_phy_cfg_lane_e82x - Configure PHY quad for single/multi-lane timestamp + * @hw: pointer to HW struct + * @port: to configure the quad for + */ +-static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) ++static void ice_phy_cfg_lane_e82x(struct ice_hw *hw, u8 port) + { + enum ice_ptp_link_spd link_spd; + int err; + u32 val; + u8 quad; + +- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, NULL); ++ err = ice_phy_get_speed_and_fec_e82x(hw, port, &link_spd, NULL); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to get PHY link speed, err %d\n", + err); +@@ -1605,7 +1605,7 @@ static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) + + quad = port / ICE_PORTS_PER_QUAD; + +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, &val); ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_MEM_GLB_CFG, err %d\n", + err); +@@ -1617,7 +1617,7 @@ static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) + else + val |= Q_REG_TX_MEM_GBL_CFG_LANE_TYPE_M; + +- err = ice_write_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, val); ++ err = ice_write_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write back TX_MEM_GBL_CFG, err %d\n", + err); +@@ -1626,7 +1626,7 @@ static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_phy_cfg_uix_e822 - Configure Serdes UI to TU conversion for E822 ++ * ice_phy_cfg_uix_e82x - Configure Serdes UI to TU conversion for E822 + * @hw: pointer to the HW structure + * @port: the port to configure + * +@@ -1671,12 +1671,12 @@ static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) + * a divide by 390,625,000. This does lose some precision, but avoids + * miscalculation due to arithmetic overflow. + */ +-static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) ++static int ice_phy_cfg_uix_e82x(struct ice_hw *hw, u8 port) + { + u64 cur_freq, clk_incval, tu_per_sec, uix; + int err; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per second divided by 256 */ +@@ -1688,7 +1688,7 @@ static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) + /* Program the 10Gb/40Gb conversion ratio */ + uix = div_u64(tu_per_sec * LINE_UI_10G_40G, 390625000); + +- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_UIX66_10G_40G_L, ++ err = ice_write_64b_phy_reg_e82x(hw, port, P_REG_UIX66_10G_40G_L, + uix); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write UIX66_10G_40G, err %d\n", +@@ -1699,7 +1699,7 @@ static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) + /* Program the 25Gb/100Gb conversion ratio */ + uix = div_u64(tu_per_sec * LINE_UI_25G_100G, 390625000); + +- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_UIX66_25G_100G_L, ++ err = ice_write_64b_phy_reg_e82x(hw, port, P_REG_UIX66_25G_100G_L, + uix); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write UIX66_25G_100G, err %d\n", +@@ -1711,7 +1711,7 @@ static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_phy_cfg_parpcs_e822 - Configure TUs per PAR/PCS clock cycle ++ * ice_phy_cfg_parpcs_e82x - Configure TUs per PAR/PCS clock cycle + * @hw: pointer to the HW struct + * @port: port to configure + * +@@ -1753,18 +1753,18 @@ static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) + * frequency is ~29 bits, so multiplying them together should fit within the + * 64 bit arithmetic. + */ +-static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) ++static int ice_phy_cfg_parpcs_e82x(struct ice_hw *hw, u8 port) + { + u64 cur_freq, clk_incval, tu_per_sec, phy_tus; + enum ice_ptp_link_spd link_spd; + enum ice_ptp_fec_mode fec_mode; + int err; + +- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); ++ err = ice_phy_get_speed_and_fec_e82x(hw, port, &link_spd, &fec_mode); + if (err) + return err; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per cycle of the PHC clock */ +@@ -1784,7 +1784,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_PAR_TX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_PAR_TX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1796,7 +1796,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_PAR_RX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_PAR_RX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1808,7 +1808,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_PCS_TX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_PCS_TX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1820,7 +1820,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_PCS_RX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_PCS_RX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1832,7 +1832,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PAR_TX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_DESK_PAR_TX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1844,7 +1844,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PAR_RX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_DESK_PAR_RX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1856,7 +1856,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PCS_TX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_DESK_PCS_TX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1868,23 +1868,23 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- return ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PCS_RX_TUS_L, ++ return ice_write_40b_phy_reg_e82x(hw, port, P_REG_DESK_PCS_RX_TUS_L, + phy_tus); + } + + /** +- * ice_calc_fixed_tx_offset_e822 - Calculated Fixed Tx offset for a port ++ * ice_calc_fixed_tx_offset_e82x - Calculated Fixed Tx offset for a port + * @hw: pointer to the HW struct + * @link_spd: the Link speed to calculate for + * + * Calculate the fixed offset due to known static latency data. + */ + static u64 +-ice_calc_fixed_tx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) ++ice_calc_fixed_tx_offset_e82x(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + { + u64 cur_freq, clk_incval, tu_per_sec, fixed_offset; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per second */ +@@ -1904,7 +1904,7 @@ ice_calc_fixed_tx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + } + + /** +- * ice_phy_cfg_tx_offset_e822 - Configure total Tx timestamp offset ++ * ice_phy_cfg_tx_offset_e82x - Configure total Tx timestamp offset + * @hw: pointer to the HW struct + * @port: the PHY port to configure + * +@@ -1926,7 +1926,7 @@ ice_calc_fixed_tx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + * Returns zero on success, -EBUSY if the hardware vernier offset + * calibration has not completed, or another error code on failure. + */ +-int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) ++int ice_phy_cfg_tx_offset_e82x(struct ice_hw *hw, u8 port) + { + enum ice_ptp_link_spd link_spd; + enum ice_ptp_fec_mode fec_mode; +@@ -1935,7 +1935,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + u32 reg; + + /* Nothing to do if we've already programmed the offset */ +- err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OR, ®); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_TX_OR, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OR for port %u, err %d\n", + port, err); +@@ -1945,7 +1945,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + if (reg) + return 0; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OV_STATUS, ®); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_TX_OV_STATUS, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OV_STATUS for port %u, err %d\n", + port, err); +@@ -1955,11 +1955,11 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + if (!(reg & P_REG_TX_OV_STATUS_OV_M)) + return -EBUSY; + +- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); ++ err = ice_phy_get_speed_and_fec_e82x(hw, port, &link_spd, &fec_mode); + if (err) + return err; + +- total_offset = ice_calc_fixed_tx_offset_e822(hw, link_spd); ++ total_offset = ice_calc_fixed_tx_offset_e82x(hw, link_spd); + + /* Read the first Vernier offset from the PHY register and add it to + * the total offset. +@@ -1970,7 +1970,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + link_spd == ICE_PTP_LNK_SPD_25G_RS || + link_spd == ICE_PTP_LNK_SPD_40G || + link_spd == ICE_PTP_LNK_SPD_50G) { +- err = ice_read_64b_phy_reg_e822(hw, port, ++ err = ice_read_64b_phy_reg_e82x(hw, port, + P_REG_PAR_PCS_TX_OFFSET_L, + &val); + if (err) +@@ -1985,7 +1985,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + */ + if (link_spd == ICE_PTP_LNK_SPD_50G_RS || + link_spd == ICE_PTP_LNK_SPD_100G_RS) { +- err = ice_read_64b_phy_reg_e822(hw, port, ++ err = ice_read_64b_phy_reg_e82x(hw, port, + P_REG_PAR_TX_TIME_L, + &val); + if (err) +@@ -1998,12 +1998,12 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + * PHY and indicate that the Tx offset is ready. After this, + * timestamps will be enabled. + */ +- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_TX_OFFSET_L, ++ err = ice_write_64b_phy_reg_e82x(hw, port, P_REG_TOTAL_TX_OFFSET_L, + total_offset); + if (err) + return err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_OR, 1); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_OR, 1); + if (err) + return err; + +@@ -2014,7 +2014,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_phy_calc_pmd_adj_e822 - Calculate PMD adjustment for Rx ++ * ice_phy_calc_pmd_adj_e82x - Calculate PMD adjustment for Rx + * @hw: pointer to the HW struct + * @port: the PHY port to adjust for + * @link_spd: the current link speed of the PHY +@@ -2026,7 +2026,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + * various delays caused when receiving a packet. + */ + static int +-ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, ++ice_phy_calc_pmd_adj_e82x(struct ice_hw *hw, u8 port, + enum ice_ptp_link_spd link_spd, + enum ice_ptp_fec_mode fec_mode, u64 *pmd_adj) + { +@@ -2035,7 +2035,7 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + u32 val; + int err; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_PMD_ALIGNMENT, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_PMD_ALIGNMENT, &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read PMD alignment, err %d\n", + err); +@@ -2044,7 +2044,7 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + + pmd_align = (u8)val; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per second */ +@@ -2123,7 +2123,7 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + u64 cycle_adj; + u8 rx_cycle; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_40_TO_160_CNT, ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_40_TO_160_CNT, + &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read 25G-RS Rx cycle count, err %d\n", +@@ -2145,7 +2145,7 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + u64 cycle_adj; + u8 rx_cycle; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_80_TO_160_CNT, ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_80_TO_160_CNT, + &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read 50G-RS Rx cycle count, err %d\n", +@@ -2172,18 +2172,18 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + } + + /** +- * ice_calc_fixed_rx_offset_e822 - Calculated the fixed Rx offset for a port ++ * ice_calc_fixed_rx_offset_e82x - Calculated the fixed Rx offset for a port + * @hw: pointer to HW struct + * @link_spd: The Link speed to calculate for + * + * Determine the fixed Rx latency for a given link speed. + */ + static u64 +-ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) ++ice_calc_fixed_rx_offset_e82x(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + { + u64 cur_freq, clk_incval, tu_per_sec, fixed_offset; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per second */ +@@ -2203,7 +2203,7 @@ ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + } + + /** +- * ice_phy_cfg_rx_offset_e822 - Configure total Rx timestamp offset ++ * ice_phy_cfg_rx_offset_e82x - Configure total Rx timestamp offset + * @hw: pointer to the HW struct + * @port: the PHY port to configure + * +@@ -2229,7 +2229,7 @@ ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + * Returns zero on success, -EBUSY if the hardware vernier offset + * calibration has not completed, or another error code on failure. + */ +-int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) ++int ice_phy_cfg_rx_offset_e82x(struct ice_hw *hw, u8 port) + { + enum ice_ptp_link_spd link_spd; + enum ice_ptp_fec_mode fec_mode; +@@ -2238,7 +2238,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + u32 reg; + + /* Nothing to do if we've already programmed the offset */ +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OR, ®); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_OR, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OR for port %u, err %d\n", + port, err); +@@ -2248,7 +2248,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + if (reg) + return 0; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OV_STATUS, ®); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_OV_STATUS, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OV_STATUS for port %u, err %d\n", + port, err); +@@ -2258,16 +2258,16 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + if (!(reg & P_REG_RX_OV_STATUS_OV_M)) + return -EBUSY; + +- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); ++ err = ice_phy_get_speed_and_fec_e82x(hw, port, &link_spd, &fec_mode); + if (err) + return err; + +- total_offset = ice_calc_fixed_rx_offset_e822(hw, link_spd); ++ total_offset = ice_calc_fixed_rx_offset_e82x(hw, link_spd); + + /* Read the first Vernier offset from the PHY register and add it to + * the total offset. + */ +- err = ice_read_64b_phy_reg_e822(hw, port, ++ err = ice_read_64b_phy_reg_e82x(hw, port, + P_REG_PAR_PCS_RX_OFFSET_L, + &val); + if (err) +@@ -2282,7 +2282,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + link_spd == ICE_PTP_LNK_SPD_50G || + link_spd == ICE_PTP_LNK_SPD_50G_RS || + link_spd == ICE_PTP_LNK_SPD_100G_RS) { +- err = ice_read_64b_phy_reg_e822(hw, port, ++ err = ice_read_64b_phy_reg_e82x(hw, port, + P_REG_PAR_RX_TIME_L, + &val); + if (err) +@@ -2292,7 +2292,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + } + + /* In addition, Rx must account for the PMD alignment */ +- err = ice_phy_calc_pmd_adj_e822(hw, port, link_spd, fec_mode, &pmd); ++ err = ice_phy_calc_pmd_adj_e82x(hw, port, link_spd, fec_mode, &pmd); + if (err) + return err; + +@@ -2308,12 +2308,12 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + * PHY and indicate that the Rx offset is ready. After this, + * timestamps will be enabled. + */ +- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_RX_OFFSET_L, ++ err = ice_write_64b_phy_reg_e82x(hw, port, P_REG_TOTAL_RX_OFFSET_L, + total_offset); + if (err) + return err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_OR, 1); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_OR, 1); + if (err) + return err; + +@@ -2324,7 +2324,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_read_phy_and_phc_time_e822 - Simultaneously capture PHC and PHY time ++ * ice_read_phy_and_phc_time_e82x - Simultaneously capture PHC and PHY time + * @hw: pointer to the HW struct + * @port: the PHY port to read + * @phy_time: on return, the 64bit PHY timer value +@@ -2334,7 +2334,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + * timer values. + */ + static int +-ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time, ++ice_read_phy_and_phc_time_e82x(struct ice_hw *hw, u8 port, u64 *phy_time, + u64 *phc_time) + { + u64 tx_time, rx_time; +@@ -2381,7 +2381,7 @@ ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time, + } + + /** +- * ice_sync_phy_timer_e822 - Synchronize the PHY timer with PHC timer ++ * ice_sync_phy_timer_e82x - Synchronize the PHY timer with PHC timer + * @hw: pointer to the HW struct + * @port: the PHY port to synchronize + * +@@ -2391,7 +2391,7 @@ ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time, + * calculate an appropriate 2s complement addition to add to the PHY timer in + * order to ensure it reads the same value as the primary PHC timer. + */ +-static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) ++static int ice_sync_phy_timer_e82x(struct ice_hw *hw, u8 port) + { + u64 phc_time, phy_time, difference; + int err; +@@ -2401,7 +2401,7 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + return -EBUSY; + } + +- err = ice_read_phy_and_phc_time_e822(hw, port, &phy_time, &phc_time); ++ err = ice_read_phy_and_phc_time_e82x(hw, port, &phy_time, &phc_time); + if (err) + goto err_unlock; + +@@ -2415,7 +2415,7 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + */ + difference = phc_time - phy_time; + +- err = ice_ptp_prep_port_adj_e822(hw, port, (s64)difference); ++ err = ice_ptp_prep_port_adj_e82x(hw, port, (s64)difference); + if (err) + goto err_unlock; + +@@ -2432,7 +2432,7 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + /* Re-capture the timer values to flush the command registers and + * verify that the time was properly adjusted. + */ +- err = ice_read_phy_and_phc_time_e822(hw, port, &phy_time, &phc_time); ++ err = ice_read_phy_and_phc_time_e82x(hw, port, &phy_time, &phc_time); + if (err) + goto err_unlock; + +@@ -2451,7 +2451,7 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_stop_phy_timer_e822 - Stop the PHY clock timer ++ * ice_stop_phy_timer_e82x - Stop the PHY clock timer + * @hw: pointer to the HW struct + * @port: the PHY port to stop + * @soft_reset: if true, hold the SOFT_RESET bit of P_REG_PS +@@ -2461,36 +2461,36 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + * initialized or when link speed changes. + */ + int +-ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset) ++ice_stop_phy_timer_e82x(struct ice_hw *hw, u8 port, bool soft_reset) + { + int err; + u32 val; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_OR, 0); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_OR, 0); + if (err) + return err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_OR, 0); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_OR, 0); + if (err) + return err; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_PS, &val); + if (err) + return err; + + val &= ~P_REG_PS_START_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + val &= ~P_REG_PS_ENA_CLK_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + if (soft_reset) { + val |= P_REG_PS_SFT_RESET_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + } +@@ -2501,7 +2501,7 @@ ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset) + } + + /** +- * ice_start_phy_timer_e822 - Start the PHY clock timer ++ * ice_start_phy_timer_e82x - Start the PHY clock timer + * @hw: pointer to the HW struct + * @port: the PHY port to start + * +@@ -2511,7 +2511,7 @@ ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset) + * + * Hardware will take Vernier measurements on Tx or Rx of packets. + */ +-int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) ++int ice_start_phy_timer_e82x(struct ice_hw *hw, u8 port) + { + u32 lo, hi, val; + u64 incval; +@@ -2520,17 +2520,17 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + + tmr_idx = ice_get_ptp_src_clock_index(hw); + +- err = ice_stop_phy_timer_e822(hw, port, false); ++ err = ice_stop_phy_timer_e82x(hw, port, false); + if (err) + return err; + +- ice_phy_cfg_lane_e822(hw, port); ++ ice_phy_cfg_lane_e82x(hw, port); + +- err = ice_phy_cfg_uix_e822(hw, port); ++ err = ice_phy_cfg_uix_e82x(hw, port); + if (err) + return err; + +- err = ice_phy_cfg_parpcs_e822(hw, port); ++ err = ice_phy_cfg_parpcs_e82x(hw, port); + if (err) + return err; + +@@ -2538,7 +2538,7 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + hi = rd32(hw, GLTSYN_INCVAL_H(tmr_idx)); + incval = (u64)hi << 32 | lo; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_TIMETUS_L, incval); ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_TIMETUS_L, incval); + if (err) + return err; + +@@ -2551,22 +2551,22 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + + ice_ptp_exec_tmr_cmd(hw); + +- err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_PS, &val); + if (err) + return err; + + val |= P_REG_PS_SFT_RESET_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + val |= P_REG_PS_START_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + val &= ~P_REG_PS_SFT_RESET_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + +@@ -2577,18 +2577,18 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + ice_ptp_exec_tmr_cmd(hw); + + val |= P_REG_PS_ENA_CLK_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + val |= P_REG_PS_LOAD_OFFSET_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + ice_ptp_exec_tmr_cmd(hw); + +- err = ice_sync_phy_timer_e822(hw, port); ++ err = ice_sync_phy_timer_e82x(hw, port); + if (err) + return err; + +@@ -2598,7 +2598,7 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_get_phy_tx_tstamp_ready_e822 - Read Tx memory status register ++ * ice_get_phy_tx_tstamp_ready_e82x - Read Tx memory status register + * @hw: pointer to the HW struct + * @quad: the timestamp quad to read from + * @tstamp_ready: contents of the Tx memory status register +@@ -2608,19 +2608,19 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + * ready to be captured from the PHY timestamp block. + */ + static int +-ice_get_phy_tx_tstamp_ready_e822(struct ice_hw *hw, u8 quad, u64 *tstamp_ready) ++ice_get_phy_tx_tstamp_ready_e82x(struct ice_hw *hw, u8 quad, u64 *tstamp_ready) + { + u32 hi, lo; + int err; + +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEMORY_STATUS_U, &hi); ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEMORY_STATUS_U, &hi); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_MEMORY_STATUS_U for quad %u, err %d\n", + quad, err); + return err; + } + +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEMORY_STATUS_L, &lo); ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEMORY_STATUS_L, &lo); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_MEMORY_STATUS_L for quad %u, err %d\n", + quad, err); +@@ -3306,7 +3306,7 @@ void ice_ptp_init_phy_model(struct ice_hw *hw) + if (ice_is_e810(hw)) + hw->phy_model = ICE_PHY_E810; + else +- hw->phy_model = ICE_PHY_E822; ++ hw->phy_model = ICE_PHY_E82X; + } + + /** +@@ -3331,8 +3331,8 @@ static int ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + case ICE_PHY_E810: + err = ice_ptp_port_cmd_e810(hw, cmd); + break; +- case ICE_PHY_E822: +- err = ice_ptp_port_cmd_e822(hw, cmd); ++ case ICE_PHY_E82X: ++ err = ice_ptp_port_cmd_e82x(hw, cmd); + break; + default: + err = -EOPNOTSUPP; +@@ -3383,8 +3383,8 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time) + case ICE_PHY_E810: + err = ice_ptp_prep_phy_time_e810(hw, time & 0xFFFFFFFF); + break; +- case ICE_PHY_E822: +- err = ice_ptp_prep_phy_time_e822(hw, time & 0xFFFFFFFF); ++ case ICE_PHY_E82X: ++ err = ice_ptp_prep_phy_time_e82x(hw, time & 0xFFFFFFFF); + break; + default: + err = -EOPNOTSUPP; +@@ -3425,8 +3425,8 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval) + case ICE_PHY_E810: + err = ice_ptp_prep_phy_incval_e810(hw, incval); + break; +- case ICE_PHY_E822: +- err = ice_ptp_prep_phy_incval_e822(hw, incval); ++ case ICE_PHY_E82X: ++ err = ice_ptp_prep_phy_incval_e82x(hw, incval); + break; + default: + err = -EOPNOTSUPP; +@@ -3491,8 +3491,8 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj) + case ICE_PHY_E810: + err = ice_ptp_prep_phy_adj_e810(hw, adj); + break; +- case ICE_PHY_E822: +- err = ice_ptp_prep_phy_adj_e822(hw, adj); ++ case ICE_PHY_E82X: ++ err = ice_ptp_prep_phy_adj_e82x(hw, adj); + break; + default: + err = -EOPNOTSUPP; +@@ -3520,8 +3520,8 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp) + switch (hw->phy_model) { + case ICE_PHY_E810: + return ice_read_phy_tstamp_e810(hw, block, idx, tstamp); +- case ICE_PHY_E822: +- return ice_read_phy_tstamp_e822(hw, block, idx, tstamp); ++ case ICE_PHY_E82X: ++ return ice_read_phy_tstamp_e82x(hw, block, idx, tstamp); + default: + return -EOPNOTSUPP; + } +@@ -3548,8 +3548,8 @@ int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx) + switch (hw->phy_model) { + case ICE_PHY_E810: + return ice_clear_phy_tstamp_e810(hw, block, idx); +- case ICE_PHY_E822: +- return ice_clear_phy_tstamp_e822(hw, block, idx); ++ case ICE_PHY_E82X: ++ return ice_clear_phy_tstamp_e82x(hw, block, idx); + default: + return -EOPNOTSUPP; + } +@@ -3607,8 +3607,8 @@ int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx) + void ice_ptp_reset_ts_memory(struct ice_hw *hw) + { + switch (hw->phy_model) { +- case ICE_PHY_E822: +- ice_ptp_reset_ts_memory_e822(hw); ++ case ICE_PHY_E82X: ++ ice_ptp_reset_ts_memory_e82x(hw); + break; + case ICE_PHY_E810: + default: +@@ -3635,8 +3635,8 @@ int ice_ptp_init_phc(struct ice_hw *hw) + switch (hw->phy_model) { + case ICE_PHY_E810: + return ice_ptp_init_phc_e810(hw); +- case ICE_PHY_E822: +- return ice_ptp_init_phc_e822(hw); ++ case ICE_PHY_E82X: ++ return ice_ptp_init_phc_e82x(hw); + default: + return -EOPNOTSUPP; + } +@@ -3659,8 +3659,8 @@ int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready) + case ICE_PHY_E810: + return ice_get_phy_tx_tstamp_ready_e810(hw, block, + tstamp_ready); +- case ICE_PHY_E822: +- return ice_get_phy_tx_tstamp_ready_e822(hw, block, ++ case ICE_PHY_E82X: ++ return ice_get_phy_tx_tstamp_ready_e82x(hw, block, + tstamp_ready); + break; + default: +@@ -3941,7 +3941,7 @@ int ice_get_cgu_rclk_pin_info(struct ice_hw *hw, u8 *base_idx, u8 *pin_num) + case ICE_DEV_ID_E823C_QSFP: + case ICE_DEV_ID_E823C_SFP: + case ICE_DEV_ID_E823C_SGMII: +- *pin_num = ICE_E822_RCLK_PINS_NUM; ++ *pin_num = ICE_E82X_RCLK_PINS_NUM; + ret = 0; + if (hw->cgu_part_number == + ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032) +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +index 9dc30918f044..0cc285614c72 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +@@ -42,7 +42,7 @@ enum ice_ptp_fec_mode { + }; + + /** +- * struct ice_time_ref_info_e822 ++ * struct ice_time_ref_info_e82x + * @pll_freq: Frequency of PLL that drives timer ticks in Hz + * @nominal_incval: increment to generate nanoseconds in GLTSYN_TIME_L + * @pps_delay: propagation delay of the PPS output signal +@@ -50,14 +50,14 @@ enum ice_ptp_fec_mode { + * Characteristic information for the various TIME_REF sources possible in the + * E822 devices + */ +-struct ice_time_ref_info_e822 { ++struct ice_time_ref_info_e82x { + u64 pll_freq; + u64 nominal_incval; + u8 pps_delay; + }; + + /** +- * struct ice_vernier_info_e822 ++ * struct ice_vernier_info_e82x + * @tx_par_clk: Frequency used to calculate P_REG_PAR_TX_TUS + * @rx_par_clk: Frequency used to calculate P_REG_PAR_RX_TUS + * @tx_pcs_clk: Frequency used to calculate P_REG_PCS_TX_TUS +@@ -80,7 +80,7 @@ struct ice_time_ref_info_e822 { + * different link speeds, either the deskew marker for multi-lane link speeds + * or the Reed Solomon gearbox marker for RS-FEC. + */ +-struct ice_vernier_info_e822 { ++struct ice_vernier_info_e82x { + u32 tx_par_clk; + u32 rx_par_clk; + u32 tx_pcs_clk; +@@ -95,7 +95,7 @@ struct ice_vernier_info_e822 { + }; + + /** +- * struct ice_cgu_pll_params_e822 ++ * struct ice_cgu_pll_params_e82x + * @refclk_pre_div: Reference clock pre-divisor + * @feedback_div: Feedback divisor + * @frac_n_div: Fractional divisor +@@ -104,7 +104,7 @@ struct ice_vernier_info_e822 { + * Clock Generation Unit parameters used to program the PLL based on the + * selected TIME_REF frequency. + */ +-struct ice_cgu_pll_params_e822 { ++struct ice_cgu_pll_params_e82x { + u32 refclk_pre_div; + u32 feedback_div; + u32 frac_n_div; +@@ -124,7 +124,7 @@ enum ice_phy_rclk_pins { + }; + + #define ICE_E810_RCLK_PINS_NUM (ICE_RCLKB_PIN + 1) +-#define ICE_E822_RCLK_PINS_NUM (ICE_RCLKA_PIN + 1) ++#define ICE_E82X_RCLK_PINS_NUM (ICE_RCLKA_PIN + 1) + #define E810T_CGU_INPUT_C827(_phy, _pin) ((_phy) * ICE_E810_RCLK_PINS_NUM + \ + (_pin) + ZL_REF1P) + +@@ -183,16 +183,16 @@ struct ice_cgu_pin_desc { + }; + + extern const struct +-ice_cgu_pll_params_e822 e822_cgu_params[NUM_ICE_TIME_REF_FREQ]; ++ice_cgu_pll_params_e82x e822_cgu_params[NUM_ICE_TIME_REF_FREQ]; + + #define E810C_QSFP_C827_0_HANDLE 2 + #define E810C_QSFP_C827_1_HANDLE 3 + + /* Table of constants related to possible TIME_REF sources */ +-extern const struct ice_time_ref_info_e822 e822_time_ref[NUM_ICE_TIME_REF_FREQ]; ++extern const struct ice_time_ref_info_e82x e822_time_ref[NUM_ICE_TIME_REF_FREQ]; + + /* Table of constants for Vernier calibration on E822 */ +-extern const struct ice_vernier_info_e822 e822_vernier[NUM_ICE_PTP_LNK_SPD]; ++extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD]; + + /* Increment value to generate nanoseconds in the GLTSYN_TIME_L register for + * the E810 devices. Based off of a PLL with an 812.5 MHz frequency. +@@ -214,23 +214,23 @@ int ice_ptp_init_phc(struct ice_hw *hw); + int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready); + + /* E822 family functions */ +-int ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val); +-int ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val); +-void ice_ptp_reset_ts_memory_quad_e822(struct ice_hw *hw, u8 quad); ++int ice_read_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 *val); ++int ice_write_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 val); ++void ice_ptp_reset_ts_memory_quad_e82x(struct ice_hw *hw, u8 quad); + + /** +- * ice_e822_time_ref - Get the current TIME_REF from capabilities ++ * ice_e82x_time_ref - Get the current TIME_REF from capabilities + * @hw: pointer to the HW structure + * + * Returns the current TIME_REF from the capabilities structure. + */ +-static inline enum ice_time_ref_freq ice_e822_time_ref(struct ice_hw *hw) ++static inline enum ice_time_ref_freq ice_e82x_time_ref(struct ice_hw *hw) + { + return hw->func_caps.ts_func_info.time_ref; + } + + /** +- * ice_set_e822_time_ref - Set new TIME_REF ++ * ice_set_e82x_time_ref - Set new TIME_REF + * @hw: pointer to the HW structure + * @time_ref: new TIME_REF to set + * +@@ -238,31 +238,31 @@ static inline enum ice_time_ref_freq ice_e822_time_ref(struct ice_hw *hw) + * change, such as an update to the CGU registers. + */ + static inline void +-ice_set_e822_time_ref(struct ice_hw *hw, enum ice_time_ref_freq time_ref) ++ice_set_e82x_time_ref(struct ice_hw *hw, enum ice_time_ref_freq time_ref) + { + hw->func_caps.ts_func_info.time_ref = time_ref; + } + +-static inline u64 ice_e822_pll_freq(enum ice_time_ref_freq time_ref) ++static inline u64 ice_e82x_pll_freq(enum ice_time_ref_freq time_ref) + { + return e822_time_ref[time_ref].pll_freq; + } + +-static inline u64 ice_e822_nominal_incval(enum ice_time_ref_freq time_ref) ++static inline u64 ice_e82x_nominal_incval(enum ice_time_ref_freq time_ref) + { + return e822_time_ref[time_ref].nominal_incval; + } + +-static inline u64 ice_e822_pps_delay(enum ice_time_ref_freq time_ref) ++static inline u64 ice_e82x_pps_delay(enum ice_time_ref_freq time_ref) + { + return e822_time_ref[time_ref].pps_delay; + } + + /* E822 Vernier calibration functions */ +-int ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset); +-int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port); +-int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port); +-int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port); ++int ice_stop_phy_timer_e82x(struct ice_hw *hw, u8 port, bool soft_reset); ++int ice_start_phy_timer_e82x(struct ice_hw *hw, u8 port); ++int ice_phy_cfg_tx_offset_e82x(struct ice_hw *hw, u8 port); ++int ice_phy_cfg_rx_offset_e82x(struct ice_hw *hw, u8 port); + + /* E810 family functions */ + int ice_ptp_init_phy_e810(struct ice_hw *hw); +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index bb5d8b681bc2..f8b658386552 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -826,7 +826,7 @@ struct ice_mbx_data { + enum ice_phy_model { + ICE_PHY_UNSUP = -1, + ICE_PHY_E810 = 1, +- ICE_PHY_E822, ++ ICE_PHY_E82X, + }; + + /* Port hardware description */ +@@ -909,10 +909,9 @@ struct ice_hw { + /* INTRL granularity in 1 us */ + u8 intrl_gran; + +-#define ICE_PHY_PER_NAC_E822 1 + #define ICE_MAX_QUAD 2 +-#define ICE_QUADS_PER_PHY_E822 2 +-#define ICE_PORTS_PER_PHY_E822 8 ++#define ICE_QUADS_PER_PHY_E82X 2 ++#define ICE_PORTS_PER_PHY_E82X 8 + #define ICE_PORTS_PER_QUAD 4 + #define ICE_PORTS_PER_PHY_E810 4 + #define ICE_NUM_EXTERNAL_PORTS (ICE_MAX_QUAD * ICE_PORTS_PER_QUAD) +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0012-ice-Schedule-service-task-in-IRQ-top-half.patch b/kernel-rt/debian/patches/ice-VDF/0012-ice-Schedule-service-task-in-IRQ-top-half.patch new file mode 100644 index 00000000..9b6a7417 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0012-ice-Schedule-service-task-in-IRQ-top-half.patch @@ -0,0 +1,104 @@ +From 3b37119a08ffe4be182ade746a6b1fe3bcf65921 Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 29 Nov 2023 13:40:22 +0100 +Subject: [PATCH 12/36] ice: Schedule service task in IRQ top half + +Schedule service task and EXTTS in the top half to avoid bottom half +scheduling if possible, which significantly reduces timestamping delay. + +Co-developed-by: Michal Michalik +Signed-off-by: Michal Michalik +Reviewed-by: Przemek Kitszel +Signed-off-by: Karol Kolacinski +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 00d50001444ef5c75c8ab476a6674708f3ff613b) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 1 - + drivers/net/ethernet/intel/ice/ice_main.c | 20 +++++++++++--------- + 2 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 54a98c4032b7..efe78d5e4da1 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -517,7 +517,6 @@ enum ice_pf_flags { + }; + + enum ice_misc_thread_tasks { +- ICE_MISC_THREAD_EXTTS_EVENT, + ICE_MISC_THREAD_TX_TSTAMP, + ICE_MISC_THREAD_NBITS /* must be last */ + }; +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index d2f3b4374d14..2acaa17a12bf 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3109,6 +3109,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf) + static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + { + struct ice_pf *pf = (struct ice_pf *)data; ++ irqreturn_t ret = IRQ_HANDLED; + struct ice_hw *hw = &pf->hw; + struct device *dev; + u32 oicr, ena_mask; +@@ -3190,8 +3191,10 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + if (oicr & PFINT_OICR_TSYN_TX_M) { + ena_mask &= ~PFINT_OICR_TSYN_TX_M; +- if (ice_ptp_pf_handles_tx_interrupt(pf)) ++ if (ice_ptp_pf_handles_tx_interrupt(pf)) { + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); ++ ret = IRQ_WAKE_THREAD; ++ } + } + + if (oicr & PFINT_OICR_TSYN_EVNT_M) { +@@ -3207,7 +3210,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + GLTSYN_STAT_EVENT1_M | + GLTSYN_STAT_EVENT2_M); + +- set_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread); ++ ice_ptp_extts_event(pf); + } + } + +@@ -3230,8 +3233,11 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + set_bit(ICE_PFR_REQ, pf->state); + } + } ++ ice_service_task_schedule(pf); ++ if (ret == IRQ_HANDLED) ++ ice_irq_dynamic_ena(hw, NULL, NULL); + +- return IRQ_WAKE_THREAD; ++ return ret; + } + + /** +@@ -3247,12 +3253,7 @@ static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) + hw = &pf->hw; + + if (ice_is_reset_in_progress(pf->state)) +- return IRQ_HANDLED; +- +- ice_service_task_schedule(pf); +- +- if (test_and_clear_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread)) +- ice_ptp_extts_event(pf); ++ goto skip_irq; + + if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) { + /* Process outstanding Tx timestamps. If there is more work, +@@ -3264,6 +3265,7 @@ static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) + } + } + ++skip_irq: + ice_irq_dynamic_ena(hw, NULL, NULL); + + return IRQ_HANDLED; +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0013-ice-Enable-SW-interrupt-from-FW-for-LL-TS.patch b/kernel-rt/debian/patches/ice-VDF/0013-ice-Enable-SW-interrupt-from-FW-for-LL-TS.patch new file mode 100644 index 00000000..639642f0 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0013-ice-Enable-SW-interrupt-from-FW-for-LL-TS.patch @@ -0,0 +1,660 @@ +From c4ab92eb3ee89178a012702f2a98477d683fad31 Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 29 Nov 2023 13:40:23 +0100 +Subject: [PATCH 13/36] ice: Enable SW interrupt from FW for LL TS + +Introduce new capability - Low Latency Timestamping with Interrupt. +On supported devices, driver can request a single timestamp from FW +without polling the register afterwards. Instead, FW can issue +a dedicated interrupt when the timestamp was read from the PHY register +and its value is available to read from the register. +This eliminates the need of bottom half scheduling, which results in +minimal delay for timestamping. + +For this mode, allocate TS indices sequentially, so that timestamps are +always completed in FIFO manner. + +Co-developed-by: Yochai Hagvi +Signed-off-by: Yochai Hagvi +Reviewed-by: Przemek Kitszel +Signed-off-by: Karol Kolacinski +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 82e71b226e0ef770d7bc143701c8b4960b4eb3d5) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 2 + + drivers/net/ethernet/intel/ice/ice_common.c | 3 + + .../net/ethernet/intel/ice/ice_hw_autogen.h | 2 + + drivers/net/ethernet/intel/ice/ice_main.c | 120 +++++++++++-- + drivers/net/ethernet/intel/ice/ice_ptp.c | 163 ++++++++++++++++-- + drivers/net/ethernet/intel/ice/ice_ptp.h | 9 + + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 1 + + drivers/net/ethernet/intel/ice/ice_type.h | 2 + + 8 files changed, 274 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index efe78d5e4da1..ee42a504c2f4 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -594,6 +594,7 @@ struct ice_pf { + u32 hw_csum_rx_error; + u32 oicr_err_reg; + struct msi_map oicr_irq; /* Other interrupt cause MSIX vector */ ++ struct msi_map ll_ts_irq; /* LL_TS interrupt MSIX vector */ + u16 max_pf_txqs; /* Total Tx queues PF wide */ + u16 max_pf_rxqs; /* Total Rx queues PF wide */ + u16 num_lan_msix; /* Total MSIX vectors for base driver */ +@@ -618,6 +619,7 @@ struct ice_pf { + unsigned long tx_timeout_last_recovery; + u32 tx_timeout_recovery_level; + char int_name[ICE_INT_NAME_STR_LEN]; ++ char int_name_ll_ts[ICE_INT_NAME_STR_LEN]; + struct auxiliary_device *adev; + int aux_idx; + u32 sw_int_count; +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 7674267a2d90..acf6ac00f804 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -2624,6 +2624,7 @@ ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, + info->tmr1_ena = ((number & ICE_TS_TMR1_ENA_M) != 0); + + info->ts_ll_read = ((number & ICE_TS_LL_TX_TS_READ_M) != 0); ++ info->ts_ll_int_read = ((number & ICE_TS_LL_TX_TS_INT_READ_M) != 0); + + info->ena_ports = logical_id; + info->tmr_own_map = phys_id; +@@ -2644,6 +2645,8 @@ ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, + info->tmr1_ena); + ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_read = %u\n", + info->ts_ll_read); ++ ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_int_read = %u\n", ++ info->ts_ll_int_read); + ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 ena_ports = %u\n", + info->ena_ports); + ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr_own_map = %u\n", +diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +index 6756f3d51d14..fa730bca7f15 100644 +--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h ++++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +@@ -200,6 +200,8 @@ + #define GLINT_VECT2FUNC_PF_NUM_M ICE_M(0x7, 12) + #define GLINT_VECT2FUNC_IS_PF_S 16 + #define GLINT_VECT2FUNC_IS_PF_M BIT(16) ++#define PFINT_ALLOC 0x001D2600 ++#define PFINT_ALLOC_FIRST ICE_M(0x7FF, 0) + #define PFINT_FW_CTL 0x0016C800 + #define PFINT_FW_CTL_MSIX_INDX_M ICE_M(0x7FF, 0) + #define PFINT_FW_CTL_ITR_INDX_S 11 +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 2acaa17a12bf..9163a72368b3 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3071,6 +3071,7 @@ static int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp) + static void ice_ena_misc_vector(struct ice_pf *pf) + { + struct ice_hw *hw = &pf->hw; ++ u32 pf_intr_start_offset; + u32 val; + + /* Disable anti-spoof detection interrupt to prevent spurious event +@@ -3099,6 +3100,47 @@ static void ice_ena_misc_vector(struct ice_pf *pf) + /* SW_ITR_IDX = 0, but don't change INTENA */ + wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index), + GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); ++ ++ if (!pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) ++ return; ++ pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST; ++ wr32(hw, GLINT_DYN_CTL(pf->ll_ts_irq.index + pf_intr_start_offset), ++ GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); ++} ++ ++/** ++ * ice_ll_ts_intr - ll_ts interrupt handler ++ * @irq: interrupt number ++ * @data: pointer to a q_vector ++ */ ++static irqreturn_t ice_ll_ts_intr(int __always_unused irq, void *data) ++{ ++ struct ice_pf *pf = data; ++ u32 pf_intr_start_offset; ++ struct ice_ptp_tx *tx; ++ unsigned long flags; ++ struct ice_hw *hw; ++ u32 val; ++ u8 idx; ++ ++ hw = &pf->hw; ++ tx = &pf->ptp.port.tx; ++ spin_lock_irqsave(&tx->lock, flags); ++ ice_ptp_complete_tx_single_tstamp(tx); ++ ++ idx = find_next_bit_wrap(tx->in_use, tx->len, ++ tx->last_ll_ts_idx_read + 1); ++ if (idx != tx->len) ++ ice_ptp_req_tx_single_tstamp(tx, idx); ++ spin_unlock_irqrestore(&tx->lock, flags); ++ ++ val = GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M | ++ (ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S); ++ pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST; ++ wr32(hw, GLINT_DYN_CTL(pf->ll_ts_irq.index + pf_intr_start_offset), ++ val); ++ ++ return IRQ_HANDLED; + } + + /** +@@ -3191,7 +3233,19 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + if (oicr & PFINT_OICR_TSYN_TX_M) { + ena_mask &= ~PFINT_OICR_TSYN_TX_M; +- if (ice_ptp_pf_handles_tx_interrupt(pf)) { ++ if (ice_pf_state_is_nominal(pf) && ++ pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) { ++ struct ice_ptp_tx *tx = &pf->ptp.port.tx; ++ unsigned long flags; ++ u8 idx; ++ ++ spin_lock_irqsave(&tx->lock, flags); ++ idx = find_next_bit_wrap(tx->in_use, tx->len, ++ tx->last_ll_ts_idx_read + 1); ++ if (idx != tx->len) ++ ice_ptp_req_tx_single_tstamp(tx, idx); ++ spin_unlock_irqrestore(&tx->lock, flags); ++ } else if (ice_ptp_pf_handles_tx_interrupt(pf)) { + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); + ret = IRQ_WAKE_THREAD; + } +@@ -3295,6 +3349,20 @@ static void ice_dis_ctrlq_interrupts(struct ice_hw *hw) + ice_flush(hw); + } + ++/** ++ * ice_free_irq_msix_ll_ts- Unroll ll_ts vector setup ++ * @pf: board private structure ++ */ ++static void ice_free_irq_msix_ll_ts(struct ice_pf *pf) ++{ ++ int irq_num = pf->ll_ts_irq.virq; ++ ++ synchronize_irq(irq_num); ++ devm_free_irq(ice_pf_to_dev(pf), irq_num, pf); ++ ++ ice_free_irq(pf, pf->ll_ts_irq); ++} ++ + /** + * ice_free_irq_msix_misc - Unroll misc vector setup + * @pf: board private structure +@@ -3314,6 +3382,8 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf) + devm_free_irq(ice_pf_to_dev(pf), misc_irq_num, pf); + + ice_free_irq(pf, pf->oicr_irq); ++ if (pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) ++ ice_free_irq_msix_ll_ts(pf); + } + + /** +@@ -3339,10 +3409,12 @@ static void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 reg_idx) + PFINT_MBX_CTL_CAUSE_ENA_M); + wr32(hw, PFINT_MBX_CTL, val); + +- /* This enables Sideband queue Interrupt causes */ +- val = ((reg_idx & PFINT_SB_CTL_MSIX_INDX_M) | +- PFINT_SB_CTL_CAUSE_ENA_M); +- wr32(hw, PFINT_SB_CTL, val); ++ if (!hw->dev_caps.ts_dev_info.ts_ll_int_read) { ++ /* enable Sideband queue Interrupt causes */ ++ val = ((reg_idx & PFINT_SB_CTL_MSIX_INDX_M) | ++ PFINT_SB_CTL_CAUSE_ENA_M); ++ wr32(hw, PFINT_SB_CTL, val); ++ } + + ice_flush(hw); + } +@@ -3359,13 +3431,17 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) + { + struct device *dev = ice_pf_to_dev(pf); + struct ice_hw *hw = &pf->hw; +- struct msi_map oicr_irq; ++ u32 pf_intr_start_offset; ++ struct msi_map irq; + int err = 0; + + if (!pf->int_name[0]) + snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", + dev_driver_string(dev), dev_name(dev)); + ++ if (!pf->int_name_ll_ts[0]) ++ snprintf(pf->int_name_ll_ts, sizeof(pf->int_name_ll_ts) - 1, ++ "%s-%s:ll_ts", dev_driver_string(dev), dev_name(dev)); + /* Do not request IRQ but do enable OICR interrupt since settings are + * lost during reset. Note that this function is called only during + * rebuild path and not while reset is in progress. +@@ -3374,11 +3450,11 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) + goto skip_req_irq; + + /* reserve one vector in irq_tracker for misc interrupts */ +- oicr_irq = ice_alloc_irq(pf, false); +- if (oicr_irq.index < 0) +- return oicr_irq.index; ++ irq = ice_alloc_irq(pf, false); ++ if (irq.index < 0) ++ return irq.index; + +- pf->oicr_irq = oicr_irq; ++ pf->oicr_irq = irq; + err = devm_request_threaded_irq(dev, pf->oicr_irq.virq, ice_misc_intr, + ice_misc_intr_thread_fn, 0, + pf->int_name, pf); +@@ -3389,10 +3465,34 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) + return err; + } + ++ /* reserve one vector in irq_tracker for ll_ts interrupt */ ++ if (!pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) ++ goto skip_req_irq; ++ ++ irq = ice_alloc_irq(pf, false); ++ if (irq.index < 0) ++ return irq.index; ++ ++ pf->ll_ts_irq = irq; ++ err = devm_request_irq(dev, pf->ll_ts_irq.virq, ice_ll_ts_intr, 0, ++ pf->int_name_ll_ts, pf); ++ if (err) { ++ dev_err(dev, "devm_request_irq for %s failed: %d\n", ++ pf->int_name_ll_ts, err); ++ ice_free_irq(pf, pf->ll_ts_irq); ++ return err; ++ } ++ + skip_req_irq: + ice_ena_misc_vector(pf); + + ice_ena_ctrlq_interrupts(hw, pf->oicr_irq.index); ++ /* This enables LL TS interrupt */ ++ pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST; ++ if (pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) ++ wr32(hw, PFINT_SB_CTL, ++ ((pf->ll_ts_irq.index + pf_intr_start_offset) & ++ PFINT_SB_CTL_MSIX_INDX_M) | PFINT_SB_CTL_CAUSE_ENA_M); + wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_irq.index), + ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 2e6e1fc84d11..75038d826f71 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -634,6 +634,119 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) + return tx->init && !tx->calibrating; + } + ++/** ++ * ice_ptp_req_tx_single_tstamp - Request Tx timestamp for a port from FW ++ * @tx: the PTP Tx timestamp tracker ++ * @idx: index of the timestamp to request ++ */ ++void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx) ++{ ++ struct ice_ptp_port *ptp_port; ++ struct sk_buff *skb; ++ struct ice_pf *pf; ++ ++ if (!tx->init) ++ return; ++ ++ ptp_port = container_of(tx, struct ice_ptp_port, tx); ++ pf = ptp_port_to_pf(ptp_port); ++ ++ /* Drop packets which have waited for more than 2 seconds */ ++ if (time_is_before_jiffies(tx->tstamps[idx].start + 2 * HZ)) { ++ /* Count the number of Tx timestamps that timed out */ ++ pf->ptp.tx_hwtstamp_timeouts++; ++ ++ skb = tx->tstamps[idx].skb; ++ tx->tstamps[idx].skb = NULL; ++ clear_bit(idx, tx->in_use); ++ ++ dev_kfree_skb_any(skb); ++ return; ++ } ++ ++ ice_trace(tx_tstamp_fw_req, tx->tstamps[idx].skb, idx); ++ ++ /* Write TS index to read to the PF register so the FW can read it */ ++ wr32(&pf->hw, PF_SB_ATQBAL, ++ TS_LL_READ_TS_INTR | FIELD_PREP(TS_LL_READ_TS_IDX, idx) | ++ TS_LL_READ_TS); ++ tx->last_ll_ts_idx_read = idx; ++} ++ ++/** ++ * ice_ptp_complete_tx_single_tstamp - Complete Tx timestamp for a port ++ * @tx: the PTP Tx timestamp tracker ++ */ ++void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) ++{ ++ struct skb_shared_hwtstamps shhwtstamps = {}; ++ u8 idx = tx->last_ll_ts_idx_read; ++ struct ice_ptp_port *ptp_port; ++ u64 raw_tstamp, tstamp; ++ bool drop_ts = false; ++ struct sk_buff *skb; ++ struct ice_pf *pf; ++ u32 val; ++ ++ if (!tx->init || tx->last_ll_ts_idx_read < 0) ++ return; ++ ++ ptp_port = container_of(tx, struct ice_ptp_port, tx); ++ pf = ptp_port_to_pf(ptp_port); ++ ++ ice_trace(tx_tstamp_fw_done, tx->tstamps[idx].skb, idx); ++ ++ val = rd32(&pf->hw, PF_SB_ATQBAL); ++ ++ /* When the bit is cleared, the TS is ready in the register */ ++ if (val & TS_LL_READ_TS) { ++ dev_err(ice_pf_to_dev(pf), "Failed to get the Tx tstamp - FW not ready"); ++ return; ++ } ++ ++ /* High 8 bit value of the TS is on the bits 16:23 */ ++ raw_tstamp = FIELD_GET(TS_LL_READ_TS_HIGH, val); ++ raw_tstamp <<= 32; ++ ++ /* Read the low 32 bit value */ ++ raw_tstamp |= (u64)rd32(&pf->hw, PF_SB_ATQBAH); ++ ++ /* For PHYs which don't implement a proper timestamp ready bitmap, ++ * verify that the timestamp value is different from the last cached ++ * timestamp. If it is not, skip this for now assuming it hasn't yet ++ * been captured by hardware. ++ */ ++ if (!drop_ts && tx->verify_cached && ++ raw_tstamp == tx->tstamps[idx].cached_tstamp) ++ return; ++ ++ if (tx->verify_cached && raw_tstamp) ++ tx->tstamps[idx].cached_tstamp = raw_tstamp; ++ clear_bit(idx, tx->in_use); ++ skb = tx->tstamps[idx].skb; ++ tx->tstamps[idx].skb = NULL; ++ if (test_and_clear_bit(idx, tx->stale)) ++ drop_ts = true; ++ ++ if (!skb) ++ return; ++ ++ if (drop_ts) { ++ dev_kfree_skb_any(skb); ++ return; ++ } ++ ++ /* Extend the timestamp using cached PHC time */ ++ tstamp = ice_ptp_extend_40b_ts(pf, raw_tstamp); ++ if (tstamp) { ++ shhwtstamps.hwtstamp = ns_to_ktime(tstamp); ++ ice_trace(tx_tstamp_complete, skb, idx); ++ } ++ ++ skb_tstamp_tx(skb, &shhwtstamps); ++ dev_kfree_skb_any(skb); ++} ++ + /** + * ice_ptp_process_tx_tstamp - Process Tx timestamps for a port + * @tx: the PTP Tx timestamp tracker +@@ -685,6 +798,7 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) + static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + { + struct ice_ptp_port *ptp_port; ++ unsigned long flags; + struct ice_pf *pf; + struct ice_hw *hw; + u64 tstamp_ready; +@@ -756,7 +870,7 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + drop_ts = true; + + skip_ts_read: +- spin_lock(&tx->lock); ++ spin_lock_irqsave(&tx->lock, flags); + if (tx->verify_cached && raw_tstamp) + tx->tstamps[idx].cached_tstamp = raw_tstamp; + clear_bit(idx, tx->in_use); +@@ -764,7 +878,7 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + tx->tstamps[idx].skb = NULL; + if (test_and_clear_bit(idx, tx->stale)) + drop_ts = true; +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + /* It is unlikely but possible that the SKB will have been + * flushed at this point due to link change or teardown. +@@ -834,6 +948,7 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) + static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) + { + bool more_timestamps; ++ unsigned long flags; + + if (!tx->init) + return ICE_TX_TSTAMP_WORK_DONE; +@@ -842,9 +957,9 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) + ice_ptp_process_tx_tstamp(tx); + + /* Check if there are outstanding Tx timestamps */ +- spin_lock(&tx->lock); ++ spin_lock_irqsave(&tx->lock, flags); + more_timestamps = tx->init && !bitmap_empty(tx->in_use, tx->len); +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + if (more_timestamps) + return ICE_TX_TSTAMP_WORK_PENDING; +@@ -881,6 +996,7 @@ ice_ptp_alloc_tx_tracker(struct ice_ptp_tx *tx) + tx->in_use = in_use; + tx->stale = stale; + tx->init = 1; ++ tx->last_ll_ts_idx_read = -1; + + spin_lock_init(&tx->lock); + +@@ -898,6 +1014,7 @@ static void + ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + { + struct ice_hw *hw = &pf->hw; ++ unsigned long flags; + u64 tstamp_ready; + int err; + u8 idx; +@@ -921,12 +1038,12 @@ ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + if (!hw->reset_ongoing && (tstamp_ready & BIT_ULL(phy_idx))) + ice_clear_phy_tstamp(hw, tx->block, phy_idx); + +- spin_lock(&tx->lock); ++ spin_lock_irqsave(&tx->lock, flags); + skb = tx->tstamps[idx].skb; + tx->tstamps[idx].skb = NULL; + clear_bit(idx, tx->in_use); + clear_bit(idx, tx->stale); +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + /* Count the number of Tx timestamps flushed */ + pf->ptp.tx_hwtstamp_flushed++; +@@ -950,9 +1067,11 @@ ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + static void + ice_ptp_mark_tx_tracker_stale(struct ice_ptp_tx *tx) + { +- spin_lock(&tx->lock); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tx->lock, flags); + bitmap_or(tx->stale, tx->stale, tx->in_use, tx->len); +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + } + + /** +@@ -965,9 +1084,11 @@ ice_ptp_mark_tx_tracker_stale(struct ice_ptp_tx *tx) + static void + ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + { +- spin_lock(&tx->lock); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tx->lock, flags); + tx->init = 0; +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + /* wait for potentially outstanding interrupt to complete */ + synchronize_irq(pf->oicr_irq.virq); +@@ -1367,6 +1488,7 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port) + struct ice_pf *pf = ptp_port_to_pf(ptp_port); + u8 port = ptp_port->port_num; + struct ice_hw *hw = &pf->hw; ++ unsigned long flags; + int err; + + if (ice_is_e810(hw)) +@@ -1380,9 +1502,9 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port) + kthread_cancel_delayed_work_sync(&ptp_port->ov_work); + + /* temporarily disable Tx timestamps while calibrating PHY offset */ +- spin_lock(&ptp_port->tx.lock); ++ spin_lock_irqsave(&ptp_port->tx.lock, flags); + ptp_port->tx.calibrating = true; +- spin_unlock(&ptp_port->tx.lock); ++ spin_unlock_irqrestore(&ptp_port->tx.lock, flags); + ptp_port->tx_fifo_busy_cnt = 0; + + /* Start the PHY timer in Vernier mode */ +@@ -1391,9 +1513,9 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port) + goto out_unlock; + + /* Enable Tx timestamps right away */ +- spin_lock(&ptp_port->tx.lock); ++ spin_lock_irqsave(&ptp_port->tx.lock, flags); + ptp_port->tx.calibrating = false; +- spin_unlock(&ptp_port->tx.lock); ++ spin_unlock_irqrestore(&ptp_port->tx.lock, flags); + + kthread_queue_delayed_work(pf->ptp.kworker, &ptp_port->ov_work, 0); + +@@ -2471,18 +2593,23 @@ static long ice_ptp_create_clock(struct ice_pf *pf) + */ + s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) + { ++ unsigned long flags; + u8 idx; + +- spin_lock(&tx->lock); ++ spin_lock_irqsave(&tx->lock, flags); + + /* Check that this tracker is accepting new timestamp requests */ + if (!ice_ptp_is_tx_tracker_up(tx)) { +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + return -1; + } + + /* Find and set the first available index */ +- idx = find_first_zero_bit(tx->in_use, tx->len); ++ idx = find_next_zero_bit(tx->in_use, tx->len, ++ tx->last_ll_ts_idx_read + 1); ++ if (idx == tx->len) ++ idx = find_first_zero_bit(tx->in_use, tx->len); ++ + if (idx < tx->len) { + /* We got a valid index that no other thread could have set. Store + * a reference to the skb and the start time to allow discarding old +@@ -2496,7 +2623,7 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) + ice_trace(tx_tstamp_request, skb, idx); + } + +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + /* return the appropriate PHY timestamp register index, -1 if no + * indexes were available. +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index a3ae008a3539..64679d3d2c49 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -131,6 +131,7 @@ enum ice_tx_tstamp_work { + * @calibrating: if true, the PHY is calibrating the Tx offset. During this + * window, timestamps are temporarily disabled. + * @verify_cached: if true, verify new timestamp differs from last read value ++ * @last_ll_ts_idx_read: index of the last LL TS read by the FW + */ + struct ice_ptp_tx { + spinlock_t lock; /* lock protecting in_use bitmap */ +@@ -143,6 +144,7 @@ struct ice_ptp_tx { + u8 init : 1; + u8 calibrating : 1; + u8 verify_cached : 1; ++ s8 last_ll_ts_idx_read; + }; + + /* Quad and port information for initializing timestamp blocks */ +@@ -296,6 +298,8 @@ int ice_get_ptp_clock_index(struct ice_pf *pf); + + void ice_ptp_extts_event(struct ice_pf *pf); + s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb); ++void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx); ++void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx); + enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf); + + void +@@ -330,6 +334,11 @@ ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) + return -1; + } + ++static inline void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx) ++{ } ++ ++static inline void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) { } ++ + static inline bool ice_ptp_process_ts(struct ice_pf *pf) + { + return true; +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +index 0cc285614c72..7e8fd369ef7c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +@@ -509,6 +509,7 @@ int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id, + #define TS_LL_READ_RETRIES 200 + #define TS_LL_READ_TS_HIGH GENMASK(23, 16) + #define TS_LL_READ_TS_IDX GENMASK(29, 24) ++#define TS_LL_READ_TS_INTR BIT(30) + #define TS_LL_READ_TS BIT(31) + + /* Internal PHY timestamp address */ +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index f8b658386552..b0f1f4db1d8b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -350,6 +350,7 @@ struct ice_ts_func_info { + #define ICE_TS_TMR0_ENA_M BIT(25) + #define ICE_TS_TMR1_ENA_M BIT(26) + #define ICE_TS_LL_TX_TS_READ_M BIT(28) ++#define ICE_TS_LL_TX_TS_INT_READ_M BIT(29) + + struct ice_ts_dev_info { + /* Device specific info */ +@@ -363,6 +364,7 @@ struct ice_ts_dev_info { + u8 tmr0_ena; + u8 tmr1_ena; + u8 ts_ll_read; ++ u8 ts_ll_int_read; + }; + + /* Function specific capabilities */ +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0014-ice-PTP-add-clock-domain-number-to-auxiliary-interfa.patch b/kernel-rt/debian/patches/ice-VDF/0014-ice-PTP-add-clock-domain-number-to-auxiliary-interfa.patch new file mode 100644 index 00000000..c8c26134 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0014-ice-PTP-add-clock-domain-number-to-auxiliary-interfa.patch @@ -0,0 +1,310 @@ +From f267daca86600496d536f85c4d1945558b982427 Mon Sep 17 00:00:00 2001 +From: Michal Michalik +Date: Thu, 27 Jul 2023 15:50:36 +0200 +Subject: [PATCH 14/36] ice: PTP: add clock domain number to auxiliary + interface + +The PHC clock id used to be moved between PFs using FW admin queue +shared parameters - move the implementation to auxiliary bus. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Jacob Keller +Signed-off-by: Michal Michalik +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit fcd2c1e3139a27766ef263bd2011195dbc8a79f5) +Signed-off-by: Jiping Ma +--- + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 5 - + drivers/net/ethernet/intel/ice/ice_ethtool.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 163 +++--------------- + drivers/net/ethernet/intel/ice/ice_ptp.h | 11 +- + 4 files changed, 34 insertions(+), 147 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 353ac55bdb9d..9bacb69ead8c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2360,11 +2360,6 @@ struct ice_aqc_driver_shared_params { + }; + + enum ice_aqc_driver_params { +- /* OS clock index for PTP timer Domain 0 */ +- ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0 = 0, +- /* OS clock index for PTP timer Domain 1 */ +- ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1, +- + /* Add new parameters above */ + ICE_AQC_DRIVER_PARAM_MAX = 16, + }; +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 456cf4785c74..057453d589d5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -3286,7 +3286,7 @@ ice_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + +- info->phc_index = ice_get_ptp_clock_index(pf); ++ info->phc_index = ice_ptp_clock_index(pf); + + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 75038d826f71..a2d0da7dfe83 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -345,131 +345,6 @@ void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) + ice_set_rx_tstamp(pf, ena); + } + +-/** +- * ice_get_ptp_clock_index - Get the PTP clock index +- * @pf: the PF pointer +- * +- * Determine the clock index of the PTP clock associated with this device. If +- * this is the PF controlling the clock, just use the local access to the +- * clock device pointer. +- * +- * Otherwise, read from the driver shared parameters to determine the clock +- * index value. +- * +- * Returns: the index of the PTP clock associated with this device, or -1 if +- * there is no associated clock. +- */ +-int ice_get_ptp_clock_index(struct ice_pf *pf) +-{ +- struct device *dev = ice_pf_to_dev(pf); +- enum ice_aqc_driver_params param_idx; +- struct ice_hw *hw = &pf->hw; +- u8 tmr_idx; +- u32 value; +- int err; +- +- /* Use the ptp_clock structure if we're the main PF */ +- if (pf->ptp.clock) +- return ptp_clock_index(pf->ptp.clock); +- +- tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc; +- if (!tmr_idx) +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0; +- else +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1; +- +- err = ice_aq_get_driver_param(hw, param_idx, &value, NULL); +- if (err) { +- dev_err(dev, "Failed to read PTP clock index parameter, err %d aq_err %s\n", +- err, ice_aq_str(hw->adminq.sq_last_status)); +- return -1; +- } +- +- /* The PTP clock index is an integer, and will be between 0 and +- * INT_MAX. The highest bit of the driver shared parameter is used to +- * indicate whether or not the currently stored clock index is valid. +- */ +- if (!(value & PTP_SHARED_CLK_IDX_VALID)) +- return -1; +- +- return value & ~PTP_SHARED_CLK_IDX_VALID; +-} +- +-/** +- * ice_set_ptp_clock_index - Set the PTP clock index +- * @pf: the PF pointer +- * +- * Set the PTP clock index for this device into the shared driver parameters, +- * so that other PFs associated with this device can read it. +- * +- * If the PF is unable to store the clock index, it will log an error, but +- * will continue operating PTP. +- */ +-static void ice_set_ptp_clock_index(struct ice_pf *pf) +-{ +- struct device *dev = ice_pf_to_dev(pf); +- enum ice_aqc_driver_params param_idx; +- struct ice_hw *hw = &pf->hw; +- u8 tmr_idx; +- u32 value; +- int err; +- +- if (!pf->ptp.clock) +- return; +- +- tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc; +- if (!tmr_idx) +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0; +- else +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1; +- +- value = (u32)ptp_clock_index(pf->ptp.clock); +- if (value > INT_MAX) { +- dev_err(dev, "PTP Clock index is too large to store\n"); +- return; +- } +- value |= PTP_SHARED_CLK_IDX_VALID; +- +- err = ice_aq_set_driver_param(hw, param_idx, value, NULL); +- if (err) { +- dev_err(dev, "Failed to set PTP clock index parameter, err %d aq_err %s\n", +- err, ice_aq_str(hw->adminq.sq_last_status)); +- } +-} +- +-/** +- * ice_clear_ptp_clock_index - Clear the PTP clock index +- * @pf: the PF pointer +- * +- * Clear the PTP clock index for this device. Must be called when +- * unregistering the PTP clock, in order to ensure other PFs stop reporting +- * a clock object that no longer exists. +- */ +-static void ice_clear_ptp_clock_index(struct ice_pf *pf) +-{ +- struct device *dev = ice_pf_to_dev(pf); +- enum ice_aqc_driver_params param_idx; +- struct ice_hw *hw = &pf->hw; +- u8 tmr_idx; +- int err; +- +- /* Do not clear the index if we don't own the timer */ +- if (!ice_pf_src_tmr_owned(pf)) +- return; +- +- tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc; +- if (!tmr_idx) +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0; +- else +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1; +- +- err = ice_aq_set_driver_param(hw, param_idx, 0, NULL); +- if (err) { +- dev_dbg(dev, "Failed to clear PTP clock index parameter, err %d aq_err %s\n", +- err, ice_aq_str(hw->adminq.sq_last_status)); +- } +-} +- + /** + * ice_ptp_read_src_clk_reg - Read the source clock register + * @pf: Board private structure +@@ -2564,7 +2439,6 @@ static void ice_ptp_set_caps(struct ice_pf *pf) + static long ice_ptp_create_clock(struct ice_pf *pf) + { + struct ptp_clock_info *info; +- struct ptp_clock *clock; + struct device *dev; + + /* No need to create a clock device if we already have one */ +@@ -2577,11 +2451,11 @@ static long ice_ptp_create_clock(struct ice_pf *pf) + dev = ice_pf_to_dev(pf); + + /* Attempt to register the clock before enabling the hardware. */ +- clock = ptp_clock_register(info, dev); +- if (IS_ERR(clock)) +- return PTR_ERR(clock); +- +- pf->ptp.clock = clock; ++ pf->ptp.clock = ptp_clock_register(info, dev); ++ if (IS_ERR(pf->ptp.clock)) { ++ dev_err(ice_pf_to_dev(pf), "Failed to register PTP clock device"); ++ return PTR_ERR(pf->ptp.clock); ++ } + + return 0; + } +@@ -2996,6 +2870,28 @@ static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf) + mutex_destroy(&pf->ptp.ports_owner.lock); + } + ++/** ++ * ice_ptp_clock_index - Get the PTP clock index for this device ++ * @pf: Board private structure ++ * ++ * Returns: the PTP clock index associated with this PF, or -1 if no PTP clock ++ * is associated. ++ */ ++int ice_ptp_clock_index(struct ice_pf *pf) ++{ ++ struct auxiliary_device *aux_dev; ++ struct ice_pf *owner_pf; ++ struct ptp_clock *clock; ++ ++ aux_dev = &pf->ptp.port.aux_dev; ++ owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev); ++ if (!owner_pf) ++ return -1; ++ clock = owner_pf->ptp.clock; ++ ++ return clock ? ptp_clock_index(clock) : -1; ++} ++ + /** + * ice_ptp_prepare_for_reset - Prepare PTP for reset + * @pf: Board private structure +@@ -3086,9 +2982,6 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + if (err) + goto err_clk; + +- /* Store the PTP clock index for other PFs */ +- ice_set_ptp_clock_index(pf); +- + err = ice_ptp_register_auxbus_driver(pf); + if (err) { + dev_err(ice_pf_to_dev(pf), "Failed to register PTP auxbus driver"); +@@ -3097,7 +2990,6 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + + return 0; + err_aux: +- ice_clear_ptp_clock_index(pf); + ptp_clock_unregister(pf->ptp.clock); + err_clk: + pf->ptp.clock = NULL; +@@ -3353,7 +3245,6 @@ void ice_ptp_release(struct ice_pf *pf) + /* Disable periodic outputs */ + ice_ptp_disable_all_clkout(pf); + +- ice_clear_ptp_clock_index(pf); + ptp_clock_unregister(pf->ptp.clock); + pf->ptp.clock = NULL; + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 64679d3d2c49..95ebd7a048ec 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -290,11 +290,11 @@ struct ice_ptp { + #define ETH_GLTSYN_ENA(_i) (0x03000348 + ((_i) * 4)) + + #if IS_ENABLED(CONFIG_PTP_1588_CLOCK) ++int ice_ptp_clock_index(struct ice_pf *pf); + struct ice_pf; + int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr); + int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr); + void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena); +-int ice_get_ptp_clock_index(struct ice_pf *pf); + + void ice_ptp_extts_event(struct ice_pf *pf); + s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb); +@@ -322,10 +322,6 @@ static inline int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) + } + + static inline void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) { } +-static inline int ice_get_ptp_clock_index(struct ice_pf *pf) +-{ +- return -1; +-} + + static inline void ice_ptp_extts_event(struct ice_pf *pf) { } + static inline s8 +@@ -353,5 +349,10 @@ static inline void ice_ptp_release(struct ice_pf *pf) { } + static inline void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + { + } ++ ++static inline int ice_ptp_clock_index(struct ice_pf *pf) ++{ ++ return -1; ++} + #endif /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */ + #endif /* _ICE_PTP_H_ */ +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0015-ice-restore-timestamp-configuration-after-device-res.patch b/kernel-rt/debian/patches/ice-VDF/0015-ice-restore-timestamp-configuration-after-device-res.patch new file mode 100644 index 00000000..ed75abed --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0015-ice-restore-timestamp-configuration-after-device-res.patch @@ -0,0 +1,266 @@ +From eb63973adae478fdcc324f5490d6803646f0cc76 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 21 Nov 2023 13:12:57 -0800 +Subject: [PATCH 15/36] ice: restore timestamp configuration after device reset + +The driver calls ice_ptp_cfg_timestamp() during ice_ptp_prepare_for_reset() +to disable timestamping while the device is resetting. This operation +destroys the user requested configuration. While the driver does call +ice_ptp_cfg_timestamp in ice_rebuild() to restore some hardware settings +after a reset, it unconditionally passes true or false, resulting in +failure to restore previous user space configuration. + +This results in a device reset forcibly disabling timestamp configuration +regardless of current user settings. + +This was not detected previously due to a quirk of the LinuxPTP ptp4l +application. If ptp4l detects a missing timestamp, it enters a fault state +and performs recovery logic which includes executing SIOCSHWTSTAMP again, +restoring the now accidentally cleared configuration. + +Not every application does this, and for these applications, timestamps +will mysteriously stop after a PF reset, without being restored until an +application restart. + +Fix this by replacing ice_ptp_cfg_timestamp() with two new functions: + +1) ice_ptp_disable_timestamp_mode() which unconditionally disables the + timestamping logic in ice_ptp_prepare_for_reset() and ice_ptp_release() + +2) ice_ptp_restore_timestamp_mode() which calls + ice_ptp_restore_tx_interrupt() to restore Tx timestamping configuration, + calls ice_set_rx_tstamp() to restore Rx timestamping configuration, and + issues an immediate TSYN_TX interrupt to ensure that timestamps which + may have occurred during the device reset get processed. + +Modify the ice_ptp_set_timestamp_mode to directly save the user +configuration and then call ice_ptp_restore_timestamp_mode. This way, reset +no longer destroys the saved user configuration. + +This obsoletes the ice_set_tx_tstamp() function which can now be safely +removed. + +With this change, all devices should now restore Tx and Rx timestamping +functionality correctly after a PF reset without application intervention. + +Fixes: 77a781155a65 ("ice: enable receive hardware timestamping") +Fixes: ea9b847cda64 ("ice: enable transmit timestamps for E810 devices") +Signed-off-by: Jacob Keller +Reviewed-by: Jesse Brandeburg +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 7758017911a4f2578d54c318e8fe77bcb5899054) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_main.c | 12 +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 74 ++++++++++++++--------- + drivers/net/ethernet/intel/ice/ice_ptp.h | 5 +- + 3 files changed, 51 insertions(+), 40 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 9163a72368b3..8cfb923198e9 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -7545,15 +7545,6 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + goto err_vsi_rebuild; + } + +- /* configure PTP timestamping after VSI rebuild */ +- if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) { +- if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) +- ice_ptp_cfg_timestamp(pf, false); +- else if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) +- /* for E82x PHC owner always need to have interrupts */ +- ice_ptp_cfg_timestamp(pf, true); +- } +- + err = ice_vsi_rebuild_by_type(pf, ICE_VSI_SWITCHDEV_CTRL); + if (err) { + dev_err(dev, "Switchdev CTRL VSI rebuild failed: %d\n", err); +@@ -7605,6 +7596,9 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + ice_plug_aux_dev(pf); + if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) + ice_lag_rebuild(pf); ++ ++ /* Restore timestamp mode settings after VSI rebuild */ ++ ice_ptp_restore_timestamp_mode(pf); + return; + + err_vsi_rebuild: +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index a2d0da7dfe83..8fc6905b0f79 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -294,18 +294,6 @@ static void ice_ptp_cfg_tx_interrupt(struct ice_pf *pf) + wr32(hw, PFINT_OICR_ENA, val); + } + +-/** +- * ice_set_tx_tstamp - Enable or disable Tx timestamping +- * @pf: The PF pointer to search in +- * @on: bool value for whether timestamps are enabled or disabled +- */ +-static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) +-{ +- pf->ptp.tstamp_config.tx_type = on ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; +- +- ice_ptp_cfg_tx_interrupt(pf); +-} +- + /** + * ice_set_rx_tstamp - Enable or disable Rx timestamping + * @pf: The PF pointer to search in +@@ -317,7 +305,7 @@ static void ice_set_rx_tstamp(struct ice_pf *pf, bool on) + u16 i; + + vsi = ice_get_main_vsi(pf); +- if (!vsi) ++ if (!vsi || !vsi->rx_rings) + return; + + /* Set the timestamp flag for all the Rx rings */ +@@ -326,23 +314,50 @@ static void ice_set_rx_tstamp(struct ice_pf *pf, bool on) + continue; + vsi->rx_rings[i]->ptp_rx = on; + } ++} ++ ++/** ++ * ice_ptp_disable_timestamp_mode - Disable current timestamp mode ++ * @pf: Board private structure ++ * ++ * Called during preparation for reset to temporarily disable timestamping on ++ * the device. Called during remove to disable timestamping while cleaning up ++ * driver resources. ++ */ ++static void ice_ptp_disable_timestamp_mode(struct ice_pf *pf) ++{ ++ struct ice_hw *hw = &pf->hw; ++ u32 val; ++ ++ val = rd32(hw, PFINT_OICR_ENA); ++ val &= ~PFINT_OICR_TSYN_TX_M; ++ wr32(hw, PFINT_OICR_ENA, val); + +- pf->ptp.tstamp_config.rx_filter = on ? HWTSTAMP_FILTER_ALL : +- HWTSTAMP_FILTER_NONE; ++ ice_set_rx_tstamp(pf, false); + } + + /** +- * ice_ptp_cfg_timestamp - Configure timestamp for init/deinit ++ * ice_ptp_restore_timestamp_mode - Restore timestamp configuration + * @pf: Board private structure +- * @ena: bool value to enable or disable time stamp + * +- * This function will configure timestamping during PTP initialization +- * and deinitialization ++ * Called at the end of rebuild to restore timestamp configuration after ++ * a device reset. + */ +-void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) ++void ice_ptp_restore_timestamp_mode(struct ice_pf *pf) + { +- ice_set_tx_tstamp(pf, ena); +- ice_set_rx_tstamp(pf, ena); ++ struct ice_hw *hw = &pf->hw; ++ bool enable_rx; ++ ++ ice_ptp_cfg_tx_interrupt(pf); ++ ++ enable_rx = pf->ptp.tstamp_config.rx_filter == HWTSTAMP_FILTER_ALL; ++ ice_set_rx_tstamp(pf, enable_rx); ++ ++ /* Trigger an immediate software interrupt to ensure that timestamps ++ * which occurred during reset are handled now. ++ */ ++ wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); ++ ice_flush(hw); + } + + /** +@@ -2152,10 +2167,10 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config) + { + switch (config->tx_type) { + case HWTSTAMP_TX_OFF: +- ice_set_tx_tstamp(pf, false); ++ pf->ptp.tstamp_config.tx_type = HWTSTAMP_TX_OFF; + break; + case HWTSTAMP_TX_ON: +- ice_set_tx_tstamp(pf, true); ++ pf->ptp.tstamp_config.tx_type = HWTSTAMP_TX_ON; + break; + default: + return -ERANGE; +@@ -2163,7 +2178,7 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config) + + switch (config->rx_filter) { + case HWTSTAMP_FILTER_NONE: +- ice_set_rx_tstamp(pf, false); ++ pf->ptp.tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: +@@ -2179,12 +2194,15 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config) + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_NTP_ALL: + case HWTSTAMP_FILTER_ALL: +- ice_set_rx_tstamp(pf, true); ++ pf->ptp.tstamp_config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + default: + return -ERANGE; + } + ++ /* Immediately update the device timestamping mode */ ++ ice_ptp_restore_timestamp_mode(pf); ++ + return 0; + } + +@@ -2904,7 +2922,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf) + clear_bit(ICE_FLAG_PTP, pf->flags); + + /* Disable timestamping for both Tx and Rx */ +- ice_ptp_cfg_timestamp(pf, false); ++ ice_ptp_disable_timestamp_mode(pf); + + kthread_cancel_delayed_work_sync(&ptp->work); + +@@ -3222,7 +3240,7 @@ void ice_ptp_release(struct ice_pf *pf) + return; + + /* Disable timestamping for both Tx and Rx */ +- ice_ptp_cfg_timestamp(pf, false); ++ ice_ptp_disable_timestamp_mode(pf); + + ice_ptp_remove_auxbus_device(pf); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 95ebd7a048ec..130e6d2ae9a5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -294,7 +294,7 @@ int ice_ptp_clock_index(struct ice_pf *pf); + struct ice_pf; + int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr); + int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr); +-void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena); ++void ice_ptp_restore_timestamp_mode(struct ice_pf *pf); + + void ice_ptp_extts_event(struct ice_pf *pf); + s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb); +@@ -321,8 +321,7 @@ static inline int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) + return -EOPNOTSUPP; + } + +-static inline void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) { } +- ++static inline void ice_ptp_restore_timestamp_mode(struct ice_pf *pf) { } + static inline void ice_ptp_extts_event(struct ice_pf *pf) { } + static inline s8 + ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0016-ice-introduce-PTP-state-machine.patch b/kernel-rt/debian/patches/ice-VDF/0016-ice-introduce-PTP-state-machine.patch new file mode 100644 index 00000000..851c986e --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0016-ice-introduce-PTP-state-machine.patch @@ -0,0 +1,316 @@ +From 5c6115d27a377927d6392b3bfbe9739188c8153c Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:49 -0800 +Subject: [PATCH 16/36] ice: introduce PTP state machine + +Add PTP state machine so that the driver can correctly identify PTP +state around resets. +When the driver got information about ungraceful reset, PTP was not +prepared for reset and it returned error. When this situation occurs, +prepare PTP before rebuilding its structures. + +Signed-off-by: Jacob Keller +Co-developed-by: Karol Kolacinski +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 8293e4cb2ff54b1ec4f7206dcb74c908f62a3fb8) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 1 - + drivers/net/ethernet/intel/ice/ice_ethtool.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 110 +++++++++++-------- + drivers/net/ethernet/intel/ice/ice_ptp.h | 10 ++ + 4 files changed, 74 insertions(+), 49 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index ee42a504c2f4..3278d032a2bd 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -492,7 +492,6 @@ enum ice_pf_flags { + ICE_FLAG_DCB_ENA, + ICE_FLAG_FD_ENA, + ICE_FLAG_PTP_SUPPORTED, /* PTP is supported by NVM */ +- ICE_FLAG_PTP, /* PTP is enabled by software */ + ICE_FLAG_ADV_FEATURES, + ICE_FLAG_TC_MQPRIO, /* support for Multi queue TC */ + ICE_FLAG_CLS_FLOWER, +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 057453d589d5..9e949c493c38 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -3276,7 +3276,7 @@ ice_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) + struct ice_pf *pf = ice_netdev_to_pf(dev); + + /* only report timestamping if PTP is enabled */ +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return ethtool_op_get_ts_info(dev, info); + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 8fc6905b0f79..36c81c5ee83b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1430,7 +1430,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + struct ice_ptp_port *ptp_port; + struct ice_hw *hw = &pf->hw; + +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return; + + if (WARN_ON_ONCE(port >= ICE_NUM_EXTERNAL_PORTS)) +@@ -2148,7 +2148,7 @@ int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) + { + struct hwtstamp_config *config; + +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return -EIO; + + config = &pf->ptp.tstamp_config; +@@ -2218,7 +2218,7 @@ int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr) + struct hwtstamp_config config; + int err; + +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return -EAGAIN; + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) +@@ -2606,7 +2606,7 @@ static void ice_ptp_periodic_work(struct kthread_work *work) + struct ice_pf *pf = container_of(ptp, struct ice_pf, ptp); + int err; + +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return; + + err = ice_ptp_update_cached_phctime(pf); +@@ -2618,6 +2618,42 @@ static void ice_ptp_periodic_work(struct kthread_work *work) + msecs_to_jiffies(err ? 10 : 500)); + } + ++/** ++ * ice_ptp_prepare_for_reset - Prepare PTP for reset ++ * @pf: Board private structure ++ */ ++void ice_ptp_prepare_for_reset(struct ice_pf *pf) ++{ ++ struct ice_ptp *ptp = &pf->ptp; ++ u8 src_tmr; ++ ++ if (ptp->state != ICE_PTP_READY) ++ return; ++ ++ ptp->state = ICE_PTP_RESETTING; ++ ++ /* Disable timestamping for both Tx and Rx */ ++ ice_ptp_disable_timestamp_mode(pf); ++ ++ kthread_cancel_delayed_work_sync(&ptp->work); ++ ++ if (test_bit(ICE_PFR_REQ, pf->state)) ++ return; ++ ++ ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); ++ ++ /* Disable periodic outputs */ ++ ice_ptp_disable_all_clkout(pf); ++ ++ src_tmr = ice_get_ptp_src_clock_index(&pf->hw); ++ ++ /* Disable source clock */ ++ wr32(&pf->hw, GLTSYN_ENA(src_tmr), (u32)~GLTSYN_ENA_TSYN_ENA_M); ++ ++ /* Acquire PHC and system timer to restore after reset */ ++ ptp->reset_time = ktime_get_real_ns(); ++} ++ + /** + * ice_ptp_reset - Initialize PTP hardware clock support after reset + * @pf: Board private structure +@@ -2630,6 +2666,14 @@ void ice_ptp_reset(struct ice_pf *pf) + int err, itr = 1; + u64 time_diff; + ++ if (ptp->state == ICE_PTP_READY) { ++ ice_ptp_prepare_for_reset(pf); ++ } else if (ptp->state != ICE_PTP_RESETTING) { ++ err = -EINVAL; ++ dev_err(ice_pf_to_dev(pf), "PTP was not initialized\n"); ++ goto err; ++ } ++ + if (test_bit(ICE_PFR_REQ, pf->state) || + !ice_pf_src_tmr_owned(pf)) + goto pfr; +@@ -2690,7 +2734,7 @@ void ice_ptp_reset(struct ice_pf *pf) + if (err) + goto err; + +- set_bit(ICE_FLAG_PTP, pf->flags); ++ ptp->state = ICE_PTP_READY; + + /* Restart the PHY timestamping block */ + if (!test_bit(ICE_PFR_REQ, pf->state) && +@@ -2704,6 +2748,7 @@ void ice_ptp_reset(struct ice_pf *pf) + return; + + err: ++ ptp->state = ICE_PTP_ERROR; + dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err); + } + +@@ -2910,39 +2955,6 @@ int ice_ptp_clock_index(struct ice_pf *pf) + return clock ? ptp_clock_index(clock) : -1; + } + +-/** +- * ice_ptp_prepare_for_reset - Prepare PTP for reset +- * @pf: Board private structure +- */ +-void ice_ptp_prepare_for_reset(struct ice_pf *pf) +-{ +- struct ice_ptp *ptp = &pf->ptp; +- u8 src_tmr; +- +- clear_bit(ICE_FLAG_PTP, pf->flags); +- +- /* Disable timestamping for both Tx and Rx */ +- ice_ptp_disable_timestamp_mode(pf); +- +- kthread_cancel_delayed_work_sync(&ptp->work); +- +- if (test_bit(ICE_PFR_REQ, pf->state)) +- return; +- +- ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); +- +- /* Disable periodic outputs */ +- ice_ptp_disable_all_clkout(pf); +- +- src_tmr = ice_get_ptp_src_clock_index(&pf->hw); +- +- /* Disable source clock */ +- wr32(&pf->hw, GLTSYN_ENA(src_tmr), (u32)~GLTSYN_ENA_TSYN_ENA_M); +- +- /* Acquire PHC and system timer to restore after reset */ +- ptp->reset_time = ktime_get_real_ns(); +-} +- + /** + * ice_ptp_init_owner - Initialize PTP_1588_CLOCK device + * @pf: Board private structure +@@ -3181,6 +3193,8 @@ void ice_ptp_init(struct ice_pf *pf) + struct ice_hw *hw = &pf->hw; + int err; + ++ ptp->state = ICE_PTP_INITIALIZING; ++ + ice_ptp_init_phy_model(hw); + + ice_ptp_init_tx_interrupt_mode(pf); +@@ -3205,12 +3219,13 @@ void ice_ptp_init(struct ice_pf *pf) + /* Configure initial Tx interrupt settings */ + ice_ptp_cfg_tx_interrupt(pf); + +- set_bit(ICE_FLAG_PTP, pf->flags); +- err = ice_ptp_init_work(pf, ptp); ++ err = ice_ptp_create_auxbus_device(pf); + if (err) + goto err; + +- err = ice_ptp_create_auxbus_device(pf); ++ ptp->state = ICE_PTP_READY; ++ ++ err = ice_ptp_init_work(pf, ptp); + if (err) + goto err; + +@@ -3223,7 +3238,7 @@ void ice_ptp_init(struct ice_pf *pf) + ptp_clock_unregister(ptp->clock); + pf->ptp.clock = NULL; + } +- clear_bit(ICE_FLAG_PTP, pf->flags); ++ ptp->state = ICE_PTP_ERROR; + dev_err(ice_pf_to_dev(pf), "PTP failed %d\n", err); + } + +@@ -3236,9 +3251,11 @@ void ice_ptp_init(struct ice_pf *pf) + */ + void ice_ptp_release(struct ice_pf *pf) + { +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return; + ++ pf->ptp.state = ICE_PTP_UNINIT; ++ + /* Disable timestamping for both Tx and Rx */ + ice_ptp_disable_timestamp_mode(pf); + +@@ -3246,8 +3263,6 @@ void ice_ptp_release(struct ice_pf *pf) + + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); + +- clear_bit(ICE_FLAG_PTP, pf->flags); +- + kthread_cancel_delayed_work_sync(&pf->ptp.work); + + ice_ptp_port_phy_stop(&pf->ptp.port); +@@ -3257,6 +3272,9 @@ void ice_ptp_release(struct ice_pf *pf) + pf->ptp.kworker = NULL; + } + ++ if (ice_pf_src_tmr_owned(pf)) ++ ice_ptp_unregister_auxbus_driver(pf); ++ + if (!pf->ptp.clock) + return; + +@@ -3266,7 +3284,5 @@ void ice_ptp_release(struct ice_pf *pf) + ptp_clock_unregister(pf->ptp.clock); + pf->ptp.clock = NULL; + +- ice_ptp_unregister_auxbus_driver(pf); +- + dev_info(ice_pf_to_dev(pf), "Removed PTP clock\n"); + } +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 130e6d2ae9a5..e3cc69692405 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -203,8 +203,17 @@ struct ice_ptp_port_owner { + + #define GLTSYN_TGT_H_IDX_MAX 4 + ++enum ice_ptp_state { ++ ICE_PTP_UNINIT = 0, ++ ICE_PTP_INITIALIZING, ++ ICE_PTP_READY, ++ ICE_PTP_RESETTING, ++ ICE_PTP_ERROR, ++}; ++ + /** + * struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK ++ * @state: current state of PTP state machine + * @tx_interrupt_mode: the TX interrupt mode for the PTP clock + * @port: data for the PHY port initialization procedure + * @ports_owner: data for the auxiliary driver owner +@@ -227,6 +236,7 @@ struct ice_ptp_port_owner { + * @late_cached_phc_updates: number of times cached PHC update is late + */ + struct ice_ptp { ++ enum ice_ptp_state state; + enum ice_ptp_tx_interrupt tx_interrupt_mode; + struct ice_ptp_port port; + struct ice_ptp_port_owner ports_owner; +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0017-ice-pass-reset-type-to-PTP-reset-functions.patch b/kernel-rt/debian/patches/ice-VDF/0017-ice-pass-reset-type-to-PTP-reset-functions.patch new file mode 100644 index 00000000..c72ff132 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0017-ice-pass-reset-type-to-PTP-reset-functions.patch @@ -0,0 +1,150 @@ +From 68d481b41ee5c177a1376fb82a98c09c148d982a Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:50 -0800 +Subject: [PATCH 17/36] ice: pass reset type to PTP reset functions + +The ice_ptp_prepare_for_reset() and ice_ptp_reset() functions currently +check the pf->flags ICE_FLAG_PFR_REQ bit to determine if the current +reset is a PF reset or not. + +This is problematic, because it is possible that a PF reset and a higher +level reset (CORE reset, GLOBAL reset, EMP reset) are requested +simultaneously. In that case, the driver performs the highest level +reset requested. However, the ICE_FLAG_PFR_REQ flag will still be set. + +The main driver reset functions take an enum ice_reset_req indicating +which reset is actually being performed. Pass this data into the PTP +functions and rely on this instead of relying on the driver flags. + +This ensures that the PTP code performs the proper level of reset that +the driver is actually undergoing. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit c75d5e675a8542274fa0f7e52f3c4db1d4859a0c) +[Adjust the ice_ptp.h with the context change.] +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_main.c | 4 ++-- + drivers/net/ethernet/intel/ice/ice_ptp.c | 13 +++++++------ + drivers/net/ethernet/intel/ice/ice_ptp.h | 17 +++++++++++++---- + 3 files changed, 22 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 8cfb923198e9..d5321410f2d7 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -615,7 +615,7 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + ice_pf_dis_all_vsi(pf, false); + + if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) +- ice_ptp_prepare_for_reset(pf); ++ ice_ptp_prepare_for_reset(pf, reset_type); + + if (ice_is_feature_supported(pf, ICE_F_GNSS)) + ice_gnss_exit(pf); +@@ -7533,7 +7533,7 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + * fail. + */ + if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) +- ice_ptp_reset(pf); ++ ice_ptp_reset(pf, reset_type); + + if (ice_is_feature_supported(pf, ICE_F_GNSS)) + ice_gnss_init(pf); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 36c81c5ee83b..20d1d22235d3 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -2621,8 +2621,9 @@ static void ice_ptp_periodic_work(struct kthread_work *work) + /** + * ice_ptp_prepare_for_reset - Prepare PTP for reset + * @pf: Board private structure ++ * @reset_type: the reset type being performed + */ +-void ice_ptp_prepare_for_reset(struct ice_pf *pf) ++void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + { + struct ice_ptp *ptp = &pf->ptp; + u8 src_tmr; +@@ -2637,7 +2638,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf) + + kthread_cancel_delayed_work_sync(&ptp->work); + +- if (test_bit(ICE_PFR_REQ, pf->state)) ++ if (reset_type == ICE_RESET_PFR) + return; + + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); +@@ -2657,8 +2658,9 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf) + /** + * ice_ptp_reset - Initialize PTP hardware clock support after reset + * @pf: Board private structure ++ * @reset_type: the reset type being performed + */ +-void ice_ptp_reset(struct ice_pf *pf) ++void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + { + struct ice_ptp *ptp = &pf->ptp; + struct ice_hw *hw = &pf->hw; +@@ -2667,15 +2669,14 @@ void ice_ptp_reset(struct ice_pf *pf) + u64 time_diff; + + if (ptp->state == ICE_PTP_READY) { +- ice_ptp_prepare_for_reset(pf); ++ ice_ptp_prepare_for_reset(pf, reset_type); + } else if (ptp->state != ICE_PTP_RESETTING) { + err = -EINVAL; + dev_err(ice_pf_to_dev(pf), "PTP was not initialized\n"); + goto err; + } + +- if (test_bit(ICE_PFR_REQ, pf->state) || +- !ice_pf_src_tmr_owned(pf)) ++ if (reset_type == ICE_RESET_PFR || !ice_pf_src_tmr_owned(pf)) + goto pfr; + + err = ice_ptp_init_phc(hw); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index e3cc69692405..cd74712a17a1 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -315,8 +315,9 @@ enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf); + void + ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, + union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb); +-void ice_ptp_reset(struct ice_pf *pf); +-void ice_ptp_prepare_for_reset(struct ice_pf *pf); ++void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type); ++void ice_ptp_prepare_for_reset(struct ice_pf *pf, ++ enum ice_reset_req reset_type); + void ice_ptp_init(struct ice_pf *pf); + void ice_ptp_release(struct ice_pf *pf); + void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup); +@@ -351,8 +352,16 @@ static inline bool ice_ptp_process_ts(struct ice_pf *pf) + static inline void + ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, + union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb) { } +-static inline void ice_ptp_reset(struct ice_pf *pf) { } +-static inline void ice_ptp_prepare_for_reset(struct ice_pf *pf) { } ++ ++static inline void ice_ptp_reset(struct ice_pf *pf, ++ enum ice_reset_req reset_type) ++{ ++} ++ ++static inline void ice_ptp_prepare_for_reset(struct ice_pf *pf, ++ enum ice_reset_req reset_type) ++{ ++} + static inline void ice_ptp_init(struct ice_pf *pf) { } + static inline void ice_ptp_release(struct ice_pf *pf) { } + static inline void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0018-ice-rename-verify_cached-to-has_ready_bitmap.patch b/kernel-rt/debian/patches/ice-VDF/0018-ice-rename-verify_cached-to-has_ready_bitmap.patch new file mode 100644 index 00000000..a17f0f89 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0018-ice-rename-verify_cached-to-has_ready_bitmap.patch @@ -0,0 +1,119 @@ +From 084497314e63f3d92178bc44500a27a277abc378 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:51 -0800 +Subject: [PATCH 18/36] ice: rename verify_cached to has_ready_bitmap + +The tx->verify_cached flag is used to inform the Tx timestamp tracking +code whether it needs to verify the cached Tx timestamp value against +a previous captured value. This is necessary on E810 hardware which does +not have a Tx timestamp ready bitmap. + +In addition, we currently rely on the fact that the +ice_get_phy_tx_tstamp_ready() function returns all 1s for E810 hardware. +Instead of introducing a brand new flag, rename and verify_cached to +has_ready_bitmap, inverting the relevant checks. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 3f2216e8dbce04da5376ea7df410541f7b687cb0) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 12 ++++++------ + drivers/net/ethernet/intel/ice/ice_ptp.h | 8 +++++--- + 2 files changed, 11 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 20d1d22235d3..a8c6b83579e6 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -606,11 +606,11 @@ void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) + * timestamp. If it is not, skip this for now assuming it hasn't yet + * been captured by hardware. + */ +- if (!drop_ts && tx->verify_cached && ++ if (!drop_ts && !tx->has_ready_bitmap && + raw_tstamp == tx->tstamps[idx].cached_tstamp) + return; + +- if (tx->verify_cached && raw_tstamp) ++ if (!tx->has_ready_bitmap && raw_tstamp) + tx->tstamps[idx].cached_tstamp = raw_tstamp; + clear_bit(idx, tx->in_use); + skb = tx->tstamps[idx].skb; +@@ -751,7 +751,7 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + * from the last cached timestamp. If it is not, skip this for + * now assuming it hasn't yet been captured by hardware. + */ +- if (!drop_ts && tx->verify_cached && ++ if (!drop_ts && !tx->has_ready_bitmap && + raw_tstamp == tx->tstamps[idx].cached_tstamp) + continue; + +@@ -761,7 +761,7 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + + skip_ts_read: + spin_lock_irqsave(&tx->lock, flags); +- if (tx->verify_cached && raw_tstamp) ++ if (!tx->has_ready_bitmap && raw_tstamp) + tx->tstamps[idx].cached_tstamp = raw_tstamp; + clear_bit(idx, tx->in_use); + skb = tx->tstamps[idx].skb; +@@ -1014,7 +1014,7 @@ ice_ptp_init_tx_e82x(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port) + tx->block = port / ICE_PORTS_PER_QUAD; + tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E82X; + tx->len = INDEX_PER_PORT_E82X; +- tx->verify_cached = 0; ++ tx->has_ready_bitmap = 1; + + return ice_ptp_alloc_tx_tracker(tx); + } +@@ -1037,7 +1037,7 @@ ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx) + * verify new timestamps against cached copy of the last read + * timestamp. + */ +- tx->verify_cached = 1; ++ tx->has_ready_bitmap = 0; + + return ice_ptp_alloc_tx_tracker(tx); + } +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index cd74712a17a1..1486a0b3b016 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -100,7 +100,7 @@ struct ice_perout_channel { + * the last timestamp we read for a given index. If the current timestamp + * value is the same as the cached value, we assume a new timestamp hasn't + * been captured. This avoids reporting stale timestamps to the stack. This is +- * only done if the verify_cached flag is set in ice_ptp_tx structure. ++ * only done if the has_ready_bitmap flag is not set in ice_ptp_tx structure. + */ + struct ice_tx_tstamp { + struct sk_buff *skb; +@@ -130,7 +130,9 @@ enum ice_tx_tstamp_work { + * @init: if true, the tracker is initialized; + * @calibrating: if true, the PHY is calibrating the Tx offset. During this + * window, timestamps are temporarily disabled. +- * @verify_cached: if true, verify new timestamp differs from last read value ++ * @has_ready_bitmap: if true, the hardware has a valid Tx timestamp ready ++ * bitmap register. If false, fall back to verifying new ++ * timestamp values against previously cached copy. + * @last_ll_ts_idx_read: index of the last LL TS read by the FW + */ + struct ice_ptp_tx { +@@ -143,7 +145,7 @@ struct ice_ptp_tx { + u8 len; + u8 init : 1; + u8 calibrating : 1; +- u8 verify_cached : 1; ++ u8 has_ready_bitmap : 1; + s8 last_ll_ts_idx_read; + }; + +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0019-ice-don-t-check-has_ready_bitmap-in-E810-functions.patch b/kernel-rt/debian/patches/ice-VDF/0019-ice-don-t-check-has_ready_bitmap-in-E810-functions.patch new file mode 100644 index 00000000..d1701f9e --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0019-ice-don-t-check-has_ready_bitmap-in-E810-functions.patch @@ -0,0 +1,77 @@ +From 375bced6b51243a8c8708204dd32960d076d5b83 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:52 -0800 +Subject: [PATCH 19/36] ice: don't check has_ready_bitmap in E810 functions + +E810 hardware does not have a Tx timestamp ready bitmap. Don't check +has_ready_bitmap in E810-specific functions. +Add has_ready_bitmap check in ice_ptp_process_tx_tstamp() to stop +relying on the fact that ice_get_phy_tx_tstamp_ready() returns all 1s. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit fea82915fca626eaa83f36d8a23194e8593ef4b4) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index a8c6b83579e6..ddc2dd0b2a28 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -601,17 +601,13 @@ void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) + /* Read the low 32 bit value */ + raw_tstamp |= (u64)rd32(&pf->hw, PF_SB_ATQBAH); + +- /* For PHYs which don't implement a proper timestamp ready bitmap, +- * verify that the timestamp value is different from the last cached +- * timestamp. If it is not, skip this for now assuming it hasn't yet +- * been captured by hardware. ++ /* Devices using this interface always verify the timestamp differs ++ * relative to the last cached timestamp value. + */ +- if (!drop_ts && !tx->has_ready_bitmap && +- raw_tstamp == tx->tstamps[idx].cached_tstamp) ++ if (raw_tstamp == tx->tstamps[idx].cached_tstamp) + return; + +- if (!tx->has_ready_bitmap && raw_tstamp) +- tx->tstamps[idx].cached_tstamp = raw_tstamp; ++ tx->tstamps[idx].cached_tstamp = raw_tstamp; + clear_bit(idx, tx->in_use); + skb = tx->tstamps[idx].skb; + tx->tstamps[idx].skb = NULL; +@@ -701,9 +697,11 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + hw = &pf->hw; + + /* Read the Tx ready status first */ +- err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready); +- if (err) +- return; ++ if (tx->has_ready_bitmap) { ++ err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready); ++ if (err) ++ return; ++ } + + /* Drop packets if the link went down */ + link_up = ptp_port->link_up; +@@ -731,7 +729,8 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + * If we do not, the hardware logic for generating a new + * interrupt can get stuck on some devices. + */ +- if (!(tstamp_ready & BIT_ULL(phy_idx))) { ++ if (tx->has_ready_bitmap && ++ !(tstamp_ready & BIT_ULL(phy_idx))) { + if (drop_ts) + goto skip_ts_read; + +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0020-ice-rename-ice_ptp_tx_cfg_intr.patch b/kernel-rt/debian/patches/ice-VDF/0020-ice-rename-ice_ptp_tx_cfg_intr.patch new file mode 100644 index 00000000..30d0631e --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0020-ice-rename-ice_ptp_tx_cfg_intr.patch @@ -0,0 +1,88 @@ +From a5318a3a04ed9535ab18ef0f0537b3d33862bee9 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:53 -0800 +Subject: [PATCH 20/36] ice: rename ice_ptp_tx_cfg_intr + +The ice_ptp_tx_cfg_intr() function sends a control queue message to +configure the PHY timestamp interrupt block. This is a very similar name +to a function which is used to configure the MAC Other Interrupt Cause +Enable register. + +Rename this function to ice_ptp_cfg_phy_interrupt in order to make it +more obvious to the reader what action it performs, and distinguish it +from other similarly named functions. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 1abefdca85e8664374f53c7bc80d5f5f827ce711) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index ddc2dd0b2a28..c6e9d77fc59b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1455,14 +1455,14 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + } + + /** +- * ice_ptp_tx_ena_intr - Enable or disable the Tx timestamp interrupt ++ * ice_ptp_cfg_phy_interrupt - Configure PHY interrupt settings + * @pf: PF private structure + * @ena: bool value to enable or disable interrupt + * @threshold: Minimum number of packets at which intr is triggered + * + * Utility function to enable or disable Tx timestamp interrupt and threshold + */ +-static int ice_ptp_tx_ena_intr(struct ice_pf *pf, bool ena, u32 threshold) ++static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold) + { + struct ice_hw *hw = &pf->hw; + int err = 0; +@@ -2664,8 +2664,8 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + struct ice_ptp *ptp = &pf->ptp; + struct ice_hw *hw = &pf->hw; + struct timespec64 ts; +- int err, itr = 1; + u64 time_diff; ++ int err; + + if (ptp->state == ICE_PTP_READY) { + ice_ptp_prepare_for_reset(pf, reset_type); +@@ -2716,7 +2716,7 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + + if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ +- err = ice_ptp_tx_ena_intr(pf, true, itr); ++ err = ice_ptp_cfg_phy_interrupt(pf, true, 1); + if (err) + goto err; + } +@@ -2967,7 +2967,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + { + struct ice_hw *hw = &pf->hw; + struct timespec64 ts; +- int err, itr = 1; ++ int err; + + err = ice_ptp_init_phc(hw); + if (err) { +@@ -3002,7 +3002,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + + if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ +- err = ice_ptp_tx_ena_intr(pf, true, itr); ++ err = ice_ptp_cfg_phy_interrupt(pf, true, 1); + if (err) + goto err_exit; + } +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0021-ice-factor-out-ice_ptp_rebuild_owner.patch b/kernel-rt/debian/patches/ice-VDF/0021-ice-factor-out-ice_ptp_rebuild_owner.patch new file mode 100644 index 00000000..075359c8 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0021-ice-factor-out-ice_ptp_rebuild_owner.patch @@ -0,0 +1,191 @@ +From 9411c5b82a7196b9712488631fd14e67e2d919fa Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:54 -0800 +Subject: [PATCH 21/36] ice: factor out ice_ptp_rebuild_owner() + +The ice_ptp_reset() function uses a goto to skip past clock owner +operations if performing a PF reset or if the device is not the clock +owner. This is a bit confusing. Factor this out into +ice_ptp_rebuild_owner() instead. + +The ice_ptp_reset() function is called by ice_rebuild() to restore PTP +functionality after a device reset. Follow the convention set by the +ice_main.c file and rename this function to ice_ptp_rebuild(), in the +same way that we have ice_prepare_for_reset() and +ice_ptp_prepare_for_reset(). + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 803bef817807d2d36c930dada20c96fffae0dd19) +[Adjust ice_ptp.h with the context change.] +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_main.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 62 ++++++++++++++--------- + drivers/net/ethernet/intel/ice/ice_ptp.h | 6 +-- + 3 files changed, 42 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index d5321410f2d7..a04dcc89c35d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -7533,7 +7533,7 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + * fail. + */ + if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) +- ice_ptp_reset(pf, reset_type); ++ ice_ptp_rebuild(pf, reset_type); + + if (ice_is_feature_supported(pf, ICE_F_GNSS)) + ice_gnss_init(pf); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index c6e9d77fc59b..780aa242c86b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -2655,11 +2655,13 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + } + + /** +- * ice_ptp_reset - Initialize PTP hardware clock support after reset ++ * ice_ptp_rebuild_owner - Initialize PTP clock owner after reset + * @pf: Board private structure +- * @reset_type: the reset type being performed ++ * ++ * Companion function for ice_ptp_rebuild() which handles tasks that only the ++ * PTP clock owner instance should perform. + */ +-void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) ++static int ice_ptp_rebuild_owner(struct ice_pf *pf) + { + struct ice_ptp *ptp = &pf->ptp; + struct ice_hw *hw = &pf->hw; +@@ -2667,32 +2669,21 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + u64 time_diff; + int err; + +- if (ptp->state == ICE_PTP_READY) { +- ice_ptp_prepare_for_reset(pf, reset_type); +- } else if (ptp->state != ICE_PTP_RESETTING) { +- err = -EINVAL; +- dev_err(ice_pf_to_dev(pf), "PTP was not initialized\n"); +- goto err; +- } +- +- if (reset_type == ICE_RESET_PFR || !ice_pf_src_tmr_owned(pf)) +- goto pfr; +- + err = ice_ptp_init_phc(hw); + if (err) +- goto err; ++ return err; + + /* Acquire the global hardware lock */ + if (!ice_ptp_lock(hw)) { + err = -EBUSY; +- goto err; ++ return err; + } + + /* Write the increment time value to PHY and LAN */ + err = ice_ptp_write_incval(hw, ice_base_incval(pf)); + if (err) { + ice_ptp_unlock(hw); +- goto err; ++ return err; + } + + /* Write the initial Time value to PHY and LAN using the cached PHC +@@ -2708,7 +2699,7 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + err = ice_ptp_write_init(pf, &ts); + if (err) { + ice_ptp_unlock(hw); +- goto err; ++ return err; + } + + /* Release the global hardware lock */ +@@ -2717,11 +2708,39 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ + err = ice_ptp_cfg_phy_interrupt(pf, true, 1); ++ if (err) ++ return err; ++ ++ ice_ptp_restart_all_phy(pf); ++ } ++ ++ return 0; ++} ++ ++/** ++ * ice_ptp_rebuild - Initialize PTP hardware clock support after reset ++ * @pf: Board private structure ++ * @reset_type: the reset type being performed ++ */ ++void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) ++{ ++ struct ice_ptp *ptp = &pf->ptp; ++ int err; ++ ++ if (ptp->state == ICE_PTP_READY) { ++ ice_ptp_prepare_for_reset(pf, reset_type); ++ } else if (ptp->state != ICE_PTP_RESETTING) { ++ err = -EINVAL; ++ dev_err(ice_pf_to_dev(pf), "PTP was not initialized\n"); ++ goto err; ++ } ++ ++ if (ice_pf_src_tmr_owned(pf) && reset_type != ICE_RESET_PFR) { ++ err = ice_ptp_rebuild_owner(pf); + if (err) + goto err; + } + +-pfr: + /* Init Tx structures */ + if (ice_is_e810(&pf->hw)) { + err = ice_ptp_init_tx_e810(pf, &ptp->port.tx); +@@ -2736,11 +2755,6 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + + ptp->state = ICE_PTP_READY; + +- /* Restart the PHY timestamping block */ +- if (!test_bit(ICE_PFR_REQ, pf->state) && +- ice_pf_src_tmr_owned(pf)) +- ice_ptp_restart_all_phy(pf); +- + /* Start periodic work going */ + kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 1486a0b3b016..352405a2daf2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -317,7 +317,7 @@ enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf); + void + ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, + union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb); +-void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type); ++void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type); + void ice_ptp_prepare_for_reset(struct ice_pf *pf, + enum ice_reset_req reset_type); + void ice_ptp_init(struct ice_pf *pf); +@@ -355,8 +355,8 @@ static inline void + ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, + union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb) { } + +-static inline void ice_ptp_reset(struct ice_pf *pf, +- enum ice_reset_req reset_type) ++static inline void ice_ptp_rebuild(struct ice_pf *pf, ++ enum ice_reset_req reset_type) + { + } + +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0022-ice-stop-destroying-and-reinitalizing-Tx-tracker-dur.patch b/kernel-rt/debian/patches/ice-VDF/0022-ice-stop-destroying-and-reinitalizing-Tx-tracker-dur.patch new file mode 100644 index 00000000..8e2133b5 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0022-ice-stop-destroying-and-reinitalizing-Tx-tracker-dur.patch @@ -0,0 +1,93 @@ +From 1c89a9e26f669bead5ebcac38fa98c20c517769c Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:55 -0800 +Subject: [PATCH 22/36] ice: stop destroying and reinitalizing Tx tracker + during reset + +The ice driver currently attempts to destroy and re-initialize the Tx +timestamp tracker during the reset flow. The release of the Tx tracker +only happened during CORE reset or GLOBAL reset. The ice_ptp_rebuild() +function always calls the ice_ptp_init_tx function which will allocate +a new tracker data structure, resulting in memory leaks during PF reset. + +Certainly the driver should not be allocating a new tracker without +removing the old tracker data, as this results in a memory leak. +Additionally, there's no reason to remove the tracker memory during a +reset. Remove this logic from the reset and rebuild flow. Instead of +releasing the Tx tracker, flush outstanding timestamps just before we +reset the PHY timestamp block in ice_ptp_cfg_phy_interrupt(). + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 7a25fe5cd5fb2265065ac6765c53c0a1f1e874d3) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 33 +++++++++++++++--------- + 1 file changed, 21 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 780aa242c86b..48ec59fc5d87 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -963,6 +963,22 @@ ice_ptp_mark_tx_tracker_stale(struct ice_ptp_tx *tx) + spin_unlock_irqrestore(&tx->lock, flags); + } + ++/** ++ * ice_ptp_flush_all_tx_tracker - Flush all timestamp trackers on this clock ++ * @pf: Board private structure ++ * ++ * Called by the clock owner to flush all the Tx timestamp trackers associated ++ * with the clock. ++ */ ++static void ++ice_ptp_flush_all_tx_tracker(struct ice_pf *pf) ++{ ++ struct ice_ptp_port *port; ++ ++ list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member) ++ ice_ptp_flush_tx_tracker(ptp_port_to_pf(port), &port->tx); ++} ++ + /** + * ice_ptp_release_tx_tracker - Release allocated memory for Tx tracker + * @pf: Board private structure +@@ -2705,6 +2721,11 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf) + /* Release the global hardware lock */ + ice_ptp_unlock(hw); + ++ /* Flush software tracking of any outstanding timestamps since we're ++ * about to flush the PHY timestamp block. ++ */ ++ ice_ptp_flush_all_tx_tracker(pf); ++ + if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ + err = ice_ptp_cfg_phy_interrupt(pf, true, 1); +@@ -2741,18 +2762,6 @@ void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + goto err; + } + +- /* Init Tx structures */ +- if (ice_is_e810(&pf->hw)) { +- err = ice_ptp_init_tx_e810(pf, &ptp->port.tx); +- } else { +- kthread_init_delayed_work(&ptp->port.ov_work, +- ice_ptp_wait_for_offsets); +- err = ice_ptp_init_tx_e82x(pf, &ptp->port.tx, +- ptp->port.port_num); +- } +- if (err) +- goto err; +- + ptp->state = ICE_PTP_READY; + + /* Start periodic work going */ +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0023-ice-Remove-and-readd-netdev-during-devlink-reload.patch b/kernel-rt/debian/patches/ice-VDF/0023-ice-Remove-and-readd-netdev-during-devlink-reload.patch new file mode 100644 index 00000000..3a902574 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0023-ice-Remove-and-readd-netdev-during-devlink-reload.patch @@ -0,0 +1,457 @@ +From 6f1d1fa58f58ff3f6ce61ab502bd29227ca1bb3f Mon Sep 17 00:00:00 2001 +From: Wojciech Drewek +Date: Mon, 5 Feb 2024 14:03:56 +0100 +Subject: [PATCH 23/36] ice: Remove and readd netdev during devlink reload + +Recent changes to the devlink reload (commit 9b2348e2d6c9 +("devlink: warn about existing entities during reload-reinit")) +force the drivers to destroy devlink ports during reinit. +Adjust ice driver to this requirement, unregister netdvice, destroy +devlink port. ice_init_eth() was removed and all the common code +between probe and reload was moved to ice_load(). + +During devlink reload we can't take devl_lock (it's already taken) +and in ice_probe() we have to lock it. Use devl_* variant of the API +which does not acquire and release devl_lock. Guard ice_load() +with devl_lock only in case of probe. + +Suggested-by: Jiri Pirko +Reviewed-by: Przemek Kitszel +Reviewed-by: Vadim Fedorenko +Reviewed-by: Simon Horman +Reviewed-by: Brett Creeley +Signed-off-by: Wojciech Drewek +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 41cc4e53934c30f1cf7745c257154e538c78a1f5) +[Adjust ice.h with the context change.] +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 2 + + drivers/net/ethernet/intel/ice/ice_devlink.c | 68 ++++++- + drivers/net/ethernet/intel/ice/ice_main.c | 186 ++++++------------- + 3 files changed, 125 insertions(+), 131 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 3278d032a2bd..d3f72f9fbcd7 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -978,6 +978,8 @@ int ice_stop(struct net_device *netdev); + void ice_service_task_schedule(struct ice_pf *pf); + int ice_load(struct ice_pf *pf); + void ice_unload(struct ice_pf *pf); ++int ice_init_dev(struct ice_pf *pf); ++void ice_deinit_dev(struct ice_pf *pf); + + /** + * ice_set_rdma_cap - enable RDMA support +diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c +index 3a2261823d93..43007e3674c4 100644 +--- a/drivers/net/ethernet/intel/ice/ice_devlink.c ++++ b/drivers/net/ethernet/intel/ice/ice_devlink.c +@@ -444,6 +444,20 @@ ice_devlink_reload_empr_start(struct ice_pf *pf, + return 0; + } + ++/** ++ * ice_devlink_reinit_down - unload given PF ++ * @pf: pointer to the PF struct ++ */ ++static void ice_devlink_reinit_down(struct ice_pf *pf) ++{ ++ /* No need to take devl_lock, it's already taken by devlink API */ ++ ice_unload(pf); ++ rtnl_lock(); ++ ice_vsi_decfg(ice_get_main_vsi(pf)); ++ rtnl_unlock(); ++ ice_deinit_dev(pf); ++} ++ + /** + * ice_devlink_reload_down - prepare for reload + * @devlink: pointer to the devlink instance to reload +@@ -477,7 +491,7 @@ ice_devlink_reload_down(struct devlink *devlink, bool netns_change, + "Remove all VFs before doing reinit\n"); + return -EOPNOTSUPP; + } +- ice_unload(pf); ++ ice_devlink_reinit_down(pf); + return 0; + case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: + return ice_devlink_reload_empr_start(pf, extack); +@@ -1240,6 +1254,45 @@ static int ice_devlink_set_parent(struct devlink_rate *devlink_rate, + return status; + } + ++/** ++ * ice_devlink_reinit_up - do reinit of the given PF ++ * @pf: pointer to the PF struct ++ */ ++static int ice_devlink_reinit_up(struct ice_pf *pf) ++{ ++ struct ice_vsi *vsi = ice_get_main_vsi(pf); ++ struct ice_vsi_cfg_params params; ++ int err; ++ ++ err = ice_init_dev(pf); ++ if (err) ++ return err; ++ ++ params = ice_vsi_to_params(vsi); ++ params.flags = ICE_VSI_FLAG_INIT; ++ ++ rtnl_lock(); ++ err = ice_vsi_cfg(vsi, ¶ms); ++ rtnl_unlock(); ++ if (err) ++ goto err_vsi_cfg; ++ ++ /* No need to take devl_lock, it's already taken by devlink API */ ++ err = ice_load(pf); ++ if (err) ++ goto err_load; ++ ++ return 0; ++ ++err_load: ++ rtnl_lock(); ++ ice_vsi_decfg(vsi); ++ rtnl_unlock(); ++err_vsi_cfg: ++ ice_deinit_dev(pf); ++ return err; ++} ++ + /** + * ice_devlink_reload_up - do reload up after reinit + * @devlink: pointer to the devlink instance reloading +@@ -1260,7 +1313,7 @@ ice_devlink_reload_up(struct devlink *devlink, + switch (action) { + case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: + *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); +- return ice_load(pf); ++ return ice_devlink_reinit_up(pf); + case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: + *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); + return ice_devlink_reload_empr_finish(pf, extack); +@@ -1540,6 +1593,7 @@ static const struct devlink_port_ops ice_devlink_port_ops = { + * @pf: the PF to create a devlink port for + * + * Create and register a devlink_port for this PF. ++ * This function has to be called under devl_lock. + * + * Return: zero on success or an error code on failure. + */ +@@ -1552,6 +1606,8 @@ int ice_devlink_create_pf_port(struct ice_pf *pf) + struct device *dev; + int err; + ++ devlink = priv_to_devlink(pf); ++ + dev = ice_pf_to_dev(pf); + + devlink_port = &pf->devlink_port; +@@ -1572,10 +1628,9 @@ int ice_devlink_create_pf_port(struct ice_pf *pf) + ice_devlink_set_switch_id(pf, &attrs.switch_id); + + devlink_port_attrs_set(devlink_port, &attrs); +- devlink = priv_to_devlink(pf); + +- err = devlink_port_register_with_ops(devlink, devlink_port, vsi->idx, +- &ice_devlink_port_ops); ++ err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx, ++ &ice_devlink_port_ops); + if (err) { + dev_err(dev, "Failed to create devlink port for PF %d, error %d\n", + pf->hw.pf_id, err); +@@ -1590,10 +1645,11 @@ int ice_devlink_create_pf_port(struct ice_pf *pf) + * @pf: the PF to cleanup + * + * Unregisters the devlink_port structure associated with this PF. ++ * This function has to be called under devl_lock. + */ + void ice_devlink_destroy_pf_port(struct ice_pf *pf) + { +- devlink_port_unregister(&pf->devlink_port); ++ devl_port_unregister(&pf->devlink_port); + } + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index a04dcc89c35d..d3340114297a 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -4588,90 +4588,6 @@ static void ice_decfg_netdev(struct ice_vsi *vsi) + vsi->netdev = NULL; + } + +-static int ice_start_eth(struct ice_vsi *vsi) +-{ +- int err; +- +- err = ice_init_mac_fltr(vsi->back); +- if (err) +- return err; +- +- err = ice_vsi_open(vsi); +- if (err) +- ice_fltr_remove_all(vsi); +- +- return err; +-} +- +-static void ice_stop_eth(struct ice_vsi *vsi) +-{ +- ice_fltr_remove_all(vsi); +- ice_vsi_close(vsi); +-} +- +-static int ice_init_eth(struct ice_pf *pf) +-{ +- struct ice_vsi *vsi = ice_get_main_vsi(pf); +- int err; +- +- if (!vsi) +- return -EINVAL; +- +- /* init channel list */ +- INIT_LIST_HEAD(&vsi->ch_list); +- +- err = ice_cfg_netdev(vsi); +- if (err) +- return err; +- /* Setup DCB netlink interface */ +- ice_dcbnl_setup(vsi); +- +- err = ice_init_mac_fltr(pf); +- if (err) +- goto err_init_mac_fltr; +- +- err = ice_devlink_create_pf_port(pf); +- if (err) +- goto err_devlink_create_pf_port; +- +- SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port); +- +- err = ice_register_netdev(vsi); +- if (err) +- goto err_register_netdev; +- +- err = ice_tc_indir_block_register(vsi); +- if (err) +- goto err_tc_indir_block_register; +- +- ice_napi_add(vsi); +- +- return 0; +- +-err_tc_indir_block_register: +- ice_unregister_netdev(vsi); +-err_register_netdev: +- ice_devlink_destroy_pf_port(pf); +-err_devlink_create_pf_port: +-err_init_mac_fltr: +- ice_decfg_netdev(vsi); +- return err; +-} +- +-static void ice_deinit_eth(struct ice_pf *pf) +-{ +- struct ice_vsi *vsi = ice_get_main_vsi(pf); +- +- if (!vsi) +- return; +- +- ice_vsi_close(vsi); +- ice_unregister_netdev(vsi); +- ice_devlink_destroy_pf_port(pf); +- ice_tc_indir_block_unregister(vsi); +- ice_decfg_netdev(vsi); +-} +- + /** + * ice_wait_for_fw - wait for full FW readiness + * @hw: pointer to the hardware structure +@@ -4697,7 +4613,7 @@ static int ice_wait_for_fw(struct ice_hw *hw, u32 timeout) + return -ETIMEDOUT; + } + +-static int ice_init_dev(struct ice_pf *pf) ++int ice_init_dev(struct ice_pf *pf) + { + struct device *dev = ice_pf_to_dev(pf); + struct ice_hw *hw = &pf->hw; +@@ -4790,7 +4706,7 @@ static int ice_init_dev(struct ice_pf *pf) + return err; + } + +-static void ice_deinit_dev(struct ice_pf *pf) ++void ice_deinit_dev(struct ice_pf *pf) + { + ice_free_irq_msix_misc(pf); + ice_deinit_pf(pf); +@@ -5091,31 +5007,47 @@ static void ice_deinit(struct ice_pf *pf) + /** + * ice_load - load pf by init hw and starting VSI + * @pf: pointer to the pf instance ++ * ++ * This function has to be called under devl_lock. + */ + int ice_load(struct ice_pf *pf) + { +- struct ice_vsi_cfg_params params = {}; + struct ice_vsi *vsi; + int err; + +- err = ice_init_dev(pf); ++ devl_assert_locked(priv_to_devlink(pf)); ++ ++ vsi = ice_get_main_vsi(pf); ++ ++ /* init channel list */ ++ INIT_LIST_HEAD(&vsi->ch_list); ++ ++ err = ice_cfg_netdev(vsi); + if (err) + return err; + +- vsi = ice_get_main_vsi(pf); ++ /* Setup DCB netlink interface */ ++ ice_dcbnl_setup(vsi); + +- params = ice_vsi_to_params(vsi); +- params.flags = ICE_VSI_FLAG_INIT; ++ err = ice_init_mac_fltr(pf); ++ if (err) ++ goto err_init_mac_fltr; + +- rtnl_lock(); +- err = ice_vsi_cfg(vsi, ¶ms); ++ err = ice_devlink_create_pf_port(pf); + if (err) +- goto err_vsi_cfg; ++ goto err_devlink_create_pf_port; + +- err = ice_start_eth(ice_get_main_vsi(pf)); ++ SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port); ++ ++ err = ice_register_netdev(vsi); ++ if (err) ++ goto err_register_netdev; ++ ++ err = ice_tc_indir_block_register(vsi); + if (err) +- goto err_start_eth; +- rtnl_unlock(); ++ goto err_tc_indir_block_register; ++ ++ ice_napi_add(vsi); + + err = ice_init_rdma(pf); + if (err) +@@ -5129,29 +5061,35 @@ int ice_load(struct ice_pf *pf) + return 0; + + err_init_rdma: +- ice_vsi_close(ice_get_main_vsi(pf)); +- rtnl_lock(); +-err_start_eth: +- ice_vsi_decfg(ice_get_main_vsi(pf)); +-err_vsi_cfg: +- rtnl_unlock(); +- ice_deinit_dev(pf); ++ ice_tc_indir_block_unregister(vsi); ++err_tc_indir_block_register: ++ ice_unregister_netdev(vsi); ++err_register_netdev: ++ ice_devlink_destroy_pf_port(pf); ++err_devlink_create_pf_port: ++err_init_mac_fltr: ++ ice_decfg_netdev(vsi); + return err; + } + + /** + * ice_unload - unload pf by stopping VSI and deinit hw + * @pf: pointer to the pf instance ++ * ++ * This function has to be called under devl_lock. + */ + void ice_unload(struct ice_pf *pf) + { ++ struct ice_vsi *vsi = ice_get_main_vsi(pf); ++ ++ devl_assert_locked(priv_to_devlink(pf)); ++ + ice_deinit_features(pf); + ice_deinit_rdma(pf); +- rtnl_lock(); +- ice_stop_eth(ice_get_main_vsi(pf)); +- ice_vsi_decfg(ice_get_main_vsi(pf)); +- rtnl_unlock(); +- ice_deinit_dev(pf); ++ ice_tc_indir_block_unregister(vsi); ++ ice_unregister_netdev(vsi); ++ ice_devlink_destroy_pf_port(pf); ++ ice_decfg_netdev(vsi); + } + + /** +@@ -5249,27 +5187,23 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) + if (err) + goto err_init; + +- err = ice_init_eth(pf); ++ devl_lock(priv_to_devlink(pf)); ++ err = ice_load(pf); ++ devl_unlock(priv_to_devlink(pf)); + if (err) +- goto err_init_eth; +- +- err = ice_init_rdma(pf); +- if (err) +- goto err_init_rdma; ++ goto err_load; + + err = ice_init_devlink(pf); + if (err) + goto err_init_devlink; + +- ice_init_features(pf); +- + return 0; + + err_init_devlink: +- ice_deinit_rdma(pf); +-err_init_rdma: +- ice_deinit_eth(pf); +-err_init_eth: ++ devl_lock(priv_to_devlink(pf)); ++ ice_unload(pf); ++ devl_unlock(priv_to_devlink(pf)); ++err_load: + ice_deinit(pf); + err_init: + pci_disable_device(pdev); +@@ -5363,12 +5297,14 @@ static void ice_remove(struct pci_dev *pdev) + + if (!ice_is_safe_mode(pf)) + ice_remove_arfs(pf); +- ice_deinit_features(pf); ++ + ice_deinit_devlink(pf); +- ice_deinit_rdma(pf); +- ice_deinit_eth(pf); +- ice_deinit(pf); + ++ devl_lock(priv_to_devlink(pf)); ++ ice_unload(pf); ++ devl_unlock(priv_to_devlink(pf)); ++ ++ ice_deinit(pf); + ice_vsi_release_all(pf); + + ice_setup_mc_magic_wake(pf); +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0024-ice-remove-FW-logging-code.patch b/kernel-rt/debian/patches/ice-VDF/0024-ice-remove-FW-logging-code.patch new file mode 100644 index 00000000..23bb1f17 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0024-ice-remove-FW-logging-code.patch @@ -0,0 +1,434 @@ +From e110839c4d9bfa4c885877a69573f48c008d3edd Mon Sep 17 00:00:00 2001 +From: Paul M Stillwell Jr +Date: Tue, 12 Dec 2023 21:07:11 -0800 +Subject: [PATCH 24/36] ice: remove FW logging code + +The FW logging code doesn't work because there is no way to set +cq_ena or uart_ena so remove the code. This code is the original +(v1) way of FW logging so it should be replaced with the v2 way. + +Signed-off-by: Paul M Stillwell Jr +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 1953fc720e603721764f31daae216a2851664167) +Signed-off-by: Jiping Ma +--- + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 78 ------- + drivers/net/ethernet/intel/ice/ice_common.c | 217 ------------------ + drivers/net/ethernet/intel/ice/ice_common.h | 1 - + drivers/net/ethernet/intel/ice/ice_main.c | 3 - + drivers/net/ethernet/intel/ice/ice_type.h | 20 -- + 5 files changed, 319 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 9bacb69ead8c..3b289e6a225b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2032,78 +2032,6 @@ struct ice_aqc_add_rdma_qset_data { + struct ice_aqc_add_tx_rdma_qset_entry rdma_qsets[]; + }; + +-/* Configure Firmware Logging Command (indirect 0xFF09) +- * Logging Information Read Response (indirect 0xFF10) +- * Note: The 0xFF10 command has no input parameters. +- */ +-struct ice_aqc_fw_logging { +- u8 log_ctrl; +-#define ICE_AQC_FW_LOG_AQ_EN BIT(0) +-#define ICE_AQC_FW_LOG_UART_EN BIT(1) +- u8 rsvd0; +- u8 log_ctrl_valid; /* Not used by 0xFF10 Response */ +-#define ICE_AQC_FW_LOG_AQ_VALID BIT(0) +-#define ICE_AQC_FW_LOG_UART_VALID BIT(1) +- u8 rsvd1[5]; +- __le32 addr_high; +- __le32 addr_low; +-}; +- +-enum ice_aqc_fw_logging_mod { +- ICE_AQC_FW_LOG_ID_GENERAL = 0, +- ICE_AQC_FW_LOG_ID_CTRL, +- ICE_AQC_FW_LOG_ID_LINK, +- ICE_AQC_FW_LOG_ID_LINK_TOPO, +- ICE_AQC_FW_LOG_ID_DNL, +- ICE_AQC_FW_LOG_ID_I2C, +- ICE_AQC_FW_LOG_ID_SDP, +- ICE_AQC_FW_LOG_ID_MDIO, +- ICE_AQC_FW_LOG_ID_ADMINQ, +- ICE_AQC_FW_LOG_ID_HDMA, +- ICE_AQC_FW_LOG_ID_LLDP, +- ICE_AQC_FW_LOG_ID_DCBX, +- ICE_AQC_FW_LOG_ID_DCB, +- ICE_AQC_FW_LOG_ID_NETPROXY, +- ICE_AQC_FW_LOG_ID_NVM, +- ICE_AQC_FW_LOG_ID_AUTH, +- ICE_AQC_FW_LOG_ID_VPD, +- ICE_AQC_FW_LOG_ID_IOSF, +- ICE_AQC_FW_LOG_ID_PARSER, +- ICE_AQC_FW_LOG_ID_SW, +- ICE_AQC_FW_LOG_ID_SCHEDULER, +- ICE_AQC_FW_LOG_ID_TXQ, +- ICE_AQC_FW_LOG_ID_RSVD, +- ICE_AQC_FW_LOG_ID_POST, +- ICE_AQC_FW_LOG_ID_WATCHDOG, +- ICE_AQC_FW_LOG_ID_TASK_DISPATCH, +- ICE_AQC_FW_LOG_ID_MNG, +- ICE_AQC_FW_LOG_ID_MAX, +-}; +- +-/* Defines for both above FW logging command/response buffers */ +-#define ICE_AQC_FW_LOG_ID_S 0 +-#define ICE_AQC_FW_LOG_ID_M (0xFFF << ICE_AQC_FW_LOG_ID_S) +- +-#define ICE_AQC_FW_LOG_CONF_SUCCESS 0 /* Used by response */ +-#define ICE_AQC_FW_LOG_CONF_BAD_INDX BIT(12) /* Used by response */ +- +-#define ICE_AQC_FW_LOG_EN_S 12 +-#define ICE_AQC_FW_LOG_EN_M (0xF << ICE_AQC_FW_LOG_EN_S) +-#define ICE_AQC_FW_LOG_INFO_EN BIT(12) /* Used by command */ +-#define ICE_AQC_FW_LOG_INIT_EN BIT(13) /* Used by command */ +-#define ICE_AQC_FW_LOG_FLOW_EN BIT(14) /* Used by command */ +-#define ICE_AQC_FW_LOG_ERR_EN BIT(15) /* Used by command */ +- +-/* Get/Clear FW Log (indirect 0xFF11) */ +-struct ice_aqc_get_clear_fw_log { +- u8 flags; +-#define ICE_AQC_FW_LOG_CLEAR BIT(0) +-#define ICE_AQC_FW_LOG_MORE_DATA_AVAIL BIT(1) +- u8 rsvd1[7]; +- __le32 addr_high; +- __le32 addr_low; +-}; +- + /* Download Package (indirect 0x0C40) */ + /* Also used for Update Package (indirect 0x0C41 and 0x0C42) */ + struct ice_aqc_download_pkg { +@@ -2448,8 +2376,6 @@ struct ice_aq_desc { + struct ice_aqc_add_rdma_qset add_rdma_qset; + struct ice_aqc_add_get_update_free_vsi vsi_cmd; + struct ice_aqc_add_update_free_vsi_resp add_update_free_vsi_res; +- struct ice_aqc_fw_logging fw_logging; +- struct ice_aqc_get_clear_fw_log get_clear_fw_log; + struct ice_aqc_download_pkg download_pkg; + struct ice_aqc_set_cgu_input_config set_cgu_input_config; + struct ice_aqc_get_cgu_input_config get_cgu_input_config; +@@ -2657,10 +2583,6 @@ enum ice_adminq_opc { + + /* Standalone Commands/Events */ + ice_aqc_opc_event_lan_overflow = 0x1001, +- +- /* debug commands */ +- ice_aqc_opc_fw_logging = 0xFF09, +- ice_aqc_opc_fw_logging_info = 0xFF10, + }; + + #endif /* _ICE_ADMINQ_CMD_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index acf6ac00f804..a5c4b7ad6a20 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -897,216 +897,6 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw) + devm_kfree(ice_hw_to_dev(hw), sw); + } + +-/** +- * ice_get_fw_log_cfg - get FW logging configuration +- * @hw: pointer to the HW struct +- */ +-static int ice_get_fw_log_cfg(struct ice_hw *hw) +-{ +- struct ice_aq_desc desc; +- __le16 *config; +- int status; +- u16 size; +- +- size = sizeof(*config) * ICE_AQC_FW_LOG_ID_MAX; +- config = kzalloc(size, GFP_KERNEL); +- if (!config) +- return -ENOMEM; +- +- ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging_info); +- +- status = ice_aq_send_cmd(hw, &desc, config, size, NULL); +- if (!status) { +- u16 i; +- +- /* Save FW logging information into the HW structure */ +- for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { +- u16 v, m, flgs; +- +- v = le16_to_cpu(config[i]); +- m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S; +- flgs = (v & ICE_AQC_FW_LOG_EN_M) >> ICE_AQC_FW_LOG_EN_S; +- +- if (m < ICE_AQC_FW_LOG_ID_MAX) +- hw->fw_log.evnts[m].cur = flgs; +- } +- } +- +- kfree(config); +- +- return status; +-} +- +-/** +- * ice_cfg_fw_log - configure FW logging +- * @hw: pointer to the HW struct +- * @enable: enable certain FW logging events if true, disable all if false +- * +- * This function enables/disables the FW logging via Rx CQ events and a UART +- * port based on predetermined configurations. FW logging via the Rx CQ can be +- * enabled/disabled for individual PF's. However, FW logging via the UART can +- * only be enabled/disabled for all PFs on the same device. +- * +- * To enable overall FW logging, the "cq_en" and "uart_en" enable bits in +- * hw->fw_log need to be set accordingly, e.g. based on user-provided input, +- * before initializing the device. +- * +- * When re/configuring FW logging, callers need to update the "cfg" elements of +- * the hw->fw_log.evnts array with the desired logging event configurations for +- * modules of interest. When disabling FW logging completely, the callers can +- * just pass false in the "enable" parameter. On completion, the function will +- * update the "cur" element of the hw->fw_log.evnts array with the resulting +- * logging event configurations of the modules that are being re/configured. FW +- * logging modules that are not part of a reconfiguration operation retain their +- * previous states. +- * +- * Before resetting the device, it is recommended that the driver disables FW +- * logging before shutting down the control queue. When disabling FW logging +- * ("enable" = false), the latest configurations of FW logging events stored in +- * hw->fw_log.evnts[] are not overridden to allow them to be reconfigured after +- * a device reset. +- * +- * When enabling FW logging to emit log messages via the Rx CQ during the +- * device's initialization phase, a mechanism alternative to interrupt handlers +- * needs to be used to extract FW log messages from the Rx CQ periodically and +- * to prevent the Rx CQ from being full and stalling other types of control +- * messages from FW to SW. Interrupts are typically disabled during the device's +- * initialization phase. +- */ +-static int ice_cfg_fw_log(struct ice_hw *hw, bool enable) +-{ +- struct ice_aqc_fw_logging *cmd; +- u16 i, chgs = 0, len = 0; +- struct ice_aq_desc desc; +- __le16 *data = NULL; +- u8 actv_evnts = 0; +- void *buf = NULL; +- int status = 0; +- +- if (!hw->fw_log.cq_en && !hw->fw_log.uart_en) +- return 0; +- +- /* Disable FW logging only when the control queue is still responsive */ +- if (!enable && +- (!hw->fw_log.actv_evnts || !ice_check_sq_alive(hw, &hw->adminq))) +- return 0; +- +- /* Get current FW log settings */ +- status = ice_get_fw_log_cfg(hw); +- if (status) +- return status; +- +- ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging); +- cmd = &desc.params.fw_logging; +- +- /* Indicate which controls are valid */ +- if (hw->fw_log.cq_en) +- cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_AQ_VALID; +- +- if (hw->fw_log.uart_en) +- cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_UART_VALID; +- +- if (enable) { +- /* Fill in an array of entries with FW logging modules and +- * logging events being reconfigured. +- */ +- for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { +- u16 val; +- +- /* Keep track of enabled event types */ +- actv_evnts |= hw->fw_log.evnts[i].cfg; +- +- if (hw->fw_log.evnts[i].cfg == hw->fw_log.evnts[i].cur) +- continue; +- +- if (!data) { +- data = devm_kcalloc(ice_hw_to_dev(hw), +- ICE_AQC_FW_LOG_ID_MAX, +- sizeof(*data), +- GFP_KERNEL); +- if (!data) +- return -ENOMEM; +- } +- +- val = i << ICE_AQC_FW_LOG_ID_S; +- val |= hw->fw_log.evnts[i].cfg << ICE_AQC_FW_LOG_EN_S; +- data[chgs++] = cpu_to_le16(val); +- } +- +- /* Only enable FW logging if at least one module is specified. +- * If FW logging is currently enabled but all modules are not +- * enabled to emit log messages, disable FW logging altogether. +- */ +- if (actv_evnts) { +- /* Leave if there is effectively no change */ +- if (!chgs) +- goto out; +- +- if (hw->fw_log.cq_en) +- cmd->log_ctrl |= ICE_AQC_FW_LOG_AQ_EN; +- +- if (hw->fw_log.uart_en) +- cmd->log_ctrl |= ICE_AQC_FW_LOG_UART_EN; +- +- buf = data; +- len = sizeof(*data) * chgs; +- desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); +- } +- } +- +- status = ice_aq_send_cmd(hw, &desc, buf, len, NULL); +- if (!status) { +- /* Update the current configuration to reflect events enabled. +- * hw->fw_log.cq_en and hw->fw_log.uart_en indicate if the FW +- * logging mode is enabled for the device. They do not reflect +- * actual modules being enabled to emit log messages. So, their +- * values remain unchanged even when all modules are disabled. +- */ +- u16 cnt = enable ? chgs : (u16)ICE_AQC_FW_LOG_ID_MAX; +- +- hw->fw_log.actv_evnts = actv_evnts; +- for (i = 0; i < cnt; i++) { +- u16 v, m; +- +- if (!enable) { +- /* When disabling all FW logging events as part +- * of device's de-initialization, the original +- * configurations are retained, and can be used +- * to reconfigure FW logging later if the device +- * is re-initialized. +- */ +- hw->fw_log.evnts[i].cur = 0; +- continue; +- } +- +- v = le16_to_cpu(data[i]); +- m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S; +- hw->fw_log.evnts[m].cur = hw->fw_log.evnts[m].cfg; +- } +- } +- +-out: +- devm_kfree(ice_hw_to_dev(hw), data); +- +- return status; +-} +- +-/** +- * ice_output_fw_log +- * @hw: pointer to the HW struct +- * @desc: pointer to the AQ message descriptor +- * @buf: pointer to the buffer accompanying the AQ message +- * +- * Formats a FW Log message and outputs it via the standard driver logs. +- */ +-void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf) +-{ +- ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg Start ]\n"); +- ice_debug_array(hw, ICE_DBG_FW_LOG, 16, 1, (u8 *)buf, +- le16_to_cpu(desc->datalen)); +- ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg End ]\n"); +-} +- + /** + * ice_get_itr_intrl_gran + * @hw: pointer to the HW struct +@@ -1164,11 +954,6 @@ int ice_init_hw(struct ice_hw *hw) + if (status) + goto err_unroll_cqinit; + +- /* Enable FW logging. Not fatal if this fails. */ +- status = ice_cfg_fw_log(hw, true); +- if (status) +- ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging.\n"); +- + status = ice_clear_pf_cfg(hw); + if (status) + goto err_unroll_cqinit; +@@ -1318,8 +1103,6 @@ void ice_deinit_hw(struct ice_hw *hw) + ice_free_hw_tbls(hw); + mutex_destroy(&hw->tnl_lock); + +- /* Attempt to disable FW logging before shutting down control queues */ +- ice_cfg_fw_log(hw, false); + ice_destroy_all_ctrlq(hw); + + /* Clear VSI contexts if not already cleared */ +diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h +index 7a966a0c224f..d47e5400351f 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.h ++++ b/drivers/net/ethernet/intel/ice/ice_common.h +@@ -199,7 +199,6 @@ ice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf, + struct ice_sq_cd *cd); + int ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle); + void ice_replay_post(struct ice_hw *hw); +-void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf); + struct ice_q_ctx * + ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle); + int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in); +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index d3340114297a..e5cc9790969c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -1535,9 +1535,6 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) + + ice_vc_process_vf_msg(pf, &event, &data); + break; +- case ice_aqc_opc_fw_logging: +- ice_output_fw_log(hw, &event.desc, event.msg_buf); +- break; + case ice_aqc_opc_lldp_set_mib_change: + ice_dcb_process_lldp_set_mib_change(pf, &event); + break; +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index b0f1f4db1d8b..6e1fed0d7384 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -731,24 +731,6 @@ struct ice_switch_info { + DECLARE_BITMAP(prof_res_bm[ICE_MAX_NUM_PROFILES], ICE_MAX_FV_WORDS); + }; + +-/* FW logging configuration */ +-struct ice_fw_log_evnt { +- u8 cfg : 4; /* New event enables to configure */ +- u8 cur : 4; /* Current/active event enables */ +-}; +- +-struct ice_fw_log_cfg { +- u8 cq_en : 1; /* FW logging is enabled via the control queue */ +- u8 uart_en : 1; /* FW logging is enabled via UART for all PFs */ +- u8 actv_evnts; /* Cumulation of currently enabled log events */ +- +-#define ICE_FW_LOG_EVNT_INFO (ICE_AQC_FW_LOG_INFO_EN >> ICE_AQC_FW_LOG_EN_S) +-#define ICE_FW_LOG_EVNT_INIT (ICE_AQC_FW_LOG_INIT_EN >> ICE_AQC_FW_LOG_EN_S) +-#define ICE_FW_LOG_EVNT_FLOW (ICE_AQC_FW_LOG_FLOW_EN >> ICE_AQC_FW_LOG_EN_S) +-#define ICE_FW_LOG_EVNT_ERR (ICE_AQC_FW_LOG_ERR_EN >> ICE_AQC_FW_LOG_EN_S) +- struct ice_fw_log_evnt evnts[ICE_AQC_FW_LOG_ID_MAX]; +-}; +- + /* Enum defining the different states of the mailbox snapshot in the + * PF-VF mailbox overflow detection algorithm. The snapshot can be in + * states: +@@ -890,8 +872,6 @@ struct ice_hw { + u8 fw_patch; /* firmware patch version */ + u32 fw_build; /* firmware build number */ + +- struct ice_fw_log_cfg fw_log; +- + /* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL + * register. Used for determining the ITR/INTRL granularity during + * initialization. +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0025-ice-configure-FW-logging.patch b/kernel-rt/debian/patches/ice-VDF/0025-ice-configure-FW-logging.patch new file mode 100644 index 00000000..203cc8e8 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0025-ice-configure-FW-logging.patch @@ -0,0 +1,1083 @@ +From 752f352c0d7da9c6c07e4c8364082e201d20fdc2 Mon Sep 17 00:00:00 2001 +From: Paul M Stillwell Jr +Date: Tue, 12 Dec 2023 21:07:12 -0800 +Subject: [PATCH 25/36] ice: configure FW logging + +Users want the ability to debug FW issues by retrieving the +FW logs from the E8xx devices. Use debugfs to allow the user to +configure the log level and number of messages for FW logging. + +If FW logging is supported on the E8xx then the file 'fwlog' will be +created under the PCI device ID for the ice driver. If the file does not +exist then either the E8xx doesn't support FW logging or debugfs is not +enabled on the system. + +One thing users want to do is control which events are reported. The +user can read and write the 'fwlog/modules/' to get/set +the log levels. Each module in the FW that supports logging ht as a file +under 'fwlog/modules' that supports reading (to see what the current log +level is) and writing (to change the log level). + +The format to set the log levels for a module are: + + # echo > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/ + +The supported log levels are: + + * none + * error + * warning + * normal + * verbose + +Each level includes the messages from the previous/lower level + +The modules that are supported are: + + * general + * ctrl + * link + * link_topo + * dnl + * i2c + * sdp + * mdio + * adminq + * hdma + * lldp + * dcbx + * dcb + * xlr + * nvm + * auth + * vpd + * iosf + * parser + * sw + * scheduler + * txq + * rsvd + * post + * watchdog + * task_dispatch + * mng + * synce + * health + * tsdrv + * pfreg + * mdlver + * all + +The module 'all' is a special module which allows the user to read or +write to all of the modules. + +The following example command would set the DCB module to the 'normal' +log level: + + # echo normal > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/dcb + +If the user wants to set the DCB, Link, and the AdminQ modules to +'verbose' then the commands are: + + # echo verbose > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/dcb + # echo verbose > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/link + # echo verbose > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/adminq + +If the user wants to set all modules to the 'warning' level then the +command is: + + # echo warning > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/all + +If the user wants to disable logging for a module then they can set the +level to 'none'. An example setting the 'watchdog' module is: + + # echo none > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/watchdog + +If the user wants to see what the log level is for a specific module +then the command is: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/dcb + +This will return the log level for the DCB module. If the user wants to +see the log level for all the modules then the command is: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/all + +Writing to the module file will update the configuration, but NOT enable the +configuration (that is a separate command). + +In addition to configuring the modules, the user can also configure the +number of log messages (nr_messages) to include in a single Admin Receive +Queue (ARQ) event.The range is 1-128 (1 means push every log message, 128 +means push only when the max AQ command buffer is full). The suggested +value is 10. + +To see/change the resolution the user can read/write the +'fwlog/nr_messages' file. An example changing the value to 50 is + + # echo 50 > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/nr_messages + +To see the current value of 'nr_messages' then the command is: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/nr_messages + +Signed-off-by: Paul M Stillwell Jr +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 96a9a9341cdaea0c3bce4c134e04a2a42ae899ac) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/Makefile | 4 +- + drivers/net/ethernet/intel/ice/ice.h | 9 + + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 80 ++++ + drivers/net/ethernet/intel/ice/ice_common.c | 6 + + drivers/net/ethernet/intel/ice/ice_debugfs.c | 359 ++++++++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.c | 261 +++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.h | 56 +++ + drivers/net/ethernet/intel/ice/ice_main.c | 18 + + drivers/net/ethernet/intel/ice/ice_type.h | 4 + + 9 files changed, 796 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/ethernet/intel/ice/ice_debugfs.c + create mode 100644 drivers/net/ethernet/intel/ice/ice_fwlog.c + create mode 100644 drivers/net/ethernet/intel/ice/ice_fwlog.h + +diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile +index 0679907980f7..8757bec23fb3 100644 +--- a/drivers/net/ethernet/intel/ice/Makefile ++++ b/drivers/net/ethernet/intel/ice/Makefile +@@ -34,7 +34,9 @@ ice-y := ice_main.o \ + ice_lag.o \ + ice_ethtool.o \ + ice_repr.o \ +- ice_tc_lib.o ++ ice_tc_lib.o \ ++ ice_fwlog.o \ ++ ice_debugfs.o + ice-$(CONFIG_PCI_IOV) += \ + ice_sriov.o \ + ice_virtchnl.o \ +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index d3f72f9fbcd7..7966ac61154c 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -559,6 +559,10 @@ struct ice_pf { + struct ice_vsi_stats **vsi_stats; + struct ice_sw *first_sw; /* first switch created by firmware */ + u16 eswitch_mode; /* current mode of eswitch */ ++ struct dentry *ice_debugfs_pf; ++ struct dentry *ice_debugfs_pf_fwlog; ++ /* keep track of all the dentrys for FW log modules */ ++ struct dentry **ice_debugfs_pf_fwlog_modules; + struct ice_vfs vfs; + DECLARE_BITMAP(features, ICE_F_MAX); + DECLARE_BITMAP(state, ICE_STATE_NBITS); +@@ -890,6 +894,11 @@ static inline bool ice_is_adq_active(struct ice_pf *pf) + return false; + } + ++void ice_debugfs_fwlog_init(struct ice_pf *pf); ++void ice_debugfs_init(void); ++void ice_debugfs_exit(void); ++void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module); ++ + bool netif_is_ice(const struct net_device *dev); + int ice_vsi_setup_tx_rings(struct ice_vsi *vsi); + int ice_vsi_setup_rx_rings(struct ice_vsi *vsi); +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 3b289e6a225b..347e4fed5e0d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2299,6 +2299,81 @@ struct ice_aqc_event_lan_overflow { + u8 reserved[8]; + }; + ++enum ice_aqc_fw_logging_mod { ++ ICE_AQC_FW_LOG_ID_GENERAL = 0, ++ ICE_AQC_FW_LOG_ID_CTRL, ++ ICE_AQC_FW_LOG_ID_LINK, ++ ICE_AQC_FW_LOG_ID_LINK_TOPO, ++ ICE_AQC_FW_LOG_ID_DNL, ++ ICE_AQC_FW_LOG_ID_I2C, ++ ICE_AQC_FW_LOG_ID_SDP, ++ ICE_AQC_FW_LOG_ID_MDIO, ++ ICE_AQC_FW_LOG_ID_ADMINQ, ++ ICE_AQC_FW_LOG_ID_HDMA, ++ ICE_AQC_FW_LOG_ID_LLDP, ++ ICE_AQC_FW_LOG_ID_DCBX, ++ ICE_AQC_FW_LOG_ID_DCB, ++ ICE_AQC_FW_LOG_ID_XLR, ++ ICE_AQC_FW_LOG_ID_NVM, ++ ICE_AQC_FW_LOG_ID_AUTH, ++ ICE_AQC_FW_LOG_ID_VPD, ++ ICE_AQC_FW_LOG_ID_IOSF, ++ ICE_AQC_FW_LOG_ID_PARSER, ++ ICE_AQC_FW_LOG_ID_SW, ++ ICE_AQC_FW_LOG_ID_SCHEDULER, ++ ICE_AQC_FW_LOG_ID_TXQ, ++ ICE_AQC_FW_LOG_ID_RSVD, ++ ICE_AQC_FW_LOG_ID_POST, ++ ICE_AQC_FW_LOG_ID_WATCHDOG, ++ ICE_AQC_FW_LOG_ID_TASK_DISPATCH, ++ ICE_AQC_FW_LOG_ID_MNG, ++ ICE_AQC_FW_LOG_ID_SYNCE, ++ ICE_AQC_FW_LOG_ID_HEALTH, ++ ICE_AQC_FW_LOG_ID_TSDRV, ++ ICE_AQC_FW_LOG_ID_PFREG, ++ ICE_AQC_FW_LOG_ID_MDLVER, ++ ICE_AQC_FW_LOG_ID_MAX, ++}; ++ ++/* Set FW Logging configuration (indirect 0xFF30) ++ * Query FW Logging (indirect 0xFF32) ++ */ ++struct ice_aqc_fw_log { ++ u8 cmd_flags; ++#define ICE_AQC_FW_LOG_CONF_UART_EN BIT(0) ++#define ICE_AQC_FW_LOG_CONF_AQ_EN BIT(1) ++#define ICE_AQC_FW_LOG_QUERY_REGISTERED BIT(2) ++#define ICE_AQC_FW_LOG_CONF_SET_VALID BIT(3) ++#define ICE_AQC_FW_LOG_AQ_QUERY BIT(2) ++ ++ u8 rsp_flag; ++ __le16 fw_rt_msb; ++ union { ++ struct { ++ __le32 fw_rt_lsb; ++ } sync; ++ struct { ++ __le16 log_resolution; ++#define ICE_AQC_FW_LOG_MIN_RESOLUTION (1) ++#define ICE_AQC_FW_LOG_MAX_RESOLUTION (128) ++ ++ __le16 mdl_cnt; ++ } cfg; ++ } ops; ++ __le32 addr_high; ++ __le32 addr_low; ++}; ++ ++/* Response Buffer for: ++ * Set Firmware Logging Configuration (0xFF30) ++ * Query FW Logging (0xFF32) ++ */ ++struct ice_aqc_fw_log_cfg_resp { ++ __le16 module_identifier; ++ u8 log_level; ++ u8 rsvd0; ++}; ++ + /** + * struct ice_aq_desc - Admin Queue (AQ) descriptor + * @flags: ICE_AQ_FLAG_* flags +@@ -2387,6 +2462,7 @@ struct ice_aq_desc { + struct ice_aqc_get_cgu_ref_prio get_cgu_ref_prio; + struct ice_aqc_get_cgu_info get_cgu_info; + struct ice_aqc_driver_shared_params drv_shared_params; ++ struct ice_aqc_fw_log fw_log; + struct ice_aqc_set_mac_lb set_mac_lb; + struct ice_aqc_alloc_free_res_cmd sw_res_ctrl; + struct ice_aqc_set_mac_cfg set_mac_cfg; +@@ -2583,6 +2659,10 @@ enum ice_adminq_opc { + + /* Standalone Commands/Events */ + ice_aqc_opc_event_lan_overflow = 0x1001, ++ ++ /* FW Logging Commands */ ++ ice_aqc_opc_fw_logs_config = 0xFF30, ++ ice_aqc_opc_fw_logs_query = 0xFF32, + }; + + #endif /* _ICE_ADMINQ_CMD_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index a5c4b7ad6a20..6dcba0577633 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -954,6 +954,11 @@ int ice_init_hw(struct ice_hw *hw) + if (status) + goto err_unroll_cqinit; + ++ status = ice_fwlog_init(hw); ++ if (status) ++ ice_debug(hw, ICE_DBG_FW_LOG, "Error initializing FW logging: %d\n", ++ status); ++ + status = ice_clear_pf_cfg(hw); + if (status) + goto err_unroll_cqinit; +@@ -1103,6 +1108,7 @@ void ice_deinit_hw(struct ice_hw *hw) + ice_free_hw_tbls(hw); + mutex_destroy(&hw->tnl_lock); + ++ ice_fwlog_deinit(hw); + ice_destroy_all_ctrlq(hw); + + /* Clear VSI contexts if not already cleared */ +diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c +new file mode 100644 +index 000000000000..3b0d9b214fd1 +--- /dev/null ++++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c +@@ -0,0 +1,359 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* Copyright (c) 2022, Intel Corporation. */ ++ ++#include ++#include ++#include ++#include ++#include "ice.h" ++ ++static struct dentry *ice_debugfs_root; ++ ++/* create a define that has an extra module that doesn't really exist. this ++ * is so we can add a module 'all' to easily enable/disable all the modules ++ */ ++#define ICE_NR_FW_LOG_MODULES (ICE_AQC_FW_LOG_ID_MAX + 1) ++ ++/* the ordering in this array is important. it matches the ordering of the ++ * values in the FW so the index is the same value as in ice_aqc_fw_logging_mod ++ */ ++static const char * const ice_fwlog_module_string[] = { ++ "general", ++ "ctrl", ++ "link", ++ "link_topo", ++ "dnl", ++ "i2c", ++ "sdp", ++ "mdio", ++ "adminq", ++ "hdma", ++ "lldp", ++ "dcbx", ++ "dcb", ++ "xlr", ++ "nvm", ++ "auth", ++ "vpd", ++ "iosf", ++ "parser", ++ "sw", ++ "scheduler", ++ "txq", ++ "rsvd", ++ "post", ++ "watchdog", ++ "task_dispatch", ++ "mng", ++ "synce", ++ "health", ++ "tsdrv", ++ "pfreg", ++ "mdlver", ++ "all", ++}; ++ ++/* the ordering in this array is important. it matches the ordering of the ++ * values in the FW so the index is the same value as in ice_fwlog_level ++ */ ++static const char * const ice_fwlog_level_string[] = { ++ "none", ++ "error", ++ "warning", ++ "normal", ++ "verbose", ++}; ++ ++/** ++ * ice_fwlog_print_module_cfg - print current FW logging module configuration ++ * @hw: pointer to the HW structure ++ * @module: module to print ++ * @s: the seq file to put data into ++ */ ++static void ++ice_fwlog_print_module_cfg(struct ice_hw *hw, int module, struct seq_file *s) ++{ ++ struct ice_fwlog_cfg *cfg = &hw->fwlog_cfg; ++ struct ice_fwlog_module_entry *entry; ++ ++ if (module != ICE_AQC_FW_LOG_ID_MAX) { ++ entry = &cfg->module_entries[module]; ++ ++ seq_printf(s, "\tModule: %s, Log Level: %s\n", ++ ice_fwlog_module_string[entry->module_id], ++ ice_fwlog_level_string[entry->log_level]); ++ } else { ++ int i; ++ ++ for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { ++ entry = &cfg->module_entries[i]; ++ ++ seq_printf(s, "\tModule: %s, Log Level: %s\n", ++ ice_fwlog_module_string[entry->module_id], ++ ice_fwlog_level_string[entry->log_level]); ++ } ++ } ++} ++ ++static int ice_find_module_by_dentry(struct ice_pf *pf, struct dentry *d) ++{ ++ int i, module; ++ ++ module = -1; ++ /* find the module based on the dentry */ ++ for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) { ++ if (d == pf->ice_debugfs_pf_fwlog_modules[i]) { ++ module = i; ++ break; ++ } ++ } ++ ++ return module; ++} ++ ++/** ++ * ice_debugfs_module_show - read from 'module' file ++ * @s: the opened file ++ * @v: pointer to the offset ++ */ ++static int ice_debugfs_module_show(struct seq_file *s, void *v) ++{ ++ const struct file *filp = s->file; ++ struct dentry *dentry; ++ struct ice_pf *pf; ++ int module; ++ ++ dentry = file_dentry(filp); ++ pf = s->private; ++ ++ module = ice_find_module_by_dentry(pf, dentry); ++ if (module < 0) { ++ dev_info(ice_pf_to_dev(pf), "unknown module\n"); ++ return -EINVAL; ++ } ++ ++ ice_fwlog_print_module_cfg(&pf->hw, module, s); ++ ++ return 0; ++} ++ ++static int ice_debugfs_module_open(struct inode *inode, struct file *filp) ++{ ++ return single_open(filp, ice_debugfs_module_show, inode->i_private); ++} ++ ++/** ++ * ice_debugfs_module_write - write into 'module' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_module_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = file_inode(filp)->i_private; ++ struct dentry *dentry = file_dentry(filp); ++ struct device *dev = ice_pf_to_dev(pf); ++ char user_val[16], *cmd_buf; ++ int module, log_level, cnt; ++ ++ /* don't allow partial writes or invalid input */ ++ if (*ppos != 0 || count > 8) ++ return -EINVAL; ++ ++ cmd_buf = memdup_user(buf, count); ++ if (IS_ERR(cmd_buf)) ++ return PTR_ERR(cmd_buf); ++ ++ module = ice_find_module_by_dentry(pf, dentry); ++ if (module < 0) { ++ dev_info(dev, "unknown module\n"); ++ return -EINVAL; ++ } ++ ++ cnt = sscanf(cmd_buf, "%s", user_val); ++ if (cnt != 1) ++ return -EINVAL; ++ ++ log_level = sysfs_match_string(ice_fwlog_level_string, user_val); ++ if (log_level < 0) { ++ dev_info(dev, "unknown log level '%s'\n", user_val); ++ return -EINVAL; ++ } ++ ++ if (module != ICE_AQC_FW_LOG_ID_MAX) { ++ ice_pf_fwlog_update_module(pf, log_level, module); ++ } else { ++ /* the module 'all' is a shortcut so that we can set ++ * all of the modules to the same level quickly ++ */ ++ int i; ++ ++ for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) ++ ice_pf_fwlog_update_module(pf, log_level, i); ++ } ++ ++ return count; ++} ++ ++static const struct file_operations ice_debugfs_module_fops = { ++ .owner = THIS_MODULE, ++ .open = ice_debugfs_module_open, ++ .read = seq_read, ++ .release = single_release, ++ .write = ice_debugfs_module_write, ++}; ++ ++/** ++ * ice_debugfs_nr_messages_read - read from 'nr_messages' file ++ * @filp: the opened file ++ * @buffer: where to write the data for the user to read ++ * @count: the size of the user's buffer ++ * @ppos: file position offset ++ */ ++static ssize_t ice_debugfs_nr_messages_read(struct file *filp, ++ char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ char buff[32] = {}; ++ ++ snprintf(buff, sizeof(buff), "%d\n", ++ hw->fwlog_cfg.log_resolution); ++ ++ return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); ++} ++ ++/** ++ * ice_debugfs_nr_messages_write - write into 'nr_messages' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_nr_messages_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct device *dev = ice_pf_to_dev(pf); ++ struct ice_hw *hw = &pf->hw; ++ char user_val[8], *cmd_buf; ++ s16 nr_messages; ++ ssize_t ret; ++ ++ /* don't allow partial writes or invalid input */ ++ if (*ppos != 0 || count > 4) ++ return -EINVAL; ++ ++ cmd_buf = memdup_user(buf, count); ++ if (IS_ERR(cmd_buf)) ++ return PTR_ERR(cmd_buf); ++ ++ ret = sscanf(cmd_buf, "%s", user_val); ++ if (ret != 1) ++ return -EINVAL; ++ ++ ret = kstrtos16(user_val, 0, &nr_messages); ++ if (ret) ++ return ret; ++ ++ if (nr_messages < ICE_AQC_FW_LOG_MIN_RESOLUTION || ++ nr_messages > ICE_AQC_FW_LOG_MAX_RESOLUTION) { ++ dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", ++ nr_messages, ICE_AQC_FW_LOG_MIN_RESOLUTION, ++ ICE_AQC_FW_LOG_MAX_RESOLUTION); ++ return -EINVAL; ++ } ++ ++ hw->fwlog_cfg.log_resolution = nr_messages; ++ ++ return count; ++} ++ ++static const struct file_operations ice_debugfs_nr_messages_fops = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .read = ice_debugfs_nr_messages_read, ++ .write = ice_debugfs_nr_messages_write, ++}; ++ ++/** ++ * ice_debugfs_fwlog_init - setup the debugfs directory ++ * @pf: the ice that is starting up ++ */ ++void ice_debugfs_fwlog_init(struct ice_pf *pf) ++{ ++ const char *name = pci_name(pf->pdev); ++ struct dentry *fw_modules_dir; ++ struct dentry **fw_modules; ++ int i; ++ ++ /* only support fw log commands on PF 0 */ ++ if (pf->hw.bus.func) ++ return; ++ ++ /* allocate space for this first because if it fails then we don't ++ * need to unwind ++ */ ++ fw_modules = kcalloc(ICE_NR_FW_LOG_MODULES, sizeof(*fw_modules), ++ GFP_KERNEL); ++ if (!fw_modules) ++ return; ++ ++ pf->ice_debugfs_pf = debugfs_create_dir(name, ice_debugfs_root); ++ if (IS_ERR(pf->ice_debugfs_pf)) ++ goto err_create_module_files; ++ ++ pf->ice_debugfs_pf_fwlog = debugfs_create_dir("fwlog", ++ pf->ice_debugfs_pf); ++ if (IS_ERR(pf->ice_debugfs_pf)) ++ goto err_create_module_files; ++ ++ fw_modules_dir = debugfs_create_dir("modules", ++ pf->ice_debugfs_pf_fwlog); ++ if (IS_ERR(fw_modules_dir)) ++ goto err_create_module_files; ++ ++ for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) { ++ fw_modules[i] = debugfs_create_file(ice_fwlog_module_string[i], ++ 0600, fw_modules_dir, pf, ++ &ice_debugfs_module_fops); ++ if (IS_ERR(fw_modules[i])) ++ goto err_create_module_files; ++ } ++ ++ debugfs_create_file("nr_messages", 0600, ++ pf->ice_debugfs_pf_fwlog, pf, ++ &ice_debugfs_nr_messages_fops); ++ ++ pf->ice_debugfs_pf_fwlog_modules = fw_modules; ++ ++ return; ++ ++err_create_module_files: ++ debugfs_remove_recursive(pf->ice_debugfs_pf_fwlog); ++ kfree(fw_modules); ++} ++ ++/** ++ * ice_debugfs_init - create root directory for debugfs entries ++ */ ++void ice_debugfs_init(void) ++{ ++ ice_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); ++ if (IS_ERR(ice_debugfs_root)) ++ pr_info("init of debugfs failed\n"); ++} ++ ++/** ++ * ice_debugfs_exit - remove debugfs entries ++ */ ++void ice_debugfs_exit(void) ++{ ++ debugfs_remove_recursive(ice_debugfs_root); ++ ice_debugfs_root = NULL; ++} +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.c b/drivers/net/ethernet/intel/ice/ice_fwlog.c +new file mode 100644 +index 000000000000..307e0d04f3fe +--- /dev/null ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.c +@@ -0,0 +1,261 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* Copyright (c) 2022, Intel Corporation. */ ++ ++#include "ice.h" ++#include "ice_common.h" ++#include "ice_fwlog.h" ++ ++/** ++ * ice_fwlog_init - Initialize FW logging configuration ++ * @hw: pointer to the HW structure ++ * ++ * This function should be called on driver initialization during ++ * ice_init_hw(). ++ */ ++int ice_fwlog_init(struct ice_hw *hw) ++{ ++ /* only support fw log commands on PF 0 */ ++ if (hw->bus.func) ++ return -EINVAL; ++ ++ ice_fwlog_set_supported(hw); ++ ++ if (ice_fwlog_supported(hw)) { ++ int status; ++ ++ /* read the current config from the FW and store it */ ++ status = ice_fwlog_get(hw, &hw->fwlog_cfg); ++ if (status) ++ return status; ++ ++ ice_debugfs_fwlog_init(hw->back); ++ } else { ++ dev_warn(ice_hw_to_dev(hw), "FW logging is not supported in this NVM image. Please update the NVM to get FW log support\n"); ++ } ++ ++ return 0; ++} ++ ++/** ++ * ice_fwlog_deinit - unroll FW logging configuration ++ * @hw: pointer to the HW structure ++ * ++ * This function should be called in ice_deinit_hw(). ++ */ ++void ice_fwlog_deinit(struct ice_hw *hw) ++{ ++ struct ice_pf *pf = hw->back; ++ int status; ++ ++ /* only support fw log commands on PF 0 */ ++ if (hw->bus.func) ++ return; ++ ++ /* make sure FW logging is disabled to not put the FW in a weird state ++ * for the next driver load ++ */ ++ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA; ++ status = ice_fwlog_set(hw, &hw->fwlog_cfg); ++ if (status) ++ dev_warn(ice_hw_to_dev(hw), "Unable to turn off FW logging, status: %d\n", ++ status); ++ ++ kfree(pf->ice_debugfs_pf_fwlog_modules); ++ ++ pf->ice_debugfs_pf_fwlog_modules = NULL; ++} ++ ++/** ++ * ice_fwlog_supported - Cached for whether FW supports FW logging or not ++ * @hw: pointer to the HW structure ++ * ++ * This will always return false if called before ice_init_hw(), so it must be ++ * called after ice_init_hw(). ++ */ ++bool ice_fwlog_supported(struct ice_hw *hw) ++{ ++ return hw->fwlog_supported; ++} ++ ++/** ++ * ice_aq_fwlog_set - Set FW logging configuration AQ command (0xFF30) ++ * @hw: pointer to the HW structure ++ * @entries: entries to configure ++ * @num_entries: number of @entries ++ * @options: options from ice_fwlog_cfg->options structure ++ * @log_resolution: logging resolution ++ */ ++static int ++ice_aq_fwlog_set(struct ice_hw *hw, struct ice_fwlog_module_entry *entries, ++ u16 num_entries, u16 options, u16 log_resolution) ++{ ++ struct ice_aqc_fw_log_cfg_resp *fw_modules; ++ struct ice_aqc_fw_log *cmd; ++ struct ice_aq_desc desc; ++ int status; ++ int i; ++ ++ fw_modules = kcalloc(num_entries, sizeof(*fw_modules), GFP_KERNEL); ++ if (!fw_modules) ++ return -ENOMEM; ++ ++ for (i = 0; i < num_entries; i++) { ++ fw_modules[i].module_identifier = ++ cpu_to_le16(entries[i].module_id); ++ fw_modules[i].log_level = entries[i].log_level; ++ } ++ ++ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_config); ++ desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); ++ ++ cmd = &desc.params.fw_log; ++ ++ cmd->cmd_flags = ICE_AQC_FW_LOG_CONF_SET_VALID; ++ cmd->ops.cfg.log_resolution = cpu_to_le16(log_resolution); ++ cmd->ops.cfg.mdl_cnt = cpu_to_le16(num_entries); ++ ++ if (options & ICE_FWLOG_OPTION_ARQ_ENA) ++ cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_AQ_EN; ++ if (options & ICE_FWLOG_OPTION_UART_ENA) ++ cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_UART_EN; ++ ++ status = ice_aq_send_cmd(hw, &desc, fw_modules, ++ sizeof(*fw_modules) * num_entries, ++ NULL); ++ ++ kfree(fw_modules); ++ ++ return status; ++} ++ ++/** ++ * ice_fwlog_set - Set the firmware logging settings ++ * @hw: pointer to the HW structure ++ * @cfg: config used to set firmware logging ++ * ++ * This function should be called whenever the driver needs to set the firmware ++ * logging configuration. It can be called on initialization, reset, or during ++ * runtime. ++ * ++ * If the PF wishes to receive FW logging then it must register via ++ * ice_fwlog_register. Note, that ice_fwlog_register does not need to be called ++ * for init. ++ */ ++int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) ++{ ++ if (!ice_fwlog_supported(hw)) ++ return -EOPNOTSUPP; ++ ++ return ice_aq_fwlog_set(hw, cfg->module_entries, ++ ICE_AQC_FW_LOG_ID_MAX, cfg->options, ++ cfg->log_resolution); ++} ++ ++/** ++ * ice_aq_fwlog_get - Get the current firmware logging configuration (0xFF32) ++ * @hw: pointer to the HW structure ++ * @cfg: firmware logging configuration to populate ++ */ ++static int ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) ++{ ++ struct ice_aqc_fw_log_cfg_resp *fw_modules; ++ struct ice_aqc_fw_log *cmd; ++ struct ice_aq_desc desc; ++ u16 module_id_cnt; ++ int status; ++ void *buf; ++ int i; ++ ++ memset(cfg, 0, sizeof(*cfg)); ++ ++ buf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_query); ++ cmd = &desc.params.fw_log; ++ ++ cmd->cmd_flags = ICE_AQC_FW_LOG_AQ_QUERY; ++ ++ status = ice_aq_send_cmd(hw, &desc, buf, ICE_AQ_MAX_BUF_LEN, NULL); ++ if (status) { ++ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to get FW log configuration\n"); ++ goto status_out; ++ } ++ ++ module_id_cnt = le16_to_cpu(cmd->ops.cfg.mdl_cnt); ++ if (module_id_cnt < ICE_AQC_FW_LOG_ID_MAX) { ++ ice_debug(hw, ICE_DBG_FW_LOG, "FW returned less than the expected number of FW log module IDs\n"); ++ } else if (module_id_cnt > ICE_AQC_FW_LOG_ID_MAX) { ++ ice_debug(hw, ICE_DBG_FW_LOG, "FW returned more than expected number of FW log module IDs, setting module_id_cnt to software expected max %u\n", ++ ICE_AQC_FW_LOG_ID_MAX); ++ module_id_cnt = ICE_AQC_FW_LOG_ID_MAX; ++ } ++ ++ cfg->log_resolution = le16_to_cpu(cmd->ops.cfg.log_resolution); ++ if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_AQ_EN) ++ cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA; ++ if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_UART_EN) ++ cfg->options |= ICE_FWLOG_OPTION_UART_ENA; ++ ++ fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf; ++ ++ for (i = 0; i < module_id_cnt; i++) { ++ struct ice_aqc_fw_log_cfg_resp *fw_module = &fw_modules[i]; ++ ++ cfg->module_entries[i].module_id = ++ le16_to_cpu(fw_module->module_identifier); ++ cfg->module_entries[i].log_level = fw_module->log_level; ++ } ++ ++status_out: ++ kfree(buf); ++ return status; ++} ++ ++/** ++ * ice_fwlog_get - Get the firmware logging settings ++ * @hw: pointer to the HW structure ++ * @cfg: config to populate based on current firmware logging settings ++ */ ++int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) ++{ ++ if (!ice_fwlog_supported(hw)) ++ return -EOPNOTSUPP; ++ ++ return ice_aq_fwlog_get(hw, cfg); ++} ++ ++/** ++ * ice_fwlog_set_supported - Set if FW logging is supported by FW ++ * @hw: pointer to the HW struct ++ * ++ * If FW returns success to the ice_aq_fwlog_get call then it supports FW ++ * logging, else it doesn't. Set the fwlog_supported flag accordingly. ++ * ++ * This function is only meant to be called during driver init to determine if ++ * the FW support FW logging. ++ */ ++void ice_fwlog_set_supported(struct ice_hw *hw) ++{ ++ struct ice_fwlog_cfg *cfg; ++ int status; ++ ++ hw->fwlog_supported = false; ++ ++ cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); ++ if (!cfg) ++ return; ++ ++ /* don't call ice_fwlog_get() because that would check to see if FW ++ * logging is supported which is what the driver is determining now ++ */ ++ status = ice_aq_fwlog_get(hw, cfg); ++ if (status) ++ ice_debug(hw, ICE_DBG_FW_LOG, "ice_aq_fwlog_get failed, FW logging is not supported on this version of FW, status %d\n", ++ status); ++ else ++ hw->fwlog_supported = true; ++ ++ kfree(cfg); ++} +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.h b/drivers/net/ethernet/intel/ice/ice_fwlog.h +new file mode 100644 +index 000000000000..8e68ee02713b +--- /dev/null ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.h +@@ -0,0 +1,56 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* Copyright (C) 2022, Intel Corporation. */ ++ ++#ifndef _ICE_FWLOG_H_ ++#define _ICE_FWLOG_H_ ++#include "ice_adminq_cmd.h" ++ ++struct ice_hw; ++ ++/* Only a single log level should be set and all log levels under the set value ++ * are enabled, e.g. if log level is set to ICE_FW_LOG_LEVEL_VERBOSE, then all ++ * other log levels are included (except ICE_FW_LOG_LEVEL_NONE) ++ */ ++enum ice_fwlog_level { ++ ICE_FWLOG_LEVEL_NONE = 0, ++ ICE_FWLOG_LEVEL_ERROR = 1, ++ ICE_FWLOG_LEVEL_WARNING = 2, ++ ICE_FWLOG_LEVEL_NORMAL = 3, ++ ICE_FWLOG_LEVEL_VERBOSE = 4, ++ ICE_FWLOG_LEVEL_INVALID, /* all values >= this entry are invalid */ ++}; ++ ++struct ice_fwlog_module_entry { ++ /* module ID for the corresponding firmware logging event */ ++ u16 module_id; ++ /* verbosity level for the module_id */ ++ u8 log_level; ++}; ++ ++struct ice_fwlog_cfg { ++ /* list of modules for configuring log level */ ++ struct ice_fwlog_module_entry module_entries[ICE_AQC_FW_LOG_ID_MAX]; ++ /* options used to configure firmware logging */ ++ u16 options; ++#define ICE_FWLOG_OPTION_ARQ_ENA BIT(0) ++#define ICE_FWLOG_OPTION_UART_ENA BIT(1) ++ /* set before calling ice_fwlog_init() so the PF registers for firmware ++ * logging on initialization ++ */ ++#define ICE_FWLOG_OPTION_REGISTER_ON_INIT BIT(2) ++ /* set in the ice_fwlog_get() response if the PF is registered for FW ++ * logging events over ARQ ++ */ ++#define ICE_FWLOG_OPTION_IS_REGISTERED BIT(3) ++ ++ /* minimum number of log events sent per Admin Receive Queue event */ ++ u16 log_resolution; ++}; ++ ++void ice_fwlog_set_supported(struct ice_hw *hw); ++bool ice_fwlog_supported(struct ice_hw *hw); ++int ice_fwlog_init(struct ice_hw *hw); ++void ice_fwlog_deinit(struct ice_hw *hw); ++int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); ++int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); ++#endif /* _ICE_FWLOG_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index e5cc9790969c..614e10ab4159 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -4506,6 +4506,19 @@ static void ice_print_wake_reason(struct ice_pf *pf) + dev_info(ice_pf_to_dev(pf), "Wake reason: %s", wake_str); + } + ++/** ++ * ice_pf_fwlog_update_module - update 1 module ++ * @pf: pointer to the PF struct ++ * @log_level: log_level to use for the @module ++ * @module: module to update ++ */ ++void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module) ++{ ++ struct ice_hw *hw = &pf->hw; ++ ++ hw->fwlog_cfg.module_entries[module].log_level = log_level; ++} ++ + /** + * ice_register_netdev - register netdev + * @vsi: pointer to the VSI struct +@@ -5283,6 +5296,8 @@ static void ice_remove(struct pci_dev *pdev) + msleep(100); + } + ++ ice_debugfs_exit(); ++ + if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) { + set_bit(ICE_VF_RESETS_DISABLED, pf->state); + ice_free_vfs(pf); +@@ -5751,6 +5766,8 @@ static int __init ice_module_init(void) + goto err_dest_wq; + } + ++ ice_debugfs_init(); ++ + status = pci_register_driver(&ice_driver); + if (status) { + pr_err("failed to register PCI driver, err %d\n", status); +@@ -5761,6 +5778,7 @@ static int __init ice_module_init(void) + + err_dest_lag_wq: + destroy_workqueue(ice_lag_wq); ++ ice_debugfs_exit(); + err_dest_wq: + destroy_workqueue(ice_wq); + return status; +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index 6e1fed0d7384..84bb61aa7409 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -17,6 +17,7 @@ + #include "ice_protocol_type.h" + #include "ice_sbq_cmd.h" + #include "ice_vlan_mode.h" ++#include "ice_fwlog.h" + + static inline bool ice_is_tc_ena(unsigned long bitmap, u8 tc) + { +@@ -872,6 +873,9 @@ struct ice_hw { + u8 fw_patch; /* firmware patch version */ + u32 fw_build; /* firmware build number */ + ++ struct ice_fwlog_cfg fwlog_cfg; ++ bool fwlog_supported; /* does hardware support FW logging? */ ++ + /* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL + * register. Used for determining the ITR/INTRL granularity during + * initialization. +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0026-ice-enable-FW-logging.patch b/kernel-rt/debian/patches/ice-VDF/0026-ice-enable-FW-logging.patch new file mode 100644 index 00000000..f61122fb --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0026-ice-enable-FW-logging.patch @@ -0,0 +1,281 @@ +From 189d58473481cf01b493fca4e9dd2ab8380d0ce5 Mon Sep 17 00:00:00 2001 +From: Paul M Stillwell Jr +Date: Tue, 12 Dec 2023 21:07:13 -0800 +Subject: [PATCH 26/36] ice: enable FW logging + +Once users have configured the FW logging then allow them to enable it +by writing to the 'fwlog/enable' file. The file accepts a boolean value +(0 or 1) where 1 means enable FW logging and 0 means disable FW logging. + + # echo > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/enable + +Where is 0 or 1. + +The user can read the 'fwlog/enable' file to see whether logging is +enabled or not. Reading the actual data is a separate patch. To see the +current value then: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/enable + +Signed-off-by: Paul M Stillwell Jr +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 73671c3162c83a689342fd57f00b5f261682e49b) +Signed-off-by: Jiping Ma +--- + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 3 + + drivers/net/ethernet/intel/ice/ice_debugfs.c | 98 +++++++++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.c | 67 +++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.h | 2 + + 4 files changed, 170 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 347e4fed5e0d..11391be4efc2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2336,6 +2336,7 @@ enum ice_aqc_fw_logging_mod { + }; + + /* Set FW Logging configuration (indirect 0xFF30) ++ * Register for FW Logging (indirect 0xFF31) + * Query FW Logging (indirect 0xFF32) + */ + struct ice_aqc_fw_log { +@@ -2344,6 +2345,7 @@ struct ice_aqc_fw_log { + #define ICE_AQC_FW_LOG_CONF_AQ_EN BIT(1) + #define ICE_AQC_FW_LOG_QUERY_REGISTERED BIT(2) + #define ICE_AQC_FW_LOG_CONF_SET_VALID BIT(3) ++#define ICE_AQC_FW_LOG_AQ_REGISTER BIT(0) + #define ICE_AQC_FW_LOG_AQ_QUERY BIT(2) + + u8 rsp_flag; +@@ -2662,6 +2664,7 @@ enum ice_adminq_opc { + + /* FW Logging Commands */ + ice_aqc_opc_fw_logs_config = 0xFF30, ++ ice_aqc_opc_fw_logs_register = 0xFF31, + ice_aqc_opc_fw_logs_query = 0xFF32, + }; + +diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c +index 3b0d9b214fd1..3dde99969132 100644 +--- a/drivers/net/ethernet/intel/ice/ice_debugfs.c ++++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c +@@ -281,6 +281,101 @@ static const struct file_operations ice_debugfs_nr_messages_fops = { + .write = ice_debugfs_nr_messages_write, + }; + ++/** ++ * ice_debugfs_enable_read - read from 'enable' file ++ * @filp: the opened file ++ * @buffer: where to write the data for the user to read ++ * @count: the size of the user's buffer ++ * @ppos: file position offset ++ */ ++static ssize_t ice_debugfs_enable_read(struct file *filp, ++ char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ char buff[32] = {}; ++ ++ snprintf(buff, sizeof(buff), "%u\n", ++ (u16)(hw->fwlog_cfg.options & ++ ICE_FWLOG_OPTION_IS_REGISTERED) >> 3); ++ ++ return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); ++} ++ ++/** ++ * ice_debugfs_enable_write - write into 'enable' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_enable_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ char user_val[8], *cmd_buf; ++ bool enable; ++ ssize_t ret; ++ ++ /* don't allow partial writes or invalid input */ ++ if (*ppos != 0 || count > 2) ++ return -EINVAL; ++ ++ cmd_buf = memdup_user(buf, count); ++ if (IS_ERR(cmd_buf)) ++ return PTR_ERR(cmd_buf); ++ ++ ret = sscanf(cmd_buf, "%s", user_val); ++ if (ret != 1) ++ return -EINVAL; ++ ++ ret = kstrtobool(user_val, &enable); ++ if (ret) ++ goto enable_write_error; ++ ++ if (enable) ++ hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_ARQ_ENA; ++ else ++ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA; ++ ++ ret = ice_fwlog_set(hw, &hw->fwlog_cfg); ++ if (ret) ++ goto enable_write_error; ++ ++ if (enable) ++ ret = ice_fwlog_register(hw); ++ else ++ ret = ice_fwlog_unregister(hw); ++ ++ if (ret) ++ goto enable_write_error; ++ ++ /* if we get here, nothing went wrong; return count since we didn't ++ * really write anything ++ */ ++ ret = (ssize_t)count; ++ ++enable_write_error: ++ /* This function always consumes all of the written input, or produces ++ * an error. Check and enforce this. Otherwise, the write operation ++ * won't complete properly. ++ */ ++ if (WARN_ON(ret != (ssize_t)count && ret >= 0)) ++ ret = -EIO; ++ ++ return ret; ++} ++ ++static const struct file_operations ice_debugfs_enable_fops = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .read = ice_debugfs_enable_read, ++ .write = ice_debugfs_enable_write, ++}; ++ + /** + * ice_debugfs_fwlog_init - setup the debugfs directory + * @pf: the ice that is starting up +@@ -332,6 +427,9 @@ void ice_debugfs_fwlog_init(struct ice_pf *pf) + + pf->ice_debugfs_pf_fwlog_modules = fw_modules; + ++ debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog, ++ pf, &ice_debugfs_enable_fops); ++ + return; + + err_create_module_files: +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.c b/drivers/net/ethernet/intel/ice/ice_fwlog.c +index 307e0d04f3fe..25a17cbc1d34 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.c ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.c +@@ -63,6 +63,11 @@ void ice_fwlog_deinit(struct ice_hw *hw) + kfree(pf->ice_debugfs_pf_fwlog_modules); + + pf->ice_debugfs_pf_fwlog_modules = NULL; ++ ++ status = ice_fwlog_unregister(hw); ++ if (status) ++ dev_warn(ice_hw_to_dev(hw), "Unable to unregister FW logging, status: %d\n", ++ status); + } + + /** +@@ -197,6 +202,8 @@ static int ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) + cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA; + if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_UART_EN) + cfg->options |= ICE_FWLOG_OPTION_UART_ENA; ++ if (cmd->cmd_flags & ICE_AQC_FW_LOG_QUERY_REGISTERED) ++ cfg->options |= ICE_FWLOG_OPTION_IS_REGISTERED; + + fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf; + +@@ -226,6 +233,66 @@ int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) + return ice_aq_fwlog_get(hw, cfg); + } + ++/** ++ * ice_aq_fwlog_register - Register PF for firmware logging events (0xFF31) ++ * @hw: pointer to the HW structure ++ * @reg: true to register and false to unregister ++ */ ++static int ice_aq_fwlog_register(struct ice_hw *hw, bool reg) ++{ ++ struct ice_aq_desc desc; ++ ++ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_register); ++ ++ if (reg) ++ desc.params.fw_log.cmd_flags = ICE_AQC_FW_LOG_AQ_REGISTER; ++ ++ return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); ++} ++ ++/** ++ * ice_fwlog_register - Register the PF for firmware logging ++ * @hw: pointer to the HW structure ++ * ++ * After this call the PF will start to receive firmware logging based on the ++ * configuration set in ice_fwlog_set. ++ */ ++int ice_fwlog_register(struct ice_hw *hw) ++{ ++ int status; ++ ++ if (!ice_fwlog_supported(hw)) ++ return -EOPNOTSUPP; ++ ++ status = ice_aq_fwlog_register(hw, true); ++ if (status) ++ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to register for firmware logging events over ARQ\n"); ++ else ++ hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_IS_REGISTERED; ++ ++ return status; ++} ++ ++/** ++ * ice_fwlog_unregister - Unregister the PF from firmware logging ++ * @hw: pointer to the HW structure ++ */ ++int ice_fwlog_unregister(struct ice_hw *hw) ++{ ++ int status; ++ ++ if (!ice_fwlog_supported(hw)) ++ return -EOPNOTSUPP; ++ ++ status = ice_aq_fwlog_register(hw, false); ++ if (status) ++ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to unregister from firmware logging events over ARQ\n"); ++ else ++ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_IS_REGISTERED; ++ ++ return status; ++} ++ + /** + * ice_fwlog_set_supported - Set if FW logging is supported by FW + * @hw: pointer to the HW struct +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.h b/drivers/net/ethernet/intel/ice/ice_fwlog.h +index 8e68ee02713b..45865558425d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.h ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.h +@@ -53,4 +53,6 @@ int ice_fwlog_init(struct ice_hw *hw); + void ice_fwlog_deinit(struct ice_hw *hw); + int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); + int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); ++int ice_fwlog_register(struct ice_hw *hw); ++int ice_fwlog_unregister(struct ice_hw *hw); + #endif /* _ICE_FWLOG_H_ */ +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0027-ice-add-ability-to-read-and-configure-FW-log-data.patch b/kernel-rt/debian/patches/ice-VDF/0027-ice-add-ability-to-read-and-configure-FW-log-data.patch new file mode 100644 index 00000000..0bca4413 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0027-ice-add-ability-to-read-and-configure-FW-log-data.patch @@ -0,0 +1,572 @@ +From a584ea88cfdc8ac3f782be1d5d67fa92c3423290 Mon Sep 17 00:00:00 2001 +From: Paul M Stillwell Jr +Date: Tue, 12 Dec 2023 21:07:14 -0800 +Subject: [PATCH 27/36] ice: add ability to read and configure FW log data + +Once logging is enabled the user should read the data from the 'data' +file. The data is in the form of a binary blob that can be sent to Intel +for decoding. To read the data use a command like: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/data > log_data.bin + +If the user wants to clear the FW log data that has been stored in the +driver then they can write any value to the 'data' file and that will clear +the data. An example is: + + # echo 34 > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/data + +In addition to being able to read the data the user can configure how +much memory is used to store FW log data. This allows the user to +increase/decrease the amount of memory based on the users situation. +The data is stored such that if the memory fills up then the oldest data +will get overwritten in a circular manner. To change the amount of +memory the user can write to the 'log_size' file like this: + + # echo > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/log_size + +Where is one of 128K, 256K, 512K, 1M, and 2M. The default value +is 1M. + +The user can see the current value of 'log_size' by reading the file: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/log_size + +Signed-off-by: Paul M Stillwell Jr +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 9d3535e71985beb738c4ad2b772c6f0efdce0202) +Signed-off-by: Jiping Ma +--- + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 2 + + drivers/net/ethernet/intel/ice/ice_debugfs.c | 210 ++++++++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.c | 142 ++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.h | 21 ++ + drivers/net/ethernet/intel/ice/ice_main.c | 29 +++ + drivers/net/ethernet/intel/ice/ice_type.h | 1 + + 6 files changed, 405 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 11391be4efc2..f63b57ff2a3d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2338,6 +2338,7 @@ enum ice_aqc_fw_logging_mod { + /* Set FW Logging configuration (indirect 0xFF30) + * Register for FW Logging (indirect 0xFF31) + * Query FW Logging (indirect 0xFF32) ++ * FW Log Event (indirect 0xFF33) + */ + struct ice_aqc_fw_log { + u8 cmd_flags; +@@ -2666,6 +2667,7 @@ enum ice_adminq_opc { + ice_aqc_opc_fw_logs_config = 0xFF30, + ice_aqc_opc_fw_logs_register = 0xFF31, + ice_aqc_opc_fw_logs_query = 0xFF32, ++ ice_aqc_opc_fw_logs_event = 0xFF33, + }; + + #endif /* _ICE_ADMINQ_CMD_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c +index 3dde99969132..c2bfba6b9ead 100644 +--- a/drivers/net/ethernet/intel/ice/ice_debugfs.c ++++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c +@@ -64,6 +64,17 @@ static const char * const ice_fwlog_level_string[] = { + "verbose", + }; + ++/* the order in this array is important. it matches the ordering of the ++ * values in the FW so the index is the same value as in ice_fwlog_level ++ */ ++static const char * const ice_fwlog_log_size[] = { ++ "128K", ++ "256K", ++ "512K", ++ "1M", ++ "2M", ++}; ++ + /** + * ice_fwlog_print_module_cfg - print current FW logging module configuration + * @hw: pointer to the HW structure +@@ -376,6 +387,199 @@ static const struct file_operations ice_debugfs_enable_fops = { + .write = ice_debugfs_enable_write, + }; + ++/** ++ * ice_debugfs_log_size_read - read from 'log_size' file ++ * @filp: the opened file ++ * @buffer: where to write the data for the user to read ++ * @count: the size of the user's buffer ++ * @ppos: file position offset ++ */ ++static ssize_t ice_debugfs_log_size_read(struct file *filp, ++ char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ char buff[32] = {}; ++ int index; ++ ++ index = hw->fwlog_ring.index; ++ snprintf(buff, sizeof(buff), "%s\n", ice_fwlog_log_size[index]); ++ ++ return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); ++} ++ ++/** ++ * ice_debugfs_log_size_write - write into 'log_size' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_log_size_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct device *dev = ice_pf_to_dev(pf); ++ struct ice_hw *hw = &pf->hw; ++ char user_val[8], *cmd_buf; ++ ssize_t ret; ++ int index; ++ ++ /* don't allow partial writes or invalid input */ ++ if (*ppos != 0 || count > 5) ++ return -EINVAL; ++ ++ cmd_buf = memdup_user(buf, count); ++ if (IS_ERR(cmd_buf)) ++ return PTR_ERR(cmd_buf); ++ ++ ret = sscanf(cmd_buf, "%s", user_val); ++ if (ret != 1) ++ return -EINVAL; ++ ++ index = sysfs_match_string(ice_fwlog_log_size, user_val); ++ if (index < 0) { ++ dev_info(dev, "Invalid log size '%s'. The value must be one of 128K, 256K, 512K, 1M, 2M\n", ++ user_val); ++ ret = -EINVAL; ++ goto log_size_write_error; ++ } else if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED) { ++ dev_info(dev, "FW logging is currently running. Please disable FW logging to change log_size\n"); ++ ret = -EINVAL; ++ goto log_size_write_error; ++ } ++ ++ /* free all the buffers and the tracking info and resize */ ++ ice_fwlog_realloc_rings(hw, index); ++ ++ /* if we get here, nothing went wrong; return count since we didn't ++ * really write anything ++ */ ++ ret = (ssize_t)count; ++ ++log_size_write_error: ++ /* This function always consumes all of the written input, or produces ++ * an error. Check and enforce this. Otherwise, the write operation ++ * won't complete properly. ++ */ ++ if (WARN_ON(ret != (ssize_t)count && ret >= 0)) ++ ret = -EIO; ++ ++ return ret; ++} ++ ++static const struct file_operations ice_debugfs_log_size_fops = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .read = ice_debugfs_log_size_read, ++ .write = ice_debugfs_log_size_write, ++}; ++ ++/** ++ * ice_debugfs_data_read - read from 'data' file ++ * @filp: the opened file ++ * @buffer: where to write the data for the user to read ++ * @count: the size of the user's buffer ++ * @ppos: file position offset ++ */ ++static ssize_t ice_debugfs_data_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ int data_copied = 0; ++ bool done = false; ++ ++ if (ice_fwlog_ring_empty(&hw->fwlog_ring)) ++ return 0; ++ ++ while (!ice_fwlog_ring_empty(&hw->fwlog_ring) && !done) { ++ struct ice_fwlog_data *log; ++ u16 cur_buf_len; ++ ++ log = &hw->fwlog_ring.rings[hw->fwlog_ring.head]; ++ cur_buf_len = log->data_size; ++ if (cur_buf_len >= count) { ++ done = true; ++ continue; ++ } ++ ++ if (copy_to_user(buffer, log->data, cur_buf_len)) { ++ /* if there is an error then bail and return whatever ++ * the driver has copied so far ++ */ ++ done = true; ++ continue; ++ } ++ ++ data_copied += cur_buf_len; ++ buffer += cur_buf_len; ++ count -= cur_buf_len; ++ *ppos += cur_buf_len; ++ ice_fwlog_ring_increment(&hw->fwlog_ring.head, ++ hw->fwlog_ring.size); ++ } ++ ++ return data_copied; ++} ++ ++/** ++ * ice_debugfs_data_write - write into 'data' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_data_write(struct file *filp, const char __user *buf, size_t count, ++ loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct device *dev = ice_pf_to_dev(pf); ++ struct ice_hw *hw = &pf->hw; ++ ssize_t ret; ++ ++ /* don't allow partial writes */ ++ if (*ppos != 0) ++ return 0; ++ ++ /* any value is allowed to clear the buffer so no need to even look at ++ * what the value is ++ */ ++ if (!(hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED)) { ++ hw->fwlog_ring.head = 0; ++ hw->fwlog_ring.tail = 0; ++ } else { ++ dev_info(dev, "Can't clear FW log data while FW log running\n"); ++ ret = -EINVAL; ++ goto nr_buffs_write_error; ++ } ++ ++ /* if we get here, nothing went wrong; return count since we didn't ++ * really write anything ++ */ ++ ret = (ssize_t)count; ++ ++nr_buffs_write_error: ++ /* This function always consumes all of the written input, or produces ++ * an error. Check and enforce this. Otherwise, the write operation ++ * won't complete properly. ++ */ ++ if (WARN_ON(ret != (ssize_t)count && ret >= 0)) ++ ret = -EIO; ++ ++ return ret; ++} ++ ++static const struct file_operations ice_debugfs_data_fops = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .read = ice_debugfs_data_read, ++ .write = ice_debugfs_data_write, ++}; ++ + /** + * ice_debugfs_fwlog_init - setup the debugfs directory + * @pf: the ice that is starting up +@@ -430,6 +634,12 @@ void ice_debugfs_fwlog_init(struct ice_pf *pf) + debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog, + pf, &ice_debugfs_enable_fops); + ++ debugfs_create_file("log_size", 0600, pf->ice_debugfs_pf_fwlog, ++ pf, &ice_debugfs_log_size_fops); ++ ++ debugfs_create_file("data", 0600, pf->ice_debugfs_pf_fwlog, ++ pf, &ice_debugfs_data_fops); ++ + return; + + err_create_module_files: +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.c b/drivers/net/ethernet/intel/ice/ice_fwlog.c +index 25a17cbc1d34..92b5dac481cd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.c ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.c +@@ -1,10 +1,128 @@ + // SPDX-License-Identifier: GPL-2.0 + /* Copyright (c) 2022, Intel Corporation. */ + ++#include + #include "ice.h" + #include "ice_common.h" + #include "ice_fwlog.h" + ++bool ice_fwlog_ring_full(struct ice_fwlog_ring *rings) ++{ ++ u16 head, tail; ++ ++ head = rings->head; ++ tail = rings->tail; ++ ++ if (head < tail && (tail - head == (rings->size - 1))) ++ return true; ++ else if (head > tail && (tail == (head - 1))) ++ return true; ++ ++ return false; ++} ++ ++bool ice_fwlog_ring_empty(struct ice_fwlog_ring *rings) ++{ ++ return rings->head == rings->tail; ++} ++ ++void ice_fwlog_ring_increment(u16 *item, u16 size) ++{ ++ *item = (*item + 1) & (size - 1); ++} ++ ++static int ice_fwlog_alloc_ring_buffs(struct ice_fwlog_ring *rings) ++{ ++ int i, nr_bytes; ++ u8 *mem; ++ ++ nr_bytes = rings->size * ICE_AQ_MAX_BUF_LEN; ++ mem = vzalloc(nr_bytes); ++ if (!mem) ++ return -ENOMEM; ++ ++ for (i = 0; i < rings->size; i++) { ++ struct ice_fwlog_data *ring = &rings->rings[i]; ++ ++ ring->data_size = ICE_AQ_MAX_BUF_LEN; ++ ring->data = mem; ++ mem += ICE_AQ_MAX_BUF_LEN; ++ } ++ ++ return 0; ++} ++ ++static void ice_fwlog_free_ring_buffs(struct ice_fwlog_ring *rings) ++{ ++ int i; ++ ++ for (i = 0; i < rings->size; i++) { ++ struct ice_fwlog_data *ring = &rings->rings[i]; ++ ++ /* the first ring is the base memory for the whole range so ++ * free it ++ */ ++ if (!i) ++ vfree(ring->data); ++ ++ ring->data = NULL; ++ ring->data_size = 0; ++ } ++} ++ ++#define ICE_FWLOG_INDEX_TO_BYTES(n) ((128 * 1024) << (n)) ++/** ++ * ice_fwlog_realloc_rings - reallocate the FW log rings ++ * @hw: pointer to the HW structure ++ * @index: the new index to use to allocate memory for the log data ++ * ++ */ ++void ice_fwlog_realloc_rings(struct ice_hw *hw, int index) ++{ ++ struct ice_fwlog_ring ring; ++ int status, ring_size; ++ ++ /* convert the number of bytes into a number of 4K buffers. externally ++ * the driver presents the interface to the FW log data as a number of ++ * bytes because that's easy for users to understand. internally the ++ * driver uses a ring of buffers because the driver doesn't know where ++ * the beginning and end of any line of log data is so the driver has ++ * to overwrite data as complete blocks. when the data is returned to ++ * the user the driver knows that the data is correct and the FW log ++ * can be correctly parsed by the tools ++ */ ++ ring_size = ICE_FWLOG_INDEX_TO_BYTES(index) / ICE_AQ_MAX_BUF_LEN; ++ if (ring_size == hw->fwlog_ring.size) ++ return; ++ ++ /* allocate space for the new rings and buffers then release the ++ * old rings and buffers. that way if we don't have enough ++ * memory then we at least have what we had before ++ */ ++ ring.rings = kcalloc(ring_size, sizeof(*ring.rings), GFP_KERNEL); ++ if (!ring.rings) ++ return; ++ ++ ring.size = ring_size; ++ ++ status = ice_fwlog_alloc_ring_buffs(&ring); ++ if (status) { ++ dev_warn(ice_hw_to_dev(hw), "Unable to allocate memory for FW log ring data buffers\n"); ++ ice_fwlog_free_ring_buffs(&ring); ++ kfree(ring.rings); ++ return; ++ } ++ ++ ice_fwlog_free_ring_buffs(&hw->fwlog_ring); ++ kfree(hw->fwlog_ring.rings); ++ ++ hw->fwlog_ring.rings = ring.rings; ++ hw->fwlog_ring.size = ring.size; ++ hw->fwlog_ring.index = index; ++ hw->fwlog_ring.head = 0; ++ hw->fwlog_ring.tail = 0; ++} ++ + /** + * ice_fwlog_init - Initialize FW logging configuration + * @hw: pointer to the HW structure +@@ -28,6 +146,25 @@ int ice_fwlog_init(struct ice_hw *hw) + if (status) + return status; + ++ hw->fwlog_ring.rings = kcalloc(ICE_FWLOG_RING_SIZE_DFLT, ++ sizeof(*hw->fwlog_ring.rings), ++ GFP_KERNEL); ++ if (!hw->fwlog_ring.rings) { ++ dev_warn(ice_hw_to_dev(hw), "Unable to allocate memory for FW log rings\n"); ++ return -ENOMEM; ++ } ++ ++ hw->fwlog_ring.size = ICE_FWLOG_RING_SIZE_DFLT; ++ hw->fwlog_ring.index = ICE_FWLOG_RING_SIZE_INDEX_DFLT; ++ ++ status = ice_fwlog_alloc_ring_buffs(&hw->fwlog_ring); ++ if (status) { ++ dev_warn(ice_hw_to_dev(hw), "Unable to allocate memory for FW log ring data buffers\n"); ++ ice_fwlog_free_ring_buffs(&hw->fwlog_ring); ++ kfree(hw->fwlog_ring.rings); ++ return status; ++ } ++ + ice_debugfs_fwlog_init(hw->back); + } else { + dev_warn(ice_hw_to_dev(hw), "FW logging is not supported in this NVM image. Please update the NVM to get FW log support\n"); +@@ -68,6 +205,11 @@ void ice_fwlog_deinit(struct ice_hw *hw) + if (status) + dev_warn(ice_hw_to_dev(hw), "Unable to unregister FW logging, status: %d\n", + status); ++ ++ if (hw->fwlog_ring.rings) { ++ ice_fwlog_free_ring_buffs(&hw->fwlog_ring); ++ kfree(hw->fwlog_ring.rings); ++ } + } + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.h b/drivers/net/ethernet/intel/ice/ice_fwlog.h +index 45865558425d..287e71fa4b86 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.h ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.h +@@ -47,6 +47,26 @@ struct ice_fwlog_cfg { + u16 log_resolution; + }; + ++struct ice_fwlog_data { ++ u16 data_size; ++ u8 *data; ++}; ++ ++struct ice_fwlog_ring { ++ struct ice_fwlog_data *rings; ++ u16 index; ++ u16 size; ++ u16 head; ++ u16 tail; ++}; ++ ++#define ICE_FWLOG_RING_SIZE_INDEX_DFLT 3 ++#define ICE_FWLOG_RING_SIZE_DFLT 256 ++#define ICE_FWLOG_RING_SIZE_MAX 512 ++ ++bool ice_fwlog_ring_full(struct ice_fwlog_ring *rings); ++bool ice_fwlog_ring_empty(struct ice_fwlog_ring *rings); ++void ice_fwlog_ring_increment(u16 *item, u16 size); + void ice_fwlog_set_supported(struct ice_hw *hw); + bool ice_fwlog_supported(struct ice_hw *hw); + int ice_fwlog_init(struct ice_hw *hw); +@@ -55,4 +75,5 @@ int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); + int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); + int ice_fwlog_register(struct ice_hw *hw); + int ice_fwlog_unregister(struct ice_hw *hw); ++void ice_fwlog_realloc_rings(struct ice_hw *hw, int index); + #endif /* _ICE_FWLOG_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 614e10ab4159..6c6ca5353f28 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -1254,6 +1254,32 @@ ice_handle_link_event(struct ice_pf *pf, struct ice_rq_event_info *event) + return status; + } + ++/** ++ * ice_get_fwlog_data - copy the FW log data from ARQ event ++ * @pf: PF that the FW log event is associated with ++ * @event: event structure containing FW log data ++ */ ++static void ++ice_get_fwlog_data(struct ice_pf *pf, struct ice_rq_event_info *event) ++{ ++ struct ice_fwlog_data *fwlog; ++ struct ice_hw *hw = &pf->hw; ++ ++ fwlog = &hw->fwlog_ring.rings[hw->fwlog_ring.tail]; ++ ++ memset(fwlog->data, 0, PAGE_SIZE); ++ fwlog->data_size = le16_to_cpu(event->desc.datalen); ++ ++ memcpy(fwlog->data, event->msg_buf, fwlog->data_size); ++ ice_fwlog_ring_increment(&hw->fwlog_ring.tail, hw->fwlog_ring.size); ++ ++ if (ice_fwlog_ring_full(&hw->fwlog_ring)) { ++ /* the rings are full so bump the head to create room */ ++ ice_fwlog_ring_increment(&hw->fwlog_ring.head, ++ hw->fwlog_ring.size); ++ } ++} ++ + /** + * ice_aq_prep_for_event - Prepare to wait for an AdminQ event from firmware + * @pf: pointer to the PF private structure +@@ -1535,6 +1561,9 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) + + ice_vc_process_vf_msg(pf, &event, &data); + break; ++ case ice_aqc_opc_fw_logs_event: ++ ice_get_fwlog_data(pf, &event); ++ break; + case ice_aqc_opc_lldp_set_mib_change: + ice_dcb_process_lldp_set_mib_change(pf, &event); + break; +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index 84bb61aa7409..28e47bb78eaf 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -875,6 +875,7 @@ struct ice_hw { + + struct ice_fwlog_cfg fwlog_cfg; + bool fwlog_supported; /* does hardware support FW logging? */ ++ struct ice_fwlog_ring fwlog_ring; + + /* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL + * register. Used for determining the ITR/INTRL granularity during +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0028-ice-Fix-debugfs-with-devlink-reload.patch b/kernel-rt/debian/patches/ice-VDF/0028-ice-Fix-debugfs-with-devlink-reload.patch new file mode 100644 index 00000000..4bfe7051 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0028-ice-Fix-debugfs-with-devlink-reload.patch @@ -0,0 +1,98 @@ +From 8a7f6d8b2105c39f236c51c558e21b787c223861 Mon Sep 17 00:00:00 2001 +From: Wojciech Drewek +Date: Mon, 5 Feb 2024 14:03:57 +0100 +Subject: [PATCH 28/36] ice: Fix debugfs with devlink reload + +During devlink reload it is needed to remove debugfs entries +correlated with only one PF. ice_debugfs_exit() removes all +entries created by ice driver so we can't use it. + +Introduce ice_debugfs_pf_deinit() in order to release PF's +debugfs entries. Move ice_debugfs_exit() call to ice_module_exit(), +it makes more sense since ice_debugfs_init() is called in +ice_module_init() and not in ice_probe(). + +Signed-off-by: Wojciech Drewek +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Reviewed-by: Brett Creeley +Reviewed-by: Simon Horman +Signed-off-by: Tony Nguyen +(cherry picked from commit 500d0df5b4b2394a06b949bab05f7ed0242b9858) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 1 + + drivers/net/ethernet/intel/ice/ice_debugfs.c | 10 ++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.c | 2 ++ + drivers/net/ethernet/intel/ice/ice_main.c | 3 +-- + 4 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 7966ac61154c..ed1c6cdedeff 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -895,6 +895,7 @@ static inline bool ice_is_adq_active(struct ice_pf *pf) + } + + void ice_debugfs_fwlog_init(struct ice_pf *pf); ++void ice_debugfs_pf_deinit(struct ice_pf *pf); + void ice_debugfs_init(void); + void ice_debugfs_exit(void); + void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module); +diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c +index c2bfba6b9ead..ba396b22bb7d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_debugfs.c ++++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c +@@ -647,6 +647,16 @@ void ice_debugfs_fwlog_init(struct ice_pf *pf) + kfree(fw_modules); + } + ++/** ++ * ice_debugfs_pf_deinit - cleanup PF's debugfs ++ * @pf: pointer to the PF struct ++ */ ++void ice_debugfs_pf_deinit(struct ice_pf *pf) ++{ ++ debugfs_remove_recursive(pf->ice_debugfs_pf); ++ pf->ice_debugfs_pf = NULL; ++} ++ + /** + * ice_debugfs_init - create root directory for debugfs entries + */ +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.c b/drivers/net/ethernet/intel/ice/ice_fwlog.c +index 92b5dac481cd..4fd15387a7e5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.c ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.c +@@ -188,6 +188,8 @@ void ice_fwlog_deinit(struct ice_hw *hw) + if (hw->bus.func) + return; + ++ ice_debugfs_pf_deinit(hw->back); ++ + /* make sure FW logging is disabled to not put the FW in a weird state + * for the next driver load + */ +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 6c6ca5353f28..c882c218281a 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -5325,8 +5325,6 @@ static void ice_remove(struct pci_dev *pdev) + msleep(100); + } + +- ice_debugfs_exit(); +- + if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) { + set_bit(ICE_VF_RESETS_DISABLED, pf->state); + ice_free_vfs(pf); +@@ -5823,6 +5821,7 @@ module_init(ice_module_init); + static void __exit ice_module_exit(void) + { + pci_unregister_driver(&ice_driver); ++ ice_debugfs_exit(); + destroy_workqueue(ice_wq); + destroy_workqueue(ice_lag_wq); + pr_info("module unloaded\n"); +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0029-ice-remove-vf-lan_vsi_num-field.patch b/kernel-rt/debian/patches/ice-VDF/0029-ice-remove-vf-lan_vsi_num-field.patch new file mode 100644 index 00000000..2411e9c5 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0029-ice-remove-vf-lan_vsi_num-field.patch @@ -0,0 +1,78 @@ +From 861015cbb4cf4cb258a1da9e80550fe991be7808 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Fri, 16 Feb 2024 14:06:38 -0800 +Subject: [PATCH 29/36] ice: remove vf->lan_vsi_num field + +The lan_vsi_num field of the VF structure is no longer used for any +purpose. Remove it. + +Signed-off-by: Jacob Keller +Reviewed-by: Przemek Kitszel +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +(cherry picked from commit 1cf94cbfc61bac89cddeb075fbc100ebd3aea81b) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_sriov.c | 1 - + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 4 +--- + drivers/net/ethernet/intel/ice/ice_vf_lib.h | 5 ----- + 3 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c +index 442162be23ea..3366ac976c44 100644 +--- a/drivers/net/ethernet/intel/ice/ice_sriov.c ++++ b/drivers/net/ethernet/intel/ice/ice_sriov.c +@@ -239,7 +239,6 @@ static struct ice_vsi *ice_vf_vsi_setup(struct ice_vf *vf) + } + + vf->lan_vsi_idx = vsi->idx; +- vf->lan_vsi_num = vsi->vsi_num; + + return vsi; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +index 03b9d7d74851..303fdf8555cf 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +@@ -298,7 +298,6 @@ static int ice_vf_rebuild_vsi(struct ice_vf *vf) + * vf->lan_vsi_idx + */ + vsi->vsi_num = ice_get_hw_vsi_num(&pf->hw, vsi->idx); +- vf->lan_vsi_num = vsi->vsi_num; + + return 0; + } +@@ -1299,13 +1298,12 @@ int ice_vf_init_host_cfg(struct ice_vf *vf, struct ice_vsi *vsi) + } + + /** +- * ice_vf_invalidate_vsi - invalidate vsi_idx/vsi_num to remove VSI access ++ * ice_vf_invalidate_vsi - invalidate vsi_idx to remove VSI access + * @vf: VF to remove access to VSI for + */ + void ice_vf_invalidate_vsi(struct ice_vf *vf) + { + vf->lan_vsi_idx = ICE_NO_VSI; +- vf->lan_vsi_num = ICE_NO_VSI; + } + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h +index 48fea6fa0362..1de07accbc5c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h +@@ -110,11 +110,6 @@ struct ice_vf { + u8 spoofchk:1; + u8 link_forced:1; + u8 link_up:1; /* only valid if VF link is forced */ +- /* VSI indices - actual VSI pointers are maintained in the PF structure +- * When assigned, these will be non-zero, because VSI 0 is always +- * the main LAN VSI for the PF. +- */ +- u16 lan_vsi_num; /* ID as used by firmware */ + unsigned int min_tx_rate; /* Minimum Tx bandwidth limit in Mbps */ + unsigned int max_tx_rate; /* Maximum Tx bandwidth limit in Mbps */ + DECLARE_BITMAP(vf_states, ICE_VF_STATES_NBITS); /* VF runtime states */ +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0030-ice-rename-ice_write_-functions-to-ice_pack_ctx_.patch b/kernel-rt/debian/patches/ice-VDF/0030-ice-rename-ice_write_-functions-to-ice_pack_ctx_.patch new file mode 100644 index 00000000..7f02562d --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0030-ice-rename-ice_write_-functions-to-ice_pack_ctx_.patch @@ -0,0 +1,150 @@ +From 6b7fae8669a04943af9f83ef89d39a922ed179fd Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Mon, 26 Feb 2024 16:14:54 -0800 +Subject: [PATCH 30/36] ice: rename ice_write_* functions to ice_pack_ctx_* + +In ice_common.c there are 4 functions used for converting the unpacked +software Tx and Rx context structure data into the packed format used by +hardware. These functions have extremely generic names: + + * ice_write_byte + * ice_write_word + * ice_write_dword + * ice_write_qword + +When I saw these function names my first thought was "write what? to +where?". Understanding what these functions do requires looking at the +implementation details. The functions take bits from an unpacked structure +and copy them into the packed layout used by hardware. + +As part of live migration, we will want functions which perform the inverse +operation of reading bits from the packed layout and copying them into the +unpacked format. Naming these as "ice_read_byte", etc would be very +confusing since they appear to write data. + +In preparation for adding this new inverse operation, rename the existing +functions to use the prefix "ice_pack_ctx_". This makes it clear that they +perform the bit packing while copying from the unpacked software context +structure to the packed hardware context. + +The inverse operations can then neatly be named ice_unpack_ctx_*, clearly +indicating they perform the bit unpacking while copying from the packed +hardware context to the unpacked software context structure. + +Signed-off-by: Jacob Keller +Reviewed-by: Przemek Kitszel +Signed-off-by: Tony Nguyen +(cherry picked from commit 1260b45dbe2dbc415f3bc1e841c6c098083bcfb8) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_common.c | 56 ++++++++++----------- + 1 file changed, 28 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 6dcba0577633..17f60a98c8ed 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -4267,13 +4267,13 @@ ice_aq_add_rdma_qsets(struct ice_hw *hw, u8 num_qset_grps, + /* End of FW Admin Queue command wrappers */ + + /** +- * ice_write_byte - write a byte to a packed context structure +- * @src_ctx: the context structure to read from +- * @dest_ctx: the context to be written to +- * @ce_info: a description of the struct to be filled ++ * ice_pack_ctx_byte - write a byte to a packed context structure ++ * @src_ctx: unpacked source context structure ++ * @dest_ctx: packed destination context data ++ * @ce_info: context element description + */ +-static void +-ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) ++static void ice_pack_ctx_byte(u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + u8 src_byte, dest_byte, mask; + u8 *from, *dest; +@@ -4306,13 +4306,13 @@ ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) + } + + /** +- * ice_write_word - write a word to a packed context structure +- * @src_ctx: the context structure to read from +- * @dest_ctx: the context to be written to +- * @ce_info: a description of the struct to be filled ++ * ice_pack_ctx_word - write a word to a packed context structure ++ * @src_ctx: unpacked source context structure ++ * @dest_ctx: packed destination context data ++ * @ce_info: context element description + */ +-static void +-ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) ++static void ice_pack_ctx_word(u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + u16 src_word, mask; + __le16 dest_word; +@@ -4349,13 +4349,13 @@ ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) + } + + /** +- * ice_write_dword - write a dword to a packed context structure +- * @src_ctx: the context structure to read from +- * @dest_ctx: the context to be written to +- * @ce_info: a description of the struct to be filled ++ * ice_pack_ctx_dword - write a dword to a packed context structure ++ * @src_ctx: unpacked source context structure ++ * @dest_ctx: packed destination context data ++ * @ce_info: context element description + */ +-static void +-ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) ++static void ice_pack_ctx_dword(u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + u32 src_dword, mask; + __le32 dest_dword; +@@ -4400,13 +4400,13 @@ ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) + } + + /** +- * ice_write_qword - write a qword to a packed context structure +- * @src_ctx: the context structure to read from +- * @dest_ctx: the context to be written to +- * @ce_info: a description of the struct to be filled ++ * ice_pack_ctx_qword - write a qword to a packed context structure ++ * @src_ctx: unpacked source context structure ++ * @dest_ctx: packed destination context data ++ * @ce_info: context element description + */ +-static void +-ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) ++static void ice_pack_ctx_qword(u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + u64 src_qword, mask; + __le64 dest_qword; +@@ -4475,16 +4475,16 @@ ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, + } + switch (ce_info[f].size_of) { + case sizeof(u8): +- ice_write_byte(src_ctx, dest_ctx, &ce_info[f]); ++ ice_pack_ctx_byte(src_ctx, dest_ctx, &ce_info[f]); + break; + case sizeof(u16): +- ice_write_word(src_ctx, dest_ctx, &ce_info[f]); ++ ice_pack_ctx_word(src_ctx, dest_ctx, &ce_info[f]); + break; + case sizeof(u32): +- ice_write_dword(src_ctx, dest_ctx, &ce_info[f]); ++ ice_pack_ctx_dword(src_ctx, dest_ctx, &ce_info[f]); + break; + case sizeof(u64): +- ice_write_qword(src_ctx, dest_ctx, &ce_info[f]); ++ ice_pack_ctx_qword(src_ctx, dest_ctx, &ce_info[f]); + break; + default: + return -EINVAL; +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0031-ice-use-GENMASK-instead-of-BIT-n-1-in-pack-functions.patch b/kernel-rt/debian/patches/ice-VDF/0031-ice-use-GENMASK-instead-of-BIT-n-1-in-pack-functions.patch new file mode 100644 index 00000000..1c8f1877 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0031-ice-use-GENMASK-instead-of-BIT-n-1-in-pack-functions.patch @@ -0,0 +1,129 @@ +From 619e0e61b39cf051137613459d36c4fe8f435e57 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Mon, 26 Feb 2024 16:14:55 -0800 +Subject: [PATCH 31/36] ice: use GENMASK instead of BIT(n) - 1 in pack + functions + +The functions used to pack the Tx and Rx context into the hardware format +rely on using BIT() and then subtracting 1 to get a bitmask. These +functions even have a comment about how x86 machines can't use this method +for certain widths because the SHL instructions will not work properly. + +The Linux kernel already provides the GENMASK macro for generating a +suitable bitmask. Further, GENMASK is capable of generating the mask +including the shift_width. Since width is the total field width, take care +to subtract one to get the final bit position. + +Since we now include the shifted bits as part of the mask, shift the source +value first before applying the mask. + +Signed-off-by: Jacob Keller +Reviewed-by: Przemek Kitszel +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit a45d1bf516c097bb7ae4983d3128ebf139be952c) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_common.c | 44 ++++----------------- + 1 file changed, 8 insertions(+), 36 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 17f60a98c8ed..55a2e264dd69 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -4284,14 +4284,11 @@ static void ice_pack_ctx_byte(u8 *src_ctx, u8 *dest_ctx, + + /* prepare the bits and mask */ + shift_width = ce_info->lsb % 8; +- mask = (u8)(BIT(ce_info->width) - 1); ++ mask = GENMASK(ce_info->width - 1 + shift_width, shift_width); + + src_byte = *from; +- src_byte &= mask; +- +- /* shift to correct alignment */ +- mask <<= shift_width; + src_byte <<= shift_width; ++ src_byte &= mask; + + /* get the current bits from the target bit string */ + dest = dest_ctx + (ce_info->lsb / 8); +@@ -4324,17 +4321,14 @@ static void ice_pack_ctx_word(u8 *src_ctx, u8 *dest_ctx, + + /* prepare the bits and mask */ + shift_width = ce_info->lsb % 8; +- mask = BIT(ce_info->width) - 1; ++ mask = GENMASK(ce_info->width - 1 + shift_width, shift_width); + + /* don't swizzle the bits until after the mask because the mask bits + * will be in a different bit position on big endian machines + */ + src_word = *(u16 *)from; +- src_word &= mask; +- +- /* shift to correct alignment */ +- mask <<= shift_width; + src_word <<= shift_width; ++ src_word &= mask; + + /* get the current bits from the target bit string */ + dest = dest_ctx + (ce_info->lsb / 8); +@@ -4367,25 +4361,14 @@ static void ice_pack_ctx_dword(u8 *src_ctx, u8 *dest_ctx, + + /* prepare the bits and mask */ + shift_width = ce_info->lsb % 8; +- +- /* if the field width is exactly 32 on an x86 machine, then the shift +- * operation will not work because the SHL instructions count is masked +- * to 5 bits so the shift will do nothing +- */ +- if (ce_info->width < 32) +- mask = BIT(ce_info->width) - 1; +- else +- mask = (u32)~0; ++ mask = GENMASK(ce_info->width - 1 + shift_width, shift_width); + + /* don't swizzle the bits until after the mask because the mask bits + * will be in a different bit position on big endian machines + */ + src_dword = *(u32 *)from; +- src_dword &= mask; +- +- /* shift to correct alignment */ +- mask <<= shift_width; + src_dword <<= shift_width; ++ src_dword &= mask; + + /* get the current bits from the target bit string */ + dest = dest_ctx + (ce_info->lsb / 8); +@@ -4418,25 +4401,14 @@ static void ice_pack_ctx_qword(u8 *src_ctx, u8 *dest_ctx, + + /* prepare the bits and mask */ + shift_width = ce_info->lsb % 8; +- +- /* if the field width is exactly 64 on an x86 machine, then the shift +- * operation will not work because the SHL instructions count is masked +- * to 6 bits so the shift will do nothing +- */ +- if (ce_info->width < 64) +- mask = BIT_ULL(ce_info->width) - 1; +- else +- mask = (u64)~0; ++ mask = GENMASK_ULL(ce_info->width - 1 + shift_width, shift_width); + + /* don't swizzle the bits until after the mask because the mask bits + * will be in a different bit position on big endian machines + */ + src_qword = *(u64 *)from; +- src_qword &= mask; +- +- /* shift to correct alignment */ +- mask <<= shift_width; + src_qword <<= shift_width; ++ src_qword &= mask; + + /* get the current bits from the target bit string */ + dest = dest_ctx + (ce_info->lsb / 8); +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0032-ice-cleanup-line-splitting-for-context-set-functions.patch b/kernel-rt/debian/patches/ice-VDF/0032-ice-cleanup-line-splitting-for-context-set-functions.patch new file mode 100644 index 00000000..4ab4b491 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0032-ice-cleanup-line-splitting-for-context-set-functions.patch @@ -0,0 +1,89 @@ +From 6502dd63a7bd436c72d2ee8b328985b93fa7e2a5 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Mon, 26 Feb 2024 16:14:56 -0800 +Subject: [PATCH 32/36] ice: cleanup line splitting for context set functions + +The indentation for ice_set_ctx and ice_write_rxq_ctx breaks the function +name after the return type. This style of breaking is used a lot throughout +the ice driver, even in cases where its not actually helpful for +readability. We no longer prefer this style of line splitting in the +driver, and new code is avoiding it. + +Normally, I would leave this alone unless the actual function contents or +description needed updating. However, a future change is going to add +inverse functions for converting packed context to unpacked context +structures. To keep this code uniform with the existing set functions, fix +up the style to the modern format of keeping the type on the same line. + +Signed-off-by: Jacob Keller +Reviewed-by: Przemek Kitszel +Signed-off-by: Tony Nguyen +(cherry picked from commit 979c2c049fbea107ce9f8d31f3ba9dba83ddb0a2) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_common.c | 12 +++++------- + drivers/net/ethernet/intel/ice/ice_common.h | 10 ++++------ + 2 files changed, 9 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 55a2e264dd69..59ede77a1473 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -1329,9 +1329,8 @@ static const struct ice_ctx_ele ice_rlan_ctx_info[] = { + * it to HW register space and enables the hardware to prefetch descriptors + * instead of only fetching them on demand + */ +-int +-ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, +- u32 rxq_index) ++int ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, ++ u32 rxq_index) + { + u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 }; + +@@ -4427,11 +4426,10 @@ static void ice_pack_ctx_qword(u8 *src_ctx, u8 *dest_ctx, + * @hw: pointer to the hardware structure + * @src_ctx: pointer to a generic non-packed context structure + * @dest_ctx: pointer to memory for the packed structure +- * @ce_info: a description of the structure to be transformed ++ * @ce_info: List of Rx context elements + */ +-int +-ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, +- const struct ice_ctx_ele *ce_info) ++int ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + int f; + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h +index d47e5400351f..1c3c29d30815 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.h ++++ b/drivers/net/ethernet/intel/ice/ice_common.h +@@ -52,9 +52,8 @@ int ice_get_caps(struct ice_hw *hw); + + void ice_set_safe_mode_caps(struct ice_hw *hw); + +-int +-ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, +- u32 rxq_index); ++int ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, ++ u32 rxq_index); + + int + ice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params); +@@ -71,9 +70,8 @@ bool ice_check_sq_alive(struct ice_hw *hw, struct ice_ctl_q_info *cq); + int ice_aq_q_shutdown(struct ice_hw *hw, bool unloading); + void ice_fill_dflt_direct_cmd_desc(struct ice_aq_desc *desc, u16 opcode); + extern const struct ice_ctx_ele ice_tlan_ctx_info[]; +-int +-ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, +- const struct ice_ctx_ele *ce_info); ++int ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info); + + extern struct mutex ice_global_cfg_lock_sw; + +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0033-ice-do-not-disable-Tx-queues-twice-in-ice_down.patch b/kernel-rt/debian/patches/ice-VDF/0033-ice-do-not-disable-Tx-queues-twice-in-ice_down.patch new file mode 100644 index 00000000..a740f1ff --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0033-ice-do-not-disable-Tx-queues-twice-in-ice_down.patch @@ -0,0 +1,161 @@ +From 675a8843a0de1411666389eeabeea452161f8cc5 Mon Sep 17 00:00:00 2001 +From: Maciej Fijalkowski +Date: Fri, 23 Feb 2024 17:06:27 +0100 +Subject: [PATCH 33/36] ice: do not disable Tx queues twice in ice_down() + +ice_down() clears QINT_TQCTL_CAUSE_ENA_M bit twice, which is not +necessary. First clearing happens in ice_vsi_dis_irq() and second in +ice_vsi_stop_tx_ring() - remove the first one. + +While at it, make ice_vsi_dis_irq() static as ice_down() is the only +current caller of it. + +Signed-off-by: Maciej Fijalkowski +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit d5926e01e3739542bb047b77f850d7f641eaa7bc) +[Adjust ice_lib.c with the context change.] +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_lib.c | 55 ----------------------- + drivers/net/ethernet/intel/ice/ice_lib.h | 2 - + drivers/net/ethernet/intel/ice/ice_main.c | 44 ++++++++++++++++++ + 3 files changed, 44 insertions(+), 57 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index 106ef843f4b5..f23cb9c8e3dd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -2877,61 +2877,6 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked) + } + } + +-/** +- * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI +- * @vsi: the VSI being un-configured +- */ +-void ice_vsi_dis_irq(struct ice_vsi *vsi) +-{ +- struct ice_pf *pf = vsi->back; +- struct ice_hw *hw = &pf->hw; +- u32 val; +- int i; +- +- /* disable interrupt causation from each queue */ +- if (vsi->tx_rings) { +- ice_for_each_txq(vsi, i) { +- if (vsi->tx_rings[i]) { +- u16 reg; +- +- reg = vsi->tx_rings[i]->reg_idx; +- val = rd32(hw, QINT_TQCTL(reg)); +- val &= ~QINT_TQCTL_CAUSE_ENA_M; +- wr32(hw, QINT_TQCTL(reg), val); +- } +- } +- } +- +- if (vsi->rx_rings) { +- ice_for_each_rxq(vsi, i) { +- if (vsi->rx_rings[i]) { +- u16 reg; +- +- reg = vsi->rx_rings[i]->reg_idx; +- val = rd32(hw, QINT_RQCTL(reg)); +- val &= ~QINT_RQCTL_CAUSE_ENA_M; +- wr32(hw, QINT_RQCTL(reg), val); +- } +- } +- } +- +- /* disable each interrupt */ +- ice_for_each_q_vector(vsi, i) { +- if (!vsi->q_vectors[i]) +- continue; +- wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); +- } +- +- ice_flush(hw); +- +- /* don't call synchronize_irq() for VF's from the host */ +- if (vsi->type == ICE_VSI_VF) +- return; +- +- ice_for_each_q_vector(vsi, i) +- synchronize_irq(vsi->q_vectors[i]->irq.virq); +-} +- + /** + * ice_vsi_release - Delete a VSI and free its resources + * @vsi: the VSI being removed +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h +index f24f5d1e6f9c..dbd0f3409323 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.h ++++ b/drivers/net/ethernet/intel/ice/ice_lib.h +@@ -110,8 +110,6 @@ void + ice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio, + bool ena_ts); + +-void ice_vsi_dis_irq(struct ice_vsi *vsi); +- + void ice_vsi_free_irq(struct ice_vsi *vsi); + + void ice_vsi_free_rx_rings(struct ice_vsi *vsi); +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index c882c218281a..685635a22616 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -7023,6 +7023,50 @@ static void ice_napi_disable_all(struct ice_vsi *vsi) + } + } + ++/** ++ * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI ++ * @vsi: the VSI being un-configured ++ */ ++static void ice_vsi_dis_irq(struct ice_vsi *vsi) ++{ ++ struct ice_pf *pf = vsi->back; ++ struct ice_hw *hw = &pf->hw; ++ u32 val; ++ int i; ++ ++ /* disable interrupt causation from each Rx queue; Tx queues are ++ * handled in ice_vsi_stop_tx_ring() ++ */ ++ if (vsi->rx_rings) { ++ ice_for_each_rxq(vsi, i) { ++ if (vsi->rx_rings[i]) { ++ u16 reg; ++ ++ reg = vsi->rx_rings[i]->reg_idx; ++ val = rd32(hw, QINT_RQCTL(reg)); ++ val &= ~QINT_RQCTL_CAUSE_ENA_M; ++ wr32(hw, QINT_RQCTL(reg), val); ++ } ++ } ++ } ++ ++ /* disable each interrupt */ ++ ice_for_each_q_vector(vsi, i) { ++ if (!vsi->q_vectors[i]) ++ continue; ++ wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); ++ } ++ ++ ice_flush(hw); ++ ++ /* don't call synchronize_irq() for VF's from the host */ ++ if (vsi->type == ICE_VSI_VF) ++ return; ++ ++ ice_for_each_q_vector(vsi, i) ++ synchronize_irq(vsi->q_vectors[i]->irq.virq); ++} ++ + /** + * ice_down - Shutdown the connection + * @vsi: The VSI being stopped +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0034-ice-Fix-improper-extts-handling.patch b/kernel-rt/debian/patches/ice-VDF/0034-ice-Fix-improper-extts-handling.patch new file mode 100644 index 00000000..928b20bf --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0034-ice-Fix-improper-extts-handling.patch @@ -0,0 +1,274 @@ +From e53280c20bbe58015a91178268244d5e831276f4 Mon Sep 17 00:00:00 2001 +From: Milena Olech +Date: Tue, 2 Jul 2024 10:14:54 -0700 +Subject: [PATCH 34/36] ice: Fix improper extts handling + +Extts events are disabled and enabled by the application ts2phc. +However, in case where the driver is removed when the application is +running, a specific extts event remains enabled and can cause a kernel +crash. +As a side effect, when the driver is reloaded and application is started +again, remaining extts event for the channel from a previous run will +keep firing and the message "extts on unexpected channel" might be +printed to the user. + +To avoid that, extts events shall be disabled when PTP is released. + +Fixes: 172db5f91d5f ("ice: add support for auxiliary input/output pins") +Reviewed-by: Przemek Kitszel +Co-developed-by: Jacob Keller +Signed-off-by: Jacob Keller +Signed-off-by: Milena Olech +Signed-off-by: Karol Kolacinski +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20240702171459.2606611-2-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit 00d3b4f54582d4e4a02cda5886bb336eeab268cc) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 105 ++++++++++++++++++----- + drivers/net/ethernet/intel/ice/ice_ptp.h | 8 ++ + 2 files changed, 91 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 48ec59fc5d87..6e06c5d596b9 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1603,27 +1603,24 @@ void ice_ptp_extts_event(struct ice_pf *pf) + /** + * ice_ptp_cfg_extts - Configure EXTTS pin and channel + * @pf: Board private structure +- * @ena: true to enable; false to disable + * @chan: GPIO channel (0-3) +- * @gpio_pin: GPIO pin +- * @extts_flags: request flags from the ptp_extts_request.flags ++ * @config: desired EXTTS configuration. ++ * @store: If set to true, the values will be stored ++ * ++ * Configure an external timestamp event on the requested channel. + */ +-static int +-ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin, +- unsigned int extts_flags) ++static void ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan, ++ struct ice_extts_channel *config, bool store) + { + u32 func, aux_reg, gpio_reg, irq_reg; + struct ice_hw *hw = &pf->hw; + u8 tmr_idx; + +- if (chan > (unsigned int)pf->ptp.info.n_ext_ts) +- return -EINVAL; +- + tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; + + irq_reg = rd32(hw, PFINT_OICR_ENA); + +- if (ena) { ++ if (config->ena) { + /* Enable the interrupt */ + irq_reg |= PFINT_OICR_TSYN_EVNT_M; + aux_reg = GLTSYN_AUX_IN_0_INT_ENA_M; +@@ -1632,9 +1629,9 @@ ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin, + #define GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE BIT(1) + + /* set event level to requested edge */ +- if (extts_flags & PTP_FALLING_EDGE) ++ if (config->flags & PTP_FALLING_EDGE) + aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE; +- if (extts_flags & PTP_RISING_EDGE) ++ if (config->flags & PTP_RISING_EDGE) + aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_RISING_EDGE; + + /* Write GPIO CTL reg. +@@ -1656,9 +1653,47 @@ ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin, + + wr32(hw, PFINT_OICR_ENA, irq_reg); + wr32(hw, GLTSYN_AUX_IN(chan, tmr_idx), aux_reg); +- wr32(hw, GLGEN_GPIO_CTL(gpio_pin), gpio_reg); ++ wr32(hw, GLGEN_GPIO_CTL(config->gpio_pin), gpio_reg); + +- return 0; ++ if (store) ++ memcpy(&pf->ptp.extts_channels[chan], config, sizeof(*config)); ++} ++ ++/** ++ * ice_ptp_disable_all_extts - Disable all EXTTS channels ++ * @pf: Board private structure ++ */ ++static void ice_ptp_disable_all_extts(struct ice_pf *pf) ++{ ++ struct ice_extts_channel extts_cfg = {}; ++ int i; ++ ++ for (i = 0; i < pf->ptp.info.n_ext_ts; i++) { ++ if (pf->ptp.extts_channels[i].ena) { ++ extts_cfg.gpio_pin = pf->ptp.extts_channels[i].gpio_pin; ++ extts_cfg.ena = false; ++ ice_ptp_cfg_extts(pf, i, &extts_cfg, false); ++ } ++ } ++ ++ synchronize_irq(pf->oicr_irq.virq); ++} ++ ++/** ++ * ice_ptp_enable_all_extts - Enable all EXTTS channels ++ * @pf: Board private structure ++ * ++ * Called during reset to restore user configuration. ++ */ ++static void ice_ptp_enable_all_extts(struct ice_pf *pf) ++{ ++ int i; ++ ++ for (i = 0; i < pf->ptp.info.n_ext_ts; i++) { ++ if (pf->ptp.extts_channels[i].ena) ++ ice_ptp_cfg_extts(pf, i, &pf->ptp.extts_channels[i], ++ false); ++ } + } + + /** +@@ -1815,7 +1850,6 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info, + struct ptp_clock_request *rq, int on) + { + struct ice_pf *pf = ptp_info_to_pf(info); +- struct ice_perout_channel clk_cfg = {0}; + bool sma_pres = false; + unsigned int chan; + u32 gpio_pin; +@@ -1826,6 +1860,9 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info, + + switch (rq->type) { + case PTP_CLK_REQ_PEROUT: ++ { ++ struct ice_perout_channel clk_cfg = {}; ++ + chan = rq->perout.index; + if (sma_pres) { + if (chan == ice_pin_desc_e810t[SMA1].chan) +@@ -1853,7 +1890,11 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info, + + err = ice_ptp_cfg_clkout(pf, chan, &clk_cfg, true); + break; ++ } + case PTP_CLK_REQ_EXTTS: ++ { ++ struct ice_extts_channel extts_cfg = {}; ++ + chan = rq->extts.index; + if (sma_pres) { + if (chan < ice_pin_desc_e810t[SMA2].chan) +@@ -1869,9 +1910,13 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info, + gpio_pin = chan; + } + +- err = ice_ptp_cfg_extts(pf, !!on, chan, gpio_pin, +- rq->extts.flags); +- break; ++ extts_cfg.flags = rq->extts.flags; ++ extts_cfg.gpio_pin = gpio_pin; ++ extts_cfg.ena = !!on; ++ ++ ice_ptp_cfg_extts(pf, chan, &extts_cfg, true); ++ return 0; ++ } + default: + return -EOPNOTSUPP; + } +@@ -1889,21 +1934,31 @@ static int ice_ptp_gpio_enable_e823(struct ptp_clock_info *info, + struct ptp_clock_request *rq, int on) + { + struct ice_pf *pf = ptp_info_to_pf(info); +- struct ice_perout_channel clk_cfg = {0}; + int err; + + switch (rq->type) { + case PTP_CLK_REQ_PPS: ++ { ++ struct ice_perout_channel clk_cfg = {}; ++ + clk_cfg.gpio_pin = PPS_PIN_INDEX; + clk_cfg.period = NSEC_PER_SEC; + clk_cfg.ena = !!on; + + err = ice_ptp_cfg_clkout(pf, PPS_CLK_GEN_CHAN, &clk_cfg, true); + break; ++ } + case PTP_CLK_REQ_EXTTS: +- err = ice_ptp_cfg_extts(pf, !!on, rq->extts.index, +- TIME_SYNC_PIN_INDEX, rq->extts.flags); +- break; ++ { ++ struct ice_extts_channel extts_cfg = {}; ++ ++ extts_cfg.flags = rq->extts.flags; ++ extts_cfg.gpio_pin = TIME_SYNC_PIN_INDEX; ++ extts_cfg.ena = !!on; ++ ++ ice_ptp_cfg_extts(pf, rq->extts.index, &extts_cfg, true); ++ return 0; ++ } + default: + return -EOPNOTSUPP; + } +@@ -2735,6 +2790,10 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf) + ice_ptp_restart_all_phy(pf); + } + ++ /* Re-enable all periodic outputs and external timestamp events */ ++ ice_ptp_enable_all_clkout(pf); ++ ice_ptp_enable_all_extts(pf); ++ + return 0; + } + +@@ -3286,6 +3345,8 @@ void ice_ptp_release(struct ice_pf *pf) + + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); + ++ ice_ptp_disable_all_extts(pf); ++ + kthread_cancel_delayed_work_sync(&pf->ptp.work); + + ice_ptp_port_phy_stop(&pf->ptp.port); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 352405a2daf2..c6469a5a7afb 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -33,6 +33,12 @@ struct ice_perout_channel { + u64 start_time; + }; + ++struct ice_extts_channel { ++ bool ena; ++ u32 gpio_pin; ++ u32 flags; ++}; ++ + /* The ice hardware captures Tx hardware timestamps in the PHY. The timestamp + * is stored in a buffer of registers. Depending on the specific hardware, + * this buffer might be shared across multiple PHY ports. +@@ -226,6 +232,7 @@ enum ice_ptp_state { + * @ext_ts_irq: the external timestamp IRQ in use + * @kworker: kwork thread for handling periodic work + * @perout_channels: periodic output data ++ * @extts_channels: channels for external timestamps + * @info: structure defining PTP hardware capabilities + * @clock: pointer to registered PTP clock device + * @tstamp_config: hardware timestamping configuration +@@ -249,6 +256,7 @@ struct ice_ptp { + u8 ext_ts_irq; + struct kthread_worker *kworker; + struct ice_perout_channel perout_channels[GLTSYN_TGT_H_IDX_MAX]; ++ struct ice_extts_channel extts_channels[GLTSYN_TGT_H_IDX_MAX]; + struct ptp_clock_info info; + struct ptp_clock *clock; + struct hwtstamp_config tstamp_config; +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0035-ice-Don-t-process-extts-if-PTP-is-disabled.patch b/kernel-rt/debian/patches/ice-VDF/0035-ice-Don-t-process-extts-if-PTP-is-disabled.patch new file mode 100644 index 00000000..feef0a9f --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0035-ice-Don-t-process-extts-if-PTP-is-disabled.patch @@ -0,0 +1,49 @@ +From 6c24a32820031f9713d0c0cf7ac6f4ead6b58052 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 2 Jul 2024 10:14:55 -0700 +Subject: [PATCH 35/36] ice: Don't process extts if PTP is disabled + +The ice_ptp_extts_event() function can race with ice_ptp_release() and +result in a NULL pointer dereference which leads to a kernel panic. + +Panic occurs because the ice_ptp_extts_event() function calls +ptp_clock_event() with a NULL pointer. The ice driver has already +released the PTP clock by the time the interrupt for the next external +timestamp event occurs. + +To fix this, modify the ice_ptp_extts_event() function to check the +PTP state and bail early if PTP is not ready. + +Fixes: 172db5f91d5f ("ice: add support for auxiliary input/output pins") +Reviewed-by: Przemek Kitszel +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20240702171459.2606611-3-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit 996422e3230e41468f652d754fefd1bdbcd4604e) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 6e06c5d596b9..ceb4ba19c511 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1578,6 +1578,10 @@ void ice_ptp_extts_event(struct ice_pf *pf) + u8 chan, tmr_idx; + u32 hi, lo; + ++ /* Don't process timestamp events if PTP is not ready */ ++ if (pf->ptp.state != ICE_PTP_READY) ++ return; ++ + tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; + /* Event time is captured by one of the two matched registers + * GLTSYN_EVNT_L: 32 LSB of sampled time event +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0036-ice-Introduce-ice_ptp_hw-struct.patch b/kernel-rt/debian/patches/ice-VDF/0036-ice-Introduce-ice_ptp_hw-struct.patch new file mode 100644 index 00000000..6d5456da --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0036-ice-Introduce-ice_ptp_hw-struct.patch @@ -0,0 +1,628 @@ +From 1ce01cb7cdb0bf4c18a546a62f224c8032d75ebd Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Tue, 28 May 2024 16:03:51 -0700 +Subject: [PATCH 36/36] ice: Introduce ice_ptp_hw struct + +Create new ice_ptp_hw struct and use it for all HW and PTP-related +fields from struct ice_hw. +Replace definitions with struct fields, which values are set accordingly +to a specific device. + +Reviewed-by: Przemek Kitszel +Reviewed-by: Arkadiusz Kubalewski +Signed-off-by: Karol Kolacinski +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Jacob Keller +Link: https://lore.kernel.org/r/20240528-next-2024-05-28-ptp-refactors-v1-1-c082739bb6f6@intel.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit d551d075b043821880b8afc0010ef70d050716d0) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_common.c | 24 ++++ + drivers/net/ethernet/intel/ice/ice_common.h | 1 + + drivers/net/ethernet/intel/ice/ice_ptp.c | 22 ++-- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 134 ++++++++++++-------- + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 4 +- + drivers/net/ethernet/intel/ice/ice_type.h | 17 ++- + 6 files changed, 126 insertions(+), 76 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 59ede77a1473..147004e0170b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -209,6 +209,30 @@ bool ice_is_e810t(struct ice_hw *hw) + return false; + } + ++/** ++ * ice_is_e822 - Check if a device is E822 family device ++ * @hw: pointer to the hardware structure ++ * ++ * Return: true if the device is E822 based, false if not. ++ */ ++bool ice_is_e822(struct ice_hw *hw) ++{ ++ switch (hw->device_id) { ++ case ICE_DEV_ID_E822C_BACKPLANE: ++ case ICE_DEV_ID_E822C_QSFP: ++ case ICE_DEV_ID_E822C_SFP: ++ case ICE_DEV_ID_E822C_10G_BASE_T: ++ case ICE_DEV_ID_E822C_SGMII: ++ case ICE_DEV_ID_E822L_BACKPLANE: ++ case ICE_DEV_ID_E822L_SFP: ++ case ICE_DEV_ID_E822L_10G_BASE_T: ++ case ICE_DEV_ID_E822L_SGMII: ++ return true; ++ default: ++ return false; ++ } ++} ++ + /** + * ice_is_e823 + * @hw: pointer to the hardware structure +diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h +index 1c3c29d30815..9d38777310e5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.h ++++ b/drivers/net/ethernet/intel/ice/ice_common.h +@@ -245,6 +245,7 @@ void + ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, + u64 *prev_stat, u64 *cur_stat); + bool ice_is_e810t(struct ice_hw *hw); ++bool ice_is_e822(struct ice_hw *hw); + bool ice_is_e823(struct ice_hw *hw); + int + ice_sched_query_elem(struct ice_hw *hw, u32 node_teid, +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index ceb4ba19c511..bb1572a353d0 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -812,7 +812,7 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) + } + mutex_unlock(&pf->ptp.ports_owner.lock); + +- for (i = 0; i < ICE_MAX_QUAD; i++) { ++ for (i = 0; i < ICE_GET_QUAD_NUM(pf->hw.ptp.num_lports); i++) { + u64 tstamp_ready; + int err; + +@@ -1026,7 +1026,7 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + static int + ice_ptp_init_tx_e82x(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port) + { +- tx->block = port / ICE_PORTS_PER_QUAD; ++ tx->block = ICE_GET_QUAD_NUM(port); + tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E82X; + tx->len = INDEX_PER_PORT_E82X; + tx->has_ready_bitmap = 1; +@@ -1248,8 +1248,8 @@ static u64 ice_base_incval(struct ice_pf *pf) + */ + static int ice_ptp_check_tx_fifo(struct ice_ptp_port *port) + { +- int quad = port->port_num / ICE_PORTS_PER_QUAD; + int offs = port->port_num % ICE_PORTS_PER_QUAD; ++ int quad = ICE_GET_QUAD_NUM(port->port_num); + struct ice_pf *pf; + struct ice_hw *hw; + u32 val, phy_sts; +@@ -1448,7 +1448,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + if (pf->ptp.state != ICE_PTP_READY) + return; + +- if (WARN_ON_ONCE(port >= ICE_NUM_EXTERNAL_PORTS)) ++ if (WARN_ON_ONCE(port >= hw->ptp.num_lports)) + return; + + ptp_port = &pf->ptp.port; +@@ -1458,7 +1458,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + /* Update cached link status for this port immediately */ + ptp_port->link_up = linkup; + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + /* Do not reconfigure E810 PHY */ + return; +@@ -1487,7 +1487,7 @@ static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold) + + ice_ptp_reset_ts_memory(hw); + +- for (quad = 0; quad < ICE_MAX_QUAD; quad++) { ++ for (quad = 0; quad < ICE_GET_QUAD_NUM(hw->ptp.num_lports); quad++) { + err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, + &val); + if (err) +@@ -2038,7 +2038,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts) + ice_ptp_enable_all_clkout(pf); + + /* Recalibrate and re-enable timestamp blocks for E822/E823 */ +- if (hw->phy_model == ICE_PHY_E82X) ++ if (hw->ptp.phy_model == ICE_PHY_E82X) + ice_ptp_restart_all_phy(pf); + exit: + if (err) { +@@ -2652,7 +2652,7 @@ static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf) + if (!ice_pf_src_tmr_owned(pf)) + return; + +- for (i = 0; i < ICE_MAX_QUAD; i++) { ++ for (i = 0; i < ICE_GET_QUAD_NUM(hw->ptp.num_lports); i++) { + u64 tstamp_ready; + int err; + +@@ -3152,7 +3152,7 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + + mutex_init(&ptp_port->ps_lock); + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_ptp_init_tx_e810(pf, &ptp_port->tx); + case ICE_PHY_E82X: +@@ -3245,7 +3245,7 @@ static void ice_ptp_remove_auxbus_device(struct ice_pf *pf) + */ + static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf) + { +- switch (pf->hw.phy_model) { ++ switch (pf->hw.ptp.phy_model) { + case ICE_PHY_E82X: + /* E822 based PHY has the clock owner process the interrupt + * for all ports. +@@ -3281,7 +3281,7 @@ void ice_ptp_init(struct ice_pf *pf) + + ptp->state = ICE_PTP_INITIALIZING; + +- ice_ptp_init_phy_model(hw); ++ ice_ptp_init_hw(hw); + + ice_ptp_init_tx_interrupt_mode(pf); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index 7337e7e710ed..313a72dad813 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -285,18 +285,21 @@ static void ice_ptp_exec_tmr_cmd(struct ice_hw *hw) + + /** + * ice_fill_phy_msg_e82x - Fill message data for a PHY register access ++ * @hw: pointer to the HW struct + * @msg: the PHY message buffer to fill in + * @port: the port to access + * @offset: the register offset + */ +-static void +-ice_fill_phy_msg_e82x(struct ice_sbq_msg_input *msg, u8 port, u16 offset) ++static void ice_fill_phy_msg_e82x(struct ice_hw *hw, ++ struct ice_sbq_msg_input *msg, u8 port, ++ u16 offset) + { + int phy_port, phy, quadtype; + +- phy_port = port % ICE_PORTS_PER_PHY_E82X; +- phy = port / ICE_PORTS_PER_PHY_E82X; +- quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E82X; ++ phy_port = port % hw->ptp.ports_per_phy; ++ phy = port / hw->ptp.ports_per_phy; ++ quadtype = ICE_GET_QUAD_NUM(port) % ++ ICE_GET_QUAD_NUM(hw->ptp.ports_per_phy); + + if (quadtype == 0) { + msg->msg_addr_low = P_Q0_L(P_0_BASE + offset, phy_port); +@@ -427,7 +430,7 @@ ice_read_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 offset, u32 *val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- ice_fill_phy_msg_e82x(&msg, port, offset); ++ ice_fill_phy_msg_e82x(hw, &msg, port, offset); + msg.opcode = ice_sbq_msg_rd; + + err = ice_sbq_rw_reg(hw, &msg); +@@ -504,7 +507,7 @@ ice_write_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 offset, u32 val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- ice_fill_phy_msg_e82x(&msg, port, offset); ++ ice_fill_phy_msg_e82x(hw, &msg, port, offset); + msg.opcode = ice_sbq_msg_wr; + msg.data = val; + +@@ -614,24 +617,30 @@ ice_write_64b_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + + /** + * ice_fill_quad_msg_e82x - Fill message data for quad register access ++ * @hw: pointer to the HW struct + * @msg: the PHY message buffer to fill in + * @quad: the quad to access + * @offset: the register offset + * + * Fill a message buffer for accessing a register in a quad shared between + * multiple PHYs. ++ * ++ * Return: ++ * * %0 - OK ++ * * %-EINVAL - invalid quad number + */ +-static int +-ice_fill_quad_msg_e82x(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) ++static int ice_fill_quad_msg_e82x(struct ice_hw *hw, ++ struct ice_sbq_msg_input *msg, u8 quad, ++ u16 offset) + { + u32 addr; + +- if (quad >= ICE_MAX_QUAD) ++ if (quad >= ICE_GET_QUAD_NUM(hw->ptp.num_lports)) + return -EINVAL; + + msg->dest_dev = rmn_0; + +- if ((quad % ICE_QUADS_PER_PHY_E82X) == 0) ++ if (!(quad % ICE_GET_QUAD_NUM(hw->ptp.ports_per_phy))) + addr = Q_0_BASE + offset; + else + addr = Q_1_BASE + offset; +@@ -658,7 +667,7 @@ ice_read_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- err = ice_fill_quad_msg_e82x(&msg, quad, offset); ++ err = ice_fill_quad_msg_e82x(hw, &msg, quad, offset); + if (err) + return err; + +@@ -692,7 +701,7 @@ ice_write_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- err = ice_fill_quad_msg_e82x(&msg, quad, offset); ++ err = ice_fill_quad_msg_e82x(hw, &msg, quad, offset); + if (err) + return err; + +@@ -813,7 +822,7 @@ static void ice_ptp_reset_ts_memory_e82x(struct ice_hw *hw) + { + unsigned int quad; + +- for (quad = 0; quad < ICE_MAX_QUAD; quad++) ++ for (quad = 0; quad < ICE_GET_QUAD_NUM(hw->ptp.num_lports); quad++) + ice_ptp_reset_ts_memory_quad_e82x(hw, quad); + } + +@@ -1110,7 +1119,7 @@ static int ice_ptp_set_vernier_wl(struct ice_hw *hw) + { + u8 port; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + int err; + + err = ice_write_phy_reg_e82x(hw, port, P_REG_WL, +@@ -1175,7 +1184,7 @@ ice_ptp_prep_phy_time_e82x(struct ice_hw *hw, u32 time) + */ + phy_time = (u64)time << 32; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + /* Tx case */ + err = ice_write_64b_phy_reg_e82x(hw, port, + P_REG_TX_TIMER_INC_PRE_L, +@@ -1278,7 +1287,7 @@ ice_ptp_prep_phy_adj_e82x(struct ice_hw *hw, s32 adj) + else + cycles = -(((s64)-adj) << 32); + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + int err; + + err = ice_ptp_prep_port_adj_e82x(hw, port, cycles); +@@ -1304,7 +1313,7 @@ ice_ptp_prep_phy_incval_e82x(struct ice_hw *hw, u64 incval) + int err; + u8 port; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_TIMETUS_L, + incval); + if (err) +@@ -1460,7 +1469,7 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + { + u8 port; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + enum ice_ptp_tmr_cmd cmd; + int err; + +@@ -1490,7 +1499,7 @@ ice_ptp_port_cmd_e82x(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + { + u8 port; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + int err; + + err = ice_ptp_write_port_cmd_e82x(hw, port, cmd); +@@ -1603,7 +1612,7 @@ static void ice_phy_cfg_lane_e82x(struct ice_hw *hw, u8 port) + return; + } + +- quad = port / ICE_PORTS_PER_QUAD; ++ quad = ICE_GET_QUAD_NUM(port); + + err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, &val); + if (err) { +@@ -2632,6 +2641,17 @@ ice_get_phy_tx_tstamp_ready_e82x(struct ice_hw *hw, u8 quad, u64 *tstamp_ready) + return 0; + } + ++/** ++ * ice_ptp_init_phy_e82x - initialize PHY parameters ++ * @ptp: pointer to the PTP HW struct ++ */ ++static void ice_ptp_init_phy_e82x(struct ice_ptp_hw *ptp) ++{ ++ ptp->phy_model = ICE_PHY_E82X; ++ ptp->num_lports = 8; ++ ptp->ports_per_phy = 8; ++} ++ + /* E810 functions + * + * The following functions operate on the E810 series devices which use +@@ -2859,17 +2879,21 @@ static int ice_clear_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx) + } + + /** +- * ice_ptp_init_phy_e810 - Enable PTP function on the external PHY ++ * ice_ptp_init_phc_e810 - Perform E810 specific PHC initialization + * @hw: pointer to HW struct + * +- * Enable the timesync PTP functionality for the external PHY connected to +- * this function. ++ * Perform E810-specific PTP hardware clock initialization steps. ++ * ++ * Return: 0 on success, other error codes when failed to initialize TimeSync + */ +-int ice_ptp_init_phy_e810(struct ice_hw *hw) ++static int ice_ptp_init_phc_e810(struct ice_hw *hw) + { + u8 tmr_idx; + int err; + ++ /* Ensure synchronization delay is zero */ ++ wr32(hw, GLTSYN_SYNC_DLAY, 0); ++ + tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; + err = ice_write_phy_reg_e810(hw, ETH_GLTSYN_ENA(tmr_idx), + GLTSYN_ENA_TSYN_ENA_M); +@@ -2880,21 +2904,6 @@ int ice_ptp_init_phy_e810(struct ice_hw *hw) + return err; + } + +-/** +- * ice_ptp_init_phc_e810 - Perform E810 specific PHC initialization +- * @hw: pointer to HW struct +- * +- * Perform E810-specific PTP hardware clock initialization steps. +- */ +-static int ice_ptp_init_phc_e810(struct ice_hw *hw) +-{ +- /* Ensure synchronization delay is zero */ +- wr32(hw, GLTSYN_SYNC_DLAY, 0); +- +- /* Initialize the PHY */ +- return ice_ptp_init_phy_e810(hw); +-} +- + /** + * ice_ptp_prep_phy_time_e810 - Prepare PHY port with initial time + * @hw: Board private structure +@@ -3238,6 +3247,17 @@ int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data) + return ice_aq_read_i2c(hw, link_topo, 0, addr, 1, data, NULL); + } + ++/** ++ * ice_ptp_init_phy_e810 - initialize PHY parameters ++ * @ptp: pointer to the PTP HW struct ++ */ ++static void ice_ptp_init_phy_e810(struct ice_ptp_hw *ptp) ++{ ++ ptp->phy_model = ICE_PHY_E810; ++ ptp->num_lports = 8; ++ ptp->ports_per_phy = 4; ++} ++ + /* Device agnostic functions + * + * The following functions implement shared behavior common to both E822 and +@@ -3295,18 +3315,22 @@ void ice_ptp_unlock(struct ice_hw *hw) + } + + /** +- * ice_ptp_init_phy_model - Initialize hw->phy_model based on device type ++ * ice_ptp_init_hw - Initialize hw based on device type + * @hw: pointer to the HW structure + * +- * Determine the PHY model for the device, and initialize hw->phy_model ++ * Determine the PHY model for the device, and initialize hw + * for use by other functions. + */ +-void ice_ptp_init_phy_model(struct ice_hw *hw) ++void ice_ptp_init_hw(struct ice_hw *hw) + { +- if (ice_is_e810(hw)) +- hw->phy_model = ICE_PHY_E810; ++ struct ice_ptp_hw *ptp = &hw->ptp; ++ ++ if (ice_is_e822(hw) || ice_is_e823(hw)) ++ ice_ptp_init_phy_e82x(ptp); ++ else if (ice_is_e810(hw)) ++ ice_ptp_init_phy_e810(ptp); + else +- hw->phy_model = ICE_PHY_E82X; ++ ptp->phy_model = ICE_PHY_UNSUP; + } + + /** +@@ -3327,7 +3351,7 @@ static int ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + ice_ptp_src_cmd(hw, cmd); + + /* Next, prepare the ports */ +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + err = ice_ptp_port_cmd_e810(hw, cmd); + break; +@@ -3379,7 +3403,7 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time) + + /* PHY timers */ + /* Fill Rx and Tx ports and send msg to PHY */ +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + err = ice_ptp_prep_phy_time_e810(hw, time & 0xFFFFFFFF); + break; +@@ -3421,7 +3445,7 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval) + wr32(hw, GLTSYN_SHADJ_L(tmr_idx), lower_32_bits(incval)); + wr32(hw, GLTSYN_SHADJ_H(tmr_idx), upper_32_bits(incval)); + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + err = ice_ptp_prep_phy_incval_e810(hw, incval); + break; +@@ -3487,7 +3511,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj) + wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0); + wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj); + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + err = ice_ptp_prep_phy_adj_e810(hw, adj); + break; +@@ -3517,7 +3541,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj) + */ + int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp) + { +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_read_phy_tstamp_e810(hw, block, idx, tstamp); + case ICE_PHY_E82X: +@@ -3545,7 +3569,7 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp) + */ + int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx) + { +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_clear_phy_tstamp_e810(hw, block, idx); + case ICE_PHY_E82X: +@@ -3606,7 +3630,7 @@ int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx) + */ + void ice_ptp_reset_ts_memory(struct ice_hw *hw) + { +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E82X: + ice_ptp_reset_ts_memory_e82x(hw); + break; +@@ -3632,7 +3656,7 @@ int ice_ptp_init_phc(struct ice_hw *hw) + /* Clear event err indications for auxiliary pins */ + (void)rd32(hw, GLTSYN_STAT(src_idx)); + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_ptp_init_phc_e810(hw); + case ICE_PHY_E82X: +@@ -3655,7 +3679,7 @@ int ice_ptp_init_phc(struct ice_hw *hw) + */ + int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready) + { +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_get_phy_tx_tstamp_ready_e810(hw, block, + tstamp_ready); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +index 7e8fd369ef7c..d788221eba57 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +@@ -211,6 +211,7 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp); + int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx); + void ice_ptp_reset_ts_memory(struct ice_hw *hw); + int ice_ptp_init_phc(struct ice_hw *hw); ++void ice_ptp_init_hw(struct ice_hw *hw); + int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready); + + /* E822 family functions */ +@@ -265,7 +266,6 @@ int ice_phy_cfg_tx_offset_e82x(struct ice_hw *hw, u8 port); + int ice_phy_cfg_rx_offset_e82x(struct ice_hw *hw, u8 port); + + /* E810 family functions */ +-int ice_ptp_init_phy_e810(struct ice_hw *hw); + int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data); + int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data); + int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data); +@@ -280,8 +280,6 @@ int ice_get_cgu_state(struct ice_hw *hw, u8 dpll_idx, + u8 *ref_state, u8 *eec_mode, s64 *phase_offset, + enum dpll_lock_status *dpll_state); + int ice_get_cgu_rclk_pin_info(struct ice_hw *hw, u8 *base_idx, u8 *pin_num); +- +-void ice_ptp_init_phy_model(struct ice_hw *hw); + int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id, + unsigned long *caps); + +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index 28e47bb78eaf..6fc4cd1030d0 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -807,6 +807,9 @@ struct ice_mbx_data { + u16 async_watermark_val; + }; + ++#define ICE_PORTS_PER_QUAD 4 ++#define ICE_GET_QUAD_NUM(port) ((port) / ICE_PORTS_PER_QUAD) ++ + /* PHY model */ + enum ice_phy_model { + ICE_PHY_UNSUP = -1, +@@ -814,6 +817,12 @@ enum ice_phy_model { + ICE_PHY_E82X, + }; + ++struct ice_ptp_hw { ++ enum ice_phy_model phy_model; ++ u8 num_lports; ++ u8 ports_per_phy; ++}; ++ + /* Port hardware description */ + struct ice_hw { + u8 __iomem *hw_addr; +@@ -835,7 +844,6 @@ struct ice_hw { + u8 revision_id; + + u8 pf_id; /* device profile info */ +- enum ice_phy_model phy_model; + + u16 max_burst_size; /* driver sets this value */ + +@@ -896,12 +904,7 @@ struct ice_hw { + /* INTRL granularity in 1 us */ + u8 intrl_gran; + +-#define ICE_MAX_QUAD 2 +-#define ICE_QUADS_PER_PHY_E82X 2 +-#define ICE_PORTS_PER_PHY_E82X 8 +-#define ICE_PORTS_PER_QUAD 4 +-#define ICE_PORTS_PER_PHY_E810 4 +-#define ICE_NUM_EXTERNAL_PORTS (ICE_MAX_QUAD * ICE_PORTS_PER_QUAD) ++ struct ice_ptp_hw ptp; + + /* Active package version (currently active) */ + struct ice_pkg_ver active_pkg_ver; +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0037-ice-Introduce-ice_get_base_incval-helper.patch b/kernel-rt/debian/patches/ice-VDF/0037-ice-Introduce-ice_get_base_incval-helper.patch new file mode 100644 index 00000000..f7e38700 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0037-ice-Introduce-ice_get_base_incval-helper.patch @@ -0,0 +1,80 @@ +From cd12b5c8239993e395436ff9a01b524103aa0641 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 28 May 2024 16:03:56 -0700 +Subject: [PATCH] ice: Introduce ice_get_base_incval() helper + +Add a new helper for getting base clock increment value for specific HW. + +Reviewed-by: Przemek Kitszel +Reviewed-by: Arkadiusz Kubalewski +Signed-off-by: Karol Kolacinski +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Jacob Keller +Link: https://lore.kernel.org/r/20240528-next-2024-05-28-ptp-refactors-v1-6-c082739bb6f6@intel.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit 1f374d57c39386520586539641cafc999d0f3ef5) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 9 +-------- + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 18 ++++++++++++++++++ + 2 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index bb1572a353d0..44b8fc8021cd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -7,8 +7,6 @@ + + #define E810_OUT_PROP_DELAY_NS 1 + +-#define UNKNOWN_INCVAL_E82X 0x100000000ULL +- + static const struct ptp_pin_desc ice_pin_desc_e810t[] = { + /* name idx func chan */ + { "GNSS", GNSS, PTP_PF_EXTTS, 0, { 0, } }, +@@ -1229,12 +1227,7 @@ static u64 ice_base_incval(struct ice_pf *pf) + struct ice_hw *hw = &pf->hw; + u64 incval; + +- if (ice_is_e810(hw)) +- incval = ICE_PTP_NOMINAL_INCVAL_E810; +- else if (ice_e82x_time_ref(hw) < NUM_ICE_TIME_REF_FREQ) +- incval = ice_e82x_nominal_incval(ice_e82x_time_ref(hw)); +- else +- incval = UNKNOWN_INCVAL_E82X; ++ incval = ice_get_base_incval(hw); + + dev_dbg(ice_pf_to_dev(pf), "PTP: using base increment value of 0x%016llx\n", + incval); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +index d788221eba57..749a3f2d8293 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +@@ -283,6 +283,24 @@ int ice_get_cgu_rclk_pin_info(struct ice_hw *hw, u8 *base_idx, u8 *pin_num); + int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id, + unsigned long *caps); + ++/** ++ * ice_get_base_incval - Get base clock increment value ++ * @hw: pointer to the HW struct ++ * ++ * Return: base clock increment value for supported PHYs, 0 otherwise ++ */ ++static inline u64 ice_get_base_incval(struct ice_hw *hw) ++{ ++ switch (hw->ptp.phy_model) { ++ case ICE_PHY_E810: ++ return ICE_PTP_NOMINAL_INCVAL_E810; ++ case ICE_PHY_E82X: ++ return ice_e82x_nominal_incval(ice_e82x_time_ref(hw)); ++ default: ++ return 0; ++ } ++} ++ + #define PFTSYN_SEM_BYTES 4 + + #define ICE_PTP_CLOCK_INDEX_0 0x00 +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/ice-VDF/0038-ice-modify-the-ice-driver-version-to-stx.4.patch b/kernel-rt/debian/patches/ice-VDF/0038-ice-modify-the-ice-driver-version-to-stx.4.patch new file mode 100644 index 00000000..ee86b103 --- /dev/null +++ b/kernel-rt/debian/patches/ice-VDF/0038-ice-modify-the-ice-driver-version-to-stx.4.patch @@ -0,0 +1,32 @@ +From 437206483113743a4ef40c2f7e14f09705049672 Mon Sep 17 00:00:00 2001 +From: Jiping Ma +Date: Mon, 2 Sep 2024 03:18:08 +0000 +Subject: [PATCH] ice:modify the ice driver version to stx.4 + +Change the ice driver min version to stx.4 because we back ported +the upstream 36 commits to our code base to support the customer's +requirement. + +The ice driver version should be ice-6.6.40-stx.4. + +Signed-off-by: Jiping Ma +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 5807b310bdca..7163d25405f8 100644 +--- a/Makefile ++++ b/Makefile +@@ -1227,7 +1227,7 @@ uapi-asm-generic: + + # KERNELRELEASE can change from a few different places, meaning version.h + # needs to be updated, so this check is forced on all builds +-ICE_STX = "-stx.3" ++ICE_STX = "-stx.4" + I40E_STX = "-stx.0" + IAVF_STX = "-stx.0" + +-- +2.43.0 + diff --git a/kernel-rt/debian/patches/series b/kernel-rt/debian/patches/series index a773d35d..c03d052b 100644 --- a/kernel-rt/debian/patches/series +++ b/kernel-rt/debian/patches/series @@ -64,3 +64,41 @@ ice-dpll/0046-dpll-fix-dpll_xa_ref_-_del-for-multiple-registration.patch ice-dpll/0047-ice-modify-the-ice-driver-min-version-to-stx.2.patch ice-mdd/0001-ice-Add-automatic-VF-reset-on-Tx-MDD-events.patch ice-mdd/0002-ice-modify-the-ice-driver-min-version-to-stx.3.patch +ice-VDF/0001-ice-Auxbus-devices-driver-for-E822-TS.patch +ice-VDF/0002-ice-introduce-ice_pf_src_tmr_owned.patch +ice-VDF/0003-ice-Re-enable-timestamping-correctly-after-reset.patch +ice-VDF/0004-ice-periodically-kick-Tx-timestamp-interrupt.patch +ice-VDF/0005-ice-PTP-Rename-macros-used-for-PHY-QUAD-port-definit.patch +ice-VDF/0006-ice-PTP-move-quad-value-check-inside-ice_fill_phy_ms.patch +ice-VDF/0007-ice-remove-ptp_tx-ring-parameter-flag.patch +ice-VDF/0008-ice-unify-logic-for-programming-PFINT_TSYN_MSK.patch +ice-VDF/0009-ice-PTP-Clean-up-timestamp-registers-correctly.patch +ice-VDF/0010-ice-Use-PTP-auxbus-for-all-PHYs-restart-in-E822.patch +ice-VDF/0011-ice-Rename-E822-to-E82X.patch +ice-VDF/0012-ice-Schedule-service-task-in-IRQ-top-half.patch +ice-VDF/0013-ice-Enable-SW-interrupt-from-FW-for-LL-TS.patch +ice-VDF/0014-ice-PTP-add-clock-domain-number-to-auxiliary-interfa.patch +ice-VDF/0015-ice-restore-timestamp-configuration-after-device-res.patch +ice-VDF/0016-ice-introduce-PTP-state-machine.patch +ice-VDF/0017-ice-pass-reset-type-to-PTP-reset-functions.patch +ice-VDF/0018-ice-rename-verify_cached-to-has_ready_bitmap.patch +ice-VDF/0019-ice-don-t-check-has_ready_bitmap-in-E810-functions.patch +ice-VDF/0020-ice-rename-ice_ptp_tx_cfg_intr.patch +ice-VDF/0021-ice-factor-out-ice_ptp_rebuild_owner.patch +ice-VDF/0022-ice-stop-destroying-and-reinitalizing-Tx-tracker-dur.patch +ice-VDF/0023-ice-Remove-and-readd-netdev-during-devlink-reload.patch +ice-VDF/0024-ice-remove-FW-logging-code.patch +ice-VDF/0025-ice-configure-FW-logging.patch +ice-VDF/0026-ice-enable-FW-logging.patch +ice-VDF/0027-ice-add-ability-to-read-and-configure-FW-log-data.patch +ice-VDF/0028-ice-Fix-debugfs-with-devlink-reload.patch +ice-VDF/0029-ice-remove-vf-lan_vsi_num-field.patch +ice-VDF/0030-ice-rename-ice_write_-functions-to-ice_pack_ctx_.patch +ice-VDF/0031-ice-use-GENMASK-instead-of-BIT-n-1-in-pack-functions.patch +ice-VDF/0032-ice-cleanup-line-splitting-for-context-set-functions.patch +ice-VDF/0033-ice-do-not-disable-Tx-queues-twice-in-ice_down.patch +ice-VDF/0034-ice-Fix-improper-extts-handling.patch +ice-VDF/0035-ice-Don-t-process-extts-if-PTP-is-disabled.patch +ice-VDF/0036-ice-Introduce-ice_ptp_hw-struct.patch +ice-VDF/0037-ice-Introduce-ice_get_base_incval-helper.patch +ice-VDF/0038-ice-modify-the-ice-driver-version-to-stx.4.patch diff --git a/kernel-std/debian/patches/ice-VDF/0001-ice-Auxbus-devices-driver-for-E822-TS.patch b/kernel-std/debian/patches/ice-VDF/0001-ice-Auxbus-devices-driver-for-E822-TS.patch new file mode 100644 index 00000000..d0ad7896 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0001-ice-Auxbus-devices-driver-for-E822-TS.patch @@ -0,0 +1,684 @@ +From ba0d88d4ff54805aac7aec77cc5b05d0df9114da Mon Sep 17 00:00:00 2001 +From: Michal Michalik +Date: Thu, 27 Jul 2023 15:50:34 +0200 +Subject: [PATCH 01/36] ice: Auxbus devices & driver for E822 TS + +There is a problem in HW in E822-based devices leading to race +condition. +It might happen that, in order: +- PF0 (which owns the PHC) requests few timestamps, +- PF1 requests a timestamp, +- interrupt is being triggered and both PF0 and PF1 threads are woken +up, +- PF0 got one timestamp, still waiting for others so not going to sleep, +- PF1 gets it's timestamp, process it and go to sleep, +- PF1 requests a timestamp again, +- just before PF0 goes to sleep timestamp of PF1 appear, +- PF0 finishes all it's timestamps and go to sleep (PF1 also sleeping). +That leaves PF1 timestamp memory not read, which lead to blocking the +next interrupt from arriving. + +Fix it by adding auxiliary devices and only one driver to handle all the +timestamps for all PF's by PHC owner. In the past each PF requested it's +own timestamps and process it from the start till the end which causes +problem described above. Currently each PF requests the timestamps as +before, but the actual reading of the completed timestamps is being done +by the PTP auxiliary driver, which is registered by the PF which owns PHC. + +Additionally, the newly introduced auxiliary driver/devices for PTP clock +owner will be used for other features in all products (including E810). + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Signed-off-by: Michal Michalik +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit d938a8cca88a5f02f523f95fe3d2d1214f4b4a8d) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 12 + + .../net/ethernet/intel/ice/ice_hw_autogen.h | 1 + + drivers/net/ethernet/intel/ice/ice_main.c | 11 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 393 +++++++++++++++++- + drivers/net/ethernet/intel/ice/ice_ptp.h | 30 ++ + 5 files changed, 430 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index b9cd0113b859..0a3d76d184ba 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -671,6 +671,18 @@ static inline bool ice_vector_ch_enabled(struct ice_q_vector *qv) + return !!qv->ch; /* Enable it to run with TC */ + } + ++/** ++ * ice_ptp_pf_handles_tx_interrupt - Check if PF handles Tx interrupt ++ * @pf: Board private structure ++ * ++ * Return true if this PF should respond to the Tx timestamp interrupt ++ * indication in the miscellaneous OICR interrupt handler. ++ */ ++static inline bool ice_ptp_pf_handles_tx_interrupt(struct ice_pf *pf) ++{ ++ return pf->ptp.tx_interrupt_mode != ICE_PTP_TX_INTERRUPT_NONE; ++} ++ + /** + * ice_irq_dynamic_ena - Enable default interrupt generation settings + * @hw: pointer to HW struct +diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +index 531cc2194741..6756f3d51d14 100644 +--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h ++++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +@@ -231,6 +231,7 @@ + #define PFINT_SB_CTL 0x0016B600 + #define PFINT_SB_CTL_MSIX_INDX_M ICE_M(0x7FF, 0) + #define PFINT_SB_CTL_CAUSE_ENA_M BIT(30) ++#define PFINT_TSYN_MSK 0x0016C980 + #define QINT_RQCTL(_QRX) (0x00150000 + ((_QRX) * 4)) + #define QINT_RQCTL_MSIX_INDX_S 0 + #define QINT_RQCTL_MSIX_INDX_M ICE_M(0x7FF, 0) +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 8a6acb5a722e..39cb6ee52abe 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3190,7 +3190,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + if (oicr & PFINT_OICR_TSYN_TX_M) { + ena_mask &= ~PFINT_OICR_TSYN_TX_M; +- if (!hw->reset_ongoing) ++ if (!hw->reset_ongoing && ice_ptp_pf_handles_tx_interrupt(pf)) + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); + } + +@@ -7444,8 +7444,13 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + } + + /* configure PTP timestamping after VSI rebuild */ +- if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) +- ice_ptp_cfg_timestamp(pf, false); ++ if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) { ++ if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) ++ ice_ptp_cfg_timestamp(pf, false); ++ else if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) ++ /* for E82x PHC owner always need to have interrupts */ ++ ice_ptp_cfg_timestamp(pf, true); ++ } + + err = ice_vsi_rebuild_by_type(pf, ICE_VSI_SWITCHDEV_CTRL); + if (err) { +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 3648d3cccacc..e3012608c9dd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -255,6 +255,24 @@ ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin, + return ice_ptp_set_sma_e810t(info, pin, func); + } + ++/** ++ * ice_ptp_configure_tx_tstamp - Enable or disable Tx timestamp interrupt ++ * @pf: The PF pointer to search in ++ * @on: bool value for whether timestamp interrupt is enabled or disabled ++ */ ++static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on) ++{ ++ u32 val; ++ ++ /* Configure the Tx timestamp interrupt */ ++ val = rd32(&pf->hw, PFINT_OICR_ENA); ++ if (on) ++ val |= PFINT_OICR_TSYN_TX_M; ++ else ++ val &= ~PFINT_OICR_TSYN_TX_M; ++ wr32(&pf->hw, PFINT_OICR_ENA, val); ++} ++ + /** + * ice_set_tx_tstamp - Enable or disable Tx timestamping + * @pf: The PF pointer to search in +@@ -263,7 +281,6 @@ ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin, + static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) + { + struct ice_vsi *vsi; +- u32 val; + u16 i; + + vsi = ice_get_main_vsi(pf); +@@ -277,13 +294,8 @@ static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) + vsi->tx_rings[i]->ptp_tx = on; + } + +- /* Configure the Tx timestamp interrupt */ +- val = rd32(&pf->hw, PFINT_OICR_ENA); +- if (on) +- val |= PFINT_OICR_TSYN_TX_M; +- else +- val &= ~PFINT_OICR_TSYN_TX_M; +- wr32(&pf->hw, PFINT_OICR_ENA, val); ++ if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) ++ ice_ptp_configure_tx_tstamp(pf, on); + + pf->ptp.tstamp_config.tx_type = on ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + } +@@ -674,9 +686,6 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + int err; + u8 idx; + +- if (!tx->init) +- return; +- + ptp_port = container_of(tx, struct ice_ptp_port, tx); + pf = ptp_port_to_pf(ptp_port); + hw = &pf->hw; +@@ -774,6 +783,39 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + } + } + ++/** ++ * ice_ptp_tx_tstamp_owner - Process Tx timestamps for all ports on the device ++ * @pf: Board private structure ++ */ ++static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) ++{ ++ struct ice_ptp_port *port; ++ unsigned int i; ++ ++ mutex_lock(&pf->ptp.ports_owner.lock); ++ list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member) { ++ struct ice_ptp_tx *tx = &port->tx; ++ ++ if (!tx || !tx->init) ++ continue; ++ ++ ice_ptp_process_tx_tstamp(tx); ++ } ++ mutex_unlock(&pf->ptp.ports_owner.lock); ++ ++ for (i = 0; i < ICE_MAX_QUAD; i++) { ++ u64 tstamp_ready; ++ int err; ++ ++ /* Read the Tx ready status first */ ++ err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready); ++ if (err || tstamp_ready) ++ return ICE_TX_TSTAMP_WORK_PENDING; ++ } ++ ++ return ICE_TX_TSTAMP_WORK_DONE; ++} ++ + /** + * ice_ptp_tx_tstamp - Process Tx timestamps for this function. + * @tx: Tx tracking structure to initialize +@@ -2448,7 +2490,21 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) + */ + enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf) + { +- return ice_ptp_tx_tstamp(&pf->ptp.port.tx); ++ switch (pf->ptp.tx_interrupt_mode) { ++ case ICE_PTP_TX_INTERRUPT_NONE: ++ /* This device has the clock owner handle timestamps for it */ ++ return ICE_TX_TSTAMP_WORK_DONE; ++ case ICE_PTP_TX_INTERRUPT_SELF: ++ /* This device handles its own timestamps */ ++ return ice_ptp_tx_tstamp(&pf->ptp.port.tx); ++ case ICE_PTP_TX_INTERRUPT_ALL: ++ /* This device handles timestamps for all ports */ ++ return ice_ptp_tx_tstamp_owner(pf); ++ default: ++ WARN_ONCE(1, "Unexpected Tx timestamp interrupt mode %u\n", ++ pf->ptp.tx_interrupt_mode); ++ return ICE_TX_TSTAMP_WORK_DONE; ++ } + } + + static void ice_ptp_periodic_work(struct kthread_work *work) +@@ -2557,6 +2613,187 @@ void ice_ptp_reset(struct ice_pf *pf) + dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err); + } + ++/** ++ * ice_ptp_aux_dev_to_aux_pf - Get auxiliary PF handle for the auxiliary device ++ * @aux_dev: auxiliary device to get the auxiliary PF for ++ */ ++static struct ice_pf * ++ice_ptp_aux_dev_to_aux_pf(struct auxiliary_device *aux_dev) ++{ ++ struct ice_ptp_port *aux_port; ++ struct ice_ptp *aux_ptp; ++ ++ aux_port = container_of(aux_dev, struct ice_ptp_port, aux_dev); ++ aux_ptp = container_of(aux_port, struct ice_ptp, port); ++ ++ return container_of(aux_ptp, struct ice_pf, ptp); ++} ++ ++/** ++ * ice_ptp_aux_dev_to_owner_pf - Get PF handle for the auxiliary device ++ * @aux_dev: auxiliary device to get the PF for ++ */ ++static struct ice_pf * ++ice_ptp_aux_dev_to_owner_pf(struct auxiliary_device *aux_dev) ++{ ++ struct ice_ptp_port_owner *ports_owner; ++ struct auxiliary_driver *aux_drv; ++ struct ice_ptp *owner_ptp; ++ ++ if (!aux_dev->dev.driver) ++ return NULL; ++ ++ aux_drv = to_auxiliary_drv(aux_dev->dev.driver); ++ ports_owner = container_of(aux_drv, struct ice_ptp_port_owner, ++ aux_driver); ++ owner_ptp = container_of(ports_owner, struct ice_ptp, ports_owner); ++ return container_of(owner_ptp, struct ice_pf, ptp); ++} ++ ++/** ++ * ice_ptp_auxbus_probe - Probe auxiliary devices ++ * @aux_dev: PF's auxiliary device ++ * @id: Auxiliary device ID ++ */ ++static int ice_ptp_auxbus_probe(struct auxiliary_device *aux_dev, ++ const struct auxiliary_device_id *id) ++{ ++ struct ice_pf *owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev); ++ struct ice_pf *aux_pf = ice_ptp_aux_dev_to_aux_pf(aux_dev); ++ ++ if (WARN_ON(!owner_pf)) ++ return -ENODEV; ++ ++ INIT_LIST_HEAD(&aux_pf->ptp.port.list_member); ++ mutex_lock(&owner_pf->ptp.ports_owner.lock); ++ list_add(&aux_pf->ptp.port.list_member, ++ &owner_pf->ptp.ports_owner.ports); ++ mutex_unlock(&owner_pf->ptp.ports_owner.lock); ++ ++ return 0; ++} ++ ++/** ++ * ice_ptp_auxbus_remove - Remove auxiliary devices from the bus ++ * @aux_dev: PF's auxiliary device ++ */ ++static void ice_ptp_auxbus_remove(struct auxiliary_device *aux_dev) ++{ ++ struct ice_pf *owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev); ++ struct ice_pf *aux_pf = ice_ptp_aux_dev_to_aux_pf(aux_dev); ++ ++ mutex_lock(&owner_pf->ptp.ports_owner.lock); ++ list_del(&aux_pf->ptp.port.list_member); ++ mutex_unlock(&owner_pf->ptp.ports_owner.lock); ++} ++ ++/** ++ * ice_ptp_auxbus_shutdown ++ * @aux_dev: PF's auxiliary device ++ */ ++static void ice_ptp_auxbus_shutdown(struct auxiliary_device *aux_dev) ++{ ++ /* Doing nothing here, but handle to auxbus driver must be satisfied */ ++} ++ ++/** ++ * ice_ptp_auxbus_suspend ++ * @aux_dev: PF's auxiliary device ++ * @state: power management state indicator ++ */ ++static int ++ice_ptp_auxbus_suspend(struct auxiliary_device *aux_dev, pm_message_t state) ++{ ++ /* Doing nothing here, but handle to auxbus driver must be satisfied */ ++ return 0; ++} ++ ++/** ++ * ice_ptp_auxbus_resume ++ * @aux_dev: PF's auxiliary device ++ */ ++static int ice_ptp_auxbus_resume(struct auxiliary_device *aux_dev) ++{ ++ /* Doing nothing here, but handle to auxbus driver must be satisfied */ ++ return 0; ++} ++ ++/** ++ * ice_ptp_auxbus_create_id_table - Create auxiliary device ID table ++ * @pf: Board private structure ++ * @name: auxiliary bus driver name ++ */ ++static struct auxiliary_device_id * ++ice_ptp_auxbus_create_id_table(struct ice_pf *pf, const char *name) ++{ ++ struct auxiliary_device_id *ids; ++ ++ /* Second id left empty to terminate the array */ ++ ids = devm_kcalloc(ice_pf_to_dev(pf), 2, ++ sizeof(struct auxiliary_device_id), GFP_KERNEL); ++ if (!ids) ++ return NULL; ++ ++ snprintf(ids[0].name, sizeof(ids[0].name), "ice.%s", name); ++ ++ return ids; ++} ++ ++/** ++ * ice_ptp_register_auxbus_driver - Register PTP auxiliary bus driver ++ * @pf: Board private structure ++ */ ++static int ice_ptp_register_auxbus_driver(struct ice_pf *pf) ++{ ++ struct auxiliary_driver *aux_driver; ++ struct ice_ptp *ptp; ++ struct device *dev; ++ char *name; ++ int err; ++ ++ ptp = &pf->ptp; ++ dev = ice_pf_to_dev(pf); ++ aux_driver = &ptp->ports_owner.aux_driver; ++ INIT_LIST_HEAD(&ptp->ports_owner.ports); ++ mutex_init(&ptp->ports_owner.lock); ++ name = devm_kasprintf(dev, GFP_KERNEL, "ptp_aux_dev_%u_%u_clk%u", ++ pf->pdev->bus->number, PCI_SLOT(pf->pdev->devfn), ++ ice_get_ptp_src_clock_index(&pf->hw)); ++ ++ aux_driver->name = name; ++ aux_driver->shutdown = ice_ptp_auxbus_shutdown; ++ aux_driver->suspend = ice_ptp_auxbus_suspend; ++ aux_driver->remove = ice_ptp_auxbus_remove; ++ aux_driver->resume = ice_ptp_auxbus_resume; ++ aux_driver->probe = ice_ptp_auxbus_probe; ++ aux_driver->id_table = ice_ptp_auxbus_create_id_table(pf, name); ++ if (!aux_driver->id_table) ++ return -ENOMEM; ++ ++ err = auxiliary_driver_register(aux_driver); ++ if (err) { ++ devm_kfree(dev, aux_driver->id_table); ++ dev_err(dev, "Failed registering aux_driver, name <%s>\n", ++ name); ++ } ++ ++ return err; ++} ++ ++/** ++ * ice_ptp_unregister_auxbus_driver - Unregister PTP auxiliary bus driver ++ * @pf: Board private structure ++ */ ++static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf) ++{ ++ struct auxiliary_driver *aux_driver = &pf->ptp.ports_owner.aux_driver; ++ ++ auxiliary_driver_unregister(aux_driver); ++ devm_kfree(ice_pf_to_dev(pf), aux_driver->id_table); ++ ++ mutex_destroy(&pf->ptp.ports_owner.lock); ++} ++ + /** + * ice_ptp_prepare_for_reset - Prepare PTP for reset + * @pf: Board private structure +@@ -2635,7 +2872,15 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + /* Release the global hardware lock */ + ice_ptp_unlock(hw); + +- if (!ice_is_e810(hw)) { ++ if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) { ++ /* The clock owner for this device type handles the timestamp ++ * interrupt for all ports. ++ */ ++ ice_ptp_configure_tx_tstamp(pf, true); ++ ++ /* React on all quads interrupts for E82x */ ++ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f); ++ + /* Enable quad interrupts */ + err = ice_ptp_tx_ena_intr(pf, true, itr); + if (err) +@@ -2650,8 +2895,16 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + /* Store the PTP clock index for other PFs */ + ice_set_ptp_clock_index(pf); + +- return 0; ++ err = ice_ptp_register_auxbus_driver(pf); ++ if (err) { ++ dev_err(ice_pf_to_dev(pf), "Failed to register PTP auxbus driver"); ++ goto err_aux; ++ } + ++ return 0; ++err_aux: ++ ice_clear_ptp_clock_index(pf); ++ ptp_clock_unregister(pf->ptp.clock); + err_clk: + pf->ptp.clock = NULL; + err_exit: +@@ -2701,6 +2954,13 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + case ICE_PHY_E810: + return ice_ptp_init_tx_e810(pf, &ptp_port->tx); + case ICE_PHY_E822: ++ /* Non-owner PFs don't react to any interrupts on E82x, ++ * neither on own quad nor on others ++ */ ++ if (!ice_ptp_pf_handles_tx_interrupt(pf)) { ++ ice_ptp_configure_tx_tstamp(pf, false); ++ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0); ++ } + kthread_init_delayed_work(&ptp_port->ov_work, + ice_ptp_wait_for_offsets); + +@@ -2711,6 +2971,101 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + } + } + ++/** ++ * ice_ptp_release_auxbus_device ++ * @dev: device that utilizes the auxbus ++ */ ++static void ice_ptp_release_auxbus_device(struct device *dev) ++{ ++ /* Doing nothing here, but handle to auxbux device must be satisfied */ ++} ++ ++/** ++ * ice_ptp_create_auxbus_device - Create PTP auxiliary bus device ++ * @pf: Board private structure ++ */ ++static int ice_ptp_create_auxbus_device(struct ice_pf *pf) ++{ ++ struct auxiliary_device *aux_dev; ++ struct ice_ptp *ptp; ++ struct device *dev; ++ char *name; ++ int err; ++ u32 id; ++ ++ ptp = &pf->ptp; ++ id = ptp->port.port_num; ++ dev = ice_pf_to_dev(pf); ++ ++ aux_dev = &ptp->port.aux_dev; ++ ++ name = devm_kasprintf(dev, GFP_KERNEL, "ptp_aux_dev_%u_%u_clk%u", ++ pf->pdev->bus->number, PCI_SLOT(pf->pdev->devfn), ++ ice_get_ptp_src_clock_index(&pf->hw)); ++ ++ aux_dev->name = name; ++ aux_dev->id = id; ++ aux_dev->dev.release = ice_ptp_release_auxbus_device; ++ aux_dev->dev.parent = dev; ++ ++ err = auxiliary_device_init(aux_dev); ++ if (err) ++ goto aux_err; ++ ++ err = auxiliary_device_add(aux_dev); ++ if (err) { ++ auxiliary_device_uninit(aux_dev); ++ goto aux_err; ++ } ++ ++ return 0; ++aux_err: ++ dev_err(dev, "Failed to create PTP auxiliary bus device <%s>\n", name); ++ devm_kfree(dev, name); ++ return err; ++} ++ ++/** ++ * ice_ptp_remove_auxbus_device - Remove PTP auxiliary bus device ++ * @pf: Board private structure ++ */ ++static void ice_ptp_remove_auxbus_device(struct ice_pf *pf) ++{ ++ struct auxiliary_device *aux_dev = &pf->ptp.port.aux_dev; ++ ++ auxiliary_device_delete(aux_dev); ++ auxiliary_device_uninit(aux_dev); ++ ++ memset(aux_dev, 0, sizeof(*aux_dev)); ++} ++ ++/** ++ * ice_ptp_init_tx_interrupt_mode - Initialize device Tx interrupt mode ++ * @pf: Board private structure ++ * ++ * Initialize the Tx timestamp interrupt mode for this device. For most device ++ * types, each PF processes the interrupt and manages its own timestamps. For ++ * E822-based devices, only the clock owner processes the timestamps. Other ++ * PFs disable the interrupt and do not process their own timestamps. ++ */ ++static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf) ++{ ++ switch (pf->hw.phy_model) { ++ case ICE_PHY_E822: ++ /* E822 based PHY has the clock owner process the interrupt ++ * for all ports. ++ */ ++ if (ice_pf_src_tmr_owned(pf)) ++ pf->ptp.tx_interrupt_mode = ICE_PTP_TX_INTERRUPT_ALL; ++ else ++ pf->ptp.tx_interrupt_mode = ICE_PTP_TX_INTERRUPT_NONE; ++ break; ++ default: ++ /* other PHY types handle their own Tx interrupt */ ++ pf->ptp.tx_interrupt_mode = ICE_PTP_TX_INTERRUPT_SELF; ++ } ++} ++ + /** + * ice_ptp_init - Initialize PTP hardware clock support + * @pf: Board private structure +@@ -2731,6 +3086,8 @@ void ice_ptp_init(struct ice_pf *pf) + + ice_ptp_init_phy_model(hw); + ++ ice_ptp_init_tx_interrupt_mode(pf); ++ + /* If this function owns the clock hardware, it must allocate and + * configure the PTP clock device to represent it. + */ +@@ -2753,6 +3110,10 @@ void ice_ptp_init(struct ice_pf *pf) + if (err) + goto err; + ++ err = ice_ptp_create_auxbus_device(pf); ++ if (err) ++ goto err; ++ + dev_info(ice_pf_to_dev(pf), "PTP init successful\n"); + return; + +@@ -2781,6 +3142,8 @@ void ice_ptp_release(struct ice_pf *pf) + /* Disable timestamping for both Tx and Rx */ + ice_ptp_cfg_timestamp(pf, false); + ++ ice_ptp_remove_auxbus_device(pf); ++ + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); + + clear_bit(ICE_FLAG_PTP, pf->flags); +@@ -2804,5 +3167,7 @@ void ice_ptp_release(struct ice_pf *pf) + ptp_clock_unregister(pf->ptp.clock); + pf->ptp.clock = NULL; + ++ ice_ptp_unregister_auxbus_driver(pf); ++ + dev_info(ice_pf_to_dev(pf), "Removed PTP clock\n"); + } +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 995a57019ba7..d94c22329df0 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -157,7 +157,9 @@ struct ice_ptp_tx { + * ready for PTP functionality. It is used to track the port initialization + * and determine when the port's PHY offset is valid. + * ++ * @list_member: list member structure of auxiliary device + * @tx: Tx timestamp tracking for this port ++ * @aux_dev: auxiliary device associated with this port + * @ov_work: delayed work task for tracking when PHY offset is valid + * @ps_lock: mutex used to protect the overall PTP PHY start procedure + * @link_up: indicates whether the link is up +@@ -165,7 +167,9 @@ struct ice_ptp_tx { + * @port_num: the port number this structure represents + */ + struct ice_ptp_port { ++ struct list_head list_member; + struct ice_ptp_tx tx; ++ struct auxiliary_device aux_dev; + struct kthread_delayed_work ov_work; + struct mutex ps_lock; /* protects overall PTP PHY start procedure */ + bool link_up; +@@ -173,11 +177,35 @@ struct ice_ptp_port { + u8 port_num; + }; + ++enum ice_ptp_tx_interrupt { ++ ICE_PTP_TX_INTERRUPT_NONE = 0, ++ ICE_PTP_TX_INTERRUPT_SELF, ++ ICE_PTP_TX_INTERRUPT_ALL, ++}; ++ ++/** ++ * struct ice_ptp_port_owner - data used to handle the PTP clock owner info ++ * ++ * This structure contains data necessary for the PTP clock owner to correctly ++ * handle the timestamping feature for all attached ports. ++ * ++ * @aux_driver: the structure carring the auxiliary driver information ++ * @ports: list of porst handled by this port owner ++ * @lock: protect access to ports list ++ */ ++struct ice_ptp_port_owner { ++ struct auxiliary_driver aux_driver; ++ struct list_head ports; ++ struct mutex lock; ++}; ++ + #define GLTSYN_TGT_H_IDX_MAX 4 + + /** + * struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK ++ * @tx_interrupt_mode: the TX interrupt mode for the PTP clock + * @port: data for the PHY port initialization procedure ++ * @ports_owner: data for the auxiliary driver owner + * @work: delayed work function for periodic tasks + * @cached_phc_time: a cached copy of the PHC time for timestamp extension + * @cached_phc_jiffies: jiffies when cached_phc_time was last updated +@@ -197,7 +225,9 @@ struct ice_ptp_port { + * @late_cached_phc_updates: number of times cached PHC update is late + */ + struct ice_ptp { ++ enum ice_ptp_tx_interrupt tx_interrupt_mode; + struct ice_ptp_port port; ++ struct ice_ptp_port_owner ports_owner; + struct kthread_delayed_work work; + u64 cached_phc_time; + unsigned long cached_phc_jiffies; +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0002-ice-introduce-ice_pf_src_tmr_owned.patch b/kernel-std/debian/patches/ice-VDF/0002-ice-introduce-ice_pf_src_tmr_owned.patch new file mode 100644 index 00000000..3078a79b --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0002-ice-introduce-ice_pf_src_tmr_owned.patch @@ -0,0 +1,95 @@ +From f6af978ef435067b4c9f5ff5e159f8b65d969268 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Fri, 8 Sep 2023 14:37:14 -0700 +Subject: [PATCH 02/36] ice: introduce ice_pf_src_tmr_owned + +Add ice_pf_src_tmr_owned() macro to check the function capability bit +indicating if the current function owns the PTP hardware clock. This is +slightly shorter than the more verbose access via +hw.func_caps.ts_func_info.src_tmr_owned. Use this where possible rather +than open coding its equivalent. + +Signed-off-by: Jacob Keller +Signed-off-by: Tony Nguyen +(cherry picked from commit 42d40bb21e332151da6fb689bf7d4af8195866ed) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 2 ++ + drivers/net/ethernet/intel/ice/ice_lib.c | 2 +- + drivers/net/ethernet/intel/ice/ice_main.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 6 +++--- + 4 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 0a3d76d184ba..54a98c4032b7 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -197,6 +197,8 @@ extern const char ice_drv_ver[]; + + #define ice_pf_to_dev(pf) (&((pf)->pdev->dev)) + ++#define ice_pf_src_tmr_owned(pf) ((pf)->hw.func_caps.ts_func_info.src_tmr_owned) ++ + enum ice_feature { + ICE_F_DSCP, + ICE_F_PHY_RCLK, +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index 632091487413..106ef843f4b5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -4010,7 +4010,7 @@ void ice_init_feature_support(struct ice_pf *pf) + if (ice_is_phy_rclk_in_netlist(&pf->hw)) + ice_set_feature_support(pf, ICE_F_PHY_RCLK); + /* If we don't own the timer - don't enable other caps */ +- if (!pf->hw.func_caps.ts_func_info.src_tmr_owned) ++ if (!ice_pf_src_tmr_owned(pf)) + break; + if (ice_is_cgu_in_netlist(&pf->hw)) + ice_set_feature_support(pf, ICE_F_CGU); +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 39cb6ee52abe..e957529b3fd6 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3200,7 +3200,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + ena_mask &= ~PFINT_OICR_TSYN_EVNT_M; + +- if (hw->func_caps.ts_func_info.src_tmr_owned) { ++ if (ice_pf_src_tmr_owned(pf)) { + /* Save EVENTs from GLTSYN register */ + pf->ptp.ext_ts_irq |= gltsyn_stat & + (GLTSYN_STAT_EVENT0_M | +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index e3012608c9dd..b1951357ba9f 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -448,7 +448,7 @@ static void ice_clear_ptp_clock_index(struct ice_pf *pf) + int err; + + /* Do not clear the index if we don't own the timer */ +- if (!hw->func_caps.ts_func_info.src_tmr_owned) ++ if (!ice_pf_src_tmr_owned(pf)) + return; + + tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc; +@@ -2538,7 +2538,7 @@ void ice_ptp_reset(struct ice_pf *pf) + if (test_bit(ICE_PFR_REQ, pf->state)) + goto pfr; + +- if (!hw->func_caps.ts_func_info.src_tmr_owned) ++ if (!ice_pf_src_tmr_owned(pf)) + goto reset_ts; + + err = ice_ptp_init_phc(hw); +@@ -3091,7 +3091,7 @@ void ice_ptp_init(struct ice_pf *pf) + /* If this function owns the clock hardware, it must allocate and + * configure the PTP clock device to represent it. + */ +- if (hw->func_caps.ts_func_info.src_tmr_owned) { ++ if (ice_pf_src_tmr_owned(pf)) { + err = ice_ptp_init_owner(pf); + if (err) + goto err; +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0003-ice-Re-enable-timestamping-correctly-after-reset.patch b/kernel-std/debian/patches/ice-VDF/0003-ice-Re-enable-timestamping-correctly-after-reset.patch new file mode 100644 index 00000000..206d655f --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0003-ice-Re-enable-timestamping-correctly-after-reset.patch @@ -0,0 +1,93 @@ +From 3c155fbf8e2a0546302a01cc06e8ece18468148e Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Fri, 1 Dec 2023 10:08:42 -0800 +Subject: [PATCH 03/36] ice: Re-enable timestamping correctly after reset + +During reset, TX_TSYN interrupt should be processed as it may process +timestamps in brief moments before and after reset. +Timestamping should be enabled on VSIs at the end of reset procedure. +On ice_get_phy_tx_tstamp_ready error, interrupt should not be rearmed +because error only happens on resets. + +Reviewed-by: Jesse Brandeburg +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 1cc5b6eaad92d69fe4d84bbee5c12ee297d56296) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_main.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 19 ++++++++++--------- + 2 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index e957529b3fd6..d2f3b4374d14 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3190,7 +3190,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + if (oicr & PFINT_OICR_TSYN_TX_M) { + ena_mask &= ~PFINT_OICR_TSYN_TX_M; +- if (!hw->reset_ongoing && ice_ptp_pf_handles_tx_interrupt(pf)) ++ if (ice_ptp_pf_handles_tx_interrupt(pf)) + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); + } + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index b1951357ba9f..92459589f6ce 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -809,7 +809,9 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) + + /* Read the Tx ready status first */ + err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready); +- if (err || tstamp_ready) ++ if (err) ++ break; ++ else if (tstamp_ready) + return ICE_TX_TSTAMP_WORK_PENDING; + } + +@@ -2535,12 +2537,10 @@ void ice_ptp_reset(struct ice_pf *pf) + int err, itr = 1; + u64 time_diff; + +- if (test_bit(ICE_PFR_REQ, pf->state)) ++ if (test_bit(ICE_PFR_REQ, pf->state) || ++ !ice_pf_src_tmr_owned(pf)) + goto pfr; + +- if (!ice_pf_src_tmr_owned(pf)) +- goto reset_ts; +- + err = ice_ptp_init_phc(hw); + if (err) + goto err; +@@ -2584,10 +2584,6 @@ void ice_ptp_reset(struct ice_pf *pf) + goto err; + } + +-reset_ts: +- /* Restart the PHY timestamping block */ +- ice_ptp_reset_phy_timestamping(pf); +- + pfr: + /* Init Tx structures */ + if (ice_is_e810(&pf->hw)) { +@@ -2603,6 +2599,11 @@ void ice_ptp_reset(struct ice_pf *pf) + + set_bit(ICE_FLAG_PTP, pf->flags); + ++ /* Restart the PHY timestamping block */ ++ if (!test_bit(ICE_PFR_REQ, pf->state) && ++ ice_pf_src_tmr_owned(pf)) ++ ice_ptp_restart_all_phy(pf); ++ + /* Start periodic work going */ + kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0); + +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0004-ice-periodically-kick-Tx-timestamp-interrupt.patch b/kernel-std/debian/patches/ice-VDF/0004-ice-periodically-kick-Tx-timestamp-interrupt.patch new file mode 100644 index 00000000..29d0c524 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0004-ice-periodically-kick-Tx-timestamp-interrupt.patch @@ -0,0 +1,121 @@ +From 214f06259ade960e3790b62f96bc1b75e5b76e79 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Fri, 1 Dec 2023 10:08:43 -0800 +Subject: [PATCH 04/36] ice: periodically kick Tx timestamp interrupt + +The E822 hardware for Tx timestamping keeps track of how many +outstanding timestamps are still in the PHY memory block. It will not +generate a new interrupt to the MAC until all of the timestamps in the +region have been read. + +If somehow all the available data is not read, but the driver has exited +its interrupt routine already, the PHY will not generate a new interrupt +even if new timestamp data is captured. Because no interrupt is +generated, the driver never processes the timestamp data. This state +results in a permanent failure for all future Tx timestamps. + +It is not clear how the driver and hardware could enter this state. +However, if it does, there is currently no recovery mechanism. + +Add a recovery mechanism via the periodic PTP work thread which invokes +ice_ptp_periodic_work(). Introduce a new check, +ice_ptp_maybe_trigger_tx_interrupt() which checks the PHY timestamp +ready bitmask. If any bits are set, trigger a software interrupt by +writing to PFINT_OICR. + +Once triggered, the main timestamp processing thread will read through +the PHY data and clear the outstanding timestamp data. Once cleared, new +data should trigger interrupts as expected. + +This should allow recovery from such a state rather than leaving the +device in a state where we cannot process Tx timestamps. + +It is possible that this function checks for timestamp data +simultaneously with the interrupt, and it might trigger additional +unnecessary interrupts. This will cause a small amount of additional +processing. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Andrii Staikov +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 712e876371f8350c446a33577cf4a0aedcd4742a) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 50 ++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 92459589f6ce..0d6c7215e0c1 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -2509,6 +2509,54 @@ enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf) + } + } + ++/** ++ * ice_ptp_maybe_trigger_tx_interrupt - Trigger Tx timstamp interrupt ++ * @pf: Board private structure ++ * ++ * The device PHY issues Tx timestamp interrupts to the driver for processing ++ * timestamp data from the PHY. It will not interrupt again until all ++ * current timestamp data is read. In rare circumstances, it is possible that ++ * the driver fails to read all outstanding data. ++ * ++ * To avoid getting permanently stuck, periodically check if the PHY has ++ * outstanding timestamp data. If so, trigger an interrupt from software to ++ * process this data. ++ */ ++static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf) ++{ ++ struct device *dev = ice_pf_to_dev(pf); ++ struct ice_hw *hw = &pf->hw; ++ bool trigger_oicr = false; ++ unsigned int i; ++ ++ if (ice_is_e810(hw)) ++ return; ++ ++ if (!ice_pf_src_tmr_owned(pf)) ++ return; ++ ++ for (i = 0; i < ICE_MAX_QUAD; i++) { ++ u64 tstamp_ready; ++ int err; ++ ++ err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready); ++ if (!err && tstamp_ready) { ++ trigger_oicr = true; ++ break; ++ } ++ } ++ ++ if (trigger_oicr) { ++ /* Trigger a software interrupt, to ensure this data ++ * gets processed. ++ */ ++ dev_dbg(dev, "PTP periodic task detected waiting timestamps. Triggering Tx timestamp interrupt now.\n"); ++ ++ wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); ++ ice_flush(hw); ++ } ++} ++ + static void ice_ptp_periodic_work(struct kthread_work *work) + { + struct ice_ptp *ptp = container_of(work, struct ice_ptp, work.work); +@@ -2520,6 +2568,8 @@ static void ice_ptp_periodic_work(struct kthread_work *work) + + err = ice_ptp_update_cached_phctime(pf); + ++ ice_ptp_maybe_trigger_tx_interrupt(pf); ++ + /* Run twice a second or reschedule if phc update failed */ + kthread_queue_delayed_work(ptp->kworker, &ptp->work, + msecs_to_jiffies(err ? 10 : 500)); +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0005-ice-PTP-Rename-macros-used-for-PHY-QUAD-port-definit.patch b/kernel-std/debian/patches/ice-VDF/0005-ice-PTP-Rename-macros-used-for-PHY-QUAD-port-definit.patch new file mode 100644 index 00000000..a31b8b17 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0005-ice-PTP-Rename-macros-used-for-PHY-QUAD-port-definit.patch @@ -0,0 +1,81 @@ +From c25fc364d599195403ed9ba51ef8fa6ed3b642ff Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 26 Jul 2023 11:27:44 -0700 +Subject: [PATCH 05/36] ice: PTP: Rename macros used for PHY/QUAD port + definitions + +The ice_fill_phy_msg_e822 function uses several macros to specify the +correct address when sending a sideband message to the PHY block in +hardware. + +The names of these macros are fairly generic and confusing. Future +development is going to extend the driver to support new hardware families +which have different relationships between PHY and QUAD. Rename the macros +for clarity and to indicate that they are E822 specific. This also matches +closer to the hardware specification in the data sheet. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 64fd7de2469dd52a7f1517ce95ae22fcb391a8a1) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 8 ++++---- + drivers/net/ethernet/intel/ice/ice_type.h | 14 +++++++------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index a299af39a7c4..03c4aa995e8d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -294,9 +294,9 @@ ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset) + { + int phy_port, phy, quadtype; + +- phy_port = port % ICE_PORTS_PER_PHY; +- phy = port / ICE_PORTS_PER_PHY; +- quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_NUM_QUAD_TYPE; ++ phy_port = port % ICE_PORTS_PER_PHY_E822; ++ phy = port / ICE_PORTS_PER_PHY_E822; ++ quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E822; + + if (quadtype == 0) { + msg->msg_addr_low = P_Q0_L(P_0_BASE + offset, phy_port); +@@ -628,7 +628,7 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + + msg->dest_dev = rmn_0; + +- if ((quad % ICE_NUM_QUAD_TYPE) == 0) ++ if ((quad % ICE_QUADS_PER_PHY_E822) == 0) + addr = Q_0_BASE + offset; + else + addr = Q_1_BASE + offset; +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index 4cd131546aa9..bb5d8b681bc2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -909,13 +909,13 @@ struct ice_hw { + /* INTRL granularity in 1 us */ + u8 intrl_gran; + +-#define ICE_PHY_PER_NAC 1 +-#define ICE_MAX_QUAD 2 +-#define ICE_NUM_QUAD_TYPE 2 +-#define ICE_PORTS_PER_QUAD 4 +-#define ICE_PHY_0_LAST_QUAD 1 +-#define ICE_PORTS_PER_PHY 8 +-#define ICE_NUM_EXTERNAL_PORTS ICE_PORTS_PER_PHY ++#define ICE_PHY_PER_NAC_E822 1 ++#define ICE_MAX_QUAD 2 ++#define ICE_QUADS_PER_PHY_E822 2 ++#define ICE_PORTS_PER_PHY_E822 8 ++#define ICE_PORTS_PER_QUAD 4 ++#define ICE_PORTS_PER_PHY_E810 4 ++#define ICE_NUM_EXTERNAL_PORTS (ICE_MAX_QUAD * ICE_PORTS_PER_QUAD) + + /* Active package version (currently active) */ + struct ice_pkg_ver active_pkg_ver; +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0006-ice-PTP-move-quad-value-check-inside-ice_fill_phy_ms.patch b/kernel-std/debian/patches/ice-VDF/0006-ice-PTP-move-quad-value-check-inside-ice_fill_phy_ms.patch new file mode 100644 index 00000000..0faf7dd3 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0006-ice-PTP-move-quad-value-check-inside-ice_fill_phy_ms.patch @@ -0,0 +1,80 @@ +From 13f48f4c94ad4d317e7c7ccaa188a11850a8aa32 Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 26 Jul 2023 11:27:45 -0700 +Subject: [PATCH 06/36] ice: PTP: move quad value check inside + ice_fill_phy_msg_e822 + +The callers of ice_fill_phy_msg_e822 check for whether the quad number is +within the expected range. Move this check inside the ice_fill_phy_msg_e822 +function instead of duplicating it twice. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit dd84744cf5ea967c8d53aae6b6a45703dbc5c5c4) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index 03c4aa995e8d..e024b88ce32b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -621,11 +621,14 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + * Fill a message buffer for accessing a register in a quad shared between + * multiple PHYs. + */ +-static void ++static int + ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + { + u32 addr; + ++ if (quad >= ICE_MAX_QUAD) ++ return -EINVAL; ++ + msg->dest_dev = rmn_0; + + if ((quad % ICE_QUADS_PER_PHY_E822) == 0) +@@ -635,6 +638,8 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + + msg->msg_addr_low = lower_16_bits(addr); + msg->msg_addr_high = upper_16_bits(addr); ++ ++ return 0; + } + + /** +@@ -653,10 +658,10 @@ ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- if (quad >= ICE_MAX_QUAD) +- return -EINVAL; ++ err = ice_fill_quad_msg_e822(&msg, quad, offset); ++ if (err) ++ return err; + +- ice_fill_quad_msg_e822(&msg, quad, offset); + msg.opcode = ice_sbq_msg_rd; + + err = ice_sbq_rw_reg(hw, &msg); +@@ -687,10 +692,10 @@ ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- if (quad >= ICE_MAX_QUAD) +- return -EINVAL; ++ err = ice_fill_quad_msg_e822(&msg, quad, offset); ++ if (err) ++ return err; + +- ice_fill_quad_msg_e822(&msg, quad, offset); + msg.opcode = ice_sbq_msg_wr; + msg.data = val; + +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0007-ice-remove-ptp_tx-ring-parameter-flag.patch b/kernel-std/debian/patches/ice-VDF/0007-ice-remove-ptp_tx-ring-parameter-flag.patch new file mode 100644 index 00000000..a2e95af6 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0007-ice-remove-ptp_tx-ring-parameter-flag.patch @@ -0,0 +1,97 @@ +From 7dae9333af82f6c9e2db1940c3a10ae38dabea7b Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 21 Nov 2023 13:12:55 -0800 +Subject: [PATCH 07/36] ice: remove ptp_tx ring parameter flag + +Before performing a Tx timestamp in ice_stamp(), the driver checks a ptp_tx +ring variable to see if timestamping is enabled on that ring. This value is +set for all rings whenever userspace configures Tx timestamping. + +Ostensibly this was done to avoid wasting cycles checking other fields when +timestamping has not been enabled. However, for Tx timestamps we already +get an individual per-SKB flag indicating whether userspace wants to +request a timestamp on that packet. We do not gain much by also having +a separate flag to check for whether timestamping was enabled. + +In fact, the driver currently fails to restore the field after a PF reset. +Because of this, if a PF reset occurs, timestamps will be disabled. + +Since this flag doesn't add value in the hotpath, remove it and always +provide a timestamp if the SKB flag has been set. + +A following change will fix the reset path to properly restore user +timestamping configuration completely. + +This went unnoticed for some time because one of the most common +applications using Tx timestamps, ptp4l, will reconfigure the socket as +part of its fault recovery logic. + +Fixes: ea9b847cda64 ("ice: enable transmit timestamps for E810 devices") +Signed-off-by: Jacob Keller +Reviewed-by: Jesse Brandeburg +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 0ffb08b1a45bd6b7694e01da0e1d9e3e788418fb) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 14 -------------- + drivers/net/ethernet/intel/ice/ice_txrx.c | 3 --- + drivers/net/ethernet/intel/ice/ice_txrx.h | 1 - + 3 files changed, 18 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 0d6c7215e0c1..c03153bdb7c3 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -280,20 +280,6 @@ static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on) + */ + static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) + { +- struct ice_vsi *vsi; +- u16 i; +- +- vsi = ice_get_main_vsi(pf); +- if (!vsi) +- return; +- +- /* Set the timestamp enable flag for all the Tx rings */ +- ice_for_each_txq(vsi, i) { +- if (!vsi->tx_rings[i]) +- continue; +- vsi->tx_rings[i]->ptp_tx = on; +- } +- + if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) + ice_ptp_configure_tx_tstamp(pf, on); + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index 24c914015973..9170a3e8f088 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -2305,9 +2305,6 @@ ice_tstamp(struct ice_tx_ring *tx_ring, struct sk_buff *skb, + if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) + return; + +- if (!tx_ring->ptp_tx) +- return; +- + /* Tx timestamps cannot be sampled when doing TSO */ + if (first->tx_flags & ICE_TX_FLAGS_TSO) + return; +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h +index 407d4c320097..b28b9826bbcd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.h ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.h +@@ -381,7 +381,6 @@ struct ice_tx_ring { + #define ICE_TX_FLAGS_RING_VLAN_L2TAG2 BIT(2) + u8 flags; + u8 dcb_tc; /* Traffic class of ring */ +- u8 ptp_tx; + } ____cacheline_internodealigned_in_smp; + + static inline bool ice_ring_uses_build_skb(struct ice_rx_ring *ring) +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0008-ice-unify-logic-for-programming-PFINT_TSYN_MSK.patch b/kernel-std/debian/patches/ice-VDF/0008-ice-unify-logic-for-programming-PFINT_TSYN_MSK.patch new file mode 100644 index 00000000..9b7c9ca9 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0008-ice-unify-logic-for-programming-PFINT_TSYN_MSK.patch @@ -0,0 +1,160 @@ +From 99007ca6255e2c35256bd97fa141705d301eb934 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 21 Nov 2023 13:12:56 -0800 +Subject: [PATCH 08/36] ice: unify logic for programming PFINT_TSYN_MSK + +Commit d938a8cca88a ("ice: Auxbus devices & driver for E822 TS") modified +how Tx timestamps are handled for E822 devices. On these devices, only the +clock owner handles reading the Tx timestamp data from firmware. To do +this, the PFINT_TSYN_MSK register is modified from the default value to one +which enables reacting to a Tx timestamp on all PHY ports. + +The driver currently programs PFINT_TSYN_MSK in different places depending +on whether the port is the clock owner or not. For the clock owner, the +PFINT_TSYN_MSK value is programmed during ice_ptp_init_owner just before +calling ice_ptp_tx_ena_intr to program the PHY ports. + +For the non-clock owner ports, the PFINT_TSYN_MSK is programmed during +ice_ptp_init_port. + +If a large enough device reset occurs, the PFINT_TSYN_MSK register will be +reset to the default value in which only the PHY associated directly with +the PF will cause the Tx timestamp interrupt to trigger. + +The driver lacks logic to reprogram the PFINT_TSYN_MSK register after a +device reset. For the E822 device, this results in the PF no longer +responding to interrupts for other ports. This results in failure to +deliver Tx timestamps to user space applications. + +Rename ice_ptp_configure_tx_tstamp to ice_ptp_cfg_tx_interrupt, and unify +the logic for programming PFINT_TSYN_MSK and PFINT_OICR_ENA into one place. +This function will program both registers according to the combination of +user configuration and device requirements. + +This ensures that PFINT_TSYN_MSK is always restored when we configure the +Tx timestamp interrupt. + +Fixes: d938a8cca88a ("ice: Auxbus devices & driver for E822 TS") +Signed-off-by: Jacob Keller +Reviewed-by: Jesse Brandeburg +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 7d606a1e2d0575b6c3a2600f43f90d1e409f9661) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 60 ++++++++++++++---------- + 1 file changed, 34 insertions(+), 26 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index c03153bdb7c3..b0bba866e8a2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -256,21 +256,42 @@ ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin, + } + + /** +- * ice_ptp_configure_tx_tstamp - Enable or disable Tx timestamp interrupt +- * @pf: The PF pointer to search in +- * @on: bool value for whether timestamp interrupt is enabled or disabled ++ * ice_ptp_cfg_tx_interrupt - Configure Tx timestamp interrupt for the device ++ * @pf: Board private structure ++ * ++ * Program the device to respond appropriately to the Tx timestamp interrupt ++ * cause. + */ +-static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on) ++static void ice_ptp_cfg_tx_interrupt(struct ice_pf *pf) + { ++ struct ice_hw *hw = &pf->hw; ++ bool enable; + u32 val; + ++ switch (pf->ptp.tx_interrupt_mode) { ++ case ICE_PTP_TX_INTERRUPT_ALL: ++ /* React to interrupts across all quads. */ ++ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f); ++ enable = true; ++ break; ++ case ICE_PTP_TX_INTERRUPT_NONE: ++ /* Do not react to interrupts on any quad. */ ++ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0); ++ enable = false; ++ break; ++ case ICE_PTP_TX_INTERRUPT_SELF: ++ default: ++ enable = pf->ptp.tstamp_config.tx_type == HWTSTAMP_TX_ON; ++ break; ++ } ++ + /* Configure the Tx timestamp interrupt */ +- val = rd32(&pf->hw, PFINT_OICR_ENA); +- if (on) ++ val = rd32(hw, PFINT_OICR_ENA); ++ if (enable) + val |= PFINT_OICR_TSYN_TX_M; + else + val &= ~PFINT_OICR_TSYN_TX_M; +- wr32(&pf->hw, PFINT_OICR_ENA, val); ++ wr32(hw, PFINT_OICR_ENA, val); + } + + /** +@@ -280,10 +301,9 @@ static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on) + */ + static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) + { +- if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) +- ice_ptp_configure_tx_tstamp(pf, on); +- + pf->ptp.tstamp_config.tx_type = on ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; ++ ++ ice_ptp_cfg_tx_interrupt(pf); + } + + /** +@@ -2909,15 +2929,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + /* Release the global hardware lock */ + ice_ptp_unlock(hw); + +- if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) { +- /* The clock owner for this device type handles the timestamp +- * interrupt for all ports. +- */ +- ice_ptp_configure_tx_tstamp(pf, true); +- +- /* React on all quads interrupts for E82x */ +- wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f); +- ++ if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ + err = ice_ptp_tx_ena_intr(pf, true, itr); + if (err) +@@ -2991,13 +3003,6 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + case ICE_PHY_E810: + return ice_ptp_init_tx_e810(pf, &ptp_port->tx); + case ICE_PHY_E822: +- /* Non-owner PFs don't react to any interrupts on E82x, +- * neither on own quad nor on others +- */ +- if (!ice_ptp_pf_handles_tx_interrupt(pf)) { +- ice_ptp_configure_tx_tstamp(pf, false); +- wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0); +- } + kthread_init_delayed_work(&ptp_port->ov_work, + ice_ptp_wait_for_offsets); + +@@ -3142,6 +3147,9 @@ void ice_ptp_init(struct ice_pf *pf) + /* Start the PHY timestamping block */ + ice_ptp_reset_phy_timestamping(pf); + ++ /* Configure initial Tx interrupt settings */ ++ ice_ptp_cfg_tx_interrupt(pf); ++ + set_bit(ICE_FLAG_PTP, pf->flags); + err = ice_ptp_init_work(pf, ptp); + if (err) +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0009-ice-PTP-Clean-up-timestamp-registers-correctly.patch b/kernel-std/debian/patches/ice-VDF/0009-ice-PTP-Clean-up-timestamp-registers-correctly.patch new file mode 100644 index 00000000..76770529 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0009-ice-PTP-Clean-up-timestamp-registers-correctly.patch @@ -0,0 +1,147 @@ +From e5a65377977e338a8f7baf92892481acf1c62403 Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 26 Jul 2023 11:27:43 -0700 +Subject: [PATCH 09/36] ice: PTP: Clean up timestamp registers correctly + +E822 PHY TS registers should not be written and the only way to clean up +them is to reset QUAD memory. + +To ensure that the status bit for the timestamp index is cleared, ensure +that ice_clear_phy_tstamp implementations first read the timestamp out. +Implementations which can write the register continue to do so. + +Add a note to indicate this function should only be called on timestamps +which have their valid bit set. Update the dynamic debug messages to +reflect the actual action taken. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit be65a1a33bdee3912daac50aa6c5270ec9c37010) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 70 +++++++++++++-------- + 1 file changed, 45 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index e024b88ce32b..cd28430cfdda 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -759,29 +759,32 @@ ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + * @quad: the quad to read from + * @idx: the timestamp index to reset + * +- * Clear a timestamp, resetting its valid bit, from the PHY quad block that is +- * shared between the internal PHYs on the E822 devices. ++ * Read the timestamp out of the quad to clear its timestamp status bit from ++ * the PHY quad block that is shared between the internal PHYs of the E822 ++ * devices. ++ * ++ * Note that unlike E810, software cannot directly write to the quad memory ++ * bank registers. E822 relies on the ice_get_phy_tx_tstamp_ready() function ++ * to determine which timestamps are valid. Reading a timestamp auto-clears ++ * the valid bit. ++ * ++ * To directly clear the contents of the timestamp block entirely, discarding ++ * all timestamp data at once, software should instead use ++ * ice_ptp_reset_ts_memory_quad_e822(). ++ * ++ * This function should only be called on an idx whose bit is set according to ++ * ice_get_phy_tx_tstamp_ready(). + */ + static int + ice_clear_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx) + { +- u16 lo_addr, hi_addr; ++ u64 unused_tstamp; + int err; + +- lo_addr = (u16)TS_L(Q_REG_TX_MEMORY_BANK_START, idx); +- hi_addr = (u16)TS_H(Q_REG_TX_MEMORY_BANK_START, idx); +- +- err = ice_write_quad_reg_e822(hw, quad, lo_addr, 0); +- if (err) { +- ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, err %d\n", +- err); +- return err; +- } +- +- err = ice_write_quad_reg_e822(hw, quad, hi_addr, 0); ++ err = ice_read_phy_tstamp_e822(hw, quad, idx, &unused_tstamp); + if (err) { +- ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register, err %d\n", +- err); ++ ice_debug(hw, ICE_DBG_PTP, "Failed to read the timestamp register for quad %u, idx %u, err %d\n", ++ quad, idx, err); + return err; + } + +@@ -2816,28 +2819,39 @@ ice_read_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp) + * @lport: the lport to read from + * @idx: the timestamp index to reset + * +- * Clear a timestamp, resetting its valid bit, from the timestamp block of the +- * external PHY on the E810 device. ++ * Read the timestamp and then forcibly overwrite its value to clear the valid ++ * bit from the timestamp block of the external PHY on the E810 device. ++ * ++ * This function should only be called on an idx whose bit is set according to ++ * ice_get_phy_tx_tstamp_ready(). + */ + static int ice_clear_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx) + { + u32 lo_addr, hi_addr; ++ u64 unused_tstamp; + int err; + ++ err = ice_read_phy_tstamp_e810(hw, lport, idx, &unused_tstamp); ++ if (err) { ++ ice_debug(hw, ICE_DBG_PTP, "Failed to read the timestamp register for lport %u, idx %u, err %d\n", ++ lport, idx, err); ++ return err; ++ } ++ + lo_addr = TS_EXT(LOW_TX_MEMORY_BANK_START, lport, idx); + hi_addr = TS_EXT(HIGH_TX_MEMORY_BANK_START, lport, idx); + + err = ice_write_phy_reg_e810(hw, lo_addr, 0); + if (err) { +- ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, err %d\n", +- err); ++ ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register for lport %u, idx %u, err %d\n", ++ lport, idx, err); + return err; + } + + err = ice_write_phy_reg_e810(hw, hi_addr, 0); + if (err) { +- ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register, err %d\n", +- err); ++ ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register for lport %u, idx %u, err %d\n", ++ lport, idx, err); + return err; + } + +@@ -3519,9 +3533,15 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp) + * @block: the block to read from + * @idx: the timestamp index to reset + * +- * Clear a timestamp, resetting its valid bit, from the timestamp block. For +- * E822 devices, the block is the quad to clear from. For E810 devices, the +- * block is the logical port to clear from. ++ * Clear a timestamp from the timestamp block, discarding its value without ++ * returning it. This resets the memory status bit for the timestamp index ++ * allowing it to be reused for another timestamp in the future. ++ * ++ * For E822 devices, the block number is the PHY quad to clear from. For E810 ++ * devices, the block number is the logical port to clear from. ++ * ++ * This function must only be called on a timestamp index whose valid bit is ++ * set according to ice_get_phy_tx_tstamp_ready(). + */ + int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx) + { +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0010-ice-Use-PTP-auxbus-for-all-PHYs-restart-in-E822.patch b/kernel-std/debian/patches/ice-VDF/0010-ice-Use-PTP-auxbus-for-all-PHYs-restart-in-E822.patch new file mode 100644 index 00000000..2a88fb45 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0010-ice-Use-PTP-auxbus-for-all-PHYs-restart-in-E822.patch @@ -0,0 +1,65 @@ +From e2a74a0a7dd399b0ee2ddd4889c609dedb85bfb5 Mon Sep 17 00:00:00 2001 +From: Michal Michalik +Date: Thu, 27 Jul 2023 15:50:35 +0200 +Subject: [PATCH 10/36] ice: Use PTP auxbus for all PHYs restart in E822 + +The E822 (and other devices based on the same PHY) is having issue while +setting the PHC timer - the PHY timers are drifting from the PHC. After +such a set all PHYs need to be restarted and resynchronised - do it +using auxiliary bus. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Michal Michalik +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit af3c5c8748e6d286d4f2dd9800f9d27f29b8e2ef) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index b0bba866e8a2..42eb1418eb90 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1496,6 +1496,24 @@ static void ice_ptp_reset_phy_timestamping(struct ice_pf *pf) + ice_ptp_port_phy_restart(&pf->ptp.port); + } + ++/** ++ * ice_ptp_restart_all_phy - Restart all PHYs to recalibrate timestamping ++ * @pf: Board private structure ++ */ ++static void ice_ptp_restart_all_phy(struct ice_pf *pf) ++{ ++ struct list_head *entry; ++ ++ list_for_each(entry, &pf->ptp.ports_owner.ports) { ++ struct ice_ptp_port *port = list_entry(entry, ++ struct ice_ptp_port, ++ list_member); ++ ++ if (port->link_up) ++ ice_ptp_port_phy_restart(port); ++ } ++} ++ + /** + * ice_ptp_adjfine - Adjust clock increment rate + * @info: the driver's PTP info structure +@@ -1933,9 +1951,9 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts) + /* Reenable periodic outputs */ + ice_ptp_enable_all_clkout(pf); + +- /* Recalibrate and re-enable timestamp block */ +- if (pf->ptp.port.link_up) +- ice_ptp_port_phy_restart(&pf->ptp.port); ++ /* Recalibrate and re-enable timestamp blocks for E822/E823 */ ++ if (hw->phy_model == ICE_PHY_E822) ++ ice_ptp_restart_all_phy(pf); + exit: + if (err) { + dev_err(ice_pf_to_dev(pf), "PTP failed to set time %d\n", err); +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0011-ice-Rename-E822-to-E82X.patch b/kernel-std/debian/patches/ice-VDF/0011-ice-Rename-E822-to-E82X.patch new file mode 100644 index 00000000..5f259989 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0011-ice-Rename-E822-to-E82X.patch @@ -0,0 +1,2177 @@ +From ed199ec1c5886cf9830921b9380cf91ee216f26f Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Fri, 1 Dec 2023 10:08:44 -0800 +Subject: [PATCH 11/36] ice: Rename E822 to E82X + +When code is applicable for both E822 and E823 devices, rename it from +E822 to E82X. +ICE_PHY_PER_NAC_E822 was unused, so just remove it. + +Signed-off-by: Karol Kolacinski +Reviewed-by: Przemek Kitszel +Reviewed-by: Simon Horman +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit a39dd252d552ab3212fea55330081ee64a9e5573) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 48 +- + drivers/net/ethernet/intel/ice/ice_ptp.h | 2 +- + .../net/ethernet/intel/ice/ice_ptp_consts.h | 12 +- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 444 +++++++++--------- + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 48 +- + drivers/net/ethernet/intel/ice/ice_type.h | 7 +- + 6 files changed, 280 insertions(+), 281 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 42eb1418eb90..2e6e1fc84d11 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -7,7 +7,7 @@ + + #define E810_OUT_PROP_DELAY_NS 1 + +-#define UNKNOWN_INCVAL_E822 0x100000000ULL ++#define UNKNOWN_INCVAL_E82X 0x100000000ULL + + static const struct ptp_pin_desc ice_pin_desc_e810t[] = { + /* name idx func chan */ +@@ -987,7 +987,7 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + } + + /** +- * ice_ptp_init_tx_e822 - Initialize tracking for Tx timestamps ++ * ice_ptp_init_tx_e82x - Initialize tracking for Tx timestamps + * @pf: Board private structure + * @tx: the Tx tracking structure to initialize + * @port: the port this structure tracks +@@ -998,11 +998,11 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + * registers into chunks based on the port number. + */ + static int +-ice_ptp_init_tx_e822(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port) ++ice_ptp_init_tx_e82x(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port) + { + tx->block = port / ICE_PORTS_PER_QUAD; +- tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E822; +- tx->len = INDEX_PER_PORT_E822; ++ tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E82X; ++ tx->len = INDEX_PER_PORT_E82X; + tx->verify_cached = 0; + + return ice_ptp_alloc_tx_tracker(tx); +@@ -1205,10 +1205,10 @@ static u64 ice_base_incval(struct ice_pf *pf) + + if (ice_is_e810(hw)) + incval = ICE_PTP_NOMINAL_INCVAL_E810; +- else if (ice_e822_time_ref(hw) < NUM_ICE_TIME_REF_FREQ) +- incval = ice_e822_nominal_incval(ice_e822_time_ref(hw)); ++ else if (ice_e82x_time_ref(hw) < NUM_ICE_TIME_REF_FREQ) ++ incval = ice_e82x_nominal_incval(ice_e82x_time_ref(hw)); + else +- incval = UNKNOWN_INCVAL_E822; ++ incval = UNKNOWN_INCVAL_E82X; + + dev_dbg(ice_pf_to_dev(pf), "PTP: using base increment value of 0x%016llx\n", + incval); +@@ -1237,10 +1237,10 @@ static int ice_ptp_check_tx_fifo(struct ice_ptp_port *port) + + /* need to read FIFO state */ + if (offs == 0 || offs == 1) +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_FIFO01_STATUS, ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_FIFO01_STATUS, + &val); + else +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_FIFO23_STATUS, ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_FIFO23_STATUS, + &val); + + if (err) { +@@ -1268,7 +1268,7 @@ static int ice_ptp_check_tx_fifo(struct ice_ptp_port *port) + dev_dbg(ice_pf_to_dev(pf), + "Port %d Tx FIFO still not empty; resetting quad %d\n", + port->port_num, quad); +- ice_ptp_reset_ts_memory_quad_e822(hw, quad); ++ ice_ptp_reset_ts_memory_quad_e82x(hw, quad); + port->tx_fifo_busy_cnt = FIFO_OK; + return 0; + } +@@ -1313,8 +1313,8 @@ static void ice_ptp_wait_for_offsets(struct kthread_work *work) + + tx_err = ice_ptp_check_tx_fifo(port); + if (!tx_err) +- tx_err = ice_phy_cfg_tx_offset_e822(hw, port->port_num); +- rx_err = ice_phy_cfg_rx_offset_e822(hw, port->port_num); ++ tx_err = ice_phy_cfg_tx_offset_e82x(hw, port->port_num); ++ rx_err = ice_phy_cfg_rx_offset_e82x(hw, port->port_num); + if (tx_err || rx_err) { + /* Tx and/or Rx offset not yet configured, try again later */ + kthread_queue_delayed_work(pf->ptp.kworker, +@@ -1343,7 +1343,7 @@ ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port) + + kthread_cancel_delayed_work_sync(&ptp_port->ov_work); + +- err = ice_stop_phy_timer_e822(hw, port, true); ++ err = ice_stop_phy_timer_e82x(hw, port, true); + if (err) + dev_err(ice_pf_to_dev(pf), "PTP failed to set PHY port %d down, err %d\n", + port, err); +@@ -1386,7 +1386,7 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port) + ptp_port->tx_fifo_busy_cnt = 0; + + /* Start the PHY timer in Vernier mode */ +- err = ice_start_phy_timer_e822(hw, port); ++ err = ice_start_phy_timer_e82x(hw, port); + if (err) + goto out_unlock; + +@@ -1435,7 +1435,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + case ICE_PHY_E810: + /* Do not reconfigure E810 PHY */ + return; +- case ICE_PHY_E822: ++ case ICE_PHY_E82X: + ice_ptp_port_phy_restart(ptp_port); + return; + default: +@@ -1461,7 +1461,7 @@ static int ice_ptp_tx_ena_intr(struct ice_pf *pf, bool ena, u32 threshold) + ice_ptp_reset_ts_memory(hw); + + for (quad = 0; quad < ICE_MAX_QUAD; quad++) { +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, + &val); + if (err) + break; +@@ -1475,7 +1475,7 @@ static int ice_ptp_tx_ena_intr(struct ice_pf *pf, bool ena, u32 threshold) + val &= ~Q_REG_TX_MEM_GBL_CFG_INTR_ENA_M; + } + +- err = ice_write_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, ++ err = ice_write_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, + val); + if (err) + break; +@@ -1713,7 +1713,7 @@ static int ice_ptp_cfg_clkout(struct ice_pf *pf, unsigned int chan, + if (ice_is_e810(hw)) + start_time -= E810_OUT_PROP_DELAY_NS; + else +- start_time -= ice_e822_pps_delay(ice_e822_time_ref(hw)); ++ start_time -= ice_e82x_pps_delay(ice_e82x_time_ref(hw)); + + /* 2. Write TARGET time */ + wr32(hw, GLTSYN_TGT_L(chan, tmr_idx), lower_32_bits(start_time)); +@@ -1952,7 +1952,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts) + ice_ptp_enable_all_clkout(pf); + + /* Recalibrate and re-enable timestamp blocks for E822/E823 */ +- if (hw->phy_model == ICE_PHY_E822) ++ if (hw->phy_model == ICE_PHY_E82X) + ice_ptp_restart_all_phy(pf); + exit: + if (err) { +@@ -2665,7 +2665,7 @@ void ice_ptp_reset(struct ice_pf *pf) + } else { + kthread_init_delayed_work(&ptp->port.ov_work, + ice_ptp_wait_for_offsets); +- err = ice_ptp_init_tx_e822(pf, &ptp->port.tx, ++ err = ice_ptp_init_tx_e82x(pf, &ptp->port.tx, + ptp->port.port_num); + } + if (err) +@@ -3020,11 +3020,11 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + switch (hw->phy_model) { + case ICE_PHY_E810: + return ice_ptp_init_tx_e810(pf, &ptp_port->tx); +- case ICE_PHY_E822: ++ case ICE_PHY_E82X: + kthread_init_delayed_work(&ptp_port->ov_work, + ice_ptp_wait_for_offsets); + +- return ice_ptp_init_tx_e822(pf, &ptp_port->tx, ++ return ice_ptp_init_tx_e82x(pf, &ptp_port->tx, + ptp_port->port_num); + default: + return -ENODEV; +@@ -3111,7 +3111,7 @@ static void ice_ptp_remove_auxbus_device(struct ice_pf *pf) + static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf) + { + switch (pf->hw.phy_model) { +- case ICE_PHY_E822: ++ case ICE_PHY_E82X: + /* E822 based PHY has the clock owner process the interrupt + * for all ports. + */ +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index d94c22329df0..a3ae008a3539 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -147,7 +147,7 @@ struct ice_ptp_tx { + + /* Quad and port information for initializing timestamp blocks */ + #define INDEX_PER_QUAD 64 +-#define INDEX_PER_PORT_E822 16 ++#define INDEX_PER_PORT_E82X 16 + #define INDEX_PER_PORT_E810 64 + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h +index 4109aa3b2fcd..2c4dab0c48ab 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h +@@ -9,17 +9,17 @@ + */ + /* Constants defined for the PTP 1588 clock hardware. */ + +-/* struct ice_time_ref_info_e822 ++/* struct ice_time_ref_info_e82x + * + * E822 hardware can use different sources as the reference for the PTP + * hardware clock. Each clock has different characteristics such as a slightly + * different frequency, etc. + * + * This lookup table defines several constants that depend on the current time +- * reference. See the struct ice_time_ref_info_e822 for information about the ++ * reference. See the struct ice_time_ref_info_e82x for information about the + * meaning of each constant. + */ +-const struct ice_time_ref_info_e822 e822_time_ref[NUM_ICE_TIME_REF_FREQ] = { ++const struct ice_time_ref_info_e82x e822_time_ref[NUM_ICE_TIME_REF_FREQ] = { + /* ICE_TIME_REF_FREQ_25_000 -> 25 MHz */ + { + /* pll_freq */ +@@ -81,7 +81,7 @@ const struct ice_time_ref_info_e822 e822_time_ref[NUM_ICE_TIME_REF_FREQ] = { + }, + }; + +-const struct ice_cgu_pll_params_e822 e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = { ++const struct ice_cgu_pll_params_e82x e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = { + /* ICE_TIME_REF_FREQ_25_000 -> 25 MHz */ + { + /* refclk_pre_div */ +@@ -155,7 +155,7 @@ const struct ice_cgu_pll_params_e822 e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = { + }, + }; + +-/* struct ice_vernier_info_e822 ++/* struct ice_vernier_info_e82x + * + * E822 hardware calibrates the delay of the timestamp indication from the + * actual packet transmission or reception during the initialization of the +@@ -168,7 +168,7 @@ const struct ice_cgu_pll_params_e822 e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = { + * used by this link speed, and that the register should be cleared by writing + * 0. Other values specify the clock frequency in Hz. + */ +-const struct ice_vernier_info_e822 e822_vernier[NUM_ICE_PTP_LNK_SPD] = { ++const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD] = { + /* ICE_PTP_LNK_SPD_1G */ + { + /* tx_par_clk */ +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index cd28430cfdda..7337e7e710ed 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -284,19 +284,19 @@ static void ice_ptp_exec_tmr_cmd(struct ice_hw *hw) + */ + + /** +- * ice_fill_phy_msg_e822 - Fill message data for a PHY register access ++ * ice_fill_phy_msg_e82x - Fill message data for a PHY register access + * @msg: the PHY message buffer to fill in + * @port: the port to access + * @offset: the register offset + */ + static void +-ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset) ++ice_fill_phy_msg_e82x(struct ice_sbq_msg_input *msg, u8 port, u16 offset) + { + int phy_port, phy, quadtype; + +- phy_port = port % ICE_PORTS_PER_PHY_E822; +- phy = port / ICE_PORTS_PER_PHY_E822; +- quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E822; ++ phy_port = port % ICE_PORTS_PER_PHY_E82X; ++ phy = port / ICE_PORTS_PER_PHY_E82X; ++ quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E82X; + + if (quadtype == 0) { + msg->msg_addr_low = P_Q0_L(P_0_BASE + offset, phy_port); +@@ -315,7 +315,7 @@ ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset) + } + + /** +- * ice_is_64b_phy_reg_e822 - Check if this is a 64bit PHY register ++ * ice_is_64b_phy_reg_e82x - Check if this is a 64bit PHY register + * @low_addr: the low address to check + * @high_addr: on return, contains the high address of the 64bit register + * +@@ -323,7 +323,7 @@ ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset) + * represented as two 32bit registers. If it is, return the appropriate high + * register offset to use. + */ +-static bool ice_is_64b_phy_reg_e822(u16 low_addr, u16 *high_addr) ++static bool ice_is_64b_phy_reg_e82x(u16 low_addr, u16 *high_addr) + { + switch (low_addr) { + case P_REG_PAR_PCS_TX_OFFSET_L: +@@ -368,7 +368,7 @@ static bool ice_is_64b_phy_reg_e822(u16 low_addr, u16 *high_addr) + } + + /** +- * ice_is_40b_phy_reg_e822 - Check if this is a 40bit PHY register ++ * ice_is_40b_phy_reg_e82x - Check if this is a 40bit PHY register + * @low_addr: the low address to check + * @high_addr: on return, contains the high address of the 40bit value + * +@@ -377,7 +377,7 @@ static bool ice_is_64b_phy_reg_e822(u16 low_addr, u16 *high_addr) + * upper 32 bits in the high register. If it is, return the appropriate high + * register offset to use. + */ +-static bool ice_is_40b_phy_reg_e822(u16 low_addr, u16 *high_addr) ++static bool ice_is_40b_phy_reg_e82x(u16 low_addr, u16 *high_addr) + { + switch (low_addr) { + case P_REG_TIMETUS_L: +@@ -413,7 +413,7 @@ static bool ice_is_40b_phy_reg_e822(u16 low_addr, u16 *high_addr) + } + + /** +- * ice_read_phy_reg_e822 - Read a PHY register ++ * ice_read_phy_reg_e82x - Read a PHY register + * @hw: pointer to the HW struct + * @port: PHY port to read from + * @offset: PHY register offset to read +@@ -422,12 +422,12 @@ static bool ice_is_40b_phy_reg_e822(u16 low_addr, u16 *high_addr) + * Read a PHY register for the given port over the device sideband queue. + */ + static int +-ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val) ++ice_read_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 offset, u32 *val) + { + struct ice_sbq_msg_input msg = {0}; + int err; + +- ice_fill_phy_msg_e822(&msg, port, offset); ++ ice_fill_phy_msg_e82x(&msg, port, offset); + msg.opcode = ice_sbq_msg_rd; + + err = ice_sbq_rw_reg(hw, &msg); +@@ -443,7 +443,7 @@ ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val) + } + + /** +- * ice_read_64b_phy_reg_e822 - Read a 64bit value from PHY registers ++ * ice_read_64b_phy_reg_e82x - Read a 64bit value from PHY registers + * @hw: pointer to the HW struct + * @port: PHY port to read from + * @low_addr: offset of the lower register to read from +@@ -455,7 +455,7 @@ ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val) + * known to be two parts of a 64bit value. + */ + static int +-ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) ++ice_read_64b_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) + { + u32 low, high; + u16 high_addr; +@@ -464,20 +464,20 @@ ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) + /* Only operate on registers known to be split into two 32bit + * registers. + */ +- if (!ice_is_64b_phy_reg_e822(low_addr, &high_addr)) { ++ if (!ice_is_64b_phy_reg_e82x(low_addr, &high_addr)) { + ice_debug(hw, ICE_DBG_PTP, "Invalid 64b register addr 0x%08x\n", + low_addr); + return -EINVAL; + } + +- err = ice_read_phy_reg_e822(hw, port, low_addr, &low); ++ err = ice_read_phy_reg_e82x(hw, port, low_addr, &low); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read from low register 0x%08x\n, err %d", + low_addr, err); + return err; + } + +- err = ice_read_phy_reg_e822(hw, port, high_addr, &high); ++ err = ice_read_phy_reg_e82x(hw, port, high_addr, &high); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read from high register 0x%08x\n, err %d", + high_addr, err); +@@ -490,7 +490,7 @@ ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) + } + + /** +- * ice_write_phy_reg_e822 - Write a PHY register ++ * ice_write_phy_reg_e82x - Write a PHY register + * @hw: pointer to the HW struct + * @port: PHY port to write to + * @offset: PHY register offset to write +@@ -499,12 +499,12 @@ ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) + * Write a PHY register for the given port over the device sideband queue. + */ + static int +-ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val) ++ice_write_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 offset, u32 val) + { + struct ice_sbq_msg_input msg = {0}; + int err; + +- ice_fill_phy_msg_e822(&msg, port, offset); ++ ice_fill_phy_msg_e82x(&msg, port, offset); + msg.opcode = ice_sbq_msg_wr; + msg.data = val; + +@@ -519,7 +519,7 @@ ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val) + } + + /** +- * ice_write_40b_phy_reg_e822 - Write a 40b value to the PHY ++ * ice_write_40b_phy_reg_e82x - Write a 40b value to the PHY + * @hw: pointer to the HW struct + * @port: port to write to + * @low_addr: offset of the low register +@@ -529,7 +529,7 @@ ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val) + * it up into two chunks, the lower 8 bits and the upper 32 bits. + */ + static int +-ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) ++ice_write_40b_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + { + u32 low, high; + u16 high_addr; +@@ -538,7 +538,7 @@ ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + /* Only operate on registers known to be split into a lower 8 bit + * register and an upper 32 bit register. + */ +- if (!ice_is_40b_phy_reg_e822(low_addr, &high_addr)) { ++ if (!ice_is_40b_phy_reg_e82x(low_addr, &high_addr)) { + ice_debug(hw, ICE_DBG_PTP, "Invalid 40b register addr 0x%08x\n", + low_addr); + return -EINVAL; +@@ -547,14 +547,14 @@ ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + low = (u32)(val & P_REG_40B_LOW_M); + high = (u32)(val >> P_REG_40B_HIGH_S); + +- err = ice_write_phy_reg_e822(hw, port, low_addr, low); ++ err = ice_write_phy_reg_e82x(hw, port, low_addr, low); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write to low register 0x%08x\n, err %d", + low_addr, err); + return err; + } + +- err = ice_write_phy_reg_e822(hw, port, high_addr, high); ++ err = ice_write_phy_reg_e82x(hw, port, high_addr, high); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write to high register 0x%08x\n, err %d", + high_addr, err); +@@ -565,7 +565,7 @@ ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + } + + /** +- * ice_write_64b_phy_reg_e822 - Write a 64bit value to PHY registers ++ * ice_write_64b_phy_reg_e82x - Write a 64bit value to PHY registers + * @hw: pointer to the HW struct + * @port: PHY port to read from + * @low_addr: offset of the lower register to read from +@@ -577,7 +577,7 @@ ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + * a 64bit value. + */ + static int +-ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) ++ice_write_64b_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + { + u32 low, high; + u16 high_addr; +@@ -586,7 +586,7 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + /* Only operate on registers known to be split into two 32bit + * registers. + */ +- if (!ice_is_64b_phy_reg_e822(low_addr, &high_addr)) { ++ if (!ice_is_64b_phy_reg_e82x(low_addr, &high_addr)) { + ice_debug(hw, ICE_DBG_PTP, "Invalid 64b register addr 0x%08x\n", + low_addr); + return -EINVAL; +@@ -595,14 +595,14 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + low = lower_32_bits(val); + high = upper_32_bits(val); + +- err = ice_write_phy_reg_e822(hw, port, low_addr, low); ++ err = ice_write_phy_reg_e82x(hw, port, low_addr, low); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write to low register 0x%08x\n, err %d", + low_addr, err); + return err; + } + +- err = ice_write_phy_reg_e822(hw, port, high_addr, high); ++ err = ice_write_phy_reg_e82x(hw, port, high_addr, high); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write to high register 0x%08x\n, err %d", + high_addr, err); +@@ -613,7 +613,7 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + } + + /** +- * ice_fill_quad_msg_e822 - Fill message data for quad register access ++ * ice_fill_quad_msg_e82x - Fill message data for quad register access + * @msg: the PHY message buffer to fill in + * @quad: the quad to access + * @offset: the register offset +@@ -622,7 +622,7 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + * multiple PHYs. + */ + static int +-ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) ++ice_fill_quad_msg_e82x(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + { + u32 addr; + +@@ -631,7 +631,7 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + + msg->dest_dev = rmn_0; + +- if ((quad % ICE_QUADS_PER_PHY_E822) == 0) ++ if ((quad % ICE_QUADS_PER_PHY_E82X) == 0) + addr = Q_0_BASE + offset; + else + addr = Q_1_BASE + offset; +@@ -643,7 +643,7 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + } + + /** +- * ice_read_quad_reg_e822 - Read a PHY quad register ++ * ice_read_quad_reg_e82x - Read a PHY quad register + * @hw: pointer to the HW struct + * @quad: quad to read from + * @offset: quad register offset to read +@@ -653,12 +653,12 @@ ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) + * shared between multiple PHYs. + */ + int +-ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) ++ice_read_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + { + struct ice_sbq_msg_input msg = {0}; + int err; + +- err = ice_fill_quad_msg_e822(&msg, quad, offset); ++ err = ice_fill_quad_msg_e82x(&msg, quad, offset); + if (err) + return err; + +@@ -677,7 +677,7 @@ ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + } + + /** +- * ice_write_quad_reg_e822 - Write a PHY quad register ++ * ice_write_quad_reg_e82x - Write a PHY quad register + * @hw: pointer to the HW struct + * @quad: quad to write to + * @offset: quad register offset to write +@@ -687,12 +687,12 @@ ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + * shared between multiple PHYs. + */ + int +-ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val) ++ice_write_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + { + struct ice_sbq_msg_input msg = {0}; + int err; + +- err = ice_fill_quad_msg_e822(&msg, quad, offset); ++ err = ice_fill_quad_msg_e82x(&msg, quad, offset); + if (err) + return err; + +@@ -710,7 +710,7 @@ ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + } + + /** +- * ice_read_phy_tstamp_e822 - Read a PHY timestamp out of the quad block ++ * ice_read_phy_tstamp_e82x - Read a PHY timestamp out of the quad block + * @hw: pointer to the HW struct + * @quad: the quad to read from + * @idx: the timestamp index to read +@@ -721,7 +721,7 @@ ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + * family of devices. + */ + static int +-ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) ++ice_read_phy_tstamp_e82x(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + { + u16 lo_addr, hi_addr; + u32 lo, hi; +@@ -730,14 +730,14 @@ ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + lo_addr = (u16)TS_L(Q_REG_TX_MEMORY_BANK_START, idx); + hi_addr = (u16)TS_H(Q_REG_TX_MEMORY_BANK_START, idx); + +- err = ice_read_quad_reg_e822(hw, quad, lo_addr, &lo); ++ err = ice_read_quad_reg_e82x(hw, quad, lo_addr, &lo); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read low PTP timestamp register, err %d\n", + err); + return err; + } + +- err = ice_read_quad_reg_e822(hw, quad, hi_addr, &hi); ++ err = ice_read_quad_reg_e82x(hw, quad, hi_addr, &hi); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read high PTP timestamp register, err %d\n", + err); +@@ -754,7 +754,7 @@ ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + } + + /** +- * ice_clear_phy_tstamp_e822 - Clear a timestamp from the quad block ++ * ice_clear_phy_tstamp_e82x - Clear a timestamp from the quad block + * @hw: pointer to the HW struct + * @quad: the quad to read from + * @idx: the timestamp index to reset +@@ -770,18 +770,18 @@ ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp) + * + * To directly clear the contents of the timestamp block entirely, discarding + * all timestamp data at once, software should instead use +- * ice_ptp_reset_ts_memory_quad_e822(). ++ * ice_ptp_reset_ts_memory_quad_e82x(). + * + * This function should only be called on an idx whose bit is set according to + * ice_get_phy_tx_tstamp_ready(). + */ + static int +-ice_clear_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx) ++ice_clear_phy_tstamp_e82x(struct ice_hw *hw, u8 quad, u8 idx) + { + u64 unused_tstamp; + int err; + +- err = ice_read_phy_tstamp_e822(hw, quad, idx, &unused_tstamp); ++ err = ice_read_phy_tstamp_e82x(hw, quad, idx, &unused_tstamp); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read the timestamp register for quad %u, idx %u, err %d\n", + quad, idx, err); +@@ -792,33 +792,33 @@ ice_clear_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx) + } + + /** +- * ice_ptp_reset_ts_memory_quad_e822 - Clear all timestamps from the quad block ++ * ice_ptp_reset_ts_memory_quad_e82x - Clear all timestamps from the quad block + * @hw: pointer to the HW struct + * @quad: the quad to read from + * + * Clear all timestamps from the PHY quad block that is shared between the + * internal PHYs on the E822 devices. + */ +-void ice_ptp_reset_ts_memory_quad_e822(struct ice_hw *hw, u8 quad) ++void ice_ptp_reset_ts_memory_quad_e82x(struct ice_hw *hw, u8 quad) + { +- ice_write_quad_reg_e822(hw, quad, Q_REG_TS_CTRL, Q_REG_TS_CTRL_M); +- ice_write_quad_reg_e822(hw, quad, Q_REG_TS_CTRL, ~(u32)Q_REG_TS_CTRL_M); ++ ice_write_quad_reg_e82x(hw, quad, Q_REG_TS_CTRL, Q_REG_TS_CTRL_M); ++ ice_write_quad_reg_e82x(hw, quad, Q_REG_TS_CTRL, ~(u32)Q_REG_TS_CTRL_M); + } + + /** +- * ice_ptp_reset_ts_memory_e822 - Clear all timestamps from all quad blocks ++ * ice_ptp_reset_ts_memory_e82x - Clear all timestamps from all quad blocks + * @hw: pointer to the HW struct + */ +-static void ice_ptp_reset_ts_memory_e822(struct ice_hw *hw) ++static void ice_ptp_reset_ts_memory_e82x(struct ice_hw *hw) + { + unsigned int quad; + + for (quad = 0; quad < ICE_MAX_QUAD; quad++) +- ice_ptp_reset_ts_memory_quad_e822(hw, quad); ++ ice_ptp_reset_ts_memory_quad_e82x(hw, quad); + } + + /** +- * ice_read_cgu_reg_e822 - Read a CGU register ++ * ice_read_cgu_reg_e82x - Read a CGU register + * @hw: pointer to the HW struct + * @addr: Register address to read + * @val: storage for register value read +@@ -827,7 +827,7 @@ static void ice_ptp_reset_ts_memory_e822(struct ice_hw *hw) + * applicable to E822 devices. + */ + static int +-ice_read_cgu_reg_e822(struct ice_hw *hw, u32 addr, u32 *val) ++ice_read_cgu_reg_e82x(struct ice_hw *hw, u32 addr, u32 *val) + { + struct ice_sbq_msg_input cgu_msg; + int err; +@@ -850,7 +850,7 @@ ice_read_cgu_reg_e822(struct ice_hw *hw, u32 addr, u32 *val) + } + + /** +- * ice_write_cgu_reg_e822 - Write a CGU register ++ * ice_write_cgu_reg_e82x - Write a CGU register + * @hw: pointer to the HW struct + * @addr: Register address to write + * @val: value to write into the register +@@ -859,7 +859,7 @@ ice_read_cgu_reg_e822(struct ice_hw *hw, u32 addr, u32 *val) + * applicable to E822 devices. + */ + static int +-ice_write_cgu_reg_e822(struct ice_hw *hw, u32 addr, u32 val) ++ice_write_cgu_reg_e82x(struct ice_hw *hw, u32 addr, u32 val) + { + struct ice_sbq_msg_input cgu_msg; + int err; +@@ -925,7 +925,7 @@ static const char *ice_clk_src_str(u8 clk_src) + } + + /** +- * ice_cfg_cgu_pll_e822 - Configure the Clock Generation Unit ++ * ice_cfg_cgu_pll_e82x - Configure the Clock Generation Unit + * @hw: pointer to the HW struct + * @clk_freq: Clock frequency to program + * @clk_src: Clock source to select (TIME_REF, or TCX0) +@@ -934,7 +934,7 @@ static const char *ice_clk_src_str(u8 clk_src) + * time reference, enabling the PLL which drives the PTP hardware clock. + */ + static int +-ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, ++ice_cfg_cgu_pll_e82x(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + enum ice_clk_src clk_src) + { + union tspll_ro_bwm_lf bwm_lf; +@@ -963,15 +963,15 @@ ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + return -EINVAL; + } + +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD9, &dw9.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD9, &dw9.val); + if (err) + return err; + +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD24, &dw24.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD24, &dw24.val); + if (err) + return err; + +- err = ice_read_cgu_reg_e822(hw, TSPLL_RO_BWM_LF, &bwm_lf.val); ++ err = ice_read_cgu_reg_e82x(hw, TSPLL_RO_BWM_LF, &bwm_lf.val); + if (err) + return err; + +@@ -986,43 +986,43 @@ ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + if (dw24.field.ts_pll_enable) { + dw24.field.ts_pll_enable = 0; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD24, dw24.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.val); + if (err) + return err; + } + + /* Set the frequency */ + dw9.field.time_ref_freq_sel = clk_freq; +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD9, dw9.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD9, dw9.val); + if (err) + return err; + + /* Configure the TS PLL feedback divisor */ +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD19, &dw19.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD19, &dw19.val); + if (err) + return err; + + dw19.field.tspll_fbdiv_intgr = e822_cgu_params[clk_freq].feedback_div; + dw19.field.tspll_ndivratio = 1; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD19, dw19.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD19, dw19.val); + if (err) + return err; + + /* Configure the TS PLL post divisor */ +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD22, &dw22.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD22, &dw22.val); + if (err) + return err; + + dw22.field.time1588clk_div = e822_cgu_params[clk_freq].post_pll_div; + dw22.field.time1588clk_sel_div2 = 0; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD22, dw22.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD22, dw22.val); + if (err) + return err; + + /* Configure the TS PLL pre divisor and clock source */ +- err = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD24, &dw24.val); ++ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD24, &dw24.val); + if (err) + return err; + +@@ -1030,21 +1030,21 @@ ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + dw24.field.tspll_fbdiv_frac = e822_cgu_params[clk_freq].frac_n_div; + dw24.field.time_ref_sel = clk_src; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD24, dw24.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.val); + if (err) + return err; + + /* Finally, enable the PLL */ + dw24.field.ts_pll_enable = 1; + +- err = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD24, dw24.val); ++ err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.val); + if (err) + return err; + + /* Wait to verify if the PLL locks */ + usleep_range(1000, 5000); + +- err = ice_read_cgu_reg_e822(hw, TSPLL_RO_BWM_LF, &bwm_lf.val); ++ err = ice_read_cgu_reg_e82x(hw, TSPLL_RO_BWM_LF, &bwm_lf.val); + if (err) + return err; + +@@ -1064,18 +1064,18 @@ ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq, + } + + /** +- * ice_init_cgu_e822 - Initialize CGU with settings from firmware ++ * ice_init_cgu_e82x - Initialize CGU with settings from firmware + * @hw: pointer to the HW structure + * + * Initialize the Clock Generation Unit of the E822 device. + */ +-static int ice_init_cgu_e822(struct ice_hw *hw) ++static int ice_init_cgu_e82x(struct ice_hw *hw) + { + struct ice_ts_func_info *ts_info = &hw->func_caps.ts_func_info; + union tspll_cntr_bist_settings cntr_bist; + int err; + +- err = ice_read_cgu_reg_e822(hw, TSPLL_CNTR_BIST_SETTINGS, ++ err = ice_read_cgu_reg_e82x(hw, TSPLL_CNTR_BIST_SETTINGS, + &cntr_bist.val); + if (err) + return err; +@@ -1084,7 +1084,7 @@ static int ice_init_cgu_e822(struct ice_hw *hw) + cntr_bist.field.i_plllock_sel_0 = 0; + cntr_bist.field.i_plllock_sel_1 = 0; + +- err = ice_write_cgu_reg_e822(hw, TSPLL_CNTR_BIST_SETTINGS, ++ err = ice_write_cgu_reg_e82x(hw, TSPLL_CNTR_BIST_SETTINGS, + cntr_bist.val); + if (err) + return err; +@@ -1092,7 +1092,7 @@ static int ice_init_cgu_e822(struct ice_hw *hw) + /* Configure the CGU PLL using the parameters from the function + * capabilities. + */ +- err = ice_cfg_cgu_pll_e822(hw, ts_info->time_ref, ++ err = ice_cfg_cgu_pll_e82x(hw, ts_info->time_ref, + (enum ice_clk_src)ts_info->clk_src); + if (err) + return err; +@@ -1113,7 +1113,7 @@ static int ice_ptp_set_vernier_wl(struct ice_hw *hw) + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + int err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_WL, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_WL, + PTP_VERNIER_WL); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to set vernier window length for port %u, err %d\n", +@@ -1126,12 +1126,12 @@ static int ice_ptp_set_vernier_wl(struct ice_hw *hw) + } + + /** +- * ice_ptp_init_phc_e822 - Perform E822 specific PHC initialization ++ * ice_ptp_init_phc_e82x - Perform E822 specific PHC initialization + * @hw: pointer to HW struct + * + * Perform PHC initialization steps specific to E822 devices. + */ +-static int ice_ptp_init_phc_e822(struct ice_hw *hw) ++static int ice_ptp_init_phc_e82x(struct ice_hw *hw) + { + int err; + u32 regval; +@@ -1145,7 +1145,7 @@ static int ice_ptp_init_phc_e822(struct ice_hw *hw) + wr32(hw, PF_SB_REM_DEV_CTL, regval); + + /* Initialize the Clock Generation Unit */ +- err = ice_init_cgu_e822(hw); ++ err = ice_init_cgu_e82x(hw); + if (err) + return err; + +@@ -1154,7 +1154,7 @@ static int ice_ptp_init_phc_e822(struct ice_hw *hw) + } + + /** +- * ice_ptp_prep_phy_time_e822 - Prepare PHY port with initial time ++ * ice_ptp_prep_phy_time_e82x - Prepare PHY port with initial time + * @hw: pointer to the HW struct + * @time: Time to initialize the PHY port clocks to + * +@@ -1164,7 +1164,7 @@ static int ice_ptp_init_phc_e822(struct ice_hw *hw) + * units of nominal nanoseconds. + */ + static int +-ice_ptp_prep_phy_time_e822(struct ice_hw *hw, u32 time) ++ice_ptp_prep_phy_time_e82x(struct ice_hw *hw, u32 time) + { + u64 phy_time; + u8 port; +@@ -1177,14 +1177,14 @@ ice_ptp_prep_phy_time_e822(struct ice_hw *hw, u32 time) + + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + /* Tx case */ +- err = ice_write_64b_phy_reg_e822(hw, port, ++ err = ice_write_64b_phy_reg_e82x(hw, port, + P_REG_TX_TIMER_INC_PRE_L, + phy_time); + if (err) + goto exit_err; + + /* Rx case */ +- err = ice_write_64b_phy_reg_e822(hw, port, ++ err = ice_write_64b_phy_reg_e82x(hw, port, + P_REG_RX_TIMER_INC_PRE_L, + phy_time); + if (err) +@@ -1201,7 +1201,7 @@ ice_ptp_prep_phy_time_e822(struct ice_hw *hw, u32 time) + } + + /** +- * ice_ptp_prep_port_adj_e822 - Prepare a single port for time adjust ++ * ice_ptp_prep_port_adj_e82x - Prepare a single port for time adjust + * @hw: pointer to HW struct + * @port: Port number to be programmed + * @time: time in cycles to adjust the port Tx and Rx clocks +@@ -1216,7 +1216,7 @@ ice_ptp_prep_phy_time_e822(struct ice_hw *hw, u32 time) + * Negative adjustments are supported using 2s complement arithmetic. + */ + static int +-ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) ++ice_ptp_prep_port_adj_e82x(struct ice_hw *hw, u8 port, s64 time) + { + u32 l_time, u_time; + int err; +@@ -1225,23 +1225,23 @@ ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) + u_time = upper_32_bits(time); + + /* Tx case */ +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_TIMER_INC_PRE_L, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_TIMER_INC_PRE_L, + l_time); + if (err) + goto exit_err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_TIMER_INC_PRE_U, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_TIMER_INC_PRE_U, + u_time); + if (err) + goto exit_err; + + /* Rx case */ +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_TIMER_INC_PRE_L, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_TIMER_INC_PRE_L, + l_time); + if (err) + goto exit_err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_TIMER_INC_PRE_U, ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_TIMER_INC_PRE_U, + u_time); + if (err) + goto exit_err; +@@ -1255,7 +1255,7 @@ ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) + } + + /** +- * ice_ptp_prep_phy_adj_e822 - Prep PHY ports for a time adjustment ++ * ice_ptp_prep_phy_adj_e82x - Prep PHY ports for a time adjustment + * @hw: pointer to HW struct + * @adj: adjustment in nanoseconds + * +@@ -1264,7 +1264,7 @@ ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) + * ADJ_TIME or ADJ_TIME_AT_TIME sync command. + */ + static int +-ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj) ++ice_ptp_prep_phy_adj_e82x(struct ice_hw *hw, s32 adj) + { + s64 cycles; + u8 port; +@@ -1281,7 +1281,7 @@ ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj) + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + int err; + +- err = ice_ptp_prep_port_adj_e822(hw, port, cycles); ++ err = ice_ptp_prep_port_adj_e82x(hw, port, cycles); + if (err) + return err; + } +@@ -1290,7 +1290,7 @@ ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj) + } + + /** +- * ice_ptp_prep_phy_incval_e822 - Prepare PHY ports for time adjustment ++ * ice_ptp_prep_phy_incval_e82x - Prepare PHY ports for time adjustment + * @hw: pointer to HW struct + * @incval: new increment value to prepare + * +@@ -1299,13 +1299,13 @@ ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj) + * issuing an INIT_INCVAL command. + */ + static int +-ice_ptp_prep_phy_incval_e822(struct ice_hw *hw, u64 incval) ++ice_ptp_prep_phy_incval_e82x(struct ice_hw *hw, u64 incval) + { + int err; + u8 port; + + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_TIMETUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_TIMETUS_L, + incval); + if (err) + goto exit_err; +@@ -1337,7 +1337,7 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) + int err; + + /* Tx case */ +- err = ice_read_64b_phy_reg_e822(hw, port, P_REG_TX_CAPTURE_L, tx_ts); ++ err = ice_read_64b_phy_reg_e82x(hw, port, P_REG_TX_CAPTURE_L, tx_ts); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read REG_TX_CAPTURE, err %d\n", + err); +@@ -1348,7 +1348,7 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) + (unsigned long long)*tx_ts); + + /* Rx case */ +- err = ice_read_64b_phy_reg_e822(hw, port, P_REG_RX_CAPTURE_L, rx_ts); ++ err = ice_read_64b_phy_reg_e82x(hw, port, P_REG_RX_CAPTURE_L, rx_ts); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_CAPTURE, err %d\n", + err); +@@ -1362,7 +1362,7 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) + } + + /** +- * ice_ptp_write_port_cmd_e822 - Prepare a single PHY port for a timer command ++ * ice_ptp_write_port_cmd_e82x - Prepare a single PHY port for a timer command + * @hw: pointer to HW struct + * @port: Port to which cmd has to be sent + * @cmd: Command to be sent to the port +@@ -1372,8 +1372,8 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) + * Do not use this function directly. If you want to configure exactly one + * port, use ice_ptp_one_port_cmd() instead. + */ +-static int +-ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) ++static int ice_ptp_write_port_cmd_e82x(struct ice_hw *hw, u8 port, ++ enum ice_ptp_tmr_cmd cmd) + { + u32 cmd_val, val; + u8 tmr_idx; +@@ -1403,7 +1403,7 @@ ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd + + /* Tx case */ + /* Read, modify, write */ +- err = ice_read_phy_reg_e822(hw, port, P_REG_TX_TMR_CMD, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_TX_TMR_CMD, &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_TMR_CMD, err %d\n", + err); +@@ -1414,7 +1414,7 @@ ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd + val &= ~TS_CMD_MASK; + val |= cmd_val; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_TMR_CMD, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_TMR_CMD, val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write back TX_TMR_CMD, err %d\n", + err); +@@ -1423,7 +1423,7 @@ ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd + + /* Rx case */ + /* Read, modify, write */ +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_TMR_CMD, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_TMR_CMD, &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_TMR_CMD, err %d\n", + err); +@@ -1434,7 +1434,7 @@ ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd + val &= ~TS_CMD_MASK; + val |= cmd_val; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_TMR_CMD, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_TMR_CMD, val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write back RX_TMR_CMD, err %d\n", + err); +@@ -1469,7 +1469,7 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + else + cmd = ICE_PTP_NOP; + +- err = ice_ptp_write_port_cmd_e822(hw, port, cmd); ++ err = ice_ptp_write_port_cmd_e82x(hw, port, cmd); + if (err) + return err; + } +@@ -1478,7 +1478,7 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + } + + /** +- * ice_ptp_port_cmd_e822 - Prepare all ports for a timer command ++ * ice_ptp_port_cmd_e82x - Prepare all ports for a timer command + * @hw: pointer to the HW struct + * @cmd: timer command to prepare + * +@@ -1486,14 +1486,14 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + * command. + */ + static int +-ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) ++ice_ptp_port_cmd_e82x(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + { + u8 port; + + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + int err; + +- err = ice_ptp_write_port_cmd_e822(hw, port, cmd); ++ err = ice_ptp_write_port_cmd_e82x(hw, port, cmd); + if (err) + return err; + } +@@ -1509,7 +1509,7 @@ ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + */ + + /** +- * ice_phy_get_speed_and_fec_e822 - Get link speed and FEC based on serdes mode ++ * ice_phy_get_speed_and_fec_e82x - Get link speed and FEC based on serdes mode + * @hw: pointer to HW struct + * @port: the port to read from + * @link_out: if non-NULL, holds link speed on success +@@ -1519,7 +1519,7 @@ ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + * algorithm. + */ + static int +-ice_phy_get_speed_and_fec_e822(struct ice_hw *hw, u8 port, ++ice_phy_get_speed_and_fec_e82x(struct ice_hw *hw, u8 port, + enum ice_ptp_link_spd *link_out, + enum ice_ptp_fec_mode *fec_out) + { +@@ -1528,7 +1528,7 @@ ice_phy_get_speed_and_fec_e822(struct ice_hw *hw, u8 port, + u32 serdes; + int err; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_LINK_SPEED, &serdes); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_LINK_SPEED, &serdes); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read serdes info\n"); + return err; +@@ -1585,18 +1585,18 @@ ice_phy_get_speed_and_fec_e822(struct ice_hw *hw, u8 port, + } + + /** +- * ice_phy_cfg_lane_e822 - Configure PHY quad for single/multi-lane timestamp ++ * ice_phy_cfg_lane_e82x - Configure PHY quad for single/multi-lane timestamp + * @hw: pointer to HW struct + * @port: to configure the quad for + */ +-static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) ++static void ice_phy_cfg_lane_e82x(struct ice_hw *hw, u8 port) + { + enum ice_ptp_link_spd link_spd; + int err; + u32 val; + u8 quad; + +- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, NULL); ++ err = ice_phy_get_speed_and_fec_e82x(hw, port, &link_spd, NULL); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to get PHY link speed, err %d\n", + err); +@@ -1605,7 +1605,7 @@ static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) + + quad = port / ICE_PORTS_PER_QUAD; + +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, &val); ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_MEM_GLB_CFG, err %d\n", + err); +@@ -1617,7 +1617,7 @@ static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) + else + val |= Q_REG_TX_MEM_GBL_CFG_LANE_TYPE_M; + +- err = ice_write_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, val); ++ err = ice_write_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write back TX_MEM_GBL_CFG, err %d\n", + err); +@@ -1626,7 +1626,7 @@ static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_phy_cfg_uix_e822 - Configure Serdes UI to TU conversion for E822 ++ * ice_phy_cfg_uix_e82x - Configure Serdes UI to TU conversion for E822 + * @hw: pointer to the HW structure + * @port: the port to configure + * +@@ -1671,12 +1671,12 @@ static void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port) + * a divide by 390,625,000. This does lose some precision, but avoids + * miscalculation due to arithmetic overflow. + */ +-static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) ++static int ice_phy_cfg_uix_e82x(struct ice_hw *hw, u8 port) + { + u64 cur_freq, clk_incval, tu_per_sec, uix; + int err; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per second divided by 256 */ +@@ -1688,7 +1688,7 @@ static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) + /* Program the 10Gb/40Gb conversion ratio */ + uix = div_u64(tu_per_sec * LINE_UI_10G_40G, 390625000); + +- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_UIX66_10G_40G_L, ++ err = ice_write_64b_phy_reg_e82x(hw, port, P_REG_UIX66_10G_40G_L, + uix); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write UIX66_10G_40G, err %d\n", +@@ -1699,7 +1699,7 @@ static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) + /* Program the 25Gb/100Gb conversion ratio */ + uix = div_u64(tu_per_sec * LINE_UI_25G_100G, 390625000); + +- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_UIX66_25G_100G_L, ++ err = ice_write_64b_phy_reg_e82x(hw, port, P_REG_UIX66_25G_100G_L, + uix); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to write UIX66_25G_100G, err %d\n", +@@ -1711,7 +1711,7 @@ static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_phy_cfg_parpcs_e822 - Configure TUs per PAR/PCS clock cycle ++ * ice_phy_cfg_parpcs_e82x - Configure TUs per PAR/PCS clock cycle + * @hw: pointer to the HW struct + * @port: port to configure + * +@@ -1753,18 +1753,18 @@ static int ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port) + * frequency is ~29 bits, so multiplying them together should fit within the + * 64 bit arithmetic. + */ +-static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) ++static int ice_phy_cfg_parpcs_e82x(struct ice_hw *hw, u8 port) + { + u64 cur_freq, clk_incval, tu_per_sec, phy_tus; + enum ice_ptp_link_spd link_spd; + enum ice_ptp_fec_mode fec_mode; + int err; + +- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); ++ err = ice_phy_get_speed_and_fec_e82x(hw, port, &link_spd, &fec_mode); + if (err) + return err; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per cycle of the PHC clock */ +@@ -1784,7 +1784,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_PAR_TX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_PAR_TX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1796,7 +1796,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_PAR_RX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_PAR_RX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1808,7 +1808,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_PCS_TX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_PCS_TX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1820,7 +1820,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_PCS_RX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_PCS_RX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1832,7 +1832,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PAR_TX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_DESK_PAR_TX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1844,7 +1844,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PAR_RX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_DESK_PAR_RX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1856,7 +1856,7 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PCS_TX_TUS_L, ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_DESK_PCS_TX_TUS_L, + phy_tus); + if (err) + return err; +@@ -1868,23 +1868,23 @@ static int ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port) + else + phy_tus = 0; + +- return ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PCS_RX_TUS_L, ++ return ice_write_40b_phy_reg_e82x(hw, port, P_REG_DESK_PCS_RX_TUS_L, + phy_tus); + } + + /** +- * ice_calc_fixed_tx_offset_e822 - Calculated Fixed Tx offset for a port ++ * ice_calc_fixed_tx_offset_e82x - Calculated Fixed Tx offset for a port + * @hw: pointer to the HW struct + * @link_spd: the Link speed to calculate for + * + * Calculate the fixed offset due to known static latency data. + */ + static u64 +-ice_calc_fixed_tx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) ++ice_calc_fixed_tx_offset_e82x(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + { + u64 cur_freq, clk_incval, tu_per_sec, fixed_offset; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per second */ +@@ -1904,7 +1904,7 @@ ice_calc_fixed_tx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + } + + /** +- * ice_phy_cfg_tx_offset_e822 - Configure total Tx timestamp offset ++ * ice_phy_cfg_tx_offset_e82x - Configure total Tx timestamp offset + * @hw: pointer to the HW struct + * @port: the PHY port to configure + * +@@ -1926,7 +1926,7 @@ ice_calc_fixed_tx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + * Returns zero on success, -EBUSY if the hardware vernier offset + * calibration has not completed, or another error code on failure. + */ +-int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) ++int ice_phy_cfg_tx_offset_e82x(struct ice_hw *hw, u8 port) + { + enum ice_ptp_link_spd link_spd; + enum ice_ptp_fec_mode fec_mode; +@@ -1935,7 +1935,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + u32 reg; + + /* Nothing to do if we've already programmed the offset */ +- err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OR, ®); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_TX_OR, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OR for port %u, err %d\n", + port, err); +@@ -1945,7 +1945,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + if (reg) + return 0; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OV_STATUS, ®); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_TX_OV_STATUS, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OV_STATUS for port %u, err %d\n", + port, err); +@@ -1955,11 +1955,11 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + if (!(reg & P_REG_TX_OV_STATUS_OV_M)) + return -EBUSY; + +- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); ++ err = ice_phy_get_speed_and_fec_e82x(hw, port, &link_spd, &fec_mode); + if (err) + return err; + +- total_offset = ice_calc_fixed_tx_offset_e822(hw, link_spd); ++ total_offset = ice_calc_fixed_tx_offset_e82x(hw, link_spd); + + /* Read the first Vernier offset from the PHY register and add it to + * the total offset. +@@ -1970,7 +1970,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + link_spd == ICE_PTP_LNK_SPD_25G_RS || + link_spd == ICE_PTP_LNK_SPD_40G || + link_spd == ICE_PTP_LNK_SPD_50G) { +- err = ice_read_64b_phy_reg_e822(hw, port, ++ err = ice_read_64b_phy_reg_e82x(hw, port, + P_REG_PAR_PCS_TX_OFFSET_L, + &val); + if (err) +@@ -1985,7 +1985,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + */ + if (link_spd == ICE_PTP_LNK_SPD_50G_RS || + link_spd == ICE_PTP_LNK_SPD_100G_RS) { +- err = ice_read_64b_phy_reg_e822(hw, port, ++ err = ice_read_64b_phy_reg_e82x(hw, port, + P_REG_PAR_TX_TIME_L, + &val); + if (err) +@@ -1998,12 +1998,12 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + * PHY and indicate that the Tx offset is ready. After this, + * timestamps will be enabled. + */ +- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_TX_OFFSET_L, ++ err = ice_write_64b_phy_reg_e82x(hw, port, P_REG_TOTAL_TX_OFFSET_L, + total_offset); + if (err) + return err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_OR, 1); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_OR, 1); + if (err) + return err; + +@@ -2014,7 +2014,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_phy_calc_pmd_adj_e822 - Calculate PMD adjustment for Rx ++ * ice_phy_calc_pmd_adj_e82x - Calculate PMD adjustment for Rx + * @hw: pointer to the HW struct + * @port: the PHY port to adjust for + * @link_spd: the current link speed of the PHY +@@ -2026,7 +2026,7 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port) + * various delays caused when receiving a packet. + */ + static int +-ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, ++ice_phy_calc_pmd_adj_e82x(struct ice_hw *hw, u8 port, + enum ice_ptp_link_spd link_spd, + enum ice_ptp_fec_mode fec_mode, u64 *pmd_adj) + { +@@ -2035,7 +2035,7 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + u32 val; + int err; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_PMD_ALIGNMENT, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_PMD_ALIGNMENT, &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read PMD alignment, err %d\n", + err); +@@ -2044,7 +2044,7 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + + pmd_align = (u8)val; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per second */ +@@ -2123,7 +2123,7 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + u64 cycle_adj; + u8 rx_cycle; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_40_TO_160_CNT, ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_40_TO_160_CNT, + &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read 25G-RS Rx cycle count, err %d\n", +@@ -2145,7 +2145,7 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + u64 cycle_adj; + u8 rx_cycle; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_80_TO_160_CNT, ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_80_TO_160_CNT, + &val); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read 50G-RS Rx cycle count, err %d\n", +@@ -2172,18 +2172,18 @@ ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port, + } + + /** +- * ice_calc_fixed_rx_offset_e822 - Calculated the fixed Rx offset for a port ++ * ice_calc_fixed_rx_offset_e82x - Calculated the fixed Rx offset for a port + * @hw: pointer to HW struct + * @link_spd: The Link speed to calculate for + * + * Determine the fixed Rx latency for a given link speed. + */ + static u64 +-ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) ++ice_calc_fixed_rx_offset_e82x(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + { + u64 cur_freq, clk_incval, tu_per_sec, fixed_offset; + +- cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw)); ++ cur_freq = ice_e82x_pll_freq(ice_e82x_time_ref(hw)); + clk_incval = ice_ptp_read_src_incval(hw); + + /* Calculate TUs per second */ +@@ -2203,7 +2203,7 @@ ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + } + + /** +- * ice_phy_cfg_rx_offset_e822 - Configure total Rx timestamp offset ++ * ice_phy_cfg_rx_offset_e82x - Configure total Rx timestamp offset + * @hw: pointer to the HW struct + * @port: the PHY port to configure + * +@@ -2229,7 +2229,7 @@ ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd) + * Returns zero on success, -EBUSY if the hardware vernier offset + * calibration has not completed, or another error code on failure. + */ +-int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) ++int ice_phy_cfg_rx_offset_e82x(struct ice_hw *hw, u8 port) + { + enum ice_ptp_link_spd link_spd; + enum ice_ptp_fec_mode fec_mode; +@@ -2238,7 +2238,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + u32 reg; + + /* Nothing to do if we've already programmed the offset */ +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OR, ®); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_OR, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OR for port %u, err %d\n", + port, err); +@@ -2248,7 +2248,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + if (reg) + return 0; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OV_STATUS, ®); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_RX_OV_STATUS, ®); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OV_STATUS for port %u, err %d\n", + port, err); +@@ -2258,16 +2258,16 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + if (!(reg & P_REG_RX_OV_STATUS_OV_M)) + return -EBUSY; + +- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode); ++ err = ice_phy_get_speed_and_fec_e82x(hw, port, &link_spd, &fec_mode); + if (err) + return err; + +- total_offset = ice_calc_fixed_rx_offset_e822(hw, link_spd); ++ total_offset = ice_calc_fixed_rx_offset_e82x(hw, link_spd); + + /* Read the first Vernier offset from the PHY register and add it to + * the total offset. + */ +- err = ice_read_64b_phy_reg_e822(hw, port, ++ err = ice_read_64b_phy_reg_e82x(hw, port, + P_REG_PAR_PCS_RX_OFFSET_L, + &val); + if (err) +@@ -2282,7 +2282,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + link_spd == ICE_PTP_LNK_SPD_50G || + link_spd == ICE_PTP_LNK_SPD_50G_RS || + link_spd == ICE_PTP_LNK_SPD_100G_RS) { +- err = ice_read_64b_phy_reg_e822(hw, port, ++ err = ice_read_64b_phy_reg_e82x(hw, port, + P_REG_PAR_RX_TIME_L, + &val); + if (err) +@@ -2292,7 +2292,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + } + + /* In addition, Rx must account for the PMD alignment */ +- err = ice_phy_calc_pmd_adj_e822(hw, port, link_spd, fec_mode, &pmd); ++ err = ice_phy_calc_pmd_adj_e82x(hw, port, link_spd, fec_mode, &pmd); + if (err) + return err; + +@@ -2308,12 +2308,12 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + * PHY and indicate that the Rx offset is ready. After this, + * timestamps will be enabled. + */ +- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_RX_OFFSET_L, ++ err = ice_write_64b_phy_reg_e82x(hw, port, P_REG_TOTAL_RX_OFFSET_L, + total_offset); + if (err) + return err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_OR, 1); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_OR, 1); + if (err) + return err; + +@@ -2324,7 +2324,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_read_phy_and_phc_time_e822 - Simultaneously capture PHC and PHY time ++ * ice_read_phy_and_phc_time_e82x - Simultaneously capture PHC and PHY time + * @hw: pointer to the HW struct + * @port: the PHY port to read + * @phy_time: on return, the 64bit PHY timer value +@@ -2334,7 +2334,7 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port) + * timer values. + */ + static int +-ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time, ++ice_read_phy_and_phc_time_e82x(struct ice_hw *hw, u8 port, u64 *phy_time, + u64 *phc_time) + { + u64 tx_time, rx_time; +@@ -2381,7 +2381,7 @@ ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time, + } + + /** +- * ice_sync_phy_timer_e822 - Synchronize the PHY timer with PHC timer ++ * ice_sync_phy_timer_e82x - Synchronize the PHY timer with PHC timer + * @hw: pointer to the HW struct + * @port: the PHY port to synchronize + * +@@ -2391,7 +2391,7 @@ ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time, + * calculate an appropriate 2s complement addition to add to the PHY timer in + * order to ensure it reads the same value as the primary PHC timer. + */ +-static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) ++static int ice_sync_phy_timer_e82x(struct ice_hw *hw, u8 port) + { + u64 phc_time, phy_time, difference; + int err; +@@ -2401,7 +2401,7 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + return -EBUSY; + } + +- err = ice_read_phy_and_phc_time_e822(hw, port, &phy_time, &phc_time); ++ err = ice_read_phy_and_phc_time_e82x(hw, port, &phy_time, &phc_time); + if (err) + goto err_unlock; + +@@ -2415,7 +2415,7 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + */ + difference = phc_time - phy_time; + +- err = ice_ptp_prep_port_adj_e822(hw, port, (s64)difference); ++ err = ice_ptp_prep_port_adj_e82x(hw, port, (s64)difference); + if (err) + goto err_unlock; + +@@ -2432,7 +2432,7 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + /* Re-capture the timer values to flush the command registers and + * verify that the time was properly adjusted. + */ +- err = ice_read_phy_and_phc_time_e822(hw, port, &phy_time, &phc_time); ++ err = ice_read_phy_and_phc_time_e82x(hw, port, &phy_time, &phc_time); + if (err) + goto err_unlock; + +@@ -2451,7 +2451,7 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_stop_phy_timer_e822 - Stop the PHY clock timer ++ * ice_stop_phy_timer_e82x - Stop the PHY clock timer + * @hw: pointer to the HW struct + * @port: the PHY port to stop + * @soft_reset: if true, hold the SOFT_RESET bit of P_REG_PS +@@ -2461,36 +2461,36 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) + * initialized or when link speed changes. + */ + int +-ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset) ++ice_stop_phy_timer_e82x(struct ice_hw *hw, u8 port, bool soft_reset) + { + int err; + u32 val; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_OR, 0); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_TX_OR, 0); + if (err) + return err; + +- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_OR, 0); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_RX_OR, 0); + if (err) + return err; + +- err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_PS, &val); + if (err) + return err; + + val &= ~P_REG_PS_START_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + val &= ~P_REG_PS_ENA_CLK_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + if (soft_reset) { + val |= P_REG_PS_SFT_RESET_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + } +@@ -2501,7 +2501,7 @@ ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset) + } + + /** +- * ice_start_phy_timer_e822 - Start the PHY clock timer ++ * ice_start_phy_timer_e82x - Start the PHY clock timer + * @hw: pointer to the HW struct + * @port: the PHY port to start + * +@@ -2511,7 +2511,7 @@ ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset) + * + * Hardware will take Vernier measurements on Tx or Rx of packets. + */ +-int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) ++int ice_start_phy_timer_e82x(struct ice_hw *hw, u8 port) + { + u32 lo, hi, val; + u64 incval; +@@ -2520,17 +2520,17 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + + tmr_idx = ice_get_ptp_src_clock_index(hw); + +- err = ice_stop_phy_timer_e822(hw, port, false); ++ err = ice_stop_phy_timer_e82x(hw, port, false); + if (err) + return err; + +- ice_phy_cfg_lane_e822(hw, port); ++ ice_phy_cfg_lane_e82x(hw, port); + +- err = ice_phy_cfg_uix_e822(hw, port); ++ err = ice_phy_cfg_uix_e82x(hw, port); + if (err) + return err; + +- err = ice_phy_cfg_parpcs_e822(hw, port); ++ err = ice_phy_cfg_parpcs_e82x(hw, port); + if (err) + return err; + +@@ -2538,7 +2538,7 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + hi = rd32(hw, GLTSYN_INCVAL_H(tmr_idx)); + incval = (u64)hi << 32 | lo; + +- err = ice_write_40b_phy_reg_e822(hw, port, P_REG_TIMETUS_L, incval); ++ err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_TIMETUS_L, incval); + if (err) + return err; + +@@ -2551,22 +2551,22 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + + ice_ptp_exec_tmr_cmd(hw); + +- err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val); ++ err = ice_read_phy_reg_e82x(hw, port, P_REG_PS, &val); + if (err) + return err; + + val |= P_REG_PS_SFT_RESET_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + val |= P_REG_PS_START_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + val &= ~P_REG_PS_SFT_RESET_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + +@@ -2577,18 +2577,18 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + ice_ptp_exec_tmr_cmd(hw); + + val |= P_REG_PS_ENA_CLK_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + val |= P_REG_PS_LOAD_OFFSET_M; +- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val); ++ err = ice_write_phy_reg_e82x(hw, port, P_REG_PS, val); + if (err) + return err; + + ice_ptp_exec_tmr_cmd(hw); + +- err = ice_sync_phy_timer_e822(hw, port); ++ err = ice_sync_phy_timer_e82x(hw, port); + if (err) + return err; + +@@ -2598,7 +2598,7 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + } + + /** +- * ice_get_phy_tx_tstamp_ready_e822 - Read Tx memory status register ++ * ice_get_phy_tx_tstamp_ready_e82x - Read Tx memory status register + * @hw: pointer to the HW struct + * @quad: the timestamp quad to read from + * @tstamp_ready: contents of the Tx memory status register +@@ -2608,19 +2608,19 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) + * ready to be captured from the PHY timestamp block. + */ + static int +-ice_get_phy_tx_tstamp_ready_e822(struct ice_hw *hw, u8 quad, u64 *tstamp_ready) ++ice_get_phy_tx_tstamp_ready_e82x(struct ice_hw *hw, u8 quad, u64 *tstamp_ready) + { + u32 hi, lo; + int err; + +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEMORY_STATUS_U, &hi); ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEMORY_STATUS_U, &hi); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_MEMORY_STATUS_U for quad %u, err %d\n", + quad, err); + return err; + } + +- err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEMORY_STATUS_L, &lo); ++ err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEMORY_STATUS_L, &lo); + if (err) { + ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_MEMORY_STATUS_L for quad %u, err %d\n", + quad, err); +@@ -3306,7 +3306,7 @@ void ice_ptp_init_phy_model(struct ice_hw *hw) + if (ice_is_e810(hw)) + hw->phy_model = ICE_PHY_E810; + else +- hw->phy_model = ICE_PHY_E822; ++ hw->phy_model = ICE_PHY_E82X; + } + + /** +@@ -3331,8 +3331,8 @@ static int ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + case ICE_PHY_E810: + err = ice_ptp_port_cmd_e810(hw, cmd); + break; +- case ICE_PHY_E822: +- err = ice_ptp_port_cmd_e822(hw, cmd); ++ case ICE_PHY_E82X: ++ err = ice_ptp_port_cmd_e82x(hw, cmd); + break; + default: + err = -EOPNOTSUPP; +@@ -3383,8 +3383,8 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time) + case ICE_PHY_E810: + err = ice_ptp_prep_phy_time_e810(hw, time & 0xFFFFFFFF); + break; +- case ICE_PHY_E822: +- err = ice_ptp_prep_phy_time_e822(hw, time & 0xFFFFFFFF); ++ case ICE_PHY_E82X: ++ err = ice_ptp_prep_phy_time_e82x(hw, time & 0xFFFFFFFF); + break; + default: + err = -EOPNOTSUPP; +@@ -3425,8 +3425,8 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval) + case ICE_PHY_E810: + err = ice_ptp_prep_phy_incval_e810(hw, incval); + break; +- case ICE_PHY_E822: +- err = ice_ptp_prep_phy_incval_e822(hw, incval); ++ case ICE_PHY_E82X: ++ err = ice_ptp_prep_phy_incval_e82x(hw, incval); + break; + default: + err = -EOPNOTSUPP; +@@ -3491,8 +3491,8 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj) + case ICE_PHY_E810: + err = ice_ptp_prep_phy_adj_e810(hw, adj); + break; +- case ICE_PHY_E822: +- err = ice_ptp_prep_phy_adj_e822(hw, adj); ++ case ICE_PHY_E82X: ++ err = ice_ptp_prep_phy_adj_e82x(hw, adj); + break; + default: + err = -EOPNOTSUPP; +@@ -3520,8 +3520,8 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp) + switch (hw->phy_model) { + case ICE_PHY_E810: + return ice_read_phy_tstamp_e810(hw, block, idx, tstamp); +- case ICE_PHY_E822: +- return ice_read_phy_tstamp_e822(hw, block, idx, tstamp); ++ case ICE_PHY_E82X: ++ return ice_read_phy_tstamp_e82x(hw, block, idx, tstamp); + default: + return -EOPNOTSUPP; + } +@@ -3548,8 +3548,8 @@ int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx) + switch (hw->phy_model) { + case ICE_PHY_E810: + return ice_clear_phy_tstamp_e810(hw, block, idx); +- case ICE_PHY_E822: +- return ice_clear_phy_tstamp_e822(hw, block, idx); ++ case ICE_PHY_E82X: ++ return ice_clear_phy_tstamp_e82x(hw, block, idx); + default: + return -EOPNOTSUPP; + } +@@ -3607,8 +3607,8 @@ int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx) + void ice_ptp_reset_ts_memory(struct ice_hw *hw) + { + switch (hw->phy_model) { +- case ICE_PHY_E822: +- ice_ptp_reset_ts_memory_e822(hw); ++ case ICE_PHY_E82X: ++ ice_ptp_reset_ts_memory_e82x(hw); + break; + case ICE_PHY_E810: + default: +@@ -3635,8 +3635,8 @@ int ice_ptp_init_phc(struct ice_hw *hw) + switch (hw->phy_model) { + case ICE_PHY_E810: + return ice_ptp_init_phc_e810(hw); +- case ICE_PHY_E822: +- return ice_ptp_init_phc_e822(hw); ++ case ICE_PHY_E82X: ++ return ice_ptp_init_phc_e82x(hw); + default: + return -EOPNOTSUPP; + } +@@ -3659,8 +3659,8 @@ int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready) + case ICE_PHY_E810: + return ice_get_phy_tx_tstamp_ready_e810(hw, block, + tstamp_ready); +- case ICE_PHY_E822: +- return ice_get_phy_tx_tstamp_ready_e822(hw, block, ++ case ICE_PHY_E82X: ++ return ice_get_phy_tx_tstamp_ready_e82x(hw, block, + tstamp_ready); + break; + default: +@@ -3941,7 +3941,7 @@ int ice_get_cgu_rclk_pin_info(struct ice_hw *hw, u8 *base_idx, u8 *pin_num) + case ICE_DEV_ID_E823C_QSFP: + case ICE_DEV_ID_E823C_SFP: + case ICE_DEV_ID_E823C_SGMII: +- *pin_num = ICE_E822_RCLK_PINS_NUM; ++ *pin_num = ICE_E82X_RCLK_PINS_NUM; + ret = 0; + if (hw->cgu_part_number == + ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032) +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +index 9dc30918f044..0cc285614c72 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +@@ -42,7 +42,7 @@ enum ice_ptp_fec_mode { + }; + + /** +- * struct ice_time_ref_info_e822 ++ * struct ice_time_ref_info_e82x + * @pll_freq: Frequency of PLL that drives timer ticks in Hz + * @nominal_incval: increment to generate nanoseconds in GLTSYN_TIME_L + * @pps_delay: propagation delay of the PPS output signal +@@ -50,14 +50,14 @@ enum ice_ptp_fec_mode { + * Characteristic information for the various TIME_REF sources possible in the + * E822 devices + */ +-struct ice_time_ref_info_e822 { ++struct ice_time_ref_info_e82x { + u64 pll_freq; + u64 nominal_incval; + u8 pps_delay; + }; + + /** +- * struct ice_vernier_info_e822 ++ * struct ice_vernier_info_e82x + * @tx_par_clk: Frequency used to calculate P_REG_PAR_TX_TUS + * @rx_par_clk: Frequency used to calculate P_REG_PAR_RX_TUS + * @tx_pcs_clk: Frequency used to calculate P_REG_PCS_TX_TUS +@@ -80,7 +80,7 @@ struct ice_time_ref_info_e822 { + * different link speeds, either the deskew marker for multi-lane link speeds + * or the Reed Solomon gearbox marker for RS-FEC. + */ +-struct ice_vernier_info_e822 { ++struct ice_vernier_info_e82x { + u32 tx_par_clk; + u32 rx_par_clk; + u32 tx_pcs_clk; +@@ -95,7 +95,7 @@ struct ice_vernier_info_e822 { + }; + + /** +- * struct ice_cgu_pll_params_e822 ++ * struct ice_cgu_pll_params_e82x + * @refclk_pre_div: Reference clock pre-divisor + * @feedback_div: Feedback divisor + * @frac_n_div: Fractional divisor +@@ -104,7 +104,7 @@ struct ice_vernier_info_e822 { + * Clock Generation Unit parameters used to program the PLL based on the + * selected TIME_REF frequency. + */ +-struct ice_cgu_pll_params_e822 { ++struct ice_cgu_pll_params_e82x { + u32 refclk_pre_div; + u32 feedback_div; + u32 frac_n_div; +@@ -124,7 +124,7 @@ enum ice_phy_rclk_pins { + }; + + #define ICE_E810_RCLK_PINS_NUM (ICE_RCLKB_PIN + 1) +-#define ICE_E822_RCLK_PINS_NUM (ICE_RCLKA_PIN + 1) ++#define ICE_E82X_RCLK_PINS_NUM (ICE_RCLKA_PIN + 1) + #define E810T_CGU_INPUT_C827(_phy, _pin) ((_phy) * ICE_E810_RCLK_PINS_NUM + \ + (_pin) + ZL_REF1P) + +@@ -183,16 +183,16 @@ struct ice_cgu_pin_desc { + }; + + extern const struct +-ice_cgu_pll_params_e822 e822_cgu_params[NUM_ICE_TIME_REF_FREQ]; ++ice_cgu_pll_params_e82x e822_cgu_params[NUM_ICE_TIME_REF_FREQ]; + + #define E810C_QSFP_C827_0_HANDLE 2 + #define E810C_QSFP_C827_1_HANDLE 3 + + /* Table of constants related to possible TIME_REF sources */ +-extern const struct ice_time_ref_info_e822 e822_time_ref[NUM_ICE_TIME_REF_FREQ]; ++extern const struct ice_time_ref_info_e82x e822_time_ref[NUM_ICE_TIME_REF_FREQ]; + + /* Table of constants for Vernier calibration on E822 */ +-extern const struct ice_vernier_info_e822 e822_vernier[NUM_ICE_PTP_LNK_SPD]; ++extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD]; + + /* Increment value to generate nanoseconds in the GLTSYN_TIME_L register for + * the E810 devices. Based off of a PLL with an 812.5 MHz frequency. +@@ -214,23 +214,23 @@ int ice_ptp_init_phc(struct ice_hw *hw); + int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready); + + /* E822 family functions */ +-int ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val); +-int ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val); +-void ice_ptp_reset_ts_memory_quad_e822(struct ice_hw *hw, u8 quad); ++int ice_read_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 *val); ++int ice_write_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 val); ++void ice_ptp_reset_ts_memory_quad_e82x(struct ice_hw *hw, u8 quad); + + /** +- * ice_e822_time_ref - Get the current TIME_REF from capabilities ++ * ice_e82x_time_ref - Get the current TIME_REF from capabilities + * @hw: pointer to the HW structure + * + * Returns the current TIME_REF from the capabilities structure. + */ +-static inline enum ice_time_ref_freq ice_e822_time_ref(struct ice_hw *hw) ++static inline enum ice_time_ref_freq ice_e82x_time_ref(struct ice_hw *hw) + { + return hw->func_caps.ts_func_info.time_ref; + } + + /** +- * ice_set_e822_time_ref - Set new TIME_REF ++ * ice_set_e82x_time_ref - Set new TIME_REF + * @hw: pointer to the HW structure + * @time_ref: new TIME_REF to set + * +@@ -238,31 +238,31 @@ static inline enum ice_time_ref_freq ice_e822_time_ref(struct ice_hw *hw) + * change, such as an update to the CGU registers. + */ + static inline void +-ice_set_e822_time_ref(struct ice_hw *hw, enum ice_time_ref_freq time_ref) ++ice_set_e82x_time_ref(struct ice_hw *hw, enum ice_time_ref_freq time_ref) + { + hw->func_caps.ts_func_info.time_ref = time_ref; + } + +-static inline u64 ice_e822_pll_freq(enum ice_time_ref_freq time_ref) ++static inline u64 ice_e82x_pll_freq(enum ice_time_ref_freq time_ref) + { + return e822_time_ref[time_ref].pll_freq; + } + +-static inline u64 ice_e822_nominal_incval(enum ice_time_ref_freq time_ref) ++static inline u64 ice_e82x_nominal_incval(enum ice_time_ref_freq time_ref) + { + return e822_time_ref[time_ref].nominal_incval; + } + +-static inline u64 ice_e822_pps_delay(enum ice_time_ref_freq time_ref) ++static inline u64 ice_e82x_pps_delay(enum ice_time_ref_freq time_ref) + { + return e822_time_ref[time_ref].pps_delay; + } + + /* E822 Vernier calibration functions */ +-int ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset); +-int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port); +-int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port); +-int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port); ++int ice_stop_phy_timer_e82x(struct ice_hw *hw, u8 port, bool soft_reset); ++int ice_start_phy_timer_e82x(struct ice_hw *hw, u8 port); ++int ice_phy_cfg_tx_offset_e82x(struct ice_hw *hw, u8 port); ++int ice_phy_cfg_rx_offset_e82x(struct ice_hw *hw, u8 port); + + /* E810 family functions */ + int ice_ptp_init_phy_e810(struct ice_hw *hw); +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index bb5d8b681bc2..f8b658386552 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -826,7 +826,7 @@ struct ice_mbx_data { + enum ice_phy_model { + ICE_PHY_UNSUP = -1, + ICE_PHY_E810 = 1, +- ICE_PHY_E822, ++ ICE_PHY_E82X, + }; + + /* Port hardware description */ +@@ -909,10 +909,9 @@ struct ice_hw { + /* INTRL granularity in 1 us */ + u8 intrl_gran; + +-#define ICE_PHY_PER_NAC_E822 1 + #define ICE_MAX_QUAD 2 +-#define ICE_QUADS_PER_PHY_E822 2 +-#define ICE_PORTS_PER_PHY_E822 8 ++#define ICE_QUADS_PER_PHY_E82X 2 ++#define ICE_PORTS_PER_PHY_E82X 8 + #define ICE_PORTS_PER_QUAD 4 + #define ICE_PORTS_PER_PHY_E810 4 + #define ICE_NUM_EXTERNAL_PORTS (ICE_MAX_QUAD * ICE_PORTS_PER_QUAD) +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0012-ice-Schedule-service-task-in-IRQ-top-half.patch b/kernel-std/debian/patches/ice-VDF/0012-ice-Schedule-service-task-in-IRQ-top-half.patch new file mode 100644 index 00000000..9b6a7417 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0012-ice-Schedule-service-task-in-IRQ-top-half.patch @@ -0,0 +1,104 @@ +From 3b37119a08ffe4be182ade746a6b1fe3bcf65921 Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 29 Nov 2023 13:40:22 +0100 +Subject: [PATCH 12/36] ice: Schedule service task in IRQ top half + +Schedule service task and EXTTS in the top half to avoid bottom half +scheduling if possible, which significantly reduces timestamping delay. + +Co-developed-by: Michal Michalik +Signed-off-by: Michal Michalik +Reviewed-by: Przemek Kitszel +Signed-off-by: Karol Kolacinski +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 00d50001444ef5c75c8ab476a6674708f3ff613b) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 1 - + drivers/net/ethernet/intel/ice/ice_main.c | 20 +++++++++++--------- + 2 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 54a98c4032b7..efe78d5e4da1 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -517,7 +517,6 @@ enum ice_pf_flags { + }; + + enum ice_misc_thread_tasks { +- ICE_MISC_THREAD_EXTTS_EVENT, + ICE_MISC_THREAD_TX_TSTAMP, + ICE_MISC_THREAD_NBITS /* must be last */ + }; +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index d2f3b4374d14..2acaa17a12bf 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3109,6 +3109,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf) + static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + { + struct ice_pf *pf = (struct ice_pf *)data; ++ irqreturn_t ret = IRQ_HANDLED; + struct ice_hw *hw = &pf->hw; + struct device *dev; + u32 oicr, ena_mask; +@@ -3190,8 +3191,10 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + if (oicr & PFINT_OICR_TSYN_TX_M) { + ena_mask &= ~PFINT_OICR_TSYN_TX_M; +- if (ice_ptp_pf_handles_tx_interrupt(pf)) ++ if (ice_ptp_pf_handles_tx_interrupt(pf)) { + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); ++ ret = IRQ_WAKE_THREAD; ++ } + } + + if (oicr & PFINT_OICR_TSYN_EVNT_M) { +@@ -3207,7 +3210,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + GLTSYN_STAT_EVENT1_M | + GLTSYN_STAT_EVENT2_M); + +- set_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread); ++ ice_ptp_extts_event(pf); + } + } + +@@ -3230,8 +3233,11 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + set_bit(ICE_PFR_REQ, pf->state); + } + } ++ ice_service_task_schedule(pf); ++ if (ret == IRQ_HANDLED) ++ ice_irq_dynamic_ena(hw, NULL, NULL); + +- return IRQ_WAKE_THREAD; ++ return ret; + } + + /** +@@ -3247,12 +3253,7 @@ static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) + hw = &pf->hw; + + if (ice_is_reset_in_progress(pf->state)) +- return IRQ_HANDLED; +- +- ice_service_task_schedule(pf); +- +- if (test_and_clear_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread)) +- ice_ptp_extts_event(pf); ++ goto skip_irq; + + if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) { + /* Process outstanding Tx timestamps. If there is more work, +@@ -3264,6 +3265,7 @@ static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) + } + } + ++skip_irq: + ice_irq_dynamic_ena(hw, NULL, NULL); + + return IRQ_HANDLED; +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0013-ice-Enable-SW-interrupt-from-FW-for-LL-TS.patch b/kernel-std/debian/patches/ice-VDF/0013-ice-Enable-SW-interrupt-from-FW-for-LL-TS.patch new file mode 100644 index 00000000..639642f0 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0013-ice-Enable-SW-interrupt-from-FW-for-LL-TS.patch @@ -0,0 +1,660 @@ +From c4ab92eb3ee89178a012702f2a98477d683fad31 Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Wed, 29 Nov 2023 13:40:23 +0100 +Subject: [PATCH 13/36] ice: Enable SW interrupt from FW for LL TS + +Introduce new capability - Low Latency Timestamping with Interrupt. +On supported devices, driver can request a single timestamp from FW +without polling the register afterwards. Instead, FW can issue +a dedicated interrupt when the timestamp was read from the PHY register +and its value is available to read from the register. +This eliminates the need of bottom half scheduling, which results in +minimal delay for timestamping. + +For this mode, allocate TS indices sequentially, so that timestamps are +always completed in FIFO manner. + +Co-developed-by: Yochai Hagvi +Signed-off-by: Yochai Hagvi +Reviewed-by: Przemek Kitszel +Signed-off-by: Karol Kolacinski +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 82e71b226e0ef770d7bc143701c8b4960b4eb3d5) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 2 + + drivers/net/ethernet/intel/ice/ice_common.c | 3 + + .../net/ethernet/intel/ice/ice_hw_autogen.h | 2 + + drivers/net/ethernet/intel/ice/ice_main.c | 120 +++++++++++-- + drivers/net/ethernet/intel/ice/ice_ptp.c | 163 ++++++++++++++++-- + drivers/net/ethernet/intel/ice/ice_ptp.h | 9 + + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 1 + + drivers/net/ethernet/intel/ice/ice_type.h | 2 + + 8 files changed, 274 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index efe78d5e4da1..ee42a504c2f4 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -594,6 +594,7 @@ struct ice_pf { + u32 hw_csum_rx_error; + u32 oicr_err_reg; + struct msi_map oicr_irq; /* Other interrupt cause MSIX vector */ ++ struct msi_map ll_ts_irq; /* LL_TS interrupt MSIX vector */ + u16 max_pf_txqs; /* Total Tx queues PF wide */ + u16 max_pf_rxqs; /* Total Rx queues PF wide */ + u16 num_lan_msix; /* Total MSIX vectors for base driver */ +@@ -618,6 +619,7 @@ struct ice_pf { + unsigned long tx_timeout_last_recovery; + u32 tx_timeout_recovery_level; + char int_name[ICE_INT_NAME_STR_LEN]; ++ char int_name_ll_ts[ICE_INT_NAME_STR_LEN]; + struct auxiliary_device *adev; + int aux_idx; + u32 sw_int_count; +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 7674267a2d90..acf6ac00f804 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -2624,6 +2624,7 @@ ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, + info->tmr1_ena = ((number & ICE_TS_TMR1_ENA_M) != 0); + + info->ts_ll_read = ((number & ICE_TS_LL_TX_TS_READ_M) != 0); ++ info->ts_ll_int_read = ((number & ICE_TS_LL_TX_TS_INT_READ_M) != 0); + + info->ena_ports = logical_id; + info->tmr_own_map = phys_id; +@@ -2644,6 +2645,8 @@ ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, + info->tmr1_ena); + ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_read = %u\n", + info->ts_ll_read); ++ ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_int_read = %u\n", ++ info->ts_ll_int_read); + ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 ena_ports = %u\n", + info->ena_ports); + ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr_own_map = %u\n", +diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +index 6756f3d51d14..fa730bca7f15 100644 +--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h ++++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +@@ -200,6 +200,8 @@ + #define GLINT_VECT2FUNC_PF_NUM_M ICE_M(0x7, 12) + #define GLINT_VECT2FUNC_IS_PF_S 16 + #define GLINT_VECT2FUNC_IS_PF_M BIT(16) ++#define PFINT_ALLOC 0x001D2600 ++#define PFINT_ALLOC_FIRST ICE_M(0x7FF, 0) + #define PFINT_FW_CTL 0x0016C800 + #define PFINT_FW_CTL_MSIX_INDX_M ICE_M(0x7FF, 0) + #define PFINT_FW_CTL_ITR_INDX_S 11 +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 2acaa17a12bf..9163a72368b3 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3071,6 +3071,7 @@ static int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp) + static void ice_ena_misc_vector(struct ice_pf *pf) + { + struct ice_hw *hw = &pf->hw; ++ u32 pf_intr_start_offset; + u32 val; + + /* Disable anti-spoof detection interrupt to prevent spurious event +@@ -3099,6 +3100,47 @@ static void ice_ena_misc_vector(struct ice_pf *pf) + /* SW_ITR_IDX = 0, but don't change INTENA */ + wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index), + GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); ++ ++ if (!pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) ++ return; ++ pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST; ++ wr32(hw, GLINT_DYN_CTL(pf->ll_ts_irq.index + pf_intr_start_offset), ++ GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); ++} ++ ++/** ++ * ice_ll_ts_intr - ll_ts interrupt handler ++ * @irq: interrupt number ++ * @data: pointer to a q_vector ++ */ ++static irqreturn_t ice_ll_ts_intr(int __always_unused irq, void *data) ++{ ++ struct ice_pf *pf = data; ++ u32 pf_intr_start_offset; ++ struct ice_ptp_tx *tx; ++ unsigned long flags; ++ struct ice_hw *hw; ++ u32 val; ++ u8 idx; ++ ++ hw = &pf->hw; ++ tx = &pf->ptp.port.tx; ++ spin_lock_irqsave(&tx->lock, flags); ++ ice_ptp_complete_tx_single_tstamp(tx); ++ ++ idx = find_next_bit_wrap(tx->in_use, tx->len, ++ tx->last_ll_ts_idx_read + 1); ++ if (idx != tx->len) ++ ice_ptp_req_tx_single_tstamp(tx, idx); ++ spin_unlock_irqrestore(&tx->lock, flags); ++ ++ val = GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M | ++ (ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S); ++ pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST; ++ wr32(hw, GLINT_DYN_CTL(pf->ll_ts_irq.index + pf_intr_start_offset), ++ val); ++ ++ return IRQ_HANDLED; + } + + /** +@@ -3191,7 +3233,19 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) + + if (oicr & PFINT_OICR_TSYN_TX_M) { + ena_mask &= ~PFINT_OICR_TSYN_TX_M; +- if (ice_ptp_pf_handles_tx_interrupt(pf)) { ++ if (ice_pf_state_is_nominal(pf) && ++ pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) { ++ struct ice_ptp_tx *tx = &pf->ptp.port.tx; ++ unsigned long flags; ++ u8 idx; ++ ++ spin_lock_irqsave(&tx->lock, flags); ++ idx = find_next_bit_wrap(tx->in_use, tx->len, ++ tx->last_ll_ts_idx_read + 1); ++ if (idx != tx->len) ++ ice_ptp_req_tx_single_tstamp(tx, idx); ++ spin_unlock_irqrestore(&tx->lock, flags); ++ } else if (ice_ptp_pf_handles_tx_interrupt(pf)) { + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); + ret = IRQ_WAKE_THREAD; + } +@@ -3295,6 +3349,20 @@ static void ice_dis_ctrlq_interrupts(struct ice_hw *hw) + ice_flush(hw); + } + ++/** ++ * ice_free_irq_msix_ll_ts- Unroll ll_ts vector setup ++ * @pf: board private structure ++ */ ++static void ice_free_irq_msix_ll_ts(struct ice_pf *pf) ++{ ++ int irq_num = pf->ll_ts_irq.virq; ++ ++ synchronize_irq(irq_num); ++ devm_free_irq(ice_pf_to_dev(pf), irq_num, pf); ++ ++ ice_free_irq(pf, pf->ll_ts_irq); ++} ++ + /** + * ice_free_irq_msix_misc - Unroll misc vector setup + * @pf: board private structure +@@ -3314,6 +3382,8 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf) + devm_free_irq(ice_pf_to_dev(pf), misc_irq_num, pf); + + ice_free_irq(pf, pf->oicr_irq); ++ if (pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) ++ ice_free_irq_msix_ll_ts(pf); + } + + /** +@@ -3339,10 +3409,12 @@ static void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 reg_idx) + PFINT_MBX_CTL_CAUSE_ENA_M); + wr32(hw, PFINT_MBX_CTL, val); + +- /* This enables Sideband queue Interrupt causes */ +- val = ((reg_idx & PFINT_SB_CTL_MSIX_INDX_M) | +- PFINT_SB_CTL_CAUSE_ENA_M); +- wr32(hw, PFINT_SB_CTL, val); ++ if (!hw->dev_caps.ts_dev_info.ts_ll_int_read) { ++ /* enable Sideband queue Interrupt causes */ ++ val = ((reg_idx & PFINT_SB_CTL_MSIX_INDX_M) | ++ PFINT_SB_CTL_CAUSE_ENA_M); ++ wr32(hw, PFINT_SB_CTL, val); ++ } + + ice_flush(hw); + } +@@ -3359,13 +3431,17 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) + { + struct device *dev = ice_pf_to_dev(pf); + struct ice_hw *hw = &pf->hw; +- struct msi_map oicr_irq; ++ u32 pf_intr_start_offset; ++ struct msi_map irq; + int err = 0; + + if (!pf->int_name[0]) + snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", + dev_driver_string(dev), dev_name(dev)); + ++ if (!pf->int_name_ll_ts[0]) ++ snprintf(pf->int_name_ll_ts, sizeof(pf->int_name_ll_ts) - 1, ++ "%s-%s:ll_ts", dev_driver_string(dev), dev_name(dev)); + /* Do not request IRQ but do enable OICR interrupt since settings are + * lost during reset. Note that this function is called only during + * rebuild path and not while reset is in progress. +@@ -3374,11 +3450,11 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) + goto skip_req_irq; + + /* reserve one vector in irq_tracker for misc interrupts */ +- oicr_irq = ice_alloc_irq(pf, false); +- if (oicr_irq.index < 0) +- return oicr_irq.index; ++ irq = ice_alloc_irq(pf, false); ++ if (irq.index < 0) ++ return irq.index; + +- pf->oicr_irq = oicr_irq; ++ pf->oicr_irq = irq; + err = devm_request_threaded_irq(dev, pf->oicr_irq.virq, ice_misc_intr, + ice_misc_intr_thread_fn, 0, + pf->int_name, pf); +@@ -3389,10 +3465,34 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) + return err; + } + ++ /* reserve one vector in irq_tracker for ll_ts interrupt */ ++ if (!pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) ++ goto skip_req_irq; ++ ++ irq = ice_alloc_irq(pf, false); ++ if (irq.index < 0) ++ return irq.index; ++ ++ pf->ll_ts_irq = irq; ++ err = devm_request_irq(dev, pf->ll_ts_irq.virq, ice_ll_ts_intr, 0, ++ pf->int_name_ll_ts, pf); ++ if (err) { ++ dev_err(dev, "devm_request_irq for %s failed: %d\n", ++ pf->int_name_ll_ts, err); ++ ice_free_irq(pf, pf->ll_ts_irq); ++ return err; ++ } ++ + skip_req_irq: + ice_ena_misc_vector(pf); + + ice_ena_ctrlq_interrupts(hw, pf->oicr_irq.index); ++ /* This enables LL TS interrupt */ ++ pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST; ++ if (pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) ++ wr32(hw, PFINT_SB_CTL, ++ ((pf->ll_ts_irq.index + pf_intr_start_offset) & ++ PFINT_SB_CTL_MSIX_INDX_M) | PFINT_SB_CTL_CAUSE_ENA_M); + wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_irq.index), + ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 2e6e1fc84d11..75038d826f71 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -634,6 +634,119 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) + return tx->init && !tx->calibrating; + } + ++/** ++ * ice_ptp_req_tx_single_tstamp - Request Tx timestamp for a port from FW ++ * @tx: the PTP Tx timestamp tracker ++ * @idx: index of the timestamp to request ++ */ ++void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx) ++{ ++ struct ice_ptp_port *ptp_port; ++ struct sk_buff *skb; ++ struct ice_pf *pf; ++ ++ if (!tx->init) ++ return; ++ ++ ptp_port = container_of(tx, struct ice_ptp_port, tx); ++ pf = ptp_port_to_pf(ptp_port); ++ ++ /* Drop packets which have waited for more than 2 seconds */ ++ if (time_is_before_jiffies(tx->tstamps[idx].start + 2 * HZ)) { ++ /* Count the number of Tx timestamps that timed out */ ++ pf->ptp.tx_hwtstamp_timeouts++; ++ ++ skb = tx->tstamps[idx].skb; ++ tx->tstamps[idx].skb = NULL; ++ clear_bit(idx, tx->in_use); ++ ++ dev_kfree_skb_any(skb); ++ return; ++ } ++ ++ ice_trace(tx_tstamp_fw_req, tx->tstamps[idx].skb, idx); ++ ++ /* Write TS index to read to the PF register so the FW can read it */ ++ wr32(&pf->hw, PF_SB_ATQBAL, ++ TS_LL_READ_TS_INTR | FIELD_PREP(TS_LL_READ_TS_IDX, idx) | ++ TS_LL_READ_TS); ++ tx->last_ll_ts_idx_read = idx; ++} ++ ++/** ++ * ice_ptp_complete_tx_single_tstamp - Complete Tx timestamp for a port ++ * @tx: the PTP Tx timestamp tracker ++ */ ++void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) ++{ ++ struct skb_shared_hwtstamps shhwtstamps = {}; ++ u8 idx = tx->last_ll_ts_idx_read; ++ struct ice_ptp_port *ptp_port; ++ u64 raw_tstamp, tstamp; ++ bool drop_ts = false; ++ struct sk_buff *skb; ++ struct ice_pf *pf; ++ u32 val; ++ ++ if (!tx->init || tx->last_ll_ts_idx_read < 0) ++ return; ++ ++ ptp_port = container_of(tx, struct ice_ptp_port, tx); ++ pf = ptp_port_to_pf(ptp_port); ++ ++ ice_trace(tx_tstamp_fw_done, tx->tstamps[idx].skb, idx); ++ ++ val = rd32(&pf->hw, PF_SB_ATQBAL); ++ ++ /* When the bit is cleared, the TS is ready in the register */ ++ if (val & TS_LL_READ_TS) { ++ dev_err(ice_pf_to_dev(pf), "Failed to get the Tx tstamp - FW not ready"); ++ return; ++ } ++ ++ /* High 8 bit value of the TS is on the bits 16:23 */ ++ raw_tstamp = FIELD_GET(TS_LL_READ_TS_HIGH, val); ++ raw_tstamp <<= 32; ++ ++ /* Read the low 32 bit value */ ++ raw_tstamp |= (u64)rd32(&pf->hw, PF_SB_ATQBAH); ++ ++ /* For PHYs which don't implement a proper timestamp ready bitmap, ++ * verify that the timestamp value is different from the last cached ++ * timestamp. If it is not, skip this for now assuming it hasn't yet ++ * been captured by hardware. ++ */ ++ if (!drop_ts && tx->verify_cached && ++ raw_tstamp == tx->tstamps[idx].cached_tstamp) ++ return; ++ ++ if (tx->verify_cached && raw_tstamp) ++ tx->tstamps[idx].cached_tstamp = raw_tstamp; ++ clear_bit(idx, tx->in_use); ++ skb = tx->tstamps[idx].skb; ++ tx->tstamps[idx].skb = NULL; ++ if (test_and_clear_bit(idx, tx->stale)) ++ drop_ts = true; ++ ++ if (!skb) ++ return; ++ ++ if (drop_ts) { ++ dev_kfree_skb_any(skb); ++ return; ++ } ++ ++ /* Extend the timestamp using cached PHC time */ ++ tstamp = ice_ptp_extend_40b_ts(pf, raw_tstamp); ++ if (tstamp) { ++ shhwtstamps.hwtstamp = ns_to_ktime(tstamp); ++ ice_trace(tx_tstamp_complete, skb, idx); ++ } ++ ++ skb_tstamp_tx(skb, &shhwtstamps); ++ dev_kfree_skb_any(skb); ++} ++ + /** + * ice_ptp_process_tx_tstamp - Process Tx timestamps for a port + * @tx: the PTP Tx timestamp tracker +@@ -685,6 +798,7 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) + static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + { + struct ice_ptp_port *ptp_port; ++ unsigned long flags; + struct ice_pf *pf; + struct ice_hw *hw; + u64 tstamp_ready; +@@ -756,7 +870,7 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + drop_ts = true; + + skip_ts_read: +- spin_lock(&tx->lock); ++ spin_lock_irqsave(&tx->lock, flags); + if (tx->verify_cached && raw_tstamp) + tx->tstamps[idx].cached_tstamp = raw_tstamp; + clear_bit(idx, tx->in_use); +@@ -764,7 +878,7 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + tx->tstamps[idx].skb = NULL; + if (test_and_clear_bit(idx, tx->stale)) + drop_ts = true; +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + /* It is unlikely but possible that the SKB will have been + * flushed at this point due to link change or teardown. +@@ -834,6 +948,7 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) + static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) + { + bool more_timestamps; ++ unsigned long flags; + + if (!tx->init) + return ICE_TX_TSTAMP_WORK_DONE; +@@ -842,9 +957,9 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) + ice_ptp_process_tx_tstamp(tx); + + /* Check if there are outstanding Tx timestamps */ +- spin_lock(&tx->lock); ++ spin_lock_irqsave(&tx->lock, flags); + more_timestamps = tx->init && !bitmap_empty(tx->in_use, tx->len); +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + if (more_timestamps) + return ICE_TX_TSTAMP_WORK_PENDING; +@@ -881,6 +996,7 @@ ice_ptp_alloc_tx_tracker(struct ice_ptp_tx *tx) + tx->in_use = in_use; + tx->stale = stale; + tx->init = 1; ++ tx->last_ll_ts_idx_read = -1; + + spin_lock_init(&tx->lock); + +@@ -898,6 +1014,7 @@ static void + ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + { + struct ice_hw *hw = &pf->hw; ++ unsigned long flags; + u64 tstamp_ready; + int err; + u8 idx; +@@ -921,12 +1038,12 @@ ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + if (!hw->reset_ongoing && (tstamp_ready & BIT_ULL(phy_idx))) + ice_clear_phy_tstamp(hw, tx->block, phy_idx); + +- spin_lock(&tx->lock); ++ spin_lock_irqsave(&tx->lock, flags); + skb = tx->tstamps[idx].skb; + tx->tstamps[idx].skb = NULL; + clear_bit(idx, tx->in_use); + clear_bit(idx, tx->stale); +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + /* Count the number of Tx timestamps flushed */ + pf->ptp.tx_hwtstamp_flushed++; +@@ -950,9 +1067,11 @@ ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + static void + ice_ptp_mark_tx_tracker_stale(struct ice_ptp_tx *tx) + { +- spin_lock(&tx->lock); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tx->lock, flags); + bitmap_or(tx->stale, tx->stale, tx->in_use, tx->len); +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + } + + /** +@@ -965,9 +1084,11 @@ ice_ptp_mark_tx_tracker_stale(struct ice_ptp_tx *tx) + static void + ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + { +- spin_lock(&tx->lock); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tx->lock, flags); + tx->init = 0; +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + /* wait for potentially outstanding interrupt to complete */ + synchronize_irq(pf->oicr_irq.virq); +@@ -1367,6 +1488,7 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port) + struct ice_pf *pf = ptp_port_to_pf(ptp_port); + u8 port = ptp_port->port_num; + struct ice_hw *hw = &pf->hw; ++ unsigned long flags; + int err; + + if (ice_is_e810(hw)) +@@ -1380,9 +1502,9 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port) + kthread_cancel_delayed_work_sync(&ptp_port->ov_work); + + /* temporarily disable Tx timestamps while calibrating PHY offset */ +- spin_lock(&ptp_port->tx.lock); ++ spin_lock_irqsave(&ptp_port->tx.lock, flags); + ptp_port->tx.calibrating = true; +- spin_unlock(&ptp_port->tx.lock); ++ spin_unlock_irqrestore(&ptp_port->tx.lock, flags); + ptp_port->tx_fifo_busy_cnt = 0; + + /* Start the PHY timer in Vernier mode */ +@@ -1391,9 +1513,9 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port) + goto out_unlock; + + /* Enable Tx timestamps right away */ +- spin_lock(&ptp_port->tx.lock); ++ spin_lock_irqsave(&ptp_port->tx.lock, flags); + ptp_port->tx.calibrating = false; +- spin_unlock(&ptp_port->tx.lock); ++ spin_unlock_irqrestore(&ptp_port->tx.lock, flags); + + kthread_queue_delayed_work(pf->ptp.kworker, &ptp_port->ov_work, 0); + +@@ -2471,18 +2593,23 @@ static long ice_ptp_create_clock(struct ice_pf *pf) + */ + s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) + { ++ unsigned long flags; + u8 idx; + +- spin_lock(&tx->lock); ++ spin_lock_irqsave(&tx->lock, flags); + + /* Check that this tracker is accepting new timestamp requests */ + if (!ice_ptp_is_tx_tracker_up(tx)) { +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + return -1; + } + + /* Find and set the first available index */ +- idx = find_first_zero_bit(tx->in_use, tx->len); ++ idx = find_next_zero_bit(tx->in_use, tx->len, ++ tx->last_ll_ts_idx_read + 1); ++ if (idx == tx->len) ++ idx = find_first_zero_bit(tx->in_use, tx->len); ++ + if (idx < tx->len) { + /* We got a valid index that no other thread could have set. Store + * a reference to the skb and the start time to allow discarding old +@@ -2496,7 +2623,7 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) + ice_trace(tx_tstamp_request, skb, idx); + } + +- spin_unlock(&tx->lock); ++ spin_unlock_irqrestore(&tx->lock, flags); + + /* return the appropriate PHY timestamp register index, -1 if no + * indexes were available. +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index a3ae008a3539..64679d3d2c49 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -131,6 +131,7 @@ enum ice_tx_tstamp_work { + * @calibrating: if true, the PHY is calibrating the Tx offset. During this + * window, timestamps are temporarily disabled. + * @verify_cached: if true, verify new timestamp differs from last read value ++ * @last_ll_ts_idx_read: index of the last LL TS read by the FW + */ + struct ice_ptp_tx { + spinlock_t lock; /* lock protecting in_use bitmap */ +@@ -143,6 +144,7 @@ struct ice_ptp_tx { + u8 init : 1; + u8 calibrating : 1; + u8 verify_cached : 1; ++ s8 last_ll_ts_idx_read; + }; + + /* Quad and port information for initializing timestamp blocks */ +@@ -296,6 +298,8 @@ int ice_get_ptp_clock_index(struct ice_pf *pf); + + void ice_ptp_extts_event(struct ice_pf *pf); + s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb); ++void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx); ++void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx); + enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf); + + void +@@ -330,6 +334,11 @@ ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) + return -1; + } + ++static inline void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx) ++{ } ++ ++static inline void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) { } ++ + static inline bool ice_ptp_process_ts(struct ice_pf *pf) + { + return true; +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +index 0cc285614c72..7e8fd369ef7c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +@@ -509,6 +509,7 @@ int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id, + #define TS_LL_READ_RETRIES 200 + #define TS_LL_READ_TS_HIGH GENMASK(23, 16) + #define TS_LL_READ_TS_IDX GENMASK(29, 24) ++#define TS_LL_READ_TS_INTR BIT(30) + #define TS_LL_READ_TS BIT(31) + + /* Internal PHY timestamp address */ +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index f8b658386552..b0f1f4db1d8b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -350,6 +350,7 @@ struct ice_ts_func_info { + #define ICE_TS_TMR0_ENA_M BIT(25) + #define ICE_TS_TMR1_ENA_M BIT(26) + #define ICE_TS_LL_TX_TS_READ_M BIT(28) ++#define ICE_TS_LL_TX_TS_INT_READ_M BIT(29) + + struct ice_ts_dev_info { + /* Device specific info */ +@@ -363,6 +364,7 @@ struct ice_ts_dev_info { + u8 tmr0_ena; + u8 tmr1_ena; + u8 ts_ll_read; ++ u8 ts_ll_int_read; + }; + + /* Function specific capabilities */ +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0014-ice-PTP-add-clock-domain-number-to-auxiliary-interfa.patch b/kernel-std/debian/patches/ice-VDF/0014-ice-PTP-add-clock-domain-number-to-auxiliary-interfa.patch new file mode 100644 index 00000000..c8c26134 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0014-ice-PTP-add-clock-domain-number-to-auxiliary-interfa.patch @@ -0,0 +1,310 @@ +From f267daca86600496d536f85c4d1945558b982427 Mon Sep 17 00:00:00 2001 +From: Michal Michalik +Date: Thu, 27 Jul 2023 15:50:36 +0200 +Subject: [PATCH 14/36] ice: PTP: add clock domain number to auxiliary + interface + +The PHC clock id used to be moved between PFs using FW admin queue +shared parameters - move the implementation to auxiliary bus. + +Signed-off-by: Karol Kolacinski +Signed-off-by: Jacob Keller +Signed-off-by: Michal Michalik +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit fcd2c1e3139a27766ef263bd2011195dbc8a79f5) +Signed-off-by: Jiping Ma +--- + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 5 - + drivers/net/ethernet/intel/ice/ice_ethtool.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 163 +++--------------- + drivers/net/ethernet/intel/ice/ice_ptp.h | 11 +- + 4 files changed, 34 insertions(+), 147 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 353ac55bdb9d..9bacb69ead8c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2360,11 +2360,6 @@ struct ice_aqc_driver_shared_params { + }; + + enum ice_aqc_driver_params { +- /* OS clock index for PTP timer Domain 0 */ +- ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0 = 0, +- /* OS clock index for PTP timer Domain 1 */ +- ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1, +- + /* Add new parameters above */ + ICE_AQC_DRIVER_PARAM_MAX = 16, + }; +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 456cf4785c74..057453d589d5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -3286,7 +3286,7 @@ ice_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + +- info->phc_index = ice_get_ptp_clock_index(pf); ++ info->phc_index = ice_ptp_clock_index(pf); + + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 75038d826f71..a2d0da7dfe83 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -345,131 +345,6 @@ void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) + ice_set_rx_tstamp(pf, ena); + } + +-/** +- * ice_get_ptp_clock_index - Get the PTP clock index +- * @pf: the PF pointer +- * +- * Determine the clock index of the PTP clock associated with this device. If +- * this is the PF controlling the clock, just use the local access to the +- * clock device pointer. +- * +- * Otherwise, read from the driver shared parameters to determine the clock +- * index value. +- * +- * Returns: the index of the PTP clock associated with this device, or -1 if +- * there is no associated clock. +- */ +-int ice_get_ptp_clock_index(struct ice_pf *pf) +-{ +- struct device *dev = ice_pf_to_dev(pf); +- enum ice_aqc_driver_params param_idx; +- struct ice_hw *hw = &pf->hw; +- u8 tmr_idx; +- u32 value; +- int err; +- +- /* Use the ptp_clock structure if we're the main PF */ +- if (pf->ptp.clock) +- return ptp_clock_index(pf->ptp.clock); +- +- tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc; +- if (!tmr_idx) +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0; +- else +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1; +- +- err = ice_aq_get_driver_param(hw, param_idx, &value, NULL); +- if (err) { +- dev_err(dev, "Failed to read PTP clock index parameter, err %d aq_err %s\n", +- err, ice_aq_str(hw->adminq.sq_last_status)); +- return -1; +- } +- +- /* The PTP clock index is an integer, and will be between 0 and +- * INT_MAX. The highest bit of the driver shared parameter is used to +- * indicate whether or not the currently stored clock index is valid. +- */ +- if (!(value & PTP_SHARED_CLK_IDX_VALID)) +- return -1; +- +- return value & ~PTP_SHARED_CLK_IDX_VALID; +-} +- +-/** +- * ice_set_ptp_clock_index - Set the PTP clock index +- * @pf: the PF pointer +- * +- * Set the PTP clock index for this device into the shared driver parameters, +- * so that other PFs associated with this device can read it. +- * +- * If the PF is unable to store the clock index, it will log an error, but +- * will continue operating PTP. +- */ +-static void ice_set_ptp_clock_index(struct ice_pf *pf) +-{ +- struct device *dev = ice_pf_to_dev(pf); +- enum ice_aqc_driver_params param_idx; +- struct ice_hw *hw = &pf->hw; +- u8 tmr_idx; +- u32 value; +- int err; +- +- if (!pf->ptp.clock) +- return; +- +- tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc; +- if (!tmr_idx) +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0; +- else +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1; +- +- value = (u32)ptp_clock_index(pf->ptp.clock); +- if (value > INT_MAX) { +- dev_err(dev, "PTP Clock index is too large to store\n"); +- return; +- } +- value |= PTP_SHARED_CLK_IDX_VALID; +- +- err = ice_aq_set_driver_param(hw, param_idx, value, NULL); +- if (err) { +- dev_err(dev, "Failed to set PTP clock index parameter, err %d aq_err %s\n", +- err, ice_aq_str(hw->adminq.sq_last_status)); +- } +-} +- +-/** +- * ice_clear_ptp_clock_index - Clear the PTP clock index +- * @pf: the PF pointer +- * +- * Clear the PTP clock index for this device. Must be called when +- * unregistering the PTP clock, in order to ensure other PFs stop reporting +- * a clock object that no longer exists. +- */ +-static void ice_clear_ptp_clock_index(struct ice_pf *pf) +-{ +- struct device *dev = ice_pf_to_dev(pf); +- enum ice_aqc_driver_params param_idx; +- struct ice_hw *hw = &pf->hw; +- u8 tmr_idx; +- int err; +- +- /* Do not clear the index if we don't own the timer */ +- if (!ice_pf_src_tmr_owned(pf)) +- return; +- +- tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc; +- if (!tmr_idx) +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0; +- else +- param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1; +- +- err = ice_aq_set_driver_param(hw, param_idx, 0, NULL); +- if (err) { +- dev_dbg(dev, "Failed to clear PTP clock index parameter, err %d aq_err %s\n", +- err, ice_aq_str(hw->adminq.sq_last_status)); +- } +-} +- + /** + * ice_ptp_read_src_clk_reg - Read the source clock register + * @pf: Board private structure +@@ -2564,7 +2439,6 @@ static void ice_ptp_set_caps(struct ice_pf *pf) + static long ice_ptp_create_clock(struct ice_pf *pf) + { + struct ptp_clock_info *info; +- struct ptp_clock *clock; + struct device *dev; + + /* No need to create a clock device if we already have one */ +@@ -2577,11 +2451,11 @@ static long ice_ptp_create_clock(struct ice_pf *pf) + dev = ice_pf_to_dev(pf); + + /* Attempt to register the clock before enabling the hardware. */ +- clock = ptp_clock_register(info, dev); +- if (IS_ERR(clock)) +- return PTR_ERR(clock); +- +- pf->ptp.clock = clock; ++ pf->ptp.clock = ptp_clock_register(info, dev); ++ if (IS_ERR(pf->ptp.clock)) { ++ dev_err(ice_pf_to_dev(pf), "Failed to register PTP clock device"); ++ return PTR_ERR(pf->ptp.clock); ++ } + + return 0; + } +@@ -2996,6 +2870,28 @@ static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf) + mutex_destroy(&pf->ptp.ports_owner.lock); + } + ++/** ++ * ice_ptp_clock_index - Get the PTP clock index for this device ++ * @pf: Board private structure ++ * ++ * Returns: the PTP clock index associated with this PF, or -1 if no PTP clock ++ * is associated. ++ */ ++int ice_ptp_clock_index(struct ice_pf *pf) ++{ ++ struct auxiliary_device *aux_dev; ++ struct ice_pf *owner_pf; ++ struct ptp_clock *clock; ++ ++ aux_dev = &pf->ptp.port.aux_dev; ++ owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev); ++ if (!owner_pf) ++ return -1; ++ clock = owner_pf->ptp.clock; ++ ++ return clock ? ptp_clock_index(clock) : -1; ++} ++ + /** + * ice_ptp_prepare_for_reset - Prepare PTP for reset + * @pf: Board private structure +@@ -3086,9 +2982,6 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + if (err) + goto err_clk; + +- /* Store the PTP clock index for other PFs */ +- ice_set_ptp_clock_index(pf); +- + err = ice_ptp_register_auxbus_driver(pf); + if (err) { + dev_err(ice_pf_to_dev(pf), "Failed to register PTP auxbus driver"); +@@ -3097,7 +2990,6 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + + return 0; + err_aux: +- ice_clear_ptp_clock_index(pf); + ptp_clock_unregister(pf->ptp.clock); + err_clk: + pf->ptp.clock = NULL; +@@ -3353,7 +3245,6 @@ void ice_ptp_release(struct ice_pf *pf) + /* Disable periodic outputs */ + ice_ptp_disable_all_clkout(pf); + +- ice_clear_ptp_clock_index(pf); + ptp_clock_unregister(pf->ptp.clock); + pf->ptp.clock = NULL; + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 64679d3d2c49..95ebd7a048ec 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -290,11 +290,11 @@ struct ice_ptp { + #define ETH_GLTSYN_ENA(_i) (0x03000348 + ((_i) * 4)) + + #if IS_ENABLED(CONFIG_PTP_1588_CLOCK) ++int ice_ptp_clock_index(struct ice_pf *pf); + struct ice_pf; + int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr); + int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr); + void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena); +-int ice_get_ptp_clock_index(struct ice_pf *pf); + + void ice_ptp_extts_event(struct ice_pf *pf); + s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb); +@@ -322,10 +322,6 @@ static inline int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) + } + + static inline void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) { } +-static inline int ice_get_ptp_clock_index(struct ice_pf *pf) +-{ +- return -1; +-} + + static inline void ice_ptp_extts_event(struct ice_pf *pf) { } + static inline s8 +@@ -353,5 +349,10 @@ static inline void ice_ptp_release(struct ice_pf *pf) { } + static inline void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + { + } ++ ++static inline int ice_ptp_clock_index(struct ice_pf *pf) ++{ ++ return -1; ++} + #endif /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */ + #endif /* _ICE_PTP_H_ */ +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0015-ice-restore-timestamp-configuration-after-device-res.patch b/kernel-std/debian/patches/ice-VDF/0015-ice-restore-timestamp-configuration-after-device-res.patch new file mode 100644 index 00000000..ed75abed --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0015-ice-restore-timestamp-configuration-after-device-res.patch @@ -0,0 +1,266 @@ +From eb63973adae478fdcc324f5490d6803646f0cc76 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 21 Nov 2023 13:12:57 -0800 +Subject: [PATCH 15/36] ice: restore timestamp configuration after device reset + +The driver calls ice_ptp_cfg_timestamp() during ice_ptp_prepare_for_reset() +to disable timestamping while the device is resetting. This operation +destroys the user requested configuration. While the driver does call +ice_ptp_cfg_timestamp in ice_rebuild() to restore some hardware settings +after a reset, it unconditionally passes true or false, resulting in +failure to restore previous user space configuration. + +This results in a device reset forcibly disabling timestamp configuration +regardless of current user settings. + +This was not detected previously due to a quirk of the LinuxPTP ptp4l +application. If ptp4l detects a missing timestamp, it enters a fault state +and performs recovery logic which includes executing SIOCSHWTSTAMP again, +restoring the now accidentally cleared configuration. + +Not every application does this, and for these applications, timestamps +will mysteriously stop after a PF reset, without being restored until an +application restart. + +Fix this by replacing ice_ptp_cfg_timestamp() with two new functions: + +1) ice_ptp_disable_timestamp_mode() which unconditionally disables the + timestamping logic in ice_ptp_prepare_for_reset() and ice_ptp_release() + +2) ice_ptp_restore_timestamp_mode() which calls + ice_ptp_restore_tx_interrupt() to restore Tx timestamping configuration, + calls ice_set_rx_tstamp() to restore Rx timestamping configuration, and + issues an immediate TSYN_TX interrupt to ensure that timestamps which + may have occurred during the device reset get processed. + +Modify the ice_ptp_set_timestamp_mode to directly save the user +configuration and then call ice_ptp_restore_timestamp_mode. This way, reset +no longer destroys the saved user configuration. + +This obsoletes the ice_set_tx_tstamp() function which can now be safely +removed. + +With this change, all devices should now restore Tx and Rx timestamping +functionality correctly after a PF reset without application intervention. + +Fixes: 77a781155a65 ("ice: enable receive hardware timestamping") +Fixes: ea9b847cda64 ("ice: enable transmit timestamps for E810 devices") +Signed-off-by: Jacob Keller +Reviewed-by: Jesse Brandeburg +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 7758017911a4f2578d54c318e8fe77bcb5899054) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_main.c | 12 +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 74 ++++++++++++++--------- + drivers/net/ethernet/intel/ice/ice_ptp.h | 5 +- + 3 files changed, 51 insertions(+), 40 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 9163a72368b3..8cfb923198e9 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -7545,15 +7545,6 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + goto err_vsi_rebuild; + } + +- /* configure PTP timestamping after VSI rebuild */ +- if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) { +- if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) +- ice_ptp_cfg_timestamp(pf, false); +- else if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) +- /* for E82x PHC owner always need to have interrupts */ +- ice_ptp_cfg_timestamp(pf, true); +- } +- + err = ice_vsi_rebuild_by_type(pf, ICE_VSI_SWITCHDEV_CTRL); + if (err) { + dev_err(dev, "Switchdev CTRL VSI rebuild failed: %d\n", err); +@@ -7605,6 +7596,9 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + ice_plug_aux_dev(pf); + if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) + ice_lag_rebuild(pf); ++ ++ /* Restore timestamp mode settings after VSI rebuild */ ++ ice_ptp_restore_timestamp_mode(pf); + return; + + err_vsi_rebuild: +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index a2d0da7dfe83..8fc6905b0f79 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -294,18 +294,6 @@ static void ice_ptp_cfg_tx_interrupt(struct ice_pf *pf) + wr32(hw, PFINT_OICR_ENA, val); + } + +-/** +- * ice_set_tx_tstamp - Enable or disable Tx timestamping +- * @pf: The PF pointer to search in +- * @on: bool value for whether timestamps are enabled or disabled +- */ +-static void ice_set_tx_tstamp(struct ice_pf *pf, bool on) +-{ +- pf->ptp.tstamp_config.tx_type = on ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; +- +- ice_ptp_cfg_tx_interrupt(pf); +-} +- + /** + * ice_set_rx_tstamp - Enable or disable Rx timestamping + * @pf: The PF pointer to search in +@@ -317,7 +305,7 @@ static void ice_set_rx_tstamp(struct ice_pf *pf, bool on) + u16 i; + + vsi = ice_get_main_vsi(pf); +- if (!vsi) ++ if (!vsi || !vsi->rx_rings) + return; + + /* Set the timestamp flag for all the Rx rings */ +@@ -326,23 +314,50 @@ static void ice_set_rx_tstamp(struct ice_pf *pf, bool on) + continue; + vsi->rx_rings[i]->ptp_rx = on; + } ++} ++ ++/** ++ * ice_ptp_disable_timestamp_mode - Disable current timestamp mode ++ * @pf: Board private structure ++ * ++ * Called during preparation for reset to temporarily disable timestamping on ++ * the device. Called during remove to disable timestamping while cleaning up ++ * driver resources. ++ */ ++static void ice_ptp_disable_timestamp_mode(struct ice_pf *pf) ++{ ++ struct ice_hw *hw = &pf->hw; ++ u32 val; ++ ++ val = rd32(hw, PFINT_OICR_ENA); ++ val &= ~PFINT_OICR_TSYN_TX_M; ++ wr32(hw, PFINT_OICR_ENA, val); + +- pf->ptp.tstamp_config.rx_filter = on ? HWTSTAMP_FILTER_ALL : +- HWTSTAMP_FILTER_NONE; ++ ice_set_rx_tstamp(pf, false); + } + + /** +- * ice_ptp_cfg_timestamp - Configure timestamp for init/deinit ++ * ice_ptp_restore_timestamp_mode - Restore timestamp configuration + * @pf: Board private structure +- * @ena: bool value to enable or disable time stamp + * +- * This function will configure timestamping during PTP initialization +- * and deinitialization ++ * Called at the end of rebuild to restore timestamp configuration after ++ * a device reset. + */ +-void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) ++void ice_ptp_restore_timestamp_mode(struct ice_pf *pf) + { +- ice_set_tx_tstamp(pf, ena); +- ice_set_rx_tstamp(pf, ena); ++ struct ice_hw *hw = &pf->hw; ++ bool enable_rx; ++ ++ ice_ptp_cfg_tx_interrupt(pf); ++ ++ enable_rx = pf->ptp.tstamp_config.rx_filter == HWTSTAMP_FILTER_ALL; ++ ice_set_rx_tstamp(pf, enable_rx); ++ ++ /* Trigger an immediate software interrupt to ensure that timestamps ++ * which occurred during reset are handled now. ++ */ ++ wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); ++ ice_flush(hw); + } + + /** +@@ -2152,10 +2167,10 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config) + { + switch (config->tx_type) { + case HWTSTAMP_TX_OFF: +- ice_set_tx_tstamp(pf, false); ++ pf->ptp.tstamp_config.tx_type = HWTSTAMP_TX_OFF; + break; + case HWTSTAMP_TX_ON: +- ice_set_tx_tstamp(pf, true); ++ pf->ptp.tstamp_config.tx_type = HWTSTAMP_TX_ON; + break; + default: + return -ERANGE; +@@ -2163,7 +2178,7 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config) + + switch (config->rx_filter) { + case HWTSTAMP_FILTER_NONE: +- ice_set_rx_tstamp(pf, false); ++ pf->ptp.tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: +@@ -2179,12 +2194,15 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config) + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_NTP_ALL: + case HWTSTAMP_FILTER_ALL: +- ice_set_rx_tstamp(pf, true); ++ pf->ptp.tstamp_config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + default: + return -ERANGE; + } + ++ /* Immediately update the device timestamping mode */ ++ ice_ptp_restore_timestamp_mode(pf); ++ + return 0; + } + +@@ -2904,7 +2922,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf) + clear_bit(ICE_FLAG_PTP, pf->flags); + + /* Disable timestamping for both Tx and Rx */ +- ice_ptp_cfg_timestamp(pf, false); ++ ice_ptp_disable_timestamp_mode(pf); + + kthread_cancel_delayed_work_sync(&ptp->work); + +@@ -3222,7 +3240,7 @@ void ice_ptp_release(struct ice_pf *pf) + return; + + /* Disable timestamping for both Tx and Rx */ +- ice_ptp_cfg_timestamp(pf, false); ++ ice_ptp_disable_timestamp_mode(pf); + + ice_ptp_remove_auxbus_device(pf); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 95ebd7a048ec..130e6d2ae9a5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -294,7 +294,7 @@ int ice_ptp_clock_index(struct ice_pf *pf); + struct ice_pf; + int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr); + int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr); +-void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena); ++void ice_ptp_restore_timestamp_mode(struct ice_pf *pf); + + void ice_ptp_extts_event(struct ice_pf *pf); + s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb); +@@ -321,8 +321,7 @@ static inline int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) + return -EOPNOTSUPP; + } + +-static inline void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) { } +- ++static inline void ice_ptp_restore_timestamp_mode(struct ice_pf *pf) { } + static inline void ice_ptp_extts_event(struct ice_pf *pf) { } + static inline s8 + ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0016-ice-introduce-PTP-state-machine.patch b/kernel-std/debian/patches/ice-VDF/0016-ice-introduce-PTP-state-machine.patch new file mode 100644 index 00000000..851c986e --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0016-ice-introduce-PTP-state-machine.patch @@ -0,0 +1,316 @@ +From 5c6115d27a377927d6392b3bfbe9739188c8153c Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:49 -0800 +Subject: [PATCH 16/36] ice: introduce PTP state machine + +Add PTP state machine so that the driver can correctly identify PTP +state around resets. +When the driver got information about ungraceful reset, PTP was not +prepared for reset and it returned error. When this situation occurs, +prepare PTP before rebuilding its structures. + +Signed-off-by: Jacob Keller +Co-developed-by: Karol Kolacinski +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 8293e4cb2ff54b1ec4f7206dcb74c908f62a3fb8) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 1 - + drivers/net/ethernet/intel/ice/ice_ethtool.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 110 +++++++++++-------- + drivers/net/ethernet/intel/ice/ice_ptp.h | 10 ++ + 4 files changed, 74 insertions(+), 49 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index ee42a504c2f4..3278d032a2bd 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -492,7 +492,6 @@ enum ice_pf_flags { + ICE_FLAG_DCB_ENA, + ICE_FLAG_FD_ENA, + ICE_FLAG_PTP_SUPPORTED, /* PTP is supported by NVM */ +- ICE_FLAG_PTP, /* PTP is enabled by software */ + ICE_FLAG_ADV_FEATURES, + ICE_FLAG_TC_MQPRIO, /* support for Multi queue TC */ + ICE_FLAG_CLS_FLOWER, +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 057453d589d5..9e949c493c38 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -3276,7 +3276,7 @@ ice_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) + struct ice_pf *pf = ice_netdev_to_pf(dev); + + /* only report timestamping if PTP is enabled */ +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return ethtool_op_get_ts_info(dev, info); + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 8fc6905b0f79..36c81c5ee83b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1430,7 +1430,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + struct ice_ptp_port *ptp_port; + struct ice_hw *hw = &pf->hw; + +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return; + + if (WARN_ON_ONCE(port >= ICE_NUM_EXTERNAL_PORTS)) +@@ -2148,7 +2148,7 @@ int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr) + { + struct hwtstamp_config *config; + +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return -EIO; + + config = &pf->ptp.tstamp_config; +@@ -2218,7 +2218,7 @@ int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr) + struct hwtstamp_config config; + int err; + +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return -EAGAIN; + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) +@@ -2606,7 +2606,7 @@ static void ice_ptp_periodic_work(struct kthread_work *work) + struct ice_pf *pf = container_of(ptp, struct ice_pf, ptp); + int err; + +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return; + + err = ice_ptp_update_cached_phctime(pf); +@@ -2618,6 +2618,42 @@ static void ice_ptp_periodic_work(struct kthread_work *work) + msecs_to_jiffies(err ? 10 : 500)); + } + ++/** ++ * ice_ptp_prepare_for_reset - Prepare PTP for reset ++ * @pf: Board private structure ++ */ ++void ice_ptp_prepare_for_reset(struct ice_pf *pf) ++{ ++ struct ice_ptp *ptp = &pf->ptp; ++ u8 src_tmr; ++ ++ if (ptp->state != ICE_PTP_READY) ++ return; ++ ++ ptp->state = ICE_PTP_RESETTING; ++ ++ /* Disable timestamping for both Tx and Rx */ ++ ice_ptp_disable_timestamp_mode(pf); ++ ++ kthread_cancel_delayed_work_sync(&ptp->work); ++ ++ if (test_bit(ICE_PFR_REQ, pf->state)) ++ return; ++ ++ ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); ++ ++ /* Disable periodic outputs */ ++ ice_ptp_disable_all_clkout(pf); ++ ++ src_tmr = ice_get_ptp_src_clock_index(&pf->hw); ++ ++ /* Disable source clock */ ++ wr32(&pf->hw, GLTSYN_ENA(src_tmr), (u32)~GLTSYN_ENA_TSYN_ENA_M); ++ ++ /* Acquire PHC and system timer to restore after reset */ ++ ptp->reset_time = ktime_get_real_ns(); ++} ++ + /** + * ice_ptp_reset - Initialize PTP hardware clock support after reset + * @pf: Board private structure +@@ -2630,6 +2666,14 @@ void ice_ptp_reset(struct ice_pf *pf) + int err, itr = 1; + u64 time_diff; + ++ if (ptp->state == ICE_PTP_READY) { ++ ice_ptp_prepare_for_reset(pf); ++ } else if (ptp->state != ICE_PTP_RESETTING) { ++ err = -EINVAL; ++ dev_err(ice_pf_to_dev(pf), "PTP was not initialized\n"); ++ goto err; ++ } ++ + if (test_bit(ICE_PFR_REQ, pf->state) || + !ice_pf_src_tmr_owned(pf)) + goto pfr; +@@ -2690,7 +2734,7 @@ void ice_ptp_reset(struct ice_pf *pf) + if (err) + goto err; + +- set_bit(ICE_FLAG_PTP, pf->flags); ++ ptp->state = ICE_PTP_READY; + + /* Restart the PHY timestamping block */ + if (!test_bit(ICE_PFR_REQ, pf->state) && +@@ -2704,6 +2748,7 @@ void ice_ptp_reset(struct ice_pf *pf) + return; + + err: ++ ptp->state = ICE_PTP_ERROR; + dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err); + } + +@@ -2910,39 +2955,6 @@ int ice_ptp_clock_index(struct ice_pf *pf) + return clock ? ptp_clock_index(clock) : -1; + } + +-/** +- * ice_ptp_prepare_for_reset - Prepare PTP for reset +- * @pf: Board private structure +- */ +-void ice_ptp_prepare_for_reset(struct ice_pf *pf) +-{ +- struct ice_ptp *ptp = &pf->ptp; +- u8 src_tmr; +- +- clear_bit(ICE_FLAG_PTP, pf->flags); +- +- /* Disable timestamping for both Tx and Rx */ +- ice_ptp_disable_timestamp_mode(pf); +- +- kthread_cancel_delayed_work_sync(&ptp->work); +- +- if (test_bit(ICE_PFR_REQ, pf->state)) +- return; +- +- ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); +- +- /* Disable periodic outputs */ +- ice_ptp_disable_all_clkout(pf); +- +- src_tmr = ice_get_ptp_src_clock_index(&pf->hw); +- +- /* Disable source clock */ +- wr32(&pf->hw, GLTSYN_ENA(src_tmr), (u32)~GLTSYN_ENA_TSYN_ENA_M); +- +- /* Acquire PHC and system timer to restore after reset */ +- ptp->reset_time = ktime_get_real_ns(); +-} +- + /** + * ice_ptp_init_owner - Initialize PTP_1588_CLOCK device + * @pf: Board private structure +@@ -3181,6 +3193,8 @@ void ice_ptp_init(struct ice_pf *pf) + struct ice_hw *hw = &pf->hw; + int err; + ++ ptp->state = ICE_PTP_INITIALIZING; ++ + ice_ptp_init_phy_model(hw); + + ice_ptp_init_tx_interrupt_mode(pf); +@@ -3205,12 +3219,13 @@ void ice_ptp_init(struct ice_pf *pf) + /* Configure initial Tx interrupt settings */ + ice_ptp_cfg_tx_interrupt(pf); + +- set_bit(ICE_FLAG_PTP, pf->flags); +- err = ice_ptp_init_work(pf, ptp); ++ err = ice_ptp_create_auxbus_device(pf); + if (err) + goto err; + +- err = ice_ptp_create_auxbus_device(pf); ++ ptp->state = ICE_PTP_READY; ++ ++ err = ice_ptp_init_work(pf, ptp); + if (err) + goto err; + +@@ -3223,7 +3238,7 @@ void ice_ptp_init(struct ice_pf *pf) + ptp_clock_unregister(ptp->clock); + pf->ptp.clock = NULL; + } +- clear_bit(ICE_FLAG_PTP, pf->flags); ++ ptp->state = ICE_PTP_ERROR; + dev_err(ice_pf_to_dev(pf), "PTP failed %d\n", err); + } + +@@ -3236,9 +3251,11 @@ void ice_ptp_init(struct ice_pf *pf) + */ + void ice_ptp_release(struct ice_pf *pf) + { +- if (!test_bit(ICE_FLAG_PTP, pf->flags)) ++ if (pf->ptp.state != ICE_PTP_READY) + return; + ++ pf->ptp.state = ICE_PTP_UNINIT; ++ + /* Disable timestamping for both Tx and Rx */ + ice_ptp_disable_timestamp_mode(pf); + +@@ -3246,8 +3263,6 @@ void ice_ptp_release(struct ice_pf *pf) + + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); + +- clear_bit(ICE_FLAG_PTP, pf->flags); +- + kthread_cancel_delayed_work_sync(&pf->ptp.work); + + ice_ptp_port_phy_stop(&pf->ptp.port); +@@ -3257,6 +3272,9 @@ void ice_ptp_release(struct ice_pf *pf) + pf->ptp.kworker = NULL; + } + ++ if (ice_pf_src_tmr_owned(pf)) ++ ice_ptp_unregister_auxbus_driver(pf); ++ + if (!pf->ptp.clock) + return; + +@@ -3266,7 +3284,5 @@ void ice_ptp_release(struct ice_pf *pf) + ptp_clock_unregister(pf->ptp.clock); + pf->ptp.clock = NULL; + +- ice_ptp_unregister_auxbus_driver(pf); +- + dev_info(ice_pf_to_dev(pf), "Removed PTP clock\n"); + } +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 130e6d2ae9a5..e3cc69692405 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -203,8 +203,17 @@ struct ice_ptp_port_owner { + + #define GLTSYN_TGT_H_IDX_MAX 4 + ++enum ice_ptp_state { ++ ICE_PTP_UNINIT = 0, ++ ICE_PTP_INITIALIZING, ++ ICE_PTP_READY, ++ ICE_PTP_RESETTING, ++ ICE_PTP_ERROR, ++}; ++ + /** + * struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK ++ * @state: current state of PTP state machine + * @tx_interrupt_mode: the TX interrupt mode for the PTP clock + * @port: data for the PHY port initialization procedure + * @ports_owner: data for the auxiliary driver owner +@@ -227,6 +236,7 @@ struct ice_ptp_port_owner { + * @late_cached_phc_updates: number of times cached PHC update is late + */ + struct ice_ptp { ++ enum ice_ptp_state state; + enum ice_ptp_tx_interrupt tx_interrupt_mode; + struct ice_ptp_port port; + struct ice_ptp_port_owner ports_owner; +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0017-ice-pass-reset-type-to-PTP-reset-functions.patch b/kernel-std/debian/patches/ice-VDF/0017-ice-pass-reset-type-to-PTP-reset-functions.patch new file mode 100644 index 00000000..c72ff132 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0017-ice-pass-reset-type-to-PTP-reset-functions.patch @@ -0,0 +1,150 @@ +From 68d481b41ee5c177a1376fb82a98c09c148d982a Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:50 -0800 +Subject: [PATCH 17/36] ice: pass reset type to PTP reset functions + +The ice_ptp_prepare_for_reset() and ice_ptp_reset() functions currently +check the pf->flags ICE_FLAG_PFR_REQ bit to determine if the current +reset is a PF reset or not. + +This is problematic, because it is possible that a PF reset and a higher +level reset (CORE reset, GLOBAL reset, EMP reset) are requested +simultaneously. In that case, the driver performs the highest level +reset requested. However, the ICE_FLAG_PFR_REQ flag will still be set. + +The main driver reset functions take an enum ice_reset_req indicating +which reset is actually being performed. Pass this data into the PTP +functions and rely on this instead of relying on the driver flags. + +This ensures that the PTP code performs the proper level of reset that +the driver is actually undergoing. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit c75d5e675a8542274fa0f7e52f3c4db1d4859a0c) +[Adjust the ice_ptp.h with the context change.] +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_main.c | 4 ++-- + drivers/net/ethernet/intel/ice/ice_ptp.c | 13 +++++++------ + drivers/net/ethernet/intel/ice/ice_ptp.h | 17 +++++++++++++---- + 3 files changed, 22 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 8cfb923198e9..d5321410f2d7 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -615,7 +615,7 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + ice_pf_dis_all_vsi(pf, false); + + if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) +- ice_ptp_prepare_for_reset(pf); ++ ice_ptp_prepare_for_reset(pf, reset_type); + + if (ice_is_feature_supported(pf, ICE_F_GNSS)) + ice_gnss_exit(pf); +@@ -7533,7 +7533,7 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + * fail. + */ + if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) +- ice_ptp_reset(pf); ++ ice_ptp_reset(pf, reset_type); + + if (ice_is_feature_supported(pf, ICE_F_GNSS)) + ice_gnss_init(pf); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 36c81c5ee83b..20d1d22235d3 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -2621,8 +2621,9 @@ static void ice_ptp_periodic_work(struct kthread_work *work) + /** + * ice_ptp_prepare_for_reset - Prepare PTP for reset + * @pf: Board private structure ++ * @reset_type: the reset type being performed + */ +-void ice_ptp_prepare_for_reset(struct ice_pf *pf) ++void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + { + struct ice_ptp *ptp = &pf->ptp; + u8 src_tmr; +@@ -2637,7 +2638,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf) + + kthread_cancel_delayed_work_sync(&ptp->work); + +- if (test_bit(ICE_PFR_REQ, pf->state)) ++ if (reset_type == ICE_RESET_PFR) + return; + + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); +@@ -2657,8 +2658,9 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf) + /** + * ice_ptp_reset - Initialize PTP hardware clock support after reset + * @pf: Board private structure ++ * @reset_type: the reset type being performed + */ +-void ice_ptp_reset(struct ice_pf *pf) ++void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + { + struct ice_ptp *ptp = &pf->ptp; + struct ice_hw *hw = &pf->hw; +@@ -2667,15 +2669,14 @@ void ice_ptp_reset(struct ice_pf *pf) + u64 time_diff; + + if (ptp->state == ICE_PTP_READY) { +- ice_ptp_prepare_for_reset(pf); ++ ice_ptp_prepare_for_reset(pf, reset_type); + } else if (ptp->state != ICE_PTP_RESETTING) { + err = -EINVAL; + dev_err(ice_pf_to_dev(pf), "PTP was not initialized\n"); + goto err; + } + +- if (test_bit(ICE_PFR_REQ, pf->state) || +- !ice_pf_src_tmr_owned(pf)) ++ if (reset_type == ICE_RESET_PFR || !ice_pf_src_tmr_owned(pf)) + goto pfr; + + err = ice_ptp_init_phc(hw); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index e3cc69692405..cd74712a17a1 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -315,8 +315,9 @@ enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf); + void + ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, + union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb); +-void ice_ptp_reset(struct ice_pf *pf); +-void ice_ptp_prepare_for_reset(struct ice_pf *pf); ++void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type); ++void ice_ptp_prepare_for_reset(struct ice_pf *pf, ++ enum ice_reset_req reset_type); + void ice_ptp_init(struct ice_pf *pf); + void ice_ptp_release(struct ice_pf *pf); + void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup); +@@ -351,8 +352,16 @@ static inline bool ice_ptp_process_ts(struct ice_pf *pf) + static inline void + ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, + union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb) { } +-static inline void ice_ptp_reset(struct ice_pf *pf) { } +-static inline void ice_ptp_prepare_for_reset(struct ice_pf *pf) { } ++ ++static inline void ice_ptp_reset(struct ice_pf *pf, ++ enum ice_reset_req reset_type) ++{ ++} ++ ++static inline void ice_ptp_prepare_for_reset(struct ice_pf *pf, ++ enum ice_reset_req reset_type) ++{ ++} + static inline void ice_ptp_init(struct ice_pf *pf) { } + static inline void ice_ptp_release(struct ice_pf *pf) { } + static inline void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0018-ice-rename-verify_cached-to-has_ready_bitmap.patch b/kernel-std/debian/patches/ice-VDF/0018-ice-rename-verify_cached-to-has_ready_bitmap.patch new file mode 100644 index 00000000..a17f0f89 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0018-ice-rename-verify_cached-to-has_ready_bitmap.patch @@ -0,0 +1,119 @@ +From 084497314e63f3d92178bc44500a27a277abc378 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:51 -0800 +Subject: [PATCH 18/36] ice: rename verify_cached to has_ready_bitmap + +The tx->verify_cached flag is used to inform the Tx timestamp tracking +code whether it needs to verify the cached Tx timestamp value against +a previous captured value. This is necessary on E810 hardware which does +not have a Tx timestamp ready bitmap. + +In addition, we currently rely on the fact that the +ice_get_phy_tx_tstamp_ready() function returns all 1s for E810 hardware. +Instead of introducing a brand new flag, rename and verify_cached to +has_ready_bitmap, inverting the relevant checks. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 3f2216e8dbce04da5376ea7df410541f7b687cb0) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 12 ++++++------ + drivers/net/ethernet/intel/ice/ice_ptp.h | 8 +++++--- + 2 files changed, 11 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 20d1d22235d3..a8c6b83579e6 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -606,11 +606,11 @@ void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) + * timestamp. If it is not, skip this for now assuming it hasn't yet + * been captured by hardware. + */ +- if (!drop_ts && tx->verify_cached && ++ if (!drop_ts && !tx->has_ready_bitmap && + raw_tstamp == tx->tstamps[idx].cached_tstamp) + return; + +- if (tx->verify_cached && raw_tstamp) ++ if (!tx->has_ready_bitmap && raw_tstamp) + tx->tstamps[idx].cached_tstamp = raw_tstamp; + clear_bit(idx, tx->in_use); + skb = tx->tstamps[idx].skb; +@@ -751,7 +751,7 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + * from the last cached timestamp. If it is not, skip this for + * now assuming it hasn't yet been captured by hardware. + */ +- if (!drop_ts && tx->verify_cached && ++ if (!drop_ts && !tx->has_ready_bitmap && + raw_tstamp == tx->tstamps[idx].cached_tstamp) + continue; + +@@ -761,7 +761,7 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + + skip_ts_read: + spin_lock_irqsave(&tx->lock, flags); +- if (tx->verify_cached && raw_tstamp) ++ if (!tx->has_ready_bitmap && raw_tstamp) + tx->tstamps[idx].cached_tstamp = raw_tstamp; + clear_bit(idx, tx->in_use); + skb = tx->tstamps[idx].skb; +@@ -1014,7 +1014,7 @@ ice_ptp_init_tx_e82x(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port) + tx->block = port / ICE_PORTS_PER_QUAD; + tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E82X; + tx->len = INDEX_PER_PORT_E82X; +- tx->verify_cached = 0; ++ tx->has_ready_bitmap = 1; + + return ice_ptp_alloc_tx_tracker(tx); + } +@@ -1037,7 +1037,7 @@ ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx) + * verify new timestamps against cached copy of the last read + * timestamp. + */ +- tx->verify_cached = 1; ++ tx->has_ready_bitmap = 0; + + return ice_ptp_alloc_tx_tracker(tx); + } +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index cd74712a17a1..1486a0b3b016 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -100,7 +100,7 @@ struct ice_perout_channel { + * the last timestamp we read for a given index. If the current timestamp + * value is the same as the cached value, we assume a new timestamp hasn't + * been captured. This avoids reporting stale timestamps to the stack. This is +- * only done if the verify_cached flag is set in ice_ptp_tx structure. ++ * only done if the has_ready_bitmap flag is not set in ice_ptp_tx structure. + */ + struct ice_tx_tstamp { + struct sk_buff *skb; +@@ -130,7 +130,9 @@ enum ice_tx_tstamp_work { + * @init: if true, the tracker is initialized; + * @calibrating: if true, the PHY is calibrating the Tx offset. During this + * window, timestamps are temporarily disabled. +- * @verify_cached: if true, verify new timestamp differs from last read value ++ * @has_ready_bitmap: if true, the hardware has a valid Tx timestamp ready ++ * bitmap register. If false, fall back to verifying new ++ * timestamp values against previously cached copy. + * @last_ll_ts_idx_read: index of the last LL TS read by the FW + */ + struct ice_ptp_tx { +@@ -143,7 +145,7 @@ struct ice_ptp_tx { + u8 len; + u8 init : 1; + u8 calibrating : 1; +- u8 verify_cached : 1; ++ u8 has_ready_bitmap : 1; + s8 last_ll_ts_idx_read; + }; + +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0019-ice-don-t-check-has_ready_bitmap-in-E810-functions.patch b/kernel-std/debian/patches/ice-VDF/0019-ice-don-t-check-has_ready_bitmap-in-E810-functions.patch new file mode 100644 index 00000000..d1701f9e --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0019-ice-don-t-check-has_ready_bitmap-in-E810-functions.patch @@ -0,0 +1,77 @@ +From 375bced6b51243a8c8708204dd32960d076d5b83 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:52 -0800 +Subject: [PATCH 19/36] ice: don't check has_ready_bitmap in E810 functions + +E810 hardware does not have a Tx timestamp ready bitmap. Don't check +has_ready_bitmap in E810-specific functions. +Add has_ready_bitmap check in ice_ptp_process_tx_tstamp() to stop +relying on the fact that ice_get_phy_tx_tstamp_ready() returns all 1s. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit fea82915fca626eaa83f36d8a23194e8593ef4b4) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index a8c6b83579e6..ddc2dd0b2a28 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -601,17 +601,13 @@ void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) + /* Read the low 32 bit value */ + raw_tstamp |= (u64)rd32(&pf->hw, PF_SB_ATQBAH); + +- /* For PHYs which don't implement a proper timestamp ready bitmap, +- * verify that the timestamp value is different from the last cached +- * timestamp. If it is not, skip this for now assuming it hasn't yet +- * been captured by hardware. ++ /* Devices using this interface always verify the timestamp differs ++ * relative to the last cached timestamp value. + */ +- if (!drop_ts && !tx->has_ready_bitmap && +- raw_tstamp == tx->tstamps[idx].cached_tstamp) ++ if (raw_tstamp == tx->tstamps[idx].cached_tstamp) + return; + +- if (!tx->has_ready_bitmap && raw_tstamp) +- tx->tstamps[idx].cached_tstamp = raw_tstamp; ++ tx->tstamps[idx].cached_tstamp = raw_tstamp; + clear_bit(idx, tx->in_use); + skb = tx->tstamps[idx].skb; + tx->tstamps[idx].skb = NULL; +@@ -701,9 +697,11 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + hw = &pf->hw; + + /* Read the Tx ready status first */ +- err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready); +- if (err) +- return; ++ if (tx->has_ready_bitmap) { ++ err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready); ++ if (err) ++ return; ++ } + + /* Drop packets if the link went down */ + link_up = ptp_port->link_up; +@@ -731,7 +729,8 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) + * If we do not, the hardware logic for generating a new + * interrupt can get stuck on some devices. + */ +- if (!(tstamp_ready & BIT_ULL(phy_idx))) { ++ if (tx->has_ready_bitmap && ++ !(tstamp_ready & BIT_ULL(phy_idx))) { + if (drop_ts) + goto skip_ts_read; + +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0020-ice-rename-ice_ptp_tx_cfg_intr.patch b/kernel-std/debian/patches/ice-VDF/0020-ice-rename-ice_ptp_tx_cfg_intr.patch new file mode 100644 index 00000000..30d0631e --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0020-ice-rename-ice_ptp_tx_cfg_intr.patch @@ -0,0 +1,88 @@ +From a5318a3a04ed9535ab18ef0f0537b3d33862bee9 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:53 -0800 +Subject: [PATCH 20/36] ice: rename ice_ptp_tx_cfg_intr + +The ice_ptp_tx_cfg_intr() function sends a control queue message to +configure the PHY timestamp interrupt block. This is a very similar name +to a function which is used to configure the MAC Other Interrupt Cause +Enable register. + +Rename this function to ice_ptp_cfg_phy_interrupt in order to make it +more obvious to the reader what action it performs, and distinguish it +from other similarly named functions. + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 1abefdca85e8664374f53c7bc80d5f5f827ce711) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index ddc2dd0b2a28..c6e9d77fc59b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1455,14 +1455,14 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + } + + /** +- * ice_ptp_tx_ena_intr - Enable or disable the Tx timestamp interrupt ++ * ice_ptp_cfg_phy_interrupt - Configure PHY interrupt settings + * @pf: PF private structure + * @ena: bool value to enable or disable interrupt + * @threshold: Minimum number of packets at which intr is triggered + * + * Utility function to enable or disable Tx timestamp interrupt and threshold + */ +-static int ice_ptp_tx_ena_intr(struct ice_pf *pf, bool ena, u32 threshold) ++static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold) + { + struct ice_hw *hw = &pf->hw; + int err = 0; +@@ -2664,8 +2664,8 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + struct ice_ptp *ptp = &pf->ptp; + struct ice_hw *hw = &pf->hw; + struct timespec64 ts; +- int err, itr = 1; + u64 time_diff; ++ int err; + + if (ptp->state == ICE_PTP_READY) { + ice_ptp_prepare_for_reset(pf, reset_type); +@@ -2716,7 +2716,7 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + + if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ +- err = ice_ptp_tx_ena_intr(pf, true, itr); ++ err = ice_ptp_cfg_phy_interrupt(pf, true, 1); + if (err) + goto err; + } +@@ -2967,7 +2967,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + { + struct ice_hw *hw = &pf->hw; + struct timespec64 ts; +- int err, itr = 1; ++ int err; + + err = ice_ptp_init_phc(hw); + if (err) { +@@ -3002,7 +3002,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf) + + if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ +- err = ice_ptp_tx_ena_intr(pf, true, itr); ++ err = ice_ptp_cfg_phy_interrupt(pf, true, 1); + if (err) + goto err_exit; + } +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0021-ice-factor-out-ice_ptp_rebuild_owner.patch b/kernel-std/debian/patches/ice-VDF/0021-ice-factor-out-ice_ptp_rebuild_owner.patch new file mode 100644 index 00000000..075359c8 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0021-ice-factor-out-ice_ptp_rebuild_owner.patch @@ -0,0 +1,191 @@ +From 9411c5b82a7196b9712488631fd14e67e2d919fa Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:54 -0800 +Subject: [PATCH 21/36] ice: factor out ice_ptp_rebuild_owner() + +The ice_ptp_reset() function uses a goto to skip past clock owner +operations if performing a PF reset or if the device is not the clock +owner. This is a bit confusing. Factor this out into +ice_ptp_rebuild_owner() instead. + +The ice_ptp_reset() function is called by ice_rebuild() to restore PTP +functionality after a device reset. Follow the convention set by the +ice_main.c file and rename this function to ice_ptp_rebuild(), in the +same way that we have ice_prepare_for_reset() and +ice_ptp_prepare_for_reset(). + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 803bef817807d2d36c930dada20c96fffae0dd19) +[Adjust ice_ptp.h with the context change.] +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_main.c | 2 +- + drivers/net/ethernet/intel/ice/ice_ptp.c | 62 ++++++++++++++--------- + drivers/net/ethernet/intel/ice/ice_ptp.h | 6 +-- + 3 files changed, 42 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index d5321410f2d7..a04dcc89c35d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -7533,7 +7533,7 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + * fail. + */ + if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) +- ice_ptp_reset(pf, reset_type); ++ ice_ptp_rebuild(pf, reset_type); + + if (ice_is_feature_supported(pf, ICE_F_GNSS)) + ice_gnss_init(pf); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index c6e9d77fc59b..780aa242c86b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -2655,11 +2655,13 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + } + + /** +- * ice_ptp_reset - Initialize PTP hardware clock support after reset ++ * ice_ptp_rebuild_owner - Initialize PTP clock owner after reset + * @pf: Board private structure +- * @reset_type: the reset type being performed ++ * ++ * Companion function for ice_ptp_rebuild() which handles tasks that only the ++ * PTP clock owner instance should perform. + */ +-void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) ++static int ice_ptp_rebuild_owner(struct ice_pf *pf) + { + struct ice_ptp *ptp = &pf->ptp; + struct ice_hw *hw = &pf->hw; +@@ -2667,32 +2669,21 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + u64 time_diff; + int err; + +- if (ptp->state == ICE_PTP_READY) { +- ice_ptp_prepare_for_reset(pf, reset_type); +- } else if (ptp->state != ICE_PTP_RESETTING) { +- err = -EINVAL; +- dev_err(ice_pf_to_dev(pf), "PTP was not initialized\n"); +- goto err; +- } +- +- if (reset_type == ICE_RESET_PFR || !ice_pf_src_tmr_owned(pf)) +- goto pfr; +- + err = ice_ptp_init_phc(hw); + if (err) +- goto err; ++ return err; + + /* Acquire the global hardware lock */ + if (!ice_ptp_lock(hw)) { + err = -EBUSY; +- goto err; ++ return err; + } + + /* Write the increment time value to PHY and LAN */ + err = ice_ptp_write_incval(hw, ice_base_incval(pf)); + if (err) { + ice_ptp_unlock(hw); +- goto err; ++ return err; + } + + /* Write the initial Time value to PHY and LAN using the cached PHC +@@ -2708,7 +2699,7 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + err = ice_ptp_write_init(pf, &ts); + if (err) { + ice_ptp_unlock(hw); +- goto err; ++ return err; + } + + /* Release the global hardware lock */ +@@ -2717,11 +2708,39 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ + err = ice_ptp_cfg_phy_interrupt(pf, true, 1); ++ if (err) ++ return err; ++ ++ ice_ptp_restart_all_phy(pf); ++ } ++ ++ return 0; ++} ++ ++/** ++ * ice_ptp_rebuild - Initialize PTP hardware clock support after reset ++ * @pf: Board private structure ++ * @reset_type: the reset type being performed ++ */ ++void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) ++{ ++ struct ice_ptp *ptp = &pf->ptp; ++ int err; ++ ++ if (ptp->state == ICE_PTP_READY) { ++ ice_ptp_prepare_for_reset(pf, reset_type); ++ } else if (ptp->state != ICE_PTP_RESETTING) { ++ err = -EINVAL; ++ dev_err(ice_pf_to_dev(pf), "PTP was not initialized\n"); ++ goto err; ++ } ++ ++ if (ice_pf_src_tmr_owned(pf) && reset_type != ICE_RESET_PFR) { ++ err = ice_ptp_rebuild_owner(pf); + if (err) + goto err; + } + +-pfr: + /* Init Tx structures */ + if (ice_is_e810(&pf->hw)) { + err = ice_ptp_init_tx_e810(pf, &ptp->port.tx); +@@ -2736,11 +2755,6 @@ void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type) + + ptp->state = ICE_PTP_READY; + +- /* Restart the PHY timestamping block */ +- if (!test_bit(ICE_PFR_REQ, pf->state) && +- ice_pf_src_tmr_owned(pf)) +- ice_ptp_restart_all_phy(pf); +- + /* Start periodic work going */ + kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 1486a0b3b016..352405a2daf2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -317,7 +317,7 @@ enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf); + void + ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, + union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb); +-void ice_ptp_reset(struct ice_pf *pf, enum ice_reset_req reset_type); ++void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type); + void ice_ptp_prepare_for_reset(struct ice_pf *pf, + enum ice_reset_req reset_type); + void ice_ptp_init(struct ice_pf *pf); +@@ -355,8 +355,8 @@ static inline void + ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, + union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb) { } + +-static inline void ice_ptp_reset(struct ice_pf *pf, +- enum ice_reset_req reset_type) ++static inline void ice_ptp_rebuild(struct ice_pf *pf, ++ enum ice_reset_req reset_type) + { + } + +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0022-ice-stop-destroying-and-reinitalizing-Tx-tracker-dur.patch b/kernel-std/debian/patches/ice-VDF/0022-ice-stop-destroying-and-reinitalizing-Tx-tracker-dur.patch new file mode 100644 index 00000000..8e2133b5 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0022-ice-stop-destroying-and-reinitalizing-Tx-tracker-dur.patch @@ -0,0 +1,93 @@ +From 1c89a9e26f669bead5ebcac38fa98c20c517769c Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Thu, 25 Jan 2024 13:57:55 -0800 +Subject: [PATCH 22/36] ice: stop destroying and reinitalizing Tx tracker + during reset + +The ice driver currently attempts to destroy and re-initialize the Tx +timestamp tracker during the reset flow. The release of the Tx tracker +only happened during CORE reset or GLOBAL reset. The ice_ptp_rebuild() +function always calls the ice_ptp_init_tx function which will allocate +a new tracker data structure, resulting in memory leaks during PF reset. + +Certainly the driver should not be allocating a new tracker without +removing the old tracker data, as this results in a memory leak. +Additionally, there's no reason to remove the tracker memory during a +reset. Remove this logic from the reset and rebuild flow. Instead of +releasing the Tx tracker, flush outstanding timestamps just before we +reset the PHY timestamp block in ice_ptp_cfg_phy_interrupt(). + +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Paolo Abeni +(cherry picked from commit 7a25fe5cd5fb2265065ac6765c53c0a1f1e874d3) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 33 +++++++++++++++--------- + 1 file changed, 21 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 780aa242c86b..48ec59fc5d87 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -963,6 +963,22 @@ ice_ptp_mark_tx_tracker_stale(struct ice_ptp_tx *tx) + spin_unlock_irqrestore(&tx->lock, flags); + } + ++/** ++ * ice_ptp_flush_all_tx_tracker - Flush all timestamp trackers on this clock ++ * @pf: Board private structure ++ * ++ * Called by the clock owner to flush all the Tx timestamp trackers associated ++ * with the clock. ++ */ ++static void ++ice_ptp_flush_all_tx_tracker(struct ice_pf *pf) ++{ ++ struct ice_ptp_port *port; ++ ++ list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member) ++ ice_ptp_flush_tx_tracker(ptp_port_to_pf(port), &port->tx); ++} ++ + /** + * ice_ptp_release_tx_tracker - Release allocated memory for Tx tracker + * @pf: Board private structure +@@ -2705,6 +2721,11 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf) + /* Release the global hardware lock */ + ice_ptp_unlock(hw); + ++ /* Flush software tracking of any outstanding timestamps since we're ++ * about to flush the PHY timestamp block. ++ */ ++ ice_ptp_flush_all_tx_tracker(pf); ++ + if (!ice_is_e810(hw)) { + /* Enable quad interrupts */ + err = ice_ptp_cfg_phy_interrupt(pf, true, 1); +@@ -2741,18 +2762,6 @@ void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) + goto err; + } + +- /* Init Tx structures */ +- if (ice_is_e810(&pf->hw)) { +- err = ice_ptp_init_tx_e810(pf, &ptp->port.tx); +- } else { +- kthread_init_delayed_work(&ptp->port.ov_work, +- ice_ptp_wait_for_offsets); +- err = ice_ptp_init_tx_e82x(pf, &ptp->port.tx, +- ptp->port.port_num); +- } +- if (err) +- goto err; +- + ptp->state = ICE_PTP_READY; + + /* Start periodic work going */ +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0023-ice-Remove-and-readd-netdev-during-devlink-reload.patch b/kernel-std/debian/patches/ice-VDF/0023-ice-Remove-and-readd-netdev-during-devlink-reload.patch new file mode 100644 index 00000000..3a902574 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0023-ice-Remove-and-readd-netdev-during-devlink-reload.patch @@ -0,0 +1,457 @@ +From 6f1d1fa58f58ff3f6ce61ab502bd29227ca1bb3f Mon Sep 17 00:00:00 2001 +From: Wojciech Drewek +Date: Mon, 5 Feb 2024 14:03:56 +0100 +Subject: [PATCH 23/36] ice: Remove and readd netdev during devlink reload + +Recent changes to the devlink reload (commit 9b2348e2d6c9 +("devlink: warn about existing entities during reload-reinit")) +force the drivers to destroy devlink ports during reinit. +Adjust ice driver to this requirement, unregister netdvice, destroy +devlink port. ice_init_eth() was removed and all the common code +between probe and reload was moved to ice_load(). + +During devlink reload we can't take devl_lock (it's already taken) +and in ice_probe() we have to lock it. Use devl_* variant of the API +which does not acquire and release devl_lock. Guard ice_load() +with devl_lock only in case of probe. + +Suggested-by: Jiri Pirko +Reviewed-by: Przemek Kitszel +Reviewed-by: Vadim Fedorenko +Reviewed-by: Simon Horman +Reviewed-by: Brett Creeley +Signed-off-by: Wojciech Drewek +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 41cc4e53934c30f1cf7745c257154e538c78a1f5) +[Adjust ice.h with the context change.] +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 2 + + drivers/net/ethernet/intel/ice/ice_devlink.c | 68 ++++++- + drivers/net/ethernet/intel/ice/ice_main.c | 186 ++++++------------- + 3 files changed, 125 insertions(+), 131 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 3278d032a2bd..d3f72f9fbcd7 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -978,6 +978,8 @@ int ice_stop(struct net_device *netdev); + void ice_service_task_schedule(struct ice_pf *pf); + int ice_load(struct ice_pf *pf); + void ice_unload(struct ice_pf *pf); ++int ice_init_dev(struct ice_pf *pf); ++void ice_deinit_dev(struct ice_pf *pf); + + /** + * ice_set_rdma_cap - enable RDMA support +diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c +index 3a2261823d93..43007e3674c4 100644 +--- a/drivers/net/ethernet/intel/ice/ice_devlink.c ++++ b/drivers/net/ethernet/intel/ice/ice_devlink.c +@@ -444,6 +444,20 @@ ice_devlink_reload_empr_start(struct ice_pf *pf, + return 0; + } + ++/** ++ * ice_devlink_reinit_down - unload given PF ++ * @pf: pointer to the PF struct ++ */ ++static void ice_devlink_reinit_down(struct ice_pf *pf) ++{ ++ /* No need to take devl_lock, it's already taken by devlink API */ ++ ice_unload(pf); ++ rtnl_lock(); ++ ice_vsi_decfg(ice_get_main_vsi(pf)); ++ rtnl_unlock(); ++ ice_deinit_dev(pf); ++} ++ + /** + * ice_devlink_reload_down - prepare for reload + * @devlink: pointer to the devlink instance to reload +@@ -477,7 +491,7 @@ ice_devlink_reload_down(struct devlink *devlink, bool netns_change, + "Remove all VFs before doing reinit\n"); + return -EOPNOTSUPP; + } +- ice_unload(pf); ++ ice_devlink_reinit_down(pf); + return 0; + case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: + return ice_devlink_reload_empr_start(pf, extack); +@@ -1240,6 +1254,45 @@ static int ice_devlink_set_parent(struct devlink_rate *devlink_rate, + return status; + } + ++/** ++ * ice_devlink_reinit_up - do reinit of the given PF ++ * @pf: pointer to the PF struct ++ */ ++static int ice_devlink_reinit_up(struct ice_pf *pf) ++{ ++ struct ice_vsi *vsi = ice_get_main_vsi(pf); ++ struct ice_vsi_cfg_params params; ++ int err; ++ ++ err = ice_init_dev(pf); ++ if (err) ++ return err; ++ ++ params = ice_vsi_to_params(vsi); ++ params.flags = ICE_VSI_FLAG_INIT; ++ ++ rtnl_lock(); ++ err = ice_vsi_cfg(vsi, ¶ms); ++ rtnl_unlock(); ++ if (err) ++ goto err_vsi_cfg; ++ ++ /* No need to take devl_lock, it's already taken by devlink API */ ++ err = ice_load(pf); ++ if (err) ++ goto err_load; ++ ++ return 0; ++ ++err_load: ++ rtnl_lock(); ++ ice_vsi_decfg(vsi); ++ rtnl_unlock(); ++err_vsi_cfg: ++ ice_deinit_dev(pf); ++ return err; ++} ++ + /** + * ice_devlink_reload_up - do reload up after reinit + * @devlink: pointer to the devlink instance reloading +@@ -1260,7 +1313,7 @@ ice_devlink_reload_up(struct devlink *devlink, + switch (action) { + case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: + *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); +- return ice_load(pf); ++ return ice_devlink_reinit_up(pf); + case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: + *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); + return ice_devlink_reload_empr_finish(pf, extack); +@@ -1540,6 +1593,7 @@ static const struct devlink_port_ops ice_devlink_port_ops = { + * @pf: the PF to create a devlink port for + * + * Create and register a devlink_port for this PF. ++ * This function has to be called under devl_lock. + * + * Return: zero on success or an error code on failure. + */ +@@ -1552,6 +1606,8 @@ int ice_devlink_create_pf_port(struct ice_pf *pf) + struct device *dev; + int err; + ++ devlink = priv_to_devlink(pf); ++ + dev = ice_pf_to_dev(pf); + + devlink_port = &pf->devlink_port; +@@ -1572,10 +1628,9 @@ int ice_devlink_create_pf_port(struct ice_pf *pf) + ice_devlink_set_switch_id(pf, &attrs.switch_id); + + devlink_port_attrs_set(devlink_port, &attrs); +- devlink = priv_to_devlink(pf); + +- err = devlink_port_register_with_ops(devlink, devlink_port, vsi->idx, +- &ice_devlink_port_ops); ++ err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx, ++ &ice_devlink_port_ops); + if (err) { + dev_err(dev, "Failed to create devlink port for PF %d, error %d\n", + pf->hw.pf_id, err); +@@ -1590,10 +1645,11 @@ int ice_devlink_create_pf_port(struct ice_pf *pf) + * @pf: the PF to cleanup + * + * Unregisters the devlink_port structure associated with this PF. ++ * This function has to be called under devl_lock. + */ + void ice_devlink_destroy_pf_port(struct ice_pf *pf) + { +- devlink_port_unregister(&pf->devlink_port); ++ devl_port_unregister(&pf->devlink_port); + } + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index a04dcc89c35d..d3340114297a 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -4588,90 +4588,6 @@ static void ice_decfg_netdev(struct ice_vsi *vsi) + vsi->netdev = NULL; + } + +-static int ice_start_eth(struct ice_vsi *vsi) +-{ +- int err; +- +- err = ice_init_mac_fltr(vsi->back); +- if (err) +- return err; +- +- err = ice_vsi_open(vsi); +- if (err) +- ice_fltr_remove_all(vsi); +- +- return err; +-} +- +-static void ice_stop_eth(struct ice_vsi *vsi) +-{ +- ice_fltr_remove_all(vsi); +- ice_vsi_close(vsi); +-} +- +-static int ice_init_eth(struct ice_pf *pf) +-{ +- struct ice_vsi *vsi = ice_get_main_vsi(pf); +- int err; +- +- if (!vsi) +- return -EINVAL; +- +- /* init channel list */ +- INIT_LIST_HEAD(&vsi->ch_list); +- +- err = ice_cfg_netdev(vsi); +- if (err) +- return err; +- /* Setup DCB netlink interface */ +- ice_dcbnl_setup(vsi); +- +- err = ice_init_mac_fltr(pf); +- if (err) +- goto err_init_mac_fltr; +- +- err = ice_devlink_create_pf_port(pf); +- if (err) +- goto err_devlink_create_pf_port; +- +- SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port); +- +- err = ice_register_netdev(vsi); +- if (err) +- goto err_register_netdev; +- +- err = ice_tc_indir_block_register(vsi); +- if (err) +- goto err_tc_indir_block_register; +- +- ice_napi_add(vsi); +- +- return 0; +- +-err_tc_indir_block_register: +- ice_unregister_netdev(vsi); +-err_register_netdev: +- ice_devlink_destroy_pf_port(pf); +-err_devlink_create_pf_port: +-err_init_mac_fltr: +- ice_decfg_netdev(vsi); +- return err; +-} +- +-static void ice_deinit_eth(struct ice_pf *pf) +-{ +- struct ice_vsi *vsi = ice_get_main_vsi(pf); +- +- if (!vsi) +- return; +- +- ice_vsi_close(vsi); +- ice_unregister_netdev(vsi); +- ice_devlink_destroy_pf_port(pf); +- ice_tc_indir_block_unregister(vsi); +- ice_decfg_netdev(vsi); +-} +- + /** + * ice_wait_for_fw - wait for full FW readiness + * @hw: pointer to the hardware structure +@@ -4697,7 +4613,7 @@ static int ice_wait_for_fw(struct ice_hw *hw, u32 timeout) + return -ETIMEDOUT; + } + +-static int ice_init_dev(struct ice_pf *pf) ++int ice_init_dev(struct ice_pf *pf) + { + struct device *dev = ice_pf_to_dev(pf); + struct ice_hw *hw = &pf->hw; +@@ -4790,7 +4706,7 @@ static int ice_init_dev(struct ice_pf *pf) + return err; + } + +-static void ice_deinit_dev(struct ice_pf *pf) ++void ice_deinit_dev(struct ice_pf *pf) + { + ice_free_irq_msix_misc(pf); + ice_deinit_pf(pf); +@@ -5091,31 +5007,47 @@ static void ice_deinit(struct ice_pf *pf) + /** + * ice_load - load pf by init hw and starting VSI + * @pf: pointer to the pf instance ++ * ++ * This function has to be called under devl_lock. + */ + int ice_load(struct ice_pf *pf) + { +- struct ice_vsi_cfg_params params = {}; + struct ice_vsi *vsi; + int err; + +- err = ice_init_dev(pf); ++ devl_assert_locked(priv_to_devlink(pf)); ++ ++ vsi = ice_get_main_vsi(pf); ++ ++ /* init channel list */ ++ INIT_LIST_HEAD(&vsi->ch_list); ++ ++ err = ice_cfg_netdev(vsi); + if (err) + return err; + +- vsi = ice_get_main_vsi(pf); ++ /* Setup DCB netlink interface */ ++ ice_dcbnl_setup(vsi); + +- params = ice_vsi_to_params(vsi); +- params.flags = ICE_VSI_FLAG_INIT; ++ err = ice_init_mac_fltr(pf); ++ if (err) ++ goto err_init_mac_fltr; + +- rtnl_lock(); +- err = ice_vsi_cfg(vsi, ¶ms); ++ err = ice_devlink_create_pf_port(pf); + if (err) +- goto err_vsi_cfg; ++ goto err_devlink_create_pf_port; + +- err = ice_start_eth(ice_get_main_vsi(pf)); ++ SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port); ++ ++ err = ice_register_netdev(vsi); ++ if (err) ++ goto err_register_netdev; ++ ++ err = ice_tc_indir_block_register(vsi); + if (err) +- goto err_start_eth; +- rtnl_unlock(); ++ goto err_tc_indir_block_register; ++ ++ ice_napi_add(vsi); + + err = ice_init_rdma(pf); + if (err) +@@ -5129,29 +5061,35 @@ int ice_load(struct ice_pf *pf) + return 0; + + err_init_rdma: +- ice_vsi_close(ice_get_main_vsi(pf)); +- rtnl_lock(); +-err_start_eth: +- ice_vsi_decfg(ice_get_main_vsi(pf)); +-err_vsi_cfg: +- rtnl_unlock(); +- ice_deinit_dev(pf); ++ ice_tc_indir_block_unregister(vsi); ++err_tc_indir_block_register: ++ ice_unregister_netdev(vsi); ++err_register_netdev: ++ ice_devlink_destroy_pf_port(pf); ++err_devlink_create_pf_port: ++err_init_mac_fltr: ++ ice_decfg_netdev(vsi); + return err; + } + + /** + * ice_unload - unload pf by stopping VSI and deinit hw + * @pf: pointer to the pf instance ++ * ++ * This function has to be called under devl_lock. + */ + void ice_unload(struct ice_pf *pf) + { ++ struct ice_vsi *vsi = ice_get_main_vsi(pf); ++ ++ devl_assert_locked(priv_to_devlink(pf)); ++ + ice_deinit_features(pf); + ice_deinit_rdma(pf); +- rtnl_lock(); +- ice_stop_eth(ice_get_main_vsi(pf)); +- ice_vsi_decfg(ice_get_main_vsi(pf)); +- rtnl_unlock(); +- ice_deinit_dev(pf); ++ ice_tc_indir_block_unregister(vsi); ++ ice_unregister_netdev(vsi); ++ ice_devlink_destroy_pf_port(pf); ++ ice_decfg_netdev(vsi); + } + + /** +@@ -5249,27 +5187,23 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) + if (err) + goto err_init; + +- err = ice_init_eth(pf); ++ devl_lock(priv_to_devlink(pf)); ++ err = ice_load(pf); ++ devl_unlock(priv_to_devlink(pf)); + if (err) +- goto err_init_eth; +- +- err = ice_init_rdma(pf); +- if (err) +- goto err_init_rdma; ++ goto err_load; + + err = ice_init_devlink(pf); + if (err) + goto err_init_devlink; + +- ice_init_features(pf); +- + return 0; + + err_init_devlink: +- ice_deinit_rdma(pf); +-err_init_rdma: +- ice_deinit_eth(pf); +-err_init_eth: ++ devl_lock(priv_to_devlink(pf)); ++ ice_unload(pf); ++ devl_unlock(priv_to_devlink(pf)); ++err_load: + ice_deinit(pf); + err_init: + pci_disable_device(pdev); +@@ -5363,12 +5297,14 @@ static void ice_remove(struct pci_dev *pdev) + + if (!ice_is_safe_mode(pf)) + ice_remove_arfs(pf); +- ice_deinit_features(pf); ++ + ice_deinit_devlink(pf); +- ice_deinit_rdma(pf); +- ice_deinit_eth(pf); +- ice_deinit(pf); + ++ devl_lock(priv_to_devlink(pf)); ++ ice_unload(pf); ++ devl_unlock(priv_to_devlink(pf)); ++ ++ ice_deinit(pf); + ice_vsi_release_all(pf); + + ice_setup_mc_magic_wake(pf); +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0024-ice-remove-FW-logging-code.patch b/kernel-std/debian/patches/ice-VDF/0024-ice-remove-FW-logging-code.patch new file mode 100644 index 00000000..23bb1f17 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0024-ice-remove-FW-logging-code.patch @@ -0,0 +1,434 @@ +From e110839c4d9bfa4c885877a69573f48c008d3edd Mon Sep 17 00:00:00 2001 +From: Paul M Stillwell Jr +Date: Tue, 12 Dec 2023 21:07:11 -0800 +Subject: [PATCH 24/36] ice: remove FW logging code + +The FW logging code doesn't work because there is no way to set +cq_ena or uart_ena so remove the code. This code is the original +(v1) way of FW logging so it should be replaced with the v2 way. + +Signed-off-by: Paul M Stillwell Jr +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 1953fc720e603721764f31daae216a2851664167) +Signed-off-by: Jiping Ma +--- + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 78 ------- + drivers/net/ethernet/intel/ice/ice_common.c | 217 ------------------ + drivers/net/ethernet/intel/ice/ice_common.h | 1 - + drivers/net/ethernet/intel/ice/ice_main.c | 3 - + drivers/net/ethernet/intel/ice/ice_type.h | 20 -- + 5 files changed, 319 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 9bacb69ead8c..3b289e6a225b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2032,78 +2032,6 @@ struct ice_aqc_add_rdma_qset_data { + struct ice_aqc_add_tx_rdma_qset_entry rdma_qsets[]; + }; + +-/* Configure Firmware Logging Command (indirect 0xFF09) +- * Logging Information Read Response (indirect 0xFF10) +- * Note: The 0xFF10 command has no input parameters. +- */ +-struct ice_aqc_fw_logging { +- u8 log_ctrl; +-#define ICE_AQC_FW_LOG_AQ_EN BIT(0) +-#define ICE_AQC_FW_LOG_UART_EN BIT(1) +- u8 rsvd0; +- u8 log_ctrl_valid; /* Not used by 0xFF10 Response */ +-#define ICE_AQC_FW_LOG_AQ_VALID BIT(0) +-#define ICE_AQC_FW_LOG_UART_VALID BIT(1) +- u8 rsvd1[5]; +- __le32 addr_high; +- __le32 addr_low; +-}; +- +-enum ice_aqc_fw_logging_mod { +- ICE_AQC_FW_LOG_ID_GENERAL = 0, +- ICE_AQC_FW_LOG_ID_CTRL, +- ICE_AQC_FW_LOG_ID_LINK, +- ICE_AQC_FW_LOG_ID_LINK_TOPO, +- ICE_AQC_FW_LOG_ID_DNL, +- ICE_AQC_FW_LOG_ID_I2C, +- ICE_AQC_FW_LOG_ID_SDP, +- ICE_AQC_FW_LOG_ID_MDIO, +- ICE_AQC_FW_LOG_ID_ADMINQ, +- ICE_AQC_FW_LOG_ID_HDMA, +- ICE_AQC_FW_LOG_ID_LLDP, +- ICE_AQC_FW_LOG_ID_DCBX, +- ICE_AQC_FW_LOG_ID_DCB, +- ICE_AQC_FW_LOG_ID_NETPROXY, +- ICE_AQC_FW_LOG_ID_NVM, +- ICE_AQC_FW_LOG_ID_AUTH, +- ICE_AQC_FW_LOG_ID_VPD, +- ICE_AQC_FW_LOG_ID_IOSF, +- ICE_AQC_FW_LOG_ID_PARSER, +- ICE_AQC_FW_LOG_ID_SW, +- ICE_AQC_FW_LOG_ID_SCHEDULER, +- ICE_AQC_FW_LOG_ID_TXQ, +- ICE_AQC_FW_LOG_ID_RSVD, +- ICE_AQC_FW_LOG_ID_POST, +- ICE_AQC_FW_LOG_ID_WATCHDOG, +- ICE_AQC_FW_LOG_ID_TASK_DISPATCH, +- ICE_AQC_FW_LOG_ID_MNG, +- ICE_AQC_FW_LOG_ID_MAX, +-}; +- +-/* Defines for both above FW logging command/response buffers */ +-#define ICE_AQC_FW_LOG_ID_S 0 +-#define ICE_AQC_FW_LOG_ID_M (0xFFF << ICE_AQC_FW_LOG_ID_S) +- +-#define ICE_AQC_FW_LOG_CONF_SUCCESS 0 /* Used by response */ +-#define ICE_AQC_FW_LOG_CONF_BAD_INDX BIT(12) /* Used by response */ +- +-#define ICE_AQC_FW_LOG_EN_S 12 +-#define ICE_AQC_FW_LOG_EN_M (0xF << ICE_AQC_FW_LOG_EN_S) +-#define ICE_AQC_FW_LOG_INFO_EN BIT(12) /* Used by command */ +-#define ICE_AQC_FW_LOG_INIT_EN BIT(13) /* Used by command */ +-#define ICE_AQC_FW_LOG_FLOW_EN BIT(14) /* Used by command */ +-#define ICE_AQC_FW_LOG_ERR_EN BIT(15) /* Used by command */ +- +-/* Get/Clear FW Log (indirect 0xFF11) */ +-struct ice_aqc_get_clear_fw_log { +- u8 flags; +-#define ICE_AQC_FW_LOG_CLEAR BIT(0) +-#define ICE_AQC_FW_LOG_MORE_DATA_AVAIL BIT(1) +- u8 rsvd1[7]; +- __le32 addr_high; +- __le32 addr_low; +-}; +- + /* Download Package (indirect 0x0C40) */ + /* Also used for Update Package (indirect 0x0C41 and 0x0C42) */ + struct ice_aqc_download_pkg { +@@ -2448,8 +2376,6 @@ struct ice_aq_desc { + struct ice_aqc_add_rdma_qset add_rdma_qset; + struct ice_aqc_add_get_update_free_vsi vsi_cmd; + struct ice_aqc_add_update_free_vsi_resp add_update_free_vsi_res; +- struct ice_aqc_fw_logging fw_logging; +- struct ice_aqc_get_clear_fw_log get_clear_fw_log; + struct ice_aqc_download_pkg download_pkg; + struct ice_aqc_set_cgu_input_config set_cgu_input_config; + struct ice_aqc_get_cgu_input_config get_cgu_input_config; +@@ -2657,10 +2583,6 @@ enum ice_adminq_opc { + + /* Standalone Commands/Events */ + ice_aqc_opc_event_lan_overflow = 0x1001, +- +- /* debug commands */ +- ice_aqc_opc_fw_logging = 0xFF09, +- ice_aqc_opc_fw_logging_info = 0xFF10, + }; + + #endif /* _ICE_ADMINQ_CMD_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index acf6ac00f804..a5c4b7ad6a20 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -897,216 +897,6 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw) + devm_kfree(ice_hw_to_dev(hw), sw); + } + +-/** +- * ice_get_fw_log_cfg - get FW logging configuration +- * @hw: pointer to the HW struct +- */ +-static int ice_get_fw_log_cfg(struct ice_hw *hw) +-{ +- struct ice_aq_desc desc; +- __le16 *config; +- int status; +- u16 size; +- +- size = sizeof(*config) * ICE_AQC_FW_LOG_ID_MAX; +- config = kzalloc(size, GFP_KERNEL); +- if (!config) +- return -ENOMEM; +- +- ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging_info); +- +- status = ice_aq_send_cmd(hw, &desc, config, size, NULL); +- if (!status) { +- u16 i; +- +- /* Save FW logging information into the HW structure */ +- for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { +- u16 v, m, flgs; +- +- v = le16_to_cpu(config[i]); +- m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S; +- flgs = (v & ICE_AQC_FW_LOG_EN_M) >> ICE_AQC_FW_LOG_EN_S; +- +- if (m < ICE_AQC_FW_LOG_ID_MAX) +- hw->fw_log.evnts[m].cur = flgs; +- } +- } +- +- kfree(config); +- +- return status; +-} +- +-/** +- * ice_cfg_fw_log - configure FW logging +- * @hw: pointer to the HW struct +- * @enable: enable certain FW logging events if true, disable all if false +- * +- * This function enables/disables the FW logging via Rx CQ events and a UART +- * port based on predetermined configurations. FW logging via the Rx CQ can be +- * enabled/disabled for individual PF's. However, FW logging via the UART can +- * only be enabled/disabled for all PFs on the same device. +- * +- * To enable overall FW logging, the "cq_en" and "uart_en" enable bits in +- * hw->fw_log need to be set accordingly, e.g. based on user-provided input, +- * before initializing the device. +- * +- * When re/configuring FW logging, callers need to update the "cfg" elements of +- * the hw->fw_log.evnts array with the desired logging event configurations for +- * modules of interest. When disabling FW logging completely, the callers can +- * just pass false in the "enable" parameter. On completion, the function will +- * update the "cur" element of the hw->fw_log.evnts array with the resulting +- * logging event configurations of the modules that are being re/configured. FW +- * logging modules that are not part of a reconfiguration operation retain their +- * previous states. +- * +- * Before resetting the device, it is recommended that the driver disables FW +- * logging before shutting down the control queue. When disabling FW logging +- * ("enable" = false), the latest configurations of FW logging events stored in +- * hw->fw_log.evnts[] are not overridden to allow them to be reconfigured after +- * a device reset. +- * +- * When enabling FW logging to emit log messages via the Rx CQ during the +- * device's initialization phase, a mechanism alternative to interrupt handlers +- * needs to be used to extract FW log messages from the Rx CQ periodically and +- * to prevent the Rx CQ from being full and stalling other types of control +- * messages from FW to SW. Interrupts are typically disabled during the device's +- * initialization phase. +- */ +-static int ice_cfg_fw_log(struct ice_hw *hw, bool enable) +-{ +- struct ice_aqc_fw_logging *cmd; +- u16 i, chgs = 0, len = 0; +- struct ice_aq_desc desc; +- __le16 *data = NULL; +- u8 actv_evnts = 0; +- void *buf = NULL; +- int status = 0; +- +- if (!hw->fw_log.cq_en && !hw->fw_log.uart_en) +- return 0; +- +- /* Disable FW logging only when the control queue is still responsive */ +- if (!enable && +- (!hw->fw_log.actv_evnts || !ice_check_sq_alive(hw, &hw->adminq))) +- return 0; +- +- /* Get current FW log settings */ +- status = ice_get_fw_log_cfg(hw); +- if (status) +- return status; +- +- ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging); +- cmd = &desc.params.fw_logging; +- +- /* Indicate which controls are valid */ +- if (hw->fw_log.cq_en) +- cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_AQ_VALID; +- +- if (hw->fw_log.uart_en) +- cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_UART_VALID; +- +- if (enable) { +- /* Fill in an array of entries with FW logging modules and +- * logging events being reconfigured. +- */ +- for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { +- u16 val; +- +- /* Keep track of enabled event types */ +- actv_evnts |= hw->fw_log.evnts[i].cfg; +- +- if (hw->fw_log.evnts[i].cfg == hw->fw_log.evnts[i].cur) +- continue; +- +- if (!data) { +- data = devm_kcalloc(ice_hw_to_dev(hw), +- ICE_AQC_FW_LOG_ID_MAX, +- sizeof(*data), +- GFP_KERNEL); +- if (!data) +- return -ENOMEM; +- } +- +- val = i << ICE_AQC_FW_LOG_ID_S; +- val |= hw->fw_log.evnts[i].cfg << ICE_AQC_FW_LOG_EN_S; +- data[chgs++] = cpu_to_le16(val); +- } +- +- /* Only enable FW logging if at least one module is specified. +- * If FW logging is currently enabled but all modules are not +- * enabled to emit log messages, disable FW logging altogether. +- */ +- if (actv_evnts) { +- /* Leave if there is effectively no change */ +- if (!chgs) +- goto out; +- +- if (hw->fw_log.cq_en) +- cmd->log_ctrl |= ICE_AQC_FW_LOG_AQ_EN; +- +- if (hw->fw_log.uart_en) +- cmd->log_ctrl |= ICE_AQC_FW_LOG_UART_EN; +- +- buf = data; +- len = sizeof(*data) * chgs; +- desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); +- } +- } +- +- status = ice_aq_send_cmd(hw, &desc, buf, len, NULL); +- if (!status) { +- /* Update the current configuration to reflect events enabled. +- * hw->fw_log.cq_en and hw->fw_log.uart_en indicate if the FW +- * logging mode is enabled for the device. They do not reflect +- * actual modules being enabled to emit log messages. So, their +- * values remain unchanged even when all modules are disabled. +- */ +- u16 cnt = enable ? chgs : (u16)ICE_AQC_FW_LOG_ID_MAX; +- +- hw->fw_log.actv_evnts = actv_evnts; +- for (i = 0; i < cnt; i++) { +- u16 v, m; +- +- if (!enable) { +- /* When disabling all FW logging events as part +- * of device's de-initialization, the original +- * configurations are retained, and can be used +- * to reconfigure FW logging later if the device +- * is re-initialized. +- */ +- hw->fw_log.evnts[i].cur = 0; +- continue; +- } +- +- v = le16_to_cpu(data[i]); +- m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S; +- hw->fw_log.evnts[m].cur = hw->fw_log.evnts[m].cfg; +- } +- } +- +-out: +- devm_kfree(ice_hw_to_dev(hw), data); +- +- return status; +-} +- +-/** +- * ice_output_fw_log +- * @hw: pointer to the HW struct +- * @desc: pointer to the AQ message descriptor +- * @buf: pointer to the buffer accompanying the AQ message +- * +- * Formats a FW Log message and outputs it via the standard driver logs. +- */ +-void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf) +-{ +- ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg Start ]\n"); +- ice_debug_array(hw, ICE_DBG_FW_LOG, 16, 1, (u8 *)buf, +- le16_to_cpu(desc->datalen)); +- ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg End ]\n"); +-} +- + /** + * ice_get_itr_intrl_gran + * @hw: pointer to the HW struct +@@ -1164,11 +954,6 @@ int ice_init_hw(struct ice_hw *hw) + if (status) + goto err_unroll_cqinit; + +- /* Enable FW logging. Not fatal if this fails. */ +- status = ice_cfg_fw_log(hw, true); +- if (status) +- ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging.\n"); +- + status = ice_clear_pf_cfg(hw); + if (status) + goto err_unroll_cqinit; +@@ -1318,8 +1103,6 @@ void ice_deinit_hw(struct ice_hw *hw) + ice_free_hw_tbls(hw); + mutex_destroy(&hw->tnl_lock); + +- /* Attempt to disable FW logging before shutting down control queues */ +- ice_cfg_fw_log(hw, false); + ice_destroy_all_ctrlq(hw); + + /* Clear VSI contexts if not already cleared */ +diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h +index 7a966a0c224f..d47e5400351f 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.h ++++ b/drivers/net/ethernet/intel/ice/ice_common.h +@@ -199,7 +199,6 @@ ice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf, + struct ice_sq_cd *cd); + int ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle); + void ice_replay_post(struct ice_hw *hw); +-void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf); + struct ice_q_ctx * + ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle); + int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in); +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index d3340114297a..e5cc9790969c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -1535,9 +1535,6 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) + + ice_vc_process_vf_msg(pf, &event, &data); + break; +- case ice_aqc_opc_fw_logging: +- ice_output_fw_log(hw, &event.desc, event.msg_buf); +- break; + case ice_aqc_opc_lldp_set_mib_change: + ice_dcb_process_lldp_set_mib_change(pf, &event); + break; +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index b0f1f4db1d8b..6e1fed0d7384 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -731,24 +731,6 @@ struct ice_switch_info { + DECLARE_BITMAP(prof_res_bm[ICE_MAX_NUM_PROFILES], ICE_MAX_FV_WORDS); + }; + +-/* FW logging configuration */ +-struct ice_fw_log_evnt { +- u8 cfg : 4; /* New event enables to configure */ +- u8 cur : 4; /* Current/active event enables */ +-}; +- +-struct ice_fw_log_cfg { +- u8 cq_en : 1; /* FW logging is enabled via the control queue */ +- u8 uart_en : 1; /* FW logging is enabled via UART for all PFs */ +- u8 actv_evnts; /* Cumulation of currently enabled log events */ +- +-#define ICE_FW_LOG_EVNT_INFO (ICE_AQC_FW_LOG_INFO_EN >> ICE_AQC_FW_LOG_EN_S) +-#define ICE_FW_LOG_EVNT_INIT (ICE_AQC_FW_LOG_INIT_EN >> ICE_AQC_FW_LOG_EN_S) +-#define ICE_FW_LOG_EVNT_FLOW (ICE_AQC_FW_LOG_FLOW_EN >> ICE_AQC_FW_LOG_EN_S) +-#define ICE_FW_LOG_EVNT_ERR (ICE_AQC_FW_LOG_ERR_EN >> ICE_AQC_FW_LOG_EN_S) +- struct ice_fw_log_evnt evnts[ICE_AQC_FW_LOG_ID_MAX]; +-}; +- + /* Enum defining the different states of the mailbox snapshot in the + * PF-VF mailbox overflow detection algorithm. The snapshot can be in + * states: +@@ -890,8 +872,6 @@ struct ice_hw { + u8 fw_patch; /* firmware patch version */ + u32 fw_build; /* firmware build number */ + +- struct ice_fw_log_cfg fw_log; +- + /* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL + * register. Used for determining the ITR/INTRL granularity during + * initialization. +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0025-ice-configure-FW-logging.patch b/kernel-std/debian/patches/ice-VDF/0025-ice-configure-FW-logging.patch new file mode 100644 index 00000000..203cc8e8 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0025-ice-configure-FW-logging.patch @@ -0,0 +1,1083 @@ +From 752f352c0d7da9c6c07e4c8364082e201d20fdc2 Mon Sep 17 00:00:00 2001 +From: Paul M Stillwell Jr +Date: Tue, 12 Dec 2023 21:07:12 -0800 +Subject: [PATCH 25/36] ice: configure FW logging + +Users want the ability to debug FW issues by retrieving the +FW logs from the E8xx devices. Use debugfs to allow the user to +configure the log level and number of messages for FW logging. + +If FW logging is supported on the E8xx then the file 'fwlog' will be +created under the PCI device ID for the ice driver. If the file does not +exist then either the E8xx doesn't support FW logging or debugfs is not +enabled on the system. + +One thing users want to do is control which events are reported. The +user can read and write the 'fwlog/modules/' to get/set +the log levels. Each module in the FW that supports logging ht as a file +under 'fwlog/modules' that supports reading (to see what the current log +level is) and writing (to change the log level). + +The format to set the log levels for a module are: + + # echo > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/ + +The supported log levels are: + + * none + * error + * warning + * normal + * verbose + +Each level includes the messages from the previous/lower level + +The modules that are supported are: + + * general + * ctrl + * link + * link_topo + * dnl + * i2c + * sdp + * mdio + * adminq + * hdma + * lldp + * dcbx + * dcb + * xlr + * nvm + * auth + * vpd + * iosf + * parser + * sw + * scheduler + * txq + * rsvd + * post + * watchdog + * task_dispatch + * mng + * synce + * health + * tsdrv + * pfreg + * mdlver + * all + +The module 'all' is a special module which allows the user to read or +write to all of the modules. + +The following example command would set the DCB module to the 'normal' +log level: + + # echo normal > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/dcb + +If the user wants to set the DCB, Link, and the AdminQ modules to +'verbose' then the commands are: + + # echo verbose > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/dcb + # echo verbose > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/link + # echo verbose > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/adminq + +If the user wants to set all modules to the 'warning' level then the +command is: + + # echo warning > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/all + +If the user wants to disable logging for a module then they can set the +level to 'none'. An example setting the 'watchdog' module is: + + # echo none > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/watchdog + +If the user wants to see what the log level is for a specific module +then the command is: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/dcb + +This will return the log level for the DCB module. If the user wants to +see the log level for all the modules then the command is: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/modules/all + +Writing to the module file will update the configuration, but NOT enable the +configuration (that is a separate command). + +In addition to configuring the modules, the user can also configure the +number of log messages (nr_messages) to include in a single Admin Receive +Queue (ARQ) event.The range is 1-128 (1 means push every log message, 128 +means push only when the max AQ command buffer is full). The suggested +value is 10. + +To see/change the resolution the user can read/write the +'fwlog/nr_messages' file. An example changing the value to 50 is + + # echo 50 > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/nr_messages + +To see the current value of 'nr_messages' then the command is: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/nr_messages + +Signed-off-by: Paul M Stillwell Jr +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 96a9a9341cdaea0c3bce4c134e04a2a42ae899ac) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/Makefile | 4 +- + drivers/net/ethernet/intel/ice/ice.h | 9 + + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 80 ++++ + drivers/net/ethernet/intel/ice/ice_common.c | 6 + + drivers/net/ethernet/intel/ice/ice_debugfs.c | 359 ++++++++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.c | 261 +++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.h | 56 +++ + drivers/net/ethernet/intel/ice/ice_main.c | 18 + + drivers/net/ethernet/intel/ice/ice_type.h | 4 + + 9 files changed, 796 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/ethernet/intel/ice/ice_debugfs.c + create mode 100644 drivers/net/ethernet/intel/ice/ice_fwlog.c + create mode 100644 drivers/net/ethernet/intel/ice/ice_fwlog.h + +diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile +index 0679907980f7..8757bec23fb3 100644 +--- a/drivers/net/ethernet/intel/ice/Makefile ++++ b/drivers/net/ethernet/intel/ice/Makefile +@@ -34,7 +34,9 @@ ice-y := ice_main.o \ + ice_lag.o \ + ice_ethtool.o \ + ice_repr.o \ +- ice_tc_lib.o ++ ice_tc_lib.o \ ++ ice_fwlog.o \ ++ ice_debugfs.o + ice-$(CONFIG_PCI_IOV) += \ + ice_sriov.o \ + ice_virtchnl.o \ +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index d3f72f9fbcd7..7966ac61154c 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -559,6 +559,10 @@ struct ice_pf { + struct ice_vsi_stats **vsi_stats; + struct ice_sw *first_sw; /* first switch created by firmware */ + u16 eswitch_mode; /* current mode of eswitch */ ++ struct dentry *ice_debugfs_pf; ++ struct dentry *ice_debugfs_pf_fwlog; ++ /* keep track of all the dentrys for FW log modules */ ++ struct dentry **ice_debugfs_pf_fwlog_modules; + struct ice_vfs vfs; + DECLARE_BITMAP(features, ICE_F_MAX); + DECLARE_BITMAP(state, ICE_STATE_NBITS); +@@ -890,6 +894,11 @@ static inline bool ice_is_adq_active(struct ice_pf *pf) + return false; + } + ++void ice_debugfs_fwlog_init(struct ice_pf *pf); ++void ice_debugfs_init(void); ++void ice_debugfs_exit(void); ++void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module); ++ + bool netif_is_ice(const struct net_device *dev); + int ice_vsi_setup_tx_rings(struct ice_vsi *vsi); + int ice_vsi_setup_rx_rings(struct ice_vsi *vsi); +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 3b289e6a225b..347e4fed5e0d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2299,6 +2299,81 @@ struct ice_aqc_event_lan_overflow { + u8 reserved[8]; + }; + ++enum ice_aqc_fw_logging_mod { ++ ICE_AQC_FW_LOG_ID_GENERAL = 0, ++ ICE_AQC_FW_LOG_ID_CTRL, ++ ICE_AQC_FW_LOG_ID_LINK, ++ ICE_AQC_FW_LOG_ID_LINK_TOPO, ++ ICE_AQC_FW_LOG_ID_DNL, ++ ICE_AQC_FW_LOG_ID_I2C, ++ ICE_AQC_FW_LOG_ID_SDP, ++ ICE_AQC_FW_LOG_ID_MDIO, ++ ICE_AQC_FW_LOG_ID_ADMINQ, ++ ICE_AQC_FW_LOG_ID_HDMA, ++ ICE_AQC_FW_LOG_ID_LLDP, ++ ICE_AQC_FW_LOG_ID_DCBX, ++ ICE_AQC_FW_LOG_ID_DCB, ++ ICE_AQC_FW_LOG_ID_XLR, ++ ICE_AQC_FW_LOG_ID_NVM, ++ ICE_AQC_FW_LOG_ID_AUTH, ++ ICE_AQC_FW_LOG_ID_VPD, ++ ICE_AQC_FW_LOG_ID_IOSF, ++ ICE_AQC_FW_LOG_ID_PARSER, ++ ICE_AQC_FW_LOG_ID_SW, ++ ICE_AQC_FW_LOG_ID_SCHEDULER, ++ ICE_AQC_FW_LOG_ID_TXQ, ++ ICE_AQC_FW_LOG_ID_RSVD, ++ ICE_AQC_FW_LOG_ID_POST, ++ ICE_AQC_FW_LOG_ID_WATCHDOG, ++ ICE_AQC_FW_LOG_ID_TASK_DISPATCH, ++ ICE_AQC_FW_LOG_ID_MNG, ++ ICE_AQC_FW_LOG_ID_SYNCE, ++ ICE_AQC_FW_LOG_ID_HEALTH, ++ ICE_AQC_FW_LOG_ID_TSDRV, ++ ICE_AQC_FW_LOG_ID_PFREG, ++ ICE_AQC_FW_LOG_ID_MDLVER, ++ ICE_AQC_FW_LOG_ID_MAX, ++}; ++ ++/* Set FW Logging configuration (indirect 0xFF30) ++ * Query FW Logging (indirect 0xFF32) ++ */ ++struct ice_aqc_fw_log { ++ u8 cmd_flags; ++#define ICE_AQC_FW_LOG_CONF_UART_EN BIT(0) ++#define ICE_AQC_FW_LOG_CONF_AQ_EN BIT(1) ++#define ICE_AQC_FW_LOG_QUERY_REGISTERED BIT(2) ++#define ICE_AQC_FW_LOG_CONF_SET_VALID BIT(3) ++#define ICE_AQC_FW_LOG_AQ_QUERY BIT(2) ++ ++ u8 rsp_flag; ++ __le16 fw_rt_msb; ++ union { ++ struct { ++ __le32 fw_rt_lsb; ++ } sync; ++ struct { ++ __le16 log_resolution; ++#define ICE_AQC_FW_LOG_MIN_RESOLUTION (1) ++#define ICE_AQC_FW_LOG_MAX_RESOLUTION (128) ++ ++ __le16 mdl_cnt; ++ } cfg; ++ } ops; ++ __le32 addr_high; ++ __le32 addr_low; ++}; ++ ++/* Response Buffer for: ++ * Set Firmware Logging Configuration (0xFF30) ++ * Query FW Logging (0xFF32) ++ */ ++struct ice_aqc_fw_log_cfg_resp { ++ __le16 module_identifier; ++ u8 log_level; ++ u8 rsvd0; ++}; ++ + /** + * struct ice_aq_desc - Admin Queue (AQ) descriptor + * @flags: ICE_AQ_FLAG_* flags +@@ -2387,6 +2462,7 @@ struct ice_aq_desc { + struct ice_aqc_get_cgu_ref_prio get_cgu_ref_prio; + struct ice_aqc_get_cgu_info get_cgu_info; + struct ice_aqc_driver_shared_params drv_shared_params; ++ struct ice_aqc_fw_log fw_log; + struct ice_aqc_set_mac_lb set_mac_lb; + struct ice_aqc_alloc_free_res_cmd sw_res_ctrl; + struct ice_aqc_set_mac_cfg set_mac_cfg; +@@ -2583,6 +2659,10 @@ enum ice_adminq_opc { + + /* Standalone Commands/Events */ + ice_aqc_opc_event_lan_overflow = 0x1001, ++ ++ /* FW Logging Commands */ ++ ice_aqc_opc_fw_logs_config = 0xFF30, ++ ice_aqc_opc_fw_logs_query = 0xFF32, + }; + + #endif /* _ICE_ADMINQ_CMD_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index a5c4b7ad6a20..6dcba0577633 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -954,6 +954,11 @@ int ice_init_hw(struct ice_hw *hw) + if (status) + goto err_unroll_cqinit; + ++ status = ice_fwlog_init(hw); ++ if (status) ++ ice_debug(hw, ICE_DBG_FW_LOG, "Error initializing FW logging: %d\n", ++ status); ++ + status = ice_clear_pf_cfg(hw); + if (status) + goto err_unroll_cqinit; +@@ -1103,6 +1108,7 @@ void ice_deinit_hw(struct ice_hw *hw) + ice_free_hw_tbls(hw); + mutex_destroy(&hw->tnl_lock); + ++ ice_fwlog_deinit(hw); + ice_destroy_all_ctrlq(hw); + + /* Clear VSI contexts if not already cleared */ +diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c +new file mode 100644 +index 000000000000..3b0d9b214fd1 +--- /dev/null ++++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c +@@ -0,0 +1,359 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* Copyright (c) 2022, Intel Corporation. */ ++ ++#include ++#include ++#include ++#include ++#include "ice.h" ++ ++static struct dentry *ice_debugfs_root; ++ ++/* create a define that has an extra module that doesn't really exist. this ++ * is so we can add a module 'all' to easily enable/disable all the modules ++ */ ++#define ICE_NR_FW_LOG_MODULES (ICE_AQC_FW_LOG_ID_MAX + 1) ++ ++/* the ordering in this array is important. it matches the ordering of the ++ * values in the FW so the index is the same value as in ice_aqc_fw_logging_mod ++ */ ++static const char * const ice_fwlog_module_string[] = { ++ "general", ++ "ctrl", ++ "link", ++ "link_topo", ++ "dnl", ++ "i2c", ++ "sdp", ++ "mdio", ++ "adminq", ++ "hdma", ++ "lldp", ++ "dcbx", ++ "dcb", ++ "xlr", ++ "nvm", ++ "auth", ++ "vpd", ++ "iosf", ++ "parser", ++ "sw", ++ "scheduler", ++ "txq", ++ "rsvd", ++ "post", ++ "watchdog", ++ "task_dispatch", ++ "mng", ++ "synce", ++ "health", ++ "tsdrv", ++ "pfreg", ++ "mdlver", ++ "all", ++}; ++ ++/* the ordering in this array is important. it matches the ordering of the ++ * values in the FW so the index is the same value as in ice_fwlog_level ++ */ ++static const char * const ice_fwlog_level_string[] = { ++ "none", ++ "error", ++ "warning", ++ "normal", ++ "verbose", ++}; ++ ++/** ++ * ice_fwlog_print_module_cfg - print current FW logging module configuration ++ * @hw: pointer to the HW structure ++ * @module: module to print ++ * @s: the seq file to put data into ++ */ ++static void ++ice_fwlog_print_module_cfg(struct ice_hw *hw, int module, struct seq_file *s) ++{ ++ struct ice_fwlog_cfg *cfg = &hw->fwlog_cfg; ++ struct ice_fwlog_module_entry *entry; ++ ++ if (module != ICE_AQC_FW_LOG_ID_MAX) { ++ entry = &cfg->module_entries[module]; ++ ++ seq_printf(s, "\tModule: %s, Log Level: %s\n", ++ ice_fwlog_module_string[entry->module_id], ++ ice_fwlog_level_string[entry->log_level]); ++ } else { ++ int i; ++ ++ for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { ++ entry = &cfg->module_entries[i]; ++ ++ seq_printf(s, "\tModule: %s, Log Level: %s\n", ++ ice_fwlog_module_string[entry->module_id], ++ ice_fwlog_level_string[entry->log_level]); ++ } ++ } ++} ++ ++static int ice_find_module_by_dentry(struct ice_pf *pf, struct dentry *d) ++{ ++ int i, module; ++ ++ module = -1; ++ /* find the module based on the dentry */ ++ for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) { ++ if (d == pf->ice_debugfs_pf_fwlog_modules[i]) { ++ module = i; ++ break; ++ } ++ } ++ ++ return module; ++} ++ ++/** ++ * ice_debugfs_module_show - read from 'module' file ++ * @s: the opened file ++ * @v: pointer to the offset ++ */ ++static int ice_debugfs_module_show(struct seq_file *s, void *v) ++{ ++ const struct file *filp = s->file; ++ struct dentry *dentry; ++ struct ice_pf *pf; ++ int module; ++ ++ dentry = file_dentry(filp); ++ pf = s->private; ++ ++ module = ice_find_module_by_dentry(pf, dentry); ++ if (module < 0) { ++ dev_info(ice_pf_to_dev(pf), "unknown module\n"); ++ return -EINVAL; ++ } ++ ++ ice_fwlog_print_module_cfg(&pf->hw, module, s); ++ ++ return 0; ++} ++ ++static int ice_debugfs_module_open(struct inode *inode, struct file *filp) ++{ ++ return single_open(filp, ice_debugfs_module_show, inode->i_private); ++} ++ ++/** ++ * ice_debugfs_module_write - write into 'module' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_module_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = file_inode(filp)->i_private; ++ struct dentry *dentry = file_dentry(filp); ++ struct device *dev = ice_pf_to_dev(pf); ++ char user_val[16], *cmd_buf; ++ int module, log_level, cnt; ++ ++ /* don't allow partial writes or invalid input */ ++ if (*ppos != 0 || count > 8) ++ return -EINVAL; ++ ++ cmd_buf = memdup_user(buf, count); ++ if (IS_ERR(cmd_buf)) ++ return PTR_ERR(cmd_buf); ++ ++ module = ice_find_module_by_dentry(pf, dentry); ++ if (module < 0) { ++ dev_info(dev, "unknown module\n"); ++ return -EINVAL; ++ } ++ ++ cnt = sscanf(cmd_buf, "%s", user_val); ++ if (cnt != 1) ++ return -EINVAL; ++ ++ log_level = sysfs_match_string(ice_fwlog_level_string, user_val); ++ if (log_level < 0) { ++ dev_info(dev, "unknown log level '%s'\n", user_val); ++ return -EINVAL; ++ } ++ ++ if (module != ICE_AQC_FW_LOG_ID_MAX) { ++ ice_pf_fwlog_update_module(pf, log_level, module); ++ } else { ++ /* the module 'all' is a shortcut so that we can set ++ * all of the modules to the same level quickly ++ */ ++ int i; ++ ++ for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) ++ ice_pf_fwlog_update_module(pf, log_level, i); ++ } ++ ++ return count; ++} ++ ++static const struct file_operations ice_debugfs_module_fops = { ++ .owner = THIS_MODULE, ++ .open = ice_debugfs_module_open, ++ .read = seq_read, ++ .release = single_release, ++ .write = ice_debugfs_module_write, ++}; ++ ++/** ++ * ice_debugfs_nr_messages_read - read from 'nr_messages' file ++ * @filp: the opened file ++ * @buffer: where to write the data for the user to read ++ * @count: the size of the user's buffer ++ * @ppos: file position offset ++ */ ++static ssize_t ice_debugfs_nr_messages_read(struct file *filp, ++ char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ char buff[32] = {}; ++ ++ snprintf(buff, sizeof(buff), "%d\n", ++ hw->fwlog_cfg.log_resolution); ++ ++ return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); ++} ++ ++/** ++ * ice_debugfs_nr_messages_write - write into 'nr_messages' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_nr_messages_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct device *dev = ice_pf_to_dev(pf); ++ struct ice_hw *hw = &pf->hw; ++ char user_val[8], *cmd_buf; ++ s16 nr_messages; ++ ssize_t ret; ++ ++ /* don't allow partial writes or invalid input */ ++ if (*ppos != 0 || count > 4) ++ return -EINVAL; ++ ++ cmd_buf = memdup_user(buf, count); ++ if (IS_ERR(cmd_buf)) ++ return PTR_ERR(cmd_buf); ++ ++ ret = sscanf(cmd_buf, "%s", user_val); ++ if (ret != 1) ++ return -EINVAL; ++ ++ ret = kstrtos16(user_val, 0, &nr_messages); ++ if (ret) ++ return ret; ++ ++ if (nr_messages < ICE_AQC_FW_LOG_MIN_RESOLUTION || ++ nr_messages > ICE_AQC_FW_LOG_MAX_RESOLUTION) { ++ dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", ++ nr_messages, ICE_AQC_FW_LOG_MIN_RESOLUTION, ++ ICE_AQC_FW_LOG_MAX_RESOLUTION); ++ return -EINVAL; ++ } ++ ++ hw->fwlog_cfg.log_resolution = nr_messages; ++ ++ return count; ++} ++ ++static const struct file_operations ice_debugfs_nr_messages_fops = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .read = ice_debugfs_nr_messages_read, ++ .write = ice_debugfs_nr_messages_write, ++}; ++ ++/** ++ * ice_debugfs_fwlog_init - setup the debugfs directory ++ * @pf: the ice that is starting up ++ */ ++void ice_debugfs_fwlog_init(struct ice_pf *pf) ++{ ++ const char *name = pci_name(pf->pdev); ++ struct dentry *fw_modules_dir; ++ struct dentry **fw_modules; ++ int i; ++ ++ /* only support fw log commands on PF 0 */ ++ if (pf->hw.bus.func) ++ return; ++ ++ /* allocate space for this first because if it fails then we don't ++ * need to unwind ++ */ ++ fw_modules = kcalloc(ICE_NR_FW_LOG_MODULES, sizeof(*fw_modules), ++ GFP_KERNEL); ++ if (!fw_modules) ++ return; ++ ++ pf->ice_debugfs_pf = debugfs_create_dir(name, ice_debugfs_root); ++ if (IS_ERR(pf->ice_debugfs_pf)) ++ goto err_create_module_files; ++ ++ pf->ice_debugfs_pf_fwlog = debugfs_create_dir("fwlog", ++ pf->ice_debugfs_pf); ++ if (IS_ERR(pf->ice_debugfs_pf)) ++ goto err_create_module_files; ++ ++ fw_modules_dir = debugfs_create_dir("modules", ++ pf->ice_debugfs_pf_fwlog); ++ if (IS_ERR(fw_modules_dir)) ++ goto err_create_module_files; ++ ++ for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) { ++ fw_modules[i] = debugfs_create_file(ice_fwlog_module_string[i], ++ 0600, fw_modules_dir, pf, ++ &ice_debugfs_module_fops); ++ if (IS_ERR(fw_modules[i])) ++ goto err_create_module_files; ++ } ++ ++ debugfs_create_file("nr_messages", 0600, ++ pf->ice_debugfs_pf_fwlog, pf, ++ &ice_debugfs_nr_messages_fops); ++ ++ pf->ice_debugfs_pf_fwlog_modules = fw_modules; ++ ++ return; ++ ++err_create_module_files: ++ debugfs_remove_recursive(pf->ice_debugfs_pf_fwlog); ++ kfree(fw_modules); ++} ++ ++/** ++ * ice_debugfs_init - create root directory for debugfs entries ++ */ ++void ice_debugfs_init(void) ++{ ++ ice_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); ++ if (IS_ERR(ice_debugfs_root)) ++ pr_info("init of debugfs failed\n"); ++} ++ ++/** ++ * ice_debugfs_exit - remove debugfs entries ++ */ ++void ice_debugfs_exit(void) ++{ ++ debugfs_remove_recursive(ice_debugfs_root); ++ ice_debugfs_root = NULL; ++} +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.c b/drivers/net/ethernet/intel/ice/ice_fwlog.c +new file mode 100644 +index 000000000000..307e0d04f3fe +--- /dev/null ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.c +@@ -0,0 +1,261 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* Copyright (c) 2022, Intel Corporation. */ ++ ++#include "ice.h" ++#include "ice_common.h" ++#include "ice_fwlog.h" ++ ++/** ++ * ice_fwlog_init - Initialize FW logging configuration ++ * @hw: pointer to the HW structure ++ * ++ * This function should be called on driver initialization during ++ * ice_init_hw(). ++ */ ++int ice_fwlog_init(struct ice_hw *hw) ++{ ++ /* only support fw log commands on PF 0 */ ++ if (hw->bus.func) ++ return -EINVAL; ++ ++ ice_fwlog_set_supported(hw); ++ ++ if (ice_fwlog_supported(hw)) { ++ int status; ++ ++ /* read the current config from the FW and store it */ ++ status = ice_fwlog_get(hw, &hw->fwlog_cfg); ++ if (status) ++ return status; ++ ++ ice_debugfs_fwlog_init(hw->back); ++ } else { ++ dev_warn(ice_hw_to_dev(hw), "FW logging is not supported in this NVM image. Please update the NVM to get FW log support\n"); ++ } ++ ++ return 0; ++} ++ ++/** ++ * ice_fwlog_deinit - unroll FW logging configuration ++ * @hw: pointer to the HW structure ++ * ++ * This function should be called in ice_deinit_hw(). ++ */ ++void ice_fwlog_deinit(struct ice_hw *hw) ++{ ++ struct ice_pf *pf = hw->back; ++ int status; ++ ++ /* only support fw log commands on PF 0 */ ++ if (hw->bus.func) ++ return; ++ ++ /* make sure FW logging is disabled to not put the FW in a weird state ++ * for the next driver load ++ */ ++ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA; ++ status = ice_fwlog_set(hw, &hw->fwlog_cfg); ++ if (status) ++ dev_warn(ice_hw_to_dev(hw), "Unable to turn off FW logging, status: %d\n", ++ status); ++ ++ kfree(pf->ice_debugfs_pf_fwlog_modules); ++ ++ pf->ice_debugfs_pf_fwlog_modules = NULL; ++} ++ ++/** ++ * ice_fwlog_supported - Cached for whether FW supports FW logging or not ++ * @hw: pointer to the HW structure ++ * ++ * This will always return false if called before ice_init_hw(), so it must be ++ * called after ice_init_hw(). ++ */ ++bool ice_fwlog_supported(struct ice_hw *hw) ++{ ++ return hw->fwlog_supported; ++} ++ ++/** ++ * ice_aq_fwlog_set - Set FW logging configuration AQ command (0xFF30) ++ * @hw: pointer to the HW structure ++ * @entries: entries to configure ++ * @num_entries: number of @entries ++ * @options: options from ice_fwlog_cfg->options structure ++ * @log_resolution: logging resolution ++ */ ++static int ++ice_aq_fwlog_set(struct ice_hw *hw, struct ice_fwlog_module_entry *entries, ++ u16 num_entries, u16 options, u16 log_resolution) ++{ ++ struct ice_aqc_fw_log_cfg_resp *fw_modules; ++ struct ice_aqc_fw_log *cmd; ++ struct ice_aq_desc desc; ++ int status; ++ int i; ++ ++ fw_modules = kcalloc(num_entries, sizeof(*fw_modules), GFP_KERNEL); ++ if (!fw_modules) ++ return -ENOMEM; ++ ++ for (i = 0; i < num_entries; i++) { ++ fw_modules[i].module_identifier = ++ cpu_to_le16(entries[i].module_id); ++ fw_modules[i].log_level = entries[i].log_level; ++ } ++ ++ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_config); ++ desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); ++ ++ cmd = &desc.params.fw_log; ++ ++ cmd->cmd_flags = ICE_AQC_FW_LOG_CONF_SET_VALID; ++ cmd->ops.cfg.log_resolution = cpu_to_le16(log_resolution); ++ cmd->ops.cfg.mdl_cnt = cpu_to_le16(num_entries); ++ ++ if (options & ICE_FWLOG_OPTION_ARQ_ENA) ++ cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_AQ_EN; ++ if (options & ICE_FWLOG_OPTION_UART_ENA) ++ cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_UART_EN; ++ ++ status = ice_aq_send_cmd(hw, &desc, fw_modules, ++ sizeof(*fw_modules) * num_entries, ++ NULL); ++ ++ kfree(fw_modules); ++ ++ return status; ++} ++ ++/** ++ * ice_fwlog_set - Set the firmware logging settings ++ * @hw: pointer to the HW structure ++ * @cfg: config used to set firmware logging ++ * ++ * This function should be called whenever the driver needs to set the firmware ++ * logging configuration. It can be called on initialization, reset, or during ++ * runtime. ++ * ++ * If the PF wishes to receive FW logging then it must register via ++ * ice_fwlog_register. Note, that ice_fwlog_register does not need to be called ++ * for init. ++ */ ++int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) ++{ ++ if (!ice_fwlog_supported(hw)) ++ return -EOPNOTSUPP; ++ ++ return ice_aq_fwlog_set(hw, cfg->module_entries, ++ ICE_AQC_FW_LOG_ID_MAX, cfg->options, ++ cfg->log_resolution); ++} ++ ++/** ++ * ice_aq_fwlog_get - Get the current firmware logging configuration (0xFF32) ++ * @hw: pointer to the HW structure ++ * @cfg: firmware logging configuration to populate ++ */ ++static int ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) ++{ ++ struct ice_aqc_fw_log_cfg_resp *fw_modules; ++ struct ice_aqc_fw_log *cmd; ++ struct ice_aq_desc desc; ++ u16 module_id_cnt; ++ int status; ++ void *buf; ++ int i; ++ ++ memset(cfg, 0, sizeof(*cfg)); ++ ++ buf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_query); ++ cmd = &desc.params.fw_log; ++ ++ cmd->cmd_flags = ICE_AQC_FW_LOG_AQ_QUERY; ++ ++ status = ice_aq_send_cmd(hw, &desc, buf, ICE_AQ_MAX_BUF_LEN, NULL); ++ if (status) { ++ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to get FW log configuration\n"); ++ goto status_out; ++ } ++ ++ module_id_cnt = le16_to_cpu(cmd->ops.cfg.mdl_cnt); ++ if (module_id_cnt < ICE_AQC_FW_LOG_ID_MAX) { ++ ice_debug(hw, ICE_DBG_FW_LOG, "FW returned less than the expected number of FW log module IDs\n"); ++ } else if (module_id_cnt > ICE_AQC_FW_LOG_ID_MAX) { ++ ice_debug(hw, ICE_DBG_FW_LOG, "FW returned more than expected number of FW log module IDs, setting module_id_cnt to software expected max %u\n", ++ ICE_AQC_FW_LOG_ID_MAX); ++ module_id_cnt = ICE_AQC_FW_LOG_ID_MAX; ++ } ++ ++ cfg->log_resolution = le16_to_cpu(cmd->ops.cfg.log_resolution); ++ if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_AQ_EN) ++ cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA; ++ if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_UART_EN) ++ cfg->options |= ICE_FWLOG_OPTION_UART_ENA; ++ ++ fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf; ++ ++ for (i = 0; i < module_id_cnt; i++) { ++ struct ice_aqc_fw_log_cfg_resp *fw_module = &fw_modules[i]; ++ ++ cfg->module_entries[i].module_id = ++ le16_to_cpu(fw_module->module_identifier); ++ cfg->module_entries[i].log_level = fw_module->log_level; ++ } ++ ++status_out: ++ kfree(buf); ++ return status; ++} ++ ++/** ++ * ice_fwlog_get - Get the firmware logging settings ++ * @hw: pointer to the HW structure ++ * @cfg: config to populate based on current firmware logging settings ++ */ ++int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) ++{ ++ if (!ice_fwlog_supported(hw)) ++ return -EOPNOTSUPP; ++ ++ return ice_aq_fwlog_get(hw, cfg); ++} ++ ++/** ++ * ice_fwlog_set_supported - Set if FW logging is supported by FW ++ * @hw: pointer to the HW struct ++ * ++ * If FW returns success to the ice_aq_fwlog_get call then it supports FW ++ * logging, else it doesn't. Set the fwlog_supported flag accordingly. ++ * ++ * This function is only meant to be called during driver init to determine if ++ * the FW support FW logging. ++ */ ++void ice_fwlog_set_supported(struct ice_hw *hw) ++{ ++ struct ice_fwlog_cfg *cfg; ++ int status; ++ ++ hw->fwlog_supported = false; ++ ++ cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); ++ if (!cfg) ++ return; ++ ++ /* don't call ice_fwlog_get() because that would check to see if FW ++ * logging is supported which is what the driver is determining now ++ */ ++ status = ice_aq_fwlog_get(hw, cfg); ++ if (status) ++ ice_debug(hw, ICE_DBG_FW_LOG, "ice_aq_fwlog_get failed, FW logging is not supported on this version of FW, status %d\n", ++ status); ++ else ++ hw->fwlog_supported = true; ++ ++ kfree(cfg); ++} +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.h b/drivers/net/ethernet/intel/ice/ice_fwlog.h +new file mode 100644 +index 000000000000..8e68ee02713b +--- /dev/null ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.h +@@ -0,0 +1,56 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* Copyright (C) 2022, Intel Corporation. */ ++ ++#ifndef _ICE_FWLOG_H_ ++#define _ICE_FWLOG_H_ ++#include "ice_adminq_cmd.h" ++ ++struct ice_hw; ++ ++/* Only a single log level should be set and all log levels under the set value ++ * are enabled, e.g. if log level is set to ICE_FW_LOG_LEVEL_VERBOSE, then all ++ * other log levels are included (except ICE_FW_LOG_LEVEL_NONE) ++ */ ++enum ice_fwlog_level { ++ ICE_FWLOG_LEVEL_NONE = 0, ++ ICE_FWLOG_LEVEL_ERROR = 1, ++ ICE_FWLOG_LEVEL_WARNING = 2, ++ ICE_FWLOG_LEVEL_NORMAL = 3, ++ ICE_FWLOG_LEVEL_VERBOSE = 4, ++ ICE_FWLOG_LEVEL_INVALID, /* all values >= this entry are invalid */ ++}; ++ ++struct ice_fwlog_module_entry { ++ /* module ID for the corresponding firmware logging event */ ++ u16 module_id; ++ /* verbosity level for the module_id */ ++ u8 log_level; ++}; ++ ++struct ice_fwlog_cfg { ++ /* list of modules for configuring log level */ ++ struct ice_fwlog_module_entry module_entries[ICE_AQC_FW_LOG_ID_MAX]; ++ /* options used to configure firmware logging */ ++ u16 options; ++#define ICE_FWLOG_OPTION_ARQ_ENA BIT(0) ++#define ICE_FWLOG_OPTION_UART_ENA BIT(1) ++ /* set before calling ice_fwlog_init() so the PF registers for firmware ++ * logging on initialization ++ */ ++#define ICE_FWLOG_OPTION_REGISTER_ON_INIT BIT(2) ++ /* set in the ice_fwlog_get() response if the PF is registered for FW ++ * logging events over ARQ ++ */ ++#define ICE_FWLOG_OPTION_IS_REGISTERED BIT(3) ++ ++ /* minimum number of log events sent per Admin Receive Queue event */ ++ u16 log_resolution; ++}; ++ ++void ice_fwlog_set_supported(struct ice_hw *hw); ++bool ice_fwlog_supported(struct ice_hw *hw); ++int ice_fwlog_init(struct ice_hw *hw); ++void ice_fwlog_deinit(struct ice_hw *hw); ++int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); ++int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); ++#endif /* _ICE_FWLOG_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index e5cc9790969c..614e10ab4159 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -4506,6 +4506,19 @@ static void ice_print_wake_reason(struct ice_pf *pf) + dev_info(ice_pf_to_dev(pf), "Wake reason: %s", wake_str); + } + ++/** ++ * ice_pf_fwlog_update_module - update 1 module ++ * @pf: pointer to the PF struct ++ * @log_level: log_level to use for the @module ++ * @module: module to update ++ */ ++void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module) ++{ ++ struct ice_hw *hw = &pf->hw; ++ ++ hw->fwlog_cfg.module_entries[module].log_level = log_level; ++} ++ + /** + * ice_register_netdev - register netdev + * @vsi: pointer to the VSI struct +@@ -5283,6 +5296,8 @@ static void ice_remove(struct pci_dev *pdev) + msleep(100); + } + ++ ice_debugfs_exit(); ++ + if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) { + set_bit(ICE_VF_RESETS_DISABLED, pf->state); + ice_free_vfs(pf); +@@ -5751,6 +5766,8 @@ static int __init ice_module_init(void) + goto err_dest_wq; + } + ++ ice_debugfs_init(); ++ + status = pci_register_driver(&ice_driver); + if (status) { + pr_err("failed to register PCI driver, err %d\n", status); +@@ -5761,6 +5778,7 @@ static int __init ice_module_init(void) + + err_dest_lag_wq: + destroy_workqueue(ice_lag_wq); ++ ice_debugfs_exit(); + err_dest_wq: + destroy_workqueue(ice_wq); + return status; +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index 6e1fed0d7384..84bb61aa7409 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -17,6 +17,7 @@ + #include "ice_protocol_type.h" + #include "ice_sbq_cmd.h" + #include "ice_vlan_mode.h" ++#include "ice_fwlog.h" + + static inline bool ice_is_tc_ena(unsigned long bitmap, u8 tc) + { +@@ -872,6 +873,9 @@ struct ice_hw { + u8 fw_patch; /* firmware patch version */ + u32 fw_build; /* firmware build number */ + ++ struct ice_fwlog_cfg fwlog_cfg; ++ bool fwlog_supported; /* does hardware support FW logging? */ ++ + /* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL + * register. Used for determining the ITR/INTRL granularity during + * initialization. +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0026-ice-enable-FW-logging.patch b/kernel-std/debian/patches/ice-VDF/0026-ice-enable-FW-logging.patch new file mode 100644 index 00000000..f61122fb --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0026-ice-enable-FW-logging.patch @@ -0,0 +1,281 @@ +From 189d58473481cf01b493fca4e9dd2ab8380d0ce5 Mon Sep 17 00:00:00 2001 +From: Paul M Stillwell Jr +Date: Tue, 12 Dec 2023 21:07:13 -0800 +Subject: [PATCH 26/36] ice: enable FW logging + +Once users have configured the FW logging then allow them to enable it +by writing to the 'fwlog/enable' file. The file accepts a boolean value +(0 or 1) where 1 means enable FW logging and 0 means disable FW logging. + + # echo > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/enable + +Where is 0 or 1. + +The user can read the 'fwlog/enable' file to see whether logging is +enabled or not. Reading the actual data is a separate patch. To see the +current value then: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/enable + +Signed-off-by: Paul M Stillwell Jr +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 73671c3162c83a689342fd57f00b5f261682e49b) +Signed-off-by: Jiping Ma +--- + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 3 + + drivers/net/ethernet/intel/ice/ice_debugfs.c | 98 +++++++++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.c | 67 +++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.h | 2 + + 4 files changed, 170 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 347e4fed5e0d..11391be4efc2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2336,6 +2336,7 @@ enum ice_aqc_fw_logging_mod { + }; + + /* Set FW Logging configuration (indirect 0xFF30) ++ * Register for FW Logging (indirect 0xFF31) + * Query FW Logging (indirect 0xFF32) + */ + struct ice_aqc_fw_log { +@@ -2344,6 +2345,7 @@ struct ice_aqc_fw_log { + #define ICE_AQC_FW_LOG_CONF_AQ_EN BIT(1) + #define ICE_AQC_FW_LOG_QUERY_REGISTERED BIT(2) + #define ICE_AQC_FW_LOG_CONF_SET_VALID BIT(3) ++#define ICE_AQC_FW_LOG_AQ_REGISTER BIT(0) + #define ICE_AQC_FW_LOG_AQ_QUERY BIT(2) + + u8 rsp_flag; +@@ -2662,6 +2664,7 @@ enum ice_adminq_opc { + + /* FW Logging Commands */ + ice_aqc_opc_fw_logs_config = 0xFF30, ++ ice_aqc_opc_fw_logs_register = 0xFF31, + ice_aqc_opc_fw_logs_query = 0xFF32, + }; + +diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c +index 3b0d9b214fd1..3dde99969132 100644 +--- a/drivers/net/ethernet/intel/ice/ice_debugfs.c ++++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c +@@ -281,6 +281,101 @@ static const struct file_operations ice_debugfs_nr_messages_fops = { + .write = ice_debugfs_nr_messages_write, + }; + ++/** ++ * ice_debugfs_enable_read - read from 'enable' file ++ * @filp: the opened file ++ * @buffer: where to write the data for the user to read ++ * @count: the size of the user's buffer ++ * @ppos: file position offset ++ */ ++static ssize_t ice_debugfs_enable_read(struct file *filp, ++ char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ char buff[32] = {}; ++ ++ snprintf(buff, sizeof(buff), "%u\n", ++ (u16)(hw->fwlog_cfg.options & ++ ICE_FWLOG_OPTION_IS_REGISTERED) >> 3); ++ ++ return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); ++} ++ ++/** ++ * ice_debugfs_enable_write - write into 'enable' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_enable_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ char user_val[8], *cmd_buf; ++ bool enable; ++ ssize_t ret; ++ ++ /* don't allow partial writes or invalid input */ ++ if (*ppos != 0 || count > 2) ++ return -EINVAL; ++ ++ cmd_buf = memdup_user(buf, count); ++ if (IS_ERR(cmd_buf)) ++ return PTR_ERR(cmd_buf); ++ ++ ret = sscanf(cmd_buf, "%s", user_val); ++ if (ret != 1) ++ return -EINVAL; ++ ++ ret = kstrtobool(user_val, &enable); ++ if (ret) ++ goto enable_write_error; ++ ++ if (enable) ++ hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_ARQ_ENA; ++ else ++ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA; ++ ++ ret = ice_fwlog_set(hw, &hw->fwlog_cfg); ++ if (ret) ++ goto enable_write_error; ++ ++ if (enable) ++ ret = ice_fwlog_register(hw); ++ else ++ ret = ice_fwlog_unregister(hw); ++ ++ if (ret) ++ goto enable_write_error; ++ ++ /* if we get here, nothing went wrong; return count since we didn't ++ * really write anything ++ */ ++ ret = (ssize_t)count; ++ ++enable_write_error: ++ /* This function always consumes all of the written input, or produces ++ * an error. Check and enforce this. Otherwise, the write operation ++ * won't complete properly. ++ */ ++ if (WARN_ON(ret != (ssize_t)count && ret >= 0)) ++ ret = -EIO; ++ ++ return ret; ++} ++ ++static const struct file_operations ice_debugfs_enable_fops = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .read = ice_debugfs_enable_read, ++ .write = ice_debugfs_enable_write, ++}; ++ + /** + * ice_debugfs_fwlog_init - setup the debugfs directory + * @pf: the ice that is starting up +@@ -332,6 +427,9 @@ void ice_debugfs_fwlog_init(struct ice_pf *pf) + + pf->ice_debugfs_pf_fwlog_modules = fw_modules; + ++ debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog, ++ pf, &ice_debugfs_enable_fops); ++ + return; + + err_create_module_files: +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.c b/drivers/net/ethernet/intel/ice/ice_fwlog.c +index 307e0d04f3fe..25a17cbc1d34 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.c ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.c +@@ -63,6 +63,11 @@ void ice_fwlog_deinit(struct ice_hw *hw) + kfree(pf->ice_debugfs_pf_fwlog_modules); + + pf->ice_debugfs_pf_fwlog_modules = NULL; ++ ++ status = ice_fwlog_unregister(hw); ++ if (status) ++ dev_warn(ice_hw_to_dev(hw), "Unable to unregister FW logging, status: %d\n", ++ status); + } + + /** +@@ -197,6 +202,8 @@ static int ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) + cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA; + if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_UART_EN) + cfg->options |= ICE_FWLOG_OPTION_UART_ENA; ++ if (cmd->cmd_flags & ICE_AQC_FW_LOG_QUERY_REGISTERED) ++ cfg->options |= ICE_FWLOG_OPTION_IS_REGISTERED; + + fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf; + +@@ -226,6 +233,66 @@ int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) + return ice_aq_fwlog_get(hw, cfg); + } + ++/** ++ * ice_aq_fwlog_register - Register PF for firmware logging events (0xFF31) ++ * @hw: pointer to the HW structure ++ * @reg: true to register and false to unregister ++ */ ++static int ice_aq_fwlog_register(struct ice_hw *hw, bool reg) ++{ ++ struct ice_aq_desc desc; ++ ++ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_register); ++ ++ if (reg) ++ desc.params.fw_log.cmd_flags = ICE_AQC_FW_LOG_AQ_REGISTER; ++ ++ return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); ++} ++ ++/** ++ * ice_fwlog_register - Register the PF for firmware logging ++ * @hw: pointer to the HW structure ++ * ++ * After this call the PF will start to receive firmware logging based on the ++ * configuration set in ice_fwlog_set. ++ */ ++int ice_fwlog_register(struct ice_hw *hw) ++{ ++ int status; ++ ++ if (!ice_fwlog_supported(hw)) ++ return -EOPNOTSUPP; ++ ++ status = ice_aq_fwlog_register(hw, true); ++ if (status) ++ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to register for firmware logging events over ARQ\n"); ++ else ++ hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_IS_REGISTERED; ++ ++ return status; ++} ++ ++/** ++ * ice_fwlog_unregister - Unregister the PF from firmware logging ++ * @hw: pointer to the HW structure ++ */ ++int ice_fwlog_unregister(struct ice_hw *hw) ++{ ++ int status; ++ ++ if (!ice_fwlog_supported(hw)) ++ return -EOPNOTSUPP; ++ ++ status = ice_aq_fwlog_register(hw, false); ++ if (status) ++ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to unregister from firmware logging events over ARQ\n"); ++ else ++ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_IS_REGISTERED; ++ ++ return status; ++} ++ + /** + * ice_fwlog_set_supported - Set if FW logging is supported by FW + * @hw: pointer to the HW struct +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.h b/drivers/net/ethernet/intel/ice/ice_fwlog.h +index 8e68ee02713b..45865558425d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.h ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.h +@@ -53,4 +53,6 @@ int ice_fwlog_init(struct ice_hw *hw); + void ice_fwlog_deinit(struct ice_hw *hw); + int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); + int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); ++int ice_fwlog_register(struct ice_hw *hw); ++int ice_fwlog_unregister(struct ice_hw *hw); + #endif /* _ICE_FWLOG_H_ */ +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0027-ice-add-ability-to-read-and-configure-FW-log-data.patch b/kernel-std/debian/patches/ice-VDF/0027-ice-add-ability-to-read-and-configure-FW-log-data.patch new file mode 100644 index 00000000..0bca4413 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0027-ice-add-ability-to-read-and-configure-FW-log-data.patch @@ -0,0 +1,572 @@ +From a584ea88cfdc8ac3f782be1d5d67fa92c3423290 Mon Sep 17 00:00:00 2001 +From: Paul M Stillwell Jr +Date: Tue, 12 Dec 2023 21:07:14 -0800 +Subject: [PATCH 27/36] ice: add ability to read and configure FW log data + +Once logging is enabled the user should read the data from the 'data' +file. The data is in the form of a binary blob that can be sent to Intel +for decoding. To read the data use a command like: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/data > log_data.bin + +If the user wants to clear the FW log data that has been stored in the +driver then they can write any value to the 'data' file and that will clear +the data. An example is: + + # echo 34 > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/data + +In addition to being able to read the data the user can configure how +much memory is used to store FW log data. This allows the user to +increase/decrease the amount of memory based on the users situation. +The data is stored such that if the memory fills up then the oldest data +will get overwritten in a circular manner. To change the amount of +memory the user can write to the 'log_size' file like this: + + # echo > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/log_size + +Where is one of 128K, 256K, 512K, 1M, and 2M. The default value +is 1M. + +The user can see the current value of 'log_size' by reading the file: + + # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/log_size + +Signed-off-by: Paul M Stillwell Jr +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit 9d3535e71985beb738c4ad2b772c6f0efdce0202) +Signed-off-by: Jiping Ma +--- + .../net/ethernet/intel/ice/ice_adminq_cmd.h | 2 + + drivers/net/ethernet/intel/ice/ice_debugfs.c | 210 ++++++++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.c | 142 ++++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.h | 21 ++ + drivers/net/ethernet/intel/ice/ice_main.c | 29 +++ + drivers/net/ethernet/intel/ice/ice_type.h | 1 + + 6 files changed, 405 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +index 11391be4efc2..f63b57ff2a3d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +@@ -2338,6 +2338,7 @@ enum ice_aqc_fw_logging_mod { + /* Set FW Logging configuration (indirect 0xFF30) + * Register for FW Logging (indirect 0xFF31) + * Query FW Logging (indirect 0xFF32) ++ * FW Log Event (indirect 0xFF33) + */ + struct ice_aqc_fw_log { + u8 cmd_flags; +@@ -2666,6 +2667,7 @@ enum ice_adminq_opc { + ice_aqc_opc_fw_logs_config = 0xFF30, + ice_aqc_opc_fw_logs_register = 0xFF31, + ice_aqc_opc_fw_logs_query = 0xFF32, ++ ice_aqc_opc_fw_logs_event = 0xFF33, + }; + + #endif /* _ICE_ADMINQ_CMD_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c +index 3dde99969132..c2bfba6b9ead 100644 +--- a/drivers/net/ethernet/intel/ice/ice_debugfs.c ++++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c +@@ -64,6 +64,17 @@ static const char * const ice_fwlog_level_string[] = { + "verbose", + }; + ++/* the order in this array is important. it matches the ordering of the ++ * values in the FW so the index is the same value as in ice_fwlog_level ++ */ ++static const char * const ice_fwlog_log_size[] = { ++ "128K", ++ "256K", ++ "512K", ++ "1M", ++ "2M", ++}; ++ + /** + * ice_fwlog_print_module_cfg - print current FW logging module configuration + * @hw: pointer to the HW structure +@@ -376,6 +387,199 @@ static const struct file_operations ice_debugfs_enable_fops = { + .write = ice_debugfs_enable_write, + }; + ++/** ++ * ice_debugfs_log_size_read - read from 'log_size' file ++ * @filp: the opened file ++ * @buffer: where to write the data for the user to read ++ * @count: the size of the user's buffer ++ * @ppos: file position offset ++ */ ++static ssize_t ice_debugfs_log_size_read(struct file *filp, ++ char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ char buff[32] = {}; ++ int index; ++ ++ index = hw->fwlog_ring.index; ++ snprintf(buff, sizeof(buff), "%s\n", ice_fwlog_log_size[index]); ++ ++ return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); ++} ++ ++/** ++ * ice_debugfs_log_size_write - write into 'log_size' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_log_size_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct device *dev = ice_pf_to_dev(pf); ++ struct ice_hw *hw = &pf->hw; ++ char user_val[8], *cmd_buf; ++ ssize_t ret; ++ int index; ++ ++ /* don't allow partial writes or invalid input */ ++ if (*ppos != 0 || count > 5) ++ return -EINVAL; ++ ++ cmd_buf = memdup_user(buf, count); ++ if (IS_ERR(cmd_buf)) ++ return PTR_ERR(cmd_buf); ++ ++ ret = sscanf(cmd_buf, "%s", user_val); ++ if (ret != 1) ++ return -EINVAL; ++ ++ index = sysfs_match_string(ice_fwlog_log_size, user_val); ++ if (index < 0) { ++ dev_info(dev, "Invalid log size '%s'. The value must be one of 128K, 256K, 512K, 1M, 2M\n", ++ user_val); ++ ret = -EINVAL; ++ goto log_size_write_error; ++ } else if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED) { ++ dev_info(dev, "FW logging is currently running. Please disable FW logging to change log_size\n"); ++ ret = -EINVAL; ++ goto log_size_write_error; ++ } ++ ++ /* free all the buffers and the tracking info and resize */ ++ ice_fwlog_realloc_rings(hw, index); ++ ++ /* if we get here, nothing went wrong; return count since we didn't ++ * really write anything ++ */ ++ ret = (ssize_t)count; ++ ++log_size_write_error: ++ /* This function always consumes all of the written input, or produces ++ * an error. Check and enforce this. Otherwise, the write operation ++ * won't complete properly. ++ */ ++ if (WARN_ON(ret != (ssize_t)count && ret >= 0)) ++ ret = -EIO; ++ ++ return ret; ++} ++ ++static const struct file_operations ice_debugfs_log_size_fops = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .read = ice_debugfs_log_size_read, ++ .write = ice_debugfs_log_size_write, ++}; ++ ++/** ++ * ice_debugfs_data_read - read from 'data' file ++ * @filp: the opened file ++ * @buffer: where to write the data for the user to read ++ * @count: the size of the user's buffer ++ * @ppos: file position offset ++ */ ++static ssize_t ice_debugfs_data_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct ice_hw *hw = &pf->hw; ++ int data_copied = 0; ++ bool done = false; ++ ++ if (ice_fwlog_ring_empty(&hw->fwlog_ring)) ++ return 0; ++ ++ while (!ice_fwlog_ring_empty(&hw->fwlog_ring) && !done) { ++ struct ice_fwlog_data *log; ++ u16 cur_buf_len; ++ ++ log = &hw->fwlog_ring.rings[hw->fwlog_ring.head]; ++ cur_buf_len = log->data_size; ++ if (cur_buf_len >= count) { ++ done = true; ++ continue; ++ } ++ ++ if (copy_to_user(buffer, log->data, cur_buf_len)) { ++ /* if there is an error then bail and return whatever ++ * the driver has copied so far ++ */ ++ done = true; ++ continue; ++ } ++ ++ data_copied += cur_buf_len; ++ buffer += cur_buf_len; ++ count -= cur_buf_len; ++ *ppos += cur_buf_len; ++ ice_fwlog_ring_increment(&hw->fwlog_ring.head, ++ hw->fwlog_ring.size); ++ } ++ ++ return data_copied; ++} ++ ++/** ++ * ice_debugfs_data_write - write into 'data' file ++ * @filp: the opened file ++ * @buf: where to find the user's data ++ * @count: the length of the user's data ++ * @ppos: file position offset ++ */ ++static ssize_t ++ice_debugfs_data_write(struct file *filp, const char __user *buf, size_t count, ++ loff_t *ppos) ++{ ++ struct ice_pf *pf = filp->private_data; ++ struct device *dev = ice_pf_to_dev(pf); ++ struct ice_hw *hw = &pf->hw; ++ ssize_t ret; ++ ++ /* don't allow partial writes */ ++ if (*ppos != 0) ++ return 0; ++ ++ /* any value is allowed to clear the buffer so no need to even look at ++ * what the value is ++ */ ++ if (!(hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED)) { ++ hw->fwlog_ring.head = 0; ++ hw->fwlog_ring.tail = 0; ++ } else { ++ dev_info(dev, "Can't clear FW log data while FW log running\n"); ++ ret = -EINVAL; ++ goto nr_buffs_write_error; ++ } ++ ++ /* if we get here, nothing went wrong; return count since we didn't ++ * really write anything ++ */ ++ ret = (ssize_t)count; ++ ++nr_buffs_write_error: ++ /* This function always consumes all of the written input, or produces ++ * an error. Check and enforce this. Otherwise, the write operation ++ * won't complete properly. ++ */ ++ if (WARN_ON(ret != (ssize_t)count && ret >= 0)) ++ ret = -EIO; ++ ++ return ret; ++} ++ ++static const struct file_operations ice_debugfs_data_fops = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .read = ice_debugfs_data_read, ++ .write = ice_debugfs_data_write, ++}; ++ + /** + * ice_debugfs_fwlog_init - setup the debugfs directory + * @pf: the ice that is starting up +@@ -430,6 +634,12 @@ void ice_debugfs_fwlog_init(struct ice_pf *pf) + debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog, + pf, &ice_debugfs_enable_fops); + ++ debugfs_create_file("log_size", 0600, pf->ice_debugfs_pf_fwlog, ++ pf, &ice_debugfs_log_size_fops); ++ ++ debugfs_create_file("data", 0600, pf->ice_debugfs_pf_fwlog, ++ pf, &ice_debugfs_data_fops); ++ + return; + + err_create_module_files: +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.c b/drivers/net/ethernet/intel/ice/ice_fwlog.c +index 25a17cbc1d34..92b5dac481cd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.c ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.c +@@ -1,10 +1,128 @@ + // SPDX-License-Identifier: GPL-2.0 + /* Copyright (c) 2022, Intel Corporation. */ + ++#include + #include "ice.h" + #include "ice_common.h" + #include "ice_fwlog.h" + ++bool ice_fwlog_ring_full(struct ice_fwlog_ring *rings) ++{ ++ u16 head, tail; ++ ++ head = rings->head; ++ tail = rings->tail; ++ ++ if (head < tail && (tail - head == (rings->size - 1))) ++ return true; ++ else if (head > tail && (tail == (head - 1))) ++ return true; ++ ++ return false; ++} ++ ++bool ice_fwlog_ring_empty(struct ice_fwlog_ring *rings) ++{ ++ return rings->head == rings->tail; ++} ++ ++void ice_fwlog_ring_increment(u16 *item, u16 size) ++{ ++ *item = (*item + 1) & (size - 1); ++} ++ ++static int ice_fwlog_alloc_ring_buffs(struct ice_fwlog_ring *rings) ++{ ++ int i, nr_bytes; ++ u8 *mem; ++ ++ nr_bytes = rings->size * ICE_AQ_MAX_BUF_LEN; ++ mem = vzalloc(nr_bytes); ++ if (!mem) ++ return -ENOMEM; ++ ++ for (i = 0; i < rings->size; i++) { ++ struct ice_fwlog_data *ring = &rings->rings[i]; ++ ++ ring->data_size = ICE_AQ_MAX_BUF_LEN; ++ ring->data = mem; ++ mem += ICE_AQ_MAX_BUF_LEN; ++ } ++ ++ return 0; ++} ++ ++static void ice_fwlog_free_ring_buffs(struct ice_fwlog_ring *rings) ++{ ++ int i; ++ ++ for (i = 0; i < rings->size; i++) { ++ struct ice_fwlog_data *ring = &rings->rings[i]; ++ ++ /* the first ring is the base memory for the whole range so ++ * free it ++ */ ++ if (!i) ++ vfree(ring->data); ++ ++ ring->data = NULL; ++ ring->data_size = 0; ++ } ++} ++ ++#define ICE_FWLOG_INDEX_TO_BYTES(n) ((128 * 1024) << (n)) ++/** ++ * ice_fwlog_realloc_rings - reallocate the FW log rings ++ * @hw: pointer to the HW structure ++ * @index: the new index to use to allocate memory for the log data ++ * ++ */ ++void ice_fwlog_realloc_rings(struct ice_hw *hw, int index) ++{ ++ struct ice_fwlog_ring ring; ++ int status, ring_size; ++ ++ /* convert the number of bytes into a number of 4K buffers. externally ++ * the driver presents the interface to the FW log data as a number of ++ * bytes because that's easy for users to understand. internally the ++ * driver uses a ring of buffers because the driver doesn't know where ++ * the beginning and end of any line of log data is so the driver has ++ * to overwrite data as complete blocks. when the data is returned to ++ * the user the driver knows that the data is correct and the FW log ++ * can be correctly parsed by the tools ++ */ ++ ring_size = ICE_FWLOG_INDEX_TO_BYTES(index) / ICE_AQ_MAX_BUF_LEN; ++ if (ring_size == hw->fwlog_ring.size) ++ return; ++ ++ /* allocate space for the new rings and buffers then release the ++ * old rings and buffers. that way if we don't have enough ++ * memory then we at least have what we had before ++ */ ++ ring.rings = kcalloc(ring_size, sizeof(*ring.rings), GFP_KERNEL); ++ if (!ring.rings) ++ return; ++ ++ ring.size = ring_size; ++ ++ status = ice_fwlog_alloc_ring_buffs(&ring); ++ if (status) { ++ dev_warn(ice_hw_to_dev(hw), "Unable to allocate memory for FW log ring data buffers\n"); ++ ice_fwlog_free_ring_buffs(&ring); ++ kfree(ring.rings); ++ return; ++ } ++ ++ ice_fwlog_free_ring_buffs(&hw->fwlog_ring); ++ kfree(hw->fwlog_ring.rings); ++ ++ hw->fwlog_ring.rings = ring.rings; ++ hw->fwlog_ring.size = ring.size; ++ hw->fwlog_ring.index = index; ++ hw->fwlog_ring.head = 0; ++ hw->fwlog_ring.tail = 0; ++} ++ + /** + * ice_fwlog_init - Initialize FW logging configuration + * @hw: pointer to the HW structure +@@ -28,6 +146,25 @@ int ice_fwlog_init(struct ice_hw *hw) + if (status) + return status; + ++ hw->fwlog_ring.rings = kcalloc(ICE_FWLOG_RING_SIZE_DFLT, ++ sizeof(*hw->fwlog_ring.rings), ++ GFP_KERNEL); ++ if (!hw->fwlog_ring.rings) { ++ dev_warn(ice_hw_to_dev(hw), "Unable to allocate memory for FW log rings\n"); ++ return -ENOMEM; ++ } ++ ++ hw->fwlog_ring.size = ICE_FWLOG_RING_SIZE_DFLT; ++ hw->fwlog_ring.index = ICE_FWLOG_RING_SIZE_INDEX_DFLT; ++ ++ status = ice_fwlog_alloc_ring_buffs(&hw->fwlog_ring); ++ if (status) { ++ dev_warn(ice_hw_to_dev(hw), "Unable to allocate memory for FW log ring data buffers\n"); ++ ice_fwlog_free_ring_buffs(&hw->fwlog_ring); ++ kfree(hw->fwlog_ring.rings); ++ return status; ++ } ++ + ice_debugfs_fwlog_init(hw->back); + } else { + dev_warn(ice_hw_to_dev(hw), "FW logging is not supported in this NVM image. Please update the NVM to get FW log support\n"); +@@ -68,6 +205,11 @@ void ice_fwlog_deinit(struct ice_hw *hw) + if (status) + dev_warn(ice_hw_to_dev(hw), "Unable to unregister FW logging, status: %d\n", + status); ++ ++ if (hw->fwlog_ring.rings) { ++ ice_fwlog_free_ring_buffs(&hw->fwlog_ring); ++ kfree(hw->fwlog_ring.rings); ++ } + } + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.h b/drivers/net/ethernet/intel/ice/ice_fwlog.h +index 45865558425d..287e71fa4b86 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.h ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.h +@@ -47,6 +47,26 @@ struct ice_fwlog_cfg { + u16 log_resolution; + }; + ++struct ice_fwlog_data { ++ u16 data_size; ++ u8 *data; ++}; ++ ++struct ice_fwlog_ring { ++ struct ice_fwlog_data *rings; ++ u16 index; ++ u16 size; ++ u16 head; ++ u16 tail; ++}; ++ ++#define ICE_FWLOG_RING_SIZE_INDEX_DFLT 3 ++#define ICE_FWLOG_RING_SIZE_DFLT 256 ++#define ICE_FWLOG_RING_SIZE_MAX 512 ++ ++bool ice_fwlog_ring_full(struct ice_fwlog_ring *rings); ++bool ice_fwlog_ring_empty(struct ice_fwlog_ring *rings); ++void ice_fwlog_ring_increment(u16 *item, u16 size); + void ice_fwlog_set_supported(struct ice_hw *hw); + bool ice_fwlog_supported(struct ice_hw *hw); + int ice_fwlog_init(struct ice_hw *hw); +@@ -55,4 +75,5 @@ int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); + int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); + int ice_fwlog_register(struct ice_hw *hw); + int ice_fwlog_unregister(struct ice_hw *hw); ++void ice_fwlog_realloc_rings(struct ice_hw *hw, int index); + #endif /* _ICE_FWLOG_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 614e10ab4159..6c6ca5353f28 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -1254,6 +1254,32 @@ ice_handle_link_event(struct ice_pf *pf, struct ice_rq_event_info *event) + return status; + } + ++/** ++ * ice_get_fwlog_data - copy the FW log data from ARQ event ++ * @pf: PF that the FW log event is associated with ++ * @event: event structure containing FW log data ++ */ ++static void ++ice_get_fwlog_data(struct ice_pf *pf, struct ice_rq_event_info *event) ++{ ++ struct ice_fwlog_data *fwlog; ++ struct ice_hw *hw = &pf->hw; ++ ++ fwlog = &hw->fwlog_ring.rings[hw->fwlog_ring.tail]; ++ ++ memset(fwlog->data, 0, PAGE_SIZE); ++ fwlog->data_size = le16_to_cpu(event->desc.datalen); ++ ++ memcpy(fwlog->data, event->msg_buf, fwlog->data_size); ++ ice_fwlog_ring_increment(&hw->fwlog_ring.tail, hw->fwlog_ring.size); ++ ++ if (ice_fwlog_ring_full(&hw->fwlog_ring)) { ++ /* the rings are full so bump the head to create room */ ++ ice_fwlog_ring_increment(&hw->fwlog_ring.head, ++ hw->fwlog_ring.size); ++ } ++} ++ + /** + * ice_aq_prep_for_event - Prepare to wait for an AdminQ event from firmware + * @pf: pointer to the PF private structure +@@ -1535,6 +1561,9 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) + + ice_vc_process_vf_msg(pf, &event, &data); + break; ++ case ice_aqc_opc_fw_logs_event: ++ ice_get_fwlog_data(pf, &event); ++ break; + case ice_aqc_opc_lldp_set_mib_change: + ice_dcb_process_lldp_set_mib_change(pf, &event); + break; +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index 84bb61aa7409..28e47bb78eaf 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -875,6 +875,7 @@ struct ice_hw { + + struct ice_fwlog_cfg fwlog_cfg; + bool fwlog_supported; /* does hardware support FW logging? */ ++ struct ice_fwlog_ring fwlog_ring; + + /* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL + * register. Used for determining the ITR/INTRL granularity during +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0028-ice-Fix-debugfs-with-devlink-reload.patch b/kernel-std/debian/patches/ice-VDF/0028-ice-Fix-debugfs-with-devlink-reload.patch new file mode 100644 index 00000000..4bfe7051 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0028-ice-Fix-debugfs-with-devlink-reload.patch @@ -0,0 +1,98 @@ +From 8a7f6d8b2105c39f236c51c558e21b787c223861 Mon Sep 17 00:00:00 2001 +From: Wojciech Drewek +Date: Mon, 5 Feb 2024 14:03:57 +0100 +Subject: [PATCH 28/36] ice: Fix debugfs with devlink reload + +During devlink reload it is needed to remove debugfs entries +correlated with only one PF. ice_debugfs_exit() removes all +entries created by ice driver so we can't use it. + +Introduce ice_debugfs_pf_deinit() in order to release PF's +debugfs entries. Move ice_debugfs_exit() call to ice_module_exit(), +it makes more sense since ice_debugfs_init() is called in +ice_module_init() and not in ice_probe(). + +Signed-off-by: Wojciech Drewek +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Reviewed-by: Brett Creeley +Reviewed-by: Simon Horman +Signed-off-by: Tony Nguyen +(cherry picked from commit 500d0df5b4b2394a06b949bab05f7ed0242b9858) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice.h | 1 + + drivers/net/ethernet/intel/ice/ice_debugfs.c | 10 ++++++++++ + drivers/net/ethernet/intel/ice/ice_fwlog.c | 2 ++ + drivers/net/ethernet/intel/ice/ice_main.c | 3 +-- + 4 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 7966ac61154c..ed1c6cdedeff 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -895,6 +895,7 @@ static inline bool ice_is_adq_active(struct ice_pf *pf) + } + + void ice_debugfs_fwlog_init(struct ice_pf *pf); ++void ice_debugfs_pf_deinit(struct ice_pf *pf); + void ice_debugfs_init(void); + void ice_debugfs_exit(void); + void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module); +diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c +index c2bfba6b9ead..ba396b22bb7d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_debugfs.c ++++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c +@@ -647,6 +647,16 @@ void ice_debugfs_fwlog_init(struct ice_pf *pf) + kfree(fw_modules); + } + ++/** ++ * ice_debugfs_pf_deinit - cleanup PF's debugfs ++ * @pf: pointer to the PF struct ++ */ ++void ice_debugfs_pf_deinit(struct ice_pf *pf) ++{ ++ debugfs_remove_recursive(pf->ice_debugfs_pf); ++ pf->ice_debugfs_pf = NULL; ++} ++ + /** + * ice_debugfs_init - create root directory for debugfs entries + */ +diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.c b/drivers/net/ethernet/intel/ice/ice_fwlog.c +index 92b5dac481cd..4fd15387a7e5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_fwlog.c ++++ b/drivers/net/ethernet/intel/ice/ice_fwlog.c +@@ -188,6 +188,8 @@ void ice_fwlog_deinit(struct ice_hw *hw) + if (hw->bus.func) + return; + ++ ice_debugfs_pf_deinit(hw->back); ++ + /* make sure FW logging is disabled to not put the FW in a weird state + * for the next driver load + */ +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 6c6ca5353f28..c882c218281a 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -5325,8 +5325,6 @@ static void ice_remove(struct pci_dev *pdev) + msleep(100); + } + +- ice_debugfs_exit(); +- + if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) { + set_bit(ICE_VF_RESETS_DISABLED, pf->state); + ice_free_vfs(pf); +@@ -5823,6 +5821,7 @@ module_init(ice_module_init); + static void __exit ice_module_exit(void) + { + pci_unregister_driver(&ice_driver); ++ ice_debugfs_exit(); + destroy_workqueue(ice_wq); + destroy_workqueue(ice_lag_wq); + pr_info("module unloaded\n"); +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0029-ice-remove-vf-lan_vsi_num-field.patch b/kernel-std/debian/patches/ice-VDF/0029-ice-remove-vf-lan_vsi_num-field.patch new file mode 100644 index 00000000..2411e9c5 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0029-ice-remove-vf-lan_vsi_num-field.patch @@ -0,0 +1,78 @@ +From 861015cbb4cf4cb258a1da9e80550fe991be7808 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Fri, 16 Feb 2024 14:06:38 -0800 +Subject: [PATCH 29/36] ice: remove vf->lan_vsi_num field + +The lan_vsi_num field of the VF structure is no longer used for any +purpose. Remove it. + +Signed-off-by: Jacob Keller +Reviewed-by: Przemek Kitszel +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +(cherry picked from commit 1cf94cbfc61bac89cddeb075fbc100ebd3aea81b) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_sriov.c | 1 - + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 4 +--- + drivers/net/ethernet/intel/ice/ice_vf_lib.h | 5 ----- + 3 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c +index 442162be23ea..3366ac976c44 100644 +--- a/drivers/net/ethernet/intel/ice/ice_sriov.c ++++ b/drivers/net/ethernet/intel/ice/ice_sriov.c +@@ -239,7 +239,6 @@ static struct ice_vsi *ice_vf_vsi_setup(struct ice_vf *vf) + } + + vf->lan_vsi_idx = vsi->idx; +- vf->lan_vsi_num = vsi->vsi_num; + + return vsi; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +index 03b9d7d74851..303fdf8555cf 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +@@ -298,7 +298,6 @@ static int ice_vf_rebuild_vsi(struct ice_vf *vf) + * vf->lan_vsi_idx + */ + vsi->vsi_num = ice_get_hw_vsi_num(&pf->hw, vsi->idx); +- vf->lan_vsi_num = vsi->vsi_num; + + return 0; + } +@@ -1299,13 +1298,12 @@ int ice_vf_init_host_cfg(struct ice_vf *vf, struct ice_vsi *vsi) + } + + /** +- * ice_vf_invalidate_vsi - invalidate vsi_idx/vsi_num to remove VSI access ++ * ice_vf_invalidate_vsi - invalidate vsi_idx to remove VSI access + * @vf: VF to remove access to VSI for + */ + void ice_vf_invalidate_vsi(struct ice_vf *vf) + { + vf->lan_vsi_idx = ICE_NO_VSI; +- vf->lan_vsi_num = ICE_NO_VSI; + } + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h +index 48fea6fa0362..1de07accbc5c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h +@@ -110,11 +110,6 @@ struct ice_vf { + u8 spoofchk:1; + u8 link_forced:1; + u8 link_up:1; /* only valid if VF link is forced */ +- /* VSI indices - actual VSI pointers are maintained in the PF structure +- * When assigned, these will be non-zero, because VSI 0 is always +- * the main LAN VSI for the PF. +- */ +- u16 lan_vsi_num; /* ID as used by firmware */ + unsigned int min_tx_rate; /* Minimum Tx bandwidth limit in Mbps */ + unsigned int max_tx_rate; /* Maximum Tx bandwidth limit in Mbps */ + DECLARE_BITMAP(vf_states, ICE_VF_STATES_NBITS); /* VF runtime states */ +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0030-ice-rename-ice_write_-functions-to-ice_pack_ctx_.patch b/kernel-std/debian/patches/ice-VDF/0030-ice-rename-ice_write_-functions-to-ice_pack_ctx_.patch new file mode 100644 index 00000000..7f02562d --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0030-ice-rename-ice_write_-functions-to-ice_pack_ctx_.patch @@ -0,0 +1,150 @@ +From 6b7fae8669a04943af9f83ef89d39a922ed179fd Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Mon, 26 Feb 2024 16:14:54 -0800 +Subject: [PATCH 30/36] ice: rename ice_write_* functions to ice_pack_ctx_* + +In ice_common.c there are 4 functions used for converting the unpacked +software Tx and Rx context structure data into the packed format used by +hardware. These functions have extremely generic names: + + * ice_write_byte + * ice_write_word + * ice_write_dword + * ice_write_qword + +When I saw these function names my first thought was "write what? to +where?". Understanding what these functions do requires looking at the +implementation details. The functions take bits from an unpacked structure +and copy them into the packed layout used by hardware. + +As part of live migration, we will want functions which perform the inverse +operation of reading bits from the packed layout and copying them into the +unpacked format. Naming these as "ice_read_byte", etc would be very +confusing since they appear to write data. + +In preparation for adding this new inverse operation, rename the existing +functions to use the prefix "ice_pack_ctx_". This makes it clear that they +perform the bit packing while copying from the unpacked software context +structure to the packed hardware context. + +The inverse operations can then neatly be named ice_unpack_ctx_*, clearly +indicating they perform the bit unpacking while copying from the packed +hardware context to the unpacked software context structure. + +Signed-off-by: Jacob Keller +Reviewed-by: Przemek Kitszel +Signed-off-by: Tony Nguyen +(cherry picked from commit 1260b45dbe2dbc415f3bc1e841c6c098083bcfb8) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_common.c | 56 ++++++++++----------- + 1 file changed, 28 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 6dcba0577633..17f60a98c8ed 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -4267,13 +4267,13 @@ ice_aq_add_rdma_qsets(struct ice_hw *hw, u8 num_qset_grps, + /* End of FW Admin Queue command wrappers */ + + /** +- * ice_write_byte - write a byte to a packed context structure +- * @src_ctx: the context structure to read from +- * @dest_ctx: the context to be written to +- * @ce_info: a description of the struct to be filled ++ * ice_pack_ctx_byte - write a byte to a packed context structure ++ * @src_ctx: unpacked source context structure ++ * @dest_ctx: packed destination context data ++ * @ce_info: context element description + */ +-static void +-ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) ++static void ice_pack_ctx_byte(u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + u8 src_byte, dest_byte, mask; + u8 *from, *dest; +@@ -4306,13 +4306,13 @@ ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) + } + + /** +- * ice_write_word - write a word to a packed context structure +- * @src_ctx: the context structure to read from +- * @dest_ctx: the context to be written to +- * @ce_info: a description of the struct to be filled ++ * ice_pack_ctx_word - write a word to a packed context structure ++ * @src_ctx: unpacked source context structure ++ * @dest_ctx: packed destination context data ++ * @ce_info: context element description + */ +-static void +-ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) ++static void ice_pack_ctx_word(u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + u16 src_word, mask; + __le16 dest_word; +@@ -4349,13 +4349,13 @@ ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) + } + + /** +- * ice_write_dword - write a dword to a packed context structure +- * @src_ctx: the context structure to read from +- * @dest_ctx: the context to be written to +- * @ce_info: a description of the struct to be filled ++ * ice_pack_ctx_dword - write a dword to a packed context structure ++ * @src_ctx: unpacked source context structure ++ * @dest_ctx: packed destination context data ++ * @ce_info: context element description + */ +-static void +-ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) ++static void ice_pack_ctx_dword(u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + u32 src_dword, mask; + __le32 dest_dword; +@@ -4400,13 +4400,13 @@ ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) + } + + /** +- * ice_write_qword - write a qword to a packed context structure +- * @src_ctx: the context structure to read from +- * @dest_ctx: the context to be written to +- * @ce_info: a description of the struct to be filled ++ * ice_pack_ctx_qword - write a qword to a packed context structure ++ * @src_ctx: unpacked source context structure ++ * @dest_ctx: packed destination context data ++ * @ce_info: context element description + */ +-static void +-ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) ++static void ice_pack_ctx_qword(u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + u64 src_qword, mask; + __le64 dest_qword; +@@ -4475,16 +4475,16 @@ ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, + } + switch (ce_info[f].size_of) { + case sizeof(u8): +- ice_write_byte(src_ctx, dest_ctx, &ce_info[f]); ++ ice_pack_ctx_byte(src_ctx, dest_ctx, &ce_info[f]); + break; + case sizeof(u16): +- ice_write_word(src_ctx, dest_ctx, &ce_info[f]); ++ ice_pack_ctx_word(src_ctx, dest_ctx, &ce_info[f]); + break; + case sizeof(u32): +- ice_write_dword(src_ctx, dest_ctx, &ce_info[f]); ++ ice_pack_ctx_dword(src_ctx, dest_ctx, &ce_info[f]); + break; + case sizeof(u64): +- ice_write_qword(src_ctx, dest_ctx, &ce_info[f]); ++ ice_pack_ctx_qword(src_ctx, dest_ctx, &ce_info[f]); + break; + default: + return -EINVAL; +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0031-ice-use-GENMASK-instead-of-BIT-n-1-in-pack-functions.patch b/kernel-std/debian/patches/ice-VDF/0031-ice-use-GENMASK-instead-of-BIT-n-1-in-pack-functions.patch new file mode 100644 index 00000000..1c8f1877 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0031-ice-use-GENMASK-instead-of-BIT-n-1-in-pack-functions.patch @@ -0,0 +1,129 @@ +From 619e0e61b39cf051137613459d36c4fe8f435e57 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Mon, 26 Feb 2024 16:14:55 -0800 +Subject: [PATCH 31/36] ice: use GENMASK instead of BIT(n) - 1 in pack + functions + +The functions used to pack the Tx and Rx context into the hardware format +rely on using BIT() and then subtracting 1 to get a bitmask. These +functions even have a comment about how x86 machines can't use this method +for certain widths because the SHL instructions will not work properly. + +The Linux kernel already provides the GENMASK macro for generating a +suitable bitmask. Further, GENMASK is capable of generating the mask +including the shift_width. Since width is the total field width, take care +to subtract one to get the final bit position. + +Since we now include the shifted bits as part of the mask, shift the source +value first before applying the mask. + +Signed-off-by: Jacob Keller +Reviewed-by: Przemek Kitszel +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit a45d1bf516c097bb7ae4983d3128ebf139be952c) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_common.c | 44 ++++----------------- + 1 file changed, 8 insertions(+), 36 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 17f60a98c8ed..55a2e264dd69 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -4284,14 +4284,11 @@ static void ice_pack_ctx_byte(u8 *src_ctx, u8 *dest_ctx, + + /* prepare the bits and mask */ + shift_width = ce_info->lsb % 8; +- mask = (u8)(BIT(ce_info->width) - 1); ++ mask = GENMASK(ce_info->width - 1 + shift_width, shift_width); + + src_byte = *from; +- src_byte &= mask; +- +- /* shift to correct alignment */ +- mask <<= shift_width; + src_byte <<= shift_width; ++ src_byte &= mask; + + /* get the current bits from the target bit string */ + dest = dest_ctx + (ce_info->lsb / 8); +@@ -4324,17 +4321,14 @@ static void ice_pack_ctx_word(u8 *src_ctx, u8 *dest_ctx, + + /* prepare the bits and mask */ + shift_width = ce_info->lsb % 8; +- mask = BIT(ce_info->width) - 1; ++ mask = GENMASK(ce_info->width - 1 + shift_width, shift_width); + + /* don't swizzle the bits until after the mask because the mask bits + * will be in a different bit position on big endian machines + */ + src_word = *(u16 *)from; +- src_word &= mask; +- +- /* shift to correct alignment */ +- mask <<= shift_width; + src_word <<= shift_width; ++ src_word &= mask; + + /* get the current bits from the target bit string */ + dest = dest_ctx + (ce_info->lsb / 8); +@@ -4367,25 +4361,14 @@ static void ice_pack_ctx_dword(u8 *src_ctx, u8 *dest_ctx, + + /* prepare the bits and mask */ + shift_width = ce_info->lsb % 8; +- +- /* if the field width is exactly 32 on an x86 machine, then the shift +- * operation will not work because the SHL instructions count is masked +- * to 5 bits so the shift will do nothing +- */ +- if (ce_info->width < 32) +- mask = BIT(ce_info->width) - 1; +- else +- mask = (u32)~0; ++ mask = GENMASK(ce_info->width - 1 + shift_width, shift_width); + + /* don't swizzle the bits until after the mask because the mask bits + * will be in a different bit position on big endian machines + */ + src_dword = *(u32 *)from; +- src_dword &= mask; +- +- /* shift to correct alignment */ +- mask <<= shift_width; + src_dword <<= shift_width; ++ src_dword &= mask; + + /* get the current bits from the target bit string */ + dest = dest_ctx + (ce_info->lsb / 8); +@@ -4418,25 +4401,14 @@ static void ice_pack_ctx_qword(u8 *src_ctx, u8 *dest_ctx, + + /* prepare the bits and mask */ + shift_width = ce_info->lsb % 8; +- +- /* if the field width is exactly 64 on an x86 machine, then the shift +- * operation will not work because the SHL instructions count is masked +- * to 6 bits so the shift will do nothing +- */ +- if (ce_info->width < 64) +- mask = BIT_ULL(ce_info->width) - 1; +- else +- mask = (u64)~0; ++ mask = GENMASK_ULL(ce_info->width - 1 + shift_width, shift_width); + + /* don't swizzle the bits until after the mask because the mask bits + * will be in a different bit position on big endian machines + */ + src_qword = *(u64 *)from; +- src_qword &= mask; +- +- /* shift to correct alignment */ +- mask <<= shift_width; + src_qword <<= shift_width; ++ src_qword &= mask; + + /* get the current bits from the target bit string */ + dest = dest_ctx + (ce_info->lsb / 8); +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0032-ice-cleanup-line-splitting-for-context-set-functions.patch b/kernel-std/debian/patches/ice-VDF/0032-ice-cleanup-line-splitting-for-context-set-functions.patch new file mode 100644 index 00000000..4ab4b491 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0032-ice-cleanup-line-splitting-for-context-set-functions.patch @@ -0,0 +1,89 @@ +From 6502dd63a7bd436c72d2ee8b328985b93fa7e2a5 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Mon, 26 Feb 2024 16:14:56 -0800 +Subject: [PATCH 32/36] ice: cleanup line splitting for context set functions + +The indentation for ice_set_ctx and ice_write_rxq_ctx breaks the function +name after the return type. This style of breaking is used a lot throughout +the ice driver, even in cases where its not actually helpful for +readability. We no longer prefer this style of line splitting in the +driver, and new code is avoiding it. + +Normally, I would leave this alone unless the actual function contents or +description needed updating. However, a future change is going to add +inverse functions for converting packed context to unpacked context +structures. To keep this code uniform with the existing set functions, fix +up the style to the modern format of keeping the type on the same line. + +Signed-off-by: Jacob Keller +Reviewed-by: Przemek Kitszel +Signed-off-by: Tony Nguyen +(cherry picked from commit 979c2c049fbea107ce9f8d31f3ba9dba83ddb0a2) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_common.c | 12 +++++------- + drivers/net/ethernet/intel/ice/ice_common.h | 10 ++++------ + 2 files changed, 9 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 55a2e264dd69..59ede77a1473 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -1329,9 +1329,8 @@ static const struct ice_ctx_ele ice_rlan_ctx_info[] = { + * it to HW register space and enables the hardware to prefetch descriptors + * instead of only fetching them on demand + */ +-int +-ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, +- u32 rxq_index) ++int ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, ++ u32 rxq_index) + { + u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 }; + +@@ -4427,11 +4426,10 @@ static void ice_pack_ctx_qword(u8 *src_ctx, u8 *dest_ctx, + * @hw: pointer to the hardware structure + * @src_ctx: pointer to a generic non-packed context structure + * @dest_ctx: pointer to memory for the packed structure +- * @ce_info: a description of the structure to be transformed ++ * @ce_info: List of Rx context elements + */ +-int +-ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, +- const struct ice_ctx_ele *ce_info) ++int ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info) + { + int f; + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h +index d47e5400351f..1c3c29d30815 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.h ++++ b/drivers/net/ethernet/intel/ice/ice_common.h +@@ -52,9 +52,8 @@ int ice_get_caps(struct ice_hw *hw); + + void ice_set_safe_mode_caps(struct ice_hw *hw); + +-int +-ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, +- u32 rxq_index); ++int ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, ++ u32 rxq_index); + + int + ice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params); +@@ -71,9 +70,8 @@ bool ice_check_sq_alive(struct ice_hw *hw, struct ice_ctl_q_info *cq); + int ice_aq_q_shutdown(struct ice_hw *hw, bool unloading); + void ice_fill_dflt_direct_cmd_desc(struct ice_aq_desc *desc, u16 opcode); + extern const struct ice_ctx_ele ice_tlan_ctx_info[]; +-int +-ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, +- const struct ice_ctx_ele *ce_info); ++int ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, ++ const struct ice_ctx_ele *ce_info); + + extern struct mutex ice_global_cfg_lock_sw; + +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0033-ice-do-not-disable-Tx-queues-twice-in-ice_down.patch b/kernel-std/debian/patches/ice-VDF/0033-ice-do-not-disable-Tx-queues-twice-in-ice_down.patch new file mode 100644 index 00000000..a740f1ff --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0033-ice-do-not-disable-Tx-queues-twice-in-ice_down.patch @@ -0,0 +1,161 @@ +From 675a8843a0de1411666389eeabeea452161f8cc5 Mon Sep 17 00:00:00 2001 +From: Maciej Fijalkowski +Date: Fri, 23 Feb 2024 17:06:27 +0100 +Subject: [PATCH 33/36] ice: do not disable Tx queues twice in ice_down() + +ice_down() clears QINT_TQCTL_CAUSE_ENA_M bit twice, which is not +necessary. First clearing happens in ice_vsi_dis_irq() and second in +ice_vsi_stop_tx_ring() - remove the first one. + +While at it, make ice_vsi_dis_irq() static as ice_down() is the only +current caller of it. + +Signed-off-by: Maciej Fijalkowski +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +(cherry picked from commit d5926e01e3739542bb047b77f850d7f641eaa7bc) +[Adjust ice_lib.c with the context change.] +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_lib.c | 55 ----------------------- + drivers/net/ethernet/intel/ice/ice_lib.h | 2 - + drivers/net/ethernet/intel/ice/ice_main.c | 44 ++++++++++++++++++ + 3 files changed, 44 insertions(+), 57 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index 106ef843f4b5..f23cb9c8e3dd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -2877,61 +2877,6 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked) + } + } + +-/** +- * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI +- * @vsi: the VSI being un-configured +- */ +-void ice_vsi_dis_irq(struct ice_vsi *vsi) +-{ +- struct ice_pf *pf = vsi->back; +- struct ice_hw *hw = &pf->hw; +- u32 val; +- int i; +- +- /* disable interrupt causation from each queue */ +- if (vsi->tx_rings) { +- ice_for_each_txq(vsi, i) { +- if (vsi->tx_rings[i]) { +- u16 reg; +- +- reg = vsi->tx_rings[i]->reg_idx; +- val = rd32(hw, QINT_TQCTL(reg)); +- val &= ~QINT_TQCTL_CAUSE_ENA_M; +- wr32(hw, QINT_TQCTL(reg), val); +- } +- } +- } +- +- if (vsi->rx_rings) { +- ice_for_each_rxq(vsi, i) { +- if (vsi->rx_rings[i]) { +- u16 reg; +- +- reg = vsi->rx_rings[i]->reg_idx; +- val = rd32(hw, QINT_RQCTL(reg)); +- val &= ~QINT_RQCTL_CAUSE_ENA_M; +- wr32(hw, QINT_RQCTL(reg), val); +- } +- } +- } +- +- /* disable each interrupt */ +- ice_for_each_q_vector(vsi, i) { +- if (!vsi->q_vectors[i]) +- continue; +- wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); +- } +- +- ice_flush(hw); +- +- /* don't call synchronize_irq() for VF's from the host */ +- if (vsi->type == ICE_VSI_VF) +- return; +- +- ice_for_each_q_vector(vsi, i) +- synchronize_irq(vsi->q_vectors[i]->irq.virq); +-} +- + /** + * ice_vsi_release - Delete a VSI and free its resources + * @vsi: the VSI being removed +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h +index f24f5d1e6f9c..dbd0f3409323 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.h ++++ b/drivers/net/ethernet/intel/ice/ice_lib.h +@@ -110,8 +110,6 @@ void + ice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio, + bool ena_ts); + +-void ice_vsi_dis_irq(struct ice_vsi *vsi); +- + void ice_vsi_free_irq(struct ice_vsi *vsi); + + void ice_vsi_free_rx_rings(struct ice_vsi *vsi); +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index c882c218281a..685635a22616 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -7023,6 +7023,50 @@ static void ice_napi_disable_all(struct ice_vsi *vsi) + } + } + ++/** ++ * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI ++ * @vsi: the VSI being un-configured ++ */ ++static void ice_vsi_dis_irq(struct ice_vsi *vsi) ++{ ++ struct ice_pf *pf = vsi->back; ++ struct ice_hw *hw = &pf->hw; ++ u32 val; ++ int i; ++ ++ /* disable interrupt causation from each Rx queue; Tx queues are ++ * handled in ice_vsi_stop_tx_ring() ++ */ ++ if (vsi->rx_rings) { ++ ice_for_each_rxq(vsi, i) { ++ if (vsi->rx_rings[i]) { ++ u16 reg; ++ ++ reg = vsi->rx_rings[i]->reg_idx; ++ val = rd32(hw, QINT_RQCTL(reg)); ++ val &= ~QINT_RQCTL_CAUSE_ENA_M; ++ wr32(hw, QINT_RQCTL(reg), val); ++ } ++ } ++ } ++ ++ /* disable each interrupt */ ++ ice_for_each_q_vector(vsi, i) { ++ if (!vsi->q_vectors[i]) ++ continue; ++ wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); ++ } ++ ++ ice_flush(hw); ++ ++ /* don't call synchronize_irq() for VF's from the host */ ++ if (vsi->type == ICE_VSI_VF) ++ return; ++ ++ ice_for_each_q_vector(vsi, i) ++ synchronize_irq(vsi->q_vectors[i]->irq.virq); ++} ++ + /** + * ice_down - Shutdown the connection + * @vsi: The VSI being stopped +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0034-ice-Fix-improper-extts-handling.patch b/kernel-std/debian/patches/ice-VDF/0034-ice-Fix-improper-extts-handling.patch new file mode 100644 index 00000000..928b20bf --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0034-ice-Fix-improper-extts-handling.patch @@ -0,0 +1,274 @@ +From e53280c20bbe58015a91178268244d5e831276f4 Mon Sep 17 00:00:00 2001 +From: Milena Olech +Date: Tue, 2 Jul 2024 10:14:54 -0700 +Subject: [PATCH 34/36] ice: Fix improper extts handling + +Extts events are disabled and enabled by the application ts2phc. +However, in case where the driver is removed when the application is +running, a specific extts event remains enabled and can cause a kernel +crash. +As a side effect, when the driver is reloaded and application is started +again, remaining extts event for the channel from a previous run will +keep firing and the message "extts on unexpected channel" might be +printed to the user. + +To avoid that, extts events shall be disabled when PTP is released. + +Fixes: 172db5f91d5f ("ice: add support for auxiliary input/output pins") +Reviewed-by: Przemek Kitszel +Co-developed-by: Jacob Keller +Signed-off-by: Jacob Keller +Signed-off-by: Milena Olech +Signed-off-by: Karol Kolacinski +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20240702171459.2606611-2-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit 00d3b4f54582d4e4a02cda5886bb336eeab268cc) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 105 ++++++++++++++++++----- + drivers/net/ethernet/intel/ice/ice_ptp.h | 8 ++ + 2 files changed, 91 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 48ec59fc5d87..6e06c5d596b9 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1603,27 +1603,24 @@ void ice_ptp_extts_event(struct ice_pf *pf) + /** + * ice_ptp_cfg_extts - Configure EXTTS pin and channel + * @pf: Board private structure +- * @ena: true to enable; false to disable + * @chan: GPIO channel (0-3) +- * @gpio_pin: GPIO pin +- * @extts_flags: request flags from the ptp_extts_request.flags ++ * @config: desired EXTTS configuration. ++ * @store: If set to true, the values will be stored ++ * ++ * Configure an external timestamp event on the requested channel. + */ +-static int +-ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin, +- unsigned int extts_flags) ++static void ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan, ++ struct ice_extts_channel *config, bool store) + { + u32 func, aux_reg, gpio_reg, irq_reg; + struct ice_hw *hw = &pf->hw; + u8 tmr_idx; + +- if (chan > (unsigned int)pf->ptp.info.n_ext_ts) +- return -EINVAL; +- + tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; + + irq_reg = rd32(hw, PFINT_OICR_ENA); + +- if (ena) { ++ if (config->ena) { + /* Enable the interrupt */ + irq_reg |= PFINT_OICR_TSYN_EVNT_M; + aux_reg = GLTSYN_AUX_IN_0_INT_ENA_M; +@@ -1632,9 +1629,9 @@ ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin, + #define GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE BIT(1) + + /* set event level to requested edge */ +- if (extts_flags & PTP_FALLING_EDGE) ++ if (config->flags & PTP_FALLING_EDGE) + aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE; +- if (extts_flags & PTP_RISING_EDGE) ++ if (config->flags & PTP_RISING_EDGE) + aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_RISING_EDGE; + + /* Write GPIO CTL reg. +@@ -1656,9 +1653,47 @@ ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin, + + wr32(hw, PFINT_OICR_ENA, irq_reg); + wr32(hw, GLTSYN_AUX_IN(chan, tmr_idx), aux_reg); +- wr32(hw, GLGEN_GPIO_CTL(gpio_pin), gpio_reg); ++ wr32(hw, GLGEN_GPIO_CTL(config->gpio_pin), gpio_reg); + +- return 0; ++ if (store) ++ memcpy(&pf->ptp.extts_channels[chan], config, sizeof(*config)); ++} ++ ++/** ++ * ice_ptp_disable_all_extts - Disable all EXTTS channels ++ * @pf: Board private structure ++ */ ++static void ice_ptp_disable_all_extts(struct ice_pf *pf) ++{ ++ struct ice_extts_channel extts_cfg = {}; ++ int i; ++ ++ for (i = 0; i < pf->ptp.info.n_ext_ts; i++) { ++ if (pf->ptp.extts_channels[i].ena) { ++ extts_cfg.gpio_pin = pf->ptp.extts_channels[i].gpio_pin; ++ extts_cfg.ena = false; ++ ice_ptp_cfg_extts(pf, i, &extts_cfg, false); ++ } ++ } ++ ++ synchronize_irq(pf->oicr_irq.virq); ++} ++ ++/** ++ * ice_ptp_enable_all_extts - Enable all EXTTS channels ++ * @pf: Board private structure ++ * ++ * Called during reset to restore user configuration. ++ */ ++static void ice_ptp_enable_all_extts(struct ice_pf *pf) ++{ ++ int i; ++ ++ for (i = 0; i < pf->ptp.info.n_ext_ts; i++) { ++ if (pf->ptp.extts_channels[i].ena) ++ ice_ptp_cfg_extts(pf, i, &pf->ptp.extts_channels[i], ++ false); ++ } + } + + /** +@@ -1815,7 +1850,6 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info, + struct ptp_clock_request *rq, int on) + { + struct ice_pf *pf = ptp_info_to_pf(info); +- struct ice_perout_channel clk_cfg = {0}; + bool sma_pres = false; + unsigned int chan; + u32 gpio_pin; +@@ -1826,6 +1860,9 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info, + + switch (rq->type) { + case PTP_CLK_REQ_PEROUT: ++ { ++ struct ice_perout_channel clk_cfg = {}; ++ + chan = rq->perout.index; + if (sma_pres) { + if (chan == ice_pin_desc_e810t[SMA1].chan) +@@ -1853,7 +1890,11 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info, + + err = ice_ptp_cfg_clkout(pf, chan, &clk_cfg, true); + break; ++ } + case PTP_CLK_REQ_EXTTS: ++ { ++ struct ice_extts_channel extts_cfg = {}; ++ + chan = rq->extts.index; + if (sma_pres) { + if (chan < ice_pin_desc_e810t[SMA2].chan) +@@ -1869,9 +1910,13 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info, + gpio_pin = chan; + } + +- err = ice_ptp_cfg_extts(pf, !!on, chan, gpio_pin, +- rq->extts.flags); +- break; ++ extts_cfg.flags = rq->extts.flags; ++ extts_cfg.gpio_pin = gpio_pin; ++ extts_cfg.ena = !!on; ++ ++ ice_ptp_cfg_extts(pf, chan, &extts_cfg, true); ++ return 0; ++ } + default: + return -EOPNOTSUPP; + } +@@ -1889,21 +1934,31 @@ static int ice_ptp_gpio_enable_e823(struct ptp_clock_info *info, + struct ptp_clock_request *rq, int on) + { + struct ice_pf *pf = ptp_info_to_pf(info); +- struct ice_perout_channel clk_cfg = {0}; + int err; + + switch (rq->type) { + case PTP_CLK_REQ_PPS: ++ { ++ struct ice_perout_channel clk_cfg = {}; ++ + clk_cfg.gpio_pin = PPS_PIN_INDEX; + clk_cfg.period = NSEC_PER_SEC; + clk_cfg.ena = !!on; + + err = ice_ptp_cfg_clkout(pf, PPS_CLK_GEN_CHAN, &clk_cfg, true); + break; ++ } + case PTP_CLK_REQ_EXTTS: +- err = ice_ptp_cfg_extts(pf, !!on, rq->extts.index, +- TIME_SYNC_PIN_INDEX, rq->extts.flags); +- break; ++ { ++ struct ice_extts_channel extts_cfg = {}; ++ ++ extts_cfg.flags = rq->extts.flags; ++ extts_cfg.gpio_pin = TIME_SYNC_PIN_INDEX; ++ extts_cfg.ena = !!on; ++ ++ ice_ptp_cfg_extts(pf, rq->extts.index, &extts_cfg, true); ++ return 0; ++ } + default: + return -EOPNOTSUPP; + } +@@ -2735,6 +2790,10 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf) + ice_ptp_restart_all_phy(pf); + } + ++ /* Re-enable all periodic outputs and external timestamp events */ ++ ice_ptp_enable_all_clkout(pf); ++ ice_ptp_enable_all_extts(pf); ++ + return 0; + } + +@@ -3286,6 +3345,8 @@ void ice_ptp_release(struct ice_pf *pf) + + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx); + ++ ice_ptp_disable_all_extts(pf); ++ + kthread_cancel_delayed_work_sync(&pf->ptp.work); + + ice_ptp_port_phy_stop(&pf->ptp.port); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index 352405a2daf2..c6469a5a7afb 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -33,6 +33,12 @@ struct ice_perout_channel { + u64 start_time; + }; + ++struct ice_extts_channel { ++ bool ena; ++ u32 gpio_pin; ++ u32 flags; ++}; ++ + /* The ice hardware captures Tx hardware timestamps in the PHY. The timestamp + * is stored in a buffer of registers. Depending on the specific hardware, + * this buffer might be shared across multiple PHY ports. +@@ -226,6 +232,7 @@ enum ice_ptp_state { + * @ext_ts_irq: the external timestamp IRQ in use + * @kworker: kwork thread for handling periodic work + * @perout_channels: periodic output data ++ * @extts_channels: channels for external timestamps + * @info: structure defining PTP hardware capabilities + * @clock: pointer to registered PTP clock device + * @tstamp_config: hardware timestamping configuration +@@ -249,6 +256,7 @@ struct ice_ptp { + u8 ext_ts_irq; + struct kthread_worker *kworker; + struct ice_perout_channel perout_channels[GLTSYN_TGT_H_IDX_MAX]; ++ struct ice_extts_channel extts_channels[GLTSYN_TGT_H_IDX_MAX]; + struct ptp_clock_info info; + struct ptp_clock *clock; + struct hwtstamp_config tstamp_config; +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0035-ice-Don-t-process-extts-if-PTP-is-disabled.patch b/kernel-std/debian/patches/ice-VDF/0035-ice-Don-t-process-extts-if-PTP-is-disabled.patch new file mode 100644 index 00000000..feef0a9f --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0035-ice-Don-t-process-extts-if-PTP-is-disabled.patch @@ -0,0 +1,49 @@ +From 6c24a32820031f9713d0c0cf7ac6f4ead6b58052 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 2 Jul 2024 10:14:55 -0700 +Subject: [PATCH 35/36] ice: Don't process extts if PTP is disabled + +The ice_ptp_extts_event() function can race with ice_ptp_release() and +result in a NULL pointer dereference which leads to a kernel panic. + +Panic occurs because the ice_ptp_extts_event() function calls +ptp_clock_event() with a NULL pointer. The ice driver has already +released the PTP clock by the time the interrupt for the next external +timestamp event occurs. + +To fix this, modify the ice_ptp_extts_event() function to check the +PTP state and bail early if PTP is not ready. + +Fixes: 172db5f91d5f ("ice: add support for auxiliary input/output pins") +Reviewed-by: Przemek Kitszel +Signed-off-by: Jacob Keller +Signed-off-by: Karol Kolacinski +Reviewed-by: Simon Horman +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20240702171459.2606611-3-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit 996422e3230e41468f652d754fefd1bdbcd4604e) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 6e06c5d596b9..ceb4ba19c511 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1578,6 +1578,10 @@ void ice_ptp_extts_event(struct ice_pf *pf) + u8 chan, tmr_idx; + u32 hi, lo; + ++ /* Don't process timestamp events if PTP is not ready */ ++ if (pf->ptp.state != ICE_PTP_READY) ++ return; ++ + tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; + /* Event time is captured by one of the two matched registers + * GLTSYN_EVNT_L: 32 LSB of sampled time event +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0036-ice-Introduce-ice_ptp_hw-struct.patch b/kernel-std/debian/patches/ice-VDF/0036-ice-Introduce-ice_ptp_hw-struct.patch new file mode 100644 index 00000000..6d5456da --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0036-ice-Introduce-ice_ptp_hw-struct.patch @@ -0,0 +1,628 @@ +From 1ce01cb7cdb0bf4c18a546a62f224c8032d75ebd Mon Sep 17 00:00:00 2001 +From: Karol Kolacinski +Date: Tue, 28 May 2024 16:03:51 -0700 +Subject: [PATCH 36/36] ice: Introduce ice_ptp_hw struct + +Create new ice_ptp_hw struct and use it for all HW and PTP-related +fields from struct ice_hw. +Replace definitions with struct fields, which values are set accordingly +to a specific device. + +Reviewed-by: Przemek Kitszel +Reviewed-by: Arkadiusz Kubalewski +Signed-off-by: Karol Kolacinski +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Jacob Keller +Link: https://lore.kernel.org/r/20240528-next-2024-05-28-ptp-refactors-v1-1-c082739bb6f6@intel.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit d551d075b043821880b8afc0010ef70d050716d0) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_common.c | 24 ++++ + drivers/net/ethernet/intel/ice/ice_common.h | 1 + + drivers/net/ethernet/intel/ice/ice_ptp.c | 22 ++-- + drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 134 ++++++++++++-------- + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 4 +- + drivers/net/ethernet/intel/ice/ice_type.h | 17 ++- + 6 files changed, 126 insertions(+), 76 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 59ede77a1473..147004e0170b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -209,6 +209,30 @@ bool ice_is_e810t(struct ice_hw *hw) + return false; + } + ++/** ++ * ice_is_e822 - Check if a device is E822 family device ++ * @hw: pointer to the hardware structure ++ * ++ * Return: true if the device is E822 based, false if not. ++ */ ++bool ice_is_e822(struct ice_hw *hw) ++{ ++ switch (hw->device_id) { ++ case ICE_DEV_ID_E822C_BACKPLANE: ++ case ICE_DEV_ID_E822C_QSFP: ++ case ICE_DEV_ID_E822C_SFP: ++ case ICE_DEV_ID_E822C_10G_BASE_T: ++ case ICE_DEV_ID_E822C_SGMII: ++ case ICE_DEV_ID_E822L_BACKPLANE: ++ case ICE_DEV_ID_E822L_SFP: ++ case ICE_DEV_ID_E822L_10G_BASE_T: ++ case ICE_DEV_ID_E822L_SGMII: ++ return true; ++ default: ++ return false; ++ } ++} ++ + /** + * ice_is_e823 + * @hw: pointer to the hardware structure +diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h +index 1c3c29d30815..9d38777310e5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.h ++++ b/drivers/net/ethernet/intel/ice/ice_common.h +@@ -245,6 +245,7 @@ void + ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, + u64 *prev_stat, u64 *cur_stat); + bool ice_is_e810t(struct ice_hw *hw); ++bool ice_is_e822(struct ice_hw *hw); + bool ice_is_e823(struct ice_hw *hw); + int + ice_sched_query_elem(struct ice_hw *hw, u32 node_teid, +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index ceb4ba19c511..bb1572a353d0 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -812,7 +812,7 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) + } + mutex_unlock(&pf->ptp.ports_owner.lock); + +- for (i = 0; i < ICE_MAX_QUAD; i++) { ++ for (i = 0; i < ICE_GET_QUAD_NUM(pf->hw.ptp.num_lports); i++) { + u64 tstamp_ready; + int err; + +@@ -1026,7 +1026,7 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + static int + ice_ptp_init_tx_e82x(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port) + { +- tx->block = port / ICE_PORTS_PER_QUAD; ++ tx->block = ICE_GET_QUAD_NUM(port); + tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E82X; + tx->len = INDEX_PER_PORT_E82X; + tx->has_ready_bitmap = 1; +@@ -1248,8 +1248,8 @@ static u64 ice_base_incval(struct ice_pf *pf) + */ + static int ice_ptp_check_tx_fifo(struct ice_ptp_port *port) + { +- int quad = port->port_num / ICE_PORTS_PER_QUAD; + int offs = port->port_num % ICE_PORTS_PER_QUAD; ++ int quad = ICE_GET_QUAD_NUM(port->port_num); + struct ice_pf *pf; + struct ice_hw *hw; + u32 val, phy_sts; +@@ -1448,7 +1448,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + if (pf->ptp.state != ICE_PTP_READY) + return; + +- if (WARN_ON_ONCE(port >= ICE_NUM_EXTERNAL_PORTS)) ++ if (WARN_ON_ONCE(port >= hw->ptp.num_lports)) + return; + + ptp_port = &pf->ptp.port; +@@ -1458,7 +1458,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) + /* Update cached link status for this port immediately */ + ptp_port->link_up = linkup; + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + /* Do not reconfigure E810 PHY */ + return; +@@ -1487,7 +1487,7 @@ static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold) + + ice_ptp_reset_ts_memory(hw); + +- for (quad = 0; quad < ICE_MAX_QUAD; quad++) { ++ for (quad = 0; quad < ICE_GET_QUAD_NUM(hw->ptp.num_lports); quad++) { + err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, + &val); + if (err) +@@ -2038,7 +2038,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts) + ice_ptp_enable_all_clkout(pf); + + /* Recalibrate and re-enable timestamp blocks for E822/E823 */ +- if (hw->phy_model == ICE_PHY_E82X) ++ if (hw->ptp.phy_model == ICE_PHY_E82X) + ice_ptp_restart_all_phy(pf); + exit: + if (err) { +@@ -2652,7 +2652,7 @@ static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf) + if (!ice_pf_src_tmr_owned(pf)) + return; + +- for (i = 0; i < ICE_MAX_QUAD; i++) { ++ for (i = 0; i < ICE_GET_QUAD_NUM(hw->ptp.num_lports); i++) { + u64 tstamp_ready; + int err; + +@@ -3152,7 +3152,7 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port) + + mutex_init(&ptp_port->ps_lock); + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_ptp_init_tx_e810(pf, &ptp_port->tx); + case ICE_PHY_E82X: +@@ -3245,7 +3245,7 @@ static void ice_ptp_remove_auxbus_device(struct ice_pf *pf) + */ + static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf) + { +- switch (pf->hw.phy_model) { ++ switch (pf->hw.ptp.phy_model) { + case ICE_PHY_E82X: + /* E822 based PHY has the clock owner process the interrupt + * for all ports. +@@ -3281,7 +3281,7 @@ void ice_ptp_init(struct ice_pf *pf) + + ptp->state = ICE_PTP_INITIALIZING; + +- ice_ptp_init_phy_model(hw); ++ ice_ptp_init_hw(hw); + + ice_ptp_init_tx_interrupt_mode(pf); + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +index 7337e7e710ed..313a72dad813 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +@@ -285,18 +285,21 @@ static void ice_ptp_exec_tmr_cmd(struct ice_hw *hw) + + /** + * ice_fill_phy_msg_e82x - Fill message data for a PHY register access ++ * @hw: pointer to the HW struct + * @msg: the PHY message buffer to fill in + * @port: the port to access + * @offset: the register offset + */ +-static void +-ice_fill_phy_msg_e82x(struct ice_sbq_msg_input *msg, u8 port, u16 offset) ++static void ice_fill_phy_msg_e82x(struct ice_hw *hw, ++ struct ice_sbq_msg_input *msg, u8 port, ++ u16 offset) + { + int phy_port, phy, quadtype; + +- phy_port = port % ICE_PORTS_PER_PHY_E82X; +- phy = port / ICE_PORTS_PER_PHY_E82X; +- quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E82X; ++ phy_port = port % hw->ptp.ports_per_phy; ++ phy = port / hw->ptp.ports_per_phy; ++ quadtype = ICE_GET_QUAD_NUM(port) % ++ ICE_GET_QUAD_NUM(hw->ptp.ports_per_phy); + + if (quadtype == 0) { + msg->msg_addr_low = P_Q0_L(P_0_BASE + offset, phy_port); +@@ -427,7 +430,7 @@ ice_read_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 offset, u32 *val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- ice_fill_phy_msg_e82x(&msg, port, offset); ++ ice_fill_phy_msg_e82x(hw, &msg, port, offset); + msg.opcode = ice_sbq_msg_rd; + + err = ice_sbq_rw_reg(hw, &msg); +@@ -504,7 +507,7 @@ ice_write_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 offset, u32 val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- ice_fill_phy_msg_e82x(&msg, port, offset); ++ ice_fill_phy_msg_e82x(hw, &msg, port, offset); + msg.opcode = ice_sbq_msg_wr; + msg.data = val; + +@@ -614,24 +617,30 @@ ice_write_64b_phy_reg_e82x(struct ice_hw *hw, u8 port, u16 low_addr, u64 val) + + /** + * ice_fill_quad_msg_e82x - Fill message data for quad register access ++ * @hw: pointer to the HW struct + * @msg: the PHY message buffer to fill in + * @quad: the quad to access + * @offset: the register offset + * + * Fill a message buffer for accessing a register in a quad shared between + * multiple PHYs. ++ * ++ * Return: ++ * * %0 - OK ++ * * %-EINVAL - invalid quad number + */ +-static int +-ice_fill_quad_msg_e82x(struct ice_sbq_msg_input *msg, u8 quad, u16 offset) ++static int ice_fill_quad_msg_e82x(struct ice_hw *hw, ++ struct ice_sbq_msg_input *msg, u8 quad, ++ u16 offset) + { + u32 addr; + +- if (quad >= ICE_MAX_QUAD) ++ if (quad >= ICE_GET_QUAD_NUM(hw->ptp.num_lports)) + return -EINVAL; + + msg->dest_dev = rmn_0; + +- if ((quad % ICE_QUADS_PER_PHY_E82X) == 0) ++ if (!(quad % ICE_GET_QUAD_NUM(hw->ptp.ports_per_phy))) + addr = Q_0_BASE + offset; + else + addr = Q_1_BASE + offset; +@@ -658,7 +667,7 @@ ice_read_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 *val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- err = ice_fill_quad_msg_e82x(&msg, quad, offset); ++ err = ice_fill_quad_msg_e82x(hw, &msg, quad, offset); + if (err) + return err; + +@@ -692,7 +701,7 @@ ice_write_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 val) + struct ice_sbq_msg_input msg = {0}; + int err; + +- err = ice_fill_quad_msg_e82x(&msg, quad, offset); ++ err = ice_fill_quad_msg_e82x(hw, &msg, quad, offset); + if (err) + return err; + +@@ -813,7 +822,7 @@ static void ice_ptp_reset_ts_memory_e82x(struct ice_hw *hw) + { + unsigned int quad; + +- for (quad = 0; quad < ICE_MAX_QUAD; quad++) ++ for (quad = 0; quad < ICE_GET_QUAD_NUM(hw->ptp.num_lports); quad++) + ice_ptp_reset_ts_memory_quad_e82x(hw, quad); + } + +@@ -1110,7 +1119,7 @@ static int ice_ptp_set_vernier_wl(struct ice_hw *hw) + { + u8 port; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + int err; + + err = ice_write_phy_reg_e82x(hw, port, P_REG_WL, +@@ -1175,7 +1184,7 @@ ice_ptp_prep_phy_time_e82x(struct ice_hw *hw, u32 time) + */ + phy_time = (u64)time << 32; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + /* Tx case */ + err = ice_write_64b_phy_reg_e82x(hw, port, + P_REG_TX_TIMER_INC_PRE_L, +@@ -1278,7 +1287,7 @@ ice_ptp_prep_phy_adj_e82x(struct ice_hw *hw, s32 adj) + else + cycles = -(((s64)-adj) << 32); + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + int err; + + err = ice_ptp_prep_port_adj_e82x(hw, port, cycles); +@@ -1304,7 +1313,7 @@ ice_ptp_prep_phy_incval_e82x(struct ice_hw *hw, u64 incval) + int err; + u8 port; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + err = ice_write_40b_phy_reg_e82x(hw, port, P_REG_TIMETUS_L, + incval); + if (err) +@@ -1460,7 +1469,7 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + { + u8 port; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + enum ice_ptp_tmr_cmd cmd; + int err; + +@@ -1490,7 +1499,7 @@ ice_ptp_port_cmd_e82x(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + { + u8 port; + +- for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { ++ for (port = 0; port < hw->ptp.num_lports; port++) { + int err; + + err = ice_ptp_write_port_cmd_e82x(hw, port, cmd); +@@ -1603,7 +1612,7 @@ static void ice_phy_cfg_lane_e82x(struct ice_hw *hw, u8 port) + return; + } + +- quad = port / ICE_PORTS_PER_QUAD; ++ quad = ICE_GET_QUAD_NUM(port); + + err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG, &val); + if (err) { +@@ -2632,6 +2641,17 @@ ice_get_phy_tx_tstamp_ready_e82x(struct ice_hw *hw, u8 quad, u64 *tstamp_ready) + return 0; + } + ++/** ++ * ice_ptp_init_phy_e82x - initialize PHY parameters ++ * @ptp: pointer to the PTP HW struct ++ */ ++static void ice_ptp_init_phy_e82x(struct ice_ptp_hw *ptp) ++{ ++ ptp->phy_model = ICE_PHY_E82X; ++ ptp->num_lports = 8; ++ ptp->ports_per_phy = 8; ++} ++ + /* E810 functions + * + * The following functions operate on the E810 series devices which use +@@ -2859,17 +2879,21 @@ static int ice_clear_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx) + } + + /** +- * ice_ptp_init_phy_e810 - Enable PTP function on the external PHY ++ * ice_ptp_init_phc_e810 - Perform E810 specific PHC initialization + * @hw: pointer to HW struct + * +- * Enable the timesync PTP functionality for the external PHY connected to +- * this function. ++ * Perform E810-specific PTP hardware clock initialization steps. ++ * ++ * Return: 0 on success, other error codes when failed to initialize TimeSync + */ +-int ice_ptp_init_phy_e810(struct ice_hw *hw) ++static int ice_ptp_init_phc_e810(struct ice_hw *hw) + { + u8 tmr_idx; + int err; + ++ /* Ensure synchronization delay is zero */ ++ wr32(hw, GLTSYN_SYNC_DLAY, 0); ++ + tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; + err = ice_write_phy_reg_e810(hw, ETH_GLTSYN_ENA(tmr_idx), + GLTSYN_ENA_TSYN_ENA_M); +@@ -2880,21 +2904,6 @@ int ice_ptp_init_phy_e810(struct ice_hw *hw) + return err; + } + +-/** +- * ice_ptp_init_phc_e810 - Perform E810 specific PHC initialization +- * @hw: pointer to HW struct +- * +- * Perform E810-specific PTP hardware clock initialization steps. +- */ +-static int ice_ptp_init_phc_e810(struct ice_hw *hw) +-{ +- /* Ensure synchronization delay is zero */ +- wr32(hw, GLTSYN_SYNC_DLAY, 0); +- +- /* Initialize the PHY */ +- return ice_ptp_init_phy_e810(hw); +-} +- + /** + * ice_ptp_prep_phy_time_e810 - Prepare PHY port with initial time + * @hw: Board private structure +@@ -3238,6 +3247,17 @@ int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data) + return ice_aq_read_i2c(hw, link_topo, 0, addr, 1, data, NULL); + } + ++/** ++ * ice_ptp_init_phy_e810 - initialize PHY parameters ++ * @ptp: pointer to the PTP HW struct ++ */ ++static void ice_ptp_init_phy_e810(struct ice_ptp_hw *ptp) ++{ ++ ptp->phy_model = ICE_PHY_E810; ++ ptp->num_lports = 8; ++ ptp->ports_per_phy = 4; ++} ++ + /* Device agnostic functions + * + * The following functions implement shared behavior common to both E822 and +@@ -3295,18 +3315,22 @@ void ice_ptp_unlock(struct ice_hw *hw) + } + + /** +- * ice_ptp_init_phy_model - Initialize hw->phy_model based on device type ++ * ice_ptp_init_hw - Initialize hw based on device type + * @hw: pointer to the HW structure + * +- * Determine the PHY model for the device, and initialize hw->phy_model ++ * Determine the PHY model for the device, and initialize hw + * for use by other functions. + */ +-void ice_ptp_init_phy_model(struct ice_hw *hw) ++void ice_ptp_init_hw(struct ice_hw *hw) + { +- if (ice_is_e810(hw)) +- hw->phy_model = ICE_PHY_E810; ++ struct ice_ptp_hw *ptp = &hw->ptp; ++ ++ if (ice_is_e822(hw) || ice_is_e823(hw)) ++ ice_ptp_init_phy_e82x(ptp); ++ else if (ice_is_e810(hw)) ++ ice_ptp_init_phy_e810(ptp); + else +- hw->phy_model = ICE_PHY_E82X; ++ ptp->phy_model = ICE_PHY_UNSUP; + } + + /** +@@ -3327,7 +3351,7 @@ static int ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) + ice_ptp_src_cmd(hw, cmd); + + /* Next, prepare the ports */ +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + err = ice_ptp_port_cmd_e810(hw, cmd); + break; +@@ -3379,7 +3403,7 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time) + + /* PHY timers */ + /* Fill Rx and Tx ports and send msg to PHY */ +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + err = ice_ptp_prep_phy_time_e810(hw, time & 0xFFFFFFFF); + break; +@@ -3421,7 +3445,7 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval) + wr32(hw, GLTSYN_SHADJ_L(tmr_idx), lower_32_bits(incval)); + wr32(hw, GLTSYN_SHADJ_H(tmr_idx), upper_32_bits(incval)); + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + err = ice_ptp_prep_phy_incval_e810(hw, incval); + break; +@@ -3487,7 +3511,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj) + wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0); + wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj); + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + err = ice_ptp_prep_phy_adj_e810(hw, adj); + break; +@@ -3517,7 +3541,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj) + */ + int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp) + { +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_read_phy_tstamp_e810(hw, block, idx, tstamp); + case ICE_PHY_E82X: +@@ -3545,7 +3569,7 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp) + */ + int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx) + { +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_clear_phy_tstamp_e810(hw, block, idx); + case ICE_PHY_E82X: +@@ -3606,7 +3630,7 @@ int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx) + */ + void ice_ptp_reset_ts_memory(struct ice_hw *hw) + { +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E82X: + ice_ptp_reset_ts_memory_e82x(hw); + break; +@@ -3632,7 +3656,7 @@ int ice_ptp_init_phc(struct ice_hw *hw) + /* Clear event err indications for auxiliary pins */ + (void)rd32(hw, GLTSYN_STAT(src_idx)); + +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_ptp_init_phc_e810(hw); + case ICE_PHY_E82X: +@@ -3655,7 +3679,7 @@ int ice_ptp_init_phc(struct ice_hw *hw) + */ + int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready) + { +- switch (hw->phy_model) { ++ switch (hw->ptp.phy_model) { + case ICE_PHY_E810: + return ice_get_phy_tx_tstamp_ready_e810(hw, block, + tstamp_ready); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +index 7e8fd369ef7c..d788221eba57 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +@@ -211,6 +211,7 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp); + int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx); + void ice_ptp_reset_ts_memory(struct ice_hw *hw); + int ice_ptp_init_phc(struct ice_hw *hw); ++void ice_ptp_init_hw(struct ice_hw *hw); + int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready); + + /* E822 family functions */ +@@ -265,7 +266,6 @@ int ice_phy_cfg_tx_offset_e82x(struct ice_hw *hw, u8 port); + int ice_phy_cfg_rx_offset_e82x(struct ice_hw *hw, u8 port); + + /* E810 family functions */ +-int ice_ptp_init_phy_e810(struct ice_hw *hw); + int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data); + int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data); + int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data); +@@ -280,8 +280,6 @@ int ice_get_cgu_state(struct ice_hw *hw, u8 dpll_idx, + u8 *ref_state, u8 *eec_mode, s64 *phase_offset, + enum dpll_lock_status *dpll_state); + int ice_get_cgu_rclk_pin_info(struct ice_hw *hw, u8 *base_idx, u8 *pin_num); +- +-void ice_ptp_init_phy_model(struct ice_hw *hw); + int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id, + unsigned long *caps); + +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index 28e47bb78eaf..6fc4cd1030d0 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -807,6 +807,9 @@ struct ice_mbx_data { + u16 async_watermark_val; + }; + ++#define ICE_PORTS_PER_QUAD 4 ++#define ICE_GET_QUAD_NUM(port) ((port) / ICE_PORTS_PER_QUAD) ++ + /* PHY model */ + enum ice_phy_model { + ICE_PHY_UNSUP = -1, +@@ -814,6 +817,12 @@ enum ice_phy_model { + ICE_PHY_E82X, + }; + ++struct ice_ptp_hw { ++ enum ice_phy_model phy_model; ++ u8 num_lports; ++ u8 ports_per_phy; ++}; ++ + /* Port hardware description */ + struct ice_hw { + u8 __iomem *hw_addr; +@@ -835,7 +844,6 @@ struct ice_hw { + u8 revision_id; + + u8 pf_id; /* device profile info */ +- enum ice_phy_model phy_model; + + u16 max_burst_size; /* driver sets this value */ + +@@ -896,12 +904,7 @@ struct ice_hw { + /* INTRL granularity in 1 us */ + u8 intrl_gran; + +-#define ICE_MAX_QUAD 2 +-#define ICE_QUADS_PER_PHY_E82X 2 +-#define ICE_PORTS_PER_PHY_E82X 8 +-#define ICE_PORTS_PER_QUAD 4 +-#define ICE_PORTS_PER_PHY_E810 4 +-#define ICE_NUM_EXTERNAL_PORTS (ICE_MAX_QUAD * ICE_PORTS_PER_QUAD) ++ struct ice_ptp_hw ptp; + + /* Active package version (currently active) */ + struct ice_pkg_ver active_pkg_ver; +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0037-ice-Introduce-ice_get_base_incval-helper.patch b/kernel-std/debian/patches/ice-VDF/0037-ice-Introduce-ice_get_base_incval-helper.patch new file mode 100644 index 00000000..f7e38700 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0037-ice-Introduce-ice_get_base_incval-helper.patch @@ -0,0 +1,80 @@ +From cd12b5c8239993e395436ff9a01b524103aa0641 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Tue, 28 May 2024 16:03:56 -0700 +Subject: [PATCH] ice: Introduce ice_get_base_incval() helper + +Add a new helper for getting base clock increment value for specific HW. + +Reviewed-by: Przemek Kitszel +Reviewed-by: Arkadiusz Kubalewski +Signed-off-by: Karol Kolacinski +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Jacob Keller +Link: https://lore.kernel.org/r/20240528-next-2024-05-28-ptp-refactors-v1-6-c082739bb6f6@intel.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit 1f374d57c39386520586539641cafc999d0f3ef5) +Signed-off-by: Jiping Ma +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 9 +-------- + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 18 ++++++++++++++++++ + 2 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index bb1572a353d0..44b8fc8021cd 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -7,8 +7,6 @@ + + #define E810_OUT_PROP_DELAY_NS 1 + +-#define UNKNOWN_INCVAL_E82X 0x100000000ULL +- + static const struct ptp_pin_desc ice_pin_desc_e810t[] = { + /* name idx func chan */ + { "GNSS", GNSS, PTP_PF_EXTTS, 0, { 0, } }, +@@ -1229,12 +1227,7 @@ static u64 ice_base_incval(struct ice_pf *pf) + struct ice_hw *hw = &pf->hw; + u64 incval; + +- if (ice_is_e810(hw)) +- incval = ICE_PTP_NOMINAL_INCVAL_E810; +- else if (ice_e82x_time_ref(hw) < NUM_ICE_TIME_REF_FREQ) +- incval = ice_e82x_nominal_incval(ice_e82x_time_ref(hw)); +- else +- incval = UNKNOWN_INCVAL_E82X; ++ incval = ice_get_base_incval(hw); + + dev_dbg(ice_pf_to_dev(pf), "PTP: using base increment value of 0x%016llx\n", + incval); +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +index d788221eba57..749a3f2d8293 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +@@ -283,6 +283,24 @@ int ice_get_cgu_rclk_pin_info(struct ice_hw *hw, u8 *base_idx, u8 *pin_num); + int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id, + unsigned long *caps); + ++/** ++ * ice_get_base_incval - Get base clock increment value ++ * @hw: pointer to the HW struct ++ * ++ * Return: base clock increment value for supported PHYs, 0 otherwise ++ */ ++static inline u64 ice_get_base_incval(struct ice_hw *hw) ++{ ++ switch (hw->ptp.phy_model) { ++ case ICE_PHY_E810: ++ return ICE_PTP_NOMINAL_INCVAL_E810; ++ case ICE_PHY_E82X: ++ return ice_e82x_nominal_incval(ice_e82x_time_ref(hw)); ++ default: ++ return 0; ++ } ++} ++ + #define PFTSYN_SEM_BYTES 4 + + #define ICE_PTP_CLOCK_INDEX_0 0x00 +-- +2.43.0 + diff --git a/kernel-std/debian/patches/ice-VDF/0038-ice-modify-the-ice-driver-version-to-stx.4.patch b/kernel-std/debian/patches/ice-VDF/0038-ice-modify-the-ice-driver-version-to-stx.4.patch new file mode 100644 index 00000000..ee86b103 --- /dev/null +++ b/kernel-std/debian/patches/ice-VDF/0038-ice-modify-the-ice-driver-version-to-stx.4.patch @@ -0,0 +1,32 @@ +From 437206483113743a4ef40c2f7e14f09705049672 Mon Sep 17 00:00:00 2001 +From: Jiping Ma +Date: Mon, 2 Sep 2024 03:18:08 +0000 +Subject: [PATCH] ice:modify the ice driver version to stx.4 + +Change the ice driver min version to stx.4 because we back ported +the upstream 36 commits to our code base to support the customer's +requirement. + +The ice driver version should be ice-6.6.40-stx.4. + +Signed-off-by: Jiping Ma +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 5807b310bdca..7163d25405f8 100644 +--- a/Makefile ++++ b/Makefile +@@ -1227,7 +1227,7 @@ uapi-asm-generic: + + # KERNELRELEASE can change from a few different places, meaning version.h + # needs to be updated, so this check is forced on all builds +-ICE_STX = "-stx.3" ++ICE_STX = "-stx.4" + I40E_STX = "-stx.0" + IAVF_STX = "-stx.0" + +-- +2.43.0 + diff --git a/kernel-std/debian/patches/series b/kernel-std/debian/patches/series index a773d35d..c03d052b 100644 --- a/kernel-std/debian/patches/series +++ b/kernel-std/debian/patches/series @@ -64,3 +64,41 @@ ice-dpll/0046-dpll-fix-dpll_xa_ref_-_del-for-multiple-registration.patch ice-dpll/0047-ice-modify-the-ice-driver-min-version-to-stx.2.patch ice-mdd/0001-ice-Add-automatic-VF-reset-on-Tx-MDD-events.patch ice-mdd/0002-ice-modify-the-ice-driver-min-version-to-stx.3.patch +ice-VDF/0001-ice-Auxbus-devices-driver-for-E822-TS.patch +ice-VDF/0002-ice-introduce-ice_pf_src_tmr_owned.patch +ice-VDF/0003-ice-Re-enable-timestamping-correctly-after-reset.patch +ice-VDF/0004-ice-periodically-kick-Tx-timestamp-interrupt.patch +ice-VDF/0005-ice-PTP-Rename-macros-used-for-PHY-QUAD-port-definit.patch +ice-VDF/0006-ice-PTP-move-quad-value-check-inside-ice_fill_phy_ms.patch +ice-VDF/0007-ice-remove-ptp_tx-ring-parameter-flag.patch +ice-VDF/0008-ice-unify-logic-for-programming-PFINT_TSYN_MSK.patch +ice-VDF/0009-ice-PTP-Clean-up-timestamp-registers-correctly.patch +ice-VDF/0010-ice-Use-PTP-auxbus-for-all-PHYs-restart-in-E822.patch +ice-VDF/0011-ice-Rename-E822-to-E82X.patch +ice-VDF/0012-ice-Schedule-service-task-in-IRQ-top-half.patch +ice-VDF/0013-ice-Enable-SW-interrupt-from-FW-for-LL-TS.patch +ice-VDF/0014-ice-PTP-add-clock-domain-number-to-auxiliary-interfa.patch +ice-VDF/0015-ice-restore-timestamp-configuration-after-device-res.patch +ice-VDF/0016-ice-introduce-PTP-state-machine.patch +ice-VDF/0017-ice-pass-reset-type-to-PTP-reset-functions.patch +ice-VDF/0018-ice-rename-verify_cached-to-has_ready_bitmap.patch +ice-VDF/0019-ice-don-t-check-has_ready_bitmap-in-E810-functions.patch +ice-VDF/0020-ice-rename-ice_ptp_tx_cfg_intr.patch +ice-VDF/0021-ice-factor-out-ice_ptp_rebuild_owner.patch +ice-VDF/0022-ice-stop-destroying-and-reinitalizing-Tx-tracker-dur.patch +ice-VDF/0023-ice-Remove-and-readd-netdev-during-devlink-reload.patch +ice-VDF/0024-ice-remove-FW-logging-code.patch +ice-VDF/0025-ice-configure-FW-logging.patch +ice-VDF/0026-ice-enable-FW-logging.patch +ice-VDF/0027-ice-add-ability-to-read-and-configure-FW-log-data.patch +ice-VDF/0028-ice-Fix-debugfs-with-devlink-reload.patch +ice-VDF/0029-ice-remove-vf-lan_vsi_num-field.patch +ice-VDF/0030-ice-rename-ice_write_-functions-to-ice_pack_ctx_.patch +ice-VDF/0031-ice-use-GENMASK-instead-of-BIT-n-1-in-pack-functions.patch +ice-VDF/0032-ice-cleanup-line-splitting-for-context-set-functions.patch +ice-VDF/0033-ice-do-not-disable-Tx-queues-twice-in-ice_down.patch +ice-VDF/0034-ice-Fix-improper-extts-handling.patch +ice-VDF/0035-ice-Don-t-process-extts-if-PTP-is-disabled.patch +ice-VDF/0036-ice-Introduce-ice_ptp_hw-struct.patch +ice-VDF/0037-ice-Introduce-ice_get_base_incval-helper.patch +ice-VDF/0038-ice-modify-the-ice-driver-version-to-stx.4.patch