Delay mlx5_ib internal resources allocations
Subsystems (5)
cover Delay mlx5_ib internal resources allocations
From: Leon Romanovsky <[email protected]>
Internal mlx5_ib resources are created during mlx5_ib module load. This behavior is not optimal because it consumes resources that are not needed when SFs are created. This patch series delays the creation of mlx5_ib internal resources to the stage when they actually used.
Thanks
Jianbo Liu (3):
net/mlx5: Reimplement write combining test
IB/mlx5: Create UMR QP just before first reg_mr occurs IB/mlx5: Allocate resources just before first QP/SRQ is created
drivers/infiniband/hw/mlx5/main.c | 171 ++++--- drivers/infiniband/hw/mlx5/mem.c | 198 -------- drivers/infiniband/hw/mlx5/mlx5_ib.h | 9 +- drivers/infiniband/hw/mlx5/mr.c | 9 + drivers/infiniband/hw/mlx5/qp.c | 20 +- drivers/infiniband/hw/mlx5/srq.c | 4 + drivers/infiniband/hw/mlx5/umr.c | 55 ++- drivers/infiniband/hw/mlx5/umr.h | 3 + .../net/ethernet/mellanox/mlx5/core/Makefile | 2 +- .../net/ethernet/mellanox/mlx5/core/main.c | 2 + drivers/net/ethernet/mellanox/mlx5/core/wc.c | 434 ++++++++++++++++++ include/linux/mlx5/driver.h | 11 + 12 files changed, 627 insertions(+), 291 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/wc.c
Signature · 1 line
2.45.1
PATCH 1/3 net/mlx5: Reimplement write combining test
From: Jianbo Liu <[email protected]>
The test of write combining was added before in mlx5_ib driver. It opens UD QP and posts NOP WQEs, and uses BlueFlame doorbell. When BlueFlame is used, WQEs get written directly to a PCI BAR of the device (in addition to memory) so that the device handles them without having to access memory.
In this test, the WQEs written in memory are different from the ones written to the BlueFlame which request CQE update. By checking the completion reports posted on CQ, we can know if BlueFlame succeeds or not. The write combining must be supported if BlueFlame succeeds as its register is written using write combining.
This patch reimplements the test in the same way, but using a pair of SQ and CQ only. It is moved to mlx5_core as a general feature used by both mlx5_core and mlx5_ib.
Besides, save write combine test result of the PCI function, so that its thousands of child functions such as SF can query without paying the time and resource penalty by itself. The test function is called only after failing to get the cached result. With this enhancement, all thousands of SFs of the PF attached to same driver no longer need to perform WC check explicitly, which is already done in the system. This saves several commands per SF, thereby speeds up SF creation and also saves completion EQ creation.
--- drivers/infiniband/hw/mlx5/main.c | 19 +- drivers/infiniband/hw/mlx5/mem.c | 198 -------- drivers/infiniband/hw/mlx5/mlx5_ib.h | 3 - drivers/infiniband/hw/mlx5/qp.c | 16 - .../net/ethernet/mellanox/mlx5/core/Makefile | 2 +- .../net/ethernet/mellanox/mlx5/core/main.c | 2 + drivers/net/ethernet/mellanox/mlx5/core/wc.c | 434 ++++++++++++++++++ include/linux/mlx5/driver.h | 11 + 8 files changed, 451 insertions(+), 234 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/wc.c
drivers/infiniband/hw/mlx5/main.c +3 -16
@@ -1841,7 +1841,7 @@ static int set_ucontext_resp(struct ib_ucontext *uctx, } resp->qp_tab_size =1 <<MLX5_CAP_GEN (dev->mdev, log_max_qp); -if (dev->wc_support) +if (mlx5_wc_support_get (dev->mdev)) resp->bf_reg_size =1 <<MLX5_CAP_GEN (dev->mdev, log_bf_reg_size); resp->cache_line_size =cache_line_size ();
@@ -2368,7 +2368,7 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vmswitch (command) {case MLX5_IB_MMAP_WC_PAGE :case MLX5_IB_MMAP_ALLOC_WC : -if (!dev->wc_support) +if (!mlx5_wc_support_get (dev->mdev))return -EPERM ; fallthrough;case MLX5_IB_MMAP_NC_PAGE :
@@ -3643,7 +3643,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_UAR_OBJ_ALLOC)( alloc_type != MLX5_IB_UAPI_UAR_ALLOC_TYPE_NC)return -EOPNOTSUPP ; -if (!to_mdev (c->ibucontext.device)->wc_support && +if (!mlx5_wc_support_get (to_mdev (c->ibucontext.device)->mdev) && alloc_type ==MLX5_IB_UAPI_UAR_ALLOC_TYPE_BF )return -EOPNOTSUPP ;
@@ -3797,18 +3797,6 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)return err; } -static int mlx5_ib_enable_driver (struct ib_device *dev) -{ -struct mlx5_ib_dev *mdev =to_mdev (dev); -int ret; - - ret =mlx5_ib_test_wc (mdev); -mlx5_ib_dbg (mdev,"Write-Combining %s" , - mdev->wc_support ?"supported" :"not supported" ); - -return ret; -} -static const struct ib_device_ops mlx5_ib_dev_ops = { .owner =THIS_MODULE , .driver_id =RDMA_DRIVER_MLX5 ,
@@ -3839,7 +3827,6 @@ static const struct ib_device_ops mlx5_ib_dev_ops = { .drain_rq = mlx5_ib_drain_rq, .drain_sq = mlx5_ib_drain_sq, .device_group = &mlx5_attr_group, - .enable_driver = mlx5_ib_enable_driver, .get_dev_fw_str = get_dev_fw_str, .get_dma_mr = mlx5_ib_get_dma_mr, .get_link_layer = mlx5_ib_port_link_layer,
drivers/infiniband/hw/mlx5/mem.c +0 -198
209 lines not on this page · raw message
drivers/infiniband/hw/mlx5/mlx5_ib.h +0 -3
@@ -341,7 +341,6 @@ struct mlx5_ib_flow_db {* rely on the range reserved for that use in the ib_qp_create_flags enum. */ #define MLX5_IB_QP_CREATE_SQPN_QP1 IB_QP_CREATE_RESERVED_START -#define MLX5_IB_QP_CREATE_WC_TEST (IB_QP_CREATE_RESERVED_START << 1)struct wr_list {u16 opcode;
@@ -1123,7 +1122,6 @@ struct mlx5_ib_dev {bool ib_active; u8 is_rep:1; u8 lag_active:1; - u8 wc_support:1;u8 fill_delay;struct umr_common umrc;/* sync used page count stats
@@ -1149,7 +1147,6 @@ struct mlx5_ib_dev {/* Array with num_ports elements */ struct mlx5_ib_port *port;struct mlx5_sq_bfreg bfreg; -struct mlx5_sq_bfreg wc_bfreg;struct mlx5_sq_bfreg fp_bfreg;struct mlx5_ib_delay_drop delay_drop;const struct mlx5_ib_profile *profile;
drivers/infiniband/hw/mlx5/qp.c +0 -16
@@ -1109,8 +1109,6 @@ static int _create_kernel_qp(struct mlx5_ib_dev *dev,if (init_attr->qp_type ==MLX5_IB_QPT_REG_UMR ) qp->bf.bfreg = &dev->fp_bfreg; -else if (qp->flags &MLX5_IB_QP_CREATE_WC_TEST ) - qp->bf.bfreg = &dev->wc_bfreg;else qp->bf.bfreg = &dev->bfreg;
@@ -2961,14 +2959,6 @@ static void process_create_flag(struct mlx5_ib_dev *dev, int *flags, int flag,return ; } -if (flag ==MLX5_IB_QP_CREATE_WC_TEST ) { -/* -* Special case, if condition didn't meet, it won't be error, -* just different in-kernel flow. -*/ - *flags &= ~MLX5_IB_QP_CREATE_WC_TEST ; -return ; - }mlx5_ib_dbg (dev,"Verbs create QP flag 0x%X is not supported\n" , flag); }
@@ -3029,8 +3019,6 @@ static int process_create_flags(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,IB_QP_CREATE_PCI_WRITE_END_PADDING , MLX5_CAP_GEN(mdev, end_pad), qp); -process_create_flag (dev, &create_flags,MLX5_IB_QP_CREATE_WC_TEST , - qp_type !=MLX5_IB_QPT_REG_UMR , qp);process_create_flag (dev, &create_flags,MLX5_IB_QP_CREATE_SQPN_QP1 , true, qp);
@@ -4611,10 +4599,6 @@ static bool mlx5_ib_modify_qp_allowed(struct mlx5_ib_dev *dev,if (qp->type ==IB_QPT_RAW_PACKET || qp->type ==MLX5_IB_QPT_REG_UMR )return true; -/* Internal QP used for wc testing, with NOPs in wq */ -if (qp->flags &MLX5_IB_QP_CREATE_WC_TEST ) -return true; -return false; }
drivers/net/ethernet/mellanox/mlx5/core/Makefile +1 -1
@@ -17,7 +17,7 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \ fs_counters.o fs_ft_pool.o rl.o lag/debugfs.o lag/lag.o dev.o events.o wq.o lib/gid.o \ lib/devcom.o lib/pci_vsc.o lib/dm.o lib/fs_ttc.o diag/fs_tracepoint.o \ diag/fw_tracer.o diag/crdump.o devlink.o diag/rsc_dump.o diag/reporter_vnic.o \ - fw_reset.o qos.o lib/tout.o lib/aso.o + fw_reset.o qos.o lib/tout.o lib/aso.o wc.o # # Netdev basic
drivers/net/ethernet/mellanox/mlx5/core/main.c +2 -0
@@ -1816,6 +1816,7 @@ int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx)mutex_init (&dev->intf_state_mutex);lockdep_set_class (&dev->intf_state_mutex, &dev->lock_key);mutex_init (&dev->mlx5e_res.uplink_netdev_lock); +mutex_init (&dev->wc_state_lock);mutex_init (&priv->bfregs.reg_head.lock);mutex_init (&priv->bfregs.wc_head.lock);
@@ -1913,6 +1914,7 @@ void mlx5_mdev_uninit(struct mlx5_core_dev *dev)mutex_destroy (&priv->alloc_mutex);mutex_destroy (&priv->bfregs.wc_head.lock);mutex_destroy (&priv->bfregs.reg_head.lock); +mutex_destroy (&dev->wc_state_lock);mutex_destroy (&dev->mlx5e_res.uplink_netdev_lock);mutex_destroy (&dev->intf_state_mutex);lockdep_unregister_key (&dev->lock_key);
drivers/net/ethernet/mellanox/mlx5/core/wc.c new file +434 -0
434 lines not on this page · raw message
include/linux/mlx5/driver.h +11 -0
@@ -766,6 +766,12 @@ struct mlx5_hca_cap {u32 max[MLX5_UN_SZ_DW (hca_cap_union)]; }; +enum mlx5_wc_state { +MLX5_WC_STATE_UNINITIALIZED , +MLX5_WC_STATE_UNSUPPORTED , +MLX5_WC_STATE_SUPPORTED , +}; +struct mlx5_core_dev {struct device *device;enum mlx5_coredev_type coredev_type;
@@ -824,6 +830,9 @@ struct mlx5_core_dev {#endif u64 num_ipsec_offloads;struct mlx5_sd *sd; +enum mlx5_wc_state wc_state; +/* sync write combining state */ +struct mutex wc_state_lock; };struct mlx5_db {
@@ -1377,4 +1386,6 @@ static inline bool mlx5_is_macsec_roce_supported(struct mlx5_core_dev *mdev)enum {MLX5_OCTWORD =16 , }; + +bool mlx5_wc_support_get (struct mlx5_core_dev *mdev);#endif /* MLX5_DRIVER_H */
Signature · 1 line
2.45.1
PATCH 2/3 IB/mlx5: Create UMR QP just before first reg_mr occurs
In reply to Leon RomanovskyFrom: Jianbo Liu <[email protected]>
UMR QP is not used in some cases, so move QP and its CQ creations from driver load flow to the time first reg_mr occurs, that is when MR interfaces are first called.
The initialization of dev->umrc.pd and dev->umrc.lock is still done in driver load because pd is needed for mlx5_mkey_cache_init and the lock is reused to protect against the concurrent creation.
When testing 4G bytes memory registration latency with rtool [1] and 8 threads in parallel, there is minor performance degradation (<5% for the max latency) is seen for the first reg_mr with this change.
--- drivers/infiniband/hw/mlx5/main.c | 3 +- drivers/infiniband/hw/mlx5/mlx5_ib.h | 2 + drivers/infiniband/hw/mlx5/mr.c | 9 +++++ drivers/infiniband/hw/mlx5/umr.c | 55 +++++++++++++++++++++------- drivers/infiniband/hw/mlx5/umr.h | 3 ++ 5 files changed, 58 insertions(+), 14 deletions(-)
drivers/infiniband/hw/mlx5/main.c +2 -1
@@ -4117,6 +4117,7 @@ static void mlx5_ib_stage_pre_ib_reg_umr_cleanup(struct mlx5_ib_dev *dev) {mlx5_mkey_cache_cleanup (dev);mlx5r_umr_resource_cleanup (dev); +mlx5r_umr_cleanup (dev); }static void mlx5_ib_stage_ib_reg_cleanup (struct mlx5_ib_dev *dev)
@@ -4128,7 +4129,7 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev) {int ret; - ret =mlx5r_umr_resource_init (dev); + ret =mlx5r_umr_init (dev);if (ret)return ret;
drivers/infiniband/hw/mlx5/mlx5_ib.h +2 -0
@@ -751,6 +751,8 @@ struct umr_common {*/ struct mutex lock;unsigned int state; +/* Protects from repeat UMR QP creation */ +struct mutex init_lock; };#define NUM_MKEYS_PER_PAGE \
drivers/infiniband/hw/mlx5/mr.c +9 -0
@@ -1480,6 +1480,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, {struct mlx5_ib_dev *dev =to_mdev (pd->device);struct ib_umem *umem; +int err;if (!IS_ENABLED (CONFIG_INFINIBAND_USER_MEM ))return ERR_PTR (-EOPNOTSUPP );
@@ -1487,6 +1488,10 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,mlx5_ib_dbg (dev,"start 0x%llx, iova 0x%llx, length 0x%llx, access_flags 0x%x\n" , start, iova, length, access_flags); + err =mlx5r_umr_resource_init (dev); +if (err) +return ERR_PTR (err); +if (access_flags &IB_ACCESS_ON_DEMAND )return create_user_odp_mr (pd, start, length, iova, access_flags, udata);
@@ -1534,6 +1539,10 @@ struct ib_mr *mlx5_ib_reg_user_mr_dmabuf(struct ib_pd *pd, u64 offset,"offset 0x%llx, virt_addr 0x%llx, length 0x%llx, fd %d, access_flags 0x%x\n" , offset, virt_addr, length, fd, access_flags); + err =mlx5r_umr_resource_init (dev); +if (err) +return ERR_PTR (err); +/* dmabuf requires xlt update via umr to work. */ if (!mlx5r_umr_can_load_pas (dev, length))return ERR_PTR (-EINVAL );
drivers/infiniband/hw/mlx5/umr.c +42 -13
101 lines not on this page · raw message
drivers/infiniband/hw/mlx5/umr.h +3 -0
@@ -16,6 +16,9 @@int mlx5r_umr_resource_init (struct mlx5_ib_dev *dev);void mlx5r_umr_resource_cleanup (struct mlx5_ib_dev *dev); +int mlx5r_umr_init (struct mlx5_ib_dev *dev); +void mlx5r_umr_cleanup (struct mlx5_ib_dev *dev); +static inline bool mlx5r_umr_can_load_pas (struct mlx5_ib_dev *dev,size_t length) {
Signature · 1 line
2.45.1
Jason Gunthorpe
maintainerRe: [PATCH rdma-next 2/3] IB/mlx5: Create UMR QP just before first reg_mr occurs
Quoted 5 lines · Leon Romanovsky
From: Jianbo Liu <[email protected]>
UMR QP is not used in some cases, so move QP and its CQ creations from driver load flow to the time first
reg_mroccurs, that is when MR interfaces are first called.
We use UMR for kernel MRs too, don't we?
Jason
Re: [PATCH rdma-next 2/3] IB/mlx5: Create UMR QP just before first reg_mr occurs
Quoted 8 lines · Jason Gunthorpe
Quoted 5 lines · Leon Romanovsky
From: Jianbo Liu <[email protected]>
UMR QP is not used in some cases, so move QP and its CQ creations from driver load flow to the time first
reg_mroccurs, that is when MR interfaces are first called.We use UMR for kernel MRs too, don't we?
Strange, I know that I answered to this email, but I don't see it in the ML.
As far as I checked, we are not. Did I miss something?
Thanks
Quoted 2 lines
Jason
Re: [PATCH rdma-next 2/3] IB/mlx5: Create UMR QP just before first reg_mr occurs
Quoted 8 lines · Leon Romanovsky
Quoted 7 lines · Jason Gunthorpe
Quoted 5 lines · Leon Romanovsky
From: Jianbo Liu <[email protected]>
UMR QP is not used in some cases, so move QP and its CQ creations from driver load flow to the time first
reg_mroccurs, that is when MR interfaces are first called.
Quoted 5 lines
Quoted 1 line
We use UMR for kernel MRs too, don't we?
Strange, I know that I answered to this email, but I don't see it in the ML.
As far as I checked, we are not. Did I miss something?
I have also found this problem. IMO, 2 reasons:
1. Delay in maillist. That is, there is a delay between a mail sent out and this mail appearing in maillist. We will find this mail in the maillist after some time.
2. sometimes, we forget to include maillist.^_^
Zhu Yanjun
Quoted 5 lines
Thanks
Quoted 2 lines
Jason
Re: [PATCH rdma-next 2/3] IB/mlx5: Create UMR QP just before first reg_mr occurs
Quoted 13 lines · Zhu Yanjun
Quoted 12 lines · Leon Romanovsky
Quoted 8 lines · Jason Gunthorpe
Quoted 5 lines · Leon Romanovsky
From: Jianbo Liu <[email protected]>
UMR QP is not used in some cases, so move QP and its CQ creations from driver load flow to the time first
reg_mroccurs, that is when MR interfaces are first called.We use UMR for kernel MRs too, don't we?
Strange, I know that I answered to this email, but I don't see it in the ML.
Quoted 8 lines
Quoted 1 line
As far as I checked, we are not. Did I miss something?
I have also found this problem. IMO, 2 reasons:
1. Delay in maillist. That is, there is a delay between a mail sent out and this mail appearing in maillist. We will find this mail in the maillist after some time.2. sometimes, we forget to include maillist.^_^
I replied on Jun, 7th.
Thanks
Quoted 9 lines
Zhu Yanjun
Quoted 5 lines
Thanks
Quoted 2 lines
Jason
Re: [PATCH rdma-next 2/3] IB/mlx5: Create UMR QP just before first reg_mr occurs
In reply to Leon RomanovskyQuoted 8 lines · Leon Romanovsky
Quoted 7 lines · Jason Gunthorpe
Quoted 5 lines · Leon Romanovsky
From: Jianbo Liu <[email protected]>
UMR QP is not used in some cases, so move QP and its CQ creations from driver load flow to the time first
reg_mroccurs, that is when MR interfaces are first called.
Quoted 5 lines
Quoted 1 line
We use UMR for kernel MRs too, don't we?
Strange, I know that I answered to this email, but I don't see it in the ML.
As far as I checked, we are not. Did I miss something?
Maybe not, but maybe we should be using UMR there..
Jason
PATCH 3/3 IB/mlx5: Allocate resources just before first QP/SRQ is created
In reply to Leon RomanovskyFrom: Jianbo Liu <[email protected]>
Previously, all IB dev resources are initialized on driver load. As they are not always used, move the initialization to the time when they are needed.
To be more specific, move PD (p0) and CQ (c0) initialization to the time when the first SRQ is created. and move SRQs(s0 and s1) initialization to the time first QP is created. To avoid concurrent creations, two new mutexes are also added.
--- drivers/infiniband/hw/mlx5/main.c | 149 +++++++++++++++++++-------- drivers/infiniband/hw/mlx5/mlx5_ib.h | 4 + drivers/infiniband/hw/mlx5/qp.c | 4 + drivers/infiniband/hw/mlx5/srq.c | 4 + 4 files changed, 118 insertions(+), 43 deletions(-)
drivers/infiniband/hw/mlx5/main.c +106 -43
@@ -2854,37 +2854,72 @@ static u8 mlx5_get_umr_fence(u8 umr_fence_cap) } } -static int mlx5_ib_dev_res_init (struct mlx5_ib_dev *dev) +int mlx5_ib_dev_res_cq_init (struct mlx5_ib_dev *dev) {struct mlx5_ib_resources *devr = &dev->devr; -struct ib_srq_init_attr attr; -struct ib_device *ibdev;struct ib_cq_init_attr cq_attr = {.cqe =1 }; -int port; +struct ib_device *ibdev; +struct ib_pd *pd; +struct ib_cq *cq;int ret =0 ; - ibdev = &dev->ib_dev; -if (!MLX5_CAP_GEN (dev->mdev, xrc)) -return -EOPNOTSUPP ; +/* +* devr->c0 is set once, never changed until device unload. +* Avoid taking the mutex if initialization is already done. +*/ +if (devr->c0) +return 0 ; - devr->p0 =ib_alloc_pd (ibdev,0 ); -if (IS_ERR (devr->p0)) -return PTR_ERR (devr->p0); +mutex_lock (&devr->cq_lock); +if (devr->c0) + goto unlock; - devr->c0 =ib_create_cq (ibdev,NULL ,NULL ,NULL , &cq_attr); -if (IS_ERR (devr->c0)) { - ret =PTR_ERR (devr->c0); - goto error1; + ibdev = &dev->ib_dev; + pd =ib_alloc_pd (ibdev,0 ); +if (IS_ERR (pd)) { + ret =PTR_ERR (pd); +mlx5_ib_err (dev,"Couldn't allocate PD for res init, err=%d\n" , ret); + goto unlock; } - ret =mlx5_cmd_xrcd_alloc (dev->mdev, &devr->xrcdn0,0 ); -if (ret) - goto error2; + cq =ib_create_cq (ibdev,NULL ,NULL ,NULL , &cq_attr); +if (IS_ERR (cq)) { + ret =PTR_ERR (cq); +mlx5_ib_err (dev,"Couldn't create CQ for res init, err=%d\n" , ret); +ib_dealloc_pd (pd); + goto unlock; + } - ret =mlx5_cmd_xrcd_alloc (dev->mdev, &devr->xrcdn1,0 ); + devr->p0 = pd; + devr->c0 = cq; + +unlock: +mutex_unlock (&devr->cq_lock); +return ret; +} + +int mlx5_ib_dev_res_srq_init (struct mlx5_ib_dev *dev) +{ +struct mlx5_ib_resources *devr = &dev->devr; +struct ib_srq_init_attr attr; +struct ib_srq *s0, *s1; +int ret =0 ; + +/* +* devr->s1 is set once, never changed until device unload. +* Avoid taking the mutex if initialization is already done. +*/ +if (devr->s1) +return 0 ; + +mutex_lock (&devr->srq_lock); +if (devr->s1) + goto unlock; + + ret =mlx5_ib_dev_res_cq_init (dev);if (ret) - goto error3; + goto unlock;memset (&attr,0 ,sizeof (attr)); attr.attr.max_sge =1 ;
@@ -2892,10 +2927,11 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev) attr.srq_type =IB_SRQT_XRC ; attr.ext.cq = devr->c0; - devr->s0 =ib_create_srq (devr->p0, &attr); -if (IS_ERR (devr->s0)) { - ret =PTR_ERR (devr->s0); - goto err_create; + s0 =ib_create_srq (devr->p0, &attr); +if (IS_ERR (s0)) { + ret =PTR_ERR (s0); +mlx5_ib_err (dev,"Couldn't create SRQ 0 for res init, err=%d\n" , ret); + goto unlock; }memset (&attr,0 ,sizeof (attr));
@@ -2903,29 +2939,48 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev) attr.attr.max_wr =1 ; attr.srq_type =IB_SRQT_BASIC ; - devr->s1 =ib_create_srq (devr->p0, &attr); -if (IS_ERR (devr->s1)) { - ret =PTR_ERR (devr->s1); - goto error6; + s1 =ib_create_srq (devr->p0, &attr); +if (IS_ERR (s1)) { + ret =PTR_ERR (s1); +mlx5_ib_err (dev,"Couldn't create SRQ 1 for res init, err=%d\n" , ret); +ib_destroy_srq (s0); + } + + devr->s0 = s0; + devr->s1 = s1; + +unlock: +mutex_unlock (&devr->srq_lock); +return ret; +} + +static int mlx5_ib_dev_res_init (struct mlx5_ib_dev *dev) +{ +struct mlx5_ib_resources *devr = &dev->devr; +int port; +int ret; + +if (!MLX5_CAP_GEN (dev->mdev, xrc)) +return -EOPNOTSUPP ; + + ret =mlx5_cmd_xrcd_alloc (dev->mdev, &devr->xrcdn0,0 ); +if (ret) +return ret; + + ret =mlx5_cmd_xrcd_alloc (dev->mdev, &devr->xrcdn1,0 ); +if (ret) { +mlx5_cmd_xrcd_dealloc (dev->mdev, devr->xrcdn0,0 ); +return ret; }for (port =0 ; port <ARRAY_SIZE (devr->ports); ++port)INIT_WORK (&devr->ports[port].pkey_change_work, pkey_change_handler); -return 0 ; +mutex_init (&devr->cq_lock); +mutex_init (&devr->srq_lock); -error6: -ib_destroy_srq (devr->s0); -err_create: -mlx5_cmd_xrcd_dealloc (dev->mdev, devr->xrcdn1,0 ); -error3: -mlx5_cmd_xrcd_dealloc (dev->mdev, devr->xrcdn0,0 ); -error2: -ib_destroy_cq (devr->c0); -error1: -ib_dealloc_pd (devr->p0); -return ret; +return 0 ; }static void mlx5_ib_dev_res_cleanup (struct mlx5_ib_dev *dev)
@@ -2942,12 +2997,20 @@ static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev)for (port =0 ; port <ARRAY_SIZE (devr->ports); ++port)cancel_work_sync (&devr->ports[port].pkey_change_work); -ib_destroy_srq (devr->s1); -ib_destroy_srq (devr->s0); +/* After s0/s1 init, they are not unset during the device lifetime. */ +if (devr->s1) { +ib_destroy_srq (devr->s1); +ib_destroy_srq (devr->s0); + }mlx5_cmd_xrcd_dealloc (dev->mdev, devr->xrcdn1,0 );mlx5_cmd_xrcd_dealloc (dev->mdev, devr->xrcdn0,0 ); -ib_destroy_cq (devr->c0); -ib_dealloc_pd (devr->p0); +/* After p0/c0 init, they are not unset during the device lifetime. */ +if (devr->c0) { +ib_destroy_cq (devr->c0); +ib_dealloc_pd (devr->p0); + } +mutex_destroy (&devr->cq_lock); +mutex_destroy (&devr->srq_lock); } static u32 get_core_cap_flags(struct ib_device *ibdev,
drivers/infiniband/hw/mlx5/mlx5_ib.h +4 -0
@@ -824,11 +824,13 @@ struct mlx5_ib_port_resources {struct mlx5_ib_resources {struct ib_cq *c0; +struct mutex cq_lock;u32 xrcdn0;u32 xrcdn1;struct ib_pd *p0;struct ib_srq *s0;struct ib_srq *s1; +struct mutex srq_lock;struct mlx5_ib_port_resources ports[2 ]; };
@@ -1272,6 +1274,8 @@ to_mmmap(struct rdma_user_mmap_entry *rdma_entry) struct mlx5_user_mmap_entry, rdma_entry); } +int mlx5_ib_dev_res_cq_init (struct mlx5_ib_dev *dev); +int mlx5_ib_dev_res_srq_init (struct mlx5_ib_dev *dev);int mlx5_ib_db_map_user (struct mlx5_ib_ucontext *context,unsigned long virt,struct mlx5_db *db);void mlx5_ib_db_unmap_user (struct mlx5_ib_ucontext *context,struct mlx5_db *db);
drivers/infiniband/hw/mlx5/qp.c +4 -0
@@ -3236,6 +3236,10 @@ int mlx5_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,enum ib_qp_type type;int err; + err =mlx5_ib_dev_res_srq_init (dev); +if (err) +return err; + err =check_qp_type (dev, attr, &type);if (err)return err;
drivers/infiniband/hw/mlx5/srq.c +4 -0
@@ -213,6 +213,10 @@ int mlx5_ib_create_srq(struct ib_srq *ib_srq,return -EINVAL ; } + err =mlx5_ib_dev_res_cq_init (dev); +if (err) +return err; +mutex_init (&srq->mutex);spin_lock_init (&srq->lock); srq->msrq.max =roundup_pow_of_two (init_attr->attr.max_wr +1 );
Signature · 1 line
2.45.1
Leon Romanovsky
AppliedRe: (subset) [PATCH rdma-next 0/3] Delay mlx5_ib internal resources allocations
In reply to Leon RomanovskyQuoted 8 lines · Leon Romanovsky
Internal
mlx5_ibresources are created duringmlx5_ibmodule load. This behavior is not optimal because it consumes resources that are not needed when SFs are created. This patch series delays the creation ofmlx5_ibinternal resources to the stage when they actually used.Thanks
[...]
Applied, thanks!
[2/3] IB/mlx5: Create UMR QP just before first reg_mr occurs
https://git.kernel.org/rdma/rdma/c/638420115cc4ad [3/3] IB/mlx5: Allocate resources just before first QP/SRQ is created https://git.kernel.org/rdma/rdma/c/5895e70f2e6e8d
Best regards,
Signature · 1 line
Leon Romanovsky <[email protected]>