mlx5_en_ethtool.c revision 353244
1290650Shselasky/*- 2353202Shselasky * Copyright (c) 2015-2019 Mellanox Technologies. All rights reserved. 3290650Shselasky * 4290650Shselasky * Redistribution and use in source and binary forms, with or without 5290650Shselasky * modification, are permitted provided that the following conditions 6290650Shselasky * are met: 7290650Shselasky * 1. Redistributions of source code must retain the above copyright 8290650Shselasky * notice, this list of conditions and the following disclaimer. 9290650Shselasky * 2. Redistributions in binary form must reproduce the above copyright 10290650Shselasky * notice, this list of conditions and the following disclaimer in the 11290650Shselasky * documentation and/or other materials provided with the distribution. 12290650Shselasky * 13290650Shselasky * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 14290650Shselasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15290650Shselasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16290650Shselasky * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17290650Shselasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18290650Shselasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19290650Shselasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20290650Shselasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21290650Shselasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22290650Shselasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23290650Shselasky * SUCH DAMAGE. 24290650Shselasky * 25290650Shselasky * $FreeBSD: stable/11/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c 353244 2019-10-07 09:52:10Z hselasky $ 26290650Shselasky */ 27290650Shselasky 28290650Shselasky#include "en.h" 29353238Shselasky#include "port_buffer.h" 30290650Shselasky 31290650Shselaskyvoid 32290650Shselaskymlx5e_create_stats(struct sysctl_ctx_list *ctx, 33290650Shselasky struct sysctl_oid_list *parent, const char *buffer, 34290650Shselasky const char **desc, unsigned num, u64 * arg) 35290650Shselasky{ 36290650Shselasky struct sysctl_oid *node; 37290650Shselasky unsigned x; 38290650Shselasky 39290650Shselasky sysctl_ctx_init(ctx); 40290650Shselasky 41290650Shselasky node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, 42290650Shselasky buffer, CTLFLAG_RD, NULL, "Statistics"); 43290650Shselasky if (node == NULL) 44290650Shselasky return; 45290650Shselasky for (x = 0; x != num; x++) { 46290650Shselasky SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 47290650Shselasky desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]); 48290650Shselasky } 49290650Shselasky} 50290650Shselasky 51300277Shselaskystatic void 52300277Shselaskymlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv *priv) 53300277Shselasky{ 54300277Shselasky /* 55300277Shselasky * Limit the maximum distance between completion events to 56300277Shselasky * half of the currently set TX queue size. 57300277Shselasky * 58300277Shselasky * The maximum number of queue entries a single IP packet can 59300277Shselasky * consume is given by MLX5_SEND_WQE_MAX_WQEBBS. 60300277Shselasky * 61300277Shselasky * The worst case max value is then given as below: 62300277Shselasky */ 63300277Shselasky uint64_t max = priv->params_ethtool.tx_queue_size / 64300277Shselasky (2 * MLX5_SEND_WQE_MAX_WQEBBS); 65300277Shselasky 66300277Shselasky /* 67300277Shselasky * Update the maximum completion factor value in case the 68300277Shselasky * tx_queue_size field changed. Ensure we don't overflow 69300277Shselasky * 16-bits. 70300277Shselasky */ 71300277Shselasky if (max < 1) 72300277Shselasky max = 1; 73300277Shselasky else if (max > 65535) 74300277Shselasky max = 65535; 75300277Shselasky priv->params_ethtool.tx_completion_fact_max = max; 76300277Shselasky 77300277Shselasky /* 78300277Shselasky * Verify that the current TX completion factor is within the 79300277Shselasky * given limits: 80300277Shselasky */ 81300277Shselasky if (priv->params_ethtool.tx_completion_fact < 1) 82300277Shselasky priv->params_ethtool.tx_completion_fact = 1; 83300277Shselasky else if (priv->params_ethtool.tx_completion_fact > max) 84300277Shselasky priv->params_ethtool.tx_completion_fact = max; 85300277Shselasky} 86300277Shselasky 87331577Shselaskystatic int 88331577Shselaskymlx5e_getmaxrate(struct mlx5e_priv *priv) 89331577Shselasky{ 90331577Shselasky struct mlx5_core_dev *mdev = priv->mdev; 91331577Shselasky u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; 92331577Shselasky u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; 93331577Shselasky int err; 94331577Shselasky int i; 95331577Shselasky 96331577Shselasky PRIV_LOCK(priv); 97331577Shselasky err = -mlx5_query_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit); 98331577Shselasky if (err) 99331577Shselasky goto done; 100331577Shselasky 101331577Shselasky for (i = 0; i <= mlx5_max_tc(mdev); i++) { 102331577Shselasky switch (max_bw_unit[i]) { 103331577Shselasky case MLX5_100_MBPS_UNIT: 104331577Shselasky priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_100MB; 105331577Shselasky break; 106331577Shselasky case MLX5_GBPS_UNIT: 107331577Shselasky priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_1GB; 108331577Shselasky break; 109331577Shselasky case MLX5_BW_NO_LIMIT: 110331577Shselasky priv->params_ethtool.max_bw_value[i] = 0; 111331577Shselasky break; 112331577Shselasky default: 113331577Shselasky priv->params_ethtool.max_bw_value[i] = -1; 114331577Shselasky WARN_ONCE(true, "non-supported BW unit"); 115331577Shselasky break; 116331577Shselasky } 117331577Shselasky } 118331577Shselaskydone: 119331577Shselasky PRIV_UNLOCK(priv); 120331577Shselasky return (err); 121331577Shselasky} 122331577Shselasky 123331577Shselaskystatic int 124341968Shselaskymlx5e_get_max_alloc(struct mlx5e_priv *priv) 125341968Shselasky{ 126341968Shselasky struct mlx5_core_dev *mdev = priv->mdev; 127341968Shselasky int err; 128341968Shselasky int x; 129341968Shselasky 130341968Shselasky PRIV_LOCK(priv); 131341968Shselasky err = -mlx5_query_port_tc_bw_alloc(mdev, priv->params_ethtool.max_bw_share); 132341968Shselasky if (err == 0) { 133341968Shselasky /* set default value */ 134341968Shselasky for (x = 0; x != IEEE_8021QAZ_MAX_TCS; x++) { 135341968Shselasky priv->params_ethtool.max_bw_share[x] = 136341968Shselasky 100 / IEEE_8021QAZ_MAX_TCS; 137341968Shselasky } 138341968Shselasky err = -mlx5_set_port_tc_bw_alloc(mdev, 139341968Shselasky priv->params_ethtool.max_bw_share); 140341968Shselasky } 141341968Shselasky PRIV_UNLOCK(priv); 142341968Shselasky 143341968Shselasky return (err); 144341968Shselasky} 145341968Shselasky 146341968Shselaskystatic int 147337098Shselaskymlx5e_get_dscp(struct mlx5e_priv *priv) 148337098Shselasky{ 149337098Shselasky struct mlx5_core_dev *mdev = priv->mdev; 150337098Shselasky int err; 151337098Shselasky 152337098Shselasky if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 || 153337098Shselasky MLX5_CAP_QCAM_REG(mdev, qpts) == 0 || 154337098Shselasky MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0) 155337098Shselasky return (EOPNOTSUPP); 156337098Shselasky 157337098Shselasky PRIV_LOCK(priv); 158337098Shselasky err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio); 159337098Shselasky if (err) 160337098Shselasky goto done; 161337098Shselasky 162337098Shselasky err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state); 163337098Shselasky if (err) 164337098Shselasky goto done; 165337098Shselaskydone: 166337098Shselasky PRIV_UNLOCK(priv); 167337098Shselasky return (err); 168337098Shselasky} 169337098Shselasky 170341968Shselaskystatic void 171341968Shselaskymlx5e_tc_get_parameters(struct mlx5e_priv *priv, 172341968Shselasky u64 *new_bw_value, u8 *max_bw_value, u8 *max_bw_unit) 173341968Shselasky{ 174341968Shselasky const u64 upper_limit_mbps = 255 * MLX5E_100MB; 175341968Shselasky const u64 upper_limit_gbps = 255 * MLX5E_1GB; 176341968Shselasky u64 temp; 177341968Shselasky int i; 178341968Shselasky 179341968Shselasky memset(max_bw_value, 0, IEEE_8021QAZ_MAX_TCS); 180341968Shselasky memset(max_bw_unit, 0, IEEE_8021QAZ_MAX_TCS); 181341968Shselasky 182341968Shselasky for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) { 183341968Shselasky temp = (new_bw_value != NULL) ? 184341968Shselasky new_bw_value[i] : priv->params_ethtool.max_bw_value[i]; 185341968Shselasky 186341968Shselasky if (!temp) { 187341968Shselasky max_bw_unit[i] = MLX5_BW_NO_LIMIT; 188341968Shselasky } else if (temp > upper_limit_gbps) { 189341968Shselasky max_bw_unit[i] = MLX5_BW_NO_LIMIT; 190341968Shselasky } else if (temp <= upper_limit_mbps) { 191341968Shselasky max_bw_value[i] = howmany(temp, MLX5E_100MB); 192341968Shselasky max_bw_unit[i] = MLX5_100_MBPS_UNIT; 193341968Shselasky } else { 194341968Shselasky max_bw_value[i] = howmany(temp, MLX5E_1GB); 195341968Shselasky max_bw_unit[i] = MLX5_GBPS_UNIT; 196341968Shselasky } 197341968Shselasky } 198341968Shselasky} 199341968Shselasky 200337098Shselaskystatic int 201331577Shselaskymlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS) 202331577Shselasky{ 203331577Shselasky struct mlx5e_priv *priv = arg1; 204331577Shselasky struct mlx5_core_dev *mdev = priv->mdev; 205331577Shselasky u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; 206331577Shselasky u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; 207341968Shselasky u64 new_bw_value[IEEE_8021QAZ_MAX_TCS]; 208341968Shselasky u8 max_rates = mlx5_max_tc(mdev) + 1; 209341968Shselasky u8 x; 210341968Shselasky int err; 211331577Shselasky 212331577Shselasky PRIV_LOCK(priv); 213341968Shselasky err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_value, 214341968Shselasky sizeof(priv->params_ethtool.max_bw_value[0]) * max_rates); 215341968Shselasky if (err || !req->newptr) 216331577Shselasky goto done; 217341968Shselasky err = SYSCTL_IN(req, new_bw_value, 218341968Shselasky sizeof(new_bw_value[0]) * max_rates); 219341968Shselasky if (err) 220341968Shselasky goto done; 221331577Shselasky 222341968Shselasky /* range check input value */ 223341968Shselasky for (x = 0; x != max_rates; x++) { 224341968Shselasky if (new_bw_value[x] % MLX5E_100MB) { 225341968Shselasky err = ERANGE; 226341968Shselasky goto done; 227341968Shselasky } 228331577Shselasky } 229331577Shselasky 230341968Shselasky mlx5e_tc_get_parameters(priv, new_bw_value, max_bw_value, max_bw_unit); 231331577Shselasky 232341968Shselasky err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit); 233341968Shselasky if (err) 234341968Shselasky goto done; 235331577Shselasky 236341968Shselasky memcpy(priv->params_ethtool.max_bw_value, new_bw_value, 237341968Shselasky sizeof(priv->params_ethtool.max_bw_value)); 238341968Shselaskydone: 239341968Shselasky PRIV_UNLOCK(priv); 240341968Shselasky return (err); 241341968Shselasky} 242341968Shselasky 243341968Shselaskystatic int 244341968Shselaskymlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS) 245341968Shselasky{ 246341968Shselasky struct mlx5e_priv *priv = arg1; 247341968Shselasky struct mlx5_core_dev *mdev = priv->mdev; 248341968Shselasky u8 max_bw_share[IEEE_8021QAZ_MAX_TCS]; 249341968Shselasky u8 max_rates = mlx5_max_tc(mdev) + 1; 250341968Shselasky int i; 251341968Shselasky int err; 252341968Shselasky int sum; 253341968Shselasky 254341968Shselasky PRIV_LOCK(priv); 255341968Shselasky err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_share, max_rates); 256341968Shselasky if (err || !req->newptr) 257341968Shselasky goto done; 258341968Shselasky err = SYSCTL_IN(req, max_bw_share, max_rates); 259341968Shselasky if (err) 260341968Shselasky goto done; 261341968Shselasky 262341968Shselasky /* range check input value */ 263341968Shselasky for (sum = i = 0; i != max_rates; i++) { 264341968Shselasky if (max_bw_share[i] < 1 || max_bw_share[i] > 100) { 265341968Shselasky err = ERANGE; 266341968Shselasky goto done; 267331577Shselasky } 268341968Shselasky sum += max_bw_share[i]; 269331577Shselasky } 270331577Shselasky 271341968Shselasky /* sum of values should be as close to 100 as possible */ 272341968Shselasky if (sum < (100 - max_rates + 1) || sum > 100) { 273341968Shselasky err = ERANGE; 274341968Shselasky goto done; 275341968Shselasky } 276341968Shselasky 277341968Shselasky err = -mlx5_set_port_tc_bw_alloc(mdev, max_bw_share); 278331577Shselasky if (err) 279331577Shselasky goto done; 280331577Shselasky 281341968Shselasky memcpy(priv->params_ethtool.max_bw_share, max_bw_share, 282341968Shselasky sizeof(priv->params_ethtool.max_bw_share)); 283331577Shselaskydone: 284331577Shselasky PRIV_UNLOCK(priv); 285331577Shselasky return (err); 286331577Shselasky} 287331577Shselasky 288331578Shselaskystatic int 289331578Shselaskymlx5e_get_prio_tc(struct mlx5e_priv *priv) 290331578Shselasky{ 291331578Shselasky struct mlx5_core_dev *mdev = priv->mdev; 292331578Shselasky int err = 0; 293331578Shselasky int i; 294331578Shselasky 295331578Shselasky PRIV_LOCK(priv); 296331578Shselasky if (!MLX5_CAP_GEN(priv->mdev, ets)) { 297331578Shselasky PRIV_UNLOCK(priv); 298331578Shselasky return (EOPNOTSUPP); 299331578Shselasky } 300331578Shselasky 301347810Shselasky for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 302347810Shselasky err = -mlx5_query_port_prio_tc(mdev, i, priv->params_ethtool.prio_tc + i); 303331578Shselasky if (err) 304331578Shselasky break; 305331578Shselasky } 306331578Shselasky PRIV_UNLOCK(priv); 307331578Shselasky return (err); 308331578Shselasky} 309331578Shselasky 310331578Shselaskystatic int 311331578Shselaskymlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS) 312331578Shselasky{ 313331578Shselasky struct mlx5e_priv *priv = arg1; 314331578Shselasky struct mlx5_core_dev *mdev = priv->mdev; 315347810Shselasky uint8_t temp[MLX5E_MAX_PRIORITY]; 316331578Shselasky int err; 317347810Shselasky int i; 318331578Shselasky 319331578Shselasky PRIV_LOCK(priv); 320347810Shselasky err = SYSCTL_OUT(req, priv->params_ethtool.prio_tc, MLX5E_MAX_PRIORITY); 321347810Shselasky if (err || !req->newptr) 322331578Shselasky goto done; 323347810Shselasky err = SYSCTL_IN(req, temp, MLX5E_MAX_PRIORITY); 324331578Shselasky if (err) 325331578Shselasky goto done; 326331578Shselasky 327347810Shselasky for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 328347810Shselasky if (temp[i] > mlx5_max_tc(mdev)) { 329347810Shselasky err = ERANGE; 330347810Shselasky goto done; 331347810Shselasky } 332347810Shselasky } 333331578Shselasky 334347810Shselasky for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 335347810Shselasky if (temp[i] == priv->params_ethtool.prio_tc[i]) 336347810Shselasky continue; 337347810Shselasky err = -mlx5_set_port_prio_tc(mdev, i, temp[i]); 338347810Shselasky if (err) 339347810Shselasky goto done; 340347810Shselasky /* update cached value */ 341347810Shselasky priv->params_ethtool.prio_tc[i] = temp[i]; 342347810Shselasky } 343331578Shselaskydone: 344331578Shselasky PRIV_UNLOCK(priv); 345331578Shselasky return (err); 346331578Shselasky} 347331578Shselasky 348353244Shselaskyint 349353244Shselaskymlx5e_fec_update(struct mlx5e_priv *priv) 350353244Shselasky{ 351353244Shselasky struct mlx5_core_dev *mdev = priv->mdev; 352353244Shselasky u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 353353244Shselasky const int sz = MLX5_ST_SZ_BYTES(pplm_reg); 354353244Shselasky int err; 355353244Shselasky 356353244Shselasky if (!MLX5_CAP_GEN(mdev, pcam_reg)) 357353244Shselasky return (EOPNOTSUPP); 358353244Shselasky 359353244Shselasky if (!MLX5_CAP_PCAM_REG(mdev, pplm)) 360353244Shselasky return (EOPNOTSUPP); 361353244Shselasky 362353244Shselasky MLX5_SET(pplm_reg, in, local_port, 1); 363353244Shselasky 364353244Shselasky err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0); 365353244Shselasky if (err) 366353244Shselasky return (err); 367353244Shselasky 368353244Shselasky /* get 10x..25x mask */ 369353244Shselasky priv->params_ethtool.fec_mask_10x_25x[0] = 370353244Shselasky MLX5_GET(pplm_reg, in, fec_override_admin_10g_40g); 371353244Shselasky priv->params_ethtool.fec_mask_10x_25x[1] = 372353244Shselasky MLX5_GET(pplm_reg, in, fec_override_admin_25g) & 373353244Shselasky MLX5_GET(pplm_reg, in, fec_override_admin_50g); 374353244Shselasky priv->params_ethtool.fec_mask_10x_25x[2] = 375353244Shselasky MLX5_GET(pplm_reg, in, fec_override_admin_56g); 376353244Shselasky priv->params_ethtool.fec_mask_10x_25x[3] = 377353244Shselasky MLX5_GET(pplm_reg, in, fec_override_admin_100g); 378353244Shselasky 379353244Shselasky /* get 10x..25x available bits */ 380353244Shselasky priv->params_ethtool.fec_avail_10x_25x[0] = 381353244Shselasky MLX5_GET(pplm_reg, in, fec_override_cap_10g_40g); 382353244Shselasky priv->params_ethtool.fec_avail_10x_25x[1] = 383353244Shselasky MLX5_GET(pplm_reg, in, fec_override_cap_25g) & 384353244Shselasky MLX5_GET(pplm_reg, in, fec_override_cap_50g); 385353244Shselasky priv->params_ethtool.fec_avail_10x_25x[2] = 386353244Shselasky MLX5_GET(pplm_reg, in, fec_override_cap_56g); 387353244Shselasky priv->params_ethtool.fec_avail_10x_25x[3] = 388353244Shselasky MLX5_GET(pplm_reg, in, fec_override_cap_100g); 389353244Shselasky 390353244Shselasky /* get 50x mask */ 391353244Shselasky priv->params_ethtool.fec_mask_50x[0] = 392353244Shselasky MLX5_GET(pplm_reg, in, fec_override_admin_50g_1x); 393353244Shselasky priv->params_ethtool.fec_mask_50x[1] = 394353244Shselasky MLX5_GET(pplm_reg, in, fec_override_admin_100g_2x); 395353244Shselasky priv->params_ethtool.fec_mask_50x[2] = 396353244Shselasky MLX5_GET(pplm_reg, in, fec_override_admin_200g_4x); 397353244Shselasky priv->params_ethtool.fec_mask_50x[3] = 398353244Shselasky MLX5_GET(pplm_reg, in, fec_override_admin_400g_8x); 399353244Shselasky 400353244Shselasky /* get 50x available bits */ 401353244Shselasky priv->params_ethtool.fec_avail_50x[0] = 402353244Shselasky MLX5_GET(pplm_reg, in, fec_override_cap_50g_1x); 403353244Shselasky priv->params_ethtool.fec_avail_50x[1] = 404353244Shselasky MLX5_GET(pplm_reg, in, fec_override_cap_100g_2x); 405353244Shselasky priv->params_ethtool.fec_avail_50x[2] = 406353244Shselasky MLX5_GET(pplm_reg, in, fec_override_cap_200g_4x); 407353244Shselasky priv->params_ethtool.fec_avail_50x[3] = 408353244Shselasky MLX5_GET(pplm_reg, in, fec_override_cap_400g_8x); 409353244Shselasky 410353244Shselasky /* get current FEC mask */ 411353244Shselasky priv->params_ethtool.fec_mode_active = 412353244Shselasky MLX5_GET(pplm_reg, in, fec_mode_active); 413353244Shselasky 414353244Shselasky return (0); 415353244Shselasky} 416353244Shselasky 417337098Shselaskystatic int 418353244Shselaskymlx5e_fec_mask_10x_25x_handler(SYSCTL_HANDLER_ARGS) 419353244Shselasky{ 420353244Shselasky struct mlx5e_priv *priv = arg1; 421353244Shselasky struct mlx5_core_dev *mdev = priv->mdev; 422353244Shselasky u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 423353244Shselasky u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 424353244Shselasky const int sz = MLX5_ST_SZ_BYTES(pplm_reg); 425353244Shselasky u8 fec_mask_10x_25x[MLX5E_MAX_FEC_10X_25X]; 426353244Shselasky u8 fec_cap_changed = 0; 427353244Shselasky u8 x; 428353244Shselasky int err; 429353244Shselasky 430353244Shselasky PRIV_LOCK(priv); 431353244Shselasky err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_10x_25x, 432353244Shselasky sizeof(priv->params_ethtool.fec_mask_10x_25x)); 433353244Shselasky if (err || !req->newptr) 434353244Shselasky goto done; 435353244Shselasky 436353244Shselasky err = SYSCTL_IN(req, fec_mask_10x_25x, 437353244Shselasky sizeof(fec_mask_10x_25x)); 438353244Shselasky if (err) 439353244Shselasky goto done; 440353244Shselasky 441353244Shselasky if (!MLX5_CAP_GEN(mdev, pcam_reg)) { 442353244Shselasky err = EOPNOTSUPP; 443353244Shselasky goto done; 444353244Shselasky } 445353244Shselasky 446353244Shselasky if (!MLX5_CAP_PCAM_REG(mdev, pplm)) { 447353244Shselasky err = EOPNOTSUPP; 448353244Shselasky goto done; 449353244Shselasky } 450353244Shselasky 451353244Shselasky MLX5_SET(pplm_reg, in, local_port, 1); 452353244Shselasky 453353244Shselasky err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0); 454353244Shselasky if (err) 455353244Shselasky goto done; 456353244Shselasky 457353244Shselasky /* range check input value */ 458353244Shselasky for (x = 0; x != MLX5E_MAX_FEC_10X_25X; x++) { 459353244Shselasky /* check only one bit is set, if any */ 460353244Shselasky if (fec_mask_10x_25x[x] & (fec_mask_10x_25x[x] - 1)) { 461353244Shselasky err = ERANGE; 462353244Shselasky goto done; 463353244Shselasky } 464353244Shselasky /* check a supported bit is set, if any */ 465353244Shselasky if (fec_mask_10x_25x[x] & 466353244Shselasky ~priv->params_ethtool.fec_avail_10x_25x[x]) { 467353244Shselasky err = ERANGE; 468353244Shselasky goto done; 469353244Shselasky } 470353244Shselasky fec_cap_changed |= (fec_mask_10x_25x[x] ^ 471353244Shselasky priv->params_ethtool.fec_mask_10x_25x[x]); 472353244Shselasky } 473353244Shselasky 474353244Shselasky /* check for no changes */ 475353244Shselasky if (fec_cap_changed == 0) 476353244Shselasky goto done; 477353244Shselasky 478353244Shselasky memset(in, 0, sizeof(in)); 479353244Shselasky 480353244Shselasky MLX5_SET(pplm_reg, in, local_port, 1); 481353244Shselasky 482353244Shselasky /* set new values */ 483353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, fec_mask_10x_25x[0]); 484353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_25g, fec_mask_10x_25x[1]); 485353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_50g, fec_mask_10x_25x[1]); 486353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_56g, fec_mask_10x_25x[2]); 487353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_100g, fec_mask_10x_25x[3]); 488353244Shselasky 489353244Shselasky /* preserve other values */ 490353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, priv->params_ethtool.fec_mask_50x[0]); 491353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, priv->params_ethtool.fec_mask_50x[1]); 492353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, priv->params_ethtool.fec_mask_50x[2]); 493353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, priv->params_ethtool.fec_mask_50x[3]); 494353244Shselasky 495353244Shselasky /* send new value to the firmware */ 496353244Shselasky err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1); 497353244Shselasky if (err) 498353244Shselasky goto done; 499353244Shselasky 500353244Shselasky memcpy(priv->params_ethtool.fec_mask_10x_25x, fec_mask_10x_25x, 501353244Shselasky sizeof(priv->params_ethtool.fec_mask_10x_25x)); 502353244Shselasky 503353244Shselasky mlx5_toggle_port_link(priv->mdev); 504353244Shselaskydone: 505353244Shselasky PRIV_UNLOCK(priv); 506353244Shselasky return (err); 507353244Shselasky} 508353244Shselasky 509353244Shselaskystatic int 510353244Shselaskymlx5e_fec_avail_10x_25x_handler(SYSCTL_HANDLER_ARGS) 511353244Shselasky{ 512353244Shselasky struct mlx5e_priv *priv = arg1; 513353244Shselasky int err; 514353244Shselasky 515353244Shselasky PRIV_LOCK(priv); 516353244Shselasky err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_10x_25x, 517353244Shselasky sizeof(priv->params_ethtool.fec_avail_10x_25x)); 518353244Shselasky PRIV_UNLOCK(priv); 519353244Shselasky return (err); 520353244Shselasky} 521353244Shselasky 522353244Shselaskystatic int 523353244Shselaskymlx5e_fec_mask_50x_handler(SYSCTL_HANDLER_ARGS) 524353244Shselasky{ 525353244Shselasky struct mlx5e_priv *priv = arg1; 526353244Shselasky struct mlx5_core_dev *mdev = priv->mdev; 527353244Shselasky u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 528353244Shselasky u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 529353244Shselasky const int sz = MLX5_ST_SZ_BYTES(pplm_reg); 530353244Shselasky u16 fec_mask_50x[MLX5E_MAX_FEC_50X]; 531353244Shselasky u16 fec_cap_changed = 0; 532353244Shselasky u8 x; 533353244Shselasky int err; 534353244Shselasky 535353244Shselasky PRIV_LOCK(priv); 536353244Shselasky err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_50x, 537353244Shselasky sizeof(priv->params_ethtool.fec_mask_50x)); 538353244Shselasky if (err || !req->newptr) 539353244Shselasky goto done; 540353244Shselasky 541353244Shselasky err = SYSCTL_IN(req, fec_mask_50x, 542353244Shselasky sizeof(fec_mask_50x)); 543353244Shselasky if (err) 544353244Shselasky goto done; 545353244Shselasky 546353244Shselasky if (!MLX5_CAP_GEN(mdev, pcam_reg)) { 547353244Shselasky err = EOPNOTSUPP; 548353244Shselasky goto done; 549353244Shselasky } 550353244Shselasky 551353244Shselasky if (!MLX5_CAP_PCAM_REG(mdev, pplm)) { 552353244Shselasky err = EOPNOTSUPP; 553353244Shselasky goto done; 554353244Shselasky } 555353244Shselasky 556353244Shselasky MLX5_SET(pplm_reg, in, local_port, 1); 557353244Shselasky 558353244Shselasky err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0); 559353244Shselasky if (err) 560353244Shselasky goto done; 561353244Shselasky 562353244Shselasky /* range check input value */ 563353244Shselasky for (x = 0; x != MLX5E_MAX_FEC_50X; x++) { 564353244Shselasky /* check only one bit is set, if any */ 565353244Shselasky if (fec_mask_50x[x] & (fec_mask_50x[x] - 1)) { 566353244Shselasky err = ERANGE; 567353244Shselasky goto done; 568353244Shselasky } 569353244Shselasky /* check a supported bit is set, if any */ 570353244Shselasky if (fec_mask_50x[x] & 571353244Shselasky ~priv->params_ethtool.fec_avail_50x[x]) { 572353244Shselasky err = ERANGE; 573353244Shselasky goto done; 574353244Shselasky } 575353244Shselasky fec_cap_changed |= (fec_mask_50x[x] ^ 576353244Shselasky priv->params_ethtool.fec_mask_50x[x]); 577353244Shselasky } 578353244Shselasky 579353244Shselasky /* check for no changes */ 580353244Shselasky if (fec_cap_changed == 0) 581353244Shselasky goto done; 582353244Shselasky 583353244Shselasky memset(in, 0, sizeof(in)); 584353244Shselasky 585353244Shselasky MLX5_SET(pplm_reg, in, local_port, 1); 586353244Shselasky 587353244Shselasky /* set new values */ 588353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, fec_mask_50x[0]); 589353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, fec_mask_50x[1]); 590353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, fec_mask_50x[2]); 591353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, fec_mask_50x[3]); 592353244Shselasky 593353244Shselasky /* preserve other values */ 594353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, priv->params_ethtool.fec_mask_10x_25x[0]); 595353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_25g, priv->params_ethtool.fec_mask_10x_25x[1]); 596353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_50g, priv->params_ethtool.fec_mask_10x_25x[1]); 597353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_56g, priv->params_ethtool.fec_mask_10x_25x[2]); 598353244Shselasky MLX5_SET(pplm_reg, in, fec_override_admin_100g, priv->params_ethtool.fec_mask_10x_25x[3]); 599353244Shselasky 600353244Shselasky /* send new value to the firmware */ 601353244Shselasky err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1); 602353244Shselasky if (err) 603353244Shselasky goto done; 604353244Shselasky 605353244Shselasky memcpy(priv->params_ethtool.fec_mask_50x, fec_mask_50x, 606353244Shselasky sizeof(priv->params_ethtool.fec_mask_50x)); 607353244Shselasky 608353244Shselasky mlx5_toggle_port_link(priv->mdev); 609353244Shselaskydone: 610353244Shselasky PRIV_UNLOCK(priv); 611353244Shselasky return (err); 612353244Shselasky} 613353244Shselasky 614353244Shselaskystatic int 615353244Shselaskymlx5e_fec_avail_50x_handler(SYSCTL_HANDLER_ARGS) 616353244Shselasky{ 617353244Shselasky struct mlx5e_priv *priv = arg1; 618353244Shselasky int err; 619353244Shselasky 620353244Shselasky PRIV_LOCK(priv); 621353244Shselasky err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_50x, 622353244Shselasky sizeof(priv->params_ethtool.fec_avail_50x)); 623353244Shselasky PRIV_UNLOCK(priv); 624353244Shselasky return (err); 625353244Shselasky} 626353244Shselasky 627353244Shselaskystatic int 628337098Shselaskymlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS) 629337098Shselasky{ 630337098Shselasky struct mlx5e_priv *priv = arg1; 631337098Shselasky struct mlx5_core_dev *mdev = priv->mdev; 632337098Shselasky int err; 633337098Shselasky u8 result; 634337098Shselasky 635337098Shselasky PRIV_LOCK(priv); 636337098Shselasky result = priv->params_ethtool.trust_state; 637337098Shselasky err = sysctl_handle_8(oidp, &result, 0, req); 638337098Shselasky if (err || !req->newptr || 639337098Shselasky result == priv->params_ethtool.trust_state) 640337098Shselasky goto done; 641337098Shselasky 642337098Shselasky switch (result) { 643337098Shselasky case MLX5_QPTS_TRUST_PCP: 644337098Shselasky case MLX5_QPTS_TRUST_DSCP: 645337098Shselasky break; 646337098Shselasky case MLX5_QPTS_TRUST_BOTH: 647337098Shselasky if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) { 648337098Shselasky err = EOPNOTSUPP; 649337098Shselasky goto done; 650337098Shselasky } 651337098Shselasky break; 652337098Shselasky default: 653337098Shselasky err = ERANGE; 654337098Shselasky goto done; 655337098Shselasky } 656337098Shselasky 657337098Shselasky err = -mlx5_set_trust_state(mdev, result); 658337098Shselasky if (err) 659337098Shselasky goto done; 660337098Shselasky 661337098Shselasky priv->params_ethtool.trust_state = result; 662341972Shselasky 663341972Shselasky /* update inline mode */ 664341972Shselasky mlx5e_refresh_sq_inline(priv); 665341972Shselasky#ifdef RATELIMIT 666341972Shselasky mlx5e_rl_refresh_sq_inline(&priv->rl); 667341972Shselasky#endif 668337098Shselaskydone: 669337098Shselasky PRIV_UNLOCK(priv); 670337098Shselasky return (err); 671337098Shselasky} 672337098Shselasky 673337098Shselaskystatic int 674337098Shselaskymlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS) 675337098Shselasky{ 676337098Shselasky struct mlx5e_priv *priv = arg1; 677337098Shselasky int prio_index = arg2; 678337098Shselasky struct mlx5_core_dev *mdev = priv->mdev; 679337098Shselasky uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP]; 680337098Shselasky uint8_t x; 681337098Shselasky int err; 682337098Shselasky 683337098Shselasky PRIV_LOCK(priv); 684337098Shselasky err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index, 685337098Shselasky sizeof(priv->params_ethtool.dscp2prio) / 8); 686337098Shselasky if (err || !req->newptr) 687337098Shselasky goto done; 688337098Shselasky 689337098Shselasky memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio)); 690337098Shselasky err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8); 691337098Shselasky if (err) 692337098Shselasky goto done; 693337098Shselasky for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) { 694337098Shselasky if (dscp2prio[x] > 7) { 695337098Shselasky err = ERANGE; 696337098Shselasky goto done; 697337098Shselasky } 698337098Shselasky } 699337098Shselasky err = -mlx5_set_dscp2prio(mdev, dscp2prio); 700337098Shselasky if (err) 701337098Shselasky goto done; 702337098Shselasky 703337098Shselasky /* update local array */ 704337098Shselasky memcpy(priv->params_ethtool.dscp2prio, dscp2prio, 705337098Shselasky sizeof(priv->params_ethtool.dscp2prio)); 706337098Shselaskydone: 707337098Shselasky PRIV_UNLOCK(priv); 708337098Shselasky return (err); 709337098Shselasky} 710337098Shselasky 711353238Shselaskyint 712353238Shselaskymlx5e_update_buf_lossy(struct mlx5e_priv *priv) 713353238Shselasky{ 714353238Shselasky struct ieee_pfc pfc; 715353238Shselasky 716353238Shselasky PRIV_ASSERT_LOCKED(priv); 717353238Shselasky bzero(&pfc, sizeof(pfc)); 718353238Shselasky pfc.pfc_en = priv->params.rx_priority_flow_control; 719353238Shselasky return (-mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_PFC, 720353238Shselasky priv->params_ethtool.hw_mtu, &pfc, NULL, NULL)); 721353238Shselasky} 722353238Shselasky 723353238Shselaskystatic int 724353238Shselaskymlx5e_buf_size_handler(SYSCTL_HANDLER_ARGS) 725353238Shselasky{ 726353238Shselasky struct mlx5e_priv *priv; 727353238Shselasky u32 buf_size[MLX5E_MAX_BUFFER]; 728353238Shselasky struct mlx5e_port_buffer port_buffer; 729353238Shselasky int error, i; 730353238Shselasky 731353238Shselasky priv = arg1; 732353238Shselasky PRIV_LOCK(priv); 733353238Shselasky error = -mlx5e_port_query_buffer(priv, &port_buffer); 734353238Shselasky if (error != 0) 735353238Shselasky goto done; 736353238Shselasky for (i = 0; i < nitems(buf_size); i++) 737353238Shselasky buf_size[i] = port_buffer.buffer[i].size; 738353238Shselasky error = SYSCTL_OUT(req, buf_size, sizeof(buf_size)); 739353238Shselasky if (error != 0 || req->newptr == NULL) 740353238Shselasky goto done; 741353238Shselasky error = SYSCTL_IN(req, buf_size, sizeof(buf_size)); 742353238Shselasky if (error != 0) 743353238Shselasky goto done; 744353238Shselasky error = -mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_SIZE, 745353238Shselasky priv->params_ethtool.hw_mtu, NULL, buf_size, NULL); 746353238Shselaskydone: 747353238Shselasky PRIV_UNLOCK(priv); 748353238Shselasky return (error); 749353238Shselasky} 750353238Shselasky 751353238Shselaskystatic int 752353238Shselaskymlx5e_buf_prio_handler(SYSCTL_HANDLER_ARGS) 753353238Shselasky{ 754353238Shselasky struct mlx5e_priv *priv; 755353238Shselasky struct mlx5_core_dev *mdev; 756353238Shselasky u8 buffer[MLX5E_MAX_BUFFER]; 757353238Shselasky int error; 758353238Shselasky 759353238Shselasky priv = arg1; 760353238Shselasky mdev = priv->mdev; 761353238Shselasky PRIV_LOCK(priv); 762353238Shselasky error = -mlx5e_port_query_priority2buffer(mdev, buffer); 763353238Shselasky if (error != 0) 764353238Shselasky goto done; 765353238Shselasky error = SYSCTL_OUT(req, buffer, MLX5E_MAX_BUFFER); 766353238Shselasky if (error != 0 || req->newptr == NULL) 767353238Shselasky goto done; 768353238Shselasky error = SYSCTL_IN(req, buffer, MLX5E_MAX_BUFFER); 769353238Shselasky if (error != 0) 770353238Shselasky goto done; 771353238Shselasky error = -mlx5e_port_manual_buffer_config(priv, 772353238Shselasky MLX5E_PORT_BUFFER_PRIO2BUFFER, 773353238Shselasky priv->params_ethtool.hw_mtu, NULL, NULL, buffer); 774353238Shselasky if (error == 0) 775353238Shselasky error = mlx5e_update_buf_lossy(priv); 776353238Shselaskydone: 777353238Shselasky PRIV_UNLOCK(priv); 778353238Shselasky return (error); 779353238Shselasky} 780353238Shselasky 781353238Shselaskystatic int 782353238Shselaskymlx5e_cable_length_handler(SYSCTL_HANDLER_ARGS) 783353238Shselasky{ 784353238Shselasky struct mlx5e_priv *priv; 785353238Shselasky u_int cable_len; 786353238Shselasky int error; 787353238Shselasky 788353238Shselasky priv = arg1; 789353238Shselasky PRIV_LOCK(priv); 790353238Shselasky cable_len = priv->dcbx.cable_len; 791353238Shselasky error = sysctl_handle_int(oidp, &cable_len, 0, req); 792353238Shselasky if (error == 0 && req->newptr != NULL && 793353238Shselasky cable_len != priv->dcbx.cable_len) { 794353238Shselasky error = -mlx5e_port_manual_buffer_config(priv, 795353238Shselasky MLX5E_PORT_BUFFER_CABLE_LEN, priv->params_ethtool.hw_mtu, 796353238Shselasky NULL, NULL, NULL); 797353238Shselasky if (error == 0) 798353238Shselasky priv->dcbx.cable_len = cable_len; 799353238Shselasky } 800353238Shselasky PRIV_UNLOCK(priv); 801353238Shselasky return (error); 802353238Shselasky} 803353238Shselasky 804300282Shselasky#define MLX5_PARAM_OFFSET(n) \ 805300282Shselasky __offsetof(struct mlx5e_priv, params_ethtool.n) 806300282Shselasky 807290650Shselaskystatic int 808290650Shselaskymlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) 809290650Shselasky{ 810290650Shselasky struct mlx5e_priv *priv = arg1; 811290650Shselasky uint64_t value; 812321995Shselasky int mode_modify; 813290650Shselasky int was_opened; 814290650Shselasky int error; 815290650Shselasky 816290650Shselasky PRIV_LOCK(priv); 817290650Shselasky value = priv->params_ethtool.arg[arg2]; 818292837Shselasky if (req != NULL) { 819292837Shselasky error = sysctl_handle_64(oidp, &value, 0, req); 820292837Shselasky if (error || req->newptr == NULL || 821292837Shselasky value == priv->params_ethtool.arg[arg2]) 822292837Shselasky goto done; 823290650Shselasky 824292837Shselasky /* assign new value */ 825292837Shselasky priv->params_ethtool.arg[arg2] = value; 826292837Shselasky } else { 827292837Shselasky error = 0; 828292837Shselasky } 829290650Shselasky /* check if device is gone */ 830290650Shselasky if (priv->gone) { 831290650Shselasky error = ENXIO; 832290650Shselasky goto done; 833290650Shselasky } 834300282Shselasky was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 835321995Shselasky mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify); 836290650Shselasky 837300282Shselasky switch (MLX5_PARAM_OFFSET(arg[arg2])) { 838300282Shselasky case MLX5_PARAM_OFFSET(rx_coalesce_usecs): 839300282Shselasky /* import RX coal time */ 840300282Shselasky if (priv->params_ethtool.rx_coalesce_usecs < 1) 841300282Shselasky priv->params_ethtool.rx_coalesce_usecs = 0; 842300282Shselasky else if (priv->params_ethtool.rx_coalesce_usecs > 843300282Shselasky MLX5E_FLD_MAX(cqc, cq_period)) { 844300282Shselasky priv->params_ethtool.rx_coalesce_usecs = 845300282Shselasky MLX5E_FLD_MAX(cqc, cq_period); 846300282Shselasky } 847300282Shselasky priv->params.rx_cq_moderation_usec = 848300282Shselasky priv->params_ethtool.rx_coalesce_usecs; 849292949Shselasky 850300282Shselasky /* check to avoid down and up the network interface */ 851300282Shselasky if (was_opened) 852300282Shselasky error = mlx5e_refresh_channel_params(priv); 853300282Shselasky break; 854292949Shselasky 855300282Shselasky case MLX5_PARAM_OFFSET(rx_coalesce_pkts): 856300282Shselasky /* import RX coal pkts */ 857300282Shselasky if (priv->params_ethtool.rx_coalesce_pkts < 1) 858300282Shselasky priv->params_ethtool.rx_coalesce_pkts = 0; 859300282Shselasky else if (priv->params_ethtool.rx_coalesce_pkts > 860300282Shselasky MLX5E_FLD_MAX(cqc, cq_max_count)) { 861300282Shselasky priv->params_ethtool.rx_coalesce_pkts = 862300282Shselasky MLX5E_FLD_MAX(cqc, cq_max_count); 863300282Shselasky } 864300282Shselasky priv->params.rx_cq_moderation_pkts = 865300282Shselasky priv->params_ethtool.rx_coalesce_pkts; 866292949Shselasky 867300282Shselasky /* check to avoid down and up the network interface */ 868300282Shselasky if (was_opened) 869300282Shselasky error = mlx5e_refresh_channel_params(priv); 870300282Shselasky break; 871292949Shselasky 872300282Shselasky case MLX5_PARAM_OFFSET(tx_coalesce_usecs): 873300282Shselasky /* import TX coal time */ 874300282Shselasky if (priv->params_ethtool.tx_coalesce_usecs < 1) 875300282Shselasky priv->params_ethtool.tx_coalesce_usecs = 0; 876300282Shselasky else if (priv->params_ethtool.tx_coalesce_usecs > 877300282Shselasky MLX5E_FLD_MAX(cqc, cq_period)) { 878300282Shselasky priv->params_ethtool.tx_coalesce_usecs = 879300282Shselasky MLX5E_FLD_MAX(cqc, cq_period); 880300282Shselasky } 881300282Shselasky priv->params.tx_cq_moderation_usec = 882300282Shselasky priv->params_ethtool.tx_coalesce_usecs; 883300282Shselasky 884300282Shselasky /* check to avoid down and up the network interface */ 885300282Shselasky if (was_opened) 886292949Shselasky error = mlx5e_refresh_channel_params(priv); 887300282Shselasky break; 888300282Shselasky 889300282Shselasky case MLX5_PARAM_OFFSET(tx_coalesce_pkts): 890300282Shselasky /* import TX coal pkts */ 891300282Shselasky if (priv->params_ethtool.tx_coalesce_pkts < 1) 892300282Shselasky priv->params_ethtool.tx_coalesce_pkts = 0; 893300282Shselasky else if (priv->params_ethtool.tx_coalesce_pkts > 894300282Shselasky MLX5E_FLD_MAX(cqc, cq_max_count)) { 895300282Shselasky priv->params_ethtool.tx_coalesce_pkts = 896300282Shselasky MLX5E_FLD_MAX(cqc, cq_max_count); 897292949Shselasky } 898300282Shselasky priv->params.tx_cq_moderation_pkts = 899300282Shselasky priv->params_ethtool.tx_coalesce_pkts; 900300282Shselasky 901300282Shselasky /* check to avoid down and up the network interface */ 902300282Shselasky if (was_opened) 903300282Shselasky error = mlx5e_refresh_channel_params(priv); 904300282Shselasky break; 905300282Shselasky 906300282Shselasky case MLX5_PARAM_OFFSET(tx_queue_size): 907300282Shselasky /* network interface must be down */ 908300282Shselasky if (was_opened) 909300282Shselasky mlx5e_close_locked(priv->ifp); 910300282Shselasky 911300282Shselasky /* import TX queue size */ 912300282Shselasky if (priv->params_ethtool.tx_queue_size < 913300282Shselasky (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { 914300282Shselasky priv->params_ethtool.tx_queue_size = 915300282Shselasky (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); 916300282Shselasky } else if (priv->params_ethtool.tx_queue_size > 917300282Shselasky priv->params_ethtool.tx_queue_size_max) { 918300282Shselasky priv->params_ethtool.tx_queue_size = 919300282Shselasky priv->params_ethtool.tx_queue_size_max; 920300282Shselasky } 921300282Shselasky /* store actual TX queue size */ 922300282Shselasky priv->params.log_sq_size = 923300282Shselasky order_base_2(priv->params_ethtool.tx_queue_size); 924290650Shselasky priv->params_ethtool.tx_queue_size = 925300282Shselasky 1 << priv->params.log_sq_size; 926290650Shselasky 927300282Shselasky /* verify TX completion factor */ 928300282Shselasky mlx5e_ethtool_sync_tx_completion_fact(priv); 929300282Shselasky 930300282Shselasky /* restart network interface, if any */ 931300282Shselasky if (was_opened) 932300282Shselasky mlx5e_open_locked(priv->ifp); 933300282Shselasky break; 934300282Shselasky 935300282Shselasky case MLX5_PARAM_OFFSET(rx_queue_size): 936300282Shselasky /* network interface must be down */ 937300282Shselasky if (was_opened) 938300282Shselasky mlx5e_close_locked(priv->ifp); 939300282Shselasky 940300282Shselasky /* import RX queue size */ 941300282Shselasky if (priv->params_ethtool.rx_queue_size < 942300282Shselasky (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { 943300282Shselasky priv->params_ethtool.rx_queue_size = 944300282Shselasky (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); 945300282Shselasky } else if (priv->params_ethtool.rx_queue_size > 946300282Shselasky priv->params_ethtool.rx_queue_size_max) { 947300282Shselasky priv->params_ethtool.rx_queue_size = 948300282Shselasky priv->params_ethtool.rx_queue_size_max; 949300282Shselasky } 950300282Shselasky /* store actual RX queue size */ 951300282Shselasky priv->params.log_rq_size = 952300282Shselasky order_base_2(priv->params_ethtool.rx_queue_size); 953290650Shselasky priv->params_ethtool.rx_queue_size = 954300282Shselasky 1 << priv->params.log_rq_size; 955290650Shselasky 956300282Shselasky /* update least number of RX WQEs */ 957300282Shselasky priv->params.min_rx_wqes = min( 958300282Shselasky priv->params_ethtool.rx_queue_size - 1, 959300282Shselasky MLX5E_PARAMS_DEFAULT_MIN_RX_WQES); 960290650Shselasky 961300282Shselasky /* restart network interface, if any */ 962300282Shselasky if (was_opened) 963300282Shselasky mlx5e_open_locked(priv->ifp); 964300282Shselasky break; 965290650Shselasky 966338552Shselasky case MLX5_PARAM_OFFSET(channels_rsss): 967338552Shselasky /* network interface must be down */ 968338552Shselasky if (was_opened) 969338552Shselasky mlx5e_close_locked(priv->ifp); 970338552Shselasky 971338552Shselasky /* import number of channels */ 972338552Shselasky if (priv->params_ethtool.channels_rsss < 1) 973338552Shselasky priv->params_ethtool.channels_rsss = 1; 974338552Shselasky else if (priv->params_ethtool.channels_rsss > 128) 975338552Shselasky priv->params_ethtool.channels_rsss = 128; 976338552Shselasky 977338552Shselasky priv->params.channels_rsss = priv->params_ethtool.channels_rsss; 978338552Shselasky 979338552Shselasky /* restart network interface, if any */ 980338552Shselasky if (was_opened) 981338552Shselasky mlx5e_open_locked(priv->ifp); 982338552Shselasky break; 983338552Shselasky 984300282Shselasky case MLX5_PARAM_OFFSET(channels): 985300282Shselasky /* network interface must be down */ 986300282Shselasky if (was_opened) 987300282Shselasky mlx5e_close_locked(priv->ifp); 988290650Shselasky 989300282Shselasky /* import number of channels */ 990300282Shselasky if (priv->params_ethtool.channels < 1) 991300282Shselasky priv->params_ethtool.channels = 1; 992300282Shselasky else if (priv->params_ethtool.channels > 993300282Shselasky (u64) priv->mdev->priv.eq_table.num_comp_vectors) { 994300282Shselasky priv->params_ethtool.channels = 995300282Shselasky (u64) priv->mdev->priv.eq_table.num_comp_vectors; 996300282Shselasky } 997300282Shselasky priv->params.num_channels = priv->params_ethtool.channels; 998291932Shselasky 999300282Shselasky /* restart network interface, if any */ 1000300282Shselasky if (was_opened) 1001300282Shselasky mlx5e_open_locked(priv->ifp); 1002300282Shselasky break; 1003300282Shselasky 1004300282Shselasky case MLX5_PARAM_OFFSET(rx_coalesce_mode): 1005300282Shselasky /* network interface must be down */ 1006321995Shselasky if (was_opened != 0 && mode_modify == 0) 1007300282Shselasky mlx5e_close_locked(priv->ifp); 1008300282Shselasky 1009300282Shselasky /* import RX coalesce mode */ 1010347796Shselasky if (priv->params_ethtool.rx_coalesce_mode > 3) 1011347796Shselasky priv->params_ethtool.rx_coalesce_mode = 3; 1012300282Shselasky priv->params.rx_cq_moderation_mode = 1013300282Shselasky priv->params_ethtool.rx_coalesce_mode; 1014300282Shselasky 1015300282Shselasky /* restart network interface, if any */ 1016321995Shselasky if (was_opened != 0) { 1017321995Shselasky if (mode_modify == 0) 1018321995Shselasky mlx5e_open_locked(priv->ifp); 1019321995Shselasky else 1020321995Shselasky error = mlx5e_refresh_channel_params(priv); 1021321995Shselasky } 1022300282Shselasky break; 1023300282Shselasky 1024300282Shselasky case MLX5_PARAM_OFFSET(tx_coalesce_mode): 1025300282Shselasky /* network interface must be down */ 1026321995Shselasky if (was_opened != 0 && mode_modify == 0) 1027300282Shselasky mlx5e_close_locked(priv->ifp); 1028300282Shselasky 1029300282Shselasky /* import TX coalesce mode */ 1030300282Shselasky if (priv->params_ethtool.tx_coalesce_mode != 0) 1031300282Shselasky priv->params_ethtool.tx_coalesce_mode = 1; 1032300282Shselasky priv->params.tx_cq_moderation_mode = 1033300282Shselasky priv->params_ethtool.tx_coalesce_mode; 1034300282Shselasky 1035300282Shselasky /* restart network interface, if any */ 1036321995Shselasky if (was_opened != 0) { 1037321995Shselasky if (mode_modify == 0) 1038321995Shselasky mlx5e_open_locked(priv->ifp); 1039321995Shselasky else 1040321995Shselasky error = mlx5e_refresh_channel_params(priv); 1041321995Shselasky } 1042300282Shselasky break; 1043300282Shselasky 1044300282Shselasky case MLX5_PARAM_OFFSET(hw_lro): 1045300282Shselasky /* network interface must be down */ 1046300282Shselasky if (was_opened) 1047300282Shselasky mlx5e_close_locked(priv->ifp); 1048300282Shselasky 1049300282Shselasky /* import HW LRO mode */ 1050341983Shselasky if (priv->params_ethtool.hw_lro != 0 && 1051341983Shselasky MLX5_CAP_ETH(priv->mdev, lro_cap)) { 1052341983Shselasky priv->params_ethtool.hw_lro = 1; 1053341983Shselasky /* check if feature should actually be enabled */ 1054341983Shselasky if (priv->ifp->if_capenable & IFCAP_LRO) { 1055341983Shselasky priv->params.hw_lro_en = true; 1056300282Shselasky } else { 1057341983Shselasky priv->params.hw_lro_en = false; 1058300282Shselasky 1059353226Shselasky mlx5_en_warn(priv->ifp, "To enable HW LRO " 1060341983Shselasky "please also enable LRO via ifconfig(8).\n"); 1061300282Shselasky } 1062294319Shselasky } else { 1063341983Shselasky /* return an error if HW does not support this feature */ 1064341983Shselasky if (priv->params_ethtool.hw_lro != 0) 1065341983Shselasky error = EINVAL; 1066341983Shselasky priv->params.hw_lro_en = false; 1067341983Shselasky priv->params_ethtool.hw_lro = 0; 1068291068Shselasky } 1069300282Shselasky /* restart network interface, if any */ 1070300282Shselasky if (was_opened) 1071300282Shselasky mlx5e_open_locked(priv->ifp); 1072300282Shselasky break; 1073290650Shselasky 1074300282Shselasky case MLX5_PARAM_OFFSET(cqe_zipping): 1075300282Shselasky /* network interface must be down */ 1076300282Shselasky if (was_opened) 1077300282Shselasky mlx5e_close_locked(priv->ifp); 1078300282Shselasky 1079300282Shselasky /* import CQE zipping mode */ 1080292838Shselasky if (priv->params_ethtool.cqe_zipping && 1081292838Shselasky MLX5_CAP_GEN(priv->mdev, cqe_compression)) { 1082292838Shselasky priv->params.cqe_zipping_en = true; 1083292838Shselasky priv->params_ethtool.cqe_zipping = 1; 1084292838Shselasky } else { 1085292838Shselasky priv->params.cqe_zipping_en = false; 1086292838Shselasky priv->params_ethtool.cqe_zipping = 0; 1087292838Shselasky } 1088300282Shselasky /* restart network interface, if any */ 1089300282Shselasky if (was_opened) 1090300282Shselasky mlx5e_open_locked(priv->ifp); 1091300282Shselasky break; 1092300277Shselasky 1093300282Shselasky case MLX5_PARAM_OFFSET(tx_completion_fact): 1094300282Shselasky /* network interface must be down */ 1095300282Shselasky if (was_opened) 1096300282Shselasky mlx5e_close_locked(priv->ifp); 1097300282Shselasky 1098300277Shselasky /* verify parameter */ 1099300277Shselasky mlx5e_ethtool_sync_tx_completion_fact(priv); 1100300282Shselasky 1101300282Shselasky /* restart network interface, if any */ 1102300282Shselasky if (was_opened) 1103300282Shselasky mlx5e_open_locked(priv->ifp); 1104300282Shselasky break; 1105300282Shselasky 1106331568Shselasky case MLX5_PARAM_OFFSET(modify_tx_dma): 1107331568Shselasky /* check if network interface is opened */ 1108331568Shselasky if (was_opened) { 1109331568Shselasky priv->params_ethtool.modify_tx_dma = 1110331568Shselasky priv->params_ethtool.modify_tx_dma ? 1 : 0; 1111331568Shselasky /* modify tx according to value */ 1112331568Shselasky mlx5e_modify_tx_dma(priv, value != 0); 1113331568Shselasky } else { 1114331568Shselasky /* if closed force enable tx */ 1115331568Shselasky priv->params_ethtool.modify_tx_dma = 0; 1116331568Shselasky } 1117331568Shselasky break; 1118331568Shselasky 1119331568Shselasky case MLX5_PARAM_OFFSET(modify_rx_dma): 1120331568Shselasky /* check if network interface is opened */ 1121331568Shselasky if (was_opened) { 1122331568Shselasky priv->params_ethtool.modify_rx_dma = 1123331568Shselasky priv->params_ethtool.modify_rx_dma ? 1 : 0; 1124331568Shselasky /* modify rx according to value */ 1125331568Shselasky mlx5e_modify_rx_dma(priv, value != 0); 1126331568Shselasky } else { 1127331568Shselasky /* if closed force enable rx */ 1128331568Shselasky priv->params_ethtool.modify_rx_dma = 0; 1129331568Shselasky } 1130331568Shselasky break; 1131331568Shselasky 1132322006Shselasky case MLX5_PARAM_OFFSET(diag_pci_enable): 1133322006Shselasky priv->params_ethtool.diag_pci_enable = 1134322006Shselasky priv->params_ethtool.diag_pci_enable ? 1 : 0; 1135322006Shselasky 1136322006Shselasky error = -mlx5_core_set_diagnostics_full(priv->mdev, 1137322006Shselasky priv->params_ethtool.diag_pci_enable, 1138322006Shselasky priv->params_ethtool.diag_general_enable); 1139322006Shselasky break; 1140322006Shselasky 1141322006Shselasky case MLX5_PARAM_OFFSET(diag_general_enable): 1142322006Shselasky priv->params_ethtool.diag_general_enable = 1143322006Shselasky priv->params_ethtool.diag_general_enable ? 1 : 0; 1144322006Shselasky 1145322006Shselasky error = -mlx5_core_set_diagnostics_full(priv->mdev, 1146322006Shselasky priv->params_ethtool.diag_pci_enable, 1147322006Shselasky priv->params_ethtool.diag_general_enable); 1148322006Shselasky break; 1149322006Shselasky 1150331569Shselasky case MLX5_PARAM_OFFSET(mc_local_lb): 1151331569Shselasky priv->params_ethtool.mc_local_lb = 1152331569Shselasky priv->params_ethtool.mc_local_lb ? 1 : 0; 1153331569Shselasky 1154331569Shselasky if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1155331569Shselasky error = mlx5_nic_vport_modify_local_lb(priv->mdev, 1156331569Shselasky MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb); 1157331569Shselasky } else { 1158331569Shselasky error = EOPNOTSUPP; 1159331569Shselasky } 1160331569Shselasky break; 1161331569Shselasky 1162331569Shselasky case MLX5_PARAM_OFFSET(uc_local_lb): 1163331569Shselasky priv->params_ethtool.uc_local_lb = 1164331569Shselasky priv->params_ethtool.uc_local_lb ? 1 : 0; 1165331569Shselasky 1166331569Shselasky if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1167331569Shselasky error = mlx5_nic_vport_modify_local_lb(priv->mdev, 1168331569Shselasky MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb); 1169331569Shselasky } else { 1170331569Shselasky error = EOPNOTSUPP; 1171331569Shselasky } 1172331569Shselasky break; 1173331569Shselasky 1174300282Shselasky default: 1175300282Shselasky break; 1176300277Shselasky } 1177290650Shselaskydone: 1178290650Shselasky PRIV_UNLOCK(priv); 1179290650Shselasky return (error); 1180290650Shselasky} 1181290650Shselasky 1182290650Shselaskystatic const char *mlx5e_params_desc[] = { 1183290650Shselasky MLX5E_PARAMS(MLX5E_STATS_DESC) 1184290650Shselasky}; 1185290650Shselasky 1186290650Shselaskystatic const char *mlx5e_port_stats_debug_desc[] = { 1187290650Shselasky MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 1188290650Shselasky}; 1189290650Shselasky 1190290650Shselaskystatic int 1191337108Shselaskymlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS) 1192337108Shselasky{ 1193337108Shselasky struct mlx5e_priv *priv; 1194337108Shselasky struct sbuf sb; 1195337108Shselasky struct mlx5e_channel *c; 1196337108Shselasky struct mlx5e_sq *sq; 1197337108Shselasky struct mlx5e_rq *rq; 1198337108Shselasky int error, i, tc; 1199353202Shselasky bool opened; 1200337108Shselasky 1201337108Shselasky priv = arg1; 1202337108Shselasky error = sysctl_wire_old_buffer(req, 0); 1203337108Shselasky if (error != 0) 1204337108Shselasky return (error); 1205353202Shselasky if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL) 1206337108Shselasky return (ENOMEM); 1207337108Shselasky sbuf_clear_flags(&sb, SBUF_INCLUDENUL); 1208337108Shselasky 1209337108Shselasky PRIV_LOCK(priv); 1210353202Shselasky opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 1211353202Shselasky 1212353202Shselasky sbuf_printf(&sb, "pages irq %d\n", 1213353202Shselasky priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector); 1214353202Shselasky sbuf_printf(&sb, "command irq %d\n", 1215353202Shselasky priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector); 1216353202Shselasky sbuf_printf(&sb, "async irq %d\n", 1217353202Shselasky priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector); 1218353202Shselasky 1219353202Shselasky for (i = 0; i != priv->params.num_channels; i++) { 1220353202Shselasky int eqn_not_used = -1; 1221353202Shselasky int irqn = MLX5_EQ_VEC_COMP_BASE; 1222353202Shselasky 1223353202Shselasky if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0) 1224353202Shselasky continue; 1225353202Shselasky 1226353202Shselasky c = opened ? &priv->channel[i] : NULL; 1227353202Shselasky rq = opened ? &c->rq : NULL; 1228353202Shselasky sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i, 1229353202Shselasky opened ? rq->rqn : -1, 1230353202Shselasky opened ? rq->cq.mcq.cqn : -1, 1231353202Shselasky priv->mdev->priv.msix_arr[irqn].vector); 1232353202Shselasky 1233353202Shselasky for (tc = 0; tc != priv->num_tc; tc++) { 1234353202Shselasky sq = opened ? &c->sq[tc] : NULL; 1235353202Shselasky sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n", 1236353202Shselasky i, tc, 1237353202Shselasky opened ? sq->sqn : -1, 1238353202Shselasky opened ? sq->cq.mcq.cqn : -1, 1239353202Shselasky priv->mdev->priv.msix_arr[irqn].vector); 1240337108Shselasky } 1241337108Shselasky } 1242337108Shselasky PRIV_UNLOCK(priv); 1243337108Shselasky error = sbuf_finish(&sb); 1244337108Shselasky sbuf_delete(&sb); 1245337108Shselasky return (error); 1246337108Shselasky} 1247337108Shselasky 1248337108Shselaskystatic int 1249290650Shselaskymlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 1250290650Shselasky{ 1251290650Shselasky struct mlx5e_priv *priv = arg1; 1252341977Shselasky int sys_debug; 1253341977Shselasky int error; 1254290650Shselasky 1255341977Shselasky PRIV_LOCK(priv); 1256347806Shselasky if (priv->gone != 0) { 1257347806Shselasky error = ENODEV; 1258347806Shselasky goto done; 1259347806Shselasky } 1260290650Shselasky sys_debug = priv->sysctl_debug; 1261341977Shselasky error = sysctl_handle_int(oidp, &sys_debug, 0, req); 1262337108Shselasky if (error != 0 || !req->newptr) 1263341977Shselasky goto done; 1264341977Shselasky sys_debug = sys_debug ? 1 : 0; 1265290650Shselasky if (sys_debug == priv->sysctl_debug) 1266341977Shselasky goto done; 1267337108Shselasky 1268341977Shselasky if ((priv->sysctl_debug = sys_debug)) { 1269290650Shselasky mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 1270290650Shselasky SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 1271290650Shselasky mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 1272290650Shselasky priv->stats.port_stats_debug.arg); 1273341977Shselasky SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx, 1274337108Shselasky SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1275337108Shselasky "hw_ctx_debug", 1276337108Shselasky CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0, 1277337108Shselasky mlx5e_ethtool_debug_channel_info, "S", ""); 1278337108Shselasky } else { 1279290650Shselasky sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 1280337108Shselasky } 1281341977Shselaskydone: 1282337108Shselasky PRIV_UNLOCK(priv); 1283341977Shselasky return (error); 1284290650Shselasky} 1285290650Shselasky 1286322006Shselaskystatic void 1287322006Shselaskymlx5e_create_diagnostics(struct mlx5e_priv *priv) 1288322006Shselasky{ 1289322006Shselasky struct mlx5_core_diagnostics_entry entry; 1290322006Shselasky struct sysctl_ctx_list *ctx; 1291322006Shselasky struct sysctl_oid *node; 1292322006Shselasky int x; 1293322006Shselasky 1294322006Shselasky /* sysctl context we are using */ 1295322006Shselasky ctx = &priv->sysctl_ctx; 1296322006Shselasky 1297322006Shselasky /* create root node */ 1298322006Shselasky node = SYSCTL_ADD_NODE(ctx, 1299322006Shselasky SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1300322006Shselasky "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 1301322006Shselasky if (node == NULL) 1302322006Shselasky return; 1303322006Shselasky 1304322006Shselasky /* create PCI diagnostics */ 1305322006Shselasky for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 1306322006Shselasky entry = mlx5_core_pci_diagnostics_table[x]; 1307322006Shselasky if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1308322006Shselasky continue; 1309322006Shselasky SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1310322006Shselasky entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 1311322006Shselasky "PCI diagnostics counter"); 1312322006Shselasky } 1313322006Shselasky 1314322006Shselasky /* create general diagnostics */ 1315322006Shselasky for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 1316322006Shselasky entry = mlx5_core_general_diagnostics_table[x]; 1317322006Shselasky if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1318322006Shselasky continue; 1319322006Shselasky SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1320322006Shselasky entry.desc, CTLFLAG_RD, priv->params_general.array + x, 1321322006Shselasky "General diagnostics counter"); 1322322006Shselasky } 1323322006Shselasky} 1324322006Shselasky 1325290650Shselaskyvoid 1326290650Shselaskymlx5e_create_ethtool(struct mlx5e_priv *priv) 1327290650Shselasky{ 1328353244Shselasky struct sysctl_oid *fec_node; 1329353244Shselasky struct sysctl_oid *qos_node; 1330353244Shselasky struct sysctl_oid *node; 1331290650Shselasky const char *pnameunit; 1332353238Shselasky struct mlx5e_port_buffer port_buffer; 1333290650Shselasky unsigned x; 1334331577Shselasky int i; 1335290650Shselasky 1336290650Shselasky /* set some defaults */ 1337290650Shselasky priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 1338290650Shselasky priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 1339290650Shselasky priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 1340290650Shselasky priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 1341290650Shselasky priv->params_ethtool.channels = priv->params.num_channels; 1342338552Shselasky priv->params_ethtool.channels_rsss = priv->params.channels_rsss; 1343290650Shselasky priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 1344290650Shselasky priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 1345290650Shselasky priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 1346290650Shselasky priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 1347290650Shselasky priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 1348291932Shselasky priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 1349290650Shselasky priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 1350290650Shselasky priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 1351290650Shselasky priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 1352292838Shselasky priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 1353300277Shselasky mlx5e_ethtool_sync_tx_completion_fact(priv); 1354290650Shselasky 1355331569Shselasky /* get default values for local loopback, if any */ 1356331569Shselasky if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1357331569Shselasky int err; 1358331569Shselasky u8 val; 1359331569Shselasky 1360331569Shselasky err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 1361331569Shselasky if (err == 0) 1362331569Shselasky priv->params_ethtool.mc_local_lb = val; 1363331569Shselasky 1364331569Shselasky err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 1365331569Shselasky if (err == 0) 1366331569Shselasky priv->params_ethtool.uc_local_lb = val; 1367331569Shselasky } 1368331569Shselasky 1369290650Shselasky /* create root node */ 1370290650Shselasky node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1371290650Shselasky SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1372290650Shselasky "conf", CTLFLAG_RW, NULL, "Configuration"); 1373290650Shselasky if (node == NULL) 1374290650Shselasky return; 1375290650Shselasky for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 1376290650Shselasky /* check for read-only parameter */ 1377331570Shselasky if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 1378331570Shselasky strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 1379290650Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1380290650Shselasky mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 1381290650Shselasky CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1382290650Shselasky mlx5e_params_desc[2 * x + 1]); 1383290650Shselasky } else { 1384292837Shselasky#if (__FreeBSD_version < 1100000) 1385292837Shselasky char path[64]; 1386292837Shselasky#endif 1387292837Shselasky /* 1388292837Shselasky * NOTE: In FreeBSD-11 and newer the 1389292837Shselasky * CTLFLAG_RWTUN flag will take care of 1390292837Shselasky * loading default sysctl value from the 1391292837Shselasky * kernel environment, if any: 1392292837Shselasky */ 1393290650Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1394290650Shselasky mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 1395290650Shselasky CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1396290650Shselasky mlx5e_params_desc[2 * x + 1]); 1397292837Shselasky 1398292837Shselasky#if (__FreeBSD_version < 1100000) 1399292837Shselasky /* compute path for sysctl */ 1400292837Shselasky snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 1401292837Shselasky device_get_unit(priv->mdev->pdev->dev.bsddev), 1402292837Shselasky mlx5e_params_desc[2 * x]); 1403292837Shselasky 1404292837Shselasky /* try to fetch tunable, if any */ 1405292837Shselasky if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 1406292837Shselasky mlx5e_ethtool_handler(NULL, priv, x, NULL); 1407292837Shselasky#endif 1408290650Shselasky } 1409290650Shselasky } 1410290650Shselasky 1411353244Shselasky /* create fec node */ 1412353244Shselasky fec_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1413353244Shselasky SYSCTL_CHILDREN(node), OID_AUTO, 1414353244Shselasky "fec", CTLFLAG_RW, NULL, "Forward Error Correction"); 1415353244Shselasky if (fec_node == NULL) 1416353244Shselasky return; 1417353244Shselasky 1418353244Shselasky if (mlx5e_fec_update(priv) == 0) { 1419353244Shselasky SYSCTL_ADD_U32(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1420353244Shselasky "mode_active", CTLFLAG_RD | CTLFLAG_MPSAFE, 1421353244Shselasky &priv->params_ethtool.fec_mode_active, 0, 1422353244Shselasky "Current FEC mode bit, if any."); 1423353244Shselasky 1424353244Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1425353244Shselasky "mask_10x_25x", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1426353244Shselasky priv, 0, &mlx5e_fec_mask_10x_25x_handler, "CU", 1427353244Shselasky "Set FEC masks for 10G_40G, 25G_50G, 56G, 100G respectivly. " 1428353244Shselasky "0:Auto " 1429353244Shselasky "1:NOFEC " 1430353244Shselasky "2:FIRECODE " 1431353244Shselasky "4:RS"); 1432353244Shselasky 1433353244Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1434353244Shselasky "avail_10x_25x", CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE, 1435353244Shselasky priv, 0, &mlx5e_fec_avail_10x_25x_handler, "CU", 1436353244Shselasky "Get available FEC bits for 10G_40G, 25G_50G, 56G, 100G respectivly. " 1437353244Shselasky "0:Auto " 1438353244Shselasky "1:NOFEC " 1439353244Shselasky "2:FIRECODE " 1440353244Shselasky "4:RS"); 1441353244Shselasky 1442353244Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1443353244Shselasky "mask_50x", CTLTYPE_U16 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1444353244Shselasky priv, 0, &mlx5e_fec_mask_50x_handler, "SU", 1445353244Shselasky "Set FEC masks for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. " 1446353244Shselasky "0:Auto " 1447353244Shselasky "128:RS " 1448353244Shselasky "512:LL RS"); 1449353244Shselasky 1450353244Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1451353244Shselasky "avail_50x", CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_MPSAFE, 1452353244Shselasky priv, 0, &mlx5e_fec_avail_50x_handler, "SU", 1453353244Shselasky "Get available FEC bits for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. " 1454353244Shselasky "0:Auto " 1455353244Shselasky "128:RS " 1456353244Shselasky "512:LL RS"); 1457353244Shselasky } 1458353244Shselasky 1459290650Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1460290650Shselasky "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 1461290650Shselasky 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 1462290650Shselasky 1463290650Shselasky pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 1464290650Shselasky 1465290650Shselasky SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 1466290650Shselasky OID_AUTO, "device_name", CTLFLAG_RD, 1467290650Shselasky __DECONST(void *, pnameunit), 0, 1468290650Shselasky "PCI device name"); 1469290650Shselasky 1470322006Shselasky /* Diagnostics support */ 1471322006Shselasky mlx5e_create_diagnostics(priv); 1472331577Shselasky 1473331577Shselasky /* create qos node */ 1474331577Shselasky qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1475331577Shselasky SYSCTL_CHILDREN(node), OID_AUTO, 1476331577Shselasky "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration"); 1477341968Shselasky if (qos_node == NULL) 1478331577Shselasky return; 1479331577Shselasky 1480341968Shselasky /* Priority rate limit support */ 1481341968Shselasky if (mlx5e_getmaxrate(priv) == 0) { 1482341968Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1483341968Shselasky OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1484341968Shselasky priv, 0, mlx5e_tc_maxrate_handler, "QU", 1485341968Shselasky "Max rate for priority, specified in kilobits, where kilo=1000, " 1486341968Shselasky "max_rate must be divisible by 100000"); 1487341968Shselasky } 1488331577Shselasky 1489341968Shselasky /* Bandwidth limiting by ratio */ 1490341968Shselasky if (mlx5e_get_max_alloc(priv) == 0) { 1491331577Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1492341968Shselasky OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1493341968Shselasky priv, 0, mlx5e_tc_rate_share_handler, "QU", 1494341968Shselasky "Specify bandwidth ratio from 1 to 100 " 1495341968Shselasky "for the available traffic classes"); 1496331577Shselasky } 1497331578Shselasky 1498341968Shselasky /* Priority to traffic class mapping */ 1499341968Shselasky if (mlx5e_get_prio_tc(priv) == 0) { 1500347810Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1501347810Shselasky OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1502347810Shselasky priv, 0, mlx5e_prio_to_tc_handler, "CU", 1503347810Shselasky "Set traffic class 0 to 7 for priority 0 to 7 inclusivly"); 1504331578Shselasky } 1505337098Shselasky 1506337098Shselasky /* DSCP support */ 1507337098Shselasky if (mlx5e_get_dscp(priv) == 0) { 1508337098Shselasky for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) { 1509337098Shselasky char name[32]; 1510337098Shselasky snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7); 1511337098Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1512337098Shselasky OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1513337098Shselasky priv, i, mlx5e_dscp_prio_handler, "CU", 1514337098Shselasky "Set DSCP to priority mapping, 0..7"); 1515337098Shselasky } 1516337107Shselasky#define A "Set trust state, 1:PCP 2:DSCP" 1517337107Shselasky#define B " 3:BOTH" 1518337098Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1519337098Shselasky OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1520337098Shselasky priv, 0, mlx5e_trust_state_handler, "CU", 1521347810Shselasky MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ? 1522337107Shselasky A B : A); 1523337107Shselasky#undef B 1524337107Shselasky#undef A 1525337098Shselasky } 1526353238Shselasky 1527353238Shselasky if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) { 1528353238Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1529353238Shselasky OID_AUTO, "buffers_size", 1530353238Shselasky CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1531353238Shselasky priv, 0, mlx5e_buf_size_handler, "IU", 1532353238Shselasky "Set buffers sizes"); 1533353238Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1534353238Shselasky OID_AUTO, "buffers_prio", 1535353238Shselasky CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1536353238Shselasky priv, 0, mlx5e_buf_prio_handler, "CU", 1537353238Shselasky "Set prio to buffers mapping"); 1538353238Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1539353238Shselasky OID_AUTO, "cable_length", 1540353238Shselasky CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1541353238Shselasky priv, 0, mlx5e_cable_length_handler, "IU", 1542353238Shselasky "Set cable length in meters for xoff threshold calculation"); 1543353238Shselasky } 1544290650Shselasky} 1545