diff options
author | Steve Wise <swise@opengridcomputing.com> | 2008-07-15 02:48:45 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-07-15 02:48:45 -0400 |
commit | e7e55829999deaab3f43e201a087731c02c54cf9 (patch) | |
tree | 665f2ff291045af9469bbb929f99224e9707965b /drivers/infiniband/hw/cxgb3/iwch_qp.c | |
parent | 00f7ec36c9324928e4cd23f02e6d8550f30c32ca (diff) |
RDMA/cxgb3: MEM_MGT_EXTENSIONS support
- set IB_DEVICE_MEM_MGT_EXTENSIONS capability bit if fw supports it.
- set max_fast_reg_page_list_len device attribute.
- add iwch_alloc_fast_reg_mr function.
- add iwch_alloc_fastreg_pbl
- add iwch_free_fastreg_pbl
- adjust the WQ depth for kernel mode work queues to account for
fastreg possibly taking 2 WR slots.
- add fastreg_mr work request support.
- add local_inv work request support.
- add send_with_inv and send_with_se_inv work request support.
- removed useless duplicate enums/defines for TPT/MW/MR stuff.
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb3/iwch_qp.c')
-rw-r--r-- | drivers/infiniband/hw/cxgb3/iwch_qp.c | 142 |
1 files changed, 97 insertions, 45 deletions
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 992613799228..3b44300a3036 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c | |||
@@ -44,54 +44,39 @@ static int iwch_build_rdma_send(union t3_wr *wqe, struct ib_send_wr *wr, | |||
44 | 44 | ||
45 | switch (wr->opcode) { | 45 | switch (wr->opcode) { |
46 | case IB_WR_SEND: | 46 | case IB_WR_SEND: |
47 | case IB_WR_SEND_WITH_IMM: | ||
48 | if (wr->send_flags & IB_SEND_SOLICITED) | 47 | if (wr->send_flags & IB_SEND_SOLICITED) |
49 | wqe->send.rdmaop = T3_SEND_WITH_SE; | 48 | wqe->send.rdmaop = T3_SEND_WITH_SE; |
50 | else | 49 | else |
51 | wqe->send.rdmaop = T3_SEND; | 50 | wqe->send.rdmaop = T3_SEND; |
52 | wqe->send.rem_stag = 0; | 51 | wqe->send.rem_stag = 0; |
53 | break; | 52 | break; |
54 | #if 0 /* Not currently supported */ | 53 | case IB_WR_SEND_WITH_INV: |
55 | case TYPE_SEND_INVALIDATE: | 54 | if (wr->send_flags & IB_SEND_SOLICITED) |
56 | case TYPE_SEND_INVALIDATE_IMMEDIATE: | 55 | wqe->send.rdmaop = T3_SEND_WITH_SE_INV; |
57 | wqe->send.rdmaop = T3_SEND_WITH_INV; | 56 | else |
58 | wqe->send.rem_stag = cpu_to_be32(wr->wr.rdma.rkey); | 57 | wqe->send.rdmaop = T3_SEND_WITH_INV; |
59 | break; | 58 | wqe->send.rem_stag = cpu_to_be32(wr->ex.invalidate_rkey); |
60 | case TYPE_SEND_SE_INVALIDATE: | ||
61 | wqe->send.rdmaop = T3_SEND_WITH_SE_INV; | ||
62 | wqe->send.rem_stag = cpu_to_be32(wr->wr.rdma.rkey); | ||
63 | break; | 59 | break; |
64 | #endif | ||
65 | default: | 60 | default: |
66 | break; | 61 | return -EINVAL; |
67 | } | 62 | } |
68 | if (wr->num_sge > T3_MAX_SGE) | 63 | if (wr->num_sge > T3_MAX_SGE) |
69 | return -EINVAL; | 64 | return -EINVAL; |
70 | wqe->send.reserved[0] = 0; | 65 | wqe->send.reserved[0] = 0; |
71 | wqe->send.reserved[1] = 0; | 66 | wqe->send.reserved[1] = 0; |
72 | wqe->send.reserved[2] = 0; | 67 | wqe->send.reserved[2] = 0; |
73 | if (wr->opcode == IB_WR_SEND_WITH_IMM) { | 68 | plen = 0; |
74 | plen = 4; | 69 | for (i = 0; i < wr->num_sge; i++) { |
75 | wqe->send.sgl[0].stag = wr->ex.imm_data; | 70 | if ((plen + wr->sg_list[i].length) < plen) |
76 | wqe->send.sgl[0].len = __constant_cpu_to_be32(0); | 71 | return -EMSGSIZE; |
77 | wqe->send.num_sgle = __constant_cpu_to_be32(0); | 72 | |
78 | *flit_cnt = 5; | 73 | plen += wr->sg_list[i].length; |
79 | } else { | 74 | wqe->send.sgl[i].stag = cpu_to_be32(wr->sg_list[i].lkey); |
80 | plen = 0; | 75 | wqe->send.sgl[i].len = cpu_to_be32(wr->sg_list[i].length); |
81 | for (i = 0; i < wr->num_sge; i++) { | 76 | wqe->send.sgl[i].to = cpu_to_be64(wr->sg_list[i].addr); |
82 | if ((plen + wr->sg_list[i].length) < plen) { | ||
83 | return -EMSGSIZE; | ||
84 | } | ||
85 | plen += wr->sg_list[i].length; | ||
86 | wqe->send.sgl[i].stag = | ||
87 | cpu_to_be32(wr->sg_list[i].lkey); | ||
88 | wqe->send.sgl[i].len = | ||
89 | cpu_to_be32(wr->sg_list[i].length); | ||
90 | wqe->send.sgl[i].to = cpu_to_be64(wr->sg_list[i].addr); | ||
91 | } | ||
92 | wqe->send.num_sgle = cpu_to_be32(wr->num_sge); | ||
93 | *flit_cnt = 4 + ((wr->num_sge) << 1); | ||
94 | } | 77 | } |
78 | wqe->send.num_sgle = cpu_to_be32(wr->num_sge); | ||
79 | *flit_cnt = 4 + ((wr->num_sge) << 1); | ||
95 | wqe->send.plen = cpu_to_be32(plen); | 80 | wqe->send.plen = cpu_to_be32(plen); |
96 | return 0; | 81 | return 0; |
97 | } | 82 | } |
@@ -143,9 +128,12 @@ static int iwch_build_rdma_read(union t3_wr *wqe, struct ib_send_wr *wr, | |||
143 | if (wr->num_sge > 1) | 128 | if (wr->num_sge > 1) |
144 | return -EINVAL; | 129 | return -EINVAL; |
145 | wqe->read.rdmaop = T3_READ_REQ; | 130 | wqe->read.rdmaop = T3_READ_REQ; |
131 | if (wr->opcode == IB_WR_RDMA_READ_WITH_INV) | ||
132 | wqe->read.local_inv = 1; | ||
133 | else | ||
134 | wqe->read.local_inv = 0; | ||
146 | wqe->read.reserved[0] = 0; | 135 | wqe->read.reserved[0] = 0; |
147 | wqe->read.reserved[1] = 0; | 136 | wqe->read.reserved[1] = 0; |
148 | wqe->read.reserved[2] = 0; | ||
149 | wqe->read.rem_stag = cpu_to_be32(wr->wr.rdma.rkey); | 137 | wqe->read.rem_stag = cpu_to_be32(wr->wr.rdma.rkey); |
150 | wqe->read.rem_to = cpu_to_be64(wr->wr.rdma.remote_addr); | 138 | wqe->read.rem_to = cpu_to_be64(wr->wr.rdma.remote_addr); |
151 | wqe->read.local_stag = cpu_to_be32(wr->sg_list[0].lkey); | 139 | wqe->read.local_stag = cpu_to_be32(wr->sg_list[0].lkey); |
@@ -155,6 +143,57 @@ static int iwch_build_rdma_read(union t3_wr *wqe, struct ib_send_wr *wr, | |||
155 | return 0; | 143 | return 0; |
156 | } | 144 | } |
157 | 145 | ||
146 | static int iwch_build_fastreg(union t3_wr *wqe, struct ib_send_wr *wr, | ||
147 | u8 *flit_cnt, int *wr_cnt, struct t3_wq *wq) | ||
148 | { | ||
149 | int i; | ||
150 | __be64 *p; | ||
151 | |||
152 | if (wr->wr.fast_reg.page_list_len > T3_MAX_FASTREG_DEPTH) | ||
153 | return -EINVAL; | ||
154 | *wr_cnt = 1; | ||
155 | wqe->fastreg.stag = cpu_to_be32(wr->wr.fast_reg.rkey); | ||
156 | wqe->fastreg.len = cpu_to_be32(wr->wr.fast_reg.length); | ||
157 | wqe->fastreg.va_base_hi = cpu_to_be32(wr->wr.fast_reg.iova_start >> 32); | ||
158 | wqe->fastreg.va_base_lo_fbo = | ||
159 | cpu_to_be32(wr->wr.fast_reg.iova_start & 0xffffffff); | ||
160 | wqe->fastreg.page_type_perms = cpu_to_be32( | ||
161 | V_FR_PAGE_COUNT(wr->wr.fast_reg.page_list_len) | | ||
162 | V_FR_PAGE_SIZE(wr->wr.fast_reg.page_shift-12) | | ||
163 | V_FR_TYPE(TPT_VATO) | | ||
164 | V_FR_PERMS(iwch_ib_to_tpt_access(wr->wr.fast_reg.access_flags))); | ||
165 | p = &wqe->fastreg.pbl_addrs[0]; | ||
166 | for (i = 0; i < wr->wr.fast_reg.page_list_len; i++, p++) { | ||
167 | |||
168 | /* If we need a 2nd WR, then set it up */ | ||
169 | if (i == T3_MAX_FASTREG_FRAG) { | ||
170 | *wr_cnt = 2; | ||
171 | wqe = (union t3_wr *)(wq->queue + | ||
172 | Q_PTR2IDX((wq->wptr+1), wq->size_log2)); | ||
173 | build_fw_riwrh((void *)wqe, T3_WR_FASTREG, 0, | ||
174 | Q_GENBIT(wq->wptr + 1, wq->size_log2), | ||
175 | 0, 1 + wr->wr.fast_reg.page_list_len - T3_MAX_FASTREG_FRAG, | ||
176 | T3_EOP); | ||
177 | |||
178 | p = &wqe->pbl_frag.pbl_addrs[0]; | ||
179 | } | ||
180 | *p = cpu_to_be64((u64)wr->wr.fast_reg.page_list->page_list[i]); | ||
181 | } | ||
182 | *flit_cnt = 5 + wr->wr.fast_reg.page_list_len; | ||
183 | if (*flit_cnt > 15) | ||
184 | *flit_cnt = 15; | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int iwch_build_inv_stag(union t3_wr *wqe, struct ib_send_wr *wr, | ||
189 | u8 *flit_cnt) | ||
190 | { | ||
191 | wqe->local_inv.stag = cpu_to_be32(wr->ex.invalidate_rkey); | ||
192 | wqe->local_inv.reserved = 0; | ||
193 | *flit_cnt = sizeof(struct t3_local_inv_wr) >> 3; | ||
194 | return 0; | ||
195 | } | ||
196 | |||
158 | /* | 197 | /* |
159 | * TBD: this is going to be moved to firmware. Missing pdid/qpid check for now. | 198 | * TBD: this is going to be moved to firmware. Missing pdid/qpid check for now. |
160 | */ | 199 | */ |
@@ -238,6 +277,7 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
238 | u32 num_wrs; | 277 | u32 num_wrs; |
239 | unsigned long flag; | 278 | unsigned long flag; |
240 | struct t3_swsq *sqp; | 279 | struct t3_swsq *sqp; |
280 | int wr_cnt = 1; | ||
241 | 281 | ||
242 | qhp = to_iwch_qp(ibqp); | 282 | qhp = to_iwch_qp(ibqp); |
243 | spin_lock_irqsave(&qhp->lock, flag); | 283 | spin_lock_irqsave(&qhp->lock, flag); |
@@ -262,15 +302,15 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
262 | t3_wr_flags = 0; | 302 | t3_wr_flags = 0; |
263 | if (wr->send_flags & IB_SEND_SOLICITED) | 303 | if (wr->send_flags & IB_SEND_SOLICITED) |
264 | t3_wr_flags |= T3_SOLICITED_EVENT_FLAG; | 304 | t3_wr_flags |= T3_SOLICITED_EVENT_FLAG; |
265 | if (wr->send_flags & IB_SEND_FENCE) | ||
266 | t3_wr_flags |= T3_READ_FENCE_FLAG; | ||
267 | if (wr->send_flags & IB_SEND_SIGNALED) | 305 | if (wr->send_flags & IB_SEND_SIGNALED) |
268 | t3_wr_flags |= T3_COMPLETION_FLAG; | 306 | t3_wr_flags |= T3_COMPLETION_FLAG; |
269 | sqp = qhp->wq.sq + | 307 | sqp = qhp->wq.sq + |
270 | Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2); | 308 | Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2); |
271 | switch (wr->opcode) { | 309 | switch (wr->opcode) { |
272 | case IB_WR_SEND: | 310 | case IB_WR_SEND: |
273 | case IB_WR_SEND_WITH_IMM: | 311 | case IB_WR_SEND_WITH_INV: |
312 | if (wr->send_flags & IB_SEND_FENCE) | ||
313 | t3_wr_flags |= T3_READ_FENCE_FLAG; | ||
274 | t3_wr_opcode = T3_WR_SEND; | 314 | t3_wr_opcode = T3_WR_SEND; |
275 | err = iwch_build_rdma_send(wqe, wr, &t3_wr_flit_cnt); | 315 | err = iwch_build_rdma_send(wqe, wr, &t3_wr_flit_cnt); |
276 | break; | 316 | break; |
@@ -280,6 +320,7 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
280 | err = iwch_build_rdma_write(wqe, wr, &t3_wr_flit_cnt); | 320 | err = iwch_build_rdma_write(wqe, wr, &t3_wr_flit_cnt); |
281 | break; | 321 | break; |
282 | case IB_WR_RDMA_READ: | 322 | case IB_WR_RDMA_READ: |
323 | case IB_WR_RDMA_READ_WITH_INV: | ||
283 | t3_wr_opcode = T3_WR_READ; | 324 | t3_wr_opcode = T3_WR_READ; |
284 | t3_wr_flags = 0; /* T3 reads are always signaled */ | 325 | t3_wr_flags = 0; /* T3 reads are always signaled */ |
285 | err = iwch_build_rdma_read(wqe, wr, &t3_wr_flit_cnt); | 326 | err = iwch_build_rdma_read(wqe, wr, &t3_wr_flit_cnt); |
@@ -289,6 +330,17 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
289 | if (!qhp->wq.oldest_read) | 330 | if (!qhp->wq.oldest_read) |
290 | qhp->wq.oldest_read = sqp; | 331 | qhp->wq.oldest_read = sqp; |
291 | break; | 332 | break; |
333 | case IB_WR_FAST_REG_MR: | ||
334 | t3_wr_opcode = T3_WR_FASTREG; | ||
335 | err = iwch_build_fastreg(wqe, wr, &t3_wr_flit_cnt, | ||
336 | &wr_cnt, &qhp->wq); | ||
337 | break; | ||
338 | case IB_WR_LOCAL_INV: | ||
339 | if (wr->send_flags & IB_SEND_FENCE) | ||
340 | t3_wr_flags |= T3_LOCAL_FENCE_FLAG; | ||
341 | t3_wr_opcode = T3_WR_INV_STAG; | ||
342 | err = iwch_build_inv_stag(wqe, wr, &t3_wr_flit_cnt); | ||
343 | break; | ||
292 | default: | 344 | default: |
293 | PDBG("%s post of type=%d TBD!\n", __func__, | 345 | PDBG("%s post of type=%d TBD!\n", __func__, |
294 | wr->opcode); | 346 | wr->opcode); |
@@ -307,14 +359,15 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
307 | 359 | ||
308 | build_fw_riwrh((void *) wqe, t3_wr_opcode, t3_wr_flags, | 360 | build_fw_riwrh((void *) wqe, t3_wr_opcode, t3_wr_flags, |
309 | Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2), | 361 | Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2), |
310 | 0, t3_wr_flit_cnt); | 362 | 0, t3_wr_flit_cnt, |
363 | (wr_cnt == 1) ? T3_SOPEOP : T3_SOP); | ||
311 | PDBG("%s cookie 0x%llx wq idx 0x%x swsq idx %ld opcode %d\n", | 364 | PDBG("%s cookie 0x%llx wq idx 0x%x swsq idx %ld opcode %d\n", |
312 | __func__, (unsigned long long) wr->wr_id, idx, | 365 | __func__, (unsigned long long) wr->wr_id, idx, |
313 | Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2), | 366 | Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2), |
314 | sqp->opcode); | 367 | sqp->opcode); |
315 | wr = wr->next; | 368 | wr = wr->next; |
316 | num_wrs--; | 369 | num_wrs--; |
317 | ++(qhp->wq.wptr); | 370 | qhp->wq.wptr += wr_cnt; |
318 | ++(qhp->wq.sq_wptr); | 371 | ++(qhp->wq.sq_wptr); |
319 | } | 372 | } |
320 | spin_unlock_irqrestore(&qhp->lock, flag); | 373 | spin_unlock_irqrestore(&qhp->lock, flag); |
@@ -359,7 +412,7 @@ int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, | |||
359 | wr->wr_id; | 412 | wr->wr_id; |
360 | build_fw_riwrh((void *) wqe, T3_WR_RCV, T3_COMPLETION_FLAG, | 413 | build_fw_riwrh((void *) wqe, T3_WR_RCV, T3_COMPLETION_FLAG, |
361 | Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2), | 414 | Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2), |
362 | 0, sizeof(struct t3_receive_wr) >> 3); | 415 | 0, sizeof(struct t3_receive_wr) >> 3, T3_SOPEOP); |
363 | PDBG("%s cookie 0x%llx idx 0x%x rq_wptr 0x%x rw_rptr 0x%x " | 416 | PDBG("%s cookie 0x%llx idx 0x%x rq_wptr 0x%x rw_rptr 0x%x " |
364 | "wqe %p \n", __func__, (unsigned long long) wr->wr_id, | 417 | "wqe %p \n", __func__, (unsigned long long) wr->wr_id, |
365 | idx, qhp->wq.rq_wptr, qhp->wq.rq_rptr, wqe); | 418 | idx, qhp->wq.rq_wptr, qhp->wq.rq_rptr, wqe); |
@@ -419,10 +472,10 @@ int iwch_bind_mw(struct ib_qp *qp, | |||
419 | sgl.lkey = mw_bind->mr->lkey; | 472 | sgl.lkey = mw_bind->mr->lkey; |
420 | sgl.length = mw_bind->length; | 473 | sgl.length = mw_bind->length; |
421 | wqe->bind.reserved = 0; | 474 | wqe->bind.reserved = 0; |
422 | wqe->bind.type = T3_VA_BASED_TO; | 475 | wqe->bind.type = TPT_VATO; |
423 | 476 | ||
424 | /* TBD: check perms */ | 477 | /* TBD: check perms */ |
425 | wqe->bind.perms = iwch_ib_to_mwbind_access(mw_bind->mw_access_flags); | 478 | wqe->bind.perms = iwch_ib_to_tpt_access(mw_bind->mw_access_flags); |
426 | wqe->bind.mr_stag = cpu_to_be32(mw_bind->mr->lkey); | 479 | wqe->bind.mr_stag = cpu_to_be32(mw_bind->mr->lkey); |
427 | wqe->bind.mw_stag = cpu_to_be32(mw->rkey); | 480 | wqe->bind.mw_stag = cpu_to_be32(mw->rkey); |
428 | wqe->bind.mw_len = cpu_to_be32(mw_bind->length); | 481 | wqe->bind.mw_len = cpu_to_be32(mw_bind->length); |
@@ -430,7 +483,7 @@ int iwch_bind_mw(struct ib_qp *qp, | |||
430 | err = iwch_sgl2pbl_map(rhp, &sgl, 1, &pbl_addr, &page_size); | 483 | err = iwch_sgl2pbl_map(rhp, &sgl, 1, &pbl_addr, &page_size); |
431 | if (err) { | 484 | if (err) { |
432 | spin_unlock_irqrestore(&qhp->lock, flag); | 485 | spin_unlock_irqrestore(&qhp->lock, flag); |
433 | return err; | 486 | return err; |
434 | } | 487 | } |
435 | wqe->send.wrid.id0.hi = qhp->wq.sq_wptr; | 488 | wqe->send.wrid.id0.hi = qhp->wq.sq_wptr; |
436 | sqp = qhp->wq.sq + Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2); | 489 | sqp = qhp->wq.sq + Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2); |
@@ -441,10 +494,9 @@ int iwch_bind_mw(struct ib_qp *qp, | |||
441 | sqp->signaled = (mw_bind->send_flags & IB_SEND_SIGNALED); | 494 | sqp->signaled = (mw_bind->send_flags & IB_SEND_SIGNALED); |
442 | wqe->bind.mr_pbl_addr = cpu_to_be32(pbl_addr); | 495 | wqe->bind.mr_pbl_addr = cpu_to_be32(pbl_addr); |
443 | wqe->bind.mr_pagesz = page_size; | 496 | wqe->bind.mr_pagesz = page_size; |
444 | wqe->flit[T3_SQ_COOKIE_FLIT] = mw_bind->wr_id; | ||
445 | build_fw_riwrh((void *)wqe, T3_WR_BIND, t3_wr_flags, | 497 | build_fw_riwrh((void *)wqe, T3_WR_BIND, t3_wr_flags, |
446 | Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2), 0, | 498 | Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2), 0, |
447 | sizeof(struct t3_bind_mw_wr) >> 3); | 499 | sizeof(struct t3_bind_mw_wr) >> 3, T3_SOPEOP); |
448 | ++(qhp->wq.wptr); | 500 | ++(qhp->wq.wptr); |
449 | ++(qhp->wq.sq_wptr); | 501 | ++(qhp->wq.sq_wptr); |
450 | spin_unlock_irqrestore(&qhp->lock, flag); | 502 | spin_unlock_irqrestore(&qhp->lock, flag); |