xref: /freebsd/sys/dev/irdma/irdma_puda.c (revision 35105900c65bb5adcde05d37ae34ad006970d4f9)
1cdcd52d4SBartosz Sobczak /*-
2cdcd52d4SBartosz Sobczak  * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
3cdcd52d4SBartosz Sobczak  *
4777e472cSBartosz Sobczak  * Copyright (c) 2015 - 2022 Intel Corporation
5cdcd52d4SBartosz Sobczak  *
6cdcd52d4SBartosz Sobczak  * This software is available to you under a choice of one of two
7cdcd52d4SBartosz Sobczak  * licenses.  You may choose to be licensed under the terms of the GNU
8cdcd52d4SBartosz Sobczak  * General Public License (GPL) Version 2, available from the file
9cdcd52d4SBartosz Sobczak  * COPYING in the main directory of this source tree, or the
10cdcd52d4SBartosz Sobczak  * OpenFabrics.org BSD license below:
11cdcd52d4SBartosz Sobczak  *
12cdcd52d4SBartosz Sobczak  *   Redistribution and use in source and binary forms, with or
13cdcd52d4SBartosz Sobczak  *   without modification, are permitted provided that the following
14cdcd52d4SBartosz Sobczak  *   conditions are met:
15cdcd52d4SBartosz Sobczak  *
16cdcd52d4SBartosz Sobczak  *    - Redistributions of source code must retain the above
17cdcd52d4SBartosz Sobczak  *	copyright notice, this list of conditions and the following
18cdcd52d4SBartosz Sobczak  *	disclaimer.
19cdcd52d4SBartosz Sobczak  *
20cdcd52d4SBartosz Sobczak  *    - Redistributions in binary form must reproduce the above
21cdcd52d4SBartosz Sobczak  *	copyright notice, this list of conditions and the following
22cdcd52d4SBartosz Sobczak  *	disclaimer in the documentation and/or other materials
23cdcd52d4SBartosz Sobczak  *	provided with the distribution.
24cdcd52d4SBartosz Sobczak  *
25cdcd52d4SBartosz Sobczak  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26cdcd52d4SBartosz Sobczak  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27cdcd52d4SBartosz Sobczak  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28cdcd52d4SBartosz Sobczak  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29cdcd52d4SBartosz Sobczak  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30cdcd52d4SBartosz Sobczak  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31cdcd52d4SBartosz Sobczak  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32cdcd52d4SBartosz Sobczak  * SOFTWARE.
33cdcd52d4SBartosz Sobczak  */
34cdcd52d4SBartosz Sobczak /*$FreeBSD$*/
35cdcd52d4SBartosz Sobczak 
36cdcd52d4SBartosz Sobczak #include "osdep.h"
37cdcd52d4SBartosz Sobczak #include "irdma_hmc.h"
38cdcd52d4SBartosz Sobczak #include "irdma_defs.h"
39cdcd52d4SBartosz Sobczak #include "irdma_type.h"
40cdcd52d4SBartosz Sobczak #include "irdma_protos.h"
41cdcd52d4SBartosz Sobczak #include "irdma_puda.h"
42cdcd52d4SBartosz Sobczak #include "irdma_ws.h"
43cdcd52d4SBartosz Sobczak 
44cdcd52d4SBartosz Sobczak static void
45cdcd52d4SBartosz Sobczak irdma_ieq_receive(struct irdma_sc_vsi *vsi,
46cdcd52d4SBartosz Sobczak 		  struct irdma_puda_buf *buf);
47cdcd52d4SBartosz Sobczak static void irdma_ieq_tx_compl(struct irdma_sc_vsi *vsi, void *sqwrid);
48cdcd52d4SBartosz Sobczak static void
49cdcd52d4SBartosz Sobczak irdma_ilq_putback_rcvbuf(struct irdma_sc_qp *qp,
50cdcd52d4SBartosz Sobczak 			 struct irdma_puda_buf *buf, u32 wqe_idx);
51cdcd52d4SBartosz Sobczak /**
52cdcd52d4SBartosz Sobczak  * irdma_puda_get_listbuf - get buffer from puda list
53cdcd52d4SBartosz Sobczak  * @list: list to use for buffers (ILQ or IEQ)
54cdcd52d4SBartosz Sobczak  */
55cdcd52d4SBartosz Sobczak static struct irdma_puda_buf *
56cdcd52d4SBartosz Sobczak irdma_puda_get_listbuf(struct list_head *list)
57cdcd52d4SBartosz Sobczak {
58cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf = NULL;
59cdcd52d4SBartosz Sobczak 
60cdcd52d4SBartosz Sobczak 	if (!list_empty(list)) {
61cdcd52d4SBartosz Sobczak 		buf = (struct irdma_puda_buf *)(list)->next;
62cdcd52d4SBartosz Sobczak 		list_del((struct list_head *)&buf->list);
63cdcd52d4SBartosz Sobczak 	}
64cdcd52d4SBartosz Sobczak 
65cdcd52d4SBartosz Sobczak 	return buf;
66cdcd52d4SBartosz Sobczak }
67cdcd52d4SBartosz Sobczak 
68cdcd52d4SBartosz Sobczak /**
69cdcd52d4SBartosz Sobczak  * irdma_puda_get_bufpool - return buffer from resource
70cdcd52d4SBartosz Sobczak  * @rsrc: resource to use for buffer
71cdcd52d4SBartosz Sobczak  */
72cdcd52d4SBartosz Sobczak struct irdma_puda_buf *
73cdcd52d4SBartosz Sobczak irdma_puda_get_bufpool(struct irdma_puda_rsrc *rsrc)
74cdcd52d4SBartosz Sobczak {
75cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf = NULL;
76cdcd52d4SBartosz Sobczak 	struct list_head *list = &rsrc->bufpool;
77cdcd52d4SBartosz Sobczak 	unsigned long flags;
78cdcd52d4SBartosz Sobczak 
79cdcd52d4SBartosz Sobczak 	spin_lock_irqsave(&rsrc->bufpool_lock, flags);
80cdcd52d4SBartosz Sobczak 	buf = irdma_puda_get_listbuf(list);
81cdcd52d4SBartosz Sobczak 	if (buf) {
82cdcd52d4SBartosz Sobczak 		rsrc->avail_buf_count--;
83cdcd52d4SBartosz Sobczak 		buf->vsi = rsrc->vsi;
84cdcd52d4SBartosz Sobczak 	} else {
85cdcd52d4SBartosz Sobczak 		rsrc->stats_buf_alloc_fail++;
86cdcd52d4SBartosz Sobczak 	}
87cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
88cdcd52d4SBartosz Sobczak 
89cdcd52d4SBartosz Sobczak 	return buf;
90cdcd52d4SBartosz Sobczak }
91cdcd52d4SBartosz Sobczak 
92cdcd52d4SBartosz Sobczak /**
93cdcd52d4SBartosz Sobczak  * irdma_puda_ret_bufpool - return buffer to rsrc list
94cdcd52d4SBartosz Sobczak  * @rsrc: resource to use for buffer
95cdcd52d4SBartosz Sobczak  * @buf: buffer to return to resource
96cdcd52d4SBartosz Sobczak  */
97cdcd52d4SBartosz Sobczak void
98cdcd52d4SBartosz Sobczak irdma_puda_ret_bufpool(struct irdma_puda_rsrc *rsrc,
99cdcd52d4SBartosz Sobczak 		       struct irdma_puda_buf *buf)
100cdcd52d4SBartosz Sobczak {
101cdcd52d4SBartosz Sobczak 	unsigned long flags;
102cdcd52d4SBartosz Sobczak 
103cdcd52d4SBartosz Sobczak 	buf->do_lpb = false;
104cdcd52d4SBartosz Sobczak 	spin_lock_irqsave(&rsrc->bufpool_lock, flags);
105cdcd52d4SBartosz Sobczak 	list_add(&buf->list, &rsrc->bufpool);
106cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
107cdcd52d4SBartosz Sobczak 	rsrc->avail_buf_count++;
108cdcd52d4SBartosz Sobczak }
109cdcd52d4SBartosz Sobczak 
110cdcd52d4SBartosz Sobczak /**
111cdcd52d4SBartosz Sobczak  * irdma_puda_post_recvbuf - set wqe for rcv buffer
112cdcd52d4SBartosz Sobczak  * @rsrc: resource ptr
113cdcd52d4SBartosz Sobczak  * @wqe_idx: wqe index to use
114cdcd52d4SBartosz Sobczak  * @buf: puda buffer for rcv q
115cdcd52d4SBartosz Sobczak  * @initial: flag if during init time
116cdcd52d4SBartosz Sobczak  */
117cdcd52d4SBartosz Sobczak static void
118cdcd52d4SBartosz Sobczak irdma_puda_post_recvbuf(struct irdma_puda_rsrc *rsrc, u32 wqe_idx,
119cdcd52d4SBartosz Sobczak 			struct irdma_puda_buf *buf, bool initial)
120cdcd52d4SBartosz Sobczak {
121cdcd52d4SBartosz Sobczak 	__le64 *wqe;
122cdcd52d4SBartosz Sobczak 	struct irdma_sc_qp *qp = &rsrc->qp;
123cdcd52d4SBartosz Sobczak 	u64 offset24 = 0;
124cdcd52d4SBartosz Sobczak 
125cdcd52d4SBartosz Sobczak 	/* Synch buffer for use by device */
126cdcd52d4SBartosz Sobczak 	dma_sync_single_for_device(hw_to_dev(rsrc->dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL);
127cdcd52d4SBartosz Sobczak 	qp->qp_uk.rq_wrid_array[wqe_idx] = (uintptr_t)buf;
128cdcd52d4SBartosz Sobczak 	wqe = qp->qp_uk.rq_base[wqe_idx].elem;
129cdcd52d4SBartosz Sobczak 	if (!initial)
130cdcd52d4SBartosz Sobczak 		get_64bit_val(wqe, IRDMA_BYTE_24, &offset24);
131cdcd52d4SBartosz Sobczak 
132777e472cSBartosz Sobczak 	offset24 = (offset24) ? 0 : FIELD_PREP(IRDMAQPSQ_VALID, 1);
133cdcd52d4SBartosz Sobczak 
134cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_16, 0);
135cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, 0, buf->mem.pa);
136cdcd52d4SBartosz Sobczak 	if (qp->qp_uk.uk_attrs->hw_rev == IRDMA_GEN_1) {
137cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_8,
138777e472cSBartosz Sobczak 			      FIELD_PREP(IRDMAQPSQ_GEN1_FRAG_LEN, buf->mem.size));
139cdcd52d4SBartosz Sobczak 	} else {
140cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_8,
141777e472cSBartosz Sobczak 			      FIELD_PREP(IRDMAQPSQ_FRAG_LEN, buf->mem.size) |
142777e472cSBartosz Sobczak 			      offset24);
143cdcd52d4SBartosz Sobczak 	}
144cdcd52d4SBartosz Sobczak 	irdma_wmb();		/* make sure WQE is written before valid bit is set */
145cdcd52d4SBartosz Sobczak 
146cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_24, offset24);
147cdcd52d4SBartosz Sobczak }
148cdcd52d4SBartosz Sobczak 
149cdcd52d4SBartosz Sobczak /**
150cdcd52d4SBartosz Sobczak  * irdma_puda_replenish_rq - post rcv buffers
151cdcd52d4SBartosz Sobczak  * @rsrc: resource to use for buffer
152cdcd52d4SBartosz Sobczak  * @initial: flag if during init time
153cdcd52d4SBartosz Sobczak  */
154cdcd52d4SBartosz Sobczak static int
155cdcd52d4SBartosz Sobczak irdma_puda_replenish_rq(struct irdma_puda_rsrc *rsrc, bool initial)
156cdcd52d4SBartosz Sobczak {
157cdcd52d4SBartosz Sobczak 	u32 i;
158cdcd52d4SBartosz Sobczak 	u32 invalid_cnt = rsrc->rxq_invalid_cnt;
159cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf = NULL;
160cdcd52d4SBartosz Sobczak 
161cdcd52d4SBartosz Sobczak 	for (i = 0; i < invalid_cnt; i++) {
162cdcd52d4SBartosz Sobczak 		buf = irdma_puda_get_bufpool(rsrc);
163cdcd52d4SBartosz Sobczak 		if (!buf)
164cdcd52d4SBartosz Sobczak 			return -ENOBUFS;
165cdcd52d4SBartosz Sobczak 		irdma_puda_post_recvbuf(rsrc, rsrc->rx_wqe_idx, buf, initial);
166cdcd52d4SBartosz Sobczak 		rsrc->rx_wqe_idx = ((rsrc->rx_wqe_idx + 1) % rsrc->rq_size);
167cdcd52d4SBartosz Sobczak 		rsrc->rxq_invalid_cnt--;
168cdcd52d4SBartosz Sobczak 	}
169cdcd52d4SBartosz Sobczak 
170cdcd52d4SBartosz Sobczak 	return 0;
171cdcd52d4SBartosz Sobczak }
172cdcd52d4SBartosz Sobczak 
173cdcd52d4SBartosz Sobczak /**
174cdcd52d4SBartosz Sobczak  * irdma_puda_alloc_buf - allocate mem for buffer
175cdcd52d4SBartosz Sobczak  * @dev: iwarp device
176cdcd52d4SBartosz Sobczak  * @len: length of buffer
177cdcd52d4SBartosz Sobczak  */
178cdcd52d4SBartosz Sobczak static struct irdma_puda_buf *
179cdcd52d4SBartosz Sobczak irdma_puda_alloc_buf(struct irdma_sc_dev *dev,
180cdcd52d4SBartosz Sobczak 		     u32 len)
181cdcd52d4SBartosz Sobczak {
182cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
183cdcd52d4SBartosz Sobczak 	struct irdma_virt_mem buf_mem;
184cdcd52d4SBartosz Sobczak 
185cdcd52d4SBartosz Sobczak 	buf_mem.size = sizeof(struct irdma_puda_buf);
186777e472cSBartosz Sobczak 	buf_mem.va = kzalloc(buf_mem.size, GFP_KERNEL);
187cdcd52d4SBartosz Sobczak 	if (!buf_mem.va)
188cdcd52d4SBartosz Sobczak 		return NULL;
189cdcd52d4SBartosz Sobczak 
190cdcd52d4SBartosz Sobczak 	buf = buf_mem.va;
191cdcd52d4SBartosz Sobczak 	buf->mem.size = len;
192cdcd52d4SBartosz Sobczak 	buf->mem.va = kzalloc(buf->mem.size, GFP_KERNEL);
193cdcd52d4SBartosz Sobczak 	if (!buf->mem.va)
194cdcd52d4SBartosz Sobczak 		goto free_virt;
195cdcd52d4SBartosz Sobczak 	buf->mem.pa = dma_map_single(hw_to_dev(dev->hw), buf->mem.va, buf->mem.size, DMA_BIDIRECTIONAL);
196cdcd52d4SBartosz Sobczak 	if (dma_mapping_error(hw_to_dev(dev->hw), buf->mem.pa)) {
197cdcd52d4SBartosz Sobczak 		kfree(buf->mem.va);
198cdcd52d4SBartosz Sobczak 		goto free_virt;
199cdcd52d4SBartosz Sobczak 	}
200cdcd52d4SBartosz Sobczak 
201cdcd52d4SBartosz Sobczak 	buf->buf_mem.va = buf_mem.va;
202cdcd52d4SBartosz Sobczak 	buf->buf_mem.size = buf_mem.size;
203cdcd52d4SBartosz Sobczak 
204cdcd52d4SBartosz Sobczak 	return buf;
205cdcd52d4SBartosz Sobczak 
206cdcd52d4SBartosz Sobczak free_virt:
207cdcd52d4SBartosz Sobczak 	kfree(buf_mem.va);
208cdcd52d4SBartosz Sobczak 	return NULL;
209cdcd52d4SBartosz Sobczak }
210cdcd52d4SBartosz Sobczak 
211cdcd52d4SBartosz Sobczak /**
212cdcd52d4SBartosz Sobczak  * irdma_puda_dele_buf - delete buffer back to system
213cdcd52d4SBartosz Sobczak  * @dev: iwarp device
214cdcd52d4SBartosz Sobczak  * @buf: buffer to free
215cdcd52d4SBartosz Sobczak  */
216cdcd52d4SBartosz Sobczak static void
217cdcd52d4SBartosz Sobczak irdma_puda_dele_buf(struct irdma_sc_dev *dev,
218cdcd52d4SBartosz Sobczak 		    struct irdma_puda_buf *buf)
219cdcd52d4SBartosz Sobczak {
220cdcd52d4SBartosz Sobczak 	if (!buf->virtdma) {
221cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(dev->hw, &buf->mem);
222cdcd52d4SBartosz Sobczak 		kfree(buf->buf_mem.va);
223cdcd52d4SBartosz Sobczak 	}
224cdcd52d4SBartosz Sobczak }
225cdcd52d4SBartosz Sobczak 
226cdcd52d4SBartosz Sobczak /**
227cdcd52d4SBartosz Sobczak  * irdma_puda_get_next_send_wqe - return next wqe for processing
228cdcd52d4SBartosz Sobczak  * @qp: puda qp for wqe
229cdcd52d4SBartosz Sobczak  * @wqe_idx: wqe index for caller
230cdcd52d4SBartosz Sobczak  */
231cdcd52d4SBartosz Sobczak static __le64 * irdma_puda_get_next_send_wqe(struct irdma_qp_uk *qp,
232cdcd52d4SBartosz Sobczak 					     u32 *wqe_idx){
233cdcd52d4SBartosz Sobczak 	int ret_code = 0;
234cdcd52d4SBartosz Sobczak 
235cdcd52d4SBartosz Sobczak 	*wqe_idx = IRDMA_RING_CURRENT_HEAD(qp->sq_ring);
236cdcd52d4SBartosz Sobczak 	if (!*wqe_idx)
237cdcd52d4SBartosz Sobczak 		qp->swqe_polarity = !qp->swqe_polarity;
238cdcd52d4SBartosz Sobczak 	IRDMA_RING_MOVE_HEAD(qp->sq_ring, ret_code);
239cdcd52d4SBartosz Sobczak 	if (ret_code)
240*35105900SBartosz Sobczak 		return NULL;
241cdcd52d4SBartosz Sobczak 
242*35105900SBartosz Sobczak 	return qp->sq_base[*wqe_idx].elem;
243cdcd52d4SBartosz Sobczak }
244cdcd52d4SBartosz Sobczak 
245cdcd52d4SBartosz Sobczak /**
246cdcd52d4SBartosz Sobczak  * irdma_puda_poll_info - poll cq for completion
247cdcd52d4SBartosz Sobczak  * @cq: cq for poll
248cdcd52d4SBartosz Sobczak  * @info: info return for successful completion
249cdcd52d4SBartosz Sobczak  */
250cdcd52d4SBartosz Sobczak static int
251cdcd52d4SBartosz Sobczak irdma_puda_poll_info(struct irdma_sc_cq *cq,
252cdcd52d4SBartosz Sobczak 		     struct irdma_puda_cmpl_info *info)
253cdcd52d4SBartosz Sobczak {
254cdcd52d4SBartosz Sobczak 	struct irdma_cq_uk *cq_uk = &cq->cq_uk;
255cdcd52d4SBartosz Sobczak 	u64 qword0, qword2, qword3, qword6;
256cdcd52d4SBartosz Sobczak 	__le64 *cqe;
257cdcd52d4SBartosz Sobczak 	__le64 *ext_cqe = NULL;
258cdcd52d4SBartosz Sobczak 	u64 qword7 = 0;
259cdcd52d4SBartosz Sobczak 	u64 comp_ctx;
260cdcd52d4SBartosz Sobczak 	bool valid_bit;
261cdcd52d4SBartosz Sobczak 	bool ext_valid = 0;
262cdcd52d4SBartosz Sobczak 	u32 major_err, minor_err;
263cdcd52d4SBartosz Sobczak 	u32 peek_head;
264cdcd52d4SBartosz Sobczak 	bool error;
265cdcd52d4SBartosz Sobczak 	u8 polarity;
266cdcd52d4SBartosz Sobczak 
267cdcd52d4SBartosz Sobczak 	cqe = IRDMA_GET_CURRENT_CQ_ELEM(&cq->cq_uk);
268cdcd52d4SBartosz Sobczak 	get_64bit_val(cqe, IRDMA_BYTE_24, &qword3);
269777e472cSBartosz Sobczak 	valid_bit = (bool)FIELD_GET(IRDMA_CQ_VALID, qword3);
270cdcd52d4SBartosz Sobczak 	if (valid_bit != cq_uk->polarity)
271cdcd52d4SBartosz Sobczak 		return -ENOENT;
272cdcd52d4SBartosz Sobczak 
273cdcd52d4SBartosz Sobczak 	if (cq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
274777e472cSBartosz Sobczak 		ext_valid = (bool)FIELD_GET(IRDMA_CQ_EXTCQE, qword3);
275cdcd52d4SBartosz Sobczak 
276cdcd52d4SBartosz Sobczak 	if (ext_valid) {
277cdcd52d4SBartosz Sobczak 		peek_head = (cq_uk->cq_ring.head + 1) % cq_uk->cq_ring.size;
278cdcd52d4SBartosz Sobczak 		ext_cqe = cq_uk->cq_base[peek_head].buf;
279cdcd52d4SBartosz Sobczak 		get_64bit_val(ext_cqe, IRDMA_BYTE_24, &qword7);
280777e472cSBartosz Sobczak 		polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword7);
281cdcd52d4SBartosz Sobczak 		if (!peek_head)
282cdcd52d4SBartosz Sobczak 			polarity ^= 1;
283cdcd52d4SBartosz Sobczak 		if (polarity != cq_uk->polarity)
284cdcd52d4SBartosz Sobczak 			return -ENOENT;
285cdcd52d4SBartosz Sobczak 
286cdcd52d4SBartosz Sobczak 		IRDMA_RING_MOVE_HEAD_NOCHECK(cq_uk->cq_ring);
287cdcd52d4SBartosz Sobczak 		if (!IRDMA_RING_CURRENT_HEAD(cq_uk->cq_ring))
288cdcd52d4SBartosz Sobczak 			cq_uk->polarity = !cq_uk->polarity;
289cdcd52d4SBartosz Sobczak 		/* update cq tail in cq shadow memory also */
290cdcd52d4SBartosz Sobczak 		IRDMA_RING_MOVE_TAIL(cq_uk->cq_ring);
291cdcd52d4SBartosz Sobczak 	}
292cdcd52d4SBartosz Sobczak 
293cdcd52d4SBartosz Sobczak 	irdma_debug_buf(cq->dev, IRDMA_DEBUG_PUDA, "PUDA CQE", cqe, 32);
294cdcd52d4SBartosz Sobczak 	if (ext_valid)
295cdcd52d4SBartosz Sobczak 		irdma_debug_buf(cq->dev, IRDMA_DEBUG_PUDA, "PUDA EXT-CQE",
296cdcd52d4SBartosz Sobczak 				ext_cqe, 32);
297cdcd52d4SBartosz Sobczak 
298777e472cSBartosz Sobczak 	error = (bool)FIELD_GET(IRDMA_CQ_ERROR, qword3);
299cdcd52d4SBartosz Sobczak 	if (error) {
300cdcd52d4SBartosz Sobczak 		irdma_debug(cq->dev, IRDMA_DEBUG_PUDA, "receive error\n");
301777e472cSBartosz Sobczak 		major_err = (u32)(FIELD_GET(IRDMA_CQ_MAJERR, qword3));
302777e472cSBartosz Sobczak 		minor_err = (u32)(FIELD_GET(IRDMA_CQ_MINERR, qword3));
303cdcd52d4SBartosz Sobczak 		info->compl_error = major_err << 16 | minor_err;
304cdcd52d4SBartosz Sobczak 		return -EIO;
305cdcd52d4SBartosz Sobczak 	}
306cdcd52d4SBartosz Sobczak 
307cdcd52d4SBartosz Sobczak 	get_64bit_val(cqe, IRDMA_BYTE_0, &qword0);
308cdcd52d4SBartosz Sobczak 	get_64bit_val(cqe, IRDMA_BYTE_16, &qword2);
309cdcd52d4SBartosz Sobczak 
310777e472cSBartosz Sobczak 	info->q_type = (u8)FIELD_GET(IRDMA_CQ_SQ, qword3);
311777e472cSBartosz Sobczak 	info->qp_id = (u32)FIELD_GET(IRDMACQ_QPID, qword2);
312cdcd52d4SBartosz Sobczak 	if (cq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
313777e472cSBartosz Sobczak 		info->ipv4 = (bool)FIELD_GET(IRDMACQ_IPV4, qword3);
314cdcd52d4SBartosz Sobczak 
315cdcd52d4SBartosz Sobczak 	get_64bit_val(cqe, IRDMA_BYTE_8, &comp_ctx);
316cdcd52d4SBartosz Sobczak 	info->qp = (struct irdma_qp_uk *)(irdma_uintptr) comp_ctx;
317777e472cSBartosz Sobczak 	info->wqe_idx = (u32)FIELD_GET(IRDMA_CQ_WQEIDX, qword3);
318cdcd52d4SBartosz Sobczak 
319cdcd52d4SBartosz Sobczak 	if (info->q_type == IRDMA_CQE_QTYPE_RQ) {
320cdcd52d4SBartosz Sobczak 		if (ext_valid) {
321777e472cSBartosz Sobczak 			info->vlan_valid = (bool)FIELD_GET(IRDMA_CQ_UDVLANVALID, qword7);
322cdcd52d4SBartosz Sobczak 			if (info->vlan_valid) {
323cdcd52d4SBartosz Sobczak 				get_64bit_val(ext_cqe, IRDMA_BYTE_16, &qword6);
324777e472cSBartosz Sobczak 				info->vlan = (u16)FIELD_GET(IRDMA_CQ_UDVLAN, qword6);
325cdcd52d4SBartosz Sobczak 			}
326777e472cSBartosz Sobczak 			info->smac_valid = (bool)FIELD_GET(IRDMA_CQ_UDSMACVALID, qword7);
327cdcd52d4SBartosz Sobczak 			if (info->smac_valid) {
328cdcd52d4SBartosz Sobczak 				get_64bit_val(ext_cqe, IRDMA_BYTE_16, &qword6);
329cdcd52d4SBartosz Sobczak 				info->smac[0] = (u8)((qword6 >> 40) & 0xFF);
330cdcd52d4SBartosz Sobczak 				info->smac[1] = (u8)((qword6 >> 32) & 0xFF);
331cdcd52d4SBartosz Sobczak 				info->smac[2] = (u8)((qword6 >> 24) & 0xFF);
332cdcd52d4SBartosz Sobczak 				info->smac[3] = (u8)((qword6 >> 16) & 0xFF);
333cdcd52d4SBartosz Sobczak 				info->smac[4] = (u8)((qword6 >> 8) & 0xFF);
334cdcd52d4SBartosz Sobczak 				info->smac[5] = (u8)(qword6 & 0xFF);
335cdcd52d4SBartosz Sobczak 			}
336cdcd52d4SBartosz Sobczak 		}
337cdcd52d4SBartosz Sobczak 
338cdcd52d4SBartosz Sobczak 		if (cq->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1) {
339777e472cSBartosz Sobczak 			info->vlan_valid = (bool)FIELD_GET(IRDMA_VLAN_TAG_VALID, qword3);
340777e472cSBartosz Sobczak 			info->l4proto = (u8)FIELD_GET(IRDMA_UDA_L4PROTO, qword2);
341777e472cSBartosz Sobczak 			info->l3proto = (u8)FIELD_GET(IRDMA_UDA_L3PROTO, qword2);
342cdcd52d4SBartosz Sobczak 		}
343cdcd52d4SBartosz Sobczak 
344777e472cSBartosz Sobczak 		info->payload_len = (u32)FIELD_GET(IRDMACQ_PAYLDLEN, qword0);
345cdcd52d4SBartosz Sobczak 	}
346cdcd52d4SBartosz Sobczak 
347cdcd52d4SBartosz Sobczak 	return 0;
348cdcd52d4SBartosz Sobczak }
349cdcd52d4SBartosz Sobczak 
350cdcd52d4SBartosz Sobczak /**
351cdcd52d4SBartosz Sobczak  * irdma_puda_poll_cmpl - processes completion for cq
352cdcd52d4SBartosz Sobczak  * @dev: iwarp device
353cdcd52d4SBartosz Sobczak  * @cq: cq getting interrupt
354cdcd52d4SBartosz Sobczak  * @compl_err: return any completion err
355cdcd52d4SBartosz Sobczak  */
356cdcd52d4SBartosz Sobczak int
357cdcd52d4SBartosz Sobczak irdma_puda_poll_cmpl(struct irdma_sc_dev *dev, struct irdma_sc_cq *cq,
358cdcd52d4SBartosz Sobczak 		     u32 *compl_err)
359cdcd52d4SBartosz Sobczak {
360cdcd52d4SBartosz Sobczak 	struct irdma_qp_uk *qp;
361cdcd52d4SBartosz Sobczak 	struct irdma_cq_uk *cq_uk = &cq->cq_uk;
362cdcd52d4SBartosz Sobczak 	struct irdma_puda_cmpl_info info = {0};
363cdcd52d4SBartosz Sobczak 	int ret = 0;
364cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
365cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *rsrc;
366cdcd52d4SBartosz Sobczak 	u8 cq_type = cq->cq_type;
367cdcd52d4SBartosz Sobczak 	unsigned long flags;
368cdcd52d4SBartosz Sobczak 
369cdcd52d4SBartosz Sobczak 	if (cq_type == IRDMA_CQ_TYPE_ILQ || cq_type == IRDMA_CQ_TYPE_IEQ) {
370cdcd52d4SBartosz Sobczak 		rsrc = (cq_type == IRDMA_CQ_TYPE_ILQ) ? cq->vsi->ilq :
371cdcd52d4SBartosz Sobczak 		    cq->vsi->ieq;
372cdcd52d4SBartosz Sobczak 	} else {
373cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "qp_type error\n");
374cdcd52d4SBartosz Sobczak 		return -EFAULT;
375cdcd52d4SBartosz Sobczak 	}
376cdcd52d4SBartosz Sobczak 
377cdcd52d4SBartosz Sobczak 	ret = irdma_puda_poll_info(cq, &info);
378cdcd52d4SBartosz Sobczak 	*compl_err = info.compl_error;
379cdcd52d4SBartosz Sobczak 	if (ret == -ENOENT)
380cdcd52d4SBartosz Sobczak 		return ret;
381cdcd52d4SBartosz Sobczak 	if (ret)
382cdcd52d4SBartosz Sobczak 		goto done;
383cdcd52d4SBartosz Sobczak 
384cdcd52d4SBartosz Sobczak 	qp = info.qp;
385cdcd52d4SBartosz Sobczak 	if (!qp || !rsrc) {
386cdcd52d4SBartosz Sobczak 		ret = -EFAULT;
387cdcd52d4SBartosz Sobczak 		goto done;
388cdcd52d4SBartosz Sobczak 	}
389cdcd52d4SBartosz Sobczak 
390cdcd52d4SBartosz Sobczak 	if (qp->qp_id != rsrc->qp_id) {
391cdcd52d4SBartosz Sobczak 		ret = -EFAULT;
392cdcd52d4SBartosz Sobczak 		goto done;
393cdcd52d4SBartosz Sobczak 	}
394cdcd52d4SBartosz Sobczak 
395cdcd52d4SBartosz Sobczak 	if (info.q_type == IRDMA_CQE_QTYPE_RQ) {
396cdcd52d4SBartosz Sobczak 		buf = (struct irdma_puda_buf *)(uintptr_t)
397cdcd52d4SBartosz Sobczak 		    qp->rq_wrid_array[info.wqe_idx];
398cdcd52d4SBartosz Sobczak 
399cdcd52d4SBartosz Sobczak 		/* reusing so synch the buffer for CPU use */
400cdcd52d4SBartosz Sobczak 		dma_sync_single_for_cpu(hw_to_dev(dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL);
401cdcd52d4SBartosz Sobczak 		/* Get all the tcpip information in the buf header */
402cdcd52d4SBartosz Sobczak 		ret = irdma_puda_get_tcpip_info(&info, buf);
403cdcd52d4SBartosz Sobczak 		if (ret) {
404cdcd52d4SBartosz Sobczak 			rsrc->stats_rcvd_pkt_err++;
405cdcd52d4SBartosz Sobczak 			if (cq_type == IRDMA_CQ_TYPE_ILQ) {
406cdcd52d4SBartosz Sobczak 				irdma_ilq_putback_rcvbuf(&rsrc->qp, buf,
407cdcd52d4SBartosz Sobczak 							 info.wqe_idx);
408cdcd52d4SBartosz Sobczak 			} else {
409cdcd52d4SBartosz Sobczak 				irdma_puda_ret_bufpool(rsrc, buf);
410cdcd52d4SBartosz Sobczak 				irdma_puda_replenish_rq(rsrc, false);
411cdcd52d4SBartosz Sobczak 			}
412cdcd52d4SBartosz Sobczak 			goto done;
413cdcd52d4SBartosz Sobczak 		}
414cdcd52d4SBartosz Sobczak 
415cdcd52d4SBartosz Sobczak 		rsrc->stats_pkt_rcvd++;
416cdcd52d4SBartosz Sobczak 		rsrc->compl_rxwqe_idx = info.wqe_idx;
417cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "RQ completion\n");
418cdcd52d4SBartosz Sobczak 		rsrc->receive(rsrc->vsi, buf);
419cdcd52d4SBartosz Sobczak 		if (cq_type == IRDMA_CQ_TYPE_ILQ)
420cdcd52d4SBartosz Sobczak 			irdma_ilq_putback_rcvbuf(&rsrc->qp, buf, info.wqe_idx);
421cdcd52d4SBartosz Sobczak 		else
422cdcd52d4SBartosz Sobczak 			irdma_puda_replenish_rq(rsrc, false);
423cdcd52d4SBartosz Sobczak 
424cdcd52d4SBartosz Sobczak 	} else {
425cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "SQ completion\n");
426cdcd52d4SBartosz Sobczak 		buf = (struct irdma_puda_buf *)(uintptr_t)
427cdcd52d4SBartosz Sobczak 		    qp->sq_wrtrk_array[info.wqe_idx].wrid;
428cdcd52d4SBartosz Sobczak 
429cdcd52d4SBartosz Sobczak 		/* reusing so synch the buffer for CPU use */
430cdcd52d4SBartosz Sobczak 		dma_sync_single_for_cpu(hw_to_dev(dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL);
431cdcd52d4SBartosz Sobczak 		IRDMA_RING_SET_TAIL(qp->sq_ring, info.wqe_idx);
432cdcd52d4SBartosz Sobczak 		rsrc->xmit_complete(rsrc->vsi, buf);
433cdcd52d4SBartosz Sobczak 		spin_lock_irqsave(&rsrc->bufpool_lock, flags);
434cdcd52d4SBartosz Sobczak 		rsrc->tx_wqe_avail_cnt++;
435cdcd52d4SBartosz Sobczak 		spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
436cdcd52d4SBartosz Sobczak 		if (!list_empty(&rsrc->txpend))
437cdcd52d4SBartosz Sobczak 			irdma_puda_send_buf(rsrc, NULL);
438cdcd52d4SBartosz Sobczak 	}
439cdcd52d4SBartosz Sobczak 
440cdcd52d4SBartosz Sobczak done:
441cdcd52d4SBartosz Sobczak 	IRDMA_RING_MOVE_HEAD_NOCHECK(cq_uk->cq_ring);
442cdcd52d4SBartosz Sobczak 	if (!IRDMA_RING_CURRENT_HEAD(cq_uk->cq_ring))
443cdcd52d4SBartosz Sobczak 		cq_uk->polarity = !cq_uk->polarity;
444cdcd52d4SBartosz Sobczak 	/* update cq tail in cq shadow memory also */
445cdcd52d4SBartosz Sobczak 	IRDMA_RING_MOVE_TAIL(cq_uk->cq_ring);
446cdcd52d4SBartosz Sobczak 	set_64bit_val(cq_uk->shadow_area, IRDMA_BYTE_0,
447cdcd52d4SBartosz Sobczak 		      IRDMA_RING_CURRENT_HEAD(cq_uk->cq_ring));
448cdcd52d4SBartosz Sobczak 
449cdcd52d4SBartosz Sobczak 	return ret;
450cdcd52d4SBartosz Sobczak }
451cdcd52d4SBartosz Sobczak 
452cdcd52d4SBartosz Sobczak /**
453cdcd52d4SBartosz Sobczak  * irdma_puda_send - complete send wqe for transmit
454cdcd52d4SBartosz Sobczak  * @qp: puda qp for send
455cdcd52d4SBartosz Sobczak  * @info: buffer information for transmit
456cdcd52d4SBartosz Sobczak  */
457cdcd52d4SBartosz Sobczak int
458cdcd52d4SBartosz Sobczak irdma_puda_send(struct irdma_sc_qp *qp, struct irdma_puda_send_info *info)
459cdcd52d4SBartosz Sobczak {
460cdcd52d4SBartosz Sobczak 	__le64 *wqe;
461cdcd52d4SBartosz Sobczak 	u32 iplen, l4len;
462cdcd52d4SBartosz Sobczak 	u64 hdr[2];
463cdcd52d4SBartosz Sobczak 	u32 wqe_idx;
464cdcd52d4SBartosz Sobczak 	u8 iipt;
465cdcd52d4SBartosz Sobczak 
466cdcd52d4SBartosz Sobczak 	/* number of 32 bits DWORDS in header */
467cdcd52d4SBartosz Sobczak 	l4len = info->tcplen >> 2;
468cdcd52d4SBartosz Sobczak 	if (info->ipv4) {
469cdcd52d4SBartosz Sobczak 		iipt = 3;
470cdcd52d4SBartosz Sobczak 		iplen = 5;
471cdcd52d4SBartosz Sobczak 	} else {
472cdcd52d4SBartosz Sobczak 		iipt = 1;
473cdcd52d4SBartosz Sobczak 		iplen = 10;
474cdcd52d4SBartosz Sobczak 	}
475cdcd52d4SBartosz Sobczak 
476cdcd52d4SBartosz Sobczak 	wqe = irdma_puda_get_next_send_wqe(&qp->qp_uk, &wqe_idx);
477cdcd52d4SBartosz Sobczak 	if (!wqe)
478cdcd52d4SBartosz Sobczak 		return -ENOSPC;
479cdcd52d4SBartosz Sobczak 
480cdcd52d4SBartosz Sobczak 	qp->qp_uk.sq_wrtrk_array[wqe_idx].wrid = (uintptr_t)info->scratch;
481cdcd52d4SBartosz Sobczak 	/* Third line of WQE descriptor */
482cdcd52d4SBartosz Sobczak 	/* maclen is in words */
483cdcd52d4SBartosz Sobczak 
484cdcd52d4SBartosz Sobczak 	if (qp->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
485cdcd52d4SBartosz Sobczak 		hdr[0] = 0;	/* Dest_QPN and Dest_QKey only for UD */
486777e472cSBartosz Sobczak 		hdr[1] = FIELD_PREP(IRDMA_UDA_QPSQ_OPCODE, IRDMA_OP_TYPE_SEND) |
487777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_L4LEN, l4len) |
488777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMAQPSQ_AHID, info->ah_id) |
489777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_SIGCOMPL, 1) |
490777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_VALID,
491777e472cSBartosz Sobczak 			       qp->qp_uk.swqe_polarity);
492cdcd52d4SBartosz Sobczak 
493cdcd52d4SBartosz Sobczak 		/* Forth line of WQE descriptor */
494cdcd52d4SBartosz Sobczak 
495cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_0, info->paddr);
496cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_8,
497777e472cSBartosz Sobczak 			      FIELD_PREP(IRDMAQPSQ_FRAG_LEN, info->len) |
498777e472cSBartosz Sobczak 			      FIELD_PREP(IRDMA_UDA_QPSQ_VALID, qp->qp_uk.swqe_polarity));
499cdcd52d4SBartosz Sobczak 	} else {
500777e472cSBartosz Sobczak 		hdr[0] = FIELD_PREP(IRDMA_UDA_QPSQ_MACLEN, info->maclen >> 1) |
501777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_IPLEN, iplen) |
502777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_L4T, 1) |
503777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_IIPT, iipt) |
504777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_GEN1_UDA_QPSQ_L4LEN, l4len);
505cdcd52d4SBartosz Sobczak 
506777e472cSBartosz Sobczak 		hdr[1] = FIELD_PREP(IRDMA_UDA_QPSQ_OPCODE, IRDMA_OP_TYPE_SEND) |
507777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_SIGCOMPL, 1) |
508777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_DOLOOPBACK, info->do_lpb) |
509777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_VALID, qp->qp_uk.swqe_polarity);
510cdcd52d4SBartosz Sobczak 
511cdcd52d4SBartosz Sobczak 		/* Forth line of WQE descriptor */
512cdcd52d4SBartosz Sobczak 
513cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_0, info->paddr);
514cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_8,
515777e472cSBartosz Sobczak 			      FIELD_PREP(IRDMAQPSQ_GEN1_FRAG_LEN, info->len));
516cdcd52d4SBartosz Sobczak 	}
517cdcd52d4SBartosz Sobczak 
518cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_16, hdr[0]);
519cdcd52d4SBartosz Sobczak 	irdma_wmb();		/* make sure WQE is written before valid bit is set */
520cdcd52d4SBartosz Sobczak 
521cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_24, hdr[1]);
522cdcd52d4SBartosz Sobczak 
523cdcd52d4SBartosz Sobczak 	irdma_debug_buf(qp->dev, IRDMA_DEBUG_PUDA, "PUDA SEND WQE", wqe, 32);
524cdcd52d4SBartosz Sobczak 	irdma_uk_qp_post_wr(&qp->qp_uk);
525cdcd52d4SBartosz Sobczak 	return 0;
526cdcd52d4SBartosz Sobczak }
527cdcd52d4SBartosz Sobczak 
528cdcd52d4SBartosz Sobczak /**
529cdcd52d4SBartosz Sobczak  * irdma_puda_send_buf - transmit puda buffer
530cdcd52d4SBartosz Sobczak  * @rsrc: resource to use for buffer
531cdcd52d4SBartosz Sobczak  * @buf: puda buffer to transmit
532cdcd52d4SBartosz Sobczak  */
533cdcd52d4SBartosz Sobczak void
534cdcd52d4SBartosz Sobczak irdma_puda_send_buf(struct irdma_puda_rsrc *rsrc,
535cdcd52d4SBartosz Sobczak 		    struct irdma_puda_buf *buf)
536cdcd52d4SBartosz Sobczak {
537cdcd52d4SBartosz Sobczak 	struct irdma_puda_send_info info;
538cdcd52d4SBartosz Sobczak 	int ret = 0;
539cdcd52d4SBartosz Sobczak 	unsigned long flags;
540cdcd52d4SBartosz Sobczak 
541cdcd52d4SBartosz Sobczak 	spin_lock_irqsave(&rsrc->bufpool_lock, flags);
542cdcd52d4SBartosz Sobczak 	/*
543cdcd52d4SBartosz Sobczak 	 * if no wqe available or not from a completion and we have pending buffers, we must queue new buffer
544cdcd52d4SBartosz Sobczak 	 */
545cdcd52d4SBartosz Sobczak 	if (!rsrc->tx_wqe_avail_cnt || (buf && !list_empty(&rsrc->txpend))) {
546cdcd52d4SBartosz Sobczak 		list_add_tail(&buf->list, &rsrc->txpend);
547cdcd52d4SBartosz Sobczak 		spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
548cdcd52d4SBartosz Sobczak 		rsrc->stats_sent_pkt_q++;
549cdcd52d4SBartosz Sobczak 		if (rsrc->type == IRDMA_PUDA_RSRC_TYPE_ILQ)
550cdcd52d4SBartosz Sobczak 			irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
551cdcd52d4SBartosz Sobczak 				    "adding to txpend\n");
552cdcd52d4SBartosz Sobczak 		return;
553cdcd52d4SBartosz Sobczak 	}
554cdcd52d4SBartosz Sobczak 	rsrc->tx_wqe_avail_cnt--;
555cdcd52d4SBartosz Sobczak 	/*
556cdcd52d4SBartosz Sobczak 	 * if we are coming from a completion and have pending buffers then Get one from pending list
557cdcd52d4SBartosz Sobczak 	 */
558cdcd52d4SBartosz Sobczak 	if (!buf) {
559cdcd52d4SBartosz Sobczak 		buf = irdma_puda_get_listbuf(&rsrc->txpend);
560cdcd52d4SBartosz Sobczak 		if (!buf)
561cdcd52d4SBartosz Sobczak 			goto done;
562cdcd52d4SBartosz Sobczak 	}
563cdcd52d4SBartosz Sobczak 
564cdcd52d4SBartosz Sobczak 	info.scratch = buf;
565cdcd52d4SBartosz Sobczak 	info.paddr = buf->mem.pa;
566cdcd52d4SBartosz Sobczak 	info.len = buf->totallen;
567cdcd52d4SBartosz Sobczak 	info.tcplen = buf->tcphlen;
568cdcd52d4SBartosz Sobczak 	info.ipv4 = buf->ipv4;
569cdcd52d4SBartosz Sobczak 
570cdcd52d4SBartosz Sobczak 	if (rsrc->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
571cdcd52d4SBartosz Sobczak 		info.ah_id = buf->ah_id;
572cdcd52d4SBartosz Sobczak 	} else {
573cdcd52d4SBartosz Sobczak 		info.maclen = buf->maclen;
574cdcd52d4SBartosz Sobczak 		info.do_lpb = buf->do_lpb;
575cdcd52d4SBartosz Sobczak 	}
576cdcd52d4SBartosz Sobczak 
577cdcd52d4SBartosz Sobczak 	/* Synch buffer for use by device */
578cdcd52d4SBartosz Sobczak 	dma_sync_single_for_cpu(hw_to_dev(rsrc->dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL);
579cdcd52d4SBartosz Sobczak 	ret = irdma_puda_send(&rsrc->qp, &info);
580cdcd52d4SBartosz Sobczak 	if (ret) {
581cdcd52d4SBartosz Sobczak 		rsrc->tx_wqe_avail_cnt++;
582cdcd52d4SBartosz Sobczak 		rsrc->stats_sent_pkt_q++;
583cdcd52d4SBartosz Sobczak 		list_add(&buf->list, &rsrc->txpend);
584cdcd52d4SBartosz Sobczak 		if (rsrc->type == IRDMA_PUDA_RSRC_TYPE_ILQ)
585cdcd52d4SBartosz Sobczak 			irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
586cdcd52d4SBartosz Sobczak 				    "adding to puda_send\n");
587cdcd52d4SBartosz Sobczak 	} else {
588cdcd52d4SBartosz Sobczak 		rsrc->stats_pkt_sent++;
589cdcd52d4SBartosz Sobczak 	}
590cdcd52d4SBartosz Sobczak done:
591cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
592cdcd52d4SBartosz Sobczak }
593cdcd52d4SBartosz Sobczak 
594cdcd52d4SBartosz Sobczak /**
595cdcd52d4SBartosz Sobczak  * irdma_puda_qp_setctx - during init, set qp's context
596cdcd52d4SBartosz Sobczak  * @rsrc: qp's resource
597cdcd52d4SBartosz Sobczak  */
598cdcd52d4SBartosz Sobczak static void
599cdcd52d4SBartosz Sobczak irdma_puda_qp_setctx(struct irdma_puda_rsrc *rsrc)
600cdcd52d4SBartosz Sobczak {
601cdcd52d4SBartosz Sobczak 	struct irdma_sc_qp *qp = &rsrc->qp;
602cdcd52d4SBartosz Sobczak 	__le64 *qp_ctx = qp->hw_host_ctx;
603cdcd52d4SBartosz Sobczak 
604cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_8, qp->sq_pa);
605cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_16, qp->rq_pa);
606cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_24,
607777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_RQSIZE, qp->hw_rq_size) |
608777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_SQSIZE, qp->hw_sq_size));
609cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_48,
610777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_SNDMSS, rsrc->buf_size));
611cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_56, 0);
612cdcd52d4SBartosz Sobczak 	if (qp->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1)
613cdcd52d4SBartosz Sobczak 		set_64bit_val(qp_ctx, IRDMA_BYTE_64, 1);
614cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_136,
615777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_TXCQNUM, rsrc->cq_id) |
616777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_RXCQNUM, rsrc->cq_id));
617cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_144,
618777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_STAT_INDEX, rsrc->stats_idx));
619cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_160,
620777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_PRIVEN, 1) |
621777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_USESTATSINSTANCE, rsrc->stats_idx_valid));
622cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_168,
623777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_QPCOMPCTX, (uintptr_t)qp));
624cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_176,
625777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_SQTPHVAL, qp->sq_tph_val) |
626777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_RQTPHVAL, qp->rq_tph_val) |
627777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_QSHANDLE, qp->qs_handle));
628cdcd52d4SBartosz Sobczak 
629cdcd52d4SBartosz Sobczak 	irdma_debug_buf(rsrc->dev, IRDMA_DEBUG_PUDA, "PUDA QP CONTEXT", qp_ctx,
630cdcd52d4SBartosz Sobczak 			IRDMA_QP_CTX_SIZE);
631cdcd52d4SBartosz Sobczak }
632cdcd52d4SBartosz Sobczak 
633cdcd52d4SBartosz Sobczak /**
634cdcd52d4SBartosz Sobczak  * irdma_puda_qp_wqe - setup wqe for qp create
635cdcd52d4SBartosz Sobczak  * @dev: Device
636cdcd52d4SBartosz Sobczak  * @qp: Resource qp
637cdcd52d4SBartosz Sobczak  */
638cdcd52d4SBartosz Sobczak static int
639cdcd52d4SBartosz Sobczak irdma_puda_qp_wqe(struct irdma_sc_dev *dev, struct irdma_sc_qp *qp)
640cdcd52d4SBartosz Sobczak {
641cdcd52d4SBartosz Sobczak 	struct irdma_sc_cqp *cqp;
642cdcd52d4SBartosz Sobczak 	__le64 *wqe;
643cdcd52d4SBartosz Sobczak 	u64 hdr;
644cdcd52d4SBartosz Sobczak 	struct irdma_ccq_cqe_info compl_info;
645cdcd52d4SBartosz Sobczak 	int status = 0;
646cdcd52d4SBartosz Sobczak 
647cdcd52d4SBartosz Sobczak 	cqp = dev->cqp;
648cdcd52d4SBartosz Sobczak 	wqe = irdma_sc_cqp_get_next_send_wqe(cqp, 0);
649cdcd52d4SBartosz Sobczak 	if (!wqe)
650cdcd52d4SBartosz Sobczak 		return -ENOSPC;
651cdcd52d4SBartosz Sobczak 
652cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_16, qp->hw_host_ctx_pa);
653cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_40, qp->shadow_area_pa);
654cdcd52d4SBartosz Sobczak 
655cdcd52d4SBartosz Sobczak 	hdr = qp->qp_uk.qp_id |
656777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_CREATE_QP) |
657777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_QP_QPTYPE, IRDMA_QP_TYPE_UDA) |
658777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_QP_CQNUMVALID, 1) |
659777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_QP_NEXTIWSTATE, 2) |
660777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
661cdcd52d4SBartosz Sobczak 	irdma_wmb();		/* make sure WQE is written before valid bit is set */
662cdcd52d4SBartosz Sobczak 
663cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_24, hdr);
664cdcd52d4SBartosz Sobczak 
665cdcd52d4SBartosz Sobczak 	irdma_debug_buf(cqp->dev, IRDMA_DEBUG_PUDA, "PUDA QP CREATE", wqe, 40);
666cdcd52d4SBartosz Sobczak 	irdma_sc_cqp_post_sq(cqp);
667cdcd52d4SBartosz Sobczak 	status = irdma_sc_poll_for_cqp_op_done(dev->cqp, IRDMA_CQP_OP_CREATE_QP,
668cdcd52d4SBartosz Sobczak 					       &compl_info);
669cdcd52d4SBartosz Sobczak 
670cdcd52d4SBartosz Sobczak 	return status;
671cdcd52d4SBartosz Sobczak }
672cdcd52d4SBartosz Sobczak 
673cdcd52d4SBartosz Sobczak /**
674cdcd52d4SBartosz Sobczak  * irdma_puda_qp_create - create qp for resource
675cdcd52d4SBartosz Sobczak  * @rsrc: resource to use for buffer
676cdcd52d4SBartosz Sobczak  */
677cdcd52d4SBartosz Sobczak static int
678cdcd52d4SBartosz Sobczak irdma_puda_qp_create(struct irdma_puda_rsrc *rsrc)
679cdcd52d4SBartosz Sobczak {
680cdcd52d4SBartosz Sobczak 	struct irdma_sc_qp *qp = &rsrc->qp;
681cdcd52d4SBartosz Sobczak 	struct irdma_qp_uk *ukqp = &qp->qp_uk;
682cdcd52d4SBartosz Sobczak 	int ret = 0;
683cdcd52d4SBartosz Sobczak 	u32 sq_size, rq_size;
684cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem *mem;
685cdcd52d4SBartosz Sobczak 
686cdcd52d4SBartosz Sobczak 	sq_size = rsrc->sq_size * IRDMA_QP_WQE_MIN_SIZE;
687cdcd52d4SBartosz Sobczak 	rq_size = rsrc->rq_size * IRDMA_QP_WQE_MIN_SIZE;
688cdcd52d4SBartosz Sobczak 	rsrc->qpmem.size = (sq_size + rq_size + (IRDMA_SHADOW_AREA_SIZE << 3) +
689cdcd52d4SBartosz Sobczak 			    IRDMA_QP_CTX_SIZE);
690cdcd52d4SBartosz Sobczak 	rsrc->qpmem.va = irdma_allocate_dma_mem(rsrc->dev->hw, &rsrc->qpmem,
691cdcd52d4SBartosz Sobczak 						rsrc->qpmem.size, IRDMA_HW_PAGE_SIZE);
692cdcd52d4SBartosz Sobczak 	if (!rsrc->qpmem.va)
693cdcd52d4SBartosz Sobczak 		return -ENOMEM;
694cdcd52d4SBartosz Sobczak 
695cdcd52d4SBartosz Sobczak 	mem = &rsrc->qpmem;
696cdcd52d4SBartosz Sobczak 	memset(mem->va, 0, rsrc->qpmem.size);
697cdcd52d4SBartosz Sobczak 	qp->hw_sq_size = irdma_get_encoded_wqe_size(rsrc->sq_size, IRDMA_QUEUE_TYPE_SQ_RQ);
698cdcd52d4SBartosz Sobczak 	qp->hw_rq_size = irdma_get_encoded_wqe_size(rsrc->rq_size, IRDMA_QUEUE_TYPE_SQ_RQ);
699cdcd52d4SBartosz Sobczak 	qp->pd = &rsrc->sc_pd;
700cdcd52d4SBartosz Sobczak 	qp->qp_uk.qp_type = IRDMA_QP_TYPE_UDA;
701cdcd52d4SBartosz Sobczak 	qp->dev = rsrc->dev;
702cdcd52d4SBartosz Sobczak 	qp->qp_uk.back_qp = rsrc;
703cdcd52d4SBartosz Sobczak 	qp->sq_pa = mem->pa;
704cdcd52d4SBartosz Sobczak 	qp->rq_pa = qp->sq_pa + sq_size;
705cdcd52d4SBartosz Sobczak 	qp->vsi = rsrc->vsi;
706cdcd52d4SBartosz Sobczak 	ukqp->sq_base = mem->va;
707cdcd52d4SBartosz Sobczak 	ukqp->rq_base = &ukqp->sq_base[rsrc->sq_size];
708cdcd52d4SBartosz Sobczak 	ukqp->shadow_area = ukqp->rq_base[rsrc->rq_size].elem;
709cdcd52d4SBartosz Sobczak 	ukqp->uk_attrs = &qp->dev->hw_attrs.uk_attrs;
710cdcd52d4SBartosz Sobczak 	qp->shadow_area_pa = qp->rq_pa + rq_size;
711cdcd52d4SBartosz Sobczak 	qp->hw_host_ctx = ukqp->shadow_area + IRDMA_SHADOW_AREA_SIZE;
712cdcd52d4SBartosz Sobczak 	qp->hw_host_ctx_pa = qp->shadow_area_pa + (IRDMA_SHADOW_AREA_SIZE << 3);
713cdcd52d4SBartosz Sobczak 	qp->push_idx = IRDMA_INVALID_PUSH_PAGE_INDEX;
714cdcd52d4SBartosz Sobczak 	ukqp->qp_id = rsrc->qp_id;
715cdcd52d4SBartosz Sobczak 	ukqp->sq_wrtrk_array = rsrc->sq_wrtrk_array;
716cdcd52d4SBartosz Sobczak 	ukqp->rq_wrid_array = rsrc->rq_wrid_array;
717cdcd52d4SBartosz Sobczak 	ukqp->sq_size = rsrc->sq_size;
718cdcd52d4SBartosz Sobczak 	ukqp->rq_size = rsrc->rq_size;
719cdcd52d4SBartosz Sobczak 
720cdcd52d4SBartosz Sobczak 	IRDMA_RING_INIT(ukqp->sq_ring, ukqp->sq_size);
721cdcd52d4SBartosz Sobczak 	IRDMA_RING_INIT(ukqp->initial_ring, ukqp->sq_size);
722cdcd52d4SBartosz Sobczak 	IRDMA_RING_INIT(ukqp->rq_ring, ukqp->rq_size);
723cdcd52d4SBartosz Sobczak 	ukqp->wqe_alloc_db = qp->pd->dev->wqe_alloc_db;
724cdcd52d4SBartosz Sobczak 
725cdcd52d4SBartosz Sobczak 	ret = rsrc->dev->ws_add(qp->vsi, qp->user_pri);
726cdcd52d4SBartosz Sobczak 	if (ret) {
727cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(rsrc->dev->hw, &rsrc->qpmem);
728cdcd52d4SBartosz Sobczak 		return ret;
729cdcd52d4SBartosz Sobczak 	}
730cdcd52d4SBartosz Sobczak 
731cdcd52d4SBartosz Sobczak 	irdma_qp_add_qos(qp);
732cdcd52d4SBartosz Sobczak 	irdma_puda_qp_setctx(rsrc);
733cdcd52d4SBartosz Sobczak 
734cdcd52d4SBartosz Sobczak 	if (rsrc->dev->ceq_valid)
735cdcd52d4SBartosz Sobczak 		ret = irdma_cqp_qp_create_cmd(rsrc->dev, qp);
736cdcd52d4SBartosz Sobczak 	else
737cdcd52d4SBartosz Sobczak 		ret = irdma_puda_qp_wqe(rsrc->dev, qp);
738cdcd52d4SBartosz Sobczak 	if (ret) {
739cdcd52d4SBartosz Sobczak 		irdma_qp_rem_qos(qp);
740cdcd52d4SBartosz Sobczak 		rsrc->dev->ws_remove(qp->vsi, qp->user_pri);
741cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(rsrc->dev->hw, &rsrc->qpmem);
742cdcd52d4SBartosz Sobczak 	}
743cdcd52d4SBartosz Sobczak 
744cdcd52d4SBartosz Sobczak 	return ret;
745cdcd52d4SBartosz Sobczak }
746cdcd52d4SBartosz Sobczak 
747cdcd52d4SBartosz Sobczak /**
748cdcd52d4SBartosz Sobczak  * irdma_puda_cq_wqe - setup wqe for CQ create
749cdcd52d4SBartosz Sobczak  * @dev: Device
750cdcd52d4SBartosz Sobczak  * @cq: resource for cq
751cdcd52d4SBartosz Sobczak  */
752cdcd52d4SBartosz Sobczak static int
753cdcd52d4SBartosz Sobczak irdma_puda_cq_wqe(struct irdma_sc_dev *dev, struct irdma_sc_cq *cq)
754cdcd52d4SBartosz Sobczak {
755cdcd52d4SBartosz Sobczak 	__le64 *wqe;
756cdcd52d4SBartosz Sobczak 	struct irdma_sc_cqp *cqp;
757cdcd52d4SBartosz Sobczak 	u64 hdr;
758cdcd52d4SBartosz Sobczak 	struct irdma_ccq_cqe_info compl_info;
759cdcd52d4SBartosz Sobczak 	int status = 0;
760cdcd52d4SBartosz Sobczak 
761cdcd52d4SBartosz Sobczak 	cqp = dev->cqp;
762cdcd52d4SBartosz Sobczak 	wqe = irdma_sc_cqp_get_next_send_wqe(cqp, 0);
763cdcd52d4SBartosz Sobczak 	if (!wqe)
764cdcd52d4SBartosz Sobczak 		return -ENOSPC;
765cdcd52d4SBartosz Sobczak 
766cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_0, cq->cq_uk.cq_size);
767cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_8, RS_64_1(cq, 1));
768cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_16,
769777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMA_CQPSQ_CQ_SHADOW_READ_THRESHOLD, cq->shadow_read_threshold));
770cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_32, cq->cq_pa);
771cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_40, cq->shadow_area_pa);
772cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_56,
773777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMA_CQPSQ_TPHVAL, cq->tph_val) |
774777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMA_CQPSQ_VSIIDX, cq->vsi->vsi_idx));
775cdcd52d4SBartosz Sobczak 
776cdcd52d4SBartosz Sobczak 	hdr = cq->cq_uk.cq_id |
777777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_CREATE_CQ) |
778777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_CQ_CHKOVERFLOW, 1) |
779777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_CQ_ENCEQEMASK, 1) |
780777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_CQ_CEQIDVALID, 1) |
781777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
782cdcd52d4SBartosz Sobczak 	irdma_wmb();		/* make sure WQE is written before valid bit is set */
783cdcd52d4SBartosz Sobczak 
784cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_24, hdr);
785cdcd52d4SBartosz Sobczak 
786cdcd52d4SBartosz Sobczak 	irdma_debug_buf(dev, IRDMA_DEBUG_PUDA, "PUDA CREATE CQ", wqe,
787cdcd52d4SBartosz Sobczak 			IRDMA_CQP_WQE_SIZE * 8);
788cdcd52d4SBartosz Sobczak 	irdma_sc_cqp_post_sq(dev->cqp);
789cdcd52d4SBartosz Sobczak 	status = irdma_sc_poll_for_cqp_op_done(dev->cqp, IRDMA_CQP_OP_CREATE_CQ,
790cdcd52d4SBartosz Sobczak 					       &compl_info);
791cdcd52d4SBartosz Sobczak 	if (!status) {
792cdcd52d4SBartosz Sobczak 		struct irdma_sc_ceq *ceq = dev->ceq[0];
793cdcd52d4SBartosz Sobczak 
794cdcd52d4SBartosz Sobczak 		if (ceq && ceq->reg_cq)
795cdcd52d4SBartosz Sobczak 			status = irdma_sc_add_cq_ctx(ceq, cq);
796cdcd52d4SBartosz Sobczak 	}
797cdcd52d4SBartosz Sobczak 
798cdcd52d4SBartosz Sobczak 	return status;
799cdcd52d4SBartosz Sobczak }
800cdcd52d4SBartosz Sobczak 
801cdcd52d4SBartosz Sobczak /**
802cdcd52d4SBartosz Sobczak  * irdma_puda_cq_create - create cq for resource
803cdcd52d4SBartosz Sobczak  * @rsrc: resource for which cq to create
804cdcd52d4SBartosz Sobczak  */
805cdcd52d4SBartosz Sobczak static int
806cdcd52d4SBartosz Sobczak irdma_puda_cq_create(struct irdma_puda_rsrc *rsrc)
807cdcd52d4SBartosz Sobczak {
808cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = rsrc->dev;
809cdcd52d4SBartosz Sobczak 	struct irdma_sc_cq *cq = &rsrc->cq;
810cdcd52d4SBartosz Sobczak 	int ret = 0;
811cdcd52d4SBartosz Sobczak 	u32 cqsize;
812cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem *mem;
813cdcd52d4SBartosz Sobczak 	struct irdma_cq_init_info info = {0};
814cdcd52d4SBartosz Sobczak 	struct irdma_cq_uk_init_info *init_info = &info.cq_uk_init_info;
815cdcd52d4SBartosz Sobczak 
816cdcd52d4SBartosz Sobczak 	cq->vsi = rsrc->vsi;
817cdcd52d4SBartosz Sobczak 	cqsize = rsrc->cq_size * (sizeof(struct irdma_cqe));
818cdcd52d4SBartosz Sobczak 	rsrc->cqmem.size = cqsize + sizeof(struct irdma_cq_shadow_area);
819cdcd52d4SBartosz Sobczak 	rsrc->cqmem.va = irdma_allocate_dma_mem(dev->hw, &rsrc->cqmem,
820cdcd52d4SBartosz Sobczak 						rsrc->cqmem.size,
821cdcd52d4SBartosz Sobczak 						IRDMA_CQ0_ALIGNMENT);
822cdcd52d4SBartosz Sobczak 	if (!rsrc->cqmem.va)
823cdcd52d4SBartosz Sobczak 		return -ENOMEM;
824cdcd52d4SBartosz Sobczak 
825cdcd52d4SBartosz Sobczak 	mem = &rsrc->cqmem;
826cdcd52d4SBartosz Sobczak 	info.dev = dev;
827cdcd52d4SBartosz Sobczak 	info.type = (rsrc->type == IRDMA_PUDA_RSRC_TYPE_ILQ) ?
828cdcd52d4SBartosz Sobczak 	    IRDMA_CQ_TYPE_ILQ : IRDMA_CQ_TYPE_IEQ;
829cdcd52d4SBartosz Sobczak 	info.shadow_read_threshold = rsrc->cq_size >> 2;
830cdcd52d4SBartosz Sobczak 	info.cq_base_pa = mem->pa;
831cdcd52d4SBartosz Sobczak 	info.shadow_area_pa = mem->pa + cqsize;
832cdcd52d4SBartosz Sobczak 	init_info->cq_base = mem->va;
833cdcd52d4SBartosz Sobczak 	init_info->shadow_area = (__le64 *) ((u8 *)mem->va + cqsize);
834cdcd52d4SBartosz Sobczak 	init_info->cq_size = rsrc->cq_size;
835cdcd52d4SBartosz Sobczak 	init_info->cq_id = rsrc->cq_id;
836cdcd52d4SBartosz Sobczak 	info.ceqe_mask = true;
837cdcd52d4SBartosz Sobczak 	info.ceq_id_valid = true;
838cdcd52d4SBartosz Sobczak 	info.vsi = rsrc->vsi;
839cdcd52d4SBartosz Sobczak 
840cdcd52d4SBartosz Sobczak 	ret = irdma_sc_cq_init(cq, &info);
841cdcd52d4SBartosz Sobczak 	if (ret)
842cdcd52d4SBartosz Sobczak 		goto error;
843cdcd52d4SBartosz Sobczak 
844cdcd52d4SBartosz Sobczak 	if (rsrc->dev->ceq_valid)
845cdcd52d4SBartosz Sobczak 		ret = irdma_cqp_cq_create_cmd(dev, cq);
846cdcd52d4SBartosz Sobczak 	else
847cdcd52d4SBartosz Sobczak 		ret = irdma_puda_cq_wqe(dev, cq);
848cdcd52d4SBartosz Sobczak error:
849cdcd52d4SBartosz Sobczak 	if (ret)
850cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(dev->hw, &rsrc->cqmem);
851cdcd52d4SBartosz Sobczak 
852cdcd52d4SBartosz Sobczak 	return ret;
853cdcd52d4SBartosz Sobczak }
854cdcd52d4SBartosz Sobczak 
855cdcd52d4SBartosz Sobczak /**
856cdcd52d4SBartosz Sobczak  * irdma_puda_free_qp - free qp for resource
857cdcd52d4SBartosz Sobczak  * @rsrc: resource for which qp to free
858cdcd52d4SBartosz Sobczak  */
859cdcd52d4SBartosz Sobczak static void
860cdcd52d4SBartosz Sobczak irdma_puda_free_qp(struct irdma_puda_rsrc *rsrc)
861cdcd52d4SBartosz Sobczak {
862cdcd52d4SBartosz Sobczak 	int ret;
863cdcd52d4SBartosz Sobczak 	struct irdma_ccq_cqe_info compl_info;
864cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = rsrc->dev;
865cdcd52d4SBartosz Sobczak 
866cdcd52d4SBartosz Sobczak 	if (rsrc->dev->ceq_valid) {
867cdcd52d4SBartosz Sobczak 		irdma_cqp_qp_destroy_cmd(dev, &rsrc->qp);
868cdcd52d4SBartosz Sobczak 		rsrc->dev->ws_remove(rsrc->qp.vsi, rsrc->qp.user_pri);
869cdcd52d4SBartosz Sobczak 		return;
870cdcd52d4SBartosz Sobczak 	}
871cdcd52d4SBartosz Sobczak 
872cdcd52d4SBartosz Sobczak 	ret = irdma_sc_qp_destroy(&rsrc->qp, 0, false, true, true);
873cdcd52d4SBartosz Sobczak 	if (ret)
874cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA,
875cdcd52d4SBartosz Sobczak 			    "error puda qp destroy wqe, status = %d\n", ret);
876cdcd52d4SBartosz Sobczak 	if (!ret) {
877cdcd52d4SBartosz Sobczak 		ret = irdma_sc_poll_for_cqp_op_done(dev->cqp, IRDMA_CQP_OP_DESTROY_QP,
878cdcd52d4SBartosz Sobczak 						    &compl_info);
879cdcd52d4SBartosz Sobczak 		if (ret)
880cdcd52d4SBartosz Sobczak 			irdma_debug(dev, IRDMA_DEBUG_PUDA,
881cdcd52d4SBartosz Sobczak 				    "error puda qp destroy failed, status = %d\n",
882cdcd52d4SBartosz Sobczak 				    ret);
883cdcd52d4SBartosz Sobczak 	}
884cdcd52d4SBartosz Sobczak 	rsrc->dev->ws_remove(rsrc->qp.vsi, rsrc->qp.user_pri);
885cdcd52d4SBartosz Sobczak }
886cdcd52d4SBartosz Sobczak 
887cdcd52d4SBartosz Sobczak /**
888cdcd52d4SBartosz Sobczak  * irdma_puda_free_cq - free cq for resource
889cdcd52d4SBartosz Sobczak  * @rsrc: resource for which cq to free
890cdcd52d4SBartosz Sobczak  */
891cdcd52d4SBartosz Sobczak static void
892cdcd52d4SBartosz Sobczak irdma_puda_free_cq(struct irdma_puda_rsrc *rsrc)
893cdcd52d4SBartosz Sobczak {
894cdcd52d4SBartosz Sobczak 	int ret;
895cdcd52d4SBartosz Sobczak 	struct irdma_ccq_cqe_info compl_info;
896cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = rsrc->dev;
897cdcd52d4SBartosz Sobczak 
898cdcd52d4SBartosz Sobczak 	if (rsrc->dev->ceq_valid) {
899cdcd52d4SBartosz Sobczak 		irdma_cqp_cq_destroy_cmd(dev, &rsrc->cq);
900cdcd52d4SBartosz Sobczak 		return;
901cdcd52d4SBartosz Sobczak 	}
902cdcd52d4SBartosz Sobczak 
903cdcd52d4SBartosz Sobczak 	ret = irdma_sc_cq_destroy(&rsrc->cq, 0, true);
904cdcd52d4SBartosz Sobczak 	if (ret)
905cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "error ieq cq destroy\n");
906cdcd52d4SBartosz Sobczak 	if (!ret) {
907cdcd52d4SBartosz Sobczak 		ret = irdma_sc_poll_for_cqp_op_done(dev->cqp, IRDMA_CQP_OP_DESTROY_CQ,
908cdcd52d4SBartosz Sobczak 						    &compl_info);
909cdcd52d4SBartosz Sobczak 		if (ret)
910cdcd52d4SBartosz Sobczak 			irdma_debug(dev, IRDMA_DEBUG_PUDA,
911cdcd52d4SBartosz Sobczak 				    "error ieq qp destroy done\n");
912cdcd52d4SBartosz Sobczak 	}
913cdcd52d4SBartosz Sobczak }
914cdcd52d4SBartosz Sobczak 
915cdcd52d4SBartosz Sobczak /**
916cdcd52d4SBartosz Sobczak  * irdma_puda_dele_rsrc - delete all resources during close
917cdcd52d4SBartosz Sobczak  * @vsi: VSI structure of device
918cdcd52d4SBartosz Sobczak  * @type: type of resource to dele
919cdcd52d4SBartosz Sobczak  * @reset: true if reset chip
920cdcd52d4SBartosz Sobczak  */
921cdcd52d4SBartosz Sobczak void
922cdcd52d4SBartosz Sobczak irdma_puda_dele_rsrc(struct irdma_sc_vsi *vsi, enum puda_rsrc_type type,
923cdcd52d4SBartosz Sobczak 		     bool reset)
924cdcd52d4SBartosz Sobczak {
925cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = vsi->dev;
926cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *rsrc;
927cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf = NULL;
928cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *nextbuf = NULL;
929cdcd52d4SBartosz Sobczak 	struct irdma_virt_mem *vmem;
930cdcd52d4SBartosz Sobczak 	struct irdma_sc_ceq *ceq;
931cdcd52d4SBartosz Sobczak 
932cdcd52d4SBartosz Sobczak 	ceq = vsi->dev->ceq[0];
933cdcd52d4SBartosz Sobczak 	switch (type) {
934cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_ILQ:
935cdcd52d4SBartosz Sobczak 		rsrc = vsi->ilq;
936cdcd52d4SBartosz Sobczak 		vmem = &vsi->ilq_mem;
937cdcd52d4SBartosz Sobczak 		vsi->ilq = NULL;
938cdcd52d4SBartosz Sobczak 		if (ceq && ceq->reg_cq)
939cdcd52d4SBartosz Sobczak 			irdma_sc_remove_cq_ctx(ceq, &rsrc->cq);
940cdcd52d4SBartosz Sobczak 		break;
941cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_IEQ:
942cdcd52d4SBartosz Sobczak 		rsrc = vsi->ieq;
943cdcd52d4SBartosz Sobczak 		vmem = &vsi->ieq_mem;
944cdcd52d4SBartosz Sobczak 		vsi->ieq = NULL;
945cdcd52d4SBartosz Sobczak 		if (ceq && ceq->reg_cq)
946cdcd52d4SBartosz Sobczak 			irdma_sc_remove_cq_ctx(ceq, &rsrc->cq);
947cdcd52d4SBartosz Sobczak 		break;
948cdcd52d4SBartosz Sobczak 	default:
949cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA,
950cdcd52d4SBartosz Sobczak 			    "error resource type = 0x%x\n", type);
951cdcd52d4SBartosz Sobczak 		return;
952cdcd52d4SBartosz Sobczak 	}
953cdcd52d4SBartosz Sobczak 
954cdcd52d4SBartosz Sobczak 	spin_lock_destroy(&rsrc->bufpool_lock);
955cdcd52d4SBartosz Sobczak 	switch (rsrc->cmpl) {
956cdcd52d4SBartosz Sobczak 	case PUDA_HASH_CRC_COMPLETE:
957cdcd52d4SBartosz Sobczak 		irdma_free_hash_desc(rsrc->hash_desc);
958cdcd52d4SBartosz Sobczak 		/* fallthrough */
959cdcd52d4SBartosz Sobczak 	case PUDA_QP_CREATED:
960cdcd52d4SBartosz Sobczak 		irdma_qp_rem_qos(&rsrc->qp);
961cdcd52d4SBartosz Sobczak 
962777e472cSBartosz Sobczak 		if (!reset)
963cdcd52d4SBartosz Sobczak 			irdma_puda_free_qp(rsrc);
964cdcd52d4SBartosz Sobczak 
965cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(dev->hw, &rsrc->qpmem);
966cdcd52d4SBartosz Sobczak 		/* fallthrough */
967cdcd52d4SBartosz Sobczak 	case PUDA_CQ_CREATED:
968777e472cSBartosz Sobczak 		if (!reset)
969cdcd52d4SBartosz Sobczak 			irdma_puda_free_cq(rsrc);
970cdcd52d4SBartosz Sobczak 
971cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(dev->hw, &rsrc->cqmem);
972cdcd52d4SBartosz Sobczak 		break;
973cdcd52d4SBartosz Sobczak 	default:
974cdcd52d4SBartosz Sobczak 		irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
975cdcd52d4SBartosz Sobczak 			    "error no resources\n");
976cdcd52d4SBartosz Sobczak 		break;
977cdcd52d4SBartosz Sobczak 	}
978cdcd52d4SBartosz Sobczak 	/* Free all allocated puda buffers for both tx and rx */
979cdcd52d4SBartosz Sobczak 	buf = rsrc->alloclist;
980cdcd52d4SBartosz Sobczak 	while (buf) {
981cdcd52d4SBartosz Sobczak 		nextbuf = buf->next;
982cdcd52d4SBartosz Sobczak 		irdma_puda_dele_buf(dev, buf);
983cdcd52d4SBartosz Sobczak 		buf = nextbuf;
984cdcd52d4SBartosz Sobczak 		rsrc->alloc_buf_count--;
985cdcd52d4SBartosz Sobczak 	}
986cdcd52d4SBartosz Sobczak 
987cdcd52d4SBartosz Sobczak 	kfree(vmem->va);
988cdcd52d4SBartosz Sobczak }
989cdcd52d4SBartosz Sobczak 
990cdcd52d4SBartosz Sobczak /**
991cdcd52d4SBartosz Sobczak  * irdma_puda_allocbufs - allocate buffers for resource
992cdcd52d4SBartosz Sobczak  * @rsrc: resource for buffer allocation
993cdcd52d4SBartosz Sobczak  * @count: number of buffers to create
994cdcd52d4SBartosz Sobczak  */
995cdcd52d4SBartosz Sobczak static int
996cdcd52d4SBartosz Sobczak irdma_puda_allocbufs(struct irdma_puda_rsrc *rsrc, u32 count)
997cdcd52d4SBartosz Sobczak {
998cdcd52d4SBartosz Sobczak 	u32 i;
999cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
1000cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *nextbuf;
1001cdcd52d4SBartosz Sobczak 	struct irdma_virt_mem buf_mem;
1002cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem *dma_mem;
1003cdcd52d4SBartosz Sobczak 	bool virtdma = false;
1004cdcd52d4SBartosz Sobczak 	unsigned long flags;
1005cdcd52d4SBartosz Sobczak 
1006cdcd52d4SBartosz Sobczak 	buf_mem.size = count * sizeof(struct irdma_puda_buf);
1007777e472cSBartosz Sobczak 	buf_mem.va = kzalloc(buf_mem.size, GFP_KERNEL);
1008cdcd52d4SBartosz Sobczak 	if (!buf_mem.va) {
1009cdcd52d4SBartosz Sobczak 		irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
1010cdcd52d4SBartosz Sobczak 			    "error virt_mem for buf\n");
1011cdcd52d4SBartosz Sobczak 		rsrc->stats_buf_alloc_fail++;
1012cdcd52d4SBartosz Sobczak 		goto trysmall;
1013cdcd52d4SBartosz Sobczak 	}
1014cdcd52d4SBartosz Sobczak 
1015cdcd52d4SBartosz Sobczak 	/*
1016cdcd52d4SBartosz Sobczak 	 * Allocate the large dma chunk and setup dma attributes into first puda buffer. This is required during free
1017cdcd52d4SBartosz Sobczak 	 */
1018cdcd52d4SBartosz Sobczak 	buf = (struct irdma_puda_buf *)buf_mem.va;
1019cdcd52d4SBartosz Sobczak 	buf->mem.va = irdma_allocate_dma_mem(rsrc->dev->hw, &buf->mem,
1020cdcd52d4SBartosz Sobczak 					     rsrc->buf_size * count, 1);
1021cdcd52d4SBartosz Sobczak 	if (!buf->mem.va) {
1022cdcd52d4SBartosz Sobczak 		irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
1023cdcd52d4SBartosz Sobczak 			    "error dma_mem for buf\n");
1024cdcd52d4SBartosz Sobczak 		kfree(buf_mem.va);
1025cdcd52d4SBartosz Sobczak 		rsrc->stats_buf_alloc_fail++;
1026cdcd52d4SBartosz Sobczak 		goto trysmall;
1027cdcd52d4SBartosz Sobczak 	}
1028cdcd52d4SBartosz Sobczak 
1029cdcd52d4SBartosz Sobczak 	/*
1030cdcd52d4SBartosz Sobczak 	 * dma_mem points to start of the large DMA chunk
1031cdcd52d4SBartosz Sobczak 	 */
1032cdcd52d4SBartosz Sobczak 	dma_mem = &buf->mem;
1033cdcd52d4SBartosz Sobczak 
1034cdcd52d4SBartosz Sobczak 	spin_lock_irqsave(&rsrc->bufpool_lock, flags);
1035cdcd52d4SBartosz Sobczak 	for (i = 0; i < count; i++) {
1036cdcd52d4SBartosz Sobczak 		buf = ((struct irdma_puda_buf *)buf_mem.va) + i;
1037cdcd52d4SBartosz Sobczak 
1038cdcd52d4SBartosz Sobczak 		buf->mem.va = (char *)dma_mem->va + (i * rsrc->buf_size);
1039cdcd52d4SBartosz Sobczak 		buf->mem.pa = dma_mem->pa + (i * rsrc->buf_size);
1040cdcd52d4SBartosz Sobczak 		buf->mem.size = rsrc->buf_size;
1041cdcd52d4SBartosz Sobczak 		buf->virtdma = virtdma;
1042cdcd52d4SBartosz Sobczak 		virtdma = true;
1043cdcd52d4SBartosz Sobczak 
1044cdcd52d4SBartosz Sobczak 		buf->buf_mem.va = buf_mem.va;
1045cdcd52d4SBartosz Sobczak 		buf->buf_mem.size = buf_mem.size;
1046cdcd52d4SBartosz Sobczak 
1047cdcd52d4SBartosz Sobczak 		list_add(&buf->list, &rsrc->bufpool);
1048cdcd52d4SBartosz Sobczak 		rsrc->alloc_buf_count++;
1049cdcd52d4SBartosz Sobczak 		if (!rsrc->alloclist) {
1050cdcd52d4SBartosz Sobczak 			rsrc->alloclist = buf;
1051cdcd52d4SBartosz Sobczak 		} else {
1052cdcd52d4SBartosz Sobczak 			nextbuf = rsrc->alloclist;
1053cdcd52d4SBartosz Sobczak 			rsrc->alloclist = buf;
1054cdcd52d4SBartosz Sobczak 			buf->next = nextbuf;
1055cdcd52d4SBartosz Sobczak 		}
1056cdcd52d4SBartosz Sobczak 	}
1057cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
1058cdcd52d4SBartosz Sobczak 
1059cdcd52d4SBartosz Sobczak 	rsrc->avail_buf_count = rsrc->alloc_buf_count;
1060cdcd52d4SBartosz Sobczak 	return 0;
1061cdcd52d4SBartosz Sobczak trysmall:
1062cdcd52d4SBartosz Sobczak 	for (i = 0; i < count; i++) {
1063cdcd52d4SBartosz Sobczak 		buf = irdma_puda_alloc_buf(rsrc->dev, rsrc->buf_size);
1064cdcd52d4SBartosz Sobczak 		if (!buf) {
1065cdcd52d4SBartosz Sobczak 			rsrc->stats_buf_alloc_fail++;
1066cdcd52d4SBartosz Sobczak 			return -ENOMEM;
1067cdcd52d4SBartosz Sobczak 		}
1068cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(rsrc, buf);
1069cdcd52d4SBartosz Sobczak 		rsrc->alloc_buf_count++;
1070cdcd52d4SBartosz Sobczak 		if (!rsrc->alloclist) {
1071cdcd52d4SBartosz Sobczak 			rsrc->alloclist = buf;
1072cdcd52d4SBartosz Sobczak 		} else {
1073cdcd52d4SBartosz Sobczak 			nextbuf = rsrc->alloclist;
1074cdcd52d4SBartosz Sobczak 			rsrc->alloclist = buf;
1075cdcd52d4SBartosz Sobczak 			buf->next = nextbuf;
1076cdcd52d4SBartosz Sobczak 		}
1077cdcd52d4SBartosz Sobczak 	}
1078cdcd52d4SBartosz Sobczak 
1079cdcd52d4SBartosz Sobczak 	rsrc->avail_buf_count = rsrc->alloc_buf_count;
1080cdcd52d4SBartosz Sobczak 
1081cdcd52d4SBartosz Sobczak 	return 0;
1082cdcd52d4SBartosz Sobczak }
1083cdcd52d4SBartosz Sobczak 
1084cdcd52d4SBartosz Sobczak /**
1085cdcd52d4SBartosz Sobczak  * irdma_puda_create_rsrc - create resource (ilq or ieq)
1086cdcd52d4SBartosz Sobczak  * @vsi: sc VSI struct
1087cdcd52d4SBartosz Sobczak  * @info: resource information
1088cdcd52d4SBartosz Sobczak  */
1089cdcd52d4SBartosz Sobczak int
1090cdcd52d4SBartosz Sobczak irdma_puda_create_rsrc(struct irdma_sc_vsi *vsi,
1091cdcd52d4SBartosz Sobczak 		       struct irdma_puda_rsrc_info *info)
1092cdcd52d4SBartosz Sobczak {
1093cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = vsi->dev;
1094cdcd52d4SBartosz Sobczak 	int ret = 0;
1095cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *rsrc;
1096cdcd52d4SBartosz Sobczak 	u32 pudasize;
1097cdcd52d4SBartosz Sobczak 	u32 sqwridsize, rqwridsize;
1098cdcd52d4SBartosz Sobczak 	struct irdma_virt_mem *vmem;
1099cdcd52d4SBartosz Sobczak 
1100cdcd52d4SBartosz Sobczak 	info->count = 1;
1101cdcd52d4SBartosz Sobczak 	pudasize = sizeof(struct irdma_puda_rsrc);
1102cdcd52d4SBartosz Sobczak 	sqwridsize = info->sq_size * sizeof(struct irdma_sq_uk_wr_trk_info);
1103cdcd52d4SBartosz Sobczak 	rqwridsize = info->rq_size * 8;
1104cdcd52d4SBartosz Sobczak 	switch (info->type) {
1105cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_ILQ:
1106cdcd52d4SBartosz Sobczak 		vmem = &vsi->ilq_mem;
1107cdcd52d4SBartosz Sobczak 		break;
1108cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_IEQ:
1109cdcd52d4SBartosz Sobczak 		vmem = &vsi->ieq_mem;
1110cdcd52d4SBartosz Sobczak 		break;
1111cdcd52d4SBartosz Sobczak 	default:
1112cdcd52d4SBartosz Sobczak 		return -EOPNOTSUPP;
1113cdcd52d4SBartosz Sobczak 	}
1114cdcd52d4SBartosz Sobczak 	vmem->size = pudasize + sqwridsize + rqwridsize;
1115777e472cSBartosz Sobczak 	vmem->va = kzalloc(vmem->size, GFP_KERNEL);
1116cdcd52d4SBartosz Sobczak 	if (!vmem->va)
1117cdcd52d4SBartosz Sobczak 		return -ENOMEM;
1118cdcd52d4SBartosz Sobczak 
1119cdcd52d4SBartosz Sobczak 	rsrc = vmem->va;
1120cdcd52d4SBartosz Sobczak 	spin_lock_init(&rsrc->bufpool_lock);
1121cdcd52d4SBartosz Sobczak 	switch (info->type) {
1122cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_ILQ:
1123cdcd52d4SBartosz Sobczak 		vsi->ilq = vmem->va;
1124cdcd52d4SBartosz Sobczak 		vsi->ilq_count = info->count;
1125cdcd52d4SBartosz Sobczak 		rsrc->receive = info->receive;
1126cdcd52d4SBartosz Sobczak 		rsrc->xmit_complete = info->xmit_complete;
1127cdcd52d4SBartosz Sobczak 		break;
1128cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_IEQ:
1129cdcd52d4SBartosz Sobczak 		vsi->ieq_count = info->count;
1130cdcd52d4SBartosz Sobczak 		vsi->ieq = vmem->va;
1131cdcd52d4SBartosz Sobczak 		rsrc->receive = irdma_ieq_receive;
1132cdcd52d4SBartosz Sobczak 		rsrc->xmit_complete = irdma_ieq_tx_compl;
1133cdcd52d4SBartosz Sobczak 		break;
1134cdcd52d4SBartosz Sobczak 	default:
1135cdcd52d4SBartosz Sobczak 		return -EOPNOTSUPP;
1136cdcd52d4SBartosz Sobczak 	}
1137cdcd52d4SBartosz Sobczak 
1138cdcd52d4SBartosz Sobczak 	rsrc->type = info->type;
1139cdcd52d4SBartosz Sobczak 	rsrc->sq_wrtrk_array = (struct irdma_sq_uk_wr_trk_info *)
1140cdcd52d4SBartosz Sobczak 	    ((u8 *)vmem->va + pudasize);
1141cdcd52d4SBartosz Sobczak 	rsrc->rq_wrid_array = (u64 *)((u8 *)vmem->va + pudasize + sqwridsize);
1142cdcd52d4SBartosz Sobczak 	/* Initialize all ieq lists */
1143cdcd52d4SBartosz Sobczak 	INIT_LIST_HEAD(&rsrc->bufpool);
1144cdcd52d4SBartosz Sobczak 	INIT_LIST_HEAD(&rsrc->txpend);
1145cdcd52d4SBartosz Sobczak 
1146cdcd52d4SBartosz Sobczak 	rsrc->tx_wqe_avail_cnt = info->sq_size - 1;
1147cdcd52d4SBartosz Sobczak 	irdma_sc_pd_init(dev, &rsrc->sc_pd, info->pd_id, info->abi_ver);
1148cdcd52d4SBartosz Sobczak 	rsrc->qp_id = info->qp_id;
1149cdcd52d4SBartosz Sobczak 	rsrc->cq_id = info->cq_id;
1150cdcd52d4SBartosz Sobczak 	rsrc->sq_size = info->sq_size;
1151cdcd52d4SBartosz Sobczak 	rsrc->rq_size = info->rq_size;
1152cdcd52d4SBartosz Sobczak 	rsrc->cq_size = info->rq_size + info->sq_size;
1153cdcd52d4SBartosz Sobczak 	if (dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1154cdcd52d4SBartosz Sobczak 		if (rsrc->type == IRDMA_PUDA_RSRC_TYPE_ILQ)
1155cdcd52d4SBartosz Sobczak 			rsrc->cq_size += info->rq_size;
1156cdcd52d4SBartosz Sobczak 	}
1157cdcd52d4SBartosz Sobczak 	rsrc->buf_size = info->buf_size;
1158cdcd52d4SBartosz Sobczak 	rsrc->dev = dev;
1159cdcd52d4SBartosz Sobczak 	rsrc->vsi = vsi;
1160cdcd52d4SBartosz Sobczak 	rsrc->stats_idx = info->stats_idx;
1161cdcd52d4SBartosz Sobczak 	rsrc->stats_idx_valid = info->stats_idx_valid;
1162cdcd52d4SBartosz Sobczak 
1163cdcd52d4SBartosz Sobczak 	ret = irdma_puda_cq_create(rsrc);
1164cdcd52d4SBartosz Sobczak 	if (!ret) {
1165cdcd52d4SBartosz Sobczak 		rsrc->cmpl = PUDA_CQ_CREATED;
1166cdcd52d4SBartosz Sobczak 		ret = irdma_puda_qp_create(rsrc);
1167cdcd52d4SBartosz Sobczak 	}
1168cdcd52d4SBartosz Sobczak 	if (ret) {
1169cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA,
1170cdcd52d4SBartosz Sobczak 			    "error qp_create type=%d, status=%d\n", rsrc->type,
1171cdcd52d4SBartosz Sobczak 			    ret);
1172cdcd52d4SBartosz Sobczak 		goto error;
1173cdcd52d4SBartosz Sobczak 	}
1174cdcd52d4SBartosz Sobczak 	rsrc->cmpl = PUDA_QP_CREATED;
1175cdcd52d4SBartosz Sobczak 
1176cdcd52d4SBartosz Sobczak 	ret = irdma_puda_allocbufs(rsrc, info->tx_buf_cnt + info->rq_size);
1177cdcd52d4SBartosz Sobczak 	if (ret) {
1178cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "error alloc_buf\n");
1179cdcd52d4SBartosz Sobczak 		goto error;
1180cdcd52d4SBartosz Sobczak 	}
1181cdcd52d4SBartosz Sobczak 
1182cdcd52d4SBartosz Sobczak 	rsrc->rxq_invalid_cnt = info->rq_size;
1183cdcd52d4SBartosz Sobczak 	ret = irdma_puda_replenish_rq(rsrc, true);
1184cdcd52d4SBartosz Sobczak 	if (ret)
1185cdcd52d4SBartosz Sobczak 		goto error;
1186cdcd52d4SBartosz Sobczak 
1187cdcd52d4SBartosz Sobczak 	if (info->type == IRDMA_PUDA_RSRC_TYPE_IEQ) {
1188cdcd52d4SBartosz Sobczak 		if (!irdma_init_hash_desc(&rsrc->hash_desc)) {
1189cdcd52d4SBartosz Sobczak 			rsrc->check_crc = true;
1190cdcd52d4SBartosz Sobczak 			rsrc->cmpl = PUDA_HASH_CRC_COMPLETE;
1191cdcd52d4SBartosz Sobczak 			ret = 0;
1192cdcd52d4SBartosz Sobczak 		}
1193cdcd52d4SBartosz Sobczak 	}
1194cdcd52d4SBartosz Sobczak 
1195cdcd52d4SBartosz Sobczak 	irdma_sc_ccq_arm(&rsrc->cq);
1196cdcd52d4SBartosz Sobczak 	return ret;
1197cdcd52d4SBartosz Sobczak 
1198cdcd52d4SBartosz Sobczak error:
1199cdcd52d4SBartosz Sobczak 	irdma_puda_dele_rsrc(vsi, info->type, false);
1200cdcd52d4SBartosz Sobczak 
1201cdcd52d4SBartosz Sobczak 	return ret;
1202cdcd52d4SBartosz Sobczak }
1203cdcd52d4SBartosz Sobczak 
1204cdcd52d4SBartosz Sobczak /**
1205cdcd52d4SBartosz Sobczak  * irdma_ilq_putback_rcvbuf - ilq buffer to put back on rq
1206cdcd52d4SBartosz Sobczak  * @qp: ilq's qp resource
1207cdcd52d4SBartosz Sobczak  * @buf: puda buffer for rcv q
1208cdcd52d4SBartosz Sobczak  * @wqe_idx:  wqe index of completed rcvbuf
1209cdcd52d4SBartosz Sobczak  */
1210cdcd52d4SBartosz Sobczak static void
1211cdcd52d4SBartosz Sobczak irdma_ilq_putback_rcvbuf(struct irdma_sc_qp *qp,
1212cdcd52d4SBartosz Sobczak 			 struct irdma_puda_buf *buf, u32 wqe_idx)
1213cdcd52d4SBartosz Sobczak {
1214cdcd52d4SBartosz Sobczak 	__le64 *wqe;
1215cdcd52d4SBartosz Sobczak 	u64 offset8, offset24;
1216cdcd52d4SBartosz Sobczak 
1217cdcd52d4SBartosz Sobczak 	/* Synch buffer for use by device */
1218cdcd52d4SBartosz Sobczak 	dma_sync_single_for_device(hw_to_dev(qp->dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL);
1219cdcd52d4SBartosz Sobczak 	wqe = qp->qp_uk.rq_base[wqe_idx].elem;
1220cdcd52d4SBartosz Sobczak 	get_64bit_val(wqe, IRDMA_BYTE_24, &offset24);
1221cdcd52d4SBartosz Sobczak 	if (qp->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1222cdcd52d4SBartosz Sobczak 		get_64bit_val(wqe, IRDMA_BYTE_8, &offset8);
1223cdcd52d4SBartosz Sobczak 		if (offset24)
1224777e472cSBartosz Sobczak 			offset8 &= ~FIELD_PREP(IRDMAQPSQ_VALID, 1);
1225cdcd52d4SBartosz Sobczak 		else
1226777e472cSBartosz Sobczak 			offset8 |= FIELD_PREP(IRDMAQPSQ_VALID, 1);
1227cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_8, offset8);
1228cdcd52d4SBartosz Sobczak 		irdma_wmb();	/* make sure WQE is written before valid bit is set */
1229cdcd52d4SBartosz Sobczak 	}
1230cdcd52d4SBartosz Sobczak 	if (offset24)
1231cdcd52d4SBartosz Sobczak 		offset24 = 0;
1232cdcd52d4SBartosz Sobczak 	else
1233777e472cSBartosz Sobczak 		offset24 = FIELD_PREP(IRDMAQPSQ_VALID, 1);
1234cdcd52d4SBartosz Sobczak 
1235cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_24, offset24);
1236cdcd52d4SBartosz Sobczak }
1237cdcd52d4SBartosz Sobczak 
1238cdcd52d4SBartosz Sobczak /**
1239cdcd52d4SBartosz Sobczak  * irdma_ieq_get_fpdu_len - get length of fpdu with or without marker
1240cdcd52d4SBartosz Sobczak  * @pfpdu: pointer to fpdu
1241cdcd52d4SBartosz Sobczak  * @datap: pointer to data in the buffer
1242cdcd52d4SBartosz Sobczak  * @rcv_seq: seqnum of the data buffer
1243cdcd52d4SBartosz Sobczak  */
1244cdcd52d4SBartosz Sobczak static u16 irdma_ieq_get_fpdu_len(struct irdma_pfpdu *pfpdu, u8 *datap,
1245cdcd52d4SBartosz Sobczak 				  u32 rcv_seq){
1246cdcd52d4SBartosz Sobczak 	u32 marker_seq, end_seq, blk_start;
1247cdcd52d4SBartosz Sobczak 	u8 marker_len = pfpdu->marker_len;
1248cdcd52d4SBartosz Sobczak 	u16 total_len = 0;
1249cdcd52d4SBartosz Sobczak 	u16 fpdu_len;
1250cdcd52d4SBartosz Sobczak 
1251cdcd52d4SBartosz Sobczak 	blk_start = (pfpdu->rcv_start_seq - rcv_seq) & (IRDMA_MRK_BLK_SZ - 1);
1252cdcd52d4SBartosz Sobczak 	if (!blk_start) {
1253cdcd52d4SBartosz Sobczak 		total_len = marker_len;
1254cdcd52d4SBartosz Sobczak 		marker_seq = rcv_seq + IRDMA_MRK_BLK_SZ;
1255cdcd52d4SBartosz Sobczak 		if (marker_len && *(u32 *)datap)
1256cdcd52d4SBartosz Sobczak 			return 0;
1257cdcd52d4SBartosz Sobczak 	} else {
1258cdcd52d4SBartosz Sobczak 		marker_seq = rcv_seq + blk_start;
1259cdcd52d4SBartosz Sobczak 	}
1260cdcd52d4SBartosz Sobczak 
1261cdcd52d4SBartosz Sobczak 	datap += total_len;
1262cdcd52d4SBartosz Sobczak 	fpdu_len = IRDMA_NTOHS(*(__be16 *) datap);
1263cdcd52d4SBartosz Sobczak 	fpdu_len += IRDMA_IEQ_MPA_FRAMING;
1264cdcd52d4SBartosz Sobczak 	fpdu_len = (fpdu_len + 3) & 0xfffc;
1265cdcd52d4SBartosz Sobczak 
1266cdcd52d4SBartosz Sobczak 	if (fpdu_len > pfpdu->max_fpdu_data)
1267cdcd52d4SBartosz Sobczak 		return 0;
1268cdcd52d4SBartosz Sobczak 
1269cdcd52d4SBartosz Sobczak 	total_len += fpdu_len;
1270cdcd52d4SBartosz Sobczak 	end_seq = rcv_seq + total_len;
1271cdcd52d4SBartosz Sobczak 	while ((int)(marker_seq - end_seq) < 0) {
1272cdcd52d4SBartosz Sobczak 		total_len += marker_len;
1273cdcd52d4SBartosz Sobczak 		end_seq += marker_len;
1274cdcd52d4SBartosz Sobczak 		marker_seq += IRDMA_MRK_BLK_SZ;
1275cdcd52d4SBartosz Sobczak 	}
1276cdcd52d4SBartosz Sobczak 
1277cdcd52d4SBartosz Sobczak 	return total_len;
1278cdcd52d4SBartosz Sobczak }
1279cdcd52d4SBartosz Sobczak 
1280cdcd52d4SBartosz Sobczak /**
1281cdcd52d4SBartosz Sobczak  * irdma_ieq_copy_to_txbuf - copydata from rcv buf to tx buf
1282cdcd52d4SBartosz Sobczak  * @buf: rcv buffer with partial
1283cdcd52d4SBartosz Sobczak  * @txbuf: tx buffer for sending back
1284cdcd52d4SBartosz Sobczak  * @buf_offset: rcv buffer offset to copy from
1285cdcd52d4SBartosz Sobczak  * @txbuf_offset: at offset in tx buf to copy
1286cdcd52d4SBartosz Sobczak  * @len: length of data to copy
1287cdcd52d4SBartosz Sobczak  */
1288cdcd52d4SBartosz Sobczak static void
1289cdcd52d4SBartosz Sobczak irdma_ieq_copy_to_txbuf(struct irdma_puda_buf *buf,
1290cdcd52d4SBartosz Sobczak 			struct irdma_puda_buf *txbuf,
1291cdcd52d4SBartosz Sobczak 			u16 buf_offset, u32 txbuf_offset, u32 len)
1292cdcd52d4SBartosz Sobczak {
1293cdcd52d4SBartosz Sobczak 	void *mem1 = (u8 *)buf->mem.va + buf_offset;
1294cdcd52d4SBartosz Sobczak 	void *mem2 = (u8 *)txbuf->mem.va + txbuf_offset;
1295cdcd52d4SBartosz Sobczak 
1296cdcd52d4SBartosz Sobczak 	irdma_memcpy(mem2, mem1, len);
1297cdcd52d4SBartosz Sobczak }
1298cdcd52d4SBartosz Sobczak 
1299cdcd52d4SBartosz Sobczak /**
1300cdcd52d4SBartosz Sobczak  * irdma_ieq_setup_tx_buf - setup tx buffer for partial handling
1301cdcd52d4SBartosz Sobczak  * @buf: reeive buffer with partial
1302cdcd52d4SBartosz Sobczak  * @txbuf: buffer to prepare
1303cdcd52d4SBartosz Sobczak  */
1304cdcd52d4SBartosz Sobczak static void
1305cdcd52d4SBartosz Sobczak irdma_ieq_setup_tx_buf(struct irdma_puda_buf *buf,
1306cdcd52d4SBartosz Sobczak 		       struct irdma_puda_buf *txbuf)
1307cdcd52d4SBartosz Sobczak {
1308cdcd52d4SBartosz Sobczak 	txbuf->tcphlen = buf->tcphlen;
1309cdcd52d4SBartosz Sobczak 	txbuf->ipv4 = buf->ipv4;
1310cdcd52d4SBartosz Sobczak 
1311cdcd52d4SBartosz Sobczak 	if (buf->vsi->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1312cdcd52d4SBartosz Sobczak 		txbuf->hdrlen = txbuf->tcphlen;
1313cdcd52d4SBartosz Sobczak 		irdma_ieq_copy_to_txbuf(buf, txbuf, IRDMA_TCP_OFFSET, 0,
1314cdcd52d4SBartosz Sobczak 					txbuf->hdrlen);
1315cdcd52d4SBartosz Sobczak 	} else {
1316cdcd52d4SBartosz Sobczak 		txbuf->maclen = buf->maclen;
1317cdcd52d4SBartosz Sobczak 		txbuf->hdrlen = buf->hdrlen;
1318cdcd52d4SBartosz Sobczak 		irdma_ieq_copy_to_txbuf(buf, txbuf, 0, 0, buf->hdrlen);
1319cdcd52d4SBartosz Sobczak 	}
1320cdcd52d4SBartosz Sobczak }
1321cdcd52d4SBartosz Sobczak 
1322cdcd52d4SBartosz Sobczak /**
1323cdcd52d4SBartosz Sobczak  * irdma_ieq_check_first_buf - check if rcv buffer's seq is in range
1324cdcd52d4SBartosz Sobczak  * @buf: receive exception buffer
1325cdcd52d4SBartosz Sobczak  * @fps: first partial sequence number
1326cdcd52d4SBartosz Sobczak  */
1327cdcd52d4SBartosz Sobczak static void
1328cdcd52d4SBartosz Sobczak irdma_ieq_check_first_buf(struct irdma_puda_buf *buf, u32 fps)
1329cdcd52d4SBartosz Sobczak {
1330cdcd52d4SBartosz Sobczak 	u32 offset;
1331cdcd52d4SBartosz Sobczak 
1332cdcd52d4SBartosz Sobczak 	if (buf->seqnum < fps) {
1333cdcd52d4SBartosz Sobczak 		offset = fps - buf->seqnum;
1334cdcd52d4SBartosz Sobczak 		if (offset > buf->datalen)
1335cdcd52d4SBartosz Sobczak 			return;
1336cdcd52d4SBartosz Sobczak 		buf->data += offset;
1337cdcd52d4SBartosz Sobczak 		buf->datalen -= (u16)offset;
1338cdcd52d4SBartosz Sobczak 		buf->seqnum = fps;
1339cdcd52d4SBartosz Sobczak 	}
1340cdcd52d4SBartosz Sobczak }
1341cdcd52d4SBartosz Sobczak 
1342cdcd52d4SBartosz Sobczak /**
1343cdcd52d4SBartosz Sobczak  * irdma_ieq_compl_pfpdu - write txbuf with full fpdu
1344cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1345cdcd52d4SBartosz Sobczak  * @rxlist: ieq's received buffer list
1346cdcd52d4SBartosz Sobczak  * @pbufl: temporary list for buffers for fpddu
1347cdcd52d4SBartosz Sobczak  * @txbuf: tx buffer for fpdu
1348cdcd52d4SBartosz Sobczak  * @fpdu_len: total length of fpdu
1349cdcd52d4SBartosz Sobczak  */
1350cdcd52d4SBartosz Sobczak static void
1351cdcd52d4SBartosz Sobczak irdma_ieq_compl_pfpdu(struct irdma_puda_rsrc *ieq,
1352cdcd52d4SBartosz Sobczak 		      struct list_head *rxlist,
1353cdcd52d4SBartosz Sobczak 		      struct list_head *pbufl,
1354cdcd52d4SBartosz Sobczak 		      struct irdma_puda_buf *txbuf, u16 fpdu_len)
1355cdcd52d4SBartosz Sobczak {
1356cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
1357cdcd52d4SBartosz Sobczak 	u32 nextseqnum;
1358cdcd52d4SBartosz Sobczak 	u16 txoffset, bufoffset;
1359cdcd52d4SBartosz Sobczak 
1360cdcd52d4SBartosz Sobczak 	buf = irdma_puda_get_listbuf(pbufl);
1361cdcd52d4SBartosz Sobczak 	if (!buf)
1362cdcd52d4SBartosz Sobczak 		return;
1363cdcd52d4SBartosz Sobczak 
1364cdcd52d4SBartosz Sobczak 	nextseqnum = buf->seqnum + fpdu_len;
1365cdcd52d4SBartosz Sobczak 	irdma_ieq_setup_tx_buf(buf, txbuf);
1366cdcd52d4SBartosz Sobczak 	if (buf->vsi->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1367cdcd52d4SBartosz Sobczak 		txoffset = txbuf->hdrlen;
1368cdcd52d4SBartosz Sobczak 		txbuf->totallen = txbuf->hdrlen + fpdu_len;
1369cdcd52d4SBartosz Sobczak 		txbuf->data = (u8 *)txbuf->mem.va + txoffset;
1370cdcd52d4SBartosz Sobczak 	} else {
1371cdcd52d4SBartosz Sobczak 		txoffset = buf->hdrlen;
1372cdcd52d4SBartosz Sobczak 		txbuf->totallen = buf->hdrlen + fpdu_len;
1373cdcd52d4SBartosz Sobczak 		txbuf->data = (u8 *)txbuf->mem.va + buf->hdrlen;
1374cdcd52d4SBartosz Sobczak 	}
1375cdcd52d4SBartosz Sobczak 	bufoffset = (u16)(buf->data - (u8 *)buf->mem.va);
1376cdcd52d4SBartosz Sobczak 
1377cdcd52d4SBartosz Sobczak 	do {
1378cdcd52d4SBartosz Sobczak 		if (buf->datalen >= fpdu_len) {
1379cdcd52d4SBartosz Sobczak 			/* copied full fpdu */
1380cdcd52d4SBartosz Sobczak 			irdma_ieq_copy_to_txbuf(buf, txbuf, bufoffset, txoffset,
1381cdcd52d4SBartosz Sobczak 						fpdu_len);
1382cdcd52d4SBartosz Sobczak 			buf->datalen -= fpdu_len;
1383cdcd52d4SBartosz Sobczak 			buf->data += fpdu_len;
1384cdcd52d4SBartosz Sobczak 			buf->seqnum = nextseqnum;
1385cdcd52d4SBartosz Sobczak 			break;
1386cdcd52d4SBartosz Sobczak 		}
1387cdcd52d4SBartosz Sobczak 		/* copy partial fpdu */
1388cdcd52d4SBartosz Sobczak 		irdma_ieq_copy_to_txbuf(buf, txbuf, bufoffset, txoffset,
1389cdcd52d4SBartosz Sobczak 					buf->datalen);
1390cdcd52d4SBartosz Sobczak 		txoffset += buf->datalen;
1391cdcd52d4SBartosz Sobczak 		fpdu_len -= buf->datalen;
1392cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, buf);
1393cdcd52d4SBartosz Sobczak 		buf = irdma_puda_get_listbuf(pbufl);
1394cdcd52d4SBartosz Sobczak 		if (!buf)
1395cdcd52d4SBartosz Sobczak 			return;
1396cdcd52d4SBartosz Sobczak 
1397cdcd52d4SBartosz Sobczak 		bufoffset = (u16)(buf->data - (u8 *)buf->mem.va);
1398cdcd52d4SBartosz Sobczak 	} while (1);
1399cdcd52d4SBartosz Sobczak 
1400cdcd52d4SBartosz Sobczak 	/* last buffer on the list */
1401cdcd52d4SBartosz Sobczak 	if (buf->datalen)
1402cdcd52d4SBartosz Sobczak 		list_add(&buf->list, rxlist);
1403cdcd52d4SBartosz Sobczak 	else
1404cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, buf);
1405cdcd52d4SBartosz Sobczak }
1406cdcd52d4SBartosz Sobczak 
1407cdcd52d4SBartosz Sobczak /**
1408cdcd52d4SBartosz Sobczak  * irdma_ieq_create_pbufl - create buffer list for single fpdu
1409cdcd52d4SBartosz Sobczak  * @pfpdu: pointer to fpdu
1410cdcd52d4SBartosz Sobczak  * @rxlist: resource list for receive ieq buffes
1411cdcd52d4SBartosz Sobczak  * @pbufl: temp. list for buffers for fpddu
1412cdcd52d4SBartosz Sobczak  * @buf: first receive buffer
1413cdcd52d4SBartosz Sobczak  * @fpdu_len: total length of fpdu
1414cdcd52d4SBartosz Sobczak  */
1415cdcd52d4SBartosz Sobczak static int
1416cdcd52d4SBartosz Sobczak irdma_ieq_create_pbufl(struct irdma_pfpdu *pfpdu,
1417cdcd52d4SBartosz Sobczak 		       struct list_head *rxlist,
1418cdcd52d4SBartosz Sobczak 		       struct list_head *pbufl,
1419cdcd52d4SBartosz Sobczak 		       struct irdma_puda_buf *buf, u16 fpdu_len)
1420cdcd52d4SBartosz Sobczak {
1421cdcd52d4SBartosz Sobczak 	int status = 0;
1422cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *nextbuf;
1423cdcd52d4SBartosz Sobczak 	u32 nextseqnum;
1424cdcd52d4SBartosz Sobczak 	u16 plen = fpdu_len - buf->datalen;
1425cdcd52d4SBartosz Sobczak 	bool done = false;
1426cdcd52d4SBartosz Sobczak 
1427cdcd52d4SBartosz Sobczak 	nextseqnum = buf->seqnum + buf->datalen;
1428cdcd52d4SBartosz Sobczak 	do {
1429cdcd52d4SBartosz Sobczak 		nextbuf = irdma_puda_get_listbuf(rxlist);
1430cdcd52d4SBartosz Sobczak 		if (!nextbuf) {
1431cdcd52d4SBartosz Sobczak 			status = -ENOBUFS;
1432cdcd52d4SBartosz Sobczak 			break;
1433cdcd52d4SBartosz Sobczak 		}
1434cdcd52d4SBartosz Sobczak 		list_add_tail(&nextbuf->list, pbufl);
1435cdcd52d4SBartosz Sobczak 		if (nextbuf->seqnum != nextseqnum) {
1436cdcd52d4SBartosz Sobczak 			pfpdu->bad_seq_num++;
1437cdcd52d4SBartosz Sobczak 			status = -ERANGE;
1438cdcd52d4SBartosz Sobczak 			break;
1439cdcd52d4SBartosz Sobczak 		}
1440cdcd52d4SBartosz Sobczak 		if (nextbuf->datalen >= plen) {
1441cdcd52d4SBartosz Sobczak 			done = true;
1442cdcd52d4SBartosz Sobczak 		} else {
1443cdcd52d4SBartosz Sobczak 			plen -= nextbuf->datalen;
1444cdcd52d4SBartosz Sobczak 			nextseqnum = nextbuf->seqnum + nextbuf->datalen;
1445cdcd52d4SBartosz Sobczak 		}
1446cdcd52d4SBartosz Sobczak 
1447cdcd52d4SBartosz Sobczak 	} while (!done);
1448cdcd52d4SBartosz Sobczak 
1449cdcd52d4SBartosz Sobczak 	return status;
1450cdcd52d4SBartosz Sobczak }
1451cdcd52d4SBartosz Sobczak 
1452cdcd52d4SBartosz Sobczak /**
1453cdcd52d4SBartosz Sobczak  * irdma_ieq_handle_partial - process partial fpdu buffer
1454cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1455cdcd52d4SBartosz Sobczak  * @pfpdu: partial management per user qp
1456cdcd52d4SBartosz Sobczak  * @buf: receive buffer
1457cdcd52d4SBartosz Sobczak  * @fpdu_len: fpdu len in the buffer
1458cdcd52d4SBartosz Sobczak  */
1459cdcd52d4SBartosz Sobczak static int
1460cdcd52d4SBartosz Sobczak irdma_ieq_handle_partial(struct irdma_puda_rsrc *ieq,
1461cdcd52d4SBartosz Sobczak 			 struct irdma_pfpdu *pfpdu,
1462cdcd52d4SBartosz Sobczak 			 struct irdma_puda_buf *buf, u16 fpdu_len)
1463cdcd52d4SBartosz Sobczak {
1464cdcd52d4SBartosz Sobczak 	int status = 0;
1465cdcd52d4SBartosz Sobczak 	u8 *crcptr;
1466cdcd52d4SBartosz Sobczak 	u32 mpacrc;
1467cdcd52d4SBartosz Sobczak 	u32 seqnum = buf->seqnum;
1468cdcd52d4SBartosz Sobczak 	struct list_head pbufl;	/* partial buffer list */
1469cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *txbuf = NULL;
1470cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1471cdcd52d4SBartosz Sobczak 
1472cdcd52d4SBartosz Sobczak 	ieq->partials_handled++;
1473cdcd52d4SBartosz Sobczak 
1474cdcd52d4SBartosz Sobczak 	INIT_LIST_HEAD(&pbufl);
1475cdcd52d4SBartosz Sobczak 	list_add(&buf->list, &pbufl);
1476cdcd52d4SBartosz Sobczak 
1477cdcd52d4SBartosz Sobczak 	status = irdma_ieq_create_pbufl(pfpdu, rxlist, &pbufl, buf, fpdu_len);
1478cdcd52d4SBartosz Sobczak 	if (status)
1479cdcd52d4SBartosz Sobczak 		goto error;
1480cdcd52d4SBartosz Sobczak 
1481cdcd52d4SBartosz Sobczak 	txbuf = irdma_puda_get_bufpool(ieq);
1482cdcd52d4SBartosz Sobczak 	if (!txbuf) {
1483cdcd52d4SBartosz Sobczak 		pfpdu->no_tx_bufs++;
1484cdcd52d4SBartosz Sobczak 		status = -ENOBUFS;
1485cdcd52d4SBartosz Sobczak 		goto error;
1486cdcd52d4SBartosz Sobczak 	}
1487cdcd52d4SBartosz Sobczak 
1488cdcd52d4SBartosz Sobczak 	irdma_ieq_compl_pfpdu(ieq, rxlist, &pbufl, txbuf, fpdu_len);
1489cdcd52d4SBartosz Sobczak 	irdma_ieq_update_tcpip_info(txbuf, fpdu_len, seqnum);
1490cdcd52d4SBartosz Sobczak 
1491cdcd52d4SBartosz Sobczak 	crcptr = txbuf->data + fpdu_len - 4;
1492cdcd52d4SBartosz Sobczak 	mpacrc = *(u32 *)crcptr;
1493cdcd52d4SBartosz Sobczak 	if (ieq->check_crc) {
1494cdcd52d4SBartosz Sobczak 		status = irdma_ieq_check_mpacrc(ieq->hash_desc, txbuf->data,
1495cdcd52d4SBartosz Sobczak 						(fpdu_len - 4), mpacrc);
1496cdcd52d4SBartosz Sobczak 		if (status) {
1497cdcd52d4SBartosz Sobczak 			irdma_debug(ieq->dev, IRDMA_DEBUG_IEQ,
1498cdcd52d4SBartosz Sobczak 				    "error bad crc\n");
1499cdcd52d4SBartosz Sobczak 			pfpdu->mpa_crc_err = true;
1500cdcd52d4SBartosz Sobczak 			goto error;
1501cdcd52d4SBartosz Sobczak 		}
1502cdcd52d4SBartosz Sobczak 	}
1503cdcd52d4SBartosz Sobczak 
1504cdcd52d4SBartosz Sobczak 	irdma_debug_buf(ieq->dev, IRDMA_DEBUG_IEQ, "IEQ TX BUFFER",
1505cdcd52d4SBartosz Sobczak 			txbuf->mem.va, txbuf->totallen);
1506cdcd52d4SBartosz Sobczak 	if (ieq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
1507cdcd52d4SBartosz Sobczak 		txbuf->ah_id = pfpdu->ah->ah_info.ah_idx;
1508cdcd52d4SBartosz Sobczak 	txbuf->do_lpb = true;
1509cdcd52d4SBartosz Sobczak 	irdma_puda_send_buf(ieq, txbuf);
1510cdcd52d4SBartosz Sobczak 	pfpdu->rcv_nxt = seqnum + fpdu_len;
1511cdcd52d4SBartosz Sobczak 	return status;
1512cdcd52d4SBartosz Sobczak 
1513cdcd52d4SBartosz Sobczak error:
1514cdcd52d4SBartosz Sobczak 	while (!list_empty(&pbufl)) {
1515cdcd52d4SBartosz Sobczak 		buf = (struct irdma_puda_buf *)(&pbufl)->prev;
1516*35105900SBartosz Sobczak 		list_move(&buf->list, rxlist);
1517cdcd52d4SBartosz Sobczak 	}
1518cdcd52d4SBartosz Sobczak 	if (txbuf)
1519cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, txbuf);
1520cdcd52d4SBartosz Sobczak 
1521cdcd52d4SBartosz Sobczak 	return status;
1522cdcd52d4SBartosz Sobczak }
1523cdcd52d4SBartosz Sobczak 
1524cdcd52d4SBartosz Sobczak /**
1525cdcd52d4SBartosz Sobczak  * irdma_ieq_process_buf - process buffer rcvd for ieq
1526cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1527cdcd52d4SBartosz Sobczak  * @pfpdu: partial management per user qp
1528cdcd52d4SBartosz Sobczak  * @buf: receive buffer
1529cdcd52d4SBartosz Sobczak  */
1530cdcd52d4SBartosz Sobczak static int
1531cdcd52d4SBartosz Sobczak irdma_ieq_process_buf(struct irdma_puda_rsrc *ieq,
1532cdcd52d4SBartosz Sobczak 		      struct irdma_pfpdu *pfpdu,
1533cdcd52d4SBartosz Sobczak 		      struct irdma_puda_buf *buf)
1534cdcd52d4SBartosz Sobczak {
1535cdcd52d4SBartosz Sobczak 	u16 fpdu_len = 0;
1536cdcd52d4SBartosz Sobczak 	u16 datalen = buf->datalen;
1537cdcd52d4SBartosz Sobczak 	u8 *datap = buf->data;
1538cdcd52d4SBartosz Sobczak 	u8 *crcptr;
1539cdcd52d4SBartosz Sobczak 	u16 ioffset = 0;
1540cdcd52d4SBartosz Sobczak 	u32 mpacrc;
1541cdcd52d4SBartosz Sobczak 	u32 seqnum = buf->seqnum;
1542cdcd52d4SBartosz Sobczak 	u16 len = 0;
1543cdcd52d4SBartosz Sobczak 	u16 full = 0;
1544cdcd52d4SBartosz Sobczak 	bool partial = false;
1545cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *txbuf;
1546cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1547cdcd52d4SBartosz Sobczak 	int ret = 0;
1548cdcd52d4SBartosz Sobczak 
1549cdcd52d4SBartosz Sobczak 	ioffset = (u16)(buf->data - (u8 *)buf->mem.va);
1550cdcd52d4SBartosz Sobczak 	while (datalen) {
1551cdcd52d4SBartosz Sobczak 		fpdu_len = irdma_ieq_get_fpdu_len(pfpdu, datap, buf->seqnum);
1552cdcd52d4SBartosz Sobczak 		if (!fpdu_len) {
1553cdcd52d4SBartosz Sobczak 			irdma_debug(ieq->dev, IRDMA_DEBUG_IEQ,
1554cdcd52d4SBartosz Sobczak 				    "error bad fpdu len\n");
1555cdcd52d4SBartosz Sobczak 			list_add(&buf->list, rxlist);
1556cdcd52d4SBartosz Sobczak 			pfpdu->mpa_crc_err = true;
1557cdcd52d4SBartosz Sobczak 			return -EINVAL;
1558cdcd52d4SBartosz Sobczak 		}
1559cdcd52d4SBartosz Sobczak 
1560cdcd52d4SBartosz Sobczak 		if (datalen < fpdu_len) {
1561cdcd52d4SBartosz Sobczak 			partial = true;
1562cdcd52d4SBartosz Sobczak 			break;
1563cdcd52d4SBartosz Sobczak 		}
1564cdcd52d4SBartosz Sobczak 		crcptr = datap + fpdu_len - 4;
1565cdcd52d4SBartosz Sobczak 		mpacrc = *(u32 *)crcptr;
1566cdcd52d4SBartosz Sobczak 		if (ieq->check_crc)
1567cdcd52d4SBartosz Sobczak 			ret = irdma_ieq_check_mpacrc(ieq->hash_desc, datap,
1568cdcd52d4SBartosz Sobczak 						     fpdu_len - 4, mpacrc);
1569cdcd52d4SBartosz Sobczak 		if (ret) {
1570cdcd52d4SBartosz Sobczak 			list_add(&buf->list, rxlist);
1571cdcd52d4SBartosz Sobczak 			irdma_debug(ieq->dev, IRDMA_DEBUG_ERR,
1572cdcd52d4SBartosz Sobczak 				    "IRDMA_ERR_MPA_CRC\n");
1573cdcd52d4SBartosz Sobczak 			pfpdu->mpa_crc_err = true;
1574cdcd52d4SBartosz Sobczak 			return ret;
1575cdcd52d4SBartosz Sobczak 		}
1576cdcd52d4SBartosz Sobczak 		full++;
1577cdcd52d4SBartosz Sobczak 		pfpdu->fpdu_processed++;
1578cdcd52d4SBartosz Sobczak 		ieq->fpdu_processed++;
1579cdcd52d4SBartosz Sobczak 		datap += fpdu_len;
1580cdcd52d4SBartosz Sobczak 		len += fpdu_len;
1581cdcd52d4SBartosz Sobczak 		datalen -= fpdu_len;
1582cdcd52d4SBartosz Sobczak 	}
1583cdcd52d4SBartosz Sobczak 	if (full) {
1584cdcd52d4SBartosz Sobczak 		/* copy full pdu's in the txbuf and send them out */
1585cdcd52d4SBartosz Sobczak 		txbuf = irdma_puda_get_bufpool(ieq);
1586cdcd52d4SBartosz Sobczak 		if (!txbuf) {
1587cdcd52d4SBartosz Sobczak 			pfpdu->no_tx_bufs++;
1588cdcd52d4SBartosz Sobczak 			list_add(&buf->list, rxlist);
1589cdcd52d4SBartosz Sobczak 			return -ENOBUFS;
1590cdcd52d4SBartosz Sobczak 		}
1591cdcd52d4SBartosz Sobczak 		/* modify txbuf's buffer header */
1592cdcd52d4SBartosz Sobczak 		irdma_ieq_setup_tx_buf(buf, txbuf);
1593cdcd52d4SBartosz Sobczak 		/* copy full fpdu's to new buffer */
1594cdcd52d4SBartosz Sobczak 		if (ieq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1595cdcd52d4SBartosz Sobczak 			irdma_ieq_copy_to_txbuf(buf, txbuf, ioffset,
1596cdcd52d4SBartosz Sobczak 						txbuf->hdrlen, len);
1597cdcd52d4SBartosz Sobczak 			txbuf->totallen = txbuf->hdrlen + len;
1598cdcd52d4SBartosz Sobczak 			txbuf->ah_id = pfpdu->ah->ah_info.ah_idx;
1599cdcd52d4SBartosz Sobczak 		} else {
1600cdcd52d4SBartosz Sobczak 			irdma_ieq_copy_to_txbuf(buf, txbuf, ioffset,
1601cdcd52d4SBartosz Sobczak 						buf->hdrlen, len);
1602cdcd52d4SBartosz Sobczak 			txbuf->totallen = buf->hdrlen + len;
1603cdcd52d4SBartosz Sobczak 		}
1604cdcd52d4SBartosz Sobczak 		irdma_ieq_update_tcpip_info(txbuf, len, buf->seqnum);
1605cdcd52d4SBartosz Sobczak 		irdma_debug_buf(ieq->dev, IRDMA_DEBUG_IEQ, "IEQ TX BUFFER",
1606cdcd52d4SBartosz Sobczak 				txbuf->mem.va, txbuf->totallen);
1607cdcd52d4SBartosz Sobczak 		txbuf->do_lpb = true;
1608cdcd52d4SBartosz Sobczak 		irdma_puda_send_buf(ieq, txbuf);
1609cdcd52d4SBartosz Sobczak 
1610cdcd52d4SBartosz Sobczak 		if (!datalen) {
1611cdcd52d4SBartosz Sobczak 			pfpdu->rcv_nxt = buf->seqnum + len;
1612cdcd52d4SBartosz Sobczak 			irdma_puda_ret_bufpool(ieq, buf);
1613cdcd52d4SBartosz Sobczak 			return 0;
1614cdcd52d4SBartosz Sobczak 		}
1615cdcd52d4SBartosz Sobczak 		buf->data = datap;
1616cdcd52d4SBartosz Sobczak 		buf->seqnum = seqnum + len;
1617cdcd52d4SBartosz Sobczak 		buf->datalen = datalen;
1618cdcd52d4SBartosz Sobczak 		pfpdu->rcv_nxt = buf->seqnum;
1619cdcd52d4SBartosz Sobczak 	}
1620cdcd52d4SBartosz Sobczak 	if (partial)
1621cdcd52d4SBartosz Sobczak 		return irdma_ieq_handle_partial(ieq, pfpdu, buf, fpdu_len);
1622cdcd52d4SBartosz Sobczak 
1623cdcd52d4SBartosz Sobczak 	return 0;
1624cdcd52d4SBartosz Sobczak }
1625cdcd52d4SBartosz Sobczak 
1626cdcd52d4SBartosz Sobczak /**
1627cdcd52d4SBartosz Sobczak  * irdma_ieq_process_fpdus - process fpdu's buffers on its list
1628cdcd52d4SBartosz Sobczak  * @qp: qp for which partial fpdus
1629cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1630cdcd52d4SBartosz Sobczak  */
1631cdcd52d4SBartosz Sobczak void
1632cdcd52d4SBartosz Sobczak irdma_ieq_process_fpdus(struct irdma_sc_qp *qp,
1633cdcd52d4SBartosz Sobczak 			struct irdma_puda_rsrc *ieq)
1634cdcd52d4SBartosz Sobczak {
1635cdcd52d4SBartosz Sobczak 	struct irdma_pfpdu *pfpdu = &qp->pfpdu;
1636cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1637cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
1638cdcd52d4SBartosz Sobczak 	int status;
1639cdcd52d4SBartosz Sobczak 
1640cdcd52d4SBartosz Sobczak 	do {
1641cdcd52d4SBartosz Sobczak 		if (list_empty(rxlist))
1642cdcd52d4SBartosz Sobczak 			break;
1643cdcd52d4SBartosz Sobczak 		buf = irdma_puda_get_listbuf(rxlist);
1644cdcd52d4SBartosz Sobczak 		if (!buf) {
1645cdcd52d4SBartosz Sobczak 			irdma_debug(ieq->dev, IRDMA_DEBUG_IEQ,
1646cdcd52d4SBartosz Sobczak 				    "error no buf\n");
1647cdcd52d4SBartosz Sobczak 			break;
1648cdcd52d4SBartosz Sobczak 		}
1649cdcd52d4SBartosz Sobczak 		if (buf->seqnum != pfpdu->rcv_nxt) {
1650cdcd52d4SBartosz Sobczak 			/* This could be out of order or missing packet */
1651cdcd52d4SBartosz Sobczak 			pfpdu->out_of_order++;
1652cdcd52d4SBartosz Sobczak 			list_add(&buf->list, rxlist);
1653cdcd52d4SBartosz Sobczak 			break;
1654cdcd52d4SBartosz Sobczak 		}
1655cdcd52d4SBartosz Sobczak 		/* keep processing buffers from the head of the list */
1656cdcd52d4SBartosz Sobczak 		status = irdma_ieq_process_buf(ieq, pfpdu, buf);
1657cdcd52d4SBartosz Sobczak 		if (status && pfpdu->mpa_crc_err) {
1658cdcd52d4SBartosz Sobczak 			while (!list_empty(rxlist)) {
1659cdcd52d4SBartosz Sobczak 				buf = irdma_puda_get_listbuf(rxlist);
1660cdcd52d4SBartosz Sobczak 				irdma_puda_ret_bufpool(ieq, buf);
1661cdcd52d4SBartosz Sobczak 				pfpdu->crc_err++;
1662cdcd52d4SBartosz Sobczak 				ieq->crc_err++;
1663cdcd52d4SBartosz Sobczak 			}
1664cdcd52d4SBartosz Sobczak 			/* create CQP for AE */
1665cdcd52d4SBartosz Sobczak 			irdma_ieq_mpa_crc_ae(ieq->dev, qp);
1666cdcd52d4SBartosz Sobczak 		}
1667cdcd52d4SBartosz Sobczak 	} while (!status);
1668cdcd52d4SBartosz Sobczak }
1669cdcd52d4SBartosz Sobczak 
1670cdcd52d4SBartosz Sobczak /**
1671cdcd52d4SBartosz Sobczak  * irdma_ieq_create_ah - create an address handle for IEQ
1672cdcd52d4SBartosz Sobczak  * @qp: qp pointer
1673cdcd52d4SBartosz Sobczak  * @buf: buf received on IEQ used to create AH
1674cdcd52d4SBartosz Sobczak  */
1675cdcd52d4SBartosz Sobczak static int
1676cdcd52d4SBartosz Sobczak irdma_ieq_create_ah(struct irdma_sc_qp *qp, struct irdma_puda_buf *buf)
1677cdcd52d4SBartosz Sobczak {
1678cdcd52d4SBartosz Sobczak 	struct irdma_ah_info ah_info = {0};
1679cdcd52d4SBartosz Sobczak 
1680cdcd52d4SBartosz Sobczak 	qp->pfpdu.ah_buf = buf;
1681cdcd52d4SBartosz Sobczak 	irdma_puda_ieq_get_ah_info(qp, &ah_info);
1682cdcd52d4SBartosz Sobczak 	return irdma_puda_create_ah(qp->vsi->dev, &ah_info, false,
1683cdcd52d4SBartosz Sobczak 				    IRDMA_PUDA_RSRC_TYPE_IEQ, qp,
1684cdcd52d4SBartosz Sobczak 				    &qp->pfpdu.ah);
1685cdcd52d4SBartosz Sobczak }
1686cdcd52d4SBartosz Sobczak 
1687cdcd52d4SBartosz Sobczak /**
1688cdcd52d4SBartosz Sobczak  * irdma_ieq_handle_exception - handle qp's exception
1689cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1690cdcd52d4SBartosz Sobczak  * @qp: qp receiving excpetion
1691cdcd52d4SBartosz Sobczak  * @buf: receive buffer
1692cdcd52d4SBartosz Sobczak  */
1693cdcd52d4SBartosz Sobczak static void
1694cdcd52d4SBartosz Sobczak irdma_ieq_handle_exception(struct irdma_puda_rsrc *ieq,
1695cdcd52d4SBartosz Sobczak 			   struct irdma_sc_qp *qp,
1696cdcd52d4SBartosz Sobczak 			   struct irdma_puda_buf *buf)
1697cdcd52d4SBartosz Sobczak {
1698cdcd52d4SBartosz Sobczak 	struct irdma_pfpdu *pfpdu = &qp->pfpdu;
1699cdcd52d4SBartosz Sobczak 	u32 *hw_host_ctx = (u32 *)qp->hw_host_ctx;
1700cdcd52d4SBartosz Sobczak 	u32 rcv_wnd = hw_host_ctx[23];
1701cdcd52d4SBartosz Sobczak 	/* first partial seq # in q2 */
1702cdcd52d4SBartosz Sobczak u32 fps = *(u32 *)(qp->q2_buf + Q2_FPSN_OFFSET);
1703cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1704cdcd52d4SBartosz Sobczak 	struct list_head *plist;
1705cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *tmpbuf = NULL;
1706cdcd52d4SBartosz Sobczak 	unsigned long flags = 0;
1707cdcd52d4SBartosz Sobczak 	u8 hw_rev = qp->dev->hw_attrs.uk_attrs.hw_rev;
1708cdcd52d4SBartosz Sobczak 
1709cdcd52d4SBartosz Sobczak 	irdma_debug_buf(ieq->dev, IRDMA_DEBUG_IEQ, "IEQ RX BUFFER", buf->mem.va,
1710cdcd52d4SBartosz Sobczak 			buf->totallen);
1711cdcd52d4SBartosz Sobczak 
1712cdcd52d4SBartosz Sobczak 	spin_lock_irqsave(&pfpdu->lock, flags);
1713cdcd52d4SBartosz Sobczak 	pfpdu->total_ieq_bufs++;
1714cdcd52d4SBartosz Sobczak 	if (pfpdu->mpa_crc_err) {
1715cdcd52d4SBartosz Sobczak 		pfpdu->crc_err++;
1716cdcd52d4SBartosz Sobczak 		goto error;
1717cdcd52d4SBartosz Sobczak 	}
1718cdcd52d4SBartosz Sobczak 	if (pfpdu->mode && fps != pfpdu->fps) {
1719cdcd52d4SBartosz Sobczak 		/* clean up qp as it is new partial sequence */
1720cdcd52d4SBartosz Sobczak 		irdma_ieq_cleanup_qp(ieq, qp);
1721cdcd52d4SBartosz Sobczak 		irdma_debug(ieq->dev, IRDMA_DEBUG_IEQ,
1722cdcd52d4SBartosz Sobczak 			    "restarting new partial\n");
1723cdcd52d4SBartosz Sobczak 		pfpdu->mode = false;
1724cdcd52d4SBartosz Sobczak 	}
1725cdcd52d4SBartosz Sobczak 
1726cdcd52d4SBartosz Sobczak 	if (!pfpdu->mode) {
1727cdcd52d4SBartosz Sobczak 		irdma_debug_buf(ieq->dev, IRDMA_DEBUG_IEQ, "Q2 BUFFER",
1728cdcd52d4SBartosz Sobczak 				(u64 *)qp->q2_buf, 128);
1729cdcd52d4SBartosz Sobczak 		/* First_Partial_Sequence_Number check */
1730cdcd52d4SBartosz Sobczak 		pfpdu->rcv_nxt = fps;
1731cdcd52d4SBartosz Sobczak 		pfpdu->fps = fps;
1732cdcd52d4SBartosz Sobczak 		pfpdu->mode = true;
1733cdcd52d4SBartosz Sobczak 		pfpdu->max_fpdu_data = (buf->ipv4) ?
1734cdcd52d4SBartosz Sobczak 		    (ieq->vsi->mtu - IRDMA_MTU_TO_MSS_IPV4) :
1735cdcd52d4SBartosz Sobczak 		    (ieq->vsi->mtu - IRDMA_MTU_TO_MSS_IPV6);
1736cdcd52d4SBartosz Sobczak 		pfpdu->pmode_count++;
1737cdcd52d4SBartosz Sobczak 		ieq->pmode_count++;
1738cdcd52d4SBartosz Sobczak 		INIT_LIST_HEAD(rxlist);
1739cdcd52d4SBartosz Sobczak 		irdma_ieq_check_first_buf(buf, fps);
1740cdcd52d4SBartosz Sobczak 	}
1741cdcd52d4SBartosz Sobczak 
1742cdcd52d4SBartosz Sobczak 	if (!(rcv_wnd >= (buf->seqnum - pfpdu->rcv_nxt))) {
1743cdcd52d4SBartosz Sobczak 		pfpdu->bad_seq_num++;
1744cdcd52d4SBartosz Sobczak 		ieq->bad_seq_num++;
1745cdcd52d4SBartosz Sobczak 		goto error;
1746cdcd52d4SBartosz Sobczak 	}
1747cdcd52d4SBartosz Sobczak 
1748cdcd52d4SBartosz Sobczak 	if (!list_empty(rxlist)) {
1749cdcd52d4SBartosz Sobczak 		tmpbuf = (struct irdma_puda_buf *)(rxlist)->next;
1750cdcd52d4SBartosz Sobczak 		while ((struct list_head *)tmpbuf != rxlist) {
1751cdcd52d4SBartosz Sobczak 			if (buf->seqnum == tmpbuf->seqnum)
1752cdcd52d4SBartosz Sobczak 				goto error;
1753cdcd52d4SBartosz Sobczak 			if ((int)(buf->seqnum - tmpbuf->seqnum) < 0)
1754cdcd52d4SBartosz Sobczak 				break;
1755cdcd52d4SBartosz Sobczak 			plist = &tmpbuf->list;
1756cdcd52d4SBartosz Sobczak 			tmpbuf = (struct irdma_puda_buf *)(plist)->next;
1757cdcd52d4SBartosz Sobczak 		}
1758cdcd52d4SBartosz Sobczak 		/* Insert buf before tmpbuf */
1759cdcd52d4SBartosz Sobczak 		list_add_tail(&buf->list, &tmpbuf->list);
1760cdcd52d4SBartosz Sobczak 	} else {
1761cdcd52d4SBartosz Sobczak 		list_add_tail(&buf->list, rxlist);
1762cdcd52d4SBartosz Sobczak 	}
1763cdcd52d4SBartosz Sobczak 	pfpdu->nextseqnum = buf->seqnum + buf->datalen;
1764cdcd52d4SBartosz Sobczak 	pfpdu->lastrcv_buf = buf;
1765cdcd52d4SBartosz Sobczak 	if (hw_rev >= IRDMA_GEN_2 && !pfpdu->ah) {
1766cdcd52d4SBartosz Sobczak 		irdma_ieq_create_ah(qp, buf);
1767cdcd52d4SBartosz Sobczak 		if (!pfpdu->ah)
1768cdcd52d4SBartosz Sobczak 			goto error;
1769cdcd52d4SBartosz Sobczak 		goto exit;
1770cdcd52d4SBartosz Sobczak 	}
1771cdcd52d4SBartosz Sobczak 	if (hw_rev == IRDMA_GEN_1)
1772cdcd52d4SBartosz Sobczak 		irdma_ieq_process_fpdus(qp, ieq);
1773cdcd52d4SBartosz Sobczak 	else if (pfpdu->ah && pfpdu->ah->ah_info.ah_valid)
1774cdcd52d4SBartosz Sobczak 		irdma_ieq_process_fpdus(qp, ieq);
1775cdcd52d4SBartosz Sobczak exit:
1776cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&pfpdu->lock, flags);
1777cdcd52d4SBartosz Sobczak 
1778cdcd52d4SBartosz Sobczak 	return;
1779cdcd52d4SBartosz Sobczak 
1780cdcd52d4SBartosz Sobczak error:
1781cdcd52d4SBartosz Sobczak 	irdma_puda_ret_bufpool(ieq, buf);
1782cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&pfpdu->lock, flags);
1783cdcd52d4SBartosz Sobczak }
1784cdcd52d4SBartosz Sobczak 
1785cdcd52d4SBartosz Sobczak /**
1786cdcd52d4SBartosz Sobczak  * irdma_ieq_receive - received exception buffer
1787cdcd52d4SBartosz Sobczak  * @vsi: VSI of device
1788cdcd52d4SBartosz Sobczak  * @buf: exception buffer received
1789cdcd52d4SBartosz Sobczak  */
1790cdcd52d4SBartosz Sobczak static void
1791cdcd52d4SBartosz Sobczak irdma_ieq_receive(struct irdma_sc_vsi *vsi,
1792cdcd52d4SBartosz Sobczak 		  struct irdma_puda_buf *buf)
1793cdcd52d4SBartosz Sobczak {
1794cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *ieq = vsi->ieq;
1795cdcd52d4SBartosz Sobczak 	struct irdma_sc_qp *qp = NULL;
1796cdcd52d4SBartosz Sobczak 	u32 wqe_idx = ieq->compl_rxwqe_idx;
1797cdcd52d4SBartosz Sobczak 
1798cdcd52d4SBartosz Sobczak 	qp = irdma_ieq_get_qp(vsi->dev, buf);
1799cdcd52d4SBartosz Sobczak 	if (!qp) {
1800cdcd52d4SBartosz Sobczak 		ieq->stats_bad_qp_id++;
1801cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, buf);
1802cdcd52d4SBartosz Sobczak 	} else {
1803cdcd52d4SBartosz Sobczak 		irdma_ieq_handle_exception(ieq, qp, buf);
1804cdcd52d4SBartosz Sobczak 	}
1805cdcd52d4SBartosz Sobczak 	/*
1806cdcd52d4SBartosz Sobczak 	 * ieq->rx_wqe_idx is used by irdma_puda_replenish_rq() on which wqe_idx to start replenish rq
1807cdcd52d4SBartosz Sobczak 	 */
1808cdcd52d4SBartosz Sobczak 	if (!ieq->rxq_invalid_cnt)
1809cdcd52d4SBartosz Sobczak 		ieq->rx_wqe_idx = wqe_idx;
1810cdcd52d4SBartosz Sobczak 	ieq->rxq_invalid_cnt++;
1811cdcd52d4SBartosz Sobczak }
1812cdcd52d4SBartosz Sobczak 
1813cdcd52d4SBartosz Sobczak /**
1814cdcd52d4SBartosz Sobczak  * irdma_ieq_tx_compl - put back after sending completed exception buffer
1815cdcd52d4SBartosz Sobczak  * @vsi: sc VSI struct
1816cdcd52d4SBartosz Sobczak  * @sqwrid: pointer to puda buffer
1817cdcd52d4SBartosz Sobczak  */
1818cdcd52d4SBartosz Sobczak static void
1819cdcd52d4SBartosz Sobczak irdma_ieq_tx_compl(struct irdma_sc_vsi *vsi, void *sqwrid)
1820cdcd52d4SBartosz Sobczak {
1821cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *ieq = vsi->ieq;
1822cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf = sqwrid;
1823cdcd52d4SBartosz Sobczak 
1824cdcd52d4SBartosz Sobczak 	irdma_puda_ret_bufpool(ieq, buf);
1825cdcd52d4SBartosz Sobczak }
1826cdcd52d4SBartosz Sobczak 
1827cdcd52d4SBartosz Sobczak /**
1828cdcd52d4SBartosz Sobczak  * irdma_ieq_cleanup_qp - qp is being destroyed
1829cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1830cdcd52d4SBartosz Sobczak  * @qp: all pending fpdu buffers
1831cdcd52d4SBartosz Sobczak  */
1832cdcd52d4SBartosz Sobczak void
1833cdcd52d4SBartosz Sobczak irdma_ieq_cleanup_qp(struct irdma_puda_rsrc *ieq, struct irdma_sc_qp *qp)
1834cdcd52d4SBartosz Sobczak {
1835cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
1836cdcd52d4SBartosz Sobczak 	struct irdma_pfpdu *pfpdu = &qp->pfpdu;
1837cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1838cdcd52d4SBartosz Sobczak 
1839cdcd52d4SBartosz Sobczak 	if (qp->pfpdu.ah) {
1840cdcd52d4SBartosz Sobczak 		irdma_puda_free_ah(ieq->dev, qp->pfpdu.ah);
1841cdcd52d4SBartosz Sobczak 		qp->pfpdu.ah = NULL;
1842cdcd52d4SBartosz Sobczak 		qp->pfpdu.ah_buf = NULL;
1843cdcd52d4SBartosz Sobczak 	}
1844cdcd52d4SBartosz Sobczak 
1845cdcd52d4SBartosz Sobczak 	if (!pfpdu->mode)
1846cdcd52d4SBartosz Sobczak 		return;
1847cdcd52d4SBartosz Sobczak 
1848cdcd52d4SBartosz Sobczak 	while (!list_empty(rxlist)) {
1849cdcd52d4SBartosz Sobczak 		buf = irdma_puda_get_listbuf(rxlist);
1850cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, buf);
1851cdcd52d4SBartosz Sobczak 	}
1852cdcd52d4SBartosz Sobczak }
1853