diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.c b/drivers/net/ethernet/intel/ice/ice_adapter.c index ad84d8ad49a6..f3e195974a8e 100644 --- a/drivers/net/ethernet/intel/ice/ice_adapter.c +++ b/drivers/net/ethernet/intel/ice/ice_adapter.c @@ -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); } diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.h b/drivers/net/ethernet/intel/ice/ice_adapter.h index eb7cac01c242..e233225848b3 100644 --- a/drivers/net/ethernet/intel/ice/ice_adapter.h +++ b/drivers/net/ethernet/intel/ice/ice_adapter.h @@ -4,18 +4,34 @@ #ifndef _ICE_ADAPTER_H_ #define _ICE_ADAPTER_H_ +#include #include #include 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 + * @ports: Ports list */ struct ice_adapter { refcount_t refcount; @@ -23,6 +39,7 @@ struct ice_adapter { spinlock_t ptp_gltsyn_time_lock; struct ice_pf *ctrl_pf; + struct ice_port_list ports; }; struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev); diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index 2fb73ab41bc2..0b3dd87a331c 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -21,7 +21,7 @@ static struct ice_pf *ice_get_ctrl_pf(struct ice_pf *pf) return !pf->adapter ? NULL : pf->adapter->ctrl_pf; } -static __maybe_unused struct ice_ptp *ice_get_ctrl_ptp(struct ice_pf *pf) +static struct ice_ptp *ice_get_ctrl_ptp(struct ice_pf *pf) { struct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf); @@ -812,8 +812,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) @@ -821,7 +821,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; @@ -986,7 +986,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); } @@ -1586,10 +1586,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); @@ -2906,6 +2906,50 @@ err: dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err); } +static bool ice_is_primary(struct ice_hw *hw) +{ + return ice_is_e825c(hw) && ice_is_dual(hw) ? + !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M) : true; +} + +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 @@ -2957,9 +3001,9 @@ static int ice_ptp_auxbus_probe(struct auxiliary_device *aux_dev, if (WARN_ON(!owner_pf)) return -ENODEV; - INIT_LIST_HEAD(&aux_pf->ptp.port.list_member); + INIT_LIST_HEAD(&aux_pf->ptp.port.list_node); mutex_lock(&owner_pf->ptp.ports_owner.lock); - list_add(&aux_pf->ptp.port.list_member, + list_add(&aux_pf->ptp.port.list_node, &owner_pf->ptp.ports_owner.ports); mutex_unlock(&owner_pf->ptp.ports_owner.lock); @@ -2976,7 +3020,7 @@ static void ice_ptp_auxbus_remove(struct auxiliary_device *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); + list_del(&aux_pf->ptp.port.list_node); mutex_unlock(&owner_pf->ptp.ports_owner.lock); } @@ -3036,7 +3080,7 @@ ice_ptp_auxbus_create_id_table(struct ice_pf *pf, const char *name) * 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) +static int __always_unused ice_ptp_register_auxbus_driver(struct ice_pf *pf) { struct auxiliary_driver *aux_driver; struct ice_ptp *ptp; @@ -3079,7 +3123,7 @@ static int ice_ptp_register_auxbus_driver(struct ice_pf *pf) * 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) +static void __always_unused ice_ptp_unregister_auxbus_driver(struct ice_pf *pf) { struct auxiliary_driver *aux_driver = &pf->ptp.ports_owner.aux_driver; @@ -3098,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; } @@ -3166,15 +3207,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf) if (err) goto err_clk; - 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: - ptp_clock_unregister(pf->ptp.clock); err_clk: pf->ptp.clock = NULL; err_exit: @@ -3250,7 +3283,7 @@ static void ice_ptp_release_auxbus_device(struct device *dev) * 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) +static __always_unused int ice_ptp_create_auxbus_device(struct ice_pf *pf) { struct auxiliary_device *aux_dev; struct ice_ptp *ptp; @@ -3297,7 +3330,7 @@ aux_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) +static __always_unused void ice_ptp_remove_auxbus_device(struct ice_pf *pf) { struct auxiliary_device *aux_dev = &pf->ptp.port.aux_dev; @@ -3361,19 +3394,26 @@ 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 (ice_pf_src_tmr_owned(pf)) { + if (ice_pf_src_tmr_owned(pf) && ice_is_primary(hw)) { + 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); @@ -3381,20 +3421,16 @@ void ice_ptp_init(struct ice_pf *pf) /* Configure initial Tx interrupt settings */ ice_ptp_cfg_tx_interrupt(pf); - err = ice_ptp_create_auxbus_device(pf); - if (err) - goto err; - ptp->state = ICE_PTP_READY; 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); @@ -3421,7 +3457,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); @@ -3436,9 +3472,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; diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h index 2db2257a0fb2..5615efc42c62 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp.h @@ -169,7 +169,7 @@ 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 @@ -179,7 +179,7 @@ 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; @@ -205,6 +205,7 @@ enum ice_ptp_tx_interrupt { * @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; diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h index 4c8b84571344..3499062218b5 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h @@ -452,6 +452,11 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw) } } +static inline bool ice_is_dual(struct ice_hw *hw) +{ + return !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_DUAL_M); +} + #define PFTSYN_SEM_BYTES 4 #define ICE_PTP_CLOCK_INDEX_0 0x00