FILE
hv_vhca_stats.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2// Copyright (c) 2018 Mellanox Technologies 3 4#include "en.h" 5#include "en/hv_vhca_stats.h" 6#include "lib/hv_vhca.h" 7#include "lib/hv.h" 8 9struct mlx5e_hv_vhca_per_ring_stats { 10 u64 rx_packets; 11 u64 rx_bytes; 12 u64 tx_packets; 13 u64 tx_bytes; 14}; 15 16static void 17mlx5e_hv_vhca_fill_ring_stats(struct mlx5e_priv *priv, int ch, 18 struct mlx5e_hv_vhca_per_ring_stats *data) 19{ 20 struct mlx5e_channel_stats *stats; 21 int tc; 22 23 stats = priv->channel_stats[ch]; 24 data->rx_packets = stats->rq.packets; 25 data->rx_bytes = stats->rq.bytes; 26 27 for (tc = 0; tc < priv->max_opened_tc; tc++) { 28 data->tx_packets += stats->sq[tc].packets; 29 data->tx_bytes += stats->sq[tc].bytes; 30 } 31} 32 33static void mlx5e_hv_vhca_fill_stats(struct mlx5e_priv *priv, void *data, 34 int buf_len) 35{ 36 int ch, i = 0; 37 38 for (ch = 0; ch < priv->stats_nch; ch++) { 39 void *buf = data + i; 40 41 if (WARN_ON_ONCE(buf + 42 sizeof(struct mlx5e_hv_vhca_per_ring_stats) > 43 data + buf_len)) 44 return; 45 46 mlx5e_hv_vhca_fill_ring_stats(priv, ch, buf); 47 i += sizeof(struct mlx5e_hv_vhca_per_ring_stats); 48 } 49} 50 51static int mlx5e_hv_vhca_stats_buf_size(struct mlx5e_priv *priv) 52{ 53 return (sizeof(struct mlx5e_hv_vhca_per_ring_stats) * 54 priv->stats_nch); 55} 56 57static void mlx5e_hv_vhca_stats_work(struct work_struct *work) 58{ 59 struct mlx5e_hv_vhca_stats_agent *sagent; 60 struct mlx5_hv_vhca_agent *agent; 61 struct delayed_work *dwork; 62 struct mlx5e_priv *priv; 63 int buf_len, rc; 64 void *buf; 65 66 dwork = to_delayed_work(work); 67 sagent = container_of(dwork, struct mlx5e_hv_vhca_stats_agent, work); 68 priv = container_of(sagent, struct mlx5e_priv, stats_agent); 69 buf_len = mlx5e_hv_vhca_stats_buf_size(priv); 70 agent = sagent->agent; 71 buf = sagent->buf; 72 73 memset(buf, 0, buf_len); 74 mlx5e_hv_vhca_fill_stats(priv, buf, buf_len); 75 76 rc = mlx5_hv_vhca_agent_write(agent, buf, buf_len); 77 if (rc) { 78 mlx5_core_err(priv->mdev, 79 "%s: Failed to write stats, err = %d\n", 80 __func__, rc); 81 return; 82 } 83 84 if (sagent->delay) 85 queue_delayed_work(priv->wq, &sagent->work, sagent->delay); 86} 87 88enum { 89 MLX5_HV_VHCA_STATS_VERSION = 1, 90 MLX5_HV_VHCA_STATS_UPDATE_ONCE = 0xFFFF, 91}; 92 93static void mlx5e_hv_vhca_stats_control(struct mlx5_hv_vhca_agent *agent, 94 struct mlx5_hv_vhca_control_block *block) 95{ 96 struct mlx5e_hv_vhca_stats_agent *sagent; 97 struct mlx5e_priv *priv; 98 99 priv = mlx5_hv_vhca_agent_priv(agent); 100 sagent = &priv->stats_agent; 101 102 block->version = MLX5_HV_VHCA_STATS_VERSION; 103 block->rings = priv->stats_nch; 104 105 if (!block->command) { 106 cancel_delayed_work_sync(&priv->stats_agent.work); 107 return; 108 } 109 110 sagent->delay = block->command == MLX5_HV_VHCA_STATS_UPDATE_ONCE ? 0 : 111 msecs_to_jiffies(block->command * 100); 112 113 queue_delayed_work(priv->wq, &sagent->work, sagent->delay); 114} 115 116static void mlx5e_hv_vhca_stats_cleanup(struct mlx5_hv_vhca_agent *agent) 117{ 118 struct mlx5e_priv *priv = mlx5_hv_vhca_agent_priv(agent); 119 120 cancel_delayed_work_sync(&priv->stats_agent.work); 121} 122 123void mlx5e_hv_vhca_stats_create(struct mlx5e_priv *priv) 124{ 125 int buf_len = mlx5e_hv_vhca_stats_buf_size(priv); 126 struct mlx5_hv_vhca_agent *agent; 127 128 priv->stats_agent.buf = kvzalloc(buf_len, GFP_KERNEL); 129 if (!priv->stats_agent.buf) 130 return; 131 132 agent = mlx5_hv_vhca_agent_create(priv->mdev->hv_vhca, 133 MLX5_HV_VHCA_AGENT_STATS, 134 mlx5e_hv_vhca_stats_control, NULL, 135 mlx5e_hv_vhca_stats_cleanup, 136 priv); 137 138 if (IS_ERR_OR_NULL(agent)) { 139 if (IS_ERR(agent)) 140 netdev_warn(priv->netdev, 141 "Failed to create hv vhca stats agent, err = %pe\n", 142 agent); 143 144 kvfree(priv->stats_agent.buf); 145 return; 146 } 147 148 priv->stats_agent.agent = agent; 149 INIT_DELAYED_WORK(&priv->stats_agent.work, mlx5e_hv_vhca_stats_work); 150} 151 152void mlx5e_hv_vhca_stats_destroy(struct mlx5e_priv *priv) 153{ 154 if (IS_ERR_OR_NULL(priv->stats_agent.agent)) 155 return; 156 157 mlx5_hv_vhca_agent_destroy(priv->stats_agent.agent); 158 kvfree(priv->stats_agent.buf); 159}
~/
Read-only file preview.