]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ice: support Rx timestamp on flex descriptor
authorSimei Su <simei.su@intel.com>
Wed, 6 Nov 2024 17:37:19 +0000 (12:37 -0500)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Fri, 14 Feb 2025 18:57:45 +0000 (10:57 -0800)
To support Rx timestamp offload, VIRTCHNL_OP_1588_PTP_CAPS is sent by
the VF to request PTP capability and responded by the PF what capability
is enabled for that VF.

Hardware captures timestamps which contain only 32 bits of nominal
nanoseconds, as opposed to the 64bit timestamps that the stack expects.
To convert 32b to 64b, we need a current PHC time.
VIRTCHNL_OP_1588_PTP_GET_TIME is sent by the VF and responded by the
PF with the current PHC time.

Signed-off-by: Simei Su <simei.su@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
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/ice/ice_base.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_ptp.c
drivers/net/ethernet/intel/ice/ice_ptp.h
drivers/net/ethernet/intel/ice/ice_vf_lib.h
drivers/net/ethernet/intel/ice/ice_virtchnl.c
drivers/net/ethernet/intel/ice/ice_virtchnl.h
drivers/net/ethernet/intel/ice/ice_virtchnl_allowlist.c
include/linux/avf/virtchnl.h

index 0e862f20427ab00ad0a816c46049c37223547e16..b3234a55a2532ff1346cc14ad89c54f3ad0fc14c 100644 (file)
@@ -473,9 +473,6 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
         */
        if (vsi->type != ICE_VSI_VF)
                ice_write_qrxflxp_cntxt(hw, pf_q, rxdid, 0x3, true);
-       else
-               ice_write_qrxflxp_cntxt(hw, pf_q, ICE_RXDID_LEGACY_1, 0x3,
-                                       false);
 
        /* Absolute queue number out of 2K needs to be passed */
        err = ice_write_rxq_ctx(hw, &rlan_ctx, pf_q);
index 978f308d3b1b954a82d6683925f0ae676cb55214..7f5b229cab059b143367ae8938d0035ef2ea7b70 100644 (file)
@@ -1775,9 +1775,8 @@ void ice_update_eth_stats(struct ice_vsi *vsi)
  * @prio: priority for the RXDID for this queue
  * @ena_ts: true to enable timestamp and false to disable timestamp
  */
-void
-ice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio,
-                       bool ena_ts)
+void ice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio,
+                            bool ena_ts)
 {
        int regval = rd32(hw, QRXFLXP_CNTXT(pf_q));
 
index b65114ff487b130b815cb2b132f74804f8809562..1bb0033347c76d7f1426a3e4adcb6030ea6673eb 100644 (file)
@@ -298,8 +298,8 @@ void ice_ptp_restore_timestamp_mode(struct ice_pf *pf)
  * @sts: Optional parameter for holding a pair of system timestamps from
  *       the system clock. Will be ignored if NULL is given.
  */
-static u64
-ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts)
+u64 ice_ptp_read_src_clk_reg(struct ice_pf *pf,
+                            struct ptp_system_timestamp *sts)
 {
        struct ice_hw *hw = &pf->hw;
        u32 hi, lo, lo2;
index 783139de7f7419030bcd3c9bb3457bd334a5ba9b..3b769a0cad00deb2927b187f956f2eab93eb6fe1 100644 (file)
@@ -304,6 +304,8 @@ void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx);
 void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx);
 enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf);
 irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf);
+u64 ice_ptp_read_src_clk_reg(struct ice_pf *pf,
+                            struct ptp_system_timestamp *sts);
 
 u64 ice_ptp_get_rx_hwts(const union ice_32b_rx_flex_desc *rx_desc,
                        const struct ice_pkt_ctx *pkt_ctx);
@@ -347,6 +349,12 @@ static inline irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf)
        return IRQ_HANDLED;
 }
 
+static inline u64 ice_ptp_read_src_clk_reg(struct ice_pf *pf,
+                                          struct ptp_system_timestamp *sts)
+{
+       return 0;
+}
+
 static inline u64
 ice_ptp_get_rx_hwts(const union ice_32b_rx_flex_desc *rx_desc,
                    const struct ice_pkt_ctx *pkt_ctx)
