Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mlx5-updates-2023-10-10' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2023-10-10

1) Adham Faris, Increase max supported channels number to 256

2) Leon Romanovsky, Allow IPsec soft/hard limits in bytes

3) Shay Drory, Replace global mlx5_intf_lock with
HCA devcom component lock

4) Wei Zhang, Optimize SF creation flow

During SF creation, HCA state gets changed from INVALID to
IN_USE step by step. Accordingly, FW sends vhca event to
driver to inform about this state change asynchronously.
Each vhca event is critical because all related SW/FW
operations are triggered by it.

Currently there is only a single mlx5 general event handler
which not only handles vhca event but many other events.
This incurs huge bottleneck because all events are forced
to be handled in serial manner.

Moreover, all SFs share same table_lock which inevitably
impacts each other when they are created in parallel.

This series will solve this issue by:

1. A dedicated vhca event handler is introduced to eliminate
the mutual impact with other mlx5 events.
2. Max FW threads work queues are employed in the vhca event
handler to fully utilize FW capability.
3. Redesign SF active work logic to completely remove
table_lock.

With above optimization, SF creation time is reduced by 25%,
i.e. from 80s to 60s when creating 100 SFs.

Patches summary:

Patch 1 - implement dedicated vhca event handler with max FW
cmd threads of work queues.
Patch 2 - remove table_lock by redesigning SF active work
logic.

* tag 'mlx5-updates-2023-10-10' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux:
net/mlx5e: Allow IPsec soft/hard limits in bytes
net/mlx5e: Increase max supported channels number to 256
net/mlx5e: Preparations for supporting larger number of channels
net/mlx5e: Refactor mlx5e_rss_init() and mlx5e_rss_free() API's
net/mlx5e: Refactor mlx5e_rss_set_rxfh() and mlx5e_rss_get_rxfh()
net/mlx5e: Refactor rx_res_init() and rx_res_free() APIs
net/mlx5e: Use PTR_ERR_OR_ZERO() to simplify code
net/mlx5: Use PTR_ERR_OR_ZERO() to simplify code
net/mlx5: fix config name in Kconfig parameter documentation
net/mlx5: Remove unused declaration
net/mlx5: Replace global mlx5_intf_lock with HCA devcom component lock
net/mlx5: Refactor LAG peer device lookout bus logic to mlx5 devcom
net/mlx5: Avoid false positive lockdep warning by adding lock_class_key
net/mlx5: Redesign SF active work to remove table_lock
net/mlx5: Parallelize vhca event handling
====================

