xref: /freebsd/sys/dev/irdma/irdma_puda.c (revision 5b5f7d0e)
1cdcd52d4SBartosz Sobczak /*-
2cdcd52d4SBartosz Sobczak  * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
3cdcd52d4SBartosz Sobczak  *
401fbb869SBartosz Sobczak  * Copyright (c) 2015 - 2023 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 
35cdcd52d4SBartosz Sobczak #include "osdep.h"
36cdcd52d4SBartosz Sobczak #include "irdma_hmc.h"
37cdcd52d4SBartosz Sobczak #include "irdma_defs.h"
38cdcd52d4SBartosz Sobczak #include "irdma_type.h"
39cdcd52d4SBartosz Sobczak #include "irdma_protos.h"
40cdcd52d4SBartosz Sobczak #include "irdma_puda.h"
41cdcd52d4SBartosz Sobczak #include "irdma_ws.h"
42cdcd52d4SBartosz Sobczak 
43cdcd52d4SBartosz Sobczak static void
44cdcd52d4SBartosz Sobczak irdma_ieq_receive(struct irdma_sc_vsi *vsi,
45cdcd52d4SBartosz Sobczak 		  struct irdma_puda_buf *buf);
46cdcd52d4SBartosz Sobczak static void irdma_ieq_tx_compl(struct irdma_sc_vsi *vsi, void *sqwrid);
47cdcd52d4SBartosz Sobczak static void
48cdcd52d4SBartosz Sobczak irdma_ilq_putback_rcvbuf(struct irdma_sc_qp *qp,
49cdcd52d4SBartosz Sobczak 			 struct irdma_puda_buf *buf, u32 wqe_idx);
505b5f7d0eSBartosz Sobczak 
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 *
irdma_puda_get_listbuf(struct list_head * list)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 *
irdma_puda_get_bufpool(struct irdma_puda_rsrc * rsrc)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
irdma_puda_ret_bufpool(struct irdma_puda_rsrc * rsrc,struct irdma_puda_buf * buf)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
irdma_puda_post_recvbuf(struct irdma_puda_rsrc * rsrc,u32 wqe_idx,struct irdma_puda_buf * buf,bool initial)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
irdma_puda_replenish_rq(struct irdma_puda_rsrc * rsrc,bool initial)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 *
irdma_puda_alloc_buf(struct irdma_sc_dev * dev,u32 len)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 
1855b5f7d0eSBartosz Sobczak 	buf_mem.size = sizeof(*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
irdma_puda_dele_buf(struct irdma_sc_dev * dev,struct irdma_puda_buf * buf)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  */
irdma_puda_get_next_send_wqe(struct irdma_qp_uk * qp,u32 * wqe_idx)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)
24035105900SBartosz Sobczak 		return NULL;
241cdcd52d4SBartosz Sobczak 
24235105900SBartosz 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
irdma_puda_poll_info(struct irdma_sc_cq * cq,struct irdma_puda_cmpl_info * info)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 
27301fbb869SBartosz Sobczak 	/* Ensure CQE contents are read after valid bit is checked */
27401fbb869SBartosz Sobczak 	rmb();
27501fbb869SBartosz Sobczak 
276cdcd52d4SBartosz Sobczak 	if (cq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
277777e472cSBartosz Sobczak 		ext_valid = (bool)FIELD_GET(IRDMA_CQ_EXTCQE, qword3);
278cdcd52d4SBartosz Sobczak 
279cdcd52d4SBartosz Sobczak 	if (ext_valid) {
280cdcd52d4SBartosz Sobczak 		peek_head = (cq_uk->cq_ring.head + 1) % cq_uk->cq_ring.size;
281cdcd52d4SBartosz Sobczak 		ext_cqe = cq_uk->cq_base[peek_head].buf;
282cdcd52d4SBartosz Sobczak 		get_64bit_val(ext_cqe, IRDMA_BYTE_24, &qword7);
283777e472cSBartosz Sobczak 		polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword7);
284cdcd52d4SBartosz Sobczak 		if (!peek_head)
285cdcd52d4SBartosz Sobczak 			polarity ^= 1;
286cdcd52d4SBartosz Sobczak 		if (polarity != cq_uk->polarity)
287cdcd52d4SBartosz Sobczak 			return -ENOENT;
288cdcd52d4SBartosz Sobczak 
28901fbb869SBartosz Sobczak 		/* Ensure ext CQE contents are read after ext valid bit is checked */
29001fbb869SBartosz Sobczak 		rmb();
29101fbb869SBartosz Sobczak 
292cdcd52d4SBartosz Sobczak 		IRDMA_RING_MOVE_HEAD_NOCHECK(cq_uk->cq_ring);
293cdcd52d4SBartosz Sobczak 		if (!IRDMA_RING_CURRENT_HEAD(cq_uk->cq_ring))
294cdcd52d4SBartosz Sobczak 			cq_uk->polarity = !cq_uk->polarity;
295cdcd52d4SBartosz Sobczak 		/* update cq tail in cq shadow memory also */
296cdcd52d4SBartosz Sobczak 		IRDMA_RING_MOVE_TAIL(cq_uk->cq_ring);
297cdcd52d4SBartosz Sobczak 	}
298cdcd52d4SBartosz Sobczak 
299cdcd52d4SBartosz Sobczak 	irdma_debug_buf(cq->dev, IRDMA_DEBUG_PUDA, "PUDA CQE", cqe, 32);
300cdcd52d4SBartosz Sobczak 	if (ext_valid)
301cdcd52d4SBartosz Sobczak 		irdma_debug_buf(cq->dev, IRDMA_DEBUG_PUDA, "PUDA EXT-CQE",
302cdcd52d4SBartosz Sobczak 				ext_cqe, 32);
303cdcd52d4SBartosz Sobczak 
304777e472cSBartosz Sobczak 	error = (bool)FIELD_GET(IRDMA_CQ_ERROR, qword3);
305cdcd52d4SBartosz Sobczak 	if (error) {
306cdcd52d4SBartosz Sobczak 		irdma_debug(cq->dev, IRDMA_DEBUG_PUDA, "receive error\n");
307777e472cSBartosz Sobczak 		major_err = (u32)(FIELD_GET(IRDMA_CQ_MAJERR, qword3));
308777e472cSBartosz Sobczak 		minor_err = (u32)(FIELD_GET(IRDMA_CQ_MINERR, qword3));
309cdcd52d4SBartosz Sobczak 		info->compl_error = major_err << 16 | minor_err;
310cdcd52d4SBartosz Sobczak 		return -EIO;
311cdcd52d4SBartosz Sobczak 	}
312cdcd52d4SBartosz Sobczak 
313cdcd52d4SBartosz Sobczak 	get_64bit_val(cqe, IRDMA_BYTE_0, &qword0);
314cdcd52d4SBartosz Sobczak 	get_64bit_val(cqe, IRDMA_BYTE_16, &qword2);
315cdcd52d4SBartosz Sobczak 
316777e472cSBartosz Sobczak 	info->q_type = (u8)FIELD_GET(IRDMA_CQ_SQ, qword3);
317777e472cSBartosz Sobczak 	info->qp_id = (u32)FIELD_GET(IRDMACQ_QPID, qword2);
318cdcd52d4SBartosz Sobczak 	if (cq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
319777e472cSBartosz Sobczak 		info->ipv4 = (bool)FIELD_GET(IRDMACQ_IPV4, qword3);
320cdcd52d4SBartosz Sobczak 
321cdcd52d4SBartosz Sobczak 	get_64bit_val(cqe, IRDMA_BYTE_8, &comp_ctx);
322cdcd52d4SBartosz Sobczak 	info->qp = (struct irdma_qp_uk *)(irdma_uintptr) comp_ctx;
323777e472cSBartosz Sobczak 	info->wqe_idx = (u32)FIELD_GET(IRDMA_CQ_WQEIDX, qword3);
324cdcd52d4SBartosz Sobczak 
325cdcd52d4SBartosz Sobczak 	if (info->q_type == IRDMA_CQE_QTYPE_RQ) {
326cdcd52d4SBartosz Sobczak 		if (ext_valid) {
327777e472cSBartosz Sobczak 			info->vlan_valid = (bool)FIELD_GET(IRDMA_CQ_UDVLANVALID, qword7);
328cdcd52d4SBartosz Sobczak 			if (info->vlan_valid) {
329cdcd52d4SBartosz Sobczak 				get_64bit_val(ext_cqe, IRDMA_BYTE_16, &qword6);
330777e472cSBartosz Sobczak 				info->vlan = (u16)FIELD_GET(IRDMA_CQ_UDVLAN, qword6);
331cdcd52d4SBartosz Sobczak 			}
332777e472cSBartosz Sobczak 			info->smac_valid = (bool)FIELD_GET(IRDMA_CQ_UDSMACVALID, qword7);
333cdcd52d4SBartosz Sobczak 			if (info->smac_valid) {
334cdcd52d4SBartosz Sobczak 				get_64bit_val(ext_cqe, IRDMA_BYTE_16, &qword6);
335cdcd52d4SBartosz Sobczak 				info->smac[0] = (u8)((qword6 >> 40) & 0xFF);
336cdcd52d4SBartosz Sobczak 				info->smac[1] = (u8)((qword6 >> 32) & 0xFF);
337cdcd52d4SBartosz Sobczak 				info->smac[2] = (u8)((qword6 >> 24) & 0xFF);
338cdcd52d4SBartosz Sobczak 				info->smac[3] = (u8)((qword6 >> 16) & 0xFF);
339cdcd52d4SBartosz Sobczak 				info->smac[4] = (u8)((qword6 >> 8) & 0xFF);
340cdcd52d4SBartosz Sobczak 				info->smac[5] = (u8)(qword6 & 0xFF);
341cdcd52d4SBartosz Sobczak 			}
342cdcd52d4SBartosz Sobczak 		}
343cdcd52d4SBartosz Sobczak 
344cdcd52d4SBartosz Sobczak 		if (cq->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1) {
345777e472cSBartosz Sobczak 			info->vlan_valid = (bool)FIELD_GET(IRDMA_VLAN_TAG_VALID, qword3);
346777e472cSBartosz Sobczak 			info->l4proto = (u8)FIELD_GET(IRDMA_UDA_L4PROTO, qword2);
347777e472cSBartosz Sobczak 			info->l3proto = (u8)FIELD_GET(IRDMA_UDA_L3PROTO, qword2);
348cdcd52d4SBartosz Sobczak 		}
349cdcd52d4SBartosz Sobczak 
350777e472cSBartosz Sobczak 		info->payload_len = (u32)FIELD_GET(IRDMACQ_PAYLDLEN, qword0);
351cdcd52d4SBartosz Sobczak 	}
352cdcd52d4SBartosz Sobczak 
353cdcd52d4SBartosz Sobczak 	return 0;
354cdcd52d4SBartosz Sobczak }
355cdcd52d4SBartosz Sobczak 
356cdcd52d4SBartosz Sobczak /**
357cdcd52d4SBartosz Sobczak  * irdma_puda_poll_cmpl - processes completion for cq
358cdcd52d4SBartosz Sobczak  * @dev: iwarp device
359cdcd52d4SBartosz Sobczak  * @cq: cq getting interrupt
360cdcd52d4SBartosz Sobczak  * @compl_err: return any completion err
361cdcd52d4SBartosz Sobczak  */
362cdcd52d4SBartosz Sobczak int
irdma_puda_poll_cmpl(struct irdma_sc_dev * dev,struct irdma_sc_cq * cq,u32 * compl_err)363cdcd52d4SBartosz Sobczak irdma_puda_poll_cmpl(struct irdma_sc_dev *dev, struct irdma_sc_cq *cq,
364cdcd52d4SBartosz Sobczak 		     u32 *compl_err)
365cdcd52d4SBartosz Sobczak {
366cdcd52d4SBartosz Sobczak 	struct irdma_qp_uk *qp;
367cdcd52d4SBartosz Sobczak 	struct irdma_cq_uk *cq_uk = &cq->cq_uk;
368cdcd52d4SBartosz Sobczak 	struct irdma_puda_cmpl_info info = {0};
369cdcd52d4SBartosz Sobczak 	int ret = 0;
370cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
371cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *rsrc;
372cdcd52d4SBartosz Sobczak 	u8 cq_type = cq->cq_type;
373cdcd52d4SBartosz Sobczak 	unsigned long flags;
374cdcd52d4SBartosz Sobczak 
375cdcd52d4SBartosz Sobczak 	if (cq_type == IRDMA_CQ_TYPE_ILQ || cq_type == IRDMA_CQ_TYPE_IEQ) {
376cdcd52d4SBartosz Sobczak 		rsrc = (cq_type == IRDMA_CQ_TYPE_ILQ) ? cq->vsi->ilq :
377cdcd52d4SBartosz Sobczak 		    cq->vsi->ieq;
378cdcd52d4SBartosz Sobczak 	} else {
379cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "qp_type error\n");
380cdcd52d4SBartosz Sobczak 		return -EFAULT;
381cdcd52d4SBartosz Sobczak 	}
382cdcd52d4SBartosz Sobczak 
383cdcd52d4SBartosz Sobczak 	ret = irdma_puda_poll_info(cq, &info);
384cdcd52d4SBartosz Sobczak 	*compl_err = info.compl_error;
385cdcd52d4SBartosz Sobczak 	if (ret == -ENOENT)
386cdcd52d4SBartosz Sobczak 		return ret;
387cdcd52d4SBartosz Sobczak 	if (ret)
388cdcd52d4SBartosz Sobczak 		goto done;
389cdcd52d4SBartosz Sobczak 
390cdcd52d4SBartosz Sobczak 	qp = info.qp;
391cdcd52d4SBartosz Sobczak 	if (!qp || !rsrc) {
392cdcd52d4SBartosz Sobczak 		ret = -EFAULT;
393cdcd52d4SBartosz Sobczak 		goto done;
394cdcd52d4SBartosz Sobczak 	}
395cdcd52d4SBartosz Sobczak 
396cdcd52d4SBartosz Sobczak 	if (qp->qp_id != rsrc->qp_id) {
397cdcd52d4SBartosz Sobczak 		ret = -EFAULT;
398cdcd52d4SBartosz Sobczak 		goto done;
399cdcd52d4SBartosz Sobczak 	}
400cdcd52d4SBartosz Sobczak 
401cdcd52d4SBartosz Sobczak 	if (info.q_type == IRDMA_CQE_QTYPE_RQ) {
402cdcd52d4SBartosz Sobczak 		buf = (struct irdma_puda_buf *)(uintptr_t)
403cdcd52d4SBartosz Sobczak 		    qp->rq_wrid_array[info.wqe_idx];
404cdcd52d4SBartosz Sobczak 
405cdcd52d4SBartosz Sobczak 		/* reusing so synch the buffer for CPU use */
406cdcd52d4SBartosz Sobczak 		dma_sync_single_for_cpu(hw_to_dev(dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL);
407cdcd52d4SBartosz Sobczak 		/* Get all the tcpip information in the buf header */
408cdcd52d4SBartosz Sobczak 		ret = irdma_puda_get_tcpip_info(&info, buf);
409cdcd52d4SBartosz Sobczak 		if (ret) {
410cdcd52d4SBartosz Sobczak 			rsrc->stats_rcvd_pkt_err++;
411cdcd52d4SBartosz Sobczak 			if (cq_type == IRDMA_CQ_TYPE_ILQ) {
412cdcd52d4SBartosz Sobczak 				irdma_ilq_putback_rcvbuf(&rsrc->qp, buf,
413cdcd52d4SBartosz Sobczak 							 info.wqe_idx);
414cdcd52d4SBartosz Sobczak 			} else {
415cdcd52d4SBartosz Sobczak 				irdma_puda_ret_bufpool(rsrc, buf);
416cdcd52d4SBartosz Sobczak 				irdma_puda_replenish_rq(rsrc, false);
417cdcd52d4SBartosz Sobczak 			}
418cdcd52d4SBartosz Sobczak 			goto done;
419cdcd52d4SBartosz Sobczak 		}
420cdcd52d4SBartosz Sobczak 
421cdcd52d4SBartosz Sobczak 		rsrc->stats_pkt_rcvd++;
422cdcd52d4SBartosz Sobczak 		rsrc->compl_rxwqe_idx = info.wqe_idx;
423cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "RQ completion\n");
424cdcd52d4SBartosz Sobczak 		rsrc->receive(rsrc->vsi, buf);
425cdcd52d4SBartosz Sobczak 		if (cq_type == IRDMA_CQ_TYPE_ILQ)
426cdcd52d4SBartosz Sobczak 			irdma_ilq_putback_rcvbuf(&rsrc->qp, buf, info.wqe_idx);
427cdcd52d4SBartosz Sobczak 		else
428cdcd52d4SBartosz Sobczak 			irdma_puda_replenish_rq(rsrc, false);
429cdcd52d4SBartosz Sobczak 
430cdcd52d4SBartosz Sobczak 	} else {
431cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "SQ completion\n");
432cdcd52d4SBartosz Sobczak 		buf = (struct irdma_puda_buf *)(uintptr_t)
433cdcd52d4SBartosz Sobczak 		    qp->sq_wrtrk_array[info.wqe_idx].wrid;
434cdcd52d4SBartosz Sobczak 
435cdcd52d4SBartosz Sobczak 		/* reusing so synch the buffer for CPU use */
436cdcd52d4SBartosz Sobczak 		dma_sync_single_for_cpu(hw_to_dev(dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL);
437cdcd52d4SBartosz Sobczak 		IRDMA_RING_SET_TAIL(qp->sq_ring, info.wqe_idx);
438cdcd52d4SBartosz Sobczak 		rsrc->xmit_complete(rsrc->vsi, buf);
439cdcd52d4SBartosz Sobczak 		spin_lock_irqsave(&rsrc->bufpool_lock, flags);
440cdcd52d4SBartosz Sobczak 		rsrc->tx_wqe_avail_cnt++;
441cdcd52d4SBartosz Sobczak 		spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
442cdcd52d4SBartosz Sobczak 		if (!list_empty(&rsrc->txpend))
443cdcd52d4SBartosz Sobczak 			irdma_puda_send_buf(rsrc, NULL);
444cdcd52d4SBartosz Sobczak 	}
445cdcd52d4SBartosz Sobczak 
446cdcd52d4SBartosz Sobczak done:
447cdcd52d4SBartosz Sobczak 	IRDMA_RING_MOVE_HEAD_NOCHECK(cq_uk->cq_ring);
448cdcd52d4SBartosz Sobczak 	if (!IRDMA_RING_CURRENT_HEAD(cq_uk->cq_ring))
449cdcd52d4SBartosz Sobczak 		cq_uk->polarity = !cq_uk->polarity;
450cdcd52d4SBartosz Sobczak 	/* update cq tail in cq shadow memory also */
451cdcd52d4SBartosz Sobczak 	IRDMA_RING_MOVE_TAIL(cq_uk->cq_ring);
452cdcd52d4SBartosz Sobczak 	set_64bit_val(cq_uk->shadow_area, IRDMA_BYTE_0,
453cdcd52d4SBartosz Sobczak 		      IRDMA_RING_CURRENT_HEAD(cq_uk->cq_ring));
454cdcd52d4SBartosz Sobczak 
455cdcd52d4SBartosz Sobczak 	return ret;
456cdcd52d4SBartosz Sobczak }
457cdcd52d4SBartosz Sobczak 
458cdcd52d4SBartosz Sobczak /**
459cdcd52d4SBartosz Sobczak  * irdma_puda_send - complete send wqe for transmit
460cdcd52d4SBartosz Sobczak  * @qp: puda qp for send
461cdcd52d4SBartosz Sobczak  * @info: buffer information for transmit
462cdcd52d4SBartosz Sobczak  */
463cdcd52d4SBartosz Sobczak int
irdma_puda_send(struct irdma_sc_qp * qp,struct irdma_puda_send_info * info)464cdcd52d4SBartosz Sobczak irdma_puda_send(struct irdma_sc_qp *qp, struct irdma_puda_send_info *info)
465cdcd52d4SBartosz Sobczak {
466cdcd52d4SBartosz Sobczak 	__le64 *wqe;
467cdcd52d4SBartosz Sobczak 	u32 iplen, l4len;
468cdcd52d4SBartosz Sobczak 	u64 hdr[2];
469cdcd52d4SBartosz Sobczak 	u32 wqe_idx;
470cdcd52d4SBartosz Sobczak 	u8 iipt;
471cdcd52d4SBartosz Sobczak 
472cdcd52d4SBartosz Sobczak 	/* number of 32 bits DWORDS in header */
473cdcd52d4SBartosz Sobczak 	l4len = info->tcplen >> 2;
474cdcd52d4SBartosz Sobczak 	if (info->ipv4) {
475cdcd52d4SBartosz Sobczak 		iipt = 3;
476cdcd52d4SBartosz Sobczak 		iplen = 5;
477cdcd52d4SBartosz Sobczak 	} else {
478cdcd52d4SBartosz Sobczak 		iipt = 1;
479cdcd52d4SBartosz Sobczak 		iplen = 10;
480cdcd52d4SBartosz Sobczak 	}
481cdcd52d4SBartosz Sobczak 
482cdcd52d4SBartosz Sobczak 	wqe = irdma_puda_get_next_send_wqe(&qp->qp_uk, &wqe_idx);
483cdcd52d4SBartosz Sobczak 	if (!wqe)
484cdcd52d4SBartosz Sobczak 		return -ENOSPC;
485cdcd52d4SBartosz Sobczak 
486cdcd52d4SBartosz Sobczak 	qp->qp_uk.sq_wrtrk_array[wqe_idx].wrid = (uintptr_t)info->scratch;
487cdcd52d4SBartosz Sobczak 	/* Third line of WQE descriptor */
488cdcd52d4SBartosz Sobczak 	/* maclen is in words */
489cdcd52d4SBartosz Sobczak 
490cdcd52d4SBartosz Sobczak 	if (qp->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
491cdcd52d4SBartosz Sobczak 		hdr[0] = 0;	/* Dest_QPN and Dest_QKey only for UD */
492777e472cSBartosz Sobczak 		hdr[1] = FIELD_PREP(IRDMA_UDA_QPSQ_OPCODE, IRDMA_OP_TYPE_SEND) |
493777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_L4LEN, l4len) |
494777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMAQPSQ_AHID, info->ah_id) |
495777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_SIGCOMPL, 1) |
496777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_VALID,
497777e472cSBartosz Sobczak 			       qp->qp_uk.swqe_polarity);
498cdcd52d4SBartosz Sobczak 
499cdcd52d4SBartosz Sobczak 		/* Forth line of WQE descriptor */
500cdcd52d4SBartosz Sobczak 
501cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_0, info->paddr);
502cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_8,
503777e472cSBartosz Sobczak 			      FIELD_PREP(IRDMAQPSQ_FRAG_LEN, info->len) |
504777e472cSBartosz Sobczak 			      FIELD_PREP(IRDMA_UDA_QPSQ_VALID, qp->qp_uk.swqe_polarity));
505cdcd52d4SBartosz Sobczak 	} else {
506777e472cSBartosz Sobczak 		hdr[0] = FIELD_PREP(IRDMA_UDA_QPSQ_MACLEN, info->maclen >> 1) |
507777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_IPLEN, iplen) |
508777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_L4T, 1) |
509777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_IIPT, iipt) |
510777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_GEN1_UDA_QPSQ_L4LEN, l4len);
511cdcd52d4SBartosz Sobczak 
512777e472cSBartosz Sobczak 		hdr[1] = FIELD_PREP(IRDMA_UDA_QPSQ_OPCODE, IRDMA_OP_TYPE_SEND) |
513777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_SIGCOMPL, 1) |
514777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_DOLOOPBACK, info->do_lpb) |
515777e472cSBartosz Sobczak 		    FIELD_PREP(IRDMA_UDA_QPSQ_VALID, qp->qp_uk.swqe_polarity);
516cdcd52d4SBartosz Sobczak 
517cdcd52d4SBartosz Sobczak 		/* Forth line of WQE descriptor */
518cdcd52d4SBartosz Sobczak 
519cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_0, info->paddr);
520cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_8,
521777e472cSBartosz Sobczak 			      FIELD_PREP(IRDMAQPSQ_GEN1_FRAG_LEN, info->len));
522cdcd52d4SBartosz Sobczak 	}
523cdcd52d4SBartosz Sobczak 
524cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_16, hdr[0]);
525cdcd52d4SBartosz Sobczak 	irdma_wmb();		/* make sure WQE is written before valid bit is set */
526cdcd52d4SBartosz Sobczak 
527cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_24, hdr[1]);
528cdcd52d4SBartosz Sobczak 
529cdcd52d4SBartosz Sobczak 	irdma_debug_buf(qp->dev, IRDMA_DEBUG_PUDA, "PUDA SEND WQE", wqe, 32);
530cdcd52d4SBartosz Sobczak 	irdma_uk_qp_post_wr(&qp->qp_uk);
531cdcd52d4SBartosz Sobczak 	return 0;
532cdcd52d4SBartosz Sobczak }
533cdcd52d4SBartosz Sobczak 
534cdcd52d4SBartosz Sobczak /**
535cdcd52d4SBartosz Sobczak  * irdma_puda_send_buf - transmit puda buffer
536cdcd52d4SBartosz Sobczak  * @rsrc: resource to use for buffer
537cdcd52d4SBartosz Sobczak  * @buf: puda buffer to transmit
538cdcd52d4SBartosz Sobczak  */
539cdcd52d4SBartosz Sobczak void
irdma_puda_send_buf(struct irdma_puda_rsrc * rsrc,struct irdma_puda_buf * buf)540cdcd52d4SBartosz Sobczak irdma_puda_send_buf(struct irdma_puda_rsrc *rsrc,
541cdcd52d4SBartosz Sobczak 		    struct irdma_puda_buf *buf)
542cdcd52d4SBartosz Sobczak {
543cdcd52d4SBartosz Sobczak 	struct irdma_puda_send_info info;
544cdcd52d4SBartosz Sobczak 	int ret = 0;
545cdcd52d4SBartosz Sobczak 	unsigned long flags;
546cdcd52d4SBartosz Sobczak 
547cdcd52d4SBartosz Sobczak 	spin_lock_irqsave(&rsrc->bufpool_lock, flags);
548cdcd52d4SBartosz Sobczak 	/*
549cdcd52d4SBartosz Sobczak 	 * if no wqe available or not from a completion and we have pending buffers, we must queue new buffer
550cdcd52d4SBartosz Sobczak 	 */
551cdcd52d4SBartosz Sobczak 	if (!rsrc->tx_wqe_avail_cnt || (buf && !list_empty(&rsrc->txpend))) {
552cdcd52d4SBartosz Sobczak 		list_add_tail(&buf->list, &rsrc->txpend);
553cdcd52d4SBartosz Sobczak 		spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
554cdcd52d4SBartosz Sobczak 		rsrc->stats_sent_pkt_q++;
555cdcd52d4SBartosz Sobczak 		if (rsrc->type == IRDMA_PUDA_RSRC_TYPE_ILQ)
556cdcd52d4SBartosz Sobczak 			irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
557cdcd52d4SBartosz Sobczak 				    "adding to txpend\n");
558cdcd52d4SBartosz Sobczak 		return;
559cdcd52d4SBartosz Sobczak 	}
560cdcd52d4SBartosz Sobczak 	rsrc->tx_wqe_avail_cnt--;
561cdcd52d4SBartosz Sobczak 	/*
562cdcd52d4SBartosz Sobczak 	 * if we are coming from a completion and have pending buffers then Get one from pending list
563cdcd52d4SBartosz Sobczak 	 */
564cdcd52d4SBartosz Sobczak 	if (!buf) {
565cdcd52d4SBartosz Sobczak 		buf = irdma_puda_get_listbuf(&rsrc->txpend);
566cdcd52d4SBartosz Sobczak 		if (!buf)
567cdcd52d4SBartosz Sobczak 			goto done;
568cdcd52d4SBartosz Sobczak 	}
569cdcd52d4SBartosz Sobczak 
570cdcd52d4SBartosz Sobczak 	info.scratch = buf;
571cdcd52d4SBartosz Sobczak 	info.paddr = buf->mem.pa;
572cdcd52d4SBartosz Sobczak 	info.len = buf->totallen;
573cdcd52d4SBartosz Sobczak 	info.tcplen = buf->tcphlen;
574cdcd52d4SBartosz Sobczak 	info.ipv4 = buf->ipv4;
575cdcd52d4SBartosz Sobczak 
576cdcd52d4SBartosz Sobczak 	if (rsrc->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
577cdcd52d4SBartosz Sobczak 		info.ah_id = buf->ah_id;
578cdcd52d4SBartosz Sobczak 	} else {
579cdcd52d4SBartosz Sobczak 		info.maclen = buf->maclen;
580cdcd52d4SBartosz Sobczak 		info.do_lpb = buf->do_lpb;
581cdcd52d4SBartosz Sobczak 	}
582cdcd52d4SBartosz Sobczak 
583cdcd52d4SBartosz Sobczak 	/* Synch buffer for use by device */
584cdcd52d4SBartosz Sobczak 	dma_sync_single_for_cpu(hw_to_dev(rsrc->dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL);
585cdcd52d4SBartosz Sobczak 	ret = irdma_puda_send(&rsrc->qp, &info);
586cdcd52d4SBartosz Sobczak 	if (ret) {
587cdcd52d4SBartosz Sobczak 		rsrc->tx_wqe_avail_cnt++;
588cdcd52d4SBartosz Sobczak 		rsrc->stats_sent_pkt_q++;
589cdcd52d4SBartosz Sobczak 		list_add(&buf->list, &rsrc->txpend);
590cdcd52d4SBartosz Sobczak 		if (rsrc->type == IRDMA_PUDA_RSRC_TYPE_ILQ)
591cdcd52d4SBartosz Sobczak 			irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
592cdcd52d4SBartosz Sobczak 				    "adding to puda_send\n");
593cdcd52d4SBartosz Sobczak 	} else {
594cdcd52d4SBartosz Sobczak 		rsrc->stats_pkt_sent++;
595cdcd52d4SBartosz Sobczak 	}
596cdcd52d4SBartosz Sobczak done:
597cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
598cdcd52d4SBartosz Sobczak }
599cdcd52d4SBartosz Sobczak 
600cdcd52d4SBartosz Sobczak /**
601cdcd52d4SBartosz Sobczak  * irdma_puda_qp_setctx - during init, set qp's context
602cdcd52d4SBartosz Sobczak  * @rsrc: qp's resource
603cdcd52d4SBartosz Sobczak  */
604cdcd52d4SBartosz Sobczak static void
irdma_puda_qp_setctx(struct irdma_puda_rsrc * rsrc)605cdcd52d4SBartosz Sobczak irdma_puda_qp_setctx(struct irdma_puda_rsrc *rsrc)
606cdcd52d4SBartosz Sobczak {
607cdcd52d4SBartosz Sobczak 	struct irdma_sc_qp *qp = &rsrc->qp;
608cdcd52d4SBartosz Sobczak 	__le64 *qp_ctx = qp->hw_host_ctx;
609cdcd52d4SBartosz Sobczak 
610cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_8, qp->sq_pa);
611cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_16, qp->rq_pa);
612cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_24,
613777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_RQSIZE, qp->hw_rq_size) |
614777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_SQSIZE, qp->hw_sq_size));
615cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_48,
616777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_SNDMSS, rsrc->buf_size));
617cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_56, 0);
618cdcd52d4SBartosz Sobczak 	if (qp->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1)
619cdcd52d4SBartosz Sobczak 		set_64bit_val(qp_ctx, IRDMA_BYTE_64, 1);
620cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_136,
621777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_TXCQNUM, rsrc->cq_id) |
622777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_RXCQNUM, rsrc->cq_id));
623cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_144,
624777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_STAT_INDEX, rsrc->stats_idx));
625cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_160,
626777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_PRIVEN, 1) |
627777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_USESTATSINSTANCE, rsrc->stats_idx_valid));
628cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_168,
629777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_QPCOMPCTX, (uintptr_t)qp));
630cdcd52d4SBartosz Sobczak 	set_64bit_val(qp_ctx, IRDMA_BYTE_176,
631777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_SQTPHVAL, qp->sq_tph_val) |
632777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_RQTPHVAL, qp->rq_tph_val) |
633777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMAQPC_QSHANDLE, qp->qs_handle));
634cdcd52d4SBartosz Sobczak 
635cdcd52d4SBartosz Sobczak 	irdma_debug_buf(rsrc->dev, IRDMA_DEBUG_PUDA, "PUDA QP CONTEXT", qp_ctx,
636cdcd52d4SBartosz Sobczak 			IRDMA_QP_CTX_SIZE);
637cdcd52d4SBartosz Sobczak }
638cdcd52d4SBartosz Sobczak 
639cdcd52d4SBartosz Sobczak /**
640cdcd52d4SBartosz Sobczak  * irdma_puda_qp_wqe - setup wqe for qp create
641cdcd52d4SBartosz Sobczak  * @dev: Device
642cdcd52d4SBartosz Sobczak  * @qp: Resource qp
643cdcd52d4SBartosz Sobczak  */
644cdcd52d4SBartosz Sobczak static int
irdma_puda_qp_wqe(struct irdma_sc_dev * dev,struct irdma_sc_qp * qp)645cdcd52d4SBartosz Sobczak irdma_puda_qp_wqe(struct irdma_sc_dev *dev, struct irdma_sc_qp *qp)
646cdcd52d4SBartosz Sobczak {
647cdcd52d4SBartosz Sobczak 	struct irdma_sc_cqp *cqp;
648cdcd52d4SBartosz Sobczak 	__le64 *wqe;
649cdcd52d4SBartosz Sobczak 	u64 hdr;
650cdcd52d4SBartosz Sobczak 	struct irdma_ccq_cqe_info compl_info;
651cdcd52d4SBartosz Sobczak 	int status = 0;
652cdcd52d4SBartosz Sobczak 
653cdcd52d4SBartosz Sobczak 	cqp = dev->cqp;
654cdcd52d4SBartosz Sobczak 	wqe = irdma_sc_cqp_get_next_send_wqe(cqp, 0);
655cdcd52d4SBartosz Sobczak 	if (!wqe)
656cdcd52d4SBartosz Sobczak 		return -ENOSPC;
657cdcd52d4SBartosz Sobczak 
658cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_16, qp->hw_host_ctx_pa);
659cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_40, qp->shadow_area_pa);
660cdcd52d4SBartosz Sobczak 
661cdcd52d4SBartosz Sobczak 	hdr = qp->qp_uk.qp_id |
662777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_CREATE_QP) |
663777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_QP_QPTYPE, IRDMA_QP_TYPE_UDA) |
664777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_QP_CQNUMVALID, 1) |
665777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_QP_NEXTIWSTATE, 2) |
666777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
667cdcd52d4SBartosz Sobczak 	irdma_wmb();		/* make sure WQE is written before valid bit is set */
668cdcd52d4SBartosz Sobczak 
669cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_24, hdr);
670cdcd52d4SBartosz Sobczak 
671cdcd52d4SBartosz Sobczak 	irdma_debug_buf(cqp->dev, IRDMA_DEBUG_PUDA, "PUDA QP CREATE", wqe, 40);
672cdcd52d4SBartosz Sobczak 	irdma_sc_cqp_post_sq(cqp);
673cdcd52d4SBartosz Sobczak 	status = irdma_sc_poll_for_cqp_op_done(dev->cqp, IRDMA_CQP_OP_CREATE_QP,
674cdcd52d4SBartosz Sobczak 					       &compl_info);
675cdcd52d4SBartosz Sobczak 
676cdcd52d4SBartosz Sobczak 	return status;
677cdcd52d4SBartosz Sobczak }
678cdcd52d4SBartosz Sobczak 
679cdcd52d4SBartosz Sobczak /**
680cdcd52d4SBartosz Sobczak  * irdma_puda_qp_create - create qp for resource
681cdcd52d4SBartosz Sobczak  * @rsrc: resource to use for buffer
682cdcd52d4SBartosz Sobczak  */
683cdcd52d4SBartosz Sobczak static int
irdma_puda_qp_create(struct irdma_puda_rsrc * rsrc)684cdcd52d4SBartosz Sobczak irdma_puda_qp_create(struct irdma_puda_rsrc *rsrc)
685cdcd52d4SBartosz Sobczak {
686cdcd52d4SBartosz Sobczak 	struct irdma_sc_qp *qp = &rsrc->qp;
687cdcd52d4SBartosz Sobczak 	struct irdma_qp_uk *ukqp = &qp->qp_uk;
688cdcd52d4SBartosz Sobczak 	int ret = 0;
689cdcd52d4SBartosz Sobczak 	u32 sq_size, rq_size;
690cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem *mem;
691cdcd52d4SBartosz Sobczak 
692cdcd52d4SBartosz Sobczak 	sq_size = rsrc->sq_size * IRDMA_QP_WQE_MIN_SIZE;
693cdcd52d4SBartosz Sobczak 	rq_size = rsrc->rq_size * IRDMA_QP_WQE_MIN_SIZE;
694cdcd52d4SBartosz Sobczak 	rsrc->qpmem.size = (sq_size + rq_size + (IRDMA_SHADOW_AREA_SIZE << 3) +
695cdcd52d4SBartosz Sobczak 			    IRDMA_QP_CTX_SIZE);
696cdcd52d4SBartosz Sobczak 	rsrc->qpmem.va = irdma_allocate_dma_mem(rsrc->dev->hw, &rsrc->qpmem,
697cdcd52d4SBartosz Sobczak 						rsrc->qpmem.size, IRDMA_HW_PAGE_SIZE);
698cdcd52d4SBartosz Sobczak 	if (!rsrc->qpmem.va)
699cdcd52d4SBartosz Sobczak 		return -ENOMEM;
700cdcd52d4SBartosz Sobczak 
701cdcd52d4SBartosz Sobczak 	mem = &rsrc->qpmem;
702cdcd52d4SBartosz Sobczak 	memset(mem->va, 0, rsrc->qpmem.size);
703cdcd52d4SBartosz Sobczak 	qp->hw_sq_size = irdma_get_encoded_wqe_size(rsrc->sq_size, IRDMA_QUEUE_TYPE_SQ_RQ);
704cdcd52d4SBartosz Sobczak 	qp->hw_rq_size = irdma_get_encoded_wqe_size(rsrc->rq_size, IRDMA_QUEUE_TYPE_SQ_RQ);
705cdcd52d4SBartosz Sobczak 	qp->pd = &rsrc->sc_pd;
706cdcd52d4SBartosz Sobczak 	qp->qp_uk.qp_type = IRDMA_QP_TYPE_UDA;
707cdcd52d4SBartosz Sobczak 	qp->dev = rsrc->dev;
708cdcd52d4SBartosz Sobczak 	qp->qp_uk.back_qp = rsrc;
709cdcd52d4SBartosz Sobczak 	qp->sq_pa = mem->pa;
710cdcd52d4SBartosz Sobczak 	qp->rq_pa = qp->sq_pa + sq_size;
711cdcd52d4SBartosz Sobczak 	qp->vsi = rsrc->vsi;
712cdcd52d4SBartosz Sobczak 	ukqp->sq_base = mem->va;
713cdcd52d4SBartosz Sobczak 	ukqp->rq_base = &ukqp->sq_base[rsrc->sq_size];
714cdcd52d4SBartosz Sobczak 	ukqp->shadow_area = ukqp->rq_base[rsrc->rq_size].elem;
715cdcd52d4SBartosz Sobczak 	ukqp->uk_attrs = &qp->dev->hw_attrs.uk_attrs;
716cdcd52d4SBartosz Sobczak 	qp->shadow_area_pa = qp->rq_pa + rq_size;
717cdcd52d4SBartosz Sobczak 	qp->hw_host_ctx = ukqp->shadow_area + IRDMA_SHADOW_AREA_SIZE;
718cdcd52d4SBartosz Sobczak 	qp->hw_host_ctx_pa = qp->shadow_area_pa + (IRDMA_SHADOW_AREA_SIZE << 3);
719cdcd52d4SBartosz Sobczak 	qp->push_idx = IRDMA_INVALID_PUSH_PAGE_INDEX;
720cdcd52d4SBartosz Sobczak 	ukqp->qp_id = rsrc->qp_id;
721cdcd52d4SBartosz Sobczak 	ukqp->sq_wrtrk_array = rsrc->sq_wrtrk_array;
722cdcd52d4SBartosz Sobczak 	ukqp->rq_wrid_array = rsrc->rq_wrid_array;
723cdcd52d4SBartosz Sobczak 	ukqp->sq_size = rsrc->sq_size;
724cdcd52d4SBartosz Sobczak 	ukqp->rq_size = rsrc->rq_size;
725cdcd52d4SBartosz Sobczak 
726cdcd52d4SBartosz Sobczak 	IRDMA_RING_INIT(ukqp->sq_ring, ukqp->sq_size);
727cdcd52d4SBartosz Sobczak 	IRDMA_RING_INIT(ukqp->initial_ring, ukqp->sq_size);
728cdcd52d4SBartosz Sobczak 	IRDMA_RING_INIT(ukqp->rq_ring, ukqp->rq_size);
729cdcd52d4SBartosz Sobczak 	ukqp->wqe_alloc_db = qp->pd->dev->wqe_alloc_db;
730cdcd52d4SBartosz Sobczak 
731cdcd52d4SBartosz Sobczak 	ret = rsrc->dev->ws_add(qp->vsi, qp->user_pri);
732cdcd52d4SBartosz Sobczak 	if (ret) {
733cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(rsrc->dev->hw, &rsrc->qpmem);
734cdcd52d4SBartosz Sobczak 		return ret;
735cdcd52d4SBartosz Sobczak 	}
736cdcd52d4SBartosz Sobczak 
737cdcd52d4SBartosz Sobczak 	irdma_qp_add_qos(qp);
738cdcd52d4SBartosz Sobczak 	irdma_puda_qp_setctx(rsrc);
739cdcd52d4SBartosz Sobczak 
740cdcd52d4SBartosz Sobczak 	if (rsrc->dev->ceq_valid)
741cdcd52d4SBartosz Sobczak 		ret = irdma_cqp_qp_create_cmd(rsrc->dev, qp);
742cdcd52d4SBartosz Sobczak 	else
743cdcd52d4SBartosz Sobczak 		ret = irdma_puda_qp_wqe(rsrc->dev, qp);
744cdcd52d4SBartosz Sobczak 	if (ret) {
745cdcd52d4SBartosz Sobczak 		irdma_qp_rem_qos(qp);
746cdcd52d4SBartosz Sobczak 		rsrc->dev->ws_remove(qp->vsi, qp->user_pri);
747cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(rsrc->dev->hw, &rsrc->qpmem);
748cdcd52d4SBartosz Sobczak 	}
749cdcd52d4SBartosz Sobczak 
750cdcd52d4SBartosz Sobczak 	return ret;
751cdcd52d4SBartosz Sobczak }
752cdcd52d4SBartosz Sobczak 
753cdcd52d4SBartosz Sobczak /**
754cdcd52d4SBartosz Sobczak  * irdma_puda_cq_wqe - setup wqe for CQ create
755cdcd52d4SBartosz Sobczak  * @dev: Device
756cdcd52d4SBartosz Sobczak  * @cq: resource for cq
757cdcd52d4SBartosz Sobczak  */
758cdcd52d4SBartosz Sobczak static int
irdma_puda_cq_wqe(struct irdma_sc_dev * dev,struct irdma_sc_cq * cq)759cdcd52d4SBartosz Sobczak irdma_puda_cq_wqe(struct irdma_sc_dev *dev, struct irdma_sc_cq *cq)
760cdcd52d4SBartosz Sobczak {
761cdcd52d4SBartosz Sobczak 	__le64 *wqe;
762cdcd52d4SBartosz Sobczak 	struct irdma_sc_cqp *cqp;
763cdcd52d4SBartosz Sobczak 	u64 hdr;
764cdcd52d4SBartosz Sobczak 	struct irdma_ccq_cqe_info compl_info;
765cdcd52d4SBartosz Sobczak 	int status = 0;
766cdcd52d4SBartosz Sobczak 
767cdcd52d4SBartosz Sobczak 	cqp = dev->cqp;
768cdcd52d4SBartosz Sobczak 	wqe = irdma_sc_cqp_get_next_send_wqe(cqp, 0);
769cdcd52d4SBartosz Sobczak 	if (!wqe)
770cdcd52d4SBartosz Sobczak 		return -ENOSPC;
771cdcd52d4SBartosz Sobczak 
772cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_0, cq->cq_uk.cq_size);
773cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_8, RS_64_1(cq, 1));
774cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_16,
775777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMA_CQPSQ_CQ_SHADOW_READ_THRESHOLD, cq->shadow_read_threshold));
776cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_32, cq->cq_pa);
777cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_40, cq->shadow_area_pa);
778cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_56,
779777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMA_CQPSQ_TPHVAL, cq->tph_val) |
780777e472cSBartosz Sobczak 		      FIELD_PREP(IRDMA_CQPSQ_VSIIDX, cq->vsi->vsi_idx));
781cdcd52d4SBartosz Sobczak 
782cdcd52d4SBartosz Sobczak 	hdr = cq->cq_uk.cq_id |
783777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_CREATE_CQ) |
784777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_CQ_CHKOVERFLOW, 1) |
785777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_CQ_ENCEQEMASK, 1) |
786777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_CQ_CEQIDVALID, 1) |
787777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
788cdcd52d4SBartosz Sobczak 	irdma_wmb();		/* make sure WQE is written before valid bit is set */
789cdcd52d4SBartosz Sobczak 
790cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_24, hdr);
791cdcd52d4SBartosz Sobczak 
792cdcd52d4SBartosz Sobczak 	irdma_debug_buf(dev, IRDMA_DEBUG_PUDA, "PUDA CREATE CQ", wqe,
793cdcd52d4SBartosz Sobczak 			IRDMA_CQP_WQE_SIZE * 8);
794cdcd52d4SBartosz Sobczak 	irdma_sc_cqp_post_sq(dev->cqp);
795cdcd52d4SBartosz Sobczak 	status = irdma_sc_poll_for_cqp_op_done(dev->cqp, IRDMA_CQP_OP_CREATE_CQ,
796cdcd52d4SBartosz Sobczak 					       &compl_info);
797cdcd52d4SBartosz Sobczak 	if (!status) {
798cdcd52d4SBartosz Sobczak 		struct irdma_sc_ceq *ceq = dev->ceq[0];
799cdcd52d4SBartosz Sobczak 
800cdcd52d4SBartosz Sobczak 		if (ceq && ceq->reg_cq)
801cdcd52d4SBartosz Sobczak 			status = irdma_sc_add_cq_ctx(ceq, cq);
802cdcd52d4SBartosz Sobczak 	}
803cdcd52d4SBartosz Sobczak 
804cdcd52d4SBartosz Sobczak 	return status;
805cdcd52d4SBartosz Sobczak }
806cdcd52d4SBartosz Sobczak 
807cdcd52d4SBartosz Sobczak /**
808cdcd52d4SBartosz Sobczak  * irdma_puda_cq_create - create cq for resource
809cdcd52d4SBartosz Sobczak  * @rsrc: resource for which cq to create
810cdcd52d4SBartosz Sobczak  */
811cdcd52d4SBartosz Sobczak static int
irdma_puda_cq_create(struct irdma_puda_rsrc * rsrc)812cdcd52d4SBartosz Sobczak irdma_puda_cq_create(struct irdma_puda_rsrc *rsrc)
813cdcd52d4SBartosz Sobczak {
814cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = rsrc->dev;
815cdcd52d4SBartosz Sobczak 	struct irdma_sc_cq *cq = &rsrc->cq;
816cdcd52d4SBartosz Sobczak 	int ret = 0;
817cdcd52d4SBartosz Sobczak 	u32 cqsize;
818cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem *mem;
819cdcd52d4SBartosz Sobczak 	struct irdma_cq_init_info info = {0};
820cdcd52d4SBartosz Sobczak 	struct irdma_cq_uk_init_info *init_info = &info.cq_uk_init_info;
821cdcd52d4SBartosz Sobczak 
822cdcd52d4SBartosz Sobczak 	cq->vsi = rsrc->vsi;
823cdcd52d4SBartosz Sobczak 	cqsize = rsrc->cq_size * (sizeof(struct irdma_cqe));
824cdcd52d4SBartosz Sobczak 	rsrc->cqmem.size = cqsize + sizeof(struct irdma_cq_shadow_area);
825cdcd52d4SBartosz Sobczak 	rsrc->cqmem.va = irdma_allocate_dma_mem(dev->hw, &rsrc->cqmem,
826cdcd52d4SBartosz Sobczak 						rsrc->cqmem.size,
827cdcd52d4SBartosz Sobczak 						IRDMA_CQ0_ALIGNMENT);
828cdcd52d4SBartosz Sobczak 	if (!rsrc->cqmem.va)
829cdcd52d4SBartosz Sobczak 		return -ENOMEM;
830cdcd52d4SBartosz Sobczak 
831cdcd52d4SBartosz Sobczak 	mem = &rsrc->cqmem;
832cdcd52d4SBartosz Sobczak 	info.dev = dev;
833cdcd52d4SBartosz Sobczak 	info.type = (rsrc->type == IRDMA_PUDA_RSRC_TYPE_ILQ) ?
834cdcd52d4SBartosz Sobczak 	    IRDMA_CQ_TYPE_ILQ : IRDMA_CQ_TYPE_IEQ;
835cdcd52d4SBartosz Sobczak 	info.shadow_read_threshold = rsrc->cq_size >> 2;
836cdcd52d4SBartosz Sobczak 	info.cq_base_pa = mem->pa;
837cdcd52d4SBartosz Sobczak 	info.shadow_area_pa = mem->pa + cqsize;
838cdcd52d4SBartosz Sobczak 	init_info->cq_base = mem->va;
839cdcd52d4SBartosz Sobczak 	init_info->shadow_area = (__le64 *) ((u8 *)mem->va + cqsize);
840cdcd52d4SBartosz Sobczak 	init_info->cq_size = rsrc->cq_size;
841cdcd52d4SBartosz Sobczak 	init_info->cq_id = rsrc->cq_id;
842cdcd52d4SBartosz Sobczak 	info.ceqe_mask = true;
843cdcd52d4SBartosz Sobczak 	info.ceq_id_valid = true;
844cdcd52d4SBartosz Sobczak 	info.vsi = rsrc->vsi;
845cdcd52d4SBartosz Sobczak 
846cdcd52d4SBartosz Sobczak 	ret = irdma_sc_cq_init(cq, &info);
847cdcd52d4SBartosz Sobczak 	if (ret)
848cdcd52d4SBartosz Sobczak 		goto error;
849cdcd52d4SBartosz Sobczak 
850cdcd52d4SBartosz Sobczak 	if (rsrc->dev->ceq_valid)
851cdcd52d4SBartosz Sobczak 		ret = irdma_cqp_cq_create_cmd(dev, cq);
852cdcd52d4SBartosz Sobczak 	else
853cdcd52d4SBartosz Sobczak 		ret = irdma_puda_cq_wqe(dev, cq);
854cdcd52d4SBartosz Sobczak error:
855cdcd52d4SBartosz Sobczak 	if (ret)
856cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(dev->hw, &rsrc->cqmem);
857cdcd52d4SBartosz Sobczak 
858cdcd52d4SBartosz Sobczak 	return ret;
859cdcd52d4SBartosz Sobczak }
860cdcd52d4SBartosz Sobczak 
861cdcd52d4SBartosz Sobczak /**
862cdcd52d4SBartosz Sobczak  * irdma_puda_free_qp - free qp for resource
863cdcd52d4SBartosz Sobczak  * @rsrc: resource for which qp to free
864cdcd52d4SBartosz Sobczak  */
865cdcd52d4SBartosz Sobczak static void
irdma_puda_free_qp(struct irdma_puda_rsrc * rsrc)866cdcd52d4SBartosz Sobczak irdma_puda_free_qp(struct irdma_puda_rsrc *rsrc)
867cdcd52d4SBartosz Sobczak {
868cdcd52d4SBartosz Sobczak 	int ret;
869cdcd52d4SBartosz Sobczak 	struct irdma_ccq_cqe_info compl_info;
870cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = rsrc->dev;
871cdcd52d4SBartosz Sobczak 
872cdcd52d4SBartosz Sobczak 	if (rsrc->dev->ceq_valid) {
873cdcd52d4SBartosz Sobczak 		irdma_cqp_qp_destroy_cmd(dev, &rsrc->qp);
874cdcd52d4SBartosz Sobczak 		rsrc->dev->ws_remove(rsrc->qp.vsi, rsrc->qp.user_pri);
875cdcd52d4SBartosz Sobczak 		return;
876cdcd52d4SBartosz Sobczak 	}
877cdcd52d4SBartosz Sobczak 
878cdcd52d4SBartosz Sobczak 	ret = irdma_sc_qp_destroy(&rsrc->qp, 0, false, true, true);
879cdcd52d4SBartosz Sobczak 	if (ret)
880cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA,
881cdcd52d4SBartosz Sobczak 			    "error puda qp destroy wqe, status = %d\n", ret);
882cdcd52d4SBartosz Sobczak 	if (!ret) {
883cdcd52d4SBartosz Sobczak 		ret = irdma_sc_poll_for_cqp_op_done(dev->cqp, IRDMA_CQP_OP_DESTROY_QP,
884cdcd52d4SBartosz Sobczak 						    &compl_info);
885cdcd52d4SBartosz Sobczak 		if (ret)
886cdcd52d4SBartosz Sobczak 			irdma_debug(dev, IRDMA_DEBUG_PUDA,
887cdcd52d4SBartosz Sobczak 				    "error puda qp destroy failed, status = %d\n",
888cdcd52d4SBartosz Sobczak 				    ret);
889cdcd52d4SBartosz Sobczak 	}
890cdcd52d4SBartosz Sobczak 	rsrc->dev->ws_remove(rsrc->qp.vsi, rsrc->qp.user_pri);
891cdcd52d4SBartosz Sobczak }
892cdcd52d4SBartosz Sobczak 
893cdcd52d4SBartosz Sobczak /**
894cdcd52d4SBartosz Sobczak  * irdma_puda_free_cq - free cq for resource
895cdcd52d4SBartosz Sobczak  * @rsrc: resource for which cq to free
896cdcd52d4SBartosz Sobczak  */
897cdcd52d4SBartosz Sobczak static void
irdma_puda_free_cq(struct irdma_puda_rsrc * rsrc)898cdcd52d4SBartosz Sobczak irdma_puda_free_cq(struct irdma_puda_rsrc *rsrc)
899cdcd52d4SBartosz Sobczak {
900cdcd52d4SBartosz Sobczak 	int ret;
901cdcd52d4SBartosz Sobczak 	struct irdma_ccq_cqe_info compl_info;
902cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = rsrc->dev;
903cdcd52d4SBartosz Sobczak 
904cdcd52d4SBartosz Sobczak 	if (rsrc->dev->ceq_valid) {
905cdcd52d4SBartosz Sobczak 		irdma_cqp_cq_destroy_cmd(dev, &rsrc->cq);
906cdcd52d4SBartosz Sobczak 		return;
907cdcd52d4SBartosz Sobczak 	}
908cdcd52d4SBartosz Sobczak 
909cdcd52d4SBartosz Sobczak 	ret = irdma_sc_cq_destroy(&rsrc->cq, 0, true);
910cdcd52d4SBartosz Sobczak 	if (ret)
911cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "error ieq cq destroy\n");
912cdcd52d4SBartosz Sobczak 	if (!ret) {
913cdcd52d4SBartosz Sobczak 		ret = irdma_sc_poll_for_cqp_op_done(dev->cqp, IRDMA_CQP_OP_DESTROY_CQ,
914cdcd52d4SBartosz Sobczak 						    &compl_info);
915cdcd52d4SBartosz Sobczak 		if (ret)
916cdcd52d4SBartosz Sobczak 			irdma_debug(dev, IRDMA_DEBUG_PUDA,
917cdcd52d4SBartosz Sobczak 				    "error ieq qp destroy done\n");
918cdcd52d4SBartosz Sobczak 	}
919cdcd52d4SBartosz Sobczak }
920cdcd52d4SBartosz Sobczak 
921cdcd52d4SBartosz Sobczak /**
922cdcd52d4SBartosz Sobczak  * irdma_puda_dele_rsrc - delete all resources during close
923cdcd52d4SBartosz Sobczak  * @vsi: VSI structure of device
924cdcd52d4SBartosz Sobczak  * @type: type of resource to dele
925cdcd52d4SBartosz Sobczak  * @reset: true if reset chip
926cdcd52d4SBartosz Sobczak  */
927cdcd52d4SBartosz Sobczak void
irdma_puda_dele_rsrc(struct irdma_sc_vsi * vsi,enum puda_rsrc_type type,bool reset)928cdcd52d4SBartosz Sobczak irdma_puda_dele_rsrc(struct irdma_sc_vsi *vsi, enum puda_rsrc_type type,
929cdcd52d4SBartosz Sobczak 		     bool reset)
930cdcd52d4SBartosz Sobczak {
931cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = vsi->dev;
932cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *rsrc;
933cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf = NULL;
934cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *nextbuf = NULL;
935cdcd52d4SBartosz Sobczak 	struct irdma_virt_mem *vmem;
936cdcd52d4SBartosz Sobczak 	struct irdma_sc_ceq *ceq;
937cdcd52d4SBartosz Sobczak 
938cdcd52d4SBartosz Sobczak 	ceq = vsi->dev->ceq[0];
9395b5f7d0eSBartosz Sobczak 
940cdcd52d4SBartosz Sobczak 	switch (type) {
941cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_ILQ:
942cdcd52d4SBartosz Sobczak 		rsrc = vsi->ilq;
943cdcd52d4SBartosz Sobczak 		vmem = &vsi->ilq_mem;
944cdcd52d4SBartosz Sobczak 		vsi->ilq = NULL;
945cdcd52d4SBartosz Sobczak 		if (ceq && ceq->reg_cq)
946cdcd52d4SBartosz Sobczak 			irdma_sc_remove_cq_ctx(ceq, &rsrc->cq);
947cdcd52d4SBartosz Sobczak 		break;
948cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_IEQ:
949cdcd52d4SBartosz Sobczak 		rsrc = vsi->ieq;
950cdcd52d4SBartosz Sobczak 		vmem = &vsi->ieq_mem;
951cdcd52d4SBartosz Sobczak 		vsi->ieq = NULL;
952cdcd52d4SBartosz Sobczak 		if (ceq && ceq->reg_cq)
953cdcd52d4SBartosz Sobczak 			irdma_sc_remove_cq_ctx(ceq, &rsrc->cq);
954cdcd52d4SBartosz Sobczak 		break;
955cdcd52d4SBartosz Sobczak 	default:
956cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA,
957cdcd52d4SBartosz Sobczak 			    "error resource type = 0x%x\n", type);
958cdcd52d4SBartosz Sobczak 		return;
959cdcd52d4SBartosz Sobczak 	}
960cdcd52d4SBartosz Sobczak 
961cdcd52d4SBartosz Sobczak 	spin_lock_destroy(&rsrc->bufpool_lock);
962cdcd52d4SBartosz Sobczak 	switch (rsrc->cmpl) {
963cdcd52d4SBartosz Sobczak 	case PUDA_HASH_CRC_COMPLETE:
964cdcd52d4SBartosz Sobczak 		irdma_free_hash_desc(rsrc->hash_desc);
965cdcd52d4SBartosz Sobczak 		/* fallthrough */
966cdcd52d4SBartosz Sobczak 	case PUDA_QP_CREATED:
967cdcd52d4SBartosz Sobczak 		irdma_qp_rem_qos(&rsrc->qp);
968cdcd52d4SBartosz Sobczak 
969777e472cSBartosz Sobczak 		if (!reset)
970cdcd52d4SBartosz Sobczak 			irdma_puda_free_qp(rsrc);
971cdcd52d4SBartosz Sobczak 
972cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(dev->hw, &rsrc->qpmem);
973cdcd52d4SBartosz Sobczak 		/* fallthrough */
974cdcd52d4SBartosz Sobczak 	case PUDA_CQ_CREATED:
975777e472cSBartosz Sobczak 		if (!reset)
976cdcd52d4SBartosz Sobczak 			irdma_puda_free_cq(rsrc);
977cdcd52d4SBartosz Sobczak 
978cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(dev->hw, &rsrc->cqmem);
979cdcd52d4SBartosz Sobczak 		break;
980cdcd52d4SBartosz Sobczak 	default:
981cdcd52d4SBartosz Sobczak 		irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
982cdcd52d4SBartosz Sobczak 			    "error no resources\n");
983cdcd52d4SBartosz Sobczak 		break;
984cdcd52d4SBartosz Sobczak 	}
985cdcd52d4SBartosz Sobczak 	/* Free all allocated puda buffers for both tx and rx */
986cdcd52d4SBartosz Sobczak 	buf = rsrc->alloclist;
987cdcd52d4SBartosz Sobczak 	while (buf) {
988cdcd52d4SBartosz Sobczak 		nextbuf = buf->next;
989cdcd52d4SBartosz Sobczak 		irdma_puda_dele_buf(dev, buf);
990cdcd52d4SBartosz Sobczak 		buf = nextbuf;
991cdcd52d4SBartosz Sobczak 		rsrc->alloc_buf_count--;
992cdcd52d4SBartosz Sobczak 	}
993cdcd52d4SBartosz Sobczak 
994cdcd52d4SBartosz Sobczak 	kfree(vmem->va);
995cdcd52d4SBartosz Sobczak }
996cdcd52d4SBartosz Sobczak 
997cdcd52d4SBartosz Sobczak /**
998cdcd52d4SBartosz Sobczak  * irdma_puda_allocbufs - allocate buffers for resource
999cdcd52d4SBartosz Sobczak  * @rsrc: resource for buffer allocation
1000cdcd52d4SBartosz Sobczak  * @count: number of buffers to create
1001cdcd52d4SBartosz Sobczak  */
1002cdcd52d4SBartosz Sobczak static int
irdma_puda_allocbufs(struct irdma_puda_rsrc * rsrc,u32 count)1003cdcd52d4SBartosz Sobczak irdma_puda_allocbufs(struct irdma_puda_rsrc *rsrc, u32 count)
1004cdcd52d4SBartosz Sobczak {
1005cdcd52d4SBartosz Sobczak 	u32 i;
1006cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
1007cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *nextbuf;
1008cdcd52d4SBartosz Sobczak 	struct irdma_virt_mem buf_mem;
1009cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem *dma_mem;
1010cdcd52d4SBartosz Sobczak 	bool virtdma = false;
1011cdcd52d4SBartosz Sobczak 	unsigned long flags;
1012cdcd52d4SBartosz Sobczak 
10135b5f7d0eSBartosz Sobczak 	buf_mem.size = count * sizeof(*buf);
1014777e472cSBartosz Sobczak 	buf_mem.va = kzalloc(buf_mem.size, GFP_KERNEL);
1015cdcd52d4SBartosz Sobczak 	if (!buf_mem.va) {
1016cdcd52d4SBartosz Sobczak 		irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
1017cdcd52d4SBartosz Sobczak 			    "error virt_mem for buf\n");
1018cdcd52d4SBartosz Sobczak 		rsrc->stats_buf_alloc_fail++;
1019cdcd52d4SBartosz Sobczak 		goto trysmall;
1020cdcd52d4SBartosz Sobczak 	}
1021cdcd52d4SBartosz Sobczak 
1022cdcd52d4SBartosz Sobczak 	/*
1023cdcd52d4SBartosz Sobczak 	 * Allocate the large dma chunk and setup dma attributes into first puda buffer. This is required during free
1024cdcd52d4SBartosz Sobczak 	 */
1025cdcd52d4SBartosz Sobczak 	buf = (struct irdma_puda_buf *)buf_mem.va;
1026cdcd52d4SBartosz Sobczak 	buf->mem.va = irdma_allocate_dma_mem(rsrc->dev->hw, &buf->mem,
1027cdcd52d4SBartosz Sobczak 					     rsrc->buf_size * count, 1);
1028cdcd52d4SBartosz Sobczak 	if (!buf->mem.va) {
1029cdcd52d4SBartosz Sobczak 		irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA,
1030cdcd52d4SBartosz Sobczak 			    "error dma_mem for buf\n");
1031cdcd52d4SBartosz Sobczak 		kfree(buf_mem.va);
1032cdcd52d4SBartosz Sobczak 		rsrc->stats_buf_alloc_fail++;
1033cdcd52d4SBartosz Sobczak 		goto trysmall;
1034cdcd52d4SBartosz Sobczak 	}
1035cdcd52d4SBartosz Sobczak 
1036cdcd52d4SBartosz Sobczak 	/*
1037cdcd52d4SBartosz Sobczak 	 * dma_mem points to start of the large DMA chunk
1038cdcd52d4SBartosz Sobczak 	 */
1039cdcd52d4SBartosz Sobczak 	dma_mem = &buf->mem;
1040cdcd52d4SBartosz Sobczak 
1041cdcd52d4SBartosz Sobczak 	spin_lock_irqsave(&rsrc->bufpool_lock, flags);
1042cdcd52d4SBartosz Sobczak 	for (i = 0; i < count; i++) {
1043cdcd52d4SBartosz Sobczak 		buf = ((struct irdma_puda_buf *)buf_mem.va) + i;
1044cdcd52d4SBartosz Sobczak 
1045cdcd52d4SBartosz Sobczak 		buf->mem.va = (char *)dma_mem->va + (i * rsrc->buf_size);
1046cdcd52d4SBartosz Sobczak 		buf->mem.pa = dma_mem->pa + (i * rsrc->buf_size);
1047cdcd52d4SBartosz Sobczak 		buf->mem.size = rsrc->buf_size;
1048cdcd52d4SBartosz Sobczak 		buf->virtdma = virtdma;
1049cdcd52d4SBartosz Sobczak 		virtdma = true;
1050cdcd52d4SBartosz Sobczak 
1051cdcd52d4SBartosz Sobczak 		buf->buf_mem.va = buf_mem.va;
1052cdcd52d4SBartosz Sobczak 		buf->buf_mem.size = buf_mem.size;
1053cdcd52d4SBartosz Sobczak 
1054cdcd52d4SBartosz Sobczak 		list_add(&buf->list, &rsrc->bufpool);
1055cdcd52d4SBartosz Sobczak 		rsrc->alloc_buf_count++;
1056cdcd52d4SBartosz Sobczak 		if (!rsrc->alloclist) {
1057cdcd52d4SBartosz Sobczak 			rsrc->alloclist = buf;
1058cdcd52d4SBartosz Sobczak 		} else {
1059cdcd52d4SBartosz Sobczak 			nextbuf = rsrc->alloclist;
1060cdcd52d4SBartosz Sobczak 			rsrc->alloclist = buf;
1061cdcd52d4SBartosz Sobczak 			buf->next = nextbuf;
1062cdcd52d4SBartosz Sobczak 		}
1063cdcd52d4SBartosz Sobczak 	}
1064cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
1065cdcd52d4SBartosz Sobczak 
1066cdcd52d4SBartosz Sobczak 	rsrc->avail_buf_count = rsrc->alloc_buf_count;
1067cdcd52d4SBartosz Sobczak 	return 0;
1068cdcd52d4SBartosz Sobczak trysmall:
1069cdcd52d4SBartosz Sobczak 	for (i = 0; i < count; i++) {
1070cdcd52d4SBartosz Sobczak 		buf = irdma_puda_alloc_buf(rsrc->dev, rsrc->buf_size);
1071cdcd52d4SBartosz Sobczak 		if (!buf) {
1072cdcd52d4SBartosz Sobczak 			rsrc->stats_buf_alloc_fail++;
1073cdcd52d4SBartosz Sobczak 			return -ENOMEM;
1074cdcd52d4SBartosz Sobczak 		}
1075cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(rsrc, buf);
1076cdcd52d4SBartosz Sobczak 		rsrc->alloc_buf_count++;
1077cdcd52d4SBartosz Sobczak 		if (!rsrc->alloclist) {
1078cdcd52d4SBartosz Sobczak 			rsrc->alloclist = buf;
1079cdcd52d4SBartosz Sobczak 		} else {
1080cdcd52d4SBartosz Sobczak 			nextbuf = rsrc->alloclist;
1081cdcd52d4SBartosz Sobczak 			rsrc->alloclist = buf;
1082cdcd52d4SBartosz Sobczak 			buf->next = nextbuf;
1083cdcd52d4SBartosz Sobczak 		}
1084cdcd52d4SBartosz Sobczak 	}
1085cdcd52d4SBartosz Sobczak 
1086cdcd52d4SBartosz Sobczak 	rsrc->avail_buf_count = rsrc->alloc_buf_count;
1087cdcd52d4SBartosz Sobczak 
1088cdcd52d4SBartosz Sobczak 	return 0;
1089cdcd52d4SBartosz Sobczak }
1090cdcd52d4SBartosz Sobczak 
1091cdcd52d4SBartosz Sobczak /**
1092cdcd52d4SBartosz Sobczak  * irdma_puda_create_rsrc - create resource (ilq or ieq)
1093cdcd52d4SBartosz Sobczak  * @vsi: sc VSI struct
1094cdcd52d4SBartosz Sobczak  * @info: resource information
1095cdcd52d4SBartosz Sobczak  */
1096cdcd52d4SBartosz Sobczak int
irdma_puda_create_rsrc(struct irdma_sc_vsi * vsi,struct irdma_puda_rsrc_info * info)1097cdcd52d4SBartosz Sobczak irdma_puda_create_rsrc(struct irdma_sc_vsi *vsi,
1098cdcd52d4SBartosz Sobczak 		       struct irdma_puda_rsrc_info *info)
1099cdcd52d4SBartosz Sobczak {
1100cdcd52d4SBartosz Sobczak 	struct irdma_sc_dev *dev = vsi->dev;
1101cdcd52d4SBartosz Sobczak 	int ret = 0;
1102cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *rsrc;
1103cdcd52d4SBartosz Sobczak 	u32 pudasize;
1104cdcd52d4SBartosz Sobczak 	u32 sqwridsize, rqwridsize;
1105cdcd52d4SBartosz Sobczak 	struct irdma_virt_mem *vmem;
1106cdcd52d4SBartosz Sobczak 
1107cdcd52d4SBartosz Sobczak 	info->count = 1;
11085b5f7d0eSBartosz Sobczak 	pudasize = sizeof(*rsrc);
1109cdcd52d4SBartosz Sobczak 	sqwridsize = info->sq_size * sizeof(struct irdma_sq_uk_wr_trk_info);
1110cdcd52d4SBartosz Sobczak 	rqwridsize = info->rq_size * 8;
1111cdcd52d4SBartosz Sobczak 	switch (info->type) {
1112cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_ILQ:
1113cdcd52d4SBartosz Sobczak 		vmem = &vsi->ilq_mem;
1114cdcd52d4SBartosz Sobczak 		break;
1115cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_IEQ:
1116cdcd52d4SBartosz Sobczak 		vmem = &vsi->ieq_mem;
1117cdcd52d4SBartosz Sobczak 		break;
1118cdcd52d4SBartosz Sobczak 	default:
1119cdcd52d4SBartosz Sobczak 		return -EOPNOTSUPP;
1120cdcd52d4SBartosz Sobczak 	}
1121cdcd52d4SBartosz Sobczak 	vmem->size = pudasize + sqwridsize + rqwridsize;
1122777e472cSBartosz Sobczak 	vmem->va = kzalloc(vmem->size, GFP_KERNEL);
1123cdcd52d4SBartosz Sobczak 	if (!vmem->va)
1124cdcd52d4SBartosz Sobczak 		return -ENOMEM;
1125cdcd52d4SBartosz Sobczak 
1126cdcd52d4SBartosz Sobczak 	rsrc = vmem->va;
1127cdcd52d4SBartosz Sobczak 	spin_lock_init(&rsrc->bufpool_lock);
1128cdcd52d4SBartosz Sobczak 	switch (info->type) {
1129cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_ILQ:
1130cdcd52d4SBartosz Sobczak 		vsi->ilq = vmem->va;
1131cdcd52d4SBartosz Sobczak 		vsi->ilq_count = info->count;
1132cdcd52d4SBartosz Sobczak 		rsrc->receive = info->receive;
1133cdcd52d4SBartosz Sobczak 		rsrc->xmit_complete = info->xmit_complete;
1134cdcd52d4SBartosz Sobczak 		break;
1135cdcd52d4SBartosz Sobczak 	case IRDMA_PUDA_RSRC_TYPE_IEQ:
1136cdcd52d4SBartosz Sobczak 		vsi->ieq_count = info->count;
1137cdcd52d4SBartosz Sobczak 		vsi->ieq = vmem->va;
1138cdcd52d4SBartosz Sobczak 		rsrc->receive = irdma_ieq_receive;
1139cdcd52d4SBartosz Sobczak 		rsrc->xmit_complete = irdma_ieq_tx_compl;
1140cdcd52d4SBartosz Sobczak 		break;
1141cdcd52d4SBartosz Sobczak 	default:
1142cdcd52d4SBartosz Sobczak 		return -EOPNOTSUPP;
1143cdcd52d4SBartosz Sobczak 	}
1144cdcd52d4SBartosz Sobczak 
1145cdcd52d4SBartosz Sobczak 	rsrc->type = info->type;
1146cdcd52d4SBartosz Sobczak 	rsrc->sq_wrtrk_array = (struct irdma_sq_uk_wr_trk_info *)
1147cdcd52d4SBartosz Sobczak 	    ((u8 *)vmem->va + pudasize);
1148cdcd52d4SBartosz Sobczak 	rsrc->rq_wrid_array = (u64 *)((u8 *)vmem->va + pudasize + sqwridsize);
1149cdcd52d4SBartosz Sobczak 	/* Initialize all ieq lists */
1150cdcd52d4SBartosz Sobczak 	INIT_LIST_HEAD(&rsrc->bufpool);
1151cdcd52d4SBartosz Sobczak 	INIT_LIST_HEAD(&rsrc->txpend);
1152cdcd52d4SBartosz Sobczak 
1153cdcd52d4SBartosz Sobczak 	rsrc->tx_wqe_avail_cnt = info->sq_size - 1;
1154cdcd52d4SBartosz Sobczak 	irdma_sc_pd_init(dev, &rsrc->sc_pd, info->pd_id, info->abi_ver);
1155cdcd52d4SBartosz Sobczak 	rsrc->qp_id = info->qp_id;
1156cdcd52d4SBartosz Sobczak 	rsrc->cq_id = info->cq_id;
1157cdcd52d4SBartosz Sobczak 	rsrc->sq_size = info->sq_size;
1158cdcd52d4SBartosz Sobczak 	rsrc->rq_size = info->rq_size;
1159cdcd52d4SBartosz Sobczak 	rsrc->cq_size = info->rq_size + info->sq_size;
1160cdcd52d4SBartosz Sobczak 	if (dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1161cdcd52d4SBartosz Sobczak 		if (rsrc->type == IRDMA_PUDA_RSRC_TYPE_ILQ)
1162cdcd52d4SBartosz Sobczak 			rsrc->cq_size += info->rq_size;
1163cdcd52d4SBartosz Sobczak 	}
1164cdcd52d4SBartosz Sobczak 	rsrc->buf_size = info->buf_size;
1165cdcd52d4SBartosz Sobczak 	rsrc->dev = dev;
1166cdcd52d4SBartosz Sobczak 	rsrc->vsi = vsi;
1167cdcd52d4SBartosz Sobczak 	rsrc->stats_idx = info->stats_idx;
1168cdcd52d4SBartosz Sobczak 	rsrc->stats_idx_valid = info->stats_idx_valid;
1169cdcd52d4SBartosz Sobczak 
1170cdcd52d4SBartosz Sobczak 	ret = irdma_puda_cq_create(rsrc);
1171cdcd52d4SBartosz Sobczak 	if (!ret) {
1172cdcd52d4SBartosz Sobczak 		rsrc->cmpl = PUDA_CQ_CREATED;
1173cdcd52d4SBartosz Sobczak 		ret = irdma_puda_qp_create(rsrc);
1174cdcd52d4SBartosz Sobczak 	}
1175cdcd52d4SBartosz Sobczak 	if (ret) {
1176cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA,
1177cdcd52d4SBartosz Sobczak 			    "error qp_create type=%d, status=%d\n", rsrc->type,
1178cdcd52d4SBartosz Sobczak 			    ret);
1179cdcd52d4SBartosz Sobczak 		goto error;
1180cdcd52d4SBartosz Sobczak 	}
1181cdcd52d4SBartosz Sobczak 	rsrc->cmpl = PUDA_QP_CREATED;
1182cdcd52d4SBartosz Sobczak 
1183cdcd52d4SBartosz Sobczak 	ret = irdma_puda_allocbufs(rsrc, info->tx_buf_cnt + info->rq_size);
1184cdcd52d4SBartosz Sobczak 	if (ret) {
1185cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_PUDA, "error alloc_buf\n");
1186cdcd52d4SBartosz Sobczak 		goto error;
1187cdcd52d4SBartosz Sobczak 	}
1188cdcd52d4SBartosz Sobczak 
1189cdcd52d4SBartosz Sobczak 	rsrc->rxq_invalid_cnt = info->rq_size;
1190cdcd52d4SBartosz Sobczak 	ret = irdma_puda_replenish_rq(rsrc, true);
1191cdcd52d4SBartosz Sobczak 	if (ret)
1192cdcd52d4SBartosz Sobczak 		goto error;
1193cdcd52d4SBartosz Sobczak 
1194cdcd52d4SBartosz Sobczak 	if (info->type == IRDMA_PUDA_RSRC_TYPE_IEQ) {
1195cdcd52d4SBartosz Sobczak 		if (!irdma_init_hash_desc(&rsrc->hash_desc)) {
1196cdcd52d4SBartosz Sobczak 			rsrc->check_crc = true;
1197cdcd52d4SBartosz Sobczak 			rsrc->cmpl = PUDA_HASH_CRC_COMPLETE;
1198cdcd52d4SBartosz Sobczak 			ret = 0;
1199cdcd52d4SBartosz Sobczak 		}
1200cdcd52d4SBartosz Sobczak 	}
1201cdcd52d4SBartosz Sobczak 
1202cdcd52d4SBartosz Sobczak 	irdma_sc_ccq_arm(&rsrc->cq);
1203cdcd52d4SBartosz Sobczak 	return ret;
1204cdcd52d4SBartosz Sobczak 
1205cdcd52d4SBartosz Sobczak error:
1206cdcd52d4SBartosz Sobczak 	irdma_puda_dele_rsrc(vsi, info->type, false);
1207cdcd52d4SBartosz Sobczak 
1208cdcd52d4SBartosz Sobczak 	return ret;
1209cdcd52d4SBartosz Sobczak }
1210cdcd52d4SBartosz Sobczak 
1211cdcd52d4SBartosz Sobczak /**
1212cdcd52d4SBartosz Sobczak  * irdma_ilq_putback_rcvbuf - ilq buffer to put back on rq
1213cdcd52d4SBartosz Sobczak  * @qp: ilq's qp resource
1214cdcd52d4SBartosz Sobczak  * @buf: puda buffer for rcv q
1215cdcd52d4SBartosz Sobczak  * @wqe_idx:  wqe index of completed rcvbuf
1216cdcd52d4SBartosz Sobczak  */
1217cdcd52d4SBartosz Sobczak static void
irdma_ilq_putback_rcvbuf(struct irdma_sc_qp * qp,struct irdma_puda_buf * buf,u32 wqe_idx)1218cdcd52d4SBartosz Sobczak irdma_ilq_putback_rcvbuf(struct irdma_sc_qp *qp,
1219cdcd52d4SBartosz Sobczak 			 struct irdma_puda_buf *buf, u32 wqe_idx)
1220cdcd52d4SBartosz Sobczak {
1221cdcd52d4SBartosz Sobczak 	__le64 *wqe;
1222cdcd52d4SBartosz Sobczak 	u64 offset8, offset24;
1223cdcd52d4SBartosz Sobczak 
1224cdcd52d4SBartosz Sobczak 	/* Synch buffer for use by device */
1225cdcd52d4SBartosz Sobczak 	dma_sync_single_for_device(hw_to_dev(qp->dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL);
1226cdcd52d4SBartosz Sobczak 	wqe = qp->qp_uk.rq_base[wqe_idx].elem;
1227cdcd52d4SBartosz Sobczak 	get_64bit_val(wqe, IRDMA_BYTE_24, &offset24);
1228cdcd52d4SBartosz Sobczak 	if (qp->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1229cdcd52d4SBartosz Sobczak 		get_64bit_val(wqe, IRDMA_BYTE_8, &offset8);
1230cdcd52d4SBartosz Sobczak 		if (offset24)
1231777e472cSBartosz Sobczak 			offset8 &= ~FIELD_PREP(IRDMAQPSQ_VALID, 1);
1232cdcd52d4SBartosz Sobczak 		else
1233777e472cSBartosz Sobczak 			offset8 |= FIELD_PREP(IRDMAQPSQ_VALID, 1);
1234cdcd52d4SBartosz Sobczak 		set_64bit_val(wqe, IRDMA_BYTE_8, offset8);
1235cdcd52d4SBartosz Sobczak 		irdma_wmb();	/* make sure WQE is written before valid bit is set */
1236cdcd52d4SBartosz Sobczak 	}
1237cdcd52d4SBartosz Sobczak 	if (offset24)
1238cdcd52d4SBartosz Sobczak 		offset24 = 0;
1239cdcd52d4SBartosz Sobczak 	else
1240777e472cSBartosz Sobczak 		offset24 = FIELD_PREP(IRDMAQPSQ_VALID, 1);
1241cdcd52d4SBartosz Sobczak 
1242cdcd52d4SBartosz Sobczak 	set_64bit_val(wqe, IRDMA_BYTE_24, offset24);
1243cdcd52d4SBartosz Sobczak }
1244cdcd52d4SBartosz Sobczak 
1245cdcd52d4SBartosz Sobczak /**
1246cdcd52d4SBartosz Sobczak  * irdma_ieq_get_fpdu_len - get length of fpdu with or without marker
1247cdcd52d4SBartosz Sobczak  * @pfpdu: pointer to fpdu
1248cdcd52d4SBartosz Sobczak  * @datap: pointer to data in the buffer
1249cdcd52d4SBartosz Sobczak  * @rcv_seq: seqnum of the data buffer
1250cdcd52d4SBartosz Sobczak  */
irdma_ieq_get_fpdu_len(struct irdma_pfpdu * pfpdu,u8 * datap,u32 rcv_seq)1251cdcd52d4SBartosz Sobczak static u16 irdma_ieq_get_fpdu_len(struct irdma_pfpdu *pfpdu, u8 *datap,
1252cdcd52d4SBartosz Sobczak 				  u32 rcv_seq){
1253cdcd52d4SBartosz Sobczak 	u32 marker_seq, end_seq, blk_start;
1254cdcd52d4SBartosz Sobczak 	u8 marker_len = pfpdu->marker_len;
1255cdcd52d4SBartosz Sobczak 	u16 total_len = 0;
1256cdcd52d4SBartosz Sobczak 	u16 fpdu_len;
1257cdcd52d4SBartosz Sobczak 
1258cdcd52d4SBartosz Sobczak 	blk_start = (pfpdu->rcv_start_seq - rcv_seq) & (IRDMA_MRK_BLK_SZ - 1);
1259cdcd52d4SBartosz Sobczak 	if (!blk_start) {
1260cdcd52d4SBartosz Sobczak 		total_len = marker_len;
1261cdcd52d4SBartosz Sobczak 		marker_seq = rcv_seq + IRDMA_MRK_BLK_SZ;
1262cdcd52d4SBartosz Sobczak 		if (marker_len && *(u32 *)datap)
1263cdcd52d4SBartosz Sobczak 			return 0;
1264cdcd52d4SBartosz Sobczak 	} else {
1265cdcd52d4SBartosz Sobczak 		marker_seq = rcv_seq + blk_start;
1266cdcd52d4SBartosz Sobczak 	}
1267cdcd52d4SBartosz Sobczak 
1268cdcd52d4SBartosz Sobczak 	datap += total_len;
1269cdcd52d4SBartosz Sobczak 	fpdu_len = IRDMA_NTOHS(*(__be16 *) datap);
1270cdcd52d4SBartosz Sobczak 	fpdu_len += IRDMA_IEQ_MPA_FRAMING;
1271cdcd52d4SBartosz Sobczak 	fpdu_len = (fpdu_len + 3) & 0xfffc;
1272cdcd52d4SBartosz Sobczak 
1273cdcd52d4SBartosz Sobczak 	if (fpdu_len > pfpdu->max_fpdu_data)
1274cdcd52d4SBartosz Sobczak 		return 0;
1275cdcd52d4SBartosz Sobczak 
1276cdcd52d4SBartosz Sobczak 	total_len += fpdu_len;
1277cdcd52d4SBartosz Sobczak 	end_seq = rcv_seq + total_len;
1278cdcd52d4SBartosz Sobczak 	while ((int)(marker_seq - end_seq) < 0) {
1279cdcd52d4SBartosz Sobczak 		total_len += marker_len;
1280cdcd52d4SBartosz Sobczak 		end_seq += marker_len;
1281cdcd52d4SBartosz Sobczak 		marker_seq += IRDMA_MRK_BLK_SZ;
1282cdcd52d4SBartosz Sobczak 	}
1283cdcd52d4SBartosz Sobczak 
1284cdcd52d4SBartosz Sobczak 	return total_len;
1285cdcd52d4SBartosz Sobczak }
1286cdcd52d4SBartosz Sobczak 
1287cdcd52d4SBartosz Sobczak /**
1288cdcd52d4SBartosz Sobczak  * irdma_ieq_copy_to_txbuf - copydata from rcv buf to tx buf
1289cdcd52d4SBartosz Sobczak  * @buf: rcv buffer with partial
1290cdcd52d4SBartosz Sobczak  * @txbuf: tx buffer for sending back
1291cdcd52d4SBartosz Sobczak  * @buf_offset: rcv buffer offset to copy from
1292cdcd52d4SBartosz Sobczak  * @txbuf_offset: at offset in tx buf to copy
1293cdcd52d4SBartosz Sobczak  * @len: length of data to copy
1294cdcd52d4SBartosz Sobczak  */
1295cdcd52d4SBartosz Sobczak static void
irdma_ieq_copy_to_txbuf(struct irdma_puda_buf * buf,struct irdma_puda_buf * txbuf,u16 buf_offset,u32 txbuf_offset,u32 len)1296cdcd52d4SBartosz Sobczak irdma_ieq_copy_to_txbuf(struct irdma_puda_buf *buf,
1297cdcd52d4SBartosz Sobczak 			struct irdma_puda_buf *txbuf,
1298cdcd52d4SBartosz Sobczak 			u16 buf_offset, u32 txbuf_offset, u32 len)
1299cdcd52d4SBartosz Sobczak {
1300cdcd52d4SBartosz Sobczak 	void *mem1 = (u8 *)buf->mem.va + buf_offset;
1301cdcd52d4SBartosz Sobczak 	void *mem2 = (u8 *)txbuf->mem.va + txbuf_offset;
1302cdcd52d4SBartosz Sobczak 
1303cdcd52d4SBartosz Sobczak 	irdma_memcpy(mem2, mem1, len);
1304cdcd52d4SBartosz Sobczak }
1305cdcd52d4SBartosz Sobczak 
1306cdcd52d4SBartosz Sobczak /**
1307cdcd52d4SBartosz Sobczak  * irdma_ieq_setup_tx_buf - setup tx buffer for partial handling
1308cdcd52d4SBartosz Sobczak  * @buf: reeive buffer with partial
1309cdcd52d4SBartosz Sobczak  * @txbuf: buffer to prepare
1310cdcd52d4SBartosz Sobczak  */
1311cdcd52d4SBartosz Sobczak static void
irdma_ieq_setup_tx_buf(struct irdma_puda_buf * buf,struct irdma_puda_buf * txbuf)1312cdcd52d4SBartosz Sobczak irdma_ieq_setup_tx_buf(struct irdma_puda_buf *buf,
1313cdcd52d4SBartosz Sobczak 		       struct irdma_puda_buf *txbuf)
1314cdcd52d4SBartosz Sobczak {
1315cdcd52d4SBartosz Sobczak 	txbuf->tcphlen = buf->tcphlen;
1316cdcd52d4SBartosz Sobczak 	txbuf->ipv4 = buf->ipv4;
1317cdcd52d4SBartosz Sobczak 
1318cdcd52d4SBartosz Sobczak 	if (buf->vsi->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1319cdcd52d4SBartosz Sobczak 		txbuf->hdrlen = txbuf->tcphlen;
1320cdcd52d4SBartosz Sobczak 		irdma_ieq_copy_to_txbuf(buf, txbuf, IRDMA_TCP_OFFSET, 0,
1321cdcd52d4SBartosz Sobczak 					txbuf->hdrlen);
1322cdcd52d4SBartosz Sobczak 	} else {
1323cdcd52d4SBartosz Sobczak 		txbuf->maclen = buf->maclen;
1324cdcd52d4SBartosz Sobczak 		txbuf->hdrlen = buf->hdrlen;
1325cdcd52d4SBartosz Sobczak 		irdma_ieq_copy_to_txbuf(buf, txbuf, 0, 0, buf->hdrlen);
1326cdcd52d4SBartosz Sobczak 	}
1327cdcd52d4SBartosz Sobczak }
1328cdcd52d4SBartosz Sobczak 
1329cdcd52d4SBartosz Sobczak /**
1330cdcd52d4SBartosz Sobczak  * irdma_ieq_check_first_buf - check if rcv buffer's seq is in range
1331cdcd52d4SBartosz Sobczak  * @buf: receive exception buffer
1332cdcd52d4SBartosz Sobczak  * @fps: first partial sequence number
1333cdcd52d4SBartosz Sobczak  */
1334cdcd52d4SBartosz Sobczak static void
irdma_ieq_check_first_buf(struct irdma_puda_buf * buf,u32 fps)1335cdcd52d4SBartosz Sobczak irdma_ieq_check_first_buf(struct irdma_puda_buf *buf, u32 fps)
1336cdcd52d4SBartosz Sobczak {
1337cdcd52d4SBartosz Sobczak 	u32 offset;
1338cdcd52d4SBartosz Sobczak 
1339cdcd52d4SBartosz Sobczak 	if (buf->seqnum < fps) {
1340cdcd52d4SBartosz Sobczak 		offset = fps - buf->seqnum;
1341cdcd52d4SBartosz Sobczak 		if (offset > buf->datalen)
1342cdcd52d4SBartosz Sobczak 			return;
1343cdcd52d4SBartosz Sobczak 		buf->data += offset;
1344cdcd52d4SBartosz Sobczak 		buf->datalen -= (u16)offset;
1345cdcd52d4SBartosz Sobczak 		buf->seqnum = fps;
1346cdcd52d4SBartosz Sobczak 	}
1347cdcd52d4SBartosz Sobczak }
1348cdcd52d4SBartosz Sobczak 
1349cdcd52d4SBartosz Sobczak /**
1350cdcd52d4SBartosz Sobczak  * irdma_ieq_compl_pfpdu - write txbuf with full fpdu
1351cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1352cdcd52d4SBartosz Sobczak  * @rxlist: ieq's received buffer list
1353cdcd52d4SBartosz Sobczak  * @pbufl: temporary list for buffers for fpddu
1354cdcd52d4SBartosz Sobczak  * @txbuf: tx buffer for fpdu
1355cdcd52d4SBartosz Sobczak  * @fpdu_len: total length of fpdu
1356cdcd52d4SBartosz Sobczak  */
1357cdcd52d4SBartosz Sobczak static void
irdma_ieq_compl_pfpdu(struct irdma_puda_rsrc * ieq,struct list_head * rxlist,struct list_head * pbufl,struct irdma_puda_buf * txbuf,u16 fpdu_len)1358cdcd52d4SBartosz Sobczak irdma_ieq_compl_pfpdu(struct irdma_puda_rsrc *ieq,
1359cdcd52d4SBartosz Sobczak 		      struct list_head *rxlist,
1360cdcd52d4SBartosz Sobczak 		      struct list_head *pbufl,
1361cdcd52d4SBartosz Sobczak 		      struct irdma_puda_buf *txbuf, u16 fpdu_len)
1362cdcd52d4SBartosz Sobczak {
1363cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
1364cdcd52d4SBartosz Sobczak 	u32 nextseqnum;
1365cdcd52d4SBartosz Sobczak 	u16 txoffset, bufoffset;
1366cdcd52d4SBartosz Sobczak 
1367cdcd52d4SBartosz Sobczak 	buf = irdma_puda_get_listbuf(pbufl);
1368cdcd52d4SBartosz Sobczak 	if (!buf)
1369cdcd52d4SBartosz Sobczak 		return;
1370cdcd52d4SBartosz Sobczak 
1371cdcd52d4SBartosz Sobczak 	nextseqnum = buf->seqnum + fpdu_len;
1372cdcd52d4SBartosz Sobczak 	irdma_ieq_setup_tx_buf(buf, txbuf);
1373cdcd52d4SBartosz Sobczak 	if (buf->vsi->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1374cdcd52d4SBartosz Sobczak 		txoffset = txbuf->hdrlen;
1375cdcd52d4SBartosz Sobczak 		txbuf->totallen = txbuf->hdrlen + fpdu_len;
1376cdcd52d4SBartosz Sobczak 		txbuf->data = (u8 *)txbuf->mem.va + txoffset;
1377cdcd52d4SBartosz Sobczak 	} else {
1378cdcd52d4SBartosz Sobczak 		txoffset = buf->hdrlen;
1379cdcd52d4SBartosz Sobczak 		txbuf->totallen = buf->hdrlen + fpdu_len;
1380cdcd52d4SBartosz Sobczak 		txbuf->data = (u8 *)txbuf->mem.va + buf->hdrlen;
1381cdcd52d4SBartosz Sobczak 	}
1382cdcd52d4SBartosz Sobczak 	bufoffset = (u16)(buf->data - (u8 *)buf->mem.va);
1383cdcd52d4SBartosz Sobczak 
1384cdcd52d4SBartosz Sobczak 	do {
1385cdcd52d4SBartosz Sobczak 		if (buf->datalen >= fpdu_len) {
1386cdcd52d4SBartosz Sobczak 			/* copied full fpdu */
1387cdcd52d4SBartosz Sobczak 			irdma_ieq_copy_to_txbuf(buf, txbuf, bufoffset, txoffset,
1388cdcd52d4SBartosz Sobczak 						fpdu_len);
1389cdcd52d4SBartosz Sobczak 			buf->datalen -= fpdu_len;
1390cdcd52d4SBartosz Sobczak 			buf->data += fpdu_len;
1391cdcd52d4SBartosz Sobczak 			buf->seqnum = nextseqnum;
1392cdcd52d4SBartosz Sobczak 			break;
1393cdcd52d4SBartosz Sobczak 		}
1394cdcd52d4SBartosz Sobczak 		/* copy partial fpdu */
1395cdcd52d4SBartosz Sobczak 		irdma_ieq_copy_to_txbuf(buf, txbuf, bufoffset, txoffset,
1396cdcd52d4SBartosz Sobczak 					buf->datalen);
1397cdcd52d4SBartosz Sobczak 		txoffset += buf->datalen;
1398cdcd52d4SBartosz Sobczak 		fpdu_len -= buf->datalen;
1399cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, buf);
1400cdcd52d4SBartosz Sobczak 		buf = irdma_puda_get_listbuf(pbufl);
1401cdcd52d4SBartosz Sobczak 		if (!buf)
1402cdcd52d4SBartosz Sobczak 			return;
1403cdcd52d4SBartosz Sobczak 
1404cdcd52d4SBartosz Sobczak 		bufoffset = (u16)(buf->data - (u8 *)buf->mem.va);
1405cdcd52d4SBartosz Sobczak 	} while (1);
1406cdcd52d4SBartosz Sobczak 
1407cdcd52d4SBartosz Sobczak 	/* last buffer on the list */
1408cdcd52d4SBartosz Sobczak 	if (buf->datalen)
1409cdcd52d4SBartosz Sobczak 		list_add(&buf->list, rxlist);
1410cdcd52d4SBartosz Sobczak 	else
1411cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, buf);
1412cdcd52d4SBartosz Sobczak }
1413cdcd52d4SBartosz Sobczak 
1414cdcd52d4SBartosz Sobczak /**
1415cdcd52d4SBartosz Sobczak  * irdma_ieq_create_pbufl - create buffer list for single fpdu
1416cdcd52d4SBartosz Sobczak  * @pfpdu: pointer to fpdu
1417cdcd52d4SBartosz Sobczak  * @rxlist: resource list for receive ieq buffes
1418cdcd52d4SBartosz Sobczak  * @pbufl: temp. list for buffers for fpddu
1419cdcd52d4SBartosz Sobczak  * @buf: first receive buffer
1420cdcd52d4SBartosz Sobczak  * @fpdu_len: total length of fpdu
1421cdcd52d4SBartosz Sobczak  */
1422cdcd52d4SBartosz Sobczak static int
irdma_ieq_create_pbufl(struct irdma_pfpdu * pfpdu,struct list_head * rxlist,struct list_head * pbufl,struct irdma_puda_buf * buf,u16 fpdu_len)1423cdcd52d4SBartosz Sobczak irdma_ieq_create_pbufl(struct irdma_pfpdu *pfpdu,
1424cdcd52d4SBartosz Sobczak 		       struct list_head *rxlist,
1425cdcd52d4SBartosz Sobczak 		       struct list_head *pbufl,
1426cdcd52d4SBartosz Sobczak 		       struct irdma_puda_buf *buf, u16 fpdu_len)
1427cdcd52d4SBartosz Sobczak {
1428cdcd52d4SBartosz Sobczak 	int status = 0;
1429cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *nextbuf;
1430cdcd52d4SBartosz Sobczak 	u32 nextseqnum;
1431cdcd52d4SBartosz Sobczak 	u16 plen = fpdu_len - buf->datalen;
1432cdcd52d4SBartosz Sobczak 	bool done = false;
1433cdcd52d4SBartosz Sobczak 
1434cdcd52d4SBartosz Sobczak 	nextseqnum = buf->seqnum + buf->datalen;
1435cdcd52d4SBartosz Sobczak 	do {
1436cdcd52d4SBartosz Sobczak 		nextbuf = irdma_puda_get_listbuf(rxlist);
1437cdcd52d4SBartosz Sobczak 		if (!nextbuf) {
1438cdcd52d4SBartosz Sobczak 			status = -ENOBUFS;
1439cdcd52d4SBartosz Sobczak 			break;
1440cdcd52d4SBartosz Sobczak 		}
1441cdcd52d4SBartosz Sobczak 		list_add_tail(&nextbuf->list, pbufl);
1442cdcd52d4SBartosz Sobczak 		if (nextbuf->seqnum != nextseqnum) {
1443cdcd52d4SBartosz Sobczak 			pfpdu->bad_seq_num++;
1444cdcd52d4SBartosz Sobczak 			status = -ERANGE;
1445cdcd52d4SBartosz Sobczak 			break;
1446cdcd52d4SBartosz Sobczak 		}
1447cdcd52d4SBartosz Sobczak 		if (nextbuf->datalen >= plen) {
1448cdcd52d4SBartosz Sobczak 			done = true;
1449cdcd52d4SBartosz Sobczak 		} else {
1450cdcd52d4SBartosz Sobczak 			plen -= nextbuf->datalen;
1451cdcd52d4SBartosz Sobczak 			nextseqnum = nextbuf->seqnum + nextbuf->datalen;
1452cdcd52d4SBartosz Sobczak 		}
1453cdcd52d4SBartosz Sobczak 
1454cdcd52d4SBartosz Sobczak 	} while (!done);
1455cdcd52d4SBartosz Sobczak 
1456cdcd52d4SBartosz Sobczak 	return status;
1457cdcd52d4SBartosz Sobczak }
1458cdcd52d4SBartosz Sobczak 
1459cdcd52d4SBartosz Sobczak /**
1460cdcd52d4SBartosz Sobczak  * irdma_ieq_handle_partial - process partial fpdu buffer
1461cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1462cdcd52d4SBartosz Sobczak  * @pfpdu: partial management per user qp
1463cdcd52d4SBartosz Sobczak  * @buf: receive buffer
1464cdcd52d4SBartosz Sobczak  * @fpdu_len: fpdu len in the buffer
1465cdcd52d4SBartosz Sobczak  */
1466cdcd52d4SBartosz Sobczak static int
irdma_ieq_handle_partial(struct irdma_puda_rsrc * ieq,struct irdma_pfpdu * pfpdu,struct irdma_puda_buf * buf,u16 fpdu_len)1467cdcd52d4SBartosz Sobczak irdma_ieq_handle_partial(struct irdma_puda_rsrc *ieq,
1468cdcd52d4SBartosz Sobczak 			 struct irdma_pfpdu *pfpdu,
1469cdcd52d4SBartosz Sobczak 			 struct irdma_puda_buf *buf, u16 fpdu_len)
1470cdcd52d4SBartosz Sobczak {
1471cdcd52d4SBartosz Sobczak 	int status = 0;
1472cdcd52d4SBartosz Sobczak 	u8 *crcptr;
1473cdcd52d4SBartosz Sobczak 	u32 mpacrc;
1474cdcd52d4SBartosz Sobczak 	u32 seqnum = buf->seqnum;
1475cdcd52d4SBartosz Sobczak 	struct list_head pbufl;	/* partial buffer list */
1476cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *txbuf = NULL;
1477cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1478cdcd52d4SBartosz Sobczak 
1479cdcd52d4SBartosz Sobczak 	ieq->partials_handled++;
1480cdcd52d4SBartosz Sobczak 
1481cdcd52d4SBartosz Sobczak 	INIT_LIST_HEAD(&pbufl);
1482cdcd52d4SBartosz Sobczak 	list_add(&buf->list, &pbufl);
1483cdcd52d4SBartosz Sobczak 
1484cdcd52d4SBartosz Sobczak 	status = irdma_ieq_create_pbufl(pfpdu, rxlist, &pbufl, buf, fpdu_len);
1485cdcd52d4SBartosz Sobczak 	if (status)
1486cdcd52d4SBartosz Sobczak 		goto error;
1487cdcd52d4SBartosz Sobczak 
1488cdcd52d4SBartosz Sobczak 	txbuf = irdma_puda_get_bufpool(ieq);
1489cdcd52d4SBartosz Sobczak 	if (!txbuf) {
1490cdcd52d4SBartosz Sobczak 		pfpdu->no_tx_bufs++;
1491cdcd52d4SBartosz Sobczak 		status = -ENOBUFS;
1492cdcd52d4SBartosz Sobczak 		goto error;
1493cdcd52d4SBartosz Sobczak 	}
1494cdcd52d4SBartosz Sobczak 
1495cdcd52d4SBartosz Sobczak 	irdma_ieq_compl_pfpdu(ieq, rxlist, &pbufl, txbuf, fpdu_len);
1496cdcd52d4SBartosz Sobczak 	irdma_ieq_update_tcpip_info(txbuf, fpdu_len, seqnum);
1497cdcd52d4SBartosz Sobczak 
1498cdcd52d4SBartosz Sobczak 	crcptr = txbuf->data + fpdu_len - 4;
1499cdcd52d4SBartosz Sobczak 	mpacrc = *(u32 *)crcptr;
1500cdcd52d4SBartosz Sobczak 	if (ieq->check_crc) {
1501cdcd52d4SBartosz Sobczak 		status = irdma_ieq_check_mpacrc(ieq->hash_desc, txbuf->data,
1502cdcd52d4SBartosz Sobczak 						(fpdu_len - 4), mpacrc);
1503cdcd52d4SBartosz Sobczak 		if (status) {
1504cdcd52d4SBartosz Sobczak 			irdma_debug(ieq->dev, IRDMA_DEBUG_IEQ,
1505cdcd52d4SBartosz Sobczak 				    "error bad crc\n");
1506cdcd52d4SBartosz Sobczak 			pfpdu->mpa_crc_err = true;
1507cdcd52d4SBartosz Sobczak 			goto error;
1508cdcd52d4SBartosz Sobczak 		}
1509cdcd52d4SBartosz Sobczak 	}
1510cdcd52d4SBartosz Sobczak 
1511cdcd52d4SBartosz Sobczak 	irdma_debug_buf(ieq->dev, IRDMA_DEBUG_IEQ, "IEQ TX BUFFER",
1512cdcd52d4SBartosz Sobczak 			txbuf->mem.va, txbuf->totallen);
1513cdcd52d4SBartosz Sobczak 	if (ieq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
1514cdcd52d4SBartosz Sobczak 		txbuf->ah_id = pfpdu->ah->ah_info.ah_idx;
1515cdcd52d4SBartosz Sobczak 	txbuf->do_lpb = true;
1516cdcd52d4SBartosz Sobczak 	irdma_puda_send_buf(ieq, txbuf);
1517cdcd52d4SBartosz Sobczak 	pfpdu->rcv_nxt = seqnum + fpdu_len;
1518cdcd52d4SBartosz Sobczak 	return status;
1519cdcd52d4SBartosz Sobczak 
1520cdcd52d4SBartosz Sobczak error:
1521cdcd52d4SBartosz Sobczak 	while (!list_empty(&pbufl)) {
1522cdcd52d4SBartosz Sobczak 		buf = (struct irdma_puda_buf *)(&pbufl)->prev;
152335105900SBartosz Sobczak 		list_move(&buf->list, rxlist);
1524cdcd52d4SBartosz Sobczak 	}
1525cdcd52d4SBartosz Sobczak 	if (txbuf)
1526cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, txbuf);
1527cdcd52d4SBartosz Sobczak 
1528cdcd52d4SBartosz Sobczak 	return status;
1529cdcd52d4SBartosz Sobczak }
1530cdcd52d4SBartosz Sobczak 
1531cdcd52d4SBartosz Sobczak /**
1532cdcd52d4SBartosz Sobczak  * irdma_ieq_process_buf - process buffer rcvd for ieq
1533cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1534cdcd52d4SBartosz Sobczak  * @pfpdu: partial management per user qp
1535cdcd52d4SBartosz Sobczak  * @buf: receive buffer
1536cdcd52d4SBartosz Sobczak  */
1537cdcd52d4SBartosz Sobczak static int
irdma_ieq_process_buf(struct irdma_puda_rsrc * ieq,struct irdma_pfpdu * pfpdu,struct irdma_puda_buf * buf)1538cdcd52d4SBartosz Sobczak irdma_ieq_process_buf(struct irdma_puda_rsrc *ieq,
1539cdcd52d4SBartosz Sobczak 		      struct irdma_pfpdu *pfpdu,
1540cdcd52d4SBartosz Sobczak 		      struct irdma_puda_buf *buf)
1541cdcd52d4SBartosz Sobczak {
1542cdcd52d4SBartosz Sobczak 	u16 fpdu_len = 0;
1543cdcd52d4SBartosz Sobczak 	u16 datalen = buf->datalen;
1544cdcd52d4SBartosz Sobczak 	u8 *datap = buf->data;
1545cdcd52d4SBartosz Sobczak 	u8 *crcptr;
1546cdcd52d4SBartosz Sobczak 	u16 ioffset = 0;
1547cdcd52d4SBartosz Sobczak 	u32 mpacrc;
1548cdcd52d4SBartosz Sobczak 	u32 seqnum = buf->seqnum;
1549cdcd52d4SBartosz Sobczak 	u16 len = 0;
1550cdcd52d4SBartosz Sobczak 	u16 full = 0;
1551cdcd52d4SBartosz Sobczak 	bool partial = false;
1552cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *txbuf;
1553cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1554cdcd52d4SBartosz Sobczak 	int ret = 0;
1555cdcd52d4SBartosz Sobczak 
1556cdcd52d4SBartosz Sobczak 	ioffset = (u16)(buf->data - (u8 *)buf->mem.va);
1557cdcd52d4SBartosz Sobczak 	while (datalen) {
1558cdcd52d4SBartosz Sobczak 		fpdu_len = irdma_ieq_get_fpdu_len(pfpdu, datap, buf->seqnum);
1559cdcd52d4SBartosz Sobczak 		if (!fpdu_len) {
1560cdcd52d4SBartosz Sobczak 			irdma_debug(ieq->dev, IRDMA_DEBUG_IEQ,
1561cdcd52d4SBartosz Sobczak 				    "error bad fpdu len\n");
1562cdcd52d4SBartosz Sobczak 			list_add(&buf->list, rxlist);
1563cdcd52d4SBartosz Sobczak 			pfpdu->mpa_crc_err = true;
1564cdcd52d4SBartosz Sobczak 			return -EINVAL;
1565cdcd52d4SBartosz Sobczak 		}
1566cdcd52d4SBartosz Sobczak 
1567cdcd52d4SBartosz Sobczak 		if (datalen < fpdu_len) {
1568cdcd52d4SBartosz Sobczak 			partial = true;
1569cdcd52d4SBartosz Sobczak 			break;
1570cdcd52d4SBartosz Sobczak 		}
1571cdcd52d4SBartosz Sobczak 		crcptr = datap + fpdu_len - 4;
1572cdcd52d4SBartosz Sobczak 		mpacrc = *(u32 *)crcptr;
1573cdcd52d4SBartosz Sobczak 		if (ieq->check_crc)
1574cdcd52d4SBartosz Sobczak 			ret = irdma_ieq_check_mpacrc(ieq->hash_desc, datap,
1575cdcd52d4SBartosz Sobczak 						     fpdu_len - 4, mpacrc);
1576cdcd52d4SBartosz Sobczak 		if (ret) {
1577cdcd52d4SBartosz Sobczak 			list_add(&buf->list, rxlist);
1578cdcd52d4SBartosz Sobczak 			irdma_debug(ieq->dev, IRDMA_DEBUG_ERR,
1579cdcd52d4SBartosz Sobczak 				    "IRDMA_ERR_MPA_CRC\n");
1580cdcd52d4SBartosz Sobczak 			pfpdu->mpa_crc_err = true;
1581cdcd52d4SBartosz Sobczak 			return ret;
1582cdcd52d4SBartosz Sobczak 		}
1583cdcd52d4SBartosz Sobczak 		full++;
1584cdcd52d4SBartosz Sobczak 		pfpdu->fpdu_processed++;
1585cdcd52d4SBartosz Sobczak 		ieq->fpdu_processed++;
1586cdcd52d4SBartosz Sobczak 		datap += fpdu_len;
1587cdcd52d4SBartosz Sobczak 		len += fpdu_len;
1588cdcd52d4SBartosz Sobczak 		datalen -= fpdu_len;
1589cdcd52d4SBartosz Sobczak 	}
1590cdcd52d4SBartosz Sobczak 	if (full) {
1591cdcd52d4SBartosz Sobczak 		/* copy full pdu's in the txbuf and send them out */
1592cdcd52d4SBartosz Sobczak 		txbuf = irdma_puda_get_bufpool(ieq);
1593cdcd52d4SBartosz Sobczak 		if (!txbuf) {
1594cdcd52d4SBartosz Sobczak 			pfpdu->no_tx_bufs++;
1595cdcd52d4SBartosz Sobczak 			list_add(&buf->list, rxlist);
1596cdcd52d4SBartosz Sobczak 			return -ENOBUFS;
1597cdcd52d4SBartosz Sobczak 		}
1598cdcd52d4SBartosz Sobczak 		/* modify txbuf's buffer header */
1599cdcd52d4SBartosz Sobczak 		irdma_ieq_setup_tx_buf(buf, txbuf);
1600cdcd52d4SBartosz Sobczak 		/* copy full fpdu's to new buffer */
1601cdcd52d4SBartosz Sobczak 		if (ieq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) {
1602cdcd52d4SBartosz Sobczak 			irdma_ieq_copy_to_txbuf(buf, txbuf, ioffset,
1603cdcd52d4SBartosz Sobczak 						txbuf->hdrlen, len);
1604cdcd52d4SBartosz Sobczak 			txbuf->totallen = txbuf->hdrlen + len;
1605cdcd52d4SBartosz Sobczak 			txbuf->ah_id = pfpdu->ah->ah_info.ah_idx;
1606cdcd52d4SBartosz Sobczak 		} else {
1607cdcd52d4SBartosz Sobczak 			irdma_ieq_copy_to_txbuf(buf, txbuf, ioffset,
1608cdcd52d4SBartosz Sobczak 						buf->hdrlen, len);
1609cdcd52d4SBartosz Sobczak 			txbuf->totallen = buf->hdrlen + len;
1610cdcd52d4SBartosz Sobczak 		}
1611cdcd52d4SBartosz Sobczak 		irdma_ieq_update_tcpip_info(txbuf, len, buf->seqnum);
1612cdcd52d4SBartosz Sobczak 		irdma_debug_buf(ieq->dev, IRDMA_DEBUG_IEQ, "IEQ TX BUFFER",
1613cdcd52d4SBartosz Sobczak 				txbuf->mem.va, txbuf->totallen);
1614cdcd52d4SBartosz Sobczak 		txbuf->do_lpb = true;
1615cdcd52d4SBartosz Sobczak 		irdma_puda_send_buf(ieq, txbuf);
1616cdcd52d4SBartosz Sobczak 
1617cdcd52d4SBartosz Sobczak 		if (!datalen) {
1618cdcd52d4SBartosz Sobczak 			pfpdu->rcv_nxt = buf->seqnum + len;
1619cdcd52d4SBartosz Sobczak 			irdma_puda_ret_bufpool(ieq, buf);
1620cdcd52d4SBartosz Sobczak 			return 0;
1621cdcd52d4SBartosz Sobczak 		}
1622cdcd52d4SBartosz Sobczak 		buf->data = datap;
1623cdcd52d4SBartosz Sobczak 		buf->seqnum = seqnum + len;
1624cdcd52d4SBartosz Sobczak 		buf->datalen = datalen;
1625cdcd52d4SBartosz Sobczak 		pfpdu->rcv_nxt = buf->seqnum;
1626cdcd52d4SBartosz Sobczak 	}
1627cdcd52d4SBartosz Sobczak 	if (partial)
1628cdcd52d4SBartosz Sobczak 		return irdma_ieq_handle_partial(ieq, pfpdu, buf, fpdu_len);
1629cdcd52d4SBartosz Sobczak 
1630cdcd52d4SBartosz Sobczak 	return 0;
1631cdcd52d4SBartosz Sobczak }
1632cdcd52d4SBartosz Sobczak 
1633cdcd52d4SBartosz Sobczak /**
1634cdcd52d4SBartosz Sobczak  * irdma_ieq_process_fpdus - process fpdu's buffers on its list
1635cdcd52d4SBartosz Sobczak  * @qp: qp for which partial fpdus
1636cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1637cdcd52d4SBartosz Sobczak  */
1638cdcd52d4SBartosz Sobczak void
irdma_ieq_process_fpdus(struct irdma_sc_qp * qp,struct irdma_puda_rsrc * ieq)1639cdcd52d4SBartosz Sobczak irdma_ieq_process_fpdus(struct irdma_sc_qp *qp,
1640cdcd52d4SBartosz Sobczak 			struct irdma_puda_rsrc *ieq)
1641cdcd52d4SBartosz Sobczak {
1642cdcd52d4SBartosz Sobczak 	struct irdma_pfpdu *pfpdu = &qp->pfpdu;
1643cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1644cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
1645cdcd52d4SBartosz Sobczak 	int status;
1646cdcd52d4SBartosz Sobczak 
1647cdcd52d4SBartosz Sobczak 	do {
1648cdcd52d4SBartosz Sobczak 		if (list_empty(rxlist))
1649cdcd52d4SBartosz Sobczak 			break;
1650cdcd52d4SBartosz Sobczak 		buf = irdma_puda_get_listbuf(rxlist);
1651cdcd52d4SBartosz Sobczak 		if (!buf) {
1652cdcd52d4SBartosz Sobczak 			irdma_debug(ieq->dev, IRDMA_DEBUG_IEQ,
1653cdcd52d4SBartosz Sobczak 				    "error no buf\n");
1654cdcd52d4SBartosz Sobczak 			break;
1655cdcd52d4SBartosz Sobczak 		}
1656cdcd52d4SBartosz Sobczak 		if (buf->seqnum != pfpdu->rcv_nxt) {
1657cdcd52d4SBartosz Sobczak 			/* This could be out of order or missing packet */
1658cdcd52d4SBartosz Sobczak 			pfpdu->out_of_order++;
1659cdcd52d4SBartosz Sobczak 			list_add(&buf->list, rxlist);
1660cdcd52d4SBartosz Sobczak 			break;
1661cdcd52d4SBartosz Sobczak 		}
1662cdcd52d4SBartosz Sobczak 		/* keep processing buffers from the head of the list */
1663cdcd52d4SBartosz Sobczak 		status = irdma_ieq_process_buf(ieq, pfpdu, buf);
1664cdcd52d4SBartosz Sobczak 		if (status && pfpdu->mpa_crc_err) {
1665cdcd52d4SBartosz Sobczak 			while (!list_empty(rxlist)) {
1666cdcd52d4SBartosz Sobczak 				buf = irdma_puda_get_listbuf(rxlist);
1667cdcd52d4SBartosz Sobczak 				irdma_puda_ret_bufpool(ieq, buf);
1668cdcd52d4SBartosz Sobczak 				pfpdu->crc_err++;
1669cdcd52d4SBartosz Sobczak 				ieq->crc_err++;
1670cdcd52d4SBartosz Sobczak 			}
1671cdcd52d4SBartosz Sobczak 			/* create CQP for AE */
1672cdcd52d4SBartosz Sobczak 			irdma_ieq_mpa_crc_ae(ieq->dev, qp);
1673cdcd52d4SBartosz Sobczak 		}
1674cdcd52d4SBartosz Sobczak 	} while (!status);
1675cdcd52d4SBartosz Sobczak }
1676cdcd52d4SBartosz Sobczak 
1677cdcd52d4SBartosz Sobczak /**
1678cdcd52d4SBartosz Sobczak  * irdma_ieq_create_ah - create an address handle for IEQ
1679cdcd52d4SBartosz Sobczak  * @qp: qp pointer
1680cdcd52d4SBartosz Sobczak  * @buf: buf received on IEQ used to create AH
1681cdcd52d4SBartosz Sobczak  */
1682cdcd52d4SBartosz Sobczak static int
irdma_ieq_create_ah(struct irdma_sc_qp * qp,struct irdma_puda_buf * buf)1683cdcd52d4SBartosz Sobczak irdma_ieq_create_ah(struct irdma_sc_qp *qp, struct irdma_puda_buf *buf)
1684cdcd52d4SBartosz Sobczak {
1685cdcd52d4SBartosz Sobczak 	struct irdma_ah_info ah_info = {0};
1686cdcd52d4SBartosz Sobczak 
1687cdcd52d4SBartosz Sobczak 	qp->pfpdu.ah_buf = buf;
1688cdcd52d4SBartosz Sobczak 	irdma_puda_ieq_get_ah_info(qp, &ah_info);
1689cdcd52d4SBartosz Sobczak 	return irdma_puda_create_ah(qp->vsi->dev, &ah_info, false,
1690cdcd52d4SBartosz Sobczak 				    IRDMA_PUDA_RSRC_TYPE_IEQ, qp,
1691cdcd52d4SBartosz Sobczak 				    &qp->pfpdu.ah);
1692cdcd52d4SBartosz Sobczak }
1693cdcd52d4SBartosz Sobczak 
1694cdcd52d4SBartosz Sobczak /**
1695cdcd52d4SBartosz Sobczak  * irdma_ieq_handle_exception - handle qp's exception
1696cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1697cdcd52d4SBartosz Sobczak  * @qp: qp receiving excpetion
1698cdcd52d4SBartosz Sobczak  * @buf: receive buffer
1699cdcd52d4SBartosz Sobczak  */
1700cdcd52d4SBartosz Sobczak static void
irdma_ieq_handle_exception(struct irdma_puda_rsrc * ieq,struct irdma_sc_qp * qp,struct irdma_puda_buf * buf)1701cdcd52d4SBartosz Sobczak irdma_ieq_handle_exception(struct irdma_puda_rsrc *ieq,
1702cdcd52d4SBartosz Sobczak 			   struct irdma_sc_qp *qp,
1703cdcd52d4SBartosz Sobczak 			   struct irdma_puda_buf *buf)
1704cdcd52d4SBartosz Sobczak {
1705cdcd52d4SBartosz Sobczak 	struct irdma_pfpdu *pfpdu = &qp->pfpdu;
1706cdcd52d4SBartosz Sobczak 	u32 *hw_host_ctx = (u32 *)qp->hw_host_ctx;
1707cdcd52d4SBartosz Sobczak 	u32 rcv_wnd = hw_host_ctx[23];
17085b5f7d0eSBartosz Sobczak 
1709cdcd52d4SBartosz Sobczak 	/* first partial seq # in q2 */
1710cdcd52d4SBartosz Sobczak u32 fps = *(u32 *)(qp->q2_buf + Q2_FPSN_OFFSET);
1711cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1712cdcd52d4SBartosz Sobczak 	struct list_head *plist;
1713cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *tmpbuf = NULL;
1714cdcd52d4SBartosz Sobczak 	unsigned long flags = 0;
1715cdcd52d4SBartosz Sobczak 	u8 hw_rev = qp->dev->hw_attrs.uk_attrs.hw_rev;
1716cdcd52d4SBartosz Sobczak 
1717cdcd52d4SBartosz Sobczak 	irdma_debug_buf(ieq->dev, IRDMA_DEBUG_IEQ, "IEQ RX BUFFER", buf->mem.va,
1718cdcd52d4SBartosz Sobczak 			buf->totallen);
1719cdcd52d4SBartosz Sobczak 
1720cdcd52d4SBartosz Sobczak 	spin_lock_irqsave(&pfpdu->lock, flags);
1721cdcd52d4SBartosz Sobczak 	pfpdu->total_ieq_bufs++;
1722cdcd52d4SBartosz Sobczak 	if (pfpdu->mpa_crc_err) {
1723cdcd52d4SBartosz Sobczak 		pfpdu->crc_err++;
1724cdcd52d4SBartosz Sobczak 		goto error;
1725cdcd52d4SBartosz Sobczak 	}
1726cdcd52d4SBartosz Sobczak 	if (pfpdu->mode && fps != pfpdu->fps) {
1727cdcd52d4SBartosz Sobczak 		/* clean up qp as it is new partial sequence */
1728cdcd52d4SBartosz Sobczak 		irdma_ieq_cleanup_qp(ieq, qp);
1729cdcd52d4SBartosz Sobczak 		irdma_debug(ieq->dev, IRDMA_DEBUG_IEQ,
1730cdcd52d4SBartosz Sobczak 			    "restarting new partial\n");
1731cdcd52d4SBartosz Sobczak 		pfpdu->mode = false;
1732cdcd52d4SBartosz Sobczak 	}
1733cdcd52d4SBartosz Sobczak 
1734cdcd52d4SBartosz Sobczak 	if (!pfpdu->mode) {
1735cdcd52d4SBartosz Sobczak 		irdma_debug_buf(ieq->dev, IRDMA_DEBUG_IEQ, "Q2 BUFFER",
1736cdcd52d4SBartosz Sobczak 				(u64 *)qp->q2_buf, 128);
1737cdcd52d4SBartosz Sobczak 		/* First_Partial_Sequence_Number check */
1738cdcd52d4SBartosz Sobczak 		pfpdu->rcv_nxt = fps;
1739cdcd52d4SBartosz Sobczak 		pfpdu->fps = fps;
1740cdcd52d4SBartosz Sobczak 		pfpdu->mode = true;
1741cdcd52d4SBartosz Sobczak 		pfpdu->max_fpdu_data = (buf->ipv4) ?
1742cdcd52d4SBartosz Sobczak 		    (ieq->vsi->mtu - IRDMA_MTU_TO_MSS_IPV4) :
1743cdcd52d4SBartosz Sobczak 		    (ieq->vsi->mtu - IRDMA_MTU_TO_MSS_IPV6);
1744cdcd52d4SBartosz Sobczak 		pfpdu->pmode_count++;
1745cdcd52d4SBartosz Sobczak 		ieq->pmode_count++;
1746cdcd52d4SBartosz Sobczak 		INIT_LIST_HEAD(rxlist);
1747cdcd52d4SBartosz Sobczak 		irdma_ieq_check_first_buf(buf, fps);
1748cdcd52d4SBartosz Sobczak 	}
1749cdcd52d4SBartosz Sobczak 
1750cdcd52d4SBartosz Sobczak 	if (!(rcv_wnd >= (buf->seqnum - pfpdu->rcv_nxt))) {
1751cdcd52d4SBartosz Sobczak 		pfpdu->bad_seq_num++;
1752cdcd52d4SBartosz Sobczak 		ieq->bad_seq_num++;
1753cdcd52d4SBartosz Sobczak 		goto error;
1754cdcd52d4SBartosz Sobczak 	}
1755cdcd52d4SBartosz Sobczak 
1756cdcd52d4SBartosz Sobczak 	if (!list_empty(rxlist)) {
1757cdcd52d4SBartosz Sobczak 		tmpbuf = (struct irdma_puda_buf *)(rxlist)->next;
1758cdcd52d4SBartosz Sobczak 		while ((struct list_head *)tmpbuf != rxlist) {
1759cdcd52d4SBartosz Sobczak 			if (buf->seqnum == tmpbuf->seqnum)
1760cdcd52d4SBartosz Sobczak 				goto error;
1761cdcd52d4SBartosz Sobczak 			if ((int)(buf->seqnum - tmpbuf->seqnum) < 0)
1762cdcd52d4SBartosz Sobczak 				break;
1763cdcd52d4SBartosz Sobczak 			plist = &tmpbuf->list;
1764cdcd52d4SBartosz Sobczak 			tmpbuf = (struct irdma_puda_buf *)(plist)->next;
1765cdcd52d4SBartosz Sobczak 		}
1766cdcd52d4SBartosz Sobczak 		/* Insert buf before tmpbuf */
1767cdcd52d4SBartosz Sobczak 		list_add_tail(&buf->list, &tmpbuf->list);
1768cdcd52d4SBartosz Sobczak 	} else {
1769cdcd52d4SBartosz Sobczak 		list_add_tail(&buf->list, rxlist);
1770cdcd52d4SBartosz Sobczak 	}
1771cdcd52d4SBartosz Sobczak 	pfpdu->nextseqnum = buf->seqnum + buf->datalen;
1772cdcd52d4SBartosz Sobczak 	pfpdu->lastrcv_buf = buf;
1773cdcd52d4SBartosz Sobczak 	if (hw_rev >= IRDMA_GEN_2 && !pfpdu->ah) {
1774cdcd52d4SBartosz Sobczak 		irdma_ieq_create_ah(qp, buf);
1775cdcd52d4SBartosz Sobczak 		if (!pfpdu->ah)
1776cdcd52d4SBartosz Sobczak 			goto error;
1777cdcd52d4SBartosz Sobczak 		goto exit;
1778cdcd52d4SBartosz Sobczak 	}
1779cdcd52d4SBartosz Sobczak 	if (hw_rev == IRDMA_GEN_1)
1780cdcd52d4SBartosz Sobczak 		irdma_ieq_process_fpdus(qp, ieq);
1781cdcd52d4SBartosz Sobczak 	else if (pfpdu->ah && pfpdu->ah->ah_info.ah_valid)
1782cdcd52d4SBartosz Sobczak 		irdma_ieq_process_fpdus(qp, ieq);
1783cdcd52d4SBartosz Sobczak exit:
1784cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&pfpdu->lock, flags);
1785cdcd52d4SBartosz Sobczak 
1786cdcd52d4SBartosz Sobczak 	return;
1787cdcd52d4SBartosz Sobczak 
1788cdcd52d4SBartosz Sobczak error:
1789cdcd52d4SBartosz Sobczak 	irdma_puda_ret_bufpool(ieq, buf);
1790cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&pfpdu->lock, flags);
1791cdcd52d4SBartosz Sobczak }
1792cdcd52d4SBartosz Sobczak 
1793cdcd52d4SBartosz Sobczak /**
1794cdcd52d4SBartosz Sobczak  * irdma_ieq_receive - received exception buffer
1795cdcd52d4SBartosz Sobczak  * @vsi: VSI of device
1796cdcd52d4SBartosz Sobczak  * @buf: exception buffer received
1797cdcd52d4SBartosz Sobczak  */
1798cdcd52d4SBartosz Sobczak static void
irdma_ieq_receive(struct irdma_sc_vsi * vsi,struct irdma_puda_buf * buf)1799cdcd52d4SBartosz Sobczak irdma_ieq_receive(struct irdma_sc_vsi *vsi,
1800cdcd52d4SBartosz Sobczak 		  struct irdma_puda_buf *buf)
1801cdcd52d4SBartosz Sobczak {
1802cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *ieq = vsi->ieq;
1803cdcd52d4SBartosz Sobczak 	struct irdma_sc_qp *qp = NULL;
1804cdcd52d4SBartosz Sobczak 	u32 wqe_idx = ieq->compl_rxwqe_idx;
1805cdcd52d4SBartosz Sobczak 
1806cdcd52d4SBartosz Sobczak 	qp = irdma_ieq_get_qp(vsi->dev, buf);
1807cdcd52d4SBartosz Sobczak 	if (!qp) {
1808cdcd52d4SBartosz Sobczak 		ieq->stats_bad_qp_id++;
1809cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, buf);
1810cdcd52d4SBartosz Sobczak 	} else {
1811cdcd52d4SBartosz Sobczak 		irdma_ieq_handle_exception(ieq, qp, buf);
1812cdcd52d4SBartosz Sobczak 	}
1813cdcd52d4SBartosz Sobczak 	/*
1814cdcd52d4SBartosz Sobczak 	 * ieq->rx_wqe_idx is used by irdma_puda_replenish_rq() on which wqe_idx to start replenish rq
1815cdcd52d4SBartosz Sobczak 	 */
1816cdcd52d4SBartosz Sobczak 	if (!ieq->rxq_invalid_cnt)
1817cdcd52d4SBartosz Sobczak 		ieq->rx_wqe_idx = wqe_idx;
1818cdcd52d4SBartosz Sobczak 	ieq->rxq_invalid_cnt++;
1819cdcd52d4SBartosz Sobczak }
1820cdcd52d4SBartosz Sobczak 
1821cdcd52d4SBartosz Sobczak /**
1822cdcd52d4SBartosz Sobczak  * irdma_ieq_tx_compl - put back after sending completed exception buffer
1823cdcd52d4SBartosz Sobczak  * @vsi: sc VSI struct
1824cdcd52d4SBartosz Sobczak  * @sqwrid: pointer to puda buffer
1825cdcd52d4SBartosz Sobczak  */
1826cdcd52d4SBartosz Sobczak static void
irdma_ieq_tx_compl(struct irdma_sc_vsi * vsi,void * sqwrid)1827cdcd52d4SBartosz Sobczak irdma_ieq_tx_compl(struct irdma_sc_vsi *vsi, void *sqwrid)
1828cdcd52d4SBartosz Sobczak {
1829cdcd52d4SBartosz Sobczak 	struct irdma_puda_rsrc *ieq = vsi->ieq;
1830cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf = sqwrid;
1831cdcd52d4SBartosz Sobczak 
1832cdcd52d4SBartosz Sobczak 	irdma_puda_ret_bufpool(ieq, buf);
1833cdcd52d4SBartosz Sobczak }
1834cdcd52d4SBartosz Sobczak 
1835cdcd52d4SBartosz Sobczak /**
1836cdcd52d4SBartosz Sobczak  * irdma_ieq_cleanup_qp - qp is being destroyed
1837cdcd52d4SBartosz Sobczak  * @ieq: ieq resource
1838cdcd52d4SBartosz Sobczak  * @qp: all pending fpdu buffers
1839cdcd52d4SBartosz Sobczak  */
1840cdcd52d4SBartosz Sobczak void
irdma_ieq_cleanup_qp(struct irdma_puda_rsrc * ieq,struct irdma_sc_qp * qp)1841cdcd52d4SBartosz Sobczak irdma_ieq_cleanup_qp(struct irdma_puda_rsrc *ieq, struct irdma_sc_qp *qp)
1842cdcd52d4SBartosz Sobczak {
1843cdcd52d4SBartosz Sobczak 	struct irdma_puda_buf *buf;
1844cdcd52d4SBartosz Sobczak 	struct irdma_pfpdu *pfpdu = &qp->pfpdu;
1845cdcd52d4SBartosz Sobczak 	struct list_head *rxlist = &pfpdu->rxlist;
1846cdcd52d4SBartosz Sobczak 
1847cdcd52d4SBartosz Sobczak 	if (qp->pfpdu.ah) {
1848cdcd52d4SBartosz Sobczak 		irdma_puda_free_ah(ieq->dev, qp->pfpdu.ah);
1849cdcd52d4SBartosz Sobczak 		qp->pfpdu.ah = NULL;
1850cdcd52d4SBartosz Sobczak 		qp->pfpdu.ah_buf = NULL;
1851cdcd52d4SBartosz Sobczak 	}
1852cdcd52d4SBartosz Sobczak 
1853cdcd52d4SBartosz Sobczak 	if (!pfpdu->mode)
1854cdcd52d4SBartosz Sobczak 		return;
1855cdcd52d4SBartosz Sobczak 
1856cdcd52d4SBartosz Sobczak 	while (!list_empty(rxlist)) {
1857cdcd52d4SBartosz Sobczak 		buf = irdma_puda_get_listbuf(rxlist);
1858cdcd52d4SBartosz Sobczak 		irdma_puda_ret_bufpool(ieq, buf);
1859cdcd52d4SBartosz Sobczak 	}
1860cdcd52d4SBartosz Sobczak }
1861