xref: /freebsd/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c (revision 5dc00f00)
1dc7e38acSHans Petter Selasky /*-
2c8d16d1eSHans Petter Selasky  * Copyright (c) 2015-2021 Mellanox Technologies. All rights reserved.
3dc7e38acSHans Petter Selasky  *
4dc7e38acSHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
5dc7e38acSHans Petter Selasky  * modification, are permitted provided that the following conditions
6dc7e38acSHans Petter Selasky  * are met:
7dc7e38acSHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
8dc7e38acSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer.
9dc7e38acSHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
10dc7e38acSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
11dc7e38acSHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
12dc7e38acSHans Petter Selasky  *
13dc7e38acSHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14dc7e38acSHans Petter Selasky  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15dc7e38acSHans Petter Selasky  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16dc7e38acSHans Petter Selasky  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17dc7e38acSHans Petter Selasky  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18dc7e38acSHans Petter Selasky  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19dc7e38acSHans Petter Selasky  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20dc7e38acSHans Petter Selasky  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21dc7e38acSHans Petter Selasky  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22dc7e38acSHans Petter Selasky  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23dc7e38acSHans Petter Selasky  * SUCH DAMAGE.
24dc7e38acSHans Petter Selasky  *
25dc7e38acSHans Petter Selasky  * $FreeBSD$
26dc7e38acSHans Petter Selasky  */
27dc7e38acSHans Petter Selasky 
28b984b956SKonstantin Belousov #include "opt_rss.h"
29b984b956SKonstantin Belousov #include "opt_ratelimit.h"
30b984b956SKonstantin Belousov 
3189918a23SKonstantin Belousov #include <dev/mlx5/mlx5_en/en.h>
3289918a23SKonstantin Belousov #include <dev/mlx5/mlx5_en/port_buffer.h>
33dc7e38acSHans Petter Selasky 
34dc7e38acSHans Petter Selasky void
35dc7e38acSHans Petter Selasky mlx5e_create_stats(struct sysctl_ctx_list *ctx,
36dc7e38acSHans Petter Selasky     struct sysctl_oid_list *parent, const char *buffer,
37dc7e38acSHans Petter Selasky     const char **desc, unsigned num, u64 * arg)
38dc7e38acSHans Petter Selasky {
39dc7e38acSHans Petter Selasky 	struct sysctl_oid *node;
40dc7e38acSHans Petter Selasky 	unsigned x;
41dc7e38acSHans Petter Selasky 
42dc7e38acSHans Petter Selasky 	sysctl_ctx_init(ctx);
43dc7e38acSHans Petter Selasky 
44dc7e38acSHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO,
457029da5cSPawel Biernacki 	    buffer, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Statistics");
46dc7e38acSHans Petter Selasky 	if (node == NULL)
47dc7e38acSHans Petter Selasky 		return;
48dc7e38acSHans Petter Selasky 	for (x = 0; x != num; x++) {
49dc7e38acSHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
50dc7e38acSHans Petter Selasky 		    desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]);
51dc7e38acSHans Petter Selasky 	}
52dc7e38acSHans Petter Selasky }
53dc7e38acSHans Petter Selasky 
547272f9cdSHans Petter Selasky void
557272f9cdSHans Petter Selasky mlx5e_create_counter_stats(struct sysctl_ctx_list *ctx,
567272f9cdSHans Petter Selasky     struct sysctl_oid_list *parent, const char *buffer,
577272f9cdSHans Petter Selasky     const char **desc, unsigned num, counter_u64_t *arg)
587272f9cdSHans Petter Selasky {
597272f9cdSHans Petter Selasky 	struct sysctl_oid *node;
607272f9cdSHans Petter Selasky 	unsigned x;
617272f9cdSHans Petter Selasky 
627272f9cdSHans Petter Selasky 	sysctl_ctx_init(ctx);
637272f9cdSHans Petter Selasky 
647272f9cdSHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO,
657029da5cSPawel Biernacki 	    buffer, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Statistics");
667272f9cdSHans Petter Selasky 	if (node == NULL)
677272f9cdSHans Petter Selasky 		return;
687272f9cdSHans Petter Selasky 	for (x = 0; x != num; x++) {
697272f9cdSHans Petter Selasky 		SYSCTL_ADD_COUNTER_U64(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
707272f9cdSHans Petter Selasky 		    desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]);
717272f9cdSHans Petter Selasky 	}
727272f9cdSHans Petter Selasky }
737272f9cdSHans Petter Selasky 
74376bcf63SHans Petter Selasky static void
75376bcf63SHans Petter Selasky mlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv *priv)
76376bcf63SHans Petter Selasky {
77376bcf63SHans Petter Selasky 	/*
78376bcf63SHans Petter Selasky 	 * Limit the maximum distance between completion events to
79376bcf63SHans Petter Selasky 	 * half of the currently set TX queue size.
80376bcf63SHans Petter Selasky 	 *
81376bcf63SHans Petter Selasky 	 * The maximum number of queue entries a single IP packet can
82376bcf63SHans Petter Selasky 	 * consume is given by MLX5_SEND_WQE_MAX_WQEBBS.
83376bcf63SHans Petter Selasky 	 *
84376bcf63SHans Petter Selasky 	 * The worst case max value is then given as below:
85376bcf63SHans Petter Selasky 	 */
86376bcf63SHans Petter Selasky 	uint64_t max = priv->params_ethtool.tx_queue_size /
87376bcf63SHans Petter Selasky 	    (2 * MLX5_SEND_WQE_MAX_WQEBBS);
88376bcf63SHans Petter Selasky 
89376bcf63SHans Petter Selasky 	/*
90376bcf63SHans Petter Selasky 	 * Update the maximum completion factor value in case the
91376bcf63SHans Petter Selasky 	 * tx_queue_size field changed. Ensure we don't overflow
92376bcf63SHans Petter Selasky 	 * 16-bits.
93376bcf63SHans Petter Selasky 	 */
94376bcf63SHans Petter Selasky 	if (max < 1)
95376bcf63SHans Petter Selasky 		max = 1;
96376bcf63SHans Petter Selasky 	else if (max > 65535)
97376bcf63SHans Petter Selasky 		max = 65535;
98376bcf63SHans Petter Selasky 	priv->params_ethtool.tx_completion_fact_max = max;
99376bcf63SHans Petter Selasky 
100376bcf63SHans Petter Selasky 	/*
101376bcf63SHans Petter Selasky 	 * Verify that the current TX completion factor is within the
102376bcf63SHans Petter Selasky 	 * given limits:
103376bcf63SHans Petter Selasky 	 */
104376bcf63SHans Petter Selasky 	if (priv->params_ethtool.tx_completion_fact < 1)
105376bcf63SHans Petter Selasky 		priv->params_ethtool.tx_completion_fact = 1;
106376bcf63SHans Petter Selasky 	else if (priv->params_ethtool.tx_completion_fact > max)
107376bcf63SHans Petter Selasky 		priv->params_ethtool.tx_completion_fact = max;
108376bcf63SHans Petter Selasky }
109376bcf63SHans Petter Selasky 
110cfc9c386SHans Petter Selasky static int
111cfc9c386SHans Petter Selasky mlx5e_getmaxrate(struct mlx5e_priv *priv)
112cfc9c386SHans Petter Selasky {
113cfc9c386SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
114cfc9c386SHans Petter Selasky 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
115cfc9c386SHans Petter Selasky 	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
116cfc9c386SHans Petter Selasky 	int err;
117cfc9c386SHans Petter Selasky 	int i;
118cfc9c386SHans Petter Selasky 
119cfc9c386SHans Petter Selasky 	PRIV_LOCK(priv);
120cfc9c386SHans Petter Selasky 	err = -mlx5_query_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
121cfc9c386SHans Petter Selasky 	if (err)
122cfc9c386SHans Petter Selasky 		goto done;
123cfc9c386SHans Petter Selasky 
124cfc9c386SHans Petter Selasky 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
125cfc9c386SHans Petter Selasky 		switch (max_bw_unit[i]) {
126cfc9c386SHans Petter Selasky 		case MLX5_100_MBPS_UNIT:
127cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_100MB;
128cfc9c386SHans Petter Selasky 			break;
129cfc9c386SHans Petter Selasky 		case MLX5_GBPS_UNIT:
130cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_1GB;
131cfc9c386SHans Petter Selasky 			break;
132cfc9c386SHans Petter Selasky 		case MLX5_BW_NO_LIMIT:
133cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = 0;
134cfc9c386SHans Petter Selasky 			break;
135cfc9c386SHans Petter Selasky 		default:
136cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = -1;
137cfc9c386SHans Petter Selasky 			WARN_ONCE(true, "non-supported BW unit");
138cfc9c386SHans Petter Selasky 			break;
139cfc9c386SHans Petter Selasky 		}
140cfc9c386SHans Petter Selasky 	}
141cfc9c386SHans Petter Selasky done:
142cfc9c386SHans Petter Selasky 	PRIV_UNLOCK(priv);
143cfc9c386SHans Petter Selasky 	return (err);
144cfc9c386SHans Petter Selasky }
145cfc9c386SHans Petter Selasky 
146cfc9c386SHans Petter Selasky static int
147e870c0abSSlava Shwartsman mlx5e_get_max_alloc(struct mlx5e_priv *priv)
148e870c0abSSlava Shwartsman {
149e870c0abSSlava Shwartsman 	struct mlx5_core_dev *mdev = priv->mdev;
150e870c0abSSlava Shwartsman 	int err;
151e870c0abSSlava Shwartsman 	int x;
152e870c0abSSlava Shwartsman 
153e870c0abSSlava Shwartsman 	PRIV_LOCK(priv);
154e870c0abSSlava Shwartsman 	err = -mlx5_query_port_tc_bw_alloc(mdev, priv->params_ethtool.max_bw_share);
155e870c0abSSlava Shwartsman 	if (err == 0) {
156e870c0abSSlava Shwartsman 		/* set default value */
157e870c0abSSlava Shwartsman 		for (x = 0; x != IEEE_8021QAZ_MAX_TCS; x++) {
158e870c0abSSlava Shwartsman 			priv->params_ethtool.max_bw_share[x] =
159e870c0abSSlava Shwartsman 			    100 / IEEE_8021QAZ_MAX_TCS;
160e870c0abSSlava Shwartsman 		}
161e870c0abSSlava Shwartsman 		err = -mlx5_set_port_tc_bw_alloc(mdev,
162e870c0abSSlava Shwartsman 		    priv->params_ethtool.max_bw_share);
163e870c0abSSlava Shwartsman 	}
164e870c0abSSlava Shwartsman 	PRIV_UNLOCK(priv);
165e870c0abSSlava Shwartsman 
166e870c0abSSlava Shwartsman 	return (err);
167e870c0abSSlava Shwartsman }
168e870c0abSSlava Shwartsman 
169e870c0abSSlava Shwartsman static int
170ed0cee0bSHans Petter Selasky mlx5e_get_dscp(struct mlx5e_priv *priv)
171ed0cee0bSHans Petter Selasky {
172ed0cee0bSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
173ed0cee0bSHans Petter Selasky 	int err;
174ed0cee0bSHans Petter Selasky 
175ed0cee0bSHans Petter Selasky 	if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 ||
176ed0cee0bSHans Petter Selasky 	    MLX5_CAP_QCAM_REG(mdev, qpts) == 0 ||
177ed0cee0bSHans Petter Selasky 	    MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0)
178ed0cee0bSHans Petter Selasky 		return (EOPNOTSUPP);
179ed0cee0bSHans Petter Selasky 
180ed0cee0bSHans Petter Selasky 	PRIV_LOCK(priv);
181ed0cee0bSHans Petter Selasky 	err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio);
182ed0cee0bSHans Petter Selasky 	if (err)
183ed0cee0bSHans Petter Selasky 		goto done;
184ed0cee0bSHans Petter Selasky 
185ed0cee0bSHans Petter Selasky 	err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state);
186ed0cee0bSHans Petter Selasky 	if (err)
187ed0cee0bSHans Petter Selasky 		goto done;
188ed0cee0bSHans Petter Selasky done:
189ed0cee0bSHans Petter Selasky 	PRIV_UNLOCK(priv);
190ed0cee0bSHans Petter Selasky 	return (err);
191ed0cee0bSHans Petter Selasky }
192ed0cee0bSHans Petter Selasky 
193e870c0abSSlava Shwartsman static void
194e870c0abSSlava Shwartsman mlx5e_tc_get_parameters(struct mlx5e_priv *priv,
195e870c0abSSlava Shwartsman     u64 *new_bw_value, u8 *max_bw_value, u8 *max_bw_unit)
196e870c0abSSlava Shwartsman {
197e870c0abSSlava Shwartsman 	const u64 upper_limit_mbps = 255 * MLX5E_100MB;
198e870c0abSSlava Shwartsman 	const u64 upper_limit_gbps = 255 * MLX5E_1GB;
199e870c0abSSlava Shwartsman 	u64 temp;
200e870c0abSSlava Shwartsman 	int i;
201e870c0abSSlava Shwartsman 
202e870c0abSSlava Shwartsman 	memset(max_bw_value, 0, IEEE_8021QAZ_MAX_TCS);
203e870c0abSSlava Shwartsman 	memset(max_bw_unit, 0, IEEE_8021QAZ_MAX_TCS);
204e870c0abSSlava Shwartsman 
205e870c0abSSlava Shwartsman 	for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) {
206e870c0abSSlava Shwartsman 		temp = (new_bw_value != NULL) ?
207e870c0abSSlava Shwartsman 		    new_bw_value[i] : priv->params_ethtool.max_bw_value[i];
208e870c0abSSlava Shwartsman 
209e870c0abSSlava Shwartsman 		if (!temp) {
210e870c0abSSlava Shwartsman 			max_bw_unit[i] = MLX5_BW_NO_LIMIT;
211e870c0abSSlava Shwartsman 		} else if (temp > upper_limit_gbps) {
212e870c0abSSlava Shwartsman 			max_bw_unit[i] = MLX5_BW_NO_LIMIT;
213e870c0abSSlava Shwartsman 		} else if (temp <= upper_limit_mbps) {
214e870c0abSSlava Shwartsman 			max_bw_value[i] = howmany(temp, MLX5E_100MB);
215e870c0abSSlava Shwartsman 			max_bw_unit[i]  = MLX5_100_MBPS_UNIT;
216e870c0abSSlava Shwartsman 		} else {
217e870c0abSSlava Shwartsman 			max_bw_value[i] = howmany(temp, MLX5E_1GB);
218e870c0abSSlava Shwartsman 			max_bw_unit[i]  = MLX5_GBPS_UNIT;
219e870c0abSSlava Shwartsman 		}
220e870c0abSSlava Shwartsman 	}
221e870c0abSSlava Shwartsman }
222e870c0abSSlava Shwartsman 
223ed0cee0bSHans Petter Selasky static int
224cfc9c386SHans Petter Selasky mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS)
225cfc9c386SHans Petter Selasky {
226cfc9c386SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
227cfc9c386SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
228cfc9c386SHans Petter Selasky 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
229cfc9c386SHans Petter Selasky 	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
230e870c0abSSlava Shwartsman 	u64 new_bw_value[IEEE_8021QAZ_MAX_TCS];
231e870c0abSSlava Shwartsman 	u8 max_rates = mlx5_max_tc(mdev) + 1;
232e870c0abSSlava Shwartsman 	u8 x;
233e870c0abSSlava Shwartsman 	int err;
234cfc9c386SHans Petter Selasky 
235cfc9c386SHans Petter Selasky 	PRIV_LOCK(priv);
236e870c0abSSlava Shwartsman 	err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_value,
237e870c0abSSlava Shwartsman 	    sizeof(priv->params_ethtool.max_bw_value[0]) * max_rates);
238e870c0abSSlava Shwartsman 	if (err || !req->newptr)
239e870c0abSSlava Shwartsman 		goto done;
240e870c0abSSlava Shwartsman 	err = SYSCTL_IN(req, new_bw_value,
241e870c0abSSlava Shwartsman 	    sizeof(new_bw_value[0]) * max_rates);
242e870c0abSSlava Shwartsman 	if (err)
243cfc9c386SHans Petter Selasky 		goto done;
244cfc9c386SHans Petter Selasky 
245e870c0abSSlava Shwartsman 	/* range check input value */
246e870c0abSSlava Shwartsman 	for (x = 0; x != max_rates; x++) {
247e870c0abSSlava Shwartsman 		if (new_bw_value[x] % MLX5E_100MB) {
248cfc9c386SHans Petter Selasky 			err = ERANGE;
249cfc9c386SHans Petter Selasky 			goto done;
250cfc9c386SHans Petter Selasky 		}
251cfc9c386SHans Petter Selasky 	}
252e870c0abSSlava Shwartsman 
253e870c0abSSlava Shwartsman 	mlx5e_tc_get_parameters(priv, new_bw_value, max_bw_value, max_bw_unit);
254cfc9c386SHans Petter Selasky 
255cfc9c386SHans Petter Selasky 	err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
256cfc9c386SHans Petter Selasky 	if (err)
257cfc9c386SHans Petter Selasky 		goto done;
258cfc9c386SHans Petter Selasky 
259e870c0abSSlava Shwartsman 	memcpy(priv->params_ethtool.max_bw_value, new_bw_value,
260e870c0abSSlava Shwartsman 	    sizeof(priv->params_ethtool.max_bw_value));
261e870c0abSSlava Shwartsman done:
262e870c0abSSlava Shwartsman 	PRIV_UNLOCK(priv);
263e870c0abSSlava Shwartsman 	return (err);
264e870c0abSSlava Shwartsman }
265e870c0abSSlava Shwartsman 
266e870c0abSSlava Shwartsman static int
267e870c0abSSlava Shwartsman mlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS)
268e870c0abSSlava Shwartsman {
269e870c0abSSlava Shwartsman 	struct mlx5e_priv *priv = arg1;
270e870c0abSSlava Shwartsman 	struct mlx5_core_dev *mdev = priv->mdev;
271e870c0abSSlava Shwartsman 	u8 max_bw_share[IEEE_8021QAZ_MAX_TCS];
272e870c0abSSlava Shwartsman 	u8 max_rates = mlx5_max_tc(mdev) + 1;
273e870c0abSSlava Shwartsman 	int i;
274e870c0abSSlava Shwartsman 	int err;
275e870c0abSSlava Shwartsman 	int sum;
276e870c0abSSlava Shwartsman 
277e870c0abSSlava Shwartsman 	PRIV_LOCK(priv);
278e870c0abSSlava Shwartsman 	err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_share, max_rates);
279e870c0abSSlava Shwartsman 	if (err || !req->newptr)
280e870c0abSSlava Shwartsman 		goto done;
281e870c0abSSlava Shwartsman 	err = SYSCTL_IN(req, max_bw_share, max_rates);
282e870c0abSSlava Shwartsman 	if (err)
283e870c0abSSlava Shwartsman 		goto done;
284e870c0abSSlava Shwartsman 
285e870c0abSSlava Shwartsman 	/* range check input value */
286e870c0abSSlava Shwartsman 	for (sum = i = 0; i != max_rates; i++) {
287e870c0abSSlava Shwartsman 		if (max_bw_share[i] < 1 || max_bw_share[i] > 100) {
288e870c0abSSlava Shwartsman 			err = ERANGE;
289e870c0abSSlava Shwartsman 			goto done;
290e870c0abSSlava Shwartsman 		}
291e870c0abSSlava Shwartsman 		sum += max_bw_share[i];
292e870c0abSSlava Shwartsman 	}
293e870c0abSSlava Shwartsman 
294e870c0abSSlava Shwartsman 	/* sum of values should be as close to 100 as possible */
295e870c0abSSlava Shwartsman 	if (sum < (100 - max_rates + 1) || sum > 100) {
296e870c0abSSlava Shwartsman 		err = ERANGE;
297e870c0abSSlava Shwartsman 		goto done;
298e870c0abSSlava Shwartsman 	}
299e870c0abSSlava Shwartsman 
300e870c0abSSlava Shwartsman 	err = -mlx5_set_port_tc_bw_alloc(mdev, max_bw_share);
301e870c0abSSlava Shwartsman 	if (err)
302e870c0abSSlava Shwartsman 		goto done;
303e870c0abSSlava Shwartsman 
304e870c0abSSlava Shwartsman 	memcpy(priv->params_ethtool.max_bw_share, max_bw_share,
305e870c0abSSlava Shwartsman 	    sizeof(priv->params_ethtool.max_bw_share));
306cfc9c386SHans Petter Selasky done:
307cfc9c386SHans Petter Selasky 	PRIV_UNLOCK(priv);
308cfc9c386SHans Petter Selasky 	return (err);
309cfc9c386SHans Petter Selasky }
310cfc9c386SHans Petter Selasky 
3112e9c3a4fSHans Petter Selasky static int
3122e9c3a4fSHans Petter Selasky mlx5e_get_prio_tc(struct mlx5e_priv *priv)
3132e9c3a4fSHans Petter Selasky {
3142e9c3a4fSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
3152e9c3a4fSHans Petter Selasky 	int err = 0;
3162e9c3a4fSHans Petter Selasky 	int i;
3172e9c3a4fSHans Petter Selasky 
3182e9c3a4fSHans Petter Selasky 	PRIV_LOCK(priv);
3192e9c3a4fSHans Petter Selasky 	if (!MLX5_CAP_GEN(priv->mdev, ets)) {
3202e9c3a4fSHans Petter Selasky 		PRIV_UNLOCK(priv);
3212e9c3a4fSHans Petter Selasky 		return (EOPNOTSUPP);
3222e9c3a4fSHans Petter Selasky 	}
3232e9c3a4fSHans Petter Selasky 
32424385321SHans Petter Selasky 	for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
32524385321SHans Petter Selasky 		err = -mlx5_query_port_prio_tc(mdev, i, priv->params_ethtool.prio_tc + i);
3262e9c3a4fSHans Petter Selasky 		if (err)
3272e9c3a4fSHans Petter Selasky 			break;
3282e9c3a4fSHans Petter Selasky 	}
3292e9c3a4fSHans Petter Selasky 	PRIV_UNLOCK(priv);
3302e9c3a4fSHans Petter Selasky 	return (err);
3312e9c3a4fSHans Petter Selasky }
3322e9c3a4fSHans Petter Selasky 
3332e9c3a4fSHans Petter Selasky static int
3342e9c3a4fSHans Petter Selasky mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS)
3352e9c3a4fSHans Petter Selasky {
3362e9c3a4fSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
3372e9c3a4fSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
33824385321SHans Petter Selasky 	uint8_t temp[MLX5E_MAX_PRIORITY];
3392e9c3a4fSHans Petter Selasky 	int err;
34024385321SHans Petter Selasky 	int i;
3412e9c3a4fSHans Petter Selasky 
3422e9c3a4fSHans Petter Selasky 	PRIV_LOCK(priv);
34324385321SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.prio_tc, MLX5E_MAX_PRIORITY);
34424385321SHans Petter Selasky 	if (err || !req->newptr)
3452e9c3a4fSHans Petter Selasky 		goto done;
34624385321SHans Petter Selasky 	err = SYSCTL_IN(req, temp, MLX5E_MAX_PRIORITY);
3472e9c3a4fSHans Petter Selasky 	if (err)
3482e9c3a4fSHans Petter Selasky 		goto done;
3492e9c3a4fSHans Petter Selasky 
35024385321SHans Petter Selasky 	for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
35124385321SHans Petter Selasky 		if (temp[i] > mlx5_max_tc(mdev)) {
35224385321SHans Petter Selasky 			err = ERANGE;
35324385321SHans Petter Selasky 			goto done;
35424385321SHans Petter Selasky 		}
35524385321SHans Petter Selasky 	}
3562e9c3a4fSHans Petter Selasky 
35724385321SHans Petter Selasky 	for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
35824385321SHans Petter Selasky 		if (temp[i] == priv->params_ethtool.prio_tc[i])
35924385321SHans Petter Selasky 			continue;
36024385321SHans Petter Selasky 		err = -mlx5_set_port_prio_tc(mdev, i, temp[i]);
36124385321SHans Petter Selasky 		if (err)
36224385321SHans Petter Selasky 			goto done;
36324385321SHans Petter Selasky 		/* update cached value */
36424385321SHans Petter Selasky 		priv->params_ethtool.prio_tc[i] = temp[i];
36524385321SHans Petter Selasky 	}
3662e9c3a4fSHans Petter Selasky done:
3672e9c3a4fSHans Petter Selasky 	PRIV_UNLOCK(priv);
3682e9c3a4fSHans Petter Selasky 	return (err);
3692e9c3a4fSHans Petter Selasky }
3702e9c3a4fSHans Petter Selasky 
37196425f44SHans Petter Selasky int
37296425f44SHans Petter Selasky mlx5e_fec_update(struct mlx5e_priv *priv)
37396425f44SHans Petter Selasky {
37496425f44SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
37596425f44SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
37696425f44SHans Petter Selasky 	const int sz = MLX5_ST_SZ_BYTES(pplm_reg);
37796425f44SHans Petter Selasky 	int err;
37896425f44SHans Petter Selasky 
37996425f44SHans Petter Selasky 	if (!MLX5_CAP_GEN(mdev, pcam_reg))
38096425f44SHans Petter Selasky 		return (EOPNOTSUPP);
38196425f44SHans Petter Selasky 
38296425f44SHans Petter Selasky 	if (!MLX5_CAP_PCAM_REG(mdev, pplm))
38396425f44SHans Petter Selasky 		return (EOPNOTSUPP);
38496425f44SHans Petter Selasky 
38596425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
38696425f44SHans Petter Selasky 
38796425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0);
38896425f44SHans Petter Selasky 	if (err)
38996425f44SHans Petter Selasky 		return (err);
39096425f44SHans Petter Selasky 
39196425f44SHans Petter Selasky 	/* get 10x..25x mask */
39296425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_10x_25x[0] =
39396425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_10g_40g);
39496425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_10x_25x[1] =
39596425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_25g) &
39696425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_50g);
39796425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_10x_25x[2] =
39896425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_56g);
39996425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_10x_25x[3] =
40096425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_100g);
40196425f44SHans Petter Selasky 
40296425f44SHans Petter Selasky 	/* get 10x..25x available bits */
40396425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_10x_25x[0] =
40496425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_10g_40g);
40596425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_10x_25x[1] =
40696425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_25g) &
40796425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_50g);
40896425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_10x_25x[2] =
40996425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_56g);
41096425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_10x_25x[3] =
41196425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_100g);
41296425f44SHans Petter Selasky 
41396425f44SHans Petter Selasky 	/* get 50x mask */
41496425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_50x[0] =
41596425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_50g_1x);
41696425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_50x[1] =
41796425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_100g_2x);
41896425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_50x[2] =
41996425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_200g_4x);
42096425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_50x[3] =
42196425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_400g_8x);
42296425f44SHans Petter Selasky 
42396425f44SHans Petter Selasky 	/* get 50x available bits */
42496425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_50x[0] =
42596425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_50g_1x);
42696425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_50x[1] =
42796425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_100g_2x);
42896425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_50x[2] =
42996425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_200g_4x);
43096425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_50x[3] =
43196425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_400g_8x);
43296425f44SHans Petter Selasky 
43396425f44SHans Petter Selasky 	/* get current FEC mask */
43496425f44SHans Petter Selasky 	priv->params_ethtool.fec_mode_active =
43596425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_mode_active);
43696425f44SHans Petter Selasky 
43796425f44SHans Petter Selasky 	return (0);
43896425f44SHans Petter Selasky }
43996425f44SHans Petter Selasky 
44096425f44SHans Petter Selasky static int
44196425f44SHans Petter Selasky mlx5e_fec_mask_10x_25x_handler(SYSCTL_HANDLER_ARGS)
44296425f44SHans Petter Selasky {
44396425f44SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
44496425f44SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
44596425f44SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
44696425f44SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
44796425f44SHans Petter Selasky 	const int sz = MLX5_ST_SZ_BYTES(pplm_reg);
44896425f44SHans Petter Selasky 	u8 fec_mask_10x_25x[MLX5E_MAX_FEC_10X_25X];
44996425f44SHans Petter Selasky 	u8 fec_cap_changed = 0;
45096425f44SHans Petter Selasky 	u8 x;
45196425f44SHans Petter Selasky 	int err;
45296425f44SHans Petter Selasky 
45396425f44SHans Petter Selasky 	PRIV_LOCK(priv);
45496425f44SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_10x_25x,
45596425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_mask_10x_25x));
45696425f44SHans Petter Selasky 	if (err || !req->newptr)
45796425f44SHans Petter Selasky 		goto done;
45896425f44SHans Petter Selasky 
45996425f44SHans Petter Selasky 	err = SYSCTL_IN(req, fec_mask_10x_25x,
46096425f44SHans Petter Selasky 	    sizeof(fec_mask_10x_25x));
46196425f44SHans Petter Selasky 	if (err)
46296425f44SHans Petter Selasky 		goto done;
46396425f44SHans Petter Selasky 
46496425f44SHans Petter Selasky 	if (!MLX5_CAP_GEN(mdev, pcam_reg)) {
46596425f44SHans Petter Selasky 		err = EOPNOTSUPP;
46696425f44SHans Petter Selasky 		goto done;
46796425f44SHans Petter Selasky 	}
46896425f44SHans Petter Selasky 
46996425f44SHans Petter Selasky 	if (!MLX5_CAP_PCAM_REG(mdev, pplm)) {
47096425f44SHans Petter Selasky 		err = EOPNOTSUPP;
47196425f44SHans Petter Selasky 		goto done;
47296425f44SHans Petter Selasky 	}
47396425f44SHans Petter Selasky 
47496425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
47596425f44SHans Petter Selasky 
47696425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0);
47796425f44SHans Petter Selasky 	if (err)
47896425f44SHans Petter Selasky 		goto done;
47996425f44SHans Petter Selasky 
48096425f44SHans Petter Selasky 	/* range check input value */
48196425f44SHans Petter Selasky 	for (x = 0; x != MLX5E_MAX_FEC_10X_25X; x++) {
48296425f44SHans Petter Selasky 		/* check only one bit is set, if any */
48396425f44SHans Petter Selasky 		if (fec_mask_10x_25x[x] & (fec_mask_10x_25x[x] - 1)) {
48496425f44SHans Petter Selasky 			err = ERANGE;
48596425f44SHans Petter Selasky 			goto done;
48696425f44SHans Petter Selasky 		}
48796425f44SHans Petter Selasky 		/* check a supported bit is set, if any */
48896425f44SHans Petter Selasky 		if (fec_mask_10x_25x[x] &
48996425f44SHans Petter Selasky 		    ~priv->params_ethtool.fec_avail_10x_25x[x]) {
49096425f44SHans Petter Selasky 			err = ERANGE;
49196425f44SHans Petter Selasky 			goto done;
49296425f44SHans Petter Selasky 		}
49396425f44SHans Petter Selasky 		fec_cap_changed |= (fec_mask_10x_25x[x] ^
49496425f44SHans Petter Selasky 		    priv->params_ethtool.fec_mask_10x_25x[x]);
49596425f44SHans Petter Selasky 	}
49696425f44SHans Petter Selasky 
49796425f44SHans Petter Selasky 	/* check for no changes */
49896425f44SHans Petter Selasky 	if (fec_cap_changed == 0)
49996425f44SHans Petter Selasky 		goto done;
50096425f44SHans Petter Selasky 
50196425f44SHans Petter Selasky 	memset(in, 0, sizeof(in));
50296425f44SHans Petter Selasky 
50396425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
50496425f44SHans Petter Selasky 
50596425f44SHans Petter Selasky 	/* set new values */
50696425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, fec_mask_10x_25x[0]);
50796425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_25g, fec_mask_10x_25x[1]);
50896425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_50g, fec_mask_10x_25x[1]);
50996425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_56g, fec_mask_10x_25x[2]);
51096425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_100g, fec_mask_10x_25x[3]);
51196425f44SHans Petter Selasky 
51296425f44SHans Petter Selasky 	/* preserve other values */
51396425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, priv->params_ethtool.fec_mask_50x[0]);
51496425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, priv->params_ethtool.fec_mask_50x[1]);
51596425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, priv->params_ethtool.fec_mask_50x[2]);
51696425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, priv->params_ethtool.fec_mask_50x[3]);
51796425f44SHans Petter Selasky 
51896425f44SHans Petter Selasky 	/* send new value to the firmware */
51996425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1);
52096425f44SHans Petter Selasky 	if (err)
52196425f44SHans Petter Selasky 		goto done;
52296425f44SHans Petter Selasky 
52396425f44SHans Petter Selasky 	memcpy(priv->params_ethtool.fec_mask_10x_25x, fec_mask_10x_25x,
52496425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_mask_10x_25x));
52596425f44SHans Petter Selasky 
52696425f44SHans Petter Selasky 	mlx5_toggle_port_link(priv->mdev);
52796425f44SHans Petter Selasky done:
52896425f44SHans Petter Selasky 	PRIV_UNLOCK(priv);
52996425f44SHans Petter Selasky 	return (err);
53096425f44SHans Petter Selasky }
53196425f44SHans Petter Selasky 
53296425f44SHans Petter Selasky static int
53396425f44SHans Petter Selasky mlx5e_fec_avail_10x_25x_handler(SYSCTL_HANDLER_ARGS)
53496425f44SHans Petter Selasky {
53596425f44SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
53696425f44SHans Petter Selasky 	int err;
53796425f44SHans Petter Selasky 
53896425f44SHans Petter Selasky 	PRIV_LOCK(priv);
53996425f44SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_10x_25x,
54096425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_avail_10x_25x));
54196425f44SHans Petter Selasky 	PRIV_UNLOCK(priv);
54296425f44SHans Petter Selasky 	return (err);
54396425f44SHans Petter Selasky }
54496425f44SHans Petter Selasky 
54596425f44SHans Petter Selasky static int
54696425f44SHans Petter Selasky mlx5e_fec_mask_50x_handler(SYSCTL_HANDLER_ARGS)
54796425f44SHans Petter Selasky {
54896425f44SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
54996425f44SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
55096425f44SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
55196425f44SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
55296425f44SHans Petter Selasky 	const int sz = MLX5_ST_SZ_BYTES(pplm_reg);
55396425f44SHans Petter Selasky 	u16 fec_mask_50x[MLX5E_MAX_FEC_50X];
55496425f44SHans Petter Selasky 	u16 fec_cap_changed = 0;
55596425f44SHans Petter Selasky 	u8 x;
55696425f44SHans Petter Selasky 	int err;
55796425f44SHans Petter Selasky 
55896425f44SHans Petter Selasky 	PRIV_LOCK(priv);
55996425f44SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_50x,
56096425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_mask_50x));
56196425f44SHans Petter Selasky 	if (err || !req->newptr)
56296425f44SHans Petter Selasky 		goto done;
56396425f44SHans Petter Selasky 
56496425f44SHans Petter Selasky 	err = SYSCTL_IN(req, fec_mask_50x,
56596425f44SHans Petter Selasky 	    sizeof(fec_mask_50x));
56696425f44SHans Petter Selasky 	if (err)
56796425f44SHans Petter Selasky 		goto done;
56896425f44SHans Petter Selasky 
56996425f44SHans Petter Selasky 	if (!MLX5_CAP_GEN(mdev, pcam_reg)) {
57096425f44SHans Petter Selasky 		err = EOPNOTSUPP;
57196425f44SHans Petter Selasky 		goto done;
57296425f44SHans Petter Selasky 	}
57396425f44SHans Petter Selasky 
57496425f44SHans Petter Selasky 	if (!MLX5_CAP_PCAM_REG(mdev, pplm)) {
57596425f44SHans Petter Selasky 		err = EOPNOTSUPP;
57696425f44SHans Petter Selasky 		goto done;
57796425f44SHans Petter Selasky 	}
57896425f44SHans Petter Selasky 
57996425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
58096425f44SHans Petter Selasky 
58196425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0);
58296425f44SHans Petter Selasky 	if (err)
58396425f44SHans Petter Selasky 		goto done;
58496425f44SHans Petter Selasky 
58596425f44SHans Petter Selasky 	/* range check input value */
58696425f44SHans Petter Selasky 	for (x = 0; x != MLX5E_MAX_FEC_50X; x++) {
58796425f44SHans Petter Selasky 		/* check only one bit is set, if any */
58896425f44SHans Petter Selasky 		if (fec_mask_50x[x] & (fec_mask_50x[x] - 1)) {
58996425f44SHans Petter Selasky 			err = ERANGE;
59096425f44SHans Petter Selasky 			goto done;
59196425f44SHans Petter Selasky 		}
59296425f44SHans Petter Selasky 		/* check a supported bit is set, if any */
59396425f44SHans Petter Selasky 		if (fec_mask_50x[x] &
59496425f44SHans Petter Selasky 		    ~priv->params_ethtool.fec_avail_50x[x]) {
59596425f44SHans Petter Selasky 			err = ERANGE;
59696425f44SHans Petter Selasky 			goto done;
59796425f44SHans Petter Selasky 		}
59896425f44SHans Petter Selasky 		fec_cap_changed |= (fec_mask_50x[x] ^
59996425f44SHans Petter Selasky 		    priv->params_ethtool.fec_mask_50x[x]);
60096425f44SHans Petter Selasky 	}
60196425f44SHans Petter Selasky 
60296425f44SHans Petter Selasky 	/* check for no changes */
60396425f44SHans Petter Selasky 	if (fec_cap_changed == 0)
60496425f44SHans Petter Selasky 		goto done;
60596425f44SHans Petter Selasky 
60696425f44SHans Petter Selasky 	memset(in, 0, sizeof(in));
60796425f44SHans Petter Selasky 
60896425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
60996425f44SHans Petter Selasky 
61096425f44SHans Petter Selasky 	/* set new values */
61196425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, fec_mask_50x[0]);
61296425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, fec_mask_50x[1]);
61396425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, fec_mask_50x[2]);
61496425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, fec_mask_50x[3]);
61596425f44SHans Petter Selasky 
61696425f44SHans Petter Selasky 	/* preserve other values */
61796425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, priv->params_ethtool.fec_mask_10x_25x[0]);
61896425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_25g, priv->params_ethtool.fec_mask_10x_25x[1]);
61996425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_50g, priv->params_ethtool.fec_mask_10x_25x[1]);
62096425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_56g, priv->params_ethtool.fec_mask_10x_25x[2]);
62196425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_100g, priv->params_ethtool.fec_mask_10x_25x[3]);
62296425f44SHans Petter Selasky 
62396425f44SHans Petter Selasky 	/* send new value to the firmware */
62496425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1);
62596425f44SHans Petter Selasky 	if (err)
62696425f44SHans Petter Selasky 		goto done;
62796425f44SHans Petter Selasky 
62896425f44SHans Petter Selasky 	memcpy(priv->params_ethtool.fec_mask_50x, fec_mask_50x,
62996425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_mask_50x));
63096425f44SHans Petter Selasky 
63196425f44SHans Petter Selasky 	mlx5_toggle_port_link(priv->mdev);
63296425f44SHans Petter Selasky done:
63396425f44SHans Petter Selasky 	PRIV_UNLOCK(priv);
63496425f44SHans Petter Selasky 	return (err);
63596425f44SHans Petter Selasky }
63696425f44SHans Petter Selasky 
63796425f44SHans Petter Selasky static int
63896425f44SHans Petter Selasky mlx5e_fec_avail_50x_handler(SYSCTL_HANDLER_ARGS)
63996425f44SHans Petter Selasky {
64096425f44SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
64196425f44SHans Petter Selasky 	int err;
64296425f44SHans Petter Selasky 
64396425f44SHans Petter Selasky 	PRIV_LOCK(priv);
64496425f44SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_50x,
64596425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_avail_50x));
64696425f44SHans Petter Selasky 	PRIV_UNLOCK(priv);
64796425f44SHans Petter Selasky 	return (err);
64896425f44SHans Petter Selasky }
64996425f44SHans Petter Selasky 
650ed0cee0bSHans Petter Selasky static int
651ed0cee0bSHans Petter Selasky mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS)
652ed0cee0bSHans Petter Selasky {
653ed0cee0bSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
654ed0cee0bSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
655ed0cee0bSHans Petter Selasky 	int err;
656ed0cee0bSHans Petter Selasky 	u8 result;
657ed0cee0bSHans Petter Selasky 
658ed0cee0bSHans Petter Selasky 	PRIV_LOCK(priv);
659ed0cee0bSHans Petter Selasky 	result = priv->params_ethtool.trust_state;
660ed0cee0bSHans Petter Selasky 	err = sysctl_handle_8(oidp, &result, 0, req);
661ed0cee0bSHans Petter Selasky 	if (err || !req->newptr ||
662ed0cee0bSHans Petter Selasky 	    result == priv->params_ethtool.trust_state)
663ed0cee0bSHans Petter Selasky 		goto done;
664ed0cee0bSHans Petter Selasky 
665ed0cee0bSHans Petter Selasky 	switch (result) {
666ed0cee0bSHans Petter Selasky 	case MLX5_QPTS_TRUST_PCP:
667ed0cee0bSHans Petter Selasky 	case MLX5_QPTS_TRUST_DSCP:
668ed0cee0bSHans Petter Selasky 		break;
669ed0cee0bSHans Petter Selasky 	case MLX5_QPTS_TRUST_BOTH:
670ed0cee0bSHans Petter Selasky 		if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) {
671ed0cee0bSHans Petter Selasky 			err = EOPNOTSUPP;
672ed0cee0bSHans Petter Selasky 			goto done;
673ed0cee0bSHans Petter Selasky 		}
674ed0cee0bSHans Petter Selasky 		break;
675ed0cee0bSHans Petter Selasky 	default:
676ed0cee0bSHans Petter Selasky 		err = ERANGE;
677ed0cee0bSHans Petter Selasky 		goto done;
678ed0cee0bSHans Petter Selasky 	}
679ed0cee0bSHans Petter Selasky 
680ed0cee0bSHans Petter Selasky 	err = -mlx5_set_trust_state(mdev, result);
681ed0cee0bSHans Petter Selasky 	if (err)
682ed0cee0bSHans Petter Selasky 		goto done;
683ed0cee0bSHans Petter Selasky 
684ed0cee0bSHans Petter Selasky 	priv->params_ethtool.trust_state = result;
6853e581cabSSlava Shwartsman 
6863e581cabSSlava Shwartsman 	/* update inline mode */
6873e581cabSSlava Shwartsman 	mlx5e_refresh_sq_inline(priv);
6883e581cabSSlava Shwartsman #ifdef RATELIMIT
6893e581cabSSlava Shwartsman 	mlx5e_rl_refresh_sq_inline(&priv->rl);
6903e581cabSSlava Shwartsman #endif
691ed0cee0bSHans Petter Selasky done:
692ed0cee0bSHans Petter Selasky 	PRIV_UNLOCK(priv);
693ed0cee0bSHans Petter Selasky 	return (err);
694ed0cee0bSHans Petter Selasky }
695ed0cee0bSHans Petter Selasky 
696ed0cee0bSHans Petter Selasky static int
697ed0cee0bSHans Petter Selasky mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS)
698ed0cee0bSHans Petter Selasky {
699ed0cee0bSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
700ed0cee0bSHans Petter Selasky 	int prio_index = arg2;
701ed0cee0bSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
702ed0cee0bSHans Petter Selasky 	uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP];
703ed0cee0bSHans Petter Selasky 	uint8_t x;
704ed0cee0bSHans Petter Selasky 	int err;
705ed0cee0bSHans Petter Selasky 
706ed0cee0bSHans Petter Selasky 	PRIV_LOCK(priv);
707ed0cee0bSHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index,
708ed0cee0bSHans Petter Selasky 	    sizeof(priv->params_ethtool.dscp2prio) / 8);
709ed0cee0bSHans Petter Selasky 	if (err || !req->newptr)
710ed0cee0bSHans Petter Selasky 		goto done;
711ed0cee0bSHans Petter Selasky 
712ed0cee0bSHans Petter Selasky 	memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio));
713ed0cee0bSHans Petter Selasky 	err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8);
714ed0cee0bSHans Petter Selasky 	if (err)
715ed0cee0bSHans Petter Selasky 		goto done;
716ed0cee0bSHans Petter Selasky 	for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) {
717ed0cee0bSHans Petter Selasky 		if (dscp2prio[x] > 7) {
718ed0cee0bSHans Petter Selasky 			err = ERANGE;
719ed0cee0bSHans Petter Selasky 			goto done;
720ed0cee0bSHans Petter Selasky 		}
721ed0cee0bSHans Petter Selasky 	}
722ed0cee0bSHans Petter Selasky 	err = -mlx5_set_dscp2prio(mdev, dscp2prio);
723ed0cee0bSHans Petter Selasky 	if (err)
724ed0cee0bSHans Petter Selasky 		goto done;
725ed0cee0bSHans Petter Selasky 
726ed0cee0bSHans Petter Selasky 	/* update local array */
727ed0cee0bSHans Petter Selasky 	memcpy(priv->params_ethtool.dscp2prio, dscp2prio,
728ed0cee0bSHans Petter Selasky 	    sizeof(priv->params_ethtool.dscp2prio));
729ed0cee0bSHans Petter Selasky done:
730ed0cee0bSHans Petter Selasky 	PRIV_UNLOCK(priv);
731ed0cee0bSHans Petter Selasky 	return (err);
732ed0cee0bSHans Petter Selasky }
733ed0cee0bSHans Petter Selasky 
7346deb0b1eSHans Petter Selasky int
7356deb0b1eSHans Petter Selasky mlx5e_update_buf_lossy(struct mlx5e_priv *priv)
7366deb0b1eSHans Petter Selasky {
7376deb0b1eSHans Petter Selasky 	struct ieee_pfc pfc;
7386deb0b1eSHans Petter Selasky 
7396deb0b1eSHans Petter Selasky 	PRIV_ASSERT_LOCKED(priv);
7406deb0b1eSHans Petter Selasky 	bzero(&pfc, sizeof(pfc));
7416deb0b1eSHans Petter Selasky 	pfc.pfc_en = priv->params.rx_priority_flow_control;
7426deb0b1eSHans Petter Selasky 	return (-mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_PFC,
7436deb0b1eSHans Petter Selasky 	    priv->params_ethtool.hw_mtu, &pfc, NULL, NULL));
7446deb0b1eSHans Petter Selasky }
7456deb0b1eSHans Petter Selasky 
7466deb0b1eSHans Petter Selasky static int
7476deb0b1eSHans Petter Selasky mlx5e_buf_size_handler(SYSCTL_HANDLER_ARGS)
7486deb0b1eSHans Petter Selasky {
7496deb0b1eSHans Petter Selasky 	struct mlx5e_priv *priv;
7506deb0b1eSHans Petter Selasky 	u32 buf_size[MLX5E_MAX_BUFFER];
7516deb0b1eSHans Petter Selasky 	struct mlx5e_port_buffer port_buffer;
7526deb0b1eSHans Petter Selasky 	int error, i;
7536deb0b1eSHans Petter Selasky 
7546deb0b1eSHans Petter Selasky 	priv = arg1;
7556deb0b1eSHans Petter Selasky 	PRIV_LOCK(priv);
7566deb0b1eSHans Petter Selasky 	error = -mlx5e_port_query_buffer(priv, &port_buffer);
7576deb0b1eSHans Petter Selasky 	if (error != 0)
7586deb0b1eSHans Petter Selasky 		goto done;
7596deb0b1eSHans Petter Selasky 	for (i = 0; i < nitems(buf_size); i++)
7606deb0b1eSHans Petter Selasky 		buf_size[i] = port_buffer.buffer[i].size;
7616deb0b1eSHans Petter Selasky 	error = SYSCTL_OUT(req, buf_size, sizeof(buf_size));
7626deb0b1eSHans Petter Selasky 	if (error != 0 || req->newptr == NULL)
7636deb0b1eSHans Petter Selasky 		goto done;
7646deb0b1eSHans Petter Selasky 	error = SYSCTL_IN(req, buf_size, sizeof(buf_size));
7656deb0b1eSHans Petter Selasky 	if (error != 0)
7666deb0b1eSHans Petter Selasky 		goto done;
7676deb0b1eSHans Petter Selasky 	error = -mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_SIZE,
7686deb0b1eSHans Petter Selasky 	    priv->params_ethtool.hw_mtu, NULL, buf_size, NULL);
7696deb0b1eSHans Petter Selasky done:
7706deb0b1eSHans Petter Selasky 	PRIV_UNLOCK(priv);
7716deb0b1eSHans Petter Selasky 	return (error);
7726deb0b1eSHans Petter Selasky }
7736deb0b1eSHans Petter Selasky 
7746deb0b1eSHans Petter Selasky static int
7756deb0b1eSHans Petter Selasky mlx5e_buf_prio_handler(SYSCTL_HANDLER_ARGS)
7766deb0b1eSHans Petter Selasky {
7776deb0b1eSHans Petter Selasky 	struct mlx5e_priv *priv;
7786deb0b1eSHans Petter Selasky 	struct mlx5_core_dev *mdev;
7796deb0b1eSHans Petter Selasky 	u8 buffer[MLX5E_MAX_BUFFER];
7806deb0b1eSHans Petter Selasky 	int error;
7816deb0b1eSHans Petter Selasky 
7826deb0b1eSHans Petter Selasky 	priv = arg1;
7836deb0b1eSHans Petter Selasky 	mdev = priv->mdev;
7846deb0b1eSHans Petter Selasky 	PRIV_LOCK(priv);
7856deb0b1eSHans Petter Selasky 	error = -mlx5e_port_query_priority2buffer(mdev, buffer);
7866deb0b1eSHans Petter Selasky 	if (error != 0)
7876deb0b1eSHans Petter Selasky 		goto done;
7886deb0b1eSHans Petter Selasky 	error = SYSCTL_OUT(req, buffer, MLX5E_MAX_BUFFER);
7896deb0b1eSHans Petter Selasky 	if (error != 0 || req->newptr == NULL)
7906deb0b1eSHans Petter Selasky 		goto done;
7916deb0b1eSHans Petter Selasky 	error = SYSCTL_IN(req, buffer, MLX5E_MAX_BUFFER);
7926deb0b1eSHans Petter Selasky 	if (error != 0)
7936deb0b1eSHans Petter Selasky 		goto done;
7946deb0b1eSHans Petter Selasky 	error = -mlx5e_port_manual_buffer_config(priv,
7956deb0b1eSHans Petter Selasky 	    MLX5E_PORT_BUFFER_PRIO2BUFFER,
7966deb0b1eSHans Petter Selasky 	    priv->params_ethtool.hw_mtu, NULL, NULL, buffer);
7976deb0b1eSHans Petter Selasky 	if (error == 0)
7986deb0b1eSHans Petter Selasky 		error = mlx5e_update_buf_lossy(priv);
7996deb0b1eSHans Petter Selasky done:
8006deb0b1eSHans Petter Selasky 	PRIV_UNLOCK(priv);
8016deb0b1eSHans Petter Selasky 	return (error);
8026deb0b1eSHans Petter Selasky }
8036deb0b1eSHans Petter Selasky 
8046deb0b1eSHans Petter Selasky static int
8056deb0b1eSHans Petter Selasky mlx5e_cable_length_handler(SYSCTL_HANDLER_ARGS)
8066deb0b1eSHans Petter Selasky {
8076deb0b1eSHans Petter Selasky 	struct mlx5e_priv *priv;
8086deb0b1eSHans Petter Selasky 	u_int cable_len;
8096deb0b1eSHans Petter Selasky 	int error;
8106deb0b1eSHans Petter Selasky 
8116deb0b1eSHans Petter Selasky 	priv = arg1;
8126deb0b1eSHans Petter Selasky 	PRIV_LOCK(priv);
8136deb0b1eSHans Petter Selasky 	cable_len = priv->dcbx.cable_len;
8146deb0b1eSHans Petter Selasky 	error = sysctl_handle_int(oidp, &cable_len, 0, req);
8156deb0b1eSHans Petter Selasky 	if (error == 0 && req->newptr != NULL &&
8166deb0b1eSHans Petter Selasky 	    cable_len != priv->dcbx.cable_len) {
8176deb0b1eSHans Petter Selasky 		error = -mlx5e_port_manual_buffer_config(priv,
8186deb0b1eSHans Petter Selasky 		    MLX5E_PORT_BUFFER_CABLE_LEN, priv->params_ethtool.hw_mtu,
8196deb0b1eSHans Petter Selasky 		    NULL, NULL, NULL);
8206deb0b1eSHans Petter Selasky 		if (error == 0)
8216deb0b1eSHans Petter Selasky 			priv->dcbx.cable_len = cable_len;
8226deb0b1eSHans Petter Selasky 	}
8236deb0b1eSHans Petter Selasky 	PRIV_UNLOCK(priv);
8246deb0b1eSHans Petter Selasky 	return (error);
8256deb0b1eSHans Petter Selasky }
8266deb0b1eSHans Petter Selasky 
827decb087cSHans Petter Selasky static int
828decb087cSHans Petter Selasky mlx5e_hw_temperature_handler(SYSCTL_HANDLER_ARGS)
829decb087cSHans Petter Selasky {
830decb087cSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
831decb087cSHans Petter Selasky 	int err;
832decb087cSHans Petter Selasky 
833decb087cSHans Petter Selasky 	PRIV_LOCK(priv);
834decb087cSHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.hw_val_temp,
835decb087cSHans Petter Selasky 	    sizeof(priv->params_ethtool.hw_val_temp[0]) *
836decb087cSHans Petter Selasky 	    priv->params_ethtool.hw_num_temp);
837decb087cSHans Petter Selasky 	if (err == 0 && req->newptr != NULL)
838decb087cSHans Petter Selasky 		err = EOPNOTSUPP;
839decb087cSHans Petter Selasky 	PRIV_UNLOCK(priv);
840decb087cSHans Petter Selasky 	return (err);
841decb087cSHans Petter Selasky }
842decb087cSHans Petter Selasky 
843decb087cSHans Petter Selasky int
844decb087cSHans Petter Selasky mlx5e_hw_temperature_update(struct mlx5e_priv *priv)
845decb087cSHans Petter Selasky {
846decb087cSHans Petter Selasky 	int err;
847decb087cSHans Petter Selasky 	u32 x;
848decb087cSHans Petter Selasky 
849decb087cSHans Petter Selasky 	if (priv->params_ethtool.hw_num_temp == 0) {
850decb087cSHans Petter Selasky 		u32 out_cap[MLX5_ST_SZ_DW(mtcap)] = {};
851decb087cSHans Petter Selasky 		const int sz_cap = MLX5_ST_SZ_BYTES(mtcap);
852decb087cSHans Petter Selasky 		u32 value;
853decb087cSHans Petter Selasky 
854decb087cSHans Petter Selasky 		err = -mlx5_core_access_reg(priv->mdev, NULL, 0, out_cap, sz_cap,
855decb087cSHans Petter Selasky 		    MLX5_ACCESS_REG_SUMMARY_CTRL_ID_MTCAP, 0, 0);
856decb087cSHans Petter Selasky 		if (err)
857decb087cSHans Petter Selasky 			goto done;
858decb087cSHans Petter Selasky 		value = MLX5_GET(mtcap, out_cap, sensor_count);
859decb087cSHans Petter Selasky 		if (value == 0)
860decb087cSHans Petter Selasky 			return (0);
861decb087cSHans Petter Selasky 		if (value > MLX5_MAX_TEMPERATURE)
862decb087cSHans Petter Selasky 			value = MLX5_MAX_TEMPERATURE;
863decb087cSHans Petter Selasky 		/* update number of temperature sensors */
864decb087cSHans Petter Selasky 		priv->params_ethtool.hw_num_temp = value;
865decb087cSHans Petter Selasky 	}
866decb087cSHans Petter Selasky 
867decb087cSHans Petter Selasky 	for (x = 0; x != priv->params_ethtool.hw_num_temp; x++) {
868decb087cSHans Petter Selasky 		u32 out_sensor[MLX5_ST_SZ_DW(mtmp_reg)] = {};
869decb087cSHans Petter Selasky 		const int sz_sensor = MLX5_ST_SZ_BYTES(mtmp_reg);
870decb087cSHans Petter Selasky 
871decb087cSHans Petter Selasky 		MLX5_SET(mtmp_reg, out_sensor, sensor_index, x);
872decb087cSHans Petter Selasky 
873decb087cSHans Petter Selasky 		err = -mlx5_core_access_reg(priv->mdev, out_sensor, sz_sensor,
874decb087cSHans Petter Selasky 		    out_sensor, sz_sensor,
875decb087cSHans Petter Selasky 		    MLX5_ACCESS_REG_SUMMARY_CTRL_ID_MTMP, 0, 0);
876decb087cSHans Petter Selasky 		if (err)
877decb087cSHans Petter Selasky 			goto done;
8789097ac9aSElyes HAOUAS 		/* convert from 0.125 celsius to millicelsius */
879decb087cSHans Petter Selasky 		priv->params_ethtool.hw_val_temp[x] =
880decb087cSHans Petter Selasky 		    (s16)MLX5_GET(mtmp_reg, out_sensor, temperature) * 125;
881decb087cSHans Petter Selasky 	}
882decb087cSHans Petter Selasky done:
883decb087cSHans Petter Selasky 	return (err);
884decb087cSHans Petter Selasky }
885decb087cSHans Petter Selasky 
88682d2623eSHans Petter Selasky #define	MLX5_PARAM_OFFSET(n)				\
88782d2623eSHans Petter Selasky     __offsetof(struct mlx5e_priv, params_ethtool.n)
88882d2623eSHans Petter Selasky 
889dc7e38acSHans Petter Selasky static int
890dc7e38acSHans Petter Selasky mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)
891dc7e38acSHans Petter Selasky {
892dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
893dc7e38acSHans Petter Selasky 	uint64_t value;
894d2bf00a9SHans Petter Selasky 	int mode_modify;
895dc7e38acSHans Petter Selasky 	int was_opened;
896dc7e38acSHans Petter Selasky 	int error;
897dc7e38acSHans Petter Selasky 
898dc7e38acSHans Petter Selasky 	PRIV_LOCK(priv);
899dc7e38acSHans Petter Selasky 	value = priv->params_ethtool.arg[arg2];
900ec0143b2SHans Petter Selasky 	if (req != NULL) {
901dc7e38acSHans Petter Selasky 		error = sysctl_handle_64(oidp, &value, 0, req);
902dc7e38acSHans Petter Selasky 		if (error || req->newptr == NULL ||
903dc7e38acSHans Petter Selasky 		    value == priv->params_ethtool.arg[arg2])
904dc7e38acSHans Petter Selasky 			goto done;
905dc7e38acSHans Petter Selasky 
906dc7e38acSHans Petter Selasky 		/* assign new value */
907dc7e38acSHans Petter Selasky 		priv->params_ethtool.arg[arg2] = value;
908ec0143b2SHans Petter Selasky 	} else {
909ec0143b2SHans Petter Selasky 		error = 0;
910ec0143b2SHans Petter Selasky 	}
911dc7e38acSHans Petter Selasky 	/* check if device is gone */
912dc7e38acSHans Petter Selasky 	if (priv->gone) {
913dc7e38acSHans Petter Selasky 		error = ENXIO;
914dc7e38acSHans Petter Selasky 		goto done;
915dc7e38acSHans Petter Selasky 	}
91682d2623eSHans Petter Selasky 	was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
917d2bf00a9SHans Petter Selasky 	mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify);
91882d2623eSHans Petter Selasky 
91982d2623eSHans Petter Selasky 	switch (MLX5_PARAM_OFFSET(arg[arg2])) {
92082d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_usecs):
921f03f517bSHans Petter Selasky 		/* import RX coal time */
922f03f517bSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_usecs < 1)
923f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_usecs = 0;
924f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.rx_coalesce_usecs >
925f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_period)) {
926f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_usecs =
927f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_period);
928f03f517bSHans Petter Selasky 		}
92982d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_usec =
93082d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_usecs;
931f03f517bSHans Petter Selasky 
93282d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
93382d2623eSHans Petter Selasky 		if (was_opened)
93482d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
93582d2623eSHans Petter Selasky 		break;
93682d2623eSHans Petter Selasky 
93782d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_pkts):
938f03f517bSHans Petter Selasky 		/* import RX coal pkts */
939f03f517bSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_pkts < 1)
940f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_pkts = 0;
941f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.rx_coalesce_pkts >
942f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
943f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_pkts =
944f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_max_count);
945f03f517bSHans Petter Selasky 		}
94682d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_pkts =
94782d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_pkts;
948f03f517bSHans Petter Selasky 
94982d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
95082d2623eSHans Petter Selasky 		if (was_opened)
95182d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
95282d2623eSHans Petter Selasky 		break;
95382d2623eSHans Petter Selasky 
95482d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_usecs):
955f03f517bSHans Petter Selasky 		/* import TX coal time */
956f03f517bSHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_usecs < 1)
957f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_usecs = 0;
958f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.tx_coalesce_usecs >
959f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_period)) {
960f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_usecs =
961f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_period);
962f03f517bSHans Petter Selasky 		}
96382d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_usec =
96482d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_usecs;
965f03f517bSHans Petter Selasky 
96682d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
96782d2623eSHans Petter Selasky 		if (was_opened)
96882d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
96982d2623eSHans Petter Selasky 		break;
97082d2623eSHans Petter Selasky 
97182d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_pkts):
972f03f517bSHans Petter Selasky 		/* import TX coal pkts */
973f03f517bSHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_pkts < 1)
974f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_pkts = 0;
975f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.tx_coalesce_pkts >
976f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
97782d2623eSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_pkts =
97882d2623eSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_max_count);
979f03f517bSHans Petter Selasky 		}
98082d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_pkts =
98182d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_pkts;
982dc7e38acSHans Petter Selasky 
98382d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
98482d2623eSHans Petter Selasky 		if (was_opened)
985f03f517bSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
98682d2623eSHans Petter Selasky 		break;
98782d2623eSHans Petter Selasky 
98882d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_queue_size):
98982d2623eSHans Petter Selasky 		/* network interface must be down */
99082d2623eSHans Petter Selasky 		if (was_opened)
991f03f517bSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
99282d2623eSHans Petter Selasky 
993dc7e38acSHans Petter Selasky 		/* import TX queue size */
994dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.tx_queue_size <
995dc7e38acSHans Petter Selasky 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
996dc7e38acSHans Petter Selasky 			priv->params_ethtool.tx_queue_size =
997dc7e38acSHans Petter Selasky 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE);
998dc7e38acSHans Petter Selasky 		} else if (priv->params_ethtool.tx_queue_size >
999dc7e38acSHans Petter Selasky 		    priv->params_ethtool.tx_queue_size_max) {
1000dc7e38acSHans Petter Selasky 			priv->params_ethtool.tx_queue_size =
1001dc7e38acSHans Petter Selasky 			    priv->params_ethtool.tx_queue_size_max;
1002dc7e38acSHans Petter Selasky 		}
100382d2623eSHans Petter Selasky 		/* store actual TX queue size */
1004dc7e38acSHans Petter Selasky 		priv->params.log_sq_size =
1005dc7e38acSHans Petter Selasky 		    order_base_2(priv->params_ethtool.tx_queue_size);
100682d2623eSHans Petter Selasky 		priv->params_ethtool.tx_queue_size =
100782d2623eSHans Petter Selasky 		    1 << priv->params.log_sq_size;
100882d2623eSHans Petter Selasky 
100982d2623eSHans Petter Selasky 		/* verify TX completion factor */
101082d2623eSHans Petter Selasky 		mlx5e_ethtool_sync_tx_completion_fact(priv);
101182d2623eSHans Petter Selasky 
101282d2623eSHans Petter Selasky 		/* restart network interface, if any */
101382d2623eSHans Petter Selasky 		if (was_opened)
101482d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
101582d2623eSHans Petter Selasky 		break;
101682d2623eSHans Petter Selasky 
101782d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_queue_size):
101882d2623eSHans Petter Selasky 		/* network interface must be down */
101982d2623eSHans Petter Selasky 		if (was_opened)
102082d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
1021dc7e38acSHans Petter Selasky 
1022dc7e38acSHans Petter Selasky 		/* import RX queue size */
1023dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.rx_queue_size <
1024dc7e38acSHans Petter Selasky 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) {
1025dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_queue_size =
1026dc7e38acSHans Petter Selasky 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE);
1027dc7e38acSHans Petter Selasky 		} else if (priv->params_ethtool.rx_queue_size >
1028dc7e38acSHans Petter Selasky 		    priv->params_ethtool.rx_queue_size_max) {
1029dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_queue_size =
1030dc7e38acSHans Petter Selasky 			    priv->params_ethtool.rx_queue_size_max;
1031dc7e38acSHans Petter Selasky 		}
103282d2623eSHans Petter Selasky 		/* store actual RX queue size */
1033dc7e38acSHans Petter Selasky 		priv->params.log_rq_size =
1034dc7e38acSHans Petter Selasky 		    order_base_2(priv->params_ethtool.rx_queue_size);
103582d2623eSHans Petter Selasky 		priv->params_ethtool.rx_queue_size =
103682d2623eSHans Petter Selasky 		    1 << priv->params.log_rq_size;
1037dc7e38acSHans Petter Selasky 
103882d2623eSHans Petter Selasky 		/* update least number of RX WQEs */
103982d2623eSHans Petter Selasky 		priv->params.min_rx_wqes = min(
1040dc7e38acSHans Petter Selasky 		    priv->params_ethtool.rx_queue_size - 1,
1041dc7e38acSHans Petter Selasky 		    MLX5E_PARAMS_DEFAULT_MIN_RX_WQES);
1042dc7e38acSHans Petter Selasky 
104382d2623eSHans Petter Selasky 		/* restart network interface, if any */
104482d2623eSHans Petter Selasky 		if (was_opened)
104582d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
104682d2623eSHans Petter Selasky 		break;
104782d2623eSHans Petter Selasky 
104816ae32f9SHans Petter Selasky 	case MLX5_PARAM_OFFSET(channels_rsss):
104916ae32f9SHans Petter Selasky 		/* network interface must be down */
105016ae32f9SHans Petter Selasky 		if (was_opened)
105116ae32f9SHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
105216ae32f9SHans Petter Selasky 
105316ae32f9SHans Petter Selasky 		/* import number of channels */
105416ae32f9SHans Petter Selasky 		if (priv->params_ethtool.channels_rsss < 1)
105516ae32f9SHans Petter Selasky 			priv->params_ethtool.channels_rsss = 1;
105616ae32f9SHans Petter Selasky 		else if (priv->params_ethtool.channels_rsss > 128)
105716ae32f9SHans Petter Selasky 			priv->params_ethtool.channels_rsss = 128;
105816ae32f9SHans Petter Selasky 
105916ae32f9SHans Petter Selasky 		priv->params.channels_rsss = priv->params_ethtool.channels_rsss;
106016ae32f9SHans Petter Selasky 
106116ae32f9SHans Petter Selasky 		/* restart network interface, if any */
106216ae32f9SHans Petter Selasky 		if (was_opened)
106316ae32f9SHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
106416ae32f9SHans Petter Selasky 		break;
106516ae32f9SHans Petter Selasky 
106682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(channels):
106782d2623eSHans Petter Selasky 		/* network interface must be down */
106882d2623eSHans Petter Selasky 		if (was_opened)
106982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
107082d2623eSHans Petter Selasky 
1071dc7e38acSHans Petter Selasky 		/* import number of channels */
1072dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.channels < 1)
1073dc7e38acSHans Petter Selasky 			priv->params_ethtool.channels = 1;
1074dc7e38acSHans Petter Selasky 		else if (priv->params_ethtool.channels >
1075dc7e38acSHans Petter Selasky 		    (u64) priv->mdev->priv.eq_table.num_comp_vectors) {
1076dc7e38acSHans Petter Selasky 			priv->params_ethtool.channels =
1077dc7e38acSHans Petter Selasky 			    (u64) priv->mdev->priv.eq_table.num_comp_vectors;
1078dc7e38acSHans Petter Selasky 		}
1079dc7e38acSHans Petter Selasky 		priv->params.num_channels = priv->params_ethtool.channels;
1080dc7e38acSHans Petter Selasky 
108182d2623eSHans Petter Selasky 		/* restart network interface, if any */
108282d2623eSHans Petter Selasky 		if (was_opened)
108382d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
108482d2623eSHans Petter Selasky 		break;
108582d2623eSHans Petter Selasky 
108682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_mode):
108782d2623eSHans Petter Selasky 		/* network interface must be down */
1088d2bf00a9SHans Petter Selasky 		if (was_opened != 0 && mode_modify == 0)
108982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
109082d2623eSHans Petter Selasky 
109182d2623eSHans Petter Selasky 		/* import RX coalesce mode */
1092423530beSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_mode > 3)
1093423530beSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_mode = 3;
109482d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_mode =
109582d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_mode;
1096dc7e38acSHans Petter Selasky 
109782d2623eSHans Petter Selasky 		/* restart network interface, if any */
1098d2bf00a9SHans Petter Selasky 		if (was_opened != 0) {
1099d2bf00a9SHans Petter Selasky 			if (mode_modify == 0)
110082d2623eSHans Petter Selasky 				mlx5e_open_locked(priv->ifp);
1101d2bf00a9SHans Petter Selasky 			else
1102d2bf00a9SHans Petter Selasky 				error = mlx5e_refresh_channel_params(priv);
1103d2bf00a9SHans Petter Selasky 		}
110482d2623eSHans Petter Selasky 		break;
110582d2623eSHans Petter Selasky 
110682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_mode):
110782d2623eSHans Petter Selasky 		/* network interface must be down */
1108d2bf00a9SHans Petter Selasky 		if (was_opened != 0 && mode_modify == 0)
110982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
111082d2623eSHans Petter Selasky 
111182d2623eSHans Petter Selasky 		/* import TX coalesce mode */
111274540a31SHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_mode != 0)
111374540a31SHans Petter Selasky 			priv->params_ethtool.tx_coalesce_mode = 1;
111482d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_mode =
111582d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_mode;
111674540a31SHans Petter Selasky 
111782d2623eSHans Petter Selasky 		/* restart network interface, if any */
1118d2bf00a9SHans Petter Selasky 		if (was_opened != 0) {
1119d2bf00a9SHans Petter Selasky 			if (mode_modify == 0)
112082d2623eSHans Petter Selasky 				mlx5e_open_locked(priv->ifp);
1121d2bf00a9SHans Petter Selasky 			else
1122d2bf00a9SHans Petter Selasky 				error = mlx5e_refresh_channel_params(priv);
1123d2bf00a9SHans Petter Selasky 		}
112482d2623eSHans Petter Selasky 		break;
112582d2623eSHans Petter Selasky 
112682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(hw_lro):
112782d2623eSHans Petter Selasky 		/* network interface must be down */
112882d2623eSHans Petter Selasky 		if (was_opened)
112982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
113082d2623eSHans Petter Selasky 
113182d2623eSHans Petter Selasky 		/* import HW LRO mode */
113271defedaSSlava Shwartsman 		if (priv->params_ethtool.hw_lro != 0 &&
1133d7633a30SHans Petter Selasky 		    MLX5_CAP_ETH(priv->mdev, lro_cap)) {
1134d7633a30SHans Petter Selasky 			priv->params_ethtool.hw_lro = 1;
113571defedaSSlava Shwartsman 			/* check if feature should actually be enabled */
11365dc00f00SJustin Hibbits 			if (if_getcapenable(priv->ifp) & IFCAP_LRO) {
113771defedaSSlava Shwartsman 				priv->params.hw_lro_en = true;
1138d7633a30SHans Petter Selasky 			} else {
113971defedaSSlava Shwartsman 				priv->params.hw_lro_en = false;
1140d7633a30SHans Petter Selasky 
11416b4040d8SHans Petter Selasky 				mlx5_en_warn(priv->ifp, "To enable HW LRO "
114271defedaSSlava Shwartsman 				    "please also enable LRO via ifconfig(8).\n");
114336c1007dSHans Petter Selasky 			}
1144bb3853c6SHans Petter Selasky 		} else {
114571defedaSSlava Shwartsman 			/* return an error if HW does not support this feature */
114671defedaSSlava Shwartsman 			if (priv->params_ethtool.hw_lro != 0)
114771defedaSSlava Shwartsman 				error = EINVAL;
114871defedaSSlava Shwartsman 			priv->params.hw_lro_en = false;
114971defedaSSlava Shwartsman 			priv->params_ethtool.hw_lro = 0;
1150dc7e38acSHans Petter Selasky 		}
115182d2623eSHans Petter Selasky 		/* restart network interface, if any */
115282d2623eSHans Petter Selasky 		if (was_opened)
115382d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
115482d2623eSHans Petter Selasky 		break;
1155dc7e38acSHans Petter Selasky 
115682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(cqe_zipping):
115782d2623eSHans Petter Selasky 		/* network interface must be down */
115882d2623eSHans Petter Selasky 		if (was_opened)
115982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
116082d2623eSHans Petter Selasky 
116182d2623eSHans Petter Selasky 		/* import CQE zipping mode */
116290cc1c77SHans Petter Selasky 		if (priv->params_ethtool.cqe_zipping &&
116390cc1c77SHans Petter Selasky 		    MLX5_CAP_GEN(priv->mdev, cqe_compression)) {
116490cc1c77SHans Petter Selasky 			priv->params.cqe_zipping_en = true;
116590cc1c77SHans Petter Selasky 			priv->params_ethtool.cqe_zipping = 1;
116690cc1c77SHans Petter Selasky 		} else {
116790cc1c77SHans Petter Selasky 			priv->params.cqe_zipping_en = false;
116890cc1c77SHans Petter Selasky 			priv->params_ethtool.cqe_zipping = 0;
116990cc1c77SHans Petter Selasky 		}
117082d2623eSHans Petter Selasky 		/* restart network interface, if any */
1171dc7e38acSHans Petter Selasky 		if (was_opened)
1172dc7e38acSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
117382d2623eSHans Petter Selasky 		break;
117482d2623eSHans Petter Selasky 
117582d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_completion_fact):
117682d2623eSHans Petter Selasky 		/* network interface must be down */
117782d2623eSHans Petter Selasky 		if (was_opened)
117882d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
117982d2623eSHans Petter Selasky 
118082d2623eSHans Petter Selasky 		/* verify parameter */
118182d2623eSHans Petter Selasky 		mlx5e_ethtool_sync_tx_completion_fact(priv);
118282d2623eSHans Petter Selasky 
118382d2623eSHans Petter Selasky 		/* restart network interface, if any */
118482d2623eSHans Petter Selasky 		if (was_opened)
118582d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
118682d2623eSHans Petter Selasky 		break;
118782d2623eSHans Petter Selasky 
1188bb3616abSHans Petter Selasky 	case MLX5_PARAM_OFFSET(modify_tx_dma):
1189bb3616abSHans Petter Selasky 		/* check if network interface is opened */
1190bb3616abSHans Petter Selasky 		if (was_opened) {
1191bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_tx_dma =
1192bb3616abSHans Petter Selasky 			    priv->params_ethtool.modify_tx_dma ? 1 : 0;
1193bb3616abSHans Petter Selasky 			/* modify tx according to value */
1194bb3616abSHans Petter Selasky 			mlx5e_modify_tx_dma(priv, value != 0);
1195bb3616abSHans Petter Selasky 		} else {
1196bb3616abSHans Petter Selasky 			/* if closed force enable tx */
1197bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_tx_dma = 0;
1198bb3616abSHans Petter Selasky 		}
1199bb3616abSHans Petter Selasky 		break;
1200bb3616abSHans Petter Selasky 
1201bb3616abSHans Petter Selasky 	case MLX5_PARAM_OFFSET(modify_rx_dma):
1202bb3616abSHans Petter Selasky 		/* check if network interface is opened */
1203bb3616abSHans Petter Selasky 		if (was_opened) {
1204bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_rx_dma =
1205bb3616abSHans Petter Selasky 			    priv->params_ethtool.modify_rx_dma ? 1 : 0;
1206bb3616abSHans Petter Selasky 			/* modify rx according to value */
1207bb3616abSHans Petter Selasky 			mlx5e_modify_rx_dma(priv, value != 0);
1208bb3616abSHans Petter Selasky 		} else {
1209bb3616abSHans Petter Selasky 			/* if closed force enable rx */
1210bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_rx_dma = 0;
1211bb3616abSHans Petter Selasky 		}
1212bb3616abSHans Petter Selasky 		break;
1213bb3616abSHans Petter Selasky 
121466d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_pci_enable):
121566d53750SHans Petter Selasky 		priv->params_ethtool.diag_pci_enable =
121666d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable ? 1 : 0;
121766d53750SHans Petter Selasky 
121866d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
121966d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
122066d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
122166d53750SHans Petter Selasky 		break;
122266d53750SHans Petter Selasky 
122366d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_general_enable):
122466d53750SHans Petter Selasky 		priv->params_ethtool.diag_general_enable =
122566d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable ? 1 : 0;
122666d53750SHans Petter Selasky 
122766d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
122866d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
122966d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
123066d53750SHans Petter Selasky 		break;
123166d53750SHans Petter Selasky 
123261fd7ac0SHans Petter Selasky 	case MLX5_PARAM_OFFSET(mc_local_lb):
1233ea00d7e8SHans Petter Selasky 		/* check if mlx5ib is managing this feature */
1234ea00d7e8SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) {
1235ea00d7e8SHans Petter Selasky 			error = EOPNOTSUPP;
1236ea00d7e8SHans Petter Selasky 			break;
1237ea00d7e8SHans Petter Selasky 		}
1238ea00d7e8SHans Petter Selasky 
123961fd7ac0SHans Petter Selasky 		priv->params_ethtool.mc_local_lb =
124061fd7ac0SHans Petter Selasky 		    priv->params_ethtool.mc_local_lb ? 1 : 0;
124161fd7ac0SHans Petter Selasky 
1242c1b76119SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, disable_local_lb_mc)) {
124361fd7ac0SHans Petter Selasky 			error = mlx5_nic_vport_modify_local_lb(priv->mdev,
124461fd7ac0SHans Petter Selasky 			    MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb);
124561fd7ac0SHans Petter Selasky 		} else {
124661fd7ac0SHans Petter Selasky 			error = EOPNOTSUPP;
124761fd7ac0SHans Petter Selasky 		}
124861fd7ac0SHans Petter Selasky 		break;
124961fd7ac0SHans Petter Selasky 
125061fd7ac0SHans Petter Selasky 	case MLX5_PARAM_OFFSET(uc_local_lb):
1251ea00d7e8SHans Petter Selasky 		/* check if mlx5ib is managing this feature */
1252ea00d7e8SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) {
1253ea00d7e8SHans Petter Selasky 			error = EOPNOTSUPP;
1254ea00d7e8SHans Petter Selasky 			break;
1255ea00d7e8SHans Petter Selasky 		}
1256ea00d7e8SHans Petter Selasky 
125761fd7ac0SHans Petter Selasky 		priv->params_ethtool.uc_local_lb =
125861fd7ac0SHans Petter Selasky 		    priv->params_ethtool.uc_local_lb ? 1 : 0;
125961fd7ac0SHans Petter Selasky 
1260c1b76119SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, disable_local_lb_uc)) {
126161fd7ac0SHans Petter Selasky 			error = mlx5_nic_vport_modify_local_lb(priv->mdev,
126261fd7ac0SHans Petter Selasky 			    MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb);
126361fd7ac0SHans Petter Selasky 		} else {
126461fd7ac0SHans Petter Selasky 			error = EOPNOTSUPP;
126561fd7ac0SHans Petter Selasky 		}
126661fd7ac0SHans Petter Selasky 		break;
126761fd7ac0SHans Petter Selasky 
1268c8d16d1eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(irq_cpu_base):
1269c8d16d1eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(irq_cpu_stride):
1270c8d16d1eSHans Petter Selasky 		if (was_opened) {
1271c8d16d1eSHans Petter Selasky 			/* network interface must toggled */
1272c8d16d1eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
1273c8d16d1eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
1274c8d16d1eSHans Petter Selasky 		}
1275c8d16d1eSHans Petter Selasky 		break;
1276c8d16d1eSHans Petter Selasky 
127782d2623eSHans Petter Selasky 	default:
127882d2623eSHans Petter Selasky 		break;
127982d2623eSHans Petter Selasky 	}
1280dc7e38acSHans Petter Selasky done:
1281dc7e38acSHans Petter Selasky 	PRIV_UNLOCK(priv);
1282dc7e38acSHans Petter Selasky 	return (error);
1283dc7e38acSHans Petter Selasky }
1284dc7e38acSHans Petter Selasky 
1285dc7e38acSHans Petter Selasky static const char *mlx5e_params_desc[] = {
1286dc7e38acSHans Petter Selasky 	MLX5E_PARAMS(MLX5E_STATS_DESC)
1287dc7e38acSHans Petter Selasky };
1288dc7e38acSHans Petter Selasky 
1289dc7e38acSHans Petter Selasky static const char *mlx5e_port_stats_debug_desc[] = {
1290dc7e38acSHans Petter Selasky 	MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC)
1291dc7e38acSHans Petter Selasky };
1292dc7e38acSHans Petter Selasky 
1293dc7e38acSHans Petter Selasky static int
1294f2b4782cSHans Petter Selasky mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS)
1295f2b4782cSHans Petter Selasky {
1296f2b4782cSHans Petter Selasky 	struct mlx5e_priv *priv;
1297f2b4782cSHans Petter Selasky 	struct sbuf sb;
1298f2b4782cSHans Petter Selasky 	struct mlx5e_channel *c;
1299f2b4782cSHans Petter Selasky 	struct mlx5e_sq *sq;
1300f2b4782cSHans Petter Selasky 	struct mlx5e_rq *rq;
1301f2b4782cSHans Petter Selasky 	int error, i, tc;
13022110251aSHans Petter Selasky 	bool opened;
1303f2b4782cSHans Petter Selasky 
1304f2b4782cSHans Petter Selasky 	priv = arg1;
1305f2b4782cSHans Petter Selasky 	error = sysctl_wire_old_buffer(req, 0);
1306f2b4782cSHans Petter Selasky 	if (error != 0)
1307f2b4782cSHans Petter Selasky 		return (error);
13082110251aSHans Petter Selasky 	if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL)
1309f2b4782cSHans Petter Selasky 		return (ENOMEM);
1310f2b4782cSHans Petter Selasky 	sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
1311f2b4782cSHans Petter Selasky 
1312f2b4782cSHans Petter Selasky 	PRIV_LOCK(priv);
13132110251aSHans Petter Selasky 	opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
13142110251aSHans Petter Selasky 
13152110251aSHans Petter Selasky 	sbuf_printf(&sb, "pages irq %d\n",
13162110251aSHans Petter Selasky 	    priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector);
13172110251aSHans Petter Selasky 	sbuf_printf(&sb, "command irq %d\n",
13182110251aSHans Petter Selasky 	    priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector);
13192110251aSHans Petter Selasky 	sbuf_printf(&sb, "async irq %d\n",
13202110251aSHans Petter Selasky 	    priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector);
13212110251aSHans Petter Selasky 
13222110251aSHans Petter Selasky 	for (i = 0; i != priv->params.num_channels; i++) {
13232110251aSHans Petter Selasky 		int eqn_not_used = -1;
13242110251aSHans Petter Selasky 		int irqn = MLX5_EQ_VEC_COMP_BASE;
13252110251aSHans Petter Selasky 
13262110251aSHans Petter Selasky 		if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0)
13272110251aSHans Petter Selasky 			continue;
13282110251aSHans Petter Selasky 
13292110251aSHans Petter Selasky 		c = opened ? &priv->channel[i] : NULL;
13302110251aSHans Petter Selasky 		rq = opened ? &c->rq : NULL;
13312110251aSHans Petter Selasky 		sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i,
13322110251aSHans Petter Selasky 		    opened ? rq->rqn : -1,
13332110251aSHans Petter Selasky 		    opened ? rq->cq.mcq.cqn : -1,
13342110251aSHans Petter Selasky 		    priv->mdev->priv.msix_arr[irqn].vector);
13352110251aSHans Petter Selasky 
13362110251aSHans Petter Selasky 		for (tc = 0; tc != priv->num_tc; tc++) {
13372110251aSHans Petter Selasky 			sq = opened ? &c->sq[tc] : NULL;
13382110251aSHans Petter Selasky 			sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n",
13392110251aSHans Petter Selasky 			    i, tc,
13402110251aSHans Petter Selasky 			    opened ? sq->sqn : -1,
13412110251aSHans Petter Selasky 			    opened ? sq->cq.mcq.cqn : -1,
13422110251aSHans Petter Selasky 			    priv->mdev->priv.msix_arr[irqn].vector);
1343f2b4782cSHans Petter Selasky 		}
1344f2b4782cSHans Petter Selasky 	}
1345f2b4782cSHans Petter Selasky 	PRIV_UNLOCK(priv);
1346f2b4782cSHans Petter Selasky 	error = sbuf_finish(&sb);
1347f2b4782cSHans Petter Selasky 	sbuf_delete(&sb);
1348f2b4782cSHans Petter Selasky 	return (error);
1349f2b4782cSHans Petter Selasky }
1350f2b4782cSHans Petter Selasky 
1351f2b4782cSHans Petter Selasky static int
1352dc7e38acSHans Petter Selasky mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS)
1353dc7e38acSHans Petter Selasky {
1354dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
1355b3cf1493SSlava Shwartsman 	int sys_debug;
1356b3cf1493SSlava Shwartsman 	int error;
1357f2b4782cSHans Petter Selasky 
1358f2b4782cSHans Petter Selasky 	PRIV_LOCK(priv);
1359069963d7SHans Petter Selasky 	if (priv->gone != 0) {
1360069963d7SHans Petter Selasky 		error = ENODEV;
1361069963d7SHans Petter Selasky 		goto done;
1362069963d7SHans Petter Selasky 	}
1363b3cf1493SSlava Shwartsman 	sys_debug = priv->sysctl_debug;
1364b3cf1493SSlava Shwartsman 	error = sysctl_handle_int(oidp, &sys_debug, 0, req);
1365b3cf1493SSlava Shwartsman 	if (error != 0 || !req->newptr)
1366b3cf1493SSlava Shwartsman 		goto done;
1367b3cf1493SSlava Shwartsman 	sys_debug = sys_debug ? 1 : 0;
1368b3cf1493SSlava Shwartsman 	if (sys_debug == priv->sysctl_debug)
1369b3cf1493SSlava Shwartsman 		goto done;
1370b3cf1493SSlava Shwartsman 
1371b3cf1493SSlava Shwartsman 	if ((priv->sysctl_debug = sys_debug)) {
1372dc7e38acSHans Petter Selasky 		mlx5e_create_stats(&priv->stats.port_stats_debug.ctx,
1373dc7e38acSHans Petter Selasky 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats",
1374dc7e38acSHans Petter Selasky 		    mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM,
1375dc7e38acSHans Petter Selasky 		    priv->stats.port_stats_debug.arg);
1376b3cf1493SSlava Shwartsman 		SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx,
1377f2b4782cSHans Petter Selasky 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
1378f2b4782cSHans Petter Selasky 		    "hw_ctx_debug",
1379f2b4782cSHans Petter Selasky 		    CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0,
1380f2b4782cSHans Petter Selasky 		    mlx5e_ethtool_debug_channel_info, "S", "");
1381f2b4782cSHans Petter Selasky 	} else {
1382dc7e38acSHans Petter Selasky 		sysctl_ctx_free(&priv->stats.port_stats_debug.ctx);
1383f2b4782cSHans Petter Selasky 	}
1384b3cf1493SSlava Shwartsman done:
1385f2b4782cSHans Petter Selasky 	PRIV_UNLOCK(priv);
1386b3cf1493SSlava Shwartsman 	return (error);
1387dc7e38acSHans Petter Selasky }
1388dc7e38acSHans Petter Selasky 
138966d53750SHans Petter Selasky static void
139066d53750SHans Petter Selasky mlx5e_create_diagnostics(struct mlx5e_priv *priv)
139166d53750SHans Petter Selasky {
139266d53750SHans Petter Selasky 	struct mlx5_core_diagnostics_entry entry;
139366d53750SHans Petter Selasky 	struct sysctl_ctx_list *ctx;
139466d53750SHans Petter Selasky 	struct sysctl_oid *node;
139566d53750SHans Petter Selasky 	int x;
139666d53750SHans Petter Selasky 
139766d53750SHans Petter Selasky 	/* sysctl context we are using */
139866d53750SHans Petter Selasky 	ctx = &priv->sysctl_ctx;
139966d53750SHans Petter Selasky 
140066d53750SHans Petter Selasky 	/* create root node */
140166d53750SHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx,
140266d53750SHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
14037029da5cSPawel Biernacki 	    "diagnostics", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Diagnostics");
140466d53750SHans Petter Selasky 	if (node == NULL)
140566d53750SHans Petter Selasky 		return;
140666d53750SHans Petter Selasky 
140766d53750SHans Petter Selasky 	/* create PCI diagnostics */
140866d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) {
140966d53750SHans Petter Selasky 		entry = mlx5_core_pci_diagnostics_table[x];
141066d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
141166d53750SHans Petter Selasky 			continue;
141266d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
141366d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_pci.array + x,
141466d53750SHans Petter Selasky 		    "PCI diagnostics counter");
141566d53750SHans Petter Selasky 	}
141666d53750SHans Petter Selasky 
141766d53750SHans Petter Selasky 	/* create general diagnostics */
141866d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) {
141966d53750SHans Petter Selasky 		entry = mlx5_core_general_diagnostics_table[x];
142066d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
142166d53750SHans Petter Selasky 			continue;
142266d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
142366d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_general.array + x,
142466d53750SHans Petter Selasky 		    "General diagnostics counter");
142566d53750SHans Petter Selasky 	}
142666d53750SHans Petter Selasky }
142766d53750SHans Petter Selasky 
1428dc7e38acSHans Petter Selasky void
1429dc7e38acSHans Petter Selasky mlx5e_create_ethtool(struct mlx5e_priv *priv)
1430dc7e38acSHans Petter Selasky {
143196425f44SHans Petter Selasky 	struct sysctl_oid *fec_node;
143296425f44SHans Petter Selasky 	struct sysctl_oid *qos_node;
143396425f44SHans Petter Selasky 	struct sysctl_oid *node;
1434dc7e38acSHans Petter Selasky 	const char *pnameunit;
14356deb0b1eSHans Petter Selasky 	struct mlx5e_port_buffer port_buffer;
1436dc7e38acSHans Petter Selasky 	unsigned x;
1437cfc9c386SHans Petter Selasky 	int i;
1438dc7e38acSHans Petter Selasky 
1439dc7e38acSHans Petter Selasky 	/* set some defaults */
1440c8d16d1eSHans Petter Selasky 	priv->params_ethtool.irq_cpu_base = -1;	/* disabled */
1441c8d16d1eSHans Petter Selasky 	priv->params_ethtool.irq_cpu_stride = 1;
1442dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
1443dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE;
1444dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size;
1445dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size;
1446dc7e38acSHans Petter Selasky 	priv->params_ethtool.channels = priv->params.num_channels;
144716ae32f9SHans Petter Selasky 	priv->params_ethtool.channels_rsss = priv->params.channels_rsss;
1448dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count);
1449dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period);
1450dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode;
1451dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec;
1452dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts;
145374540a31SHans Petter Selasky 	priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode;
1454dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec;
1455dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts;
1456dc7e38acSHans Petter Selasky 	priv->params_ethtool.hw_lro = priv->params.hw_lro_en;
145790cc1c77SHans Petter Selasky 	priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en;
1458376bcf63SHans Petter Selasky 	mlx5e_ethtool_sync_tx_completion_fact(priv);
1459dc7e38acSHans Petter Selasky 
146061fd7ac0SHans Petter Selasky 	/* get default values for local loopback, if any */
1461c1b76119SHans Petter Selasky 	if (MLX5_CAP_GEN(priv->mdev, disable_local_lb_mc) ||
1462c1b76119SHans Petter Selasky 	    MLX5_CAP_GEN(priv->mdev, disable_local_lb_uc)) {
146361fd7ac0SHans Petter Selasky 		int err;
146461fd7ac0SHans Petter Selasky 		u8 val;
146561fd7ac0SHans Petter Selasky 
146661fd7ac0SHans Petter Selasky 		err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val);
146761fd7ac0SHans Petter Selasky 		if (err == 0)
146861fd7ac0SHans Petter Selasky 			priv->params_ethtool.mc_local_lb = val;
146961fd7ac0SHans Petter Selasky 
147061fd7ac0SHans Petter Selasky 		err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val);
147161fd7ac0SHans Petter Selasky 		if (err == 0)
147261fd7ac0SHans Petter Selasky 			priv->params_ethtool.uc_local_lb = val;
147361fd7ac0SHans Petter Selasky 	}
147461fd7ac0SHans Petter Selasky 
1475dc7e38acSHans Petter Selasky 	/* create root node */
1476dc7e38acSHans Petter Selasky 	node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1477dc7e38acSHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
14787029da5cSPawel Biernacki 	    "conf", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, "Configuration");
1479dc7e38acSHans Petter Selasky 	if (node == NULL)
1480dc7e38acSHans Petter Selasky 		return;
1481dc7e38acSHans Petter Selasky 	for (x = 0; x != MLX5E_PARAMS_NUM; x++) {
1482dc7e38acSHans Petter Selasky 		/* check for read-only parameter */
148353d7bb46SHans Petter Selasky 		if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL ||
148453d7bb46SHans Petter Selasky 		    strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) {
1485dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1486dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD |
1487dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1488dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
1489a60f9534SHans Petter Selasky 		} else if (strcmp(mlx5e_params_desc[2 * x], "hw_lro") == 0) {
1490a60f9534SHans Petter Selasky 			/* read-only, but tunable parameters */
1491a60f9534SHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1492a60f9534SHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RDTUN |
1493a60f9534SHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1494a60f9534SHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
1495dc7e38acSHans Petter Selasky 		} else {
1496ec0143b2SHans Petter Selasky 			/*
1497ec0143b2SHans Petter Selasky 			 * NOTE: In FreeBSD-11 and newer the
1498ec0143b2SHans Petter Selasky 			 * CTLFLAG_RWTUN flag will take care of
1499ec0143b2SHans Petter Selasky 			 * loading default sysctl value from the
1500ec0143b2SHans Petter Selasky 			 * kernel environment, if any:
1501ec0143b2SHans Petter Selasky 			 */
1502dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1503dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN |
1504dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1505dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
1506dc7e38acSHans Petter Selasky 		}
1507dc7e38acSHans Petter Selasky 	}
1508dc7e38acSHans Petter Selasky 
150996425f44SHans Petter Selasky 	/* create fec node */
151096425f44SHans Petter Selasky 	fec_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
151196425f44SHans Petter Selasky 	    SYSCTL_CHILDREN(node), OID_AUTO,
15127029da5cSPawel Biernacki 	    "fec", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
15137029da5cSPawel Biernacki 	    "Forward Error Correction");
151496425f44SHans Petter Selasky 	if (fec_node == NULL)
151596425f44SHans Petter Selasky 		return;
151696425f44SHans Petter Selasky 
151796425f44SHans Petter Selasky 	if (mlx5e_fec_update(priv) == 0) {
151896425f44SHans Petter Selasky 		SYSCTL_ADD_U32(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
151996425f44SHans Petter Selasky 		    "mode_active", CTLFLAG_RD | CTLFLAG_MPSAFE,
152096425f44SHans Petter Selasky 		    &priv->params_ethtool.fec_mode_active, 0,
152196425f44SHans Petter Selasky 		    "Current FEC mode bit, if any.");
152296425f44SHans Petter Selasky 
152396425f44SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
152496425f44SHans Petter Selasky 		    "mask_10x_25x", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
152596425f44SHans Petter Selasky 		    priv, 0, &mlx5e_fec_mask_10x_25x_handler, "CU",
152696425f44SHans Petter Selasky 		    "Set FEC masks for 10G_40G, 25G_50G, 56G, 100G respectivly. "
152796425f44SHans Petter Selasky 		    "0:Auto "
152896425f44SHans Petter Selasky 		    "1:NOFEC "
152996425f44SHans Petter Selasky 		    "2:FIRECODE "
153096425f44SHans Petter Selasky 		    "4:RS");
153196425f44SHans Petter Selasky 
153296425f44SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
153396425f44SHans Petter Selasky 		    "avail_10x_25x", CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE,
153496425f44SHans Petter Selasky 		    priv, 0, &mlx5e_fec_avail_10x_25x_handler, "CU",
153596425f44SHans Petter Selasky 		    "Get available FEC bits for 10G_40G, 25G_50G, 56G, 100G respectivly. "
153696425f44SHans Petter Selasky 		    "0:Auto "
153796425f44SHans Petter Selasky 		    "1:NOFEC "
153896425f44SHans Petter Selasky 		    "2:FIRECODE "
153996425f44SHans Petter Selasky 		    "4:RS");
154096425f44SHans Petter Selasky 
154196425f44SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
154296425f44SHans Petter Selasky 		    "mask_50x", CTLTYPE_U16 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
154396425f44SHans Petter Selasky 		    priv, 0, &mlx5e_fec_mask_50x_handler, "SU",
154496425f44SHans Petter Selasky 		    "Set FEC masks for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. "
154596425f44SHans Petter Selasky 		    "0:Auto "
154696425f44SHans Petter Selasky 		    "128:RS "
154796425f44SHans Petter Selasky 		    "512:LL RS");
154896425f44SHans Petter Selasky 
154996425f44SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
155096425f44SHans Petter Selasky 		    "avail_50x", CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_MPSAFE,
155196425f44SHans Petter Selasky 		    priv, 0, &mlx5e_fec_avail_50x_handler, "SU",
155296425f44SHans Petter Selasky 		    "Get available FEC bits for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. "
155396425f44SHans Petter Selasky 		    "0:Auto "
155496425f44SHans Petter Selasky 		    "128:RS "
155596425f44SHans Petter Selasky 		    "512:LL RS");
155696425f44SHans Petter Selasky 	}
155796425f44SHans Petter Selasky 
1558dc7e38acSHans Petter Selasky 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1559dc7e38acSHans Petter Selasky 	    "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv,
1560dc7e38acSHans Petter Selasky 	    0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics");
1561dc7e38acSHans Petter Selasky 
1562dc7e38acSHans Petter Selasky 	pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
1563dc7e38acSHans Petter Selasky 
1564dc7e38acSHans Petter Selasky 	SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node),
1565dc7e38acSHans Petter Selasky 	    OID_AUTO, "device_name", CTLFLAG_RD,
1566dc7e38acSHans Petter Selasky 	    __DECONST(void *, pnameunit), 0,
1567dc7e38acSHans Petter Selasky 	    "PCI device name");
1568dc7e38acSHans Petter Selasky 
156966d53750SHans Petter Selasky 	/* Diagnostics support */
157066d53750SHans Petter Selasky 	mlx5e_create_diagnostics(priv);
1571cfc9c386SHans Petter Selasky 
1572cfc9c386SHans Petter Selasky 	/* create qos node */
1573cfc9c386SHans Petter Selasky 	qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1574cfc9c386SHans Petter Selasky 	    SYSCTL_CHILDREN(node), OID_AUTO,
15757029da5cSPawel Biernacki 	    "qos", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
15767029da5cSPawel Biernacki 	    "Quality Of Service configuration");
1577e870c0abSSlava Shwartsman 	if (qos_node == NULL)
1578cfc9c386SHans Petter Selasky 		return;
1579cfc9c386SHans Petter Selasky 
1580e870c0abSSlava Shwartsman 	/* Priority rate limit support */
1581e870c0abSSlava Shwartsman 	if (mlx5e_getmaxrate(priv) == 0) {
1582cfc9c386SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1583e870c0abSSlava Shwartsman 		    OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1584e870c0abSSlava Shwartsman 		    priv, 0, mlx5e_tc_maxrate_handler, "QU",
1585e870c0abSSlava Shwartsman 		    "Max rate for priority, specified in kilobits, where kilo=1000, "
1586e870c0abSSlava Shwartsman 		    "max_rate must be divisible by 100000");
1587cfc9c386SHans Petter Selasky 	}
15882e9c3a4fSHans Petter Selasky 
1589e870c0abSSlava Shwartsman 	/* Bandwidth limiting by ratio */
1590e870c0abSSlava Shwartsman 	if (mlx5e_get_max_alloc(priv) == 0) {
1591e870c0abSSlava Shwartsman 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1592e870c0abSSlava Shwartsman 		    OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1593e870c0abSSlava Shwartsman 		    priv, 0, mlx5e_tc_rate_share_handler, "QU",
1594e870c0abSSlava Shwartsman 		    "Specify bandwidth ratio from 1 to 100 "
1595e870c0abSSlava Shwartsman 		    "for the available traffic classes");
1596e870c0abSSlava Shwartsman 	}
15972e9c3a4fSHans Petter Selasky 
1598e870c0abSSlava Shwartsman 	/* Priority to traffic class mapping */
1599e870c0abSSlava Shwartsman 	if (mlx5e_get_prio_tc(priv) == 0) {
16002e9c3a4fSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
160124385321SHans Petter Selasky 		    OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
160224385321SHans Petter Selasky 		    priv, 0, mlx5e_prio_to_tc_handler, "CU",
160324385321SHans Petter Selasky 		    "Set traffic class 0 to 7 for priority 0 to 7 inclusivly");
1604e870c0abSSlava Shwartsman 	}
1605ed0cee0bSHans Petter Selasky 
1606ed0cee0bSHans Petter Selasky 	/* DSCP support */
1607ed0cee0bSHans Petter Selasky 	if (mlx5e_get_dscp(priv) == 0) {
1608ed0cee0bSHans Petter Selasky 		for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) {
1609ed0cee0bSHans Petter Selasky 			char name[32];
1610ed0cee0bSHans Petter Selasky 			snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7);
1611ed0cee0bSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1612ed0cee0bSHans Petter Selasky 				OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1613ed0cee0bSHans Petter Selasky 				priv, i, mlx5e_dscp_prio_handler, "CU",
1614ed0cee0bSHans Petter Selasky 				"Set DSCP to priority mapping, 0..7");
1615ed0cee0bSHans Petter Selasky 		}
1616a880c1ffSHans Petter Selasky #define	A	"Set trust state, 1:PCP 2:DSCP"
1617a880c1ffSHans Petter Selasky #define	B	" 3:BOTH"
1618ed0cee0bSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1619ed0cee0bSHans Petter Selasky 		    OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1620ed0cee0bSHans Petter Selasky 		    priv, 0, mlx5e_trust_state_handler, "CU",
1621dfea1c3eSHans Petter Selasky 		    MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ?
1622a880c1ffSHans Petter Selasky 		    A B : A);
1623a880c1ffSHans Petter Selasky #undef B
1624a880c1ffSHans Petter Selasky #undef A
1625ed0cee0bSHans Petter Selasky 	}
16266deb0b1eSHans Petter Selasky 
16276deb0b1eSHans Petter Selasky 	if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) {
16286deb0b1eSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
16296deb0b1eSHans Petter Selasky 		    OID_AUTO, "buffers_size",
16306deb0b1eSHans Petter Selasky 		    CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
16316deb0b1eSHans Petter Selasky 		    priv, 0, mlx5e_buf_size_handler, "IU",
16326deb0b1eSHans Petter Selasky 		    "Set buffers sizes");
16336deb0b1eSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
16346deb0b1eSHans Petter Selasky 		    OID_AUTO, "buffers_prio",
16356deb0b1eSHans Petter Selasky 		    CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
16366deb0b1eSHans Petter Selasky 		    priv, 0, mlx5e_buf_prio_handler, "CU",
16376deb0b1eSHans Petter Selasky 		    "Set prio to buffers mapping");
16386deb0b1eSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
16396deb0b1eSHans Petter Selasky 		    OID_AUTO, "cable_length",
16406deb0b1eSHans Petter Selasky 		    CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
16416deb0b1eSHans Petter Selasky 		    priv, 0, mlx5e_cable_length_handler, "IU",
16426deb0b1eSHans Petter Selasky 		    "Set cable length in meters for xoff threshold calculation");
16436deb0b1eSHans Petter Selasky 	}
1644decb087cSHans Petter Selasky 
1645decb087cSHans Petter Selasky 	if (mlx5e_hw_temperature_update(priv) == 0) {
1646decb087cSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(priv->sysctl_ifnet),
1647decb087cSHans Petter Selasky 		    OID_AUTO, "hw_temperature",
1648decb087cSHans Petter Selasky 		    CTLTYPE_S32 | CTLFLAG_RD | CTLFLAG_MPSAFE,
1649decb087cSHans Petter Selasky 		    priv, 0, mlx5e_hw_temperature_handler, "I",
16509097ac9aSElyes HAOUAS 		    "HW temperature in millicelsius");
1651decb087cSHans Petter Selasky 	}
1652dc7e38acSHans Petter Selasky }
1653