index 4261fe1c2bcd7029c71547d6ddaf14a6034bc0fd..799b2c1f118447236d4dfd3453c65fc0210107c1 100644 (file)
@@ -124,6 +124,9 @@ struct ice_vf {
        u8 spoofchk:1;
        u8 link_forced:1;
        u8 link_up:1;                   /* only valid if VF link is forced */
+
+       u32 ptp_caps;
+
        unsigned int min_tx_rate;       /* Minimum Tx bandwidth limit in Mbps */
        unsigned int max_tx_rate;       /* Maximum Tx bandwidth limit in Mbps */
        DECLARE_BITMAP(vf_states, ICE_VF_STATES_NBITS); /* VF runtime states */
index ff4ad788d96ac5b8cff0b02dbbf081b2b0a22cc0..629f04d1c3ff1d49674813ce31fb91221f4681e4 100644 (file)
@@ -498,6 +498,9 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
        if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_QOS)
                vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_QOS;
 
+       if (vf->driver_caps & VIRTCHNL_VF_CAP_PTP)
+               vfres->vf_cap_flags |= VIRTCHNL_VF_CAP_PTP;
+
        vfres->num_vsis = 1;
        /* Tx and Rx queue are equal for VF */
        vfres->num_queue_pairs = vsi->num_txq;
@@ -1975,6 +1978,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
        struct ice_vsi *vsi;
        u8 act_prt, pri_prt;
        int i = -1, q_idx;
+       bool ena_ts;
 
        lag = pf->lag;
        mutex_lock(&pf->lag_mutex);
@@ -2104,9 +2108,14 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
                                rxdid = ICE_RXDID_LEGACY_1;
                        }
 
+                       ena_ts = ((vf->driver_caps &
+                                 VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC) &&
+                                 (vf->driver_caps & VIRTCHNL_VF_CAP_PTP) &&
+                                 (qpi->rxq.flags & VIRTCHNL_PTP_RX_TSTAMP));
+
                        ice_write_qrxflxp_cntxt(&vsi->back->hw,
-                                               vsi->rxq_map[q_idx],
-                                               rxdid, 0x03, false);
+                                               vsi->rxq_map[q_idx], rxdid,
+                                               ICE_RXDID_PRIO, ena_ts);
                }
        }
 
@@ -4092,6 +4101,59 @@ out:
                                     v_ret, NULL, 0);
 }
 
