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 361171 2020-05-18 09:04:24Z 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 804361171Shselaskystatic int 805361171Shselaskymlx5e_hw_temperature_handler(SYSCTL_HANDLER_ARGS) 806361171Shselasky{ 807361171Shselasky struct mlx5e_priv *priv = arg1; 808361171Shselasky int err; 809361171Shselasky 810361171Shselasky PRIV_LOCK(priv); 811361171Shselasky err = SYSCTL_OUT(req, priv->params_ethtool.hw_val_temp, 812361171Shselasky sizeof(priv->params_ethtool.hw_val_temp[0]) * 813361171Shselasky priv->params_ethtool.hw_num_temp); 814361171Shselasky if (err == 0 && req->newptr != NULL) 815361171Shselasky err = EOPNOTSUPP; 816361171Shselasky PRIV_UNLOCK(priv); 817361171Shselasky return (err); 818361171Shselasky} 819361171Shselasky 820361171Shselaskyint 821361171Shselaskymlx5e_hw_temperature_update(struct mlx5e_priv *priv) 822361171Shselasky{ 823361171Shselasky int err; 824361171Shselasky u32 x; 825361171Shselasky 826361171Shselasky if (priv->params_ethtool.hw_num_temp == 0) { 827361171Shselasky u32 out_cap[MLX5_ST_SZ_DW(mtcap)] = {}; 828361171Shselasky const int sz_cap = MLX5_ST_SZ_BYTES(mtcap); 829361171Shselasky u32 value; 830361171Shselasky 831361171Shselasky err = -mlx5_core_access_reg(priv->mdev, NULL, 0, out_cap, sz_cap, 832361171Shselasky MLX5_ACCESS_REG_SUMMARY_CTRL_ID_MTCAP, 0, 0); 833361171Shselasky if (err) 834361171Shselasky goto done; 835361171Shselasky value = MLX5_GET(mtcap, out_cap, sensor_count); 836361171Shselasky if (value == 0) 837361171Shselasky return (0); 838361171Shselasky if (value > MLX5_MAX_TEMPERATURE) 839361171Shselasky value = MLX5_MAX_TEMPERATURE; 840361171Shselasky /* update number of temperature sensors */ 841361171Shselasky priv->params_ethtool.hw_num_temp = value; 842361171Shselasky } 843361171Shselasky 844361171Shselasky for (x = 0; x != priv->params_ethtool.hw_num_temp; x++) { 845361171Shselasky u32 out_sensor[MLX5_ST_SZ_DW(mtmp_reg)] = {}; 846361171Shselasky const int sz_sensor = MLX5_ST_SZ_BYTES(mtmp_reg); 847361171Shselasky 848361171Shselasky MLX5_SET(mtmp_reg, out_sensor, sensor_index, x); 849361171Shselasky 850361171Shselasky err = -mlx5_core_access_reg(priv->mdev, out_sensor, sz_sensor, 851361171Shselasky out_sensor, sz_sensor, 852361171Shselasky MLX5_ACCESS_REG_SUMMARY_CTRL_ID_MTMP, 0, 0); 853361171Shselasky if (err) 854361171Shselasky goto done; 855361171Shselasky /* convert from 0.125 celcius to millicelcius */ 856361171Shselasky priv->params_ethtool.hw_val_temp[x] = 857361171Shselasky (s16)MLX5_GET(mtmp_reg, out_sensor, temperature) * 125; 858361171Shselasky } 859361171Shselaskydone: 860361171Shselasky return (err); 861361171Shselasky} 862361171Shselasky 863300282Shselasky#define MLX5_PARAM_OFFSET(n) \ 864300282Shselasky __offsetof(struct mlx5e_priv, params_ethtool.n) 865300282Shselasky 866290650Shselaskystatic int 867290650Shselaskymlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) 868290650Shselasky{ 869290650Shselasky struct mlx5e_priv *priv = arg1; 870290650Shselasky uint64_t value; 871321995Shselasky int mode_modify; 872290650Shselasky int was_opened; 873290650Shselasky int error; 874290650Shselasky 875290650Shselasky PRIV_LOCK(priv); 876290650Shselasky value = priv->params_ethtool.arg[arg2]; 877292837Shselasky if (req != NULL) { 878292837Shselasky error = sysctl_handle_64(oidp, &value, 0, req); 879292837Shselasky if (error || req->newptr == NULL || 880292837Shselasky value == priv->params_ethtool.arg[arg2]) 881292837Shselasky goto done; 882290650Shselasky 883292837Shselasky /* assign new value */ 884292837Shselasky priv->params_ethtool.arg[arg2] = value; 885292837Shselasky } else { 886292837Shselasky error = 0; 887292837Shselasky } 888290650Shselasky /* check if device is gone */ 889290650Shselasky if (priv->gone) { 890290650Shselasky error = ENXIO; 891290650Shselasky goto done; 892290650Shselasky } 893300282Shselasky was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 894321995Shselasky mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify); 895290650Shselasky 896300282Shselasky switch (MLX5_PARAM_OFFSET(arg[arg2])) { 897300282Shselasky case MLX5_PARAM_OFFSET(rx_coalesce_usecs): 898300282Shselasky /* import RX coal time */ 899300282Shselasky if (priv->params_ethtool.rx_coalesce_usecs < 1) 900300282Shselasky priv->params_ethtool.rx_coalesce_usecs = 0; 901300282Shselasky else if (priv->params_ethtool.rx_coalesce_usecs > 902300282Shselasky MLX5E_FLD_MAX(cqc, cq_period)) { 903300282Shselasky priv->params_ethtool.rx_coalesce_usecs = 904300282Shselasky MLX5E_FLD_MAX(cqc, cq_period); 905300282Shselasky } 906300282Shselasky priv->params.rx_cq_moderation_usec = 907300282Shselasky priv->params_ethtool.rx_coalesce_usecs; 908292949Shselasky 909300282Shselasky /* check to avoid down and up the network interface */ 910300282Shselasky if (was_opened) 911300282Shselasky error = mlx5e_refresh_channel_params(priv); 912300282Shselasky break; 913292949Shselasky 914300282Shselasky case MLX5_PARAM_OFFSET(rx_coalesce_pkts): 915300282Shselasky /* import RX coal pkts */ 916300282Shselasky if (priv->params_ethtool.rx_coalesce_pkts < 1) 917300282Shselasky priv->params_ethtool.rx_coalesce_pkts = 0; 918300282Shselasky else if (priv->params_ethtool.rx_coalesce_pkts > 919300282Shselasky MLX5E_FLD_MAX(cqc, cq_max_count)) { 920300282Shselasky priv->params_ethtool.rx_coalesce_pkts = 921300282Shselasky MLX5E_FLD_MAX(cqc, cq_max_count); 922300282Shselasky } 923300282Shselasky priv->params.rx_cq_moderation_pkts = 924300282Shselasky priv->params_ethtool.rx_coalesce_pkts; 925292949Shselasky 926300282Shselasky /* check to avoid down and up the network interface */ 927300282Shselasky if (was_opened) 928300282Shselasky error = mlx5e_refresh_channel_params(priv); 929300282Shselasky break; 930292949Shselasky 931300282Shselasky case MLX5_PARAM_OFFSET(tx_coalesce_usecs): 932300282Shselasky /* import TX coal time */ 933300282Shselasky if (priv->params_ethtool.tx_coalesce_usecs < 1) 934300282Shselasky priv->params_ethtool.tx_coalesce_usecs = 0; 935300282Shselasky else if (priv->params_ethtool.tx_coalesce_usecs > 936300282Shselasky MLX5E_FLD_MAX(cqc, cq_period)) { 937300282Shselasky priv->params_ethtool.tx_coalesce_usecs = 938300282Shselasky MLX5E_FLD_MAX(cqc, cq_period); 939300282Shselasky } 940300282Shselasky priv->params.tx_cq_moderation_usec = 941300282Shselasky priv->params_ethtool.tx_coalesce_usecs; 942300282Shselasky 943300282Shselasky /* check to avoid down and up the network interface */ 944300282Shselasky if (was_opened) 945292949Shselasky error = mlx5e_refresh_channel_params(priv); 946300282Shselasky break; 947300282Shselasky 948300282Shselasky case MLX5_PARAM_OFFSET(tx_coalesce_pkts): 949300282Shselasky /* import TX coal pkts */ 950300282Shselasky if (priv->params_ethtool.tx_coalesce_pkts < 1) 951300282Shselasky priv->params_ethtool.tx_coalesce_pkts = 0; 952300282Shselasky else if (priv->params_ethtool.tx_coalesce_pkts > 953300282Shselasky MLX5E_FLD_MAX(cqc, cq_max_count)) { 954300282Shselasky priv->params_ethtool.tx_coalesce_pkts = 955300282Shselasky MLX5E_FLD_MAX(cqc, cq_max_count); 956292949Shselasky } 957300282Shselasky priv->params.tx_cq_moderation_pkts = 958300282Shselasky priv->params_ethtool.tx_coalesce_pkts; 959300282Shselasky 960300282Shselasky /* check to avoid down and up the network interface */ 961300282Shselasky if (was_opened) 962300282Shselasky error = mlx5e_refresh_channel_params(priv); 963300282Shselasky break; 964300282Shselasky 965300282Shselasky case MLX5_PARAM_OFFSET(tx_queue_size): 966300282Shselasky /* network interface must be down */ 967300282Shselasky if (was_opened) 968300282Shselasky mlx5e_close_locked(priv->ifp); 969300282Shselasky 970300282Shselasky /* import TX queue size */ 971300282Shselasky if (priv->params_ethtool.tx_queue_size < 972300282Shselasky (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { 973300282Shselasky priv->params_ethtool.tx_queue_size = 974300282Shselasky (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); 975300282Shselasky } else if (priv->params_ethtool.tx_queue_size > 976300282Shselasky priv->params_ethtool.tx_queue_size_max) { 977300282Shselasky priv->params_ethtool.tx_queue_size = 978300282Shselasky priv->params_ethtool.tx_queue_size_max; 979300282Shselasky } 980300282Shselasky /* store actual TX queue size */ 981300282Shselasky priv->params.log_sq_size = 982300282Shselasky order_base_2(priv->params_ethtool.tx_queue_size); 983290650Shselasky priv->params_ethtool.tx_queue_size = 984300282Shselasky 1 << priv->params.log_sq_size; 985290650Shselasky 986300282Shselasky /* verify TX completion factor */ 987300282Shselasky mlx5e_ethtool_sync_tx_completion_fact(priv); 988300282Shselasky 989300282Shselasky /* restart network interface, if any */ 990300282Shselasky if (was_opened) 991300282Shselasky mlx5e_open_locked(priv->ifp); 992300282Shselasky break; 993300282Shselasky 994300282Shselasky case MLX5_PARAM_OFFSET(rx_queue_size): 995300282Shselasky /* network interface must be down */ 996300282Shselasky if (was_opened) 997300282Shselasky mlx5e_close_locked(priv->ifp); 998300282Shselasky 999300282Shselasky /* import RX queue size */ 1000300282Shselasky if (priv->params_ethtool.rx_queue_size < 1001300282Shselasky (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { 1002300282Shselasky priv->params_ethtool.rx_queue_size = 1003300282Shselasky (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); 1004300282Shselasky } else if (priv->params_ethtool.rx_queue_size > 1005300282Shselasky priv->params_ethtool.rx_queue_size_max) { 1006300282Shselasky priv->params_ethtool.rx_queue_size = 1007300282Shselasky priv->params_ethtool.rx_queue_size_max; 1008300282Shselasky } 1009300282Shselasky /* store actual RX queue size */ 1010300282Shselasky priv->params.log_rq_size = 1011300282Shselasky order_base_2(priv->params_ethtool.rx_queue_size); 1012290650Shselasky priv->params_ethtool.rx_queue_size = 1013300282Shselasky 1 << priv->params.log_rq_size; 1014290650Shselasky 1015300282Shselasky /* update least number of RX WQEs */ 1016300282Shselasky priv->params.min_rx_wqes = min( 1017300282Shselasky priv->params_ethtool.rx_queue_size - 1, 1018300282Shselasky MLX5E_PARAMS_DEFAULT_MIN_RX_WQES); 1019290650Shselasky 1020300282Shselasky /* restart network interface, if any */ 1021300282Shselasky if (was_opened) 1022300282Shselasky mlx5e_open_locked(priv->ifp); 1023300282Shselasky break; 1024290650Shselasky 1025338552Shselasky case MLX5_PARAM_OFFSET(channels_rsss): 1026338552Shselasky /* network interface must be down */ 1027338552Shselasky if (was_opened) 1028338552Shselasky mlx5e_close_locked(priv->ifp); 1029338552Shselasky 1030338552Shselasky /* import number of channels */ 1031338552Shselasky if (priv->params_ethtool.channels_rsss < 1) 1032338552Shselasky priv->params_ethtool.channels_rsss = 1; 1033338552Shselasky else if (priv->params_ethtool.channels_rsss > 128) 1034338552Shselasky priv->params_ethtool.channels_rsss = 128; 1035338552Shselasky 1036338552Shselasky priv->params.channels_rsss = priv->params_ethtool.channels_rsss; 1037338552Shselasky 1038338552Shselasky /* restart network interface, if any */ 1039338552Shselasky if (was_opened) 1040338552Shselasky mlx5e_open_locked(priv->ifp); 1041338552Shselasky break; 1042338552Shselasky 1043300282Shselasky case MLX5_PARAM_OFFSET(channels): 1044300282Shselasky /* network interface must be down */ 1045300282Shselasky if (was_opened) 1046300282Shselasky mlx5e_close_locked(priv->ifp); 1047290650Shselasky 1048300282Shselasky /* import number of channels */ 1049300282Shselasky if (priv->params_ethtool.channels < 1) 1050300282Shselasky priv->params_ethtool.channels = 1; 1051300282Shselasky else if (priv->params_ethtool.channels > 1052300282Shselasky (u64) priv->mdev->priv.eq_table.num_comp_vectors) { 1053300282Shselasky priv->params_ethtool.channels = 1054300282Shselasky (u64) priv->mdev->priv.eq_table.num_comp_vectors; 1055300282Shselasky } 1056300282Shselasky priv->params.num_channels = priv->params_ethtool.channels; 1057291932Shselasky 1058300282Shselasky /* restart network interface, if any */ 1059300282Shselasky if (was_opened) 1060300282Shselasky mlx5e_open_locked(priv->ifp); 1061300282Shselasky break; 1062300282Shselasky 1063300282Shselasky case MLX5_PARAM_OFFSET(rx_coalesce_mode): 1064300282Shselasky /* network interface must be down */ 1065321995Shselasky if (was_opened != 0 && mode_modify == 0) 1066300282Shselasky mlx5e_close_locked(priv->ifp); 1067300282Shselasky 1068300282Shselasky /* import RX coalesce mode */ 1069347796Shselasky if (priv->params_ethtool.rx_coalesce_mode > 3) 1070347796Shselasky priv->params_ethtool.rx_coalesce_mode = 3; 1071300282Shselasky priv->params.rx_cq_moderation_mode = 1072300282Shselasky priv->params_ethtool.rx_coalesce_mode; 1073300282Shselasky 1074300282Shselasky /* restart network interface, if any */ 1075321995Shselasky if (was_opened != 0) { 1076321995Shselasky if (mode_modify == 0) 1077321995Shselasky mlx5e_open_locked(priv->ifp); 1078321995Shselasky else 1079321995Shselasky error = mlx5e_refresh_channel_params(priv); 1080321995Shselasky } 1081300282Shselasky break; 1082300282Shselasky 1083300282Shselasky case MLX5_PARAM_OFFSET(tx_coalesce_mode): 1084300282Shselasky /* network interface must be down */ 1085321995Shselasky if (was_opened != 0 && mode_modify == 0) 1086300282Shselasky mlx5e_close_locked(priv->ifp); 1087300282Shselasky 1088300282Shselasky /* import TX coalesce mode */ 1089300282Shselasky if (priv->params_ethtool.tx_coalesce_mode != 0) 1090300282Shselasky priv->params_ethtool.tx_coalesce_mode = 1; 1091300282Shselasky priv->params.tx_cq_moderation_mode = 1092300282Shselasky priv->params_ethtool.tx_coalesce_mode; 1093300282Shselasky 1094300282Shselasky /* restart network interface, if any */ 1095321995Shselasky if (was_opened != 0) { 1096321995Shselasky if (mode_modify == 0) 1097321995Shselasky mlx5e_open_locked(priv->ifp); 1098321995Shselasky else 1099321995Shselasky error = mlx5e_refresh_channel_params(priv); 1100321995Shselasky } 1101300282Shselasky break; 1102300282Shselasky 1103300282Shselasky case MLX5_PARAM_OFFSET(hw_lro): 1104300282Shselasky /* network interface must be down */ 1105300282Shselasky if (was_opened) 1106300282Shselasky mlx5e_close_locked(priv->ifp); 1107300282Shselasky 1108300282Shselasky /* import HW LRO mode */ 1109341983Shselasky if (priv->params_ethtool.hw_lro != 0 && 1110341983Shselasky MLX5_CAP_ETH(priv->mdev, lro_cap)) { 1111341983Shselasky priv->params_ethtool.hw_lro = 1; 1112341983Shselasky /* check if feature should actually be enabled */ 1113341983Shselasky if (priv->ifp->if_capenable & IFCAP_LRO) { 1114341983Shselasky priv->params.hw_lro_en = true; 1115300282Shselasky } else { 1116341983Shselasky priv->params.hw_lro_en = false; 1117300282Shselasky 1118353226Shselasky mlx5_en_warn(priv->ifp, "To enable HW LRO " 1119341983Shselasky "please also enable LRO via ifconfig(8).\n"); 1120300282Shselasky } 1121294319Shselasky } else { 1122341983Shselasky /* return an error if HW does not support this feature */ 1123341983Shselasky if (priv->params_ethtool.hw_lro != 0) 1124341983Shselasky error = EINVAL; 1125341983Shselasky priv->params.hw_lro_en = false; 1126341983Shselasky priv->params_ethtool.hw_lro = 0; 1127291068Shselasky } 1128300282Shselasky /* restart network interface, if any */ 1129300282Shselasky if (was_opened) 1130300282Shselasky mlx5e_open_locked(priv->ifp); 1131300282Shselasky break; 1132290650Shselasky 1133300282Shselasky case MLX5_PARAM_OFFSET(cqe_zipping): 1134300282Shselasky /* network interface must be down */ 1135300282Shselasky if (was_opened) 1136300282Shselasky mlx5e_close_locked(priv->ifp); 1137300282Shselasky 1138300282Shselasky /* import CQE zipping mode */ 1139292838Shselasky if (priv->params_ethtool.cqe_zipping && 1140292838Shselasky MLX5_CAP_GEN(priv->mdev, cqe_compression)) { 1141292838Shselasky priv->params.cqe_zipping_en = true; 1142292838Shselasky priv->params_ethtool.cqe_zipping = 1; 1143292838Shselasky } else { 1144292838Shselasky priv->params.cqe_zipping_en = false; 1145292838Shselasky priv->params_ethtool.cqe_zipping = 0; 1146292838Shselasky } 1147300282Shselasky /* restart network interface, if any */ 1148300282Shselasky if (was_opened) 1149300282Shselasky mlx5e_open_locked(priv->ifp); 1150300282Shselasky break; 1151300277Shselasky 1152300282Shselasky case MLX5_PARAM_OFFSET(tx_completion_fact): 1153300282Shselasky /* network interface must be down */ 1154300282Shselasky if (was_opened) 1155300282Shselasky mlx5e_close_locked(priv->ifp); 1156300282Shselasky 1157300277Shselasky /* verify parameter */ 1158300277Shselasky mlx5e_ethtool_sync_tx_completion_fact(priv); 1159300282Shselasky 1160300282Shselasky /* restart network interface, if any */ 1161300282Shselasky if (was_opened) 1162300282Shselasky mlx5e_open_locked(priv->ifp); 1163300282Shselasky break; 1164300282Shselasky 1165331568Shselasky case MLX5_PARAM_OFFSET(modify_tx_dma): 1166331568Shselasky /* check if network interface is opened */ 1167331568Shselasky if (was_opened) { 1168331568Shselasky priv->params_ethtool.modify_tx_dma = 1169331568Shselasky priv->params_ethtool.modify_tx_dma ? 1 : 0; 1170331568Shselasky /* modify tx according to value */ 1171331568Shselasky mlx5e_modify_tx_dma(priv, value != 0); 1172331568Shselasky } else { 1173331568Shselasky /* if closed force enable tx */ 1174331568Shselasky priv->params_ethtool.modify_tx_dma = 0; 1175331568Shselasky } 1176331568Shselasky break; 1177331568Shselasky 1178331568Shselasky case MLX5_PARAM_OFFSET(modify_rx_dma): 1179331568Shselasky /* check if network interface is opened */ 1180331568Shselasky if (was_opened) { 1181331568Shselasky priv->params_ethtool.modify_rx_dma = 1182331568Shselasky priv->params_ethtool.modify_rx_dma ? 1 : 0; 1183331568Shselasky /* modify rx according to value */ 1184331568Shselasky mlx5e_modify_rx_dma(priv, value != 0); 1185331568Shselasky } else { 1186331568Shselasky /* if closed force enable rx */ 1187331568Shselasky priv->params_ethtool.modify_rx_dma = 0; 1188331568Shselasky } 1189331568Shselasky break; 1190331568Shselasky 1191322006Shselasky case MLX5_PARAM_OFFSET(diag_pci_enable): 1192322006Shselasky priv->params_ethtool.diag_pci_enable = 1193322006Shselasky priv->params_ethtool.diag_pci_enable ? 1 : 0; 1194322006Shselasky 1195322006Shselasky error = -mlx5_core_set_diagnostics_full(priv->mdev, 1196322006Shselasky priv->params_ethtool.diag_pci_enable, 1197322006Shselasky priv->params_ethtool.diag_general_enable); 1198322006Shselasky break; 1199322006Shselasky 1200322006Shselasky case MLX5_PARAM_OFFSET(diag_general_enable): 1201322006Shselasky priv->params_ethtool.diag_general_enable = 1202322006Shselasky priv->params_ethtool.diag_general_enable ? 1 : 0; 1203322006Shselasky 1204322006Shselasky error = -mlx5_core_set_diagnostics_full(priv->mdev, 1205322006Shselasky priv->params_ethtool.diag_pci_enable, 1206322006Shselasky priv->params_ethtool.diag_general_enable); 1207322006Shselasky break; 1208322006Shselasky 1209331569Shselasky case MLX5_PARAM_OFFSET(mc_local_lb): 1210331569Shselasky priv->params_ethtool.mc_local_lb = 1211331569Shselasky priv->params_ethtool.mc_local_lb ? 1 : 0; 1212331569Shselasky 1213331569Shselasky if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1214331569Shselasky error = mlx5_nic_vport_modify_local_lb(priv->mdev, 1215331569Shselasky MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb); 1216331569Shselasky } else { 1217331569Shselasky error = EOPNOTSUPP; 1218331569Shselasky } 1219331569Shselasky break; 1220331569Shselasky 1221331569Shselasky case MLX5_PARAM_OFFSET(uc_local_lb): 1222331569Shselasky priv->params_ethtool.uc_local_lb = 1223331569Shselasky priv->params_ethtool.uc_local_lb ? 1 : 0; 1224331569Shselasky 1225331569Shselasky if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1226331569Shselasky error = mlx5_nic_vport_modify_local_lb(priv->mdev, 1227331569Shselasky MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb); 1228331569Shselasky } else { 1229331569Shselasky error = EOPNOTSUPP; 1230331569Shselasky } 1231331569Shselasky break; 1232331569Shselasky 1233300282Shselasky default: 1234300282Shselasky break; 1235300277Shselasky } 1236290650Shselaskydone: 1237290650Shselasky PRIV_UNLOCK(priv); 1238290650Shselasky return (error); 1239290650Shselasky} 1240290650Shselasky 1241290650Shselaskystatic const char *mlx5e_params_desc[] = { 1242290650Shselasky MLX5E_PARAMS(MLX5E_STATS_DESC) 1243290650Shselasky}; 1244290650Shselasky 1245290650Shselaskystatic const char *mlx5e_port_stats_debug_desc[] = { 1246290650Shselasky MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 1247290650Shselasky}; 1248290650Shselasky 1249290650Shselaskystatic int 1250337108Shselaskymlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS) 1251337108Shselasky{ 1252337108Shselasky struct mlx5e_priv *priv; 1253337108Shselasky struct sbuf sb; 1254337108Shselasky struct mlx5e_channel *c; 1255337108Shselasky struct mlx5e_sq *sq; 1256337108Shselasky struct mlx5e_rq *rq; 1257337108Shselasky int error, i, tc; 1258353202Shselasky bool opened; 1259337108Shselasky 1260337108Shselasky priv = arg1; 1261337108Shselasky error = sysctl_wire_old_buffer(req, 0); 1262337108Shselasky if (error != 0) 1263337108Shselasky return (error); 1264353202Shselasky if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL) 1265337108Shselasky return (ENOMEM); 1266337108Shselasky sbuf_clear_flags(&sb, SBUF_INCLUDENUL); 1267337108Shselasky 1268337108Shselasky PRIV_LOCK(priv); 1269353202Shselasky opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 1270353202Shselasky 1271353202Shselasky sbuf_printf(&sb, "pages irq %d\n", 1272353202Shselasky priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector); 1273353202Shselasky sbuf_printf(&sb, "command irq %d\n", 1274353202Shselasky priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector); 1275353202Shselasky sbuf_printf(&sb, "async irq %d\n", 1276353202Shselasky priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector); 1277353202Shselasky 1278353202Shselasky for (i = 0; i != priv->params.num_channels; i++) { 1279353202Shselasky int eqn_not_used = -1; 1280353202Shselasky int irqn = MLX5_EQ_VEC_COMP_BASE; 1281353202Shselasky 1282353202Shselasky if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0) 1283353202Shselasky continue; 1284353202Shselasky 1285353202Shselasky c = opened ? &priv->channel[i] : NULL; 1286353202Shselasky rq = opened ? &c->rq : NULL; 1287353202Shselasky sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i, 1288353202Shselasky opened ? rq->rqn : -1, 1289353202Shselasky opened ? rq->cq.mcq.cqn : -1, 1290353202Shselasky priv->mdev->priv.msix_arr[irqn].vector); 1291353202Shselasky 1292353202Shselasky for (tc = 0; tc != priv->num_tc; tc++) { 1293353202Shselasky sq = opened ? &c->sq[tc] : NULL; 1294353202Shselasky sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n", 1295353202Shselasky i, tc, 1296353202Shselasky opened ? sq->sqn : -1, 1297353202Shselasky opened ? sq->cq.mcq.cqn : -1, 1298353202Shselasky priv->mdev->priv.msix_arr[irqn].vector); 1299337108Shselasky } 1300337108Shselasky } 1301337108Shselasky PRIV_UNLOCK(priv); 1302337108Shselasky error = sbuf_finish(&sb); 1303337108Shselasky sbuf_delete(&sb); 1304337108Shselasky return (error); 1305337108Shselasky} 1306337108Shselasky 1307337108Shselaskystatic int 1308290650Shselaskymlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 1309290650Shselasky{ 1310290650Shselasky struct mlx5e_priv *priv = arg1; 1311341977Shselasky int sys_debug; 1312341977Shselasky int error; 1313290650Shselasky 1314341977Shselasky PRIV_LOCK(priv); 1315347806Shselasky if (priv->gone != 0) { 1316347806Shselasky error = ENODEV; 1317347806Shselasky goto done; 1318347806Shselasky } 1319290650Shselasky sys_debug = priv->sysctl_debug; 1320341977Shselasky error = sysctl_handle_int(oidp, &sys_debug, 0, req); 1321337108Shselasky if (error != 0 || !req->newptr) 1322341977Shselasky goto done; 1323341977Shselasky sys_debug = sys_debug ? 1 : 0; 1324290650Shselasky if (sys_debug == priv->sysctl_debug) 1325341977Shselasky goto done; 1326337108Shselasky 1327341977Shselasky if ((priv->sysctl_debug = sys_debug)) { 1328290650Shselasky mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 1329290650Shselasky SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 1330290650Shselasky mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 1331290650Shselasky priv->stats.port_stats_debug.arg); 1332341977Shselasky SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx, 1333337108Shselasky SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1334337108Shselasky "hw_ctx_debug", 1335337108Shselasky CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0, 1336337108Shselasky mlx5e_ethtool_debug_channel_info, "S", ""); 1337337108Shselasky } else { 1338290650Shselasky sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 1339337108Shselasky } 1340341977Shselaskydone: 1341337108Shselasky PRIV_UNLOCK(priv); 1342341977Shselasky return (error); 1343290650Shselasky} 1344290650Shselasky 1345322006Shselaskystatic void 1346322006Shselaskymlx5e_create_diagnostics(struct mlx5e_priv *priv) 1347322006Shselasky{ 1348322006Shselasky struct mlx5_core_diagnostics_entry entry; 1349322006Shselasky struct sysctl_ctx_list *ctx; 1350322006Shselasky struct sysctl_oid *node; 1351322006Shselasky int x; 1352322006Shselasky 1353322006Shselasky /* sysctl context we are using */ 1354322006Shselasky ctx = &priv->sysctl_ctx; 1355322006Shselasky 1356322006Shselasky /* create root node */ 1357322006Shselasky node = SYSCTL_ADD_NODE(ctx, 1358322006Shselasky SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1359322006Shselasky "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 1360322006Shselasky if (node == NULL) 1361322006Shselasky return; 1362322006Shselasky 1363322006Shselasky /* create PCI diagnostics */ 1364322006Shselasky for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 1365322006Shselasky entry = mlx5_core_pci_diagnostics_table[x]; 1366322006Shselasky if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1367322006Shselasky continue; 1368322006Shselasky SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1369322006Shselasky entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 1370322006Shselasky "PCI diagnostics counter"); 1371322006Shselasky } 1372322006Shselasky 1373322006Shselasky /* create general diagnostics */ 1374322006Shselasky for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 1375322006Shselasky entry = mlx5_core_general_diagnostics_table[x]; 1376322006Shselasky if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1377322006Shselasky continue; 1378322006Shselasky SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1379322006Shselasky entry.desc, CTLFLAG_RD, priv->params_general.array + x, 1380322006Shselasky "General diagnostics counter"); 1381322006Shselasky } 1382322006Shselasky} 1383322006Shselasky 1384290650Shselaskyvoid 1385290650Shselaskymlx5e_create_ethtool(struct mlx5e_priv *priv) 1386290650Shselasky{ 1387353244Shselasky struct sysctl_oid *fec_node; 1388353244Shselasky struct sysctl_oid *qos_node; 1389353244Shselasky struct sysctl_oid *node; 1390290650Shselasky const char *pnameunit; 1391353238Shselasky struct mlx5e_port_buffer port_buffer; 1392290650Shselasky unsigned x; 1393331577Shselasky int i; 1394290650Shselasky 1395290650Shselasky /* set some defaults */ 1396290650Shselasky priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 1397290650Shselasky priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 1398290650Shselasky priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 1399290650Shselasky priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 1400290650Shselasky priv->params_ethtool.channels = priv->params.num_channels; 1401338552Shselasky priv->params_ethtool.channels_rsss = priv->params.channels_rsss; 1402290650Shselasky priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 1403290650Shselasky priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 1404290650Shselasky priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 1405290650Shselasky priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 1406290650Shselasky priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 1407291932Shselasky priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 1408290650Shselasky priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 1409290650Shselasky priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 1410290650Shselasky priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 1411292838Shselasky priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 1412300277Shselasky mlx5e_ethtool_sync_tx_completion_fact(priv); 1413290650Shselasky 1414331569Shselasky /* get default values for local loopback, if any */ 1415331569Shselasky if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1416331569Shselasky int err; 1417331569Shselasky u8 val; 1418331569Shselasky 1419331569Shselasky err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 1420331569Shselasky if (err == 0) 1421331569Shselasky priv->params_ethtool.mc_local_lb = val; 1422331569Shselasky 1423331569Shselasky err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 1424331569Shselasky if (err == 0) 1425331569Shselasky priv->params_ethtool.uc_local_lb = val; 1426331569Shselasky } 1427331569Shselasky 1428290650Shselasky /* create root node */ 1429290650Shselasky node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1430290650Shselasky SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1431290650Shselasky "conf", CTLFLAG_RW, NULL, "Configuration"); 1432290650Shselasky if (node == NULL) 1433290650Shselasky return; 1434290650Shselasky for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 1435290650Shselasky /* check for read-only parameter */ 1436331570Shselasky if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 1437331570Shselasky strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 1438290650Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1439290650Shselasky mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 1440290650Shselasky CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1441290650Shselasky mlx5e_params_desc[2 * x + 1]); 1442290650Shselasky } else { 1443292837Shselasky#if (__FreeBSD_version < 1100000) 1444292837Shselasky char path[64]; 1445292837Shselasky#endif 1446292837Shselasky /* 1447292837Shselasky * NOTE: In FreeBSD-11 and newer the 1448292837Shselasky * CTLFLAG_RWTUN flag will take care of 1449292837Shselasky * loading default sysctl value from the 1450292837Shselasky * kernel environment, if any: 1451292837Shselasky */ 1452290650Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1453290650Shselasky mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 1454290650Shselasky CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1455290650Shselasky mlx5e_params_desc[2 * x + 1]); 1456292837Shselasky 1457292837Shselasky#if (__FreeBSD_version < 1100000) 1458292837Shselasky /* compute path for sysctl */ 1459292837Shselasky snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 1460292837Shselasky device_get_unit(priv->mdev->pdev->dev.bsddev), 1461292837Shselasky mlx5e_params_desc[2 * x]); 1462292837Shselasky 1463292837Shselasky /* try to fetch tunable, if any */ 1464292837Shselasky if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 1465292837Shselasky mlx5e_ethtool_handler(NULL, priv, x, NULL); 1466292837Shselasky#endif 1467290650Shselasky } 1468290650Shselasky } 1469290650Shselasky 1470353244Shselasky /* create fec node */ 1471353244Shselasky fec_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1472353244Shselasky SYSCTL_CHILDREN(node), OID_AUTO, 1473353244Shselasky "fec", CTLFLAG_RW, NULL, "Forward Error Correction"); 1474353244Shselasky if (fec_node == NULL) 1475353244Shselasky return; 1476353244Shselasky 1477353244Shselasky if (mlx5e_fec_update(priv) == 0) { 1478353244Shselasky SYSCTL_ADD_U32(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1479353244Shselasky "mode_active", CTLFLAG_RD | CTLFLAG_MPSAFE, 1480353244Shselasky &priv->params_ethtool.fec_mode_active, 0, 1481353244Shselasky "Current FEC mode bit, if any."); 1482353244Shselasky 1483353244Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1484353244Shselasky "mask_10x_25x", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1485353244Shselasky priv, 0, &mlx5e_fec_mask_10x_25x_handler, "CU", 1486353244Shselasky "Set FEC masks for 10G_40G, 25G_50G, 56G, 100G respectivly. " 1487353244Shselasky "0:Auto " 1488353244Shselasky "1:NOFEC " 1489353244Shselasky "2:FIRECODE " 1490353244Shselasky "4:RS"); 1491353244Shselasky 1492353244Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1493353244Shselasky "avail_10x_25x", CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE, 1494353244Shselasky priv, 0, &mlx5e_fec_avail_10x_25x_handler, "CU", 1495353244Shselasky "Get available FEC bits for 10G_40G, 25G_50G, 56G, 100G respectivly. " 1496353244Shselasky "0:Auto " 1497353244Shselasky "1:NOFEC " 1498353244Shselasky "2:FIRECODE " 1499353244Shselasky "4:RS"); 1500353244Shselasky 1501353244Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1502353244Shselasky "mask_50x", CTLTYPE_U16 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1503353244Shselasky priv, 0, &mlx5e_fec_mask_50x_handler, "SU", 1504353244Shselasky "Set FEC masks for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. " 1505353244Shselasky "0:Auto " 1506353244Shselasky "128:RS " 1507353244Shselasky "512:LL RS"); 1508353244Shselasky 1509353244Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1510353244Shselasky "avail_50x", CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_MPSAFE, 1511353244Shselasky priv, 0, &mlx5e_fec_avail_50x_handler, "SU", 1512353244Shselasky "Get available FEC bits for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. " 1513353244Shselasky "0:Auto " 1514353244Shselasky "128:RS " 1515353244Shselasky "512:LL RS"); 1516353244Shselasky } 1517353244Shselasky 1518290650Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1519290650Shselasky "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 1520290650Shselasky 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 1521290650Shselasky 1522290650Shselasky pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 1523290650Shselasky 1524290650Shselasky SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 1525290650Shselasky OID_AUTO, "device_name", CTLFLAG_RD, 1526290650Shselasky __DECONST(void *, pnameunit), 0, 1527290650Shselasky "PCI device name"); 1528290650Shselasky 1529322006Shselasky /* Diagnostics support */ 1530322006Shselasky mlx5e_create_diagnostics(priv); 1531331577Shselasky 1532331577Shselasky /* create qos node */ 1533331577Shselasky qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1534331577Shselasky SYSCTL_CHILDREN(node), OID_AUTO, 1535331577Shselasky "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration"); 1536341968Shselasky if (qos_node == NULL) 1537331577Shselasky return; 1538331577Shselasky 1539341968Shselasky /* Priority rate limit support */ 1540341968Shselasky if (mlx5e_getmaxrate(priv) == 0) { 1541341968Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1542341968Shselasky OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1543341968Shselasky priv, 0, mlx5e_tc_maxrate_handler, "QU", 1544341968Shselasky "Max rate for priority, specified in kilobits, where kilo=1000, " 1545341968Shselasky "max_rate must be divisible by 100000"); 1546341968Shselasky } 1547331577Shselasky 1548341968Shselasky /* Bandwidth limiting by ratio */ 1549341968Shselasky if (mlx5e_get_max_alloc(priv) == 0) { 1550331577Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1551341968Shselasky OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1552341968Shselasky priv, 0, mlx5e_tc_rate_share_handler, "QU", 1553341968Shselasky "Specify bandwidth ratio from 1 to 100 " 1554341968Shselasky "for the available traffic classes"); 1555331577Shselasky } 1556331578Shselasky 1557341968Shselasky /* Priority to traffic class mapping */ 1558341968Shselasky if (mlx5e_get_prio_tc(priv) == 0) { 1559347810Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1560347810Shselasky OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1561347810Shselasky priv, 0, mlx5e_prio_to_tc_handler, "CU", 1562347810Shselasky "Set traffic class 0 to 7 for priority 0 to 7 inclusivly"); 1563331578Shselasky } 1564337098Shselasky 1565337098Shselasky /* DSCP support */ 1566337098Shselasky if (mlx5e_get_dscp(priv) == 0) { 1567337098Shselasky for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) { 1568337098Shselasky char name[32]; 1569337098Shselasky snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7); 1570337098Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1571337098Shselasky OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1572337098Shselasky priv, i, mlx5e_dscp_prio_handler, "CU", 1573337098Shselasky "Set DSCP to priority mapping, 0..7"); 1574337098Shselasky } 1575337107Shselasky#define A "Set trust state, 1:PCP 2:DSCP" 1576337107Shselasky#define B " 3:BOTH" 1577337098Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1578337098Shselasky OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1579337098Shselasky priv, 0, mlx5e_trust_state_handler, "CU", 1580347810Shselasky MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ? 1581337107Shselasky A B : A); 1582337107Shselasky#undef B 1583337107Shselasky#undef A 1584337098Shselasky } 1585353238Shselasky 1586353238Shselasky if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) { 1587353238Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1588353238Shselasky OID_AUTO, "buffers_size", 1589353238Shselasky CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1590353238Shselasky priv, 0, mlx5e_buf_size_handler, "IU", 1591353238Shselasky "Set buffers sizes"); 1592353238Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1593353238Shselasky OID_AUTO, "buffers_prio", 1594353238Shselasky CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1595353238Shselasky priv, 0, mlx5e_buf_prio_handler, "CU", 1596353238Shselasky "Set prio to buffers mapping"); 1597353238Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1598353238Shselasky OID_AUTO, "cable_length", 1599353238Shselasky CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1600353238Shselasky priv, 0, mlx5e_cable_length_handler, "IU", 1601353238Shselasky "Set cable length in meters for xoff threshold calculation"); 1602353238Shselasky } 1603361171Shselasky 1604361171Shselasky if (mlx5e_hw_temperature_update(priv) == 0) { 1605361171Shselasky SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(priv->sysctl_ifnet), 1606361171Shselasky OID_AUTO, "hw_temperature", 1607361171Shselasky CTLTYPE_S32 | CTLFLAG_RD | CTLFLAG_MPSAFE, 1608361171Shselasky priv, 0, mlx5e_hw_temperature_handler, "I", 1609361171Shselasky "HW temperature in millicelcius"); 1610361171Shselasky } 1611290650Shselasky} 1612