cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

devlink.c (25311B)


      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, extack);
    104	if (err)
    105		return err;
    106
    107	return mlx5_fw_reset_wait_reset_done(dev);
    108}
    109
    110static int mlx5_devlink_trigger_fw_live_patch(struct devlink *devlink,
    111					      struct netlink_ext_ack *extack)
    112{
    113	struct mlx5_core_dev *dev = devlink_priv(devlink);
    114	u8 reset_level;
    115	int err;
    116
    117	err = mlx5_fw_reset_query(dev, &reset_level, NULL);
    118	if (err)
    119		return err;
    120	if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL0)) {
    121		NL_SET_ERR_MSG_MOD(extack,
    122				   "FW upgrade to the stored FW can't be done by FW live patching");
    123		return -EINVAL;
    124	}
    125
    126	return mlx5_fw_reset_set_live_patch(dev);
    127}
    128
    129static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
    130				    enum devlink_reload_action action,
    131				    enum devlink_reload_limit limit,
    132				    struct netlink_ext_ack *extack)
    133{
    134	struct mlx5_core_dev *dev = devlink_priv(devlink);
    135	struct pci_dev *pdev = dev->pdev;
    136	bool sf_dev_allocated;
    137
    138	sf_dev_allocated = mlx5_sf_dev_allocated(dev);
    139	if (sf_dev_allocated) {
    140		/* Reload results in deleting SF device which further results in
    141		 * unregistering devlink instance while holding devlink_mutext.
    142		 * Hence, do not support reload.
    143		 */
    144		NL_SET_ERR_MSG_MOD(extack, "reload is unsupported when SFs are allocated");
    145		return -EOPNOTSUPP;
    146	}
    147
    148	if (mlx5_lag_is_active(dev)) {
    149		NL_SET_ERR_MSG_MOD(extack, "reload is unsupported in Lag mode");
    150		return -EOPNOTSUPP;
    151	}
    152
    153	if (pci_num_vf(pdev)) {
    154		NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable");
    155	}
    156
    157	switch (action) {
    158	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
    159		mlx5_unload_one(dev);
    160		return 0;
    161	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
    162		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
    163			return mlx5_devlink_trigger_fw_live_patch(devlink, extack);
    164		return mlx5_devlink_reload_fw_activate(devlink, extack);
    165	default:
    166		/* Unsupported action should not get to this function */
    167		WARN_ON(1);
    168		return -EOPNOTSUPP;
    169	}
    170}
    171
    172static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action,
    173				  enum devlink_reload_limit limit, u32 *actions_performed,
    174				  struct netlink_ext_ack *extack)
    175{
    176	struct mlx5_core_dev *dev = devlink_priv(devlink);
    177
    178	*actions_performed = BIT(action);
    179	switch (action) {
    180	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
    181		return mlx5_load_one(dev, false);
    182	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
    183		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
    184			break;
    185		/* On fw_activate action, also driver is reloaded and reinit performed */
    186		*actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
    187		return mlx5_load_one(dev, false);
    188	default:
    189		/* Unsupported action should not get to this function */
    190		WARN_ON(1);
    191		return -EOPNOTSUPP;
    192	}
    193
    194	return 0;
    195}
    196
    197static struct mlx5_devlink_trap *mlx5_find_trap_by_id(struct mlx5_core_dev *dev, int trap_id)
    198{
    199	struct mlx5_devlink_trap *dl_trap;
    200
    201	list_for_each_entry(dl_trap, &dev->priv.traps, list)
    202		if (dl_trap->trap.id == trap_id)
    203			return dl_trap;
    204
    205	return NULL;
    206}
    207
    208static int mlx5_devlink_trap_init(struct devlink *devlink, const struct devlink_trap *trap,
    209				  void *trap_ctx)
    210{
    211	struct mlx5_core_dev *dev = devlink_priv(devlink);
    212	struct mlx5_devlink_trap *dl_trap;
    213
    214	dl_trap = kzalloc(sizeof(*dl_trap), GFP_KERNEL);
    215	if (!dl_trap)
    216		return -ENOMEM;
    217
    218	dl_trap->trap.id = trap->id;
    219	dl_trap->trap.action = DEVLINK_TRAP_ACTION_DROP;
    220	dl_trap->item = trap_ctx;
    221
    222	if (mlx5_find_trap_by_id(dev, trap->id)) {
    223		kfree(dl_trap);
    224		mlx5_core_err(dev, "Devlink trap: Trap 0x%x already found", trap->id);
    225		return -EEXIST;
    226	}
    227
    228	list_add_tail(&dl_trap->list, &dev->priv.traps);
    229	return 0;
    230}
    231
    232static void mlx5_devlink_trap_fini(struct devlink *devlink, const struct devlink_trap *trap,
    233				   void *trap_ctx)
    234{
    235	struct mlx5_core_dev *dev = devlink_priv(devlink);
    236	struct mlx5_devlink_trap *dl_trap;
    237
    238	dl_trap = mlx5_find_trap_by_id(dev, trap->id);
    239	if (!dl_trap) {
    240		mlx5_core_err(dev, "Devlink trap: Missing trap id 0x%x", trap->id);
    241		return;
    242	}
    243	list_del(&dl_trap->list);
    244	kfree(dl_trap);
    245}
    246
    247static int mlx5_devlink_trap_action_set(struct devlink *devlink,
    248					const struct devlink_trap *trap,
    249					enum devlink_trap_action action,
    250					struct netlink_ext_ack *extack)
    251{
    252	struct mlx5_core_dev *dev = devlink_priv(devlink);
    253	enum devlink_trap_action action_orig;
    254	struct mlx5_devlink_trap *dl_trap;
    255	int err = 0;
    256
    257	if (is_mdev_switchdev_mode(dev)) {
    258		NL_SET_ERR_MSG_MOD(extack, "Devlink traps can't be set in switchdev mode");
    259		return -EOPNOTSUPP;
    260	}
    261
    262	dl_trap = mlx5_find_trap_by_id(dev, trap->id);
    263	if (!dl_trap) {
    264		mlx5_core_err(dev, "Devlink trap: Set action on invalid trap id 0x%x", trap->id);
    265		err = -EINVAL;
    266		goto out;
    267	}
    268
    269	if (action != DEVLINK_TRAP_ACTION_DROP && action != DEVLINK_TRAP_ACTION_TRAP) {
    270		err = -EOPNOTSUPP;
    271		goto out;
    272	}
    273
    274	if (action == dl_trap->trap.action)
    275		goto out;
    276
    277	action_orig = dl_trap->trap.action;
    278	dl_trap->trap.action = action;
    279	err = mlx5_blocking_notifier_call_chain(dev, MLX5_DRIVER_EVENT_TYPE_TRAP,
    280						&dl_trap->trap);
    281	if (err)
    282		dl_trap->trap.action = action_orig;
    283out:
    284	return err;
    285}
    286
    287static const struct devlink_ops mlx5_devlink_ops = {
    288#ifdef CONFIG_MLX5_ESWITCH
    289	.eswitch_mode_set = mlx5_devlink_eswitch_mode_set,
    290	.eswitch_mode_get = mlx5_devlink_eswitch_mode_get,
    291	.eswitch_inline_mode_set = mlx5_devlink_eswitch_inline_mode_set,
    292	.eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get,
    293	.eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set,
    294	.eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get,
    295	.port_function_hw_addr_get = mlx5_devlink_port_function_hw_addr_get,
    296	.port_function_hw_addr_set = mlx5_devlink_port_function_hw_addr_set,
    297	.rate_leaf_tx_share_set = mlx5_esw_devlink_rate_leaf_tx_share_set,
    298	.rate_leaf_tx_max_set = mlx5_esw_devlink_rate_leaf_tx_max_set,
    299	.rate_node_tx_share_set = mlx5_esw_devlink_rate_node_tx_share_set,
    300	.rate_node_tx_max_set = mlx5_esw_devlink_rate_node_tx_max_set,
    301	.rate_node_new = mlx5_esw_devlink_rate_node_new,
    302	.rate_node_del = mlx5_esw_devlink_rate_node_del,
    303	.rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set,
    304#endif
    305#ifdef CONFIG_MLX5_SF_MANAGER
    306	.port_new = mlx5_devlink_sf_port_new,
    307	.port_del = mlx5_devlink_sf_port_del,
    308	.port_fn_state_get = mlx5_devlink_sf_port_fn_state_get,
    309	.port_fn_state_set = mlx5_devlink_sf_port_fn_state_set,
    310#endif
    311	.flash_update = mlx5_devlink_flash_update,
    312	.info_get = mlx5_devlink_info_get,
    313	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
    314			  BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
    315	.reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET),
    316	.reload_down = mlx5_devlink_reload_down,
    317	.reload_up = mlx5_devlink_reload_up,
    318	.trap_init = mlx5_devlink_trap_init,
    319	.trap_fini = mlx5_devlink_trap_fini,
    320	.trap_action_set = mlx5_devlink_trap_action_set,
    321};
    322
    323void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb,
    324			      struct devlink_port *dl_port)
    325{
    326	struct devlink *devlink = priv_to_devlink(dev);
    327	struct mlx5_devlink_trap *dl_trap;
    328
    329	dl_trap = mlx5_find_trap_by_id(dev, trap_id);
    330	if (!dl_trap) {
    331		mlx5_core_err(dev, "Devlink trap: Report on invalid trap id 0x%x", trap_id);
    332		return;
    333	}
    334
    335	if (dl_trap->trap.action != DEVLINK_TRAP_ACTION_TRAP) {
    336		mlx5_core_dbg(dev, "Devlink trap: Trap id %d has action %d", trap_id,
    337			      dl_trap->trap.action);
    338		return;
    339	}
    340	devlink_trap_report(devlink, skb, dl_trap->item, dl_port, NULL);
    341}
    342
    343int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev)
    344{
    345	struct mlx5_devlink_trap *dl_trap;
    346	int count = 0;
    347
    348	list_for_each_entry(dl_trap, &dev->priv.traps, list)
    349		if (dl_trap->trap.action == DEVLINK_TRAP_ACTION_TRAP)
    350			count++;
    351
    352	return count;
    353}
    354
    355int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id,
    356				  enum devlink_trap_action *action)
    357{
    358	struct mlx5_devlink_trap *dl_trap;
    359
    360	dl_trap = mlx5_find_trap_by_id(dev, trap_id);
    361	if (!dl_trap) {
    362		mlx5_core_err(dev, "Devlink trap: Get action on invalid trap id 0x%x",
    363			      trap_id);
    364		return -EINVAL;
    365	}
    366
    367	*action = dl_trap->trap.action;
    368	return 0;
    369}
    370
    371struct devlink *mlx5_devlink_alloc(struct device *dev)
    372{
    373	return devlink_alloc(&mlx5_devlink_ops, sizeof(struct mlx5_core_dev),
    374			     dev);
    375}
    376
    377void mlx5_devlink_free(struct devlink *devlink)
    378{
    379	devlink_free(devlink);
    380}
    381
    382static int mlx5_devlink_fs_mode_validate(struct devlink *devlink, u32 id,
    383					 union devlink_param_value val,
    384					 struct netlink_ext_ack *extack)
    385{
    386	struct mlx5_core_dev *dev = devlink_priv(devlink);
    387	char *value = val.vstr;
    388	int err = 0;
    389
    390	if (!strcmp(value, "dmfs")) {
    391		return 0;
    392	} else if (!strcmp(value, "smfs")) {
    393		u8 eswitch_mode;
    394		bool smfs_cap;
    395
    396		eswitch_mode = mlx5_eswitch_mode(dev);
    397		smfs_cap = mlx5_fs_dr_is_supported(dev);
    398
    399		if (!smfs_cap) {
    400			err = -EOPNOTSUPP;
    401			NL_SET_ERR_MSG_MOD(extack,
    402					   "Software managed steering is not supported by current device");
    403		}
    404
    405		else if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) {
    406			NL_SET_ERR_MSG_MOD(extack,
    407					   "Software managed steering is not supported when eswitch offloads enabled.");
    408			err = -EOPNOTSUPP;
    409		}
    410	} else {
    411		NL_SET_ERR_MSG_MOD(extack,
    412				   "Bad parameter: supported values are [\"dmfs\", \"smfs\"]");
    413		err = -EINVAL;
    414	}
    415
    416	return err;
    417}
    418
    419static int mlx5_devlink_fs_mode_set(struct devlink *devlink, u32 id,
    420				    struct devlink_param_gset_ctx *ctx)
    421{
    422	struct mlx5_core_dev *dev = devlink_priv(devlink);
    423	enum mlx5_flow_steering_mode mode;
    424
    425	if (!strcmp(ctx->val.vstr, "smfs"))
    426		mode = MLX5_FLOW_STEERING_MODE_SMFS;
    427	else
    428		mode = MLX5_FLOW_STEERING_MODE_DMFS;
    429	dev->priv.steering->mode = mode;
    430
    431	return 0;
    432}
    433
    434static int mlx5_devlink_fs_mode_get(struct devlink *devlink, u32 id,
    435				    struct devlink_param_gset_ctx *ctx)
    436{
    437	struct mlx5_core_dev *dev = devlink_priv(devlink);
    438
    439	if (dev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_SMFS)
    440		strcpy(ctx->val.vstr, "smfs");
    441	else
    442		strcpy(ctx->val.vstr, "dmfs");
    443	return 0;
    444}
    445
    446static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
    447					     union devlink_param_value val,
    448					     struct netlink_ext_ack *extack)
    449{
    450	struct mlx5_core_dev *dev = devlink_priv(devlink);
    451	bool new_state = val.vbool;
    452
    453	if (new_state && !MLX5_CAP_GEN(dev, roce) &&
    454	    !MLX5_CAP_GEN(dev, roce_rw_supported)) {
    455		NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE");
    456		return -EOPNOTSUPP;
    457	}
    458	if (mlx5_core_is_mp_slave(dev) || mlx5_lag_is_active(dev)) {
    459		NL_SET_ERR_MSG_MOD(extack, "Multi port slave/Lag device can't configure RoCE");
    460		return -EOPNOTSUPP;
    461	}
    462
    463	return 0;
    464}
    465
    466#ifdef CONFIG_MLX5_ESWITCH
    467static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id,
    468						 union devlink_param_value val,
    469						 struct netlink_ext_ack *extack)
    470{
    471	int group_num = val.vu32;
    472
    473	if (group_num < 1 || group_num > 1024) {
    474		NL_SET_ERR_MSG_MOD(extack,
    475				   "Unsupported group number, supported range is 1-1024");
    476		return -EOPNOTSUPP;
    477	}
    478
    479	return 0;
    480}
    481
    482static int mlx5_devlink_esw_port_metadata_set(struct devlink *devlink, u32 id,
    483					      struct devlink_param_gset_ctx *ctx)
    484{
    485	struct mlx5_core_dev *dev = devlink_priv(devlink);
    486
    487	if (!MLX5_ESWITCH_MANAGER(dev))
    488		return -EOPNOTSUPP;
    489
    490	return mlx5_esw_offloads_vport_metadata_set(dev->priv.eswitch, ctx->val.vbool);
    491}
    492
    493static int mlx5_devlink_esw_port_metadata_get(struct devlink *devlink, u32 id,
    494					      struct devlink_param_gset_ctx *ctx)
    495{
    496	struct mlx5_core_dev *dev = devlink_priv(devlink);
    497
    498	if (!MLX5_ESWITCH_MANAGER(dev))
    499		return -EOPNOTSUPP;
    500
    501	ctx->val.vbool = mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch);
    502	return 0;
    503}
    504
    505static int mlx5_devlink_esw_port_metadata_validate(struct devlink *devlink, u32 id,
    506						   union devlink_param_value val,
    507						   struct netlink_ext_ack *extack)
    508{
    509	struct mlx5_core_dev *dev = devlink_priv(devlink);
    510	u8 esw_mode;
    511
    512	if (!MLX5_ESWITCH_MANAGER(dev)) {
    513		NL_SET_ERR_MSG_MOD(extack, "E-Switch is unsupported");
    514		return -EOPNOTSUPP;
    515	}
    516	esw_mode = mlx5_eswitch_mode(dev);
    517	if (esw_mode == MLX5_ESWITCH_OFFLOADS) {
    518		NL_SET_ERR_MSG_MOD(extack,
    519				   "E-Switch must either disabled or non switchdev mode");
    520		return -EBUSY;
    521	}
    522	return 0;
    523}
    524
    525#endif
    526
    527static int mlx5_devlink_enable_remote_dev_reset_set(struct devlink *devlink, u32 id,
    528						    struct devlink_param_gset_ctx *ctx)
    529{
    530	struct mlx5_core_dev *dev = devlink_priv(devlink);
    531
    532	mlx5_fw_reset_enable_remote_dev_reset_set(dev, ctx->val.vbool);
    533	return 0;
    534}
    535
    536static int mlx5_devlink_enable_remote_dev_reset_get(struct devlink *devlink, u32 id,
    537						    struct devlink_param_gset_ctx *ctx)
    538{
    539	struct mlx5_core_dev *dev = devlink_priv(devlink);
    540
    541	ctx->val.vbool = mlx5_fw_reset_enable_remote_dev_reset_get(dev);
    542	return 0;
    543}
    544
    545static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id,
    546					  union devlink_param_value val,
    547					  struct netlink_ext_ack *extack)
    548{
    549	return (val.vu16 >= 64 && val.vu16 <= 4096) ? 0 : -EINVAL;
    550}
    551
    552static const struct devlink_param mlx5_devlink_params[] = {
    553	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_FLOW_STEERING_MODE,
    554			     "flow_steering_mode", DEVLINK_PARAM_TYPE_STRING,
    555			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
    556			     mlx5_devlink_fs_mode_get, mlx5_devlink_fs_mode_set,
    557			     mlx5_devlink_fs_mode_validate),
    558	DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
    559			      NULL, NULL, mlx5_devlink_enable_roce_validate),
    560#ifdef CONFIG_MLX5_ESWITCH
    561	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
    562			     "fdb_large_groups", DEVLINK_PARAM_TYPE_U32,
    563			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
    564			     NULL, NULL,
    565			     mlx5_devlink_large_group_num_validate),
    566	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_PORT_METADATA,
    567			     "esw_port_metadata", DEVLINK_PARAM_TYPE_BOOL,
    568			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
    569			     mlx5_devlink_esw_port_metadata_get,
    570			     mlx5_devlink_esw_port_metadata_set,
    571			     mlx5_devlink_esw_port_metadata_validate),
    572#endif
    573	DEVLINK_PARAM_GENERIC(ENABLE_REMOTE_DEV_RESET, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
    574			      mlx5_devlink_enable_remote_dev_reset_get,
    575			      mlx5_devlink_enable_remote_dev_reset_set, NULL),
    576	DEVLINK_PARAM_GENERIC(IO_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
    577			      NULL, NULL, mlx5_devlink_eq_depth_validate),
    578	DEVLINK_PARAM_GENERIC(EVENT_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
    579			      NULL, NULL, mlx5_devlink_eq_depth_validate),
    580};
    581
    582static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
    583{
    584	struct mlx5_core_dev *dev = devlink_priv(devlink);
    585	union devlink_param_value value;
    586
    587	value.vbool = MLX5_CAP_GEN(dev, roce);
    588	devlink_param_driverinit_value_set(devlink,
    589					   DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
    590					   value);
    591
    592#ifdef CONFIG_MLX5_ESWITCH
    593	value.vu32 = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
    594	devlink_param_driverinit_value_set(devlink,
    595					   MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
    596					   value);
    597#endif
    598
    599	value.vu32 = MLX5_COMP_EQ_SIZE;
    600	devlink_param_driverinit_value_set(devlink,
    601					   DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE,
    602					   value);
    603
    604	value.vu32 = MLX5_NUM_ASYNC_EQE;
    605	devlink_param_driverinit_value_set(devlink,
    606					   DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE,
    607					   value);
    608}
    609
    610static const struct devlink_param enable_eth_param =
    611	DEVLINK_PARAM_GENERIC(ENABLE_ETH, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
    612			      NULL, NULL, NULL);
    613
    614static int mlx5_devlink_eth_param_register(struct devlink *devlink)
    615{
    616	struct mlx5_core_dev *dev = devlink_priv(devlink);
    617	union devlink_param_value value;
    618	int err;
    619
    620	if (!mlx5_eth_supported(dev))
    621		return 0;
    622
    623	err = devlink_param_register(devlink, &enable_eth_param);
    624	if (err)
    625		return err;
    626
    627	value.vbool = true;
    628	devlink_param_driverinit_value_set(devlink,
    629					   DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
    630					   value);
    631	return 0;
    632}
    633
    634static void mlx5_devlink_eth_param_unregister(struct devlink *devlink)
    635{
    636	struct mlx5_core_dev *dev = devlink_priv(devlink);
    637
    638	if (!mlx5_eth_supported(dev))
    639		return;
    640
    641	devlink_param_unregister(devlink, &enable_eth_param);
    642}
    643
    644static int mlx5_devlink_enable_rdma_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	bool new_state = val.vbool;
    650
    651	if (new_state && !mlx5_rdma_supported(dev))
    652		return -EOPNOTSUPP;
    653	return 0;
    654}
    655
    656static const struct devlink_param enable_rdma_param =
    657	DEVLINK_PARAM_GENERIC(ENABLE_RDMA, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
    658			      NULL, NULL, mlx5_devlink_enable_rdma_validate);
    659
    660static int mlx5_devlink_rdma_param_register(struct devlink *devlink)
    661{
    662	union devlink_param_value value;
    663	int err;
    664
    665	if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND))
    666		return 0;
    667
    668	err = devlink_param_register(devlink, &enable_rdma_param);
    669	if (err)
    670		return err;
    671
    672	value.vbool = true;
    673	devlink_param_driverinit_value_set(devlink,
    674					   DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
    675					   value);
    676	return 0;
    677}
    678
    679static void mlx5_devlink_rdma_param_unregister(struct devlink *devlink)
    680{
    681	if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND))
    682		return;
    683
    684	devlink_param_unregister(devlink, &enable_rdma_param);
    685}
    686
    687static const struct devlink_param enable_vnet_param =
    688	DEVLINK_PARAM_GENERIC(ENABLE_VNET, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
    689			      NULL, NULL, NULL);
    690
    691static int mlx5_devlink_vnet_param_register(struct devlink *devlink)
    692{
    693	struct mlx5_core_dev *dev = devlink_priv(devlink);
    694	union devlink_param_value value;
    695	int err;
    696
    697	if (!mlx5_vnet_supported(dev))
    698		return 0;
    699
    700	err = devlink_param_register(devlink, &enable_vnet_param);
    701	if (err)
    702		return err;
    703
    704	value.vbool = true;
    705	devlink_param_driverinit_value_set(devlink,
    706					   DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
    707					   value);
    708	return 0;
    709}
    710
    711static void mlx5_devlink_vnet_param_unregister(struct devlink *devlink)
    712{
    713	struct mlx5_core_dev *dev = devlink_priv(devlink);
    714
    715	if (!mlx5_vnet_supported(dev))
    716		return;
    717
    718	devlink_param_unregister(devlink, &enable_vnet_param);
    719}
    720
    721static int mlx5_devlink_auxdev_params_register(struct devlink *devlink)
    722{
    723	int err;
    724
    725	err = mlx5_devlink_eth_param_register(devlink);
    726	if (err)
    727		return err;
    728
    729	err = mlx5_devlink_rdma_param_register(devlink);
    730	if (err)
    731		goto rdma_err;
    732
    733	err = mlx5_devlink_vnet_param_register(devlink);
    734	if (err)
    735		goto vnet_err;
    736	return 0;
    737
    738vnet_err:
    739	mlx5_devlink_rdma_param_unregister(devlink);
    740rdma_err:
    741	mlx5_devlink_eth_param_unregister(devlink);
    742	return err;
    743}
    744
    745static void mlx5_devlink_auxdev_params_unregister(struct devlink *devlink)
    746{
    747	mlx5_devlink_vnet_param_unregister(devlink);
    748	mlx5_devlink_rdma_param_unregister(devlink);
    749	mlx5_devlink_eth_param_unregister(devlink);
    750}
    751
    752static int mlx5_devlink_max_uc_list_validate(struct devlink *devlink, u32 id,
    753					     union devlink_param_value val,
    754					     struct netlink_ext_ack *extack)
    755{
    756	struct mlx5_core_dev *dev = devlink_priv(devlink);
    757
    758	if (val.vu32 == 0) {
    759		NL_SET_ERR_MSG_MOD(extack, "max_macs value must be greater than 0");
    760		return -EINVAL;
    761	}
    762
    763	if (!is_power_of_2(val.vu32)) {
    764		NL_SET_ERR_MSG_MOD(extack, "Only power of 2 values are supported for max_macs");
    765		return -EINVAL;
    766	}
    767
    768	if (ilog2(val.vu32) >
    769	    MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list)) {
    770		NL_SET_ERR_MSG_MOD(extack, "max_macs value is out of the supported range");
    771		return -EINVAL;
    772	}
    773
    774	return 0;
    775}
    776
    777static const struct devlink_param max_uc_list_param =
    778	DEVLINK_PARAM_GENERIC(MAX_MACS, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
    779			      NULL, NULL, mlx5_devlink_max_uc_list_validate);
    780
    781static int mlx5_devlink_max_uc_list_param_register(struct devlink *devlink)
    782{
    783	struct mlx5_core_dev *dev = devlink_priv(devlink);
    784	union devlink_param_value value;
    785	int err;
    786
    787	if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported))
    788		return 0;
    789
    790	err = devlink_param_register(devlink, &max_uc_list_param);
    791	if (err)
    792		return err;
    793
    794	value.vu32 = 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list);
    795	devlink_param_driverinit_value_set(devlink,
    796					   DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
    797					   value);
    798	return 0;
    799}
    800
    801static void
    802mlx5_devlink_max_uc_list_param_unregister(struct devlink *devlink)
    803{
    804	struct mlx5_core_dev *dev = devlink_priv(devlink);
    805
    806	if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported))
    807		return;
    808
    809	devlink_param_unregister(devlink, &max_uc_list_param);
    810}
    811
    812#define MLX5_TRAP_DROP(_id, _group_id)					\
    813	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				\
    814			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
    815			     DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT)
    816
    817static const struct devlink_trap mlx5_traps_arr[] = {
    818	MLX5_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
    819	MLX5_TRAP_DROP(DMAC_FILTER, L2_DROPS),
    820};
    821
    822static const struct devlink_trap_group mlx5_trap_groups_arr[] = {
    823	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
    824};
    825
    826static int mlx5_devlink_traps_register(struct devlink *devlink)
    827{
    828	struct mlx5_core_dev *core_dev = devlink_priv(devlink);
    829	int err;
    830
    831	err = devlink_trap_groups_register(devlink, mlx5_trap_groups_arr,
    832					   ARRAY_SIZE(mlx5_trap_groups_arr));
    833	if (err)
    834		return err;
    835
    836	err = devlink_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr),
    837				     &core_dev->priv);
    838	if (err)
    839		goto err_trap_group;
    840	return 0;
    841
    842err_trap_group:
    843	devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
    844				       ARRAY_SIZE(mlx5_trap_groups_arr));
    845	return err;
    846}
    847
    848static void mlx5_devlink_traps_unregister(struct devlink *devlink)
    849{
    850	devlink_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr));
    851	devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
    852				       ARRAY_SIZE(mlx5_trap_groups_arr));
    853}
    854
    855int mlx5_devlink_register(struct devlink *devlink)
    856{
    857	struct mlx5_core_dev *dev = devlink_priv(devlink);
    858	int err;
    859
    860	err = devlink_params_register(devlink, mlx5_devlink_params,
    861				      ARRAY_SIZE(mlx5_devlink_params));
    862	if (err)
    863		return err;
    864
    865	mlx5_devlink_set_params_init_values(devlink);
    866
    867	err = mlx5_devlink_auxdev_params_register(devlink);
    868	if (err)
    869		goto auxdev_reg_err;
    870
    871	err = mlx5_devlink_max_uc_list_param_register(devlink);
    872	if (err)
    873		goto max_uc_list_err;
    874
    875	err = mlx5_devlink_traps_register(devlink);
    876	if (err)
    877		goto traps_reg_err;
    878
    879	if (!mlx5_core_is_mp_slave(dev))
    880		devlink_set_features(devlink, DEVLINK_F_RELOAD);
    881
    882	return 0;
    883
    884traps_reg_err:
    885	mlx5_devlink_max_uc_list_param_unregister(devlink);
    886max_uc_list_err:
    887	mlx5_devlink_auxdev_params_unregister(devlink);
    888auxdev_reg_err:
    889	devlink_params_unregister(devlink, mlx5_devlink_params,
    890				  ARRAY_SIZE(mlx5_devlink_params));
    891	return err;
    892}
    893
    894void mlx5_devlink_unregister(struct devlink *devlink)
    895{
    896	mlx5_devlink_traps_unregister(devlink);
    897	mlx5_devlink_max_uc_list_param_unregister(devlink);
    898	mlx5_devlink_auxdev_params_unregister(devlink);
    899	devlink_params_unregister(devlink, mlx5_devlink_params,
    900				  ARRAY_SIZE(mlx5_devlink_params));
    901}