diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/net/ethernet/intel/idpf/idpf.h | 17 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/idpf/idpf_ethtool.c | 56 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/idpf/idpf_ptp.c | 11 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c | 4 |
4 files changed, 87 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h index 6e79fa8556e9..6db6d6f0562a 100644 --- a/drivers/net/ethernet/intel/idpf/idpf.h +++ b/drivers/net/ethernet/intel/idpf/idpf.h @@ -256,6 +256,21 @@ enum idpf_vport_flags { IDPF_VPORT_FLAGS_NBITS, }; +/** + * struct idpf_tstamp_stats - Tx timestamp statistics + * @stats_sync: See struct u64_stats_sync + * @packets: Number of packets successfully timestamped by the hardware + * @discarded: Number of Tx skbs discarded due to cached PHC + * being too old to correctly extend timestamp + * @flushed: Number of Tx skbs flushed due to interface closed + */ +struct idpf_tstamp_stats { + struct u64_stats_sync stats_sync; + u64_stats_t packets; + u64_stats_t discarded; + u64_stats_t flushed; +}; + struct idpf_port_stats { struct u64_stats_sync stats_sync; u64_stats_t rx_hw_csum_err; @@ -328,6 +343,7 @@ struct idpf_fsteer_fltr { * @tx_tstamp_caps: Capabilities negotiated for Tx timestamping * @tstamp_config: The Tx tstamp config * @tstamp_task: Tx timestamping task + * @tstamp_stats: Tx timestamping statistics */ struct idpf_vport { u16 num_txq; @@ -386,6 +402,7 @@ struct idpf_vport { struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps; struct kernel_hwtstamp_config tstamp_config; struct work_struct tstamp_task; + struct idpf_tstamp_stats tstamp_stats; }; /** diff --git a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c index 0eb812ac19c2..786d0bacdd3c 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c +++ b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c @@ -1685,6 +1685,61 @@ unlock: return err; } +/** + * idpf_get_ts_stats - Collect HW tstamping statistics + * @netdev: network interface device structure + * @ts_stats: HW timestamping stats structure + * + * Collect HW timestamping statistics including successfully timestamped + * packets, discarded due to illegal values, flushed during releasing PTP and + * skipped due to lack of the free index. + */ +static void idpf_get_ts_stats(struct net_device *netdev, + struct ethtool_ts_stats *ts_stats) +{ + struct idpf_netdev_priv *np = netdev_priv(netdev); + struct idpf_vport *vport; + unsigned int start; + + idpf_vport_ctrl_lock(netdev); + vport = idpf_netdev_to_vport(netdev); + do { + start = u64_stats_fetch_begin(&vport->tstamp_stats.stats_sync); + ts_stats->pkts = u64_stats_read(&vport->tstamp_stats.packets); + ts_stats->lost = u64_stats_read(&vport->tstamp_stats.flushed); + ts_stats->err = u64_stats_read(&vport->tstamp_stats.discarded); + } while (u64_stats_fetch_retry(&vport->tstamp_stats.stats_sync, start)); + + if (np->state != __IDPF_VPORT_UP) + goto exit; + + for (u16 i = 0; i < vport->num_txq_grp; i++) { + struct idpf_txq_group *txq_grp = &vport->txq_grps[i]; + + for (u16 j = 0; j < txq_grp->num_txq; j++) { + struct idpf_tx_queue *txq = txq_grp->txqs[j]; + struct idpf_tx_queue_stats *stats; + u64 ts; + + if (!txq) + continue; + + stats = &txq->q_stats; + do { + start = u64_stats_fetch_begin(&txq->stats_sync); + + ts = u64_stats_read(&stats->tstamp_skipped); + } while (u64_stats_fetch_retry(&txq->stats_sync, + start)); + + ts_stats->lost += ts; + } + } + +exit: + idpf_vport_ctrl_unlock(netdev); +} + static const struct ethtool_ops idpf_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_USE_ADAPTIVE, @@ -1711,6 +1766,7 @@ static const struct ethtool_ops idpf_ethtool_ops = { .set_ringparam = idpf_set_ringparam, .get_link_ksettings = idpf_get_link_ksettings, .get_ts_info = idpf_get_ts_info, + .get_ts_stats = idpf_get_ts_stats, }; /** diff --git a/drivers/net/ethernet/intel/idpf/idpf_ptp.c b/drivers/net/ethernet/intel/idpf/idpf_ptp.c index ee21f2ff0cad..142823af1f9e 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_ptp.c +++ b/drivers/net/ethernet/intel/idpf/idpf_ptp.c @@ -618,8 +618,13 @@ u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u64 in_tstamp) discard_time = ptp->cached_phc_jiffies + 2 * HZ; - if (time_is_before_jiffies(discard_time)) + if (time_is_before_jiffies(discard_time)) { + u64_stats_update_begin(&vport->tstamp_stats.stats_sync); + u64_stats_inc(&vport->tstamp_stats.discarded); + u64_stats_update_end(&vport->tstamp_stats.stats_sync); + return 0; + } return idpf_ptp_tstamp_extend_32b_to_64b(ptp->cached_phc_time, lower_32_bits(in_tstamp)); @@ -853,10 +858,14 @@ static void idpf_ptp_release_vport_tstamp(struct idpf_vport *vport) /* Remove list with latches in use */ head = &vport->tx_tstamp_caps->latches_in_use; + u64_stats_update_begin(&vport->tstamp_stats.stats_sync); list_for_each_entry_safe(ptp_tx_tstamp, tmp, head, list_member) { + u64_stats_inc(&vport->tstamp_stats.flushed); + list_del(&ptp_tx_tstamp->list_member); kfree(ptp_tx_tstamp); } + u64_stats_update_end(&vport->tstamp_stats.stats_sync); spin_unlock_bh(&vport->tx_tstamp_caps->latches_lock); diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c index 4f1fb0cefe51..8a2e0f8c5e36 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c +++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl_ptp.c @@ -521,6 +521,10 @@ idpf_ptp_get_tstamp_value(struct idpf_vport *vport, list_add(&ptp_tx_tstamp->list_member, &tx_tstamp_caps->latches_free); + u64_stats_update_begin(&vport->tstamp_stats.stats_sync); + u64_stats_inc(&vport->tstamp_stats.packets); + u64_stats_update_end(&vport->tstamp_stats.stats_sync); + return 0; } |
