@@ -40,11 +40,17 @@ static struct ice_adapter *ice_adapter_new(void)
spin_lock_init(&adapter->ptp_gltsyn_time_lock);
refcount_set(&adapter->refcount, 1);
+ mutex_init(&adapter->ports.lock);
+ INIT_LIST_HEAD(&adapter->ports.ports);
+
return adapter;
}
static void ice_adapter_free(struct ice_adapter *adapter)
{
+ WARN_ON(!list_empty(&adapter->ports.ports));
+ mutex_destroy(&adapter->ports.lock);
+
kfree(adapter);
}
@@ -4,22 +4,41 @@
#ifndef _ICE_ADAPTER_H_
#define _ICE_ADAPTER_H_
+#include <linux/types.h>
#include <linux/spinlock_types.h>
#include <linux/refcount_types.h>
struct pci_dev;
+struct ice_pf;
+
+/**
+ * struct ice_port_list - data used to store the list of adapter ports
+ *
+ * This structure contains data used to maintain a list of adapter ports
+ *
+ * @ports: list of ports
+ * @lock: protect access to the ports list
+ */
+struct ice_port_list {
+ struct list_head ports;
+ /* To synchronize the ports list operations */
+ struct mutex lock;
+};
/**
* struct ice_adapter - PCI adapter resources shared across PFs
* @ptp_gltsyn_time_lock: Spinlock protecting access to the GLTSYN_TIME
* register of the PTP clock.
* @refcount: Reference count. struct ice_pf objects hold the references.
+ * @ctrl_pf: Control PF of the adapter
*/
struct ice_adapter {
/* For access to the GLTSYN_TIME register */
spinlock_t ptp_gltsyn_time_lock;
-
refcount_t refcount;
+
+ struct ice_pf *ctrl_pf;
+ struct ice_port_list ports;
};
struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev);
@@ -821,8 +821,8 @@ 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) {
+ mutex_lock(&pf->adapter->ports.lock);
+ list_for_each_entry(port, &pf->adapter->ports.ports, list_node) {
struct ice_ptp_tx *tx = &port->tx;
if (!tx || !tx->init)
@@ -830,7 +830,7 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
ice_ptp_process_tx_tstamp(tx);
}
- mutex_unlock(&pf->ptp.ports_owner.lock);
+ mutex_unlock(&pf->adapter->ports.lock);
for (i = 0; i < ICE_GET_QUAD_NUM(pf->hw.ptp.num_lports); i++) {
u64 tstamp_ready;
@@ -995,7 +995,7 @@ 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)
+ list_for_each_entry(port, &pf->adapter->ports.ports, list_node)
ice_ptp_flush_tx_tracker(ptp_port_to_pf(port), &port->tx);
}
@@ -1592,10 +1592,10 @@ static void ice_ptp_restart_all_phy(struct ice_pf *pf)
{
struct list_head *entry;
- list_for_each(entry, &pf->ptp.ports_owner.ports) {
+ list_for_each(entry, &pf->adapter->ports.ports) {
struct ice_ptp_port *port = list_entry(entry,
struct ice_ptp_port,
- list_member);
+ list_node);
if (port->link_up)
ice_ptp_port_phy_restart(port);
@@ -2912,6 +2912,44 @@ void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err);
}
+static int ice_ptp_setup_adapter(struct ice_pf *pf)
+{
+ if (!ice_pf_src_tmr_owned(pf) || !ice_is_primary(&pf->hw))
+ return -EPERM;
+
+ pf->adapter->ctrl_pf = pf;
+
+ return 0;
+}
+
+static int ice_ptp_setup_pf(struct ice_pf *pf)
+{
+ struct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(pf);
+ struct ice_ptp *ptp = &pf->ptp;
+
+ if (WARN_ON(!ctrl_ptp) || ice_get_phy_model(&pf->hw) == ICE_PHY_UNSUP)
+ return -ENODEV;
+
+ INIT_LIST_HEAD(&ptp->port.list_node);
+ mutex_lock(&pf->adapter->ports.lock);
+
+ list_add(&ptp->port.list_node,
+ &pf->adapter->ports.ports);
+ mutex_unlock(&pf->adapter->ports.lock);
+
+ return 0;
+}
+
+static void ice_ptp_cleanup_pf(struct ice_pf *pf)
+{
+ struct ice_ptp *ptp = &pf->ptp;
+
+ if (ice_get_phy_model(&pf->hw) != ICE_PHY_UNSUP) {
+ mutex_lock(&pf->adapter->ports.lock);
+ list_del(&ptp->port.list_node);
+ mutex_unlock(&pf->adapter->ports.lock);
+ }
+}
/**
* 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
@@ -3104,15 +3142,12 @@ static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf)
*/
int ice_ptp_clock_index(struct ice_pf *pf)
{
- struct auxiliary_device *aux_dev;
- struct ice_pf *owner_pf;
+ struct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(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)
+ if (!ctrl_ptp)
return -1;
- clock = owner_pf->ptp.clock;
+ clock = ctrl_ptp->clock;
return clock ? ptp_clock_index(clock) : -1;
}
@@ -3368,18 +3403,25 @@ void ice_ptp_init(struct ice_pf *pf)
* configure the PTP clock device to represent it.
*/
if (ice_pf_src_tmr_owned(pf)) {
+ err = ice_ptp_setup_adapter(pf);
+ if (err)
+ goto err_exit;
err = ice_ptp_init_owner(pf);
if (err)
- goto err;
+ goto err_exit;
}
+ err = ice_ptp_setup_pf(pf);
+ if (err)
+ goto err_exit;
+
ptp->port.port_num = hw->pf_id;
if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
ptp->port.port_num = hw->pf_id * 2;
err = ice_ptp_init_port(pf, &ptp->port);
if (err)
- goto err;
+ goto err_exit;
/* Start the PHY timestamping block */
ice_ptp_reset_phy_timestamping(pf);
@@ -3395,12 +3437,12 @@ void ice_ptp_init(struct ice_pf *pf)
err = ice_ptp_init_work(pf, ptp);
if (err)
- goto err;
+ goto err_exit;
dev_info(ice_pf_to_dev(pf), "PTP init successful\n");
return;
-err:
+err_exit:
/* If we registered a PTP clock, release it */
if (pf->ptp.clock) {
ptp_clock_unregister(ptp->clock);
@@ -3427,7 +3469,7 @@ void ice_ptp_release(struct ice_pf *pf)
/* Disable timestamping for both Tx and Rx */
ice_ptp_disable_timestamp_mode(pf);
- ice_ptp_remove_auxbus_device(pf);
+ ice_ptp_cleanup_pf(pf);
ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
@@ -3442,9 +3484,6 @@ 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;
@@ -169,9 +169,8 @@ 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
+ * @list_node: list member structure
* @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
@@ -179,9 +178,8 @@ struct ice_ptp_tx {
* @port_num: the port number this structure represents
*/
struct ice_ptp_port {
- struct list_head list_member;
+ struct list_head list_node;
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;
@@ -195,22 +193,6 @@ enum ice_ptp_tx_interrupt {
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
enum ice_ptp_state {
@@ -226,7 +208,6 @@ enum ice_ptp_state {
* @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
* @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
@@ -250,7 +231,6 @@ 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;
struct kthread_delayed_work work;
u64 cached_phc_time;
unsigned long cached_phc_jiffies;
@@ -451,6 +451,11 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
}
}
+static inline bool ice_is_primary(struct ice_hw *hw)
+{
+ return !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M);
+}
+
#define PFTSYN_SEM_BYTES 4
#define ICE_PTP_CLOCK_INDEX_0 0x00