xref: /freebsd/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c (revision 3e581cab)
1dc7e38acSHans Petter Selasky /*-
2dc7e38acSHans Petter Selasky  * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
3dc7e38acSHans Petter Selasky  *
4dc7e38acSHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
5dc7e38acSHans Petter Selasky  * modification, are permitted provided that the following conditions
6dc7e38acSHans Petter Selasky  * are met:
7dc7e38acSHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
8dc7e38acSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer.
9dc7e38acSHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
10dc7e38acSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
11dc7e38acSHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
12dc7e38acSHans Petter Selasky  *
13dc7e38acSHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14dc7e38acSHans Petter Selasky  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15dc7e38acSHans Petter Selasky  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16dc7e38acSHans Petter Selasky  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17dc7e38acSHans Petter Selasky  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18dc7e38acSHans Petter Selasky  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19dc7e38acSHans Petter Selasky  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20dc7e38acSHans Petter Selasky  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21dc7e38acSHans Petter Selasky  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22dc7e38acSHans Petter Selasky  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23dc7e38acSHans Petter Selasky  * SUCH DAMAGE.
24dc7e38acSHans Petter Selasky  *
25dc7e38acSHans Petter Selasky  * $FreeBSD$
26dc7e38acSHans Petter Selasky  */
27dc7e38acSHans Petter Selasky 
28dc7e38acSHans Petter Selasky #include "en.h"
29dc7e38acSHans Petter Selasky #include <net/sff8472.h>
30dc7e38acSHans Petter Selasky 
31dc7e38acSHans Petter Selasky void
32dc7e38acSHans Petter Selasky mlx5e_create_stats(struct sysctl_ctx_list *ctx,
33dc7e38acSHans Petter Selasky     struct sysctl_oid_list *parent, const char *buffer,
34dc7e38acSHans Petter Selasky     const char **desc, unsigned num, u64 * arg)
35dc7e38acSHans Petter Selasky {
36dc7e38acSHans Petter Selasky 	struct sysctl_oid *node;
37dc7e38acSHans Petter Selasky 	unsigned x;
38dc7e38acSHans Petter Selasky 
39dc7e38acSHans Petter Selasky 	sysctl_ctx_init(ctx);
40dc7e38acSHans Petter Selasky 
41dc7e38acSHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO,
42dc7e38acSHans Petter Selasky 	    buffer, CTLFLAG_RD, NULL, "Statistics");
43dc7e38acSHans Petter Selasky 	if (node == NULL)
44dc7e38acSHans Petter Selasky 		return;
45dc7e38acSHans Petter Selasky 	for (x = 0; x != num; x++) {
46dc7e38acSHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
47dc7e38acSHans Petter Selasky 		    desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]);
48dc7e38acSHans Petter Selasky 	}
49dc7e38acSHans Petter Selasky }
50dc7e38acSHans Petter Selasky 
51376bcf63SHans Petter Selasky static void
52376bcf63SHans Petter Selasky mlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv *priv)
53376bcf63SHans Petter Selasky {
54376bcf63SHans Petter Selasky 	/*
55376bcf63SHans Petter Selasky 	 * Limit the maximum distance between completion events to
56376bcf63SHans Petter Selasky 	 * half of the currently set TX queue size.
57376bcf63SHans Petter Selasky 	 *
58376bcf63SHans Petter Selasky 	 * The maximum number of queue entries a single IP packet can
59376bcf63SHans Petter Selasky 	 * consume is given by MLX5_SEND_WQE_MAX_WQEBBS.
60376bcf63SHans Petter Selasky 	 *
61376bcf63SHans Petter Selasky 	 * The worst case max value is then given as below:
62376bcf63SHans Petter Selasky 	 */
63376bcf63SHans Petter Selasky 	uint64_t max = priv->params_ethtool.tx_queue_size /
64376bcf63SHans Petter Selasky 	    (2 * MLX5_SEND_WQE_MAX_WQEBBS);
65376bcf63SHans Petter Selasky 
66376bcf63SHans Petter Selasky 	/*
67376bcf63SHans Petter Selasky 	 * Update the maximum completion factor value in case the
68376bcf63SHans Petter Selasky 	 * tx_queue_size field changed. Ensure we don't overflow
69376bcf63SHans Petter Selasky 	 * 16-bits.
70376bcf63SHans Petter Selasky 	 */
71376bcf63SHans Petter Selasky 	if (max < 1)
72376bcf63SHans Petter Selasky 		max = 1;
73376bcf63SHans Petter Selasky 	else if (max > 65535)
74376bcf63SHans Petter Selasky 		max = 65535;
75376bcf63SHans Petter Selasky 	priv->params_ethtool.tx_completion_fact_max = max;
76376bcf63SHans Petter Selasky 
77376bcf63SHans Petter Selasky 	/*
78376bcf63SHans Petter Selasky 	 * Verify that the current TX completion factor is within the
79376bcf63SHans Petter Selasky 	 * given limits:
80376bcf63SHans Petter Selasky 	 */
81376bcf63SHans Petter Selasky 	if (priv->params_ethtool.tx_completion_fact < 1)
82376bcf63SHans Petter Selasky 		priv->params_ethtool.tx_completion_fact = 1;
83376bcf63SHans Petter Selasky 	else if (priv->params_ethtool.tx_completion_fact > max)
84376bcf63SHans Petter Selasky 		priv->params_ethtool.tx_completion_fact = max;
85376bcf63SHans Petter Selasky }
86376bcf63SHans Petter Selasky 
87cfc9c386SHans Petter Selasky static int
88cfc9c386SHans Petter Selasky mlx5e_getmaxrate(struct mlx5e_priv *priv)
89cfc9c386SHans Petter Selasky {
90cfc9c386SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
91cfc9c386SHans Petter Selasky 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
92cfc9c386SHans Petter Selasky 	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
93cfc9c386SHans Petter Selasky 	int err;
94cfc9c386SHans Petter Selasky 	int i;
95cfc9c386SHans Petter Selasky 
96cfc9c386SHans Petter Selasky 	PRIV_LOCK(priv);
97cfc9c386SHans Petter Selasky 	err = -mlx5_query_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
98cfc9c386SHans Petter Selasky 	if (err)
99cfc9c386SHans Petter Selasky 		goto done;
100cfc9c386SHans Petter Selasky 
101cfc9c386SHans Petter Selasky 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
102cfc9c386SHans Petter Selasky 		switch (max_bw_unit[i]) {
103cfc9c386SHans Petter Selasky 		case MLX5_100_MBPS_UNIT:
104cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_100MB;
105cfc9c386SHans Petter Selasky 			break;
106cfc9c386SHans Petter Selasky 		case MLX5_GBPS_UNIT:
107cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_1GB;
108cfc9c386SHans Petter Selasky 			break;
109cfc9c386SHans Petter Selasky 		case MLX5_BW_NO_LIMIT:
110cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = 0;
111cfc9c386SHans Petter Selasky 			break;
112cfc9c386SHans Petter Selasky 		default:
113cfc9c386SHans Petter Selasky 			priv->params_ethtool.max_bw_value[i] = -1;
114cfc9c386SHans Petter Selasky 			WARN_ONCE(true, "non-supported BW unit");
115cfc9c386SHans Petter Selasky 			break;
116cfc9c386SHans Petter Selasky 		}
117cfc9c386SHans Petter Selasky 	}
118cfc9c386SHans Petter Selasky done:
119cfc9c386SHans Petter Selasky 	PRIV_UNLOCK(priv);
120cfc9c386SHans Petter Selasky 	return (err);
121cfc9c386SHans Petter Selasky }
122cfc9c386SHans Petter Selasky 
123cfc9c386SHans Petter Selasky static int
124e870c0abSSlava Shwartsman mlx5e_get_max_alloc(struct mlx5e_priv *priv)
125e870c0abSSlava Shwartsman {
126e870c0abSSlava Shwartsman 	struct mlx5_core_dev *mdev = priv->mdev;
127e870c0abSSlava Shwartsman 	int err;
128e870c0abSSlava Shwartsman 	int x;
129e870c0abSSlava Shwartsman 
130e870c0abSSlava Shwartsman 	PRIV_LOCK(priv);
131e870c0abSSlava Shwartsman 	err = -mlx5_query_port_tc_bw_alloc(mdev, priv->params_ethtool.max_bw_share);
132e870c0abSSlava Shwartsman 	if (err == 0) {
133e870c0abSSlava Shwartsman 		/* set default value */
134e870c0abSSlava Shwartsman 		for (x = 0; x != IEEE_8021QAZ_MAX_TCS; x++) {
135e870c0abSSlava Shwartsman 			priv->params_ethtool.max_bw_share[x] =
136e870c0abSSlava Shwartsman 			    100 / IEEE_8021QAZ_MAX_TCS;
137e870c0abSSlava Shwartsman 		}
138e870c0abSSlava Shwartsman 		err = -mlx5_set_port_tc_bw_alloc(mdev,
139e870c0abSSlava Shwartsman 		    priv->params_ethtool.max_bw_share);
140e870c0abSSlava Shwartsman 	}
141e870c0abSSlava Shwartsman 	PRIV_UNLOCK(priv);
142e870c0abSSlava Shwartsman 
143e870c0abSSlava Shwartsman 	return (err);
144e870c0abSSlava Shwartsman }
145e870c0abSSlava Shwartsman 
146e870c0abSSlava Shwartsman static int
147ed0cee0bSHans Petter Selasky mlx5e_get_dscp(struct mlx5e_priv *priv)
148ed0cee0bSHans Petter Selasky {
149ed0cee0bSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
150ed0cee0bSHans Petter Selasky 	int err;
151ed0cee0bSHans Petter Selasky 
152ed0cee0bSHans Petter Selasky 	if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 ||
153ed0cee0bSHans Petter Selasky 	    MLX5_CAP_QCAM_REG(mdev, qpts) == 0 ||
154ed0cee0bSHans Petter Selasky 	    MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0)
155ed0cee0bSHans Petter Selasky 		return (EOPNOTSUPP);
156ed0cee0bSHans Petter Selasky 
157ed0cee0bSHans Petter Selasky 	PRIV_LOCK(priv);
158ed0cee0bSHans Petter Selasky 	err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio);
159ed0cee0bSHans Petter Selasky 	if (err)
160ed0cee0bSHans Petter Selasky 		goto done;
161ed0cee0bSHans Petter Selasky 
162ed0cee0bSHans Petter Selasky 	err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state);
163ed0cee0bSHans Petter Selasky 	if (err)
164ed0cee0bSHans Petter Selasky 		goto done;
165ed0cee0bSHans Petter Selasky done:
166ed0cee0bSHans Petter Selasky 	PRIV_UNLOCK(priv);
167ed0cee0bSHans Petter Selasky 	return (err);
168ed0cee0bSHans Petter Selasky }
169ed0cee0bSHans Petter Selasky 
170e870c0abSSlava Shwartsman static void
171e870c0abSSlava Shwartsman mlx5e_tc_get_parameters(struct mlx5e_priv *priv,
172e870c0abSSlava Shwartsman     u64 *new_bw_value, u8 *max_bw_value, u8 *max_bw_unit)
173e870c0abSSlava Shwartsman {
174e870c0abSSlava Shwartsman 	const u64 upper_limit_mbps = 255 * MLX5E_100MB;
175e870c0abSSlava Shwartsman 	const u64 upper_limit_gbps = 255 * MLX5E_1GB;
176e870c0abSSlava Shwartsman 	u64 temp;
177e870c0abSSlava Shwartsman 	int i;
178e870c0abSSlava Shwartsman 
179e870c0abSSlava Shwartsman 	memset(max_bw_value, 0, IEEE_8021QAZ_MAX_TCS);
180e870c0abSSlava Shwartsman 	memset(max_bw_unit, 0, IEEE_8021QAZ_MAX_TCS);
181e870c0abSSlava Shwartsman 
182e870c0abSSlava Shwartsman 	for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) {
183e870c0abSSlava Shwartsman 		temp = (new_bw_value != NULL) ?
184e870c0abSSlava Shwartsman 		    new_bw_value[i] : priv->params_ethtool.max_bw_value[i];
185e870c0abSSlava Shwartsman 
186e870c0abSSlava Shwartsman 		if (!temp) {
187e870c0abSSlava Shwartsman 			max_bw_unit[i] = MLX5_BW_NO_LIMIT;
188e870c0abSSlava Shwartsman 		} else if (temp > upper_limit_gbps) {
189e870c0abSSlava Shwartsman 			max_bw_unit[i] = MLX5_BW_NO_LIMIT;
190e870c0abSSlava Shwartsman 		} else if (temp <= upper_limit_mbps) {
191e870c0abSSlava Shwartsman 			max_bw_value[i] = howmany(temp, MLX5E_100MB);
192e870c0abSSlava Shwartsman 			max_bw_unit[i]  = MLX5_100_MBPS_UNIT;
193e870c0abSSlava Shwartsman 		} else {
194e870c0abSSlava Shwartsman 			max_bw_value[i] = howmany(temp, MLX5E_1GB);
195e870c0abSSlava Shwartsman 			max_bw_unit[i]  = MLX5_GBPS_UNIT;
196e870c0abSSlava Shwartsman 		}
197e870c0abSSlava Shwartsman 	}
198e870c0abSSlava Shwartsman }
199e870c0abSSlava Shwartsman 
200ed0cee0bSHans Petter Selasky static int
201cfc9c386SHans Petter Selasky mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS)
202cfc9c386SHans Petter Selasky {
203cfc9c386SHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
204cfc9c386SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
205cfc9c386SHans Petter Selasky 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
206cfc9c386SHans Petter Selasky 	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
207e870c0abSSlava Shwartsman 	u64 new_bw_value[IEEE_8021QAZ_MAX_TCS];
208e870c0abSSlava Shwartsman 	u8 max_rates = mlx5_max_tc(mdev) + 1;
209e870c0abSSlava Shwartsman 	u8 x;
210e870c0abSSlava Shwartsman 	int err;
211cfc9c386SHans Petter Selasky 
212cfc9c386SHans Petter Selasky 	PRIV_LOCK(priv);
213e870c0abSSlava Shwartsman 	err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_value,
214e870c0abSSlava Shwartsman 	    sizeof(priv->params_ethtool.max_bw_value[0]) * max_rates);
215e870c0abSSlava Shwartsman 	if (err || !req->newptr)
216e870c0abSSlava Shwartsman 		goto done;
217e870c0abSSlava Shwartsman 	err = SYSCTL_IN(req, new_bw_value,
218e870c0abSSlava Shwartsman 	    sizeof(new_bw_value[0]) * max_rates);
219e870c0abSSlava Shwartsman 	if (err)
220cfc9c386SHans Petter Selasky 		goto done;
221cfc9c386SHans Petter Selasky 
222e870c0abSSlava Shwartsman 	/* range check input value */
223e870c0abSSlava Shwartsman 	for (x = 0; x != max_rates; x++) {
224e870c0abSSlava Shwartsman 		if (new_bw_value[x] % MLX5E_100MB) {
225cfc9c386SHans Petter Selasky 			err = ERANGE;
226cfc9c386SHans Petter Selasky 			goto done;
227cfc9c386SHans Petter Selasky 		}
228cfc9c386SHans Petter Selasky 	}
229e870c0abSSlava Shwartsman 
230e870c0abSSlava Shwartsman 	mlx5e_tc_get_parameters(priv, new_bw_value, max_bw_value, max_bw_unit);
231cfc9c386SHans Petter Selasky 
232cfc9c386SHans Petter Selasky 	err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
233cfc9c386SHans Petter Selasky 	if (err)
234cfc9c386SHans Petter Selasky 		goto done;
235cfc9c386SHans Petter Selasky 
236e870c0abSSlava Shwartsman 	memcpy(priv->params_ethtool.max_bw_value, new_bw_value,
237e870c0abSSlava Shwartsman 	    sizeof(priv->params_ethtool.max_bw_value));
238e870c0abSSlava Shwartsman done:
239e870c0abSSlava Shwartsman 	PRIV_UNLOCK(priv);
240e870c0abSSlava Shwartsman 	return (err);
241e870c0abSSlava Shwartsman }
242e870c0abSSlava Shwartsman 
243e870c0abSSlava Shwartsman static int
244e870c0abSSlava Shwartsman mlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS)
245e870c0abSSlava Shwartsman {
246e870c0abSSlava Shwartsman 	struct mlx5e_priv *priv = arg1;
247e870c0abSSlava Shwartsman 	struct mlx5_core_dev *mdev = priv->mdev;
248e870c0abSSlava Shwartsman 	u8 max_bw_share[IEEE_8021QAZ_MAX_TCS];
249e870c0abSSlava Shwartsman 	u8 max_rates = mlx5_max_tc(mdev) + 1;
250e870c0abSSlava Shwartsman 	int i;
251e870c0abSSlava Shwartsman 	int err;
252e870c0abSSlava Shwartsman 	int sum;
253e870c0abSSlava Shwartsman 
254e870c0abSSlava Shwartsman 	PRIV_LOCK(priv);
255e870c0abSSlava Shwartsman 	err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_share, max_rates);
256e870c0abSSlava Shwartsman 	if (err || !req->newptr)
257e870c0abSSlava Shwartsman 		goto done;
258e870c0abSSlava Shwartsman 	err = SYSCTL_IN(req, max_bw_share, max_rates);
259e870c0abSSlava Shwartsman 	if (err)
260e870c0abSSlava Shwartsman 		goto done;
261e870c0abSSlava Shwartsman 
262e870c0abSSlava Shwartsman 	/* range check input value */
263e870c0abSSlava Shwartsman 	for (sum = i = 0; i != max_rates; i++) {
264e870c0abSSlava Shwartsman 		if (max_bw_share[i] < 1 || max_bw_share[i] > 100) {
265e870c0abSSlava Shwartsman 			err = ERANGE;
266e870c0abSSlava Shwartsman 			goto done;
267e870c0abSSlava Shwartsman 		}
268e870c0abSSlava Shwartsman 		sum += max_bw_share[i];
269e870c0abSSlava Shwartsman 	}
270e870c0abSSlava Shwartsman 
271e870c0abSSlava Shwartsman 	/* sum of values should be as close to 100 as possible */
272e870c0abSSlava Shwartsman 	if (sum < (100 - max_rates + 1) || sum > 100) {
273e870c0abSSlava Shwartsman 		err = ERANGE;
274e870c0abSSlava Shwartsman 		goto done;
275e870c0abSSlava Shwartsman 	}
276e870c0abSSlava Shwartsman 
277e870c0abSSlava Shwartsman 	err = -mlx5_set_port_tc_bw_alloc(mdev, max_bw_share);
278e870c0abSSlava Shwartsman 	if (err)
279e870c0abSSlava Shwartsman 		goto done;
280e870c0abSSlava Shwartsman 
281e870c0abSSlava Shwartsman 	memcpy(priv->params_ethtool.max_bw_share, max_bw_share,
282e870c0abSSlava Shwartsman 	    sizeof(priv->params_ethtool.max_bw_share));
283cfc9c386SHans Petter Selasky done:
284cfc9c386SHans Petter Selasky 	PRIV_UNLOCK(priv);
285cfc9c386SHans Petter Selasky 	return (err);
286cfc9c386SHans Petter Selasky }
287cfc9c386SHans Petter Selasky 
2882e9c3a4fSHans Petter Selasky static int
2892e9c3a4fSHans Petter Selasky mlx5e_get_prio_tc(struct mlx5e_priv *priv)
2902e9c3a4fSHans Petter Selasky {
2912e9c3a4fSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
2922e9c3a4fSHans Petter Selasky 	int err = 0;
2932e9c3a4fSHans Petter Selasky 	int i;
2942e9c3a4fSHans Petter Selasky 
2952e9c3a4fSHans Petter Selasky 	PRIV_LOCK(priv);
2962e9c3a4fSHans Petter Selasky 	if (!MLX5_CAP_GEN(priv->mdev, ets)) {
2972e9c3a4fSHans Petter Selasky 		PRIV_UNLOCK(priv);
2982e9c3a4fSHans Petter Selasky 		return (EOPNOTSUPP);
2992e9c3a4fSHans Petter Selasky 	}
3002e9c3a4fSHans Petter Selasky 
3012e9c3a4fSHans Petter Selasky 	for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) {
3022e9c3a4fSHans Petter Selasky 		err = -mlx5_query_port_prio_tc(mdev, i, &(priv->params_ethtool.prio_tc[i]));
3032e9c3a4fSHans Petter Selasky 		if (err)
3042e9c3a4fSHans Petter Selasky 			break;
3052e9c3a4fSHans Petter Selasky 	}
3062e9c3a4fSHans Petter Selasky 	PRIV_UNLOCK(priv);
3072e9c3a4fSHans Petter Selasky 	return (err);
3082e9c3a4fSHans Petter Selasky }
3092e9c3a4fSHans Petter Selasky 
3102e9c3a4fSHans Petter Selasky static int
3112e9c3a4fSHans Petter Selasky mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS)
3122e9c3a4fSHans Petter Selasky {
3132e9c3a4fSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
3142e9c3a4fSHans Petter Selasky 	int prio_index = arg2;
3152e9c3a4fSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
3162e9c3a4fSHans Petter Selasky 	int err;
317e870c0abSSlava Shwartsman 	uint8_t result;
3182e9c3a4fSHans Petter Selasky 
3192e9c3a4fSHans Petter Selasky 	PRIV_LOCK(priv);
320e870c0abSSlava Shwartsman 	result = priv->params_ethtool.prio_tc[prio_index];
3212e9c3a4fSHans Petter Selasky 	err = sysctl_handle_8(oidp, &result, 0, req);
3222e9c3a4fSHans Petter Selasky 	if (err || !req->newptr ||
3232e9c3a4fSHans Petter Selasky 	    result == priv->params_ethtool.prio_tc[prio_index])
3242e9c3a4fSHans Petter Selasky 		goto done;
3252e9c3a4fSHans Petter Selasky 
3262e9c3a4fSHans Petter Selasky 	if (result > mlx5_max_tc(mdev)) {
3272e9c3a4fSHans Petter Selasky 		err = ERANGE;
3282e9c3a4fSHans Petter Selasky 		goto done;
3292e9c3a4fSHans Petter Selasky 	}
3302e9c3a4fSHans Petter Selasky 
3312e9c3a4fSHans Petter Selasky 	err = -mlx5_set_port_prio_tc(mdev, prio_index, result);
3322e9c3a4fSHans Petter Selasky 	if (err)
3332e9c3a4fSHans Petter Selasky 		goto done;
3342e9c3a4fSHans Petter Selasky 
3352e9c3a4fSHans Petter Selasky 	priv->params_ethtool.prio_tc[prio_index] = result;
3362e9c3a4fSHans Petter Selasky 
3372e9c3a4fSHans Petter Selasky done:
3382e9c3a4fSHans Petter Selasky 	PRIV_UNLOCK(priv);
3392e9c3a4fSHans Petter Selasky 	return (err);
3402e9c3a4fSHans Petter Selasky }
3412e9c3a4fSHans Petter Selasky 
342ed0cee0bSHans Petter Selasky static int
343ed0cee0bSHans Petter Selasky mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS)
344ed0cee0bSHans Petter Selasky {
345ed0cee0bSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
346ed0cee0bSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
347ed0cee0bSHans Petter Selasky 	int err;
348ed0cee0bSHans Petter Selasky 	u8 result;
349ed0cee0bSHans Petter Selasky 
350ed0cee0bSHans Petter Selasky 	PRIV_LOCK(priv);
351ed0cee0bSHans Petter Selasky 	result = priv->params_ethtool.trust_state;
352ed0cee0bSHans Petter Selasky 	err = sysctl_handle_8(oidp, &result, 0, req);
353ed0cee0bSHans Petter Selasky 	if (err || !req->newptr ||
354ed0cee0bSHans Petter Selasky 	    result == priv->params_ethtool.trust_state)
355ed0cee0bSHans Petter Selasky 		goto done;
356ed0cee0bSHans Petter Selasky 
357ed0cee0bSHans Petter Selasky 	switch (result) {
358ed0cee0bSHans Petter Selasky 	case MLX5_QPTS_TRUST_PCP:
359ed0cee0bSHans Petter Selasky 	case MLX5_QPTS_TRUST_DSCP:
360ed0cee0bSHans Petter Selasky 		break;
361ed0cee0bSHans Petter Selasky 	case MLX5_QPTS_TRUST_BOTH:
362ed0cee0bSHans Petter Selasky 		if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) {
363ed0cee0bSHans Petter Selasky 			err = EOPNOTSUPP;
364ed0cee0bSHans Petter Selasky 			goto done;
365ed0cee0bSHans Petter Selasky 		}
366ed0cee0bSHans Petter Selasky 		break;
367ed0cee0bSHans Petter Selasky 	default:
368ed0cee0bSHans Petter Selasky 		err = ERANGE;
369ed0cee0bSHans Petter Selasky 		goto done;
370ed0cee0bSHans Petter Selasky 	}
371ed0cee0bSHans Petter Selasky 
372ed0cee0bSHans Petter Selasky 	err = -mlx5_set_trust_state(mdev, result);
373ed0cee0bSHans Petter Selasky 	if (err)
374ed0cee0bSHans Petter Selasky 		goto done;
375ed0cee0bSHans Petter Selasky 
376ed0cee0bSHans Petter Selasky 	priv->params_ethtool.trust_state = result;
3773e581cabSSlava Shwartsman 
3783e581cabSSlava Shwartsman 	/* update inline mode */
3793e581cabSSlava Shwartsman 	mlx5e_refresh_sq_inline(priv);
3803e581cabSSlava Shwartsman #ifdef RATELIMIT
3813e581cabSSlava Shwartsman 	mlx5e_rl_refresh_sq_inline(&priv->rl);
3823e581cabSSlava Shwartsman #endif
383ed0cee0bSHans Petter Selasky done:
384ed0cee0bSHans Petter Selasky 	PRIV_UNLOCK(priv);
385ed0cee0bSHans Petter Selasky 	return (err);
386ed0cee0bSHans Petter Selasky }
387ed0cee0bSHans Petter Selasky 
388ed0cee0bSHans Petter Selasky static int
389ed0cee0bSHans Petter Selasky mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS)
390ed0cee0bSHans Petter Selasky {
391ed0cee0bSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
392ed0cee0bSHans Petter Selasky 	int prio_index = arg2;
393ed0cee0bSHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
394ed0cee0bSHans Petter Selasky 	uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP];
395ed0cee0bSHans Petter Selasky 	uint8_t x;
396ed0cee0bSHans Petter Selasky 	int err;
397ed0cee0bSHans Petter Selasky 
398ed0cee0bSHans Petter Selasky 	PRIV_LOCK(priv);
399ed0cee0bSHans Petter Selasky 	err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index,
400ed0cee0bSHans Petter Selasky 	    sizeof(priv->params_ethtool.dscp2prio) / 8);
401ed0cee0bSHans Petter Selasky 	if (err || !req->newptr)
402ed0cee0bSHans Petter Selasky 		goto done;
403ed0cee0bSHans Petter Selasky 
404ed0cee0bSHans Petter Selasky 	memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio));
405ed0cee0bSHans Petter Selasky 	err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8);
406ed0cee0bSHans Petter Selasky 	if (err)
407ed0cee0bSHans Petter Selasky 		goto done;
408ed0cee0bSHans Petter Selasky 	for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) {
409ed0cee0bSHans Petter Selasky 		if (dscp2prio[x] > 7) {
410ed0cee0bSHans Petter Selasky 			err = ERANGE;
411ed0cee0bSHans Petter Selasky 			goto done;
412ed0cee0bSHans Petter Selasky 		}
413ed0cee0bSHans Petter Selasky 	}
414ed0cee0bSHans Petter Selasky 	err = -mlx5_set_dscp2prio(mdev, dscp2prio);
415ed0cee0bSHans Petter Selasky 	if (err)
416ed0cee0bSHans Petter Selasky 		goto done;
417ed0cee0bSHans Petter Selasky 
418ed0cee0bSHans Petter Selasky 	/* update local array */
419ed0cee0bSHans Petter Selasky 	memcpy(priv->params_ethtool.dscp2prio, dscp2prio,
420ed0cee0bSHans Petter Selasky 	    sizeof(priv->params_ethtool.dscp2prio));
421ed0cee0bSHans Petter Selasky done:
422ed0cee0bSHans Petter Selasky 	PRIV_UNLOCK(priv);
423ed0cee0bSHans Petter Selasky 	return (err);
424ed0cee0bSHans Petter Selasky }
425ed0cee0bSHans Petter Selasky 
42682d2623eSHans Petter Selasky #define	MLX5_PARAM_OFFSET(n)				\
42782d2623eSHans Petter Selasky     __offsetof(struct mlx5e_priv, params_ethtool.n)
42882d2623eSHans Petter Selasky 
429dc7e38acSHans Petter Selasky static int
430dc7e38acSHans Petter Selasky mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)
431dc7e38acSHans Petter Selasky {
432dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
433dc7e38acSHans Petter Selasky 	uint64_t value;
434d2bf00a9SHans Petter Selasky 	int mode_modify;
435dc7e38acSHans Petter Selasky 	int was_opened;
436dc7e38acSHans Petter Selasky 	int error;
437dc7e38acSHans Petter Selasky 
438dc7e38acSHans Petter Selasky 	PRIV_LOCK(priv);
439dc7e38acSHans Petter Selasky 	value = priv->params_ethtool.arg[arg2];
440ec0143b2SHans Petter Selasky 	if (req != NULL) {
441dc7e38acSHans Petter Selasky 		error = sysctl_handle_64(oidp, &value, 0, req);
442dc7e38acSHans Petter Selasky 		if (error || req->newptr == NULL ||
443dc7e38acSHans Petter Selasky 		    value == priv->params_ethtool.arg[arg2])
444dc7e38acSHans Petter Selasky 			goto done;
445dc7e38acSHans Petter Selasky 
446dc7e38acSHans Petter Selasky 		/* assign new value */
447dc7e38acSHans Petter Selasky 		priv->params_ethtool.arg[arg2] = value;
448ec0143b2SHans Petter Selasky 	} else {
449ec0143b2SHans Petter Selasky 		error = 0;
450ec0143b2SHans Petter Selasky 	}
451dc7e38acSHans Petter Selasky 	/* check if device is gone */
452dc7e38acSHans Petter Selasky 	if (priv->gone) {
453dc7e38acSHans Petter Selasky 		error = ENXIO;
454dc7e38acSHans Petter Selasky 		goto done;
455dc7e38acSHans Petter Selasky 	}
45682d2623eSHans Petter Selasky 	was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
457d2bf00a9SHans Petter Selasky 	mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify);
45882d2623eSHans Petter Selasky 
45982d2623eSHans Petter Selasky 	switch (MLX5_PARAM_OFFSET(arg[arg2])) {
46082d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_usecs):
461f03f517bSHans Petter Selasky 		/* import RX coal time */
462f03f517bSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_usecs < 1)
463f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_usecs = 0;
464f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.rx_coalesce_usecs >
465f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_period)) {
466f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_usecs =
467f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_period);
468f03f517bSHans Petter Selasky 		}
46982d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_usec =
47082d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_usecs;
471f03f517bSHans Petter Selasky 
47282d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
47382d2623eSHans Petter Selasky 		if (was_opened)
47482d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
47582d2623eSHans Petter Selasky 		break;
47682d2623eSHans Petter Selasky 
47782d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_pkts):
478f03f517bSHans Petter Selasky 		/* import RX coal pkts */
479f03f517bSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_pkts < 1)
480f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_pkts = 0;
481f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.rx_coalesce_pkts >
482f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
483f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_pkts =
484f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_max_count);
485f03f517bSHans Petter Selasky 		}
48682d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_pkts =
48782d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_pkts;
488f03f517bSHans Petter Selasky 
48982d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
49082d2623eSHans Petter Selasky 		if (was_opened)
49182d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
49282d2623eSHans Petter Selasky 		break;
49382d2623eSHans Petter Selasky 
49482d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_usecs):
495f03f517bSHans Petter Selasky 		/* import TX coal time */
496f03f517bSHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_usecs < 1)
497f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_usecs = 0;
498f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.tx_coalesce_usecs >
499f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_period)) {
500f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_usecs =
501f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_period);
502f03f517bSHans Petter Selasky 		}
50382d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_usec =
50482d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_usecs;
505f03f517bSHans Petter Selasky 
50682d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
50782d2623eSHans Petter Selasky 		if (was_opened)
50882d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
50982d2623eSHans Petter Selasky 		break;
51082d2623eSHans Petter Selasky 
51182d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_pkts):
512f03f517bSHans Petter Selasky 		/* import TX coal pkts */
513f03f517bSHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_pkts < 1)
514f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_pkts = 0;
515f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.tx_coalesce_pkts >
516f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
51782d2623eSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_pkts =
51882d2623eSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_max_count);
519f03f517bSHans Petter Selasky 		}
52082d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_pkts =
52182d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_pkts;
522dc7e38acSHans Petter Selasky 
52382d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
52482d2623eSHans Petter Selasky 		if (was_opened)
525f03f517bSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
52682d2623eSHans Petter Selasky 		break;
52782d2623eSHans Petter Selasky 
52882d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_queue_size):
52982d2623eSHans Petter Selasky 		/* network interface must be down */
53082d2623eSHans Petter Selasky 		if (was_opened)
531f03f517bSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
53282d2623eSHans Petter Selasky 
533dc7e38acSHans Petter Selasky 		/* import TX queue size */
534dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.tx_queue_size <
535dc7e38acSHans Petter Selasky 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
536dc7e38acSHans Petter Selasky 			priv->params_ethtool.tx_queue_size =
537dc7e38acSHans Petter Selasky 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE);
538dc7e38acSHans Petter Selasky 		} else if (priv->params_ethtool.tx_queue_size >
539dc7e38acSHans Petter Selasky 		    priv->params_ethtool.tx_queue_size_max) {
540dc7e38acSHans Petter Selasky 			priv->params_ethtool.tx_queue_size =
541dc7e38acSHans Petter Selasky 			    priv->params_ethtool.tx_queue_size_max;
542dc7e38acSHans Petter Selasky 		}
54382d2623eSHans Petter Selasky 		/* store actual TX queue size */
544dc7e38acSHans Petter Selasky 		priv->params.log_sq_size =
545dc7e38acSHans Petter Selasky 		    order_base_2(priv->params_ethtool.tx_queue_size);
54682d2623eSHans Petter Selasky 		priv->params_ethtool.tx_queue_size =
54782d2623eSHans Petter Selasky 		    1 << priv->params.log_sq_size;
54882d2623eSHans Petter Selasky 
54982d2623eSHans Petter Selasky 		/* verify TX completion factor */
55082d2623eSHans Petter Selasky 		mlx5e_ethtool_sync_tx_completion_fact(priv);
55182d2623eSHans Petter Selasky 
55282d2623eSHans Petter Selasky 		/* restart network interface, if any */
55382d2623eSHans Petter Selasky 		if (was_opened)
55482d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
55582d2623eSHans Petter Selasky 		break;
55682d2623eSHans Petter Selasky 
55782d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_queue_size):
55882d2623eSHans Petter Selasky 		/* network interface must be down */
55982d2623eSHans Petter Selasky 		if (was_opened)
56082d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
561dc7e38acSHans Petter Selasky 
562dc7e38acSHans Petter Selasky 		/* import RX queue size */
563dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.rx_queue_size <
564dc7e38acSHans Petter Selasky 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) {
565dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_queue_size =
566dc7e38acSHans Petter Selasky 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE);
567dc7e38acSHans Petter Selasky 		} else if (priv->params_ethtool.rx_queue_size >
568dc7e38acSHans Petter Selasky 		    priv->params_ethtool.rx_queue_size_max) {
569dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_queue_size =
570dc7e38acSHans Petter Selasky 			    priv->params_ethtool.rx_queue_size_max;
571dc7e38acSHans Petter Selasky 		}
57282d2623eSHans Petter Selasky 		/* store actual RX queue size */
573dc7e38acSHans Petter Selasky 		priv->params.log_rq_size =
574dc7e38acSHans Petter Selasky 		    order_base_2(priv->params_ethtool.rx_queue_size);
57582d2623eSHans Petter Selasky 		priv->params_ethtool.rx_queue_size =
57682d2623eSHans Petter Selasky 		    1 << priv->params.log_rq_size;
577dc7e38acSHans Petter Selasky 
57882d2623eSHans Petter Selasky 		/* update least number of RX WQEs */
57982d2623eSHans Petter Selasky 		priv->params.min_rx_wqes = min(
580dc7e38acSHans Petter Selasky 		    priv->params_ethtool.rx_queue_size - 1,
581dc7e38acSHans Petter Selasky 		    MLX5E_PARAMS_DEFAULT_MIN_RX_WQES);
582dc7e38acSHans Petter Selasky 
58382d2623eSHans Petter Selasky 		/* restart network interface, if any */
58482d2623eSHans Petter Selasky 		if (was_opened)
58582d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
58682d2623eSHans Petter Selasky 		break;
58782d2623eSHans Petter Selasky 
58816ae32f9SHans Petter Selasky 	case MLX5_PARAM_OFFSET(channels_rsss):
58916ae32f9SHans Petter Selasky 		/* network interface must be down */
59016ae32f9SHans Petter Selasky 		if (was_opened)
59116ae32f9SHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
59216ae32f9SHans Petter Selasky 
59316ae32f9SHans Petter Selasky 		/* import number of channels */
59416ae32f9SHans Petter Selasky 		if (priv->params_ethtool.channels_rsss < 1)
59516ae32f9SHans Petter Selasky 			priv->params_ethtool.channels_rsss = 1;
59616ae32f9SHans Petter Selasky 		else if (priv->params_ethtool.channels_rsss > 128)
59716ae32f9SHans Petter Selasky 			priv->params_ethtool.channels_rsss = 128;
59816ae32f9SHans Petter Selasky 
59916ae32f9SHans Petter Selasky 		priv->params.channels_rsss = priv->params_ethtool.channels_rsss;
60016ae32f9SHans Petter Selasky 
60116ae32f9SHans Petter Selasky 		/* restart network interface, if any */
60216ae32f9SHans Petter Selasky 		if (was_opened)
60316ae32f9SHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
60416ae32f9SHans Petter Selasky 		break;
60516ae32f9SHans Petter Selasky 
60682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(channels):
60782d2623eSHans Petter Selasky 		/* network interface must be down */
60882d2623eSHans Petter Selasky 		if (was_opened)
60982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
61082d2623eSHans Petter Selasky 
611dc7e38acSHans Petter Selasky 		/* import number of channels */
612dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.channels < 1)
613dc7e38acSHans Petter Selasky 			priv->params_ethtool.channels = 1;
614dc7e38acSHans Petter Selasky 		else if (priv->params_ethtool.channels >
615dc7e38acSHans Petter Selasky 		    (u64) priv->mdev->priv.eq_table.num_comp_vectors) {
616dc7e38acSHans Petter Selasky 			priv->params_ethtool.channels =
617dc7e38acSHans Petter Selasky 			    (u64) priv->mdev->priv.eq_table.num_comp_vectors;
618dc7e38acSHans Petter Selasky 		}
619dc7e38acSHans Petter Selasky 		priv->params.num_channels = priv->params_ethtool.channels;
620dc7e38acSHans Petter Selasky 
62182d2623eSHans Petter Selasky 		/* restart network interface, if any */
62282d2623eSHans Petter Selasky 		if (was_opened)
62382d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
62482d2623eSHans Petter Selasky 		break;
62582d2623eSHans Petter Selasky 
62682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_mode):
62782d2623eSHans Petter Selasky 		/* network interface must be down */
628d2bf00a9SHans Petter Selasky 		if (was_opened != 0 && mode_modify == 0)
62982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
63082d2623eSHans Petter Selasky 
63182d2623eSHans Petter Selasky 		/* import RX coalesce mode */
632dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_mode != 0)
633dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_mode = 1;
63482d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_mode =
63582d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_mode;
636dc7e38acSHans Petter Selasky 
63782d2623eSHans Petter Selasky 		/* restart network interface, if any */
638d2bf00a9SHans Petter Selasky 		if (was_opened != 0) {
639d2bf00a9SHans Petter Selasky 			if (mode_modify == 0)
64082d2623eSHans Petter Selasky 				mlx5e_open_locked(priv->ifp);
641d2bf00a9SHans Petter Selasky 			else
642d2bf00a9SHans Petter Selasky 				error = mlx5e_refresh_channel_params(priv);
643d2bf00a9SHans Petter Selasky 		}
64482d2623eSHans Petter Selasky 		break;
64582d2623eSHans Petter Selasky 
64682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_mode):
64782d2623eSHans Petter Selasky 		/* network interface must be down */
648d2bf00a9SHans Petter Selasky 		if (was_opened != 0 && mode_modify == 0)
64982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
65082d2623eSHans Petter Selasky 
65182d2623eSHans Petter Selasky 		/* import TX coalesce mode */
65274540a31SHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_mode != 0)
65374540a31SHans Petter Selasky 			priv->params_ethtool.tx_coalesce_mode = 1;
65482d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_mode =
65582d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_mode;
65674540a31SHans Petter Selasky 
65782d2623eSHans Petter Selasky 		/* restart network interface, if any */
658d2bf00a9SHans Petter Selasky 		if (was_opened != 0) {
659d2bf00a9SHans Petter Selasky 			if (mode_modify == 0)
66082d2623eSHans Petter Selasky 				mlx5e_open_locked(priv->ifp);
661d2bf00a9SHans Petter Selasky 			else
662d2bf00a9SHans Petter Selasky 				error = mlx5e_refresh_channel_params(priv);
663d2bf00a9SHans Petter Selasky 		}
66482d2623eSHans Petter Selasky 		break;
66582d2623eSHans Petter Selasky 
66682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(hw_lro):
66782d2623eSHans Petter Selasky 		/* network interface must be down */
66882d2623eSHans Petter Selasky 		if (was_opened)
66982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
67082d2623eSHans Petter Selasky 
67182d2623eSHans Petter Selasky 		/* import HW LRO mode */
672d7633a30SHans Petter Selasky 		if (priv->params_ethtool.hw_lro != 0) {
673d7633a30SHans Petter Selasky 			if ((priv->ifp->if_capenable & IFCAP_LRO) &&
674d7633a30SHans Petter Selasky 			    MLX5_CAP_ETH(priv->mdev, lro_cap)) {
675d7633a30SHans Petter Selasky 				priv->params.hw_lro_en = 1;
676d7633a30SHans Petter Selasky 				priv->params_ethtool.hw_lro = 1;
677d7633a30SHans Petter Selasky 			} else {
678d7633a30SHans Petter Selasky 				priv->params.hw_lro_en = 0;
67936c1007dSHans Petter Selasky 				priv->params_ethtool.hw_lro = 0;
68036c1007dSHans Petter Selasky 				error = EINVAL;
681d7633a30SHans Petter Selasky 
682d7633a30SHans Petter Selasky 				if_printf(priv->ifp, "Can't enable HW LRO: "
68382d2623eSHans Petter Selasky 				    "The HW or SW LRO feature is disabled\n");
68436c1007dSHans Petter Selasky 			}
685bb3853c6SHans Petter Selasky 		} else {
686d7633a30SHans Petter Selasky 			priv->params.hw_lro_en = 0;
687dc7e38acSHans Petter Selasky 		}
68882d2623eSHans Petter Selasky 		/* restart network interface, if any */
68982d2623eSHans Petter Selasky 		if (was_opened)
69082d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
69182d2623eSHans Petter Selasky 		break;
692dc7e38acSHans Petter Selasky 
69382d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(cqe_zipping):
69482d2623eSHans Petter Selasky 		/* network interface must be down */
69582d2623eSHans Petter Selasky 		if (was_opened)
69682d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
69782d2623eSHans Petter Selasky 
69882d2623eSHans Petter Selasky 		/* import CQE zipping mode */
69990cc1c77SHans Petter Selasky 		if (priv->params_ethtool.cqe_zipping &&
70090cc1c77SHans Petter Selasky 		    MLX5_CAP_GEN(priv->mdev, cqe_compression)) {
70190cc1c77SHans Petter Selasky 			priv->params.cqe_zipping_en = true;
70290cc1c77SHans Petter Selasky 			priv->params_ethtool.cqe_zipping = 1;
70390cc1c77SHans Petter Selasky 		} else {
70490cc1c77SHans Petter Selasky 			priv->params.cqe_zipping_en = false;
70590cc1c77SHans Petter Selasky 			priv->params_ethtool.cqe_zipping = 0;
70690cc1c77SHans Petter Selasky 		}
70782d2623eSHans Petter Selasky 		/* restart network interface, if any */
708dc7e38acSHans Petter Selasky 		if (was_opened)
709dc7e38acSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
71082d2623eSHans Petter Selasky 		break;
71182d2623eSHans Petter Selasky 
71282d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_completion_fact):
71382d2623eSHans Petter Selasky 		/* network interface must be down */
71482d2623eSHans Petter Selasky 		if (was_opened)
71582d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
71682d2623eSHans Petter Selasky 
71782d2623eSHans Petter Selasky 		/* verify parameter */
71882d2623eSHans Petter Selasky 		mlx5e_ethtool_sync_tx_completion_fact(priv);
71982d2623eSHans Petter Selasky 
72082d2623eSHans Petter Selasky 		/* restart network interface, if any */
72182d2623eSHans Petter Selasky 		if (was_opened)
72282d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
72382d2623eSHans Petter Selasky 		break;
72482d2623eSHans Petter Selasky 
725bb3616abSHans Petter Selasky 	case MLX5_PARAM_OFFSET(modify_tx_dma):
726bb3616abSHans Petter Selasky 		/* check if network interface is opened */
727bb3616abSHans Petter Selasky 		if (was_opened) {
728bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_tx_dma =
729bb3616abSHans Petter Selasky 			    priv->params_ethtool.modify_tx_dma ? 1 : 0;
730bb3616abSHans Petter Selasky 			/* modify tx according to value */
731bb3616abSHans Petter Selasky 			mlx5e_modify_tx_dma(priv, value != 0);
732bb3616abSHans Petter Selasky 		} else {
733bb3616abSHans Petter Selasky 			/* if closed force enable tx */
734bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_tx_dma = 0;
735bb3616abSHans Petter Selasky 		}
736bb3616abSHans Petter Selasky 		break;
737bb3616abSHans Petter Selasky 
738bb3616abSHans Petter Selasky 	case MLX5_PARAM_OFFSET(modify_rx_dma):
739bb3616abSHans Petter Selasky 		/* check if network interface is opened */
740bb3616abSHans Petter Selasky 		if (was_opened) {
741bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_rx_dma =
742bb3616abSHans Petter Selasky 			    priv->params_ethtool.modify_rx_dma ? 1 : 0;
743bb3616abSHans Petter Selasky 			/* modify rx according to value */
744bb3616abSHans Petter Selasky 			mlx5e_modify_rx_dma(priv, value != 0);
745bb3616abSHans Petter Selasky 		} else {
746bb3616abSHans Petter Selasky 			/* if closed force enable rx */
747bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_rx_dma = 0;
748bb3616abSHans Petter Selasky 		}
749bb3616abSHans Petter Selasky 		break;
750bb3616abSHans Petter Selasky 
75166d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_pci_enable):
75266d53750SHans Petter Selasky 		priv->params_ethtool.diag_pci_enable =
75366d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable ? 1 : 0;
75466d53750SHans Petter Selasky 
75566d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
75666d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
75766d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
75866d53750SHans Petter Selasky 		break;
75966d53750SHans Petter Selasky 
76066d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_general_enable):
76166d53750SHans Petter Selasky 		priv->params_ethtool.diag_general_enable =
76266d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable ? 1 : 0;
76366d53750SHans Petter Selasky 
76466d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
76566d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
76666d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
76766d53750SHans Petter Selasky 		break;
76866d53750SHans Petter Selasky 
76961fd7ac0SHans Petter Selasky 	case MLX5_PARAM_OFFSET(mc_local_lb):
77061fd7ac0SHans Petter Selasky 		priv->params_ethtool.mc_local_lb =
77161fd7ac0SHans Petter Selasky 		    priv->params_ethtool.mc_local_lb ? 1 : 0;
77261fd7ac0SHans Petter Selasky 
77361fd7ac0SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) {
77461fd7ac0SHans Petter Selasky 			error = mlx5_nic_vport_modify_local_lb(priv->mdev,
77561fd7ac0SHans Petter Selasky 			    MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb);
77661fd7ac0SHans Petter Selasky 		} else {
77761fd7ac0SHans Petter Selasky 			error = EOPNOTSUPP;
77861fd7ac0SHans Petter Selasky 		}
77961fd7ac0SHans Petter Selasky 		break;
78061fd7ac0SHans Petter Selasky 
78161fd7ac0SHans Petter Selasky 	case MLX5_PARAM_OFFSET(uc_local_lb):
78261fd7ac0SHans Petter Selasky 		priv->params_ethtool.uc_local_lb =
78361fd7ac0SHans Petter Selasky 		    priv->params_ethtool.uc_local_lb ? 1 : 0;
78461fd7ac0SHans Petter Selasky 
78561fd7ac0SHans Petter Selasky 		if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) {
78661fd7ac0SHans Petter Selasky 			error = mlx5_nic_vport_modify_local_lb(priv->mdev,
78761fd7ac0SHans Petter Selasky 			    MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb);
78861fd7ac0SHans Petter Selasky 		} else {
78961fd7ac0SHans Petter Selasky 			error = EOPNOTSUPP;
79061fd7ac0SHans Petter Selasky 		}
79161fd7ac0SHans Petter Selasky 		break;
79261fd7ac0SHans Petter Selasky 
79382d2623eSHans Petter Selasky 	default:
79482d2623eSHans Petter Selasky 		break;
79582d2623eSHans Petter Selasky 	}
796dc7e38acSHans Petter Selasky done:
797dc7e38acSHans Petter Selasky 	PRIV_UNLOCK(priv);
798dc7e38acSHans Petter Selasky 	return (error);
799dc7e38acSHans Petter Selasky }
800dc7e38acSHans Petter Selasky 
801dc7e38acSHans Petter Selasky /*
802dc7e38acSHans Petter Selasky  * Read the first three bytes of the eeprom in order to get the needed info
803dc7e38acSHans Petter Selasky  * for the whole reading.
804dc7e38acSHans Petter Selasky  * Byte 0 - Identifier byte
805dc7e38acSHans Petter Selasky  * Byte 1 - Revision byte
806dc7e38acSHans Petter Selasky  * Byte 2 - Status byte
807dc7e38acSHans Petter Selasky  */
808dc7e38acSHans Petter Selasky static int
809dc7e38acSHans Petter Selasky mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom)
810dc7e38acSHans Petter Selasky {
811dc7e38acSHans Petter Selasky 	struct mlx5_core_dev *dev = priv->mdev;
812dc7e38acSHans Petter Selasky 	u32 data = 0;
813dc7e38acSHans Petter Selasky 	int size_read = 0;
814dc7e38acSHans Petter Selasky 	int ret;
815dc7e38acSHans Petter Selasky 
816dc7e38acSHans Petter Selasky 	ret = mlx5_query_module_num(dev, &eeprom->module_num);
817dc7e38acSHans Petter Selasky 	if (ret) {
818dc7e38acSHans Petter Selasky 		if_printf(priv->ifp, "%s:%d: Failed query module error=%d\n",
819dc7e38acSHans Petter Selasky 		    __func__, __LINE__, ret);
820dc7e38acSHans Petter Selasky 		return (ret);
821dc7e38acSHans Petter Selasky 	}
822dc7e38acSHans Petter Selasky 
823dc7e38acSHans Petter Selasky 	/* Read the first three bytes to get Identifier, Revision and Status */
824dc7e38acSHans Petter Selasky 	ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num,
825dc7e38acSHans Petter Selasky 	    eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data,
826dc7e38acSHans Petter Selasky 	    &size_read);
827dc7e38acSHans Petter Selasky 	if (ret) {
828dc7e38acSHans Petter Selasky 		if_printf(priv->ifp, "%s:%d: Failed query eeprom module error=0x%x\n",
829dc7e38acSHans Petter Selasky 		    __func__, __LINE__, ret);
830dc7e38acSHans Petter Selasky 		return (ret);
831dc7e38acSHans Petter Selasky 	}
832dc7e38acSHans Petter Selasky 
833dc7e38acSHans Petter Selasky 	switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) {
834dc7e38acSHans Petter Selasky 	case SFF_8024_ID_QSFP:
835dc7e38acSHans Petter Selasky 		eeprom->type = MLX5E_ETH_MODULE_SFF_8436;
836dc7e38acSHans Petter Selasky 		eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN;
837dc7e38acSHans Petter Selasky 		break;
838dc7e38acSHans Petter Selasky 	case SFF_8024_ID_QSFPPLUS:
839dc7e38acSHans Petter Selasky 	case SFF_8024_ID_QSFP28:
840dc7e38acSHans Petter Selasky 		if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 ||
841dc7e38acSHans Petter Selasky 		    ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) {
842dc7e38acSHans Petter Selasky 			eeprom->type = MLX5E_ETH_MODULE_SFF_8636;
843dc7e38acSHans Petter Selasky 			eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN;
844dc7e38acSHans Petter Selasky 		} else {
845dc7e38acSHans Petter Selasky 			eeprom->type = MLX5E_ETH_MODULE_SFF_8436;
846dc7e38acSHans Petter Selasky 			eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN;
847dc7e38acSHans Petter Selasky 		}
848dc7e38acSHans Petter Selasky 		if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0)
849dc7e38acSHans Petter Selasky 			eeprom->page_valid = 1;
850dc7e38acSHans Petter Selasky 		break;
851dc7e38acSHans Petter Selasky 	case SFF_8024_ID_SFP:
852dc7e38acSHans Petter Selasky 		eeprom->type = MLX5E_ETH_MODULE_SFF_8472;
853dc7e38acSHans Petter Selasky 		eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN;
854dc7e38acSHans Petter Selasky 		break;
855dc7e38acSHans Petter Selasky 	default:
8567e1b8bc0SHans Petter Selasky 		if_printf(priv->ifp, "%s:%d: Not recognized cable type = 0x%x(%s)\n",
8577e1b8bc0SHans Petter Selasky 		    __func__, __LINE__, data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK,
8587e1b8bc0SHans Petter Selasky 		    sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]);
859dc7e38acSHans Petter Selasky 		return (EINVAL);
860dc7e38acSHans Petter Selasky 	}
861dc7e38acSHans Petter Selasky 	return (0);
862dc7e38acSHans Petter Selasky }
863dc7e38acSHans Petter Selasky 
864dc7e38acSHans Petter Selasky /* Read both low and high pages of the eeprom */
865dc7e38acSHans Petter Selasky static int
866dc7e38acSHans Petter Selasky mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee)
867dc7e38acSHans Petter Selasky {
868dc7e38acSHans Petter Selasky 	struct mlx5_core_dev *dev = priv->mdev;
869dc7e38acSHans Petter Selasky 	int size_read = 0;
870dc7e38acSHans Petter Selasky 	int ret;
871dc7e38acSHans Petter Selasky 
872dc7e38acSHans Petter Selasky 	if (ee->len == 0)
873dc7e38acSHans Petter Selasky 		return (EINVAL);
874dc7e38acSHans Petter Selasky 
875dc7e38acSHans Petter Selasky 	/* Read low page of the eeprom */
876dc7e38acSHans Petter Selasky 	while (ee->device_addr < ee->len) {
877dc7e38acSHans Petter Selasky 		ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr,
878dc7e38acSHans Petter Selasky 		    ee->len - ee->device_addr, ee->module_num,
879dc7e38acSHans Petter Selasky 		    ee->data + (ee->device_addr / 4), &size_read);
880dc7e38acSHans Petter Selasky 		if (ret) {
881dc7e38acSHans Petter Selasky 			if_printf(priv->ifp, "%s:%d: Failed reading eeprom, "
882dc7e38acSHans Petter Selasky 			    "error = 0x%02x\n", __func__, __LINE__, ret);
883dc7e38acSHans Petter Selasky 			return (ret);
884dc7e38acSHans Petter Selasky 		}
885dc7e38acSHans Petter Selasky 		ee->device_addr += size_read;
886dc7e38acSHans Petter Selasky 	}
887dc7e38acSHans Petter Selasky 
888dc7e38acSHans Petter Selasky 	/* Read high page of the eeprom */
889dc7e38acSHans Petter Selasky 	if (ee->page_valid) {
890dc7e38acSHans Petter Selasky 		ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET;
891dc7e38acSHans Petter Selasky 		ee->page_num = MLX5E_EEPROM_HIGH_PAGE;
892dc7e38acSHans Petter Selasky 		size_read = 0;
893dc7e38acSHans Petter Selasky 		while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) {
894dc7e38acSHans Petter Selasky 			ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num,
895dc7e38acSHans Petter Selasky 			    ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr,
896dc7e38acSHans Petter Selasky 			    ee->module_num, ee->data + (ee->len / 4) +
897dc7e38acSHans Petter Selasky 			    ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4),
898dc7e38acSHans Petter Selasky 			    &size_read);
899dc7e38acSHans Petter Selasky 			if (ret) {
900dc7e38acSHans Petter Selasky 				if_printf(priv->ifp, "%s:%d: Failed reading eeprom, "
901dc7e38acSHans Petter Selasky 				    "error = 0x%02x\n", __func__, __LINE__, ret);
902dc7e38acSHans Petter Selasky 				return (ret);
903dc7e38acSHans Petter Selasky 			}
904dc7e38acSHans Petter Selasky 			ee->device_addr += size_read;
905dc7e38acSHans Petter Selasky 		}
906dc7e38acSHans Petter Selasky 	}
907dc7e38acSHans Petter Selasky 	return (0);
908dc7e38acSHans Petter Selasky }
909dc7e38acSHans Petter Selasky 
910dc7e38acSHans Petter Selasky static void
911dc7e38acSHans Petter Selasky mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom)
912dc7e38acSHans Petter Selasky {
913ee41fc8fSHans Petter Selasky 	int row;
914ee41fc8fSHans Petter Selasky 	int index_in_row;
915ee41fc8fSHans Petter Selasky 	int byte_to_write = 0;
916ee41fc8fSHans Petter Selasky 	int line_length = 16;
917dc7e38acSHans Petter Selasky 
918dc7e38acSHans Petter Selasky 	printf("\nOffset\t\tValues\n");
919ee41fc8fSHans Petter Selasky 	printf("------\t\t------");
920ee41fc8fSHans Petter Selasky 	while (byte_to_write < eeprom->len) {
921ee41fc8fSHans Petter Selasky 		printf("\n0x%04X\t\t", byte_to_write);
922ee41fc8fSHans Petter Selasky 		for (index_in_row = 0; index_in_row < line_length; index_in_row++) {
923ee41fc8fSHans Petter Selasky 			printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]);
924ee41fc8fSHans Petter Selasky 			byte_to_write++;
925dc7e38acSHans Petter Selasky 		}
926dc7e38acSHans Petter Selasky 	}
927dc7e38acSHans Petter Selasky 
928dc7e38acSHans Petter Selasky 	if (eeprom->page_valid) {
929dc7e38acSHans Petter Selasky 		row = MLX5E_EEPROM_HIGH_PAGE_OFFSET;
930ee41fc8fSHans Petter Selasky 		printf("\n\nUpper Page 0x03\n");
931dc7e38acSHans Petter Selasky 		printf("\nOffset\t\tValues\n");
932ee41fc8fSHans Petter Selasky 		printf("------\t\t------");
933dc7e38acSHans Petter Selasky 		while (row < MLX5E_EEPROM_PAGE_LENGTH) {
934ee41fc8fSHans Petter Selasky 			printf("\n0x%04X\t\t", row);
935ee41fc8fSHans Petter Selasky 			for (index_in_row = 0; index_in_row < line_length; index_in_row++) {
936ee41fc8fSHans Petter Selasky 				printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]);
937ee41fc8fSHans Petter Selasky 				byte_to_write++;
938dc7e38acSHans Petter Selasky 				row++;
939dc7e38acSHans Petter Selasky 			}
940dc7e38acSHans Petter Selasky 		}
941dc7e38acSHans Petter Selasky 	}
942dc7e38acSHans Petter Selasky }
943dc7e38acSHans Petter Selasky 
944dc7e38acSHans Petter Selasky /*
945dc7e38acSHans Petter Selasky  * Read cable EEPROM module information by first inspecting the first
946dc7e38acSHans Petter Selasky  * three bytes to get the initial information for a whole reading.
947dc7e38acSHans Petter Selasky  * Information will be printed to dmesg.
948dc7e38acSHans Petter Selasky  */
949dc7e38acSHans Petter Selasky static int
950dc7e38acSHans Petter Selasky mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS)
951dc7e38acSHans Petter Selasky {
952dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
953dc7e38acSHans Petter Selasky 	struct mlx5e_eeprom eeprom;
954dc7e38acSHans Petter Selasky 	int error;
955dc7e38acSHans Petter Selasky 	int result = 0;
956dc7e38acSHans Petter Selasky 
957dc7e38acSHans Petter Selasky 	PRIV_LOCK(priv);
958dc7e38acSHans Petter Selasky 	error = sysctl_handle_int(oidp, &result, 0, req);
959dc7e38acSHans Petter Selasky 	if (error || !req->newptr)
960dc7e38acSHans Petter Selasky 		goto done;
961dc7e38acSHans Petter Selasky 
962dc7e38acSHans Petter Selasky 	/* Check if device is gone */
963dc7e38acSHans Petter Selasky 	if (priv->gone) {
964dc7e38acSHans Petter Selasky 		error = ENXIO;
965dc7e38acSHans Petter Selasky 		goto done;
966dc7e38acSHans Petter Selasky 	}
967dc7e38acSHans Petter Selasky 
968dc7e38acSHans Petter Selasky 	if (result == 1) {
969dc7e38acSHans Petter Selasky 		eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW;
970dc7e38acSHans Petter Selasky 		eeprom.device_addr = 0;
971dc7e38acSHans Petter Selasky 		eeprom.page_num = MLX5E_EEPROM_LOW_PAGE;
972dc7e38acSHans Petter Selasky 		eeprom.page_valid = 0;
973dc7e38acSHans Petter Selasky 
974dc7e38acSHans Petter Selasky 		/* Read three first bytes to get important info */
975dc7e38acSHans Petter Selasky 		error = mlx5e_get_eeprom_info(priv, &eeprom);
976dc7e38acSHans Petter Selasky 		if (error) {
977dc7e38acSHans Petter Selasky 			if_printf(priv->ifp, "%s:%d: Failed reading eeprom's "
978dc7e38acSHans Petter Selasky 			    "initial information\n", __func__, __LINE__);
979dc7e38acSHans Petter Selasky 			error = 0;
980dc7e38acSHans Petter Selasky 			goto done;
981dc7e38acSHans Petter Selasky 		}
982bb3853c6SHans Petter Selasky 		/*
983bb3853c6SHans Petter Selasky 		 * Allocate needed length buffer and additional space for
984bb3853c6SHans Petter Selasky 		 * page 0x03
985bb3853c6SHans Petter Selasky 		 */
986dc7e38acSHans Petter Selasky 		eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH,
987dc7e38acSHans Petter Selasky 		    M_MLX5EN, M_WAITOK | M_ZERO);
988dc7e38acSHans Petter Selasky 
989dc7e38acSHans Petter Selasky 		/* Read the whole eeprom information */
990dc7e38acSHans Petter Selasky 		error = mlx5e_get_eeprom(priv, &eeprom);
991dc7e38acSHans Petter Selasky 		if (error) {
992dc7e38acSHans Petter Selasky 			if_printf(priv->ifp, "%s:%d: Failed reading eeprom\n",
993dc7e38acSHans Petter Selasky 			    __func__, __LINE__);
994dc7e38acSHans Petter Selasky 			error = 0;
995bb3853c6SHans Petter Selasky 			/*
996bb3853c6SHans Petter Selasky 			 * Continue printing partial information in case of
997bb3853c6SHans Petter Selasky 			 * an error
998bb3853c6SHans Petter Selasky 			 */
999dc7e38acSHans Petter Selasky 		}
1000dc7e38acSHans Petter Selasky 		mlx5e_print_eeprom(&eeprom);
1001dc7e38acSHans Petter Selasky 		free(eeprom.data, M_MLX5EN);
1002dc7e38acSHans Petter Selasky 	}
1003dc7e38acSHans Petter Selasky done:
1004dc7e38acSHans Petter Selasky 	PRIV_UNLOCK(priv);
1005dc7e38acSHans Petter Selasky 	return (error);
1006dc7e38acSHans Petter Selasky }
1007dc7e38acSHans Petter Selasky 
1008dc7e38acSHans Petter Selasky static const char *mlx5e_params_desc[] = {
1009dc7e38acSHans Petter Selasky 	MLX5E_PARAMS(MLX5E_STATS_DESC)
1010dc7e38acSHans Petter Selasky };
1011dc7e38acSHans Petter Selasky 
1012dc7e38acSHans Petter Selasky static const char *mlx5e_port_stats_debug_desc[] = {
1013dc7e38acSHans Petter Selasky 	MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC)
1014dc7e38acSHans Petter Selasky };
1015dc7e38acSHans Petter Selasky 
1016dc7e38acSHans Petter Selasky static int
1017f2b4782cSHans Petter Selasky mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS)
1018f2b4782cSHans Petter Selasky {
1019f2b4782cSHans Petter Selasky 	struct mlx5e_priv *priv;
1020f2b4782cSHans Petter Selasky 	struct sbuf sb;
1021f2b4782cSHans Petter Selasky 	struct mlx5e_channel *c;
1022f2b4782cSHans Petter Selasky 	struct mlx5e_sq *sq;
1023f2b4782cSHans Petter Selasky 	struct mlx5e_rq *rq;
1024f2b4782cSHans Petter Selasky 	int error, i, tc;
1025f2b4782cSHans Petter Selasky 
1026f2b4782cSHans Petter Selasky 	priv = arg1;
1027f2b4782cSHans Petter Selasky 	error = sysctl_wire_old_buffer(req, 0);
1028f2b4782cSHans Petter Selasky 	if (error != 0)
1029f2b4782cSHans Petter Selasky 		return (error);
1030f2b4782cSHans Petter Selasky 	if (sbuf_new_for_sysctl(&sb, NULL, 128, req) == NULL)
1031f2b4782cSHans Petter Selasky 		return (ENOMEM);
1032f2b4782cSHans Petter Selasky 	sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
1033f2b4782cSHans Petter Selasky 
1034f2b4782cSHans Petter Selasky 	PRIV_LOCK(priv);
1035f2b4782cSHans Petter Selasky 	if (test_bit(MLX5E_STATE_OPENED, &priv->state) == 0)
1036f2b4782cSHans Petter Selasky 		goto out;
1037f2b4782cSHans Petter Selasky 	for (i = 0; i < priv->params.num_channels; i++) {
1038f2b4782cSHans Petter Selasky 		c = priv->channel[i];
1039f2b4782cSHans Petter Selasky 		rq = &c->rq;
1040f2b4782cSHans Petter Selasky 		sbuf_printf(&sb, "channel %d rq %d cq %d\n",
1041f2b4782cSHans Petter Selasky 		    c->ix, rq->rqn, rq->cq.mcq.cqn);
1042f2b4782cSHans Petter Selasky 		for (tc = 0; tc < c->num_tc; tc++) {
1043f2b4782cSHans Petter Selasky 			sq = &c->sq[tc];
1044f2b4782cSHans Petter Selasky 			sbuf_printf(&sb, "channel %d tc %d sq %d cq %d\n",
1045f2b4782cSHans Petter Selasky 			    c->ix, tc, sq->sqn, sq->cq.mcq.cqn);
1046f2b4782cSHans Petter Selasky 		}
1047f2b4782cSHans Petter Selasky 	}
1048f2b4782cSHans Petter Selasky out:
1049f2b4782cSHans Petter Selasky 	PRIV_UNLOCK(priv);
1050f2b4782cSHans Petter Selasky 	error = sbuf_finish(&sb);
1051f2b4782cSHans Petter Selasky 	sbuf_delete(&sb);
1052f2b4782cSHans Petter Selasky 	return (error);
1053f2b4782cSHans Petter Selasky }
1054f2b4782cSHans Petter Selasky 
1055f2b4782cSHans Petter Selasky static int
1056dc7e38acSHans Petter Selasky mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS)
1057dc7e38acSHans Petter Selasky {
1058dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
1059f2b4782cSHans Petter Selasky 	int error, sys_debug;
1060dc7e38acSHans Petter Selasky 
1061dc7e38acSHans Petter Selasky 	sys_debug = priv->sysctl_debug;
1062dc7e38acSHans Petter Selasky 	error = sysctl_handle_int(oidp, &priv->sysctl_debug, 0, req);
1063f2b4782cSHans Petter Selasky 	if (error != 0 || !req->newptr)
1064dc7e38acSHans Petter Selasky 		return (error);
1065f2b4782cSHans Petter Selasky 	priv->sysctl_debug = priv->sysctl_debug != 0;
1066dc7e38acSHans Petter Selasky 	if (sys_debug == priv->sysctl_debug)
1067f2b4782cSHans Petter Selasky 		return (0);
1068f2b4782cSHans Petter Selasky 
1069f2b4782cSHans Petter Selasky 	PRIV_LOCK(priv);
1070f2b4782cSHans Petter Selasky 	if (priv->sysctl_debug) {
1071dc7e38acSHans Petter Selasky 		mlx5e_create_stats(&priv->stats.port_stats_debug.ctx,
1072dc7e38acSHans Petter Selasky 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats",
1073dc7e38acSHans Petter Selasky 		    mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM,
1074dc7e38acSHans Petter Selasky 		    priv->stats.port_stats_debug.arg);
1075f2b4782cSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx_channel_debug,
1076f2b4782cSHans Petter Selasky 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
1077f2b4782cSHans Petter Selasky 		    "hw_ctx_debug",
1078f2b4782cSHans Petter Selasky 		    CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0,
1079f2b4782cSHans Petter Selasky 		    mlx5e_ethtool_debug_channel_info, "S", "");
1080f2b4782cSHans Petter Selasky 	} else {
1081dc7e38acSHans Petter Selasky 		sysctl_ctx_free(&priv->stats.port_stats_debug.ctx);
1082f2b4782cSHans Petter Selasky 		sysctl_ctx_free(&priv->sysctl_ctx_channel_debug);
1083f2b4782cSHans Petter Selasky 	}
1084f2b4782cSHans Petter Selasky 	PRIV_UNLOCK(priv);
1085f2b4782cSHans Petter Selasky 	return (0);
1086dc7e38acSHans Petter Selasky }
1087dc7e38acSHans Petter Selasky 
108866d53750SHans Petter Selasky static void
108966d53750SHans Petter Selasky mlx5e_create_diagnostics(struct mlx5e_priv *priv)
109066d53750SHans Petter Selasky {
109166d53750SHans Petter Selasky 	struct mlx5_core_diagnostics_entry entry;
109266d53750SHans Petter Selasky 	struct sysctl_ctx_list *ctx;
109366d53750SHans Petter Selasky 	struct sysctl_oid *node;
109466d53750SHans Petter Selasky 	int x;
109566d53750SHans Petter Selasky 
109666d53750SHans Petter Selasky 	/* sysctl context we are using */
109766d53750SHans Petter Selasky 	ctx = &priv->sysctl_ctx;
109866d53750SHans Petter Selasky 
109966d53750SHans Petter Selasky 	/* create root node */
110066d53750SHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx,
110166d53750SHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
110266d53750SHans Petter Selasky 	    "diagnostics", CTLFLAG_RD, NULL, "Diagnostics");
110366d53750SHans Petter Selasky 	if (node == NULL)
110466d53750SHans Petter Selasky 		return;
110566d53750SHans Petter Selasky 
110666d53750SHans Petter Selasky 	/* create PCI diagnostics */
110766d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) {
110866d53750SHans Petter Selasky 		entry = mlx5_core_pci_diagnostics_table[x];
110966d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
111066d53750SHans Petter Selasky 			continue;
111166d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
111266d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_pci.array + x,
111366d53750SHans Petter Selasky 		    "PCI diagnostics counter");
111466d53750SHans Petter Selasky 	}
111566d53750SHans Petter Selasky 
111666d53750SHans Petter Selasky 	/* create general diagnostics */
111766d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) {
111866d53750SHans Petter Selasky 		entry = mlx5_core_general_diagnostics_table[x];
111966d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
112066d53750SHans Petter Selasky 			continue;
112166d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
112266d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_general.array + x,
112366d53750SHans Petter Selasky 		    "General diagnostics counter");
112466d53750SHans Petter Selasky 	}
112566d53750SHans Petter Selasky }
112666d53750SHans Petter Selasky 
1127dc7e38acSHans Petter Selasky void
1128dc7e38acSHans Petter Selasky mlx5e_create_ethtool(struct mlx5e_priv *priv)
1129dc7e38acSHans Petter Selasky {
1130cfc9c386SHans Petter Selasky 	struct mlx5_core_dev *mdev = priv->mdev;
1131cfc9c386SHans Petter Selasky 	struct sysctl_oid *node, *qos_node;
1132dc7e38acSHans Petter Selasky 	const char *pnameunit;
1133dc7e38acSHans Petter Selasky 	unsigned x;
1134cfc9c386SHans Petter Selasky 	int i;
1135dc7e38acSHans Petter Selasky 
1136dc7e38acSHans Petter Selasky 	/* set some defaults */
1137dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
1138dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE;
1139dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size;
1140dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size;
1141dc7e38acSHans Petter Selasky 	priv->params_ethtool.channels = priv->params.num_channels;
114216ae32f9SHans Petter Selasky 	priv->params_ethtool.channels_rsss = priv->params.channels_rsss;
1143dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count);
1144dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period);
1145dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode;
1146dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec;
1147dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts;
114874540a31SHans Petter Selasky 	priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode;
1149dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec;
1150dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts;
1151dc7e38acSHans Petter Selasky 	priv->params_ethtool.hw_lro = priv->params.hw_lro_en;
115290cc1c77SHans Petter Selasky 	priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en;
1153376bcf63SHans Petter Selasky 	mlx5e_ethtool_sync_tx_completion_fact(priv);
1154dc7e38acSHans Petter Selasky 
115561fd7ac0SHans Petter Selasky 	/* get default values for local loopback, if any */
115661fd7ac0SHans Petter Selasky 	if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) {
115761fd7ac0SHans Petter Selasky 		int err;
115861fd7ac0SHans Petter Selasky 		u8 val;
115961fd7ac0SHans Petter Selasky 
116061fd7ac0SHans Petter Selasky 		err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val);
116161fd7ac0SHans Petter Selasky 		if (err == 0)
116261fd7ac0SHans Petter Selasky 			priv->params_ethtool.mc_local_lb = val;
116361fd7ac0SHans Petter Selasky 
116461fd7ac0SHans Petter Selasky 		err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val);
116561fd7ac0SHans Petter Selasky 		if (err == 0)
116661fd7ac0SHans Petter Selasky 			priv->params_ethtool.uc_local_lb = val;
116761fd7ac0SHans Petter Selasky 	}
116861fd7ac0SHans Petter Selasky 
1169dc7e38acSHans Petter Selasky 	/* create root node */
1170dc7e38acSHans Petter Selasky 	node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1171dc7e38acSHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
1172dc7e38acSHans Petter Selasky 	    "conf", CTLFLAG_RW, NULL, "Configuration");
1173dc7e38acSHans Petter Selasky 	if (node == NULL)
1174dc7e38acSHans Petter Selasky 		return;
1175dc7e38acSHans Petter Selasky 	for (x = 0; x != MLX5E_PARAMS_NUM; x++) {
1176dc7e38acSHans Petter Selasky 		/* check for read-only parameter */
117753d7bb46SHans Petter Selasky 		if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL ||
117853d7bb46SHans Petter Selasky 		    strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) {
1179dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1180dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD |
1181dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1182dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
1183dc7e38acSHans Petter Selasky 		} else {
1184ec0143b2SHans Petter Selasky #if (__FreeBSD_version < 1100000)
1185ec0143b2SHans Petter Selasky 			char path[64];
1186ec0143b2SHans Petter Selasky #endif
1187ec0143b2SHans Petter Selasky 			/*
1188ec0143b2SHans Petter Selasky 			 * NOTE: In FreeBSD-11 and newer the
1189ec0143b2SHans Petter Selasky 			 * CTLFLAG_RWTUN flag will take care of
1190ec0143b2SHans Petter Selasky 			 * loading default sysctl value from the
1191ec0143b2SHans Petter Selasky 			 * kernel environment, if any:
1192ec0143b2SHans Petter Selasky 			 */
1193dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1194dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN |
1195dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1196dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
1197ec0143b2SHans Petter Selasky 
1198ec0143b2SHans Petter Selasky #if (__FreeBSD_version < 1100000)
1199ec0143b2SHans Petter Selasky 			/* compute path for sysctl */
1200ec0143b2SHans Petter Selasky 			snprintf(path, sizeof(path), "dev.mce.%d.conf.%s",
1201ec0143b2SHans Petter Selasky 			    device_get_unit(priv->mdev->pdev->dev.bsddev),
1202ec0143b2SHans Petter Selasky 			    mlx5e_params_desc[2 * x]);
1203ec0143b2SHans Petter Selasky 
1204ec0143b2SHans Petter Selasky 			/* try to fetch tunable, if any */
1205ec0143b2SHans Petter Selasky 			if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x]))
1206ec0143b2SHans Petter Selasky 				mlx5e_ethtool_handler(NULL, priv, x, NULL);
1207ec0143b2SHans Petter Selasky #endif
1208dc7e38acSHans Petter Selasky 		}
1209dc7e38acSHans Petter Selasky 	}
1210dc7e38acSHans Petter Selasky 
1211dc7e38acSHans Petter Selasky 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1212dc7e38acSHans Petter Selasky 	    "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv,
1213dc7e38acSHans Petter Selasky 	    0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics");
1214dc7e38acSHans Petter Selasky 
1215dc7e38acSHans Petter Selasky 	pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
1216dc7e38acSHans Petter Selasky 
1217dc7e38acSHans Petter Selasky 	SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node),
1218dc7e38acSHans Petter Selasky 	    OID_AUTO, "device_name", CTLFLAG_RD,
1219dc7e38acSHans Petter Selasky 	    __DECONST(void *, pnameunit), 0,
1220dc7e38acSHans Petter Selasky 	    "PCI device name");
1221dc7e38acSHans Petter Selasky 
1222dc7e38acSHans Petter Selasky 	/* EEPROM support */
1223dc7e38acSHans Petter Selasky 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info",
1224dc7e38acSHans Petter Selasky 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
1225dc7e38acSHans Petter Selasky 	    mlx5e_read_eeprom, "I", "EEPROM information");
122666d53750SHans Petter Selasky 
122766d53750SHans Petter Selasky 	/* Diagnostics support */
122866d53750SHans Petter Selasky 	mlx5e_create_diagnostics(priv);
1229cfc9c386SHans Petter Selasky 
1230cfc9c386SHans Petter Selasky 	/* create qos node */
1231cfc9c386SHans Petter Selasky 	qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1232cfc9c386SHans Petter Selasky 	    SYSCTL_CHILDREN(node), OID_AUTO,
1233cfc9c386SHans Petter Selasky 	    "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration");
1234e870c0abSSlava Shwartsman 	if (qos_node == NULL)
1235cfc9c386SHans Petter Selasky 		return;
1236cfc9c386SHans Petter Selasky 
1237e870c0abSSlava Shwartsman 	/* Priority rate limit support */
1238e870c0abSSlava Shwartsman 	if (mlx5e_getmaxrate(priv) == 0) {
1239cfc9c386SHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1240e870c0abSSlava Shwartsman 		    OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1241e870c0abSSlava Shwartsman 		    priv, 0, mlx5e_tc_maxrate_handler, "QU",
1242e870c0abSSlava Shwartsman 		    "Max rate for priority, specified in kilobits, where kilo=1000, "
1243e870c0abSSlava Shwartsman 		    "max_rate must be divisible by 100000");
1244cfc9c386SHans Petter Selasky 	}
12452e9c3a4fSHans Petter Selasky 
1246e870c0abSSlava Shwartsman 	/* Bandwidth limiting by ratio */
1247e870c0abSSlava Shwartsman 	if (mlx5e_get_max_alloc(priv) == 0) {
1248e870c0abSSlava Shwartsman 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1249e870c0abSSlava Shwartsman 		    OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1250e870c0abSSlava Shwartsman 		    priv, 0, mlx5e_tc_rate_share_handler, "QU",
1251e870c0abSSlava Shwartsman 		    "Specify bandwidth ratio from 1 to 100 "
1252e870c0abSSlava Shwartsman 		    "for the available traffic classes");
1253e870c0abSSlava Shwartsman 	}
12542e9c3a4fSHans Petter Selasky 
1255e870c0abSSlava Shwartsman 	/* Priority to traffic class mapping */
1256e870c0abSSlava Shwartsman 	if (mlx5e_get_prio_tc(priv) == 0) {
12572e9c3a4fSHans Petter Selasky 		for (i = 0; i <= mlx5_max_tc(mdev); i++) {
12582e9c3a4fSHans Petter Selasky 			char name[32];
12592e9c3a4fSHans Petter Selasky 			snprintf(name, sizeof(name), "prio_%d_to_tc", i);
12602e9c3a4fSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1261e870c0abSSlava Shwartsman 				OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
12622e9c3a4fSHans Petter Selasky 				priv, i, mlx5e_prio_to_tc_handler, "CU",
12632e9c3a4fSHans Petter Selasky 				"Set priority to traffic class");
12642e9c3a4fSHans Petter Selasky 		}
1265e870c0abSSlava Shwartsman 	}
1266ed0cee0bSHans Petter Selasky 
1267ed0cee0bSHans Petter Selasky 	/* DSCP support */
1268ed0cee0bSHans Petter Selasky 	if (mlx5e_get_dscp(priv) == 0) {
1269ed0cee0bSHans Petter Selasky 		for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) {
1270ed0cee0bSHans Petter Selasky 			char name[32];
1271ed0cee0bSHans Petter Selasky 			snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7);
1272ed0cee0bSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1273ed0cee0bSHans Petter Selasky 				OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1274ed0cee0bSHans Petter Selasky 				priv, i, mlx5e_dscp_prio_handler, "CU",
1275ed0cee0bSHans Petter Selasky 				"Set DSCP to priority mapping, 0..7");
1276ed0cee0bSHans Petter Selasky 		}
1277a880c1ffSHans Petter Selasky #define	A	"Set trust state, 1:PCP 2:DSCP"
1278a880c1ffSHans Petter Selasky #define	B	" 3:BOTH"
1279ed0cee0bSHans Petter Selasky 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1280ed0cee0bSHans Petter Selasky 		    OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1281ed0cee0bSHans Petter Selasky 		    priv, 0, mlx5e_trust_state_handler, "CU",
1282a880c1ffSHans Petter Selasky 		    MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both) ?
1283a880c1ffSHans Petter Selasky 		    A B : A);
1284a880c1ffSHans Petter Selasky #undef B
1285a880c1ffSHans Petter Selasky #undef A
1286ed0cee0bSHans Petter Selasky 	}
1287dc7e38acSHans Petter Selasky }
1288