Link: https://lore.kernel.org/r/20231014171908.290428-1-saeed@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+548 -372
+1 -1
Documentation/networking/device_drivers/ethernet/mellanox/mlx5/kconfig.rst
··· 67 67 | Enables :ref:`IPSec XFRM cryptography-offload acceleration <xfrm_device>`. 68 68 69 69 70 - **CONFIG_MLX5_EN_MACSEC=(y/n)** 70 + **CONFIG_MLX5_MACSEC=(y/n)** 71 71 72 72 | Build support for MACsec cryptography-offload acceleration in the NIC. 73 73
+10 -95
drivers/net/ethernet/mellanox/mlx5/core/dev.c
··· 38 38 #include "devlink.h" 39 39 #include "lag/lag.h" 40 40 41 - /* intf dev list mutex */ 42 - static DEFINE_MUTEX(mlx5_intf_mutex); 43 41 static DEFINE_IDA(mlx5_adev_ida); 44 42 45 43 static bool is_eth_rep_supported(struct mlx5_core_dev *dev) ··· 335 337 336 338 void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev) 337 339 { 338 - mutex_lock(&mlx5_intf_mutex); 340 + mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp); 339 341 dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV; 340 - mutex_unlock(&mlx5_intf_mutex); 342 + mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp); 341 343 } 342 344 343 345 bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev) ··· 353 355 int ret = 0, i; 354 356 355 357 devl_assert_locked(priv_to_devlink(dev)); 356 - mutex_lock(&mlx5_intf_mutex); 358 + mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp); 357 359 priv->flags &= ~MLX5_PRIV_FLAGS_DETACH; 358 360 for (i = 0; i < ARRAY_SIZE(mlx5_adev_devices); i++) { 359 361 if (!priv->adev[i]) { ··· 398 400 break; 399 401 } 400 402 } 401 - mutex_unlock(&mlx5_intf_mutex); 403 + mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp); 402 404 return ret; 403 405 } 404 406 ··· 411 413 int i; 412 414 413 415 devl_assert_locked(priv_to_devlink(dev)); 414 - mutex_lock(&mlx5_intf_mutex); 416 + mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp); 415 417 for (i = ARRAY_SIZE(mlx5_adev_devices) - 1; i >= 0; i--) { 416 418 if (!priv->adev[i]) 417 419 continue; ··· 441 443 priv->adev[i] = NULL; 442 444 } 443 445 priv->flags |= MLX5_PRIV_FLAGS_DETACH; 444 - mutex_unlock(&mlx5_intf_mutex); 446 + mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp); 445 447 } 446 448 447 449 int mlx5_register_device(struct mlx5_core_dev *dev) ··· 449 451 int ret; 450 452 451 453 devl_assert_locked(priv_to_devlink(dev)); 452 - mutex_lock(&mlx5_intf_mutex); 454 + mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp); 453 455 dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV; 454 456 ret = mlx5_rescan_drivers_locked(dev); 455 - mutex_unlock(&mlx5_intf_mutex); 457 + mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp); 456 458 if (ret) 457 459 mlx5_unregister_device(dev); 458 460 ··· 462 464 void mlx5_unregister_device(struct mlx5_core_dev *dev) 463 465 { 464 466 devl_assert_locked(priv_to_devlink(dev)); 465 - mutex_lock(&mlx5_intf_mutex); 467 + mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp); 466 468 dev->priv.flags = MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV; 467 469 mlx5_rescan_drivers_locked(dev); 468 - mutex_unlock(&mlx5_intf_mutex); 470 + mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp); 469 471 } 470 472 471 473 static int add_drivers(struct mlx5_core_dev *dev) ··· 543 545 { 544 546 struct mlx5_priv *priv = &dev->priv; 545 547 546 - lockdep_assert_held(&mlx5_intf_mutex); 547 548 if (priv->flags & MLX5_PRIV_FLAGS_DETACH) 548 549 return 0; 549 550 ··· 561 564 psystem_guid = mlx5_query_nic_system_image_guid(peer_dev); 562 565 563 566 return (fsystem_guid && psystem_guid && fsystem_guid == psystem_guid); 564 - } 565 - 566 - static u32 mlx5_gen_pci_id(const struct mlx5_core_dev *dev) 567 - { 568 - return (u32)((pci_domain_nr(dev->pdev->bus) << 16) | 569 - (dev->pdev->bus->number << 8) | 570 - PCI_SLOT(dev->pdev->devfn)); 571 - } 572 - 573 - static int _next_phys_dev(struct mlx5_core_dev *mdev, 574 - const struct mlx5_core_dev *curr) 575 - { 576 - if (!mlx5_core_is_pf(mdev)) 577 - return 0; 578 - 579 - if (mdev == curr) 580 - return 0; 581 - 582 - if (!mlx5_same_hw_devs(mdev, (struct mlx5_core_dev *)curr) && 583 - mlx5_gen_pci_id(mdev) != mlx5_gen_pci_id(curr)) 584 - return 0; 585 - 586 - return 1; 587 - } 588 - 589 - static void *pci_get_other_drvdata(struct device *this, struct device *other) 590 - { 591 - if (this->driver != other->driver) 592 - return NULL; 593 - 594 - return pci_get_drvdata(to_pci_dev(other)); 595 - } 596 - 597 - static int next_phys_dev_lag(struct device *dev, const void *data) 598 - { 599 - struct mlx5_core_dev *mdev, *this = (struct mlx5_core_dev *)data; 600 - 601 - mdev = pci_get_other_drvdata(this->device, dev); 602 - if (!mdev) 603 - return 0; 604 - 605 - if (!mlx5_lag_is_supported(mdev)) 606 - return 0; 607 - 608 - return _next_phys_dev(mdev, data); 609 - } 610 - 611 - static struct mlx5_core_dev *mlx5_get_next_dev(struct mlx5_core_dev *dev, 612 - int (*match)(struct device *dev, const void *data)) 613 - { 614 - struct device *next; 615 - 616 - if (!mlx5_core_is_pf(dev)) 617 - return NULL; 618 - 619 - next = bus_find_device(&pci_bus_type, NULL, dev, match); 620 - if (!next) 621 - return NULL; 622 - 623 - put_device(next); 624 - return pci_get_drvdata(to_pci_dev(next)); 625 - } 626 - 627 - /* Must be called with intf_mutex held */ 628 - struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev) 629 - { 630 - lockdep_assert_held(&mlx5_intf_mutex); 631 - return mlx5_get_next_dev(dev, &next_phys_dev_lag); 632 - } 633 - 634 - void mlx5_dev_list_lock(void) 635 - { 636 - mutex_lock(&mlx5_intf_mutex); 637 - } 638 - void mlx5_dev_list_unlock(void) 639 - { 640 - mutex_unlock(&mlx5_intf_mutex); 641 - } 642 - 643 - int mlx5_dev_list_trylock(void) 644 - { 645 - return mutex_trylock(&mlx5_intf_mutex); 646 567 }
+3 -2
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 141 141 #define MLX5E_PARAMS_DEFAULT_MIN_RX_WQES_MPW 0x2 142 142 143 143 #define MLX5E_MIN_NUM_CHANNELS 0x1 144 - #define MLX5E_MAX_NUM_CHANNELS (MLX5E_INDIR_RQT_SIZE / 2) 144 + #define MLX5E_MAX_NUM_CHANNELS 256 145 145 #define MLX5E_TX_CQ_POLL_BUDGET 128 146 146 #define MLX5E_TX_XSK_POLL_BUDGET 64 147 147 #define MLX5E_SQ_RECOVER_MIN_INTERVAL 500 /* msecs */ ··· 200 200 { 201 201 return is_kdump_kernel() ? 202 202 MLX5E_MIN_NUM_CHANNELS : 203 - min_t(int, mlx5_comp_vectors_max(mdev), MLX5E_MAX_NUM_CHANNELS); 203 + min3(mlx5_comp_vectors_max(mdev), (u32)MLX5E_MAX_NUM_CHANNELS, 204 + (u32)(1 << MLX5_CAP_GEN(mdev, log_max_rqt_size))); 204 205 } 205 206 206 207 /* The maximum WQE size can be retrieved by max_wqe_sz_sq in
-1
drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
··· 150 150 struct dentry *dfs_root); 151 151 void mlx5e_fs_cleanup(struct mlx5e_flow_steering *fs); 152 152 struct mlx5e_vlan_table *mlx5e_fs_get_vlan(struct mlx5e_flow_steering *fs); 153 - void mlx5e_fs_set_tc(struct mlx5e_flow_steering *fs, struct mlx5e_tc_table *tc); 154 153 struct mlx5e_tc_table *mlx5e_fs_get_tc(struct mlx5e_flow_steering *fs); 155 154 struct mlx5e_l2_table *mlx5e_fs_get_l2(struct mlx5e_flow_steering *fs); 156 155 struct mlx5_flow_namespace *mlx5e_fs_get_ns(struct mlx5e_flow_steering *fs, bool egress);
+22 -10
drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c
··· 9 9 { 10 10 unsigned int i; 11 11 12 - for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) 12 + for (i = 0; i < indir->actual_table_size; i++) 13 13 indir->table[i] = i % num_channels; 14 14 } 15 15 ··· 45 45 } 46 46 47 47 int mlx5e_rqt_init_direct(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 48 - bool indir_enabled, u32 init_rqn) 48 + bool indir_enabled, u32 init_rqn, u32 indir_table_size) 49 49 { 50 - u16 max_size = indir_enabled ? MLX5E_INDIR_RQT_SIZE : 1; 50 + u16 max_size = indir_enabled ? indir_table_size : 1; 51 51 52 52 return mlx5e_rqt_init(rqt, mdev, max_size, &init_rqn, 1); 53 53 } ··· 68 68 { 69 69 unsigned int i; 70 70 71 - for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) { 71 + for (i = 0; i < indir->actual_table_size; i++) { 72 72 unsigned int ix = i; 73 73 74 74 if (hfunc == ETH_RSS_HASH_XOR) 75 - ix = mlx5e_bits_invert(ix, ilog2(MLX5E_INDIR_RQT_SIZE)); 75 + ix = mlx5e_bits_invert(ix, ilog2(indir->actual_table_size)); 76 76 77 77 ix = indir->table[ix]; 78 78 ··· 94 94 u32 *rss_rqns; 95 95 int err; 96 96 97 - rss_rqns = kvmalloc_array(MLX5E_INDIR_RQT_SIZE, sizeof(*rss_rqns), GFP_KERNEL); 97 + rss_rqns = kvmalloc_array(indir->actual_table_size, sizeof(*rss_rqns), GFP_KERNEL); 98 98 if (!rss_rqns) 99 99 return -ENOMEM; 100 100 ··· 102 102 if (err) 103 103 goto out; 104 104 105 - err = mlx5e_rqt_init(rqt, mdev, MLX5E_INDIR_RQT_SIZE, rss_rqns, MLX5E_INDIR_RQT_SIZE); 105 + err = mlx5e_rqt_init(rqt, mdev, indir->max_table_size, rss_rqns, 106 + indir->actual_table_size); 106 107 107 108 out: 108 109 kvfree(rss_rqns); 109 110 return err; 111 + } 112 + 113 + #define MLX5E_UNIFORM_SPREAD_RQT_FACTOR 2 114 + 115 + u32 mlx5e_rqt_size(struct mlx5_core_dev *mdev, unsigned int num_channels) 116 + { 117 + u32 rqt_size = max_t(u32, MLX5E_INDIR_MIN_RQT_SIZE, 118 + roundup_pow_of_two(num_channels * MLX5E_UNIFORM_SPREAD_RQT_FACTOR)); 119 + u32 max_cap_rqt_size = 1 << MLX5_CAP_GEN(mdev, log_max_rqt_size); 120 + 121 + return min_t(u32, rqt_size, max_cap_rqt_size); 110 122 } 111 123 112 124 void mlx5e_rqt_destroy(struct mlx5e_rqt *rqt) ··· 163 151 u32 *rss_rqns; 164 152 int err; 165 153 166 - if (WARN_ON(rqt->size != MLX5E_INDIR_RQT_SIZE)) 154 + if (WARN_ON(rqt->size != indir->max_table_size)) 167 155 return -EINVAL; 168 156 169 - rss_rqns = kvmalloc_array(MLX5E_INDIR_RQT_SIZE, sizeof(*rss_rqns), GFP_KERNEL); 157 + rss_rqns = kvmalloc_array(indir->actual_table_size, sizeof(*rss_rqns), GFP_KERNEL); 170 158 if (!rss_rqns) 171 159 return -ENOMEM; 172 160 ··· 174 162 if (err) 175 163 goto out; 176 164 177 - err = mlx5e_rqt_redirect(rqt, rss_rqns, MLX5E_INDIR_RQT_SIZE); 165 + err = mlx5e_rqt_redirect(rqt, rss_rqns, indir->actual_table_size); 178 166 179 167 out: 180 168 kvfree(rss_rqns);
+6 -3
drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
··· 6 6 7 7 #include <linux/kernel.h> 8 8 9 - #define MLX5E_INDIR_RQT_SIZE (1 << 8) 9 + #define MLX5E_INDIR_MIN_RQT_SIZE (BIT(8)) 10 10 11 11 struct mlx5_core_dev; 12 12 13 13 struct mlx5e_rss_params_indir { 14 - u32 table[MLX5E_INDIR_RQT_SIZE]; 14 + u32 *table; 15 + u32 actual_table_size; 16 + u32 max_table_size; 15 17 }; 16 18 17 19 void mlx5e_rss_params_indir_init_uniform(struct mlx5e_rss_params_indir *indir, ··· 26 24 }; 27 25 28 26 int mlx5e_rqt_init_direct(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 29 - bool indir_enabled, u32 init_rqn); 27 + bool indir_enabled, u32 init_rqn, u32 indir_table_size); 30 28 int mlx5e_rqt_init_indir(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 31 29 u32 *rqns, unsigned int num_rqns, 32 30 u8 hfunc, struct mlx5e_rss_params_indir *indir); ··· 37 35 return rqt->rqtn; 38 36 } 39 37 38 + u32 mlx5e_rqt_size(struct mlx5_core_dev *mdev, unsigned int num_channels); 40 39 int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn); 41 40 int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int num_rqns, 42 41 u8 hfunc, struct mlx5e_rss_params_indir *indir);
+115 -37
drivers/net/ethernet/mellanox/mlx5/core/en/rss.c
··· 81 81 refcount_t refcnt; 82 82 }; 83 83 84 - struct mlx5e_rss *mlx5e_rss_alloc(void) 84 + void mlx5e_rss_params_indir_modify_actual_size(struct mlx5e_rss *rss, u32 num_channels) 85 85 { 86 - return kvzalloc(sizeof(struct mlx5e_rss), GFP_KERNEL); 86 + rss->indir.actual_table_size = mlx5e_rqt_size(rss->mdev, num_channels); 87 87 } 88 88 89 - void mlx5e_rss_free(struct mlx5e_rss *rss) 89 + int mlx5e_rss_params_indir_init(struct mlx5e_rss_params_indir *indir, struct mlx5_core_dev *mdev, 90 + u32 actual_table_size, u32 max_table_size) 90 91 { 92 + indir->table = kvmalloc_array(max_table_size, sizeof(*indir->table), GFP_KERNEL); 93 + if (!indir->table) 94 + return -ENOMEM; 95 + 96 + indir->max_table_size = max_table_size; 97 + indir->actual_table_size = actual_table_size; 98 + 99 + return 0; 100 + } 101 + 102 + void mlx5e_rss_params_indir_cleanup(struct mlx5e_rss_params_indir *indir) 103 + { 104 + kvfree(indir->table); 105 + } 106 + 107 + static int mlx5e_rss_copy(struct mlx5e_rss *to, const struct mlx5e_rss *from) 108 + { 109 + u32 *dst_indir_table; 110 + 111 + if (to->indir.actual_table_size != from->indir.actual_table_size || 112 + to->indir.max_table_size != from->indir.max_table_size) { 113 + mlx5e_rss_warn(to->mdev, 114 + "Failed to copy RSS due to size mismatch, src (actual %u, max %u) != dst (actual %u, max %u)\n", 115 + from->indir.actual_table_size, from->indir.max_table_size, 116 + to->indir.actual_table_size, to->indir.max_table_size); 117 + return -EINVAL; 118 + } 119 + 120 + dst_indir_table = to->indir.table; 121 + *to = *from; 122 + to->indir.table = dst_indir_table; 123 + memcpy(to->indir.table, from->indir.table, 124 + from->indir.actual_table_size * sizeof(*from->indir.table)); 125 + return 0; 126 + } 127 + 128 + static struct mlx5e_rss *mlx5e_rss_init_copy(const struct mlx5e_rss *from) 129 + { 130 + struct mlx5e_rss *rss; 131 + int err; 132 + 133 + rss = kvzalloc(sizeof(*rss), GFP_KERNEL); 134 + if (!rss) 135 + return ERR_PTR(-ENOMEM); 136 + 137 + err = mlx5e_rss_params_indir_init(&rss->indir, from->mdev, from->indir.actual_table_size, 138 + from->indir.max_table_size); 139 + if (err) 140 + goto err_free_rss; 141 + 142 + err = mlx5e_rss_copy(rss, from); 143 + if (err) 144 + goto err_free_indir; 145 + 146 + return rss; 147 + 148 + err_free_indir: 149 + mlx5e_rss_params_indir_cleanup(&rss->indir); 150 + err_free_rss: 91 151 kvfree(rss); 152 + return ERR_PTR(err); 92 153 } 93 154 94 155 static void mlx5e_rss_params_init(struct mlx5e_rss *rss) ··· 343 282 return retval; 344 283 } 345 284 346 - int mlx5e_rss_init_no_tirs(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, 347 - bool inner_ft_support, u32 drop_rqn) 285 + static int mlx5e_rss_init_no_tirs(struct mlx5e_rss *rss) 348 286 { 287 + mlx5e_rss_params_init(rss); 288 + refcount_set(&rss->refcnt, 1); 289 + 290 + return mlx5e_rqt_init_direct(&rss->rqt, rss->mdev, true, 291 + rss->drop_rqn, rss->indir.max_table_size); 292 + } 293 + 294 + struct mlx5e_rss *mlx5e_rss_init(struct mlx5_core_dev *mdev, bool inner_ft_support, u32 drop_rqn, 295 + const struct mlx5e_packet_merge_param *init_pkt_merge_param, 296 + enum mlx5e_rss_init_type type, unsigned int nch, 297 + unsigned int max_nch) 298 + { 299 + struct mlx5e_rss *rss; 300 + int err; 301 + 302 + rss = kvzalloc(sizeof(*rss), GFP_KERNEL); 303 + if (!rss) 304 + return ERR_PTR(-ENOMEM); 305 + 306 + err = mlx5e_rss_params_indir_init(&rss->indir, mdev, 307 + mlx5e_rqt_size(mdev, nch), 308 + mlx5e_rqt_size(mdev, max_nch)); 309 + if (err) 310 + goto err_free_rss; 311 + 349 312 rss->mdev = mdev; 350 313 rss->inner_ft_support = inner_ft_support; 351 314 rss->drop_rqn = drop_rqn; 352 315 353 - mlx5e_rss_params_init(rss); 354 - refcount_set(&rss->refcnt, 1); 355 - 356 - return mlx5e_rqt_init_direct(&rss->rqt, mdev, true, drop_rqn); 357 - } 358 - 359 - int mlx5e_rss_init(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, 360 - bool inner_ft_support, u32 drop_rqn, 361 - const struct mlx5e_packet_merge_param *init_pkt_merge_param) 362 - { 363 - int err; 364 - 365 - err = mlx5e_rss_init_no_tirs(rss, mdev, inner_ft_support, drop_rqn); 316 + err = mlx5e_rss_init_no_tirs(rss); 366 317 if (err) 367 - goto err_out; 318 + goto err_free_indir; 319 + 320 + if (type == MLX5E_RSS_INIT_NO_TIRS) 321 + goto out; 368 322 369 323 err = mlx5e_rss_create_tirs(rss, init_pkt_merge_param, false); 370 324 if (err) ··· 391 315 goto err_destroy_tirs; 392 316 } 393 317 394 - return 0; 318 + out: 319 + return rss; 395 320 396 321 err_destroy_tirs: 397 322 mlx5e_rss_destroy_tirs(rss, false); 398 323 err_destroy_rqt: 399 324 mlx5e_rqt_destroy(&rss->rqt); 400 - err_out: 401 - return err; 325 + err_free_indir: 326 + mlx5e_rss_params_indir_cleanup(&rss->indir); 327 + err_free_rss: 328 + kvfree(rss); 329 + return ERR_PTR(err); 402 330 } 403 331 404 332 int mlx5e_rss_cleanup(struct mlx5e_rss *rss) ··· 416 336 mlx5e_rss_destroy_tirs(rss, true); 417 337 418 338 mlx5e_rqt_destroy(&rss->rqt); 339 + mlx5e_rss_params_indir_cleanup(&rss->indir); 340 + kvfree(rss); 419 341 420 342 return 0; 421 343 } ··· 552 470 553 471 int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc) 554 472 { 555 - unsigned int i; 556 - 557 473 if (indir) 558 - for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) 559 - indir[i] = rss->indir.table[i]; 474 + memcpy(indir, rss->indir.table, 475 + rss->indir.actual_table_size * sizeof(*rss->indir.table)); 560 476 561 477 if (key) 562 478 memcpy(key, rss->hash.toeplitz_hash_key, ··· 575 495 struct mlx5e_rss *old_rss; 576 496 int err = 0; 577 497 578 - old_rss = mlx5e_rss_alloc(); 579 - if (!old_rss) 580 - return -ENOMEM; 581 - 582 - *old_rss = *rss; 498 + old_rss = mlx5e_rss_init_copy(rss); 499 + if (IS_ERR(old_rss)) 500 + return PTR_ERR(old_rss); 583 501 584 502 if (hfunc && *hfunc != rss->hash.hfunc) { 585 503 switch (*hfunc) { ··· 601 523 } 602 524 603 525 if (indir) { 604 - unsigned int i; 605 - 606 526 changed_indir = true; 607 527 608 - for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) 609 - rss->indir.table[i] = indir[i]; 528 + memcpy(rss->indir.table, indir, 529 + rss->indir.actual_table_size * sizeof(*rss->indir.table)); 610 530 } 611 531 612 532 if (changed_indir && rss->enabled) { 613 533 err = mlx5e_rss_apply(rss, rqns, num_rqns); 614 534 if (err) { 615 - *rss = *old_rss; 535 + mlx5e_rss_copy(rss, old_rss); 616 536 goto out; 617 537 } 618 538 } ··· 619 543 mlx5e_rss_update_tirs(rss); 620 544 621 545 out: 622 - mlx5e_rss_free(old_rss); 546 + mlx5e_rss_params_indir_cleanup(&old_rss->indir); 547 + kvfree(old_rss); 548 + 623 549 return err; 624 550 } 625 551
+13 -7
drivers/net/ethernet/mellanox/mlx5/core/en/rss.h
··· 8 8 #include "tir.h" 9 9 #include "fs.h" 10 10 11 + enum mlx5e_rss_init_type { 12 + MLX5E_RSS_INIT_NO_TIRS = 0, 13 + MLX5E_RSS_INIT_TIRS 14 + }; 15 + 11 16 struct mlx5e_rss_params_traffic_type 12 17 mlx5e_rss_get_default_tt_config(enum mlx5_traffic_types tt); 13 18 14 19 struct mlx5e_rss; 15 20 16 - struct mlx5e_rss *mlx5e_rss_alloc(void); 17 - void mlx5e_rss_free(struct mlx5e_rss *rss); 18 - int mlx5e_rss_init(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, 19 - bool inner_ft_support, u32 drop_rqn, 20 - const struct mlx5e_packet_merge_param *init_pkt_merge_param); 21 - int mlx5e_rss_init_no_tirs(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, 22 - bool inner_ft_support, u32 drop_rqn); 21 + int mlx5e_rss_params_indir_init(struct mlx5e_rss_params_indir *indir, struct mlx5_core_dev *mdev, 22 + u32 actual_table_size, u32 max_table_size); 23 + void mlx5e_rss_params_indir_cleanup(struct mlx5e_rss_params_indir *indir); 24 + void mlx5e_rss_params_indir_modify_actual_size(struct mlx5e_rss *rss, u32 num_channels); 25 + struct mlx5e_rss *mlx5e_rss_init(struct mlx5_core_dev *mdev, bool inner_ft_support, u32 drop_rqn, 26 + const struct mlx5e_packet_merge_param *init_pkt_merge_param, 27 + enum mlx5e_rss_init_type type, unsigned int nch, 28 + unsigned int max_nch); 23 29 int mlx5e_rss_cleanup(struct mlx5e_rss *rss); 24 30 25 31 void mlx5e_rss_refcnt_inc(struct mlx5e_rss *rss);
+61 -44
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
··· 18 18 19 19 struct mlx5e_rss *rss[MLX5E_MAX_NUM_RSS]; 20 20 bool rss_active; 21 - u32 rss_rqns[MLX5E_INDIR_RQT_SIZE]; 21 + u32 *rss_rqns; 22 22 unsigned int rss_nch; 23 23 24 24 struct { ··· 34 34 35 35 /* API for rx_res_rss_* */ 36 36 37 + void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch) 38 + { 39 + int i; 40 + 41 + for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) { 42 + if (res->rss[i]) 43 + mlx5e_rss_params_indir_modify_actual_size(res->rss[i], nch); 44 + } 45 + } 46 + 37 47 static int mlx5e_rx_res_rss_init_def(struct mlx5e_rx_res *res, 38 48 unsigned int init_nch) 39 49 { 40 50 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 41 51 struct mlx5e_rss *rss; 42 - int err; 43 52 44 53 if (WARN_ON(res->rss[0])) 45 54 return -EINVAL; 46 55 47 - rss = mlx5e_rss_alloc(); 48 - if (!rss) 49 - return -ENOMEM; 50 - 51 - err = mlx5e_rss_init(rss, res->mdev, inner_ft_support, res->drop_rqn, 52 - &res->pkt_merge_param); 53 - if (err) 54 - goto err_rss_free; 56 + rss = mlx5e_rss_init(res->mdev, inner_ft_support, res->drop_rqn, 57 + &res->pkt_merge_param, MLX5E_RSS_INIT_TIRS, init_nch, res->max_nch); 58 + if (IS_ERR(rss)) 59 + return PTR_ERR(rss); 55 60 56 61 mlx5e_rss_set_indir_uniform(rss, init_nch); 57 62 58 63 res->rss[0] = rss; 59 64 60 65 return 0; 61 - 62 - err_rss_free: 63 - mlx5e_rss_free(rss); 64 - return err; 65 66 } 66 67 67 68 int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch) 68 69 { 69 70 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 70 71 struct mlx5e_rss *rss; 71 - int err, i; 72 + int i; 72 73 73 74 for (i = 1; i < MLX5E_MAX_NUM_RSS; i++) 74 75 if (!res->rss[i]) ··· 78 77 if (i == MLX5E_MAX_NUM_RSS) 79 78 return -ENOSPC; 80 79 81 - rss = mlx5e_rss_alloc(); 82 - if (!rss) 83 - return -ENOMEM; 84 - 85 - err = mlx5e_rss_init_no_tirs(rss, res->mdev, inner_ft_support, res->drop_rqn); 86 - if (err) 87 - goto err_rss_free; 80 + rss = mlx5e_rss_init(res->mdev, inner_ft_support, res->drop_rqn, 81 + &res->pkt_merge_param, MLX5E_RSS_INIT_NO_TIRS, init_nch, 82 + res->max_nch); 83 + if (IS_ERR(rss)) 84 + return PTR_ERR(rss); 88 85 89 86 mlx5e_rss_set_indir_uniform(rss, init_nch); 90 87 if (res->rss_active) ··· 92 93 *rss_idx = i; 93 94 94 95 return 0; 95 - 96 - err_rss_free: 97 - mlx5e_rss_free(rss); 98 - return err; 99 96 } 100 97 101 98 static int __mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx) ··· 103 108 if (err) 104 109 return err; 105 110 106 - mlx5e_rss_free(rss); 107 111 res->rss[rss_idx] = NULL; 108 112 109 113 return 0; ··· 278 284 279 285 /* End of API rx_res_rss_* */ 280 286 281 - struct mlx5e_rx_res *mlx5e_rx_res_alloc(void) 287 + static void mlx5e_rx_res_free(struct mlx5e_rx_res *res) 282 288 { 283 - return kvzalloc(sizeof(struct mlx5e_rx_res), GFP_KERNEL); 289 + kvfree(res->rss_rqns); 290 + kvfree(res); 291 + } 292 + 293 + static struct mlx5e_rx_res *mlx5e_rx_res_alloc(struct mlx5_core_dev *mdev, unsigned int max_nch) 294 + { 295 + struct mlx5e_rx_res *rx_res; 296 + 297 + rx_res = kvzalloc(sizeof(*rx_res), GFP_KERNEL); 298 + if (!rx_res) 299 + return NULL; 300 + 301 + rx_res->rss_rqns = kvcalloc(max_nch, sizeof(*rx_res->rss_rqns), GFP_KERNEL); 302 + if (!rx_res->rss_rqns) { 303 + kvfree(rx_res); 304 + return NULL; 305 + } 306 + 307 + return rx_res; 284 308 } 285 309 286 310 static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res) ··· 320 308 321 309 for (ix = 0; ix < res->max_nch; ix++) { 322 310 err = mlx5e_rqt_init_direct(&res->channels[ix].direct_rqt, 323 - res->mdev, false, res->drop_rqn); 311 + res->mdev, false, res->drop_rqn, 312 + mlx5e_rqt_size(res->mdev, res->max_nch)); 324 313 if (err) { 325 314 mlx5_core_warn(res->mdev, "Failed to create a direct RQT: err = %d, ix = %u\n", 326 315 err, ix); ··· 375 362 if (!builder) 376 363 return -ENOMEM; 377 364 378 - err = mlx5e_rqt_init_direct(&res->ptp.rqt, res->mdev, false, res->drop_rqn); 365 + err = mlx5e_rqt_init_direct(&res->ptp.rqt, res->mdev, false, res->drop_rqn, 366 + mlx5e_rqt_size(res->mdev, res->max_nch)); 379 367 if (err) 380 368 goto out; 381 369 ··· 418 404 mlx5e_rqt_destroy(&res->ptp.rqt); 419 405 } 420 406 421 - int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, 422 - enum mlx5e_rx_res_features features, unsigned int max_nch, 423 - u32 drop_rqn, const struct mlx5e_packet_merge_param *init_pkt_merge_param, 424 - unsigned int init_nch) 407 + struct mlx5e_rx_res * 408 + mlx5e_rx_res_create(struct mlx5_core_dev *mdev, enum mlx5e_rx_res_features features, 409 + unsigned int max_nch, u32 drop_rqn, 410 + const struct mlx5e_packet_merge_param *init_pkt_merge_param, 411 + unsigned int init_nch) 425 412 { 413 + struct mlx5e_rx_res *res; 426 414 int err; 415 + 416 + res = mlx5e_rx_res_alloc(mdev, max_nch); 417 + if (!res) 418 + return ERR_PTR(-ENOMEM); 427 419 428 420 res->mdev = mdev; 429 421 res->features = features; ··· 441 421 442 422 err = mlx5e_rx_res_rss_init_def(res, init_nch); 443 423 if (err) 444 - goto err_out; 424 + goto err_rx_res_free; 445 425 446 426 err = mlx5e_rx_res_channels_init(res); 447 427 if (err) ··· 451 431 if (err) 452 432 goto err_channels_destroy; 453 433 454 - return 0; 434 + return res; 455 435 456 436 err_channels_destroy: 457 437 mlx5e_rx_res_channels_destroy(res); 458 438 err_rss_destroy: 459 439 __mlx5e_rx_res_rss_destroy(res, 0); 460 - err_out: 461 - return err; 440 + err_rx_res_free: 441 + mlx5e_rx_res_free(res); 442 + return ERR_PTR(err); 462 443 } 463 444 464 445 void mlx5e_rx_res_destroy(struct mlx5e_rx_res *res) ··· 467 446 mlx5e_rx_res_ptp_destroy(res); 468 447 mlx5e_rx_res_channels_destroy(res); 469 448 mlx5e_rx_res_rss_destroy_all(res); 470 - } 471 - 472 - void mlx5e_rx_res_free(struct mlx5e_rx_res *res) 473 - { 474 - kvfree(res); 449 + mlx5e_rx_res_free(res); 475 450 } 476 451 477 452 u32 mlx5e_rx_res_get_tirn_direct(struct mlx5e_rx_res *res, unsigned int ix)
+6 -6
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h
··· 21 21 }; 22 22 23 23 /* Setup */ 24 - struct mlx5e_rx_res *mlx5e_rx_res_alloc(void); 25 - int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, 26 - enum mlx5e_rx_res_features features, unsigned int max_nch, 27 - u32 drop_rqn, const struct mlx5e_packet_merge_param *init_pkt_merge_param, 28 - unsigned int init_nch); 24 + struct mlx5e_rx_res * 25 + mlx5e_rx_res_create(struct mlx5_core_dev *mdev, enum mlx5e_rx_res_features features, 26 + unsigned int max_nch, u32 drop_rqn, 27 + const struct mlx5e_packet_merge_param *init_pkt_merge_param, 28 + unsigned int init_nch); 29 29 void mlx5e_rx_res_destroy(struct mlx5e_rx_res *res); 30 - void mlx5e_rx_res_free(struct mlx5e_rx_res *res); 31 30 32 31 /* TIRN getters for flow steering */ 33 32 u32 mlx5e_rx_res_get_tirn_direct(struct mlx5e_rx_res *res, unsigned int ix); ··· 59 60 int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res); 60 61 int mlx5e_rx_res_rss_index(struct mlx5e_rx_res *res, struct mlx5e_rss *rss); 61 62 struct mlx5e_rss *mlx5e_rx_res_rss_get(struct mlx5e_rx_res *res, u32 rss_idx); 63 + void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch); 62 64 63 65 /* Workaround for hairpin */ 64 66 struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res);
+14 -9
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
··· 56 56 return (struct mlx5e_ipsec_pol_entry *)x->xdo.offload_handle; 57 57 } 58 58 59 - static void mlx5e_ipsec_handle_tx_limit(struct work_struct *_work) 59 + static void mlx5e_ipsec_handle_sw_limits(struct work_struct *_work) 60 60 { 61 61 struct mlx5e_ipsec_dwork *dwork = 62 62 container_of(_work, struct mlx5e_ipsec_dwork, dwork.work); ··· 486 486 return -EINVAL; 487 487 } 488 488 489 - if (x->lft.hard_byte_limit != XFRM_INF || 490 - x->lft.soft_byte_limit != XFRM_INF) { 491 - NL_SET_ERR_MSG_MOD(extack, "Device doesn't support limits in bytes"); 489 + if (x->lft.soft_byte_limit >= x->lft.hard_byte_limit && 490 + x->lft.hard_byte_limit != XFRM_INF) { 491 + /* XFRM stack doesn't prevent such configuration :(. */ 492 + NL_SET_ERR_MSG_MOD(extack, "Hard byte limit must be greater than soft one"); 493 + return -EINVAL; 494 + } 495 + 496 + if (!x->lft.soft_byte_limit || !x->lft.hard_byte_limit) { 497 + NL_SET_ERR_MSG_MOD(extack, "Soft/hard byte limits can't be 0"); 492 498 return -EINVAL; 493 499 } 494 500 ··· 630 624 if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET) 631 625 return 0; 632 626 633 - if (x->xso.dir != XFRM_DEV_OFFLOAD_OUT) 634 - return 0; 635 - 636 627 if (x->lft.soft_packet_limit == XFRM_INF && 637 - x->lft.hard_packet_limit == XFRM_INF) 628 + x->lft.hard_packet_limit == XFRM_INF && 629 + x->lft.soft_byte_limit == XFRM_INF && 630 + x->lft.hard_byte_limit == XFRM_INF) 638 631 return 0; 639 632 640 633 dwork = kzalloc(sizeof(*dwork), GFP_KERNEL); ··· 641 636 return -ENOMEM; 642 637 643 638 dwork->sa_entry = sa_entry; 644 - INIT_DELAYED_WORK(&dwork->dwork, mlx5e_ipsec_handle_tx_limit); 639 + INIT_DELAYED_WORK(&dwork->dwork, mlx5e_ipsec_handle_sw_limits); 645 640 sa_entry->dwork = dwork; 646 641 return 0; 647 642 }
+14 -10
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
··· 1326 1326 setup_fte_no_frags(spec); 1327 1327 setup_fte_upper_proto_match(spec, &attrs->upspec); 1328 1328 1329 - if (rx != ipsec->rx_esw) 1330 - err = setup_modify_header(ipsec, attrs->type, 1331 - sa_entry->ipsec_obj_id | BIT(31), 1332 - XFRM_DEV_OFFLOAD_IN, &flow_act); 1333 - else 1334 - err = mlx5_esw_ipsec_rx_setup_modify_header(sa_entry, &flow_act); 1329 + if (!attrs->drop) { 1330 + if (rx != ipsec->rx_esw) 1331 + err = setup_modify_header(ipsec, attrs->type, 1332 + sa_entry->ipsec_obj_id | BIT(31), 1333 + XFRM_DEV_OFFLOAD_IN, &flow_act); 1334 + else 1335 + err = mlx5_esw_ipsec_rx_setup_modify_header(sa_entry, &flow_act); 1335 1336 1336 - if (err) 1337 - goto err_mod_header; 1337 + if (err) 1338 + goto err_mod_header; 1339 + } 1338 1340 1339 1341 switch (attrs->type) { 1340 1342 case XFRM_DEV_OFFLOAD_PACKET: ··· 1386 1384 if (flow_act.pkt_reformat) 1387 1385 mlx5_packet_reformat_dealloc(mdev, flow_act.pkt_reformat); 1388 1386 err_pkt_reformat: 1389 - mlx5_modify_header_dealloc(mdev, flow_act.modify_hdr); 1387 + if (flow_act.modify_hdr) 1388 + mlx5_modify_header_dealloc(mdev, flow_act.modify_hdr); 1390 1389 err_mod_header: 1391 1390 kvfree(spec); 1392 1391 err_alloc: ··· 1885 1882 return; 1886 1883 } 1887 1884 1888 - mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr); 1885 + if (ipsec_rule->modify_hdr) 1886 + mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr); 1889 1887 mlx5_esw_ipsec_rx_id_mapping_remove(sa_entry); 1890 1888 rx_ft_put(sa_entry->ipsec, sa_entry->attrs.family, sa_entry->attrs.type); 1891 1889 }
-1
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
··· 54 54 55 55 #ifdef CONFIG_MLX5_EN_IPSEC 56 56 57 - void mlx5e_ipsec_inverse_table_init(void); 58 57 void mlx5e_ipsec_set_iv_esn(struct sk_buff *skb, struct xfrm_state *x, 59 58 struct xfrm_offload *xo); 60 59 void mlx5e_ipsec_set_iv(struct sk_buff *skb, struct xfrm_state *x,
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
··· 1247 1247 1248 1248 u32 mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv *priv) 1249 1249 { 1250 - return MLX5E_INDIR_RQT_SIZE; 1250 + return mlx5e_rqt_size(priv->mdev, priv->channels.params.num_channels); 1251 1251 } 1252 1252 1253 1253 static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev)
+2 -6
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
··· 1283 1283 mlx5e_set_inner_ttc_params(fs, rx_res, &ttc_params); 1284 1284 fs->inner_ttc = mlx5_create_inner_ttc_table(fs->mdev, 1285 1285 &ttc_params); 1286 - if (IS_ERR(fs->inner_ttc)) 1287 - return PTR_ERR(fs->inner_ttc); 1288 - return 0; 1286 + return PTR_ERR_OR_ZERO(fs->inner_ttc); 1289 1287 } 1290 1288 1291 1289 int mlx5e_create_ttc_table(struct mlx5e_flow_steering *fs, ··· 1293 1295 1294 1296 mlx5e_set_ttc_params(fs, rx_res, &ttc_params, true); 1295 1297 fs->ttc = mlx5_create_ttc_table(fs->mdev, &ttc_params); 1296 - if (IS_ERR(fs->ttc)) 1297 - return PTR_ERR(fs->ttc); 1298 - return 0; 1298 + return PTR_ERR_OR_ZERO(fs->ttc); 1299 1299 } 1300 1300 1301 1301 int mlx5e_create_flow_steering(struct mlx5e_flow_steering *fs,
+17 -15
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 2948 2948 mlx5e_set_default_xps_cpumasks(priv, &priv->channels.params); 2949 2949 2950 2950 /* This function may be called on attach, before priv->rx_res is created. */ 2951 - if (!netif_is_rxfh_configured(priv->netdev) && priv->rx_res) 2952 - mlx5e_rx_res_rss_set_indir_uniform(priv->rx_res, count); 2951 + if (priv->rx_res) { 2952 + mlx5e_rx_res_rss_update_num_channels(priv->rx_res, count); 2953 + 2954 + if (!netif_is_rxfh_configured(priv->netdev)) 2955 + mlx5e_rx_res_rss_set_indir_uniform(priv->rx_res, count); 2956 + } 2953 2957 2954 2958 return 0; 2955 2959 } ··· 5393 5389 enum mlx5e_rx_res_features features; 5394 5390 int err; 5395 5391 5396 - priv->rx_res = mlx5e_rx_res_alloc(); 5397 - if (!priv->rx_res) 5398 - return -ENOMEM; 5399 - 5400 5392 mlx5e_create_q_counters(priv); 5401 5393 5402 5394 err = mlx5e_open_drop_rq(priv, &priv->drop_rq); ··· 5404 5404 features = MLX5E_RX_RES_FEATURE_PTP; 5405 5405 if (mlx5_tunnel_inner_ft_supported(mdev)) 5406 5406 features |= MLX5E_RX_RES_FEATURE_INNER_FT; 5407 - err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, features, 5408 - priv->max_nch, priv->drop_rq.rqn, 5409 - &priv->channels.params.packet_merge, 5410 - priv->channels.params.num_channels); 5411 - if (err) 5407 + 5408 + priv->rx_res = mlx5e_rx_res_create(priv->mdev, features, priv->max_nch, priv->drop_rq.rqn, 5409 + &priv->channels.params.packet_merge, 5410 + priv->channels.params.num_channels); 5411 + if (IS_ERR(priv->rx_res)) { 5412 + err = PTR_ERR(priv->rx_res); 5413 + priv->rx_res = NULL; 5414 + mlx5_core_err(mdev, "create rx resources failed, %d\n", err); 5412 5415 goto err_close_drop_rq; 5416 + } 5413 5417 5414 5418 err = mlx5e_create_flow_steering(priv->fs, priv->rx_res, priv->profile, 5415 5419 priv->netdev); ··· 5443 5439 priv->profile); 5444 5440 err_destroy_rx_res: 5445 5441 mlx5e_rx_res_destroy(priv->rx_res); 5442 + priv->rx_res = NULL; 5446 5443 err_close_drop_rq: 5447 5444 mlx5e_close_drop_rq(&priv->drop_rq); 5448 5445 err_destroy_q_counters: 5449 5446 mlx5e_destroy_q_counters(priv); 5450 - mlx5e_rx_res_free(priv->rx_res); 5451 - priv->rx_res = NULL; 5452 5447 return err; 5453 5448 } 5454 5449 ··· 5458 5455 mlx5e_destroy_flow_steering(priv->fs, !!(priv->netdev->hw_features & NETIF_F_NTUPLE), 5459 5456 priv->profile); 5460 5457 mlx5e_rx_res_destroy(priv->rx_res); 5458 + priv->rx_res = NULL; 5461 5459 mlx5e_close_drop_rq(&priv->drop_rq); 5462 5460 mlx5e_destroy_q_counters(priv); 5463 - mlx5e_rx_res_free(priv->rx_res); 5464 - priv->rx_res = NULL; 5465 5461 } 5466 5462 5467 5463 static void mlx5e_set_mqprio_rl(struct mlx5e_priv *priv)
+10 -17
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
··· 998 998 struct mlx5_core_dev *mdev = priv->mdev; 999 999 int err; 1000 1000 1001 - priv->rx_res = mlx5e_rx_res_alloc(); 1002 - if (!priv->rx_res) { 1003 - err = -ENOMEM; 1004 - goto err_free_fs; 1005 - } 1006 - 1007 1001 mlx5e_fs_init_l2_addr(priv->fs, priv->netdev); 1008 1002 1009 1003 err = mlx5e_open_drop_rq(priv, &priv->drop_rq); 1010 1004 if (err) { 1011 1005 mlx5_core_err(mdev, "open drop rq failed, %d\n", err); 1012 - goto err_rx_res_free; 1006 + goto err_free_fs; 1013 1007 } 1014 1008 1015 - err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, 1016 - priv->max_nch, priv->drop_rq.rqn, 1017 - &priv->channels.params.packet_merge, 1018 - priv->channels.params.num_channels); 1019 - if (err) 1009 + priv->rx_res = mlx5e_rx_res_create(priv->mdev, 0, priv->max_nch, priv->drop_rq.rqn, 1010 + &priv->channels.params.packet_merge, 1011 + priv->channels.params.num_channels); 1012 + if (IS_ERR(priv->rx_res)) { 1013 + err = PTR_ERR(priv->rx_res); 1014 + mlx5_core_err(mdev, "Create rx resources failed, err=%d\n", err); 1020 1015 goto err_close_drop_rq; 1016 + } 1021 1017 1022 1018 err = mlx5e_create_rep_ttc_table(priv); 1023 1019 if (err) ··· 1037 1041 mlx5_destroy_ttc_table(mlx5e_fs_get_ttc(priv->fs, false)); 1038 1042 err_destroy_rx_res: 1039 1043 mlx5e_rx_res_destroy(priv->rx_res); 1044 + priv->rx_res = ERR_PTR(-EINVAL); 1040 1045 err_close_drop_rq: 1041 1046 mlx5e_close_drop_rq(&priv->drop_rq); 1042 - err_rx_res_free: 1043 - mlx5e_rx_res_free(priv->rx_res); 1044 - priv->rx_res = NULL; 1045 1047 err_free_fs: 1046 1048 mlx5e_fs_cleanup(priv->fs); 1047 1049 priv->fs = NULL; ··· 1053 1059 mlx5e_destroy_rep_root_ft(priv); 1054 1060 mlx5_destroy_ttc_table(mlx5e_fs_get_ttc(priv->fs, false)); 1055 1061 mlx5e_rx_res_destroy(priv->rx_res); 1062 + priv->rx_res = ERR_PTR(-EINVAL); 1056 1063 mlx5e_close_drop_rq(&priv->drop_rq); 1057 - mlx5e_rx_res_free(priv->rx_res); 1058 - priv->rx_res = NULL; 1059 1064 } 1060 1065 1061 1066 static void mlx5e_rep_mpesw_work(struct work_struct *work)
+9 -7
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 753 753 { 754 754 struct mlx5e_priv *priv = hp->func_priv; 755 755 struct mlx5_core_dev *mdev = priv->mdev; 756 - struct mlx5e_rss_params_indir *indir; 756 + struct mlx5e_rss_params_indir indir; 757 757 int err; 758 758 759 - indir = kvmalloc(sizeof(*indir), GFP_KERNEL); 760 - if (!indir) 761 - return -ENOMEM; 759 + err = mlx5e_rss_params_indir_init(&indir, mdev, 760 + mlx5e_rqt_size(mdev, hp->num_channels), 761 + mlx5e_rqt_size(mdev, priv->max_nch)); 762 + if (err) 763 + return err; 762 764 763 - mlx5e_rss_params_indir_init_uniform(indir, hp->num_channels); 765 + mlx5e_rss_params_indir_init_uniform(&indir, hp->num_channels); 764 766 err = mlx5e_rqt_init_indir(&hp->indir_rqt, mdev, hp->pair->rqn, hp->num_channels, 765 767 mlx5e_rx_res_get_current_hash(priv->rx_res).hfunc, 766 - indir); 768 + &indir); 767 769 768 - kvfree(indir); 770 + mlx5e_rss_params_indir_cleanup(&indir); 769 771 return err; 770 772 } 771 773
-5
drivers/net/ethernet/mellanox/mlx5/core/events.c
··· 441 441 442 442 return blocking_notifier_call_chain(&events->sw_nh, event, data); 443 443 } 444 - 445 - void mlx5_events_work_enqueue(struct mlx5_core_dev *dev, struct work_struct *work) 446 - { 447 - queue_work(dev->priv.events->wq, work); 448 - }
+8 -16
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
··· 418 418 return -ENOMEM; 419 419 } 420 420 421 - priv->rx_res = mlx5e_rx_res_alloc(); 422 - if (!priv->rx_res) { 423 - err = -ENOMEM; 424 - goto err_free_fs; 425 - } 426 - 427 421 mlx5e_create_q_counters(priv); 428 422 429 423 err = mlx5e_open_drop_rq(priv, &priv->drop_rq); ··· 426 432 goto err_destroy_q_counters; 427 433 } 428 434 429 - err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, 430 - priv->max_nch, priv->drop_rq.rqn, 431 - &priv->channels.params.packet_merge, 432 - priv->channels.params.num_channels); 433 - if (err) 435 + priv->rx_res = mlx5e_rx_res_create(priv->mdev, 0, priv->max_nch, priv->drop_rq.rqn, 436 + &priv->channels.params.packet_merge, 437 + priv->channels.params.num_channels); 438 + if (IS_ERR(priv->rx_res)) { 439 + err = PTR_ERR(priv->rx_res); 434 440 goto err_close_drop_rq; 441 + } 435 442 436 443 err = mlx5i_create_flow_steering(priv); 437 444 if (err) ··· 442 447 443 448 err_destroy_rx_res: 444 449 mlx5e_rx_res_destroy(priv->rx_res); 450 + priv->rx_res = ERR_PTR(-EINVAL); 445 451 err_close_drop_rq: 446 452 mlx5e_close_drop_rq(&priv->drop_rq); 447 453 err_destroy_q_counters: 448 454 mlx5e_destroy_q_counters(priv); 449 - mlx5e_rx_res_free(priv->rx_res); 450 - priv->rx_res = NULL; 451 - err_free_fs: 452 455 mlx5e_fs_cleanup(priv->fs); 453 456 return err; 454 457 } ··· 455 462 { 456 463 mlx5i_destroy_flow_steering(priv); 457 464 mlx5e_rx_res_destroy(priv->rx_res); 465 + priv->rx_res = ERR_PTR(-EINVAL); 458 466 mlx5e_close_drop_rq(&priv->drop_rq); 459 467 mlx5e_destroy_q_counters(priv); 460 - mlx5e_rx_res_free(priv->rx_res); 461 - priv->rx_res = NULL; 462 468 mlx5e_fs_cleanup(priv->fs); 463 469 } 464 470
+38 -9
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
··· 943 943 } 944 944 } 945 945 946 + /* The last mdev to unregister will destroy the workqueue before removing the 947 + * devcom component, and as all the mdevs use the same devcom component we are 948 + * guaranteed that the devcom is valid while the calling work is running. 949 + */ 950 + struct mlx5_devcom_comp_dev *mlx5_lag_get_devcom_comp(struct mlx5_lag *ldev) 951 + { 952 + struct mlx5_devcom_comp_dev *devcom = NULL; 953 + int i; 954 + 955 + mutex_lock(&ldev->lock); 956 + for (i = 0; i < ldev->ports; i++) { 957 + if (ldev->pf[i].dev) { 958 + devcom = ldev->pf[i].dev->priv.hca_devcom_comp; 959 + break; 960 + } 961 + } 962 + mutex_unlock(&ldev->lock); 963 + return devcom; 964 + } 965 + 946 966 static void mlx5_queue_bond_work(struct mlx5_lag *ldev, unsigned long delay) 947 967 { 948 968 queue_delayed_work(ldev->wq, &ldev->bond_work, delay); ··· 973 953 struct delayed_work *delayed_work = to_delayed_work(work); 974 954 struct mlx5_lag *ldev = container_of(delayed_work, struct mlx5_lag, 975 955 bond_work); 956 + struct mlx5_devcom_comp_dev *devcom; 976 957 int status; 977 958 978 - status = mlx5_dev_list_trylock(); 959 + devcom = mlx5_lag_get_devcom_comp(ldev); 960 + if (!devcom) 961 + return; 962 + 963 + status = mlx5_devcom_comp_trylock(devcom); 979 964 if (!status) { 980 965 mlx5_queue_bond_work(ldev, HZ); 981 966 return; ··· 989 964 mutex_lock(&ldev->lock); 990 965 if (ldev->mode_changes_in_progress) { 991 966 mutex_unlock(&ldev->lock); 992 - mlx5_dev_list_unlock(); 967 + mlx5_devcom_comp_unlock(devcom); 993 968 mlx5_queue_bond_work(ldev, HZ); 994 969 return; 995 970 } 996 971 997 972 mlx5_do_bond(ldev); 998 973 mutex_unlock(&ldev->lock); 999 - mlx5_dev_list_unlock(); 974 + mlx5_devcom_comp_unlock(devcom); 1000 975 } 1001 976 1002 977 static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, ··· 1237 1212 dev->priv.lag = NULL; 1238 1213 } 1239 1214 1240 - /* Must be called with intf_mutex held */ 1215 + /* Must be called with HCA devcom component lock held */ 1241 1216 static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev) 1242 1217 { 1218 + struct mlx5_devcom_comp_dev *pos = NULL; 1243 1219 struct mlx5_lag *ldev = NULL; 1244 1220 struct mlx5_core_dev *tmp_dev; 1245 1221 1246 - tmp_dev = mlx5_get_next_phys_dev_lag(dev); 1222 + tmp_dev = mlx5_devcom_get_next_peer_data(dev->priv.hca_devcom_comp, &pos); 1247 1223 if (tmp_dev) 1248 1224 ldev = mlx5_lag_dev(tmp_dev); 1249 1225 ··· 1301 1275 if (!mlx5_lag_is_supported(dev)) 1302 1276 return; 1303 1277 1278 + if (IS_ERR_OR_NULL(dev->priv.hca_devcom_comp)) 1279 + return; 1280 + 1304 1281 recheck: 1305 - mlx5_dev_list_lock(); 1282 + mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp); 1306 1283 err = __mlx5_lag_dev_add_mdev(dev); 1307 - mlx5_dev_list_unlock(); 1284 + mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp); 1308 1285 1309 1286 if (err) { 1310 1287 msleep(100); ··· 1460 1431 if (!ldev) 1461 1432 return; 1462 1433 1463 - mlx5_dev_list_lock(); 1434 + mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp); 1464 1435 mutex_lock(&ldev->lock); 1465 1436 1466 1437 ldev->mode_changes_in_progress++; ··· 1468 1439 mlx5_disable_lag(ldev); 1469 1440 1470 1441 mutex_unlock(&ldev->lock); 1471 - mlx5_dev_list_unlock(); 1442 + mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp); 1472 1443 } 1473 1444 1474 1445 void mlx5_lag_enable_change(struct mlx5_core_dev *dev)
+1
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
··· 112 112 void mlx5_lag_remove_devices(struct mlx5_lag *ldev); 113 113 int mlx5_deactivate_lag(struct mlx5_lag *ldev); 114 114 void mlx5_lag_add_devices(struct mlx5_lag *ldev); 115 + struct mlx5_devcom_comp_dev *mlx5_lag_get_devcom_comp(struct mlx5_lag *ldev); 115 116 116 117 static inline bool mlx5_lag_is_supported(struct mlx5_core_dev *dev) 117 118 {
+7 -2
drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
··· 129 129 static void mlx5_mpesw_work(struct work_struct *work) 130 130 { 131 131 struct mlx5_mpesw_work_st *mpesww = container_of(work, struct mlx5_mpesw_work_st, work); 132 + struct mlx5_devcom_comp_dev *devcom; 132 133 struct mlx5_lag *ldev = mpesww->lag; 133 134 134 - mlx5_dev_list_lock(); 135 + devcom = mlx5_lag_get_devcom_comp(ldev); 136 + if (!devcom) 137 + return; 138 + 139 + mlx5_devcom_comp_lock(devcom); 135 140 mutex_lock(&ldev->lock); 136 141 if (ldev->mode_changes_in_progress) { 137 142 mpesww->result = -EAGAIN; ··· 149 144 disable_mpesw(ldev); 150 145 unlock: 151 146 mutex_unlock(&ldev->lock); 152 - mlx5_dev_list_unlock(); 147 + mlx5_devcom_comp_unlock(devcom); 153 148 complete(&mpesww->comp); 154 149 } 155 150
+2 -8
drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
··· 507 507 508 508 mlx5_lag_set_outer_ttc_params(ldev, &ttc_params); 509 509 port_sel->outer.ttc = mlx5_create_ttc_table(dev, &ttc_params); 510 - if (IS_ERR(port_sel->outer.ttc)) 511 - return PTR_ERR(port_sel->outer.ttc); 512 - 513 - return 0; 510 + return PTR_ERR_OR_ZERO(port_sel->outer.ttc); 514 511 } 515 512 516 513 static int mlx5_lag_create_inner_ttc_table(struct mlx5_lag *ldev) ··· 518 521 519 522 mlx5_lag_set_inner_ttc_params(ldev, &ttc_params); 520 523 port_sel->inner.ttc = mlx5_create_inner_ttc_table(dev, &ttc_params); 521 - if (IS_ERR(port_sel->inner.ttc)) 522 - return PTR_ERR(port_sel->inner.ttc); 523 - 524 - return 0; 524 + return PTR_ERR_OR_ZERO(port_sel->inner.ttc); 525 525 } 526 526 527 527 int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
+25
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
··· 31 31 struct kref ref; 32 32 bool ready; 33 33 struct rw_semaphore sem; 34 + struct lock_class_key lock_key; 34 35 }; 35 36 36 37 struct mlx5_devcom_comp_dev { ··· 120 119 comp->key = key; 121 120 comp->handler = handler; 122 121 init_rwsem(&comp->sem); 122 + lockdep_register_key(&comp->lock_key); 123 + lockdep_set_class(&comp->sem, &comp->lock_key); 123 124 kref_init(&comp->ref); 124 125 INIT_LIST_HEAD(&comp->comp_dev_list_head); 125 126 ··· 136 133 mutex_lock(&comp_list_lock); 137 134 list_del(&comp->comp_list); 138 135 mutex_unlock(&comp_list_lock); 136 + lockdep_unregister_key(&comp->lock_key); 139 137 kfree(comp); 140 138 } 141 139 ··· 386 382 387 383 *pos = tmp; 388 384 return data; 385 + } 386 + 387 + void mlx5_devcom_comp_lock(struct mlx5_devcom_comp_dev *devcom) 388 + { 389 + if (IS_ERR_OR_NULL(devcom)) 390 + return; 391 + down_write(&devcom->comp->sem); 392 + } 393 + 394 + void mlx5_devcom_comp_unlock(struct mlx5_devcom_comp_dev *devcom) 395 + { 396 + if (IS_ERR_OR_NULL(devcom)) 397 + return; 398 + up_write(&devcom->comp->sem); 399 + } 400 + 401 + int mlx5_devcom_comp_trylock(struct mlx5_devcom_comp_dev *devcom) 402 + { 403 + if (IS_ERR_OR_NULL(devcom)) 404 + return 0; 405 + return down_write_trylock(&devcom->comp->sem); 389 406 }
+5
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
··· 9 9 enum mlx5_devcom_component { 10 10 MLX5_DEVCOM_ESW_OFFLOADS, 11 11 MLX5_DEVCOM_MPV, 12 + MLX5_DEVCOM_HCA_PORTS, 12 13 MLX5_DEVCOM_NUM_COMPONENTS, 13 14 }; 14 15 ··· 52 51 for (pos = NULL, data = mlx5_devcom_get_next_peer_data_rcu(devcom, &pos); \ 53 52 data; \ 54 53 data = mlx5_devcom_get_next_peer_data_rcu(devcom, &pos)) 54 + 55 + void mlx5_devcom_comp_lock(struct mlx5_devcom_comp_dev *devcom); 56 + void mlx5_devcom_comp_unlock(struct mlx5_devcom_comp_dev *devcom); 57 + int mlx5_devcom_comp_trylock(struct mlx5_devcom_comp_dev *devcom); 55 58 56 59 #endif /* __LIB_MLX5_DEVCOM_H__ */
-1
drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
··· 85 85 struct mlx5_eq_comp *mlx5_eqn2comp_eq(struct mlx5_core_dev *dev, int eqn); 86 86 struct mlx5_eq *mlx5_get_async_eq(struct mlx5_core_dev *dev); 87 87 void mlx5_cq_tasklet_cb(struct tasklet_struct *t); 88 - struct cpumask *mlx5_eq_comp_cpumask(struct mlx5_core_dev *dev, int ix); 89 88 90 89 u32 mlx5_eq_poll_irq_disabled(struct mlx5_eq_comp *eq); 91 90 void mlx5_cmd_eq_recover(struct mlx5_core_dev *dev);
+25
drivers/net/ethernet/mellanox/mlx5/core/main.c
··· 73 73 #include "sf/sf.h" 74 74 #include "mlx5_irq.h" 75 75 #include "hwmon.h" 76 + #include "lag/lag.h" 76 77 77 78 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>"); 78 79 MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver"); ··· 953 952 mlx5_pci_disable_device(dev); 954 953 } 955 954 955 + static void mlx5_register_hca_devcom_comp(struct mlx5_core_dev *dev) 956 + { 957 + /* This component is use to sync adding core_dev to lag_dev and to sync 958 + * changes of mlx5_adev_devices between LAG layer and other layers. 959 + */ 960 + if (!mlx5_lag_is_supported(dev)) 961 + return; 962 + 963 + dev->priv.hca_devcom_comp = 964 + mlx5_devcom_register_component(dev->priv.devc, MLX5_DEVCOM_HCA_PORTS, 965 + mlx5_query_nic_system_image_guid(dev), 966 + NULL, dev); 967 + if (IS_ERR_OR_NULL(dev->priv.hca_devcom_comp)) 968 + mlx5_core_err(dev, "Failed to register devcom HCA component\n"); 969 + } 970 + 971 + static void mlx5_unregister_hca_devcom_comp(struct mlx5_core_dev *dev) 972 + { 973 + mlx5_devcom_unregister_component(dev->priv.hca_devcom_comp); 974 + } 975 + 956 976 static int mlx5_init_once(struct mlx5_core_dev *dev) 957 977 { 958 978 int err; ··· 982 960 if (IS_ERR(dev->priv.devc)) 983 961 mlx5_core_warn(dev, "failed to register devcom device %ld\n", 984 962 PTR_ERR(dev->priv.devc)); 963 + mlx5_register_hca_devcom_comp(dev); 985 964 986 965 err = mlx5_query_board_id(dev); 987 966 if (err) { ··· 1117 1094 err_irq_cleanup: 1118 1095 mlx5_irq_table_cleanup(dev); 1119 1096 err_devcom: 1097 + mlx5_unregister_hca_devcom_comp(dev); 1120 1098 mlx5_devcom_unregister_device(dev->priv.devc); 1121 1099 1122 1100 return err; ··· 1147 1123 mlx5_events_cleanup(dev); 1148 1124 mlx5_eq_table_cleanup(dev); 1149 1125 mlx5_irq_table_cleanup(dev); 1126 + mlx5_unregister_hca_devcom_comp(dev); 1150 1127 mlx5_devcom_unregister_device(dev->priv.devc); 1151 1128 } 1152 1129
+5 -9
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
··· 41 41 #include <linux/mlx5/cq.h> 42 42 #include <linux/mlx5/fs.h> 43 43 #include <linux/mlx5/driver.h> 44 + #include "lib/devcom.h" 44 45 45 46 extern uint mlx5_core_debug_mask; 46 47 ··· 160 159 161 160 #define MLX5_DEFAULT_PROF 2 162 161 #define MLX5_SF_PROF 3 162 + #define MLX5_NUM_FW_CMD_THREADS 8 163 + #define MLX5_DEV_MAX_WQS MLX5_NUM_FW_CMD_THREADS 163 164 164 165 static inline int mlx5_flexible_inlen(struct mlx5_core_dev *dev, size_t fixed, 165 166 size_t item_size, size_t num_items, ··· 267 264 void mlx5_unregister_device(struct mlx5_core_dev *dev); 268 265 void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev); 269 266 bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev); 270 - struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev); 271 - void mlx5_dev_list_lock(void); 272 - void mlx5_dev_list_unlock(void); 273 - int mlx5_dev_list_trylock(void); 274 267 275 268 void mlx5_fw_reporters_create(struct mlx5_core_dev *dev); 276 269 int mlx5_query_mtpps(struct mlx5_core_dev *dev, u32 *mtpps, u32 mtpps_size); ··· 305 306 { 306 307 int ret; 307 308 308 - mlx5_dev_list_lock(); 309 + mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp); 309 310 ret = mlx5_rescan_drivers_locked(dev); 310 - mlx5_dev_list_unlock(); 311 + mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp); 311 312 return ret; 312 313 } 313 - 314 - void mlx5_lag_update(struct mlx5_core_dev *dev); 315 314 316 315 enum { 317 316 MLX5_NIC_IFC_FULL = 0, ··· 344 347 #define mlx5_vport_get_other_func_general_cap(dev, vport, out) \ 345 348 mlx5_vport_get_other_func_cap(dev, vport, out, MLX5_CAP_GENERAL) 346 349 347 - void mlx5_events_work_enqueue(struct mlx5_core_dev *dev, struct work_struct *work); 348 350 static inline u32 mlx5_sriov_get_vf_total_msix(struct pci_dev *pdev) 349 351 { 350 352 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
+57 -29
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c
··· 17 17 phys_addr_t base_address; 18 18 u64 sf_bar_length; 19 19 struct notifier_block nb; 20 - struct mutex table_lock; /* Serializes sf life cycle and vhca state change handler */ 21 20 struct workqueue_struct *active_wq; 22 21 struct work_struct work; 23 22 u8 stop_active_wq:1; 24 23 struct mlx5_core_dev *dev; 24 + }; 25 + 26 + struct mlx5_sf_dev_active_work_ctx { 27 + struct work_struct work; 28 + struct mlx5_vhca_state_event event; 29 + struct mlx5_sf_dev_table *table; 30 + int sf_index; 25 31 }; 26 32 27 33 static bool mlx5_sf_dev_supported(const struct mlx5_core_dev *dev) ··· 171 165 return 0; 172 166 173 167 sf_index = event->function_id - base_id; 174 - mutex_lock(&table->table_lock); 175 168 sf_dev = xa_load(&table->devices, sf_index); 176 169 switch (event->new_vhca_state) { 177 170 case MLX5_VHCA_STATE_INVALID: ··· 194 189 default: 195 190 break; 196 191 } 197 - mutex_unlock(&table->table_lock); 198 192 return 0; 199 193 } 200 194 ··· 218 214 return 0; 219 215 } 220 216 221 - static void mlx5_sf_dev_add_active_work(struct work_struct *work) 217 + static void mlx5_sf_dev_add_active_work(struct work_struct *_work) 222 218 { 223 - struct mlx5_sf_dev_table *table = container_of(work, struct mlx5_sf_dev_table, work); 219 + struct mlx5_sf_dev_active_work_ctx *work_ctx; 220 + 221 + work_ctx = container_of(_work, struct mlx5_sf_dev_active_work_ctx, work); 222 + if (work_ctx->table->stop_active_wq) 223 + goto out; 224 + /* Don't probe device which is already probe */ 225 + if (!xa_load(&work_ctx->table->devices, work_ctx->sf_index)) 226 + mlx5_sf_dev_add(work_ctx->table->dev, work_ctx->sf_index, 227 + work_ctx->event.function_id, work_ctx->event.sw_function_id); 228 + /* There is a race where SF got inactive after the query 229 + * above. e.g.: the query returns that the state of the 230 + * SF is active, and after that the eswitch manager set it to 231 + * inactive. 232 + * This case cannot be managed in SW, since the probing of the 233 + * SF is on one system, and the inactivation is on a different 234 + * system. 235 + * If the inactive is done after the SF perform init_hca(), 236 + * the SF will fully probe and then removed. If it was 237 + * done before init_hca(), the SF probe will fail. 238 + */ 239 + out: 240 + kfree(work_ctx); 241 + } 242 + 243 + /* In case SFs are generated externally, probe active SFs */ 244 + static void mlx5_sf_dev_queue_active_works(struct work_struct *_work) 245 + { 246 + struct mlx5_sf_dev_table *table = container_of(_work, struct mlx5_sf_dev_table, work); 224 247 u32 out[MLX5_ST_SZ_DW(query_vhca_state_out)] = {}; 248 + struct mlx5_sf_dev_active_work_ctx *work_ctx; 225 249 struct mlx5_core_dev *dev = table->dev; 226 250 u16 max_functions; 227 251 u16 function_id; 228 252 u16 sw_func_id; 229 253 int err = 0; 254 + int wq_idx; 230 255 u8 state; 231 256 int i; 232 257 ··· 275 242 continue; 276 243 277 244 sw_func_id = MLX5_GET(query_vhca_state_out, out, vhca_state_context.sw_function_id); 278 - mutex_lock(&table->table_lock); 279 - /* Don't probe device which is already probe */ 280 - if (!xa_load(&table->devices, i)) 281 - mlx5_sf_dev_add(dev, i, function_id, sw_func_id); 282 - /* There is a race where SF got inactive after the query 283 - * above. e.g.: the query returns that the state of the 284 - * SF is active, and after that the eswitch manager set it to 285 - * inactive. 286 - * This case cannot be managed in SW, since the probing of the 287 - * SF is on one system, and the inactivation is on a different 288 - * system. 289 - * If the inactive is done after the SF perform init_hca(), 290 - * the SF will fully probe and then removed. If it was 291 - * done before init_hca(), the SF probe will fail. 292 - */ 293 - mutex_unlock(&table->table_lock); 245 + work_ctx = kzalloc(sizeof(*work_ctx), GFP_KERNEL); 246 + if (!work_ctx) 247 + return; 248 + 249 + INIT_WORK(&work_ctx->work, &mlx5_sf_dev_add_active_work); 250 + work_ctx->event.function_id = function_id; 251 + work_ctx->event.sw_function_id = sw_func_id; 252 + work_ctx->table = table; 253 + work_ctx->sf_index = i; 254 + wq_idx = work_ctx->event.function_id % MLX5_DEV_MAX_WQS; 255 + mlx5_vhca_events_work_enqueue(dev, wq_idx, &work_ctx->work); 294 256 } 295 257 } 296 258 297 259 /* In case SFs are generated externally, probe active SFs */ 298 - static int mlx5_sf_dev_queue_active_work(struct mlx5_sf_dev_table *table) 260 + static int mlx5_sf_dev_create_active_works(struct mlx5_sf_dev_table *table) 299 261 { 300 262 if (MLX5_CAP_GEN(table->dev, eswitch_manager)) 301 263 return 0; /* the table is local */ ··· 301 273 table->active_wq = create_singlethread_workqueue("mlx5_active_sf"); 302 274 if (!table->active_wq) 303 275 return -ENOMEM; 304 - INIT_WORK(&table->work, &mlx5_sf_dev_add_active_work); 276 + INIT_WORK(&table->work, &mlx5_sf_dev_queue_active_works); 305 277 queue_work(table->active_wq, &table->work); 306 278 return 0; 307 279 } 308 280 309 - static void mlx5_sf_dev_destroy_active_work(struct mlx5_sf_dev_table *table) 281 + static void mlx5_sf_dev_destroy_active_works(struct mlx5_sf_dev_table *table) 310 282 { 311 283 if (table->active_wq) { 312 284 table->stop_active_wq = true; ··· 333 305 table->sf_bar_length = 1 << (MLX5_CAP_GEN(dev, log_min_sf_size) + 12); 334 306 table->base_address = pci_resource_start(dev->pdev, 2); 335 307 xa_init(&table->devices); 336 - mutex_init(&table->table_lock); 337 308 dev->priv.sf_dev_table = table; 338 309 339 310 err = mlx5_vhca_event_notifier_register(dev, &table->nb); 340 311 if (err) 341 312 goto vhca_err; 342 313 343 - err = mlx5_sf_dev_queue_active_work(table); 314 + err = mlx5_sf_dev_create_active_works(table); 344 315 if (err) 345 316 goto add_active_err; 346 317 ··· 349 322 return; 350 323 351 324 arm_err: 352 - mlx5_sf_dev_destroy_active_work(table); 325 + mlx5_sf_dev_destroy_active_works(table); 353 326 add_active_err: 354 327 mlx5_vhca_event_notifier_unregister(dev, &table->nb); 328 + mlx5_vhca_event_work_queues_flush(dev); 355 329 vhca_err: 356 330 kfree(table); 357 331 dev->priv.sf_dev_table = NULL; ··· 378 350 if (!table) 379 351 return; 380 352 381 - mlx5_sf_dev_destroy_active_work(table); 353 + mlx5_sf_dev_destroy_active_works(table); 382 354 mlx5_vhca_event_notifier_unregister(dev, &table->nb); 383 - mutex_destroy(&table->table_lock); 355 + mlx5_vhca_event_work_queues_flush(dev); 384 356 385 357 /* Now that event handler is not running, it is safe to destroy 386 358 * the sf device without race.
+66 -3
drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c
··· 21 21 struct mlx5_vhca_state_event event; 22 22 }; 23 23 24 + struct mlx5_vhca_event_handler { 25 + struct workqueue_struct *wq; 26 + }; 27 + 28 + struct mlx5_vhca_events { 29 + struct mlx5_core_dev *dev; 30 + struct mlx5_vhca_event_handler handler[MLX5_DEV_MAX_WQS]; 31 + }; 32 + 24 33 int mlx5_cmd_query_vhca_state(struct mlx5_core_dev *dev, u16 function_id, u32 *out, u32 outlen) 25 34 { 26 35 u32 in[MLX5_ST_SZ_DW(query_vhca_state_in)] = {}; ··· 108 99 kfree(work); 109 100 } 110 101 102 + void mlx5_vhca_events_work_enqueue(struct mlx5_core_dev *dev, int idx, struct work_struct *work) 103 + { 104 + queue_work(dev->priv.vhca_events->handler[idx].wq, work); 105 + } 106 + 111 107 static int 112 108 mlx5_vhca_state_change_notifier(struct notifier_block *nb, unsigned long type, void *data) 113 109 { ··· 120 106 mlx5_nb_cof(nb, struct mlx5_vhca_state_notifier, nb); 121 107 struct mlx5_vhca_event_work *work; 122 108 struct mlx5_eqe *eqe = data; 109 + int wq_idx; 123 110 124 111 work = kzalloc(sizeof(*work), GFP_ATOMIC); 125 112 if (!work) ··· 128 113 INIT_WORK(&work->work, &mlx5_vhca_state_work_handler); 129 114 work->notifier = notifier; 130 115 work->event.function_id = be16_to_cpu(eqe->data.vhca_state.function_id); 131 - mlx5_events_work_enqueue(notifier->dev, &work->work); 116 + wq_idx = work->event.function_id % MLX5_DEV_MAX_WQS; 117 + mlx5_vhca_events_work_enqueue(notifier->dev, wq_idx, &work->work); 132 118 return NOTIFY_OK; 133 119 } 134 120 ··· 148 132 int mlx5_vhca_event_init(struct mlx5_core_dev *dev) 149 133 { 150 134 struct mlx5_vhca_state_notifier *notifier; 135 + char wq_name[MLX5_CMD_WQ_MAX_NAME]; 136 + struct mlx5_vhca_events *events; 137 + int err, i; 151 138 152 139 if (!mlx5_vhca_event_supported(dev)) 153 140 return 0; 154 141 155 - notifier = kzalloc(sizeof(*notifier), GFP_KERNEL); 156 - if (!notifier) 142 + events = kzalloc(sizeof(*events), GFP_KERNEL); 143 + if (!events) 157 144 return -ENOMEM; 145 + 146 + events->dev = dev; 147 + dev->priv.vhca_events = events; 148 + for (i = 0; i < MLX5_DEV_MAX_WQS; i++) { 149 + snprintf(wq_name, MLX5_CMD_WQ_MAX_NAME, "mlx5_vhca_event%d", i); 150 + events->handler[i].wq = create_singlethread_workqueue(wq_name); 151 + if (!events->handler[i].wq) { 152 + err = -ENOMEM; 153 + goto err_create_wq; 154 + } 155 + } 156 + 157 + notifier = kzalloc(sizeof(*notifier), GFP_KERNEL); 158 + if (!notifier) { 159 + err = -ENOMEM; 160 + goto err_notifier; 161 + } 158 162 159 163 dev->priv.vhca_state_notifier = notifier; 160 164 notifier->dev = dev; 161 165 BLOCKING_INIT_NOTIFIER_HEAD(&notifier->n_head); 162 166 MLX5_NB_INIT(&notifier->nb, mlx5_vhca_state_change_notifier, VHCA_STATE_CHANGE); 163 167 return 0; 168 + 169 + err_notifier: 170 + err_create_wq: 171 + for (--i; i >= 0; i--) 172 + destroy_workqueue(events->handler[i].wq); 173 + kfree(events); 174 + return err; 175 + } 176 + 177 + void mlx5_vhca_event_work_queues_flush(struct mlx5_core_dev *dev) 178 + { 179 + struct mlx5_vhca_events *vhca_events; 180 + int i; 181 + 182 + if (!mlx5_vhca_event_supported(dev)) 183 + return; 184 + 185 + vhca_events = dev->priv.vhca_events; 186 + for (i = 0; i < MLX5_DEV_MAX_WQS; i++) 187 + flush_workqueue(vhca_events->handler[i].wq); 164 188 } 165 189 166 190 void mlx5_vhca_event_cleanup(struct mlx5_core_dev *dev) 167 191 { 192 + struct mlx5_vhca_events *vhca_events; 193 + int i; 194 + 168 195 if (!mlx5_vhca_event_supported(dev)) 169 196 return; 170 197 171 198 kfree(dev->priv.vhca_state_notifier); 172 199 dev->priv.vhca_state_notifier = NULL; 200 + vhca_events = dev->priv.vhca_events; 201 + for (i = 0; i < MLX5_DEV_MAX_WQS; i++) 202 + destroy_workqueue(vhca_events->handler[i].wq); 203 + kvfree(vhca_events); 173 204 } 174 205 175 206 void mlx5_vhca_event_start(struct mlx5_core_dev *dev)
+3
drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.h
··· 28 28 int mlx5_vhca_event_arm(struct mlx5_core_dev *dev, u16 function_id); 29 29 int mlx5_cmd_query_vhca_state(struct mlx5_core_dev *dev, u16 function_id, 30 30 u32 *out, u32 outlen); 31 + void mlx5_vhca_events_work_enqueue(struct mlx5_core_dev *dev, int idx, struct work_struct *work); 32 + void mlx5_vhca_event_work_queues_flush(struct mlx5_core_dev *dev); 33 + 31 34 #else 32 35 33 36 static inline void mlx5_vhca_state_cap_handle(struct mlx5_core_dev *dev, void *set_hca_cap)
-4
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
··· 436 436 struct mlx5dr_ste_build *sb, 437 437 struct mlx5dr_match_param *mask, 438 438 bool inner, bool rx); 439 - void mlx5dr_ste_build_tnl_mpls(struct mlx5dr_ste_ctx *ste_ctx, 440 - struct mlx5dr_ste_build *sb, 441 - struct mlx5dr_match_param *mask, 442 - bool inner, bool rx); 443 439 void mlx5dr_ste_build_tnl_mpls_over_gre(struct mlx5dr_ste_ctx *ste_ctx, 444 440 struct mlx5dr_ste_build *sb, 445 441 struct mlx5dr_match_param *mask,
+2 -14
include/linux/mlx5/driver.h
··· 615 615 int adev_idx; 616 616 int sw_vhca_id; 617 617 struct mlx5_events *events; 618 + struct mlx5_vhca_events *vhca_events; 618 619 619 620 struct mlx5_flow_steering *steering; 620 621 struct mlx5_mpfs *mpfs; ··· 624 623 struct mlx5_lag *lag; 625 624 u32 flags; 626 625 struct mlx5_devcom_dev *devc; 626 + struct mlx5_devcom_comp_dev *hca_devcom_comp; 627 627 struct mlx5_fw_reset *fw_reset; 628 628 struct mlx5_core_roce roce; 629 629 struct mlx5_fc_stats fc_stats; ··· 1043 1041 int mlx5_frag_buf_alloc_node(struct mlx5_core_dev *dev, int size, 1044 1042 struct mlx5_frag_buf *buf, int node); 1045 1043 void mlx5_frag_buf_free(struct mlx5_core_dev *dev, struct mlx5_frag_buf *buf); 1046 - struct mlx5_cmd_mailbox *mlx5_alloc_cmd_mailbox_chain(struct mlx5_core_dev *dev, 1047 - gfp_t flags, int npages); 1048 - void mlx5_free_cmd_mailbox_chain(struct mlx5_core_dev *dev, 1049 - struct mlx5_cmd_mailbox *head); 1050 1044 int mlx5_core_create_mkey(struct mlx5_core_dev *dev, u32 *mkey, u32 *in, 1051 1045 int inlen); 1052 1046 int mlx5_core_destroy_mkey(struct mlx5_core_dev *dev, u32 mkey); ··· 1056 1058 void mlx5_pagealloc_stop(struct mlx5_core_dev *dev); 1057 1059 void mlx5_pages_debugfs_init(struct mlx5_core_dev *dev); 1058 1060 void mlx5_pages_debugfs_cleanup(struct mlx5_core_dev *dev); 1059 - void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, 1060 - s32 npages, bool ec_function); 1061 1061 int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot); 1062 1062 int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev); 1063 1063 void mlx5_register_debugfs(void); ··· 1095 1099 int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num); 1096 1100 __be32 mlx5_core_get_terminate_scatter_list_mkey(struct mlx5_core_dev *dev); 1097 1101 void mlx5_core_put_rsc(struct mlx5_core_rsc_common *common); 1098 - int mlx5_query_odp_caps(struct mlx5_core_dev *dev, 1099 - struct mlx5_odp_caps *odp_caps); 1100 1102 1101 1103 int mlx5_init_rl_table(struct mlx5_core_dev *dev); 1102 1104 void mlx5_cleanup_rl_table(struct mlx5_core_dev *dev); ··· 1196 1202 void mlx5_sriov_blocking_notifier_unregister(struct mlx5_core_dev *mdev, 1197 1203 int vf_id, 1198 1204 struct notifier_block *nb); 1199 - #ifdef CONFIG_MLX5_CORE_IPOIB 1200 - struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, 1201 - struct ib_device *ibdev, 1202 - const char *name, 1203 - void (*setup)(struct net_device *)); 1204 - #endif /* CONFIG_MLX5_CORE_IPOIB */ 1205 1205 int mlx5_rdma_rn_get_params(struct mlx5_core_dev *mdev, 1206 1206 struct ib_device *device, 1207 1207 struct rdma_netdev_alloc_params *params);