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 14 static 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 23 static u8 mlx5_fw_ver_major(u32 version) 24 { 25 return (version >> 24) & 0xff; 26 } 27 28 static u8 mlx5_fw_ver_minor(u32 version) 29 { 30 return (version >> 16) & 0xff; 31 } 32 33 static u16 mlx5_fw_ver_subminor(u32 version) 34 { 35 return version & 0xffff; 36 } 37 38 #define DEVLINK_FW_STRING_LEN 32 39 40 static int 41 mlx5_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 84 static 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); 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 115 static 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 134 static 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 bool sf_dev_allocated; 142 int ret = 0; 143 144 sf_dev_allocated = mlx5_sf_dev_allocated(dev); 145 if (sf_dev_allocated) { 146 /* Reload results in deleting SF device which further results in 147 * unregistering devlink instance while holding devlink_mutext. 148 * Hence, do not support reload. 149 */ 150 NL_SET_ERR_MSG_MOD(extack, "reload is unsupported when SFs are allocated"); 151 return -EOPNOTSUPP; 152 } 153 154 if (mlx5_lag_is_active(dev)) { 155 NL_SET_ERR_MSG_MOD(extack, "reload is unsupported in Lag mode"); 156 return -EOPNOTSUPP; 157 } 158 159 if (mlx5_core_is_mp_slave(dev)) { 160 NL_SET_ERR_MSG_MOD(extack, "reload is unsupported for multi port slave"); 161 return -EOPNOTSUPP; 162 } 163 164 if (pci_num_vf(pdev)) { 165 NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable"); 166 } 167 168 switch (action) { 169 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 170 mlx5_unload_one_devl_locked(dev); 171 break; 172 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 173 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET) 174 ret = mlx5_devlink_trigger_fw_live_patch(devlink, extack); 175 else 176 ret = mlx5_devlink_reload_fw_activate(devlink, extack); 177 break; 178 default: 179 /* Unsupported action should not get to this function */ 180 WARN_ON(1); 181 ret = -EOPNOTSUPP; 182 } 183 184 return ret; 185 } 186 187 static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action, 188 enum devlink_reload_limit limit, u32 *actions_performed, 189 struct netlink_ext_ack *extack) 190 { 191 struct mlx5_core_dev *dev = devlink_priv(devlink); 192 int ret = 0; 193 194 *actions_performed = BIT(action); 195 switch (action) { 196 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 197 ret = mlx5_load_one_devl_locked(dev, false); 198 break; 199 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 200 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET) 201 break; 202 /* On fw_activate action, also driver is reloaded and reinit performed */ 203 *actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 204 ret = mlx5_load_one_devl_locked(dev, false); 205 break; 206 default: 207 /* Unsupported action should not get to this function */ 208 WARN_ON(1); 209 ret = -EOPNOTSUPP; 210 } 211 212 return ret; 213 } 214 215 static struct mlx5_devlink_trap *mlx5_find_trap_by_id(struct mlx5_core_dev *dev, int trap_id) 216 { 217 struct mlx5_devlink_trap *dl_trap; 218 219 list_for_each_entry(dl_trap, &dev->priv.traps, list) 220 if (dl_trap->trap.id == trap_id) 221 return dl_trap; 222 223 return NULL; 224 } 225 226 static int mlx5_devlink_trap_init(struct devlink *devlink, const struct devlink_trap *trap, 227 void *trap_ctx) 228 { 229 struct mlx5_core_dev *dev = devlink_priv(devlink); 230 struct mlx5_devlink_trap *dl_trap; 231 232 dl_trap = kzalloc(sizeof(*dl_trap), GFP_KERNEL); 233 if (!dl_trap) 234 return -ENOMEM; 235 236 dl_trap->trap.id = trap->id; 237 dl_trap->trap.action = DEVLINK_TRAP_ACTION_DROP; 238 dl_trap->item = trap_ctx; 239 240 if (mlx5_find_trap_by_id(dev, trap->id)) { 241 kfree(dl_trap); 242 mlx5_core_err(dev, "Devlink trap: Trap 0x%x already found", trap->id); 243 return -EEXIST; 244 } 245 246 list_add_tail(&dl_trap->list, &dev->priv.traps); 247 return 0; 248 } 249 250 static void mlx5_devlink_trap_fini(struct devlink *devlink, const struct devlink_trap *trap, 251 void *trap_ctx) 252 { 253 struct mlx5_core_dev *dev = devlink_priv(devlink); 254 struct mlx5_devlink_trap *dl_trap; 255 256 dl_trap = mlx5_find_trap_by_id(dev, trap->id); 257 if (!dl_trap) { 258 mlx5_core_err(dev, "Devlink trap: Missing trap id 0x%x", trap->id); 259 return; 260 } 261 list_del(&dl_trap->list); 262 kfree(dl_trap); 263 } 264 265 static int mlx5_devlink_trap_action_set(struct devlink *devlink, 266 const struct devlink_trap *trap, 267 enum devlink_trap_action action, 268 struct netlink_ext_ack *extack) 269 { 270 struct mlx5_core_dev *dev = devlink_priv(devlink); 271 enum devlink_trap_action action_orig; 272 struct mlx5_devlink_trap *dl_trap; 273 int err = 0; 274 275 if (is_mdev_switchdev_mode(dev)) { 276 NL_SET_ERR_MSG_MOD(extack, "Devlink traps can't be set in switchdev mode"); 277 return -EOPNOTSUPP; 278 } 279 280 dl_trap = mlx5_find_trap_by_id(dev, trap->id); 281 if (!dl_trap) { 282 mlx5_core_err(dev, "Devlink trap: Set action on invalid trap id 0x%x", trap->id); 283 err = -EINVAL; 284 goto out; 285 } 286 287 if (action != DEVLINK_TRAP_ACTION_DROP && action != DEVLINK_TRAP_ACTION_TRAP) { 288 err = -EOPNOTSUPP; 289 goto out; 290 } 291 292 if (action == dl_trap->trap.action) 293 goto out; 294 295 action_orig = dl_trap->trap.action; 296 dl_trap->trap.action = action; 297 err = mlx5_blocking_notifier_call_chain(dev, MLX5_DRIVER_EVENT_TYPE_TRAP, 298 &dl_trap->trap); 299 if (err) 300 dl_trap->trap.action = action_orig; 301 out: 302 return err; 303 } 304 305 static const struct devlink_ops mlx5_devlink_ops = { 306 #ifdef CONFIG_MLX5_ESWITCH 307 .eswitch_mode_set = mlx5_devlink_eswitch_mode_set, 308 .eswitch_mode_get = mlx5_devlink_eswitch_mode_get, 309 .eswitch_inline_mode_set = mlx5_devlink_eswitch_inline_mode_set, 310 .eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get, 311 .eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set, 312 .eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get, 313 .port_function_hw_addr_get = mlx5_devlink_port_function_hw_addr_get, 314 .port_function_hw_addr_set = mlx5_devlink_port_function_hw_addr_set, 315 .rate_leaf_tx_share_set = mlx5_esw_devlink_rate_leaf_tx_share_set, 316 .rate_leaf_tx_max_set = mlx5_esw_devlink_rate_leaf_tx_max_set, 317 .rate_node_tx_share_set = mlx5_esw_devlink_rate_node_tx_share_set, 318 .rate_node_tx_max_set = mlx5_esw_devlink_rate_node_tx_max_set, 319 .rate_node_new = mlx5_esw_devlink_rate_node_new, 320 .rate_node_del = mlx5_esw_devlink_rate_node_del, 321 .rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set, 322 .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, 323 .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, 324 .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get, 325 .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set, 326 #endif 327 #ifdef CONFIG_MLX5_SF_MANAGER 328 .port_new = mlx5_devlink_sf_port_new, 329 .port_del = mlx5_devlink_sf_port_del, 330 .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get, 331 .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set, 332 #endif 333 .flash_update = mlx5_devlink_flash_update, 334 .info_get = mlx5_devlink_info_get, 335 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 336 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 337 .reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET), 338 .reload_down = mlx5_devlink_reload_down, 339 .reload_up = mlx5_devlink_reload_up, 340 .trap_init = mlx5_devlink_trap_init, 341 .trap_fini = mlx5_devlink_trap_fini, 342 .trap_action_set = mlx5_devlink_trap_action_set, 343 }; 344 345 void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb, 346 struct devlink_port *dl_port) 347 { 348 struct devlink *devlink = priv_to_devlink(dev); 349 struct mlx5_devlink_trap *dl_trap; 350 351 dl_trap = mlx5_find_trap_by_id(dev, trap_id); 352 if (!dl_trap) { 353 mlx5_core_err(dev, "Devlink trap: Report on invalid trap id 0x%x", trap_id); 354 return; 355 } 356 357 if (dl_trap->trap.action != DEVLINK_TRAP_ACTION_TRAP) { 358 mlx5_core_dbg(dev, "Devlink trap: Trap id %d has action %d", trap_id, 359 dl_trap->trap.action); 360 return; 361 } 362 devlink_trap_report(devlink, skb, dl_trap->item, dl_port, NULL); 363 } 364 365 int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev) 366 { 367 struct mlx5_devlink_trap *dl_trap; 368 int count = 0; 369 370 list_for_each_entry(dl_trap, &dev->priv.traps, list) 371 if (dl_trap->trap.action == DEVLINK_TRAP_ACTION_TRAP) 372 count++; 373 374 return count; 375 } 376 377 int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id, 378 enum devlink_trap_action *action) 379 { 380 struct mlx5_devlink_trap *dl_trap; 381 382 dl_trap = mlx5_find_trap_by_id(dev, trap_id); 383 if (!dl_trap) { 384 mlx5_core_err(dev, "Devlink trap: Get action on invalid trap id 0x%x", 385 trap_id); 386 return -EINVAL; 387 } 388 389 *action = dl_trap->trap.action; 390 return 0; 391 } 392 393 struct devlink *mlx5_devlink_alloc(struct device *dev) 394 { 395 return devlink_alloc(&mlx5_devlink_ops, sizeof(struct mlx5_core_dev), 396 dev); 397 } 398 399 void mlx5_devlink_free(struct devlink *devlink) 400 { 401 devlink_free(devlink); 402 } 403 404 static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 405 union devlink_param_value val, 406 struct netlink_ext_ack *extack) 407 { 408 struct mlx5_core_dev *dev = devlink_priv(devlink); 409 bool new_state = val.vbool; 410 411 if (new_state && !MLX5_CAP_GEN(dev, roce) && 412 !(MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce))) { 413 NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE"); 414 return -EOPNOTSUPP; 415 } 416 if (mlx5_core_is_mp_slave(dev) || mlx5_lag_is_active(dev)) { 417 NL_SET_ERR_MSG_MOD(extack, "Multi port slave/Lag device can't configure RoCE"); 418 return -EOPNOTSUPP; 419 } 420 421 return 0; 422 } 423 424 #ifdef CONFIG_MLX5_ESWITCH 425 static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id, 426 union devlink_param_value val, 427 struct netlink_ext_ack *extack) 428 { 429 int group_num = val.vu32; 430 431 if (group_num < 1 || group_num > 1024) { 432 NL_SET_ERR_MSG_MOD(extack, 433 "Unsupported group number, supported range is 1-1024"); 434 return -EOPNOTSUPP; 435 } 436 437 return 0; 438 } 439 440 #endif 441 442 static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id, 443 union devlink_param_value val, 444 struct netlink_ext_ack *extack) 445 { 446 return (val.vu32 >= 64 && val.vu32 <= 4096) ? 0 : -EINVAL; 447 } 448 449 static const struct devlink_param mlx5_devlink_params[] = { 450 DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 451 NULL, NULL, mlx5_devlink_enable_roce_validate), 452 #ifdef CONFIG_MLX5_ESWITCH 453 DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 454 "fdb_large_groups", DEVLINK_PARAM_TYPE_U32, 455 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 456 NULL, NULL, 457 mlx5_devlink_large_group_num_validate), 458 #endif 459 DEVLINK_PARAM_GENERIC(IO_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 460 NULL, NULL, mlx5_devlink_eq_depth_validate), 461 DEVLINK_PARAM_GENERIC(EVENT_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 462 NULL, NULL, mlx5_devlink_eq_depth_validate), 463 }; 464 465 static void mlx5_devlink_set_params_init_values(struct devlink *devlink) 466 { 467 struct mlx5_core_dev *dev = devlink_priv(devlink); 468 union devlink_param_value value; 469 470 value.vbool = MLX5_CAP_GEN(dev, roce); 471 devl_param_driverinit_value_set(devlink, 472 DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, 473 value); 474 475 #ifdef CONFIG_MLX5_ESWITCH 476 value.vu32 = ESW_OFFLOADS_DEFAULT_NUM_GROUPS; 477 devl_param_driverinit_value_set(devlink, 478 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 479 value); 480 #endif 481 482 value.vu32 = MLX5_COMP_EQ_SIZE; 483 devl_param_driverinit_value_set(devlink, 484 DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE, 485 value); 486 487 value.vu32 = MLX5_NUM_ASYNC_EQE; 488 devl_param_driverinit_value_set(devlink, 489 DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE, 490 value); 491 } 492 493 static const struct devlink_param mlx5_devlink_eth_params[] = { 494 DEVLINK_PARAM_GENERIC(ENABLE_ETH, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 495 NULL, NULL, NULL), 496 }; 497 498 static int mlx5_devlink_eth_params_register(struct devlink *devlink) 499 { 500 struct mlx5_core_dev *dev = devlink_priv(devlink); 501 union devlink_param_value value; 502 int err; 503 504 if (!mlx5_eth_supported(dev)) 505 return 0; 506 507 err = devl_params_register(devlink, mlx5_devlink_eth_params, 508 ARRAY_SIZE(mlx5_devlink_eth_params)); 509 if (err) 510 return err; 511 512 value.vbool = true; 513 devl_param_driverinit_value_set(devlink, 514 DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, 515 value); 516 return 0; 517 } 518 519 static void mlx5_devlink_eth_params_unregister(struct devlink *devlink) 520 { 521 struct mlx5_core_dev *dev = devlink_priv(devlink); 522 523 if (!mlx5_eth_supported(dev)) 524 return; 525 526 devl_params_unregister(devlink, mlx5_devlink_eth_params, 527 ARRAY_SIZE(mlx5_devlink_eth_params)); 528 } 529 530 static int mlx5_devlink_enable_rdma_validate(struct devlink *devlink, u32 id, 531 union devlink_param_value val, 532 struct netlink_ext_ack *extack) 533 { 534 struct mlx5_core_dev *dev = devlink_priv(devlink); 535 bool new_state = val.vbool; 536 537 if (new_state && !mlx5_rdma_supported(dev)) 538 return -EOPNOTSUPP; 539 return 0; 540 } 541 542 static const struct devlink_param mlx5_devlink_rdma_params[] = { 543 DEVLINK_PARAM_GENERIC(ENABLE_RDMA, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 544 NULL, NULL, mlx5_devlink_enable_rdma_validate), 545 }; 546 547 static int mlx5_devlink_rdma_params_register(struct devlink *devlink) 548 { 549 union devlink_param_value value; 550 int err; 551 552 if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND)) 553 return 0; 554 555 err = devl_params_register(devlink, mlx5_devlink_rdma_params, 556 ARRAY_SIZE(mlx5_devlink_rdma_params)); 557 if (err) 558 return err; 559 560 value.vbool = true; 561 devl_param_driverinit_value_set(devlink, 562 DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, 563 value); 564 return 0; 565 } 566 567 static void mlx5_devlink_rdma_params_unregister(struct devlink *devlink) 568 { 569 if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND)) 570 return; 571 572 devl_params_unregister(devlink, mlx5_devlink_rdma_params, 573 ARRAY_SIZE(mlx5_devlink_rdma_params)); 574 } 575 576 static const struct devlink_param mlx5_devlink_vnet_params[] = { 577 DEVLINK_PARAM_GENERIC(ENABLE_VNET, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 578 NULL, NULL, NULL), 579 }; 580 581 static int mlx5_devlink_vnet_params_register(struct devlink *devlink) 582 { 583 struct mlx5_core_dev *dev = devlink_priv(devlink); 584 union devlink_param_value value; 585 int err; 586 587 if (!mlx5_vnet_supported(dev)) 588 return 0; 589 590 err = devl_params_register(devlink, mlx5_devlink_vnet_params, 591 ARRAY_SIZE(mlx5_devlink_vnet_params)); 592 if (err) 593 return err; 594 595 value.vbool = true; 596 devl_param_driverinit_value_set(devlink, 597 DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, 598 value); 599 return 0; 600 } 601 602 static void mlx5_devlink_vnet_params_unregister(struct devlink *devlink) 603 { 604 struct mlx5_core_dev *dev = devlink_priv(devlink); 605 606 if (!mlx5_vnet_supported(dev)) 607 return; 608 609 devl_params_unregister(devlink, mlx5_devlink_vnet_params, 610 ARRAY_SIZE(mlx5_devlink_vnet_params)); 611 } 612 613 static int mlx5_devlink_auxdev_params_register(struct devlink *devlink) 614 { 615 int err; 616 617 err = mlx5_devlink_eth_params_register(devlink); 618 if (err) 619 return err; 620 621 err = mlx5_devlink_rdma_params_register(devlink); 622 if (err) 623 goto rdma_err; 624 625 err = mlx5_devlink_vnet_params_register(devlink); 626 if (err) 627 goto vnet_err; 628 return 0; 629 630 vnet_err: 631 mlx5_devlink_rdma_params_unregister(devlink); 632 rdma_err: 633 mlx5_devlink_eth_params_unregister(devlink); 634 return err; 635 } 636 637 static void mlx5_devlink_auxdev_params_unregister(struct devlink *devlink) 638 { 639 mlx5_devlink_vnet_params_unregister(devlink); 640 mlx5_devlink_rdma_params_unregister(devlink); 641 mlx5_devlink_eth_params_unregister(devlink); 642 } 643 644 static int mlx5_devlink_max_uc_list_validate(struct devlink *devlink, u32 id, 645 union devlink_param_value val, 646 struct netlink_ext_ack *extack) 647 { 648 struct mlx5_core_dev *dev = devlink_priv(devlink); 649 650 if (val.vu32 == 0) { 651 NL_SET_ERR_MSG_MOD(extack, "max_macs value must be greater than 0"); 652 return -EINVAL; 653 } 654 655 if (!is_power_of_2(val.vu32)) { 656 NL_SET_ERR_MSG_MOD(extack, "Only power of 2 values are supported for max_macs"); 657 return -EINVAL; 658 } 659 660 if (ilog2(val.vu32) > 661 MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list)) { 662 NL_SET_ERR_MSG_MOD(extack, "max_macs value is out of the supported range"); 663 return -EINVAL; 664 } 665 666 return 0; 667 } 668 669 static const struct devlink_param mlx5_devlink_max_uc_list_params[] = { 670 DEVLINK_PARAM_GENERIC(MAX_MACS, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 671 NULL, NULL, mlx5_devlink_max_uc_list_validate), 672 }; 673 674 static int mlx5_devlink_max_uc_list_params_register(struct devlink *devlink) 675 { 676 struct mlx5_core_dev *dev = devlink_priv(devlink); 677 union devlink_param_value value; 678 int err; 679 680 if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported)) 681 return 0; 682 683 err = devl_params_register(devlink, mlx5_devlink_max_uc_list_params, 684 ARRAY_SIZE(mlx5_devlink_max_uc_list_params)); 685 if (err) 686 return err; 687 688 value.vu32 = 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list); 689 devl_param_driverinit_value_set(devlink, 690 DEVLINK_PARAM_GENERIC_ID_MAX_MACS, 691 value); 692 return 0; 693 } 694 695 static void 696 mlx5_devlink_max_uc_list_params_unregister(struct devlink *devlink) 697 { 698 struct mlx5_core_dev *dev = devlink_priv(devlink); 699 700 if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported)) 701 return; 702 703 devl_params_unregister(devlink, mlx5_devlink_max_uc_list_params, 704 ARRAY_SIZE(mlx5_devlink_max_uc_list_params)); 705 } 706 707 #define MLX5_TRAP_DROP(_id, _group_id) \ 708 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ 709 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 710 DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) 711 712 static const struct devlink_trap mlx5_traps_arr[] = { 713 MLX5_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS), 714 MLX5_TRAP_DROP(DMAC_FILTER, L2_DROPS), 715 }; 716 717 static const struct devlink_trap_group mlx5_trap_groups_arr[] = { 718 DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0), 719 }; 720 721 int mlx5_devlink_traps_register(struct devlink *devlink) 722 { 723 struct mlx5_core_dev *core_dev = devlink_priv(devlink); 724 int err; 725 726 err = devl_trap_groups_register(devlink, mlx5_trap_groups_arr, 727 ARRAY_SIZE(mlx5_trap_groups_arr)); 728 if (err) 729 return err; 730 731 err = devl_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr), 732 &core_dev->priv); 733 if (err) 734 goto err_trap_group; 735 return 0; 736 737 err_trap_group: 738 devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr, 739 ARRAY_SIZE(mlx5_trap_groups_arr)); 740 return err; 741 } 742 743 void mlx5_devlink_traps_unregister(struct devlink *devlink) 744 { 745 devl_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr)); 746 devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr, 747 ARRAY_SIZE(mlx5_trap_groups_arr)); 748 } 749 750 int mlx5_devlink_params_register(struct devlink *devlink) 751 { 752 int err; 753 754 err = devl_params_register(devlink, mlx5_devlink_params, 755 ARRAY_SIZE(mlx5_devlink_params)); 756 if (err) 757 return err; 758 759 mlx5_devlink_set_params_init_values(devlink); 760 761 err = mlx5_devlink_auxdev_params_register(devlink); 762 if (err) 763 goto auxdev_reg_err; 764 765 err = mlx5_devlink_max_uc_list_params_register(devlink); 766 if (err) 767 goto max_uc_list_err; 768 769 return 0; 770 771 max_uc_list_err: 772 mlx5_devlink_auxdev_params_unregister(devlink); 773 auxdev_reg_err: 774 devl_params_unregister(devlink, mlx5_devlink_params, 775 ARRAY_SIZE(mlx5_devlink_params)); 776 return err; 777 } 778 779 void mlx5_devlink_params_unregister(struct devlink *devlink) 780 { 781 mlx5_devlink_max_uc_list_params_unregister(devlink); 782 mlx5_devlink_auxdev_params_unregister(devlink); 783 devl_params_unregister(devlink, mlx5_devlink_params, 784 ARRAY_SIZE(mlx5_devlink_params)); 785 } 786