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