xref: /openbmc/linux/drivers/infiniband/hw/mlx5/umr.c (revision ba6a9c6899b2dce3c615ce9fac6bead976e43a48)
104876c12SAharon Landau // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
204876c12SAharon Landau /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
304876c12SAharon Landau 
404876c12SAharon Landau #include "mlx5_ib.h"
504876c12SAharon Landau #include "umr.h"
604876c12SAharon Landau 
78a8a5d37SAharon Landau static __be64 get_umr_enable_mr_mask(void)
88a8a5d37SAharon Landau {
98a8a5d37SAharon Landau 	u64 result;
108a8a5d37SAharon Landau 
118a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_KEY |
128a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_FREE;
138a8a5d37SAharon Landau 
148a8a5d37SAharon Landau 	return cpu_to_be64(result);
158a8a5d37SAharon Landau }
168a8a5d37SAharon Landau 
178a8a5d37SAharon Landau static __be64 get_umr_disable_mr_mask(void)
188a8a5d37SAharon Landau {
198a8a5d37SAharon Landau 	u64 result;
208a8a5d37SAharon Landau 
218a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_FREE;
228a8a5d37SAharon Landau 
238a8a5d37SAharon Landau 	return cpu_to_be64(result);
248a8a5d37SAharon Landau }
258a8a5d37SAharon Landau 
268a8a5d37SAharon Landau static __be64 get_umr_update_translation_mask(void)
278a8a5d37SAharon Landau {
288a8a5d37SAharon Landau 	u64 result;
298a8a5d37SAharon Landau 
308a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_LEN |
318a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_PAGE_SIZE |
328a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_START_ADDR;
338a8a5d37SAharon Landau 
348a8a5d37SAharon Landau 	return cpu_to_be64(result);
358a8a5d37SAharon Landau }
368a8a5d37SAharon Landau 
37*ba6a9c68SAharon Landau static __be64 get_umr_update_access_mask(struct mlx5_ib_dev *dev)
388a8a5d37SAharon Landau {
398a8a5d37SAharon Landau 	u64 result;
408a8a5d37SAharon Landau 
418a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_LR |
428a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_LW |
438a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_RR |
448a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_RW;
458a8a5d37SAharon Landau 
46*ba6a9c68SAharon Landau 	if (MLX5_CAP_GEN(dev->mdev, atomic))
478a8a5d37SAharon Landau 		result |= MLX5_MKEY_MASK_A;
488a8a5d37SAharon Landau 
49*ba6a9c68SAharon Landau 	if (MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr))
508a8a5d37SAharon Landau 		result |= MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE;
518a8a5d37SAharon Landau 
52*ba6a9c68SAharon Landau 	if (MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))
538a8a5d37SAharon Landau 		result |= MLX5_MKEY_MASK_RELAXED_ORDERING_READ;
548a8a5d37SAharon Landau 
558a8a5d37SAharon Landau 	return cpu_to_be64(result);
568a8a5d37SAharon Landau }
578a8a5d37SAharon Landau 
588a8a5d37SAharon Landau static __be64 get_umr_update_pd_mask(void)
598a8a5d37SAharon Landau {
608a8a5d37SAharon Landau 	u64 result;
618a8a5d37SAharon Landau 
628a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_PD;
638a8a5d37SAharon Landau 
648a8a5d37SAharon Landau 	return cpu_to_be64(result);
658a8a5d37SAharon Landau }
668a8a5d37SAharon Landau 
678a8a5d37SAharon Landau static int umr_check_mkey_mask(struct mlx5_ib_dev *dev, u64 mask)
688a8a5d37SAharon Landau {
698a8a5d37SAharon Landau 	if (mask & MLX5_MKEY_MASK_PAGE_SIZE &&
708a8a5d37SAharon Landau 	    MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))
718a8a5d37SAharon Landau 		return -EPERM;
728a8a5d37SAharon Landau 
738a8a5d37SAharon Landau 	if (mask & MLX5_MKEY_MASK_A &&
748a8a5d37SAharon Landau 	    MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled))
758a8a5d37SAharon Landau 		return -EPERM;
768a8a5d37SAharon Landau 
778a8a5d37SAharon Landau 	if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE &&
788a8a5d37SAharon Landau 	    !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr))
798a8a5d37SAharon Landau 		return -EPERM;
808a8a5d37SAharon Landau 
818a8a5d37SAharon Landau 	if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_READ &&
828a8a5d37SAharon Landau 	    !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))
838a8a5d37SAharon Landau 		return -EPERM;
848a8a5d37SAharon Landau 
858a8a5d37SAharon Landau 	return 0;
868a8a5d37SAharon Landau }
878a8a5d37SAharon Landau 
888a8a5d37SAharon Landau int mlx5r_umr_set_umr_ctrl_seg(struct mlx5_ib_dev *dev,
898a8a5d37SAharon Landau 			       struct mlx5_wqe_umr_ctrl_seg *umr,
908a8a5d37SAharon Landau 			       const struct ib_send_wr *wr)
918a8a5d37SAharon Landau {
928a8a5d37SAharon Landau 	const struct mlx5_umr_wr *umrwr = umr_wr(wr);
938a8a5d37SAharon Landau 
948a8a5d37SAharon Landau 	memset(umr, 0, sizeof(*umr));
958a8a5d37SAharon Landau 
968a8a5d37SAharon Landau 	if (!umrwr->ignore_free_state) {
978a8a5d37SAharon Landau 		if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE)
988a8a5d37SAharon Landau 			 /* fail if free */
998a8a5d37SAharon Landau 			umr->flags = MLX5_UMR_CHECK_FREE;
1008a8a5d37SAharon Landau 		else
1018a8a5d37SAharon Landau 			/* fail if not free */
1028a8a5d37SAharon Landau 			umr->flags = MLX5_UMR_CHECK_NOT_FREE;
1038a8a5d37SAharon Landau 	}
1048a8a5d37SAharon Landau 
1058a8a5d37SAharon Landau 	umr->xlt_octowords =
1068a8a5d37SAharon Landau 		cpu_to_be16(mlx5r_umr_get_xlt_octo(umrwr->xlt_size));
1078a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_XLT) {
1088a8a5d37SAharon Landau 		u64 offset = mlx5r_umr_get_xlt_octo(umrwr->offset);
1098a8a5d37SAharon Landau 
1108a8a5d37SAharon Landau 		umr->xlt_offset = cpu_to_be16(offset & 0xffff);
1118a8a5d37SAharon Landau 		umr->xlt_offset_47_16 = cpu_to_be32(offset >> 16);
1128a8a5d37SAharon Landau 		umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN;
1138a8a5d37SAharon Landau 	}
1148a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION)
1158a8a5d37SAharon Landau 		umr->mkey_mask |= get_umr_update_translation_mask();
1168a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS) {
117*ba6a9c68SAharon Landau 		umr->mkey_mask |= get_umr_update_access_mask(dev);
1188a8a5d37SAharon Landau 		umr->mkey_mask |= get_umr_update_pd_mask();
1198a8a5d37SAharon Landau 	}
1208a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_ENABLE_MR)
1218a8a5d37SAharon Landau 		umr->mkey_mask |= get_umr_enable_mr_mask();
1228a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_DISABLE_MR)
1238a8a5d37SAharon Landau 		umr->mkey_mask |= get_umr_disable_mr_mask();
1248a8a5d37SAharon Landau 
1258a8a5d37SAharon Landau 	if (!wr->num_sge)
1268a8a5d37SAharon Landau 		umr->flags |= MLX5_UMR_INLINE;
1278a8a5d37SAharon Landau 
1288a8a5d37SAharon Landau 	return umr_check_mkey_mask(dev, be64_to_cpu(umr->mkey_mask));
1298a8a5d37SAharon Landau }
1308a8a5d37SAharon Landau 
13104876c12SAharon Landau enum {
13204876c12SAharon Landau 	MAX_UMR_WR = 128,
13304876c12SAharon Landau };
13404876c12SAharon Landau 
13504876c12SAharon Landau static int mlx5r_umr_qp_rst2rts(struct mlx5_ib_dev *dev, struct ib_qp *qp)
13604876c12SAharon Landau {
13704876c12SAharon Landau 	struct ib_qp_attr attr = {};
13804876c12SAharon Landau 	int ret;
13904876c12SAharon Landau 
14004876c12SAharon Landau 	attr.qp_state = IB_QPS_INIT;
14104876c12SAharon Landau 	attr.port_num = 1;
14204876c12SAharon Landau 	ret = ib_modify_qp(qp, &attr,
14304876c12SAharon Landau 			   IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT);
14404876c12SAharon Landau 	if (ret) {
14504876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n");
14604876c12SAharon Landau 		return ret;
14704876c12SAharon Landau 	}
14804876c12SAharon Landau 
14904876c12SAharon Landau 	memset(&attr, 0, sizeof(attr));
15004876c12SAharon Landau 	attr.qp_state = IB_QPS_RTR;
15104876c12SAharon Landau 
15204876c12SAharon Landau 	ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
15304876c12SAharon Landau 	if (ret) {
15404876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n");
15504876c12SAharon Landau 		return ret;
15604876c12SAharon Landau 	}
15704876c12SAharon Landau 
15804876c12SAharon Landau 	memset(&attr, 0, sizeof(attr));
15904876c12SAharon Landau 	attr.qp_state = IB_QPS_RTS;
16004876c12SAharon Landau 	ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
16104876c12SAharon Landau 	if (ret) {
16204876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n");
16304876c12SAharon Landau 		return ret;
16404876c12SAharon Landau 	}
16504876c12SAharon Landau 
16604876c12SAharon Landau 	return 0;
16704876c12SAharon Landau }
16804876c12SAharon Landau 
16904876c12SAharon Landau int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)
17004876c12SAharon Landau {
17104876c12SAharon Landau 	struct ib_qp_init_attr init_attr = {};
17204876c12SAharon Landau 	struct ib_pd *pd;
17304876c12SAharon Landau 	struct ib_cq *cq;
17404876c12SAharon Landau 	struct ib_qp *qp;
17504876c12SAharon Landau 	int ret;
17604876c12SAharon Landau 
17704876c12SAharon Landau 	pd = ib_alloc_pd(&dev->ib_dev, 0);
17804876c12SAharon Landau 	if (IS_ERR(pd)) {
17904876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n");
18004876c12SAharon Landau 		return PTR_ERR(pd);
18104876c12SAharon Landau 	}
18204876c12SAharon Landau 
18304876c12SAharon Landau 	cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ);
18404876c12SAharon Landau 	if (IS_ERR(cq)) {
18504876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n");
18604876c12SAharon Landau 		ret = PTR_ERR(cq);
18704876c12SAharon Landau 		goto destroy_pd;
18804876c12SAharon Landau 	}
18904876c12SAharon Landau 
19004876c12SAharon Landau 	init_attr.send_cq = cq;
19104876c12SAharon Landau 	init_attr.recv_cq = cq;
19204876c12SAharon Landau 	init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
19304876c12SAharon Landau 	init_attr.cap.max_send_wr = MAX_UMR_WR;
19404876c12SAharon Landau 	init_attr.cap.max_send_sge = 1;
19504876c12SAharon Landau 	init_attr.qp_type = MLX5_IB_QPT_REG_UMR;
19604876c12SAharon Landau 	init_attr.port_num = 1;
19704876c12SAharon Landau 	qp = ib_create_qp(pd, &init_attr);
19804876c12SAharon Landau 	if (IS_ERR(qp)) {
19904876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n");
20004876c12SAharon Landau 		ret = PTR_ERR(qp);
20104876c12SAharon Landau 		goto destroy_cq;
20204876c12SAharon Landau 	}
20304876c12SAharon Landau 
20404876c12SAharon Landau 	ret = mlx5r_umr_qp_rst2rts(dev, qp);
20504876c12SAharon Landau 	if (ret)
20604876c12SAharon Landau 		goto destroy_qp;
20704876c12SAharon Landau 
20804876c12SAharon Landau 	dev->umrc.qp = qp;
20904876c12SAharon Landau 	dev->umrc.cq = cq;
21004876c12SAharon Landau 	dev->umrc.pd = pd;
21104876c12SAharon Landau 
21204876c12SAharon Landau 	sema_init(&dev->umrc.sem, MAX_UMR_WR);
21304876c12SAharon Landau 
21404876c12SAharon Landau 	return 0;
21504876c12SAharon Landau 
21604876c12SAharon Landau destroy_qp:
21704876c12SAharon Landau 	ib_destroy_qp(qp);
21804876c12SAharon Landau destroy_cq:
21904876c12SAharon Landau 	ib_free_cq(cq);
22004876c12SAharon Landau destroy_pd:
22104876c12SAharon Landau 	ib_dealloc_pd(pd);
22204876c12SAharon Landau 	return ret;
22304876c12SAharon Landau }
22404876c12SAharon Landau 
22504876c12SAharon Landau void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev)
22604876c12SAharon Landau {
22704876c12SAharon Landau 	ib_destroy_qp(dev->umrc.qp);
22804876c12SAharon Landau 	ib_free_cq(dev->umrc.cq);
22904876c12SAharon Landau 	ib_dealloc_pd(dev->umrc.pd);
23004876c12SAharon Landau }
231