Milena Olech wrote:
> Add functions to request Tx timestamp for the PTP packets, read the Tx
> timestamp when the completion tag for that packet is being received,
> extend the Tx timestamp value and set the supported timestamping modes.
> 
> Tx timestamp is requested for the PTP packets by setting a TSYN bit and
> index value in the Tx context descriptor. The driver assumption is that
> the Tx timestamp value is ready to be read when the completion tag is
> received. Then the driver schedules delayed work and the Tx timestamp
> value read is requested through virtchnl message. At the end, the Tx
> timestamp value is extended to 64-bit and provided back to the skb.
> 
> Co-developed-by: Josh Hay <joshua.a....@intel.com>
> Signed-off-by: Josh Hay <joshua.a....@intel.com>
> Signed-off-by: Milena Olech <milena.ol...@intel.com>
> ---
> v1 -> v2: add timestamping stats, use ndo_hwtamp_get/ndo_hwstamp_set

> +/**
> + * idpf_set_timestamp_filters - Set the supported timestamping mode
> + * @vport: Virtual port structure
> + * @info: ethtool timestamping info structure
> + *
> + * Set the Tx/Rx timestamp filters.
> + */
> +static void idpf_set_timestamp_filters(const struct idpf_vport *vport,
> +                                    struct kernel_ethtool_ts_info *info)

This is not really a setter. It modifies no vport state.

idpf_get_timestamp_filters? Or just merge into the below caller.

> +{
> +     if (!vport->tx_tstamp_caps ||
> +         vport->adapter->ptp->tx_tstamp_access == IDPF_PTP_NONE)
> +             return;
> +
> +     info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
> +                             SOF_TIMESTAMPING_TX_HARDWARE |
> +                             SOF_TIMESTAMPING_RX_HARDWARE |
> +                             SOF_TIMESTAMPING_RAW_HARDWARE;
> +
> +     info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
> +}
> +
> +/**
> + * idpf_get_ts_info - Get device PHC association
> + * @netdev: network interface device structure
> + * @info: ethtool timestamping info structure
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +static int idpf_get_ts_info(struct net_device *netdev,
> +                         struct kernel_ethtool_ts_info *info)
> +{
> +     struct idpf_adapter *adapter = idpf_netdev_to_adapter(netdev);
> +     struct idpf_vport *vport;
> +     int err = 0;
> +
> +     idpf_vport_cfg_lock(adapter);
> +     vport = idpf_netdev_to_vport(netdev);
> +
> +     if (!vport->adapter->ptp) {
> +             err = -EOPNOTSUPP;
> +             goto unlock;
> +     }
> +
> +     idpf_set_timestamp_filters(vport, info);

Probably move this in the below if, als it gets entirely overwritten
if the else is taken.
> +
> +     if (idpf_is_cap_ena(vport->adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_PTP) 
> &&
> +         vport->adapter->ptp->clock) {
> +             info->phc_index = ptp_clock_index(vport->adapter->ptp->clock);
> +     } else {
> +             pci_dbg(vport->adapter->pdev, "PTP clock not detected\n");
> +             err = ethtool_op_get_ts_info(netdev, info);
> +     }
> +
> +unlock:
> +     idpf_vport_cfg_unlock(adapter);
> +
> +     return err;
> +}

> +/**
> + * idpf_ptp_extend_ts - Convert a 40b timestamp to 64b nanoseconds
> + * @vport: Virtual port structure
> + * @in_tstamp: Ingress/egress timestamp value
> + *
> + * It is assumed that the caller verifies the timestamp is valid prior to
> + * calling this function.
> + *
> + * Extract the 32bit nominal nanoseconds and extend them. Use the cached PHC
> + * time stored in the device private PTP structure as the basis for timestamp
> + * extension.
> + *
> + * Return: Tx timestamp value extended to 64 bits.
> + */
> +u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u64 in_tstamp)
> +{
> +     struct idpf_ptp *ptp = vport->adapter->ptp;
> +     unsigned long discard_time;
> +
> +     discard_time = ptp->cached_phc_jiffies + 2 * HZ;
> +
> +     if (time_is_before_jiffies(discard_time)) {
> +             vport->tstamp_stats.tx_hwtstamp_discarded++;
> +             return 0;
> +     }
> +
> +     return idpf_ptp_tstamp_extend_32b_to_64b(ptp->cached_phc_time,
> +                                              lower_32_bits(in_tstamp));
> +}

> +#if (IS_ENABLED(CONFIG_PTP_1588_CLOCK))
> +/**
> + * idpf_tx_tstamp - set up context descriptor for hardware timestamp
> + * @tx_q: queue to send buffer on
> + * @skb: pointer to the SKB we're sending
> + * @off: pointer to the offload struct
> + *
> + * Return: Positive index number on success, negative otherwise.
> + */
> +static int idpf_tx_tstamp(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
> +                       struct idpf_tx_offload_params *off)
> +{
> +     int err, idx;
> +
> +     /* only timestamp the outbound packet if the user has requested it */
> +     if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)))
> +             return -1;
> +
> +     if (!idpf_ptp_get_txq_tstamp_capability(tx_q))
> +             return -1;
> +
> +     /* Tx timestamps cannot be sampled when doing TSO */
> +     if (off->tx_flags & IDPF_TX_FLAGS_TSO)
> +             return -1;
> +
> +     /* Grab an open timestamp slot */
> +     err = idpf_ptp_request_ts(tx_q, skb, &idx);
> +     if (err) {
> +             tx_q->txq_grp->vport->tstamp_stats.tx_hwtstamp_skipped++;

What is the mutual exclusion on these stats fields?

In ndo_start_xmit the txq lock is held, but no vport wide lock?

> +             return -1;
> +     }
> +
> +     off->tx_flags |= IDPF_TX_FLAGS_TSYN;
> +
> +     return idx;
> +}

Reply via email to