root/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mlx5e_hv_vhca_fill_ring_stats
  2. mlx5e_hv_vhca_fill_stats
  3. mlx5e_hv_vhca_stats_buf_size
  4. mlx5e_hv_vhca_stats_work
  5. mlx5e_hv_vhca_stats_control
  6. mlx5e_hv_vhca_stats_cleanup
  7. mlx5e_hv_vhca_stats_create
  8. mlx5e_hv_vhca_stats_destroy

   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 
   9 struct mlx5e_hv_vhca_per_ring_stats {
  10         u64     rx_packets;
  11         u64     rx_bytes;
  12         u64     tx_packets;
  13         u64     tx_bytes;
  14 };
  15 
  16 static void
  17 mlx5e_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 
  33 static 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->max_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 
  51 static int mlx5e_hv_vhca_stats_buf_size(struct mlx5e_priv *priv)
  52 {
  53         return (sizeof(struct mlx5e_hv_vhca_per_ring_stats) *
  54                 priv->max_nch);
  55 }
  56 
  57 static 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 
  88 enum {
  89         MLX5_HV_VHCA_STATS_VERSION     = 1,
  90         MLX5_HV_VHCA_STATS_UPDATE_ONCE = 0xFFFF,
  91 };
  92 
  93 static 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->max_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 
 116 static 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 
 123 int 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 -ENOMEM;
 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 = %ld\n",
 142                                     PTR_ERR(agent));
 143 
 144                 kvfree(priv->stats_agent.buf);
 145                 return IS_ERR_OR_NULL(agent);
 146         }
 147 
 148         priv->stats_agent.agent = agent;
 149         INIT_DELAYED_WORK(&priv->stats_agent.work, mlx5e_hv_vhca_stats_work);
 150 
 151         return 0;
 152 }
 153 
 154 void mlx5e_hv_vhca_stats_destroy(struct mlx5e_priv *priv)
 155 {
 156         if (IS_ERR_OR_NULL(priv->stats_agent.agent))
 157                 return;
 158 
 159         mlx5_hv_vhca_agent_destroy(priv->stats_agent.agent);
 160         kvfree(priv->stats_agent.buf);
 161 }

/* [<][>][^][v][top][bottom][index][help] */