1
2
3
4#include "en.h"
5#include "monitor_stats.h"
6#include "lib/eq.h"
7
8
9
10
11
12
13
14
15
16
17
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
23int 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
39void 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
49static 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
60static 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
69static 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
76static 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
82static 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
99static 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
114static 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
143void 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
152static 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
165void mlx5e_monitor_counter_cleanup(struct mlx5e_priv *priv)
166{
167 mlx5e_monitor_counter_disable(priv);
168 mlx5e_monitor_counter_stop(priv);
169}
170