]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iavf: handle set and get timestamps ops
authorJacob Keller <jacob.e.keller@intel.com>
Wed, 6 Nov 2024 17:37:30 +0000 (12:37 -0500)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Fri, 14 Feb 2025 18:58:08 +0000 (10:58 -0800)
Add handlers for the .ndo_hwtstamp_get and .ndo_hwtstamp_set ops which
allow userspace to request timestamp enablement for the device. This
support allows standard Linux applications to request the timestamping
desired.

As with other devices that support timestamping all packets, the driver
will upgrade any request for timestamping of a specific type of packet
to HWTSTAMP_FILTER_ALL.

The current configuration is stored, so that it can be retrieved by
calling .ndo_hwtstamp_get

The Tx timestamps are not implemented yet so calling set ops for
Tx path will end with EOPNOTSUPP error code.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Co-developed-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com>
Signed-off-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_ptp.c
drivers/net/ethernet/intel/iavf/iavf_ptp.h
drivers/net/ethernet/intel/iavf/iavf_txrx.h

index d545b34496e73433116f4ec845de1c4b47b7e199..2d908ff0152ca0ae961993378352f21e2155d258 100644 (file)
@@ -5170,6 +5170,25 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev,
        return iavf_fix_strip_features(adapter, features);
 }
 
+static int iavf_hwstamp_get(struct net_device *netdev,
+                           struct kernel_hwtstamp_config *config)
+{
+       struct iavf_adapter *adapter = netdev_priv(netdev);
+
+       *config = adapter->ptp.hwtstamp_config;
+
+       return 0;
+}
+
+static int iavf_hwstamp_set(struct net_device *netdev,
+                           struct kernel_hwtstamp_config *config,
+                           struct netlink_ext_ack *extack)
+{
+       struct iavf_adapter *adapter = netdev_priv(netdev);
+
+       return iavf_ptp_set_ts_config(adapter, config, extack);
+}
+
 static int
 iavf_verify_shaper(struct net_shaper_binding *binding,
                   const struct net_shaper *shaper,
@@ -5278,6 +5297,8 @@ static const struct net_device_ops iavf_netdev_ops = {
        .ndo_set_features       = iavf_set_features,
        .ndo_setup_tc           = iavf_setup_tc,
        .net_shaper_ops         = &iavf_shaper_ops,
+       .ndo_hwtstamp_get       = iavf_hwstamp_get,
+       .ndo_hwtstamp_set       = iavf_hwstamp_set,
 };
 
 /**
index c2e0d27552b00dd3bc6cd6dbe62f9f7b1fbdf74f..4246ddfa6f0d25fbf930915cbceae5497cdcbec0 100644 (file)
@@ -7,6 +7,100 @@
 #define iavf_clock_to_adapter(info)                            \
        container_of_const(info, struct iavf_adapter, ptp.info)
 
+/**
+ * iavf_ptp_disable_rx_tstamp - Disable timestamping in Rx rings
+ * @adapter: private adapter structure
+ *
+ * Disable timestamp reporting for all Rx rings.
+ */
+static void iavf_ptp_disable_rx_tstamp(struct iavf_adapter *adapter)
+{
+       for (u32 i = 0; i < adapter->num_active_queues; i++)
+               adapter->rx_rings[i].flags &= ~IAVF_TXRX_FLAGS_HW_TSTAMP;
+}
+
+/**
+ * iavf_ptp_enable_rx_tstamp - Enable timestamping in Rx rings
+ * @adapter: private adapter structure
+ *
+ * Enable timestamp reporting for all Rx rings.
+ */
+static void iavf_ptp_enable_rx_tstamp(struct iavf_adapter *adapter)
+{
+       for (u32 i = 0; i < adapter->num_active_queues; i++)
+               adapter->rx_rings[i].flags |= IAVF_TXRX_FLAGS_HW_TSTAMP;
+}
+
+/**
+ * iavf_ptp_set_timestamp_mode - Set device timestamping mode
+ * @adapter: private adapter structure
+ * @config: pointer to kernel_hwtstamp_config
+ *
+ * Set the timestamping mode requested from the userspace.
+ *
+ * Note: this function always translates Rx timestamp requests for any packet
+ * category into HWTSTAMP_FILTER_ALL.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+static int iavf_ptp_set_timestamp_mode(struct iavf_adapter *adapter,
+                                      struct kernel_hwtstamp_config *config)
+{
+       /* Reserved for future extensions. */
+       if (config->flags)
+               return -EINVAL;
+
+       switch (config->tx_type) {
+       case HWTSTAMP_TX_OFF:
+               break;
+       case HWTSTAMP_TX_ON:
+               return -EOPNOTSUPP;
+       default:
+               return -ERANGE;
+       }
+
+       if (config->rx_filter == HWTSTAMP_FILTER_NONE) {
+               iavf_ptp_disable_rx_tstamp(adapter);
+               return 0;
+       } else if (config->rx_filter > HWTSTAMP_FILTER_NTP_ALL) {
+               return -ERANGE;
+       } else if (!(iavf_ptp_cap_supported(adapter,
+                                           VIRTCHNL_1588_PTP_CAP_RX_TSTAMP))) {
+               return -EOPNOTSUPP;
+       }
+
+       config->rx_filter = HWTSTAMP_FILTER_ALL;
+       iavf_ptp_enable_rx_tstamp(adapter);
+
+       return 0;
+}
+
+/**
+ * iavf_ptp_set_ts_config - Set timestamping configuration
+ * @adapter: private adapter structure
+ * @config: pointer to kernel_hwtstamp_config structure
+ * @extack: pointer to netlink_ext_ack structure
+ *
+ * Program the requested timestamping configuration to the device.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+int iavf_ptp_set_ts_config(struct iavf_adapter *adapter,
+                          struct kernel_hwtstamp_config *config,
+                          struct netlink_ext_ack *extack)
+{
+       int err;
+
+       err = iavf_ptp_set_timestamp_mode(adapter, config);
+       if (err)
+               return err;
+
+       /* Save successful settings for future reference */
+       adapter->ptp.hwtstamp_config = *config;
+
+       return 0;
+}
+
 /**
  * iavf_ptp_cap_supported - Check if a PTP capability is supported
  * @adapter: private adapter structure
@@ -321,4 +415,10 @@ void iavf_ptp_process_caps(struct iavf_adapter *adapter)
                iavf_ptp_release(adapter);
        else if (!adapter->ptp.clock && phc)
                iavf_ptp_init(adapter);
+
+       /* Check if the device lost access to Rx timestamp incoming packets */
+       if (!iavf_ptp_cap_supported(adapter, VIRTCHNL_1588_PTP_CAP_RX_TSTAMP)) {
+               adapter->ptp.hwtstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+               iavf_ptp_disable_rx_tstamp(adapter);
+       }
 }
