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

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

DEFINITIONS

This source file includes following definitions.
  1. mlx5e_monitor_counter_supported
  2. mlx5e_monitor_counter_arm
  3. mlx5e_monitor_counters_work
  4. mlx5e_monitor_event_handler
  5. mlx5e_monitor_counter_start
  6. mlx5e_monitor_counter_stop
  7. fill_monitor_counter_ppcnt_set1
  8. fill_monitor_counter_q_counter_set1
  9. mlx5e_set_monitor_counter
  10. mlx5e_monitor_counter_init
  11. mlx5e_monitor_counter_disable
  12. mlx5e_monitor_counter_cleanup

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /* Copyright (c) 2018 Mellanox Technologies. */
   3 
   4 #include "en.h"
   5 #include "monitor_stats.h"
   6 #include "lib/eq.h"
   7 
   8 /* Driver will set the following watch counters list:
   9  * Ppcnt.802_3:
  10  * a_in_range_length_errors      Type: 0x0, Counter:  0x0, group_id = N/A
  11  * a_out_of_range_length_field   Type: 0x0, Counter:  0x1, group_id = N/A
  12  * a_frame_too_long_errors       Type: 0x0, Counter:  0x2, group_id = N/A
  13  * a_frame_check_sequence_errors Type: 0x0, Counter:  0x3, group_id = N/A
  14  * a_alignment_errors            Type: 0x0, Counter:  0x4, group_id = N/A
  15  * if_out_discards               Type: 0x0, Counter:  0x5, group_id = N/A
  16  * Q_Counters:
  17  * Q[index].rx_out_of_buffer   Type: 0x1, Counter:  0x4, group_id = counter_ix
  18  */
  19 
  20 #define NUM_REQ_PPCNT_COUNTER_S1 MLX5_CMD_SET_MONITOR_NUM_PPCNT_COUNTER_SET1
  21 #define NUM_REQ_Q_COUNTERS_S1    MLX5_CMD_SET_MONITOR_NUM_Q_COUNTERS_SET1
  22 
  23 int mlx5e_monitor_counter_supported(struct mlx5e_priv *priv)
  24 {
  25         struct mlx5_core_dev *mdev = priv->mdev;
  26 
  27         if (!MLX5_CAP_GEN(mdev, max_num_of_monitor_counters))
  28                 return false;
  29         if (MLX5_CAP_PCAM_REG(mdev, ppcnt) &&
  30             MLX5_CAP_GEN(mdev, num_ppcnt_monitor_counters) <
  31             NUM_REQ_PPCNT_COUNTER_S1)
  32                 return false;
  33         if (MLX5_CAP_GEN(mdev, num_q_monitor_counters) <
  34             NUM_REQ_Q_COUNTERS_S1)
  35                 return false;
  36         return true;
  37 }
  38 
  39 void mlx5e_monitor_counter_arm(struct mlx5e_priv *priv)
  40 {
  41         u32  in[MLX5_ST_SZ_DW(arm_monitor_counter_in)]  = {};
  42         u32 out[MLX5_ST_SZ_DW(arm_monitor_counter_out)] = {};
  43 
  44         MLX5_SET(arm_monitor_counter_in, in, opcode,
  45                  MLX5_CMD_OP_ARM_MONITOR_COUNTER);
  46         mlx5_cmd_exec(priv->mdev, in, sizeof(in), out, sizeof(out));
  47 }
  48 
  49 static void mlx5e_monitor_counters_work(struct work_struct *work)
  50 {
  51         struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
  52                                                monitor_counters_work);
  53 
  54         mutex_lock(&priv->state_lock);
  55         mlx5e_update_ndo_stats(priv);
  56         mutex_unlock(&priv->state_lock);
  57         mlx5e_monitor_counter_arm(priv);
  58 }
  59 
  60 static int mlx5e_monitor_event_handler(struct notifier_block *nb,
  61                                        unsigned long event, void *eqe)
  62 {
  63         struct mlx5e_priv *priv = mlx5_nb_cof(nb, struct mlx5e_priv,
  64                                               monitor_counters_nb);
  65         queue_work(priv->wq, &priv->monitor_counters_work);
  66         return NOTIFY_OK;
  67 }
  68 
  69 static void mlx5e_monitor_counter_start(struct mlx5e_priv *priv)
  70 {
  71         MLX5_NB_INIT(&priv->monitor_counters_nb, mlx5e_monitor_event_handler,
  72                      MONITOR_COUNTER);
  73         mlx5_eq_notifier_register(priv->mdev, &priv->monitor_counters_nb);
  74 }
  75 
  76 static void mlx5e_monitor_counter_stop(struct mlx5e_priv *priv)
  77 {
  78         mlx5_eq_notifier_unregister(priv->mdev, &priv->monitor_counters_nb);
  79         cancel_work_sync(&priv->monitor_counters_work);
  80 }
  81 
  82 static int fill_monitor_counter_ppcnt_set1(int cnt, u32 *in)
  83 {
  84         enum mlx5_monitor_counter_ppcnt ppcnt_cnt;
  85 
  86         for (ppcnt_cnt = 0;
  87              ppcnt_cnt < NUM_REQ_PPCNT_COUNTER_S1;
  88              ppcnt_cnt++, cnt++) {
  89                 MLX5_SET(set_monitor_counter_in, in,
  90                          monitor_counter[cnt].type,
  91                          MLX5_QUERY_MONITOR_CNT_TYPE_PPCNT);
  92                 MLX5_SET(set_monitor_counter_in, in,
  93                          monitor_counter[cnt].counter,
  94                          ppcnt_cnt);
  95         }
  96         return ppcnt_cnt;
  97 }
  98 
  99 static int fill_monitor_counter_q_counter_set1(int cnt, int q_counter, u32 *in)
 100 {
 101         MLX5_SET(set_monitor_counter_in, in,
 102                  monitor_counter[cnt].type,
 103                  MLX5_QUERY_MONITOR_CNT_TYPE_Q_COUNTER);
 104         MLX5_SET(set_monitor_counter_in, in,
 105                  monitor_counter[cnt].counter,
 106                  MLX5_QUERY_MONITOR_Q_COUNTER_RX_OUT_OF_BUFFER);
 107         MLX5_SET(set_monitor_counter_in, in,
 108                  monitor_counter[cnt].counter_group_id,
 109                  q_counter);
 110         return 1;
 111 }
 112 
 113 /* check if mlx5e_monitor_counter_supported before calling this function*/
 114 static void mlx5e_set_monitor_counter(struct mlx5e_priv *priv)
 115 {
 116         struct mlx5_core_dev *mdev = priv->mdev;
 117         int max_num_of_counters = MLX5_CAP_GEN(mdev, max_num_of_monitor_counters);
 118         int num_q_counters      = MLX5_CAP_GEN(mdev, num_q_monitor_counters);
 119         int num_ppcnt_counters  = !MLX5_CAP_PCAM_REG(mdev, ppcnt) ? 0 :
 120                                   MLX5_CAP_GEN(mdev, num_ppcnt_monitor_counters);
 121         u32  in[MLX5_ST_SZ_DW(set_monitor_counter_in)]  = {};
 122         u32 out[MLX5_ST_SZ_DW(set_monitor_counter_out)] = {};
 123         int q_counter = priv->q_counter;
 124         int cnt = 0;
 125 
 126         if (num_ppcnt_counters  >=  NUM_REQ_PPCNT_COUNTER_S1 &&
 127             max_num_of_counters >= (NUM_REQ_PPCNT_COUNTER_S1 + cnt))
 128                 cnt += fill_monitor_counter_ppcnt_set1(cnt, in);
 129 
 130         if (num_q_counters      >=  NUM_REQ_Q_COUNTERS_S1 &&
 131             max_num_of_counters >= (NUM_REQ_Q_COUNTERS_S1 + cnt) &&
 132             q_counter)
 133                 cnt += fill_monitor_counter_q_counter_set1(cnt, q_counter, in);
 134 
 135         MLX5_SET(set_monitor_counter_in, in, num_of_counters, cnt);
 136         MLX5_SET(set_monitor_counter_in, in, opcode,
 137                  MLX5_CMD_OP_SET_MONITOR_COUNTER);
 138 
 139         mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
 140 }
 141 
 142 /* check if mlx5e_monitor_counter_supported before calling this function*/
 143 void mlx5e_monitor_counter_init(struct mlx5e_priv *priv)
 144 {
 145         INIT_WORK(&priv->monitor_counters_work, mlx5e_monitor_counters_work);
 146         mlx5e_monitor_counter_start(priv);
 147         mlx5e_set_monitor_counter(priv);
 148         mlx5e_monitor_counter_arm(priv);
 149         queue_work(priv->wq, &priv->update_stats_work);
 150 }
 151 
 152 static void mlx5e_monitor_counter_disable(struct mlx5e_priv *priv)
 153 {
 154         u32  in[MLX5_ST_SZ_DW(set_monitor_counter_in)]  = {};
 155         u32 out[MLX5_ST_SZ_DW(set_monitor_counter_out)] = {};
 156 
 157         MLX5_SET(set_monitor_counter_in, in, num_of_counters, 0);
 158         MLX5_SET(set_monitor_counter_in, in, opcode,
 159                  MLX5_CMD_OP_SET_MONITOR_COUNTER);
 160 
 161         mlx5_cmd_exec(priv->mdev, in, sizeof(in), out, sizeof(out));
 162 }
 163 
 164 /* check if mlx5e_monitor_counter_supported before calling this function*/
 165 void mlx5e_monitor_counter_cleanup(struct mlx5e_priv *priv)
 166 {
 167         mlx5e_monitor_counter_disable(priv);
 168         mlx5e_monitor_counter_stop(priv);
 169 }

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