xref: /openbmc/linux/drivers/infiniband/hw/mlx5/umr.c (revision 8a8a5d37c7b4334ede6e7121f7b0757ec7a2e2ed)
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 
7*8a8a5d37SAharon Landau static __be64 get_umr_enable_mr_mask(void)
8*8a8a5d37SAharon Landau {
9*8a8a5d37SAharon Landau 	u64 result;
10*8a8a5d37SAharon Landau 
11*8a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_KEY |
12*8a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_FREE;
13*8a8a5d37SAharon Landau 
14*8a8a5d37SAharon Landau 	return cpu_to_be64(result);
15*8a8a5d37SAharon Landau }
16*8a8a5d37SAharon Landau 
17*8a8a5d37SAharon Landau static __be64 get_umr_disable_mr_mask(void)
18*8a8a5d37SAharon Landau {
19*8a8a5d37SAharon Landau 	u64 result;
20*8a8a5d37SAharon Landau 
21*8a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_FREE;
22*8a8a5d37SAharon Landau 
23*8a8a5d37SAharon Landau 	return cpu_to_be64(result);
24*8a8a5d37SAharon Landau }
25*8a8a5d37SAharon Landau 
26*8a8a5d37SAharon Landau static __be64 get_umr_update_translation_mask(void)
27*8a8a5d37SAharon Landau {
28*8a8a5d37SAharon Landau 	u64 result;
29*8a8a5d37SAharon Landau 
30*8a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_LEN |
31*8a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_PAGE_SIZE |
32*8a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_START_ADDR;
33*8a8a5d37SAharon Landau 
34*8a8a5d37SAharon Landau 	return cpu_to_be64(result);
35*8a8a5d37SAharon Landau }
36*8a8a5d37SAharon Landau 
37*8a8a5d37SAharon Landau static __be64 get_umr_update_access_mask(int atomic,
38*8a8a5d37SAharon Landau 					 int relaxed_ordering_write,
39*8a8a5d37SAharon Landau 					 int relaxed_ordering_read)
40*8a8a5d37SAharon Landau {
41*8a8a5d37SAharon Landau 	u64 result;
42*8a8a5d37SAharon Landau 
43*8a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_LR |
44*8a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_LW |
45*8a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_RR |
46*8a8a5d37SAharon Landau 		 MLX5_MKEY_MASK_RW;
47*8a8a5d37SAharon Landau 
48*8a8a5d37SAharon Landau 	if (atomic)
49*8a8a5d37SAharon Landau 		result |= MLX5_MKEY_MASK_A;
50*8a8a5d37SAharon Landau 
51*8a8a5d37SAharon Landau 	if (relaxed_ordering_write)
52*8a8a5d37SAharon Landau 		result |= MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE;
53*8a8a5d37SAharon Landau 
54*8a8a5d37SAharon Landau 	if (relaxed_ordering_read)
55*8a8a5d37SAharon Landau 		result |= MLX5_MKEY_MASK_RELAXED_ORDERING_READ;
56*8a8a5d37SAharon Landau 
57*8a8a5d37SAharon Landau 	return cpu_to_be64(result);
58*8a8a5d37SAharon Landau }
59*8a8a5d37SAharon Landau 
60*8a8a5d37SAharon Landau static __be64 get_umr_update_pd_mask(void)
61*8a8a5d37SAharon Landau {
62*8a8a5d37SAharon Landau 	u64 result;
63*8a8a5d37SAharon Landau 
64*8a8a5d37SAharon Landau 	result = MLX5_MKEY_MASK_PD;
65*8a8a5d37SAharon Landau 
66*8a8a5d37SAharon Landau 	return cpu_to_be64(result);
67*8a8a5d37SAharon Landau }
68*8a8a5d37SAharon Landau 
69*8a8a5d37SAharon Landau static int umr_check_mkey_mask(struct mlx5_ib_dev *dev, u64 mask)
70*8a8a5d37SAharon Landau {
71*8a8a5d37SAharon Landau 	if (mask & MLX5_MKEY_MASK_PAGE_SIZE &&
72*8a8a5d37SAharon Landau 	    MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))
73*8a8a5d37SAharon Landau 		return -EPERM;
74*8a8a5d37SAharon Landau 
75*8a8a5d37SAharon Landau 	if (mask & MLX5_MKEY_MASK_A &&
76*8a8a5d37SAharon Landau 	    MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled))
77*8a8a5d37SAharon Landau 		return -EPERM;
78*8a8a5d37SAharon Landau 
79*8a8a5d37SAharon Landau 	if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE &&
80*8a8a5d37SAharon Landau 	    !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr))
81*8a8a5d37SAharon Landau 		return -EPERM;
82*8a8a5d37SAharon Landau 
83*8a8a5d37SAharon Landau 	if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_READ &&
84*8a8a5d37SAharon Landau 	    !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))
85*8a8a5d37SAharon Landau 		return -EPERM;
86*8a8a5d37SAharon Landau 
87*8a8a5d37SAharon Landau 	return 0;
88*8a8a5d37SAharon Landau }
89*8a8a5d37SAharon Landau 
90*8a8a5d37SAharon Landau int mlx5r_umr_set_umr_ctrl_seg(struct mlx5_ib_dev *dev,
91*8a8a5d37SAharon Landau 			       struct mlx5_wqe_umr_ctrl_seg *umr,
92*8a8a5d37SAharon Landau 			       const struct ib_send_wr *wr)
93*8a8a5d37SAharon Landau {
94*8a8a5d37SAharon Landau 	const struct mlx5_umr_wr *umrwr = umr_wr(wr);
95*8a8a5d37SAharon Landau 
96*8a8a5d37SAharon Landau 	memset(umr, 0, sizeof(*umr));
97*8a8a5d37SAharon Landau 
98*8a8a5d37SAharon Landau 	if (!umrwr->ignore_free_state) {
99*8a8a5d37SAharon Landau 		if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE)
100*8a8a5d37SAharon Landau 			 /* fail if free */
101*8a8a5d37SAharon Landau 			umr->flags = MLX5_UMR_CHECK_FREE;
102*8a8a5d37SAharon Landau 		else
103*8a8a5d37SAharon Landau 			/* fail if not free */
104*8a8a5d37SAharon Landau 			umr->flags = MLX5_UMR_CHECK_NOT_FREE;
105*8a8a5d37SAharon Landau 	}
106*8a8a5d37SAharon Landau 
107*8a8a5d37SAharon Landau 	umr->xlt_octowords =
108*8a8a5d37SAharon Landau 		cpu_to_be16(mlx5r_umr_get_xlt_octo(umrwr->xlt_size));
109*8a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_XLT) {
110*8a8a5d37SAharon Landau 		u64 offset = mlx5r_umr_get_xlt_octo(umrwr->offset);
111*8a8a5d37SAharon Landau 
112*8a8a5d37SAharon Landau 		umr->xlt_offset = cpu_to_be16(offset & 0xffff);
113*8a8a5d37SAharon Landau 		umr->xlt_offset_47_16 = cpu_to_be32(offset >> 16);
114*8a8a5d37SAharon Landau 		umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN;
115*8a8a5d37SAharon Landau 	}
116*8a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION)
117*8a8a5d37SAharon Landau 		umr->mkey_mask |= get_umr_update_translation_mask();
118*8a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS) {
119*8a8a5d37SAharon Landau 		umr->mkey_mask |= get_umr_update_access_mask(
120*8a8a5d37SAharon Landau 			!!MLX5_CAP_GEN(dev->mdev, atomic),
121*8a8a5d37SAharon Landau 			!!MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr),
122*8a8a5d37SAharon Landau 			!!MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr));
123*8a8a5d37SAharon Landau 		umr->mkey_mask |= get_umr_update_pd_mask();
124*8a8a5d37SAharon Landau 	}
125*8a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_ENABLE_MR)
126*8a8a5d37SAharon Landau 		umr->mkey_mask |= get_umr_enable_mr_mask();
127*8a8a5d37SAharon Landau 	if (wr->send_flags & MLX5_IB_SEND_UMR_DISABLE_MR)
128*8a8a5d37SAharon Landau 		umr->mkey_mask |= get_umr_disable_mr_mask();
129*8a8a5d37SAharon Landau 
130*8a8a5d37SAharon Landau 	if (!wr->num_sge)
131*8a8a5d37SAharon Landau 		umr->flags |= MLX5_UMR_INLINE;
132*8a8a5d37SAharon Landau 
133*8a8a5d37SAharon Landau 	return umr_check_mkey_mask(dev, be64_to_cpu(umr->mkey_mask));
134*8a8a5d37SAharon Landau }
135*8a8a5d37SAharon Landau 
13604876c12SAharon Landau enum {
13704876c12SAharon Landau 	MAX_UMR_WR = 128,
13804876c12SAharon Landau };
13904876c12SAharon Landau 
14004876c12SAharon Landau static int mlx5r_umr_qp_rst2rts(struct mlx5_ib_dev *dev, struct ib_qp *qp)
14104876c12SAharon Landau {
14204876c12SAharon Landau 	struct ib_qp_attr attr = {};
14304876c12SAharon Landau 	int ret;
14404876c12SAharon Landau 
14504876c12SAharon Landau 	attr.qp_state = IB_QPS_INIT;
14604876c12SAharon Landau 	attr.port_num = 1;
14704876c12SAharon Landau 	ret = ib_modify_qp(qp, &attr,
14804876c12SAharon Landau 			   IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT);
14904876c12SAharon Landau 	if (ret) {
15004876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n");
15104876c12SAharon Landau 		return ret;
15204876c12SAharon Landau 	}
15304876c12SAharon Landau 
15404876c12SAharon Landau 	memset(&attr, 0, sizeof(attr));
15504876c12SAharon Landau 	attr.qp_state = IB_QPS_RTR;
15604876c12SAharon Landau 
15704876c12SAharon Landau 	ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
15804876c12SAharon Landau 	if (ret) {
15904876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n");
16004876c12SAharon Landau 		return ret;
16104876c12SAharon Landau 	}
16204876c12SAharon Landau 
16304876c12SAharon Landau 	memset(&attr, 0, sizeof(attr));
16404876c12SAharon Landau 	attr.qp_state = IB_QPS_RTS;
16504876c12SAharon Landau 	ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
16604876c12SAharon Landau 	if (ret) {
16704876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n");
16804876c12SAharon Landau 		return ret;
16904876c12SAharon Landau 	}
17004876c12SAharon Landau 
17104876c12SAharon Landau 	return 0;
17204876c12SAharon Landau }
17304876c12SAharon Landau 
17404876c12SAharon Landau int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)
17504876c12SAharon Landau {
17604876c12SAharon Landau 	struct ib_qp_init_attr init_attr = {};
17704876c12SAharon Landau 	struct ib_pd *pd;
17804876c12SAharon Landau 	struct ib_cq *cq;
17904876c12SAharon Landau 	struct ib_qp *qp;
18004876c12SAharon Landau 	int ret;
18104876c12SAharon Landau 
18204876c12SAharon Landau 	pd = ib_alloc_pd(&dev->ib_dev, 0);
18304876c12SAharon Landau 	if (IS_ERR(pd)) {
18404876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n");
18504876c12SAharon Landau 		return PTR_ERR(pd);
18604876c12SAharon Landau 	}
18704876c12SAharon Landau 
18804876c12SAharon Landau 	cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ);
18904876c12SAharon Landau 	if (IS_ERR(cq)) {
19004876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n");
19104876c12SAharon Landau 		ret = PTR_ERR(cq);
19204876c12SAharon Landau 		goto destroy_pd;
19304876c12SAharon Landau 	}
19404876c12SAharon Landau 
19504876c12SAharon Landau 	init_attr.send_cq = cq;
19604876c12SAharon Landau 	init_attr.recv_cq = cq;
19704876c12SAharon Landau 	init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
19804876c12SAharon Landau 	init_attr.cap.max_send_wr = MAX_UMR_WR;
19904876c12SAharon Landau 	init_attr.cap.max_send_sge = 1;
20004876c12SAharon Landau 	init_attr.qp_type = MLX5_IB_QPT_REG_UMR;
20104876c12SAharon Landau 	init_attr.port_num = 1;
20204876c12SAharon Landau 	qp = ib_create_qp(pd, &init_attr);
20304876c12SAharon Landau 	if (IS_ERR(qp)) {
20404876c12SAharon Landau 		mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n");
20504876c12SAharon Landau 		ret = PTR_ERR(qp);
20604876c12SAharon Landau 		goto destroy_cq;
20704876c12SAharon Landau 	}
20804876c12SAharon Landau 
20904876c12SAharon Landau 	ret = mlx5r_umr_qp_rst2rts(dev, qp);
21004876c12SAharon Landau 	if (ret)
21104876c12SAharon Landau 		goto destroy_qp;
21204876c12SAharon Landau 
21304876c12SAharon Landau 	dev->umrc.qp = qp;
21404876c12SAharon Landau 	dev->umrc.cq = cq;
21504876c12SAharon Landau 	dev->umrc.pd = pd;
21604876c12SAharon Landau 
21704876c12SAharon Landau 	sema_init(&dev->umrc.sem, MAX_UMR_WR);
21804876c12SAharon Landau 
21904876c12SAharon Landau 	return 0;
22004876c12SAharon Landau 
22104876c12SAharon Landau destroy_qp:
22204876c12SAharon Landau 	ib_destroy_qp(qp);
22304876c12SAharon Landau destroy_cq:
22404876c12SAharon Landau 	ib_free_cq(cq);
22504876c12SAharon Landau destroy_pd:
22604876c12SAharon Landau 	ib_dealloc_pd(pd);
22704876c12SAharon Landau 	return ret;
22804876c12SAharon Landau }
22904876c12SAharon Landau 
23004876c12SAharon Landau void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev)
23104876c12SAharon Landau {
23204876c12SAharon Landau 	ib_destroy_qp(dev->umrc.qp);
23304876c12SAharon Landau 	ib_free_cq(dev->umrc.cq);
23404876c12SAharon Landau 	ib_dealloc_pd(dev->umrc.pd);
23504876c12SAharon Landau }
236