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