@@ -197,8 +197,6 @@
#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,
@@ -1010,4 +1008,25 @@ static inline void ice_clear_rdma_cap(struct ice_pf *pf)
}
extern const struct xdp_metadata_ops ice_xdp_md_ops;
+
+/**
+ * ice_pf_src_tmr_owned - check if PF is owner of source timer
+ * @pf: Board private structure
+ */
+static inline bool ice_pf_src_tmr_owned(struct ice_pf *pf)
+{
+ if (pf->hw.ptp.phy_model == ICE_PHY_ETH56G && !pf->hw.ptp.primary_nac)
+ return false;
+ else
+ return pf->hw.func_caps.ts_func_info.src_tmr_owned;
+}
+
+/**
+ * ice_is_primary - check if PF is on a primary NAC
+ * @pf: Board private structure
+ */
+static inline bool ice_is_primary(struct ice_pf *pf)
+{
+ return pf->hw.dev_caps.nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M;
+}
#endif /* _ICE_H_ */
@@ -371,6 +371,9 @@ ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts)
u32 hi, lo, lo2;
u8 tmr_idx;
+ if (!hw->ptp.primary_nac)
+ hw = hw->ptp.primary_hw;
+
tmr_idx = ice_get_ptp_src_clock_index(hw);
guard(spinlock)(&pf->adapter->ptp_gltsyn_time_lock);
/* Read the system timestamp pre PHC read */
@@ -2673,6 +2676,31 @@ static void ice_ptp_periodic_work(struct kthread_work *work)
msecs_to_jiffies(err ? 10 : 500));
}
+/**
+ * ice_ptp_prepare_rebuild_sec - Prepare second NAC for PTP reset or rebuild
+ * @pf: Board private structure
+ * @rebuild: rebuild if true, prepare if false
+ * @reset_type: the reset type being performed
+ */
+static void ice_ptp_prepare_rebuild_sec(struct ice_pf *pf, bool rebuild,
+ enum ice_reset_req reset_type)
+{
+ struct ice_ptp_port *port;
+
+ mutex_lock(&pf->ptp.ports_owner.lock);
+ list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member) {
+ struct ice_pf *peer_pf = ptp_port_to_pf(port);
+
+ if (!peer_pf->hw.ptp.primary_nac) {
+ if (rebuild)
+ ice_ptp_rebuild(peer_pf, reset_type);
+ else
+ ice_ptp_prepare_for_reset(peer_pf, reset_type);
+ }
+ }
+ mutex_unlock(&pf->ptp.ports_owner.lock);
+}
+
/**
* ice_ptp_prepare_for_reset - Prepare PTP for reset
* @pf: Board private structure
@@ -2681,6 +2709,7 @@ static void ice_ptp_periodic_work(struct kthread_work *work)
void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
{
struct ice_ptp *ptp = &pf->ptp;
+ struct ice_hw *hw = &pf->hw;
u8 src_tmr;
if (ptp->state != ICE_PTP_READY)
@@ -2696,15 +2725,18 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
if (reset_type == ICE_RESET_PFR)
return;
+ if (ice_pf_src_tmr_owned(pf) && ice_is_e825c(hw))
+ ice_ptp_prepare_rebuild_sec(pf, false, reset_type);
+
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);
+ src_tmr = ice_get_ptp_src_clock_index(hw);
/* Disable source clock */
- wr32(&pf->hw, GLTSYN_ENA(src_tmr), (u32)~GLTSYN_ENA_TSYN_ENA_M);
+ wr32(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();
@@ -2800,6 +2832,9 @@ void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
err = ice_ptp_rebuild_owner(pf);
if (err)
goto err;
+
+ if (ice_is_e825c(&pf->hw))
+ ice_ptp_prepare_rebuild_sec(pf, true, reset_type);
}
ptp->state = ICE_PTP_READY;
@@ -2872,6 +2907,9 @@ static int ice_ptp_auxbus_probe(struct auxiliary_device *aux_dev,
&owner_pf->ptp.ports_owner.ports);
mutex_unlock(&owner_pf->ptp.ports_owner.lock);
+ if (!aux_pf->hw.ptp.primary_nac)
+ aux_pf->hw.ptp.primary_hw = &owner_pf->hw;
+
return 0;
}
@@ -2949,6 +2987,7 @@ static int ice_ptp_register_auxbus_driver(struct ice_pf *pf)
{
struct auxiliary_driver *aux_driver;
struct ice_ptp *ptp;
+ char busdev[8] = {};
struct device *dev;
char *name;
int err;
@@ -2958,8 +2997,10 @@ static int ice_ptp_register_auxbus_driver(struct ice_pf *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),
+ if (ice_is_e810(&pf->hw))
+ sprintf(busdev, "%u_%u_", pf->pdev->bus->number,
+ PCI_SLOT(pf->pdev->devfn));
+ name = devm_kasprintf(dev, GFP_KERNEL, "ptp_%sclk%u", busdev,
ice_get_ptp_src_clock_index(&pf->hw));
if (!name)
return -ENOMEM;
@@ -3163,6 +3204,7 @@ static int ice_ptp_create_auxbus_device(struct ice_pf *pf)
{
struct auxiliary_device *aux_dev;
struct ice_ptp *ptp;
+ char busdev[8] = {};
struct device *dev;
char *name;
int err;
@@ -3174,8 +3216,11 @@ static int ice_ptp_create_auxbus_device(struct ice_pf *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),
+ if (ice_is_e810(&pf->hw))
+ sprintf(busdev, "%u_%u_", pf->pdev->bus->number,
+ PCI_SLOT(pf->pdev->devfn));
+
+ name = devm_kasprintf(dev, GFP_KERNEL, "ptp_%sclk%u", busdev,
ice_get_ptp_src_clock_index(&pf->hw));
if (!name)
return -ENOMEM;
@@ -3263,6 +3308,11 @@ void ice_ptp_init(struct ice_pf *pf)
ptp->state = ICE_PTP_INITIALIZING;
+ if (ice_is_e825c(hw) && !ice_is_primary(pf))
+ hw->ptp.primary_nac = false;
+ else
+ hw->ptp.primary_nac = true;
+
ice_ptp_init_hw(hw);
ice_ptp_init_tx_interrupt_mode(pf);
@@ -834,7 +834,10 @@ void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
{
u32 cmd_val = ice_ptp_tmr_cmd_to_src_reg(hw, cmd);
- wr32(hw, GLTSYN_CMD, cmd_val);
+ if (hw->ptp.primary_nac)
+ wr32(hw, GLTSYN_CMD, cmd_val);
+ else
+ wr32(hw->ptp.primary_hw, GLTSYN_CMD, cmd_val);
}
/**
@@ -850,7 +853,10 @@ static void ice_ptp_exec_tmr_cmd(struct ice_hw *hw)
struct ice_pf *pf = container_of(hw, struct ice_pf, hw);
guard(spinlock)(&pf->adapter->ptp_gltsyn_time_lock);
- wr32(hw, GLTSYN_CMD_SYNC, SYNC_EXEC_CMD);
+ if (hw->ptp.primary_nac)
+ wr32(hw, GLTSYN_CMD_SYNC, SYNC_EXEC_CMD);
+ else
+ wr32(hw->ptp.primary_hw, GLTSYN_CMD_SYNC, SYNC_EXEC_CMD);
ice_flush(hw);
}
@@ -2168,8 +2174,13 @@ static int ice_read_phy_and_phc_time_eth56g(struct ice_hw *hw, u8 port,
ice_ptp_exec_tmr_cmd(hw);
/* Read the captured PHC time from the shadow time registers */
- zo = rd32(hw, GLTSYN_SHTIME_0(tmr_idx));
- lo = rd32(hw, GLTSYN_SHTIME_L(tmr_idx));
+ if (hw->ptp.primary_nac) {
+ zo = rd32(hw, GLTSYN_SHTIME_0(tmr_idx));
+ lo = rd32(hw, GLTSYN_SHTIME_L(tmr_idx));
+ } else {
+ zo = rd32(hw->ptp.primary_hw, GLTSYN_SHTIME_0(tmr_idx));
+ lo = rd32(hw->ptp.primary_hw, GLTSYN_SHTIME_L(tmr_idx));
+ }
*phc_time = (u64)lo << 32 | zo;
/* Read the captured PHY time from the PHY shadow registers */
@@ -2319,8 +2330,13 @@ int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port)
if (err)
return err;
- lo = rd32(hw, GLTSYN_INCVAL_L(tmr_idx));
- hi = rd32(hw, GLTSYN_INCVAL_H(tmr_idx));
+ if (hw->ptp.primary_nac) {
+ lo = rd32(hw, GLTSYN_INCVAL_L(tmr_idx));
+ hi = rd32(hw, GLTSYN_INCVAL_H(tmr_idx));
+ } else {
+ lo = rd32(hw->ptp.primary_hw, GLTSYN_INCVAL_L(tmr_idx));
+ hi = rd32(hw->ptp.primary_hw, GLTSYN_INCVAL_H(tmr_idx));
+ }
incval = (u64)hi << 32 | lo;
err = ice_write_40b_ptp_reg_eth56g(hw, port, PHY_REG_TIMETUS_L, incval);
@@ -858,6 +858,8 @@ struct ice_ptp_hw {
union ice_phy_params phy;
u8 num_lports;
u8 ports_per_phy;
+ bool primary_nac;
+ struct ice_hw *primary_hw;
};
/* Port hardware description */