index 8e2f1ed18b868616489c8f372448e02b21a35a08..0801e3ff5a5965c0d638a8694e825d0c9f2df1b9 100644 (file)
@@ -12,6 +12,9 @@ void iavf_ptp_release(struct iavf_adapter *adapter);
 void iavf_ptp_process_caps(struct iavf_adapter *adapter);
 bool iavf_ptp_cap_supported(const struct iavf_adapter *adapter, u32 cap);
 void iavf_virtchnl_send_ptp_cmd(struct iavf_adapter *adapter);
+int iavf_ptp_set_ts_config(struct iavf_adapter *adapter,
+                          struct kernel_hwtstamp_config *config,
+                          struct netlink_ext_ack *extack);
 #else /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */
 static inline void iavf_ptp_init(struct iavf_adapter *adapter) { }
 static inline void iavf_ptp_release(struct iavf_adapter *adapter) { }
@@ -23,5 +26,11 @@ static inline bool iavf_ptp_cap_supported(const struct iavf_adapter *adapter,
 }
 
 static inline void iavf_virtchnl_send_ptp_cmd(struct iavf_adapter *adapter) { }
+static inline int iavf_ptp_set_ts_config(struct iavf_adapter *adapter,
+                                        struct kernel_hwtstamp_config *config,
+                                        struct netlink_ext_ack *extack)
+{
+       return -1;
+}
 #endif /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */
 #endif /* _IAVF_PTP_H_ */
index dff5c8cd27ab89e0d030847c33392c2fddfd5bba..79ad554f2d53b35bf91a91bb9ab0cb2b8f52e7df 100644 (file)
@@ -252,6 +252,7 @@ struct iavf_ring {
 #define IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1    BIT(3)
 #define IAVF_TXR_FLAGS_VLAN_TAG_LOC_L2TAG2     BIT(4)
 #define IAVF_RXR_FLAGS_VLAN_TAG_LOC_L2TAG2_2   BIT(5)
+#define IAVF_TXRX_FLAGS_HW_TSTAMP              BIT(6)
 
        /* stats structs */
        struct iavf_queue_stats stats;