xref: /freebsd/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c (revision 95ee2897)
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 
26b984b956SKonstantin Belousov #include "opt_rss.h"
27b984b956SKonstantin Belousov #include "opt_ratelimit.h"
28b984b956SKonstantin Belousov 
2989918a23SKonstantin Belousov #include <dev/mlx5/mlx5_en/en.h>
3089918a23SKonstantin Belousov #include <dev/mlx5/mlx5_en/port_buffer.h>
31dc7e38acSHans Petter Selasky 
32dc7e38acSHans Petter Selasky void
mlx5e_create_stats(struct sysctl_ctx_list * ctx,struct sysctl_oid_list * parent,const char * buffer,const char ** desc,unsigned num,u64 * arg)33dc7e38acSHans Petter Selasky mlx5e_create_stats(struct sysctl_ctx_list *ctx,
34dc7e38acSHans Petter Selasky     struct sysctl_oid_list *parent, const char *buffer,
35dc7e38acSHans Petter Selasky     const char **desc, unsigned num, u64 * arg)
36dc7e38acSHans Petter Selasky {
37dc7e38acSHans Petter Selasky 	struct sysctl_oid *node;
38dc7e38acSHans Petter Selasky 	unsigned x;
39dc7e38acSHans Petter Selasky 
40dc7e38acSHans Petter Selasky 	sysctl_ctx_init(ctx);
41dc7e38acSHans Petter Selasky 
42dc7e38acSHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO,
437029da5cSPawel Biernacki 	    buffer, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Statistics");
44dc7e38acSHans Petter Selasky 	if (node == NULL)
45dc7e38acSHans Petter Selasky 		return;
46dc7e38acSHans Petter Selasky 	for (x = 0; x != num; x++) {
47dc7e38acSHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
48dc7e38acSHans Petter Selasky 		    desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]);
49dc7e38acSHans Petter Selasky 	}
50dc7e38acSHans Petter Selasky }
51dc7e38acSHans Petter Selasky 
527272f9cdSHans Petter Selasky void
mlx5e_create_counter_stats(struct sysctl_ctx_list * ctx,struct sysctl_oid_list * parent,const char * buffer,const char ** desc,unsigned num,counter_u64_t * arg)537272f9cdSHans Petter Selasky mlx5e_create_counter_stats(struct sysctl_ctx_list *ctx,
547272f9cdSHans Petter Selasky     struct sysctl_oid_list *parent, const char *buffer,
557272f9cdSHans Petter Selasky     const char **desc, unsigned num, counter_u64_t *arg)
567272f9cdSHans Petter Selasky {
577272f9cdSHans Petter Selasky 	struct sysctl_oid *node;
587272f9cdSHans Petter Selasky 	unsigned x;
597272f9cdSHans Petter Selasky 
607272f9cdSHans Petter Selasky 	sysctl_ctx_init(ctx);
617272f9cdSHans Petter Selasky 
627272f9cdSHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO,
637029da5cSPawel Biernacki 	    buffer, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Statistics");
647272f9cdSHans Petter Selasky 	if (node == NULL)
657272f9cdSHans Petter Selasky 		return;
667272f9cdSHans Petter Selasky 	for (x = 0; x != num; x++) {
677272f9cdSHans Petter Selasky 		SYSCTL_ADD_COUNTER_U64(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
687272f9cdSHans Petter Selasky 		    desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]);
697272f9cdSHans Petter Selasky 	}
707272f9cdSHans Petter Selasky }
717272f9cdSHans Petter Selasky 
72376bcf63SHans Petter Selasky static void
mlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv * priv)73376bcf63SHans Petter Selasky mlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv *priv)
74376bcf63SHans Petter Selasky {
75376bcf63SHans Petter Selasky 	/*
76376bcf63SHans Petter Selasky 	 * Limit the maximum distance between completion events to
77376bcf63SHans Petter Selasky 	 * half of the currently set TX queue size.
78376bcf63SHans Petter Selasky 	 *
79376bcf63SHans Petter Selasky 	 * The maximum number of queue entries a single IP packet can
80376bcf63SHans Petter Selasky 	 * consume is given by MLX5_SEND_WQE_MAX_WQEBBS.
81376bcf63SHans Petter Selasky 	 *
82376bcf63SHans Petter Selasky 	 * The worst case max value is then given as below:
83376bcf63SHans Petter Selasky 	 */
84376bcf63SHans Petter Selasky 	uint64_t max = priv->params_ethtool.tx_queue_size /
85376bcf63SHans Petter Selasky 	    (2 * MLX5_SEND_WQE_MAX_WQEBBS);
86376bcf63SHans Petter Selasky 
87376bcf63SHans Petter Selasky 	/*
88376bcf63SHans Petter Selasky 	 * Update the maximum completion factor value in case the
89376bcf63SHans Petter Selasky 	 * tx_queue_size field changed. Ensure we don't overflow
90376bcf63SHans Petter Selasky 	 * 16-bits.
91376bcf63SHans Petter Selasky 	 */
92376bcf63SHans Petter Selasky 	if (max < 1)
93376bcf63SHans Petter Selasky 		max = 1;
94376bcf63SHans Petter Selasky 	else if (max > 65535)
95376bcf63SHans Petter Selasky 		max = 65535;
96376bcf63SHans Petter Selasky 	priv->params_ethtool.tx_completion_fact_max = max;
97376bcf63SHans Petter Selasky 
98376bcf63SHans Petter Selasky 	/*
99376bcf63SHans Petter Selasky 	 * Verify that the current TX completion factor is within the
100376bcf63SHans Petter Selasky 	 * given limits:
101376bcf63SHans Petter Selasky 	 */
102376bcf63SHans Petter Selasky 	if (priv->params_ethtool.tx_completion_fact < 1)
103376bcf63SHans Petter Selasky 		priv->params_ethtool.tx_completion_fact = 1;
104376bcf63SHans Petter Selasky 	else if (priv->params_ethtool.tx_completion_fact > max)
105376bcf63SHans Petter Selasky 		priv->params_ethtool.tx_completion_fact = max;
106376bcf63SHans Petter Selasky }
107376bcf63SHans Petter Selasky 
108cfc9c386SHans Petter Selasky static int
mlx5e_getmaxrate(struct mlx5e_priv * priv)109cfc9c386SHans Petter Selasky mlx5e_getmaxrate(struct mlx5e_priv *priv)
110cfc9c386SHans Petter Selasky {
111cfc9c386SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
112cfc9c386SHans Petter Selasky 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
113cfc9c386SHans Petter Selasky 	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
114cfc9c386SHans Petter Selasky 	int err;
115cfc9c386SHans Petter Selasky 	int i;
116cfc9c386SHans Petter Selasky 
117cfc9c386SHans Petter Selasky 	PRIV_LOCK(priv);
118cfc9c386SHans Petter Selasky 	err = -mlx5_query_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
119cfc9c386SHans Petter Selasky 	if (err)
120cfc9c386SHans Petter Selasky 		goto done;
121cfc9c386SHans Petter Selasky 
122cfc9c386SHans Petter Selasky 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
123cfc9c386SHans Petter Selasky 		switch (max_bw_unit[i]) {
124cfc9c386SHans Petter Selasky 		case MLX5_100_MBPS_UNIT:
125cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_100MB;
126cfc9c386SHans Petter Selasky 			break;
127cfc9c386SHans Petter Selasky 		case MLX5_GBPS_UNIT:
128cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_1GB;
129cfc9c386SHans Petter Selasky 			break;
130cfc9c386SHans Petter Selasky 		case MLX5_BW_NO_LIMIT:
131cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = 0;
132cfc9c386SHans Petter Selasky 			break;
133cfc9c386SHans Petter Selasky 		default:
134cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = -1;
135cfc9c386SHans Petter Selasky 			WARN_ONCE(true, "non-supported BW unit");
136cfc9c386SHans Petter Selasky 			break;
137cfc9c386SHans Petter Selasky 		}
138cfc9c386SHans Petter Selasky 	}
139cfc9c386SHans Petter Selasky done:
140cfc9c386SHans Petter Selasky 	PRIV_UNLOCK(priv);
141cfc9c386SHans Petter Selasky 	return (err);
142cfc9c386SHans Petter Selasky }
143cfc9c386SHans Petter Selasky 
144cfc9c386SHans Petter Selasky static int
mlx5e_get_max_alloc(struct mlx5e_priv * priv)145e870c0abSSlava Shwartsman mlx5e_get_max_alloc(struct mlx5e_priv *priv)
146e870c0abSSlava Shwartsman {
147e870c0abSSlava Shwartsman 	struct mlx5_core_dev *mdev = priv->mdev;
148e870c0abSSlava Shwartsman 	int err;
149e870c0abSSlava Shwartsman 	int x;
150e870c0abSSlava Shwartsman 
151e870c0abSSlava Shwartsman 	PRIV_LOCK(priv);
152e870c0abSSlava Shwartsman 	err = -mlx5_query_port_tc_bw_alloc(mdev, priv->params_ethtool.max_bw_share);
153e870c0abSSlava Shwartsman 	if (err == 0) {
154e870c0abSSlava Shwartsman 		/* set default value */
155e870c0abSSlava Shwartsman 		for (x = 0; x != IEEE_8021QAZ_MAX_TCS; x++) {
156e870c0abSSlava Shwartsman 			priv->params_ethtool.max_bw_share[x] =
157e870c0abSSlava Shwartsman 			    100 / IEEE_8021QAZ_MAX_TCS;
158e870c0abSSlava Shwartsman 		}
159e870c0abSSlava Shwartsman 		err = -mlx5_set_port_tc_bw_alloc(mdev,
160e870c0abSSlava Shwartsman 		    priv->params_ethtool.max_bw_share);
161e870c0abSSlava Shwartsman 	}
162e870c0abSSlava Shwartsman 	PRIV_UNLOCK(priv);
163e870c0abSSlava Shwartsman 
164e870c0abSSlava Shwartsman 	return (err);
165e870c0abSSlava Shwartsman }
166e870c0abSSlava Shwartsman 
167e870c0abSSlava Shwartsman static int
mlx5e_get_dscp(struct mlx5e_priv * priv)168ed0cee0bSHans Petter Selasky mlx5e_get_dscp(struct mlx5e_priv *priv)
169ed0cee0bSHans Petter Selasky {
170ed0cee0bSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
171ed0cee0bSHans Petter Selasky 	int err;
172ed0cee0bSHans Petter Selasky 
173ed0cee0bSHans Petter Selasky 	if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 ||
174ed0cee0bSHans Petter Selasky 	    MLX5_CAP_QCAM_REG(mdev, qpts) == 0 ||
175ed0cee0bSHans Petter Selasky 	    MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0)
176ed0cee0bSHans Petter Selasky 		return (EOPNOTSUPP);
177ed0cee0bSHans Petter Selasky 
178ed0cee0bSHans Petter Selasky 	PRIV_LOCK(priv);
179ed0cee0bSHans Petter Selasky 	err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio);
180ed0cee0bSHans Petter Selasky 	if (err)
181ed0cee0bSHans Petter Selasky 		goto done;
182ed0cee0bSHans Petter Selasky 
183ed0cee0bSHans Petter Selasky 	err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state);
184ed0cee0bSHans Petter Selasky 	if (err)
185ed0cee0bSHans Petter Selasky 		goto done;
186ed0cee0bSHans Petter Selasky done:
187ed0cee0bSHans Petter Selasky 	PRIV_UNLOCK(priv);
188ed0cee0bSHans Petter Selasky 	return (err);
189ed0cee0bSHans Petter Selasky }
190ed0cee0bSHans Petter Selasky 
191e870c0abSSlava Shwartsman static void
mlx5e_tc_get_parameters(struct mlx5e_priv * priv,u64 * new_bw_value,u8 * max_bw_value,u8 * max_bw_unit)192e870c0abSSlava Shwartsman mlx5e_tc_get_parameters(struct mlx5e_priv *priv,
193e870c0abSSlava Shwartsman     u64 *new_bw_value, u8 *max_bw_value, u8 *max_bw_unit)
194e870c0abSSlava Shwartsman {
195e870c0abSSlava Shwartsman 	const u64 upper_limit_mbps = 255 * MLX5E_100MB;
196e870c0abSSlava Shwartsman 	const u64 upper_limit_gbps = 255 * MLX5E_1GB;
197e870c0abSSlava Shwartsman 	u64 temp;
198e870c0abSSlava Shwartsman 	int i;
199e870c0abSSlava Shwartsman 
200e870c0abSSlava Shwartsman 	memset(max_bw_value, 0, IEEE_8021QAZ_MAX_TCS);
201e870c0abSSlava Shwartsman 	memset(max_bw_unit, 0, IEEE_8021QAZ_MAX_TCS);
202e870c0abSSlava Shwartsman 
203e870c0abSSlava Shwartsman 	for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) {
204e870c0abSSlava Shwartsman 		temp = (new_bw_value != NULL) ?
205e870c0abSSlava Shwartsman 		    new_bw_value[i] : priv->params_ethtool.max_bw_value[i];
206e870c0abSSlava Shwartsman 
207e870c0abSSlava Shwartsman 		if (!temp) {
208e870c0abSSlava Shwartsman 			max_bw_unit[i] = MLX5_BW_NO_LIMIT;
209e870c0abSSlava Shwartsman 		} else if (temp > upper_limit_gbps) {
210e870c0abSSlava Shwartsman 			max_bw_unit[i] = MLX5_BW_NO_LIMIT;
211e870c0abSSlava Shwartsman 		} else if (temp <= upper_limit_mbps) {
212e870c0abSSlava Shwartsman 			max_bw_value[i] = howmany(temp, MLX5E_100MB);
213e870c0abSSlava Shwartsman 			max_bw_unit[i]  = MLX5_100_MBPS_UNIT;
214e870c0abSSlava Shwartsman 		} else {
215e870c0abSSlava Shwartsman 			max_bw_value[i] = howmany(temp, MLX5E_1GB);
216e870c0abSSlava Shwartsman 			max_bw_unit[i]  = MLX5_GBPS_UNIT;
217e870c0abSSlava Shwartsman 		}
218e870c0abSSlava Shwartsman 	}
219e870c0abSSlava Shwartsman }
220e870c0abSSlava Shwartsman 
221ed0cee0bSHans Petter Selasky static int
mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS)222cfc9c386SHans Petter Selasky mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS)
223cfc9c386SHans Petter Selasky {
224cfc9c386SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
225cfc9c386SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
226cfc9c386SHans Petter Selasky 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
227cfc9c386SHans Petter Selasky 	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
228e870c0abSSlava Shwartsman 	u64 new_bw_value[IEEE_8021QAZ_MAX_TCS];
229e870c0abSSlava Shwartsman 	u8 max_rates = mlx5_max_tc(mdev) + 1;
230e870c0abSSlava Shwartsman 	u8 x;
231e870c0abSSlava Shwartsman 	int err;
232cfc9c386SHans Petter Selasky 
233cfc9c386SHans Petter Selasky 	PRIV_LOCK(priv);
234e870c0abSSlava Shwartsman 	err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_value,
235e870c0abSSlava Shwartsman 	    sizeof(priv->params_ethtool.max_bw_value[0]) * max_rates);
236e870c0abSSlava Shwartsman 	if (err || !req->newptr)
237e870c0abSSlava Shwartsman 		goto done;
238e870c0abSSlava Shwartsman 	err = SYSCTL_IN(req, new_bw_value,
239e870c0abSSlava Shwartsman 	    sizeof(new_bw_value[0]) * max_rates);
240e870c0abSSlava Shwartsman 	if (err)
241cfc9c386SHans Petter Selasky 		goto done;
242cfc9c386SHans Petter Selasky 
243e870c0abSSlava Shwartsman 	/* range check input value */
244e870c0abSSlava Shwartsman 	for (x = 0; x != max_rates; x++) {
245e870c0abSSlava Shwartsman 		if (new_bw_value[x] % MLX5E_100MB) {
246cfc9c386SHans Petter Selasky 			err = ERANGE;
247cfc9c386SHans Petter Selasky 			goto done;
248cfc9c386SHans Petter Selasky 		}
249cfc9c386SHans Petter Selasky 	}
250e870c0abSSlava Shwartsman 
251e870c0abSSlava Shwartsman 	mlx5e_tc_get_parameters(priv, new_bw_value, max_bw_value, max_bw_unit);
252cfc9c386SHans Petter Selasky 
253cfc9c386SHans Petter Selasky 	err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
254cfc9c386SHans Petter Selasky 	if (err)
255cfc9c386SHans Petter Selasky 		goto done;
256cfc9c386SHans Petter Selasky 
257e870c0abSSlava Shwartsman 	memcpy(priv->params_ethtool.max_bw_value, new_bw_value,
258e870c0abSSlava Shwartsman 	    sizeof(priv->params_ethtool.max_bw_value));
259e870c0abSSlava Shwartsman done:
260e870c0abSSlava Shwartsman 	PRIV_UNLOCK(priv);
261e870c0abSSlava Shwartsman 	return (err);
262e870c0abSSlava Shwartsman }
263e870c0abSSlava Shwartsman 
264e870c0abSSlava Shwartsman static int
mlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS)265e870c0abSSlava Shwartsman mlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS)
266e870c0abSSlava Shwartsman {
267e870c0abSSlava Shwartsman 	struct mlx5e_priv *priv = arg1;
268e870c0abSSlava Shwartsman 	struct mlx5_core_dev *mdev = priv->mdev;
269e870c0abSSlava Shwartsman 	u8 max_bw_share[IEEE_8021QAZ_MAX_TCS];
270e870c0abSSlava Shwartsman 	u8 max_rates = mlx5_max_tc(mdev) + 1;
271e870c0abSSlava Shwartsman 	int i;
272e870c0abSSlava Shwartsman 	int err;
273e870c0abSSlava Shwartsman 	int sum;
274e870c0abSSlava Shwartsman 
275e870c0abSSlava Shwartsman 	PRIV_LOCK(priv);
276e870c0abSSlava Shwartsman 	err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_share, max_rates);
277e870c0abSSlava Shwartsman 	if (err || !req->newptr)
278e870c0abSSlava Shwartsman 		goto done;
279e870c0abSSlava Shwartsman 	err = SYSCTL_IN(req, max_bw_share, max_rates);
280e870c0abSSlava Shwartsman 	if (err)
281e870c0abSSlava Shwartsman 		goto done;
282e870c0abSSlava Shwartsman 
283e870c0abSSlava Shwartsman 	/* range check input value */
284e870c0abSSlava Shwartsman 	for (sum = i = 0; i != max_rates; i++) {
285e870c0abSSlava Shwartsman 		if (max_bw_share[i] < 1 || max_bw_share[i] > 100) {
286e870c0abSSlava Shwartsman 			err = ERANGE;
287e870c0abSSlava Shwartsman 			goto done;
288e870c0abSSlava Shwartsman 		}
289e870c0abSSlava Shwartsman 		sum += max_bw_share[i];
290e870c0abSSlava Shwartsman 	}
291e870c0abSSlava Shwartsman 
292e870c0abSSlava Shwartsman 	/* sum of values should be as close to 100 as possible */
293e870c0abSSlava Shwartsman 	if (sum < (100 - max_rates + 1) || sum > 100) {
294e870c0abSSlava Shwartsman 		err = ERANGE;
295e870c0abSSlava Shwartsman 		goto done;
296e870c0abSSlava Shwartsman 	}
297e870c0abSSlava Shwartsman 
298e870c0abSSlava Shwartsman 	err = -mlx5_set_port_tc_bw_alloc(mdev, max_bw_share);
299e870c0abSSlava Shwartsman 	if (err)
300e870c0abSSlava Shwartsman 		goto done;
301e870c0abSSlava Shwartsman 
302e870c0abSSlava Shwartsman 	memcpy(priv->params_ethtool.max_bw_share, max_bw_share,
303e870c0abSSlava Shwartsman 	    sizeof(priv->params_ethtool.max_bw_share));
304cfc9c386SHans Petter Selasky done:
305cfc9c386SHans Petter Selasky 	PRIV_UNLOCK(priv);
306cfc9c386SHans Petter Selasky 	return (err);
307cfc9c386SHans Petter Selasky }
308cfc9c386SHans Petter Selasky 
3092e9c3a4fSHans Petter Selasky static int
mlx5e_get_prio_tc(struct mlx5e_priv * priv)3102e9c3a4fSHans Petter Selasky mlx5e_get_prio_tc(struct mlx5e_priv *priv)
3112e9c3a4fSHans Petter Selasky {
3122e9c3a4fSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
3132e9c3a4fSHans Petter Selasky 	int err = 0;
3142e9c3a4fSHans Petter Selasky 	int i;
3152e9c3a4fSHans Petter Selasky 
3162e9c3a4fSHans Petter Selasky 	PRIV_LOCK(priv);
3172e9c3a4fSHans Petter Selasky 	if (!MLX5_CAP_GEN(priv->mdev, ets)) {
3182e9c3a4fSHans Petter Selasky 		PRIV_UNLOCK(priv);
3192e9c3a4fSHans Petter Selasky 		return (EOPNOTSUPP);
3202e9c3a4fSHans Petter Selasky 	}
3212e9c3a4fSHans Petter Selasky 
32224385321SHans Petter Selasky 	for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
32324385321SHans Petter Selasky 		err = -mlx5_query_port_prio_tc(mdev, i, priv->params_ethtool.prio_tc + i);
3242e9c3a4fSHans Petter Selasky 		if (err)
3252e9c3a4fSHans Petter Selasky 			break;
3262e9c3a4fSHans Petter Selasky 	}
3272e9c3a4fSHans Petter Selasky 	PRIV_UNLOCK(priv);
3282e9c3a4fSHans Petter Selasky 	return (err);
3292e9c3a4fSHans Petter Selasky }
3302e9c3a4fSHans Petter Selasky 
3312e9c3a4fSHans Petter Selasky static int
mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS)3322e9c3a4fSHans Petter Selasky mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS)
3332e9c3a4fSHans Petter Selasky {
3342e9c3a4fSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
3352e9c3a4fSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
33624385321SHans Petter Selasky 	uint8_t temp[MLX5E_MAX_PRIORITY];
3372e9c3a4fSHans Petter Selasky 	int err;
33824385321SHans Petter Selasky 	int i;
3392e9c3a4fSHans Petter Selasky 
3402e9c3a4fSHans Petter Selasky 	PRIV_LOCK(priv);
34124385321SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.prio_tc, MLX5E_MAX_PRIORITY);
34224385321SHans Petter Selasky 	if (err || !req->newptr)
3432e9c3a4fSHans Petter Selasky 		goto done;
34424385321SHans Petter Selasky 	err = SYSCTL_IN(req, temp, MLX5E_MAX_PRIORITY);
3452e9c3a4fSHans Petter Selasky 	if (err)
3462e9c3a4fSHans Petter Selasky 		goto done;
3472e9c3a4fSHans Petter Selasky 
34824385321SHans Petter Selasky 	for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
34924385321SHans Petter Selasky 		if (temp[i] > mlx5_max_tc(mdev)) {
35024385321SHans Petter Selasky 			err = ERANGE;
35124385321SHans Petter Selasky 			goto done;
35224385321SHans Petter Selasky 		}
35324385321SHans Petter Selasky 	}
3542e9c3a4fSHans Petter Selasky 
35524385321SHans Petter Selasky 	for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
35624385321SHans Petter Selasky 		if (temp[i] == priv->params_ethtool.prio_tc[i])
35724385321SHans Petter Selasky 			continue;
35824385321SHans Petter Selasky 		err = -mlx5_set_port_prio_tc(mdev, i, temp[i]);
35924385321SHans Petter Selasky 		if (err)
36024385321SHans Petter Selasky 			goto done;
36124385321SHans Petter Selasky 		/* update cached value */
36224385321SHans Petter Selasky 		priv->params_ethtool.prio_tc[i] = temp[i];
36324385321SHans Petter Selasky 	}
3642e9c3a4fSHans Petter Selasky done:
3652e9c3a4fSHans Petter Selasky 	PRIV_UNLOCK(priv);
3662e9c3a4fSHans Petter Selasky 	return (err);
3672e9c3a4fSHans Petter Selasky }
3682e9c3a4fSHans Petter Selasky 
36996425f44SHans Petter Selasky int
mlx5e_fec_update(struct mlx5e_priv * priv)37096425f44SHans Petter Selasky mlx5e_fec_update(struct mlx5e_priv *priv)
37196425f44SHans Petter Selasky {
37296425f44SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
37396425f44SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
37496425f44SHans Petter Selasky 	const int sz = MLX5_ST_SZ_BYTES(pplm_reg);
37596425f44SHans Petter Selasky 	int err;
37696425f44SHans Petter Selasky 
37796425f44SHans Petter Selasky 	if (!MLX5_CAP_GEN(mdev, pcam_reg))
37896425f44SHans Petter Selasky 		return (EOPNOTSUPP);
37996425f44SHans Petter Selasky 
38096425f44SHans Petter Selasky 	if (!MLX5_CAP_PCAM_REG(mdev, pplm))
38196425f44SHans Petter Selasky 		return (EOPNOTSUPP);
38296425f44SHans Petter Selasky 
38396425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
38496425f44SHans Petter Selasky 
38596425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0);
38696425f44SHans Petter Selasky 	if (err)
38796425f44SHans Petter Selasky 		return (err);
38896425f44SHans Petter Selasky 
38996425f44SHans Petter Selasky 	/* get 10x..25x mask */
39096425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_10x_25x[0] =
39196425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_10g_40g);
39296425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_10x_25x[1] =
39396425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_25g) &
39496425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_50g);
39596425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_10x_25x[2] =
39696425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_56g);
39796425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_10x_25x[3] =
39896425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_100g);
39996425f44SHans Petter Selasky 
40096425f44SHans Petter Selasky 	/* get 10x..25x available bits */
40196425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_10x_25x[0] =
40296425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_10g_40g);
40396425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_10x_25x[1] =
40496425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_25g) &
40596425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_50g);
40696425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_10x_25x[2] =
40796425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_56g);
40896425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_10x_25x[3] =
40996425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_100g);
41096425f44SHans Petter Selasky 
41196425f44SHans Petter Selasky 	/* get 50x mask */
41296425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_50x[0] =
41396425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_50g_1x);
41496425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_50x[1] =
41596425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_100g_2x);
41696425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_50x[2] =
41796425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_200g_4x);
41896425f44SHans Petter Selasky 	priv->params_ethtool.fec_mask_50x[3] =
41996425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_admin_400g_8x);
42096425f44SHans Petter Selasky 
42196425f44SHans Petter Selasky 	/* get 50x available bits */
42296425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_50x[0] =
42396425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_50g_1x);
42496425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_50x[1] =
42596425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_100g_2x);
42696425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_50x[2] =
42796425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_200g_4x);
42896425f44SHans Petter Selasky 	priv->params_ethtool.fec_avail_50x[3] =
42996425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_override_cap_400g_8x);
43096425f44SHans Petter Selasky 
43196425f44SHans Petter Selasky 	/* get current FEC mask */
43296425f44SHans Petter Selasky 	priv->params_ethtool.fec_mode_active =
43396425f44SHans Petter Selasky 	    MLX5_GET(pplm_reg, in, fec_mode_active);
43496425f44SHans Petter Selasky 
43596425f44SHans Petter Selasky 	return (0);
43696425f44SHans Petter Selasky }
43796425f44SHans Petter Selasky 
43896425f44SHans Petter Selasky static int
mlx5e_fec_mask_10x_25x_handler(SYSCTL_HANDLER_ARGS)43996425f44SHans Petter Selasky mlx5e_fec_mask_10x_25x_handler(SYSCTL_HANDLER_ARGS)
44096425f44SHans Petter Selasky {
44196425f44SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
44296425f44SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
44396425f44SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
44496425f44SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
44596425f44SHans Petter Selasky 	const int sz = MLX5_ST_SZ_BYTES(pplm_reg);
44696425f44SHans Petter Selasky 	u8 fec_mask_10x_25x[MLX5E_MAX_FEC_10X_25X];
44796425f44SHans Petter Selasky 	u8 fec_cap_changed = 0;
44896425f44SHans Petter Selasky 	u8 x;
44996425f44SHans Petter Selasky 	int err;
45096425f44SHans Petter Selasky 
45196425f44SHans Petter Selasky 	PRIV_LOCK(priv);
45296425f44SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_10x_25x,
45396425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_mask_10x_25x));
45496425f44SHans Petter Selasky 	if (err || !req->newptr)
45596425f44SHans Petter Selasky 		goto done;
45696425f44SHans Petter Selasky 
45796425f44SHans Petter Selasky 	err = SYSCTL_IN(req, fec_mask_10x_25x,
45896425f44SHans Petter Selasky 	    sizeof(fec_mask_10x_25x));
45996425f44SHans Petter Selasky 	if (err)
46096425f44SHans Petter Selasky 		goto done;
46196425f44SHans Petter Selasky 
46296425f44SHans Petter Selasky 	if (!MLX5_CAP_GEN(mdev, pcam_reg)) {
46396425f44SHans Petter Selasky 		err = EOPNOTSUPP;
46496425f44SHans Petter Selasky 		goto done;
46596425f44SHans Petter Selasky 	}
46696425f44SHans Petter Selasky 
46796425f44SHans Petter Selasky 	if (!MLX5_CAP_PCAM_REG(mdev, pplm)) {
46896425f44SHans Petter Selasky 		err = EOPNOTSUPP;
46996425f44SHans Petter Selasky 		goto done;
47096425f44SHans Petter Selasky 	}
47196425f44SHans Petter Selasky 
47296425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
47396425f44SHans Petter Selasky 
47496425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0);
47596425f44SHans Petter Selasky 	if (err)
47696425f44SHans Petter Selasky 		goto done;
47796425f44SHans Petter Selasky 
47896425f44SHans Petter Selasky 	/* range check input value */
47996425f44SHans Petter Selasky 	for (x = 0; x != MLX5E_MAX_FEC_10X_25X; x++) {
48096425f44SHans Petter Selasky 		/* check only one bit is set, if any */
48196425f44SHans Petter Selasky 		if (fec_mask_10x_25x[x] & (fec_mask_10x_25x[x] - 1)) {
48296425f44SHans Petter Selasky 			err = ERANGE;
48396425f44SHans Petter Selasky 			goto done;
48496425f44SHans Petter Selasky 		}
48596425f44SHans Petter Selasky 		/* check a supported bit is set, if any */
48696425f44SHans Petter Selasky 		if (fec_mask_10x_25x[x] &
48796425f44SHans Petter Selasky 		    ~priv->params_ethtool.fec_avail_10x_25x[x]) {
48896425f44SHans Petter Selasky 			err = ERANGE;
48996425f44SHans Petter Selasky 			goto done;
49096425f44SHans Petter Selasky 		}
49196425f44SHans Petter Selasky 		fec_cap_changed |= (fec_mask_10x_25x[x] ^
49296425f44SHans Petter Selasky 		    priv->params_ethtool.fec_mask_10x_25x[x]);
49396425f44SHans Petter Selasky 	}
49496425f44SHans Petter Selasky 
49596425f44SHans Petter Selasky 	/* check for no changes */
49696425f44SHans Petter Selasky 	if (fec_cap_changed == 0)
49796425f44SHans Petter Selasky 		goto done;
49896425f44SHans Petter Selasky 
49996425f44SHans Petter Selasky 	memset(in, 0, sizeof(in));
50096425f44SHans Petter Selasky 
50196425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
50296425f44SHans Petter Selasky 
50396425f44SHans Petter Selasky 	/* set new values */
50496425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, fec_mask_10x_25x[0]);
50596425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_25g, fec_mask_10x_25x[1]);
50696425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_50g, fec_mask_10x_25x[1]);
50796425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_56g, fec_mask_10x_25x[2]);
50896425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_100g, fec_mask_10x_25x[3]);
50996425f44SHans Petter Selasky 
51096425f44SHans Petter Selasky 	/* preserve other values */
51196425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, priv->params_ethtool.fec_mask_50x[0]);
51296425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, priv->params_ethtool.fec_mask_50x[1]);
51396425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, priv->params_ethtool.fec_mask_50x[2]);
51496425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, priv->params_ethtool.fec_mask_50x[3]);
51596425f44SHans Petter Selasky 
51696425f44SHans Petter Selasky 	/* send new value to the firmware */
51796425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1);
51896425f44SHans Petter Selasky 	if (err)
51996425f44SHans Petter Selasky 		goto done;
52096425f44SHans Petter Selasky 
52196425f44SHans Petter Selasky 	memcpy(priv->params_ethtool.fec_mask_10x_25x, fec_mask_10x_25x,
52296425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_mask_10x_25x));
52396425f44SHans Petter Selasky 
52496425f44SHans Petter Selasky 	mlx5_toggle_port_link(priv->mdev);
52596425f44SHans Petter Selasky done:
52696425f44SHans Petter Selasky 	PRIV_UNLOCK(priv);
52796425f44SHans Petter Selasky 	return (err);
52896425f44SHans Petter Selasky }
52996425f44SHans Petter Selasky 
53096425f44SHans Petter Selasky static int
mlx5e_fec_avail_10x_25x_handler(SYSCTL_HANDLER_ARGS)53196425f44SHans Petter Selasky mlx5e_fec_avail_10x_25x_handler(SYSCTL_HANDLER_ARGS)
53296425f44SHans Petter Selasky {
53396425f44SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
53496425f44SHans Petter Selasky 	int err;
53596425f44SHans Petter Selasky 
53696425f44SHans Petter Selasky 	PRIV_LOCK(priv);
53796425f44SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_10x_25x,
53896425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_avail_10x_25x));
53996425f44SHans Petter Selasky 	PRIV_UNLOCK(priv);
54096425f44SHans Petter Selasky 	return (err);
54196425f44SHans Petter Selasky }
54296425f44SHans Petter Selasky 
54396425f44SHans Petter Selasky static int
mlx5e_fec_mask_50x_handler(SYSCTL_HANDLER_ARGS)54496425f44SHans Petter Selasky mlx5e_fec_mask_50x_handler(SYSCTL_HANDLER_ARGS)
54596425f44SHans Petter Selasky {
54696425f44SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
54796425f44SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
54896425f44SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
54996425f44SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
55096425f44SHans Petter Selasky 	const int sz = MLX5_ST_SZ_BYTES(pplm_reg);
55196425f44SHans Petter Selasky 	u16 fec_mask_50x[MLX5E_MAX_FEC_50X];
55296425f44SHans Petter Selasky 	u16 fec_cap_changed = 0;
55396425f44SHans Petter Selasky 	u8 x;
55496425f44SHans Petter Selasky 	int err;
55596425f44SHans Petter Selasky 
55696425f44SHans Petter Selasky 	PRIV_LOCK(priv);
55796425f44SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_50x,
55896425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_mask_50x));
55996425f44SHans Petter Selasky 	if (err || !req->newptr)
56096425f44SHans Petter Selasky 		goto done;
56196425f44SHans Petter Selasky 
56296425f44SHans Petter Selasky 	err = SYSCTL_IN(req, fec_mask_50x,
56396425f44SHans Petter Selasky 	    sizeof(fec_mask_50x));
56496425f44SHans Petter Selasky 	if (err)
56596425f44SHans Petter Selasky 		goto done;
56696425f44SHans Petter Selasky 
56796425f44SHans Petter Selasky 	if (!MLX5_CAP_GEN(mdev, pcam_reg)) {
56896425f44SHans Petter Selasky 		err = EOPNOTSUPP;
56996425f44SHans Petter Selasky 		goto done;
57096425f44SHans Petter Selasky 	}
57196425f44SHans Petter Selasky 
57296425f44SHans Petter Selasky 	if (!MLX5_CAP_PCAM_REG(mdev, pplm)) {
57396425f44SHans Petter Selasky 		err = EOPNOTSUPP;
57496425f44SHans Petter Selasky 		goto done;
57596425f44SHans Petter Selasky 	}
57696425f44SHans Petter Selasky 
57796425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
57896425f44SHans Petter Selasky 
57996425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0);
58096425f44SHans Petter Selasky 	if (err)
58196425f44SHans Petter Selasky 		goto done;
58296425f44SHans Petter Selasky 
58396425f44SHans Petter Selasky 	/* range check input value */
58496425f44SHans Petter Selasky 	for (x = 0; x != MLX5E_MAX_FEC_50X; x++) {
58596425f44SHans Petter Selasky 		/* check only one bit is set, if any */
58696425f44SHans Petter Selasky 		if (fec_mask_50x[x] & (fec_mask_50x[x] - 1)) {
58796425f44SHans Petter Selasky 			err = ERANGE;
58896425f44SHans Petter Selasky 			goto done;
58996425f44SHans Petter Selasky 		}
59096425f44SHans Petter Selasky 		/* check a supported bit is set, if any */
59196425f44SHans Petter Selasky 		if (fec_mask_50x[x] &
59296425f44SHans Petter Selasky 		    ~priv->params_ethtool.fec_avail_50x[x]) {
59396425f44SHans Petter Selasky 			err = ERANGE;
59496425f44SHans Petter Selasky 			goto done;
59596425f44SHans Petter Selasky 		}
59696425f44SHans Petter Selasky 		fec_cap_changed |= (fec_mask_50x[x] ^
59796425f44SHans Petter Selasky 		    priv->params_ethtool.fec_mask_50x[x]);
59896425f44SHans Petter Selasky 	}
59996425f44SHans Petter Selasky 
60096425f44SHans Petter Selasky 	/* check for no changes */
60196425f44SHans Petter Selasky 	if (fec_cap_changed == 0)
60296425f44SHans Petter Selasky 		goto done;
60396425f44SHans Petter Selasky 
60496425f44SHans Petter Selasky 	memset(in, 0, sizeof(in));
60596425f44SHans Petter Selasky 
60696425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, local_port, 1);
60796425f44SHans Petter Selasky 
60896425f44SHans Petter Selasky 	/* set new values */
60996425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, fec_mask_50x[0]);
61096425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, fec_mask_50x[1]);
61196425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, fec_mask_50x[2]);
61296425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, fec_mask_50x[3]);
61396425f44SHans Petter Selasky 
61496425f44SHans Petter Selasky 	/* preserve other values */
61596425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, priv->params_ethtool.fec_mask_10x_25x[0]);
61696425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_25g, priv->params_ethtool.fec_mask_10x_25x[1]);
61796425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_50g, priv->params_ethtool.fec_mask_10x_25x[1]);
61896425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_56g, priv->params_ethtool.fec_mask_10x_25x[2]);
61996425f44SHans Petter Selasky 	MLX5_SET(pplm_reg, in, fec_override_admin_100g, priv->params_ethtool.fec_mask_10x_25x[3]);
62096425f44SHans Petter Selasky 
62196425f44SHans Petter Selasky 	/* send new value to the firmware */
62296425f44SHans Petter Selasky 	err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1);
62396425f44SHans Petter Selasky 	if (err)
62496425f44SHans Petter Selasky 		goto done;
62596425f44SHans Petter Selasky 
62696425f44SHans Petter Selasky 	memcpy(priv->params_ethtool.fec_mask_50x, fec_mask_50x,
62796425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_mask_50x));
62896425f44SHans Petter Selasky 
62996425f44SHans Petter Selasky 	mlx5_toggle_port_link(priv->mdev);
63096425f44SHans Petter Selasky done:
63196425f44SHans Petter Selasky 	PRIV_UNLOCK(priv);
63296425f44SHans Petter Selasky 	return (err);
63396425f44SHans Petter Selasky }
63496425f44SHans Petter Selasky 
63596425f44SHans Petter Selasky static int
mlx5e_fec_avail_50x_handler(SYSCTL_HANDLER_ARGS)63696425f44SHans Petter Selasky mlx5e_fec_avail_50x_handler(SYSCTL_HANDLER_ARGS)
63796425f44SHans Petter Selasky {
63896425f44SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
63996425f44SHans Petter Selasky 	int err;
64096425f44SHans Petter Selasky 
64196425f44SHans Petter Selasky 	PRIV_LOCK(priv);
64296425f44SHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_50x,
64396425f44SHans Petter Selasky 	    sizeof(priv->params_ethtool.fec_avail_50x));
64496425f44SHans Petter Selasky 	PRIV_UNLOCK(priv);
64596425f44SHans Petter Selasky 	return (err);
64696425f44SHans Petter Selasky }
64796425f44SHans Petter Selasky 
648ed0cee0bSHans Petter Selasky static int
mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS)649ed0cee0bSHans Petter Selasky mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS)
650ed0cee0bSHans Petter Selasky {
651ed0cee0bSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
652ed0cee0bSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
653ed0cee0bSHans Petter Selasky 	int err;
654ed0cee0bSHans Petter Selasky 	u8 result;
655ed0cee0bSHans Petter Selasky 
656ed0cee0bSHans Petter Selasky 	PRIV_LOCK(priv);
657ed0cee0bSHans Petter Selasky 	result = priv->params_ethtool.trust_state;
658ed0cee0bSHans Petter Selasky 	err = sysctl_handle_8(oidp, &result, 0, req);
659ed0cee0bSHans Petter Selasky 	if (err || !req->newptr ||
660ed0cee0bSHans Petter Selasky 	    result == priv->params_ethtool.trust_state)
661ed0cee0bSHans Petter Selasky 		goto done;
662ed0cee0bSHans Petter Selasky 
663ed0cee0bSHans Petter Selasky 	switch (result) {
664ed0cee0bSHans Petter Selasky 	case MLX5_QPTS_TRUST_PCP:
665ed0cee0bSHans Petter Selasky 	case MLX5_QPTS_TRUST_DSCP:
666ed0cee0bSHans Petter Selasky 		break;
667ed0cee0bSHans Petter Selasky 	case MLX5_QPTS_TRUST_BOTH:
668ed0cee0bSHans Petter Selasky 		if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) {
669ed0cee0bSHans Petter Selasky 			err = EOPNOTSUPP;
670ed0cee0bSHans Petter Selasky 			goto done;
671ed0cee0bSHans Petter Selasky 		}
672ed0cee0bSHans Petter Selasky 		break;
673ed0cee0bSHans Petter Selasky 	default:
674ed0cee0bSHans Petter Selasky 		err = ERANGE;
675ed0cee0bSHans Petter Selasky 		goto done;
676ed0cee0bSHans Petter Selasky 	}
677ed0cee0bSHans Petter Selasky 
678ed0cee0bSHans Petter Selasky 	err = -mlx5_set_trust_state(mdev, result);
679ed0cee0bSHans Petter Selasky 	if (err)
680ed0cee0bSHans Petter Selasky 		goto done;
681ed0cee0bSHans Petter Selasky 
682ed0cee0bSHans Petter Selasky 	priv->params_ethtool.trust_state = result;
6833e581cabSSlava Shwartsman 
6843e581cabSSlava Shwartsman 	/* update inline mode */
6853e581cabSSlava Shwartsman 	mlx5e_refresh_sq_inline(priv);
6863e581cabSSlava Shwartsman #ifdef RATELIMIT
6873e581cabSSlava Shwartsman 	mlx5e_rl_refresh_sq_inline(&priv->rl);
6883e581cabSSlava Shwartsman #endif
689ed0cee0bSHans Petter Selasky done:
690ed0cee0bSHans Petter Selasky 	PRIV_UNLOCK(priv);
691ed0cee0bSHans Petter Selasky 	return (err);
692ed0cee0bSHans Petter Selasky }
693ed0cee0bSHans Petter Selasky 
694ed0cee0bSHans Petter Selasky static int
mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS)695ed0cee0bSHans Petter Selasky mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS)
696ed0cee0bSHans Petter Selasky {
697ed0cee0bSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
698ed0cee0bSHans Petter Selasky 	int prio_index = arg2;
699ed0cee0bSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
700ed0cee0bSHans Petter Selasky 	uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP];
701ed0cee0bSHans Petter Selasky 	uint8_t x;
702ed0cee0bSHans Petter Selasky 	int err;
703ed0cee0bSHans Petter Selasky 
704ed0cee0bSHans Petter Selasky 	PRIV_LOCK(priv);
705ed0cee0bSHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index,
706ed0cee0bSHans Petter Selasky 	    sizeof(priv->params_ethtool.dscp2prio) / 8);
707ed0cee0bSHans Petter Selasky 	if (err || !req->newptr)
708ed0cee0bSHans Petter Selasky 		goto done;
709ed0cee0bSHans Petter Selasky 
710ed0cee0bSHans Petter Selasky 	memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio));
711ed0cee0bSHans Petter Selasky 	err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8);
712ed0cee0bSHans Petter Selasky 	if (err)
713ed0cee0bSHans Petter Selasky 		goto done;
714ed0cee0bSHans Petter Selasky 	for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) {
715ed0cee0bSHans Petter Selasky 		if (dscp2prio[x] > 7) {
716ed0cee0bSHans Petter Selasky 			err = ERANGE;
717ed0cee0bSHans Petter Selasky 			goto done;
718ed0cee0bSHans Petter Selasky 		}
719ed0cee0bSHans Petter Selasky 	}
720ed0cee0bSHans Petter Selasky 	err = -mlx5_set_dscp2prio(mdev, dscp2prio);
721ed0cee0bSHans Petter Selasky 	if (err)
722ed0cee0bSHans Petter Selasky 		goto done;
723ed0cee0bSHans Petter Selasky 
724ed0cee0bSHans Petter Selasky 	/* update local array */
725ed0cee0bSHans Petter Selasky 	memcpy(priv->params_ethtool.dscp2prio, dscp2prio,
726ed0cee0bSHans Petter Selasky 	    sizeof(priv->params_ethtool.dscp2prio));
727ed0cee0bSHans Petter Selasky done:
728ed0cee0bSHans Petter Selasky 	PRIV_UNLOCK(priv);
729ed0cee0bSHans Petter Selasky 	return (err);
730ed0cee0bSHans Petter Selasky }
731ed0cee0bSHans Petter Selasky 
7326deb0b1eSHans Petter Selasky int
mlx5e_update_buf_lossy(struct mlx5e_priv * priv)7336deb0b1eSHans Petter Selasky mlx5e_update_buf_lossy(struct mlx5e_priv *priv)
7346deb0b1eSHans Petter Selasky {
7356deb0b1eSHans Petter Selasky 	struct ieee_pfc pfc;
7366deb0b1eSHans Petter Selasky 
7376deb0b1eSHans Petter Selasky 	PRIV_ASSERT_LOCKED(priv);
7386deb0b1eSHans Petter Selasky 	bzero(&pfc, sizeof(pfc));
7396deb0b1eSHans Petter Selasky 	pfc.pfc_en = priv->params.rx_priority_flow_control;
7406deb0b1eSHans Petter Selasky 	return (-mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_PFC,
7416deb0b1eSHans Petter Selasky 	    priv->params_ethtool.hw_mtu, &pfc, NULL, NULL));
7426deb0b1eSHans Petter Selasky }
7436deb0b1eSHans Petter Selasky 
7446deb0b1eSHans Petter Selasky static int
mlx5e_buf_size_handler(SYSCTL_HANDLER_ARGS)7456deb0b1eSHans Petter Selasky mlx5e_buf_size_handler(SYSCTL_HANDLER_ARGS)
7466deb0b1eSHans Petter Selasky {
7476deb0b1eSHans Petter Selasky 	struct mlx5e_priv *priv;
7486deb0b1eSHans Petter Selasky 	u32 buf_size[MLX5E_MAX_BUFFER];
7496deb0b1eSHans Petter Selasky 	struct mlx5e_port_buffer port_buffer;
7506deb0b1eSHans Petter Selasky 	int error, i;
7516deb0b1eSHans Petter Selasky 
7526deb0b1eSHans Petter Selasky 	priv = arg1;
7536deb0b1eSHans Petter Selasky 	PRIV_LOCK(priv);
7546deb0b1eSHans Petter Selasky 	error = -mlx5e_port_query_buffer(priv, &port_buffer);
7556deb0b1eSHans Petter Selasky 	if (error != 0)
7566deb0b1eSHans Petter Selasky 		goto done;
7576deb0b1eSHans Petter Selasky 	for (i = 0; i < nitems(buf_size); i++)
7586deb0b1eSHans Petter Selasky 		buf_size[i] = port_buffer.buffer[i].size;
7596deb0b1eSHans Petter Selasky 	error = SYSCTL_OUT(req, buf_size, sizeof(buf_size));
7606deb0b1eSHans Petter Selasky 	if (error != 0 || req->newptr == NULL)
7616deb0b1eSHans Petter Selasky 		goto done;
7626deb0b1eSHans Petter Selasky 	error = SYSCTL_IN(req, buf_size, sizeof(buf_size));
7636deb0b1eSHans Petter Selasky 	if (error != 0)
7646deb0b1eSHans Petter Selasky 		goto done;
7656deb0b1eSHans Petter Selasky 	error = -mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_SIZE,
7666deb0b1eSHans Petter Selasky 	    priv->params_ethtool.hw_mtu, NULL, buf_size, NULL);
7676deb0b1eSHans Petter Selasky done:
7686deb0b1eSHans Petter Selasky 	PRIV_UNLOCK(priv);
7696deb0b1eSHans Petter Selasky 	return (error);
7706deb0b1eSHans Petter Selasky }
7716deb0b1eSHans Petter Selasky 
7726deb0b1eSHans Petter Selasky static int
mlx5e_buf_prio_handler(SYSCTL_HANDLER_ARGS)7736deb0b1eSHans Petter Selasky mlx5e_buf_prio_handler(SYSCTL_HANDLER_ARGS)
7746deb0b1eSHans Petter Selasky {
7756deb0b1eSHans Petter Selasky 	struct mlx5e_priv *priv;
7766deb0b1eSHans Petter Selasky 	struct mlx5_core_dev *mdev;
7776deb0b1eSHans Petter Selasky 	u8 buffer[MLX5E_MAX_BUFFER];
7786deb0b1eSHans Petter Selasky 	int error;
7796deb0b1eSHans Petter Selasky 
7806deb0b1eSHans Petter Selasky 	priv = arg1;
7816deb0b1eSHans Petter Selasky 	mdev = priv->mdev;
7826deb0b1eSHans Petter Selasky 	PRIV_LOCK(priv);
7836deb0b1eSHans Petter Selasky 	error = -mlx5e_port_query_priority2buffer(mdev, buffer);
7846deb0b1eSHans Petter Selasky 	if (error != 0)
7856deb0b1eSHans Petter Selasky 		goto done;
7866deb0b1eSHans Petter Selasky 	error = SYSCTL_OUT(req, buffer, MLX5E_MAX_BUFFER);
7876deb0b1eSHans Petter Selasky 	if (error != 0 || req->newptr == NULL)
7886deb0b1eSHans Petter Selasky 		goto done;
7896deb0b1eSHans Petter Selasky 	error = SYSCTL_IN(req, buffer, MLX5E_MAX_BUFFER);
7906deb0b1eSHans Petter Selasky 	if (error != 0)
7916deb0b1eSHans Petter Selasky 		goto done;
7926deb0b1eSHans Petter Selasky 	error = -mlx5e_port_manual_buffer_config(priv,
7936deb0b1eSHans Petter Selasky 	    MLX5E_PORT_BUFFER_PRIO2BUFFER,
7946deb0b1eSHans Petter Selasky 	    priv->params_ethtool.hw_mtu, NULL, NULL, buffer);
7956deb0b1eSHans Petter Selasky 	if (error == 0)
7966deb0b1eSHans Petter Selasky 		error = mlx5e_update_buf_lossy(priv);
7976deb0b1eSHans Petter Selasky done:
7986deb0b1eSHans Petter Selasky 	PRIV_UNLOCK(priv);
7996deb0b1eSHans Petter Selasky 	return (error);
8006deb0b1eSHans Petter Selasky }
8016deb0b1eSHans Petter Selasky 
8026deb0b1eSHans Petter Selasky static int
mlx5e_cable_length_handler(SYSCTL_HANDLER_ARGS)8036deb0b1eSHans Petter Selasky mlx5e_cable_length_handler(SYSCTL_HANDLER_ARGS)
8046deb0b1eSHans Petter Selasky {
8056deb0b1eSHans Petter Selasky 	struct mlx5e_priv *priv;
8066deb0b1eSHans Petter Selasky 	u_int cable_len;
8076deb0b1eSHans Petter Selasky 	int error;
8086deb0b1eSHans Petter Selasky 
8096deb0b1eSHans Petter Selasky 	priv = arg1;
8106deb0b1eSHans Petter Selasky 	PRIV_LOCK(priv);
8116deb0b1eSHans Petter Selasky 	cable_len = priv->dcbx.cable_len;
8126deb0b1eSHans Petter Selasky 	error = sysctl_handle_int(oidp, &cable_len, 0, req);
8136deb0b1eSHans Petter Selasky 	if (error == 0 && req->newptr != NULL &&
8146deb0b1eSHans Petter Selasky 	    cable_len != priv->dcbx.cable_len) {
8156deb0b1eSHans Petter Selasky 		error = -mlx5e_port_manual_buffer_config(priv,
8166deb0b1eSHans Petter Selasky 		    MLX5E_PORT_BUFFER_CABLE_LEN, priv->params_ethtool.hw_mtu,
8176deb0b1eSHans Petter Selasky 		    NULL, NULL, NULL);
8186deb0b1eSHans Petter Selasky 		if (error == 0)
8196deb0b1eSHans Petter Selasky 			priv->dcbx.cable_len = cable_len;
8206deb0b1eSHans Petter Selasky 	}
8216deb0b1eSHans Petter Selasky 	PRIV_UNLOCK(priv);
8226deb0b1eSHans Petter Selasky 	return (error);
8236deb0b1eSHans Petter Selasky }
8246deb0b1eSHans Petter Selasky 
825decb087cSHans Petter Selasky static int
mlx5e_hw_temperature_handler(SYSCTL_HANDLER_ARGS)826decb087cSHans Petter Selasky mlx5e_hw_temperature_handler(SYSCTL_HANDLER_ARGS)
827decb087cSHans Petter Selasky {
828decb087cSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
829decb087cSHans Petter Selasky 	int err;
830decb087cSHans Petter Selasky 
831decb087cSHans Petter Selasky 	PRIV_LOCK(priv);
832decb087cSHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.hw_val_temp,
833decb087cSHans Petter Selasky 	    sizeof(priv->params_ethtool.hw_val_temp[0]) *
834decb087cSHans Petter Selasky 	    priv->params_ethtool.hw_num_temp);
835decb087cSHans Petter Selasky 	if (err == 0 && req->newptr != NULL)
836decb087cSHans Petter Selasky 		err = EOPNOTSUPP;
837decb087cSHans Petter Selasky 	PRIV_UNLOCK(priv);
838decb087cSHans Petter Selasky 	return (err);
839decb087cSHans Petter Selasky }
840decb087cSHans Petter Selasky 
841decb087cSHans Petter Selasky int
mlx5e_hw_temperature_update(struct mlx5e_priv * priv)842decb087cSHans Petter Selasky mlx5e_hw_temperature_update(struct mlx5e_priv *priv)
843decb087cSHans Petter Selasky {
844decb087cSHans Petter Selasky 	int err;
845decb087cSHans Petter Selasky 	u32 x;
846decb087cSHans Petter Selasky 
847decb087cSHans Petter Selasky 	if (priv->params_ethtool.hw_num_temp == 0) {
848decb087cSHans Petter Selasky 		u32 out_cap[MLX5_ST_SZ_DW(mtcap)] = {};
849decb087cSHans Petter Selasky 		const int sz_cap = MLX5_ST_SZ_BYTES(mtcap);
850decb087cSHans Petter Selasky 		u32 value;
851decb087cSHans Petter Selasky 
852decb087cSHans Petter Selasky 		err = -mlx5_core_access_reg(priv->mdev, NULL, 0, out_cap, sz_cap,
853decb087cSHans Petter Selasky 		    MLX5_ACCESS_REG_SUMMARY_CTRL_ID_MTCAP, 0, 0);
854decb087cSHans Petter Selasky 		if (err)
855decb087cSHans Petter Selasky 			goto done;
856decb087cSHans Petter Selasky 		value = MLX5_GET(mtcap, out_cap, sensor_count);
857decb087cSHans Petter Selasky 		if (value == 0)
858decb087cSHans Petter Selasky 			return (0);
859decb087cSHans Petter Selasky 		if (value > MLX5_MAX_TEMPERATURE)
860decb087cSHans Petter Selasky 			value = MLX5_MAX_TEMPERATURE;
861decb087cSHans Petter Selasky 		/* update number of temperature sensors */
862decb087cSHans Petter Selasky 		priv->params_ethtool.hw_num_temp = value;
863decb087cSHans Petter Selasky 	}
864decb087cSHans Petter Selasky 
865decb087cSHans Petter Selasky 	for (x = 0; x != priv->params_ethtool.hw_num_temp; x++) {
866decb087cSHans Petter Selasky 		u32 out_sensor[MLX5_ST_SZ_DW(mtmp_reg)] = {};
867decb087cSHans Petter Selasky 		const int sz_sensor = MLX5_ST_SZ_BYTES(mtmp_reg);
868decb087cSHans Petter Selasky 
869decb087cSHans Petter Selasky 		MLX5_SET(mtmp_reg, out_sensor, sensor_index, x);
870decb087cSHans Petter Selasky 
871decb087cSHans Petter Selasky 		err = -mlx5_core_access_reg(priv->mdev, out_sensor, sz_sensor,
872decb087cSHans Petter Selasky 		    out_sensor, sz_sensor,
873decb087cSHans Petter Selasky 		    MLX5_ACCESS_REG_SUMMARY_CTRL_ID_MTMP, 0, 0);
874decb087cSHans Petter Selasky 		if (err)
875decb087cSHans Petter Selasky 			goto done;
8769097ac9aSElyes HAOUAS 		/* convert from 0.125 celsius to millicelsius */
877decb087cSHans Petter Selasky 		priv->params_ethtool.hw_val_temp[x] =
878decb087cSHans Petter Selasky 		    (s16)MLX5_GET(mtmp_reg, out_sensor, temperature) * 125;
879decb087cSHans Petter Selasky 	}
880decb087cSHans Petter Selasky done:
881decb087cSHans Petter Selasky 	return (err);
882decb087cSHans Petter Selasky }
883decb087cSHans Petter Selasky 
88482d2623eSHans Petter Selasky #define	MLX5_PARAM_OFFSET(n)				\
88582d2623eSHans Petter Selasky     __offsetof(struct mlx5e_priv, params_ethtool.n)
88682d2623eSHans Petter Selasky 
887dc7e38acSHans Petter Selasky static int
mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)888dc7e38acSHans Petter Selasky mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)
889dc7e38acSHans Petter Selasky {
890dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
891dc7e38acSHans Petter Selasky 	uint64_t value;
892d2bf00a9SHans Petter Selasky 	int mode_modify;
893dc7e38acSHans Petter Selasky 	int was_opened;
894dc7e38acSHans Petter Selasky 	int error;
895dc7e38acSHans Petter Selasky 
896dc7e38acSHans Petter Selasky 	PRIV_LOCK(priv);
897dc7e38acSHans Petter Selasky 	value = priv->params_ethtool.arg[arg2];
898ec0143b2SHans Petter Selasky 	if (req != NULL) {
899dc7e38acSHans Petter Selasky 		error = sysctl_handle_64(oidp, &value, 0, req);
900dc7e38acSHans Petter Selasky 		if (error || req->newptr == NULL ||
901dc7e38acSHans Petter Selasky 		    value == priv->params_ethtool.arg[arg2])
902dc7e38acSHans Petter Selasky 			goto done;
903dc7e38acSHans Petter Selasky 
904dc7e38acSHans Petter Selasky 		/* assign new value */
905dc7e38acSHans Petter Selasky 		priv->params_ethtool.arg[arg2] = value;
906ec0143b2SHans Petter Selasky 	} else {
907ec0143b2SHans Petter Selasky 		error = 0;
908ec0143b2SHans Petter Selasky 	}
909dc7e38acSHans Petter Selasky 	/* check if device is gone */
910dc7e38acSHans Petter Selasky 	if (priv->gone) {
911dc7e38acSHans Petter Selasky 		error = ENXIO;
912dc7e38acSHans Petter Selasky 		goto done;
913dc7e38acSHans Petter Selasky 	}
91482d2623eSHans Petter Selasky 	was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
915d2bf00a9SHans Petter Selasky 	mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify);
91682d2623eSHans Petter Selasky 
91782d2623eSHans Petter Selasky 	switch (MLX5_PARAM_OFFSET(arg[arg2])) {
91882d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_usecs):
919f03f517bSHans Petter Selasky 		/* import RX coal time */
920f03f517bSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_usecs < 1)
921f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_usecs = 0;
922f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.rx_coalesce_usecs >
923f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_period)) {
924f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_usecs =
925f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_period);
926f03f517bSHans Petter Selasky 		}
92782d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_usec =
92882d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_usecs;
929f03f517bSHans Petter Selasky 
93082d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
93182d2623eSHans Petter Selasky 		if (was_opened)
93282d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
93382d2623eSHans Petter Selasky 		break;
93482d2623eSHans Petter Selasky 
93582d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_pkts):
936f03f517bSHans Petter Selasky 		/* import RX coal pkts */
937f03f517bSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_pkts < 1)
938f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_pkts = 0;
939f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.rx_coalesce_pkts >
940f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
941f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_pkts =
942f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_max_count);
943f03f517bSHans Petter Selasky 		}
94482d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_pkts =
94582d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_pkts;
946f03f517bSHans Petter Selasky 
94782d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
94882d2623eSHans Petter Selasky 		if (was_opened)
94982d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
95082d2623eSHans Petter Selasky 		break;
95182d2623eSHans Petter Selasky 
95282d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_usecs):
953f03f517bSHans Petter Selasky 		/* import TX coal time */
954f03f517bSHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_usecs < 1)
955f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_usecs = 0;
956f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.tx_coalesce_usecs >
957f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_period)) {
958f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_usecs =
959f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_period);
960f03f517bSHans Petter Selasky 		}
96182d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_usec =
96282d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_usecs;
963f03f517bSHans Petter Selasky 
96482d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
96582d2623eSHans Petter Selasky 		if (was_opened)
96682d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
96782d2623eSHans Petter Selasky 		break;
96882d2623eSHans Petter Selasky 
96982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_pkts):
970f03f517bSHans Petter Selasky 		/* import TX coal pkts */
971f03f517bSHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_pkts < 1)
972f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_pkts = 0;
973f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.tx_coalesce_pkts >
974f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
97582d2623eSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_pkts =
97682d2623eSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_max_count);
977f03f517bSHans Petter Selasky 		}
97882d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_pkts =
97982d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_pkts;
980dc7e38acSHans Petter Selasky 
98182d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
98282d2623eSHans Petter Selasky 		if (was_opened)
983f03f517bSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
98482d2623eSHans Petter Selasky 		break;
98582d2623eSHans Petter Selasky 
98682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_queue_size):
98782d2623eSHans Petter Selasky 		/* network interface must be down */
98882d2623eSHans Petter Selasky 		if (was_opened)
989f03f517bSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
99082d2623eSHans Petter Selasky 
991dc7e38acSHans Petter Selasky 		/* import TX queue size */
992dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.tx_queue_size <
993dc7e38acSHans Petter Selasky 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
994dc7e38acSHans Petter Selasky 			priv->params_ethtool.tx_queue_size =
995dc7e38acSHans Petter Selasky 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE);
996dc7e38acSHans Petter Selasky 		} else if (priv->params_ethtool.tx_queue_size >
997dc7e38acSHans Petter Selasky 		    priv->params_ethtool.tx_queue_size_max) {
998dc7e38acSHans Petter Selasky 			priv->params_ethtool.tx_queue_size =
999dc7e38acSHans Petter Selasky 			    priv->params_ethtool.tx_queue_size_max;
1000dc7e38acSHans Petter Selasky 		}
100182d2623eSHans Petter Selasky 		/* store actual TX queue size */
1002dc7e38acSHans Petter Selasky 		priv->params.log_sq_size =
1003dc7e38acSHans Petter Selasky 		    order_base_2(priv->params_ethtool.tx_queue_size);
100482d2623eSHans Petter Selasky 		priv->params_ethtool.tx_queue_size =
100582d2623eSHans Petter Selasky 		    1 << priv->params.log_sq_size;
100682d2623eSHans Petter Selasky 
100782d2623eSHans Petter Selasky 		/* verify TX completion factor */
100882d2623eSHans Petter Selasky 		mlx5e_ethtool_sync_tx_completion_fact(priv);
100982d2623eSHans Petter Selasky 
101082d2623eSHans Petter Selasky 		/* restart network interface, if any */
101182d2623eSHans Petter Selasky 		if (was_opened)
101282d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
101382d2623eSHans Petter Selasky 		break;
101482d2623eSHans Petter Selasky 
101582d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_queue_size):
101682d2623eSHans Petter Selasky 		/* network interface must be down */
101782d2623eSHans Petter Selasky 		if (was_opened)
101882d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
1019dc7e38acSHans Petter Selasky 
1020dc7e38acSHans Petter Selasky 		/* import RX queue size */
1021dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.rx_queue_size <
1022dc7e38acSHans Petter Selasky 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) {
1023dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_queue_size =
1024dc7e38acSHans Petter Selasky 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE);
1025dc7e38acSHans Petter Selasky 		} else if (priv->params_ethtool.rx_queue_size >
1026dc7e38acSHans Petter Selasky 		    priv->params_ethtool.rx_queue_size_max) {
1027dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_queue_size =
1028dc7e38acSHans Petter Selasky 			    priv->params_ethtool.rx_queue_size_max;
1029dc7e38acSHans Petter Selasky 		}
103082d2623eSHans Petter Selasky 		/* store actual RX queue size */
1031dc7e38acSHans Petter Selasky 		priv->params.log_rq_size =
1032dc7e38acSHans Petter Selasky 		    order_base_2(priv->params_ethtool.rx_queue_size);
103382d2623eSHans Petter Selasky 		priv->params_ethtool.rx_queue_size =
103482d2623eSHans Petter Selasky 		    1 << priv->params.log_rq_size;
1035dc7e38acSHans Petter Selasky 
103682d2623eSHans Petter Selasky 		/* restart network interface, if any */
103782d2623eSHans Petter Selasky 		if (was_opened)
103882d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
103982d2623eSHans Petter Selasky 		break;
104082d2623eSHans Petter Selasky 
104116ae32f9SHans Petter Selasky 	case MLX5_PARAM_OFFSET(channels_rsss):
104216ae32f9SHans Petter Selasky 		/* network interface must be down */
104316ae32f9SHans Petter Selasky 		if (was_opened)
104416ae32f9SHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
104516ae32f9SHans Petter Selasky 
104616ae32f9SHans Petter Selasky 		/* import number of channels */
104716ae32f9SHans Petter Selasky 		if (priv->params_ethtool.channels_rsss < 1)
104816ae32f9SHans Petter Selasky 			priv->params_ethtool.channels_rsss = 1;
104916ae32f9SHans Petter Selasky 		else if (priv->params_ethtool.channels_rsss > 128)
105016ae32f9SHans Petter Selasky 			priv->params_ethtool.channels_rsss = 128;
105116ae32f9SHans Petter Selasky 
105216ae32f9SHans Petter Selasky 		priv->params.channels_rsss = priv->params_ethtool.channels_rsss;
105316ae32f9SHans Petter Selasky 
105416ae32f9SHans Petter Selasky 		/* restart network interface, if any */
105516ae32f9SHans Petter Selasky 		if (was_opened)
105616ae32f9SHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
105716ae32f9SHans Petter Selasky 		break;
105816ae32f9SHans Petter Selasky 
105982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(channels):
106082d2623eSHans Petter Selasky 		/* network interface must be down */
106182d2623eSHans Petter Selasky 		if (was_opened)
106282d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
106382d2623eSHans Petter Selasky 
1064dc7e38acSHans Petter Selasky 		/* import number of channels */
1065dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.channels < 1)
1066dc7e38acSHans Petter Selasky 			priv->params_ethtool.channels = 1;
1067dc7e38acSHans Petter Selasky 		else if (priv->params_ethtool.channels >
1068dc7e38acSHans Petter Selasky 		    (u64) priv->mdev->priv.eq_table.num_comp_vectors) {
1069dc7e38acSHans Petter Selasky 			priv->params_ethtool.channels =
1070dc7e38acSHans Petter Selasky 			    (u64) priv->mdev->priv.eq_table.num_comp_vectors;
1071dc7e38acSHans Petter Selasky 		}
1072dc7e38acSHans Petter Selasky 		priv->params.num_channels = priv->params_ethtool.channels;
1073dc7e38acSHans Petter Selasky 
107482d2623eSHans Petter Selasky 		/* restart network interface, if any */
107582d2623eSHans Petter Selasky 		if (was_opened)
107682d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
107782d2623eSHans Petter Selasky 		break;
107882d2623eSHans Petter Selasky 
107982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_mode):
108082d2623eSHans Petter Selasky 		/* network interface must be down */
1081d2bf00a9SHans Petter Selasky 		if (was_opened != 0 && mode_modify == 0)
108282d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
108382d2623eSHans Petter Selasky 
108482d2623eSHans Petter Selasky 		/* import RX coalesce mode */
1085423530beSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_mode > 3)
1086423530beSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_mode = 3;
108782d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_mode =
108882d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_mode;
1089dc7e38acSHans Petter Selasky 
109082d2623eSHans Petter Selasky 		/* restart network interface, if any */
1091d2bf00a9SHans Petter Selasky 		if (was_opened != 0) {
1092d2bf00a9SHans Petter Selasky 			if (mode_modify == 0)
109382d2623eSHans Petter Selasky 				mlx5e_open_locked(priv->ifp);
1094d2bf00a9SHans Petter Selasky 			else
1095d2bf00a9SHans Petter Selasky 				error = mlx5e_refresh_channel_params(priv);
1096d2bf00a9SHans Petter Selasky 		}
109782d2623eSHans Petter Selasky 		break;
109882d2623eSHans Petter Selasky 
109982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_mode):
110082d2623eSHans Petter Selasky 		/* network interface must be down */
1101d2bf00a9SHans Petter Selasky 		if (was_opened != 0 && mode_modify == 0)
110282d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
110382d2623eSHans Petter Selasky 
110482d2623eSHans Petter Selasky 		/* import TX coalesce mode */
110574540a31SHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_mode != 0)
110674540a31SHans Petter Selasky 			priv->params_ethtool.tx_coalesce_mode = 1;
110782d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_mode =
110882d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_mode;
110974540a31SHans Petter Selasky 
111082d2623eSHans Petter Selasky 		/* restart network interface, if any */
1111d2bf00a9SHans Petter Selasky 		if (was_opened != 0) {
1112d2bf00a9SHans Petter Selasky 			if (mode_modify == 0)
111382d2623eSHans Petter Selasky 				mlx5e_open_locked(priv->ifp);
1114d2bf00a9SHans Petter Selasky 			else
1115d2bf00a9SHans Petter Selasky 				error = mlx5e_refresh_channel_params(priv);
1116d2bf00a9SHans Petter Selasky 		}
111782d2623eSHans Petter Selasky 		break;
111882d2623eSHans Petter Selasky 
111982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(hw_lro):
112082d2623eSHans Petter Selasky 		/* network interface must be down */
112182d2623eSHans Petter Selasky 		if (was_opened)
112282d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
112382d2623eSHans Petter Selasky 
112482d2623eSHans Petter Selasky 		/* import HW LRO mode */
112571defedaSSlava Shwartsman 		if (priv->params_ethtool.hw_lro != 0 &&
1126d7633a30SHans Petter Selasky 		    MLX5_CAP_ETH(priv->mdev, lro_cap)) {
1127d7633a30SHans Petter Selasky 			priv->params_ethtool.hw_lro = 1;
112871defedaSSlava Shwartsman 			/* check if feature should actually be enabled */
11295dc00f00SJustin Hibbits 			if (if_getcapenable(priv->ifp) & IFCAP_LRO) {
113071defedaSSlava Shwartsman 				priv->params.hw_lro_en = true;
1131d7633a30SHans Petter Selasky 			} else {
113271defedaSSlava Shwartsman 				priv->params.hw_lro_en = false;
1133d7633a30SHans Petter Selasky 
11346b4040d8SHans Petter Selasky 				mlx5_en_warn(priv->ifp, "To enable HW LRO "
113571defedaSSlava Shwartsman 				    "please also enable LRO via ifconfig(8).\n");
113636c1007dSHans Petter Selasky 			}
1137bb3853c6SHans Petter Selasky 		} else {
113871defedaSSlava Shwartsman 			/* return an error if HW does not support this feature */
113971defedaSSlava Shwartsman 			if (priv->params_ethtool.hw_lro != 0)
114071defedaSSlava Shwartsman 				error = EINVAL;
114171defedaSSlava Shwartsman 			priv->params.hw_lro_en = false;
114271defedaSSlava Shwartsman 			priv->params_ethtool.hw_lro = 0;
1143dc7e38acSHans Petter Selasky 		}
114482d2623eSHans Petter Selasky 		/* restart network interface, if any */
114582d2623eSHans Petter Selasky 		if (was_opened)
114682d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
114782d2623eSHans Petter Selasky 		break;
1148dc7e38acSHans Petter Selasky 
114982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(cqe_zipping):
115082d2623eSHans Petter Selasky 		/* network interface must be down */
115182d2623eSHans Petter Selasky 		if (was_opened)
115282d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
115382d2623eSHans Petter Selasky 
115482d2623eSHans Petter Selasky 		/* import CQE zipping mode */
115590cc1c77SHans Petter Selasky 		if (priv->params_ethtool.cqe_zipping &&
115690cc1c77SHans Petter Selasky 		    MLX5_CAP_GEN(priv->mdev, cqe_compression)) {
115790cc1c77SHans Petter Selasky 			priv->params.cqe_zipping_en = true;
115890cc1c77SHans Petter Selasky 			priv->params_ethtool.cqe_zipping = 1;
115990cc1c77SHans Petter Selasky 		} else {
116090cc1c77SHans Petter Selasky 			priv->params.cqe_zipping_en = false;
116190cc1c77SHans Petter Selasky 			priv->params_ethtool.cqe_zipping = 0;
116290cc1c77SHans Petter Selasky 		}
116382d2623eSHans Petter Selasky 		/* restart network interface, if any */
1164dc7e38acSHans Petter Selasky 		if (was_opened)
1165dc7e38acSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
116682d2623eSHans Petter Selasky 		break;
116782d2623eSHans Petter Selasky 
116882d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_completion_fact):
116982d2623eSHans Petter Selasky 		/* network interface must be down */
117082d2623eSHans Petter Selasky 		if (was_opened)
117182d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
117282d2623eSHans Petter Selasky 
117382d2623eSHans Petter Selasky 		/* verify parameter */
117482d2623eSHans Petter Selasky 		mlx5e_ethtool_sync_tx_completion_fact(priv);
117582d2623eSHans Petter Selasky 
117682d2623eSHans Petter Selasky 		/* restart network interface, if any */
117782d2623eSHans Petter Selasky 		if (was_opened)
117882d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
117982d2623eSHans Petter Selasky 		break;
118082d2623eSHans Petter Selasky 
1181bb3616abSHans Petter Selasky 	case MLX5_PARAM_OFFSET(modify_tx_dma):
1182bb3616abSHans Petter Selasky 		/* check if network interface is opened */
1183bb3616abSHans Petter Selasky 		if (was_opened) {
1184bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_tx_dma =
1185bb3616abSHans Petter Selasky 			    priv->params_ethtool.modify_tx_dma ? 1 : 0;
1186bb3616abSHans Petter Selasky 			/* modify tx according to value */
1187bb3616abSHans Petter Selasky 			mlx5e_modify_tx_dma(priv, value != 0);
1188bb3616abSHans Petter Selasky 		} else {
1189bb3616abSHans Petter Selasky 			/* if closed force enable tx */
1190bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_tx_dma = 0;
1191bb3616abSHans Petter Selasky 		}
1192bb3616abSHans Petter Selasky 		break;
1193bb3616abSHans Petter Selasky 
1194bb3616abSHans Petter Selasky 	case MLX5_PARAM_OFFSET(modify_rx_dma):
1195bb3616abSHans Petter Selasky 		/* check if network interface is opened */
1196bb3616abSHans Petter Selasky 		if (was_opened) {
1197bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_rx_dma =
1198bb3616abSHans Petter Selasky 			    priv->params_ethtool.modify_rx_dma ? 1 : 0;
1199bb3616abSHans Petter Selasky 			/* modify rx according to value */
1200bb3616abSHans Petter Selasky 			mlx5e_modify_rx_dma(priv, value != 0);
1201bb3616abSHans Petter Selasky 		} else {
1202bb3616abSHans Petter Selasky 			/* if closed force enable rx */
1203bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_rx_dma = 0;
1204bb3616abSHans Petter Selasky 		}
1205bb3616abSHans Petter Selasky 		break;
1206bb3616abSHans Petter Selasky 
120766d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_pci_enable):
120866d53750SHans Petter Selasky 		priv->params_ethtool.diag_pci_enable =
120966d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable ? 1 : 0;
121066d53750SHans Petter Selasky 
121166d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
121266d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
121366d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
121466d53750SHans Petter Selasky 		break;
121566d53750SHans Petter Selasky 
121666d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_general_enable):
121766d53750SHans Petter Selasky 		priv->params_ethtool.diag_general_enable =
121866d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable ? 1 : 0;
121966d53750SHans Petter Selasky 
122066d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
122166d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
122266d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
122366d53750SHans Petter Selasky 		break;
122466d53750SHans Petter Selasky 
122561fd7ac0SHans Petter Selasky 	case MLX5_PARAM_OFFSET(mc_local_lb):
1226ea00d7e8SHans Petter Selasky 		/* check if mlx5ib is managing this feature */
1227ea00d7e8SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) {
1228ea00d7e8SHans Petter Selasky 			error = EOPNOTSUPP;
1229ea00d7e8SHans Petter Selasky 			break;
1230ea00d7e8SHans Petter Selasky 		}
1231ea00d7e8SHans Petter Selasky 
123261fd7ac0SHans Petter Selasky 		priv->params_ethtool.mc_local_lb =
123361fd7ac0SHans Petter Selasky 		    priv->params_ethtool.mc_local_lb ? 1 : 0;
123461fd7ac0SHans Petter Selasky 
1235c1b76119SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, disable_local_lb_mc)) {
123661fd7ac0SHans Petter Selasky 			error = mlx5_nic_vport_modify_local_lb(priv->mdev,
123761fd7ac0SHans Petter Selasky 			    MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb);
123861fd7ac0SHans Petter Selasky 		} else {
123961fd7ac0SHans Petter Selasky 			error = EOPNOTSUPP;
124061fd7ac0SHans Petter Selasky 		}
124161fd7ac0SHans Petter Selasky 		break;
124261fd7ac0SHans Petter Selasky 
124361fd7ac0SHans Petter Selasky 	case MLX5_PARAM_OFFSET(uc_local_lb):
1244ea00d7e8SHans Petter Selasky 		/* check if mlx5ib is managing this feature */
1245ea00d7e8SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) {
1246ea00d7e8SHans Petter Selasky 			error = EOPNOTSUPP;
1247ea00d7e8SHans Petter Selasky 			break;
1248ea00d7e8SHans Petter Selasky 		}
1249ea00d7e8SHans Petter Selasky 
125061fd7ac0SHans Petter Selasky 		priv->params_ethtool.uc_local_lb =
125161fd7ac0SHans Petter Selasky 		    priv->params_ethtool.uc_local_lb ? 1 : 0;
125261fd7ac0SHans Petter Selasky 
1253c1b76119SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, disable_local_lb_uc)) {
125461fd7ac0SHans Petter Selasky 			error = mlx5_nic_vport_modify_local_lb(priv->mdev,
125561fd7ac0SHans Petter Selasky 			    MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb);
125661fd7ac0SHans Petter Selasky 		} else {
125761fd7ac0SHans Petter Selasky 			error = EOPNOTSUPP;
125861fd7ac0SHans Petter Selasky 		}
125961fd7ac0SHans Petter Selasky 		break;
126061fd7ac0SHans Petter Selasky 
1261c8d16d1eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(irq_cpu_base):
1262c8d16d1eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(irq_cpu_stride):
1263c8d16d1eSHans Petter Selasky 		if (was_opened) {
1264c8d16d1eSHans Petter Selasky 			/* network interface must toggled */
1265c8d16d1eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
1266c8d16d1eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
1267c8d16d1eSHans Petter Selasky 		}
1268c8d16d1eSHans Petter Selasky 		break;
1269c8d16d1eSHans Petter Selasky 
127082d2623eSHans Petter Selasky 	default:
127182d2623eSHans Petter Selasky 		break;
127282d2623eSHans Petter Selasky 	}
1273dc7e38acSHans Petter Selasky done:
1274dc7e38acSHans Petter Selasky 	PRIV_UNLOCK(priv);
1275dc7e38acSHans Petter Selasky 	return (error);
1276dc7e38acSHans Petter Selasky }
1277dc7e38acSHans Petter Selasky 
1278dc7e38acSHans Petter Selasky static const char *mlx5e_params_desc[] = {
1279dc7e38acSHans Petter Selasky 	MLX5E_PARAMS(MLX5E_STATS_DESC)
1280dc7e38acSHans Petter Selasky };
1281dc7e38acSHans Petter Selasky 
1282dc7e38acSHans Petter Selasky static const char *mlx5e_port_stats_debug_desc[] = {
1283dc7e38acSHans Petter Selasky 	MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC)
1284dc7e38acSHans Petter Selasky };
1285dc7e38acSHans Petter Selasky 
1286dc7e38acSHans Petter Selasky static int
mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS)1287f2b4782cSHans Petter Selasky mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS)
1288f2b4782cSHans Petter Selasky {
1289f2b4782cSHans Petter Selasky 	struct mlx5e_priv *priv;
1290f2b4782cSHans Petter Selasky 	struct sbuf sb;
1291f2b4782cSHans Petter Selasky 	struct mlx5e_channel *c;
1292f2b4782cSHans Petter Selasky 	struct mlx5e_sq *sq;
1293f2b4782cSHans Petter Selasky 	struct mlx5e_rq *rq;
1294f2b4782cSHans Petter Selasky 	int error, i, tc;
12952110251aSHans Petter Selasky 	bool opened;
1296f2b4782cSHans Petter Selasky 
1297f2b4782cSHans Petter Selasky 	priv = arg1;
1298f2b4782cSHans Petter Selasky 	error = sysctl_wire_old_buffer(req, 0);
1299f2b4782cSHans Petter Selasky 	if (error != 0)
1300f2b4782cSHans Petter Selasky 		return (error);
13012110251aSHans Petter Selasky 	if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL)
1302f2b4782cSHans Petter Selasky 		return (ENOMEM);
1303f2b4782cSHans Petter Selasky 	sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
1304f2b4782cSHans Petter Selasky 
1305f2b4782cSHans Petter Selasky 	PRIV_LOCK(priv);
13062110251aSHans Petter Selasky 	opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
13072110251aSHans Petter Selasky 
13082110251aSHans Petter Selasky 	sbuf_printf(&sb, "pages irq %d\n",
13092110251aSHans Petter Selasky 	    priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector);
13102110251aSHans Petter Selasky 	sbuf_printf(&sb, "command irq %d\n",
13112110251aSHans Petter Selasky 	    priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector);
13122110251aSHans Petter Selasky 	sbuf_printf(&sb, "async irq %d\n",
13132110251aSHans Petter Selasky 	    priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector);
13142110251aSHans Petter Selasky 
13152110251aSHans Petter Selasky 	for (i = 0; i != priv->params.num_channels; i++) {
13162110251aSHans Petter Selasky 		int eqn_not_used = -1;
13172110251aSHans Petter Selasky 		int irqn = MLX5_EQ_VEC_COMP_BASE;
13182110251aSHans Petter Selasky 
13192110251aSHans Petter Selasky 		if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0)
13202110251aSHans Petter Selasky 			continue;
13212110251aSHans Petter Selasky 
13222110251aSHans Petter Selasky 		c = opened ? &priv->channel[i] : NULL;
13232110251aSHans Petter Selasky 		rq = opened ? &c->rq : NULL;
13242110251aSHans Petter Selasky 		sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i,
13252110251aSHans Petter Selasky 		    opened ? rq->rqn : -1,
13262110251aSHans Petter Selasky 		    opened ? rq->cq.mcq.cqn : -1,
13272110251aSHans Petter Selasky 		    priv->mdev->priv.msix_arr[irqn].vector);
13282110251aSHans Petter Selasky 
13292110251aSHans Petter Selasky 		for (tc = 0; tc != priv->num_tc; tc++) {
13302110251aSHans Petter Selasky 			sq = opened ? &c->sq[tc] : NULL;
13312110251aSHans Petter Selasky 			sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n",
13322110251aSHans Petter Selasky 			    i, tc,
13332110251aSHans Petter Selasky 			    opened ? sq->sqn : -1,
13342110251aSHans Petter Selasky 			    opened ? sq->cq.mcq.cqn : -1,
13352110251aSHans Petter Selasky 			    priv->mdev->priv.msix_arr[irqn].vector);
1336f2b4782cSHans Petter Selasky 		}
1337f2b4782cSHans Petter Selasky 	}
1338f2b4782cSHans Petter Selasky 	PRIV_UNLOCK(priv);
1339f2b4782cSHans Petter Selasky 	error = sbuf_finish(&sb);
1340f2b4782cSHans Petter Selasky 	sbuf_delete(&sb);
1341f2b4782cSHans Petter Selasky 	return (error);
1342f2b4782cSHans Petter Selasky }
1343f2b4782cSHans Petter Selasky 
1344f2b4782cSHans Petter Selasky static int
mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS)1345dc7e38acSHans Petter Selasky mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS)
1346dc7e38acSHans Petter Selasky {
1347dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
1348b3cf1493SSlava Shwartsman 	int sys_debug;
1349b3cf1493SSlava Shwartsman 	int error;
1350f2b4782cSHans Petter Selasky 
1351f2b4782cSHans Petter Selasky 	PRIV_LOCK(priv);
1352069963d7SHans Petter Selasky 	if (priv->gone != 0) {
1353069963d7SHans Petter Selasky 		error = ENODEV;
1354069963d7SHans Petter Selasky 		goto done;
1355069963d7SHans Petter Selasky 	}
1356b3cf1493SSlava Shwartsman 	sys_debug = priv->sysctl_debug;
1357b3cf1493SSlava Shwartsman 	error = sysctl_handle_int(oidp, &sys_debug, 0, req);
1358b3cf1493SSlava Shwartsman 	if (error != 0 || !req->newptr)
1359b3cf1493SSlava Shwartsman 		goto done;
1360b3cf1493SSlava Shwartsman 	sys_debug = sys_debug ? 1 : 0;
1361b3cf1493SSlava Shwartsman 	if (sys_debug == priv->sysctl_debug)
1362b3cf1493SSlava Shwartsman 		goto done;
1363b3cf1493SSlava Shwartsman 
1364b3cf1493SSlava Shwartsman 	if ((priv->sysctl_debug = sys_debug)) {
1365dc7e38acSHans Petter Selasky 		mlx5e_create_stats(&priv->stats.port_stats_debug.ctx,
1366dc7e38acSHans Petter Selasky 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats",
1367dc7e38acSHans Petter Selasky 		    mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM,
1368dc7e38acSHans Petter Selasky 		    priv->stats.port_stats_debug.arg);
1369b3cf1493SSlava Shwartsman 		SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx,
1370f2b4782cSHans Petter Selasky 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
1371f2b4782cSHans Petter Selasky 		    "hw_ctx_debug",
1372f2b4782cSHans Petter Selasky 		    CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0,
1373f2b4782cSHans Petter Selasky 		    mlx5e_ethtool_debug_channel_info, "S", "");
1374f2b4782cSHans Petter Selasky 	} else {
1375dc7e38acSHans Petter Selasky 		sysctl_ctx_free(&priv->stats.port_stats_debug.ctx);
1376f2b4782cSHans Petter Selasky 	}
1377b3cf1493SSlava Shwartsman done:
1378f2b4782cSHans Petter Selasky 	PRIV_UNLOCK(priv);
1379b3cf1493SSlava Shwartsman 	return (error);
1380dc7e38acSHans Petter Selasky }
1381dc7e38acSHans Petter Selasky 
138266d53750SHans Petter Selasky static void
mlx5e_create_diagnostics(struct mlx5e_priv * priv)138366d53750SHans Petter Selasky mlx5e_create_diagnostics(struct mlx5e_priv *priv)
138466d53750SHans Petter Selasky {
138566d53750SHans Petter Selasky 	struct mlx5_core_diagnostics_entry entry;
138666d53750SHans Petter Selasky 	struct sysctl_ctx_list *ctx;
138766d53750SHans Petter Selasky 	struct sysctl_oid *node;
138866d53750SHans Petter Selasky 	int x;
138966d53750SHans Petter Selasky 
139066d53750SHans Petter Selasky 	/* sysctl context we are using */
139166d53750SHans Petter Selasky 	ctx = &priv->sysctl_ctx;
139266d53750SHans Petter Selasky 
139366d53750SHans Petter Selasky 	/* create root node */
139466d53750SHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx,
139566d53750SHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
13967029da5cSPawel Biernacki 	    "diagnostics", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Diagnostics");
139766d53750SHans Petter Selasky 	if (node == NULL)
139866d53750SHans Petter Selasky 		return;
139966d53750SHans Petter Selasky 
140066d53750SHans Petter Selasky 	/* create PCI diagnostics */
140166d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) {
140266d53750SHans Petter Selasky 		entry = mlx5_core_pci_diagnostics_table[x];
140366d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
140466d53750SHans Petter Selasky 			continue;
140566d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
140666d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_pci.array + x,
140766d53750SHans Petter Selasky 		    "PCI diagnostics counter");
140866d53750SHans Petter Selasky 	}
140966d53750SHans Petter Selasky 
141066d53750SHans Petter Selasky 	/* create general diagnostics */
141166d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) {
141266d53750SHans Petter Selasky 		entry = mlx5_core_general_diagnostics_table[x];
141366d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
141466d53750SHans Petter Selasky 			continue;
141566d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
141666d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_general.array + x,
141766d53750SHans Petter Selasky 		    "General diagnostics counter");
141866d53750SHans Petter Selasky 	}
141966d53750SHans Petter Selasky }
142066d53750SHans Petter Selasky 
1421dc7e38acSHans Petter Selasky void
mlx5e_create_ethtool(struct mlx5e_priv * priv)1422dc7e38acSHans Petter Selasky mlx5e_create_ethtool(struct mlx5e_priv *priv)
1423dc7e38acSHans Petter Selasky {
142496425f44SHans Petter Selasky 	struct sysctl_oid *fec_node;
142596425f44SHans Petter Selasky 	struct sysctl_oid *qos_node;
142696425f44SHans Petter Selasky 	struct sysctl_oid *node;
1427dc7e38acSHans Petter Selasky 	const char *pnameunit;
14286deb0b1eSHans Petter Selasky 	struct mlx5e_port_buffer port_buffer;
1429dc7e38acSHans Petter Selasky 	unsigned x;
1430cfc9c386SHans Petter Selasky 	int i;
1431dc7e38acSHans Petter Selasky 
1432dc7e38acSHans Petter Selasky 	/* set some defaults */
1433c8d16d1eSHans Petter Selasky 	priv->params_ethtool.irq_cpu_base = -1;	/* disabled */
1434c8d16d1eSHans Petter Selasky 	priv->params_ethtool.irq_cpu_stride = 1;
1435dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
1436dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE;
1437dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size;
1438dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size;
1439dc7e38acSHans Petter Selasky 	priv->params_ethtool.channels = priv->params.num_channels;
144016ae32f9SHans Petter Selasky 	priv->params_ethtool.channels_rsss = priv->params.channels_rsss;
1441dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count);
1442dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period);
1443dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode;
1444dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec;
1445dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts;
144674540a31SHans Petter Selasky 	priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode;
1447dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec;
1448dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts;
1449dc7e38acSHans Petter Selasky 	priv->params_ethtool.hw_lro = priv->params.hw_lro_en;
145090cc1c77SHans Petter Selasky 	priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en;
1451376bcf63SHans Petter Selasky 	mlx5e_ethtool_sync_tx_completion_fact(priv);
1452dc7e38acSHans Petter Selasky 
145361fd7ac0SHans Petter Selasky 	/* get default values for local loopback, if any */
1454c1b76119SHans Petter Selasky 	if (MLX5_CAP_GEN(priv->mdev, disable_local_lb_mc) ||
1455c1b76119SHans Petter Selasky 	    MLX5_CAP_GEN(priv->mdev, disable_local_lb_uc)) {
145661fd7ac0SHans Petter Selasky 		int err;
145761fd7ac0SHans Petter Selasky 		u8 val;
145861fd7ac0SHans Petter Selasky 
145961fd7ac0SHans Petter Selasky 		err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val);
146061fd7ac0SHans Petter Selasky 		if (err == 0)
146161fd7ac0SHans Petter Selasky 			priv->params_ethtool.mc_local_lb = val;
146261fd7ac0SHans Petter Selasky 
146361fd7ac0SHans Petter Selasky 		err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val);
146461fd7ac0SHans Petter Selasky 		if (err == 0)
146561fd7ac0SHans Petter Selasky 			priv->params_ethtool.uc_local_lb = val;
146661fd7ac0SHans Petter Selasky 	}
146761fd7ac0SHans Petter Selasky 
1468dc7e38acSHans Petter Selasky 	/* create root node */
1469dc7e38acSHans Petter Selasky 	node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1470dc7e38acSHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
14717029da5cSPawel Biernacki 	    "conf", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, "Configuration");
1472dc7e38acSHans Petter Selasky 	if (node == NULL)
1473dc7e38acSHans Petter Selasky 		return;
1474dc7e38acSHans Petter Selasky 	for (x = 0; x != MLX5E_PARAMS_NUM; x++) {
1475dc7e38acSHans Petter Selasky 		/* check for read-only parameter */
147653d7bb46SHans Petter Selasky 		if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL ||
147753d7bb46SHans Petter Selasky 		    strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) {
1478dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1479dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD |
1480dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1481dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
1482a60f9534SHans Petter Selasky 		} else if (strcmp(mlx5e_params_desc[2 * x], "hw_lro") == 0) {
1483a60f9534SHans Petter Selasky 			/* read-only, but tunable parameters */
1484a60f9534SHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1485a60f9534SHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RDTUN |
1486a60f9534SHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1487a60f9534SHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
1488dc7e38acSHans Petter Selasky 		} else {
1489ec0143b2SHans Petter Selasky 			/*
1490ec0143b2SHans Petter Selasky 			 * NOTE: In FreeBSD-11 and newer the
1491ec0143b2SHans Petter Selasky 			 * CTLFLAG_RWTUN flag will take care of
1492ec0143b2SHans Petter Selasky 			 * loading default sysctl value from the
1493ec0143b2SHans Petter Selasky 			 * kernel environment, if any:
1494ec0143b2SHans Petter Selasky 			 */
1495dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1496dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN |
1497dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1498dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
1499dc7e38acSHans Petter Selasky 		}
1500dc7e38acSHans Petter Selasky 	}
1501dc7e38acSHans Petter Selasky 
150296425f44SHans Petter Selasky 	/* create fec node */
150396425f44SHans Petter Selasky 	fec_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
150496425f44SHans Petter Selasky 	    SYSCTL_CHILDREN(node), OID_AUTO,
15057029da5cSPawel Biernacki 	    "fec", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
15067029da5cSPawel Biernacki 	    "Forward Error Correction");
150796425f44SHans Petter Selasky 	if (fec_node == NULL)
150896425f44SHans Petter Selasky 		return;
150996425f44SHans Petter Selasky 
151096425f44SHans Petter Selasky 	if (mlx5e_fec_update(priv) == 0) {
151196425f44SHans Petter Selasky 		SYSCTL_ADD_U32(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
151296425f44SHans Petter Selasky 		    "mode_active", CTLFLAG_RD | CTLFLAG_MPSAFE,
151396425f44SHans Petter Selasky 		    &priv->params_ethtool.fec_mode_active, 0,
151496425f44SHans Petter Selasky 		    "Current FEC mode bit, if any.");
151596425f44SHans Petter Selasky 
151696425f44SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
151796425f44SHans Petter Selasky 		    "mask_10x_25x", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
151896425f44SHans Petter Selasky 		    priv, 0, &mlx5e_fec_mask_10x_25x_handler, "CU",
151996425f44SHans Petter Selasky 		    "Set FEC masks for 10G_40G, 25G_50G, 56G, 100G respectivly. "
152096425f44SHans Petter Selasky 		    "0:Auto "
152196425f44SHans Petter Selasky 		    "1:NOFEC "
152296425f44SHans Petter Selasky 		    "2:FIRECODE "
152396425f44SHans Petter Selasky 		    "4:RS");
152496425f44SHans Petter Selasky 
152596425f44SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
152696425f44SHans Petter Selasky 		    "avail_10x_25x", CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE,
152796425f44SHans Petter Selasky 		    priv, 0, &mlx5e_fec_avail_10x_25x_handler, "CU",
152896425f44SHans Petter Selasky 		    "Get available FEC bits for 10G_40G, 25G_50G, 56G, 100G respectivly. "
152996425f44SHans Petter Selasky 		    "0:Auto "
153096425f44SHans Petter Selasky 		    "1:NOFEC "
153196425f44SHans Petter Selasky 		    "2:FIRECODE "
153296425f44SHans Petter Selasky 		    "4:RS");
153396425f44SHans Petter Selasky 
153496425f44SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
153596425f44SHans Petter Selasky 		    "mask_50x", CTLTYPE_U16 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
153696425f44SHans Petter Selasky 		    priv, 0, &mlx5e_fec_mask_50x_handler, "SU",
153796425f44SHans Petter Selasky 		    "Set FEC masks for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. "
153896425f44SHans Petter Selasky 		    "0:Auto "
153996425f44SHans Petter Selasky 		    "128:RS "
154096425f44SHans Petter Selasky 		    "512:LL RS");
154196425f44SHans Petter Selasky 
154296425f44SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
154396425f44SHans Petter Selasky 		    "avail_50x", CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_MPSAFE,
154496425f44SHans Petter Selasky 		    priv, 0, &mlx5e_fec_avail_50x_handler, "SU",
154596425f44SHans Petter Selasky 		    "Get available FEC bits for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. "
154696425f44SHans Petter Selasky 		    "0:Auto "
154796425f44SHans Petter Selasky 		    "128:RS "
154896425f44SHans Petter Selasky 		    "512:LL RS");
154996425f44SHans Petter Selasky 	}
155096425f44SHans Petter Selasky 
1551dc7e38acSHans Petter Selasky 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1552dc7e38acSHans Petter Selasky 	    "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv,
1553dc7e38acSHans Petter Selasky 	    0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics");
1554dc7e38acSHans Petter Selasky 
1555dc7e38acSHans Petter Selasky 	pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
1556dc7e38acSHans Petter Selasky 
1557dc7e38acSHans Petter Selasky 	SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node),
1558dc7e38acSHans Petter Selasky 	    OID_AUTO, "device_name", CTLFLAG_RD,
1559dc7e38acSHans Petter Selasky 	    __DECONST(void *, pnameunit), 0,
1560dc7e38acSHans Petter Selasky 	    "PCI device name");
1561dc7e38acSHans Petter Selasky 
156266d53750SHans Petter Selasky 	/* Diagnostics support */
156366d53750SHans Petter Selasky 	mlx5e_create_diagnostics(priv);
1564cfc9c386SHans Petter Selasky 
1565cfc9c386SHans Petter Selasky 	/* create qos node */
1566cfc9c386SHans Petter Selasky 	qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1567cfc9c386SHans Petter Selasky 	    SYSCTL_CHILDREN(node), OID_AUTO,
15687029da5cSPawel Biernacki 	    "qos", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
15697029da5cSPawel Biernacki 	    "Quality Of Service configuration");
1570e870c0abSSlava Shwartsman 	if (qos_node == NULL)
1571cfc9c386SHans Petter Selasky 		return;
1572cfc9c386SHans Petter Selasky 
1573e870c0abSSlava Shwartsman 	/* Priority rate limit support */
1574e870c0abSSlava Shwartsman 	if (mlx5e_getmaxrate(priv) == 0) {
1575cfc9c386SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1576e870c0abSSlava Shwartsman 		    OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1577e870c0abSSlava Shwartsman 		    priv, 0, mlx5e_tc_maxrate_handler, "QU",
1578e870c0abSSlava Shwartsman 		    "Max rate for priority, specified in kilobits, where kilo=1000, "
1579e870c0abSSlava Shwartsman 		    "max_rate must be divisible by 100000");
1580cfc9c386SHans Petter Selasky 	}
15812e9c3a4fSHans Petter Selasky 
1582e870c0abSSlava Shwartsman 	/* Bandwidth limiting by ratio */
1583e870c0abSSlava Shwartsman 	if (mlx5e_get_max_alloc(priv) == 0) {
1584e870c0abSSlava Shwartsman 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1585e870c0abSSlava Shwartsman 		    OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1586e870c0abSSlava Shwartsman 		    priv, 0, mlx5e_tc_rate_share_handler, "QU",
1587e870c0abSSlava Shwartsman 		    "Specify bandwidth ratio from 1 to 100 "
1588e870c0abSSlava Shwartsman 		    "for the available traffic classes");
1589e870c0abSSlava Shwartsman 	}
15902e9c3a4fSHans Petter Selasky 
1591e870c0abSSlava Shwartsman 	/* Priority to traffic class mapping */
1592e870c0abSSlava Shwartsman 	if (mlx5e_get_prio_tc(priv) == 0) {
15932e9c3a4fSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
159424385321SHans Petter Selasky 		    OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
159524385321SHans Petter Selasky 		    priv, 0, mlx5e_prio_to_tc_handler, "CU",
159624385321SHans Petter Selasky 		    "Set traffic class 0 to 7 for priority 0 to 7 inclusivly");
1597e870c0abSSlava Shwartsman 	}
1598ed0cee0bSHans Petter Selasky 
1599ed0cee0bSHans Petter Selasky 	/* DSCP support */
1600ed0cee0bSHans Petter Selasky 	if (mlx5e_get_dscp(priv) == 0) {
1601ed0cee0bSHans Petter Selasky 		for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) {
1602ed0cee0bSHans Petter Selasky 			char name[32];
1603ed0cee0bSHans Petter Selasky 			snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7);
1604ed0cee0bSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1605ed0cee0bSHans Petter Selasky 				OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1606ed0cee0bSHans Petter Selasky 				priv, i, mlx5e_dscp_prio_handler, "CU",
1607ed0cee0bSHans Petter Selasky 				"Set DSCP to priority mapping, 0..7");
1608ed0cee0bSHans Petter Selasky 		}
1609a880c1ffSHans Petter Selasky #define	A	"Set trust state, 1:PCP 2:DSCP"
1610a880c1ffSHans Petter Selasky #define	B	" 3:BOTH"
1611ed0cee0bSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1612ed0cee0bSHans Petter Selasky 		    OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1613ed0cee0bSHans Petter Selasky 		    priv, 0, mlx5e_trust_state_handler, "CU",
1614dfea1c3eSHans Petter Selasky 		    MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ?
1615a880c1ffSHans Petter Selasky 		    A B : A);
1616a880c1ffSHans Petter Selasky #undef B
1617a880c1ffSHans Petter Selasky #undef A
1618ed0cee0bSHans Petter Selasky 	}
16196deb0b1eSHans Petter Selasky 
16206deb0b1eSHans Petter Selasky 	if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) {
16216deb0b1eSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
16226deb0b1eSHans Petter Selasky 		    OID_AUTO, "buffers_size",
16236deb0b1eSHans Petter Selasky 		    CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
16246deb0b1eSHans Petter Selasky 		    priv, 0, mlx5e_buf_size_handler, "IU",
16256deb0b1eSHans Petter Selasky 		    "Set buffers sizes");
16266deb0b1eSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
16276deb0b1eSHans Petter Selasky 		    OID_AUTO, "buffers_prio",
16286deb0b1eSHans Petter Selasky 		    CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
16296deb0b1eSHans Petter Selasky 		    priv, 0, mlx5e_buf_prio_handler, "CU",
16306deb0b1eSHans Petter Selasky 		    "Set prio to buffers mapping");
16316deb0b1eSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
16326deb0b1eSHans Petter Selasky 		    OID_AUTO, "cable_length",
16336deb0b1eSHans Petter Selasky 		    CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
16346deb0b1eSHans Petter Selasky 		    priv, 0, mlx5e_cable_length_handler, "IU",
16356deb0b1eSHans Petter Selasky 		    "Set cable length in meters for xoff threshold calculation");
16366deb0b1eSHans Petter Selasky 	}
1637decb087cSHans Petter Selasky 
1638decb087cSHans Petter Selasky 	if (mlx5e_hw_temperature_update(priv) == 0) {
1639decb087cSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(priv->sysctl_ifnet),
1640decb087cSHans Petter Selasky 		    OID_AUTO, "hw_temperature",
1641decb087cSHans Petter Selasky 		    CTLTYPE_S32 | CTLFLAG_RD | CTLFLAG_MPSAFE,
1642decb087cSHans Petter Selasky 		    priv, 0, mlx5e_hw_temperature_handler, "I",
16439097ac9aSElyes HAOUAS 		    "HW temperature in millicelsius");
1644decb087cSHans Petter Selasky 	}
1645dc7e38acSHans Petter Selasky }
1646