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