File Index
Files and directories
Sign in
FILE

devlink.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/devlink.c C
   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#include "lib/nv_param.h"
  14
  15static 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
  24static u8 mlx5_fw_ver_major(u32 version)
  25{
  26	return (version >> 24) & 0xff;
  27}
  28
  29static u8 mlx5_fw_ver_minor(u32 version)
  30{
  31	return (version >> 16) & 0xff;
  32}
  33
  34static u16 mlx5_fw_ver_subminor(u32 version)
  35{
  36	return version & 0xffff;
  37}
  38
  39static int mlx5_devlink_serial_numbers_put(struct mlx5_core_dev *dev,
  40					   struct devlink_info_req *req,
  41					   struct netlink_ext_ack *extack)
  42{
  43	struct pci_dev *pdev = dev->pdev;
  44	unsigned int vpd_size, kw_len;
  45	char *str, *end;
  46	u8 *vpd_data;
  47	int err = 0;
  48	int start;
  49
  50	vpd_data = pci_vpd_alloc(pdev, &vpd_size);
  51	if (IS_ERR(vpd_data))
  52		return 0;
  53
  54	start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
  55					     PCI_VPD_RO_KEYWORD_SERIALNO, &kw_len);
  56	if (start >= 0) {
  57		str = kstrndup(vpd_data + start, kw_len, GFP_KERNEL);
  58		if (!str) {
  59			err = -ENOMEM;
  60			goto end;
  61		}
  62		end = strchrnul(str, ' ');
  63		*end = '\0';
  64		err = devlink_info_board_serial_number_put(req, str);
  65		kfree(str);
  66		if (err)
  67			goto end;
  68	}
  69
  70	start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size, "V3", &kw_len);
  71	if (start >= 0) {
  72		str = kstrndup(vpd_data + start, kw_len, GFP_KERNEL);
  73		if (!str) {
  74			err = -ENOMEM;
  75			goto end;
  76		}
  77		err = devlink_info_serial_number_put(req, str);
  78		kfree(str);
  79		if (err)
  80			goto end;
  81	}
  82
  83end:
  84	kfree(vpd_data);
  85	return err;
  86}
  87
  88#define DEVLINK_FW_STRING_LEN 32
  89
  90static int
  91mlx5_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
  92		      struct netlink_ext_ack *extack)
  93{
  94	struct mlx5_core_dev *dev = devlink_priv(devlink);
  95	char version_str[DEVLINK_FW_STRING_LEN];
  96	u32 running_fw, stored_fw;
  97	int err;
  98
  99	if (!mlx5_core_is_pf(dev))
 100		return 0;
 101
 102	err = mlx5_devlink_serial_numbers_put(dev, req, extack);
 103	if (err)
 104		return err;
 105
 106	err = devlink_info_version_fixed_put(req, "fw.psid", dev->board_id);
 107	if (err)
 108		return err;
 109
 110	mlx5_fw_version_query(dev, &running_fw, &stored_fw);
 111
 112	snprintf(version_str, sizeof(version_str), "%d.%d.%04d",
 113		 mlx5_fw_ver_major(running_fw), mlx5_fw_ver_minor(running_fw),
 114		 mlx5_fw_ver_subminor(running_fw));
 115	err = devlink_info_version_running_put(req, "fw.version", version_str);
 116	if (err)
 117		return err;
 118	err = devlink_info_version_running_put(req,
 119					       DEVLINK_INFO_VERSION_GENERIC_FW,
 120					       version_str);
 121	if (err)
 122		return err;
 123
 124	/* no pending version, return running (stored) version */
 125	if (stored_fw == 0)
 126		stored_fw = running_fw;
 127
 128	snprintf(version_str, sizeof(version_str), "%d.%d.%04d",
 129		 mlx5_fw_ver_major(stored_fw), mlx5_fw_ver_minor(stored_fw),
 130		 mlx5_fw_ver_subminor(stored_fw));
 131	err = devlink_info_version_stored_put(req, "fw.version", version_str);
 132	if (err)
 133		return err;
 134	return devlink_info_version_stored_put(req,
 135					       DEVLINK_INFO_VERSION_GENERIC_FW,
 136					       version_str);
 137}
 138
 139static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netlink_ext_ack *extack)
 140{
 141	struct mlx5_core_dev *dev = devlink_priv(devlink);
 142	u8 reset_level, reset_type, net_port_alive;
 143	int err;
 144
 145	err = mlx5_fw_reset_query(dev, &reset_level, &reset_type);
 146	if (err)
 147		return err;
 148	if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL3)) {
 149		NL_SET_ERR_MSG_MOD(extack, "FW activate requires reboot");
 150		return -EINVAL;
 151	}
 152
 153	net_port_alive = !!(reset_type & MLX5_MFRL_REG_RESET_TYPE_NET_PORT_ALIVE);
 154	err = mlx5_fw_reset_set_reset_sync(dev, net_port_alive, extack);
 155	if (err)
 156		return err;
 157
 158	err = mlx5_fw_reset_wait_reset_done(dev);
 159	if (err)
 160		return err;
 161
 162	mlx5_sync_reset_unload_flow(dev, true);
 163	err = mlx5_health_wait_pci_up(dev);
 164	if (err)
 165		NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset");
 166
 167	return err;
 168}
 169
 170static int mlx5_devlink_trigger_fw_live_patch(struct devlink *devlink,
 171					      struct netlink_ext_ack *extack)
 172{
 173	struct mlx5_core_dev *dev = devlink_priv(devlink);
 174	u8 reset_level;
 175	int err;
 176
 177	err = mlx5_fw_reset_query(dev, &reset_level, NULL);
 178	if (err)
 179		return err;
 180	if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL0)) {
 181		NL_SET_ERR_MSG_MOD(extack,
 182				   "FW upgrade to the stored FW can't be done by FW live patching");
 183		return -EINVAL;
 184	}
 185
 186	return mlx5_fw_reset_set_live_patch(dev);
 187}
 188
 189static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
 190				    enum devlink_reload_action action,
 191				    enum devlink_reload_limit limit,
 192				    struct netlink_ext_ack *extack)
 193{
 194	struct mlx5_core_dev *dev = devlink_priv(devlink);
 195	struct pci_dev *pdev = dev->pdev;
 196	int ret = 0;
 197
 198	if (mlx5_fw_reset_in_progress(dev)) {
 199		NL_SET_ERR_MSG_MOD(extack, "Can't reload during firmware reset");
 200		return -EBUSY;
 201	}
 202
 203	if (mlx5_dev_is_lightweight(dev)) {
 204		if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
 205			return -EOPNOTSUPP;
 206		mlx5_unload_one_light(dev);
 207		return 0;
 208	}
 209
 210	if (mlx5_core_is_mp_slave(dev)) {
 211		NL_SET_ERR_MSG_MOD(extack, "reload is unsupported for multi port slave");
 212		return -EOPNOTSUPP;
 213	}
 214
 215	if (action == DEVLINK_RELOAD_ACTION_FW_ACTIVATE &&
 216	    !dev->priv.fw_reset) {
 217		NL_SET_ERR_MSG_MOD(extack, "FW activate is unsupported for this function");
 218		return -EOPNOTSUPP;
 219	}
 220
 221	if (mlx5_core_is_pf(dev) && pci_num_vf(pdev))
 222		NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable");
 223
 224	switch (action) {
 225	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
 226		mlx5_unload_one_devl_locked(dev, false);
 227		break;
 228	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
 229		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
 230			ret = mlx5_devlink_trigger_fw_live_patch(devlink, extack);
 231		else
 232			ret = mlx5_devlink_reload_fw_activate(devlink, extack);
 233		break;
 234	default:
 235		/* Unsupported action should not get to this function */
 236		WARN_ON(1);
 237		ret = -EOPNOTSUPP;
 238	}
 239
 240	return ret;
 241}
 242
 243static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action,
 244				  enum devlink_reload_limit limit, u32 *actions_performed,
 245				  struct netlink_ext_ack *extack)
 246{
 247	struct mlx5_core_dev *dev = devlink_priv(devlink);
 248	int ret = 0;
 249
 250	*actions_performed = BIT(action);
 251	switch (action) {
 252	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
 253		if (mlx5_dev_is_lightweight(dev)) {
 254			mlx5_fw_reporters_create(dev);
 255			return mlx5_init_one_devl_locked(dev);
 256		}
 257		ret = mlx5_load_one_devl_locked(dev, false);
 258		break;
 259	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
 260		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
 261			break;
 262		/* On fw_activate action, also driver is reloaded and reinit performed */
 263		*actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
 264		ret = mlx5_load_one_devl_locked(dev, true);
 265		if (ret)
 266			return ret;
 267		ret = mlx5_fw_reset_verify_fw_complete(dev, extack);
 268		break;
 269	default:
 270		/* Unsupported action should not get to this function */
 271		WARN_ON(1);
 272		ret = -EOPNOTSUPP;
 273	}
 274
 275	return ret;
 276}
 277
 278static struct mlx5_devlink_trap *mlx5_find_trap_by_id(struct mlx5_core_dev *dev, int trap_id)
 279{
 280	struct mlx5_devlink_trap *dl_trap;
 281
 282	list_for_each_entry(dl_trap, &dev->priv.traps, list)
 283		if (dl_trap->trap.id == trap_id)
 284			return dl_trap;
 285
 286	return NULL;
 287}
 288
 289static int mlx5_devlink_trap_init(struct devlink *devlink, const struct devlink_trap *trap,
 290				  void *trap_ctx)
 291{
 292	struct mlx5_core_dev *dev = devlink_priv(devlink);
 293	struct mlx5_devlink_trap *dl_trap;
 294
 295	dl_trap = kzalloc(sizeof(*dl_trap), GFP_KERNEL);
 296	if (!dl_trap)
 297		return -ENOMEM;
 298
 299	dl_trap->trap.id = trap->id;
 300	dl_trap->trap.action = DEVLINK_TRAP_ACTION_DROP;
 301	dl_trap->item = trap_ctx;
 302
 303	if (mlx5_find_trap_by_id(dev, trap->id)) {
 304		kfree(dl_trap);
 305		mlx5_core_err(dev, "Devlink trap: Trap 0x%x already found", trap->id);
 306		return -EEXIST;
 307	}
 308
 309	list_add_tail(&dl_trap->list, &dev->priv.traps);
 310	return 0;
 311}
 312
 313static void mlx5_devlink_trap_fini(struct devlink *devlink, const struct devlink_trap *trap,
 314				   void *trap_ctx)
 315{
 316	struct mlx5_core_dev *dev = devlink_priv(devlink);
 317	struct mlx5_devlink_trap *dl_trap;
 318
 319	dl_trap = mlx5_find_trap_by_id(dev, trap->id);
 320	if (!dl_trap) {
 321		mlx5_core_err(dev, "Devlink trap: Missing trap id 0x%x", trap->id);
 322		return;
 323	}
 324	list_del(&dl_trap->list);
 325	kfree(dl_trap);
 326}
 327
 328static int mlx5_devlink_trap_action_set(struct devlink *devlink,
 329					const struct devlink_trap *trap,
 330					enum devlink_trap_action action,
 331					struct netlink_ext_ack *extack)
 332{
 333	struct mlx5_core_dev *dev = devlink_priv(devlink);
 334	struct mlx5_devlink_trap_event_ctx trap_event_ctx;
 335	enum devlink_trap_action action_orig;
 336	struct mlx5_devlink_trap *dl_trap;
 337	int err;
 338
 339	if (is_mdev_switchdev_mode(dev)) {
 340		NL_SET_ERR_MSG_MOD(extack, "Devlink traps can't be set in switchdev mode");
 341		return -EOPNOTSUPP;
 342	}
 343
 344	dl_trap = mlx5_find_trap_by_id(dev, trap->id);
 345	if (!dl_trap) {
 346		mlx5_core_err(dev, "Devlink trap: Set action on invalid trap id 0x%x", trap->id);
 347		return -EINVAL;
 348	}
 349
 350	if (action != DEVLINK_TRAP_ACTION_DROP && action != DEVLINK_TRAP_ACTION_TRAP)
 351		return -EOPNOTSUPP;
 352
 353	if (action == dl_trap->trap.action)
 354		return 0;
 355
 356	action_orig = dl_trap->trap.action;
 357	dl_trap->trap.action = action;
 358	trap_event_ctx.trap = &dl_trap->trap;
 359	trap_event_ctx.err = 0;
 360	err = mlx5_blocking_notifier_call_chain(dev, MLX5_DRIVER_EVENT_TYPE_TRAP,
 361						&trap_event_ctx);
 362	if (err == NOTIFY_BAD)
 363		dl_trap->trap.action = action_orig;
 364
 365	return trap_event_ctx.err;
 366}
 367
 368static const struct devlink_ops mlx5_devlink_ops = {
 369#ifdef CONFIG_MLX5_ESWITCH
 370	.eswitch_mode_set = mlx5_devlink_eswitch_mode_set,
 371	.eswitch_mode_get = mlx5_devlink_eswitch_mode_get,
 372	.eswitch_inline_mode_set = mlx5_devlink_eswitch_inline_mode_set,
 373	.eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get,
 374	.eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set,
 375	.eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get,
 376	.rate_leaf_tx_share_set = mlx5_esw_devlink_rate_leaf_tx_share_set,
 377	.rate_leaf_tx_max_set = mlx5_esw_devlink_rate_leaf_tx_max_set,
 378	.rate_leaf_tc_bw_set = mlx5_esw_devlink_rate_leaf_tc_bw_set,
 379	.rate_node_tc_bw_set = mlx5_esw_devlink_rate_node_tc_bw_set,
 380	.rate_node_tx_share_set = mlx5_esw_devlink_rate_node_tx_share_set,
 381	.rate_node_tx_max_set = mlx5_esw_devlink_rate_node_tx_max_set,
 382	.rate_node_new = mlx5_esw_devlink_rate_node_new,
 383	.rate_node_del = mlx5_esw_devlink_rate_node_del,
 384	.rate_leaf_parent_set = mlx5_esw_devlink_rate_leaf_parent_set,
 385	.rate_node_parent_set = mlx5_esw_devlink_rate_node_parent_set,
 386#endif
 387#ifdef CONFIG_MLX5_SF_MANAGER
 388	.port_new = mlx5_devlink_sf_port_new,
 389#endif
 390	.flash_update = mlx5_devlink_flash_update,
 391	.info_get = mlx5_devlink_info_get,
 392	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
 393			  BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
 394	.reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET),
 395	.reload_down = mlx5_devlink_reload_down,
 396	.reload_up = mlx5_devlink_reload_up,
 397	.trap_init = mlx5_devlink_trap_init,
 398	.trap_fini = mlx5_devlink_trap_fini,
 399	.trap_action_set = mlx5_devlink_trap_action_set,
 400};
 401
 402void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb,
 403			      struct devlink_port *dl_port)
 404{
 405	struct devlink *devlink = priv_to_devlink(dev);
 406	struct mlx5_devlink_trap *dl_trap;
 407
 408	dl_trap = mlx5_find_trap_by_id(dev, trap_id);
 409	if (!dl_trap) {
 410		mlx5_core_err(dev, "Devlink trap: Report on invalid trap id 0x%x", trap_id);
 411		return;
 412	}
 413
 414	if (dl_trap->trap.action != DEVLINK_TRAP_ACTION_TRAP) {
 415		mlx5_core_dbg(dev, "Devlink trap: Trap id %d has action %d", trap_id,
 416			      dl_trap->trap.action);
 417		return;
 418	}
 419	devlink_trap_report(devlink, skb, dl_trap->item, dl_port, NULL);
 420}
 421
 422int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev)
 423{
 424	struct mlx5_devlink_trap *dl_trap;
 425	int count = 0;
 426
 427	list_for_each_entry(dl_trap, &dev->priv.traps, list)
 428		if (dl_trap->trap.action == DEVLINK_TRAP_ACTION_TRAP)
 429			count++;
 430
 431	return count;
 432}
 433
 434int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id,
 435				  enum devlink_trap_action *action)
 436{
 437	struct mlx5_devlink_trap *dl_trap;
 438
 439	dl_trap = mlx5_find_trap_by_id(dev, trap_id);
 440	if (!dl_trap) {
 441		mlx5_core_err(dev, "Devlink trap: Get action on invalid trap id 0x%x",
 442			      trap_id);
 443		return -EINVAL;
 444	}
 445
 446	*action = dl_trap->trap.action;
 447	return 0;
 448}
 449
 450struct devlink *mlx5_devlink_alloc(struct device *dev)
 451{
 452	return devlink_alloc(&mlx5_devlink_ops, sizeof(struct mlx5_core_dev),
 453			     dev);
 454}
 455
 456void mlx5_devlink_free(struct devlink *devlink)
 457{
 458	devlink_free(devlink);
 459}
 460
 461static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
 462					     union devlink_param_value val,
 463					     struct netlink_ext_ack *extack)
 464{
 465	struct mlx5_core_dev *dev = devlink_priv(devlink);
 466	bool new_state = val.vbool;
 467
 468	if (new_state && !MLX5_CAP_GEN(dev, roce) &&
 469	    !(MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce))) {
 470		NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE");
 471		return -EOPNOTSUPP;
 472	}
 473	if (mlx5_core_is_mp_slave(dev) || mlx5_lag_is_active(dev)) {
 474		NL_SET_ERR_MSG_MOD(extack, "Multi port slave/Lag device can't configure RoCE");
 475		return -EOPNOTSUPP;
 476	}
 477
 478	return 0;
 479}
 480
 481#ifdef CONFIG_MLX5_ESWITCH
 482static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id,
 483						 union devlink_param_value val,
 484						 struct netlink_ext_ack *extack)
 485{
 486	int group_num = val.vu32;
 487
 488	if (group_num < 1 || group_num > 1024) {
 489		NL_SET_ERR_MSG_MOD(extack,
 490				   "Unsupported group number, supported range is 1-1024");
 491		return -EOPNOTSUPP;
 492	}
 493
 494	return 0;
 495}
 496#endif
 497
 498static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id,
 499					  union devlink_param_value val,
 500					  struct netlink_ext_ack *extack)
 501{
 502	return (val.vu32 >= 64 && val.vu32 <= 4096) ? 0 : -EINVAL;
 503}
 504
 505static int
 506mlx5_devlink_hairpin_num_queues_validate(struct devlink *devlink, u32 id,
 507					 union devlink_param_value val,
 508					 struct netlink_ext_ack *extack)
 509{
 510	return val.vu32 ? 0 : -EINVAL;
 511}
 512
 513static int
 514mlx5_devlink_hairpin_queue_size_validate(struct devlink *devlink, u32 id,
 515					 union devlink_param_value val,
 516					 struct netlink_ext_ack *extack)
 517{
 518	struct mlx5_core_dev *dev = devlink_priv(devlink);
 519	u32 val32 = val.vu32;
 520
 521	if (!is_power_of_2(val32)) {
 522		NL_SET_ERR_MSG_MOD(extack, "Value is not power of two");
 523		return -EINVAL;
 524	}
 525
 526	if (val32 > BIT(MLX5_CAP_GEN(dev, log_max_hairpin_num_packets))) {
 527		NL_SET_ERR_MSG_FMT_MOD(
 528			extack, "Maximum hairpin queue size is %lu",
 529			BIT(MLX5_CAP_GEN(dev, log_max_hairpin_num_packets)));
 530		return -EINVAL;
 531	}
 532
 533	return 0;
 534}
 535
 536static int mlx5_devlink_num_doorbells_validate(struct devlink *devlink, u32 id,
 537					       union devlink_param_value val,
 538					       struct netlink_ext_ack *extack)
 539{
 540	struct mlx5_core_dev *mdev = devlink_priv(devlink);
 541	u32 val32 = val.vu32;
 542	u32 max_num_channels;
 543
 544	max_num_channels = mlx5e_get_max_num_channels(mdev);
 545	if (val32 > max_num_channels) {
 546		NL_SET_ERR_MSG_FMT_MOD(extack,
 547				       "Requested num_doorbells (%u) exceeds max number of channels (%u)",
 548				       val32, max_num_channels);
 549		return -EINVAL;
 550	}
 551
 552	return 0;
 553}
 554
 555static void mlx5_devlink_hairpin_params_init_values(struct devlink *devlink)
 556{
 557	struct mlx5_core_dev *dev = devlink_priv(devlink);
 558	union devlink_param_value value;
 559	u32 link_speed = 0;
 560	u64 link_speed64;
 561
 562	/* set hairpin pair per each 50Gbs share of the link */
 563	mlx5_port_max_linkspeed(dev, &link_speed);
 564	link_speed = max_t(u32, link_speed, 50000);
 565	link_speed64 = link_speed;
 566	do_div(link_speed64, 50000);
 567
 568	value.vu32 = link_speed64;
 569	devl_param_driverinit_value_set(
 570		devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES, value);
 571
 572	value.vu32 =
 573		BIT(min_t(u32, 16 - MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(dev),
 574			  MLX5_CAP_GEN(dev, log_max_hairpin_num_packets)));
 575	devl_param_driverinit_value_set(
 576		devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_QUEUE_SIZE, value);
 577}
 578
 579static const struct devlink_param mlx5_devlink_params[] = {
 580	DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
 581			      NULL, NULL, mlx5_devlink_enable_roce_validate),
 582#ifdef CONFIG_MLX5_ESWITCH
 583	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
 584			     "fdb_large_groups", DEVLINK_PARAM_TYPE_U32,
 585			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
 586			     NULL, NULL,
 587			     mlx5_devlink_large_group_num_validate),
 588#endif
 589	DEVLINK_PARAM_GENERIC(IO_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
 590			      NULL, NULL, mlx5_devlink_eq_depth_validate),
 591	DEVLINK_PARAM_GENERIC(EVENT_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
 592			      NULL, NULL, mlx5_devlink_eq_depth_validate),
 593};
 594
 595static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
 596{
 597	struct mlx5_core_dev *dev = devlink_priv(devlink);
 598	union devlink_param_value value;
 599
 600	value.vbool = MLX5_CAP_GEN(dev, roce) && !mlx5_dev_is_lightweight(dev);
 601	devl_param_driverinit_value_set(devlink,
 602					DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
 603					value);
 604
 605#ifdef CONFIG_MLX5_ESWITCH
 606	value.vu32 = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
 607	devl_param_driverinit_value_set(devlink,
 608					MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
 609					value);
 610#endif
 611
 612	value.vu32 = MLX5_COMP_EQ_SIZE;
 613	devl_param_driverinit_value_set(devlink,
 614					DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE,
 615					value);
 616
 617	value.vu32 = MLX5_NUM_ASYNC_EQE;
 618	devl_param_driverinit_value_set(devlink,
 619					DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE,
 620					value);
 621}
 622
 623static const struct devlink_param mlx5_devlink_eth_params[] = {
 624	DEVLINK_PARAM_GENERIC(ENABLE_ETH, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
 625			      NULL, NULL, NULL),
 626	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES,
 627			     "hairpin_num_queues", DEVLINK_PARAM_TYPE_U32,
 628			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL,
 629			     mlx5_devlink_hairpin_num_queues_validate),
 630	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_HAIRPIN_QUEUE_SIZE,
 631			     "hairpin_queue_size", DEVLINK_PARAM_TYPE_U32,
 632			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL,
 633			     mlx5_devlink_hairpin_queue_size_validate),
 634	DEVLINK_PARAM_GENERIC(NUM_DOORBELLS,
 635			      BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL,
 636			      mlx5_devlink_num_doorbells_validate),
 637};
 638
 639static int mlx5_devlink_eth_params_register(struct devlink *devlink)
 640{
 641	struct mlx5_core_dev *dev = devlink_priv(devlink);
 642	union devlink_param_value value;
 643	int err;
 644
 645	if (!mlx5_eth_supported(dev))
 646		return 0;
 647
 648	err = devl_params_register(devlink, mlx5_devlink_eth_params,
 649				   ARRAY_SIZE(mlx5_devlink_eth_params));
 650	if (err)
 651		return err;
 652
 653	value.vbool = !mlx5_dev_is_lightweight(dev);
 654	devl_param_driverinit_value_set(devlink,
 655					DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
 656					value);
 657
 658	mlx5_devlink_hairpin_params_init_values(devlink);
 659
 660	value.vu32 = MLX5_DEFAULT_NUM_DOORBELLS;
 661	devl_param_driverinit_value_set(devlink,
 662					DEVLINK_PARAM_GENERIC_ID_NUM_DOORBELLS,
 663					value);
 664	return 0;
 665}
 666
 667static void mlx5_devlink_eth_params_unregister(struct devlink *devlink)
 668{
 669	struct mlx5_core_dev *dev = devlink_priv(devlink);
 670
 671	if (!mlx5_eth_supported(dev))
 672		return;
 673
 674	devl_params_unregister(devlink, mlx5_devlink_eth_params,
 675			       ARRAY_SIZE(mlx5_devlink_eth_params));
 676}
 677
 678#define MLX5_PCIE_CONG_THRESH_MAX	10000
 679#define MLX5_PCIE_CONG_THRESH_DEF_LOW	7500
 680#define MLX5_PCIE_CONG_THRESH_DEF_HIGH	9000
 681
 682static int
 683mlx5_devlink_pcie_cong_thresh_validate(struct devlink *devl, u32 id,
 684				       union devlink_param_value val,
 685				       struct netlink_ext_ack *extack)
 686{
 687	if (val.vu16 > MLX5_PCIE_CONG_THRESH_MAX) {
 688		NL_SET_ERR_MSG_FMT_MOD(extack, "Value %u > max supported (%u)",
 689				       val.vu16, MLX5_PCIE_CONG_THRESH_MAX);
 690
 691		return -EINVAL;
 692	}
 693
 694	switch (id) {
 695	case MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW:
 696	case MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH:
 697	case MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW:
 698	case MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH:
 699		break;
 700	default:
 701		return -EOPNOTSUPP;
 702	}
 703
 704	return 0;
 705}
 706
 707static void mlx5_devlink_pcie_cong_init_values(struct devlink *devlink)
 708{
 709	union devlink_param_value value;
 710	u32 id;
 711
 712	value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_LOW;
 713	id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW;
 714	devl_param_driverinit_value_set(devlink, id, value);
 715
 716	value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_HIGH;
 717	id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH;
 718	devl_param_driverinit_value_set(devlink, id, value);
 719
 720	value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_LOW;
 721	id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW;
 722	devl_param_driverinit_value_set(devlink, id, value);
 723
 724	value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_HIGH;
 725	id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH;
 726	devl_param_driverinit_value_set(devlink, id, value);
 727}
 728
 729static const struct devlink_param mlx5_devlink_pcie_cong_params[] = {
 730	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW,
 731			     "pcie_cong_inbound_low", DEVLINK_PARAM_TYPE_U16,
 732			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL,
 733			     mlx5_devlink_pcie_cong_thresh_validate),
 734	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH,
 735			     "pcie_cong_inbound_high", DEVLINK_PARAM_TYPE_U16,
 736			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL,
 737			     mlx5_devlink_pcie_cong_thresh_validate),
 738	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW,
 739			     "pcie_cong_outbound_low", DEVLINK_PARAM_TYPE_U16,
 740			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL,
 741			     mlx5_devlink_pcie_cong_thresh_validate),
 742	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH,
 743			     "pcie_cong_outbound_high", DEVLINK_PARAM_TYPE_U16,
 744			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL,
 745			     mlx5_devlink_pcie_cong_thresh_validate),
 746};
 747
 748static int mlx5_devlink_pcie_cong_params_register(struct devlink *devlink)
 749{
 750	struct mlx5_core_dev *dev = devlink_priv(devlink);
 751	int err;
 752
 753	if (!mlx5_pcie_cong_event_supported(dev))
 754		return 0;
 755
 756	err = devl_params_register(devlink, mlx5_devlink_pcie_cong_params,
 757				   ARRAY_SIZE(mlx5_devlink_pcie_cong_params));
 758	if (err)
 759		return err;
 760
 761	mlx5_devlink_pcie_cong_init_values(devlink);
 762
 763	return 0;
 764}
 765
 766static void mlx5_devlink_pcie_cong_params_unregister(struct devlink *devlink)
 767{
 768	struct mlx5_core_dev *dev = devlink_priv(devlink);
 769
 770	if (!mlx5_pcie_cong_event_supported(dev))
 771		return;
 772
 773	devl_params_unregister(devlink, mlx5_devlink_pcie_cong_params,
 774			       ARRAY_SIZE(mlx5_devlink_pcie_cong_params));
 775}
 776
 777static int mlx5_devlink_enable_rdma_validate(struct devlink *devlink, u32 id,
 778					     union devlink_param_value val,
 779					     struct netlink_ext_ack *extack)
 780{
 781	struct mlx5_core_dev *dev = devlink_priv(devlink);
 782	bool new_state = val.vbool;
 783
 784	if (new_state && !mlx5_rdma_supported(dev))
 785		return -EOPNOTSUPP;
 786	return 0;
 787}
 788
 789static const struct devlink_param mlx5_devlink_rdma_params[] = {
 790	DEVLINK_PARAM_GENERIC(ENABLE_RDMA, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
 791			      NULL, NULL, mlx5_devlink_enable_rdma_validate),
 792};
 793
 794static int mlx5_devlink_rdma_params_register(struct devlink *devlink)
 795{
 796	struct mlx5_core_dev *dev = devlink_priv(devlink);
 797	union devlink_param_value value;
 798	int err;
 799
 800	if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND))
 801		return 0;
 802
 803	err = devl_params_register(devlink, mlx5_devlink_rdma_params,
 804				   ARRAY_SIZE(mlx5_devlink_rdma_params));
 805	if (err)
 806		return err;
 807
 808	value.vbool = !mlx5_dev_is_lightweight(dev);
 809	devl_param_driverinit_value_set(devlink,
 810					DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
 811					value);
 812	return 0;
 813}
 814
 815static void mlx5_devlink_rdma_params_unregister(struct devlink *devlink)
 816{
 817	if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND))
 818		return;
 819
 820	devl_params_unregister(devlink, mlx5_devlink_rdma_params,
 821			       ARRAY_SIZE(mlx5_devlink_rdma_params));
 822}
 823
 824static const struct devlink_param mlx5_devlink_vnet_params[] = {
 825	DEVLINK_PARAM_GENERIC(ENABLE_VNET, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
 826			      NULL, NULL, NULL),
 827};
 828
 829static int mlx5_devlink_vnet_params_register(struct devlink *devlink)
 830{
 831	struct mlx5_core_dev *dev = devlink_priv(devlink);
 832	union devlink_param_value value;
 833	int err;
 834
 835	if (!mlx5_vnet_supported(dev))
 836		return 0;
 837
 838	err = devl_params_register(devlink, mlx5_devlink_vnet_params,
 839				   ARRAY_SIZE(mlx5_devlink_vnet_params));
 840	if (err)
 841		return err;
 842
 843	value.vbool = !mlx5_dev_is_lightweight(dev);
 844	devl_param_driverinit_value_set(devlink,
 845					DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
 846					value);
 847	return 0;
 848}
 849
 850static void mlx5_devlink_vnet_params_unregister(struct devlink *devlink)
 851{
 852	struct mlx5_core_dev *dev = devlink_priv(devlink);
 853
 854	if (!mlx5_vnet_supported(dev))
 855		return;
 856
 857	devl_params_unregister(devlink, mlx5_devlink_vnet_params,
 858			       ARRAY_SIZE(mlx5_devlink_vnet_params));
 859}
 860
 861static int mlx5_devlink_auxdev_params_register(struct devlink *devlink)
 862{
 863	int err;
 864
 865	err = mlx5_devlink_eth_params_register(devlink);
 866	if (err)
 867		return err;
 868
 869	err = mlx5_devlink_rdma_params_register(devlink);
 870	if (err)
 871		goto rdma_err;
 872
 873	err = mlx5_devlink_vnet_params_register(devlink);
 874	if (err)
 875		goto vnet_err;
 876	return 0;
 877
 878vnet_err:
 879	mlx5_devlink_rdma_params_unregister(devlink);
 880rdma_err:
 881	mlx5_devlink_eth_params_unregister(devlink);
 882	return err;
 883}
 884
 885static void mlx5_devlink_auxdev_params_unregister(struct devlink *devlink)
 886{
 887	mlx5_devlink_vnet_params_unregister(devlink);
 888	mlx5_devlink_rdma_params_unregister(devlink);
 889	mlx5_devlink_eth_params_unregister(devlink);
 890}
 891
 892static int mlx5_devlink_max_uc_list_validate(struct devlink *devlink, u32 id,
 893					     union devlink_param_value val,
 894					     struct netlink_ext_ack *extack)
 895{
 896	struct mlx5_core_dev *dev = devlink_priv(devlink);
 897
 898	if (val.vu32 == 0) {
 899		NL_SET_ERR_MSG_MOD(extack, "max_macs value must be greater than 0");
 900		return -EINVAL;
 901	}
 902
 903	if (!is_power_of_2(val.vu32)) {
 904		NL_SET_ERR_MSG_MOD(extack, "Only power of 2 values are supported for max_macs");
 905		return -EINVAL;
 906	}
 907
 908	if (ilog2(val.vu32) >
 909	    MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list)) {
 910		NL_SET_ERR_MSG_MOD(extack, "max_macs value is out of the supported range");
 911		return -EINVAL;
 912	}
 913
 914	return 0;
 915}
 916
 917static const struct devlink_param mlx5_devlink_max_uc_list_params[] = {
 918	DEVLINK_PARAM_GENERIC(MAX_MACS, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
 919			      NULL, NULL, mlx5_devlink_max_uc_list_validate),
 920};
 921
 922static int mlx5_devlink_max_uc_list_params_register(struct devlink *devlink)
 923{
 924	struct mlx5_core_dev *dev = devlink_priv(devlink);
 925	union devlink_param_value value;
 926	int err;
 927
 928	if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported))
 929		return 0;
 930
 931	err = devl_params_register(devlink, mlx5_devlink_max_uc_list_params,
 932				   ARRAY_SIZE(mlx5_devlink_max_uc_list_params));
 933	if (err)
 934		return err;
 935
 936	value.vu32 = 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list);
 937	devl_param_driverinit_value_set(devlink,
 938					DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
 939					value);
 940	return 0;
 941}
 942
 943static void
 944mlx5_devlink_max_uc_list_params_unregister(struct devlink *devlink)
 945{
 946	struct mlx5_core_dev *dev = devlink_priv(devlink);
 947
 948	if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported))
 949		return;
 950
 951	devl_params_unregister(devlink, mlx5_devlink_max_uc_list_params,
 952			       ARRAY_SIZE(mlx5_devlink_max_uc_list_params));
 953}
 954
 955#define MLX5_TRAP_DROP(_id, _group_id)					\
 956	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				\
 957			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
 958			     DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT)
 959
 960static const struct devlink_trap mlx5_traps_arr[] = {
 961	MLX5_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
 962	MLX5_TRAP_DROP(DMAC_FILTER, L2_DROPS),
 963};
 964
 965static const struct devlink_trap_group mlx5_trap_groups_arr[] = {
 966	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
 967};
 968
 969int mlx5_devlink_traps_register(struct devlink *devlink)
 970{
 971	struct mlx5_core_dev *core_dev = devlink_priv(devlink);
 972	int err;
 973
 974	err = devl_trap_groups_register(devlink, mlx5_trap_groups_arr,
 975					ARRAY_SIZE(mlx5_trap_groups_arr));
 976	if (err)
 977		return err;
 978
 979	err = devl_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr),
 980				  &core_dev->priv);
 981	if (err)
 982		goto err_trap_group;
 983	return 0;
 984
 985err_trap_group:
 986	devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
 987				    ARRAY_SIZE(mlx5_trap_groups_arr));
 988	return err;
 989}
 990
 991void mlx5_devlink_traps_unregister(struct devlink *devlink)
 992{
 993	devl_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr));
 994	devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
 995				    ARRAY_SIZE(mlx5_trap_groups_arr));
 996}
 997
 998int mlx5_devlink_params_register(struct devlink *devlink)
 999{
1000	int err;
1001
1002	/* Here only the driver init params should be registered.
1003	 * Runtime params should be registered by the code which
1004	 * behaviour they configure.
1005	 */
1006
1007	err = devl_params_register(devlink, mlx5_devlink_params,
1008				   ARRAY_SIZE(mlx5_devlink_params));
1009	if (err)
1010		return err;
1011
1012	mlx5_devlink_set_params_init_values(devlink);
1013
1014	err = mlx5_devlink_auxdev_params_register(devlink);
1015	if (err)
1016		goto auxdev_reg_err;
1017
1018	err = mlx5_devlink_max_uc_list_params_register(devlink);
1019	if (err)
1020		goto max_uc_list_err;
1021
1022	err = mlx5_devlink_pcie_cong_params_register(devlink);
1023	if (err)
1024		goto pcie_cong_err;
1025
1026	err = mlx5_nv_param_register_dl_params(devlink);
1027	if (err)
1028		goto nv_param_err;
1029
1030	return 0;
1031
1032nv_param_err:
1033	mlx5_devlink_pcie_cong_params_unregister(devlink);
1034pcie_cong_err:
1035	mlx5_devlink_max_uc_list_params_unregister(devlink);
1036max_uc_list_err:
1037	mlx5_devlink_auxdev_params_unregister(devlink);
1038auxdev_reg_err:
1039	devl_params_unregister(devlink, mlx5_devlink_params,
1040			       ARRAY_SIZE(mlx5_devlink_params));
1041	return err;
1042}
1043
1044void mlx5_devlink_params_unregister(struct devlink *devlink)
1045{
1046	mlx5_nv_param_unregister_dl_params(devlink);
1047	mlx5_devlink_pcie_cong_params_unregister(devlink);
1048	mlx5_devlink_max_uc_list_params_unregister(devlink);
1049	mlx5_devlink_auxdev_params_unregister(devlink);
1050	devl_params_unregister(devlink, mlx5_devlink_params,
1051			       ARRAY_SIZE(mlx5_devlink_params));
1052}
~/ Read-only file preview.