From: Mateusz Polchlopek <mateusz.polchlo...@intel.com> Date: Tue, 30 Jul 2024 05:15:02 -0400
> From: Jacob Keller <jacob.e.kel...@intel.com> > > Implement support for reading the PHC time indirectly via the > VIRTCHNL_OP_1588_PTP_GET_TIME operation. [...] > diff --git a/drivers/net/ethernet/intel/iavf/iavf_ptp.c > b/drivers/net/ethernet/intel/iavf/iavf_ptp.c > index 1344298481d4..46c4f8e11bdd 100644 > --- a/drivers/net/ethernet/intel/iavf/iavf_ptp.c > +++ b/drivers/net/ethernet/intel/iavf/iavf_ptp.c > @@ -3,6 +3,23 @@ > > #include "iavf.h" > > +/** > + * clock_to_adapter - Convert clock info pointer to adapter pointer > + * @ptp_info: PTP info structure > + * > + * Use container_of in order to extract a pointer to the iAVF adapter private > + * structure. > + * > + * Return: pointer to iavf_adapter structure > + */ > +static struct iavf_adapter *clock_to_adapter(struct ptp_clock_info *ptp_info) > +{ > + struct iavf_ptp *ptp_priv; > + > + ptp_priv = container_of(ptp_info, struct iavf_ptp, info); > + return container_of(ptp_priv, struct iavf_adapter, ptp); 1. 'iavf_' prefix. 2. #define iavf_clock_to_adapter(info) \ container_of_const(info, struct iavf_adapter, ptp.info) > +} [...] > +/** > + * iavf_send_phc_read - Send request to read PHC time > + * @adapter: private adapter structure > + * > + * Send a request to obtain the PTP hardware clock time. This allocates the > + * VIRTCHNL_OP_1588_PTP_GET_TIME message and queues it up to send to > + * indirectly read the PHC time. > + * > + * This function does not wait for the reply from the PF. > + * > + * Return: 0 if success, error code otherwise Period at the end of the sentence. > + */ > +static int iavf_send_phc_read(struct iavf_adapter *adapter) > +{ > + struct iavf_ptp_aq_cmd *cmd; > + > + if (!adapter->ptp.initialized) > + return -EOPNOTSUPP; > + > + cmd = iavf_allocate_ptp_cmd(VIRTCHNL_OP_1588_PTP_GET_TIME, > + sizeof(struct virtchnl_phc_time)); > + if (!cmd) > + return -ENOMEM; > + > + iavf_queue_ptp_cmd(adapter, cmd); > + > + return 0; > +} > + > +/** > + * iavf_read_phc_indirect - Indirectly read the PHC time via virtchnl > + * @adapter: private adapter structure > + * @ts: storage for the timestamp value > + * @sts: system timestamp values before and after the read > + * > + * Used when the device does not have direct register access to the PHC time. > + * Indirectly reads the time via the VIRTCHNL_OP_1588_PTP_GET_TIME, and waits > + * for the reply from the PF. > + * > + * Based on some simple measurements using ftrace and phc2sys, this clock > + * access method has about a ~110 usec latency even when the system is not > + * under load. In order to achieve acceptable results when using phc2sys with > + * the indirect clock access method, it is recommended to use more > + * conservative proportional and integration constants with the P/I servo. > + * > + * Return: 0 if success, error code otherwise Same. > + */ > +static int iavf_read_phc_indirect(struct iavf_adapter *adapter, > + struct timespec64 *ts, > + struct ptp_system_timestamp *sts) > +{ > + long ret; > + int err; > + > + adapter->ptp.phc_time_ready = false; > + ptp_read_system_prets(sts); [...] > diff --git a/drivers/net/ethernet/intel/iavf/iavf_ptp.h > b/drivers/net/ethernet/intel/iavf/iavf_ptp.h > index 4939c219bd18..24081b01fb16 100644 > --- a/drivers/net/ethernet/intel/iavf/iavf_ptp.h > +++ b/drivers/net/ethernet/intel/iavf/iavf_ptp.h > @@ -6,10 +6,25 @@ > > #include <linux/ptp_clock_kernel.h> > > +/* structure used to queue PTP commands for processing */ > +struct iavf_ptp_aq_cmd { > + struct list_head list; > + enum virtchnl_ops v_opcode; You can make it `v_opcode:16` to avoid a hole here. > + u16 msglen; > + u8 msg[]; u8 msg[] __counted_by(msglen); > +}; > + > /* fields used for PTP support */ > struct iavf_ptp { > + wait_queue_head_t phc_time_waitqueue; > struct virtchnl_ptp_caps hw_caps; > + struct list_head aq_cmds; > + /* Lock protecting access to the AQ command list */ > + struct mutex aq_cmd_lock; > + u64 cached_phc_time; > + unsigned long cached_phc_updated; > bool initialized; > + bool phc_time_ready; These two can be `bool :1`. > struct ptp_clock_info info; > struct ptp_clock *clock; > }; > @@ -18,5 +33,6 @@ void iavf_ptp_init(struct iavf_adapter *adapter); > void iavf_ptp_release(struct iavf_adapter *adapter); > void iavf_ptp_process_caps(struct iavf_adapter *adapter); > bool iavf_ptp_cap_supported(struct iavf_adapter *adapter, u32 cap); > +void iavf_virtchnl_send_ptp_cmd(struct iavf_adapter *adapter); > > #endif /* _IAVF_PTP_H_ */ > diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c > b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c > index a75a9cf46591..4163dfe90b4a 100644 > --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c > +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c > @@ -1532,6 +1532,63 @@ void iavf_disable_vlan_insertion_v2(struct > iavf_adapter *adapter, u16 tpid) > VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2); > } > > +/** > + * iavf_virtchnl_send_ptp_cmd - Send one queued PTP command > + * @adapter: adapter private structure > + * > + * De-queue one PTP command request and send the command message to the PF. > + * Clear IAVF_FLAG_AQ_SEND_PTP_CMD if no more messages are left to send. > + */ > +void iavf_virtchnl_send_ptp_cmd(struct iavf_adapter *adapter) > +{ > + struct device *dev = &adapter->pdev->dev; > + struct iavf_ptp_aq_cmd *cmd; > + int err; > + > + if (WARN_ON(!adapter->ptp.initialized)) { (no WARN()s) > + /* This shouldn't be possible to hit, since no messages should > + * be queued if PTP is not initialized. > + */ > + adapter->aq_required &= ~IAVF_FLAG_AQ_SEND_PTP_CMD; > + return; > + } [...] Thanks, Olek