+static int ice_vc_get_ptp_cap(struct ice_vf *vf,
+                             const struct virtchnl_ptp_caps *msg)
+{
+       enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+       u32 caps = VIRTCHNL_1588_PTP_CAP_RX_TSTAMP |
+                  VIRTCHNL_1588_PTP_CAP_READ_PHC;
+
+       if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
+               goto err;
+
+       v_ret = VIRTCHNL_STATUS_SUCCESS;
+
+       if (msg->caps & caps)
+               vf->ptp_caps = caps;
+
+err:
+       /* send the response back to the VF */
+       return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_1588_PTP_GET_CAPS, v_ret,
+                                    (u8 *)&vf->ptp_caps,
+                                    sizeof(struct virtchnl_ptp_caps));
+}
+
+static int ice_vc_get_phc_time(struct ice_vf *vf)
+{
+       enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+       struct virtchnl_phc_time *phc_time = NULL;
+       struct ice_pf *pf = vf->pf;
+       u32 len = 0;
+       int ret;
+
+       if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
+               goto err;
+
+       v_ret = VIRTCHNL_STATUS_SUCCESS;
+
+       phc_time = kzalloc(sizeof(*phc_time), GFP_KERNEL);
+       if (!phc_time) {
+               v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
+               goto err;
+       }
+
+       len = sizeof(*phc_time);
+
+       phc_time->time = ice_ptp_read_src_clk_reg(pf, NULL);
+
+err:
+       /* send the response back to the VF */
+       ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_1588_PTP_GET_TIME, v_ret,
+                                   (u8 *)phc_time, len);
+       kfree(phc_time);
+       return ret;
+}
+
 static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = {
        .get_ver_msg = ice_vc_get_ver_msg,
        .get_vf_res_msg = ice_vc_get_vf_res_msg,
@@ -4128,6 +4190,8 @@ static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = {
        .get_qos_caps = ice_vc_get_qos_caps,
        .cfg_q_bw = ice_vc_cfg_q_bw,
        .cfg_q_quanta = ice_vc_cfg_q_quanta,
+       .get_ptp_cap = ice_vc_get_ptp_cap,
+       .get_phc_time = ice_vc_get_phc_time,
        /* If you add a new op here please make sure to add it to
         * ice_virtchnl_repr_ops as well.
         */
@@ -4264,6 +4328,8 @@ static const struct ice_virtchnl_ops ice_virtchnl_repr_ops = {
        .get_qos_caps = ice_vc_get_qos_caps,
        .cfg_q_bw = ice_vc_cfg_q_bw,
        .cfg_q_quanta = ice_vc_cfg_q_quanta,
+       .get_ptp_cap = ice_vc_get_ptp_cap,
+       .get_phc_time = ice_vc_get_phc_time,
 };
 
 /**
@@ -4501,6 +4567,12 @@ error_handler:
        case VIRTCHNL_OP_CONFIG_QUANTA:
                err = ops->cfg_q_quanta(vf, msg);
                break;
+       case VIRTCHNL_OP_1588_PTP_GET_CAPS:
+               err = ops->get_ptp_cap(vf, (const void *)msg);
+               break;
+       case VIRTCHNL_OP_1588_PTP_GET_TIME:
+               err = ops->get_phc_time(vf);
+               break;
        case VIRTCHNL_OP_UNKNOWN:
        default:
                dev_err(dev, "Unsupported opcode %d from VF %d\n", v_opcode,
index 0c629aef9baf1c3bd788e2c46c5902244d2a7709..222990f229d5ed0810da5dda3ec5990895ff6f4a 100644 (file)
@@ -26,6 +26,9 @@
 #define ICE_MAX_MACADDR_PER_VF         18
 #define ICE_FLEX_DESC_RXDID_MAX_NUM    64
 
+/* Priority to be compared against previous priority from the pipe */
+#define ICE_RXDID_PRIO                 0x03
+
 /* VFs only get a single VSI. For ice hardware, the VF does not need to know
  * its VSI index. However, the virtchnl interface requires a VSI number,
  * mainly due to legacy hardware.
@@ -72,6 +75,9 @@ struct ice_virtchnl_ops {
        int (*cfg_q_tc_map)(struct ice_vf *vf, u8 *msg);
        int (*cfg_q_bw)(struct ice_vf *vf, u8 *msg);
        int (*cfg_q_quanta)(struct ice_vf *vf, u8 *msg);
+       int (*get_ptp_cap)(struct ice_vf *vf,
+                          const struct virtchnl_ptp_caps *msg);
+       int (*get_phc_time)(struct ice_vf *vf);
 };
 
 #ifdef CONFIG_PCI_IOV
index c105a82ee1364a91e15e557de56f36e1a8c9ad71..a3d1579a619a55428690a5d224f27569ae2003d4 100644 (file)
@@ -84,6 +84,12 @@ static const u32 fdir_pf_allowlist_opcodes[] = {
        VIRTCHNL_OP_ADD_FDIR_FILTER, VIRTCHNL_OP_DEL_FDIR_FILTER,
 };
 
+/* VIRTCHNL_VF_CAP_PTP */
+static const u32 ptp_allowlist_opcodes[] = {
+       VIRTCHNL_OP_1588_PTP_GET_CAPS,
+       VIRTCHNL_OP_1588_PTP_GET_TIME,
+};
+
 static const u32 tc_allowlist_opcodes[] = {
        VIRTCHNL_OP_GET_QOS_CAPS, VIRTCHNL_OP_CONFIG_QUEUE_BW,
        VIRTCHNL_OP_CONFIG_QUANTA,
@@ -110,6 +116,7 @@ static const struct allowlist_opcode_info allowlist_opcodes[] = {
        ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_FDIR_PF, fdir_pf_allowlist_opcodes),
        ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_VLAN_V2, vlan_v2_allowlist_opcodes),
        ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_QOS, tc_allowlist_opcodes),
+       ALLOW_ITEM(VIRTCHNL_VF_CAP_PTP, ptp_allowlist_opcodes),
 };
 
 /**
index 92866e449b21a179ea7a408f088e5c82888d198d..56baf97c44d02f073ec31a37dea457fe24f8de40 100644 (file)
@@ -313,6 +313,18 @@ struct virtchnl_txq_info {
 
 VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_txq_info);
 
+/* virtchnl_rxq_info_flags - definition of bits in the flags field of the
+ *                          virtchnl_rxq_info structure.
+ *
+ * @VIRTCHNL_PTP_RX_TSTAMP: request to enable Rx timestamping
+ *
+ * Other flag bits are currently reserved and they may be extended in the
+ * future.
+ */
+enum virtchnl_rxq_info_flags {
+       VIRTCHNL_PTP_RX_TSTAMP = BIT(0),
+};
+
 /* VIRTCHNL_OP_CONFIG_RX_QUEUE
  * VF sends this message to set up parameters for one RX queue.
  * External data buffer contains one instance of virtchnl_rxq_info.
@@ -336,7 +348,8 @@ struct virtchnl_rxq_info {
        u32 max_pkt_size;
        u8 crc_disable;
        u8 rxdid;
-       u8 pad1[2];
+       enum virtchnl_rxq_info_flags flags:8; /* see virtchnl_rxq_info_flags */
+       u8 pad1;
        u64 dma_ring_addr;
 
        /* see enum virtchnl_rx_hsplit; deprecated with AVF 1.0 */