1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
4*4882a593Smuzhiyun * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/skbuff.h>
8*4882a593Smuzhiyun #include <crypto/hash.h>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include "rxe.h"
11*4882a593Smuzhiyun #include "rxe_loc.h"
12*4882a593Smuzhiyun #include "rxe_queue.h"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun static int next_opcode(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
15*4882a593Smuzhiyun u32 opcode);
16*4882a593Smuzhiyun
retry_first_write_send(struct rxe_qp * qp,struct rxe_send_wqe * wqe,unsigned int mask,int npsn)17*4882a593Smuzhiyun static inline void retry_first_write_send(struct rxe_qp *qp,
18*4882a593Smuzhiyun struct rxe_send_wqe *wqe,
19*4882a593Smuzhiyun unsigned int mask, int npsn)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun int i;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun for (i = 0; i < npsn; i++) {
24*4882a593Smuzhiyun int to_send = (wqe->dma.resid > qp->mtu) ?
25*4882a593Smuzhiyun qp->mtu : wqe->dma.resid;
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun qp->req.opcode = next_opcode(qp, wqe,
28*4882a593Smuzhiyun wqe->wr.opcode);
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun if (wqe->wr.send_flags & IB_SEND_INLINE) {
31*4882a593Smuzhiyun wqe->dma.resid -= to_send;
32*4882a593Smuzhiyun wqe->dma.sge_offset += to_send;
33*4882a593Smuzhiyun } else {
34*4882a593Smuzhiyun advance_dma_data(&wqe->dma, to_send);
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun if (mask & WR_WRITE_MASK)
37*4882a593Smuzhiyun wqe->iova += qp->mtu;
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
req_retry(struct rxe_qp * qp)41*4882a593Smuzhiyun static void req_retry(struct rxe_qp *qp)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun struct rxe_send_wqe *wqe;
44*4882a593Smuzhiyun unsigned int wqe_index;
45*4882a593Smuzhiyun unsigned int mask;
46*4882a593Smuzhiyun int npsn;
47*4882a593Smuzhiyun int first = 1;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun qp->req.wqe_index = consumer_index(qp->sq.queue);
50*4882a593Smuzhiyun qp->req.psn = qp->comp.psn;
51*4882a593Smuzhiyun qp->req.opcode = -1;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun for (wqe_index = consumer_index(qp->sq.queue);
54*4882a593Smuzhiyun wqe_index != producer_index(qp->sq.queue);
55*4882a593Smuzhiyun wqe_index = next_index(qp->sq.queue, wqe_index)) {
56*4882a593Smuzhiyun wqe = addr_from_index(qp->sq.queue, wqe_index);
57*4882a593Smuzhiyun mask = wr_opcode_mask(wqe->wr.opcode, qp);
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun if (wqe->state == wqe_state_posted)
60*4882a593Smuzhiyun break;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun if (wqe->state == wqe_state_done)
63*4882a593Smuzhiyun continue;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun wqe->iova = (mask & WR_ATOMIC_MASK) ?
66*4882a593Smuzhiyun wqe->wr.wr.atomic.remote_addr :
67*4882a593Smuzhiyun (mask & WR_READ_OR_WRITE_MASK) ?
68*4882a593Smuzhiyun wqe->wr.wr.rdma.remote_addr :
69*4882a593Smuzhiyun 0;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun if (!first || (mask & WR_READ_MASK) == 0) {
72*4882a593Smuzhiyun wqe->dma.resid = wqe->dma.length;
73*4882a593Smuzhiyun wqe->dma.cur_sge = 0;
74*4882a593Smuzhiyun wqe->dma.sge_offset = 0;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun if (first) {
78*4882a593Smuzhiyun first = 0;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (mask & WR_WRITE_OR_SEND_MASK) {
81*4882a593Smuzhiyun npsn = (qp->comp.psn - wqe->first_psn) &
82*4882a593Smuzhiyun BTH_PSN_MASK;
83*4882a593Smuzhiyun retry_first_write_send(qp, wqe, mask, npsn);
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun if (mask & WR_READ_MASK) {
87*4882a593Smuzhiyun npsn = (wqe->dma.length - wqe->dma.resid) /
88*4882a593Smuzhiyun qp->mtu;
89*4882a593Smuzhiyun wqe->iova += npsn * qp->mtu;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun wqe->state = wqe_state_posted;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
rnr_nak_timer(struct timer_list * t)97*4882a593Smuzhiyun void rnr_nak_timer(struct timer_list *t)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun struct rxe_qp *qp = from_timer(qp, t, rnr_nak_timer);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun pr_debug("qp#%d rnr nak timer fired\n", qp_num(qp));
102*4882a593Smuzhiyun rxe_run_task(&qp->req.task, 1);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
req_next_wqe(struct rxe_qp * qp)105*4882a593Smuzhiyun static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun struct rxe_send_wqe *wqe = queue_head(qp->sq.queue);
108*4882a593Smuzhiyun unsigned long flags;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun if (unlikely(qp->req.state == QP_STATE_DRAIN)) {
111*4882a593Smuzhiyun /* check to see if we are drained;
112*4882a593Smuzhiyun * state_lock used by requester and completer
113*4882a593Smuzhiyun */
114*4882a593Smuzhiyun spin_lock_irqsave(&qp->state_lock, flags);
115*4882a593Smuzhiyun do {
116*4882a593Smuzhiyun if (qp->req.state != QP_STATE_DRAIN) {
117*4882a593Smuzhiyun /* comp just finished */
118*4882a593Smuzhiyun spin_unlock_irqrestore(&qp->state_lock,
119*4882a593Smuzhiyun flags);
120*4882a593Smuzhiyun break;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun if (wqe && ((qp->req.wqe_index !=
124*4882a593Smuzhiyun consumer_index(qp->sq.queue)) ||
125*4882a593Smuzhiyun (wqe->state != wqe_state_posted))) {
126*4882a593Smuzhiyun /* comp not done yet */
127*4882a593Smuzhiyun spin_unlock_irqrestore(&qp->state_lock,
128*4882a593Smuzhiyun flags);
129*4882a593Smuzhiyun break;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun qp->req.state = QP_STATE_DRAINED;
133*4882a593Smuzhiyun spin_unlock_irqrestore(&qp->state_lock, flags);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun if (qp->ibqp.event_handler) {
136*4882a593Smuzhiyun struct ib_event ev;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun ev.device = qp->ibqp.device;
139*4882a593Smuzhiyun ev.element.qp = &qp->ibqp;
140*4882a593Smuzhiyun ev.event = IB_EVENT_SQ_DRAINED;
141*4882a593Smuzhiyun qp->ibqp.event_handler(&ev,
142*4882a593Smuzhiyun qp->ibqp.qp_context);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun } while (0);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun if (qp->req.wqe_index == producer_index(qp->sq.queue))
148*4882a593Smuzhiyun return NULL;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun wqe = addr_from_index(qp->sq.queue, qp->req.wqe_index);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (unlikely((qp->req.state == QP_STATE_DRAIN ||
153*4882a593Smuzhiyun qp->req.state == QP_STATE_DRAINED) &&
154*4882a593Smuzhiyun (wqe->state != wqe_state_processing)))
155*4882a593Smuzhiyun return NULL;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun if (unlikely((wqe->wr.send_flags & IB_SEND_FENCE) &&
158*4882a593Smuzhiyun (qp->req.wqe_index != consumer_index(qp->sq.queue)))) {
159*4882a593Smuzhiyun qp->req.wait_fence = 1;
160*4882a593Smuzhiyun return NULL;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun wqe->mask = wr_opcode_mask(wqe->wr.opcode, qp);
164*4882a593Smuzhiyun return wqe;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
next_opcode_rc(struct rxe_qp * qp,u32 opcode,int fits)167*4882a593Smuzhiyun static int next_opcode_rc(struct rxe_qp *qp, u32 opcode, int fits)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun switch (opcode) {
170*4882a593Smuzhiyun case IB_WR_RDMA_WRITE:
171*4882a593Smuzhiyun if (qp->req.opcode == IB_OPCODE_RC_RDMA_WRITE_FIRST ||
172*4882a593Smuzhiyun qp->req.opcode == IB_OPCODE_RC_RDMA_WRITE_MIDDLE)
173*4882a593Smuzhiyun return fits ?
174*4882a593Smuzhiyun IB_OPCODE_RC_RDMA_WRITE_LAST :
175*4882a593Smuzhiyun IB_OPCODE_RC_RDMA_WRITE_MIDDLE;
176*4882a593Smuzhiyun else
177*4882a593Smuzhiyun return fits ?
178*4882a593Smuzhiyun IB_OPCODE_RC_RDMA_WRITE_ONLY :
179*4882a593Smuzhiyun IB_OPCODE_RC_RDMA_WRITE_FIRST;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun case IB_WR_RDMA_WRITE_WITH_IMM:
182*4882a593Smuzhiyun if (qp->req.opcode == IB_OPCODE_RC_RDMA_WRITE_FIRST ||
183*4882a593Smuzhiyun qp->req.opcode == IB_OPCODE_RC_RDMA_WRITE_MIDDLE)
184*4882a593Smuzhiyun return fits ?
185*4882a593Smuzhiyun IB_OPCODE_RC_RDMA_WRITE_LAST_WITH_IMMEDIATE :
186*4882a593Smuzhiyun IB_OPCODE_RC_RDMA_WRITE_MIDDLE;
187*4882a593Smuzhiyun else
188*4882a593Smuzhiyun return fits ?
189*4882a593Smuzhiyun IB_OPCODE_RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE :
190*4882a593Smuzhiyun IB_OPCODE_RC_RDMA_WRITE_FIRST;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun case IB_WR_SEND:
193*4882a593Smuzhiyun if (qp->req.opcode == IB_OPCODE_RC_SEND_FIRST ||
194*4882a593Smuzhiyun qp->req.opcode == IB_OPCODE_RC_SEND_MIDDLE)
195*4882a593Smuzhiyun return fits ?
196*4882a593Smuzhiyun IB_OPCODE_RC_SEND_LAST :
197*4882a593Smuzhiyun IB_OPCODE_RC_SEND_MIDDLE;
198*4882a593Smuzhiyun else
199*4882a593Smuzhiyun return fits ?
200*4882a593Smuzhiyun IB_OPCODE_RC_SEND_ONLY :
201*4882a593Smuzhiyun IB_OPCODE_RC_SEND_FIRST;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun case IB_WR_SEND_WITH_IMM:
204*4882a593Smuzhiyun if (qp->req.opcode == IB_OPCODE_RC_SEND_FIRST ||
205*4882a593Smuzhiyun qp->req.opcode == IB_OPCODE_RC_SEND_MIDDLE)
206*4882a593Smuzhiyun return fits ?
207*4882a593Smuzhiyun IB_OPCODE_RC_SEND_LAST_WITH_IMMEDIATE :
208*4882a593Smuzhiyun IB_OPCODE_RC_SEND_MIDDLE;
209*4882a593Smuzhiyun else
210*4882a593Smuzhiyun return fits ?
211*4882a593Smuzhiyun IB_OPCODE_RC_SEND_ONLY_WITH_IMMEDIATE :
212*4882a593Smuzhiyun IB_OPCODE_RC_SEND_FIRST;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun case IB_WR_RDMA_READ:
215*4882a593Smuzhiyun return IB_OPCODE_RC_RDMA_READ_REQUEST;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun case IB_WR_ATOMIC_CMP_AND_SWP:
218*4882a593Smuzhiyun return IB_OPCODE_RC_COMPARE_SWAP;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun case IB_WR_ATOMIC_FETCH_AND_ADD:
221*4882a593Smuzhiyun return IB_OPCODE_RC_FETCH_ADD;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun case IB_WR_SEND_WITH_INV:
224*4882a593Smuzhiyun if (qp->req.opcode == IB_OPCODE_RC_SEND_FIRST ||
225*4882a593Smuzhiyun qp->req.opcode == IB_OPCODE_RC_SEND_MIDDLE)
226*4882a593Smuzhiyun return fits ? IB_OPCODE_RC_SEND_LAST_WITH_INVALIDATE :
227*4882a593Smuzhiyun IB_OPCODE_RC_SEND_MIDDLE;
228*4882a593Smuzhiyun else
229*4882a593Smuzhiyun return fits ? IB_OPCODE_RC_SEND_ONLY_WITH_INVALIDATE :
230*4882a593Smuzhiyun IB_OPCODE_RC_SEND_FIRST;
231*4882a593Smuzhiyun case IB_WR_REG_MR:
232*4882a593Smuzhiyun case IB_WR_LOCAL_INV:
233*4882a593Smuzhiyun return opcode;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun return -EINVAL;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
next_opcode_uc(struct rxe_qp * qp,u32 opcode,int fits)239*4882a593Smuzhiyun static int next_opcode_uc(struct rxe_qp *qp, u32 opcode, int fits)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun switch (opcode) {
242*4882a593Smuzhiyun case IB_WR_RDMA_WRITE:
243*4882a593Smuzhiyun if (qp->req.opcode == IB_OPCODE_UC_RDMA_WRITE_FIRST ||
244*4882a593Smuzhiyun qp->req.opcode == IB_OPCODE_UC_RDMA_WRITE_MIDDLE)
245*4882a593Smuzhiyun return fits ?
246*4882a593Smuzhiyun IB_OPCODE_UC_RDMA_WRITE_LAST :
247*4882a593Smuzhiyun IB_OPCODE_UC_RDMA_WRITE_MIDDLE;
248*4882a593Smuzhiyun else
249*4882a593Smuzhiyun return fits ?
250*4882a593Smuzhiyun IB_OPCODE_UC_RDMA_WRITE_ONLY :
251*4882a593Smuzhiyun IB_OPCODE_UC_RDMA_WRITE_FIRST;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun case IB_WR_RDMA_WRITE_WITH_IMM:
254*4882a593Smuzhiyun if (qp->req.opcode == IB_OPCODE_UC_RDMA_WRITE_FIRST ||
255*4882a593Smuzhiyun qp->req.opcode == IB_OPCODE_UC_RDMA_WRITE_MIDDLE)
256*4882a593Smuzhiyun return fits ?
257*4882a593Smuzhiyun IB_OPCODE_UC_RDMA_WRITE_LAST_WITH_IMMEDIATE :
258*4882a593Smuzhiyun IB_OPCODE_UC_RDMA_WRITE_MIDDLE;
259*4882a593Smuzhiyun else
260*4882a593Smuzhiyun return fits ?
261*4882a593Smuzhiyun IB_OPCODE_UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE :
262*4882a593Smuzhiyun IB_OPCODE_UC_RDMA_WRITE_FIRST;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun case IB_WR_SEND:
265*4882a593Smuzhiyun if (qp->req.opcode == IB_OPCODE_UC_SEND_FIRST ||
266*4882a593Smuzhiyun qp->req.opcode == IB_OPCODE_UC_SEND_MIDDLE)
267*4882a593Smuzhiyun return fits ?
268*4882a593Smuzhiyun IB_OPCODE_UC_SEND_LAST :
269*4882a593Smuzhiyun IB_OPCODE_UC_SEND_MIDDLE;
270*4882a593Smuzhiyun else
271*4882a593Smuzhiyun return fits ?
272*4882a593Smuzhiyun IB_OPCODE_UC_SEND_ONLY :
273*4882a593Smuzhiyun IB_OPCODE_UC_SEND_FIRST;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun case IB_WR_SEND_WITH_IMM:
276*4882a593Smuzhiyun if (qp->req.opcode == IB_OPCODE_UC_SEND_FIRST ||
277*4882a593Smuzhiyun qp->req.opcode == IB_OPCODE_UC_SEND_MIDDLE)
278*4882a593Smuzhiyun return fits ?
279*4882a593Smuzhiyun IB_OPCODE_UC_SEND_LAST_WITH_IMMEDIATE :
280*4882a593Smuzhiyun IB_OPCODE_UC_SEND_MIDDLE;
281*4882a593Smuzhiyun else
282*4882a593Smuzhiyun return fits ?
283*4882a593Smuzhiyun IB_OPCODE_UC_SEND_ONLY_WITH_IMMEDIATE :
284*4882a593Smuzhiyun IB_OPCODE_UC_SEND_FIRST;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun return -EINVAL;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
next_opcode(struct rxe_qp * qp,struct rxe_send_wqe * wqe,u32 opcode)290*4882a593Smuzhiyun static int next_opcode(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
291*4882a593Smuzhiyun u32 opcode)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun int fits = (wqe->dma.resid <= qp->mtu);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun switch (qp_type(qp)) {
296*4882a593Smuzhiyun case IB_QPT_RC:
297*4882a593Smuzhiyun return next_opcode_rc(qp, opcode, fits);
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun case IB_QPT_UC:
300*4882a593Smuzhiyun return next_opcode_uc(qp, opcode, fits);
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun case IB_QPT_SMI:
303*4882a593Smuzhiyun case IB_QPT_UD:
304*4882a593Smuzhiyun case IB_QPT_GSI:
305*4882a593Smuzhiyun switch (opcode) {
306*4882a593Smuzhiyun case IB_WR_SEND:
307*4882a593Smuzhiyun return IB_OPCODE_UD_SEND_ONLY;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun case IB_WR_SEND_WITH_IMM:
310*4882a593Smuzhiyun return IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun break;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun default:
315*4882a593Smuzhiyun break;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun return -EINVAL;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun
check_init_depth(struct rxe_qp * qp,struct rxe_send_wqe * wqe)321*4882a593Smuzhiyun static inline int check_init_depth(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun int depth;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (wqe->has_rd_atomic)
326*4882a593Smuzhiyun return 0;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun qp->req.need_rd_atomic = 1;
329*4882a593Smuzhiyun depth = atomic_dec_return(&qp->req.rd_atomic);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun if (depth >= 0) {
332*4882a593Smuzhiyun qp->req.need_rd_atomic = 0;
333*4882a593Smuzhiyun wqe->has_rd_atomic = 1;
334*4882a593Smuzhiyun return 0;
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun atomic_inc(&qp->req.rd_atomic);
338*4882a593Smuzhiyun return -EAGAIN;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
get_mtu(struct rxe_qp * qp)341*4882a593Smuzhiyun static inline int get_mtu(struct rxe_qp *qp)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun if ((qp_type(qp) == IB_QPT_RC) || (qp_type(qp) == IB_QPT_UC))
346*4882a593Smuzhiyun return qp->mtu;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun return rxe->port.mtu_cap;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun
init_req_packet(struct rxe_qp * qp,struct rxe_send_wqe * wqe,int opcode,int payload,struct rxe_pkt_info * pkt)351*4882a593Smuzhiyun static struct sk_buff *init_req_packet(struct rxe_qp *qp,
352*4882a593Smuzhiyun struct rxe_send_wqe *wqe,
353*4882a593Smuzhiyun int opcode, int payload,
354*4882a593Smuzhiyun struct rxe_pkt_info *pkt)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
357*4882a593Smuzhiyun struct sk_buff *skb;
358*4882a593Smuzhiyun struct rxe_send_wr *ibwr = &wqe->wr;
359*4882a593Smuzhiyun struct rxe_av *av;
360*4882a593Smuzhiyun int pad = (-payload) & 0x3;
361*4882a593Smuzhiyun int paylen;
362*4882a593Smuzhiyun int solicited;
363*4882a593Smuzhiyun u16 pkey;
364*4882a593Smuzhiyun u32 qp_num;
365*4882a593Smuzhiyun int ack_req;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun /* length from start of bth to end of icrc */
368*4882a593Smuzhiyun paylen = rxe_opcode[opcode].length + payload + pad + RXE_ICRC_SIZE;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun /* pkt->hdr, rxe, port_num and mask are initialized in ifc
371*4882a593Smuzhiyun * layer
372*4882a593Smuzhiyun */
373*4882a593Smuzhiyun pkt->opcode = opcode;
374*4882a593Smuzhiyun pkt->qp = qp;
375*4882a593Smuzhiyun pkt->psn = qp->req.psn;
376*4882a593Smuzhiyun pkt->mask = rxe_opcode[opcode].mask;
377*4882a593Smuzhiyun pkt->paylen = paylen;
378*4882a593Smuzhiyun pkt->offset = 0;
379*4882a593Smuzhiyun pkt->wqe = wqe;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun /* init skb */
382*4882a593Smuzhiyun av = rxe_get_av(pkt);
383*4882a593Smuzhiyun skb = rxe_init_packet(rxe, av, paylen, pkt);
384*4882a593Smuzhiyun if (unlikely(!skb))
385*4882a593Smuzhiyun return NULL;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun /* init bth */
388*4882a593Smuzhiyun solicited = (ibwr->send_flags & IB_SEND_SOLICITED) &&
389*4882a593Smuzhiyun (pkt->mask & RXE_END_MASK) &&
390*4882a593Smuzhiyun ((pkt->mask & (RXE_SEND_MASK)) ||
391*4882a593Smuzhiyun (pkt->mask & (RXE_WRITE_MASK | RXE_IMMDT_MASK)) ==
392*4882a593Smuzhiyun (RXE_WRITE_MASK | RXE_IMMDT_MASK));
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun pkey = IB_DEFAULT_PKEY_FULL;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun qp_num = (pkt->mask & RXE_DETH_MASK) ? ibwr->wr.ud.remote_qpn :
397*4882a593Smuzhiyun qp->attr.dest_qp_num;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun ack_req = ((pkt->mask & RXE_END_MASK) ||
400*4882a593Smuzhiyun (qp->req.noack_pkts++ > RXE_MAX_PKT_PER_ACK));
401*4882a593Smuzhiyun if (ack_req)
402*4882a593Smuzhiyun qp->req.noack_pkts = 0;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun bth_init(pkt, pkt->opcode, solicited, 0, pad, pkey, qp_num,
405*4882a593Smuzhiyun ack_req, pkt->psn);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /* init optional headers */
408*4882a593Smuzhiyun if (pkt->mask & RXE_RETH_MASK) {
409*4882a593Smuzhiyun reth_set_rkey(pkt, ibwr->wr.rdma.rkey);
410*4882a593Smuzhiyun reth_set_va(pkt, wqe->iova);
411*4882a593Smuzhiyun reth_set_len(pkt, wqe->dma.resid);
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun if (pkt->mask & RXE_IMMDT_MASK)
415*4882a593Smuzhiyun immdt_set_imm(pkt, ibwr->ex.imm_data);
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun if (pkt->mask & RXE_IETH_MASK)
418*4882a593Smuzhiyun ieth_set_rkey(pkt, ibwr->ex.invalidate_rkey);
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun if (pkt->mask & RXE_ATMETH_MASK) {
421*4882a593Smuzhiyun atmeth_set_va(pkt, wqe->iova);
422*4882a593Smuzhiyun if (opcode == IB_OPCODE_RC_COMPARE_SWAP ||
423*4882a593Smuzhiyun opcode == IB_OPCODE_RD_COMPARE_SWAP) {
424*4882a593Smuzhiyun atmeth_set_swap_add(pkt, ibwr->wr.atomic.swap);
425*4882a593Smuzhiyun atmeth_set_comp(pkt, ibwr->wr.atomic.compare_add);
426*4882a593Smuzhiyun } else {
427*4882a593Smuzhiyun atmeth_set_swap_add(pkt, ibwr->wr.atomic.compare_add);
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun atmeth_set_rkey(pkt, ibwr->wr.atomic.rkey);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun if (pkt->mask & RXE_DETH_MASK) {
433*4882a593Smuzhiyun if (qp->ibqp.qp_num == 1)
434*4882a593Smuzhiyun deth_set_qkey(pkt, GSI_QKEY);
435*4882a593Smuzhiyun else
436*4882a593Smuzhiyun deth_set_qkey(pkt, ibwr->wr.ud.remote_qkey);
437*4882a593Smuzhiyun deth_set_sqp(pkt, qp->ibqp.qp_num);
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun return skb;
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
fill_packet(struct rxe_qp * qp,struct rxe_send_wqe * wqe,struct rxe_pkt_info * pkt,struct sk_buff * skb,int paylen)443*4882a593Smuzhiyun static int fill_packet(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
444*4882a593Smuzhiyun struct rxe_pkt_info *pkt, struct sk_buff *skb,
445*4882a593Smuzhiyun int paylen)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
448*4882a593Smuzhiyun u32 crc = 0;
449*4882a593Smuzhiyun u32 *p;
450*4882a593Smuzhiyun int err;
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun err = rxe_prepare(pkt, skb, &crc);
453*4882a593Smuzhiyun if (err)
454*4882a593Smuzhiyun return err;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if (pkt->mask & RXE_WRITE_OR_SEND) {
457*4882a593Smuzhiyun if (wqe->wr.send_flags & IB_SEND_INLINE) {
458*4882a593Smuzhiyun u8 *tmp = &wqe->dma.inline_data[wqe->dma.sge_offset];
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun crc = rxe_crc32(rxe, crc, tmp, paylen);
461*4882a593Smuzhiyun memcpy(payload_addr(pkt), tmp, paylen);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun wqe->dma.resid -= paylen;
464*4882a593Smuzhiyun wqe->dma.sge_offset += paylen;
465*4882a593Smuzhiyun } else {
466*4882a593Smuzhiyun err = copy_data(qp->pd, 0, &wqe->dma,
467*4882a593Smuzhiyun payload_addr(pkt), paylen,
468*4882a593Smuzhiyun from_mem_obj,
469*4882a593Smuzhiyun &crc);
470*4882a593Smuzhiyun if (err)
471*4882a593Smuzhiyun return err;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun if (bth_pad(pkt)) {
474*4882a593Smuzhiyun u8 *pad = payload_addr(pkt) + paylen;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun memset(pad, 0, bth_pad(pkt));
477*4882a593Smuzhiyun crc = rxe_crc32(rxe, crc, pad, bth_pad(pkt));
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun p = payload_addr(pkt) + paylen + bth_pad(pkt);
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun *p = ~crc;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun return 0;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
update_wqe_state(struct rxe_qp * qp,struct rxe_send_wqe * wqe,struct rxe_pkt_info * pkt)487*4882a593Smuzhiyun static void update_wqe_state(struct rxe_qp *qp,
488*4882a593Smuzhiyun struct rxe_send_wqe *wqe,
489*4882a593Smuzhiyun struct rxe_pkt_info *pkt)
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun if (pkt->mask & RXE_END_MASK) {
492*4882a593Smuzhiyun if (qp_type(qp) == IB_QPT_RC)
493*4882a593Smuzhiyun wqe->state = wqe_state_pending;
494*4882a593Smuzhiyun } else {
495*4882a593Smuzhiyun wqe->state = wqe_state_processing;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
update_wqe_psn(struct rxe_qp * qp,struct rxe_send_wqe * wqe,struct rxe_pkt_info * pkt,int payload)499*4882a593Smuzhiyun static void update_wqe_psn(struct rxe_qp *qp,
500*4882a593Smuzhiyun struct rxe_send_wqe *wqe,
501*4882a593Smuzhiyun struct rxe_pkt_info *pkt,
502*4882a593Smuzhiyun int payload)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun /* number of packets left to send including current one */
505*4882a593Smuzhiyun int num_pkt = (wqe->dma.resid + payload + qp->mtu - 1) / qp->mtu;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun /* handle zero length packet case */
508*4882a593Smuzhiyun if (num_pkt == 0)
509*4882a593Smuzhiyun num_pkt = 1;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun if (pkt->mask & RXE_START_MASK) {
512*4882a593Smuzhiyun wqe->first_psn = qp->req.psn;
513*4882a593Smuzhiyun wqe->last_psn = (qp->req.psn + num_pkt - 1) & BTH_PSN_MASK;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun if (pkt->mask & RXE_READ_MASK)
517*4882a593Smuzhiyun qp->req.psn = (wqe->first_psn + num_pkt) & BTH_PSN_MASK;
518*4882a593Smuzhiyun else
519*4882a593Smuzhiyun qp->req.psn = (qp->req.psn + 1) & BTH_PSN_MASK;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
save_state(struct rxe_send_wqe * wqe,struct rxe_qp * qp,struct rxe_send_wqe * rollback_wqe,u32 * rollback_psn)522*4882a593Smuzhiyun static void save_state(struct rxe_send_wqe *wqe,
523*4882a593Smuzhiyun struct rxe_qp *qp,
524*4882a593Smuzhiyun struct rxe_send_wqe *rollback_wqe,
525*4882a593Smuzhiyun u32 *rollback_psn)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun rollback_wqe->state = wqe->state;
528*4882a593Smuzhiyun rollback_wqe->first_psn = wqe->first_psn;
529*4882a593Smuzhiyun rollback_wqe->last_psn = wqe->last_psn;
530*4882a593Smuzhiyun *rollback_psn = qp->req.psn;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
rollback_state(struct rxe_send_wqe * wqe,struct rxe_qp * qp,struct rxe_send_wqe * rollback_wqe,u32 rollback_psn)533*4882a593Smuzhiyun static void rollback_state(struct rxe_send_wqe *wqe,
534*4882a593Smuzhiyun struct rxe_qp *qp,
535*4882a593Smuzhiyun struct rxe_send_wqe *rollback_wqe,
536*4882a593Smuzhiyun u32 rollback_psn)
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun wqe->state = rollback_wqe->state;
539*4882a593Smuzhiyun wqe->first_psn = rollback_wqe->first_psn;
540*4882a593Smuzhiyun wqe->last_psn = rollback_wqe->last_psn;
541*4882a593Smuzhiyun qp->req.psn = rollback_psn;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
update_state(struct rxe_qp * qp,struct rxe_send_wqe * wqe,struct rxe_pkt_info * pkt,int payload)544*4882a593Smuzhiyun static void update_state(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
545*4882a593Smuzhiyun struct rxe_pkt_info *pkt, int payload)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun qp->req.opcode = pkt->opcode;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun if (pkt->mask & RXE_END_MASK)
550*4882a593Smuzhiyun qp->req.wqe_index = next_index(qp->sq.queue, qp->req.wqe_index);
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun qp->need_req_skb = 0;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun if (qp->qp_timeout_jiffies && !timer_pending(&qp->retrans_timer))
555*4882a593Smuzhiyun mod_timer(&qp->retrans_timer,
556*4882a593Smuzhiyun jiffies + qp->qp_timeout_jiffies);
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun
rxe_requester(void * arg)559*4882a593Smuzhiyun int rxe_requester(void *arg)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun struct rxe_qp *qp = (struct rxe_qp *)arg;
562*4882a593Smuzhiyun struct rxe_pkt_info pkt;
563*4882a593Smuzhiyun struct sk_buff *skb;
564*4882a593Smuzhiyun struct rxe_send_wqe *wqe;
565*4882a593Smuzhiyun enum rxe_hdr_mask mask;
566*4882a593Smuzhiyun int payload;
567*4882a593Smuzhiyun int mtu;
568*4882a593Smuzhiyun int opcode;
569*4882a593Smuzhiyun int ret;
570*4882a593Smuzhiyun struct rxe_send_wqe rollback_wqe;
571*4882a593Smuzhiyun u32 rollback_psn;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun rxe_add_ref(qp);
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun next_wqe:
576*4882a593Smuzhiyun if (unlikely(!qp->valid || qp->req.state == QP_STATE_ERROR))
577*4882a593Smuzhiyun goto exit;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun if (unlikely(qp->req.state == QP_STATE_RESET)) {
580*4882a593Smuzhiyun qp->req.wqe_index = consumer_index(qp->sq.queue);
581*4882a593Smuzhiyun qp->req.opcode = -1;
582*4882a593Smuzhiyun qp->req.need_rd_atomic = 0;
583*4882a593Smuzhiyun qp->req.wait_psn = 0;
584*4882a593Smuzhiyun qp->req.need_retry = 0;
585*4882a593Smuzhiyun goto exit;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun if (unlikely(qp->req.need_retry)) {
589*4882a593Smuzhiyun req_retry(qp);
590*4882a593Smuzhiyun qp->req.need_retry = 0;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun wqe = req_next_wqe(qp);
594*4882a593Smuzhiyun if (unlikely(!wqe))
595*4882a593Smuzhiyun goto exit;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun if (wqe->mask & WR_REG_MASK) {
598*4882a593Smuzhiyun if (wqe->wr.opcode == IB_WR_LOCAL_INV) {
599*4882a593Smuzhiyun struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
600*4882a593Smuzhiyun struct rxe_mem *rmr;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun rmr = rxe_pool_get_index(&rxe->mr_pool,
603*4882a593Smuzhiyun wqe->wr.ex.invalidate_rkey >> 8);
604*4882a593Smuzhiyun if (!rmr) {
605*4882a593Smuzhiyun pr_err("No mr for key %#x\n",
606*4882a593Smuzhiyun wqe->wr.ex.invalidate_rkey);
607*4882a593Smuzhiyun wqe->state = wqe_state_error;
608*4882a593Smuzhiyun wqe->status = IB_WC_MW_BIND_ERR;
609*4882a593Smuzhiyun goto exit;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun rmr->state = RXE_MEM_STATE_FREE;
612*4882a593Smuzhiyun rxe_drop_ref(rmr);
613*4882a593Smuzhiyun wqe->state = wqe_state_done;
614*4882a593Smuzhiyun wqe->status = IB_WC_SUCCESS;
615*4882a593Smuzhiyun } else if (wqe->wr.opcode == IB_WR_REG_MR) {
616*4882a593Smuzhiyun struct rxe_mem *rmr = to_rmr(wqe->wr.wr.reg.mr);
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun rmr->state = RXE_MEM_STATE_VALID;
619*4882a593Smuzhiyun rmr->access = wqe->wr.wr.reg.access;
620*4882a593Smuzhiyun rmr->ibmr.lkey = wqe->wr.wr.reg.key;
621*4882a593Smuzhiyun rmr->ibmr.rkey = wqe->wr.wr.reg.key;
622*4882a593Smuzhiyun rmr->iova = wqe->wr.wr.reg.mr->iova;
623*4882a593Smuzhiyun wqe->state = wqe_state_done;
624*4882a593Smuzhiyun wqe->status = IB_WC_SUCCESS;
625*4882a593Smuzhiyun } else {
626*4882a593Smuzhiyun goto exit;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun if ((wqe->wr.send_flags & IB_SEND_SIGNALED) ||
629*4882a593Smuzhiyun qp->sq_sig_type == IB_SIGNAL_ALL_WR)
630*4882a593Smuzhiyun rxe_run_task(&qp->comp.task, 1);
631*4882a593Smuzhiyun qp->req.wqe_index = next_index(qp->sq.queue,
632*4882a593Smuzhiyun qp->req.wqe_index);
633*4882a593Smuzhiyun goto next_wqe;
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun if (unlikely(qp_type(qp) == IB_QPT_RC &&
637*4882a593Smuzhiyun psn_compare(qp->req.psn, (qp->comp.psn +
638*4882a593Smuzhiyun RXE_MAX_UNACKED_PSNS)) > 0)) {
639*4882a593Smuzhiyun qp->req.wait_psn = 1;
640*4882a593Smuzhiyun goto exit;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun /* Limit the number of inflight SKBs per QP */
644*4882a593Smuzhiyun if (unlikely(atomic_read(&qp->skb_out) >
645*4882a593Smuzhiyun RXE_INFLIGHT_SKBS_PER_QP_HIGH)) {
646*4882a593Smuzhiyun qp->need_req_skb = 1;
647*4882a593Smuzhiyun goto exit;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun opcode = next_opcode(qp, wqe, wqe->wr.opcode);
651*4882a593Smuzhiyun if (unlikely(opcode < 0)) {
652*4882a593Smuzhiyun wqe->status = IB_WC_LOC_QP_OP_ERR;
653*4882a593Smuzhiyun goto err;
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun mask = rxe_opcode[opcode].mask;
657*4882a593Smuzhiyun if (unlikely(mask & RXE_READ_OR_ATOMIC)) {
658*4882a593Smuzhiyun if (check_init_depth(qp, wqe))
659*4882a593Smuzhiyun goto exit;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun mtu = get_mtu(qp);
663*4882a593Smuzhiyun payload = (mask & RXE_WRITE_OR_SEND) ? wqe->dma.resid : 0;
664*4882a593Smuzhiyun if (payload > mtu) {
665*4882a593Smuzhiyun if (qp_type(qp) == IB_QPT_UD) {
666*4882a593Smuzhiyun /* C10-93.1.1: If the total sum of all the buffer lengths specified for a
667*4882a593Smuzhiyun * UD message exceeds the MTU of the port as returned by QueryHCA, the CI
668*4882a593Smuzhiyun * shall not emit any packets for this message. Further, the CI shall not
669*4882a593Smuzhiyun * generate an error due to this condition.
670*4882a593Smuzhiyun */
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun /* fake a successful UD send */
673*4882a593Smuzhiyun wqe->first_psn = qp->req.psn;
674*4882a593Smuzhiyun wqe->last_psn = qp->req.psn;
675*4882a593Smuzhiyun qp->req.psn = (qp->req.psn + 1) & BTH_PSN_MASK;
676*4882a593Smuzhiyun qp->req.opcode = IB_OPCODE_UD_SEND_ONLY;
677*4882a593Smuzhiyun qp->req.wqe_index = next_index(qp->sq.queue,
678*4882a593Smuzhiyun qp->req.wqe_index);
679*4882a593Smuzhiyun wqe->state = wqe_state_done;
680*4882a593Smuzhiyun wqe->status = IB_WC_SUCCESS;
681*4882a593Smuzhiyun __rxe_do_task(&qp->comp.task);
682*4882a593Smuzhiyun rxe_drop_ref(qp);
683*4882a593Smuzhiyun return 0;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun payload = mtu;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun skb = init_req_packet(qp, wqe, opcode, payload, &pkt);
689*4882a593Smuzhiyun if (unlikely(!skb)) {
690*4882a593Smuzhiyun pr_err("qp#%d Failed allocating skb\n", qp_num(qp));
691*4882a593Smuzhiyun goto err;
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun if (fill_packet(qp, wqe, &pkt, skb, payload)) {
695*4882a593Smuzhiyun pr_debug("qp#%d Error during fill packet\n", qp_num(qp));
696*4882a593Smuzhiyun kfree_skb(skb);
697*4882a593Smuzhiyun goto err;
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun /*
701*4882a593Smuzhiyun * To prevent a race on wqe access between requester and completer,
702*4882a593Smuzhiyun * wqe members state and psn need to be set before calling
703*4882a593Smuzhiyun * rxe_xmit_packet().
704*4882a593Smuzhiyun * Otherwise, completer might initiate an unjustified retry flow.
705*4882a593Smuzhiyun */
706*4882a593Smuzhiyun save_state(wqe, qp, &rollback_wqe, &rollback_psn);
707*4882a593Smuzhiyun update_wqe_state(qp, wqe, &pkt);
708*4882a593Smuzhiyun update_wqe_psn(qp, wqe, &pkt, payload);
709*4882a593Smuzhiyun ret = rxe_xmit_packet(qp, &pkt, skb);
710*4882a593Smuzhiyun if (ret) {
711*4882a593Smuzhiyun qp->need_req_skb = 1;
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun rollback_state(wqe, qp, &rollback_wqe, rollback_psn);
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun if (ret == -EAGAIN) {
716*4882a593Smuzhiyun rxe_run_task(&qp->req.task, 1);
717*4882a593Smuzhiyun goto exit;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun goto err;
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun update_state(qp, wqe, &pkt, payload);
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun goto next_wqe;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun err:
728*4882a593Smuzhiyun wqe->status = IB_WC_LOC_PROT_ERR;
729*4882a593Smuzhiyun wqe->state = wqe_state_error;
730*4882a593Smuzhiyun __rxe_do_task(&qp->comp.task);
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun exit:
733*4882a593Smuzhiyun rxe_drop_ref(qp);
734*4882a593Smuzhiyun return -EAGAIN;
735*4882a593Smuzhiyun }
736