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 "sf/dev/dev.h" 11 #include "sf/sf.h" 12 13 static int mlx5_devlink_flash_update(struct devlink *devlink, 14 struct devlink_flash_update_params *params, 15 struct netlink_ext_ack *extack) 16 { 17 struct mlx5_core_dev *dev = devlink_priv(devlink); 18 19 return mlx5_firmware_flash(dev, params->fw, extack); 20 } 21 22 static u8 mlx5_fw_ver_major(u32 version) 23 { 24 return (version >> 24) & 0xff; 25 } 26 27 static u8 mlx5_fw_ver_minor(u32 version) 28 { 29 return (version >> 16) & 0xff; 30 } 31 32 static u16 mlx5_fw_ver_subminor(u32 version) 33 { 34 return version & 0xffff; 35 } 36 37 #define DEVLINK_FW_STRING_LEN 32 38 39 static int 40 mlx5_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, 41 struct netlink_ext_ack *extack) 42 { 43 struct mlx5_core_dev *dev = devlink_priv(devlink); 44 char version_str[DEVLINK_FW_STRING_LEN]; 45 u32 running_fw, stored_fw; 46 int err; 47 48 err = devlink_info_driver_name_put(req, KBUILD_MODNAME); 49 if (err) 50 return err; 51 52 err = devlink_info_version_fixed_put(req, "fw.psid", dev->board_id); 53 if (err) 54 return err; 55 56 err = mlx5_fw_version_query(dev, &running_fw, &stored_fw); 57 if (err) 58 return err; 59 60 snprintf(version_str, sizeof(version_str), "%d.%d.%04d", 61 mlx5_fw_ver_major(running_fw), mlx5_fw_ver_minor(running_fw), 62 mlx5_fw_ver_subminor(running_fw)); 63 err = devlink_info_version_running_put(req, "fw.version", version_str); 64 if (err) 65 return err; 66 67 /* no pending version, return running (stored) version */ 68 if (stored_fw == 0) 69 stored_fw = running_fw; 70 71 snprintf(version_str, sizeof(version_str), "%d.%d.%04d", 72 mlx5_fw_ver_major(stored_fw), mlx5_fw_ver_minor(stored_fw), 73 mlx5_fw_ver_subminor(stored_fw)); 74 err = devlink_info_version_stored_put(req, "fw.version", version_str); 75 if (err) 76 return err; 77 78 return 0; 79 } 80 81 static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netlink_ext_ack *extack) 82 { 83 struct mlx5_core_dev *dev = devlink_priv(devlink); 84 u8 reset_level, reset_type, net_port_alive; 85 int err; 86 87 err = mlx5_fw_reset_query(dev, &reset_level, &reset_type); 88 if (err) 89 return err; 90 if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL3)) { 91 NL_SET_ERR_MSG_MOD(extack, "FW activate requires reboot"); 92 return -EINVAL; 93 } 94 95 net_port_alive = !!(reset_type & MLX5_MFRL_REG_RESET_TYPE_NET_PORT_ALIVE); 96 err = mlx5_fw_reset_set_reset_sync(dev, net_port_alive); 97 if (err) 98 goto out; 99 100 err = mlx5_fw_reset_wait_reset_done(dev); 101 out: 102 if (err) 103 NL_SET_ERR_MSG_MOD(extack, "FW activate command failed"); 104 return err; 105 } 106 107 static int mlx5_devlink_trigger_fw_live_patch(struct devlink *devlink, 108 struct netlink_ext_ack *extack) 109 { 110 struct mlx5_core_dev *dev = devlink_priv(devlink); 111 u8 reset_level; 112 int err; 113 114 err = mlx5_fw_reset_query(dev, &reset_level, NULL); 115 if (err) 116 return err; 117 if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL0)) { 118 NL_SET_ERR_MSG_MOD(extack, 119 "FW upgrade to the stored FW can't be done by FW live patching"); 120 return -EINVAL; 121 } 122 123 return mlx5_fw_reset_set_live_patch(dev); 124 } 125 126 static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, 127 enum devlink_reload_action action, 128 enum devlink_reload_limit limit, 129 struct netlink_ext_ack *extack) 130 { 131 struct mlx5_core_dev *dev = devlink_priv(devlink); 132 bool sf_dev_allocated; 133 134 sf_dev_allocated = mlx5_sf_dev_allocated(dev); 135 if (sf_dev_allocated) { 136 /* Reload results in deleting SF device which further results in 137 * unregistering devlink instance while holding devlink_mutext. 138 * Hence, do not support reload. 139 */ 140 NL_SET_ERR_MSG_MOD(extack, "reload is unsupported when SFs are allocated\n"); 141 return -EOPNOTSUPP; 142 } 143 144 if (mlx5_lag_is_active(dev)) { 145 NL_SET_ERR_MSG_MOD(extack, "reload is unsupported in Lag mode\n"); 146 return -EOPNOTSUPP; 147 } 148 149 switch (action) { 150 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 151 mlx5_unload_one(dev, false); 152 return 0; 153 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 154 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET) 155 return mlx5_devlink_trigger_fw_live_patch(devlink, extack); 156 return mlx5_devlink_reload_fw_activate(devlink, extack); 157 default: 158 /* Unsupported action should not get to this function */ 159 WARN_ON(1); 160 return -EOPNOTSUPP; 161 } 162 } 163 164 static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action, 165 enum devlink_reload_limit limit, u32 *actions_performed, 166 struct netlink_ext_ack *extack) 167 { 168 struct mlx5_core_dev *dev = devlink_priv(devlink); 169 170 *actions_performed = BIT(action); 171 switch (action) { 172 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 173 return mlx5_load_one(dev, false); 174 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 175 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET) 176 break; 177 /* On fw_activate action, also driver is reloaded and reinit performed */ 178 *actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 179 return mlx5_load_one(dev, false); 180 default: 181 /* Unsupported action should not get to this function */ 182 WARN_ON(1); 183 return -EOPNOTSUPP; 184 } 185 186 return 0; 187 } 188 189 static struct mlx5_devlink_trap *mlx5_find_trap_by_id(struct mlx5_core_dev *dev, int trap_id) 190 { 191 struct mlx5_devlink_trap *dl_trap; 192 193 list_for_each_entry(dl_trap, &dev->priv.traps, list) 194 if (dl_trap->trap.id == trap_id) 195 return dl_trap; 196 197 return NULL; 198 } 199 200 static int mlx5_devlink_trap_init(struct devlink *devlink, const struct devlink_trap *trap, 201 void *trap_ctx) 202 { 203 struct mlx5_core_dev *dev = devlink_priv(devlink); 204 struct mlx5_devlink_trap *dl_trap; 205 206 dl_trap = kzalloc(sizeof(*dl_trap), GFP_KERNEL); 207 if (!dl_trap) 208 return -ENOMEM; 209 210 dl_trap->trap.id = trap->id; 211 dl_trap->trap.action = DEVLINK_TRAP_ACTION_DROP; 212 dl_trap->item = trap_ctx; 213 214 if (mlx5_find_trap_by_id(dev, trap->id)) { 215 kfree(dl_trap); 216 mlx5_core_err(dev, "Devlink trap: Trap 0x%x already found", trap->id); 217 return -EEXIST; 218 } 219 220 list_add_tail(&dl_trap->list, &dev->priv.traps); 221 return 0; 222 } 223 224 static void mlx5_devlink_trap_fini(struct devlink *devlink, const struct devlink_trap *trap, 225 void *trap_ctx) 226 { 227 struct mlx5_core_dev *dev = devlink_priv(devlink); 228 struct mlx5_devlink_trap *dl_trap; 229 230 dl_trap = mlx5_find_trap_by_id(dev, trap->id); 231 if (!dl_trap) { 232 mlx5_core_err(dev, "Devlink trap: Missing trap id 0x%x", trap->id); 233 return; 234 } 235 list_del(&dl_trap->list); 236 kfree(dl_trap); 237 } 238 239 static int mlx5_devlink_trap_action_set(struct devlink *devlink, 240 const struct devlink_trap *trap, 241 enum devlink_trap_action action, 242 struct netlink_ext_ack *extack) 243 { 244 struct mlx5_core_dev *dev = devlink_priv(devlink); 245 enum devlink_trap_action action_orig; 246 struct mlx5_devlink_trap *dl_trap; 247 int err = 0; 248 249 dl_trap = mlx5_find_trap_by_id(dev, trap->id); 250 if (!dl_trap) { 251 mlx5_core_err(dev, "Devlink trap: Set action on invalid trap id 0x%x", trap->id); 252 err = -EINVAL; 253 goto out; 254 } 255 256 if (action != DEVLINK_TRAP_ACTION_DROP && action != DEVLINK_TRAP_ACTION_TRAP) { 257 err = -EOPNOTSUPP; 258 goto out; 259 } 260 261 if (action == dl_trap->trap.action) 262 goto out; 263 264 action_orig = dl_trap->trap.action; 265 dl_trap->trap.action = action; 266 err = mlx5_blocking_notifier_call_chain(dev, MLX5_DRIVER_EVENT_TYPE_TRAP, 267 &dl_trap->trap); 268 if (err) 269 dl_trap->trap.action = action_orig; 270 out: 271 return err; 272 } 273 274 static const struct devlink_ops mlx5_devlink_ops = { 275 #ifdef CONFIG_MLX5_ESWITCH 276 .eswitch_mode_set = mlx5_devlink_eswitch_mode_set, 277 .eswitch_mode_get = mlx5_devlink_eswitch_mode_get, 278 .eswitch_inline_mode_set = mlx5_devlink_eswitch_inline_mode_set, 279 .eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get, 280 .eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set, 281 .eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get, 282 .port_function_hw_addr_get = mlx5_devlink_port_function_hw_addr_get, 283 .port_function_hw_addr_set = mlx5_devlink_port_function_hw_addr_set, 284 #endif 285 #ifdef CONFIG_MLX5_SF_MANAGER 286 .port_new = mlx5_devlink_sf_port_new, 287 .port_del = mlx5_devlink_sf_port_del, 288 .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get, 289 .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set, 290 #endif 291 .flash_update = mlx5_devlink_flash_update, 292 .info_get = mlx5_devlink_info_get, 293 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 294 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 295 .reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET), 296 .reload_down = mlx5_devlink_reload_down, 297 .reload_up = mlx5_devlink_reload_up, 298 .trap_init = mlx5_devlink_trap_init, 299 .trap_fini = mlx5_devlink_trap_fini, 300 .trap_action_set = mlx5_devlink_trap_action_set, 301 }; 302 303 void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb, 304 struct devlink_port *dl_port) 305 { 306 struct devlink *devlink = priv_to_devlink(dev); 307 struct mlx5_devlink_trap *dl_trap; 308 309 dl_trap = mlx5_find_trap_by_id(dev, trap_id); 310 if (!dl_trap) { 311 mlx5_core_err(dev, "Devlink trap: Report on invalid trap id 0x%x", trap_id); 312 return; 313 } 314 315 if (dl_trap->trap.action != DEVLINK_TRAP_ACTION_TRAP) { 316 mlx5_core_dbg(dev, "Devlink trap: Trap id %d has action %d", trap_id, 317 dl_trap->trap.action); 318 return; 319 } 320 devlink_trap_report(devlink, skb, dl_trap->item, dl_port, NULL); 321 } 322 323 int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev) 324 { 325 struct mlx5_devlink_trap *dl_trap; 326 int count = 0; 327 328 list_for_each_entry(dl_trap, &dev->priv.traps, list) 329 if (dl_trap->trap.action == DEVLINK_TRAP_ACTION_TRAP) 330 count++; 331 332 return count; 333 } 334 335 int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id, 336 enum devlink_trap_action *action) 337 { 338 struct mlx5_devlink_trap *dl_trap; 339 340 dl_trap = mlx5_find_trap_by_id(dev, trap_id); 341 if (!dl_trap) { 342 mlx5_core_err(dev, "Devlink trap: Get action on invalid trap id 0x%x", 343 trap_id); 344 return -EINVAL; 345 } 346 347 *action = dl_trap->trap.action; 348 return 0; 349 } 350 351 struct devlink *mlx5_devlink_alloc(void) 352 { 353 return devlink_alloc(&mlx5_devlink_ops, sizeof(struct mlx5_core_dev)); 354 } 355 356 void mlx5_devlink_free(struct devlink *devlink) 357 { 358 devlink_free(devlink); 359 } 360 361 static int mlx5_devlink_fs_mode_validate(struct devlink *devlink, u32 id, 362 union devlink_param_value val, 363 struct netlink_ext_ack *extack) 364 { 365 struct mlx5_core_dev *dev = devlink_priv(devlink); 366 char *value = val.vstr; 367 int err = 0; 368 369 if (!strcmp(value, "dmfs")) { 370 return 0; 371 } else if (!strcmp(value, "smfs")) { 372 u8 eswitch_mode; 373 bool smfs_cap; 374 375 eswitch_mode = mlx5_eswitch_mode(dev); 376 smfs_cap = mlx5_fs_dr_is_supported(dev); 377 378 if (!smfs_cap) { 379 err = -EOPNOTSUPP; 380 NL_SET_ERR_MSG_MOD(extack, 381 "Software managed steering is not supported by current device"); 382 } 383 384 else if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) { 385 NL_SET_ERR_MSG_MOD(extack, 386 "Software managed steering is not supported when eswitch offloads enabled."); 387 err = -EOPNOTSUPP; 388 } 389 } else { 390 NL_SET_ERR_MSG_MOD(extack, 391 "Bad parameter: supported values are [\"dmfs\", \"smfs\"]"); 392 err = -EINVAL; 393 } 394 395 return err; 396 } 397 398 static int mlx5_devlink_fs_mode_set(struct devlink *devlink, u32 id, 399 struct devlink_param_gset_ctx *ctx) 400 { 401 struct mlx5_core_dev *dev = devlink_priv(devlink); 402 enum mlx5_flow_steering_mode mode; 403 404 if (!strcmp(ctx->val.vstr, "smfs")) 405 mode = MLX5_FLOW_STEERING_MODE_SMFS; 406 else 407 mode = MLX5_FLOW_STEERING_MODE_DMFS; 408 dev->priv.steering->mode = mode; 409 410 return 0; 411 } 412 413 static int mlx5_devlink_fs_mode_get(struct devlink *devlink, u32 id, 414 struct devlink_param_gset_ctx *ctx) 415 { 416 struct mlx5_core_dev *dev = devlink_priv(devlink); 417 418 if (dev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_SMFS) 419 strcpy(ctx->val.vstr, "smfs"); 420 else 421 strcpy(ctx->val.vstr, "dmfs"); 422 return 0; 423 } 424 425 static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 426 union devlink_param_value val, 427 struct netlink_ext_ack *extack) 428 { 429 struct mlx5_core_dev *dev = devlink_priv(devlink); 430 bool new_state = val.vbool; 431 432 if (new_state && !MLX5_CAP_GEN(dev, roce)) { 433 NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE"); 434 return -EOPNOTSUPP; 435 } 436 if (mlx5_core_is_mp_slave(dev) || mlx5_lag_is_active(dev)) { 437 NL_SET_ERR_MSG_MOD(extack, "Multi port slave/Lag device can't configure RoCE"); 438 return -EOPNOTSUPP; 439 } 440 441 return 0; 442 } 443 444 #ifdef CONFIG_MLX5_ESWITCH 445 static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id, 446 union devlink_param_value val, 447 struct netlink_ext_ack *extack) 448 { 449 int group_num = val.vu32; 450 451 if (group_num < 1 || group_num > 1024) { 452 NL_SET_ERR_MSG_MOD(extack, 453 "Unsupported group number, supported range is 1-1024"); 454 return -EOPNOTSUPP; 455 } 456 457 return 0; 458 } 459 #endif 460 461 static int mlx5_devlink_enable_remote_dev_reset_set(struct devlink *devlink, u32 id, 462 struct devlink_param_gset_ctx *ctx) 463 { 464 struct mlx5_core_dev *dev = devlink_priv(devlink); 465 466 mlx5_fw_reset_enable_remote_dev_reset_set(dev, ctx->val.vbool); 467 return 0; 468 } 469 470 static int mlx5_devlink_enable_remote_dev_reset_get(struct devlink *devlink, u32 id, 471 struct devlink_param_gset_ctx *ctx) 472 { 473 struct mlx5_core_dev *dev = devlink_priv(devlink); 474 475 ctx->val.vbool = mlx5_fw_reset_enable_remote_dev_reset_get(dev); 476 return 0; 477 } 478 479 static const struct devlink_param mlx5_devlink_params[] = { 480 DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_FLOW_STEERING_MODE, 481 "flow_steering_mode", DEVLINK_PARAM_TYPE_STRING, 482 BIT(DEVLINK_PARAM_CMODE_RUNTIME), 483 mlx5_devlink_fs_mode_get, mlx5_devlink_fs_mode_set, 484 mlx5_devlink_fs_mode_validate), 485 DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 486 NULL, NULL, mlx5_devlink_enable_roce_validate), 487 #ifdef CONFIG_MLX5_ESWITCH 488 DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 489 "fdb_large_groups", DEVLINK_PARAM_TYPE_U32, 490 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 491 NULL, NULL, 492 mlx5_devlink_large_group_num_validate), 493 #endif 494 DEVLINK_PARAM_GENERIC(ENABLE_REMOTE_DEV_RESET, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 495 mlx5_devlink_enable_remote_dev_reset_get, 496 mlx5_devlink_enable_remote_dev_reset_set, NULL), 497 }; 498 499 static void mlx5_devlink_set_params_init_values(struct devlink *devlink) 500 { 501 struct mlx5_core_dev *dev = devlink_priv(devlink); 502 union devlink_param_value value; 503 504 if (dev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_DMFS) 505 strcpy(value.vstr, "dmfs"); 506 else 507 strcpy(value.vstr, "smfs"); 508 devlink_param_driverinit_value_set(devlink, 509 MLX5_DEVLINK_PARAM_ID_FLOW_STEERING_MODE, 510 value); 511 512 value.vbool = MLX5_CAP_GEN(dev, roce); 513 devlink_param_driverinit_value_set(devlink, 514 DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, 515 value); 516 517 #ifdef CONFIG_MLX5_ESWITCH 518 value.vu32 = ESW_OFFLOADS_DEFAULT_NUM_GROUPS; 519 devlink_param_driverinit_value_set(devlink, 520 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 521 value); 522 #endif 523 } 524 525 #define MLX5_TRAP_DROP(_id, _group_id) \ 526 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ 527 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 528 DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) 529 530 static const struct devlink_trap mlx5_traps_arr[] = { 531 MLX5_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS), 532 MLX5_TRAP_DROP(DMAC_FILTER, L2_DROPS), 533 }; 534 535 static const struct devlink_trap_group mlx5_trap_groups_arr[] = { 536 DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0), 537 }; 538 539 static int mlx5_devlink_traps_register(struct devlink *devlink) 540 { 541 struct mlx5_core_dev *core_dev = devlink_priv(devlink); 542 int err; 543 544 err = devlink_trap_groups_register(devlink, mlx5_trap_groups_arr, 545 ARRAY_SIZE(mlx5_trap_groups_arr)); 546 if (err) 547 return err; 548 549 err = devlink_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr), 550 &core_dev->priv); 551 if (err) 552 goto err_trap_group; 553 return 0; 554 555 err_trap_group: 556 devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr, 557 ARRAY_SIZE(mlx5_trap_groups_arr)); 558 return err; 559 } 560 561 static void mlx5_devlink_traps_unregister(struct devlink *devlink) 562 { 563 devlink_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr)); 564 devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr, 565 ARRAY_SIZE(mlx5_trap_groups_arr)); 566 } 567 568 int mlx5_devlink_register(struct devlink *devlink, struct device *dev) 569 { 570 int err; 571 572 err = devlink_register(devlink, dev); 573 if (err) 574 return err; 575 576 err = devlink_params_register(devlink, mlx5_devlink_params, 577 ARRAY_SIZE(mlx5_devlink_params)); 578 if (err) 579 goto params_reg_err; 580 mlx5_devlink_set_params_init_values(devlink); 581 devlink_params_publish(devlink); 582 583 err = mlx5_devlink_traps_register(devlink); 584 if (err) 585 goto traps_reg_err; 586 587 return 0; 588 589 traps_reg_err: 590 devlink_params_unregister(devlink, mlx5_devlink_params, 591 ARRAY_SIZE(mlx5_devlink_params)); 592 params_reg_err: 593 devlink_unregister(devlink); 594 return err; 595 } 596 597 void mlx5_devlink_unregister(struct devlink *devlink) 598 { 599 mlx5_devlink_traps_unregister(devlink); 600 devlink_params_unregister(devlink, mlx5_devlink_params, 601 ARRAY_SIZE(mlx5_devlink_params)); 602 devlink_unregister(devlink); 603 } 604