2 * Copyright (c) 2013-2017, Mellanox Technologies, Ltd. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <dev/mlx5/driver.h>
29 #include <dev/mlx5/diagnostics.h>
31 const struct mlx5_core_diagnostics_entry
32 mlx5_core_pci_diagnostics_table[
33 MLX5_CORE_PCI_DIAGNOSTICS_NUM] = {
34 MLX5_CORE_PCI_DIAGNOSTICS(MLX5_CORE_DIAGNOSTICS_ENTRY)
37 const struct mlx5_core_diagnostics_entry
38 mlx5_core_general_diagnostics_table[
39 MLX5_CORE_GENERAL_DIAGNOSTICS_NUM] = {
40 MLX5_CORE_GENERAL_DIAGNOSTICS(MLX5_CORE_DIAGNOSTICS_ENTRY)
43 static int mlx5_core_get_index_of_diag_counter(
44 const struct mlx5_core_diagnostics_entry *entry,
45 int size, u16 counter_id)
49 /* check for invalid counter ID */
53 /* lookup counter ID in table */
54 for (x = 0; x != size; x++) {
55 if (entry[x].counter_id == counter_id)
61 static void mlx5_core_put_diag_counter(
62 const struct mlx5_core_diagnostics_entry *entry,
63 u64 *array, int size, u16 counter_id, u64 value)
67 /* check for invalid counter ID */
71 /* lookup counter ID in table */
72 for (x = 0; x != size; x++) {
73 if (entry[x].counter_id == counter_id) {
80 int mlx5_core_set_diagnostics_full(struct mlx5_core_dev *dev,
81 u8 enable_pci, u8 enable_general)
83 void *diag_params_ctx;
91 if (MLX5_CAP_GEN(dev, debug) == 0)
94 numcounters = MLX5_CAP_GEN(dev, num_of_diagnostic_counters);
98 inlen = MLX5_ST_SZ_BYTES(set_diagnostic_params_in) +
99 MLX5_ST_SZ_BYTES(diagnostic_counter) * numcounters;
100 in = mlx5_vzalloc(inlen);
104 diag_params_ctx = MLX5_ADDR_OF(set_diagnostic_params_in, in,
105 diagnostic_params_ctx);
107 MLX5_SET(diagnostic_params_context, diag_params_ctx,
108 enable, enable_pci || enable_general);
109 MLX5_SET(diagnostic_params_context, diag_params_ctx,
111 MLX5_SET(diagnostic_params_context, diag_params_ctx,
114 /* collect the counters we want to enable */
115 for (x = y = 0; x != numcounters; x++) {
117 MLX5_CAP_DEBUG(dev, diagnostic_counter[x].counter_id);
120 if (index < 0 && enable_pci != 0) {
121 /* check if counter ID exists in local table */
122 index = mlx5_core_get_index_of_diag_counter(
123 mlx5_core_pci_diagnostics_table,
124 MLX5_CORE_PCI_DIAGNOSTICS_NUM,
127 if (index < 0 && enable_general != 0) {
128 /* check if counter ID exists in local table */
129 index = mlx5_core_get_index_of_diag_counter(
130 mlx5_core_general_diagnostics_table,
131 MLX5_CORE_GENERAL_DIAGNOSTICS_NUM,
137 MLX5_SET(diagnostic_params_context,
139 counter_id[y].counter_id,
144 /* recompute input length */
145 inlen = MLX5_ST_SZ_BYTES(set_diagnostic_params_in) +
146 MLX5_ST_SZ_BYTES(diagnostic_counter) * y;
148 /* set number of counters */
149 MLX5_SET(diagnostic_params_context, diag_params_ctx,
152 /* execute firmware command */
153 err = mlx5_set_diagnostic_params(dev, in, inlen);
160 int mlx5_core_get_diagnostics_full(struct mlx5_core_dev *dev,
161 union mlx5_core_pci_diagnostics *pdiag,
162 union mlx5_core_general_diagnostics *pgen)
172 if (MLX5_CAP_GEN(dev, debug) == 0)
175 numcounters = MLX5_CAP_GEN(dev, num_of_diagnostic_counters);
176 if (numcounters == 0)
179 outlen = MLX5_ST_SZ_BYTES(query_diagnostic_counters_out) +
180 MLX5_ST_SZ_BYTES(diagnostic_counter) * numcounters;
182 out = mlx5_vzalloc(outlen);
186 err = mlx5_query_diagnostic_counters(dev, 1, 0, out, outlen);
188 for (x = 0; x != numcounters; x++) {
189 u16 counter_id = MLX5_GET(
190 query_diagnostic_counters_out,
191 out, diag_counter[x].counter_id);
192 u64 counter_value = MLX5_GET64(
193 query_diagnostic_counters_out,
194 out, diag_counter[x].counter_value_h);
197 mlx5_core_put_diag_counter(
198 mlx5_core_pci_diagnostics_table,
200 MLX5_CORE_PCI_DIAGNOSTICS_NUM,
201 counter_id, counter_value);
204 mlx5_core_put_diag_counter(
205 mlx5_core_general_diagnostics_table,
207 MLX5_CORE_GENERAL_DIAGNOSTICS_NUM,
208 counter_id, counter_value);
215 inlen = MLX5_ST_SZ_BYTES(mpcnt_reg);
216 outlen = MLX5_ST_SZ_BYTES(mpcnt_reg);
218 in = mlx5_vzalloc(inlen);
222 out = mlx5_vzalloc(outlen);
227 MLX5_SET(mpcnt_reg, in, grp,
228 MLX5_PCIE_PERFORMANCE_COUNTERS_GROUP);
230 err = mlx5_core_access_reg(dev, in, inlen, out, outlen,
231 MLX5_REG_MPCNT, 0, 0);
233 void *pcounters = MLX5_ADDR_OF(mpcnt_reg, out,
234 counter_set.pcie_performance_counters_data_layout);
236 pdiag->counter.rx_pci_errors =
237 MLX5_GET(pcie_performance_counters_data_layout,
238 pcounters, rx_errors);
239 pdiag->counter.tx_pci_errors =
240 MLX5_GET(pcie_performance_counters_data_layout,
241 pcounters, tx_errors);
243 MLX5_SET(mpcnt_reg, in, grp,
244 MLX5_PCIE_TIMERS_AND_STATES_COUNTERS_GROUP);
246 err = mlx5_core_access_reg(dev, in, inlen, out, outlen,
247 MLX5_REG_MPCNT, 0, 0);
249 void *pcounters = MLX5_ADDR_OF(mpcnt_reg, out,
250 counter_set.pcie_timers_and_states_data_layout);
252 pdiag->counter.tx_pci_non_fatal_errors =
253 MLX5_GET(pcie_timers_and_states_data_layout,
254 pcounters, non_fatal_err_msg_sent);
255 pdiag->counter.tx_pci_fatal_errors =
256 MLX5_GET(pcie_timers_and_states_data_layout,
257 pcounters, fatal_err_msg_sent);
265 int mlx5_core_supports_diagnostics(struct mlx5_core_dev *dev, u16 counter_id)
270 if (MLX5_CAP_GEN(dev, debug) == 0)
273 /* check for any counter */
277 numcounters = MLX5_CAP_GEN(dev, num_of_diagnostic_counters);
279 /* check if counter ID exists in debug capability */
280 for (x = 0; x != numcounters; x++) {
281 if (MLX5_CAP_DEBUG(dev, diagnostic_counter[x].counter_id) ==
285 return 0; /* not supported counter */