diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.c b/drivers/net/ethernet/intel/ice/ice_adapter.c
index 536923b6ae97..572862fcd247 100644
--- a/drivers/net/ethernet/intel/ice/ice_adapter.c
+++ b/drivers/net/ethernet/intel/ice/ice_adapter.c
@@ -77,6 +77,8 @@ static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev)
spin_lock_init(&adapter->ports.lock);
INIT_LIST_HEAD(&adapter->ports.list);
+ mutex_init(&adapter->ps_lock);
+
return adapter;
}
@@ -87,6 +89,7 @@ static void ice_adapter_free(struct ice_adapter *adapter)
mutex_destroy(&adapter->cpi_phy_lock[i]);
cleanup_srcu_struct(&adapter->ports.srcu);
+ mutex_destroy(&adapter->ps_lock);
kfree(adapter);
}
diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.h b/drivers/net/ethernet/intel/ice/ice_adapter.h
index 0b01c7f5cf0d..5f39166795b6 100644
--- a/drivers/net/ethernet/intel/ice/ice_adapter.h
+++ b/drivers/net/ethernet/intel/ice/ice_adapter.h
@@ -40,6 +40,7 @@ struct ice_port_list {
* @txq_ctx_lock: Spinlock protecting access to the GLCOMM_QTX_CNTX_CTL register
* @cpi_phy_lock: Per-PHY mutex serializing CPI REQ/ACK transactions.
* Index 0 = PHY0, index 1 = PHY1. Used on E825C devices.
+ * @ps_lock: Mutex to serialize PHY port start/stop across adapter.
* @ctrl_pf: Control PF of the adapter
* @ports: Ports list
* @index: 64-bit index cached for collision detection on 32bit systems@@ -53,6 +54,9 @@ struct ice_adapter {
/* Serialize CPI REQ/ACK transactions per PHY (E825C only) */
struct mutex cpi_phy_lock[ICE_E825_MAX_PHYS];
+ /* For serializing PHY port start/stop sequences */
+ struct mutex ps_lock;
+
struct ice_pf *ctrl_pf;
struct ice_port_list ports;
u64 index;diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 55241802d17a..d1cdd38ea27c 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -1195,6 +1195,8 @@ static void ice_ptp_wait_for_offsets(struct kthread_work *work)
/**
* ice_ptp_port_phy_stop - Stop timestamping for a PHY port
* @ptp_port: PTP port to stop
+ *
+ * Context: must hold the adapter ps_lock.
*/
static int
ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port)
@@ -1204,7 +1206,7 @@ ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port)
struct ice_hw *hw = &pf->hw;
int err;
- mutex_lock(&ptp_port->ps_lock);
+ lockdep_assert_held(&pf->adapter->ps_lock);
switch (hw->mac_type) {
case ICE_MAC_E810:@@ -1226,8 +1228,6 @@ ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port)
dev_err(ice_pf_to_dev(pf), "PTP failed to set PHY port %d down, err %d\n",
port, err);
- mutex_unlock(&ptp_port->ps_lock);
-
return err;
}
@@ -1238,6 +1238,8 @@ ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port)
* Start the PHY timestamping block, and initiate Vernier timestamping
* calibration. If timestamping cannot be calibrated (such as if link is down)
* then disable the timestamping block instead.
+ *
+ * Context: must hold the adapter ps_lock.
*/
static int
ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
@@ -1248,11 +1250,11 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
unsigned long flags;
int err;
+ lockdep_assert_held(&pf->adapter->ps_lock);
+
if (!ptp_port->link_up)
return ice_ptp_port_phy_stop(ptp_port);
- mutex_lock(&ptp_port->ps_lock);
-
switch (hw->mac_type) {
case ICE_MAC_E810:
case ICE_MAC_E830:@@ -1294,8 +1296,6 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
dev_err(ice_pf_to_dev(pf), "PTP failed to set PHY port %d up, err %d\n",
port, err);
- mutex_unlock(&ptp_port->ps_lock);
-
return err;
}
@@ -1314,12 +1314,13 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
ptp_port = &pf->ptp.port;
- /* Update cached link status for this port immediately */
+ mutex_lock(&pf->adapter->ps_lock);
+
ptp_port->link_up = linkup;
/* Skip HW writes if reset is in progress */
if (pf->hw.reset_ongoing)
- return;
+ goto out_unlock;
if (hw->mac_type == ICE_MAC_GENERIC_3K_E825 &&
test_bit(ICE_FLAG_DPLL, pf->flags)) {@@ -1362,17 +1363,20 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
case ICE_MAC_E810:
case ICE_MAC_E830:
/* Do not reconfigure E810 or E830 PHY */
- return;
+ break;
case ICE_MAC_GENERIC:
ice_ptp_port_phy_restart(ptp_port);
- return;
+ break;
case ICE_MAC_GENERIC_3K_E825:
if (linkup)
ice_ptp_port_phy_restart(ptp_port);
- return;
+ break;
default:
dev_warn(ice_pf_to_dev(pf), "%s: Unknown PHY type\n", __func__);
}
+
+out_unlock:
+ mutex_unlock(&pf->adapter->ps_lock);
}
/**
@@ -1438,18 +1442,11 @@ static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold)
}
}
-/**
- * ice_ptp_reset_phy_timestamping - Reset PHY timestamping block
- * @pf: Board private structure
- */
-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
+ *
+ * Context: acquires the adapter ps_lock
*/
static void ice_ptp_restart_all_phy(struct ice_pf *pf)
{@@ -1457,6 +1454,8 @@ static void ice_ptp_restart_all_phy(struct ice_pf *pf)
struct ice_ptp_port *port;
int srcu_idx;
+ mutex_lock(&pf->adapter->ps_lock);
+
srcu_idx = srcu_read_lock(&ports->srcu);
list_for_each_entry_srcu(port, &ports->list, list_node,
srcu_read_lock_held(&ports->srcu)) {@@ -1469,6 +1468,8 @@ static void ice_ptp_restart_all_phy(struct ice_pf *pf)
kref_put(&port->ref, ice_ptp_release_port_srcu);
}
srcu_read_unlock(&ports->srcu, srcu_idx);
+
+ mutex_unlock(&pf->adapter->ps_lock);
}
/**
@@ -3308,8 +3309,6 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
{
struct ice_hw *hw = &pf->hw;
- mutex_init(&ptp_port->ps_lock);
-
switch (hw->mac_type) {
case ICE_MAC_E810:
case ICE_MAC_E830:@@ -3420,7 +3419,9 @@ void ice_ptp_init(struct ice_pf *pf)
goto err_release_tx_tracker;
/* Start the PHY timestamping block */
- ice_ptp_reset_phy_timestamping(pf);
+ mutex_lock(&pf->adapter->ps_lock);
+ ice_ptp_port_phy_restart(&ptp->port);
+ mutex_unlock(&pf->adapter->ps_lock);
/* Configure initial Tx interrupt settings */
ice_ptp_cfg_tx_interrupt(pf);
@@ -3439,7 +3440,6 @@ void ice_ptp_init(struct ice_pf *pf)
kthread_cancel_delayed_work_sync(&ptp->work);
kthread_destroy_worker(ptp->kworker);
ptp->kworker = NULL;
- mutex_destroy(&ptp->port.ps_lock);
err_exit:
/* If we registered a PTP clock, release it */
if (pf->ptp.clock) {@@ -3479,7 +3479,6 @@ void ice_ptp_release(struct ice_pf *pf)
kthread_destroy_worker(pf->ptp.kworker);
pf->ptp.kworker = NULL;
}
- mutex_destroy(&pf->ptp.port.ps_lock);
pf->ptp.state = ICE_PTP_UNINIT;
return;
@@ -3498,8 +3497,10 @@ void ice_ptp_release(struct ice_pf *pf)
kthread_cancel_delayed_work_sync(&pf->ptp.work);
+ mutex_lock(&pf->adapter->ps_lock);
ice_ptp_port_phy_stop(&pf->ptp.port);
- mutex_destroy(&pf->ptp.port.ps_lock);
+ mutex_unlock(&pf->adapter->ps_lock);
+
if (pf->ptp.kworker) {
kthread_destroy_worker(pf->ptp.kworker);
pf->ptp.kworker = NULL;diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index da2003ba3bb0..27ea502b7576 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -143,7 +143,6 @@ struct ice_ptp_tx {
* @ref: reference counter for use with adapter ports list
* @tx: Tx timestamp tracking for 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
* @tx_fifo_busy_cnt: number of times the Tx FIFO was busy
* @port_num: the port number this structure represents@@ -155,7 +154,6 @@ struct ice_ptp_port {
struct kref ref;
struct ice_ptp_tx tx;
struct kthread_delayed_work ov_work;
- struct mutex ps_lock; /* protects overall PTP PHY start procedure */
bool link_up;
u8 tx_fifo_busy_cnt;
u8 port_num;--
2.47.1