xref: /freebsd/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c (revision 66d53750)
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 
8782d2623eSHans Petter Selasky #define	MLX5_PARAM_OFFSET(n)				\
8882d2623eSHans Petter Selasky     __offsetof(struct mlx5e_priv, params_ethtool.n)
8982d2623eSHans Petter Selasky 
90dc7e38acSHans Petter Selasky static int
91dc7e38acSHans Petter Selasky mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)
92dc7e38acSHans Petter Selasky {
93dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
94dc7e38acSHans Petter Selasky 	uint64_t value;
95d2bf00a9SHans Petter Selasky 	int mode_modify;
96dc7e38acSHans Petter Selasky 	int was_opened;
97dc7e38acSHans Petter Selasky 	int error;
98dc7e38acSHans Petter Selasky 
99dc7e38acSHans Petter Selasky 	PRIV_LOCK(priv);
100dc7e38acSHans Petter Selasky 	value = priv->params_ethtool.arg[arg2];
101ec0143b2SHans Petter Selasky 	if (req != NULL) {
102dc7e38acSHans Petter Selasky 		error = sysctl_handle_64(oidp, &value, 0, req);
103dc7e38acSHans Petter Selasky 		if (error || req->newptr == NULL ||
104dc7e38acSHans Petter Selasky 		    value == priv->params_ethtool.arg[arg2])
105dc7e38acSHans Petter Selasky 			goto done;
106dc7e38acSHans Petter Selasky 
107dc7e38acSHans Petter Selasky 		/* assign new value */
108dc7e38acSHans Petter Selasky 		priv->params_ethtool.arg[arg2] = value;
109ec0143b2SHans Petter Selasky 	} else {
110ec0143b2SHans Petter Selasky 		error = 0;
111ec0143b2SHans Petter Selasky 	}
112dc7e38acSHans Petter Selasky 	/* check if device is gone */
113dc7e38acSHans Petter Selasky 	if (priv->gone) {
114dc7e38acSHans Petter Selasky 		error = ENXIO;
115dc7e38acSHans Petter Selasky 		goto done;
116dc7e38acSHans Petter Selasky 	}
11782d2623eSHans Petter Selasky 	was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
118d2bf00a9SHans Petter Selasky 	mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify);
11982d2623eSHans Petter Selasky 
12082d2623eSHans Petter Selasky 	switch (MLX5_PARAM_OFFSET(arg[arg2])) {
12182d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_usecs):
122f03f517bSHans Petter Selasky 		/* import RX coal time */
123f03f517bSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_usecs < 1)
124f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_usecs = 0;
125f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.rx_coalesce_usecs >
126f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_period)) {
127f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_usecs =
128f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_period);
129f03f517bSHans Petter Selasky 		}
13082d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_usec =
13182d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_usecs;
132f03f517bSHans Petter Selasky 
13382d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
13482d2623eSHans Petter Selasky 		if (was_opened)
13582d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
13682d2623eSHans Petter Selasky 		break;
13782d2623eSHans Petter Selasky 
13882d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_pkts):
139f03f517bSHans Petter Selasky 		/* import RX coal pkts */
140f03f517bSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_pkts < 1)
141f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_pkts = 0;
142f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.rx_coalesce_pkts >
143f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
144f03f517bSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_pkts =
145f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_max_count);
146f03f517bSHans Petter Selasky 		}
14782d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_pkts =
14882d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_pkts;
149f03f517bSHans Petter Selasky 
15082d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
15182d2623eSHans Petter Selasky 		if (was_opened)
15282d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
15382d2623eSHans Petter Selasky 		break;
15482d2623eSHans Petter Selasky 
15582d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_usecs):
156f03f517bSHans Petter Selasky 		/* import TX coal time */
157f03f517bSHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_usecs < 1)
158f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_usecs = 0;
159f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.tx_coalesce_usecs >
160f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_period)) {
161f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_usecs =
162f03f517bSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_period);
163f03f517bSHans Petter Selasky 		}
16482d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_usec =
16582d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_usecs;
166f03f517bSHans Petter Selasky 
16782d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
16882d2623eSHans Petter Selasky 		if (was_opened)
16982d2623eSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
17082d2623eSHans Petter Selasky 		break;
17182d2623eSHans Petter Selasky 
17282d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_pkts):
173f03f517bSHans Petter Selasky 		/* import TX coal pkts */
174f03f517bSHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_pkts < 1)
175f03f517bSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_pkts = 0;
176f03f517bSHans Petter Selasky 		else if (priv->params_ethtool.tx_coalesce_pkts >
177f03f517bSHans Petter Selasky 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
17882d2623eSHans Petter Selasky 			priv->params_ethtool.tx_coalesce_pkts =
17982d2623eSHans Petter Selasky 			    MLX5E_FLD_MAX(cqc, cq_max_count);
180f03f517bSHans Petter Selasky 		}
18182d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_pkts =
18282d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_pkts;
183dc7e38acSHans Petter Selasky 
18482d2623eSHans Petter Selasky 		/* check to avoid down and up the network interface */
18582d2623eSHans Petter Selasky 		if (was_opened)
186f03f517bSHans Petter Selasky 			error = mlx5e_refresh_channel_params(priv);
18782d2623eSHans Petter Selasky 		break;
18882d2623eSHans Petter Selasky 
18982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_queue_size):
19082d2623eSHans Petter Selasky 		/* network interface must be down */
19182d2623eSHans Petter Selasky 		if (was_opened)
192f03f517bSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
19382d2623eSHans Petter Selasky 
194dc7e38acSHans Petter Selasky 		/* import TX queue size */
195dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.tx_queue_size <
196dc7e38acSHans Petter Selasky 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
197dc7e38acSHans Petter Selasky 			priv->params_ethtool.tx_queue_size =
198dc7e38acSHans Petter Selasky 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE);
199dc7e38acSHans Petter Selasky 		} else if (priv->params_ethtool.tx_queue_size >
200dc7e38acSHans Petter Selasky 		    priv->params_ethtool.tx_queue_size_max) {
201dc7e38acSHans Petter Selasky 			priv->params_ethtool.tx_queue_size =
202dc7e38acSHans Petter Selasky 			    priv->params_ethtool.tx_queue_size_max;
203dc7e38acSHans Petter Selasky 		}
20482d2623eSHans Petter Selasky 		/* store actual TX queue size */
205dc7e38acSHans Petter Selasky 		priv->params.log_sq_size =
206dc7e38acSHans Petter Selasky 		    order_base_2(priv->params_ethtool.tx_queue_size);
20782d2623eSHans Petter Selasky 		priv->params_ethtool.tx_queue_size =
20882d2623eSHans Petter Selasky 		    1 << priv->params.log_sq_size;
20982d2623eSHans Petter Selasky 
21082d2623eSHans Petter Selasky 		/* verify TX completion factor */
21182d2623eSHans Petter Selasky 		mlx5e_ethtool_sync_tx_completion_fact(priv);
21282d2623eSHans Petter Selasky 
21382d2623eSHans Petter Selasky 		/* restart network interface, if any */
21482d2623eSHans Petter Selasky 		if (was_opened)
21582d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
21682d2623eSHans Petter Selasky 		break;
21782d2623eSHans Petter Selasky 
21882d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_queue_size):
21982d2623eSHans Petter Selasky 		/* network interface must be down */
22082d2623eSHans Petter Selasky 		if (was_opened)
22182d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
222dc7e38acSHans Petter Selasky 
223dc7e38acSHans Petter Selasky 		/* import RX queue size */
224dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.rx_queue_size <
225dc7e38acSHans Petter Selasky 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) {
226dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_queue_size =
227dc7e38acSHans Petter Selasky 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE);
228dc7e38acSHans Petter Selasky 		} else if (priv->params_ethtool.rx_queue_size >
229dc7e38acSHans Petter Selasky 		    priv->params_ethtool.rx_queue_size_max) {
230dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_queue_size =
231dc7e38acSHans Petter Selasky 			    priv->params_ethtool.rx_queue_size_max;
232dc7e38acSHans Petter Selasky 		}
23382d2623eSHans Petter Selasky 		/* store actual RX queue size */
234dc7e38acSHans Petter Selasky 		priv->params.log_rq_size =
235dc7e38acSHans Petter Selasky 		    order_base_2(priv->params_ethtool.rx_queue_size);
23682d2623eSHans Petter Selasky 		priv->params_ethtool.rx_queue_size =
23782d2623eSHans Petter Selasky 		    1 << priv->params.log_rq_size;
238dc7e38acSHans Petter Selasky 
23982d2623eSHans Petter Selasky 		/* update least number of RX WQEs */
24082d2623eSHans Petter Selasky 		priv->params.min_rx_wqes = min(
241dc7e38acSHans Petter Selasky 		    priv->params_ethtool.rx_queue_size - 1,
242dc7e38acSHans Petter Selasky 		    MLX5E_PARAMS_DEFAULT_MIN_RX_WQES);
243dc7e38acSHans Petter Selasky 
24482d2623eSHans Petter Selasky 		/* restart network interface, if any */
24582d2623eSHans Petter Selasky 		if (was_opened)
24682d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
24782d2623eSHans Petter Selasky 		break;
24882d2623eSHans Petter Selasky 
24982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(channels):
25082d2623eSHans Petter Selasky 		/* network interface must be down */
25182d2623eSHans Petter Selasky 		if (was_opened)
25282d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
25382d2623eSHans Petter Selasky 
254dc7e38acSHans Petter Selasky 		/* import number of channels */
255dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.channels < 1)
256dc7e38acSHans Petter Selasky 			priv->params_ethtool.channels = 1;
257dc7e38acSHans Petter Selasky 		else if (priv->params_ethtool.channels >
258dc7e38acSHans Petter Selasky 		    (u64) priv->mdev->priv.eq_table.num_comp_vectors) {
259dc7e38acSHans Petter Selasky 			priv->params_ethtool.channels =
260dc7e38acSHans Petter Selasky 			    (u64) priv->mdev->priv.eq_table.num_comp_vectors;
261dc7e38acSHans Petter Selasky 		}
262dc7e38acSHans Petter Selasky 		priv->params.num_channels = priv->params_ethtool.channels;
263dc7e38acSHans Petter Selasky 
26482d2623eSHans Petter Selasky 		/* restart network interface, if any */
26582d2623eSHans Petter Selasky 		if (was_opened)
26682d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
26782d2623eSHans Petter Selasky 		break;
26882d2623eSHans Petter Selasky 
26982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(rx_coalesce_mode):
27082d2623eSHans Petter Selasky 		/* network interface must be down */
271d2bf00a9SHans Petter Selasky 		if (was_opened != 0 && mode_modify == 0)
27282d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
27382d2623eSHans Petter Selasky 
27482d2623eSHans Petter Selasky 		/* import RX coalesce mode */
275dc7e38acSHans Petter Selasky 		if (priv->params_ethtool.rx_coalesce_mode != 0)
276dc7e38acSHans Petter Selasky 			priv->params_ethtool.rx_coalesce_mode = 1;
27782d2623eSHans Petter Selasky 		priv->params.rx_cq_moderation_mode =
27882d2623eSHans Petter Selasky 		    priv->params_ethtool.rx_coalesce_mode;
279dc7e38acSHans Petter Selasky 
28082d2623eSHans Petter Selasky 		/* restart network interface, if any */
281d2bf00a9SHans Petter Selasky 		if (was_opened != 0) {
282d2bf00a9SHans Petter Selasky 			if (mode_modify == 0)
28382d2623eSHans Petter Selasky 				mlx5e_open_locked(priv->ifp);
284d2bf00a9SHans Petter Selasky 			else
285d2bf00a9SHans Petter Selasky 				error = mlx5e_refresh_channel_params(priv);
286d2bf00a9SHans Petter Selasky 		}
28782d2623eSHans Petter Selasky 		break;
28882d2623eSHans Petter Selasky 
28982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_coalesce_mode):
29082d2623eSHans Petter Selasky 		/* network interface must be down */
291d2bf00a9SHans Petter Selasky 		if (was_opened != 0 && mode_modify == 0)
29282d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
29382d2623eSHans Petter Selasky 
29482d2623eSHans Petter Selasky 		/* import TX coalesce mode */
29574540a31SHans Petter Selasky 		if (priv->params_ethtool.tx_coalesce_mode != 0)
29674540a31SHans Petter Selasky 			priv->params_ethtool.tx_coalesce_mode = 1;
29782d2623eSHans Petter Selasky 		priv->params.tx_cq_moderation_mode =
29882d2623eSHans Petter Selasky 		    priv->params_ethtool.tx_coalesce_mode;
29974540a31SHans Petter Selasky 
30082d2623eSHans Petter Selasky 		/* restart network interface, if any */
301d2bf00a9SHans Petter Selasky 		if (was_opened != 0) {
302d2bf00a9SHans Petter Selasky 			if (mode_modify == 0)
30382d2623eSHans Petter Selasky 				mlx5e_open_locked(priv->ifp);
304d2bf00a9SHans Petter Selasky 			else
305d2bf00a9SHans Petter Selasky 				error = mlx5e_refresh_channel_params(priv);
306d2bf00a9SHans Petter Selasky 		}
30782d2623eSHans Petter Selasky 		break;
30882d2623eSHans Petter Selasky 
30982d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(hw_lro):
31082d2623eSHans Petter Selasky 		/* network interface must be down */
31182d2623eSHans Petter Selasky 		if (was_opened)
31282d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
31382d2623eSHans Petter Selasky 
31482d2623eSHans Petter Selasky 		/* import HW LRO mode */
315d7633a30SHans Petter Selasky 		if (priv->params_ethtool.hw_lro != 0) {
316d7633a30SHans Petter Selasky 			if ((priv->ifp->if_capenable & IFCAP_LRO) &&
317d7633a30SHans Petter Selasky 			    MLX5_CAP_ETH(priv->mdev, lro_cap)) {
318d7633a30SHans Petter Selasky 				priv->params.hw_lro_en = 1;
319d7633a30SHans Petter Selasky 				priv->params_ethtool.hw_lro = 1;
320d7633a30SHans Petter Selasky 			} else {
321d7633a30SHans Petter Selasky 				priv->params.hw_lro_en = 0;
32236c1007dSHans Petter Selasky 				priv->params_ethtool.hw_lro = 0;
32336c1007dSHans Petter Selasky 				error = EINVAL;
324d7633a30SHans Petter Selasky 
325d7633a30SHans Petter Selasky 				if_printf(priv->ifp, "Can't enable HW LRO: "
32682d2623eSHans Petter Selasky 				    "The HW or SW LRO feature is disabled\n");
32736c1007dSHans Petter Selasky 			}
328bb3853c6SHans Petter Selasky 		} else {
329d7633a30SHans Petter Selasky 			priv->params.hw_lro_en = 0;
330dc7e38acSHans Petter Selasky 		}
33182d2623eSHans Petter Selasky 		/* restart network interface, if any */
33282d2623eSHans Petter Selasky 		if (was_opened)
33382d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
33482d2623eSHans Petter Selasky 		break;
335dc7e38acSHans Petter Selasky 
33682d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(cqe_zipping):
33782d2623eSHans Petter Selasky 		/* network interface must be down */
33882d2623eSHans Petter Selasky 		if (was_opened)
33982d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
34082d2623eSHans Petter Selasky 
34182d2623eSHans Petter Selasky 		/* import CQE zipping mode */
34290cc1c77SHans Petter Selasky 		if (priv->params_ethtool.cqe_zipping &&
34390cc1c77SHans Petter Selasky 		    MLX5_CAP_GEN(priv->mdev, cqe_compression)) {
34490cc1c77SHans Petter Selasky 			priv->params.cqe_zipping_en = true;
34590cc1c77SHans Petter Selasky 			priv->params_ethtool.cqe_zipping = 1;
34690cc1c77SHans Petter Selasky 		} else {
34790cc1c77SHans Petter Selasky 			priv->params.cqe_zipping_en = false;
34890cc1c77SHans Petter Selasky 			priv->params_ethtool.cqe_zipping = 0;
34990cc1c77SHans Petter Selasky 		}
35082d2623eSHans Petter Selasky 		/* restart network interface, if any */
351dc7e38acSHans Petter Selasky 		if (was_opened)
352dc7e38acSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
35382d2623eSHans Petter Selasky 		break;
35482d2623eSHans Petter Selasky 
355b98ba640SHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_bufring_disable):
356b98ba640SHans Petter Selasky 		/* rangecheck input value */
357b98ba640SHans Petter Selasky 		priv->params_ethtool.tx_bufring_disable =
358b98ba640SHans Petter Selasky 		    priv->params_ethtool.tx_bufring_disable ? 1 : 0;
359b98ba640SHans Petter Selasky 
360b98ba640SHans Petter Selasky 		/* reconfigure the sendqueues, if any */
361b98ba640SHans Petter Selasky 		if (was_opened) {
362b98ba640SHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
363b98ba640SHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
364b98ba640SHans Petter Selasky 		}
365b98ba640SHans Petter Selasky 		break;
366b98ba640SHans Petter Selasky 
36782d2623eSHans Petter Selasky 	case MLX5_PARAM_OFFSET(tx_completion_fact):
36882d2623eSHans Petter Selasky 		/* network interface must be down */
36982d2623eSHans Petter Selasky 		if (was_opened)
37082d2623eSHans Petter Selasky 			mlx5e_close_locked(priv->ifp);
37182d2623eSHans Petter Selasky 
37282d2623eSHans Petter Selasky 		/* verify parameter */
37382d2623eSHans Petter Selasky 		mlx5e_ethtool_sync_tx_completion_fact(priv);
37482d2623eSHans Petter Selasky 
37582d2623eSHans Petter Selasky 		/* restart network interface, if any */
37682d2623eSHans Petter Selasky 		if (was_opened)
37782d2623eSHans Petter Selasky 			mlx5e_open_locked(priv->ifp);
37882d2623eSHans Petter Selasky 		break;
37982d2623eSHans Petter Selasky 
38066d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_pci_enable):
38166d53750SHans Petter Selasky 		priv->params_ethtool.diag_pci_enable =
38266d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable ? 1 : 0;
38366d53750SHans Petter Selasky 
38466d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
38566d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
38666d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
38766d53750SHans Petter Selasky 		break;
38866d53750SHans Petter Selasky 
38966d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_general_enable):
39066d53750SHans Petter Selasky 		priv->params_ethtool.diag_general_enable =
39166d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable ? 1 : 0;
39266d53750SHans Petter Selasky 
39366d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
39466d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
39566d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
39666d53750SHans Petter Selasky 		break;
39766d53750SHans Petter Selasky 
39882d2623eSHans Petter Selasky 	default:
39982d2623eSHans Petter Selasky 		break;
40082d2623eSHans Petter Selasky 	}
401dc7e38acSHans Petter Selasky done:
402dc7e38acSHans Petter Selasky 	PRIV_UNLOCK(priv);
403dc7e38acSHans Petter Selasky 	return (error);
404dc7e38acSHans Petter Selasky }
405dc7e38acSHans Petter Selasky 
406dc7e38acSHans Petter Selasky /*
407dc7e38acSHans Petter Selasky  * Read the first three bytes of the eeprom in order to get the needed info
408dc7e38acSHans Petter Selasky  * for the whole reading.
409dc7e38acSHans Petter Selasky  * Byte 0 - Identifier byte
410dc7e38acSHans Petter Selasky  * Byte 1 - Revision byte
411dc7e38acSHans Petter Selasky  * Byte 2 - Status byte
412dc7e38acSHans Petter Selasky  */
413dc7e38acSHans Petter Selasky static int
414dc7e38acSHans Petter Selasky mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom)
415dc7e38acSHans Petter Selasky {
416dc7e38acSHans Petter Selasky 	struct mlx5_core_dev *dev = priv->mdev;
417dc7e38acSHans Petter Selasky 	u32 data = 0;
418dc7e38acSHans Petter Selasky 	int size_read = 0;
419dc7e38acSHans Petter Selasky 	int ret;
420dc7e38acSHans Petter Selasky 
421dc7e38acSHans Petter Selasky 	ret = mlx5_query_module_num(dev, &eeprom->module_num);
422dc7e38acSHans Petter Selasky 	if (ret) {
423dc7e38acSHans Petter Selasky 		if_printf(priv->ifp, "%s:%d: Failed query module error=%d\n",
424dc7e38acSHans Petter Selasky 		    __func__, __LINE__, ret);
425dc7e38acSHans Petter Selasky 		return (ret);
426dc7e38acSHans Petter Selasky 	}
427dc7e38acSHans Petter Selasky 
428dc7e38acSHans Petter Selasky 	/* Read the first three bytes to get Identifier, Revision and Status */
429dc7e38acSHans Petter Selasky 	ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num,
430dc7e38acSHans Petter Selasky 	    eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data,
431dc7e38acSHans Petter Selasky 	    &size_read);
432dc7e38acSHans Petter Selasky 	if (ret) {
433dc7e38acSHans Petter Selasky 		if_printf(priv->ifp, "%s:%d: Failed query eeprom module error=0x%x\n",
434dc7e38acSHans Petter Selasky 		    __func__, __LINE__, ret);
435dc7e38acSHans Petter Selasky 		return (ret);
436dc7e38acSHans Petter Selasky 	}
437dc7e38acSHans Petter Selasky 
438dc7e38acSHans Petter Selasky 	switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) {
439dc7e38acSHans Petter Selasky 	case SFF_8024_ID_QSFP:
440dc7e38acSHans Petter Selasky 		eeprom->type = MLX5E_ETH_MODULE_SFF_8436;
441dc7e38acSHans Petter Selasky 		eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN;
442dc7e38acSHans Petter Selasky 		break;
443dc7e38acSHans Petter Selasky 	case SFF_8024_ID_QSFPPLUS:
444dc7e38acSHans Petter Selasky 	case SFF_8024_ID_QSFP28:
445dc7e38acSHans Petter Selasky 		if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 ||
446dc7e38acSHans Petter Selasky 		    ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) {
447dc7e38acSHans Petter Selasky 			eeprom->type = MLX5E_ETH_MODULE_SFF_8636;
448dc7e38acSHans Petter Selasky 			eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN;
449dc7e38acSHans Petter Selasky 		} else {
450dc7e38acSHans Petter Selasky 			eeprom->type = MLX5E_ETH_MODULE_SFF_8436;
451dc7e38acSHans Petter Selasky 			eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN;
452dc7e38acSHans Petter Selasky 		}
453dc7e38acSHans Petter Selasky 		if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0)
454dc7e38acSHans Petter Selasky 			eeprom->page_valid = 1;
455dc7e38acSHans Petter Selasky 		break;
456dc7e38acSHans Petter Selasky 	case SFF_8024_ID_SFP:
457dc7e38acSHans Petter Selasky 		eeprom->type = MLX5E_ETH_MODULE_SFF_8472;
458dc7e38acSHans Petter Selasky 		eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN;
459dc7e38acSHans Petter Selasky 		break;
460dc7e38acSHans Petter Selasky 	default:
4617e1b8bc0SHans Petter Selasky 		if_printf(priv->ifp, "%s:%d: Not recognized cable type = 0x%x(%s)\n",
4627e1b8bc0SHans Petter Selasky 		    __func__, __LINE__, data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK,
4637e1b8bc0SHans Petter Selasky 		    sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]);
464dc7e38acSHans Petter Selasky 		return (EINVAL);
465dc7e38acSHans Petter Selasky 	}
466dc7e38acSHans Petter Selasky 	return (0);
467dc7e38acSHans Petter Selasky }
468dc7e38acSHans Petter Selasky 
469dc7e38acSHans Petter Selasky /* Read both low and high pages of the eeprom */
470dc7e38acSHans Petter Selasky static int
471dc7e38acSHans Petter Selasky mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee)
472dc7e38acSHans Petter Selasky {
473dc7e38acSHans Petter Selasky 	struct mlx5_core_dev *dev = priv->mdev;
474dc7e38acSHans Petter Selasky 	int size_read = 0;
475dc7e38acSHans Petter Selasky 	int ret;
476dc7e38acSHans Petter Selasky 
477dc7e38acSHans Petter Selasky 	if (ee->len == 0)
478dc7e38acSHans Petter Selasky 		return (EINVAL);
479dc7e38acSHans Petter Selasky 
480dc7e38acSHans Petter Selasky 	/* Read low page of the eeprom */
481dc7e38acSHans Petter Selasky 	while (ee->device_addr < ee->len) {
482dc7e38acSHans Petter Selasky 		ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr,
483dc7e38acSHans Petter Selasky 		    ee->len - ee->device_addr, ee->module_num,
484dc7e38acSHans Petter Selasky 		    ee->data + (ee->device_addr / 4), &size_read);
485dc7e38acSHans Petter Selasky 		if (ret) {
486dc7e38acSHans Petter Selasky 			if_printf(priv->ifp, "%s:%d: Failed reading eeprom, "
487dc7e38acSHans Petter Selasky 			    "error = 0x%02x\n", __func__, __LINE__, ret);
488dc7e38acSHans Petter Selasky 			return (ret);
489dc7e38acSHans Petter Selasky 		}
490dc7e38acSHans Petter Selasky 		ee->device_addr += size_read;
491dc7e38acSHans Petter Selasky 	}
492dc7e38acSHans Petter Selasky 
493dc7e38acSHans Petter Selasky 	/* Read high page of the eeprom */
494dc7e38acSHans Petter Selasky 	if (ee->page_valid) {
495dc7e38acSHans Petter Selasky 		ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET;
496dc7e38acSHans Petter Selasky 		ee->page_num = MLX5E_EEPROM_HIGH_PAGE;
497dc7e38acSHans Petter Selasky 		size_read = 0;
498dc7e38acSHans Petter Selasky 		while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) {
499dc7e38acSHans Petter Selasky 			ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num,
500dc7e38acSHans Petter Selasky 			    ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr,
501dc7e38acSHans Petter Selasky 			    ee->module_num, ee->data + (ee->len / 4) +
502dc7e38acSHans Petter Selasky 			    ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4),
503dc7e38acSHans Petter Selasky 			    &size_read);
504dc7e38acSHans Petter Selasky 			if (ret) {
505dc7e38acSHans Petter Selasky 				if_printf(priv->ifp, "%s:%d: Failed reading eeprom, "
506dc7e38acSHans Petter Selasky 				    "error = 0x%02x\n", __func__, __LINE__, ret);
507dc7e38acSHans Petter Selasky 				return (ret);
508dc7e38acSHans Petter Selasky 			}
509dc7e38acSHans Petter Selasky 			ee->device_addr += size_read;
510dc7e38acSHans Petter Selasky 		}
511dc7e38acSHans Petter Selasky 	}
512dc7e38acSHans Petter Selasky 	return (0);
513dc7e38acSHans Petter Selasky }
514dc7e38acSHans Petter Selasky 
515dc7e38acSHans Petter Selasky static void
516dc7e38acSHans Petter Selasky mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom)
517dc7e38acSHans Petter Selasky {
518ee41fc8fSHans Petter Selasky 	int row;
519ee41fc8fSHans Petter Selasky 	int index_in_row;
520ee41fc8fSHans Petter Selasky 	int byte_to_write = 0;
521ee41fc8fSHans Petter Selasky 	int line_length = 16;
522dc7e38acSHans Petter Selasky 
523dc7e38acSHans Petter Selasky 	printf("\nOffset\t\tValues\n");
524ee41fc8fSHans Petter Selasky 	printf("------\t\t------");
525ee41fc8fSHans Petter Selasky 	while (byte_to_write < eeprom->len) {
526ee41fc8fSHans Petter Selasky 		printf("\n0x%04X\t\t", byte_to_write);
527ee41fc8fSHans Petter Selasky 		for (index_in_row = 0; index_in_row < line_length; index_in_row++) {
528ee41fc8fSHans Petter Selasky 			printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]);
529ee41fc8fSHans Petter Selasky 			byte_to_write++;
530dc7e38acSHans Petter Selasky 		}
531dc7e38acSHans Petter Selasky 	}
532dc7e38acSHans Petter Selasky 
533dc7e38acSHans Petter Selasky 	if (eeprom->page_valid) {
534dc7e38acSHans Petter Selasky 		row = MLX5E_EEPROM_HIGH_PAGE_OFFSET;
535ee41fc8fSHans Petter Selasky 		printf("\n\nUpper Page 0x03\n");
536dc7e38acSHans Petter Selasky 		printf("\nOffset\t\tValues\n");
537ee41fc8fSHans Petter Selasky 		printf("------\t\t------");
538dc7e38acSHans Petter Selasky 		while (row < MLX5E_EEPROM_PAGE_LENGTH) {
539ee41fc8fSHans Petter Selasky 			printf("\n0x%04X\t\t", row);
540ee41fc8fSHans Petter Selasky 			for (index_in_row = 0; index_in_row < line_length; index_in_row++) {
541ee41fc8fSHans Petter Selasky 				printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]);
542ee41fc8fSHans Petter Selasky 				byte_to_write++;
543dc7e38acSHans Petter Selasky 				row++;
544dc7e38acSHans Petter Selasky 			}
545dc7e38acSHans Petter Selasky 		}
546dc7e38acSHans Petter Selasky 	}
547dc7e38acSHans Petter Selasky }
548dc7e38acSHans Petter Selasky 
549dc7e38acSHans Petter Selasky /*
550dc7e38acSHans Petter Selasky  * Read cable EEPROM module information by first inspecting the first
551dc7e38acSHans Petter Selasky  * three bytes to get the initial information for a whole reading.
552dc7e38acSHans Petter Selasky  * Information will be printed to dmesg.
553dc7e38acSHans Petter Selasky  */
554dc7e38acSHans Petter Selasky static int
555dc7e38acSHans Petter Selasky mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS)
556dc7e38acSHans Petter Selasky {
557dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
558dc7e38acSHans Petter Selasky 	struct mlx5e_eeprom eeprom;
559dc7e38acSHans Petter Selasky 	int error;
560dc7e38acSHans Petter Selasky 	int result = 0;
561dc7e38acSHans Petter Selasky 
562dc7e38acSHans Petter Selasky 	PRIV_LOCK(priv);
563dc7e38acSHans Petter Selasky 	error = sysctl_handle_int(oidp, &result, 0, req);
564dc7e38acSHans Petter Selasky 	if (error || !req->newptr)
565dc7e38acSHans Petter Selasky 		goto done;
566dc7e38acSHans Petter Selasky 
567dc7e38acSHans Petter Selasky 	/* Check if device is gone */
568dc7e38acSHans Petter Selasky 	if (priv->gone) {
569dc7e38acSHans Petter Selasky 		error = ENXIO;
570dc7e38acSHans Petter Selasky 		goto done;
571dc7e38acSHans Petter Selasky 	}
572dc7e38acSHans Petter Selasky 
573dc7e38acSHans Petter Selasky 	if (result == 1) {
574dc7e38acSHans Petter Selasky 		eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW;
575dc7e38acSHans Petter Selasky 		eeprom.device_addr = 0;
576dc7e38acSHans Petter Selasky 		eeprom.page_num = MLX5E_EEPROM_LOW_PAGE;
577dc7e38acSHans Petter Selasky 		eeprom.page_valid = 0;
578dc7e38acSHans Petter Selasky 
579dc7e38acSHans Petter Selasky 		/* Read three first bytes to get important info */
580dc7e38acSHans Petter Selasky 		error = mlx5e_get_eeprom_info(priv, &eeprom);
581dc7e38acSHans Petter Selasky 		if (error) {
582dc7e38acSHans Petter Selasky 			if_printf(priv->ifp, "%s:%d: Failed reading eeprom's "
583dc7e38acSHans Petter Selasky 			    "initial information\n", __func__, __LINE__);
584dc7e38acSHans Petter Selasky 			error = 0;
585dc7e38acSHans Petter Selasky 			goto done;
586dc7e38acSHans Petter Selasky 		}
587bb3853c6SHans Petter Selasky 		/*
588bb3853c6SHans Petter Selasky 		 * Allocate needed length buffer and additional space for
589bb3853c6SHans Petter Selasky 		 * page 0x03
590bb3853c6SHans Petter Selasky 		 */
591dc7e38acSHans Petter Selasky 		eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH,
592dc7e38acSHans Petter Selasky 		    M_MLX5EN, M_WAITOK | M_ZERO);
593dc7e38acSHans Petter Selasky 
594dc7e38acSHans Petter Selasky 		/* Read the whole eeprom information */
595dc7e38acSHans Petter Selasky 		error = mlx5e_get_eeprom(priv, &eeprom);
596dc7e38acSHans Petter Selasky 		if (error) {
597dc7e38acSHans Petter Selasky 			if_printf(priv->ifp, "%s:%d: Failed reading eeprom\n",
598dc7e38acSHans Petter Selasky 			    __func__, __LINE__);
599dc7e38acSHans Petter Selasky 			error = 0;
600bb3853c6SHans Petter Selasky 			/*
601bb3853c6SHans Petter Selasky 			 * Continue printing partial information in case of
602bb3853c6SHans Petter Selasky 			 * an error
603bb3853c6SHans Petter Selasky 			 */
604dc7e38acSHans Petter Selasky 		}
605dc7e38acSHans Petter Selasky 		mlx5e_print_eeprom(&eeprom);
606dc7e38acSHans Petter Selasky 		free(eeprom.data, M_MLX5EN);
607dc7e38acSHans Petter Selasky 	}
608dc7e38acSHans Petter Selasky done:
609dc7e38acSHans Petter Selasky 	PRIV_UNLOCK(priv);
610dc7e38acSHans Petter Selasky 	return (error);
611dc7e38acSHans Petter Selasky }
612dc7e38acSHans Petter Selasky 
613dc7e38acSHans Petter Selasky static const char *mlx5e_params_desc[] = {
614dc7e38acSHans Petter Selasky 	MLX5E_PARAMS(MLX5E_STATS_DESC)
615dc7e38acSHans Petter Selasky };
616dc7e38acSHans Petter Selasky 
617dc7e38acSHans Petter Selasky static const char *mlx5e_port_stats_debug_desc[] = {
618dc7e38acSHans Petter Selasky 	MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC)
619dc7e38acSHans Petter Selasky };
620dc7e38acSHans Petter Selasky 
621dc7e38acSHans Petter Selasky static int
622dc7e38acSHans Petter Selasky mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS)
623dc7e38acSHans Petter Selasky {
624dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
625dc7e38acSHans Petter Selasky 	int error;
626dc7e38acSHans Petter Selasky 	int sys_debug;
627dc7e38acSHans Petter Selasky 
628dc7e38acSHans Petter Selasky 	sys_debug = priv->sysctl_debug;
629dc7e38acSHans Petter Selasky 	error = sysctl_handle_int(oidp, &priv->sysctl_debug, 0, req);
630dc7e38acSHans Petter Selasky 	if (error || !req->newptr)
631dc7e38acSHans Petter Selasky 		return (error);
632dc7e38acSHans Petter Selasky 	priv->sysctl_debug = !!priv->sysctl_debug;
633dc7e38acSHans Petter Selasky 	if (sys_debug == priv->sysctl_debug)
634dc7e38acSHans Petter Selasky 		return (error);
635dc7e38acSHans Petter Selasky 	if (priv->sysctl_debug)
636dc7e38acSHans Petter Selasky 		mlx5e_create_stats(&priv->stats.port_stats_debug.ctx,
637dc7e38acSHans Petter Selasky 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats",
638dc7e38acSHans Petter Selasky 		    mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM,
639dc7e38acSHans Petter Selasky 		    priv->stats.port_stats_debug.arg);
640dc7e38acSHans Petter Selasky 	else
641dc7e38acSHans Petter Selasky 		sysctl_ctx_free(&priv->stats.port_stats_debug.ctx);
642dc7e38acSHans Petter Selasky 	return (error);
643dc7e38acSHans Petter Selasky }
644dc7e38acSHans Petter Selasky 
64566d53750SHans Petter Selasky static void
64666d53750SHans Petter Selasky mlx5e_create_diagnostics(struct mlx5e_priv *priv)
64766d53750SHans Petter Selasky {
64866d53750SHans Petter Selasky 	struct mlx5_core_diagnostics_entry entry;
64966d53750SHans Petter Selasky 	struct sysctl_ctx_list *ctx;
65066d53750SHans Petter Selasky 	struct sysctl_oid *node;
65166d53750SHans Petter Selasky 	int x;
65266d53750SHans Petter Selasky 
65366d53750SHans Petter Selasky 	/* sysctl context we are using */
65466d53750SHans Petter Selasky 	ctx = &priv->sysctl_ctx;
65566d53750SHans Petter Selasky 
65666d53750SHans Petter Selasky 	/* create root node */
65766d53750SHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx,
65866d53750SHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
65966d53750SHans Petter Selasky 	    "diagnostics", CTLFLAG_RD, NULL, "Diagnostics");
66066d53750SHans Petter Selasky 	if (node == NULL)
66166d53750SHans Petter Selasky 		return;
66266d53750SHans Petter Selasky 
66366d53750SHans Petter Selasky 	/* create PCI diagnostics */
66466d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) {
66566d53750SHans Petter Selasky 		entry = mlx5_core_pci_diagnostics_table[x];
66666d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
66766d53750SHans Petter Selasky 			continue;
66866d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
66966d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_pci.array + x,
67066d53750SHans Petter Selasky 		    "PCI diagnostics counter");
67166d53750SHans Petter Selasky 	}
67266d53750SHans Petter Selasky 
67366d53750SHans Petter Selasky 	/* create general diagnostics */
67466d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) {
67566d53750SHans Petter Selasky 		entry = mlx5_core_general_diagnostics_table[x];
67666d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
67766d53750SHans Petter Selasky 			continue;
67866d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
67966d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_general.array + x,
68066d53750SHans Petter Selasky 		    "General diagnostics counter");
68166d53750SHans Petter Selasky 	}
68266d53750SHans Petter Selasky }
68366d53750SHans Petter Selasky 
684dc7e38acSHans Petter Selasky void
685dc7e38acSHans Petter Selasky mlx5e_create_ethtool(struct mlx5e_priv *priv)
686dc7e38acSHans Petter Selasky {
687dc7e38acSHans Petter Selasky 	struct sysctl_oid *node;
688dc7e38acSHans Petter Selasky 	const char *pnameunit;
689dc7e38acSHans Petter Selasky 	unsigned x;
690dc7e38acSHans Petter Selasky 
691dc7e38acSHans Petter Selasky 	/* set some defaults */
692dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
693dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE;
694dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size;
695dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size;
696dc7e38acSHans Petter Selasky 	priv->params_ethtool.channels = priv->params.num_channels;
697dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count);
698dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period);
699dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode;
700dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec;
701dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts;
70274540a31SHans Petter Selasky 	priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode;
703dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec;
704dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts;
705dc7e38acSHans Petter Selasky 	priv->params_ethtool.hw_lro = priv->params.hw_lro_en;
70690cc1c77SHans Petter Selasky 	priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en;
707376bcf63SHans Petter Selasky 	mlx5e_ethtool_sync_tx_completion_fact(priv);
708dc7e38acSHans Petter Selasky 
709dc7e38acSHans Petter Selasky 	/* create root node */
710dc7e38acSHans Petter Selasky 	node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
711dc7e38acSHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
712dc7e38acSHans Petter Selasky 	    "conf", CTLFLAG_RW, NULL, "Configuration");
713dc7e38acSHans Petter Selasky 	if (node == NULL)
714dc7e38acSHans Petter Selasky 		return;
715dc7e38acSHans Petter Selasky 	for (x = 0; x != MLX5E_PARAMS_NUM; x++) {
716dc7e38acSHans Petter Selasky 		/* check for read-only parameter */
717dc7e38acSHans Petter Selasky 		if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL) {
718dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
719dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD |
720dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
721dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
722dc7e38acSHans Petter Selasky 		} else {
723ec0143b2SHans Petter Selasky #if (__FreeBSD_version < 1100000)
724ec0143b2SHans Petter Selasky 			char path[64];
725ec0143b2SHans Petter Selasky #endif
726ec0143b2SHans Petter Selasky 			/*
727ec0143b2SHans Petter Selasky 			 * NOTE: In FreeBSD-11 and newer the
728ec0143b2SHans Petter Selasky 			 * CTLFLAG_RWTUN flag will take care of
729ec0143b2SHans Petter Selasky 			 * loading default sysctl value from the
730ec0143b2SHans Petter Selasky 			 * kernel environment, if any:
731ec0143b2SHans Petter Selasky 			 */
732dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
733dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN |
734dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
735dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
736ec0143b2SHans Petter Selasky 
737ec0143b2SHans Petter Selasky #if (__FreeBSD_version < 1100000)
738ec0143b2SHans Petter Selasky 			/* compute path for sysctl */
739ec0143b2SHans Petter Selasky 			snprintf(path, sizeof(path), "dev.mce.%d.conf.%s",
740ec0143b2SHans Petter Selasky 			    device_get_unit(priv->mdev->pdev->dev.bsddev),
741ec0143b2SHans Petter Selasky 			    mlx5e_params_desc[2 * x]);
742ec0143b2SHans Petter Selasky 
743ec0143b2SHans Petter Selasky 			/* try to fetch tunable, if any */
744ec0143b2SHans Petter Selasky 			if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x]))
745ec0143b2SHans Petter Selasky 				mlx5e_ethtool_handler(NULL, priv, x, NULL);
746ec0143b2SHans Petter Selasky #endif
747dc7e38acSHans Petter Selasky 		}
748dc7e38acSHans Petter Selasky 	}
749dc7e38acSHans Petter Selasky 
750dc7e38acSHans Petter Selasky 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
751dc7e38acSHans Petter Selasky 	    "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv,
752dc7e38acSHans Petter Selasky 	    0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics");
753dc7e38acSHans Petter Selasky 
754dc7e38acSHans Petter Selasky 	pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
755dc7e38acSHans Petter Selasky 
756dc7e38acSHans Petter Selasky 	SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node),
757dc7e38acSHans Petter Selasky 	    OID_AUTO, "device_name", CTLFLAG_RD,
758dc7e38acSHans Petter Selasky 	    __DECONST(void *, pnameunit), 0,
759dc7e38acSHans Petter Selasky 	    "PCI device name");
760dc7e38acSHans Petter Selasky 
761dc7e38acSHans Petter Selasky 	/* EEPROM support */
762dc7e38acSHans Petter Selasky 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info",
763dc7e38acSHans Petter Selasky 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
764dc7e38acSHans Petter Selasky 	    mlx5e_read_eeprom, "I", "EEPROM information");
76566d53750SHans Petter Selasky 
76666d53750SHans Petter Selasky 	/* Diagnostics support */
76766d53750SHans Petter Selasky 	mlx5e_create_diagnostics(priv);
768dc7e38acSHans Petter Selasky }
769