xref: /freebsd/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c (revision bb3616ab)
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 
380bb3616abSHans Petter Selasky 	case MLX5_PARAM_OFFSET(modify_tx_dma):
381bb3616abSHans Petter Selasky 		/* check if network interface is opened */
382bb3616abSHans Petter Selasky 		if (was_opened) {
383bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_tx_dma =
384bb3616abSHans Petter Selasky 			    priv->params_ethtool.modify_tx_dma ? 1 : 0;
385bb3616abSHans Petter Selasky 			/* modify tx according to value */
386bb3616abSHans Petter Selasky 			mlx5e_modify_tx_dma(priv, value != 0);
387bb3616abSHans Petter Selasky 		} else {
388bb3616abSHans Petter Selasky 			/* if closed force enable tx */
389bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_tx_dma = 0;
390bb3616abSHans Petter Selasky 		}
391bb3616abSHans Petter Selasky 		break;
392bb3616abSHans Petter Selasky 
393bb3616abSHans Petter Selasky 	case MLX5_PARAM_OFFSET(modify_rx_dma):
394bb3616abSHans Petter Selasky 		/* check if network interface is opened */
395bb3616abSHans Petter Selasky 		if (was_opened) {
396bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_rx_dma =
397bb3616abSHans Petter Selasky 			    priv->params_ethtool.modify_rx_dma ? 1 : 0;
398bb3616abSHans Petter Selasky 			/* modify rx according to value */
399bb3616abSHans Petter Selasky 			mlx5e_modify_rx_dma(priv, value != 0);
400bb3616abSHans Petter Selasky 		} else {
401bb3616abSHans Petter Selasky 			/* if closed force enable rx */
402bb3616abSHans Petter Selasky 			priv->params_ethtool.modify_rx_dma = 0;
403bb3616abSHans Petter Selasky 		}
404bb3616abSHans Petter Selasky 		break;
405bb3616abSHans Petter Selasky 
40666d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_pci_enable):
40766d53750SHans Petter Selasky 		priv->params_ethtool.diag_pci_enable =
40866d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable ? 1 : 0;
40966d53750SHans Petter Selasky 
41066d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
41166d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
41266d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
41366d53750SHans Petter Selasky 		break;
41466d53750SHans Petter Selasky 
41566d53750SHans Petter Selasky 	case MLX5_PARAM_OFFSET(diag_general_enable):
41666d53750SHans Petter Selasky 		priv->params_ethtool.diag_general_enable =
41766d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable ? 1 : 0;
41866d53750SHans Petter Selasky 
41966d53750SHans Petter Selasky 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
42066d53750SHans Petter Selasky 		    priv->params_ethtool.diag_pci_enable,
42166d53750SHans Petter Selasky 		    priv->params_ethtool.diag_general_enable);
42266d53750SHans Petter Selasky 		break;
42366d53750SHans Petter Selasky 
42482d2623eSHans Petter Selasky 	default:
42582d2623eSHans Petter Selasky 		break;
42682d2623eSHans Petter Selasky 	}
427dc7e38acSHans Petter Selasky done:
428dc7e38acSHans Petter Selasky 	PRIV_UNLOCK(priv);
429dc7e38acSHans Petter Selasky 	return (error);
430dc7e38acSHans Petter Selasky }
431dc7e38acSHans Petter Selasky 
432dc7e38acSHans Petter Selasky /*
433dc7e38acSHans Petter Selasky  * Read the first three bytes of the eeprom in order to get the needed info
434dc7e38acSHans Petter Selasky  * for the whole reading.
435dc7e38acSHans Petter Selasky  * Byte 0 - Identifier byte
436dc7e38acSHans Petter Selasky  * Byte 1 - Revision byte
437dc7e38acSHans Petter Selasky  * Byte 2 - Status byte
438dc7e38acSHans Petter Selasky  */
439dc7e38acSHans Petter Selasky static int
440dc7e38acSHans Petter Selasky mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom)
441dc7e38acSHans Petter Selasky {
442dc7e38acSHans Petter Selasky 	struct mlx5_core_dev *dev = priv->mdev;
443dc7e38acSHans Petter Selasky 	u32 data = 0;
444dc7e38acSHans Petter Selasky 	int size_read = 0;
445dc7e38acSHans Petter Selasky 	int ret;
446dc7e38acSHans Petter Selasky 
447dc7e38acSHans Petter Selasky 	ret = mlx5_query_module_num(dev, &eeprom->module_num);
448dc7e38acSHans Petter Selasky 	if (ret) {
449dc7e38acSHans Petter Selasky 		if_printf(priv->ifp, "%s:%d: Failed query module error=%d\n",
450dc7e38acSHans Petter Selasky 		    __func__, __LINE__, ret);
451dc7e38acSHans Petter Selasky 		return (ret);
452dc7e38acSHans Petter Selasky 	}
453dc7e38acSHans Petter Selasky 
454dc7e38acSHans Petter Selasky 	/* Read the first three bytes to get Identifier, Revision and Status */
455dc7e38acSHans Petter Selasky 	ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num,
456dc7e38acSHans Petter Selasky 	    eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data,
457dc7e38acSHans Petter Selasky 	    &size_read);
458dc7e38acSHans Petter Selasky 	if (ret) {
459dc7e38acSHans Petter Selasky 		if_printf(priv->ifp, "%s:%d: Failed query eeprom module error=0x%x\n",
460dc7e38acSHans Petter Selasky 		    __func__, __LINE__, ret);
461dc7e38acSHans Petter Selasky 		return (ret);
462dc7e38acSHans Petter Selasky 	}
463dc7e38acSHans Petter Selasky 
464dc7e38acSHans Petter Selasky 	switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) {
465dc7e38acSHans Petter Selasky 	case SFF_8024_ID_QSFP:
466dc7e38acSHans Petter Selasky 		eeprom->type = MLX5E_ETH_MODULE_SFF_8436;
467dc7e38acSHans Petter Selasky 		eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN;
468dc7e38acSHans Petter Selasky 		break;
469dc7e38acSHans Petter Selasky 	case SFF_8024_ID_QSFPPLUS:
470dc7e38acSHans Petter Selasky 	case SFF_8024_ID_QSFP28:
471dc7e38acSHans Petter Selasky 		if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 ||
472dc7e38acSHans Petter Selasky 		    ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) {
473dc7e38acSHans Petter Selasky 			eeprom->type = MLX5E_ETH_MODULE_SFF_8636;
474dc7e38acSHans Petter Selasky 			eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN;
475dc7e38acSHans Petter Selasky 		} else {
476dc7e38acSHans Petter Selasky 			eeprom->type = MLX5E_ETH_MODULE_SFF_8436;
477dc7e38acSHans Petter Selasky 			eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN;
478dc7e38acSHans Petter Selasky 		}
479dc7e38acSHans Petter Selasky 		if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0)
480dc7e38acSHans Petter Selasky 			eeprom->page_valid = 1;
481dc7e38acSHans Petter Selasky 		break;
482dc7e38acSHans Petter Selasky 	case SFF_8024_ID_SFP:
483dc7e38acSHans Petter Selasky 		eeprom->type = MLX5E_ETH_MODULE_SFF_8472;
484dc7e38acSHans Petter Selasky 		eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN;
485dc7e38acSHans Petter Selasky 		break;
486dc7e38acSHans Petter Selasky 	default:
4877e1b8bc0SHans Petter Selasky 		if_printf(priv->ifp, "%s:%d: Not recognized cable type = 0x%x(%s)\n",
4887e1b8bc0SHans Petter Selasky 		    __func__, __LINE__, data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK,
4897e1b8bc0SHans Petter Selasky 		    sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]);
490dc7e38acSHans Petter Selasky 		return (EINVAL);
491dc7e38acSHans Petter Selasky 	}
492dc7e38acSHans Petter Selasky 	return (0);
493dc7e38acSHans Petter Selasky }
494dc7e38acSHans Petter Selasky 
495dc7e38acSHans Petter Selasky /* Read both low and high pages of the eeprom */
496dc7e38acSHans Petter Selasky static int
497dc7e38acSHans Petter Selasky mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee)
498dc7e38acSHans Petter Selasky {
499dc7e38acSHans Petter Selasky 	struct mlx5_core_dev *dev = priv->mdev;
500dc7e38acSHans Petter Selasky 	int size_read = 0;
501dc7e38acSHans Petter Selasky 	int ret;
502dc7e38acSHans Petter Selasky 
503dc7e38acSHans Petter Selasky 	if (ee->len == 0)
504dc7e38acSHans Petter Selasky 		return (EINVAL);
505dc7e38acSHans Petter Selasky 
506dc7e38acSHans Petter Selasky 	/* Read low page of the eeprom */
507dc7e38acSHans Petter Selasky 	while (ee->device_addr < ee->len) {
508dc7e38acSHans Petter Selasky 		ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr,
509dc7e38acSHans Petter Selasky 		    ee->len - ee->device_addr, ee->module_num,
510dc7e38acSHans Petter Selasky 		    ee->data + (ee->device_addr / 4), &size_read);
511dc7e38acSHans Petter Selasky 		if (ret) {
512dc7e38acSHans Petter Selasky 			if_printf(priv->ifp, "%s:%d: Failed reading eeprom, "
513dc7e38acSHans Petter Selasky 			    "error = 0x%02x\n", __func__, __LINE__, ret);
514dc7e38acSHans Petter Selasky 			return (ret);
515dc7e38acSHans Petter Selasky 		}
516dc7e38acSHans Petter Selasky 		ee->device_addr += size_read;
517dc7e38acSHans Petter Selasky 	}
518dc7e38acSHans Petter Selasky 
519dc7e38acSHans Petter Selasky 	/* Read high page of the eeprom */
520dc7e38acSHans Petter Selasky 	if (ee->page_valid) {
521dc7e38acSHans Petter Selasky 		ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET;
522dc7e38acSHans Petter Selasky 		ee->page_num = MLX5E_EEPROM_HIGH_PAGE;
523dc7e38acSHans Petter Selasky 		size_read = 0;
524dc7e38acSHans Petter Selasky 		while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) {
525dc7e38acSHans Petter Selasky 			ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num,
526dc7e38acSHans Petter Selasky 			    ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr,
527dc7e38acSHans Petter Selasky 			    ee->module_num, ee->data + (ee->len / 4) +
528dc7e38acSHans Petter Selasky 			    ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4),
529dc7e38acSHans Petter Selasky 			    &size_read);
530dc7e38acSHans Petter Selasky 			if (ret) {
531dc7e38acSHans Petter Selasky 				if_printf(priv->ifp, "%s:%d: Failed reading eeprom, "
532dc7e38acSHans Petter Selasky 				    "error = 0x%02x\n", __func__, __LINE__, ret);
533dc7e38acSHans Petter Selasky 				return (ret);
534dc7e38acSHans Petter Selasky 			}
535dc7e38acSHans Petter Selasky 			ee->device_addr += size_read;
536dc7e38acSHans Petter Selasky 		}
537dc7e38acSHans Petter Selasky 	}
538dc7e38acSHans Petter Selasky 	return (0);
539dc7e38acSHans Petter Selasky }
540dc7e38acSHans Petter Selasky 
541dc7e38acSHans Petter Selasky static void
542dc7e38acSHans Petter Selasky mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom)
543dc7e38acSHans Petter Selasky {
544ee41fc8fSHans Petter Selasky 	int row;
545ee41fc8fSHans Petter Selasky 	int index_in_row;
546ee41fc8fSHans Petter Selasky 	int byte_to_write = 0;
547ee41fc8fSHans Petter Selasky 	int line_length = 16;
548dc7e38acSHans Petter Selasky 
549dc7e38acSHans Petter Selasky 	printf("\nOffset\t\tValues\n");
550ee41fc8fSHans Petter Selasky 	printf("------\t\t------");
551ee41fc8fSHans Petter Selasky 	while (byte_to_write < eeprom->len) {
552ee41fc8fSHans Petter Selasky 		printf("\n0x%04X\t\t", byte_to_write);
553ee41fc8fSHans Petter Selasky 		for (index_in_row = 0; index_in_row < line_length; index_in_row++) {
554ee41fc8fSHans Petter Selasky 			printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]);
555ee41fc8fSHans Petter Selasky 			byte_to_write++;
556dc7e38acSHans Petter Selasky 		}
557dc7e38acSHans Petter Selasky 	}
558dc7e38acSHans Petter Selasky 
559dc7e38acSHans Petter Selasky 	if (eeprom->page_valid) {
560dc7e38acSHans Petter Selasky 		row = MLX5E_EEPROM_HIGH_PAGE_OFFSET;
561ee41fc8fSHans Petter Selasky 		printf("\n\nUpper Page 0x03\n");
562dc7e38acSHans Petter Selasky 		printf("\nOffset\t\tValues\n");
563ee41fc8fSHans Petter Selasky 		printf("------\t\t------");
564dc7e38acSHans Petter Selasky 		while (row < MLX5E_EEPROM_PAGE_LENGTH) {
565ee41fc8fSHans Petter Selasky 			printf("\n0x%04X\t\t", row);
566ee41fc8fSHans Petter Selasky 			for (index_in_row = 0; index_in_row < line_length; index_in_row++) {
567ee41fc8fSHans Petter Selasky 				printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]);
568ee41fc8fSHans Petter Selasky 				byte_to_write++;
569dc7e38acSHans Petter Selasky 				row++;
570dc7e38acSHans Petter Selasky 			}
571dc7e38acSHans Petter Selasky 		}
572dc7e38acSHans Petter Selasky 	}
573dc7e38acSHans Petter Selasky }
574dc7e38acSHans Petter Selasky 
575dc7e38acSHans Petter Selasky /*
576dc7e38acSHans Petter Selasky  * Read cable EEPROM module information by first inspecting the first
577dc7e38acSHans Petter Selasky  * three bytes to get the initial information for a whole reading.
578dc7e38acSHans Petter Selasky  * Information will be printed to dmesg.
579dc7e38acSHans Petter Selasky  */
580dc7e38acSHans Petter Selasky static int
581dc7e38acSHans Petter Selasky mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS)
582dc7e38acSHans Petter Selasky {
583dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
584dc7e38acSHans Petter Selasky 	struct mlx5e_eeprom eeprom;
585dc7e38acSHans Petter Selasky 	int error;
586dc7e38acSHans Petter Selasky 	int result = 0;
587dc7e38acSHans Petter Selasky 
588dc7e38acSHans Petter Selasky 	PRIV_LOCK(priv);
589dc7e38acSHans Petter Selasky 	error = sysctl_handle_int(oidp, &result, 0, req);
590dc7e38acSHans Petter Selasky 	if (error || !req->newptr)
591dc7e38acSHans Petter Selasky 		goto done;
592dc7e38acSHans Petter Selasky 
593dc7e38acSHans Petter Selasky 	/* Check if device is gone */
594dc7e38acSHans Petter Selasky 	if (priv->gone) {
595dc7e38acSHans Petter Selasky 		error = ENXIO;
596dc7e38acSHans Petter Selasky 		goto done;
597dc7e38acSHans Petter Selasky 	}
598dc7e38acSHans Petter Selasky 
599dc7e38acSHans Petter Selasky 	if (result == 1) {
600dc7e38acSHans Petter Selasky 		eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW;
601dc7e38acSHans Petter Selasky 		eeprom.device_addr = 0;
602dc7e38acSHans Petter Selasky 		eeprom.page_num = MLX5E_EEPROM_LOW_PAGE;
603dc7e38acSHans Petter Selasky 		eeprom.page_valid = 0;
604dc7e38acSHans Petter Selasky 
605dc7e38acSHans Petter Selasky 		/* Read three first bytes to get important info */
606dc7e38acSHans Petter Selasky 		error = mlx5e_get_eeprom_info(priv, &eeprom);
607dc7e38acSHans Petter Selasky 		if (error) {
608dc7e38acSHans Petter Selasky 			if_printf(priv->ifp, "%s:%d: Failed reading eeprom's "
609dc7e38acSHans Petter Selasky 			    "initial information\n", __func__, __LINE__);
610dc7e38acSHans Petter Selasky 			error = 0;
611dc7e38acSHans Petter Selasky 			goto done;
612dc7e38acSHans Petter Selasky 		}
613bb3853c6SHans Petter Selasky 		/*
614bb3853c6SHans Petter Selasky 		 * Allocate needed length buffer and additional space for
615bb3853c6SHans Petter Selasky 		 * page 0x03
616bb3853c6SHans Petter Selasky 		 */
617dc7e38acSHans Petter Selasky 		eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH,
618dc7e38acSHans Petter Selasky 		    M_MLX5EN, M_WAITOK | M_ZERO);
619dc7e38acSHans Petter Selasky 
620dc7e38acSHans Petter Selasky 		/* Read the whole eeprom information */
621dc7e38acSHans Petter Selasky 		error = mlx5e_get_eeprom(priv, &eeprom);
622dc7e38acSHans Petter Selasky 		if (error) {
623dc7e38acSHans Petter Selasky 			if_printf(priv->ifp, "%s:%d: Failed reading eeprom\n",
624dc7e38acSHans Petter Selasky 			    __func__, __LINE__);
625dc7e38acSHans Petter Selasky 			error = 0;
626bb3853c6SHans Petter Selasky 			/*
627bb3853c6SHans Petter Selasky 			 * Continue printing partial information in case of
628bb3853c6SHans Petter Selasky 			 * an error
629bb3853c6SHans Petter Selasky 			 */
630dc7e38acSHans Petter Selasky 		}
631dc7e38acSHans Petter Selasky 		mlx5e_print_eeprom(&eeprom);
632dc7e38acSHans Petter Selasky 		free(eeprom.data, M_MLX5EN);
633dc7e38acSHans Petter Selasky 	}
634dc7e38acSHans Petter Selasky done:
635dc7e38acSHans Petter Selasky 	PRIV_UNLOCK(priv);
636dc7e38acSHans Petter Selasky 	return (error);
637dc7e38acSHans Petter Selasky }
638dc7e38acSHans Petter Selasky 
639dc7e38acSHans Petter Selasky static const char *mlx5e_params_desc[] = {
640dc7e38acSHans Petter Selasky 	MLX5E_PARAMS(MLX5E_STATS_DESC)
641dc7e38acSHans Petter Selasky };
642dc7e38acSHans Petter Selasky 
643dc7e38acSHans Petter Selasky static const char *mlx5e_port_stats_debug_desc[] = {
644dc7e38acSHans Petter Selasky 	MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC)
645dc7e38acSHans Petter Selasky };
646dc7e38acSHans Petter Selasky 
647dc7e38acSHans Petter Selasky static int
648dc7e38acSHans Petter Selasky mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS)
649dc7e38acSHans Petter Selasky {
650dc7e38acSHans Petter Selasky 	struct mlx5e_priv *priv = arg1;
651dc7e38acSHans Petter Selasky 	int error;
652dc7e38acSHans Petter Selasky 	int sys_debug;
653dc7e38acSHans Petter Selasky 
654dc7e38acSHans Petter Selasky 	sys_debug = priv->sysctl_debug;
655dc7e38acSHans Petter Selasky 	error = sysctl_handle_int(oidp, &priv->sysctl_debug, 0, req);
656dc7e38acSHans Petter Selasky 	if (error || !req->newptr)
657dc7e38acSHans Petter Selasky 		return (error);
658dc7e38acSHans Petter Selasky 	priv->sysctl_debug = !!priv->sysctl_debug;
659dc7e38acSHans Petter Selasky 	if (sys_debug == priv->sysctl_debug)
660dc7e38acSHans Petter Selasky 		return (error);
661dc7e38acSHans Petter Selasky 	if (priv->sysctl_debug)
662dc7e38acSHans Petter Selasky 		mlx5e_create_stats(&priv->stats.port_stats_debug.ctx,
663dc7e38acSHans Petter Selasky 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats",
664dc7e38acSHans Petter Selasky 		    mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM,
665dc7e38acSHans Petter Selasky 		    priv->stats.port_stats_debug.arg);
666dc7e38acSHans Petter Selasky 	else
667dc7e38acSHans Petter Selasky 		sysctl_ctx_free(&priv->stats.port_stats_debug.ctx);
668dc7e38acSHans Petter Selasky 	return (error);
669dc7e38acSHans Petter Selasky }
670dc7e38acSHans Petter Selasky 
67166d53750SHans Petter Selasky static void
67266d53750SHans Petter Selasky mlx5e_create_diagnostics(struct mlx5e_priv *priv)
67366d53750SHans Petter Selasky {
67466d53750SHans Petter Selasky 	struct mlx5_core_diagnostics_entry entry;
67566d53750SHans Petter Selasky 	struct sysctl_ctx_list *ctx;
67666d53750SHans Petter Selasky 	struct sysctl_oid *node;
67766d53750SHans Petter Selasky 	int x;
67866d53750SHans Petter Selasky 
67966d53750SHans Petter Selasky 	/* sysctl context we are using */
68066d53750SHans Petter Selasky 	ctx = &priv->sysctl_ctx;
68166d53750SHans Petter Selasky 
68266d53750SHans Petter Selasky 	/* create root node */
68366d53750SHans Petter Selasky 	node = SYSCTL_ADD_NODE(ctx,
68466d53750SHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
68566d53750SHans Petter Selasky 	    "diagnostics", CTLFLAG_RD, NULL, "Diagnostics");
68666d53750SHans Petter Selasky 	if (node == NULL)
68766d53750SHans Petter Selasky 		return;
68866d53750SHans Petter Selasky 
68966d53750SHans Petter Selasky 	/* create PCI diagnostics */
69066d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) {
69166d53750SHans Petter Selasky 		entry = mlx5_core_pci_diagnostics_table[x];
69266d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
69366d53750SHans Petter Selasky 			continue;
69466d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
69566d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_pci.array + x,
69666d53750SHans Petter Selasky 		    "PCI diagnostics counter");
69766d53750SHans Petter Selasky 	}
69866d53750SHans Petter Selasky 
69966d53750SHans Petter Selasky 	/* create general diagnostics */
70066d53750SHans Petter Selasky 	for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) {
70166d53750SHans Petter Selasky 		entry = mlx5_core_general_diagnostics_table[x];
70266d53750SHans Petter Selasky 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
70366d53750SHans Petter Selasky 			continue;
70466d53750SHans Petter Selasky 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
70566d53750SHans Petter Selasky 		    entry.desc, CTLFLAG_RD, priv->params_general.array + x,
70666d53750SHans Petter Selasky 		    "General diagnostics counter");
70766d53750SHans Petter Selasky 	}
70866d53750SHans Petter Selasky }
70966d53750SHans Petter Selasky 
710dc7e38acSHans Petter Selasky void
711dc7e38acSHans Petter Selasky mlx5e_create_ethtool(struct mlx5e_priv *priv)
712dc7e38acSHans Petter Selasky {
713dc7e38acSHans Petter Selasky 	struct sysctl_oid *node;
714dc7e38acSHans Petter Selasky 	const char *pnameunit;
715dc7e38acSHans Petter Selasky 	unsigned x;
716dc7e38acSHans Petter Selasky 
717dc7e38acSHans Petter Selasky 	/* set some defaults */
718dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
719dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE;
720dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size;
721dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size;
722dc7e38acSHans Petter Selasky 	priv->params_ethtool.channels = priv->params.num_channels;
723dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count);
724dc7e38acSHans Petter Selasky 	priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period);
725dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode;
726dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec;
727dc7e38acSHans Petter Selasky 	priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts;
72874540a31SHans Petter Selasky 	priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode;
729dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec;
730dc7e38acSHans Petter Selasky 	priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts;
731dc7e38acSHans Petter Selasky 	priv->params_ethtool.hw_lro = priv->params.hw_lro_en;
73290cc1c77SHans Petter Selasky 	priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en;
733376bcf63SHans Petter Selasky 	mlx5e_ethtool_sync_tx_completion_fact(priv);
734dc7e38acSHans Petter Selasky 
735dc7e38acSHans Petter Selasky 	/* create root node */
736dc7e38acSHans Petter Selasky 	node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
737dc7e38acSHans Petter Selasky 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
738dc7e38acSHans Petter Selasky 	    "conf", CTLFLAG_RW, NULL, "Configuration");
739dc7e38acSHans Petter Selasky 	if (node == NULL)
740dc7e38acSHans Petter Selasky 		return;
741dc7e38acSHans Petter Selasky 	for (x = 0; x != MLX5E_PARAMS_NUM; x++) {
742dc7e38acSHans Petter Selasky 		/* check for read-only parameter */
743dc7e38acSHans Petter Selasky 		if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL) {
744dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
745dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD |
746dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
747dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
748dc7e38acSHans Petter Selasky 		} else {
749ec0143b2SHans Petter Selasky #if (__FreeBSD_version < 1100000)
750ec0143b2SHans Petter Selasky 			char path[64];
751ec0143b2SHans Petter Selasky #endif
752ec0143b2SHans Petter Selasky 			/*
753ec0143b2SHans Petter Selasky 			 * NOTE: In FreeBSD-11 and newer the
754ec0143b2SHans Petter Selasky 			 * CTLFLAG_RWTUN flag will take care of
755ec0143b2SHans Petter Selasky 			 * loading default sysctl value from the
756ec0143b2SHans Petter Selasky 			 * kernel environment, if any:
757ec0143b2SHans Petter Selasky 			 */
758dc7e38acSHans Petter Selasky 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
759dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN |
760dc7e38acSHans Petter Selasky 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
761dc7e38acSHans Petter Selasky 			    mlx5e_params_desc[2 * x + 1]);
762ec0143b2SHans Petter Selasky 
763ec0143b2SHans Petter Selasky #if (__FreeBSD_version < 1100000)
764ec0143b2SHans Petter Selasky 			/* compute path for sysctl */
765ec0143b2SHans Petter Selasky 			snprintf(path, sizeof(path), "dev.mce.%d.conf.%s",
766ec0143b2SHans Petter Selasky 			    device_get_unit(priv->mdev->pdev->dev.bsddev),
767ec0143b2SHans Petter Selasky 			    mlx5e_params_desc[2 * x]);
768ec0143b2SHans Petter Selasky 
769ec0143b2SHans Petter Selasky 			/* try to fetch tunable, if any */
770ec0143b2SHans Petter Selasky 			if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x]))
771ec0143b2SHans Petter Selasky 				mlx5e_ethtool_handler(NULL, priv, x, NULL);
772ec0143b2SHans Petter Selasky #endif
773dc7e38acSHans Petter Selasky 		}
774dc7e38acSHans Petter Selasky 	}
775dc7e38acSHans Petter Selasky 
776dc7e38acSHans Petter Selasky 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
777dc7e38acSHans Petter Selasky 	    "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv,
778dc7e38acSHans Petter Selasky 	    0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics");
779dc7e38acSHans Petter Selasky 
780dc7e38acSHans Petter Selasky 	pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
781dc7e38acSHans Petter Selasky 
782dc7e38acSHans Petter Selasky 	SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node),
783dc7e38acSHans Petter Selasky 	    OID_AUTO, "device_name", CTLFLAG_RD,
784dc7e38acSHans Petter Selasky 	    __DECONST(void *, pnameunit), 0,
785dc7e38acSHans Petter Selasky 	    "PCI device name");
786dc7e38acSHans Petter Selasky 
787dc7e38acSHans Petter Selasky 	/* EEPROM support */
788dc7e38acSHans Petter Selasky 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info",
789dc7e38acSHans Petter Selasky 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
790dc7e38acSHans Petter Selasky 	    mlx5e_read_eeprom, "I", "EEPROM information");
79166d53750SHans Petter Selasky 
79266d53750SHans Petter Selasky 	/* Diagnostics support */
79366d53750SHans Petter Selasky 	mlx5e_create_diagnostics(priv);
794dc7e38acSHans Petter Selasky }
795