]> Git Repo - J-linux.git/blob - drivers/infiniband/hw/erdma/erdma_qp.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[J-linux.git] / drivers / infiniband / hw / erdma / erdma_qp.c
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2
3 /* Authors: Cheng Xu <[email protected]> */
4 /*          Kai Shen <[email protected]> */
5 /* Copyright (c) 2020-2021, Alibaba Group */
6 /* Authors: Bernard Metzler <[email protected]> */
7 /* Copyright (c) 2008-2019, IBM Corporation */
8
9 #include "erdma_cm.h"
10 #include "erdma_verbs.h"
11
12 void erdma_qp_llp_close(struct erdma_qp *qp)
13 {
14         struct erdma_qp_attrs qp_attrs;
15
16         down_write(&qp->state_lock);
17
18         switch (qp->attrs.state) {
19         case ERDMA_QP_STATE_RTS:
20         case ERDMA_QP_STATE_RTR:
21         case ERDMA_QP_STATE_IDLE:
22         case ERDMA_QP_STATE_TERMINATE:
23                 qp_attrs.state = ERDMA_QP_STATE_CLOSING;
24                 erdma_modify_qp_internal(qp, &qp_attrs, ERDMA_QP_ATTR_STATE);
25                 break;
26         case ERDMA_QP_STATE_CLOSING:
27                 qp->attrs.state = ERDMA_QP_STATE_IDLE;
28                 break;
29         default:
30                 break;
31         }
32
33         if (qp->cep) {
34                 erdma_cep_put(qp->cep);
35                 qp->cep = NULL;
36         }
37
38         up_write(&qp->state_lock);
39 }
40
41 struct ib_qp *erdma_get_ibqp(struct ib_device *ibdev, int id)
42 {
43         struct erdma_qp *qp = find_qp_by_qpn(to_edev(ibdev), id);
44
45         if (qp)
46                 return &qp->ibqp;
47
48         return NULL;
49 }
50
51 static int erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
52                                         struct erdma_qp_attrs *attrs,
53                                         enum erdma_qp_attr_mask mask)
54 {
55         int ret;
56         struct erdma_dev *dev = qp->dev;
57         struct erdma_cmdq_modify_qp_req req;
58         struct tcp_sock *tp;
59         struct erdma_cep *cep = qp->cep;
60         struct sockaddr_storage local_addr, remote_addr;
61
62         if (!(mask & ERDMA_QP_ATTR_LLP_HANDLE))
63                 return -EINVAL;
64
65         if (!(mask & ERDMA_QP_ATTR_MPA))
66                 return -EINVAL;
67
68         ret = getname_local(cep->sock, &local_addr);
69         if (ret < 0)
70                 return ret;
71
72         ret = getname_peer(cep->sock, &remote_addr);
73         if (ret < 0)
74                 return ret;
75
76         qp->attrs.state = ERDMA_QP_STATE_RTS;
77
78         tp = tcp_sk(qp->cep->sock->sk);
79
80         erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
81                                 CMDQ_OPCODE_MODIFY_QP);
82
83         req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, qp->attrs.state) |
84                   FIELD_PREP(ERDMA_CMD_MODIFY_QP_CC_MASK, qp->attrs.cc) |
85                   FIELD_PREP(ERDMA_CMD_MODIFY_QP_QPN_MASK, QP_ID(qp));
86
87         req.cookie = be32_to_cpu(qp->cep->mpa.ext_data.cookie);
88         req.dip = to_sockaddr_in(remote_addr).sin_addr.s_addr;
89         req.sip = to_sockaddr_in(local_addr).sin_addr.s_addr;
90         req.dport = to_sockaddr_in(remote_addr).sin_port;
91         req.sport = to_sockaddr_in(local_addr).sin_port;
92
93         req.send_nxt = tp->snd_nxt;
94         /* rsvd tcp seq for mpa-rsp in server. */
95         if (qp->attrs.qp_type == ERDMA_QP_PASSIVE)
96                 req.send_nxt += MPA_DEFAULT_HDR_LEN + qp->attrs.pd_len;
97         req.recv_nxt = tp->rcv_nxt;
98
99         return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
100 }
101
102 static int erdma_modify_qp_state_to_stop(struct erdma_qp *qp,
103                                          struct erdma_qp_attrs *attrs,
104                                          enum erdma_qp_attr_mask mask)
105 {
106         struct erdma_dev *dev = qp->dev;
107         struct erdma_cmdq_modify_qp_req req;
108
109         qp->attrs.state = attrs->state;
110
111         erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
112                                 CMDQ_OPCODE_MODIFY_QP);
113
114         req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, attrs->state) |
115                   FIELD_PREP(ERDMA_CMD_MODIFY_QP_QPN_MASK, QP_ID(qp));
116
117         return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
118 }
119
120 int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
121                              enum erdma_qp_attr_mask mask)
122 {
123         bool need_reflush = false;
124         int drop_conn, ret = 0;
125
126         if (!mask)
127                 return 0;
128
129         if (!(mask & ERDMA_QP_ATTR_STATE))
130                 return 0;
131
132         switch (qp->attrs.state) {
133         case ERDMA_QP_STATE_IDLE:
134         case ERDMA_QP_STATE_RTR:
135                 if (attrs->state == ERDMA_QP_STATE_RTS) {
136                         ret = erdma_modify_qp_state_to_rts(qp, attrs, mask);
137                 } else if (attrs->state == ERDMA_QP_STATE_ERROR) {
138                         qp->attrs.state = ERDMA_QP_STATE_ERROR;
139                         need_reflush = true;
140                         if (qp->cep) {
141                                 erdma_cep_put(qp->cep);
142                                 qp->cep = NULL;
143                         }
144                         ret = erdma_modify_qp_state_to_stop(qp, attrs, mask);
145                 }
146                 break;
147         case ERDMA_QP_STATE_RTS:
148                 drop_conn = 0;
149
150                 if (attrs->state == ERDMA_QP_STATE_CLOSING ||
151                     attrs->state == ERDMA_QP_STATE_TERMINATE ||
152                     attrs->state == ERDMA_QP_STATE_ERROR) {
153                         ret = erdma_modify_qp_state_to_stop(qp, attrs, mask);
154                         drop_conn = 1;
155                         need_reflush = true;
156                 }
157
158                 if (drop_conn)
159                         erdma_qp_cm_drop(qp);
160
161                 break;
162         case ERDMA_QP_STATE_TERMINATE:
163                 if (attrs->state == ERDMA_QP_STATE_ERROR)
164                         qp->attrs.state = ERDMA_QP_STATE_ERROR;
165                 break;
166         case ERDMA_QP_STATE_CLOSING:
167                 if (attrs->state == ERDMA_QP_STATE_IDLE) {
168                         qp->attrs.state = ERDMA_QP_STATE_IDLE;
169                 } else if (attrs->state == ERDMA_QP_STATE_ERROR) {
170                         ret = erdma_modify_qp_state_to_stop(qp, attrs, mask);
171                         qp->attrs.state = ERDMA_QP_STATE_ERROR;
172                 } else if (attrs->state != ERDMA_QP_STATE_CLOSING) {
173                         return -ECONNABORTED;
174                 }
175                 break;
176         default:
177                 break;
178         }
179
180         if (need_reflush && !ret && rdma_is_kernel_res(&qp->ibqp.res)) {
181                 qp->flags |= ERDMA_QP_IN_FLUSHING;
182                 mod_delayed_work(qp->dev->reflush_wq, &qp->reflush_dwork,
183                                  usecs_to_jiffies(100));
184         }
185
186         return ret;
187 }
188
189 static void erdma_qp_safe_free(struct kref *ref)
190 {
191         struct erdma_qp *qp = container_of(ref, struct erdma_qp, ref);
192
193         complete(&qp->safe_free);
194 }
195
196 void erdma_qp_put(struct erdma_qp *qp)
197 {
198         WARN_ON(kref_read(&qp->ref) < 1);
199         kref_put(&qp->ref, erdma_qp_safe_free);
200 }
201
202 void erdma_qp_get(struct erdma_qp *qp)
203 {
204         kref_get(&qp->ref);
205 }
206
207 static int fill_inline_data(struct erdma_qp *qp,
208                             const struct ib_send_wr *send_wr, u16 wqe_idx,
209                             u32 sgl_offset, __le32 *length_field)
210 {
211         u32 remain_size, copy_size, data_off, bytes = 0;
212         char *data;
213         int i = 0;
214
215         wqe_idx += (sgl_offset >> SQEBB_SHIFT);
216         sgl_offset &= (SQEBB_SIZE - 1);
217         data = get_queue_entry(qp->kern_qp.sq_buf, wqe_idx, qp->attrs.sq_size,
218                                SQEBB_SHIFT);
219
220         while (i < send_wr->num_sge) {
221                 bytes += send_wr->sg_list[i].length;
222                 if (bytes > (int)ERDMA_MAX_INLINE)
223                         return -EINVAL;
224
225                 remain_size = send_wr->sg_list[i].length;
226                 data_off = 0;
227
228                 while (1) {
229                         copy_size = min(remain_size, SQEBB_SIZE - sgl_offset);
230
231                         memcpy(data + sgl_offset,
232                                (void *)(uintptr_t)send_wr->sg_list[i].addr +
233                                        data_off,
234                                copy_size);
235                         remain_size -= copy_size;
236                         data_off += copy_size;
237                         sgl_offset += copy_size;
238                         wqe_idx += (sgl_offset >> SQEBB_SHIFT);
239                         sgl_offset &= (SQEBB_SIZE - 1);
240
241                         data = get_queue_entry(qp->kern_qp.sq_buf, wqe_idx,
242                                                qp->attrs.sq_size, SQEBB_SHIFT);
243                         if (!remain_size)
244                                 break;
245                 }
246
247                 i++;
248         }
249         *length_field = cpu_to_le32(bytes);
250
251         return bytes;
252 }
253
254 static int fill_sgl(struct erdma_qp *qp, const struct ib_send_wr *send_wr,
255                     u16 wqe_idx, u32 sgl_offset, __le32 *length_field)
256 {
257         int i = 0;
258         u32 bytes = 0;
259         char *sgl;
260
261         if (send_wr->num_sge > qp->dev->attrs.max_send_sge)
262                 return -EINVAL;
263
264         if (sgl_offset & 0xF)
265                 return -EINVAL;
266
267         while (i < send_wr->num_sge) {
268                 wqe_idx += (sgl_offset >> SQEBB_SHIFT);
269                 sgl_offset &= (SQEBB_SIZE - 1);
270                 sgl = get_queue_entry(qp->kern_qp.sq_buf, wqe_idx,
271                                       qp->attrs.sq_size, SQEBB_SHIFT);
272
273                 bytes += send_wr->sg_list[i].length;
274                 memcpy(sgl + sgl_offset, &send_wr->sg_list[i],
275                        sizeof(struct ib_sge));
276
277                 sgl_offset += sizeof(struct ib_sge);
278                 i++;
279         }
280
281         *length_field = cpu_to_le32(bytes);
282         return 0;
283 }
284
285 static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi,
286                               const struct ib_send_wr *send_wr)
287 {
288         u32 wqe_size, wqebb_cnt, hw_op, flags, sgl_offset;
289         u32 idx = *pi & (qp->attrs.sq_size - 1);
290         enum ib_wr_opcode op = send_wr->opcode;
291         struct erdma_atomic_sqe *atomic_sqe;
292         struct erdma_readreq_sqe *read_sqe;
293         struct erdma_reg_mr_sqe *regmr_sge;
294         struct erdma_write_sqe *write_sqe;
295         struct erdma_send_sqe *send_sqe;
296         struct ib_rdma_wr *rdma_wr;
297         struct erdma_sge *sge;
298         __le32 *length_field;
299         struct erdma_mr *mr;
300         u64 wqe_hdr, *entry;
301         u32 attrs;
302         int ret;
303
304         entry = get_queue_entry(qp->kern_qp.sq_buf, idx, qp->attrs.sq_size,
305                                 SQEBB_SHIFT);
306
307         /* Clear the SQE header section. */
308         *entry = 0;
309
310         qp->kern_qp.swr_tbl[idx] = send_wr->wr_id;
311         flags = send_wr->send_flags;
312         wqe_hdr = FIELD_PREP(
313                 ERDMA_SQE_HDR_CE_MASK,
314                 ((flags & IB_SEND_SIGNALED) || qp->kern_qp.sig_all) ? 1 : 0);
315         wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_SE_MASK,
316                               flags & IB_SEND_SOLICITED ? 1 : 0);
317         wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_FENCE_MASK,
318                               flags & IB_SEND_FENCE ? 1 : 0);
319         wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_INLINE_MASK,
320                               flags & IB_SEND_INLINE ? 1 : 0);
321         wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_QPN_MASK, QP_ID(qp));
322
323         switch (op) {
324         case IB_WR_RDMA_WRITE:
325         case IB_WR_RDMA_WRITE_WITH_IMM:
326                 hw_op = ERDMA_OP_WRITE;
327                 if (op == IB_WR_RDMA_WRITE_WITH_IMM)
328                         hw_op = ERDMA_OP_WRITE_WITH_IMM;
329                 wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK, hw_op);
330                 rdma_wr = container_of(send_wr, struct ib_rdma_wr, wr);
331                 write_sqe = (struct erdma_write_sqe *)entry;
332
333                 write_sqe->imm_data = send_wr->ex.imm_data;
334                 write_sqe->sink_stag = cpu_to_le32(rdma_wr->rkey);
335                 write_sqe->sink_to_h =
336                         cpu_to_le32(upper_32_bits(rdma_wr->remote_addr));
337                 write_sqe->sink_to_l =
338                         cpu_to_le32(lower_32_bits(rdma_wr->remote_addr));
339
340                 length_field = &write_sqe->length;
341                 wqe_size = sizeof(struct erdma_write_sqe);
342                 sgl_offset = wqe_size;
343                 break;
344         case IB_WR_RDMA_READ:
345         case IB_WR_RDMA_READ_WITH_INV:
346                 read_sqe = (struct erdma_readreq_sqe *)entry;
347                 if (unlikely(send_wr->num_sge != 1))
348                         return -EINVAL;
349                 hw_op = ERDMA_OP_READ;
350                 if (op == IB_WR_RDMA_READ_WITH_INV) {
351                         hw_op = ERDMA_OP_READ_WITH_INV;
352                         read_sqe->invalid_stag =
353                                 cpu_to_le32(send_wr->ex.invalidate_rkey);
354                 }
355
356                 wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK, hw_op);
357                 rdma_wr = container_of(send_wr, struct ib_rdma_wr, wr);
358                 read_sqe->length = cpu_to_le32(send_wr->sg_list[0].length);
359                 read_sqe->sink_stag = cpu_to_le32(send_wr->sg_list[0].lkey);
360                 read_sqe->sink_to_l =
361                         cpu_to_le32(lower_32_bits(send_wr->sg_list[0].addr));
362                 read_sqe->sink_to_h =
363                         cpu_to_le32(upper_32_bits(send_wr->sg_list[0].addr));
364
365                 sge = get_queue_entry(qp->kern_qp.sq_buf, idx + 1,
366                                       qp->attrs.sq_size, SQEBB_SHIFT);
367                 sge->addr = cpu_to_le64(rdma_wr->remote_addr);
368                 sge->key = cpu_to_le32(rdma_wr->rkey);
369                 sge->length = cpu_to_le32(send_wr->sg_list[0].length);
370                 wqe_size = sizeof(struct erdma_readreq_sqe) +
371                            send_wr->num_sge * sizeof(struct ib_sge);
372
373                 goto out;
374         case IB_WR_SEND:
375         case IB_WR_SEND_WITH_IMM:
376         case IB_WR_SEND_WITH_INV:
377                 send_sqe = (struct erdma_send_sqe *)entry;
378                 hw_op = ERDMA_OP_SEND;
379                 if (op == IB_WR_SEND_WITH_IMM) {
380                         hw_op = ERDMA_OP_SEND_WITH_IMM;
381                         send_sqe->imm_data = send_wr->ex.imm_data;
382                 } else if (op == IB_WR_SEND_WITH_INV) {
383                         hw_op = ERDMA_OP_SEND_WITH_INV;
384                         send_sqe->invalid_stag =
385                                 cpu_to_le32(send_wr->ex.invalidate_rkey);
386                 }
387                 wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK, hw_op);
388                 length_field = &send_sqe->length;
389                 wqe_size = sizeof(struct erdma_send_sqe);
390                 sgl_offset = wqe_size;
391
392                 break;
393         case IB_WR_REG_MR:
394                 wqe_hdr |=
395                         FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK, ERDMA_OP_REG_MR);
396                 regmr_sge = (struct erdma_reg_mr_sqe *)entry;
397                 mr = to_emr(reg_wr(send_wr)->mr);
398
399                 mr->access = ERDMA_MR_ACC_LR |
400                              to_erdma_access_flags(reg_wr(send_wr)->access);
401                 regmr_sge->addr = cpu_to_le64(mr->ibmr.iova);
402                 regmr_sge->length = cpu_to_le32(mr->ibmr.length);
403                 regmr_sge->stag = cpu_to_le32(reg_wr(send_wr)->key);
404                 attrs = FIELD_PREP(ERDMA_SQE_MR_ACCESS_MASK, mr->access) |
405                         FIELD_PREP(ERDMA_SQE_MR_MTT_CNT_MASK,
406                                    mr->mem.mtt_nents);
407
408                 if (mr->mem.mtt_nents <= ERDMA_MAX_INLINE_MTT_ENTRIES) {
409                         attrs |= FIELD_PREP(ERDMA_SQE_MR_MTT_TYPE_MASK, 0);
410                         /* Copy SGLs to SQE content to accelerate */
411                         memcpy(get_queue_entry(qp->kern_qp.sq_buf, idx + 1,
412                                                qp->attrs.sq_size, SQEBB_SHIFT),
413                                mr->mem.mtt->buf, MTT_SIZE(mr->mem.mtt_nents));
414                         wqe_size = sizeof(struct erdma_reg_mr_sqe) +
415                                    MTT_SIZE(mr->mem.mtt_nents);
416                 } else {
417                         attrs |= FIELD_PREP(ERDMA_SQE_MR_MTT_TYPE_MASK, 1);
418                         wqe_size = sizeof(struct erdma_reg_mr_sqe);
419                 }
420
421                 regmr_sge->attrs = cpu_to_le32(attrs);
422                 goto out;
423         case IB_WR_LOCAL_INV:
424                 wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK,
425                                       ERDMA_OP_LOCAL_INV);
426                 regmr_sge = (struct erdma_reg_mr_sqe *)entry;
427                 regmr_sge->stag = cpu_to_le32(send_wr->ex.invalidate_rkey);
428                 wqe_size = sizeof(struct erdma_reg_mr_sqe);
429                 goto out;
430         case IB_WR_ATOMIC_CMP_AND_SWP:
431         case IB_WR_ATOMIC_FETCH_AND_ADD:
432                 atomic_sqe = (struct erdma_atomic_sqe *)entry;
433                 if (op == IB_WR_ATOMIC_CMP_AND_SWP) {
434                         wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK,
435                                               ERDMA_OP_ATOMIC_CAS);
436                         atomic_sqe->fetchadd_swap_data =
437                                 cpu_to_le64(atomic_wr(send_wr)->swap);
438                         atomic_sqe->cmp_data =
439                                 cpu_to_le64(atomic_wr(send_wr)->compare_add);
440                 } else {
441                         wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK,
442                                               ERDMA_OP_ATOMIC_FAA);
443                         atomic_sqe->fetchadd_swap_data =
444                                 cpu_to_le64(atomic_wr(send_wr)->compare_add);
445                 }
446
447                 sge = get_queue_entry(qp->kern_qp.sq_buf, idx + 1,
448                                       qp->attrs.sq_size, SQEBB_SHIFT);
449                 sge->addr = cpu_to_le64(atomic_wr(send_wr)->remote_addr);
450                 sge->key = cpu_to_le32(atomic_wr(send_wr)->rkey);
451                 sge++;
452
453                 sge->addr = cpu_to_le64(send_wr->sg_list[0].addr);
454                 sge->key = cpu_to_le32(send_wr->sg_list[0].lkey);
455                 sge->length = cpu_to_le32(send_wr->sg_list[0].length);
456
457                 wqe_size = sizeof(*atomic_sqe);
458                 goto out;
459         default:
460                 return -EOPNOTSUPP;
461         }
462
463         if (flags & IB_SEND_INLINE) {
464                 ret = fill_inline_data(qp, send_wr, idx, sgl_offset,
465                                        length_field);
466                 if (ret < 0)
467                         return -EINVAL;
468                 wqe_size += ret;
469                 wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_SGL_LEN_MASK, ret);
470         } else {
471                 ret = fill_sgl(qp, send_wr, idx, sgl_offset, length_field);
472                 if (ret)
473                         return -EINVAL;
474                 wqe_size += send_wr->num_sge * sizeof(struct ib_sge);
475                 wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_SGL_LEN_MASK,
476                                       send_wr->num_sge);
477         }
478
479 out:
480         wqebb_cnt = SQEBB_COUNT(wqe_size);
481         wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_WQEBB_CNT_MASK, wqebb_cnt - 1);
482         *pi += wqebb_cnt;
483         wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_WQEBB_INDEX_MASK, *pi);
484
485         *entry = wqe_hdr;
486
487         return 0;
488 }
489
490 static void kick_sq_db(struct erdma_qp *qp, u16 pi)
491 {
492         u64 db_data = FIELD_PREP(ERDMA_SQE_HDR_QPN_MASK, QP_ID(qp)) |
493                       FIELD_PREP(ERDMA_SQE_HDR_WQEBB_INDEX_MASK, pi);
494
495         *(u64 *)qp->kern_qp.sq_db_info = db_data;
496         writeq(db_data, qp->kern_qp.hw_sq_db);
497 }
498
499 int erdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *send_wr,
500                     const struct ib_send_wr **bad_send_wr)
501 {
502         struct erdma_qp *qp = to_eqp(ibqp);
503         int ret = 0;
504         const struct ib_send_wr *wr = send_wr;
505         unsigned long flags;
506         u16 sq_pi;
507
508         if (!send_wr)
509                 return -EINVAL;
510
511         spin_lock_irqsave(&qp->lock, flags);
512         sq_pi = qp->kern_qp.sq_pi;
513
514         while (wr) {
515                 if ((u16)(sq_pi - qp->kern_qp.sq_ci) >= qp->attrs.sq_size) {
516                         ret = -ENOMEM;
517                         *bad_send_wr = send_wr;
518                         break;
519                 }
520
521                 ret = erdma_push_one_sqe(qp, &sq_pi, wr);
522                 if (ret) {
523                         *bad_send_wr = wr;
524                         break;
525                 }
526                 qp->kern_qp.sq_pi = sq_pi;
527                 kick_sq_db(qp, sq_pi);
528
529                 wr = wr->next;
530         }
531         spin_unlock_irqrestore(&qp->lock, flags);
532
533         if (unlikely(qp->flags & ERDMA_QP_IN_FLUSHING))
534                 mod_delayed_work(qp->dev->reflush_wq, &qp->reflush_dwork,
535                                  usecs_to_jiffies(100));
536
537         return ret;
538 }
539
540 static int erdma_post_recv_one(struct erdma_qp *qp,
541                                const struct ib_recv_wr *recv_wr)
542 {
543         struct erdma_rqe *rqe =
544                 get_queue_entry(qp->kern_qp.rq_buf, qp->kern_qp.rq_pi,
545                                 qp->attrs.rq_size, RQE_SHIFT);
546
547         rqe->qe_idx = cpu_to_le16(qp->kern_qp.rq_pi + 1);
548         rqe->qpn = cpu_to_le32(QP_ID(qp));
549
550         if (recv_wr->num_sge == 0) {
551                 rqe->length = 0;
552         } else if (recv_wr->num_sge == 1) {
553                 rqe->stag = cpu_to_le32(recv_wr->sg_list[0].lkey);
554                 rqe->to = cpu_to_le64(recv_wr->sg_list[0].addr);
555                 rqe->length = cpu_to_le32(recv_wr->sg_list[0].length);
556         } else {
557                 return -EINVAL;
558         }
559
560         *(u64 *)qp->kern_qp.rq_db_info = *(u64 *)rqe;
561         writeq(*(u64 *)rqe, qp->kern_qp.hw_rq_db);
562
563         qp->kern_qp.rwr_tbl[qp->kern_qp.rq_pi & (qp->attrs.rq_size - 1)] =
564                 recv_wr->wr_id;
565         qp->kern_qp.rq_pi++;
566
567         return 0;
568 }
569
570 int erdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *recv_wr,
571                     const struct ib_recv_wr **bad_recv_wr)
572 {
573         const struct ib_recv_wr *wr = recv_wr;
574         struct erdma_qp *qp = to_eqp(ibqp);
575         unsigned long flags;
576         int ret;
577
578         spin_lock_irqsave(&qp->lock, flags);
579
580         while (wr) {
581                 ret = erdma_post_recv_one(qp, wr);
582                 if (ret) {
583                         *bad_recv_wr = wr;
584                         break;
585                 }
586                 wr = wr->next;
587         }
588
589         spin_unlock_irqrestore(&qp->lock, flags);
590
591         if (unlikely(qp->flags & ERDMA_QP_IN_FLUSHING))
592                 mod_delayed_work(qp->dev->reflush_wq, &qp->reflush_dwork,
593                                  usecs_to_jiffies(100));
594
595         return ret;
596 }
This page took 0.064566 seconds and 4 git commands to generate.