1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2019 Mellanox Technologies */ 3 4#include <devlink.h> 5 6#include "mlx5_core.h" 7#include "fw_reset.h" 8#include "fs_core.h" 9#include "eswitch.h" 10#include "esw/qos.h" 11#include "sf/dev/dev.h" 12#include "sf/sf.h" 13 14static int mlx5_devlink_flash_update(struct devlink *devlink, 15 struct devlink_flash_update_params *params, 16 struct netlink_ext_ack *extack) 17{ 18 struct mlx5_core_dev *dev = devlink_priv(devlink); 19 20 return mlx5_firmware_flash(dev, params->fw, extack); 21} 22 23static u8 mlx5_fw_ver_major(u32 version) 24{ 25 return (version >> 24) & 0xff; 26} 27 28static u8 mlx5_fw_ver_minor(u32 version) 29{ 30 return (version >> 16) & 0xff; 31} 32 33static u16 mlx5_fw_ver_subminor(u32 version) 34{ 35 return version & 0xffff; 36} 37 38#define DEVLINK_FW_STRING_LEN 32 39 40static int 41mlx5_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, 42 struct netlink_ext_ack *extack) 43{ 44 struct mlx5_core_dev *dev = devlink_priv(devlink); 45 char version_str[DEVLINK_FW_STRING_LEN]; 46 u32 running_fw, stored_fw; 47 int err; 48 49 err = devlink_info_version_fixed_put(req, "fw.psid", dev->board_id); 50 if (err) 51 return err; 52 53 err = mlx5_fw_version_query(dev, &running_fw, &stored_fw); 54 if (err) 55 return err; 56 57 snprintf(version_str, sizeof(version_str), "%d.%d.%04d", 58 mlx5_fw_ver_major(running_fw), mlx5_fw_ver_minor(running_fw), 59 mlx5_fw_ver_subminor(running_fw)); 60 err = devlink_info_version_running_put(req, "fw.version", version_str); 61 if (err) 62 return err; 63 err = devlink_info_version_running_put(req, 64 DEVLINK_INFO_VERSION_GENERIC_FW, 65 version_str); 66 if (err) 67 return err; 68 69 /* no pending version, return running (stored) version */ 70 if (stored_fw == 0) 71 stored_fw = running_fw; 72 73 snprintf(version_str, sizeof(version_str), "%d.%d.%04d", 74 mlx5_fw_ver_major(stored_fw), mlx5_fw_ver_minor(stored_fw), 75 mlx5_fw_ver_subminor(stored_fw)); 76 err = devlink_info_version_stored_put(req, "fw.version", version_str); 77 if (err) 78 return err; 79 return devlink_info_version_stored_put(req, 80 DEVLINK_INFO_VERSION_GENERIC_FW, 81 version_str); 82} 83 84static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netlink_ext_ack *extack) 85{ 86 struct mlx5_core_dev *dev = devlink_priv(devlink); 87 u8 reset_level, reset_type, net_port_alive; 88 int err; 89 90 err = mlx5_fw_reset_query(dev, &reset_level, &reset_type); 91 if (err) 92 return err; 93 if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL3)) { 94 NL_SET_ERR_MSG_MOD(extack, "FW activate requires reboot"); 95 return -EINVAL; 96 } 97 98 net_port_alive = !!(reset_type & MLX5_MFRL_REG_RESET_TYPE_NET_PORT_ALIVE); 99 err = mlx5_fw_reset_set_reset_sync(dev, net_port_alive, extack); 100 if (err) 101 return err; 102 103 err = mlx5_fw_reset_wait_reset_done(dev); 104 if (err) 105 return err; 106 107 mlx5_unload_one_devl_locked(dev, true); 108 err = mlx5_health_wait_pci_up(dev); 109 if (err) 110 NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); 111 112 return err; 113} 114 115static int mlx5_devlink_trigger_fw_live_patch(struct devlink *devlink, 116 struct netlink_ext_ack *extack) 117{ 118 struct mlx5_core_dev *dev = devlink_priv(devlink); 119 u8 reset_level; 120 int err; 121 122 err = mlx5_fw_reset_query(dev, &reset_level, NULL); 123 if (err) 124 return err; 125 if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL0)) { 126 NL_SET_ERR_MSG_MOD(extack, 127 "FW upgrade to the stored FW can't be done by FW live patching"); 128 return -EINVAL; 129 } 130 131 return mlx5_fw_reset_set_live_patch(dev); 132} 133 134static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, 135 enum devlink_reload_action action, 136 enum devlink_reload_limit limit, 137 struct netlink_ext_ack *extack) 138{ 139 struct mlx5_core_dev *dev = devlink_priv(devlink); 140 struct pci_dev *pdev = dev->pdev; 141 int ret = 0; 142 143 if (mlx5_dev_is_lightweight(dev)) { 144 if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) 145 return -EOPNOTSUPP; 146 mlx5_unload_one_light(dev); 147 return 0; 148 } 149 150 if (mlx5_lag_is_active(dev)) { 151 NL_SET_ERR_MSG_MOD(extack, "reload is unsupported in Lag mode"); 152 return -EOPNOTSUPP; 153 } 154 155 if (mlx5_core_is_mp_slave(dev)) { 156 NL_SET_ERR_MSG_MOD(extack, "reload is unsupported for multi port slave"); 157 return -EOPNOTSUPP; 158 } 159 160 if (action == DEVLINK_RELOAD_ACTION_FW_ACTIVATE && 161 !dev->priv.fw_reset) { 162 NL_SET_ERR_MSG_MOD(extack, "FW activate is unsupported for this function"); 163 return -EOPNOTSUPP; 164 } 165 166 if (mlx5_core_is_pf(dev) && pci_num_vf(pdev)) 167 NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable"); 168 169 switch (action) { 170 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 171 mlx5_unload_one_devl_locked(dev, false); 172 break; 173 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 174 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET) 175 ret = mlx5_devlink_trigger_fw_live_patch(devlink, extack); 176 else 177 ret = mlx5_devlink_reload_fw_activate(devlink, extack); 178 break; 179 default: 180 /* Unsupported action should not get to this function */ 181 WARN_ON(1); 182 ret = -EOPNOTSUPP; 183 } 184 185 return ret; 186} 187 188static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action, 189 enum devlink_reload_limit limit, u32 *actions_performed, 190 struct netlink_ext_ack *extack) 191{ 192 struct mlx5_core_dev *dev = devlink_priv(devlink); 193 int ret = 0; 194 195 *actions_performed = BIT(action); 196 switch (action) { 197 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 198 if (mlx5_dev_is_lightweight(dev)) { 199 mlx5_fw_reporters_create(dev); 200 return mlx5_init_one_devl_locked(dev); 201 } 202 ret = mlx5_load_one_devl_locked(dev, false); 203 break; 204 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 205 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET) 206 break; 207 /* On fw_activate action, also driver is reloaded and reinit performed */ 208 *actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 209 ret = mlx5_load_one_devl_locked(dev, true); 210 if (ret) 211 return ret; 212 ret = mlx5_fw_reset_verify_fw_complete(dev, extack); 213 break; 214 default: 215 /* Unsupported action should not get to this function */ 216 WARN_ON(1); 217 ret = -EOPNOTSUPP; 218 } 219 220 return ret; 221} 222 223static struct mlx5_devlink_trap *mlx5_find_trap_by_id(struct mlx5_core_dev *dev, int trap_id) 224{ 225 struct mlx5_devlink_trap *dl_trap; 226 227 list_for_each_entry(dl_trap, &dev->priv.traps, list) 228 if (dl_trap->trap.id == trap_id) 229 return dl_trap; 230 231 return NULL; 232} 233 234static int mlx5_devlink_trap_init(struct devlink *devlink, const struct devlink_trap *trap, 235 void *trap_ctx) 236{ 237 struct mlx5_core_dev *dev = devlink_priv(devlink); 238 struct mlx5_devlink_trap *dl_trap; 239 240 dl_trap = kzalloc(sizeof(*dl_trap), GFP_KERNEL); 241 if (!dl_trap) 242 return -ENOMEM; 243 244 dl_trap->trap.id = trap->id; 245 dl_trap->trap.action = DEVLINK_TRAP_ACTION_DROP; 246 dl_trap->item = trap_ctx; 247 248 if (mlx5_find_trap_by_id(dev, trap->id)) { 249 kfree(dl_trap); 250 mlx5_core_err(dev, "Devlink trap: Trap 0x%x already found", trap->id); 251 return -EEXIST; 252 } 253 254 list_add_tail(&dl_trap->list, &dev->priv.traps); 255 return 0; 256} 257 258static void mlx5_devlink_trap_fini(struct devlink *devlink, const struct devlink_trap *trap, 259 void *trap_ctx) 260{ 261 struct mlx5_core_dev *dev = devlink_priv(devlink); 262 struct mlx5_devlink_trap *dl_trap; 263 264 dl_trap = mlx5_find_trap_by_id(dev, trap->id); 265 if (!dl_trap) { 266 mlx5_core_err(dev, "Devlink trap: Missing trap id 0x%x", trap->id); 267 return; 268 } 269 list_del(&dl_trap->list); 270 kfree(dl_trap); 271} 272 273static int mlx5_devlink_trap_action_set(struct devlink *devlink, 274 const struct devlink_trap *trap, 275 enum devlink_trap_action action, 276 struct netlink_ext_ack *extack) 277{ 278 struct mlx5_core_dev *dev = devlink_priv(devlink); 279 struct mlx5_devlink_trap_event_ctx trap_event_ctx; 280 enum devlink_trap_action action_orig; 281 struct mlx5_devlink_trap *dl_trap; 282 int err; 283 284 if (is_mdev_switchdev_mode(dev)) { 285 NL_SET_ERR_MSG_MOD(extack, "Devlink traps can't be set in switchdev mode"); 286 return -EOPNOTSUPP; 287 } 288 289 dl_trap = mlx5_find_trap_by_id(dev, trap->id); 290 if (!dl_trap) { 291 mlx5_core_err(dev, "Devlink trap: Set action on invalid trap id 0x%x", trap->id); 292 return -EINVAL; 293 } 294 295 if (action != DEVLINK_TRAP_ACTION_DROP && action != DEVLINK_TRAP_ACTION_TRAP) 296 return -EOPNOTSUPP; 297 298 if (action == dl_trap->trap.action) 299 return 0; 300 301 action_orig = dl_trap->trap.action; 302 dl_trap->trap.action = action; 303 trap_event_ctx.trap = &dl_trap->trap; 304 trap_event_ctx.err = 0; 305 err = mlx5_blocking_notifier_call_chain(dev, MLX5_DRIVER_EVENT_TYPE_TRAP, 306 &trap_event_ctx); 307 if (err == NOTIFY_BAD) 308 dl_trap->trap.action = action_orig; 309 310 return trap_event_ctx.err; 311} 312 313static const struct devlink_ops mlx5_devlink_ops = { 314#ifdef CONFIG_MLX5_ESWITCH 315 .eswitch_mode_set = mlx5_devlink_eswitch_mode_set, 316 .eswitch_mode_get = mlx5_devlink_eswitch_mode_get, 317 .eswitch_inline_mode_set = mlx5_devlink_eswitch_inline_mode_set, 318 .eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get, 319 .eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set, 320 .eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get, 321 .rate_leaf_tx_share_set = mlx5_esw_devlink_rate_leaf_tx_share_set, 322 .rate_leaf_tx_max_set = mlx5_esw_devlink_rate_leaf_tx_max_set, 323 .rate_node_tx_share_set = mlx5_esw_devlink_rate_node_tx_share_set, 324 .rate_node_tx_max_set = mlx5_esw_devlink_rate_node_tx_max_set, 325 .rate_node_new = mlx5_esw_devlink_rate_node_new, 326 .rate_node_del = mlx5_esw_devlink_rate_node_del, 327 .rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set, 328#endif 329#ifdef CONFIG_MLX5_SF_MANAGER 330 .port_new = mlx5_devlink_sf_port_new, 331#endif 332 .flash_update = mlx5_devlink_flash_update, 333 .info_get = mlx5_devlink_info_get, 334 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 335 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 336 .reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET), 337 .reload_down = mlx5_devlink_reload_down, 338 .reload_up = mlx5_devlink_reload_up, 339 .trap_init = mlx5_devlink_trap_init, 340 .trap_fini = mlx5_devlink_trap_fini, 341 .trap_action_set = mlx5_devlink_trap_action_set, 342}; 343 344void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb, 345 struct devlink_port *dl_port) 346{ 347 struct devlink *devlink = priv_to_devlink(dev); 348 struct mlx5_devlink_trap *dl_trap; 349 350 dl_trap = mlx5_find_trap_by_id(dev, trap_id); 351 if (!dl_trap) { 352 mlx5_core_err(dev, "Devlink trap: Report on invalid trap id 0x%x", trap_id); 353 return; 354 } 355 356 if (dl_trap->trap.action != DEVLINK_TRAP_ACTION_TRAP) { 357 mlx5_core_dbg(dev, "Devlink trap: Trap id %d has action %d", trap_id, 358 dl_trap->trap.action); 359 return; 360 } 361 devlink_trap_report(devlink, skb, dl_trap->item, dl_port, NULL); 362} 363 364int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev) 365{ 366 struct mlx5_devlink_trap *dl_trap; 367 int count = 0; 368 369 list_for_each_entry(dl_trap, &dev->priv.traps, list) 370 if (dl_trap->trap.action == DEVLINK_TRAP_ACTION_TRAP) 371 count++; 372 373 return count; 374} 375 376int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id, 377 enum devlink_trap_action *action) 378{ 379 struct mlx5_devlink_trap *dl_trap; 380 381 dl_trap = mlx5_find_trap_by_id(dev, trap_id); 382 if (!dl_trap) { 383 mlx5_core_err(dev, "Devlink trap: Get action on invalid trap id 0x%x", 384 trap_id); 385 return -EINVAL; 386 } 387 388 *action = dl_trap->trap.action; 389 return 0; 390} 391 392struct devlink *mlx5_devlink_alloc(struct device *dev) 393{ 394 return devlink_alloc(&mlx5_devlink_ops, sizeof(struct mlx5_core_dev), 395 dev); 396} 397 398void mlx5_devlink_free(struct devlink *devlink) 399{ 400 devlink_free(devlink); 401} 402 403static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 404 union devlink_param_value val, 405 struct netlink_ext_ack *extack) 406{ 407 struct mlx5_core_dev *dev = devlink_priv(devlink); 408 bool new_state = val.vbool; 409 410 if (new_state && !MLX5_CAP_GEN(dev, roce) && 411 !(MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce))) { 412 NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE"); 413 return -EOPNOTSUPP; 414 } 415 if (mlx5_core_is_mp_slave(dev) || mlx5_lag_is_active(dev)) { 416 NL_SET_ERR_MSG_MOD(extack, "Multi port slave/Lag device can't configure RoCE"); 417 return -EOPNOTSUPP; 418 } 419 420 return 0; 421} 422 423#ifdef CONFIG_MLX5_ESWITCH 424static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id, 425 union devlink_param_value val, 426 struct netlink_ext_ack *extack) 427{ 428 int group_num = val.vu32; 429 430 if (group_num < 1 || group_num > 1024) { 431 NL_SET_ERR_MSG_MOD(extack, 432 "Unsupported group number, supported range is 1-1024"); 433 return -EOPNOTSUPP; 434 } 435 436 return 0; 437} 438#endif 439 440static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id, 441 union devlink_param_value val, 442 struct netlink_ext_ack *extack) 443{ 444 return (val.vu32 >= 64 && val.vu32 <= 4096) ? 0 : -EINVAL; 445} 446 447static int 448mlx5_devlink_hairpin_num_queues_validate(struct devlink *devlink, u32 id, 449 union devlink_param_value val, 450 struct netlink_ext_ack *extack) 451{ 452 return val.vu32 ? 0 : -EINVAL; 453} 454 455static int 456mlx5_devlink_hairpin_queue_size_validate(struct devlink *devlink, u32 id, 457 union devlink_param_value val, 458 struct netlink_ext_ack *extack) 459{ 460 struct mlx5_core_dev *dev = devlink_priv(devlink); 461 u32 val32 = val.vu32; 462 463 if (!is_power_of_2(val32)) { 464 NL_SET_ERR_MSG_MOD(extack, "Value is not power of two"); 465 return -EINVAL; 466 } 467 468 if (val32 > BIT(MLX5_CAP_GEN(dev, log_max_hairpin_num_packets))) { 469 NL_SET_ERR_MSG_FMT_MOD( 470 extack, "Maximum hairpin queue size is %lu", 471 BIT(MLX5_CAP_GEN(dev, log_max_hairpin_num_packets))); 472 return -EINVAL; 473 } 474 475 return 0; 476} 477 478static void mlx5_devlink_hairpin_params_init_values(struct devlink *devlink) 479{ 480 struct mlx5_core_dev *dev = devlink_priv(devlink); 481 union devlink_param_value value; 482 u32 link_speed = 0; 483 u64 link_speed64; 484 485 /* set hairpin pair per each 50Gbs share of the link */ 486 mlx5_port_max_linkspeed(dev, &link_speed); 487 link_speed = max_t(u32, link_speed, 50000); 488 link_speed64 = link_speed; 489 do_div(link_speed64, 50000); 490 491 value.vu32 = link_speed64; 492 devl_param_driverinit_value_set( 493 devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES, value); 494 495 value.vu32 = 496 BIT(min_t(u32, 16 - MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(dev), 497 MLX5_CAP_GEN(dev, log_max_hairpin_num_packets))); 498 devl_param_driverinit_value_set( 499 devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_QUEUE_SIZE, value); 500} 501 502static const struct devlink_param mlx5_devlink_params[] = { 503 DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 504 NULL, NULL, mlx5_devlink_enable_roce_validate), 505#ifdef CONFIG_MLX5_ESWITCH 506 DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 507 "fdb_large_groups", DEVLINK_PARAM_TYPE_U32, 508 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 509 NULL, NULL, 510 mlx5_devlink_large_group_num_validate), 511#endif 512 DEVLINK_PARAM_GENERIC(IO_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 513 NULL, NULL, mlx5_devlink_eq_depth_validate), 514 DEVLINK_PARAM_GENERIC(EVENT_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 515 NULL, NULL, mlx5_devlink_eq_depth_validate), 516}; 517 518static void mlx5_devlink_set_params_init_values(struct devlink *devlink) 519{ 520 struct mlx5_core_dev *dev = devlink_priv(devlink); 521 union devlink_param_value value; 522 523 value.vbool = MLX5_CAP_GEN(dev, roce) && !mlx5_dev_is_lightweight(dev); 524 devl_param_driverinit_value_set(devlink, 525 DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, 526 value); 527 528#ifdef CONFIG_MLX5_ESWITCH 529 value.vu32 = ESW_OFFLOADS_DEFAULT_NUM_GROUPS; 530 devl_param_driverinit_value_set(devlink, 531 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 532 value); 533#endif 534 535 value.vu32 = MLX5_COMP_EQ_SIZE; 536 devl_param_driverinit_value_set(devlink, 537 DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE, 538 value); 539 540 value.vu32 = MLX5_NUM_ASYNC_EQE; 541 devl_param_driverinit_value_set(devlink, 542 DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE, 543 value); 544} 545 546static const struct devlink_param mlx5_devlink_eth_params[] = { 547 DEVLINK_PARAM_GENERIC(ENABLE_ETH, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 548 NULL, NULL, NULL), 549 DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES, 550 "hairpin_num_queues", DEVLINK_PARAM_TYPE_U32, 551 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL, 552 mlx5_devlink_hairpin_num_queues_validate), 553 DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_HAIRPIN_QUEUE_SIZE, 554 "hairpin_queue_size", DEVLINK_PARAM_TYPE_U32, 555 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL, 556 mlx5_devlink_hairpin_queue_size_validate), 557}; 558 559static int mlx5_devlink_eth_params_register(struct devlink *devlink) 560{ 561 struct mlx5_core_dev *dev = devlink_priv(devlink); 562 union devlink_param_value value; 563 int err; 564 565 if (!mlx5_eth_supported(dev)) 566 return 0; 567 568 err = devl_params_register(devlink, mlx5_devlink_eth_params, 569 ARRAY_SIZE(mlx5_devlink_eth_params)); 570 if (err) 571 return err; 572 573 value.vbool = !mlx5_dev_is_lightweight(dev); 574 devl_param_driverinit_value_set(devlink, 575 DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, 576 value); 577 578 mlx5_devlink_hairpin_params_init_values(devlink); 579 580 return 0; 581} 582 583static void mlx5_devlink_eth_params_unregister(struct devlink *devlink) 584{ 585 struct mlx5_core_dev *dev = devlink_priv(devlink); 586 587 if (!mlx5_eth_supported(dev)) 588 return; 589 590 devl_params_unregister(devlink, mlx5_devlink_eth_params, 591 ARRAY_SIZE(mlx5_devlink_eth_params)); 592} 593 594static int mlx5_devlink_enable_rdma_validate(struct devlink *devlink, u32 id, 595 union devlink_param_value val, 596 struct netlink_ext_ack *extack) 597{ 598 struct mlx5_core_dev *dev = devlink_priv(devlink); 599 bool new_state = val.vbool; 600 601 if (new_state && !mlx5_rdma_supported(dev)) 602 return -EOPNOTSUPP; 603 return 0; 604} 605 606static const struct devlink_param mlx5_devlink_rdma_params[] = { 607 DEVLINK_PARAM_GENERIC(ENABLE_RDMA, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 608 NULL, NULL, mlx5_devlink_enable_rdma_validate), 609}; 610 611static int mlx5_devlink_rdma_params_register(struct devlink *devlink) 612{ 613 struct mlx5_core_dev *dev = devlink_priv(devlink); 614 union devlink_param_value value; 615 int err; 616 617 if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND)) 618 return 0; 619 620 err = devl_params_register(devlink, mlx5_devlink_rdma_params, 621 ARRAY_SIZE(mlx5_devlink_rdma_params)); 622 if (err) 623 return err; 624 625 value.vbool = !mlx5_dev_is_lightweight(dev); 626 devl_param_driverinit_value_set(devlink, 627 DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, 628 value); 629 return 0; 630} 631 632static void mlx5_devlink_rdma_params_unregister(struct devlink *devlink) 633{ 634 if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND)) 635 return; 636 637 devl_params_unregister(devlink, mlx5_devlink_rdma_params, 638 ARRAY_SIZE(mlx5_devlink_rdma_params)); 639} 640 641static const struct devlink_param mlx5_devlink_vnet_params[] = { 642 DEVLINK_PARAM_GENERIC(ENABLE_VNET, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 643 NULL, NULL, NULL), 644}; 645 646static int mlx5_devlink_vnet_params_register(struct devlink *devlink) 647{ 648 struct mlx5_core_dev *dev = devlink_priv(devlink); 649 union devlink_param_value value; 650 int err; 651 652 if (!mlx5_vnet_supported(dev)) 653 return 0; 654 655 err = devl_params_register(devlink, mlx5_devlink_vnet_params, 656 ARRAY_SIZE(mlx5_devlink_vnet_params)); 657 if (err) 658 return err; 659 660 value.vbool = !mlx5_dev_is_lightweight(dev); 661 devl_param_driverinit_value_set(devlink, 662 DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, 663 value); 664 return 0; 665} 666 667static void mlx5_devlink_vnet_params_unregister(struct devlink *devlink) 668{ 669 struct mlx5_core_dev *dev = devlink_priv(devlink); 670 671 if (!mlx5_vnet_supported(dev)) 672 return; 673 674 devl_params_unregister(devlink, mlx5_devlink_vnet_params, 675 ARRAY_SIZE(mlx5_devlink_vnet_params)); 676} 677 678static int mlx5_devlink_auxdev_params_register(struct devlink *devlink) 679{ 680 int err; 681 682 err = mlx5_devlink_eth_params_register(devlink); 683 if (err) 684 return err; 685 686 err = mlx5_devlink_rdma_params_register(devlink); 687 if (err) 688 goto rdma_err; 689 690 err = mlx5_devlink_vnet_params_register(devlink); 691 if (err) 692 goto vnet_err; 693 return 0; 694 695vnet_err: 696 mlx5_devlink_rdma_params_unregister(devlink); 697rdma_err: 698 mlx5_devlink_eth_params_unregister(devlink); 699 return err; 700} 701 702static void mlx5_devlink_auxdev_params_unregister(struct devlink *devlink) 703{ 704 mlx5_devlink_vnet_params_unregister(devlink); 705 mlx5_devlink_rdma_params_unregister(devlink); 706 mlx5_devlink_eth_params_unregister(devlink); 707} 708 709static int mlx5_devlink_max_uc_list_validate(struct devlink *devlink, u32 id, 710 union devlink_param_value val, 711 struct netlink_ext_ack *extack) 712{ 713 struct mlx5_core_dev *dev = devlink_priv(devlink); 714 715 if (val.vu32 == 0) { 716 NL_SET_ERR_MSG_MOD(extack, "max_macs value must be greater than 0"); 717 return -EINVAL; 718 } 719 720 if (!is_power_of_2(val.vu32)) { 721 NL_SET_ERR_MSG_MOD(extack, "Only power of 2 values are supported for max_macs"); 722 return -EINVAL; 723 } 724 725 if (ilog2(val.vu32) > 726 MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list)) { 727 NL_SET_ERR_MSG_MOD(extack, "max_macs value is out of the supported range"); 728 return -EINVAL; 729 } 730 731 return 0; 732} 733 734static const struct devlink_param mlx5_devlink_max_uc_list_params[] = { 735 DEVLINK_PARAM_GENERIC(MAX_MACS, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 736 NULL, NULL, mlx5_devlink_max_uc_list_validate), 737}; 738 739static int mlx5_devlink_max_uc_list_params_register(struct devlink *devlink) 740{ 741 struct mlx5_core_dev *dev = devlink_priv(devlink); 742 union devlink_param_value value; 743 int err; 744 745 if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported)) 746 return 0; 747 748 err = devl_params_register(devlink, mlx5_devlink_max_uc_list_params, 749 ARRAY_SIZE(mlx5_devlink_max_uc_list_params)); 750 if (err) 751 return err; 752 753 value.vu32 = 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list); 754 devl_param_driverinit_value_set(devlink, 755 DEVLINK_PARAM_GENERIC_ID_MAX_MACS, 756 value); 757 return 0; 758} 759 760static void 761mlx5_devlink_max_uc_list_params_unregister(struct devlink *devlink) 762{ 763 struct mlx5_core_dev *dev = devlink_priv(devlink); 764 765 if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported)) 766 return; 767 768 devl_params_unregister(devlink, mlx5_devlink_max_uc_list_params, 769 ARRAY_SIZE(mlx5_devlink_max_uc_list_params)); 770} 771 772#define MLX5_TRAP_DROP(_id, _group_id) \ 773 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ 774 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 775 DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) 776 777static const struct devlink_trap mlx5_traps_arr[] = { 778 MLX5_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS), 779 MLX5_TRAP_DROP(DMAC_FILTER, L2_DROPS), 780}; 781 782static const struct devlink_trap_group mlx5_trap_groups_arr[] = { 783 DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0), 784}; 785 786int mlx5_devlink_traps_register(struct devlink *devlink) 787{ 788 struct mlx5_core_dev *core_dev = devlink_priv(devlink); 789 int err; 790 791 err = devl_trap_groups_register(devlink, mlx5_trap_groups_arr, 792 ARRAY_SIZE(mlx5_trap_groups_arr)); 793 if (err) 794 return err; 795 796 err = devl_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr), 797 &core_dev->priv); 798 if (err) 799 goto err_trap_group; 800 return 0; 801 802err_trap_group: 803 devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr, 804 ARRAY_SIZE(mlx5_trap_groups_arr)); 805 return err; 806} 807 808void mlx5_devlink_traps_unregister(struct devlink *devlink) 809{ 810 devl_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr)); 811 devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr, 812 ARRAY_SIZE(mlx5_trap_groups_arr)); 813} 814 815int mlx5_devlink_params_register(struct devlink *devlink) 816{ 817 int err; 818 819 /* Here only the driver init params should be registered. 820 * Runtime params should be registered by the code which 821 * behaviour they configure. 822 */ 823 824 err = devl_params_register(devlink, mlx5_devlink_params, 825 ARRAY_SIZE(mlx5_devlink_params)); 826 if (err) 827 return err; 828 829 mlx5_devlink_set_params_init_values(devlink); 830 831 err = mlx5_devlink_auxdev_params_register(devlink); 832 if (err) 833 goto auxdev_reg_err; 834 835 err = mlx5_devlink_max_uc_list_params_register(devlink); 836 if (err) 837 goto max_uc_list_err; 838 839 return 0; 840 841max_uc_list_err: 842 mlx5_devlink_auxdev_params_unregister(devlink); 843auxdev_reg_err: 844 devl_params_unregister(devlink, mlx5_devlink_params, 845 ARRAY_SIZE(mlx5_devlink_params)); 846 return err; 847} 848 849void mlx5_devlink_params_unregister(struct devlink *devlink) 850{ 851 mlx5_devlink_max_uc_list_params_unregister(devlink); 852 mlx5_devlink_auxdev_params_unregister(devlink); 853 devl_params_unregister(devlink, mlx5_devlink_params, 854 ARRAY_SIZE(mlx5_devlink_params)); 855} 856