1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35#include "i40iw_osdep.h"
36#include "i40iw_register.h"
37#include "i40iw_status.h"
38#include "i40iw_hmc.h"
39
40#include "i40iw_d.h"
41#include "i40iw_type.h"
42#include "i40iw_p.h"
43#include "i40iw_puda.h"
44
45static void i40iw_ieq_receive(struct i40iw_sc_vsi *vsi,
46 struct i40iw_puda_buf *buf);
47static void i40iw_ieq_tx_compl(struct i40iw_sc_vsi *vsi, void *sqwrid);
48static void i40iw_ilq_putback_rcvbuf(struct i40iw_sc_qp *qp, u32 wqe_idx);
49static enum i40iw_status_code i40iw_puda_replenish_rq(struct i40iw_puda_rsrc
50 *rsrc, bool initial);
51static void i40iw_ieq_cleanup_qp(struct i40iw_puda_rsrc *ieq, struct i40iw_sc_qp *qp);
52
53
54
55
56static struct i40iw_puda_buf *i40iw_puda_get_listbuf(struct list_head *list)
57{
58 struct i40iw_puda_buf *buf = NULL;
59
60 if (!list_empty(list)) {
61 buf = (struct i40iw_puda_buf *)list->next;
62 list_del((struct list_head *)&buf->list);
63 }
64 return buf;
65}
66
67
68
69
70
71struct i40iw_puda_buf *i40iw_puda_get_bufpool(struct i40iw_puda_rsrc *rsrc)
72{
73 struct i40iw_puda_buf *buf = NULL;
74 struct list_head *list = &rsrc->bufpool;
75 unsigned long flags;
76
77 spin_lock_irqsave(&rsrc->bufpool_lock, flags);
78 buf = i40iw_puda_get_listbuf(list);
79 if (buf)
80 rsrc->avail_buf_count--;
81 else
82 rsrc->stats_buf_alloc_fail++;
83 spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
84 return buf;
85}
86
87
88
89
90
91
92void i40iw_puda_ret_bufpool(struct i40iw_puda_rsrc *rsrc,
93 struct i40iw_puda_buf *buf)
94{
95 unsigned long flags;
96
97 spin_lock_irqsave(&rsrc->bufpool_lock, flags);
98 list_add(&buf->list, &rsrc->bufpool);
99 spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
100 rsrc->avail_buf_count++;
101}
102
103
104
105
106
107
108
109
110static void i40iw_puda_post_recvbuf(struct i40iw_puda_rsrc *rsrc, u32 wqe_idx,
111 struct i40iw_puda_buf *buf, bool initial)
112{
113 u64 *wqe;
114 struct i40iw_sc_qp *qp = &rsrc->qp;
115 u64 offset24 = 0;
116
117 qp->qp_uk.rq_wrid_array[wqe_idx] = (uintptr_t)buf;
118 wqe = qp->qp_uk.rq_base[wqe_idx].elem;
119 i40iw_debug(rsrc->dev, I40IW_DEBUG_PUDA,
120 "%s: wqe_idx= %d buf = %p wqe = %p\n", __func__,
121 wqe_idx, buf, wqe);
122 if (!initial)
123 get_64bit_val(wqe, 24, &offset24);
124
125 offset24 = (offset24) ? 0 : LS_64(1, I40IWQPSQ_VALID);
126 set_64bit_val(wqe, 24, offset24);
127
128 set_64bit_val(wqe, 0, buf->mem.pa);
129 set_64bit_val(wqe, 8,
130 LS_64(buf->mem.size, I40IWQPSQ_FRAG_LEN));
131 set_64bit_val(wqe, 24, offset24);
132}
133
134
135
136
137
138
139static enum i40iw_status_code i40iw_puda_replenish_rq(struct i40iw_puda_rsrc *rsrc,
140 bool initial)
141{
142 u32 i;
143 u32 invalid_cnt = rsrc->rxq_invalid_cnt;
144 struct i40iw_puda_buf *buf = NULL;
145
146 for (i = 0; i < invalid_cnt; i++) {
147 buf = i40iw_puda_get_bufpool(rsrc);
148 if (!buf)
149 return I40IW_ERR_list_empty;
150 i40iw_puda_post_recvbuf(rsrc, rsrc->rx_wqe_idx, buf,
151 initial);
152 rsrc->rx_wqe_idx =
153 ((rsrc->rx_wqe_idx + 1) % rsrc->rq_size);
154 rsrc->rxq_invalid_cnt--;
155 }
156 return 0;
157}
158
159
160
161
162
163
164static struct i40iw_puda_buf *i40iw_puda_alloc_buf(struct i40iw_sc_dev *dev,
165 u32 length)
166{
167 struct i40iw_puda_buf *buf = NULL;
168 struct i40iw_virt_mem buf_mem;
169 enum i40iw_status_code ret;
170
171 ret = i40iw_allocate_virt_mem(dev->hw, &buf_mem,
172 sizeof(struct i40iw_puda_buf));
173 if (ret) {
174 i40iw_debug(dev, I40IW_DEBUG_PUDA,
175 "%s: error mem for buf\n", __func__);
176 return NULL;
177 }
178 buf = (struct i40iw_puda_buf *)buf_mem.va;
179 ret = i40iw_allocate_dma_mem(dev->hw, &buf->mem, length, 1);
180 if (ret) {
181 i40iw_debug(dev, I40IW_DEBUG_PUDA,
182 "%s: error dma mem for buf\n", __func__);
183 i40iw_free_virt_mem(dev->hw, &buf_mem);
184 return NULL;
185 }
186 buf->buf_mem.va = buf_mem.va;
187 buf->buf_mem.size = buf_mem.size;
188 return buf;
189}
190
191
192
193
194
195
196static void i40iw_puda_dele_buf(struct i40iw_sc_dev *dev,
197 struct i40iw_puda_buf *buf)
198{
199 i40iw_free_dma_mem(dev->hw, &buf->mem);
200 i40iw_free_virt_mem(dev->hw, &buf->buf_mem);
201}
202
203
204
205
206
207
208static u64 *i40iw_puda_get_next_send_wqe(struct i40iw_qp_uk *qp, u32 *wqe_idx)
209{
210 u64 *wqe = NULL;
211 enum i40iw_status_code ret_code = 0;
212
213 *wqe_idx = I40IW_RING_GETCURRENT_HEAD(qp->sq_ring);
214 if (!*wqe_idx)
215 qp->swqe_polarity = !qp->swqe_polarity;
216 I40IW_RING_MOVE_HEAD(qp->sq_ring, ret_code);
217 if (ret_code)
218 return wqe;
219 wqe = qp->sq_base[*wqe_idx].elem;
220
221 return wqe;
222}
223
224
225
226
227
228
229static enum i40iw_status_code i40iw_puda_poll_info(struct i40iw_sc_cq *cq,
230 struct i40iw_puda_completion_info *info)
231{
232 u64 qword0, qword2, qword3;
233 u64 *cqe;
234 u64 comp_ctx;
235 bool valid_bit;
236 u32 major_err, minor_err;
237 bool error;
238
239 cqe = (u64 *)I40IW_GET_CURRENT_CQ_ELEMENT(&cq->cq_uk);
240 get_64bit_val(cqe, 24, &qword3);
241 valid_bit = (bool)RS_64(qword3, I40IW_CQ_VALID);
242
243 if (valid_bit != cq->cq_uk.polarity)
244 return I40IW_ERR_QUEUE_EMPTY;
245
246 i40iw_debug_buf(cq->dev, I40IW_DEBUG_PUDA, "PUDA CQE", cqe, 32);
247 error = (bool)RS_64(qword3, I40IW_CQ_ERROR);
248 if (error) {
249 i40iw_debug(cq->dev, I40IW_DEBUG_PUDA, "%s receive error\n", __func__);
250 major_err = (u32)(RS_64(qword3, I40IW_CQ_MAJERR));
251 minor_err = (u32)(RS_64(qword3, I40IW_CQ_MINERR));
252 info->compl_error = major_err << 16 | minor_err;
253 return I40IW_ERR_CQ_COMPL_ERROR;
254 }
255
256 get_64bit_val(cqe, 0, &qword0);
257 get_64bit_val(cqe, 16, &qword2);
258
259 info->q_type = (u8)RS_64(qword3, I40IW_CQ_SQ);
260 info->qp_id = (u32)RS_64(qword2, I40IWCQ_QPID);
261
262 get_64bit_val(cqe, 8, &comp_ctx);
263 info->qp = (struct i40iw_qp_uk *)(unsigned long)comp_ctx;
264 info->wqe_idx = (u32)RS_64(qword3, I40IW_CQ_WQEIDX);
265
266 if (info->q_type == I40IW_CQE_QTYPE_RQ) {
267 info->vlan_valid = (bool)RS_64(qword3, I40IW_VLAN_TAG_VALID);
268 info->l4proto = (u8)RS_64(qword2, I40IW_UDA_L4PROTO);
269 info->l3proto = (u8)RS_64(qword2, I40IW_UDA_L3PROTO);
270 info->payload_len = (u16)RS_64(qword0, I40IW_UDA_PAYLOADLEN);
271 }
272
273 return 0;
274}
275
276
277
278
279
280
281
282enum i40iw_status_code i40iw_puda_poll_completion(struct i40iw_sc_dev *dev,
283 struct i40iw_sc_cq *cq, u32 *compl_err)
284{
285 struct i40iw_qp_uk *qp;
286 struct i40iw_cq_uk *cq_uk = &cq->cq_uk;
287 struct i40iw_puda_completion_info info;
288 enum i40iw_status_code ret = 0;
289 struct i40iw_puda_buf *buf;
290 struct i40iw_puda_rsrc *rsrc;
291 void *sqwrid;
292 u8 cq_type = cq->cq_type;
293 unsigned long flags;
294
295 if ((cq_type == I40IW_CQ_TYPE_ILQ) || (cq_type == I40IW_CQ_TYPE_IEQ)) {
296 rsrc = (cq_type == I40IW_CQ_TYPE_ILQ) ? cq->vsi->ilq : cq->vsi->ieq;
297 } else {
298 i40iw_debug(dev, I40IW_DEBUG_PUDA, "%s qp_type error\n", __func__);
299 return I40IW_ERR_BAD_PTR;
300 }
301 memset(&info, 0, sizeof(info));
302 ret = i40iw_puda_poll_info(cq, &info);
303 *compl_err = info.compl_error;
304 if (ret == I40IW_ERR_QUEUE_EMPTY)
305 return ret;
306 if (ret)
307 goto done;
308
309 qp = info.qp;
310 if (!qp || !rsrc) {
311 ret = I40IW_ERR_BAD_PTR;
312 goto done;
313 }
314
315 if (qp->qp_id != rsrc->qp_id) {
316 ret = I40IW_ERR_BAD_PTR;
317 goto done;
318 }
319
320 if (info.q_type == I40IW_CQE_QTYPE_RQ) {
321 buf = (struct i40iw_puda_buf *)(uintptr_t)qp->rq_wrid_array[info.wqe_idx];
322
323 ret = i40iw_puda_get_tcpip_info(&info, buf);
324 if (ret) {
325 rsrc->stats_rcvd_pkt_err++;
326 if (cq_type == I40IW_CQ_TYPE_ILQ) {
327 i40iw_ilq_putback_rcvbuf(&rsrc->qp,
328 info.wqe_idx);
329 } else {
330 i40iw_puda_ret_bufpool(rsrc, buf);
331 i40iw_puda_replenish_rq(rsrc, false);
332 }
333 goto done;
334 }
335
336 rsrc->stats_pkt_rcvd++;
337 rsrc->compl_rxwqe_idx = info.wqe_idx;
338 i40iw_debug(dev, I40IW_DEBUG_PUDA, "%s RQ completion\n", __func__);
339 rsrc->receive(rsrc->vsi, buf);
340 if (cq_type == I40IW_CQ_TYPE_ILQ)
341 i40iw_ilq_putback_rcvbuf(&rsrc->qp, info.wqe_idx);
342 else
343 i40iw_puda_replenish_rq(rsrc, false);
344
345 } else {
346 i40iw_debug(dev, I40IW_DEBUG_PUDA, "%s SQ completion\n", __func__);
347 sqwrid = (void *)(uintptr_t)qp->sq_wrtrk_array[info.wqe_idx].wrid;
348 I40IW_RING_SET_TAIL(qp->sq_ring, info.wqe_idx);
349 rsrc->xmit_complete(rsrc->vsi, sqwrid);
350 spin_lock_irqsave(&rsrc->bufpool_lock, flags);
351 rsrc->tx_wqe_avail_cnt++;
352 spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
353 if (!list_empty(&rsrc->vsi->ilq->txpend))
354 i40iw_puda_send_buf(rsrc->vsi->ilq, NULL);
355 }
356
357done:
358 I40IW_RING_MOVE_HEAD(cq_uk->cq_ring, ret);
359 if (I40IW_RING_GETCURRENT_HEAD(cq_uk->cq_ring) == 0)
360 cq_uk->polarity = !cq_uk->polarity;
361
362 I40IW_RING_MOVE_TAIL(cq_uk->cq_ring);
363 set_64bit_val(cq_uk->shadow_area, 0,
364 I40IW_RING_GETCURRENT_HEAD(cq_uk->cq_ring));
365 return 0;
366}
367
368
369
370
371
372
373enum i40iw_status_code i40iw_puda_send(struct i40iw_sc_qp *qp,
374 struct i40iw_puda_send_info *info)
375{
376 u64 *wqe;
377 u32 iplen, l4len;
378 u64 header[2];
379 u32 wqe_idx;
380 u8 iipt;
381
382
383 l4len = info->tcplen >> 2;
384 if (info->ipv4) {
385 iipt = 3;
386 iplen = 5;
387 } else {
388 iipt = 1;
389 iplen = 10;
390 }
391
392 wqe = i40iw_puda_get_next_send_wqe(&qp->qp_uk, &wqe_idx);
393 if (!wqe)
394 return I40IW_ERR_QP_TOOMANY_WRS_POSTED;
395 qp->qp_uk.sq_wrtrk_array[wqe_idx].wrid = (uintptr_t)info->scratch;
396
397
398 header[0] = LS_64((info->maclen >> 1), I40IW_UDA_QPSQ_MACLEN) |
399 LS_64(iplen, I40IW_UDA_QPSQ_IPLEN) | LS_64(1, I40IW_UDA_QPSQ_L4T) |
400 LS_64(iipt, I40IW_UDA_QPSQ_IIPT) |
401 LS_64(l4len, I40IW_UDA_QPSQ_L4LEN);
402
403 header[1] = LS_64(I40IW_OP_TYPE_SEND, I40IW_UDA_QPSQ_OPCODE) |
404 LS_64(1, I40IW_UDA_QPSQ_SIGCOMPL) |
405 LS_64(info->doloopback, I40IW_UDA_QPSQ_DOLOOPBACK) |
406 LS_64(qp->qp_uk.swqe_polarity, I40IW_UDA_QPSQ_VALID);
407
408 set_64bit_val(wqe, 0, info->paddr);
409 set_64bit_val(wqe, 8, LS_64(info->len, I40IWQPSQ_FRAG_LEN));
410 set_64bit_val(wqe, 16, header[0]);
411 set_64bit_val(wqe, 24, header[1]);
412
413 i40iw_debug_buf(qp->dev, I40IW_DEBUG_PUDA, "PUDA SEND WQE", wqe, 32);
414 i40iw_qp_post_wr(&qp->qp_uk);
415 return 0;
416}
417
418
419
420
421
422
423void i40iw_puda_send_buf(struct i40iw_puda_rsrc *rsrc, struct i40iw_puda_buf *buf)
424{
425 struct i40iw_puda_send_info info;
426 enum i40iw_status_code ret = 0;
427 unsigned long flags;
428
429 spin_lock_irqsave(&rsrc->bufpool_lock, flags);
430
431
432
433 if (!rsrc->tx_wqe_avail_cnt || (buf && !list_empty(&rsrc->txpend))) {
434 list_add_tail(&buf->list, &rsrc->txpend);
435 spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
436 rsrc->stats_sent_pkt_q++;
437 if (rsrc->type == I40IW_PUDA_RSRC_TYPE_ILQ)
438 i40iw_debug(rsrc->dev, I40IW_DEBUG_PUDA,
439 "%s: adding to txpend\n", __func__);
440 return;
441 }
442 rsrc->tx_wqe_avail_cnt--;
443
444
445
446 if (!buf) {
447 buf = i40iw_puda_get_listbuf(&rsrc->txpend);
448 if (!buf)
449 goto done;
450 }
451
452 info.scratch = (void *)buf;
453 info.paddr = buf->mem.pa;
454 info.len = buf->totallen;
455 info.tcplen = buf->tcphlen;
456 info.maclen = buf->maclen;
457 info.ipv4 = buf->ipv4;
458 info.doloopback = (rsrc->type == I40IW_PUDA_RSRC_TYPE_IEQ);
459
460 ret = i40iw_puda_send(&rsrc->qp, &info);
461 if (ret) {
462 rsrc->tx_wqe_avail_cnt++;
463 rsrc->stats_sent_pkt_q++;
464 list_add(&buf->list, &rsrc->txpend);
465 if (rsrc->type == I40IW_PUDA_RSRC_TYPE_ILQ)
466 i40iw_debug(rsrc->dev, I40IW_DEBUG_PUDA,
467 "%s: adding to puda_send\n", __func__);
468 } else {
469 rsrc->stats_pkt_sent++;
470 }
471done:
472 spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
473}
474
475
476
477
478
479static void i40iw_puda_qp_setctx(struct i40iw_puda_rsrc *rsrc)
480{
481 struct i40iw_sc_qp *qp = &rsrc->qp;
482 u64 *qp_ctx = qp->hw_host_ctx;
483
484 set_64bit_val(qp_ctx, 8, qp->sq_pa);
485 set_64bit_val(qp_ctx, 16, qp->rq_pa);
486
487 set_64bit_val(qp_ctx, 24,
488 LS_64(qp->hw_rq_size, I40IWQPC_RQSIZE) |
489 LS_64(qp->hw_sq_size, I40IWQPC_SQSIZE));
490
491 set_64bit_val(qp_ctx, 48, LS_64(1514, I40IWQPC_SNDMSS));
492 set_64bit_val(qp_ctx, 56, 0);
493 set_64bit_val(qp_ctx, 64, 1);
494
495 set_64bit_val(qp_ctx, 136,
496 LS_64(rsrc->cq_id, I40IWQPC_TXCQNUM) |
497 LS_64(rsrc->cq_id, I40IWQPC_RXCQNUM));
498
499 set_64bit_val(qp_ctx, 160, LS_64(1, I40IWQPC_PRIVEN));
500
501 set_64bit_val(qp_ctx, 168,
502 LS_64((uintptr_t)qp, I40IWQPC_QPCOMPCTX));
503
504 set_64bit_val(qp_ctx, 176,
505 LS_64(qp->sq_tph_val, I40IWQPC_SQTPHVAL) |
506 LS_64(qp->rq_tph_val, I40IWQPC_RQTPHVAL) |
507 LS_64(qp->qs_handle, I40IWQPC_QSHANDLE));
508
509 i40iw_debug_buf(rsrc->dev, I40IW_DEBUG_PUDA, "PUDA QP CONTEXT",
510 qp_ctx, I40IW_QP_CTX_SIZE);
511}
512
513
514
515
516
517static enum i40iw_status_code i40iw_puda_qp_wqe(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp)
518{
519 struct i40iw_sc_cqp *cqp;
520 u64 *wqe;
521 u64 header;
522 struct i40iw_ccq_cqe_info compl_info;
523 enum i40iw_status_code status = 0;
524
525 cqp = dev->cqp;
526 wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, 0);
527 if (!wqe)
528 return I40IW_ERR_RING_FULL;
529
530 set_64bit_val(wqe, 16, qp->hw_host_ctx_pa);
531 set_64bit_val(wqe, 40, qp->shadow_area_pa);
532 header = qp->qp_uk.qp_id |
533 LS_64(I40IW_CQP_OP_CREATE_QP, I40IW_CQPSQ_OPCODE) |
534 LS_64(I40IW_QP_TYPE_UDA, I40IW_CQPSQ_QP_QPTYPE) |
535 LS_64(1, I40IW_CQPSQ_QP_CQNUMVALID) |
536 LS_64(2, I40IW_CQPSQ_QP_NEXTIWSTATE) |
537 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
538
539 set_64bit_val(wqe, 24, header);
540
541 i40iw_debug_buf(cqp->dev, I40IW_DEBUG_PUDA, "PUDA CQE", wqe, 32);
542 i40iw_sc_cqp_post_sq(cqp);
543 status = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
544 I40IW_CQP_OP_CREATE_QP,
545 &compl_info);
546 return status;
547}
548
549
550
551
552
553static enum i40iw_status_code i40iw_puda_qp_create(struct i40iw_puda_rsrc *rsrc)
554{
555 struct i40iw_sc_qp *qp = &rsrc->qp;
556 struct i40iw_qp_uk *ukqp = &qp->qp_uk;
557 enum i40iw_status_code ret = 0;
558 u32 sq_size, rq_size, t_size;
559 struct i40iw_dma_mem *mem;
560
561 sq_size = rsrc->sq_size * I40IW_QP_WQE_MIN_SIZE;
562 rq_size = rsrc->rq_size * I40IW_QP_WQE_MIN_SIZE;
563 t_size = (sq_size + rq_size + (I40IW_SHADOW_AREA_SIZE << 3) +
564 I40IW_QP_CTX_SIZE);
565
566 ret =
567 i40iw_allocate_dma_mem(rsrc->dev->hw, &rsrc->qpmem, t_size,
568 I40IW_HW_PAGE_SIZE);
569 if (ret) {
570 i40iw_debug(rsrc->dev, I40IW_DEBUG_PUDA, "%s: error dma mem\n", __func__);
571 return ret;
572 }
573
574 mem = &rsrc->qpmem;
575 memset(mem->va, 0, t_size);
576 qp->hw_sq_size = i40iw_get_encoded_wqe_size(rsrc->sq_size, false);
577 qp->hw_rq_size = i40iw_get_encoded_wqe_size(rsrc->rq_size, false);
578 qp->pd = &rsrc->sc_pd;
579 qp->qp_type = I40IW_QP_TYPE_UDA;
580 qp->dev = rsrc->dev;
581 qp->back_qp = (void *)rsrc;
582 qp->sq_pa = mem->pa;
583 qp->rq_pa = qp->sq_pa + sq_size;
584 qp->vsi = rsrc->vsi;
585 ukqp->sq_base = mem->va;
586 ukqp->rq_base = &ukqp->sq_base[rsrc->sq_size];
587 ukqp->shadow_area = ukqp->rq_base[rsrc->rq_size].elem;
588 qp->shadow_area_pa = qp->rq_pa + rq_size;
589 qp->hw_host_ctx = ukqp->shadow_area + I40IW_SHADOW_AREA_SIZE;
590 qp->hw_host_ctx_pa =
591 qp->shadow_area_pa + (I40IW_SHADOW_AREA_SIZE << 3);
592 ukqp->qp_id = rsrc->qp_id;
593 ukqp->sq_wrtrk_array = rsrc->sq_wrtrk_array;
594 ukqp->rq_wrid_array = rsrc->rq_wrid_array;
595
596 ukqp->qp_id = rsrc->qp_id;
597 ukqp->sq_size = rsrc->sq_size;
598 ukqp->rq_size = rsrc->rq_size;
599
600 I40IW_RING_INIT(ukqp->sq_ring, ukqp->sq_size);
601 I40IW_RING_INIT(ukqp->initial_ring, ukqp->sq_size);
602 I40IW_RING_INIT(ukqp->rq_ring, ukqp->rq_size);
603
604 if (qp->pd->dev->is_pf)
605 ukqp->wqe_alloc_reg = (u32 __iomem *)(i40iw_get_hw_addr(qp->pd->dev) +
606 I40E_PFPE_WQEALLOC);
607 else
608 ukqp->wqe_alloc_reg = (u32 __iomem *)(i40iw_get_hw_addr(qp->pd->dev) +
609 I40E_VFPE_WQEALLOC1);
610
611 qp->user_pri = 0;
612 i40iw_qp_add_qos(qp);
613 i40iw_puda_qp_setctx(rsrc);
614 if (rsrc->ceq_valid)
615 ret = i40iw_cqp_qp_create_cmd(rsrc->dev, qp);
616 else
617 ret = i40iw_puda_qp_wqe(rsrc->dev, qp);
618 if (ret)
619 i40iw_free_dma_mem(rsrc->dev->hw, &rsrc->qpmem);
620 return ret;
621}
622
623
624
625
626
627static enum i40iw_status_code i40iw_puda_cq_wqe(struct i40iw_sc_dev *dev, struct i40iw_sc_cq *cq)
628{
629 u64 *wqe;
630 struct i40iw_sc_cqp *cqp;
631 u64 header;
632 struct i40iw_ccq_cqe_info compl_info;
633 enum i40iw_status_code status = 0;
634
635 cqp = dev->cqp;
636 wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, 0);
637 if (!wqe)
638 return I40IW_ERR_RING_FULL;
639
640 set_64bit_val(wqe, 0, cq->cq_uk.cq_size);
641 set_64bit_val(wqe, 8, RS_64_1(cq, 1));
642 set_64bit_val(wqe, 16,
643 LS_64(cq->shadow_read_threshold,
644 I40IW_CQPSQ_CQ_SHADOW_READ_THRESHOLD));
645 set_64bit_val(wqe, 32, cq->cq_pa);
646
647 set_64bit_val(wqe, 40, cq->shadow_area_pa);
648
649 header = cq->cq_uk.cq_id |
650 LS_64(I40IW_CQP_OP_CREATE_CQ, I40IW_CQPSQ_OPCODE) |
651 LS_64(1, I40IW_CQPSQ_CQ_CHKOVERFLOW) |
652 LS_64(1, I40IW_CQPSQ_CQ_ENCEQEMASK) |
653 LS_64(1, I40IW_CQPSQ_CQ_CEQIDVALID) |
654 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
655 set_64bit_val(wqe, 24, header);
656
657 i40iw_debug_buf(dev, I40IW_DEBUG_PUDA, "PUDA CQE",
658 wqe, I40IW_CQP_WQE_SIZE * 8);
659
660 i40iw_sc_cqp_post_sq(dev->cqp);
661 status = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
662 I40IW_CQP_OP_CREATE_CQ,
663 &compl_info);
664 return status;
665}
666
667
668
669
670
671static enum i40iw_status_code i40iw_puda_cq_create(struct i40iw_puda_rsrc *rsrc)
672{
673 struct i40iw_sc_dev *dev = rsrc->dev;
674 struct i40iw_sc_cq *cq = &rsrc->cq;
675 enum i40iw_status_code ret = 0;
676 u32 tsize, cqsize;
677 struct i40iw_dma_mem *mem;
678 struct i40iw_cq_init_info info;
679 struct i40iw_cq_uk_init_info *init_info = &info.cq_uk_init_info;
680
681 cq->vsi = rsrc->vsi;
682 cqsize = rsrc->cq_size * (sizeof(struct i40iw_cqe));
683 tsize = cqsize + sizeof(struct i40iw_cq_shadow_area);
684 ret = i40iw_allocate_dma_mem(dev->hw, &rsrc->cqmem, tsize,
685 I40IW_CQ0_ALIGNMENT_MASK);
686 if (ret)
687 return ret;
688
689 mem = &rsrc->cqmem;
690 memset(&info, 0, sizeof(info));
691 info.dev = dev;
692 info.type = (rsrc->type == I40IW_PUDA_RSRC_TYPE_ILQ) ?
693 I40IW_CQ_TYPE_ILQ : I40IW_CQ_TYPE_IEQ;
694 info.shadow_read_threshold = rsrc->cq_size >> 2;
695 info.ceq_id_valid = true;
696 info.cq_base_pa = mem->pa;
697 info.shadow_area_pa = mem->pa + cqsize;
698 init_info->cq_base = mem->va;
699 init_info->shadow_area = (u64 *)((u8 *)mem->va + cqsize);
700 init_info->cq_size = rsrc->cq_size;
701 init_info->cq_id = rsrc->cq_id;
702 info.ceqe_mask = true;
703 info.ceq_id_valid = true;
704 ret = dev->iw_priv_cq_ops->cq_init(cq, &info);
705 if (ret)
706 goto error;
707 if (rsrc->ceq_valid)
708 ret = i40iw_cqp_cq_create_cmd(dev, cq);
709 else
710 ret = i40iw_puda_cq_wqe(dev, cq);
711error:
712 if (ret)
713 i40iw_free_dma_mem(dev->hw, &rsrc->cqmem);
714 return ret;
715}
716
717
718
719
720
721static void i40iw_puda_free_qp(struct i40iw_puda_rsrc *rsrc)
722{
723 enum i40iw_status_code ret;
724 struct i40iw_ccq_cqe_info compl_info;
725 struct i40iw_sc_dev *dev = rsrc->dev;
726
727 if (rsrc->ceq_valid) {
728 i40iw_cqp_qp_destroy_cmd(dev, &rsrc->qp);
729 return;
730 }
731
732 ret = dev->iw_priv_qp_ops->qp_destroy(&rsrc->qp,
733 0, false, true, true);
734 if (ret)
735 i40iw_debug(dev, I40IW_DEBUG_PUDA,
736 "%s error puda qp destroy wqe\n",
737 __func__);
738
739 if (!ret) {
740 ret = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
741 I40IW_CQP_OP_DESTROY_QP,
742 &compl_info);
743 if (ret)
744 i40iw_debug(dev, I40IW_DEBUG_PUDA,
745 "%s error puda qp destroy failed\n",
746 __func__);
747 }
748}
749
750
751
752
753
754static void i40iw_puda_free_cq(struct i40iw_puda_rsrc *rsrc)
755{
756 enum i40iw_status_code ret;
757 struct i40iw_ccq_cqe_info compl_info;
758 struct i40iw_sc_dev *dev = rsrc->dev;
759
760 if (rsrc->ceq_valid) {
761 i40iw_cqp_cq_destroy_cmd(dev, &rsrc->cq);
762 return;
763 }
764 ret = dev->iw_priv_cq_ops->cq_destroy(&rsrc->cq, 0, true);
765
766 if (ret)
767 i40iw_debug(dev, I40IW_DEBUG_PUDA,
768 "%s error ieq cq destroy\n",
769 __func__);
770
771 if (!ret) {
772 ret = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
773 I40IW_CQP_OP_DESTROY_CQ,
774 &compl_info);
775 if (ret)
776 i40iw_debug(dev, I40IW_DEBUG_PUDA,
777 "%s error ieq qp destroy done\n",
778 __func__);
779 }
780}
781
782
783
784
785
786
787
788void i40iw_puda_dele_resources(struct i40iw_sc_vsi *vsi,
789 enum puda_resource_type type,
790 bool reset)
791{
792 struct i40iw_sc_dev *dev = vsi->dev;
793 struct i40iw_puda_rsrc *rsrc;
794 struct i40iw_puda_buf *buf = NULL;
795 struct i40iw_puda_buf *nextbuf = NULL;
796 struct i40iw_virt_mem *vmem;
797
798 switch (type) {
799 case I40IW_PUDA_RSRC_TYPE_ILQ:
800 rsrc = vsi->ilq;
801 vmem = &vsi->ilq_mem;
802 break;
803 case I40IW_PUDA_RSRC_TYPE_IEQ:
804 rsrc = vsi->ieq;
805 vmem = &vsi->ieq_mem;
806 break;
807 default:
808 i40iw_debug(dev, I40IW_DEBUG_PUDA, "%s: error resource type = 0x%x\n",
809 __func__, type);
810 return;
811 }
812
813 switch (rsrc->completion) {
814 case PUDA_HASH_CRC_COMPLETE:
815 i40iw_free_hash_desc(rsrc->hash_desc);
816 case PUDA_QP_CREATED:
817 if (!reset)
818 i40iw_puda_free_qp(rsrc);
819
820 i40iw_free_dma_mem(dev->hw, &rsrc->qpmem);
821
822 case PUDA_CQ_CREATED:
823 if (!reset)
824 i40iw_puda_free_cq(rsrc);
825
826 i40iw_free_dma_mem(dev->hw, &rsrc->cqmem);
827 break;
828 default:
829 i40iw_debug(rsrc->dev, I40IW_DEBUG_PUDA, "%s error no resources\n", __func__);
830 break;
831 }
832
833 buf = rsrc->alloclist;
834 while (buf) {
835 nextbuf = buf->next;
836 i40iw_puda_dele_buf(dev, buf);
837 buf = nextbuf;
838 rsrc->alloc_buf_count--;
839 }
840 i40iw_free_virt_mem(dev->hw, vmem);
841}
842
843
844
845
846
847
848static enum i40iw_status_code i40iw_puda_allocbufs(struct i40iw_puda_rsrc *rsrc,
849 u32 count)
850{
851 u32 i;
852 struct i40iw_puda_buf *buf;
853 struct i40iw_puda_buf *nextbuf;
854
855 for (i = 0; i < count; i++) {
856 buf = i40iw_puda_alloc_buf(rsrc->dev, rsrc->buf_size);
857 if (!buf) {
858 rsrc->stats_buf_alloc_fail++;
859 return I40IW_ERR_NO_MEMORY;
860 }
861 i40iw_puda_ret_bufpool(rsrc, buf);
862 rsrc->alloc_buf_count++;
863 if (!rsrc->alloclist) {
864 rsrc->alloclist = buf;
865 } else {
866 nextbuf = rsrc->alloclist;
867 rsrc->alloclist = buf;
868 buf->next = nextbuf;
869 }
870 }
871 rsrc->avail_buf_count = rsrc->alloc_buf_count;
872 return 0;
873}
874
875
876
877
878
879
880enum i40iw_status_code i40iw_puda_create_rsrc(struct i40iw_sc_vsi *vsi,
881 struct i40iw_puda_rsrc_info *info)
882{
883 struct i40iw_sc_dev *dev = vsi->dev;
884 enum i40iw_status_code ret = 0;
885 struct i40iw_puda_rsrc *rsrc;
886 u32 pudasize;
887 u32 sqwridsize, rqwridsize;
888 struct i40iw_virt_mem *vmem;
889
890 info->count = 1;
891 pudasize = sizeof(struct i40iw_puda_rsrc);
892 sqwridsize = info->sq_size * sizeof(struct i40iw_sq_uk_wr_trk_info);
893 rqwridsize = info->rq_size * 8;
894 switch (info->type) {
895 case I40IW_PUDA_RSRC_TYPE_ILQ:
896 vmem = &vsi->ilq_mem;
897 break;
898 case I40IW_PUDA_RSRC_TYPE_IEQ:
899 vmem = &vsi->ieq_mem;
900 break;
901 default:
902 return I40IW_NOT_SUPPORTED;
903 }
904 ret =
905 i40iw_allocate_virt_mem(dev->hw, vmem,
906 pudasize + sqwridsize + rqwridsize);
907 if (ret)
908 return ret;
909 rsrc = (struct i40iw_puda_rsrc *)vmem->va;
910 spin_lock_init(&rsrc->bufpool_lock);
911 if (info->type == I40IW_PUDA_RSRC_TYPE_ILQ) {
912 vsi->ilq = (struct i40iw_puda_rsrc *)vmem->va;
913 vsi->ilq_count = info->count;
914 rsrc->receive = info->receive;
915 rsrc->xmit_complete = info->xmit_complete;
916 } else {
917 vmem = &vsi->ieq_mem;
918 vsi->ieq_count = info->count;
919 vsi->ieq = (struct i40iw_puda_rsrc *)vmem->va;
920 rsrc->receive = i40iw_ieq_receive;
921 rsrc->xmit_complete = i40iw_ieq_tx_compl;
922 }
923
924 rsrc->ceq_valid = info->ceq_valid;
925 rsrc->type = info->type;
926 rsrc->sq_wrtrk_array = (struct i40iw_sq_uk_wr_trk_info *)((u8 *)vmem->va + pudasize);
927 rsrc->rq_wrid_array = (u64 *)((u8 *)vmem->va + pudasize + sqwridsize);
928
929 INIT_LIST_HEAD(&rsrc->bufpool);
930 INIT_LIST_HEAD(&rsrc->txpend);
931
932 rsrc->tx_wqe_avail_cnt = info->sq_size - 1;
933 dev->iw_pd_ops->pd_init(dev, &rsrc->sc_pd, info->pd_id, -1);
934 rsrc->qp_id = info->qp_id;
935 rsrc->cq_id = info->cq_id;
936 rsrc->sq_size = info->sq_size;
937 rsrc->rq_size = info->rq_size;
938 rsrc->cq_size = info->rq_size + info->sq_size;
939 rsrc->buf_size = info->buf_size;
940 rsrc->dev = dev;
941 rsrc->vsi = vsi;
942
943 ret = i40iw_puda_cq_create(rsrc);
944 if (!ret) {
945 rsrc->completion = PUDA_CQ_CREATED;
946 ret = i40iw_puda_qp_create(rsrc);
947 }
948 if (ret) {
949 i40iw_debug(dev, I40IW_DEBUG_PUDA, "[%s] error qp_create\n", __func__);
950 goto error;
951 }
952 rsrc->completion = PUDA_QP_CREATED;
953
954 ret = i40iw_puda_allocbufs(rsrc, info->tx_buf_cnt + info->rq_size);
955 if (ret) {
956 i40iw_debug(dev, I40IW_DEBUG_PUDA, "[%s] error allloc_buf\n", __func__);
957 goto error;
958 }
959
960 rsrc->rxq_invalid_cnt = info->rq_size;
961 ret = i40iw_puda_replenish_rq(rsrc, true);
962 if (ret)
963 goto error;
964
965 if (info->type == I40IW_PUDA_RSRC_TYPE_IEQ) {
966 if (!i40iw_init_hash_desc(&rsrc->hash_desc)) {
967 rsrc->check_crc = true;
968 rsrc->completion = PUDA_HASH_CRC_COMPLETE;
969 ret = 0;
970 }
971 }
972
973 dev->ccq_ops->ccq_arm(&rsrc->cq);
974 return ret;
975 error:
976 i40iw_puda_dele_resources(vsi, info->type, false);
977
978 return ret;
979}
980
981
982
983
984
985
986static void i40iw_ilq_putback_rcvbuf(struct i40iw_sc_qp *qp, u32 wqe_idx)
987{
988 u64 *wqe;
989 u64 offset24;
990
991 wqe = qp->qp_uk.rq_base[wqe_idx].elem;
992 get_64bit_val(wqe, 24, &offset24);
993 offset24 = (offset24) ? 0 : LS_64(1, I40IWQPSQ_VALID);
994 set_64bit_val(wqe, 24, offset24);
995}
996
997
998
999
1000
1001static u16 i40iw_ieq_get_fpdu_length(u16 length)
1002{
1003 u16 fpdu_len;
1004
1005 fpdu_len = length + I40IW_IEQ_MPA_FRAMING;
1006 fpdu_len = (fpdu_len + 3) & 0xfffffffc;
1007 return fpdu_len;
1008}
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018static void i40iw_ieq_copy_to_txbuf(struct i40iw_puda_buf *buf,
1019 struct i40iw_puda_buf *txbuf,
1020 u16 buf_offset, u32 txbuf_offset,
1021 u32 length)
1022{
1023 void *mem1 = (u8 *)buf->mem.va + buf_offset;
1024 void *mem2 = (u8 *)txbuf->mem.va + txbuf_offset;
1025
1026 memcpy(mem2, mem1, length);
1027}
1028
1029
1030
1031
1032
1033
1034static void i40iw_ieq_setup_tx_buf(struct i40iw_puda_buf *buf,
1035 struct i40iw_puda_buf *txbuf)
1036{
1037 txbuf->maclen = buf->maclen;
1038 txbuf->tcphlen = buf->tcphlen;
1039 txbuf->ipv4 = buf->ipv4;
1040 txbuf->hdrlen = buf->hdrlen;
1041 i40iw_ieq_copy_to_txbuf(buf, txbuf, 0, 0, buf->hdrlen);
1042}
1043
1044
1045
1046
1047
1048
1049static void i40iw_ieq_check_first_buf(struct i40iw_puda_buf *buf, u32 fps)
1050{
1051 u32 offset;
1052
1053 if (buf->seqnum < fps) {
1054 offset = fps - buf->seqnum;
1055 if (offset > buf->datalen)
1056 return;
1057 buf->data += offset;
1058 buf->datalen -= (u16)offset;
1059 buf->seqnum = fps;
1060 }
1061}
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071static void i40iw_ieq_compl_pfpdu(struct i40iw_puda_rsrc *ieq,
1072 struct list_head *rxlist,
1073 struct list_head *pbufl,
1074 struct i40iw_puda_buf *txbuf,
1075 u16 fpdu_len)
1076{
1077 struct i40iw_puda_buf *buf;
1078 u32 nextseqnum;
1079 u16 txoffset, bufoffset;
1080
1081 buf = i40iw_puda_get_listbuf(pbufl);
1082 if (!buf)
1083 return;
1084 nextseqnum = buf->seqnum + fpdu_len;
1085 txbuf->totallen = buf->hdrlen + fpdu_len;
1086 txbuf->data = (u8 *)txbuf->mem.va + buf->hdrlen;
1087 i40iw_ieq_setup_tx_buf(buf, txbuf);
1088
1089 txoffset = buf->hdrlen;
1090 bufoffset = (u16)(buf->data - (u8 *)buf->mem.va);
1091
1092 do {
1093 if (buf->datalen >= fpdu_len) {
1094
1095 i40iw_ieq_copy_to_txbuf(buf, txbuf, bufoffset, txoffset, fpdu_len);
1096 buf->datalen -= fpdu_len;
1097 buf->data += fpdu_len;
1098 buf->seqnum = nextseqnum;
1099 break;
1100 }
1101
1102 i40iw_ieq_copy_to_txbuf(buf, txbuf, bufoffset, txoffset, buf->datalen);
1103 txoffset += buf->datalen;
1104 fpdu_len -= buf->datalen;
1105 i40iw_puda_ret_bufpool(ieq, buf);
1106 buf = i40iw_puda_get_listbuf(pbufl);
1107 if (!buf)
1108 return;
1109 bufoffset = (u16)(buf->data - (u8 *)buf->mem.va);
1110 } while (1);
1111
1112
1113 if (buf->datalen)
1114 list_add(&buf->list, rxlist);
1115 else
1116 i40iw_puda_ret_bufpool(ieq, buf);
1117}
1118
1119
1120
1121
1122
1123
1124
1125
1126static enum i40iw_status_code i40iw_ieq_create_pbufl(
1127 struct i40iw_pfpdu *pfpdu,
1128 struct list_head *rxlist,
1129 struct list_head *pbufl,
1130 struct i40iw_puda_buf *buf,
1131 u16 fpdu_len)
1132{
1133 enum i40iw_status_code status = 0;
1134 struct i40iw_puda_buf *nextbuf;
1135 u32 nextseqnum;
1136 u16 plen = fpdu_len - buf->datalen;
1137 bool done = false;
1138
1139 nextseqnum = buf->seqnum + buf->datalen;
1140 do {
1141 nextbuf = i40iw_puda_get_listbuf(rxlist);
1142 if (!nextbuf) {
1143 status = I40IW_ERR_list_empty;
1144 break;
1145 }
1146 list_add_tail(&nextbuf->list, pbufl);
1147 if (nextbuf->seqnum != nextseqnum) {
1148 pfpdu->bad_seq_num++;
1149 status = I40IW_ERR_SEQ_NUM;
1150 break;
1151 }
1152 if (nextbuf->datalen >= plen) {
1153 done = true;
1154 } else {
1155 plen -= nextbuf->datalen;
1156 nextseqnum = nextbuf->seqnum + nextbuf->datalen;
1157 }
1158
1159 } while (!done);
1160
1161 return status;
1162}
1163
1164
1165
1166
1167
1168
1169
1170
1171static enum i40iw_status_code i40iw_ieq_handle_partial(struct i40iw_puda_rsrc *ieq,
1172 struct i40iw_pfpdu *pfpdu,
1173 struct i40iw_puda_buf *buf,
1174 u16 fpdu_len)
1175{
1176 enum i40iw_status_code status = 0;
1177 u8 *crcptr;
1178 u32 mpacrc;
1179 u32 seqnum = buf->seqnum;
1180 struct list_head pbufl;
1181 struct i40iw_puda_buf *txbuf = NULL;
1182 struct list_head *rxlist = &pfpdu->rxlist;
1183
1184 INIT_LIST_HEAD(&pbufl);
1185 list_add(&buf->list, &pbufl);
1186
1187 status = i40iw_ieq_create_pbufl(pfpdu, rxlist, &pbufl, buf, fpdu_len);
1188 if (status)
1189 goto error;
1190
1191 txbuf = i40iw_puda_get_bufpool(ieq);
1192 if (!txbuf) {
1193 pfpdu->no_tx_bufs++;
1194 status = I40IW_ERR_NO_TXBUFS;
1195 goto error;
1196 }
1197
1198 i40iw_ieq_compl_pfpdu(ieq, rxlist, &pbufl, txbuf, fpdu_len);
1199 i40iw_ieq_update_tcpip_info(txbuf, fpdu_len, seqnum);
1200 crcptr = txbuf->data + fpdu_len - 4;
1201 mpacrc = *(u32 *)crcptr;
1202 if (ieq->check_crc) {
1203 status = i40iw_ieq_check_mpacrc(ieq->hash_desc, txbuf->data,
1204 (fpdu_len - 4), mpacrc);
1205 if (status) {
1206 i40iw_debug(ieq->dev, I40IW_DEBUG_IEQ,
1207 "%s: error bad crc\n", __func__);
1208 goto error;
1209 }
1210 }
1211
1212 i40iw_debug_buf(ieq->dev, I40IW_DEBUG_IEQ, "IEQ TX BUFFER",
1213 txbuf->mem.va, txbuf->totallen);
1214 i40iw_puda_send_buf(ieq, txbuf);
1215 pfpdu->rcv_nxt = seqnum + fpdu_len;
1216 return status;
1217 error:
1218 while (!list_empty(&pbufl)) {
1219 buf = (struct i40iw_puda_buf *)(pbufl.prev);
1220 list_del(&buf->list);
1221 list_add(&buf->list, rxlist);
1222 }
1223 if (txbuf)
1224 i40iw_puda_ret_bufpool(ieq, txbuf);
1225 return status;
1226}
1227
1228
1229
1230
1231
1232
1233
1234static enum i40iw_status_code i40iw_ieq_process_buf(struct i40iw_puda_rsrc *ieq,
1235 struct i40iw_pfpdu *pfpdu,
1236 struct i40iw_puda_buf *buf)
1237{
1238 u16 fpdu_len = 0;
1239 u16 datalen = buf->datalen;
1240 u8 *datap = buf->data;
1241 u8 *crcptr;
1242 u16 ioffset = 0;
1243 u32 mpacrc;
1244 u32 seqnum = buf->seqnum;
1245 u16 length = 0;
1246 u16 full = 0;
1247 bool partial = false;
1248 struct i40iw_puda_buf *txbuf;
1249 struct list_head *rxlist = &pfpdu->rxlist;
1250 enum i40iw_status_code ret = 0;
1251 enum i40iw_status_code status = 0;
1252
1253 ioffset = (u16)(buf->data - (u8 *)buf->mem.va);
1254 while (datalen) {
1255 fpdu_len = i40iw_ieq_get_fpdu_length(ntohs(*(__be16 *)datap));
1256 if (fpdu_len > pfpdu->max_fpdu_data) {
1257 i40iw_debug(ieq->dev, I40IW_DEBUG_IEQ,
1258 "%s: error bad fpdu_len\n", __func__);
1259 status = I40IW_ERR_MPA_CRC;
1260 list_add(&buf->list, rxlist);
1261 return status;
1262 }
1263
1264 if (datalen < fpdu_len) {
1265 partial = true;
1266 break;
1267 }
1268 crcptr = datap + fpdu_len - 4;
1269 mpacrc = *(u32 *)crcptr;
1270 if (ieq->check_crc)
1271 ret = i40iw_ieq_check_mpacrc(ieq->hash_desc,
1272 datap, fpdu_len - 4, mpacrc);
1273 if (ret) {
1274 status = I40IW_ERR_MPA_CRC;
1275 list_add(&buf->list, rxlist);
1276 return status;
1277 }
1278 full++;
1279 pfpdu->fpdu_processed++;
1280 datap += fpdu_len;
1281 length += fpdu_len;
1282 datalen -= fpdu_len;
1283 }
1284 if (full) {
1285
1286 txbuf = i40iw_puda_get_bufpool(ieq);
1287 if (!txbuf) {
1288 pfpdu->no_tx_bufs++;
1289 status = I40IW_ERR_NO_TXBUFS;
1290 list_add(&buf->list, rxlist);
1291 return status;
1292 }
1293
1294 i40iw_ieq_setup_tx_buf(buf, txbuf);
1295
1296 i40iw_ieq_copy_to_txbuf(buf, txbuf, ioffset, buf->hdrlen,
1297 length);
1298 txbuf->totallen = buf->hdrlen + length;
1299
1300 i40iw_ieq_update_tcpip_info(txbuf, length, buf->seqnum);
1301 i40iw_puda_send_buf(ieq, txbuf);
1302
1303 if (!datalen) {
1304 pfpdu->rcv_nxt = buf->seqnum + length;
1305 i40iw_puda_ret_bufpool(ieq, buf);
1306 return status;
1307 }
1308 buf->data = datap;
1309 buf->seqnum = seqnum + length;
1310 buf->datalen = datalen;
1311 pfpdu->rcv_nxt = buf->seqnum;
1312 }
1313 if (partial)
1314 status = i40iw_ieq_handle_partial(ieq, pfpdu, buf, fpdu_len);
1315
1316 return status;
1317}
1318
1319
1320
1321
1322
1323
1324static void i40iw_ieq_process_fpdus(struct i40iw_sc_qp *qp,
1325 struct i40iw_puda_rsrc *ieq)
1326{
1327 struct i40iw_pfpdu *pfpdu = &qp->pfpdu;
1328 struct list_head *rxlist = &pfpdu->rxlist;
1329 struct i40iw_puda_buf *buf;
1330 enum i40iw_status_code status;
1331
1332 do {
1333 if (list_empty(rxlist))
1334 break;
1335 buf = i40iw_puda_get_listbuf(rxlist);
1336 if (!buf) {
1337 i40iw_debug(ieq->dev, I40IW_DEBUG_IEQ,
1338 "%s: error no buf\n", __func__);
1339 break;
1340 }
1341 if (buf->seqnum != pfpdu->rcv_nxt) {
1342
1343 pfpdu->out_of_order++;
1344 list_add(&buf->list, rxlist);
1345 break;
1346 }
1347
1348 status = i40iw_ieq_process_buf(ieq, pfpdu, buf);
1349 if (status == I40IW_ERR_MPA_CRC) {
1350 pfpdu->mpa_crc_err = true;
1351 while (!list_empty(rxlist)) {
1352 buf = i40iw_puda_get_listbuf(rxlist);
1353 i40iw_puda_ret_bufpool(ieq, buf);
1354 pfpdu->crc_err++;
1355 }
1356
1357 i40iw_ieq_mpa_crc_ae(ieq->dev, qp);
1358 }
1359 } while (!status);
1360}
1361
1362
1363
1364
1365
1366
1367
1368static void i40iw_ieq_handle_exception(struct i40iw_puda_rsrc *ieq,
1369 struct i40iw_sc_qp *qp,
1370 struct i40iw_puda_buf *buf)
1371{
1372 struct i40iw_puda_buf *tmpbuf = NULL;
1373 struct i40iw_pfpdu *pfpdu = &qp->pfpdu;
1374 u32 *hw_host_ctx = (u32 *)qp->hw_host_ctx;
1375 u32 rcv_wnd = hw_host_ctx[23];
1376
1377 u32 fps = qp->q2_buf[16];
1378 struct list_head *rxlist = &pfpdu->rxlist;
1379 struct list_head *plist;
1380
1381 pfpdu->total_ieq_bufs++;
1382
1383 if (pfpdu->mpa_crc_err) {
1384 pfpdu->crc_err++;
1385 goto error;
1386 }
1387 if (pfpdu->mode && (fps != pfpdu->fps)) {
1388
1389 i40iw_ieq_cleanup_qp(ieq, qp);
1390 i40iw_debug(ieq->dev, I40IW_DEBUG_IEQ,
1391 "%s: restarting new partial\n", __func__);
1392 pfpdu->mode = false;
1393 }
1394
1395 if (!pfpdu->mode) {
1396 i40iw_debug_buf(ieq->dev, I40IW_DEBUG_IEQ, "Q2 BUFFER", (u64 *)qp->q2_buf, 128);
1397
1398 pfpdu->rcv_nxt = fps;
1399 pfpdu->fps = fps;
1400 pfpdu->mode = true;
1401 pfpdu->max_fpdu_data = ieq->vsi->mss;
1402 pfpdu->pmode_count++;
1403 INIT_LIST_HEAD(rxlist);
1404 i40iw_ieq_check_first_buf(buf, fps);
1405 }
1406
1407 if (!(rcv_wnd >= (buf->seqnum - pfpdu->rcv_nxt))) {
1408 pfpdu->bad_seq_num++;
1409 goto error;
1410 }
1411
1412 if (!list_empty(rxlist)) {
1413 tmpbuf = (struct i40iw_puda_buf *)rxlist->next;
1414 plist = &tmpbuf->list;
1415 while ((struct list_head *)tmpbuf != rxlist) {
1416 if ((int)(buf->seqnum - tmpbuf->seqnum) < 0)
1417 break;
1418 tmpbuf = (struct i40iw_puda_buf *)plist->next;
1419 }
1420
1421 list_add_tail(&buf->list, &tmpbuf->list);
1422 } else {
1423 list_add_tail(&buf->list, rxlist);
1424 }
1425 i40iw_ieq_process_fpdus(qp, ieq);
1426 return;
1427 error:
1428 i40iw_puda_ret_bufpool(ieq, buf);
1429}
1430
1431
1432
1433
1434
1435
1436static void i40iw_ieq_receive(struct i40iw_sc_vsi *vsi,
1437 struct i40iw_puda_buf *buf)
1438{
1439 struct i40iw_puda_rsrc *ieq = vsi->ieq;
1440 struct i40iw_sc_qp *qp = NULL;
1441 u32 wqe_idx = ieq->compl_rxwqe_idx;
1442
1443 qp = i40iw_ieq_get_qp(vsi->dev, buf);
1444 if (!qp) {
1445 ieq->stats_bad_qp_id++;
1446 i40iw_puda_ret_bufpool(ieq, buf);
1447 } else {
1448 i40iw_ieq_handle_exception(ieq, qp, buf);
1449 }
1450
1451
1452
1453
1454 if (!ieq->rxq_invalid_cnt)
1455 ieq->rx_wqe_idx = wqe_idx;
1456 ieq->rxq_invalid_cnt++;
1457}
1458
1459
1460
1461
1462
1463
1464static void i40iw_ieq_tx_compl(struct i40iw_sc_vsi *vsi, void *sqwrid)
1465{
1466 struct i40iw_puda_rsrc *ieq = vsi->ieq;
1467 struct i40iw_puda_buf *buf = (struct i40iw_puda_buf *)sqwrid;
1468
1469 i40iw_puda_ret_bufpool(ieq, buf);
1470 if (!list_empty(&ieq->txpend)) {
1471 buf = i40iw_puda_get_listbuf(&ieq->txpend);
1472 i40iw_puda_send_buf(ieq, buf);
1473 }
1474}
1475
1476
1477
1478
1479
1480
1481static void i40iw_ieq_cleanup_qp(struct i40iw_puda_rsrc *ieq, struct i40iw_sc_qp *qp)
1482{
1483 struct i40iw_puda_buf *buf;
1484 struct i40iw_pfpdu *pfpdu = &qp->pfpdu;
1485 struct list_head *rxlist = &pfpdu->rxlist;
1486
1487 if (!pfpdu->mode)
1488 return;
1489 while (!list_empty(rxlist)) {
1490 buf = i40iw_puda_get_listbuf(rxlist);
1491 i40iw_puda_ret_bufpool(ieq, buf);
1492 }
1493}
1494