diff options
author | Shani Michaeli <shanim@mellanox.com> | 2013-02-06 11:19:15 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-02-25 13:44:32 -0500 |
commit | 6ff63e194066a1f14aee805366a1d79c541fddae (patch) | |
tree | d619416f696cf6859587fa5875845609a9ba6a4e | |
parent | 804d6a89a5c0b076317966bcbcd7a63d42241831 (diff) |
IB/mlx4: Support memory window binding
* Implement memory windows binding in mlx4_ib_post_send.
* Implement mlx4_ib_bind_mw by deferring to mlx4_ib_post_send.
* Rename MLX4_WQE_FMR_PERM_* flags to MLX4_WQE_FMR_AND_BIND_PERM_*,
indicating that they are used both for fast registration work
requests, and for memory window bind work requests.
Signed-off-by: Haggai Eran <haggaie@mellanox.com>
Signed-off-by: Shani Michaeli <shanim@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/mr.c | 22 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 35 | ||||
-rw-r--r-- | include/linux/mlx4/qp.h | 11 |
4 files changed, 64 insertions, 6 deletions
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index 9ba0aaf3a58e..f61ec26500c4 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
@@ -592,6 +592,8 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, | |||
592 | struct ib_udata *udata); | 592 | struct ib_udata *udata); |
593 | int mlx4_ib_dereg_mr(struct ib_mr *mr); | 593 | int mlx4_ib_dereg_mr(struct ib_mr *mr); |
594 | struct ib_mw *mlx4_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type); | 594 | struct ib_mw *mlx4_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type); |
595 | int mlx4_ib_bind_mw(struct ib_qp *qp, struct ib_mw *mw, | ||
596 | struct ib_mw_bind *mw_bind); | ||
595 | int mlx4_ib_dealloc_mw(struct ib_mw *mw); | 597 | int mlx4_ib_dealloc_mw(struct ib_mw *mw); |
596 | struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd, | 598 | struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd, |
597 | int max_page_list_len); | 599 | int max_page_list_len); |
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index 5adf4c47ee18..e471f089ff00 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c | |||
@@ -231,6 +231,28 @@ err_free: | |||
231 | return ERR_PTR(err); | 231 | return ERR_PTR(err); |
232 | } | 232 | } |
233 | 233 | ||
234 | int mlx4_ib_bind_mw(struct ib_qp *qp, struct ib_mw *mw, | ||
235 | struct ib_mw_bind *mw_bind) | ||
236 | { | ||
237 | struct ib_send_wr wr; | ||
238 | struct ib_send_wr *bad_wr; | ||
239 | int ret; | ||
240 | |||
241 | memset(&wr, 0, sizeof(wr)); | ||
242 | wr.opcode = IB_WR_BIND_MW; | ||
243 | wr.wr_id = mw_bind->wr_id; | ||
244 | wr.send_flags = mw_bind->send_flags; | ||
245 | wr.wr.bind_mw.mw = mw; | ||
246 | wr.wr.bind_mw.bind_info = mw_bind->bind_info; | ||
247 | wr.wr.bind_mw.rkey = ib_inc_rkey(mw->rkey); | ||
248 | |||
249 | ret = mlx4_ib_post_send(qp, &wr, &bad_wr); | ||
250 | if (!ret) | ||
251 | mw->rkey = wr.wr.bind_mw.rkey; | ||
252 | |||
253 | return ret; | ||
254 | } | ||
255 | |||
234 | int mlx4_ib_dealloc_mw(struct ib_mw *ibmw) | 256 | int mlx4_ib_dealloc_mw(struct ib_mw *ibmw) |
235 | { | 257 | { |
236 | struct mlx4_ib_mw *mw = to_mmw(ibmw); | 258 | struct mlx4_ib_mw *mw = to_mmw(ibmw); |
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index ebadebe83b11..35cced2a4da8 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
@@ -104,6 +104,7 @@ static const __be32 mlx4_ib_opcode[] = { | |||
104 | [IB_WR_FAST_REG_MR] = cpu_to_be32(MLX4_OPCODE_FMR), | 104 | [IB_WR_FAST_REG_MR] = cpu_to_be32(MLX4_OPCODE_FMR), |
105 | [IB_WR_MASKED_ATOMIC_CMP_AND_SWP] = cpu_to_be32(MLX4_OPCODE_MASKED_ATOMIC_CS), | 105 | [IB_WR_MASKED_ATOMIC_CMP_AND_SWP] = cpu_to_be32(MLX4_OPCODE_MASKED_ATOMIC_CS), |
106 | [IB_WR_MASKED_ATOMIC_FETCH_AND_ADD] = cpu_to_be32(MLX4_OPCODE_MASKED_ATOMIC_FA), | 106 | [IB_WR_MASKED_ATOMIC_FETCH_AND_ADD] = cpu_to_be32(MLX4_OPCODE_MASKED_ATOMIC_FA), |
107 | [IB_WR_BIND_MW] = cpu_to_be32(MLX4_OPCODE_BIND_MW), | ||
107 | }; | 108 | }; |
108 | 109 | ||
109 | static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp) | 110 | static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp) |
@@ -1953,9 +1954,12 @@ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq | |||
1953 | 1954 | ||
1954 | static __be32 convert_access(int acc) | 1955 | static __be32 convert_access(int acc) |
1955 | { | 1956 | { |
1956 | return (acc & IB_ACCESS_REMOTE_ATOMIC ? cpu_to_be32(MLX4_WQE_FMR_PERM_ATOMIC) : 0) | | 1957 | return (acc & IB_ACCESS_REMOTE_ATOMIC ? |
1957 | (acc & IB_ACCESS_REMOTE_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_WRITE) : 0) | | 1958 | cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC) : 0) | |
1958 | (acc & IB_ACCESS_REMOTE_READ ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_READ) : 0) | | 1959 | (acc & IB_ACCESS_REMOTE_WRITE ? |
1960 | cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_WRITE) : 0) | | ||
1961 | (acc & IB_ACCESS_REMOTE_READ ? | ||
1962 | cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_READ) : 0) | | ||
1959 | (acc & IB_ACCESS_LOCAL_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE) : 0) | | 1963 | (acc & IB_ACCESS_LOCAL_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE) : 0) | |
1960 | cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ); | 1964 | cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ); |
1961 | } | 1965 | } |
@@ -1981,6 +1985,24 @@ static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr) | |||
1981 | fseg->reserved[1] = 0; | 1985 | fseg->reserved[1] = 0; |
1982 | } | 1986 | } |
1983 | 1987 | ||
1988 | static void set_bind_seg(struct mlx4_wqe_bind_seg *bseg, struct ib_send_wr *wr) | ||
1989 | { | ||
1990 | bseg->flags1 = | ||
1991 | convert_access(wr->wr.bind_mw.bind_info.mw_access_flags) & | ||
1992 | cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_READ | | ||
1993 | MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_WRITE | | ||
1994 | MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC); | ||
1995 | bseg->flags2 = 0; | ||
1996 | if (wr->wr.bind_mw.mw->type == IB_MW_TYPE_2) | ||
1997 | bseg->flags2 |= cpu_to_be32(MLX4_WQE_BIND_TYPE_2); | ||
1998 | if (wr->wr.bind_mw.bind_info.mw_access_flags & IB_ZERO_BASED) | ||
1999 | bseg->flags2 |= cpu_to_be32(MLX4_WQE_BIND_ZERO_BASED); | ||
2000 | bseg->new_rkey = cpu_to_be32(wr->wr.bind_mw.rkey); | ||
2001 | bseg->lkey = cpu_to_be32(wr->wr.bind_mw.bind_info.mr->lkey); | ||
2002 | bseg->addr = cpu_to_be64(wr->wr.bind_mw.bind_info.addr); | ||
2003 | bseg->length = cpu_to_be64(wr->wr.bind_mw.bind_info.length); | ||
2004 | } | ||
2005 | |||
1984 | static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey) | 2006 | static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey) |
1985 | { | 2007 | { |
1986 | memset(iseg, 0, sizeof(*iseg)); | 2008 | memset(iseg, 0, sizeof(*iseg)); |
@@ -2289,6 +2311,13 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
2289 | size += sizeof (struct mlx4_wqe_fmr_seg) / 16; | 2311 | size += sizeof (struct mlx4_wqe_fmr_seg) / 16; |
2290 | break; | 2312 | break; |
2291 | 2313 | ||
2314 | case IB_WR_BIND_MW: | ||
2315 | ctrl->srcrb_flags |= | ||
2316 | cpu_to_be32(MLX4_WQE_CTRL_STRONG_ORDER); | ||
2317 | set_bind_seg(wqe, wr); | ||
2318 | wqe += sizeof(struct mlx4_wqe_bind_seg); | ||
2319 | size += sizeof(struct mlx4_wqe_bind_seg) / 16; | ||
2320 | break; | ||
2292 | default: | 2321 | default: |
2293 | /* No extra segments required for sends */ | 2322 | /* No extra segments required for sends */ |
2294 | break; | 2323 | break; |
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index 6c8a68c602be..67f46ad6920a 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h | |||
@@ -265,6 +265,11 @@ struct mlx4_wqe_lso_seg { | |||
265 | __be32 header[0]; | 265 | __be32 header[0]; |
266 | }; | 266 | }; |
267 | 267 | ||
268 | enum mlx4_wqe_bind_seg_flags2 { | ||
269 | MLX4_WQE_BIND_ZERO_BASED = (1 << 30), | ||
270 | MLX4_WQE_BIND_TYPE_2 = (1 << 31), | ||
271 | }; | ||
272 | |||
268 | struct mlx4_wqe_bind_seg { | 273 | struct mlx4_wqe_bind_seg { |
269 | __be32 flags1; | 274 | __be32 flags1; |
270 | __be32 flags2; | 275 | __be32 flags2; |
@@ -277,9 +282,9 @@ struct mlx4_wqe_bind_seg { | |||
277 | enum { | 282 | enum { |
278 | MLX4_WQE_FMR_PERM_LOCAL_READ = 1 << 27, | 283 | MLX4_WQE_FMR_PERM_LOCAL_READ = 1 << 27, |
279 | MLX4_WQE_FMR_PERM_LOCAL_WRITE = 1 << 28, | 284 | MLX4_WQE_FMR_PERM_LOCAL_WRITE = 1 << 28, |
280 | MLX4_WQE_FMR_PERM_REMOTE_READ = 1 << 29, | 285 | MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_READ = 1 << 29, |
281 | MLX4_WQE_FMR_PERM_REMOTE_WRITE = 1 << 30, | 286 | MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_WRITE = 1 << 30, |
282 | MLX4_WQE_FMR_PERM_ATOMIC = 1 << 31 | 287 | MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC = 1 << 31 |
283 | }; | 288 | }; |
284 | 289 | ||
285 | struct mlx4_wqe_fmr_seg { | 290 | struct mlx4_wqe_fmr_seg { |