1fa790ea9SDavid C Somayajulu /*
2fa790ea9SDavid C Somayajulu * Copyright (c) 2018-2019 Cavium, Inc.
3fa790ea9SDavid C Somayajulu * All rights reserved.
4fa790ea9SDavid C Somayajulu *
5fa790ea9SDavid C Somayajulu * Redistribution and use in source and binary forms, with or without
6fa790ea9SDavid C Somayajulu * modification, are permitted provided that the following conditions
7fa790ea9SDavid C Somayajulu * are met:
8fa790ea9SDavid C Somayajulu *
9fa790ea9SDavid C Somayajulu * 1. Redistributions of source code must retain the above copyright
10fa790ea9SDavid C Somayajulu * notice, this list of conditions and the following disclaimer.
11fa790ea9SDavid C Somayajulu * 2. Redistributions in binary form must reproduce the above copyright
12fa790ea9SDavid C Somayajulu * notice, this list of conditions and the following disclaimer in the
13fa790ea9SDavid C Somayajulu * documentation and/or other materials provided with the distribution.
14fa790ea9SDavid C Somayajulu *
15fa790ea9SDavid C Somayajulu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16fa790ea9SDavid C Somayajulu * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17fa790ea9SDavid C Somayajulu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18fa790ea9SDavid C Somayajulu * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19fa790ea9SDavid C Somayajulu * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20fa790ea9SDavid C Somayajulu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21fa790ea9SDavid C Somayajulu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22fa790ea9SDavid C Somayajulu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23fa790ea9SDavid C Somayajulu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24fa790ea9SDavid C Somayajulu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25fa790ea9SDavid C Somayajulu * POSSIBILITY OF SUCH DAMAGE.
26fa790ea9SDavid C Somayajulu */
27fa790ea9SDavid C Somayajulu
28fa790ea9SDavid C Somayajulu /*
29fa790ea9SDavid C Somayajulu * File: qlnxr_verbs.c
30fa790ea9SDavid C Somayajulu */
31fa790ea9SDavid C Somayajulu #include <sys/cdefs.h>
32fa790ea9SDavid C Somayajulu #include "qlnxr_def.h"
33fa790ea9SDavid C Somayajulu #include "rdma_common.h"
34fa790ea9SDavid C Somayajulu #include "qlnxr_roce.h"
35fa790ea9SDavid C Somayajulu #include "qlnxr_cm.h"
36fa790ea9SDavid C Somayajulu
37fa790ea9SDavid C Somayajulu #define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo))
38fa790ea9SDavid C Somayajulu
39fa790ea9SDavid C Somayajulu #define TYPEPTR_ADDR_SET(type_ptr, field, vaddr) \
40fa790ea9SDavid C Somayajulu do { \
41fa790ea9SDavid C Somayajulu (type_ptr)->field.hi = cpu_to_le32(upper_32_bits(vaddr));\
42fa790ea9SDavid C Somayajulu (type_ptr)->field.lo = cpu_to_le32(lower_32_bits(vaddr));\
43fa790ea9SDavid C Somayajulu } while (0)
44fa790ea9SDavid C Somayajulu
45fa790ea9SDavid C Somayajulu #define RQ_SGE_SET(sge, vaddr, vlength, vflags) \
46fa790ea9SDavid C Somayajulu do { \
47fa790ea9SDavid C Somayajulu TYPEPTR_ADDR_SET(sge, addr, vaddr); \
48fa790ea9SDavid C Somayajulu (sge)->length = cpu_to_le32(vlength); \
49fa790ea9SDavid C Somayajulu (sge)->flags = cpu_to_le32(vflags); \
50fa790ea9SDavid C Somayajulu } while (0)
51fa790ea9SDavid C Somayajulu
52fa790ea9SDavid C Somayajulu #define SRQ_HDR_SET(hdr, vwr_id, num_sge) \
53fa790ea9SDavid C Somayajulu do { \
54fa790ea9SDavid C Somayajulu TYPEPTR_ADDR_SET(hdr, wr_id, vwr_id); \
55fa790ea9SDavid C Somayajulu (hdr)->num_sges = num_sge; \
56fa790ea9SDavid C Somayajulu } while (0)
57fa790ea9SDavid C Somayajulu
58fa790ea9SDavid C Somayajulu #define SRQ_SGE_SET(sge, vaddr, vlength, vlkey) \
59fa790ea9SDavid C Somayajulu do { \
60fa790ea9SDavid C Somayajulu TYPEPTR_ADDR_SET(sge, addr, vaddr); \
61fa790ea9SDavid C Somayajulu (sge)->length = cpu_to_le32(vlength); \
62fa790ea9SDavid C Somayajulu (sge)->l_key = cpu_to_le32(vlkey); \
63fa790ea9SDavid C Somayajulu } while (0)
64fa790ea9SDavid C Somayajulu
65fa790ea9SDavid C Somayajulu #define NIPQUAD(addr) \
66fa790ea9SDavid C Somayajulu ((unsigned char *)&addr)[0], \
67fa790ea9SDavid C Somayajulu ((unsigned char *)&addr)[1], \
68fa790ea9SDavid C Somayajulu ((unsigned char *)&addr)[2], \
69fa790ea9SDavid C Somayajulu ((unsigned char *)&addr)[3]
70fa790ea9SDavid C Somayajulu
71fa790ea9SDavid C Somayajulu static int
72b633e08cSHans Petter Selasky qlnxr_check_srq_params(struct qlnxr_dev *dev,
73fa790ea9SDavid C Somayajulu struct ib_srq_init_attr *attrs);
74fa790ea9SDavid C Somayajulu
75fa790ea9SDavid C Somayajulu static int
76fa790ea9SDavid C Somayajulu qlnxr_init_srq_user_params(struct ib_ucontext *ib_ctx,
77fa790ea9SDavid C Somayajulu struct qlnxr_srq *srq,
78fa790ea9SDavid C Somayajulu struct qlnxr_create_srq_ureq *ureq,
79fa790ea9SDavid C Somayajulu int access, int dmasync);
80fa790ea9SDavid C Somayajulu
81fa790ea9SDavid C Somayajulu static int
82fa790ea9SDavid C Somayajulu qlnxr_alloc_srq_kernel_params(struct qlnxr_srq *srq,
83fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev,
84fa790ea9SDavid C Somayajulu struct ib_srq_init_attr *init_attr);
85fa790ea9SDavid C Somayajulu
86fa790ea9SDavid C Somayajulu static int
87fa790ea9SDavid C Somayajulu qlnxr_copy_srq_uresp(struct qlnxr_dev *dev,
88fa790ea9SDavid C Somayajulu struct qlnxr_srq *srq,
89fa790ea9SDavid C Somayajulu struct ib_udata *udata);
90fa790ea9SDavid C Somayajulu
91fa790ea9SDavid C Somayajulu static void
92fa790ea9SDavid C Somayajulu qlnxr_free_srq_user_params(struct qlnxr_srq *srq);
93fa790ea9SDavid C Somayajulu
94fa790ea9SDavid C Somayajulu static void
95fa790ea9SDavid C Somayajulu qlnxr_free_srq_kernel_params(struct qlnxr_srq *srq);
96fa790ea9SDavid C Somayajulu
97fa790ea9SDavid C Somayajulu static u32
98fa790ea9SDavid C Somayajulu qlnxr_srq_elem_left(struct qlnxr_srq_hwq_info *hw_srq);
99fa790ea9SDavid C Somayajulu
100fa790ea9SDavid C Somayajulu int
qlnxr_iw_query_gid(struct ib_device * ibdev,u8 port,int index,union ib_gid * sgid)101fa790ea9SDavid C Somayajulu qlnxr_iw_query_gid(struct ib_device *ibdev, u8 port, int index,
102fa790ea9SDavid C Somayajulu union ib_gid *sgid)
103fa790ea9SDavid C Somayajulu {
104fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
105fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
106fa790ea9SDavid C Somayajulu
107fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
108fa790ea9SDavid C Somayajulu ha = dev->ha;
109fa790ea9SDavid C Somayajulu
110fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
111fa790ea9SDavid C Somayajulu
112fa790ea9SDavid C Somayajulu memset(sgid->raw, 0, sizeof(sgid->raw));
113fa790ea9SDavid C Somayajulu
114fa790ea9SDavid C Somayajulu memcpy(sgid->raw, dev->ha->primary_mac, sizeof (dev->ha->primary_mac));
115fa790ea9SDavid C Somayajulu
116fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
117fa790ea9SDavid C Somayajulu
118fa790ea9SDavid C Somayajulu return 0;
119fa790ea9SDavid C Somayajulu }
120fa790ea9SDavid C Somayajulu
121fa790ea9SDavid C Somayajulu int
qlnxr_query_gid(struct ib_device * ibdev,u8 port,int index,union ib_gid * sgid)122fa790ea9SDavid C Somayajulu qlnxr_query_gid(struct ib_device *ibdev, u8 port, int index,
123fa790ea9SDavid C Somayajulu union ib_gid *sgid)
124fa790ea9SDavid C Somayajulu {
125fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
126fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
127fa790ea9SDavid C Somayajulu
128fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
129fa790ea9SDavid C Somayajulu ha = dev->ha;
130fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter index: %d\n", index);
131fa790ea9SDavid C Somayajulu #if 0
132fa790ea9SDavid C Somayajulu int ret = 0;
133fa790ea9SDavid C Somayajulu /* @@@: if DEFINE_ROCE_GID_TABLE to be used here */
134fa790ea9SDavid C Somayajulu //if (!rdma_cap_roce_gid_table(ibdev, port)) {
135fa790ea9SDavid C Somayajulu if (!(rdma_protocol_roce(ibdev, port) &&
136fa790ea9SDavid C Somayajulu ibdev->add_gid && ibdev->del_gid)) {
137fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "acquire gid failed\n");
138fa790ea9SDavid C Somayajulu return -ENODEV;
139fa790ea9SDavid C Somayajulu }
140fa790ea9SDavid C Somayajulu
141fa790ea9SDavid C Somayajulu ret = ib_get_cached_gid(ibdev, port, index, sgid, NULL);
142fa790ea9SDavid C Somayajulu if (ret == -EAGAIN) {
143fa790ea9SDavid C Somayajulu memcpy(sgid, &zgid, sizeof(*sgid));
144fa790ea9SDavid C Somayajulu return 0;
145fa790ea9SDavid C Somayajulu }
146fa790ea9SDavid C Somayajulu #endif
147fa790ea9SDavid C Somayajulu if ((index >= QLNXR_MAX_SGID) || (index < 0)) {
148fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "invalid gid index %d\n", index);
149fa790ea9SDavid C Somayajulu memset(sgid, 0, sizeof(*sgid));
150fa790ea9SDavid C Somayajulu return -EINVAL;
151fa790ea9SDavid C Somayajulu }
152fa790ea9SDavid C Somayajulu memcpy(sgid, &dev->sgid_tbl[index], sizeof(*sgid));
153fa790ea9SDavid C Somayajulu
154fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit : %p\n", sgid);
155fa790ea9SDavid C Somayajulu
156fa790ea9SDavid C Somayajulu return 0;
157fa790ea9SDavid C Somayajulu }
158fa790ea9SDavid C Somayajulu
159b633e08cSHans Petter Selasky int
qlnxr_create_srq(struct ib_srq * ibsrq,struct ib_srq_init_attr * init_attr,struct ib_udata * udata)160b633e08cSHans Petter Selasky qlnxr_create_srq(struct ib_srq *ibsrq,
161b633e08cSHans Petter Selasky struct ib_srq_init_attr *init_attr,
162fa790ea9SDavid C Somayajulu struct ib_udata *udata)
163fa790ea9SDavid C Somayajulu {
164fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
165fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
166fa790ea9SDavid C Somayajulu struct ecore_rdma_destroy_srq_in_params destroy_in_params;
167fa790ea9SDavid C Somayajulu struct ecore_rdma_create_srq_out_params out_params;
168fa790ea9SDavid C Somayajulu struct ecore_rdma_create_srq_in_params in_params;
169fa790ea9SDavid C Somayajulu u64 pbl_base_addr, phy_prod_pair_addr;
170fa790ea9SDavid C Somayajulu struct qlnxr_srq_hwq_info *hw_srq;
171b633e08cSHans Petter Selasky struct qlnxr_ucontext *ctx;
172fa790ea9SDavid C Somayajulu struct qlnxr_create_srq_ureq ureq;
173fa790ea9SDavid C Somayajulu u32 page_cnt, page_size;
174b633e08cSHans Petter Selasky struct qlnxr_srq *srq = get_qlnxr_srq(ibsrq);
175fa790ea9SDavid C Somayajulu int ret = 0;
176fa790ea9SDavid C Somayajulu
177b633e08cSHans Petter Selasky dev = get_qlnxr_dev(ibsrq->device);
178fa790ea9SDavid C Somayajulu ha = dev->ha;
179fa790ea9SDavid C Somayajulu
180fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
181fa790ea9SDavid C Somayajulu
182b633e08cSHans Petter Selasky ret = qlnxr_check_srq_params(dev, init_attr);
183fa790ea9SDavid C Somayajulu
184fa790ea9SDavid C Somayajulu srq->dev = dev;
185fa790ea9SDavid C Somayajulu hw_srq = &srq->hw_srq;
186fa790ea9SDavid C Somayajulu spin_lock_init(&srq->lock);
187fa790ea9SDavid C Somayajulu memset(&in_params, 0, sizeof(in_params));
188fa790ea9SDavid C Somayajulu
189b633e08cSHans Petter Selasky if (udata) {
190b633e08cSHans Petter Selasky ctx = rdma_udata_to_drv_context(
191b633e08cSHans Petter Selasky udata, struct qlnxr_ucontext, ibucontext);
192fa790ea9SDavid C Somayajulu
193fa790ea9SDavid C Somayajulu memset(&ureq, 0, sizeof(ureq));
194fa790ea9SDavid C Somayajulu if (ib_copy_from_udata(&ureq, udata, min(sizeof(ureq),
195fa790ea9SDavid C Somayajulu udata->inlen))) {
196fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "problem"
197fa790ea9SDavid C Somayajulu " copying data from user space\n");
198fa790ea9SDavid C Somayajulu goto err0;
199fa790ea9SDavid C Somayajulu }
200fa790ea9SDavid C Somayajulu
201b633e08cSHans Petter Selasky ret = qlnxr_init_srq_user_params(&ctx->ibucontext, srq, &ureq, 0, 0);
202fa790ea9SDavid C Somayajulu if (ret)
203fa790ea9SDavid C Somayajulu goto err0;
204fa790ea9SDavid C Somayajulu
205fa790ea9SDavid C Somayajulu page_cnt = srq->usrq.pbl_info.num_pbes;
206fa790ea9SDavid C Somayajulu pbl_base_addr = srq->usrq.pbl_tbl->pa;
207fa790ea9SDavid C Somayajulu phy_prod_pair_addr = hw_srq->phy_prod_pair_addr;
208fa790ea9SDavid C Somayajulu // @@@ : if DEFINE_IB_UMEM_PAGE_SHIFT
209fa790ea9SDavid C Somayajulu // page_size = BIT(srq->usrq.umem->page_shift);
210fa790ea9SDavid C Somayajulu // else
211fa790ea9SDavid C Somayajulu page_size = srq->usrq.umem->page_size;
212fa790ea9SDavid C Somayajulu } else {
213fa790ea9SDavid C Somayajulu struct ecore_chain *pbl;
214fa790ea9SDavid C Somayajulu ret = qlnxr_alloc_srq_kernel_params(srq, dev, init_attr);
215fa790ea9SDavid C Somayajulu if (ret)
216fa790ea9SDavid C Somayajulu goto err0;
217fa790ea9SDavid C Somayajulu pbl = &hw_srq->pbl;
218fa790ea9SDavid C Somayajulu
219fa790ea9SDavid C Somayajulu page_cnt = ecore_chain_get_page_cnt(pbl);
220fa790ea9SDavid C Somayajulu pbl_base_addr = ecore_chain_get_pbl_phys(pbl);
221fa790ea9SDavid C Somayajulu phy_prod_pair_addr = hw_srq->phy_prod_pair_addr;
222fa790ea9SDavid C Somayajulu page_size = pbl->elem_per_page << 4;
223fa790ea9SDavid C Somayajulu }
224fa790ea9SDavid C Somayajulu
225b633e08cSHans Petter Selasky in_params.pd_id = get_qlnxr_pd(ibsrq->pd)->pd_id;
226fa790ea9SDavid C Somayajulu in_params.pbl_base_addr = pbl_base_addr;
227fa790ea9SDavid C Somayajulu in_params.prod_pair_addr = phy_prod_pair_addr;
228fa790ea9SDavid C Somayajulu in_params.num_pages = page_cnt;
229fa790ea9SDavid C Somayajulu in_params.page_size = page_size;
230fa790ea9SDavid C Somayajulu
231fa790ea9SDavid C Somayajulu ret = ecore_rdma_create_srq(dev->rdma_ctx, &in_params, &out_params);
232fa790ea9SDavid C Somayajulu if (ret)
233fa790ea9SDavid C Somayajulu goto err1;
234fa790ea9SDavid C Somayajulu
235fa790ea9SDavid C Somayajulu srq->srq_id = out_params.srq_id;
236fa790ea9SDavid C Somayajulu
237fa790ea9SDavid C Somayajulu if (udata) {
238fa790ea9SDavid C Somayajulu ret = qlnxr_copy_srq_uresp(dev, srq, udata);
239fa790ea9SDavid C Somayajulu if (ret)
240fa790ea9SDavid C Somayajulu goto err2;
241fa790ea9SDavid C Somayajulu }
242fa790ea9SDavid C Somayajulu
243fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "created srq with srq_id = 0x%0x\n", srq->srq_id);
244b633e08cSHans Petter Selasky return (0);
245fa790ea9SDavid C Somayajulu err2:
246fa790ea9SDavid C Somayajulu memset(&in_params, 0, sizeof(in_params));
247fa790ea9SDavid C Somayajulu destroy_in_params.srq_id = srq->srq_id;
248fa790ea9SDavid C Somayajulu ecore_rdma_destroy_srq(dev->rdma_ctx, &destroy_in_params);
249fa790ea9SDavid C Somayajulu
250fa790ea9SDavid C Somayajulu err1:
251fa790ea9SDavid C Somayajulu if (udata)
252fa790ea9SDavid C Somayajulu qlnxr_free_srq_user_params(srq);
253fa790ea9SDavid C Somayajulu else
254fa790ea9SDavid C Somayajulu qlnxr_free_srq_kernel_params(srq);
255fa790ea9SDavid C Somayajulu
256fa790ea9SDavid C Somayajulu err0:
257b633e08cSHans Petter Selasky return (-EFAULT);
258fa790ea9SDavid C Somayajulu }
259fa790ea9SDavid C Somayajulu
260b633e08cSHans Petter Selasky void
qlnxr_destroy_srq(struct ib_srq * ibsrq,struct ib_udata * udata)261b633e08cSHans Petter Selasky qlnxr_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata)
262fa790ea9SDavid C Somayajulu {
263fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
264fa790ea9SDavid C Somayajulu struct qlnxr_srq *srq;
265fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
266fa790ea9SDavid C Somayajulu struct ecore_rdma_destroy_srq_in_params in_params;
267fa790ea9SDavid C Somayajulu
268fa790ea9SDavid C Somayajulu srq = get_qlnxr_srq(ibsrq);
269fa790ea9SDavid C Somayajulu dev = srq->dev;
270fa790ea9SDavid C Somayajulu ha = dev->ha;
271fa790ea9SDavid C Somayajulu
272fa790ea9SDavid C Somayajulu memset(&in_params, 0, sizeof(in_params));
273fa790ea9SDavid C Somayajulu in_params.srq_id = srq->srq_id;
274fa790ea9SDavid C Somayajulu
275fa790ea9SDavid C Somayajulu ecore_rdma_destroy_srq(dev->rdma_ctx, &in_params);
276fa790ea9SDavid C Somayajulu
277fa790ea9SDavid C Somayajulu if (ibsrq->pd->uobject && ibsrq->pd->uobject->context)
278fa790ea9SDavid C Somayajulu qlnxr_free_srq_user_params(srq);
279fa790ea9SDavid C Somayajulu else
280fa790ea9SDavid C Somayajulu qlnxr_free_srq_kernel_params(srq);
281fa790ea9SDavid C Somayajulu
282fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "destroyed srq_id=0x%0x\n", srq->srq_id);
283fa790ea9SDavid C Somayajulu }
284fa790ea9SDavid C Somayajulu
285fa790ea9SDavid C Somayajulu int
qlnxr_modify_srq(struct ib_srq * ibsrq,struct ib_srq_attr * attr,enum ib_srq_attr_mask attr_mask,struct ib_udata * udata)286fa790ea9SDavid C Somayajulu qlnxr_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
287fa790ea9SDavid C Somayajulu enum ib_srq_attr_mask attr_mask, struct ib_udata *udata)
288fa790ea9SDavid C Somayajulu {
289fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
290fa790ea9SDavid C Somayajulu struct qlnxr_srq *srq;
291fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
292fa790ea9SDavid C Somayajulu struct ecore_rdma_modify_srq_in_params in_params;
293fa790ea9SDavid C Somayajulu int ret = 0;
294fa790ea9SDavid C Somayajulu
295fa790ea9SDavid C Somayajulu srq = get_qlnxr_srq(ibsrq);
296fa790ea9SDavid C Somayajulu dev = srq->dev;
297fa790ea9SDavid C Somayajulu ha = dev->ha;
298fa790ea9SDavid C Somayajulu
299fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
300fa790ea9SDavid C Somayajulu if (attr_mask & IB_SRQ_MAX_WR) {
301fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "invalid attribute mask=0x%x"
302fa790ea9SDavid C Somayajulu " specified for %p\n", attr_mask, srq);
303fa790ea9SDavid C Somayajulu return -EINVAL;
304fa790ea9SDavid C Somayajulu }
305fa790ea9SDavid C Somayajulu
306fa790ea9SDavid C Somayajulu if (attr_mask & IB_SRQ_LIMIT) {
307fa790ea9SDavid C Somayajulu if (attr->srq_limit >= srq->hw_srq.max_wr) {
308fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "invalid srq_limit=0x%x"
309fa790ea9SDavid C Somayajulu " (max_srq_limit = 0x%x)\n",
310fa790ea9SDavid C Somayajulu attr->srq_limit, srq->hw_srq.max_wr);
311fa790ea9SDavid C Somayajulu return -EINVAL;
312fa790ea9SDavid C Somayajulu }
313fa790ea9SDavid C Somayajulu memset(&in_params, 0, sizeof(in_params));
314fa790ea9SDavid C Somayajulu in_params.srq_id = srq->srq_id;
315fa790ea9SDavid C Somayajulu in_params.wqe_limit = attr->srq_limit;
316fa790ea9SDavid C Somayajulu ret = ecore_rdma_modify_srq(dev->rdma_ctx, &in_params);
317fa790ea9SDavid C Somayajulu if (ret)
318fa790ea9SDavid C Somayajulu return ret;
319fa790ea9SDavid C Somayajulu }
320fa790ea9SDavid C Somayajulu
321fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "modified srq with srq_id = 0x%0x\n", srq->srq_id);
322fa790ea9SDavid C Somayajulu return 0;
323fa790ea9SDavid C Somayajulu }
324fa790ea9SDavid C Somayajulu
325fa790ea9SDavid C Somayajulu int
qlnxr_query_srq(struct ib_srq * ibsrq,struct ib_srq_attr * srq_attr)326fa790ea9SDavid C Somayajulu qlnxr_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
327fa790ea9SDavid C Somayajulu {
328fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
329fa790ea9SDavid C Somayajulu struct qlnxr_srq *srq;
330fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
331fa790ea9SDavid C Somayajulu struct ecore_rdma_device *qattr;
332fa790ea9SDavid C Somayajulu srq = get_qlnxr_srq(ibsrq);
333fa790ea9SDavid C Somayajulu dev = srq->dev;
334fa790ea9SDavid C Somayajulu ha = dev->ha;
335fa790ea9SDavid C Somayajulu //qattr = &dev->attr;
336fa790ea9SDavid C Somayajulu qattr = ecore_rdma_query_device(dev->rdma_ctx);
337fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
338fa790ea9SDavid C Somayajulu
339fa790ea9SDavid C Somayajulu if (!dev->rdma_ctx) {
340fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "called with invalid params"
341fa790ea9SDavid C Somayajulu " rdma_ctx is NULL\n");
342fa790ea9SDavid C Somayajulu return -EINVAL;
343fa790ea9SDavid C Somayajulu }
344fa790ea9SDavid C Somayajulu
345fa790ea9SDavid C Somayajulu srq_attr->srq_limit = qattr->max_srq;
346fa790ea9SDavid C Somayajulu srq_attr->max_wr = qattr->max_srq_wr;
347fa790ea9SDavid C Somayajulu srq_attr->max_sge = qattr->max_sge;
348fa790ea9SDavid C Somayajulu
349fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
350fa790ea9SDavid C Somayajulu return 0;
351fa790ea9SDavid C Somayajulu }
352fa790ea9SDavid C Somayajulu
353fa790ea9SDavid C Somayajulu /* Increment srq wr producer by one */
354fa790ea9SDavid C Somayajulu static
qlnxr_inc_srq_wr_prod(struct qlnxr_srq_hwq_info * info)355fa790ea9SDavid C Somayajulu void qlnxr_inc_srq_wr_prod (struct qlnxr_srq_hwq_info *info)
356fa790ea9SDavid C Somayajulu {
357fa790ea9SDavid C Somayajulu info->wr_prod_cnt++;
358fa790ea9SDavid C Somayajulu }
359fa790ea9SDavid C Somayajulu
360fa790ea9SDavid C Somayajulu /* Increment srq wr consumer by one */
361fa790ea9SDavid C Somayajulu static
qlnxr_inc_srq_wr_cons(struct qlnxr_srq_hwq_info * info)362fa790ea9SDavid C Somayajulu void qlnxr_inc_srq_wr_cons(struct qlnxr_srq_hwq_info *info)
363fa790ea9SDavid C Somayajulu {
364fa790ea9SDavid C Somayajulu info->wr_cons_cnt++;
365fa790ea9SDavid C Somayajulu }
366fa790ea9SDavid C Somayajulu
367fa790ea9SDavid C Somayajulu /* get_port_immutable verb is not available in FreeBSD */
368fa790ea9SDavid C Somayajulu #if 0
369fa790ea9SDavid C Somayajulu int
370fa790ea9SDavid C Somayajulu qlnxr_roce_port_immutable(struct ib_device *ibdev, u8 port_num,
371fa790ea9SDavid C Somayajulu struct ib_port_immutable *immutable)
372fa790ea9SDavid C Somayajulu {
373fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
374fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
375fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
376fa790ea9SDavid C Somayajulu ha = dev->ha;
377fa790ea9SDavid C Somayajulu
378fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "entered but not implemented!!!\n");
379fa790ea9SDavid C Somayajulu }
380fa790ea9SDavid C Somayajulu #endif
381fa790ea9SDavid C Somayajulu
382fa790ea9SDavid C Somayajulu int
qlnxr_post_srq_recv(struct ib_srq * ibsrq,const struct ib_recv_wr * wr,const struct ib_recv_wr ** bad_wr)383c3987b8eSHans Petter Selasky qlnxr_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
384c3987b8eSHans Petter Selasky const struct ib_recv_wr **bad_wr)
385fa790ea9SDavid C Somayajulu {
386fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
387fa790ea9SDavid C Somayajulu struct qlnxr_srq *srq;
388fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
389fa790ea9SDavid C Somayajulu struct qlnxr_srq_hwq_info *hw_srq;
390fa790ea9SDavid C Somayajulu struct ecore_chain *pbl;
391fa790ea9SDavid C Somayajulu unsigned long flags;
392fa790ea9SDavid C Somayajulu int status = 0;
393fa790ea9SDavid C Somayajulu u32 num_sge, offset;
394fa790ea9SDavid C Somayajulu
395fa790ea9SDavid C Somayajulu srq = get_qlnxr_srq(ibsrq);
396fa790ea9SDavid C Somayajulu dev = srq->dev;
397fa790ea9SDavid C Somayajulu ha = dev->ha;
398fa790ea9SDavid C Somayajulu hw_srq = &srq->hw_srq;
399fa790ea9SDavid C Somayajulu
400fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
401fa790ea9SDavid C Somayajulu spin_lock_irqsave(&srq->lock, flags);
402fa790ea9SDavid C Somayajulu
403fa790ea9SDavid C Somayajulu pbl = &srq->hw_srq.pbl;
404fa790ea9SDavid C Somayajulu while (wr) {
405fa790ea9SDavid C Somayajulu struct rdma_srq_wqe_header *hdr;
406fa790ea9SDavid C Somayajulu int i;
407fa790ea9SDavid C Somayajulu
408fa790ea9SDavid C Somayajulu if (!qlnxr_srq_elem_left(hw_srq) ||
409fa790ea9SDavid C Somayajulu wr->num_sge > srq->hw_srq.max_sges) {
410fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "WR cannot be posted"
411fa790ea9SDavid C Somayajulu " (%d, %d) || (%d > %d)\n",
412fa790ea9SDavid C Somayajulu hw_srq->wr_prod_cnt, hw_srq->wr_cons_cnt,
413fa790ea9SDavid C Somayajulu wr->num_sge, srq->hw_srq.max_sges);
414fa790ea9SDavid C Somayajulu status = -ENOMEM;
415fa790ea9SDavid C Somayajulu *bad_wr = wr;
416fa790ea9SDavid C Somayajulu break;
417fa790ea9SDavid C Somayajulu }
418fa790ea9SDavid C Somayajulu
419fa790ea9SDavid C Somayajulu hdr = ecore_chain_produce(pbl);
420fa790ea9SDavid C Somayajulu num_sge = wr->num_sge;
421fa790ea9SDavid C Somayajulu /* Set number of sge and WR id in header */
422fa790ea9SDavid C Somayajulu SRQ_HDR_SET(hdr, wr->wr_id, num_sge);
423fa790ea9SDavid C Somayajulu
424fa790ea9SDavid C Somayajulu /* PBL is maintained in case of WR granularity.
425fa790ea9SDavid C Somayajulu * So increment WR producer in case we post a WR.
426fa790ea9SDavid C Somayajulu */
427fa790ea9SDavid C Somayajulu qlnxr_inc_srq_wr_prod(hw_srq);
428fa790ea9SDavid C Somayajulu hw_srq->wqe_prod++;
429fa790ea9SDavid C Somayajulu hw_srq->sge_prod++;
430fa790ea9SDavid C Somayajulu
431fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "SRQ WR : SGEs: %d with wr_id[%d] = %llx\n",
432fa790ea9SDavid C Somayajulu wr->num_sge, hw_srq->wqe_prod, wr->wr_id);
433fa790ea9SDavid C Somayajulu
434fa790ea9SDavid C Somayajulu for (i = 0; i < wr->num_sge; i++) {
435fa790ea9SDavid C Somayajulu struct rdma_srq_sge *srq_sge =
436fa790ea9SDavid C Somayajulu ecore_chain_produce(pbl);
437fa790ea9SDavid C Somayajulu /* Set SGE length, lkey and address */
438fa790ea9SDavid C Somayajulu SRQ_SGE_SET(srq_sge, wr->sg_list[i].addr,
439fa790ea9SDavid C Somayajulu wr->sg_list[i].length, wr->sg_list[i].lkey);
440fa790ea9SDavid C Somayajulu
441fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "[%d]: len %d, key %x, addr %x:%x\n",
442fa790ea9SDavid C Somayajulu i, srq_sge->length, srq_sge->l_key,
443fa790ea9SDavid C Somayajulu srq_sge->addr.hi, srq_sge->addr.lo);
444fa790ea9SDavid C Somayajulu hw_srq->sge_prod++;
445fa790ea9SDavid C Somayajulu }
446fa790ea9SDavid C Somayajulu wmb();
447fa790ea9SDavid C Somayajulu /*
448fa790ea9SDavid C Somayajulu * SRQ prod is 8 bytes. Need to update SGE prod in index
449fa790ea9SDavid C Somayajulu * in first 4 bytes and need to update WQE prod in next
450fa790ea9SDavid C Somayajulu * 4 bytes.
451fa790ea9SDavid C Somayajulu */
452fa790ea9SDavid C Somayajulu *(srq->hw_srq.virt_prod_pair_addr) = hw_srq->sge_prod;
453fa790ea9SDavid C Somayajulu offset = offsetof(struct rdma_srq_producers, wqe_prod);
454fa790ea9SDavid C Somayajulu *((u8 *)srq->hw_srq.virt_prod_pair_addr + offset) =
455fa790ea9SDavid C Somayajulu hw_srq->wqe_prod;
456fa790ea9SDavid C Somayajulu /* Flush prod after updating it */
457fa790ea9SDavid C Somayajulu wmb();
458fa790ea9SDavid C Somayajulu wr = wr->next;
459fa790ea9SDavid C Somayajulu }
460fa790ea9SDavid C Somayajulu
461fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "Elements in SRQ: %d\n",
462fa790ea9SDavid C Somayajulu ecore_chain_get_elem_left(pbl));
463fa790ea9SDavid C Somayajulu
464fa790ea9SDavid C Somayajulu spin_unlock_irqrestore(&srq->lock, flags);
465fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
466fa790ea9SDavid C Somayajulu return status;
467fa790ea9SDavid C Somayajulu }
468fa790ea9SDavid C Somayajulu
469fa790ea9SDavid C Somayajulu int
qlnxr_query_device(struct ib_device * ibdev,struct ib_device_attr * attr,struct ib_udata * udata)470fa790ea9SDavid C Somayajulu qlnxr_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
471fa790ea9SDavid C Somayajulu struct ib_udata *udata)
472fa790ea9SDavid C Somayajulu {
473fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
474fa790ea9SDavid C Somayajulu struct ecore_rdma_device *qattr;
475fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
476fa790ea9SDavid C Somayajulu
477fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
478fa790ea9SDavid C Somayajulu ha = dev->ha;
479fa790ea9SDavid C Somayajulu
480fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
481fa790ea9SDavid C Somayajulu
482fa790ea9SDavid C Somayajulu if (udata->inlen || udata->outlen)
483fa790ea9SDavid C Somayajulu return -EINVAL;
484fa790ea9SDavid C Somayajulu
485fa790ea9SDavid C Somayajulu if (dev->rdma_ctx == NULL) {
486fa790ea9SDavid C Somayajulu return -EINVAL;
487fa790ea9SDavid C Somayajulu }
488fa790ea9SDavid C Somayajulu
489fa790ea9SDavid C Somayajulu qattr = ecore_rdma_query_device(dev->rdma_ctx);
490fa790ea9SDavid C Somayajulu
491fa790ea9SDavid C Somayajulu memset(attr, 0, sizeof *attr);
492fa790ea9SDavid C Somayajulu
493fa790ea9SDavid C Somayajulu attr->fw_ver = qattr->fw_ver;
494fa790ea9SDavid C Somayajulu attr->sys_image_guid = qattr->sys_image_guid;
495fa790ea9SDavid C Somayajulu attr->max_mr_size = qattr->max_mr_size;
496fa790ea9SDavid C Somayajulu attr->page_size_cap = qattr->page_size_caps;
497fa790ea9SDavid C Somayajulu attr->vendor_id = qattr->vendor_id;
498fa790ea9SDavid C Somayajulu attr->vendor_part_id = qattr->vendor_part_id;
499fa790ea9SDavid C Somayajulu attr->hw_ver = qattr->hw_ver;
500fa790ea9SDavid C Somayajulu attr->max_qp = qattr->max_qp;
501fa790ea9SDavid C Somayajulu attr->device_cap_flags = IB_DEVICE_CURR_QP_STATE_MOD |
502fa790ea9SDavid C Somayajulu IB_DEVICE_RC_RNR_NAK_GEN |
503fa790ea9SDavid C Somayajulu IB_DEVICE_LOCAL_DMA_LKEY |
504fa790ea9SDavid C Somayajulu IB_DEVICE_MEM_MGT_EXTENSIONS;
505fa790ea9SDavid C Somayajulu
506fa790ea9SDavid C Somayajulu attr->max_sge = qattr->max_sge;
507fa790ea9SDavid C Somayajulu attr->max_sge_rd = qattr->max_sge;
508fa790ea9SDavid C Somayajulu attr->max_cq = qattr->max_cq;
509fa790ea9SDavid C Somayajulu attr->max_cqe = qattr->max_cqe;
510fa790ea9SDavid C Somayajulu attr->max_mr = qattr->max_mr;
511fa790ea9SDavid C Somayajulu attr->max_mw = qattr->max_mw;
512fa790ea9SDavid C Somayajulu attr->max_pd = qattr->max_pd;
513fa790ea9SDavid C Somayajulu attr->atomic_cap = dev->atomic_cap;
514fa790ea9SDavid C Somayajulu attr->max_fmr = qattr->max_fmr;
515fa790ea9SDavid C Somayajulu attr->max_map_per_fmr = 16; /* TBD: FMR */
516fa790ea9SDavid C Somayajulu
517fa790ea9SDavid C Somayajulu /* There is an implicit assumption in some of the ib_xxx apps that the
518fa790ea9SDavid C Somayajulu * qp_rd_atom is smaller than the qp_init_rd_atom. Specifically, in
519fa790ea9SDavid C Somayajulu * communication the qp_rd_atom is passed to the other side and used as
520fa790ea9SDavid C Somayajulu * init_rd_atom without check device capabilities for init_rd_atom.
521fa790ea9SDavid C Somayajulu * for this reason, we set the qp_rd_atom to be the minimum between the
522fa790ea9SDavid C Somayajulu * two...There is an additional assumption in mlx4 driver that the
523fa790ea9SDavid C Somayajulu * values are power of two, fls is performed on the value - 1, which
524fa790ea9SDavid C Somayajulu * in fact gives a larger power of two for values which are not a power
525fa790ea9SDavid C Somayajulu * of two. This should be fixed in mlx4 driver, but until then ->
526fa790ea9SDavid C Somayajulu * we provide a value that is a power of two in our code.
527fa790ea9SDavid C Somayajulu */
528fa790ea9SDavid C Somayajulu attr->max_qp_init_rd_atom =
529fa790ea9SDavid C Somayajulu 1 << (fls(qattr->max_qp_req_rd_atomic_resc) - 1);
530fa790ea9SDavid C Somayajulu attr->max_qp_rd_atom =
531fa790ea9SDavid C Somayajulu min(1 << (fls(qattr->max_qp_resp_rd_atomic_resc) - 1),
532fa790ea9SDavid C Somayajulu attr->max_qp_init_rd_atom);
533fa790ea9SDavid C Somayajulu
534fa790ea9SDavid C Somayajulu attr->max_srq = qattr->max_srq;
535fa790ea9SDavid C Somayajulu attr->max_srq_sge = qattr->max_srq_sge;
536fa790ea9SDavid C Somayajulu attr->max_srq_wr = qattr->max_srq_wr;
537fa790ea9SDavid C Somayajulu
538fa790ea9SDavid C Somayajulu /* TODO: R&D to more properly configure the following */
539fa790ea9SDavid C Somayajulu attr->local_ca_ack_delay = qattr->dev_ack_delay;
540fa790ea9SDavid C Somayajulu attr->max_fast_reg_page_list_len = qattr->max_mr/8;
541fa790ea9SDavid C Somayajulu attr->max_pkeys = QLNXR_ROCE_PKEY_MAX;
542fa790ea9SDavid C Somayajulu attr->max_ah = qattr->max_ah;
543fa790ea9SDavid C Somayajulu
544fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
545fa790ea9SDavid C Somayajulu return 0;
546fa790ea9SDavid C Somayajulu }
547fa790ea9SDavid C Somayajulu
548fa790ea9SDavid C Somayajulu static inline void
get_link_speed_and_width(int speed,uint8_t * ib_speed,uint8_t * ib_width)549fa790ea9SDavid C Somayajulu get_link_speed_and_width(int speed, uint8_t *ib_speed, uint8_t *ib_width)
550fa790ea9SDavid C Somayajulu {
551fa790ea9SDavid C Somayajulu switch (speed) {
552fa790ea9SDavid C Somayajulu case 1000:
553fa790ea9SDavid C Somayajulu *ib_speed = IB_SPEED_SDR;
554fa790ea9SDavid C Somayajulu *ib_width = IB_WIDTH_1X;
555fa790ea9SDavid C Somayajulu break;
556fa790ea9SDavid C Somayajulu case 10000:
557fa790ea9SDavid C Somayajulu *ib_speed = IB_SPEED_QDR;
558fa790ea9SDavid C Somayajulu *ib_width = IB_WIDTH_1X;
559fa790ea9SDavid C Somayajulu break;
560fa790ea9SDavid C Somayajulu
561fa790ea9SDavid C Somayajulu case 20000:
562fa790ea9SDavid C Somayajulu *ib_speed = IB_SPEED_DDR;
563fa790ea9SDavid C Somayajulu *ib_width = IB_WIDTH_4X;
564fa790ea9SDavid C Somayajulu break;
565fa790ea9SDavid C Somayajulu
566fa790ea9SDavid C Somayajulu case 25000:
567fa790ea9SDavid C Somayajulu *ib_speed = IB_SPEED_EDR;
568fa790ea9SDavid C Somayajulu *ib_width = IB_WIDTH_1X;
569fa790ea9SDavid C Somayajulu break;
570fa790ea9SDavid C Somayajulu
571fa790ea9SDavid C Somayajulu case 40000:
572fa790ea9SDavid C Somayajulu *ib_speed = IB_SPEED_QDR;
573fa790ea9SDavid C Somayajulu *ib_width = IB_WIDTH_4X;
574fa790ea9SDavid C Somayajulu break;
575fa790ea9SDavid C Somayajulu
576fa790ea9SDavid C Somayajulu case 50000:
577fa790ea9SDavid C Somayajulu *ib_speed = IB_SPEED_QDR;
578fa790ea9SDavid C Somayajulu *ib_width = IB_WIDTH_4X; // TODO doesn't add up to 50...
579fa790ea9SDavid C Somayajulu break;
580fa790ea9SDavid C Somayajulu
581fa790ea9SDavid C Somayajulu case 100000:
582fa790ea9SDavid C Somayajulu *ib_speed = IB_SPEED_EDR;
583fa790ea9SDavid C Somayajulu *ib_width = IB_WIDTH_4X;
584fa790ea9SDavid C Somayajulu break;
585fa790ea9SDavid C Somayajulu
586fa790ea9SDavid C Somayajulu default:
587fa790ea9SDavid C Somayajulu /* Unsupported */
588fa790ea9SDavid C Somayajulu *ib_speed = IB_SPEED_SDR;
589fa790ea9SDavid C Somayajulu *ib_width = IB_WIDTH_1X;
590fa790ea9SDavid C Somayajulu }
591fa790ea9SDavid C Somayajulu return;
592fa790ea9SDavid C Somayajulu }
593fa790ea9SDavid C Somayajulu
594fa790ea9SDavid C Somayajulu int
qlnxr_query_port(struct ib_device * ibdev,uint8_t port,struct ib_port_attr * attr)595fa790ea9SDavid C Somayajulu qlnxr_query_port(struct ib_device *ibdev, uint8_t port,
596fa790ea9SDavid C Somayajulu struct ib_port_attr *attr)
597fa790ea9SDavid C Somayajulu {
598fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
599fa790ea9SDavid C Somayajulu struct ecore_rdma_port *rdma_port;
600fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
601fa790ea9SDavid C Somayajulu
602fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
603fa790ea9SDavid C Somayajulu ha = dev->ha;
604fa790ea9SDavid C Somayajulu
605fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
606fa790ea9SDavid C Somayajulu
607fa790ea9SDavid C Somayajulu if (port > 1) {
608fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "port [%d] > 1 \n", port);
609fa790ea9SDavid C Somayajulu return -EINVAL;
610fa790ea9SDavid C Somayajulu }
611fa790ea9SDavid C Somayajulu
612fa790ea9SDavid C Somayajulu if (dev->rdma_ctx == NULL) {
613fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "rdma_ctx == NULL\n");
614fa790ea9SDavid C Somayajulu return -EINVAL;
615fa790ea9SDavid C Somayajulu }
616fa790ea9SDavid C Somayajulu
617fa790ea9SDavid C Somayajulu rdma_port = ecore_rdma_query_port(dev->rdma_ctx);
618fa790ea9SDavid C Somayajulu memset(attr, 0, sizeof *attr);
619fa790ea9SDavid C Somayajulu
620fa790ea9SDavid C Somayajulu if (rdma_port->port_state == ECORE_RDMA_PORT_UP) {
621fa790ea9SDavid C Somayajulu attr->state = IB_PORT_ACTIVE;
622fa790ea9SDavid C Somayajulu attr->phys_state = 5;
623fa790ea9SDavid C Somayajulu } else {
624fa790ea9SDavid C Somayajulu attr->state = IB_PORT_DOWN;
625fa790ea9SDavid C Somayajulu attr->phys_state = 3;
626fa790ea9SDavid C Somayajulu }
627fa790ea9SDavid C Somayajulu
628fa790ea9SDavid C Somayajulu attr->max_mtu = IB_MTU_4096;
629*727bfe38SJustin Hibbits attr->active_mtu = iboe_get_mtu(if_getmtu(dev->ha->ifp));
630fa790ea9SDavid C Somayajulu attr->lid = 0;
631fa790ea9SDavid C Somayajulu attr->lmc = 0;
632fa790ea9SDavid C Somayajulu attr->sm_lid = 0;
633fa790ea9SDavid C Somayajulu attr->sm_sl = 0;
634fa790ea9SDavid C Somayajulu attr->port_cap_flags = 0;
635fa790ea9SDavid C Somayajulu
636fa790ea9SDavid C Somayajulu if (QLNX_IS_IWARP(dev)) {
637fa790ea9SDavid C Somayajulu attr->gid_tbl_len = 1;
638fa790ea9SDavid C Somayajulu attr->pkey_tbl_len = 1;
639fa790ea9SDavid C Somayajulu } else {
640fa790ea9SDavid C Somayajulu attr->gid_tbl_len = QLNXR_MAX_SGID;
641fa790ea9SDavid C Somayajulu attr->pkey_tbl_len = QLNXR_ROCE_PKEY_TABLE_LEN;
642fa790ea9SDavid C Somayajulu }
643fa790ea9SDavid C Somayajulu
644fa790ea9SDavid C Somayajulu attr->bad_pkey_cntr = rdma_port->pkey_bad_counter;
645fa790ea9SDavid C Somayajulu attr->qkey_viol_cntr = 0;
646fa790ea9SDavid C Somayajulu
647fa790ea9SDavid C Somayajulu get_link_speed_and_width(rdma_port->link_speed,
648fa790ea9SDavid C Somayajulu &attr->active_speed, &attr->active_width);
649fa790ea9SDavid C Somayajulu
650fa790ea9SDavid C Somayajulu attr->max_msg_sz = rdma_port->max_msg_size;
651fa790ea9SDavid C Somayajulu attr->max_vl_num = 4; /* TODO -> figure this one out... */
652fa790ea9SDavid C Somayajulu
653fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "state = %d phys_state = %d "
654fa790ea9SDavid C Somayajulu " link_speed = %d active_speed = %d active_width = %d"
655fa790ea9SDavid C Somayajulu " attr->gid_tbl_len = %d attr->pkey_tbl_len = %d"
656fa790ea9SDavid C Somayajulu " max_msg_sz = 0x%x max_vl_num = 0x%x \n",
657fa790ea9SDavid C Somayajulu attr->state, attr->phys_state,
658fa790ea9SDavid C Somayajulu rdma_port->link_speed, attr->active_speed,
659fa790ea9SDavid C Somayajulu attr->active_width, attr->gid_tbl_len, attr->pkey_tbl_len,
660fa790ea9SDavid C Somayajulu attr->max_msg_sz, attr->max_vl_num);
661fa790ea9SDavid C Somayajulu
662fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
663fa790ea9SDavid C Somayajulu return 0;
664fa790ea9SDavid C Somayajulu }
665fa790ea9SDavid C Somayajulu
666fa790ea9SDavid C Somayajulu int
qlnxr_modify_port(struct ib_device * ibdev,uint8_t port,int mask,struct ib_port_modify * props)667fa790ea9SDavid C Somayajulu qlnxr_modify_port(struct ib_device *ibdev, uint8_t port, int mask,
668fa790ea9SDavid C Somayajulu struct ib_port_modify *props)
669fa790ea9SDavid C Somayajulu {
670fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
671fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
672fa790ea9SDavid C Somayajulu
673fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
674fa790ea9SDavid C Somayajulu ha = dev->ha;
675fa790ea9SDavid C Somayajulu
676fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
677fa790ea9SDavid C Somayajulu
678fa790ea9SDavid C Somayajulu if (port > 1) {
679fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "port (%d) > 1\n", port);
680fa790ea9SDavid C Somayajulu return -EINVAL;
681fa790ea9SDavid C Somayajulu }
682fa790ea9SDavid C Somayajulu
683fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
684fa790ea9SDavid C Somayajulu return 0;
685fa790ea9SDavid C Somayajulu }
686fa790ea9SDavid C Somayajulu
687fa790ea9SDavid C Somayajulu enum rdma_link_layer
qlnxr_link_layer(struct ib_device * ibdev,uint8_t port_num)688fa790ea9SDavid C Somayajulu qlnxr_link_layer(struct ib_device *ibdev, uint8_t port_num)
689fa790ea9SDavid C Somayajulu {
690fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
691fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
692fa790ea9SDavid C Somayajulu
693fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
694fa790ea9SDavid C Somayajulu ha = dev->ha;
695fa790ea9SDavid C Somayajulu
696fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ibdev = %p port_num = 0x%x\n", ibdev, port_num);
697fa790ea9SDavid C Somayajulu
698fa790ea9SDavid C Somayajulu return IB_LINK_LAYER_ETHERNET;
699fa790ea9SDavid C Somayajulu }
700fa790ea9SDavid C Somayajulu
701b633e08cSHans Petter Selasky int
qlnxr_alloc_pd(struct ib_pd * ibpd,struct ib_udata * udata)702b633e08cSHans Petter Selasky qlnxr_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
703fa790ea9SDavid C Somayajulu {
704b633e08cSHans Petter Selasky struct ib_device *ibdev = ibpd->device;
705b633e08cSHans Petter Selasky struct qlnxr_pd *pd = get_qlnxr_pd(ibpd);
706fa790ea9SDavid C Somayajulu u16 pd_id;
707fa790ea9SDavid C Somayajulu int rc;
708fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
709fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
710fa790ea9SDavid C Somayajulu
711fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
712fa790ea9SDavid C Somayajulu ha = dev->ha;
713fa790ea9SDavid C Somayajulu
714b633e08cSHans Petter Selasky QL_DPRINT12(ha, "ibdev = %p udata = %p enter\n", ibdev, udata);
715fa790ea9SDavid C Somayajulu
716fa790ea9SDavid C Somayajulu if (dev->rdma_ctx == NULL) {
717fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "dev->rdma_ctx = NULL\n");
718fa790ea9SDavid C Somayajulu rc = -1;
719fa790ea9SDavid C Somayajulu goto err;
720fa790ea9SDavid C Somayajulu }
721fa790ea9SDavid C Somayajulu
722fa790ea9SDavid C Somayajulu rc = ecore_rdma_alloc_pd(dev->rdma_ctx, &pd_id);
723fa790ea9SDavid C Somayajulu if (rc) {
724fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ecore_rdma_alloc_pd failed\n");
725fa790ea9SDavid C Somayajulu goto err;
726fa790ea9SDavid C Somayajulu }
727fa790ea9SDavid C Somayajulu
728fa790ea9SDavid C Somayajulu pd->pd_id = pd_id;
729fa790ea9SDavid C Somayajulu
730b633e08cSHans Petter Selasky if (udata) {
731fa790ea9SDavid C Somayajulu rc = ib_copy_to_udata(udata, &pd->pd_id, sizeof(pd->pd_id));
732fa790ea9SDavid C Somayajulu if (rc) {
733fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ib_copy_to_udata failed\n");
734fa790ea9SDavid C Somayajulu ecore_rdma_free_pd(dev->rdma_ctx, pd_id);
735fa790ea9SDavid C Somayajulu goto err;
736fa790ea9SDavid C Somayajulu }
737fa790ea9SDavid C Somayajulu
738b633e08cSHans Petter Selasky pd->uctx = rdma_udata_to_drv_context(
739b633e08cSHans Petter Selasky udata, struct qlnxr_ucontext, ibucontext);
740fa790ea9SDavid C Somayajulu pd->uctx->pd = pd;
741fa790ea9SDavid C Somayajulu }
742fa790ea9SDavid C Somayajulu
743fa790ea9SDavid C Somayajulu atomic_add_rel_32(&dev->pd_count, 1);
744fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [pd, pd_id, pd_count] = [%p, 0x%x, %d]\n",
745fa790ea9SDavid C Somayajulu pd, pd_id, dev->pd_count);
746fa790ea9SDavid C Somayajulu
747b633e08cSHans Petter Selasky return (0);
748fa790ea9SDavid C Somayajulu
749fa790ea9SDavid C Somayajulu err:
750fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit -1\n");
751b633e08cSHans Petter Selasky return (rc);
752fa790ea9SDavid C Somayajulu }
753fa790ea9SDavid C Somayajulu
754b633e08cSHans Petter Selasky void
qlnxr_dealloc_pd(struct ib_pd * ibpd,struct ib_udata * udata)755b633e08cSHans Petter Selasky qlnxr_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
756fa790ea9SDavid C Somayajulu {
757fa790ea9SDavid C Somayajulu struct qlnxr_pd *pd;
758fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
759fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
760fa790ea9SDavid C Somayajulu
761fa790ea9SDavid C Somayajulu pd = get_qlnxr_pd(ibpd);
762fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev((ibpd->device));
763fa790ea9SDavid C Somayajulu ha = dev->ha;
764fa790ea9SDavid C Somayajulu
765fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
766fa790ea9SDavid C Somayajulu
767fa790ea9SDavid C Somayajulu if (pd == NULL) {
768fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "pd = NULL\n");
769fa790ea9SDavid C Somayajulu } else {
770fa790ea9SDavid C Somayajulu ecore_rdma_free_pd(dev->rdma_ctx, pd->pd_id);
771fa790ea9SDavid C Somayajulu atomic_subtract_rel_32(&dev->pd_count, 1);
772fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [pd, pd_id, pd_count] = [%p, 0x%x, %d]\n",
773fa790ea9SDavid C Somayajulu pd, pd->pd_id, dev->pd_count);
774fa790ea9SDavid C Somayajulu }
775fa790ea9SDavid C Somayajulu
776fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
777fa790ea9SDavid C Somayajulu }
778fa790ea9SDavid C Somayajulu
779fa790ea9SDavid C Somayajulu #define ROCE_WQE_ELEM_SIZE sizeof(struct rdma_sq_sge)
780fa790ea9SDavid C Somayajulu #define RDMA_MAX_SGE_PER_SRQ (4) /* Should be part of HSI */
781fa790ea9SDavid C Somayajulu /* Should be part of HSI */
782fa790ea9SDavid C Somayajulu #define RDMA_MAX_SRQ_WQE_SIZE (RDMA_MAX_SGE_PER_SRQ + 1) /* +1 for header */
783fa790ea9SDavid C Somayajulu #define DB_ADDR_SHIFT(addr) ((addr) << DB_PWM_ADDR_OFFSET_SHIFT)
784fa790ea9SDavid C Somayajulu
785fa790ea9SDavid C Somayajulu static void qlnxr_cleanup_user(struct qlnxr_dev *, struct qlnxr_qp *);
786fa790ea9SDavid C Somayajulu static void qlnxr_cleanup_kernel(struct qlnxr_dev *, struct qlnxr_qp *);
787fa790ea9SDavid C Somayajulu
788fa790ea9SDavid C Somayajulu int
qlnxr_query_pkey(struct ib_device * ibdev,u8 port,u16 index,u16 * pkey)789fa790ea9SDavid C Somayajulu qlnxr_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
790fa790ea9SDavid C Somayajulu {
791fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
792fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
793fa790ea9SDavid C Somayajulu
794fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
795fa790ea9SDavid C Somayajulu ha = dev->ha;
796fa790ea9SDavid C Somayajulu
797fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter index = 0x%x\n", index);
798fa790ea9SDavid C Somayajulu
799fa790ea9SDavid C Somayajulu if (index > QLNXR_ROCE_PKEY_TABLE_LEN)
800fa790ea9SDavid C Somayajulu return -EINVAL;
801fa790ea9SDavid C Somayajulu
802fa790ea9SDavid C Somayajulu *pkey = QLNXR_ROCE_PKEY_DEFAULT;
803fa790ea9SDavid C Somayajulu
804fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
805fa790ea9SDavid C Somayajulu return 0;
806fa790ea9SDavid C Somayajulu }
807fa790ea9SDavid C Somayajulu
808fa790ea9SDavid C Somayajulu static inline bool
qlnxr_get_vlan_id_qp(qlnx_host_t * ha,struct ib_qp_attr * attr,int attr_mask,u16 * vlan_id)809fa790ea9SDavid C Somayajulu qlnxr_get_vlan_id_qp(qlnx_host_t *ha, struct ib_qp_attr *attr, int attr_mask,
810fa790ea9SDavid C Somayajulu u16 *vlan_id)
811fa790ea9SDavid C Somayajulu {
812fa790ea9SDavid C Somayajulu bool ret = false;
813fa790ea9SDavid C Somayajulu
814bbe35708SElliott Mitchell u16 tmp_vlan_id;
815bbe35708SElliott Mitchell
816bbe35708SElliott Mitchell union ib_gid *dgid;
817bbe35708SElliott Mitchell
818fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter \n");
819fa790ea9SDavid C Somayajulu
820fa790ea9SDavid C Somayajulu *vlan_id = 0;
821fa790ea9SDavid C Somayajulu
822fa790ea9SDavid C Somayajulu dgid = &attr->ah_attr.grh.dgid;
823fa790ea9SDavid C Somayajulu tmp_vlan_id = (dgid->raw[11] << 8) | dgid->raw[12];
824fa790ea9SDavid C Somayajulu
825fa790ea9SDavid C Somayajulu if (!(tmp_vlan_id & ~EVL_VLID_MASK)) {
826fa790ea9SDavid C Somayajulu *vlan_id = tmp_vlan_id;
827fa790ea9SDavid C Somayajulu ret = true;
828fa790ea9SDavid C Somayajulu }
829fa790ea9SDavid C Somayajulu
830fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit vlan_id = 0x%x ret = %d \n", *vlan_id, ret);
831fa790ea9SDavid C Somayajulu
832fa790ea9SDavid C Somayajulu return (ret);
833fa790ea9SDavid C Somayajulu }
834fa790ea9SDavid C Somayajulu
835fa790ea9SDavid C Somayajulu static inline void
get_gid_info(struct ib_qp * ibqp,struct ib_qp_attr * attr,int attr_mask,struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct ecore_rdma_modify_qp_in_params * qp_params)836fa790ea9SDavid C Somayajulu get_gid_info(struct ib_qp *ibqp, struct ib_qp_attr *attr,
837fa790ea9SDavid C Somayajulu int attr_mask,
838fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev,
839fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
840fa790ea9SDavid C Somayajulu struct ecore_rdma_modify_qp_in_params *qp_params)
841fa790ea9SDavid C Somayajulu {
842fa790ea9SDavid C Somayajulu int i;
843fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
844fa790ea9SDavid C Somayajulu
845fa790ea9SDavid C Somayajulu ha = dev->ha;
846fa790ea9SDavid C Somayajulu
847fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
848fa790ea9SDavid C Somayajulu
849fa790ea9SDavid C Somayajulu memcpy(&qp_params->sgid.bytes[0],
850fa790ea9SDavid C Somayajulu &dev->sgid_tbl[qp->sgid_idx].raw[0],
851fa790ea9SDavid C Somayajulu sizeof(qp_params->sgid.bytes));
852fa790ea9SDavid C Somayajulu memcpy(&qp_params->dgid.bytes[0],
853fa790ea9SDavid C Somayajulu &attr->ah_attr.grh.dgid.raw[0],
854fa790ea9SDavid C Somayajulu sizeof(qp_params->dgid));
855fa790ea9SDavid C Somayajulu
856fa790ea9SDavid C Somayajulu qlnxr_get_vlan_id_qp(ha, attr, attr_mask, &qp_params->vlan_id);
857fa790ea9SDavid C Somayajulu
858fa790ea9SDavid C Somayajulu for (i = 0; i < (sizeof(qp_params->sgid.dwords)/sizeof(uint32_t)); i++) {
859fa790ea9SDavid C Somayajulu qp_params->sgid.dwords[i] = ntohl(qp_params->sgid.dwords[i]);
860fa790ea9SDavid C Somayajulu qp_params->dgid.dwords[i] = ntohl(qp_params->dgid.dwords[i]);
861fa790ea9SDavid C Somayajulu }
862fa790ea9SDavid C Somayajulu
863fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
864fa790ea9SDavid C Somayajulu return;
865fa790ea9SDavid C Somayajulu }
866fa790ea9SDavid C Somayajulu
867fa790ea9SDavid C Somayajulu static int
qlnxr_add_mmap(struct qlnxr_ucontext * uctx,u64 phy_addr,unsigned long len)868fa790ea9SDavid C Somayajulu qlnxr_add_mmap(struct qlnxr_ucontext *uctx, u64 phy_addr, unsigned long len)
869fa790ea9SDavid C Somayajulu {
870fa790ea9SDavid C Somayajulu struct qlnxr_mm *mm;
871fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
872fa790ea9SDavid C Somayajulu
873fa790ea9SDavid C Somayajulu ha = uctx->dev->ha;
874fa790ea9SDavid C Somayajulu
875fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
876fa790ea9SDavid C Somayajulu
877fa790ea9SDavid C Somayajulu mm = kzalloc(sizeof(*mm), GFP_KERNEL);
878fa790ea9SDavid C Somayajulu if (mm == NULL) {
879fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "mm = NULL\n");
880fa790ea9SDavid C Somayajulu return -ENOMEM;
881fa790ea9SDavid C Somayajulu }
882fa790ea9SDavid C Somayajulu
883fa790ea9SDavid C Somayajulu mm->key.phy_addr = phy_addr;
884fa790ea9SDavid C Somayajulu
885fa790ea9SDavid C Somayajulu /* This function might be called with a length which is not a multiple
886fa790ea9SDavid C Somayajulu * of PAGE_SIZE, while the mapping is PAGE_SIZE grained and the kernel
887fa790ea9SDavid C Somayajulu * forces this granularity by increasing the requested size if needed.
888fa790ea9SDavid C Somayajulu * When qedr_mmap is called, it will search the list with the updated
889fa790ea9SDavid C Somayajulu * length as a key. To prevent search failures, the length is rounded up
890fa790ea9SDavid C Somayajulu * in advance to PAGE_SIZE.
891fa790ea9SDavid C Somayajulu */
892fa790ea9SDavid C Somayajulu mm->key.len = roundup(len, PAGE_SIZE);
893fa790ea9SDavid C Somayajulu INIT_LIST_HEAD(&mm->entry);
894fa790ea9SDavid C Somayajulu
895fa790ea9SDavid C Somayajulu mutex_lock(&uctx->mm_list_lock);
896fa790ea9SDavid C Somayajulu list_add(&mm->entry, &uctx->mm_head);
897fa790ea9SDavid C Somayajulu mutex_unlock(&uctx->mm_list_lock);
898fa790ea9SDavid C Somayajulu
899fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "added (addr=0x%llx,len=0x%lx) for ctx=%p\n",
900fa790ea9SDavid C Somayajulu (unsigned long long)mm->key.phy_addr,
901fa790ea9SDavid C Somayajulu (unsigned long)mm->key.len, uctx);
902fa790ea9SDavid C Somayajulu
903fa790ea9SDavid C Somayajulu return 0;
904fa790ea9SDavid C Somayajulu }
905fa790ea9SDavid C Somayajulu
906fa790ea9SDavid C Somayajulu static bool
qlnxr_search_mmap(struct qlnxr_ucontext * uctx,u64 phy_addr,unsigned long len)907fa790ea9SDavid C Somayajulu qlnxr_search_mmap(struct qlnxr_ucontext *uctx, u64 phy_addr, unsigned long len)
908fa790ea9SDavid C Somayajulu {
909fa790ea9SDavid C Somayajulu bool found = false;
910fa790ea9SDavid C Somayajulu struct qlnxr_mm *mm;
911fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
912fa790ea9SDavid C Somayajulu
913fa790ea9SDavid C Somayajulu ha = uctx->dev->ha;
914fa790ea9SDavid C Somayajulu
915fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
916fa790ea9SDavid C Somayajulu
917fa790ea9SDavid C Somayajulu mutex_lock(&uctx->mm_list_lock);
918fa790ea9SDavid C Somayajulu list_for_each_entry(mm, &uctx->mm_head, entry) {
919fa790ea9SDavid C Somayajulu if (len != mm->key.len || phy_addr != mm->key.phy_addr)
920fa790ea9SDavid C Somayajulu continue;
921fa790ea9SDavid C Somayajulu
922fa790ea9SDavid C Somayajulu found = true;
923fa790ea9SDavid C Somayajulu break;
924fa790ea9SDavid C Somayajulu }
925fa790ea9SDavid C Somayajulu mutex_unlock(&uctx->mm_list_lock);
926fa790ea9SDavid C Somayajulu
927fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
928fa790ea9SDavid C Somayajulu "searched for (addr=0x%llx,len=0x%lx) for ctx=%p, found=%d\n",
929fa790ea9SDavid C Somayajulu mm->key.phy_addr, mm->key.len, uctx, found);
930fa790ea9SDavid C Somayajulu
931fa790ea9SDavid C Somayajulu return found;
932fa790ea9SDavid C Somayajulu }
933fa790ea9SDavid C Somayajulu
934b633e08cSHans Petter Selasky int
qlnxr_alloc_ucontext(struct ib_ucontext * uctx,struct ib_udata * udata)935b633e08cSHans Petter Selasky qlnxr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
936fa790ea9SDavid C Somayajulu {
937fa790ea9SDavid C Somayajulu int rc;
938b633e08cSHans Petter Selasky struct qlnxr_ucontext *ctx = get_qlnxr_ucontext(uctx);
939fa790ea9SDavid C Somayajulu struct qlnxr_alloc_ucontext_resp uresp;
940b633e08cSHans Petter Selasky struct qlnxr_dev *dev = get_qlnxr_dev(uctx->device);
941fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
942fa790ea9SDavid C Somayajulu struct ecore_rdma_add_user_out_params oparams;
943fa790ea9SDavid C Somayajulu
944b633e08cSHans Petter Selasky if (!udata)
945b633e08cSHans Petter Selasky return -EFAULT;
946fa790ea9SDavid C Somayajulu
947fa790ea9SDavid C Somayajulu rc = ecore_rdma_add_user(dev->rdma_ctx, &oparams);
948fa790ea9SDavid C Somayajulu if (rc) {
949fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
950fa790ea9SDavid C Somayajulu "Failed to allocate a DPI for a new RoCE application "
951fa790ea9SDavid C Somayajulu ",rc = %d. To overcome this, consider to increase "
952fa790ea9SDavid C Somayajulu "the number of DPIs, increase the doorbell BAR size "
953fa790ea9SDavid C Somayajulu "or just close unnecessary RoCE applications. In "
954fa790ea9SDavid C Somayajulu "order to increase the number of DPIs consult the "
955fa790ea9SDavid C Somayajulu "README\n", rc);
956fa790ea9SDavid C Somayajulu goto err;
957fa790ea9SDavid C Somayajulu }
958fa790ea9SDavid C Somayajulu
959fa790ea9SDavid C Somayajulu ctx->dpi = oparams.dpi;
960fa790ea9SDavid C Somayajulu ctx->dpi_addr = oparams.dpi_addr;
961fa790ea9SDavid C Somayajulu ctx->dpi_phys_addr = oparams.dpi_phys_addr;
962fa790ea9SDavid C Somayajulu ctx->dpi_size = oparams.dpi_size;
963fa790ea9SDavid C Somayajulu INIT_LIST_HEAD(&ctx->mm_head);
964fa790ea9SDavid C Somayajulu mutex_init(&ctx->mm_list_lock);
965fa790ea9SDavid C Somayajulu
966fa790ea9SDavid C Somayajulu memset(&uresp, 0, sizeof(uresp));
967fa790ea9SDavid C Somayajulu uresp.dpm_enabled = offsetof(struct qlnxr_alloc_ucontext_resp, dpm_enabled)
968fa790ea9SDavid C Somayajulu < udata->outlen ? dev->user_dpm_enabled : 0; //TODO: figure this out
969fa790ea9SDavid C Somayajulu uresp.wids_enabled = offsetof(struct qlnxr_alloc_ucontext_resp, wids_enabled)
970fa790ea9SDavid C Somayajulu < udata->outlen ? 1 : 0; //TODO: figure this out
971fa790ea9SDavid C Somayajulu uresp.wid_count = offsetof(struct qlnxr_alloc_ucontext_resp, wid_count)
972fa790ea9SDavid C Somayajulu < udata->outlen ? oparams.wid_count : 0; //TODO: figure this out
973fa790ea9SDavid C Somayajulu uresp.db_pa = ctx->dpi_phys_addr;
974fa790ea9SDavid C Somayajulu uresp.db_size = ctx->dpi_size;
975fa790ea9SDavid C Somayajulu uresp.max_send_wr = dev->attr.max_sqe;
976fa790ea9SDavid C Somayajulu uresp.max_recv_wr = dev->attr.max_rqe;
977fa790ea9SDavid C Somayajulu uresp.max_srq_wr = dev->attr.max_srq_wr;
978fa790ea9SDavid C Somayajulu uresp.sges_per_send_wr = QLNXR_MAX_SQE_ELEMENTS_PER_SQE;
979fa790ea9SDavid C Somayajulu uresp.sges_per_recv_wr = QLNXR_MAX_RQE_ELEMENTS_PER_RQE;
980fa790ea9SDavid C Somayajulu uresp.sges_per_srq_wr = dev->attr.max_srq_sge;
981fa790ea9SDavid C Somayajulu uresp.max_cqes = QLNXR_MAX_CQES;
982fa790ea9SDavid C Somayajulu
983fa790ea9SDavid C Somayajulu rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
984fa790ea9SDavid C Somayajulu if (rc)
985fa790ea9SDavid C Somayajulu goto err;
986fa790ea9SDavid C Somayajulu
987fa790ea9SDavid C Somayajulu ctx->dev = dev;
988fa790ea9SDavid C Somayajulu
989fa790ea9SDavid C Somayajulu rc = qlnxr_add_mmap(ctx, ctx->dpi_phys_addr, ctx->dpi_size);
990fa790ea9SDavid C Somayajulu if (rc)
991fa790ea9SDavid C Somayajulu goto err;
992fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "Allocated user context %p\n",
993fa790ea9SDavid C Somayajulu &ctx->ibucontext);
994fa790ea9SDavid C Somayajulu
995b633e08cSHans Petter Selasky return (0);
996fa790ea9SDavid C Somayajulu err:
997b633e08cSHans Petter Selasky return (rc);
998fa790ea9SDavid C Somayajulu }
999fa790ea9SDavid C Somayajulu
1000b633e08cSHans Petter Selasky void
qlnxr_dealloc_ucontext(struct ib_ucontext * ibctx)1001fa790ea9SDavid C Somayajulu qlnxr_dealloc_ucontext(struct ib_ucontext *ibctx)
1002fa790ea9SDavid C Somayajulu {
1003fa790ea9SDavid C Somayajulu struct qlnxr_ucontext *uctx = get_qlnxr_ucontext(ibctx);
1004fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = uctx->dev;
1005fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
1006fa790ea9SDavid C Somayajulu struct qlnxr_mm *mm, *tmp;
1007fa790ea9SDavid C Somayajulu
1008fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "Deallocating user context %p\n",
1009fa790ea9SDavid C Somayajulu uctx);
1010fa790ea9SDavid C Somayajulu
1011fa790ea9SDavid C Somayajulu if (dev) {
1012fa790ea9SDavid C Somayajulu ecore_rdma_remove_user(uctx->dev->rdma_ctx, uctx->dpi);
1013fa790ea9SDavid C Somayajulu }
1014fa790ea9SDavid C Somayajulu
1015fa790ea9SDavid C Somayajulu list_for_each_entry_safe(mm, tmp, &uctx->mm_head, entry) {
1016fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "deleted addr= 0x%llx, len = 0x%lx for"
1017fa790ea9SDavid C Somayajulu " ctx=%p\n",
1018fa790ea9SDavid C Somayajulu mm->key.phy_addr, mm->key.len, uctx);
1019fa790ea9SDavid C Somayajulu list_del(&mm->entry);
1020fa790ea9SDavid C Somayajulu kfree(mm);
1021fa790ea9SDavid C Somayajulu }
1022fa790ea9SDavid C Somayajulu }
1023fa790ea9SDavid C Somayajulu
1024fa790ea9SDavid C Somayajulu int
qlnxr_mmap(struct ib_ucontext * context,struct vm_area_struct * vma)1025fa790ea9SDavid C Somayajulu qlnxr_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
1026fa790ea9SDavid C Somayajulu {
1027fa790ea9SDavid C Somayajulu struct qlnxr_ucontext *ucontext = get_qlnxr_ucontext(context);
1028fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev((context->device));
1029fa790ea9SDavid C Somayajulu unsigned long vm_page = vma->vm_pgoff << PAGE_SHIFT;
1030fa790ea9SDavid C Somayajulu u64 unmapped_db;
1031fa790ea9SDavid C Somayajulu unsigned long len = (vma->vm_end - vma->vm_start);
1032fa790ea9SDavid C Somayajulu int rc = 0;
1033fa790ea9SDavid C Somayajulu bool found;
1034fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1035fa790ea9SDavid C Somayajulu
1036fa790ea9SDavid C Somayajulu ha = dev->ha;
1037fa790ea9SDavid C Somayajulu
1038fa790ea9SDavid C Somayajulu unmapped_db = dev->db_phys_addr + (ucontext->dpi * ucontext->dpi_size);
1039fa790ea9SDavid C Somayajulu
1040fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qedr_mmap enter vm_page=0x%lx"
1041fa790ea9SDavid C Somayajulu " vm_pgoff=0x%lx unmapped_db=0x%llx db_size=%x, len=%lx\n",
1042fa790ea9SDavid C Somayajulu vm_page, vma->vm_pgoff, unmapped_db,
1043fa790ea9SDavid C Somayajulu dev->db_size, len);
1044fa790ea9SDavid C Somayajulu
1045fa790ea9SDavid C Somayajulu if ((vma->vm_start & (PAGE_SIZE - 1)) || (len & (PAGE_SIZE - 1))) {
1046fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "Vma_start not page aligned "
1047fa790ea9SDavid C Somayajulu "vm_start = %ld vma_end = %ld\n", vma->vm_start,
1048fa790ea9SDavid C Somayajulu vma->vm_end);
1049fa790ea9SDavid C Somayajulu return -EINVAL;
1050fa790ea9SDavid C Somayajulu }
1051fa790ea9SDavid C Somayajulu
1052fa790ea9SDavid C Somayajulu found = qlnxr_search_mmap(ucontext, vm_page, len);
1053fa790ea9SDavid C Somayajulu if (!found) {
1054fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "Vma_pgoff not found in mapped array = %ld\n",
1055fa790ea9SDavid C Somayajulu vma->vm_pgoff);
1056fa790ea9SDavid C Somayajulu return -EINVAL;
1057fa790ea9SDavid C Somayajulu }
1058fa790ea9SDavid C Somayajulu
1059fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "Mapping doorbell bar\n");
1060fa790ea9SDavid C Somayajulu
1061fa790ea9SDavid C Somayajulu if ((vm_page < unmapped_db) ||
1062fa790ea9SDavid C Somayajulu ((vm_page + len) > (unmapped_db + ucontext->dpi_size))) {
1063fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "failed pages are outside of dpi;"
1064fa790ea9SDavid C Somayajulu "page address=0x%lx, unmapped_db=0x%lx, dpi_size=0x%x\n",
1065fa790ea9SDavid C Somayajulu vm_page, unmapped_db, ucontext->dpi_size);
1066fa790ea9SDavid C Somayajulu return -EINVAL;
1067fa790ea9SDavid C Somayajulu }
1068fa790ea9SDavid C Somayajulu
1069fa790ea9SDavid C Somayajulu if (vma->vm_flags & VM_READ) {
1070fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "failed mmap, cannot map doorbell bar for read\n");
1071fa790ea9SDavid C Somayajulu return -EINVAL;
1072fa790ea9SDavid C Somayajulu }
1073fa790ea9SDavid C Somayajulu
1074fa790ea9SDavid C Somayajulu vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1075fa790ea9SDavid C Somayajulu rc = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, len,
1076fa790ea9SDavid C Somayajulu vma->vm_page_prot);
1077fa790ea9SDavid C Somayajulu
1078fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
1079fa790ea9SDavid C Somayajulu return rc;
1080fa790ea9SDavid C Somayajulu }
1081fa790ea9SDavid C Somayajulu
1082fa790ea9SDavid C Somayajulu struct ib_mr *
qlnxr_get_dma_mr(struct ib_pd * ibpd,int acc)1083fa790ea9SDavid C Somayajulu qlnxr_get_dma_mr(struct ib_pd *ibpd, int acc)
1084fa790ea9SDavid C Somayajulu {
1085fa790ea9SDavid C Somayajulu struct qlnxr_mr *mr;
1086fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev((ibpd->device));
1087fa790ea9SDavid C Somayajulu struct qlnxr_pd *pd = get_qlnxr_pd(ibpd);
1088fa790ea9SDavid C Somayajulu int rc;
1089fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1090fa790ea9SDavid C Somayajulu
1091fa790ea9SDavid C Somayajulu ha = dev->ha;
1092fa790ea9SDavid C Somayajulu
1093fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1094fa790ea9SDavid C Somayajulu
1095fa790ea9SDavid C Somayajulu if (acc & IB_ACCESS_MW_BIND) {
1096fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "Unsupported access flags received for dma mr\n");
1097fa790ea9SDavid C Somayajulu }
1098fa790ea9SDavid C Somayajulu
1099fa790ea9SDavid C Somayajulu mr = kzalloc(sizeof(*mr), GFP_KERNEL);
1100fa790ea9SDavid C Somayajulu if (!mr) {
1101fa790ea9SDavid C Somayajulu rc = -ENOMEM;
1102fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "kzalloc(mr) failed %d\n", rc);
1103fa790ea9SDavid C Somayajulu goto err0;
1104fa790ea9SDavid C Somayajulu }
1105fa790ea9SDavid C Somayajulu
1106fa790ea9SDavid C Somayajulu mr->type = QLNXR_MR_DMA;
1107fa790ea9SDavid C Somayajulu
1108fa790ea9SDavid C Somayajulu rc = ecore_rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid);
1109fa790ea9SDavid C Somayajulu if (rc) {
1110fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ecore_rdma_alloc_tid failed %d\n", rc);
1111fa790ea9SDavid C Somayajulu goto err1;
1112fa790ea9SDavid C Somayajulu }
1113fa790ea9SDavid C Somayajulu
1114fa790ea9SDavid C Somayajulu /* index only, 18 bit long, lkey = itid << 8 | key */
1115fa790ea9SDavid C Somayajulu mr->hw_mr.tid_type = ECORE_RDMA_TID_REGISTERED_MR;
1116fa790ea9SDavid C Somayajulu mr->hw_mr.pd = pd->pd_id;
1117fa790ea9SDavid C Somayajulu mr->hw_mr.local_read = 1;
1118fa790ea9SDavid C Somayajulu mr->hw_mr.local_write = (acc & IB_ACCESS_LOCAL_WRITE) ? 1 : 0;
1119fa790ea9SDavid C Somayajulu mr->hw_mr.remote_read = (acc & IB_ACCESS_REMOTE_READ) ? 1 : 0;
1120fa790ea9SDavid C Somayajulu mr->hw_mr.remote_write = (acc & IB_ACCESS_REMOTE_WRITE) ? 1 : 0;
1121fa790ea9SDavid C Somayajulu mr->hw_mr.remote_atomic = (acc & IB_ACCESS_REMOTE_ATOMIC) ? 1 : 0;
1122fa790ea9SDavid C Somayajulu mr->hw_mr.dma_mr = true;
1123fa790ea9SDavid C Somayajulu
1124fa790ea9SDavid C Somayajulu rc = ecore_rdma_register_tid(dev->rdma_ctx, &mr->hw_mr);
1125fa790ea9SDavid C Somayajulu if (rc) {
1126fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ecore_rdma_register_tid failed %d\n", rc);
1127fa790ea9SDavid C Somayajulu goto err2;
1128fa790ea9SDavid C Somayajulu }
1129fa790ea9SDavid C Somayajulu
1130fa790ea9SDavid C Somayajulu mr->ibmr.lkey = mr->hw_mr.itid << 8 | mr->hw_mr.key;
1131fa790ea9SDavid C Somayajulu
1132fa790ea9SDavid C Somayajulu if (mr->hw_mr.remote_write || mr->hw_mr.remote_read ||
1133fa790ea9SDavid C Somayajulu mr->hw_mr.remote_atomic) {
1134fa790ea9SDavid C Somayajulu mr->ibmr.rkey = mr->hw_mr.itid << 8 | mr->hw_mr.key;
1135fa790ea9SDavid C Somayajulu }
1136fa790ea9SDavid C Somayajulu
1137fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "lkey = %x\n", mr->ibmr.lkey);
1138fa790ea9SDavid C Somayajulu
1139fa790ea9SDavid C Somayajulu return &mr->ibmr;
1140fa790ea9SDavid C Somayajulu
1141fa790ea9SDavid C Somayajulu err2:
1142fa790ea9SDavid C Somayajulu ecore_rdma_free_tid(dev->rdma_ctx, mr->hw_mr.itid);
1143fa790ea9SDavid C Somayajulu err1:
1144fa790ea9SDavid C Somayajulu kfree(mr);
1145fa790ea9SDavid C Somayajulu err0:
1146fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
1147fa790ea9SDavid C Somayajulu
1148fa790ea9SDavid C Somayajulu return ERR_PTR(rc);
1149fa790ea9SDavid C Somayajulu }
1150fa790ea9SDavid C Somayajulu
1151fa790ea9SDavid C Somayajulu static void
qlnxr_free_pbl(struct qlnxr_dev * dev,struct qlnxr_pbl_info * pbl_info,struct qlnxr_pbl * pbl)1152fa790ea9SDavid C Somayajulu qlnxr_free_pbl(struct qlnxr_dev *dev, struct qlnxr_pbl_info *pbl_info,
1153fa790ea9SDavid C Somayajulu struct qlnxr_pbl *pbl)
1154fa790ea9SDavid C Somayajulu {
1155fa790ea9SDavid C Somayajulu int i;
1156fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1157fa790ea9SDavid C Somayajulu
1158fa790ea9SDavid C Somayajulu ha = dev->ha;
1159fa790ea9SDavid C Somayajulu
1160fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1161fa790ea9SDavid C Somayajulu
1162fa790ea9SDavid C Somayajulu for (i = 0; i < pbl_info->num_pbls; i++) {
1163fa790ea9SDavid C Somayajulu if (!pbl[i].va)
1164fa790ea9SDavid C Somayajulu continue;
1165fa790ea9SDavid C Somayajulu qlnx_dma_free_coherent(&dev->ha->cdev, pbl[i].va, pbl[i].pa,
1166fa790ea9SDavid C Somayajulu pbl_info->pbl_size);
1167fa790ea9SDavid C Somayajulu }
1168fa790ea9SDavid C Somayajulu kfree(pbl);
1169fa790ea9SDavid C Somayajulu
1170fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
1171fa790ea9SDavid C Somayajulu return;
1172fa790ea9SDavid C Somayajulu }
1173fa790ea9SDavid C Somayajulu
1174fa790ea9SDavid C Somayajulu #define MIN_FW_PBL_PAGE_SIZE (4*1024)
1175fa790ea9SDavid C Somayajulu #define MAX_FW_PBL_PAGE_SIZE (64*1024)
1176fa790ea9SDavid C Somayajulu
1177fa790ea9SDavid C Somayajulu #define NUM_PBES_ON_PAGE(_page_size) (_page_size / sizeof(u64))
1178fa790ea9SDavid C Somayajulu #define MAX_PBES_ON_PAGE NUM_PBES_ON_PAGE(MAX_FW_PBL_PAGE_SIZE)
1179fa790ea9SDavid C Somayajulu #define MAX_PBES_TWO_LAYER (MAX_PBES_ON_PAGE*MAX_PBES_ON_PAGE)
1180fa790ea9SDavid C Somayajulu
1181fa790ea9SDavid C Somayajulu static struct qlnxr_pbl *
qlnxr_alloc_pbl_tbl(struct qlnxr_dev * dev,struct qlnxr_pbl_info * pbl_info,gfp_t flags)1182fa790ea9SDavid C Somayajulu qlnxr_alloc_pbl_tbl(struct qlnxr_dev *dev,
1183fa790ea9SDavid C Somayajulu struct qlnxr_pbl_info *pbl_info, gfp_t flags)
1184fa790ea9SDavid C Somayajulu {
1185fa790ea9SDavid C Somayajulu void *va;
1186fa790ea9SDavid C Somayajulu dma_addr_t pa;
1187fa790ea9SDavid C Somayajulu dma_addr_t *pbl_main_tbl;
1188fa790ea9SDavid C Somayajulu struct qlnxr_pbl *pbl_table;
118991aa93ebSJohn Baldwin int i;
1190fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1191fa790ea9SDavid C Somayajulu
1192fa790ea9SDavid C Somayajulu ha = dev->ha;
1193fa790ea9SDavid C Somayajulu
1194fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1195fa790ea9SDavid C Somayajulu
1196fa790ea9SDavid C Somayajulu pbl_table = kzalloc(sizeof(*pbl_table) * pbl_info->num_pbls, flags);
1197fa790ea9SDavid C Somayajulu
1198fa790ea9SDavid C Somayajulu if (!pbl_table) {
1199fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "pbl_table = NULL\n");
1200fa790ea9SDavid C Somayajulu return NULL;
1201fa790ea9SDavid C Somayajulu }
1202fa790ea9SDavid C Somayajulu
1203fa790ea9SDavid C Somayajulu for (i = 0; i < pbl_info->num_pbls; i++) {
1204fa790ea9SDavid C Somayajulu va = qlnx_dma_alloc_coherent(&dev->ha->cdev, &pa, pbl_info->pbl_size);
1205fa790ea9SDavid C Somayajulu if (!va) {
1206fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "Failed to allocate pbl#%d\n", i);
1207fa790ea9SDavid C Somayajulu goto err;
1208fa790ea9SDavid C Somayajulu }
1209fa790ea9SDavid C Somayajulu memset(va, 0, pbl_info->pbl_size);
1210fa790ea9SDavid C Somayajulu pbl_table[i].va = va;
1211fa790ea9SDavid C Somayajulu pbl_table[i].pa = pa;
1212fa790ea9SDavid C Somayajulu }
1213fa790ea9SDavid C Somayajulu
1214fa790ea9SDavid C Somayajulu /* Two-Layer PBLs, if we have more than one pbl we need to initialize
1215fa790ea9SDavid C Somayajulu * the first one with physical pointers to all of the rest
1216fa790ea9SDavid C Somayajulu */
1217fa790ea9SDavid C Somayajulu pbl_main_tbl = (dma_addr_t *)pbl_table[0].va;
1218fa790ea9SDavid C Somayajulu for (i = 0; i < pbl_info->num_pbls - 1; i++)
1219fa790ea9SDavid C Somayajulu pbl_main_tbl[i] = pbl_table[i + 1].pa;
1220fa790ea9SDavid C Somayajulu
1221fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
1222fa790ea9SDavid C Somayajulu return pbl_table;
1223fa790ea9SDavid C Somayajulu
1224fa790ea9SDavid C Somayajulu err:
1225fa790ea9SDavid C Somayajulu qlnxr_free_pbl(dev, pbl_info, pbl_table);
1226fa790ea9SDavid C Somayajulu
1227fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit with error\n");
1228fa790ea9SDavid C Somayajulu return NULL;
1229fa790ea9SDavid C Somayajulu }
1230fa790ea9SDavid C Somayajulu
1231fa790ea9SDavid C Somayajulu static int
qlnxr_prepare_pbl_tbl(struct qlnxr_dev * dev,struct qlnxr_pbl_info * pbl_info,u32 num_pbes,int two_layer_capable)1232fa790ea9SDavid C Somayajulu qlnxr_prepare_pbl_tbl(struct qlnxr_dev *dev,
1233fa790ea9SDavid C Somayajulu struct qlnxr_pbl_info *pbl_info,
1234fa790ea9SDavid C Somayajulu u32 num_pbes,
1235fa790ea9SDavid C Somayajulu int two_layer_capable)
1236fa790ea9SDavid C Somayajulu {
1237fa790ea9SDavid C Somayajulu u32 pbl_capacity;
1238fa790ea9SDavid C Somayajulu u32 pbl_size;
1239fa790ea9SDavid C Somayajulu u32 num_pbls;
1240fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1241fa790ea9SDavid C Somayajulu
1242fa790ea9SDavid C Somayajulu ha = dev->ha;
1243fa790ea9SDavid C Somayajulu
1244fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1245fa790ea9SDavid C Somayajulu
1246fa790ea9SDavid C Somayajulu if ((num_pbes > MAX_PBES_ON_PAGE) && two_layer_capable) {
1247fa790ea9SDavid C Somayajulu if (num_pbes > MAX_PBES_TWO_LAYER) {
1248fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "prepare pbl table: too many pages %d\n",
1249fa790ea9SDavid C Somayajulu num_pbes);
1250fa790ea9SDavid C Somayajulu return -EINVAL;
1251fa790ea9SDavid C Somayajulu }
1252fa790ea9SDavid C Somayajulu
1253fa790ea9SDavid C Somayajulu /* calculate required pbl page size */
1254fa790ea9SDavid C Somayajulu pbl_size = MIN_FW_PBL_PAGE_SIZE;
1255fa790ea9SDavid C Somayajulu pbl_capacity = NUM_PBES_ON_PAGE(pbl_size) *
1256fa790ea9SDavid C Somayajulu NUM_PBES_ON_PAGE(pbl_size);
1257fa790ea9SDavid C Somayajulu
1258fa790ea9SDavid C Somayajulu while (pbl_capacity < num_pbes) {
1259fa790ea9SDavid C Somayajulu pbl_size *= 2;
1260fa790ea9SDavid C Somayajulu pbl_capacity = pbl_size / sizeof(u64);
1261fa790ea9SDavid C Somayajulu pbl_capacity = pbl_capacity * pbl_capacity;
1262fa790ea9SDavid C Somayajulu }
1263fa790ea9SDavid C Somayajulu
1264fa790ea9SDavid C Somayajulu num_pbls = DIV_ROUND_UP(num_pbes, NUM_PBES_ON_PAGE(pbl_size));
1265fa790ea9SDavid C Somayajulu num_pbls++; /* One for the layer0 ( points to the pbls) */
1266fa790ea9SDavid C Somayajulu pbl_info->two_layered = true;
1267fa790ea9SDavid C Somayajulu } else {
1268fa790ea9SDavid C Somayajulu /* One layered PBL */
1269fa790ea9SDavid C Somayajulu num_pbls = 1;
1270fa790ea9SDavid C Somayajulu pbl_size = max_t(u32, MIN_FW_PBL_PAGE_SIZE, \
1271fa790ea9SDavid C Somayajulu roundup_pow_of_two((num_pbes * sizeof(u64))));
1272fa790ea9SDavid C Somayajulu pbl_info->two_layered = false;
1273fa790ea9SDavid C Somayajulu }
1274fa790ea9SDavid C Somayajulu
1275fa790ea9SDavid C Somayajulu pbl_info->num_pbls = num_pbls;
1276fa790ea9SDavid C Somayajulu pbl_info->pbl_size = pbl_size;
1277fa790ea9SDavid C Somayajulu pbl_info->num_pbes = num_pbes;
1278fa790ea9SDavid C Somayajulu
1279fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "prepare pbl table: num_pbes=%d, num_pbls=%d pbl_size=%d\n",
1280fa790ea9SDavid C Somayajulu pbl_info->num_pbes, pbl_info->num_pbls, pbl_info->pbl_size);
1281fa790ea9SDavid C Somayajulu
1282fa790ea9SDavid C Somayajulu return 0;
1283fa790ea9SDavid C Somayajulu }
1284fa790ea9SDavid C Somayajulu
1285fa790ea9SDavid C Somayajulu static void
qlnxr_populate_pbls(struct qlnxr_dev * dev,struct ib_umem * umem,struct qlnxr_pbl * pbl,struct qlnxr_pbl_info * pbl_info)1286fa790ea9SDavid C Somayajulu qlnxr_populate_pbls(struct qlnxr_dev *dev, struct ib_umem *umem,
1287fa790ea9SDavid C Somayajulu struct qlnxr_pbl *pbl, struct qlnxr_pbl_info *pbl_info)
1288fa790ea9SDavid C Somayajulu {
1289fa790ea9SDavid C Somayajulu struct regpair *pbe;
1290fa790ea9SDavid C Somayajulu struct qlnxr_pbl *pbl_tbl;
1291fa790ea9SDavid C Somayajulu struct scatterlist *sg;
1292fa790ea9SDavid C Somayajulu int shift, pg_cnt, pages, pbe_cnt, total_num_pbes = 0;
1293fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1294fa790ea9SDavid C Somayajulu int entry;
1295fa790ea9SDavid C Somayajulu
1296fa790ea9SDavid C Somayajulu ha = dev->ha;
1297fa790ea9SDavid C Somayajulu
1298fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1299fa790ea9SDavid C Somayajulu
1300fa790ea9SDavid C Somayajulu if (!pbl_info) {
1301fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "PBL_INFO not initialized\n");
1302fa790ea9SDavid C Somayajulu return;
1303fa790ea9SDavid C Somayajulu }
1304fa790ea9SDavid C Somayajulu
1305fa790ea9SDavid C Somayajulu if (!pbl_info->num_pbes) {
1306fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "pbl_info->num_pbes == 0\n");
1307fa790ea9SDavid C Somayajulu return;
1308fa790ea9SDavid C Somayajulu }
1309fa790ea9SDavid C Somayajulu
1310fa790ea9SDavid C Somayajulu /* If we have a two layered pbl, the first pbl points to the rest
1311fa790ea9SDavid C Somayajulu * of the pbls and the first entry lays on the second pbl in the table
1312fa790ea9SDavid C Somayajulu */
1313fa790ea9SDavid C Somayajulu if (pbl_info->two_layered)
1314fa790ea9SDavid C Somayajulu pbl_tbl = &pbl[1];
1315fa790ea9SDavid C Somayajulu else
1316fa790ea9SDavid C Somayajulu pbl_tbl = pbl;
1317fa790ea9SDavid C Somayajulu
1318fa790ea9SDavid C Somayajulu pbe = (struct regpair *)pbl_tbl->va;
1319fa790ea9SDavid C Somayajulu if (!pbe) {
1320fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "pbe is NULL\n");
1321fa790ea9SDavid C Somayajulu return;
1322fa790ea9SDavid C Somayajulu }
1323fa790ea9SDavid C Somayajulu
1324fa790ea9SDavid C Somayajulu pbe_cnt = 0;
1325fa790ea9SDavid C Somayajulu
1326fa790ea9SDavid C Somayajulu shift = ilog2(umem->page_size);
1327fa790ea9SDavid C Somayajulu
1328fa790ea9SDavid C Somayajulu for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
1329fa790ea9SDavid C Somayajulu pages = sg_dma_len(sg) >> shift;
1330fa790ea9SDavid C Somayajulu for (pg_cnt = 0; pg_cnt < pages; pg_cnt++) {
1331fa790ea9SDavid C Somayajulu /* store the page address in pbe */
1332fa790ea9SDavid C Somayajulu pbe->lo =
1333fa790ea9SDavid C Somayajulu cpu_to_le32(sg_dma_address(sg) +
1334fa790ea9SDavid C Somayajulu (umem->page_size * pg_cnt));
1335fa790ea9SDavid C Somayajulu pbe->hi =
1336fa790ea9SDavid C Somayajulu cpu_to_le32(upper_32_bits
1337fa790ea9SDavid C Somayajulu ((sg_dma_address(sg) +
1338fa790ea9SDavid C Somayajulu umem->page_size * pg_cnt)));
1339fa790ea9SDavid C Somayajulu
1340fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
1341fa790ea9SDavid C Somayajulu "Populate pbl table:"
1342fa790ea9SDavid C Somayajulu " pbe->addr=0x%x:0x%x "
1343fa790ea9SDavid C Somayajulu " pbe_cnt = %d total_num_pbes=%d"
1344fa790ea9SDavid C Somayajulu " pbe=%p\n", pbe->lo, pbe->hi, pbe_cnt,
1345fa790ea9SDavid C Somayajulu total_num_pbes, pbe);
1346fa790ea9SDavid C Somayajulu
1347fa790ea9SDavid C Somayajulu pbe_cnt ++;
1348fa790ea9SDavid C Somayajulu total_num_pbes ++;
1349fa790ea9SDavid C Somayajulu pbe++;
1350fa790ea9SDavid C Somayajulu
1351fa790ea9SDavid C Somayajulu if (total_num_pbes == pbl_info->num_pbes)
1352fa790ea9SDavid C Somayajulu return;
1353fa790ea9SDavid C Somayajulu
1354fa790ea9SDavid C Somayajulu /* if the given pbl is full storing the pbes,
1355fa790ea9SDavid C Somayajulu * move to next pbl.
1356fa790ea9SDavid C Somayajulu */
1357fa790ea9SDavid C Somayajulu if (pbe_cnt ==
1358fa790ea9SDavid C Somayajulu (pbl_info->pbl_size / sizeof(u64))) {
1359fa790ea9SDavid C Somayajulu pbl_tbl++;
1360fa790ea9SDavid C Somayajulu pbe = (struct regpair *)pbl_tbl->va;
1361fa790ea9SDavid C Somayajulu pbe_cnt = 0;
1362fa790ea9SDavid C Somayajulu }
1363fa790ea9SDavid C Somayajulu }
1364fa790ea9SDavid C Somayajulu }
1365fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
1366fa790ea9SDavid C Somayajulu return;
1367fa790ea9SDavid C Somayajulu }
1368fa790ea9SDavid C Somayajulu
1369fa790ea9SDavid C Somayajulu static void
free_mr_info(struct qlnxr_dev * dev,struct mr_info * info)1370fa790ea9SDavid C Somayajulu free_mr_info(struct qlnxr_dev *dev, struct mr_info *info)
1371fa790ea9SDavid C Somayajulu {
1372fa790ea9SDavid C Somayajulu struct qlnxr_pbl *pbl, *tmp;
1373fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1374fa790ea9SDavid C Somayajulu
1375fa790ea9SDavid C Somayajulu ha = dev->ha;
1376fa790ea9SDavid C Somayajulu
1377fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1378fa790ea9SDavid C Somayajulu
1379fa790ea9SDavid C Somayajulu if (info->pbl_table)
1380fa790ea9SDavid C Somayajulu list_add_tail(&info->pbl_table->list_entry,
1381fa790ea9SDavid C Somayajulu &info->free_pbl_list);
1382fa790ea9SDavid C Somayajulu
1383fa790ea9SDavid C Somayajulu if (!list_empty(&info->inuse_pbl_list))
1384fa790ea9SDavid C Somayajulu list_splice(&info->inuse_pbl_list, &info->free_pbl_list);
1385fa790ea9SDavid C Somayajulu
1386fa790ea9SDavid C Somayajulu list_for_each_entry_safe(pbl, tmp, &info->free_pbl_list, list_entry) {
1387fa790ea9SDavid C Somayajulu list_del(&pbl->list_entry);
1388fa790ea9SDavid C Somayajulu qlnxr_free_pbl(dev, &info->pbl_info, pbl);
1389fa790ea9SDavid C Somayajulu }
1390fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
1391fa790ea9SDavid C Somayajulu
1392fa790ea9SDavid C Somayajulu return;
1393fa790ea9SDavid C Somayajulu }
1394fa790ea9SDavid C Somayajulu
1395fa790ea9SDavid C Somayajulu static int
qlnxr_init_mr_info(struct qlnxr_dev * dev,struct mr_info * info,size_t page_list_len,bool two_layered)1396fa790ea9SDavid C Somayajulu qlnxr_init_mr_info(struct qlnxr_dev *dev, struct mr_info *info,
1397fa790ea9SDavid C Somayajulu size_t page_list_len, bool two_layered)
1398fa790ea9SDavid C Somayajulu {
1399fa790ea9SDavid C Somayajulu int rc;
1400fa790ea9SDavid C Somayajulu struct qlnxr_pbl *tmp;
1401fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1402fa790ea9SDavid C Somayajulu
1403fa790ea9SDavid C Somayajulu ha = dev->ha;
1404fa790ea9SDavid C Somayajulu
1405fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1406fa790ea9SDavid C Somayajulu
1407fa790ea9SDavid C Somayajulu INIT_LIST_HEAD(&info->free_pbl_list);
1408fa790ea9SDavid C Somayajulu INIT_LIST_HEAD(&info->inuse_pbl_list);
1409fa790ea9SDavid C Somayajulu
1410fa790ea9SDavid C Somayajulu rc = qlnxr_prepare_pbl_tbl(dev, &info->pbl_info,
1411fa790ea9SDavid C Somayajulu page_list_len, two_layered);
1412fa790ea9SDavid C Somayajulu if (rc) {
1413fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_prepare_pbl_tbl [%d]\n", rc);
1414fa790ea9SDavid C Somayajulu goto done;
1415fa790ea9SDavid C Somayajulu }
1416fa790ea9SDavid C Somayajulu
1417fa790ea9SDavid C Somayajulu info->pbl_table = qlnxr_alloc_pbl_tbl(dev, &info->pbl_info, GFP_KERNEL);
1418fa790ea9SDavid C Somayajulu
1419fa790ea9SDavid C Somayajulu if (!info->pbl_table) {
1420fa790ea9SDavid C Somayajulu rc = -ENOMEM;
1421fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_alloc_pbl_tbl returned NULL\n");
1422fa790ea9SDavid C Somayajulu goto done;
1423fa790ea9SDavid C Somayajulu }
1424fa790ea9SDavid C Somayajulu
1425fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "pbl_table_pa = %pa\n", &info->pbl_table->pa);
1426fa790ea9SDavid C Somayajulu
1427fa790ea9SDavid C Somayajulu /* in usual case we use 2 PBLs, so we add one to free
1428fa790ea9SDavid C Somayajulu * list and allocating another one
1429fa790ea9SDavid C Somayajulu */
1430fa790ea9SDavid C Somayajulu tmp = qlnxr_alloc_pbl_tbl(dev, &info->pbl_info, GFP_KERNEL);
1431fa790ea9SDavid C Somayajulu
1432fa790ea9SDavid C Somayajulu if (!tmp) {
1433fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "Extra PBL is not allocated\n");
1434fa790ea9SDavid C Somayajulu goto done; /* it's OK if second allocation fails, so rc = 0*/
1435fa790ea9SDavid C Somayajulu }
1436fa790ea9SDavid C Somayajulu
1437fa790ea9SDavid C Somayajulu list_add_tail(&tmp->list_entry, &info->free_pbl_list);
1438fa790ea9SDavid C Somayajulu
1439fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "extra pbl_table_pa = %pa\n", &tmp->pa);
1440fa790ea9SDavid C Somayajulu
1441fa790ea9SDavid C Somayajulu done:
1442fa790ea9SDavid C Somayajulu if (rc)
1443fa790ea9SDavid C Somayajulu free_mr_info(dev, info);
1444fa790ea9SDavid C Somayajulu
1445fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
1446fa790ea9SDavid C Somayajulu
1447fa790ea9SDavid C Somayajulu return rc;
1448fa790ea9SDavid C Somayajulu }
1449fa790ea9SDavid C Somayajulu
1450fa790ea9SDavid C Somayajulu struct ib_mr *
qlnxr_reg_user_mr(struct ib_pd * ibpd,u64 start,u64 len,u64 usr_addr,int acc,struct ib_udata * udata)1451fa790ea9SDavid C Somayajulu qlnxr_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,
1452fa790ea9SDavid C Somayajulu u64 usr_addr, int acc, struct ib_udata *udata)
1453fa790ea9SDavid C Somayajulu {
1454fa790ea9SDavid C Somayajulu int rc = -ENOMEM;
1455fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev((ibpd->device));
1456fa790ea9SDavid C Somayajulu struct qlnxr_mr *mr;
1457fa790ea9SDavid C Somayajulu struct qlnxr_pd *pd;
1458fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1459fa790ea9SDavid C Somayajulu
1460fa790ea9SDavid C Somayajulu ha = dev->ha;
1461fa790ea9SDavid C Somayajulu
1462fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1463fa790ea9SDavid C Somayajulu
1464fa790ea9SDavid C Somayajulu pd = get_qlnxr_pd(ibpd);
1465fa790ea9SDavid C Somayajulu
1466fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qedr_register user mr pd = %d"
1467fa790ea9SDavid C Somayajulu " start = %lld, len = %lld, usr_addr = %lld, acc = %d\n",
1468fa790ea9SDavid C Somayajulu pd->pd_id, start, len, usr_addr, acc);
1469fa790ea9SDavid C Somayajulu
1470fa790ea9SDavid C Somayajulu if (acc & IB_ACCESS_REMOTE_WRITE && !(acc & IB_ACCESS_LOCAL_WRITE)) {
1471fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,
1472fa790ea9SDavid C Somayajulu "(acc & IB_ACCESS_REMOTE_WRITE &&"
1473fa790ea9SDavid C Somayajulu " !(acc & IB_ACCESS_LOCAL_WRITE))\n");
1474fa790ea9SDavid C Somayajulu return ERR_PTR(-EINVAL);
1475fa790ea9SDavid C Somayajulu }
1476fa790ea9SDavid C Somayajulu
1477fa790ea9SDavid C Somayajulu mr = kzalloc(sizeof(*mr), GFP_KERNEL);
1478fa790ea9SDavid C Somayajulu if (!mr) {
1479fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "kzalloc(mr) failed\n");
1480fa790ea9SDavid C Somayajulu return ERR_PTR(rc);
1481fa790ea9SDavid C Somayajulu }
1482fa790ea9SDavid C Somayajulu
1483fa790ea9SDavid C Somayajulu mr->type = QLNXR_MR_USER;
1484fa790ea9SDavid C Somayajulu
1485fa790ea9SDavid C Somayajulu mr->umem = ib_umem_get(ibpd->uobject->context, start, len, acc, 0);
1486fa790ea9SDavid C Somayajulu if (IS_ERR(mr->umem)) {
1487fa790ea9SDavid C Somayajulu rc = -EFAULT;
1488fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ib_umem_get failed [%p]\n", mr->umem);
1489fa790ea9SDavid C Somayajulu goto err0;
1490fa790ea9SDavid C Somayajulu }
1491fa790ea9SDavid C Somayajulu
1492fa790ea9SDavid C Somayajulu rc = qlnxr_init_mr_info(dev, &mr->info, ib_umem_page_count(mr->umem), 1);
1493fa790ea9SDavid C Somayajulu if (rc) {
1494fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,
1495fa790ea9SDavid C Somayajulu "qlnxr_init_mr_info failed [%d]\n", rc);
1496fa790ea9SDavid C Somayajulu goto err1;
1497fa790ea9SDavid C Somayajulu }
1498fa790ea9SDavid C Somayajulu
1499fa790ea9SDavid C Somayajulu qlnxr_populate_pbls(dev, mr->umem, mr->info.pbl_table,
1500fa790ea9SDavid C Somayajulu &mr->info.pbl_info);
1501fa790ea9SDavid C Somayajulu
1502fa790ea9SDavid C Somayajulu rc = ecore_rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid);
1503fa790ea9SDavid C Somayajulu
1504fa790ea9SDavid C Somayajulu if (rc) {
1505fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "roce alloc tid returned an error %d\n", rc);
1506fa790ea9SDavid C Somayajulu goto err1;
1507fa790ea9SDavid C Somayajulu }
1508fa790ea9SDavid C Somayajulu
1509fa790ea9SDavid C Somayajulu /* index only, 18 bit long, lkey = itid << 8 | key */
1510fa790ea9SDavid C Somayajulu mr->hw_mr.tid_type = ECORE_RDMA_TID_REGISTERED_MR;
1511fa790ea9SDavid C Somayajulu mr->hw_mr.key = 0;
1512fa790ea9SDavid C Somayajulu mr->hw_mr.pd = pd->pd_id;
1513fa790ea9SDavid C Somayajulu mr->hw_mr.local_read = 1;
1514fa790ea9SDavid C Somayajulu mr->hw_mr.local_write = (acc & IB_ACCESS_LOCAL_WRITE) ? 1 : 0;
1515fa790ea9SDavid C Somayajulu mr->hw_mr.remote_read = (acc & IB_ACCESS_REMOTE_READ) ? 1 : 0;
1516fa790ea9SDavid C Somayajulu mr->hw_mr.remote_write = (acc & IB_ACCESS_REMOTE_WRITE) ? 1 : 0;
1517fa790ea9SDavid C Somayajulu mr->hw_mr.remote_atomic = (acc & IB_ACCESS_REMOTE_ATOMIC) ? 1 : 0;
1518fa790ea9SDavid C Somayajulu mr->hw_mr.mw_bind = false; /* TBD MW BIND */
1519fa790ea9SDavid C Somayajulu mr->hw_mr.pbl_ptr = mr->info.pbl_table[0].pa;
1520fa790ea9SDavid C Somayajulu mr->hw_mr.pbl_two_level = mr->info.pbl_info.two_layered;
1521fa790ea9SDavid C Somayajulu mr->hw_mr.pbl_page_size_log = ilog2(mr->info.pbl_info.pbl_size);
1522fa790ea9SDavid C Somayajulu mr->hw_mr.page_size_log = ilog2(mr->umem->page_size); /* for the MR pages */
1523fa790ea9SDavid C Somayajulu
1524fa790ea9SDavid C Somayajulu mr->hw_mr.fbo = ib_umem_offset(mr->umem);
1525fa790ea9SDavid C Somayajulu mr->hw_mr.length = len;
1526fa790ea9SDavid C Somayajulu mr->hw_mr.vaddr = usr_addr;
1527fa790ea9SDavid C Somayajulu mr->hw_mr.zbva = false; /* TBD figure when this should be true */
1528fa790ea9SDavid C Somayajulu mr->hw_mr.phy_mr = false; /* Fast MR - True, Regular Register False */
1529fa790ea9SDavid C Somayajulu mr->hw_mr.dma_mr = false;
1530fa790ea9SDavid C Somayajulu
1531fa790ea9SDavid C Somayajulu rc = ecore_rdma_register_tid(dev->rdma_ctx, &mr->hw_mr);
1532fa790ea9SDavid C Somayajulu if (rc) {
1533fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "roce register tid returned an error %d\n", rc);
1534fa790ea9SDavid C Somayajulu goto err2;
1535fa790ea9SDavid C Somayajulu }
1536fa790ea9SDavid C Somayajulu
1537fa790ea9SDavid C Somayajulu mr->ibmr.lkey = mr->hw_mr.itid << 8 | mr->hw_mr.key;
1538fa790ea9SDavid C Somayajulu if (mr->hw_mr.remote_write || mr->hw_mr.remote_read ||
1539fa790ea9SDavid C Somayajulu mr->hw_mr.remote_atomic)
1540fa790ea9SDavid C Somayajulu mr->ibmr.rkey = mr->hw_mr.itid << 8 | mr->hw_mr.key;
1541fa790ea9SDavid C Somayajulu
1542fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "register user mr lkey: %x\n", mr->ibmr.lkey);
1543fa790ea9SDavid C Somayajulu
1544fa790ea9SDavid C Somayajulu return (&mr->ibmr);
1545fa790ea9SDavid C Somayajulu
1546fa790ea9SDavid C Somayajulu err2:
1547fa790ea9SDavid C Somayajulu ecore_rdma_free_tid(dev->rdma_ctx, mr->hw_mr.itid);
1548fa790ea9SDavid C Somayajulu err1:
1549fa790ea9SDavid C Somayajulu qlnxr_free_pbl(dev, &mr->info.pbl_info, mr->info.pbl_table);
1550fa790ea9SDavid C Somayajulu err0:
1551fa790ea9SDavid C Somayajulu kfree(mr);
1552fa790ea9SDavid C Somayajulu
1553fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
1554fa790ea9SDavid C Somayajulu return (ERR_PTR(rc));
1555fa790ea9SDavid C Somayajulu }
1556fa790ea9SDavid C Somayajulu
1557fa790ea9SDavid C Somayajulu int
qlnxr_dereg_mr(struct ib_mr * ib_mr,struct ib_udata * udata)1558b633e08cSHans Petter Selasky qlnxr_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
1559fa790ea9SDavid C Somayajulu {
1560fa790ea9SDavid C Somayajulu struct qlnxr_mr *mr = get_qlnxr_mr(ib_mr);
1561fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev((ib_mr->device));
1562fa790ea9SDavid C Somayajulu int rc = 0;
1563fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1564fa790ea9SDavid C Somayajulu
1565fa790ea9SDavid C Somayajulu ha = dev->ha;
1566fa790ea9SDavid C Somayajulu
1567fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1568fa790ea9SDavid C Somayajulu
1569fa790ea9SDavid C Somayajulu if ((mr->type != QLNXR_MR_DMA) && (mr->type != QLNXR_MR_FRMR))
1570fa790ea9SDavid C Somayajulu qlnxr_free_pbl(dev, &mr->info.pbl_info, mr->info.pbl_table);
1571fa790ea9SDavid C Somayajulu
1572fa790ea9SDavid C Somayajulu /* it could be user registered memory. */
1573fa790ea9SDavid C Somayajulu if (mr->umem)
1574fa790ea9SDavid C Somayajulu ib_umem_release(mr->umem);
1575fa790ea9SDavid C Somayajulu
1576fa790ea9SDavid C Somayajulu kfree(mr->pages);
1577fa790ea9SDavid C Somayajulu
1578fa790ea9SDavid C Somayajulu kfree(mr);
1579fa790ea9SDavid C Somayajulu
1580fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
1581fa790ea9SDavid C Somayajulu return rc;
1582fa790ea9SDavid C Somayajulu }
1583fa790ea9SDavid C Somayajulu
1584fa790ea9SDavid C Somayajulu static int
qlnxr_copy_cq_uresp(struct qlnxr_dev * dev,struct qlnxr_cq * cq,struct ib_udata * udata)1585fa790ea9SDavid C Somayajulu qlnxr_copy_cq_uresp(struct qlnxr_dev *dev,
1586fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq, struct ib_udata *udata)
1587fa790ea9SDavid C Somayajulu {
1588fa790ea9SDavid C Somayajulu struct qlnxr_create_cq_uresp uresp;
1589fa790ea9SDavid C Somayajulu int rc;
1590fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1591fa790ea9SDavid C Somayajulu
1592fa790ea9SDavid C Somayajulu ha = dev->ha;
1593fa790ea9SDavid C Somayajulu
1594fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1595fa790ea9SDavid C Somayajulu
1596fa790ea9SDavid C Somayajulu memset(&uresp, 0, sizeof(uresp));
1597fa790ea9SDavid C Somayajulu
1598fa790ea9SDavid C Somayajulu uresp.db_offset = DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT);
1599fa790ea9SDavid C Somayajulu uresp.icid = cq->icid;
1600fa790ea9SDavid C Somayajulu
1601fa790ea9SDavid C Somayajulu rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
1602fa790ea9SDavid C Somayajulu
1603fa790ea9SDavid C Somayajulu if (rc) {
1604fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ib_copy_to_udata error cqid=0x%x[%d]\n",
1605fa790ea9SDavid C Somayajulu cq->icid, rc);
1606fa790ea9SDavid C Somayajulu }
1607fa790ea9SDavid C Somayajulu
1608fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
1609fa790ea9SDavid C Somayajulu return rc;
1610fa790ea9SDavid C Somayajulu }
1611fa790ea9SDavid C Somayajulu
1612fa790ea9SDavid C Somayajulu static void
consume_cqe(struct qlnxr_cq * cq)1613fa790ea9SDavid C Somayajulu consume_cqe(struct qlnxr_cq *cq)
1614fa790ea9SDavid C Somayajulu {
1615fa790ea9SDavid C Somayajulu
1616fa790ea9SDavid C Somayajulu if (cq->latest_cqe == cq->toggle_cqe)
1617fa790ea9SDavid C Somayajulu cq->pbl_toggle ^= RDMA_RESIZE_CQ_RAMROD_DATA_TOGGLE_BIT_MASK;
1618fa790ea9SDavid C Somayajulu
1619fa790ea9SDavid C Somayajulu cq->latest_cqe = ecore_chain_consume(&cq->pbl);
1620fa790ea9SDavid C Somayajulu }
1621fa790ea9SDavid C Somayajulu
1622fa790ea9SDavid C Somayajulu static inline int
qlnxr_align_cq_entries(int entries)1623fa790ea9SDavid C Somayajulu qlnxr_align_cq_entries(int entries)
1624fa790ea9SDavid C Somayajulu {
1625fa790ea9SDavid C Somayajulu u64 size, aligned_size;
1626fa790ea9SDavid C Somayajulu
1627fa790ea9SDavid C Somayajulu /* We allocate an extra entry that we don't report to the FW.
1628fa790ea9SDavid C Somayajulu * Why?
1629fa790ea9SDavid C Somayajulu * The CQE size is 32 bytes but the FW writes in chunks of 64 bytes
1630fa790ea9SDavid C Somayajulu * (for performance purposes). Allocating an extra entry and telling
1631fa790ea9SDavid C Somayajulu * the FW we have less prevents overwriting the first entry in case of
1632fa790ea9SDavid C Somayajulu * a wrap i.e. when the FW writes the last entry and the application
1633fa790ea9SDavid C Somayajulu * hasn't read the first one.
1634fa790ea9SDavid C Somayajulu */
1635fa790ea9SDavid C Somayajulu size = (entries + 1) * QLNXR_CQE_SIZE;
1636fa790ea9SDavid C Somayajulu
1637fa790ea9SDavid C Somayajulu /* We align to PAGE_SIZE.
1638fa790ea9SDavid C Somayajulu * Why?
1639fa790ea9SDavid C Somayajulu * Since the CQ is going to be mapped and the mapping is anyhow in whole
1640fa790ea9SDavid C Somayajulu * kernel pages we benefit from the possibly extra CQEs.
1641fa790ea9SDavid C Somayajulu */
1642fa790ea9SDavid C Somayajulu aligned_size = ALIGN(size, PAGE_SIZE);
1643fa790ea9SDavid C Somayajulu
1644fa790ea9SDavid C Somayajulu /* note: for CQs created in user space the result of this function
1645fa790ea9SDavid C Somayajulu * should match the size mapped in user space
1646fa790ea9SDavid C Somayajulu */
1647fa790ea9SDavid C Somayajulu return (aligned_size / QLNXR_CQE_SIZE);
1648fa790ea9SDavid C Somayajulu }
1649fa790ea9SDavid C Somayajulu
1650fa790ea9SDavid C Somayajulu static inline int
qlnxr_init_user_queue(struct ib_ucontext * ib_ctx,struct qlnxr_dev * dev,struct qlnxr_userq * q,u64 buf_addr,size_t buf_len,int access,int dmasync,int alloc_and_init)1651fa790ea9SDavid C Somayajulu qlnxr_init_user_queue(struct ib_ucontext *ib_ctx, struct qlnxr_dev *dev,
1652fa790ea9SDavid C Somayajulu struct qlnxr_userq *q, u64 buf_addr, size_t buf_len,
1653fa790ea9SDavid C Somayajulu int access, int dmasync, int alloc_and_init)
1654fa790ea9SDavid C Somayajulu {
1655fa790ea9SDavid C Somayajulu int page_cnt;
1656fa790ea9SDavid C Somayajulu int rc;
1657fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1658fa790ea9SDavid C Somayajulu
1659fa790ea9SDavid C Somayajulu ha = dev->ha;
1660fa790ea9SDavid C Somayajulu
1661fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1662fa790ea9SDavid C Somayajulu
1663fa790ea9SDavid C Somayajulu q->buf_addr = buf_addr;
1664fa790ea9SDavid C Somayajulu q->buf_len = buf_len;
1665fa790ea9SDavid C Somayajulu
1666fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "buf_addr : %llx, buf_len : %x, access : %x"
1667fa790ea9SDavid C Somayajulu " dmasync : %x\n", q->buf_addr, q->buf_len,
1668fa790ea9SDavid C Somayajulu access, dmasync);
1669fa790ea9SDavid C Somayajulu
1670fa790ea9SDavid C Somayajulu q->umem = ib_umem_get(ib_ctx, q->buf_addr, q->buf_len, access, dmasync);
1671fa790ea9SDavid C Somayajulu
1672fa790ea9SDavid C Somayajulu if (IS_ERR(q->umem)) {
1673fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ib_umem_get failed [%lx]\n", PTR_ERR(q->umem));
1674fa790ea9SDavid C Somayajulu return PTR_ERR(q->umem);
1675fa790ea9SDavid C Somayajulu }
1676fa790ea9SDavid C Somayajulu
1677fa790ea9SDavid C Somayajulu page_cnt = ib_umem_page_count(q->umem);
1678fa790ea9SDavid C Somayajulu rc = qlnxr_prepare_pbl_tbl(dev, &q->pbl_info, page_cnt,
1679fa790ea9SDavid C Somayajulu 0 /* SQ and RQ don't support dual layer pbl.
1680fa790ea9SDavid C Somayajulu * CQ may, but this is yet uncoded.
1681fa790ea9SDavid C Somayajulu */);
1682fa790ea9SDavid C Somayajulu if (rc) {
1683fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_prepare_pbl_tbl failed [%d]\n", rc);
1684fa790ea9SDavid C Somayajulu goto err;
1685fa790ea9SDavid C Somayajulu }
1686fa790ea9SDavid C Somayajulu
1687fa790ea9SDavid C Somayajulu if (alloc_and_init) {
1688fa790ea9SDavid C Somayajulu q->pbl_tbl = qlnxr_alloc_pbl_tbl(dev, &q->pbl_info, GFP_KERNEL);
1689fa790ea9SDavid C Somayajulu
1690fa790ea9SDavid C Somayajulu if (!q->pbl_tbl) {
1691fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_alloc_pbl_tbl failed\n");
1692fa790ea9SDavid C Somayajulu rc = -ENOMEM;
1693fa790ea9SDavid C Somayajulu goto err;
1694fa790ea9SDavid C Somayajulu }
1695fa790ea9SDavid C Somayajulu
1696fa790ea9SDavid C Somayajulu qlnxr_populate_pbls(dev, q->umem, q->pbl_tbl, &q->pbl_info);
1697fa790ea9SDavid C Somayajulu } else {
1698fa790ea9SDavid C Somayajulu q->pbl_tbl = kzalloc(sizeof(*q->pbl_tbl), GFP_KERNEL);
1699fa790ea9SDavid C Somayajulu
1700fa790ea9SDavid C Somayajulu if (!q->pbl_tbl) {
1701fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_alloc_pbl_tbl failed\n");
1702fa790ea9SDavid C Somayajulu rc = -ENOMEM;
1703fa790ea9SDavid C Somayajulu goto err;
1704fa790ea9SDavid C Somayajulu }
1705fa790ea9SDavid C Somayajulu }
1706fa790ea9SDavid C Somayajulu
1707fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
1708fa790ea9SDavid C Somayajulu return 0;
1709fa790ea9SDavid C Somayajulu
1710fa790ea9SDavid C Somayajulu err:
1711fa790ea9SDavid C Somayajulu ib_umem_release(q->umem);
1712fa790ea9SDavid C Somayajulu q->umem = NULL;
1713fa790ea9SDavid C Somayajulu
1714fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
1715fa790ea9SDavid C Somayajulu return rc;
1716fa790ea9SDavid C Somayajulu }
1717fa790ea9SDavid C Somayajulu
1718b633e08cSHans Petter Selasky int
qlnxr_create_cq(struct ib_cq * ibcq,const struct ib_cq_init_attr * attr,struct ib_udata * udata)1719b633e08cSHans Petter Selasky qlnxr_create_cq(struct ib_cq *ibcq,
1720fa790ea9SDavid C Somayajulu const struct ib_cq_init_attr *attr,
1721fa790ea9SDavid C Somayajulu struct ib_udata *udata)
1722fa790ea9SDavid C Somayajulu {
1723fa790ea9SDavid C Somayajulu struct qlnxr_ucontext *ctx;
1724fa790ea9SDavid C Somayajulu struct ecore_rdma_destroy_cq_out_params destroy_oparams;
1725fa790ea9SDavid C Somayajulu struct ecore_rdma_destroy_cq_in_params destroy_iparams;
1726fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
1727fa790ea9SDavid C Somayajulu struct ecore_rdma_create_cq_in_params params;
1728fa790ea9SDavid C Somayajulu struct qlnxr_create_cq_ureq ureq;
1729fa790ea9SDavid C Somayajulu
1730fa790ea9SDavid C Somayajulu int vector = attr->comp_vector;
1731fa790ea9SDavid C Somayajulu int entries = attr->cqe;
1732b633e08cSHans Petter Selasky struct qlnxr_cq *cq = get_qlnxr_cq(ibcq);
1733fa790ea9SDavid C Somayajulu int chain_entries, rc, page_cnt;
1734fa790ea9SDavid C Somayajulu u64 pbl_ptr;
1735fa790ea9SDavid C Somayajulu u16 icid;
1736fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1737fa790ea9SDavid C Somayajulu
1738b633e08cSHans Petter Selasky dev = get_qlnxr_dev(ibcq->device);
1739fa790ea9SDavid C Somayajulu ha = dev->ha;
1740fa790ea9SDavid C Somayajulu
1741fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "called from %s. entries = %d, "
1742fa790ea9SDavid C Somayajulu "vector = %d\n",
1743fa790ea9SDavid C Somayajulu (udata ? "User Lib" : "Kernel"), entries, vector);
1744fa790ea9SDavid C Somayajulu
1745fa790ea9SDavid C Somayajulu memset(¶ms, 0, sizeof(struct ecore_rdma_create_cq_in_params));
1746fa790ea9SDavid C Somayajulu memset(&destroy_iparams, 0, sizeof(struct ecore_rdma_destroy_cq_in_params));
1747fa790ea9SDavid C Somayajulu memset(&destroy_oparams, 0, sizeof(struct ecore_rdma_destroy_cq_out_params));
1748fa790ea9SDavid C Somayajulu
1749fa790ea9SDavid C Somayajulu if (entries > QLNXR_MAX_CQES) {
1750fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,
1751fa790ea9SDavid C Somayajulu "the number of entries %d is too high. "
1752fa790ea9SDavid C Somayajulu "Must be equal or below %d.\n",
1753fa790ea9SDavid C Somayajulu entries, QLNXR_MAX_CQES);
1754b633e08cSHans Petter Selasky return -EINVAL;
1755fa790ea9SDavid C Somayajulu }
1756fa790ea9SDavid C Somayajulu chain_entries = qlnxr_align_cq_entries(entries);
1757fa790ea9SDavid C Somayajulu chain_entries = min_t(int, chain_entries, QLNXR_MAX_CQES);
1758fa790ea9SDavid C Somayajulu
1759fa790ea9SDavid C Somayajulu if (udata) {
1760b633e08cSHans Petter Selasky ctx = rdma_udata_to_drv_context(
1761b633e08cSHans Petter Selasky udata, struct qlnxr_ucontext, ibucontext);
1762b633e08cSHans Petter Selasky
1763fa790ea9SDavid C Somayajulu memset(&ureq, 0, sizeof(ureq));
1764fa790ea9SDavid C Somayajulu
1765fa790ea9SDavid C Somayajulu if (ib_copy_from_udata(&ureq, udata,
1766fa790ea9SDavid C Somayajulu min(sizeof(ureq), udata->inlen))) {
1767fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ib_copy_from_udata failed\n");
1768fa790ea9SDavid C Somayajulu goto err0;
1769fa790ea9SDavid C Somayajulu }
1770fa790ea9SDavid C Somayajulu
1771fa790ea9SDavid C Somayajulu if (!ureq.len) {
1772fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ureq.len == 0\n");
1773fa790ea9SDavid C Somayajulu goto err0;
1774fa790ea9SDavid C Somayajulu }
1775fa790ea9SDavid C Somayajulu
1776fa790ea9SDavid C Somayajulu cq->cq_type = QLNXR_CQ_TYPE_USER;
1777fa790ea9SDavid C Somayajulu
1778b633e08cSHans Petter Selasky qlnxr_init_user_queue(&ctx->ibucontext, dev, &cq->q, ureq.addr, ureq.len,
1779fa790ea9SDavid C Somayajulu IB_ACCESS_LOCAL_WRITE, 1, 1);
1780fa790ea9SDavid C Somayajulu
1781fa790ea9SDavid C Somayajulu pbl_ptr = cq->q.pbl_tbl->pa;
1782fa790ea9SDavid C Somayajulu page_cnt = cq->q.pbl_info.num_pbes;
1783fa790ea9SDavid C Somayajulu cq->ibcq.cqe = chain_entries;
1784fa790ea9SDavid C Somayajulu } else {
1785b633e08cSHans Petter Selasky ctx = NULL;
1786b633e08cSHans Petter Selasky
1787fa790ea9SDavid C Somayajulu cq->cq_type = QLNXR_CQ_TYPE_KERNEL;
1788fa790ea9SDavid C Somayajulu
1789fa790ea9SDavid C Somayajulu rc = ecore_chain_alloc(&dev->ha->cdev,
1790fa790ea9SDavid C Somayajulu ECORE_CHAIN_USE_TO_CONSUME,
1791fa790ea9SDavid C Somayajulu ECORE_CHAIN_MODE_PBL,
1792fa790ea9SDavid C Somayajulu ECORE_CHAIN_CNT_TYPE_U32,
1793fa790ea9SDavid C Somayajulu chain_entries,
1794fa790ea9SDavid C Somayajulu sizeof(union roce_cqe),
1795fa790ea9SDavid C Somayajulu &cq->pbl, NULL);
1796fa790ea9SDavid C Somayajulu
1797fa790ea9SDavid C Somayajulu if (rc)
1798fa790ea9SDavid C Somayajulu goto err1;
1799fa790ea9SDavid C Somayajulu
1800fa790ea9SDavid C Somayajulu page_cnt = ecore_chain_get_page_cnt(&cq->pbl);
1801fa790ea9SDavid C Somayajulu pbl_ptr = ecore_chain_get_pbl_phys(&cq->pbl);
1802fa790ea9SDavid C Somayajulu cq->ibcq.cqe = cq->pbl.capacity;
1803fa790ea9SDavid C Somayajulu }
1804fa790ea9SDavid C Somayajulu
1805fa790ea9SDavid C Somayajulu params.cq_handle_hi = upper_32_bits((uintptr_t)cq);
1806fa790ea9SDavid C Somayajulu params.cq_handle_lo = lower_32_bits((uintptr_t)cq);
1807fa790ea9SDavid C Somayajulu params.cnq_id = vector;
1808fa790ea9SDavid C Somayajulu params.cq_size = chain_entries - 1;
1809fa790ea9SDavid C Somayajulu params.pbl_num_pages = page_cnt;
1810fa790ea9SDavid C Somayajulu params.pbl_ptr = pbl_ptr;
1811fa790ea9SDavid C Somayajulu params.pbl_two_level = 0;
1812fa790ea9SDavid C Somayajulu
1813b633e08cSHans Petter Selasky if (udata) {
1814fa790ea9SDavid C Somayajulu params.dpi = ctx->dpi;
1815fa790ea9SDavid C Somayajulu } else {
1816fa790ea9SDavid C Somayajulu params.dpi = dev->dpi;
1817fa790ea9SDavid C Somayajulu }
1818fa790ea9SDavid C Somayajulu
1819fa790ea9SDavid C Somayajulu rc = ecore_rdma_create_cq(dev->rdma_ctx, ¶ms, &icid);
1820fa790ea9SDavid C Somayajulu if (rc)
1821fa790ea9SDavid C Somayajulu goto err2;
1822fa790ea9SDavid C Somayajulu
1823fa790ea9SDavid C Somayajulu cq->icid = icid;
1824fa790ea9SDavid C Somayajulu cq->sig = QLNXR_CQ_MAGIC_NUMBER;
1825fa790ea9SDavid C Somayajulu spin_lock_init(&cq->cq_lock);
1826fa790ea9SDavid C Somayajulu
1827b633e08cSHans Petter Selasky if (udata) {
1828fa790ea9SDavid C Somayajulu rc = qlnxr_copy_cq_uresp(dev, cq, udata);
1829fa790ea9SDavid C Somayajulu if (rc)
1830fa790ea9SDavid C Somayajulu goto err3;
1831fa790ea9SDavid C Somayajulu } else {
1832fa790ea9SDavid C Somayajulu /* Generate doorbell address.
1833fa790ea9SDavid C Somayajulu * Configure bits 3-9 with DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT.
1834fa790ea9SDavid C Somayajulu * TODO: consider moving to device scope as it is a function of
1835fa790ea9SDavid C Somayajulu * the device.
1836fa790ea9SDavid C Somayajulu * TODO: add ifdef if plan to support 16 bit.
1837fa790ea9SDavid C Somayajulu */
1838fa790ea9SDavid C Somayajulu cq->db_addr = dev->db_addr +
1839fa790ea9SDavid C Somayajulu DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT);
1840fa790ea9SDavid C Somayajulu cq->db.data.icid = cq->icid;
1841fa790ea9SDavid C Somayajulu cq->db.data.params = DB_AGG_CMD_SET <<
1842fa790ea9SDavid C Somayajulu RDMA_PWM_VAL32_DATA_AGG_CMD_SHIFT;
1843fa790ea9SDavid C Somayajulu
1844fa790ea9SDavid C Somayajulu /* point to the very last element, passing it we will toggle */
1845fa790ea9SDavid C Somayajulu cq->toggle_cqe = ecore_chain_get_last_elem(&cq->pbl);
1846fa790ea9SDavid C Somayajulu cq->pbl_toggle = RDMA_RESIZE_CQ_RAMROD_DATA_TOGGLE_BIT_MASK;
1847fa790ea9SDavid C Somayajulu
1848fa790ea9SDavid C Somayajulu /* must be different from pbl_toggle */
1849fa790ea9SDavid C Somayajulu cq->latest_cqe = NULL;
1850fa790ea9SDavid C Somayajulu consume_cqe(cq);
1851fa790ea9SDavid C Somayajulu cq->cq_cons = ecore_chain_get_cons_idx_u32(&cq->pbl);
1852fa790ea9SDavid C Somayajulu }
1853fa790ea9SDavid C Somayajulu
1854fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit icid = 0x%0x, addr = %p,"
1855fa790ea9SDavid C Somayajulu " number of entries = 0x%x\n",
1856fa790ea9SDavid C Somayajulu cq->icid, cq, params.cq_size);
1857fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,"cq_addr = %p\n", cq);
1858b633e08cSHans Petter Selasky return (0);
1859fa790ea9SDavid C Somayajulu
1860fa790ea9SDavid C Somayajulu err3:
1861fa790ea9SDavid C Somayajulu destroy_iparams.icid = cq->icid;
1862fa790ea9SDavid C Somayajulu ecore_rdma_destroy_cq(dev->rdma_ctx, &destroy_iparams, &destroy_oparams);
1863fa790ea9SDavid C Somayajulu err2:
1864fa790ea9SDavid C Somayajulu if (udata)
1865fa790ea9SDavid C Somayajulu qlnxr_free_pbl(dev, &cq->q.pbl_info, cq->q.pbl_tbl);
1866fa790ea9SDavid C Somayajulu else
1867fa790ea9SDavid C Somayajulu ecore_chain_free(&dev->ha->cdev, &cq->pbl);
1868fa790ea9SDavid C Somayajulu err1:
1869fa790ea9SDavid C Somayajulu if (udata)
1870fa790ea9SDavid C Somayajulu ib_umem_release(cq->q.umem);
1871fa790ea9SDavid C Somayajulu err0:
1872fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit error\n");
1873fa790ea9SDavid C Somayajulu
1874b633e08cSHans Petter Selasky return (-EINVAL);
1875fa790ea9SDavid C Somayajulu }
1876fa790ea9SDavid C Somayajulu
qlnxr_resize_cq(struct ib_cq * ibcq,int new_cnt,struct ib_udata * udata)1877fa790ea9SDavid C Somayajulu int qlnxr_resize_cq(struct ib_cq *ibcq, int new_cnt, struct ib_udata *udata)
1878fa790ea9SDavid C Somayajulu {
1879fa790ea9SDavid C Somayajulu int status = 0;
1880fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev((ibcq->device));
1881fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1882fa790ea9SDavid C Somayajulu
1883fa790ea9SDavid C Somayajulu ha = dev->ha;
1884fa790ea9SDavid C Somayajulu
1885fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter/exit\n");
1886fa790ea9SDavid C Somayajulu
1887fa790ea9SDavid C Somayajulu return status;
1888fa790ea9SDavid C Somayajulu }
1889fa790ea9SDavid C Somayajulu
1890b633e08cSHans Petter Selasky void
qlnxr_destroy_cq(struct ib_cq * ibcq,struct ib_udata * udata)1891b633e08cSHans Petter Selasky qlnxr_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
1892fa790ea9SDavid C Somayajulu {
1893fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev((ibcq->device));
1894fa790ea9SDavid C Somayajulu struct ecore_rdma_destroy_cq_out_params oparams;
1895fa790ea9SDavid C Somayajulu struct ecore_rdma_destroy_cq_in_params iparams;
1896fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq = get_qlnxr_cq(ibcq);
1897fa790ea9SDavid C Somayajulu int rc = 0;
1898fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1899fa790ea9SDavid C Somayajulu
1900fa790ea9SDavid C Somayajulu ha = dev->ha;
1901fa790ea9SDavid C Somayajulu
1902fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter cq_id = %d\n", cq->icid);
1903fa790ea9SDavid C Somayajulu
1904fa790ea9SDavid C Somayajulu cq->destroyed = 1;
1905fa790ea9SDavid C Somayajulu
1906fa790ea9SDavid C Somayajulu /* TODO: Syncronize irq of the CNQ the CQ belongs to for validation
1907fa790ea9SDavid C Somayajulu * that all completions with notification are dealt with. The rest
1908fa790ea9SDavid C Somayajulu * of the completions are not interesting
1909fa790ea9SDavid C Somayajulu */
1910fa790ea9SDavid C Somayajulu
1911fa790ea9SDavid C Somayajulu /* GSIs CQs are handled by driver, so they don't exist in the FW */
1912fa790ea9SDavid C Somayajulu
1913fa790ea9SDavid C Somayajulu if (cq->cq_type != QLNXR_CQ_TYPE_GSI) {
1914fa790ea9SDavid C Somayajulu iparams.icid = cq->icid;
1915fa790ea9SDavid C Somayajulu
1916fa790ea9SDavid C Somayajulu rc = ecore_rdma_destroy_cq(dev->rdma_ctx, &iparams, &oparams);
1917fa790ea9SDavid C Somayajulu
1918fa790ea9SDavid C Somayajulu if (rc) {
1919fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ecore_rdma_destroy_cq failed cq_id = %d\n",
1920fa790ea9SDavid C Somayajulu cq->icid);
1921b633e08cSHans Petter Selasky return;
1922fa790ea9SDavid C Somayajulu }
1923fa790ea9SDavid C Somayajulu
1924fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "free cq->pbl cq_id = %d\n", cq->icid);
1925fa790ea9SDavid C Somayajulu ecore_chain_free(&dev->ha->cdev, &cq->pbl);
1926fa790ea9SDavid C Somayajulu }
1927fa790ea9SDavid C Somayajulu
1928b633e08cSHans Petter Selasky if (udata) {
1929fa790ea9SDavid C Somayajulu qlnxr_free_pbl(dev, &cq->q.pbl_info, cq->q.pbl_tbl);
1930fa790ea9SDavid C Somayajulu ib_umem_release(cq->q.umem);
1931fa790ea9SDavid C Somayajulu }
1932fa790ea9SDavid C Somayajulu
1933fa790ea9SDavid C Somayajulu cq->sig = ~cq->sig;
1934fa790ea9SDavid C Somayajulu
1935fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit cq_id = %d\n", cq->icid);
1936fa790ea9SDavid C Somayajulu }
1937fa790ea9SDavid C Somayajulu
1938fa790ea9SDavid C Somayajulu static int
qlnxr_check_qp_attrs(struct ib_pd * ibpd,struct qlnxr_dev * dev,struct ib_qp_init_attr * attrs,struct ib_udata * udata)1939fa790ea9SDavid C Somayajulu qlnxr_check_qp_attrs(struct ib_pd *ibpd,
1940fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev,
1941fa790ea9SDavid C Somayajulu struct ib_qp_init_attr *attrs,
1942fa790ea9SDavid C Somayajulu struct ib_udata *udata)
1943fa790ea9SDavid C Somayajulu {
1944fa790ea9SDavid C Somayajulu struct ecore_rdma_device *qattr;
1945fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
1946fa790ea9SDavid C Somayajulu
1947fa790ea9SDavid C Somayajulu qattr = ecore_rdma_query_device(dev->rdma_ctx);
1948fa790ea9SDavid C Somayajulu ha = dev->ha;
1949fa790ea9SDavid C Somayajulu
1950fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
1951fa790ea9SDavid C Somayajulu
1952fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "attrs->sq_sig_type = %d\n", attrs->sq_sig_type);
1953fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "attrs->qp_type = %d\n", attrs->qp_type);
1954fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "attrs->create_flags = %d\n", attrs->create_flags);
1955fa790ea9SDavid C Somayajulu
1956fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "attrs->port_num = %d\n", attrs->port_num);
1957fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "attrs->cap.max_send_wr = 0x%x\n", attrs->cap.max_send_wr);
1958fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "attrs->cap.max_recv_wr = 0x%x\n", attrs->cap.max_recv_wr);
1959fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "attrs->cap.max_send_sge = 0x%x\n", attrs->cap.max_send_sge);
1960fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "attrs->cap.max_recv_sge = 0x%x\n", attrs->cap.max_recv_sge);
1961fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "attrs->cap.max_inline_data = 0x%x\n",
1962fa790ea9SDavid C Somayajulu attrs->cap.max_inline_data);
1963fa790ea9SDavid C Somayajulu
1964fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "\n\nqattr->vendor_id = 0x%x\n", qattr->vendor_id);
1965fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->vendor_part_id = 0x%x\n", qattr->vendor_part_id);
1966fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->hw_ver = 0x%x\n", qattr->hw_ver);
1967fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->fw_ver = %p\n", (void *)qattr->fw_ver);
1968fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->node_guid = %p\n", (void *)qattr->node_guid);
1969fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->sys_image_guid = %p\n",
1970fa790ea9SDavid C Somayajulu (void *)qattr->sys_image_guid);
1971fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_cnq = 0x%x\n", qattr->max_cnq);
1972fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_sge = 0x%x\n", qattr->max_sge);
1973fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_srq_sge = 0x%x\n", qattr->max_srq_sge);
1974fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_inline = 0x%x\n", qattr->max_inline);
1975fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_wqe = 0x%x\n", qattr->max_wqe);
1976fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_srq_wqe = 0x%x\n", qattr->max_srq_wqe);
1977fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_qp_resp_rd_atomic_resc = 0x%x\n",
1978fa790ea9SDavid C Somayajulu qattr->max_qp_resp_rd_atomic_resc);
1979fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_qp_req_rd_atomic_resc = 0x%x\n",
1980fa790ea9SDavid C Somayajulu qattr->max_qp_req_rd_atomic_resc);
1981fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_dev_resp_rd_atomic_resc = 0x%x\n",
1982fa790ea9SDavid C Somayajulu qattr->max_dev_resp_rd_atomic_resc);
1983fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_cq = 0x%x\n", qattr->max_cq);
1984fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_qp = 0x%x\n", qattr->max_qp);
1985fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_srq = 0x%x\n", qattr->max_srq);
1986fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_mr = 0x%x\n", qattr->max_mr);
1987fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_mr_size = %p\n", (void *)qattr->max_mr_size);
1988fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_cqe = 0x%x\n", qattr->max_cqe);
1989fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_mw = 0x%x\n", qattr->max_mw);
1990fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_fmr = 0x%x\n", qattr->max_fmr);
1991fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_mr_mw_fmr_pbl = 0x%x\n",
1992fa790ea9SDavid C Somayajulu qattr->max_mr_mw_fmr_pbl);
1993fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_mr_mw_fmr_size = %p\n",
1994fa790ea9SDavid C Somayajulu (void *)qattr->max_mr_mw_fmr_size);
1995fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_pd = 0x%x\n", qattr->max_pd);
1996fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_ah = 0x%x\n", qattr->max_ah);
1997fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_pkey = 0x%x\n", qattr->max_pkey);
1998fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_srq_wr = 0x%x\n", qattr->max_srq_wr);
1999fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->max_stats_queues = 0x%x\n",
2000fa790ea9SDavid C Somayajulu qattr->max_stats_queues);
2001fa790ea9SDavid C Somayajulu //QL_DPRINT12(ha, "qattr->dev_caps = 0x%x\n", qattr->dev_caps);
2002fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->page_size_caps = %p\n",
2003fa790ea9SDavid C Somayajulu (void *)qattr->page_size_caps);
2004fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->dev_ack_delay = 0x%x\n", qattr->dev_ack_delay);
2005fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->reserved_lkey = 0x%x\n", qattr->reserved_lkey);
2006fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qattr->bad_pkey_counter = 0x%x\n",
2007fa790ea9SDavid C Somayajulu qattr->bad_pkey_counter);
2008fa790ea9SDavid C Somayajulu
2009fa790ea9SDavid C Somayajulu if ((attrs->qp_type == IB_QPT_GSI) && udata) {
2010fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "unexpected udata when creating GSI QP\n");
2011fa790ea9SDavid C Somayajulu return -EINVAL;
2012fa790ea9SDavid C Somayajulu }
2013fa790ea9SDavid C Somayajulu
2014fa790ea9SDavid C Somayajulu if (udata && !(ibpd->uobject && ibpd->uobject->context)) {
2015fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "called from user without context\n");
2016fa790ea9SDavid C Somayajulu return -EINVAL;
2017fa790ea9SDavid C Somayajulu }
2018fa790ea9SDavid C Somayajulu
2019fa790ea9SDavid C Somayajulu /* QP0... attrs->qp_type == IB_QPT_GSI */
2020fa790ea9SDavid C Somayajulu if (attrs->qp_type != IB_QPT_RC && attrs->qp_type != IB_QPT_GSI) {
2021fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "unsupported qp type=0x%x requested\n",
2022fa790ea9SDavid C Somayajulu attrs->qp_type);
2023fa790ea9SDavid C Somayajulu return -EINVAL;
2024fa790ea9SDavid C Somayajulu }
2025fa790ea9SDavid C Somayajulu if (attrs->qp_type == IB_QPT_GSI && attrs->srq) {
2026fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "cannot create GSI qp with SRQ\n");
2027fa790ea9SDavid C Somayajulu return -EINVAL;
2028fa790ea9SDavid C Somayajulu }
2029fa790ea9SDavid C Somayajulu /* Skip the check for QP1 to support CM size of 128 */
2030fa790ea9SDavid C Somayajulu if (attrs->cap.max_send_wr > qattr->max_wqe) {
2031fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "cannot create a SQ with %d elements "
2032fa790ea9SDavid C Somayajulu " (max_send_wr=0x%x)\n",
2033fa790ea9SDavid C Somayajulu attrs->cap.max_send_wr, qattr->max_wqe);
2034fa790ea9SDavid C Somayajulu return -EINVAL;
2035fa790ea9SDavid C Somayajulu }
2036fa790ea9SDavid C Somayajulu if (!attrs->srq && (attrs->cap.max_recv_wr > qattr->max_wqe)) {
2037fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "cannot create a RQ with %d elements"
2038fa790ea9SDavid C Somayajulu " (max_recv_wr=0x%x)\n",
2039fa790ea9SDavid C Somayajulu attrs->cap.max_recv_wr, qattr->max_wqe);
2040fa790ea9SDavid C Somayajulu return -EINVAL;
2041fa790ea9SDavid C Somayajulu }
2042fa790ea9SDavid C Somayajulu if (attrs->cap.max_inline_data > qattr->max_inline) {
2043fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
2044fa790ea9SDavid C Somayajulu "unsupported inline data size=0x%x "
2045fa790ea9SDavid C Somayajulu "requested (max_inline=0x%x)\n",
2046fa790ea9SDavid C Somayajulu attrs->cap.max_inline_data, qattr->max_inline);
2047fa790ea9SDavid C Somayajulu return -EINVAL;
2048fa790ea9SDavid C Somayajulu }
2049fa790ea9SDavid C Somayajulu if (attrs->cap.max_send_sge > qattr->max_sge) {
2050fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
2051fa790ea9SDavid C Somayajulu "unsupported send_sge=0x%x "
2052fa790ea9SDavid C Somayajulu "requested (max_send_sge=0x%x)\n",
2053fa790ea9SDavid C Somayajulu attrs->cap.max_send_sge, qattr->max_sge);
2054fa790ea9SDavid C Somayajulu return -EINVAL;
2055fa790ea9SDavid C Somayajulu }
2056fa790ea9SDavid C Somayajulu if (attrs->cap.max_recv_sge > qattr->max_sge) {
2057fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
2058fa790ea9SDavid C Somayajulu "unsupported recv_sge=0x%x requested "
2059fa790ea9SDavid C Somayajulu " (max_recv_sge=0x%x)\n",
2060fa790ea9SDavid C Somayajulu attrs->cap.max_recv_sge, qattr->max_sge);
2061fa790ea9SDavid C Somayajulu return -EINVAL;
2062fa790ea9SDavid C Somayajulu }
2063fa790ea9SDavid C Somayajulu /* unprivileged user space cannot create special QP */
2064fa790ea9SDavid C Somayajulu if (ibpd->uobject && attrs->qp_type == IB_QPT_GSI) {
2065fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
2066fa790ea9SDavid C Somayajulu "userspace can't create special QPs of type=0x%x\n",
2067fa790ea9SDavid C Somayajulu attrs->qp_type);
2068fa790ea9SDavid C Somayajulu return -EINVAL;
2069fa790ea9SDavid C Somayajulu }
2070fa790ea9SDavid C Somayajulu /* allow creating only one GSI type of QP */
2071fa790ea9SDavid C Somayajulu if (attrs->qp_type == IB_QPT_GSI && dev->gsi_qp_created) {
2072fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
2073fa790ea9SDavid C Somayajulu "create qp: GSI special QPs already created.\n");
2074fa790ea9SDavid C Somayajulu return -EINVAL;
2075fa790ea9SDavid C Somayajulu }
2076fa790ea9SDavid C Somayajulu
2077fa790ea9SDavid C Somayajulu /* verify consumer QPs are not trying to use GSI QP's CQ */
2078fa790ea9SDavid C Somayajulu if ((attrs->qp_type != IB_QPT_GSI) && (dev->gsi_qp_created)) {
2079fa790ea9SDavid C Somayajulu struct qlnxr_cq *send_cq = get_qlnxr_cq(attrs->send_cq);
2080fa790ea9SDavid C Somayajulu struct qlnxr_cq *recv_cq = get_qlnxr_cq(attrs->recv_cq);
2081fa790ea9SDavid C Somayajulu
2082fa790ea9SDavid C Somayajulu if ((send_cq->cq_type == QLNXR_CQ_TYPE_GSI) ||
2083fa790ea9SDavid C Somayajulu (recv_cq->cq_type == QLNXR_CQ_TYPE_GSI)) {
2084fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "consumer QP cannot use GSI CQs.\n");
2085fa790ea9SDavid C Somayajulu return -EINVAL;
2086fa790ea9SDavid C Somayajulu }
2087fa790ea9SDavid C Somayajulu }
2088fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2089fa790ea9SDavid C Somayajulu return 0;
2090fa790ea9SDavid C Somayajulu }
2091fa790ea9SDavid C Somayajulu
2092fa790ea9SDavid C Somayajulu static int
qlnxr_copy_srq_uresp(struct qlnxr_dev * dev,struct qlnxr_srq * srq,struct ib_udata * udata)2093fa790ea9SDavid C Somayajulu qlnxr_copy_srq_uresp(struct qlnxr_dev *dev,
2094fa790ea9SDavid C Somayajulu struct qlnxr_srq *srq,
2095fa790ea9SDavid C Somayajulu struct ib_udata *udata)
2096fa790ea9SDavid C Somayajulu {
2097fa790ea9SDavid C Somayajulu struct qlnxr_create_srq_uresp uresp;
2098fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2099fa790ea9SDavid C Somayajulu int rc;
2100fa790ea9SDavid C Somayajulu
2101fa790ea9SDavid C Somayajulu ha = dev->ha;
2102fa790ea9SDavid C Somayajulu
2103fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2104fa790ea9SDavid C Somayajulu
2105fa790ea9SDavid C Somayajulu memset(&uresp, 0, sizeof(uresp));
2106fa790ea9SDavid C Somayajulu
2107fa790ea9SDavid C Somayajulu uresp.srq_id = srq->srq_id;
2108fa790ea9SDavid C Somayajulu
2109fa790ea9SDavid C Somayajulu rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
2110fa790ea9SDavid C Somayajulu
2111fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
2112fa790ea9SDavid C Somayajulu return rc;
2113fa790ea9SDavid C Somayajulu }
2114fa790ea9SDavid C Somayajulu
2115fa790ea9SDavid C Somayajulu static void
qlnxr_copy_rq_uresp(struct qlnxr_dev * dev,struct qlnxr_create_qp_uresp * uresp,struct qlnxr_qp * qp)2116fa790ea9SDavid C Somayajulu qlnxr_copy_rq_uresp(struct qlnxr_dev *dev,
2117fa790ea9SDavid C Somayajulu struct qlnxr_create_qp_uresp *uresp,
2118fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp)
2119fa790ea9SDavid C Somayajulu {
2120fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2121fa790ea9SDavid C Somayajulu
2122fa790ea9SDavid C Somayajulu ha = dev->ha;
2123fa790ea9SDavid C Somayajulu
2124fa790ea9SDavid C Somayajulu /* Return if QP is associated with SRQ instead of RQ */
2125fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter qp->srq = %p\n", qp->srq);
2126fa790ea9SDavid C Somayajulu
2127fa790ea9SDavid C Somayajulu if (qp->srq)
2128fa790ea9SDavid C Somayajulu return;
2129fa790ea9SDavid C Somayajulu
2130fa790ea9SDavid C Somayajulu /* iWARP requires two doorbells per RQ. */
2131fa790ea9SDavid C Somayajulu if (QLNX_IS_IWARP(dev)) {
2132fa790ea9SDavid C Somayajulu uresp->rq_db_offset =
2133fa790ea9SDavid C Somayajulu DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_IWARP_RQ_PROD);
2134fa790ea9SDavid C Somayajulu uresp->rq_db2_offset =
2135fa790ea9SDavid C Somayajulu DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_FLAGS);
2136fa790ea9SDavid C Somayajulu
2137fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "uresp->rq_db_offset = 0x%x "
2138fa790ea9SDavid C Somayajulu "uresp->rq_db2_offset = 0x%x\n",
2139fa790ea9SDavid C Somayajulu uresp->rq_db_offset, uresp->rq_db2_offset);
2140fa790ea9SDavid C Somayajulu } else {
2141fa790ea9SDavid C Somayajulu uresp->rq_db_offset =
2142fa790ea9SDavid C Somayajulu DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_ROCE_RQ_PROD);
2143fa790ea9SDavid C Somayajulu }
2144fa790ea9SDavid C Somayajulu uresp->rq_icid = qp->icid;
2145fa790ea9SDavid C Somayajulu
2146fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2147fa790ea9SDavid C Somayajulu return;
2148fa790ea9SDavid C Somayajulu }
2149fa790ea9SDavid C Somayajulu
2150fa790ea9SDavid C Somayajulu static void
qlnxr_copy_sq_uresp(struct qlnxr_dev * dev,struct qlnxr_create_qp_uresp * uresp,struct qlnxr_qp * qp)2151fa790ea9SDavid C Somayajulu qlnxr_copy_sq_uresp(struct qlnxr_dev *dev,
2152fa790ea9SDavid C Somayajulu struct qlnxr_create_qp_uresp *uresp,
2153fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp)
2154fa790ea9SDavid C Somayajulu {
2155fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2156fa790ea9SDavid C Somayajulu
2157fa790ea9SDavid C Somayajulu ha = dev->ha;
2158fa790ea9SDavid C Somayajulu
2159fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2160fa790ea9SDavid C Somayajulu
2161fa790ea9SDavid C Somayajulu uresp->sq_db_offset = DB_ADDR_SHIFT(DQ_PWM_OFFSET_XCM_RDMA_SQ_PROD);
2162fa790ea9SDavid C Somayajulu
2163fa790ea9SDavid C Somayajulu /* iWARP uses the same cid for rq and sq*/
2164fa790ea9SDavid C Somayajulu if (QLNX_IS_IWARP(dev)) {
2165fa790ea9SDavid C Somayajulu uresp->sq_icid = qp->icid;
2166fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "uresp->sq_icid = 0x%x\n", uresp->sq_icid);
2167fa790ea9SDavid C Somayajulu } else
2168fa790ea9SDavid C Somayajulu uresp->sq_icid = qp->icid + 1;
2169fa790ea9SDavid C Somayajulu
2170fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2171fa790ea9SDavid C Somayajulu return;
2172fa790ea9SDavid C Somayajulu }
2173fa790ea9SDavid C Somayajulu
2174fa790ea9SDavid C Somayajulu static int
qlnxr_copy_qp_uresp(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct ib_udata * udata)2175fa790ea9SDavid C Somayajulu qlnxr_copy_qp_uresp(struct qlnxr_dev *dev,
2176fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
2177fa790ea9SDavid C Somayajulu struct ib_udata *udata)
2178fa790ea9SDavid C Somayajulu {
2179fa790ea9SDavid C Somayajulu int rc;
2180fa790ea9SDavid C Somayajulu struct qlnxr_create_qp_uresp uresp;
2181fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2182fa790ea9SDavid C Somayajulu
2183fa790ea9SDavid C Somayajulu ha = dev->ha;
2184fa790ea9SDavid C Somayajulu
2185fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter qp->icid =0x%x\n", qp->icid);
2186fa790ea9SDavid C Somayajulu
2187fa790ea9SDavid C Somayajulu memset(&uresp, 0, sizeof(uresp));
2188fa790ea9SDavid C Somayajulu qlnxr_copy_sq_uresp(dev, &uresp, qp);
2189fa790ea9SDavid C Somayajulu qlnxr_copy_rq_uresp(dev, &uresp, qp);
2190fa790ea9SDavid C Somayajulu
2191fa790ea9SDavid C Somayajulu uresp.atomic_supported = dev->atomic_cap != IB_ATOMIC_NONE;
2192fa790ea9SDavid C Somayajulu uresp.qp_id = qp->qp_id;
2193fa790ea9SDavid C Somayajulu
2194fa790ea9SDavid C Somayajulu rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
2195fa790ea9SDavid C Somayajulu
2196fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
2197fa790ea9SDavid C Somayajulu return rc;
2198fa790ea9SDavid C Somayajulu }
2199fa790ea9SDavid C Somayajulu
2200fa790ea9SDavid C Somayajulu static void
qlnxr_set_common_qp_params(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct qlnxr_pd * pd,struct ib_qp_init_attr * attrs)2201fa790ea9SDavid C Somayajulu qlnxr_set_common_qp_params(struct qlnxr_dev *dev,
2202fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
2203fa790ea9SDavid C Somayajulu struct qlnxr_pd *pd,
2204fa790ea9SDavid C Somayajulu struct ib_qp_init_attr *attrs)
2205fa790ea9SDavid C Somayajulu {
2206fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2207fa790ea9SDavid C Somayajulu
2208fa790ea9SDavid C Somayajulu ha = dev->ha;
2209fa790ea9SDavid C Somayajulu
2210fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2211fa790ea9SDavid C Somayajulu
2212fa790ea9SDavid C Somayajulu spin_lock_init(&qp->q_lock);
2213fa790ea9SDavid C Somayajulu
2214fa790ea9SDavid C Somayajulu atomic_set(&qp->refcnt, 1);
2215fa790ea9SDavid C Somayajulu qp->pd = pd;
2216fa790ea9SDavid C Somayajulu qp->sig = QLNXR_QP_MAGIC_NUMBER;
2217fa790ea9SDavid C Somayajulu qp->qp_type = attrs->qp_type;
2218fa790ea9SDavid C Somayajulu qp->max_inline_data = ROCE_REQ_MAX_INLINE_DATA_SIZE;
2219fa790ea9SDavid C Somayajulu qp->sq.max_sges = attrs->cap.max_send_sge;
2220fa790ea9SDavid C Somayajulu qp->state = ECORE_ROCE_QP_STATE_RESET;
2221fa790ea9SDavid C Somayajulu qp->signaled = (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) ? true : false;
2222fa790ea9SDavid C Somayajulu qp->sq_cq = get_qlnxr_cq(attrs->send_cq);
2223fa790ea9SDavid C Somayajulu qp->rq_cq = get_qlnxr_cq(attrs->recv_cq);
2224fa790ea9SDavid C Somayajulu qp->dev = dev;
2225fa790ea9SDavid C Somayajulu
2226fa790ea9SDavid C Somayajulu if (!attrs->srq) {
2227fa790ea9SDavid C Somayajulu /* QP is associated with RQ instead of SRQ */
2228fa790ea9SDavid C Somayajulu qp->rq.max_sges = attrs->cap.max_recv_sge;
2229fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "RQ params:\trq_max_sges = %d, rq_cq_id = %d\n",
2230fa790ea9SDavid C Somayajulu qp->rq.max_sges, qp->rq_cq->icid);
2231fa790ea9SDavid C Somayajulu } else {
2232fa790ea9SDavid C Somayajulu qp->srq = get_qlnxr_srq(attrs->srq);
2233fa790ea9SDavid C Somayajulu }
2234fa790ea9SDavid C Somayajulu
2235fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
2236fa790ea9SDavid C Somayajulu "QP params:\tpd = %d, qp_type = %d, max_inline_data = %d,"
2237fa790ea9SDavid C Somayajulu " state = %d, signaled = %d, use_srq=%d\n",
2238fa790ea9SDavid C Somayajulu pd->pd_id, qp->qp_type, qp->max_inline_data,
2239fa790ea9SDavid C Somayajulu qp->state, qp->signaled, ((attrs->srq) ? 1 : 0));
2240fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "SQ params:\tsq_max_sges = %d, sq_cq_id = %d\n",
2241fa790ea9SDavid C Somayajulu qp->sq.max_sges, qp->sq_cq->icid);
2242fa790ea9SDavid C Somayajulu return;
2243fa790ea9SDavid C Somayajulu }
2244fa790ea9SDavid C Somayajulu
2245fa790ea9SDavid C Somayajulu static int
qlnxr_check_srq_params(struct qlnxr_dev * dev,struct ib_srq_init_attr * attrs)2246b633e08cSHans Petter Selasky qlnxr_check_srq_params(struct qlnxr_dev *dev,
2247fa790ea9SDavid C Somayajulu struct ib_srq_init_attr *attrs)
2248fa790ea9SDavid C Somayajulu {
2249fa790ea9SDavid C Somayajulu struct ecore_rdma_device *qattr;
2250fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2251fa790ea9SDavid C Somayajulu
2252fa790ea9SDavid C Somayajulu ha = dev->ha;
2253fa790ea9SDavid C Somayajulu qattr = ecore_rdma_query_device(dev->rdma_ctx);
2254fa790ea9SDavid C Somayajulu
2255fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2256fa790ea9SDavid C Somayajulu
2257fa790ea9SDavid C Somayajulu if (attrs->attr.max_wr > qattr->max_srq_wqe) {
2258fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "unsupported srq_wr=0x%x"
2259fa790ea9SDavid C Somayajulu " requested (max_srq_wr=0x%x)\n",
2260fa790ea9SDavid C Somayajulu attrs->attr.max_wr, qattr->max_srq_wr);
2261fa790ea9SDavid C Somayajulu return -EINVAL;
2262fa790ea9SDavid C Somayajulu }
2263fa790ea9SDavid C Somayajulu
2264fa790ea9SDavid C Somayajulu if (attrs->attr.max_sge > qattr->max_sge) {
2265fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
2266fa790ea9SDavid C Somayajulu "unsupported sge=0x%x requested (max_srq_sge=0x%x)\n",
2267fa790ea9SDavid C Somayajulu attrs->attr.max_sge, qattr->max_sge);
2268fa790ea9SDavid C Somayajulu return -EINVAL;
2269fa790ea9SDavid C Somayajulu }
2270fa790ea9SDavid C Somayajulu
2271fa790ea9SDavid C Somayajulu if (attrs->attr.srq_limit > attrs->attr.max_wr) {
2272fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
2273fa790ea9SDavid C Somayajulu "unsupported srq_limit=0x%x requested"
2274fa790ea9SDavid C Somayajulu " (max_srq_limit=0x%x)\n",
2275fa790ea9SDavid C Somayajulu attrs->attr.srq_limit, attrs->attr.srq_limit);
2276fa790ea9SDavid C Somayajulu return -EINVAL;
2277fa790ea9SDavid C Somayajulu }
2278fa790ea9SDavid C Somayajulu
2279fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2280fa790ea9SDavid C Somayajulu return 0;
2281fa790ea9SDavid C Somayajulu }
2282fa790ea9SDavid C Somayajulu
2283fa790ea9SDavid C Somayajulu static void
qlnxr_free_srq_user_params(struct qlnxr_srq * srq)2284fa790ea9SDavid C Somayajulu qlnxr_free_srq_user_params(struct qlnxr_srq *srq)
2285fa790ea9SDavid C Somayajulu {
2286fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = srq->dev;
2287fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2288fa790ea9SDavid C Somayajulu
2289fa790ea9SDavid C Somayajulu ha = dev->ha;
2290fa790ea9SDavid C Somayajulu
2291fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2292fa790ea9SDavid C Somayajulu
2293fa790ea9SDavid C Somayajulu qlnxr_free_pbl(srq->dev, &srq->usrq.pbl_info, srq->usrq.pbl_tbl);
2294fa790ea9SDavid C Somayajulu ib_umem_release(srq->usrq.umem);
2295fa790ea9SDavid C Somayajulu ib_umem_release(srq->prod_umem);
2296fa790ea9SDavid C Somayajulu
2297fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2298fa790ea9SDavid C Somayajulu return;
2299fa790ea9SDavid C Somayajulu }
2300fa790ea9SDavid C Somayajulu
2301fa790ea9SDavid C Somayajulu static void
qlnxr_free_srq_kernel_params(struct qlnxr_srq * srq)2302fa790ea9SDavid C Somayajulu qlnxr_free_srq_kernel_params(struct qlnxr_srq *srq)
2303fa790ea9SDavid C Somayajulu {
2304fa790ea9SDavid C Somayajulu struct qlnxr_srq_hwq_info *hw_srq = &srq->hw_srq;
2305fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = srq->dev;
2306fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2307fa790ea9SDavid C Somayajulu
2308fa790ea9SDavid C Somayajulu ha = dev->ha;
2309fa790ea9SDavid C Somayajulu
2310fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2311fa790ea9SDavid C Somayajulu
2312fa790ea9SDavid C Somayajulu ecore_chain_free(dev->cdev, &hw_srq->pbl);
2313fa790ea9SDavid C Somayajulu
2314fa790ea9SDavid C Somayajulu qlnx_dma_free_coherent(&dev->cdev,
2315fa790ea9SDavid C Somayajulu hw_srq->virt_prod_pair_addr,
2316fa790ea9SDavid C Somayajulu hw_srq->phy_prod_pair_addr,
2317fa790ea9SDavid C Somayajulu sizeof(struct rdma_srq_producers));
2318fa790ea9SDavid C Somayajulu
2319fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2320fa790ea9SDavid C Somayajulu
2321fa790ea9SDavid C Somayajulu return;
2322fa790ea9SDavid C Somayajulu }
2323fa790ea9SDavid C Somayajulu
2324fa790ea9SDavid C Somayajulu static int
qlnxr_init_srq_user_params(struct ib_ucontext * ib_ctx,struct qlnxr_srq * srq,struct qlnxr_create_srq_ureq * ureq,int access,int dmasync)2325fa790ea9SDavid C Somayajulu qlnxr_init_srq_user_params(struct ib_ucontext *ib_ctx,
2326fa790ea9SDavid C Somayajulu struct qlnxr_srq *srq,
2327fa790ea9SDavid C Somayajulu struct qlnxr_create_srq_ureq *ureq,
2328fa790ea9SDavid C Somayajulu int access, int dmasync)
2329fa790ea9SDavid C Somayajulu {
2330fa790ea9SDavid C Somayajulu struct scatterlist *sg;
2331fa790ea9SDavid C Somayajulu int rc;
2332fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = srq->dev;
2333fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2334fa790ea9SDavid C Somayajulu
2335fa790ea9SDavid C Somayajulu ha = dev->ha;
2336fa790ea9SDavid C Somayajulu
2337fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2338fa790ea9SDavid C Somayajulu
2339fa790ea9SDavid C Somayajulu rc = qlnxr_init_user_queue(ib_ctx, srq->dev, &srq->usrq, ureq->srq_addr,
2340fa790ea9SDavid C Somayajulu ureq->srq_len, access, dmasync, 1);
2341fa790ea9SDavid C Somayajulu if (rc)
2342fa790ea9SDavid C Somayajulu return rc;
2343fa790ea9SDavid C Somayajulu
2344fa790ea9SDavid C Somayajulu srq->prod_umem = ib_umem_get(ib_ctx, ureq->prod_pair_addr,
2345fa790ea9SDavid C Somayajulu sizeof(struct rdma_srq_producers),
2346fa790ea9SDavid C Somayajulu access, dmasync);
2347fa790ea9SDavid C Somayajulu if (IS_ERR(srq->prod_umem)) {
2348fa790ea9SDavid C Somayajulu qlnxr_free_pbl(srq->dev, &srq->usrq.pbl_info, srq->usrq.pbl_tbl);
2349fa790ea9SDavid C Somayajulu ib_umem_release(srq->usrq.umem);
2350fa790ea9SDavid C Somayajulu
2351fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ib_umem_get failed for producer [%p]\n",
2352fa790ea9SDavid C Somayajulu PTR_ERR(srq->prod_umem));
2353fa790ea9SDavid C Somayajulu
2354fa790ea9SDavid C Somayajulu return PTR_ERR(srq->prod_umem);
2355fa790ea9SDavid C Somayajulu }
2356fa790ea9SDavid C Somayajulu
2357fa790ea9SDavid C Somayajulu sg = srq->prod_umem->sg_head.sgl;
2358fa790ea9SDavid C Somayajulu srq->hw_srq.phy_prod_pair_addr = sg_dma_address(sg);
2359fa790ea9SDavid C Somayajulu
2360fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2361fa790ea9SDavid C Somayajulu return 0;
2362fa790ea9SDavid C Somayajulu }
2363fa790ea9SDavid C Somayajulu
2364fa790ea9SDavid C Somayajulu static int
qlnxr_alloc_srq_kernel_params(struct qlnxr_srq * srq,struct qlnxr_dev * dev,struct ib_srq_init_attr * init_attr)2365fa790ea9SDavid C Somayajulu qlnxr_alloc_srq_kernel_params(struct qlnxr_srq *srq,
2366fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev,
2367fa790ea9SDavid C Somayajulu struct ib_srq_init_attr *init_attr)
2368fa790ea9SDavid C Somayajulu {
2369fa790ea9SDavid C Somayajulu struct qlnxr_srq_hwq_info *hw_srq = &srq->hw_srq;
2370fa790ea9SDavid C Somayajulu dma_addr_t phy_prod_pair_addr;
2371fa790ea9SDavid C Somayajulu u32 num_elems, max_wr;
2372fa790ea9SDavid C Somayajulu void *va;
2373fa790ea9SDavid C Somayajulu int rc;
2374fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2375fa790ea9SDavid C Somayajulu
2376fa790ea9SDavid C Somayajulu ha = dev->ha;
2377fa790ea9SDavid C Somayajulu
2378fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2379fa790ea9SDavid C Somayajulu
2380fa790ea9SDavid C Somayajulu va = qlnx_dma_alloc_coherent(&dev->cdev,
2381fa790ea9SDavid C Somayajulu &phy_prod_pair_addr,
2382fa790ea9SDavid C Somayajulu sizeof(struct rdma_srq_producers));
2383fa790ea9SDavid C Somayajulu if (!va) {
2384fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnx_dma_alloc_coherent failed for produceer\n");
2385fa790ea9SDavid C Somayajulu return -ENOMEM;
2386fa790ea9SDavid C Somayajulu }
2387fa790ea9SDavid C Somayajulu
2388fa790ea9SDavid C Somayajulu hw_srq->phy_prod_pair_addr = phy_prod_pair_addr;
2389fa790ea9SDavid C Somayajulu hw_srq->virt_prod_pair_addr = va;
2390fa790ea9SDavid C Somayajulu
2391fa790ea9SDavid C Somayajulu max_wr = init_attr->attr.max_wr;
2392fa790ea9SDavid C Somayajulu
2393fa790ea9SDavid C Somayajulu num_elems = max_wr * RDMA_MAX_SRQ_WQE_SIZE;
2394fa790ea9SDavid C Somayajulu
2395fa790ea9SDavid C Somayajulu rc = ecore_chain_alloc(dev->cdev,
2396fa790ea9SDavid C Somayajulu ECORE_CHAIN_USE_TO_CONSUME_PRODUCE,
2397fa790ea9SDavid C Somayajulu ECORE_CHAIN_MODE_PBL,
2398fa790ea9SDavid C Somayajulu ECORE_CHAIN_CNT_TYPE_U32,
2399fa790ea9SDavid C Somayajulu num_elems,
2400fa790ea9SDavid C Somayajulu ECORE_RDMA_SRQ_WQE_ELEM_SIZE,
2401fa790ea9SDavid C Somayajulu &hw_srq->pbl, NULL);
2402fa790ea9SDavid C Somayajulu
2403fa790ea9SDavid C Somayajulu if (rc) {
2404fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ecore_chain_alloc failed [%d]\n", rc);
2405fa790ea9SDavid C Somayajulu goto err0;
2406fa790ea9SDavid C Somayajulu }
2407fa790ea9SDavid C Somayajulu
2408fa790ea9SDavid C Somayajulu hw_srq->max_wr = max_wr;
2409fa790ea9SDavid C Somayajulu hw_srq->num_elems = num_elems;
2410fa790ea9SDavid C Somayajulu hw_srq->max_sges = RDMA_MAX_SGE_PER_SRQ;
2411fa790ea9SDavid C Somayajulu
2412fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2413fa790ea9SDavid C Somayajulu return 0;
2414fa790ea9SDavid C Somayajulu
2415fa790ea9SDavid C Somayajulu err0:
2416fa790ea9SDavid C Somayajulu qlnx_dma_free_coherent(&dev->cdev, va, phy_prod_pair_addr,
2417fa790ea9SDavid C Somayajulu sizeof(struct rdma_srq_producers));
2418fa790ea9SDavid C Somayajulu
2419fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
2420fa790ea9SDavid C Somayajulu return rc;
2421fa790ea9SDavid C Somayajulu }
2422fa790ea9SDavid C Somayajulu
2423fa790ea9SDavid C Somayajulu static inline void
qlnxr_init_common_qp_in_params(struct qlnxr_dev * dev,struct qlnxr_pd * pd,struct qlnxr_qp * qp,struct ib_qp_init_attr * attrs,bool fmr_and_reserved_lkey,struct ecore_rdma_create_qp_in_params * params)2424fa790ea9SDavid C Somayajulu qlnxr_init_common_qp_in_params(struct qlnxr_dev *dev,
2425fa790ea9SDavid C Somayajulu struct qlnxr_pd *pd,
2426fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
2427fa790ea9SDavid C Somayajulu struct ib_qp_init_attr *attrs,
2428fa790ea9SDavid C Somayajulu bool fmr_and_reserved_lkey,
2429fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_in_params *params)
2430fa790ea9SDavid C Somayajulu {
2431fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2432fa790ea9SDavid C Somayajulu
2433fa790ea9SDavid C Somayajulu ha = dev->ha;
2434fa790ea9SDavid C Somayajulu
2435fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2436fa790ea9SDavid C Somayajulu
2437fa790ea9SDavid C Somayajulu /* QP handle to be written in an async event */
2438fa790ea9SDavid C Somayajulu params->qp_handle_async_lo = lower_32_bits((uintptr_t)qp);
2439fa790ea9SDavid C Somayajulu params->qp_handle_async_hi = upper_32_bits((uintptr_t)qp);
2440fa790ea9SDavid C Somayajulu
2441fa790ea9SDavid C Somayajulu params->signal_all = (attrs->sq_sig_type == IB_SIGNAL_ALL_WR);
2442fa790ea9SDavid C Somayajulu params->fmr_and_reserved_lkey = fmr_and_reserved_lkey;
2443fa790ea9SDavid C Somayajulu params->pd = pd->pd_id;
2444fa790ea9SDavid C Somayajulu params->dpi = pd->uctx ? pd->uctx->dpi : dev->dpi;
2445fa790ea9SDavid C Somayajulu params->sq_cq_id = get_qlnxr_cq(attrs->send_cq)->icid;
2446fa790ea9SDavid C Somayajulu params->stats_queue = 0;
2447fa790ea9SDavid C Somayajulu
2448fa790ea9SDavid C Somayajulu params->rq_cq_id = get_qlnxr_cq(attrs->recv_cq)->icid;
2449fa790ea9SDavid C Somayajulu
2450fa790ea9SDavid C Somayajulu if (qp->srq) {
2451fa790ea9SDavid C Somayajulu /* QP is associated with SRQ instead of RQ */
2452fa790ea9SDavid C Somayajulu params->srq_id = qp->srq->srq_id;
2453fa790ea9SDavid C Somayajulu params->use_srq = true;
2454fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "exit srq_id = 0x%x use_srq = 0x%x\n",
2455fa790ea9SDavid C Somayajulu params->srq_id, params->use_srq);
2456fa790ea9SDavid C Somayajulu return;
2457fa790ea9SDavid C Somayajulu }
2458fa790ea9SDavid C Somayajulu
2459fa790ea9SDavid C Somayajulu params->srq_id = 0;
2460fa790ea9SDavid C Somayajulu params->use_srq = false;
2461fa790ea9SDavid C Somayajulu
2462fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2463fa790ea9SDavid C Somayajulu return;
2464fa790ea9SDavid C Somayajulu }
2465fa790ea9SDavid C Somayajulu
2466fa790ea9SDavid C Somayajulu static inline void
qlnxr_qp_user_print(struct qlnxr_dev * dev,struct qlnxr_qp * qp)2467fa790ea9SDavid C Somayajulu qlnxr_qp_user_print( struct qlnxr_dev *dev,
2468fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp)
2469fa790ea9SDavid C Somayajulu {
2470fa790ea9SDavid C Somayajulu QL_DPRINT12((dev->ha), "qp=%p. sq_addr=0x%llx, sq_len=%zd, "
2471fa790ea9SDavid C Somayajulu "rq_addr=0x%llx, rq_len=%zd\n",
2472fa790ea9SDavid C Somayajulu qp, qp->usq.buf_addr, qp->usq.buf_len, qp->urq.buf_addr,
2473fa790ea9SDavid C Somayajulu qp->urq.buf_len);
2474fa790ea9SDavid C Somayajulu return;
2475fa790ea9SDavid C Somayajulu }
2476fa790ea9SDavid C Somayajulu
2477fa790ea9SDavid C Somayajulu static int
qlnxr_idr_add(struct qlnxr_dev * dev,void * ptr,u32 id)2478fa790ea9SDavid C Somayajulu qlnxr_idr_add(struct qlnxr_dev *dev, void *ptr, u32 id)
2479fa790ea9SDavid C Somayajulu {
2480fa790ea9SDavid C Somayajulu u32 newid;
2481fa790ea9SDavid C Somayajulu int rc;
2482fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2483fa790ea9SDavid C Somayajulu
2484fa790ea9SDavid C Somayajulu ha = dev->ha;
2485fa790ea9SDavid C Somayajulu
2486fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2487fa790ea9SDavid C Somayajulu
2488fa790ea9SDavid C Somayajulu if (!QLNX_IS_IWARP(dev))
2489fa790ea9SDavid C Somayajulu return 0;
2490fa790ea9SDavid C Somayajulu
2491fa790ea9SDavid C Somayajulu do {
2492fa790ea9SDavid C Somayajulu if (!idr_pre_get(&dev->qpidr, GFP_KERNEL)) {
2493fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "idr_pre_get failed\n");
2494fa790ea9SDavid C Somayajulu return -ENOMEM;
2495fa790ea9SDavid C Somayajulu }
2496fa790ea9SDavid C Somayajulu
2497fa790ea9SDavid C Somayajulu mtx_lock(&dev->idr_lock);
2498fa790ea9SDavid C Somayajulu
2499fa790ea9SDavid C Somayajulu rc = idr_get_new_above(&dev->qpidr, ptr, id, &newid);
2500fa790ea9SDavid C Somayajulu
2501fa790ea9SDavid C Somayajulu mtx_unlock(&dev->idr_lock);
2502fa790ea9SDavid C Somayajulu
2503fa790ea9SDavid C Somayajulu } while (rc == -EAGAIN);
2504fa790ea9SDavid C Somayajulu
2505fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
2506fa790ea9SDavid C Somayajulu
2507fa790ea9SDavid C Somayajulu return rc;
2508fa790ea9SDavid C Somayajulu }
2509fa790ea9SDavid C Somayajulu
2510fa790ea9SDavid C Somayajulu static void
qlnxr_idr_remove(struct qlnxr_dev * dev,u32 id)2511fa790ea9SDavid C Somayajulu qlnxr_idr_remove(struct qlnxr_dev *dev, u32 id)
2512fa790ea9SDavid C Somayajulu {
2513fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2514fa790ea9SDavid C Somayajulu
2515fa790ea9SDavid C Somayajulu ha = dev->ha;
2516fa790ea9SDavid C Somayajulu
2517fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2518fa790ea9SDavid C Somayajulu
2519fa790ea9SDavid C Somayajulu if (!QLNX_IS_IWARP(dev))
2520fa790ea9SDavid C Somayajulu return;
2521fa790ea9SDavid C Somayajulu
2522fa790ea9SDavid C Somayajulu mtx_lock(&dev->idr_lock);
2523fa790ea9SDavid C Somayajulu idr_remove(&dev->qpidr, id);
2524fa790ea9SDavid C Somayajulu mtx_unlock(&dev->idr_lock);
2525fa790ea9SDavid C Somayajulu
2526fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit \n");
2527fa790ea9SDavid C Somayajulu
2528fa790ea9SDavid C Somayajulu return;
2529fa790ea9SDavid C Somayajulu }
2530fa790ea9SDavid C Somayajulu
2531fa790ea9SDavid C Somayajulu static inline void
qlnxr_iwarp_populate_user_qp(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct ecore_rdma_create_qp_out_params * out_params)2532fa790ea9SDavid C Somayajulu qlnxr_iwarp_populate_user_qp(struct qlnxr_dev *dev,
2533fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
2534fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_out_params *out_params)
2535fa790ea9SDavid C Somayajulu {
2536fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2537fa790ea9SDavid C Somayajulu
2538fa790ea9SDavid C Somayajulu ha = dev->ha;
2539fa790ea9SDavid C Somayajulu
2540fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2541fa790ea9SDavid C Somayajulu
2542fa790ea9SDavid C Somayajulu qp->usq.pbl_tbl->va = out_params->sq_pbl_virt;
2543fa790ea9SDavid C Somayajulu qp->usq.pbl_tbl->pa = out_params->sq_pbl_phys;
2544fa790ea9SDavid C Somayajulu
2545fa790ea9SDavid C Somayajulu qlnxr_populate_pbls(dev, qp->usq.umem, qp->usq.pbl_tbl,
2546fa790ea9SDavid C Somayajulu &qp->usq.pbl_info);
2547fa790ea9SDavid C Somayajulu
2548fa790ea9SDavid C Somayajulu if (qp->srq) {
2549fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qp->srq = %p\n", qp->srq);
2550fa790ea9SDavid C Somayajulu return;
2551fa790ea9SDavid C Somayajulu }
2552fa790ea9SDavid C Somayajulu
2553fa790ea9SDavid C Somayajulu qp->urq.pbl_tbl->va = out_params->rq_pbl_virt;
2554fa790ea9SDavid C Somayajulu qp->urq.pbl_tbl->pa = out_params->rq_pbl_phys;
2555fa790ea9SDavid C Somayajulu
2556fa790ea9SDavid C Somayajulu qlnxr_populate_pbls(dev, qp->urq.umem, qp->urq.pbl_tbl,
2557fa790ea9SDavid C Somayajulu &qp->urq.pbl_info);
2558fa790ea9SDavid C Somayajulu
2559fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2560fa790ea9SDavid C Somayajulu return;
2561fa790ea9SDavid C Somayajulu }
2562fa790ea9SDavid C Somayajulu
2563fa790ea9SDavid C Somayajulu static int
qlnxr_create_user_qp(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct ib_pd * ibpd,struct ib_udata * udata,struct ib_qp_init_attr * attrs)2564fa790ea9SDavid C Somayajulu qlnxr_create_user_qp(struct qlnxr_dev *dev,
2565fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
2566fa790ea9SDavid C Somayajulu struct ib_pd *ibpd,
2567fa790ea9SDavid C Somayajulu struct ib_udata *udata,
2568fa790ea9SDavid C Somayajulu struct ib_qp_init_attr *attrs)
2569fa790ea9SDavid C Somayajulu {
2570fa790ea9SDavid C Somayajulu struct ecore_rdma_destroy_qp_out_params d_out_params;
2571fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_in_params in_params;
2572fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_out_params out_params;
2573fa790ea9SDavid C Somayajulu struct qlnxr_pd *pd = get_qlnxr_pd(ibpd);
2574fa790ea9SDavid C Somayajulu struct ib_ucontext *ib_ctx = NULL;
2575fa790ea9SDavid C Somayajulu struct qlnxr_create_qp_ureq ureq;
2576fa790ea9SDavid C Somayajulu int alloc_and_init = QLNX_IS_ROCE(dev);
2577fa790ea9SDavid C Somayajulu int rc = -EINVAL;
2578fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2579fa790ea9SDavid C Somayajulu
2580fa790ea9SDavid C Somayajulu ha = dev->ha;
2581fa790ea9SDavid C Somayajulu
2582fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2583fa790ea9SDavid C Somayajulu
2584fa790ea9SDavid C Somayajulu ib_ctx = ibpd->uobject->context;
2585fa790ea9SDavid C Somayajulu
2586fa790ea9SDavid C Somayajulu memset(&ureq, 0, sizeof(ureq));
2587fa790ea9SDavid C Somayajulu rc = ib_copy_from_udata(&ureq, udata, sizeof(ureq));
2588fa790ea9SDavid C Somayajulu
2589fa790ea9SDavid C Somayajulu if (rc) {
2590fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ib_copy_from_udata failed [%d]\n", rc);
2591fa790ea9SDavid C Somayajulu return rc;
2592fa790ea9SDavid C Somayajulu }
2593fa790ea9SDavid C Somayajulu
2594fa790ea9SDavid C Somayajulu /* SQ - read access only (0), dma sync not required (0) */
2595fa790ea9SDavid C Somayajulu rc = qlnxr_init_user_queue(ib_ctx, dev, &qp->usq, ureq.sq_addr,
2596fa790ea9SDavid C Somayajulu ureq.sq_len, 0, 0,
2597fa790ea9SDavid C Somayajulu alloc_and_init);
2598fa790ea9SDavid C Somayajulu if (rc) {
2599fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_init_user_queue failed [%d]\n", rc);
2600fa790ea9SDavid C Somayajulu return rc;
2601fa790ea9SDavid C Somayajulu }
2602fa790ea9SDavid C Somayajulu
2603fa790ea9SDavid C Somayajulu if (!qp->srq) {
2604fa790ea9SDavid C Somayajulu /* RQ - read access only (0), dma sync not required (0) */
2605fa790ea9SDavid C Somayajulu rc = qlnxr_init_user_queue(ib_ctx, dev, &qp->urq, ureq.rq_addr,
2606fa790ea9SDavid C Somayajulu ureq.rq_len, 0, 0,
2607fa790ea9SDavid C Somayajulu alloc_and_init);
2608fa790ea9SDavid C Somayajulu
2609fa790ea9SDavid C Somayajulu if (rc) {
2610fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_init_user_queue failed [%d]\n", rc);
2611fa790ea9SDavid C Somayajulu return rc;
2612fa790ea9SDavid C Somayajulu }
2613fa790ea9SDavid C Somayajulu }
2614fa790ea9SDavid C Somayajulu
2615fa790ea9SDavid C Somayajulu memset(&in_params, 0, sizeof(in_params));
2616fa790ea9SDavid C Somayajulu qlnxr_init_common_qp_in_params(dev, pd, qp, attrs, false, &in_params);
2617fa790ea9SDavid C Somayajulu in_params.qp_handle_lo = ureq.qp_handle_lo;
2618fa790ea9SDavid C Somayajulu in_params.qp_handle_hi = ureq.qp_handle_hi;
2619fa790ea9SDavid C Somayajulu in_params.sq_num_pages = qp->usq.pbl_info.num_pbes;
2620fa790ea9SDavid C Somayajulu in_params.sq_pbl_ptr = qp->usq.pbl_tbl->pa;
2621fa790ea9SDavid C Somayajulu
2622fa790ea9SDavid C Somayajulu if (!qp->srq) {
2623fa790ea9SDavid C Somayajulu in_params.rq_num_pages = qp->urq.pbl_info.num_pbes;
2624fa790ea9SDavid C Somayajulu in_params.rq_pbl_ptr = qp->urq.pbl_tbl->pa;
2625fa790ea9SDavid C Somayajulu }
2626fa790ea9SDavid C Somayajulu
2627fa790ea9SDavid C Somayajulu qp->ecore_qp = ecore_rdma_create_qp(dev->rdma_ctx, &in_params, &out_params);
2628fa790ea9SDavid C Somayajulu
2629fa790ea9SDavid C Somayajulu if (!qp->ecore_qp) {
2630fa790ea9SDavid C Somayajulu rc = -ENOMEM;
2631fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ecore_rdma_create_qp failed\n");
2632fa790ea9SDavid C Somayajulu goto err1;
2633fa790ea9SDavid C Somayajulu }
2634fa790ea9SDavid C Somayajulu
2635fa790ea9SDavid C Somayajulu if (QLNX_IS_IWARP(dev))
2636fa790ea9SDavid C Somayajulu qlnxr_iwarp_populate_user_qp(dev, qp, &out_params);
2637fa790ea9SDavid C Somayajulu
2638fa790ea9SDavid C Somayajulu qp->qp_id = out_params.qp_id;
2639fa790ea9SDavid C Somayajulu qp->icid = out_params.icid;
2640fa790ea9SDavid C Somayajulu
2641fa790ea9SDavid C Somayajulu rc = qlnxr_copy_qp_uresp(dev, qp, udata);
2642fa790ea9SDavid C Somayajulu
2643fa790ea9SDavid C Somayajulu if (rc) {
2644fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_copy_qp_uresp failed\n");
2645fa790ea9SDavid C Somayajulu goto err;
2646fa790ea9SDavid C Somayajulu }
2647fa790ea9SDavid C Somayajulu
2648fa790ea9SDavid C Somayajulu qlnxr_qp_user_print(dev, qp);
2649fa790ea9SDavid C Somayajulu
2650fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2651fa790ea9SDavid C Somayajulu return 0;
2652fa790ea9SDavid C Somayajulu err:
2653fa790ea9SDavid C Somayajulu rc = ecore_rdma_destroy_qp(dev->rdma_ctx, qp->ecore_qp, &d_out_params);
2654fa790ea9SDavid C Somayajulu
2655fa790ea9SDavid C Somayajulu if (rc)
2656fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "fatal fault\n");
2657fa790ea9SDavid C Somayajulu
2658fa790ea9SDavid C Somayajulu err1:
2659fa790ea9SDavid C Somayajulu qlnxr_cleanup_user(dev, qp);
2660fa790ea9SDavid C Somayajulu
2661fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit[%d]\n", rc);
2662fa790ea9SDavid C Somayajulu return rc;
2663fa790ea9SDavid C Somayajulu }
2664fa790ea9SDavid C Somayajulu
2665fa790ea9SDavid C Somayajulu static void
qlnxr_set_roce_db_info(struct qlnxr_dev * dev,struct qlnxr_qp * qp)2666fa790ea9SDavid C Somayajulu qlnxr_set_roce_db_info(struct qlnxr_dev *dev,
2667fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp)
2668fa790ea9SDavid C Somayajulu {
2669fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2670fa790ea9SDavid C Somayajulu
2671fa790ea9SDavid C Somayajulu ha = dev->ha;
2672fa790ea9SDavid C Somayajulu
2673fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter qp = %p qp->srq %p\n", qp, qp->srq);
2674fa790ea9SDavid C Somayajulu
2675fa790ea9SDavid C Somayajulu qp->sq.db = dev->db_addr +
2676fa790ea9SDavid C Somayajulu DB_ADDR_SHIFT(DQ_PWM_OFFSET_XCM_RDMA_SQ_PROD);
2677fa790ea9SDavid C Somayajulu qp->sq.db_data.data.icid = qp->icid + 1;
2678fa790ea9SDavid C Somayajulu
2679fa790ea9SDavid C Somayajulu if (!qp->srq) {
2680fa790ea9SDavid C Somayajulu qp->rq.db = dev->db_addr +
2681fa790ea9SDavid C Somayajulu DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_ROCE_RQ_PROD);
2682fa790ea9SDavid C Somayajulu qp->rq.db_data.data.icid = qp->icid;
2683fa790ea9SDavid C Somayajulu }
2684fa790ea9SDavid C Somayajulu
2685fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2686fa790ea9SDavid C Somayajulu return;
2687fa790ea9SDavid C Somayajulu }
2688fa790ea9SDavid C Somayajulu
2689fa790ea9SDavid C Somayajulu static void
qlnxr_set_iwarp_db_info(struct qlnxr_dev * dev,struct qlnxr_qp * qp)2690fa790ea9SDavid C Somayajulu qlnxr_set_iwarp_db_info(struct qlnxr_dev *dev,
2691fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp)
2692fa790ea9SDavid C Somayajulu
2693fa790ea9SDavid C Somayajulu {
2694fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2695fa790ea9SDavid C Somayajulu
2696fa790ea9SDavid C Somayajulu ha = dev->ha;
2697fa790ea9SDavid C Somayajulu
2698fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter qp = %p qp->srq %p\n", qp, qp->srq);
2699fa790ea9SDavid C Somayajulu
2700fa790ea9SDavid C Somayajulu qp->sq.db = dev->db_addr +
2701fa790ea9SDavid C Somayajulu DB_ADDR_SHIFT(DQ_PWM_OFFSET_XCM_RDMA_SQ_PROD);
2702fa790ea9SDavid C Somayajulu qp->sq.db_data.data.icid = qp->icid;
2703fa790ea9SDavid C Somayajulu
2704fa790ea9SDavid C Somayajulu if (!qp->srq) {
2705fa790ea9SDavid C Somayajulu qp->rq.db = dev->db_addr +
2706fa790ea9SDavid C Somayajulu DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_IWARP_RQ_PROD);
2707fa790ea9SDavid C Somayajulu qp->rq.db_data.data.icid = qp->icid;
2708fa790ea9SDavid C Somayajulu
2709fa790ea9SDavid C Somayajulu qp->rq.iwarp_db2 = dev->db_addr +
2710fa790ea9SDavid C Somayajulu DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_FLAGS);
2711fa790ea9SDavid C Somayajulu qp->rq.iwarp_db2_data.data.icid = qp->icid;
2712fa790ea9SDavid C Somayajulu qp->rq.iwarp_db2_data.data.value = DQ_TCM_IWARP_POST_RQ_CF_CMD;
2713fa790ea9SDavid C Somayajulu }
2714fa790ea9SDavid C Somayajulu
2715fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
2716fa790ea9SDavid C Somayajulu "qp->sq.db = %p qp->sq.db_data.data.icid =0x%x\n"
2717fa790ea9SDavid C Somayajulu "\t\t\tqp->rq.db = %p qp->rq.db_data.data.icid =0x%x\n"
2718fa790ea9SDavid C Somayajulu "\t\t\tqp->rq.iwarp_db2 = %p qp->rq.iwarp_db2.data.icid =0x%x"
2719fa790ea9SDavid C Somayajulu " qp->rq.iwarp_db2.data.prod_val =0x%x\n",
2720fa790ea9SDavid C Somayajulu qp->sq.db, qp->sq.db_data.data.icid,
2721fa790ea9SDavid C Somayajulu qp->rq.db, qp->rq.db_data.data.icid,
2722fa790ea9SDavid C Somayajulu qp->rq.iwarp_db2, qp->rq.iwarp_db2_data.data.icid,
2723fa790ea9SDavid C Somayajulu qp->rq.iwarp_db2_data.data.value);
2724fa790ea9SDavid C Somayajulu
2725fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2726fa790ea9SDavid C Somayajulu return;
2727fa790ea9SDavid C Somayajulu }
2728fa790ea9SDavid C Somayajulu
2729fa790ea9SDavid C Somayajulu static int
qlnxr_roce_create_kernel_qp(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct ecore_rdma_create_qp_in_params * in_params,u32 n_sq_elems,u32 n_rq_elems)2730fa790ea9SDavid C Somayajulu qlnxr_roce_create_kernel_qp(struct qlnxr_dev *dev,
2731fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
2732fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_in_params *in_params,
2733fa790ea9SDavid C Somayajulu u32 n_sq_elems,
2734fa790ea9SDavid C Somayajulu u32 n_rq_elems)
2735fa790ea9SDavid C Somayajulu {
2736fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_out_params out_params;
2737fa790ea9SDavid C Somayajulu int rc;
2738fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2739fa790ea9SDavid C Somayajulu
2740fa790ea9SDavid C Somayajulu ha = dev->ha;
2741fa790ea9SDavid C Somayajulu
2742fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2743fa790ea9SDavid C Somayajulu
2744fa790ea9SDavid C Somayajulu rc = ecore_chain_alloc(
2745fa790ea9SDavid C Somayajulu dev->cdev,
2746fa790ea9SDavid C Somayajulu ECORE_CHAIN_USE_TO_PRODUCE,
2747fa790ea9SDavid C Somayajulu ECORE_CHAIN_MODE_PBL,
2748fa790ea9SDavid C Somayajulu ECORE_CHAIN_CNT_TYPE_U32,
2749fa790ea9SDavid C Somayajulu n_sq_elems,
2750fa790ea9SDavid C Somayajulu QLNXR_SQE_ELEMENT_SIZE,
2751fa790ea9SDavid C Somayajulu &qp->sq.pbl,
2752fa790ea9SDavid C Somayajulu NULL);
2753fa790ea9SDavid C Somayajulu
2754fa790ea9SDavid C Somayajulu if (rc) {
2755fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ecore_chain_alloc qp->sq.pbl failed[%d]\n", rc);
2756fa790ea9SDavid C Somayajulu return rc;
2757fa790ea9SDavid C Somayajulu }
2758fa790ea9SDavid C Somayajulu
2759fa790ea9SDavid C Somayajulu in_params->sq_num_pages = ecore_chain_get_page_cnt(&qp->sq.pbl);
2760fa790ea9SDavid C Somayajulu in_params->sq_pbl_ptr = ecore_chain_get_pbl_phys(&qp->sq.pbl);
2761fa790ea9SDavid C Somayajulu
2762fa790ea9SDavid C Somayajulu if (!qp->srq) {
2763fa790ea9SDavid C Somayajulu rc = ecore_chain_alloc(
2764fa790ea9SDavid C Somayajulu dev->cdev,
2765fa790ea9SDavid C Somayajulu ECORE_CHAIN_USE_TO_CONSUME_PRODUCE,
2766fa790ea9SDavid C Somayajulu ECORE_CHAIN_MODE_PBL,
2767fa790ea9SDavid C Somayajulu ECORE_CHAIN_CNT_TYPE_U32,
2768fa790ea9SDavid C Somayajulu n_rq_elems,
2769fa790ea9SDavid C Somayajulu QLNXR_RQE_ELEMENT_SIZE,
2770fa790ea9SDavid C Somayajulu &qp->rq.pbl,
2771fa790ea9SDavid C Somayajulu NULL);
2772fa790ea9SDavid C Somayajulu
2773fa790ea9SDavid C Somayajulu if (rc) {
2774fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,
2775fa790ea9SDavid C Somayajulu "ecore_chain_alloc qp->rq.pbl failed[%d]\n", rc);
2776fa790ea9SDavid C Somayajulu return rc;
2777fa790ea9SDavid C Somayajulu }
2778fa790ea9SDavid C Somayajulu
2779fa790ea9SDavid C Somayajulu in_params->rq_num_pages = ecore_chain_get_page_cnt(&qp->rq.pbl);
2780fa790ea9SDavid C Somayajulu in_params->rq_pbl_ptr = ecore_chain_get_pbl_phys(&qp->rq.pbl);
2781fa790ea9SDavid C Somayajulu }
2782fa790ea9SDavid C Somayajulu
2783fa790ea9SDavid C Somayajulu qp->ecore_qp = ecore_rdma_create_qp(dev->rdma_ctx, in_params, &out_params);
2784fa790ea9SDavid C Somayajulu
2785fa790ea9SDavid C Somayajulu if (!qp->ecore_qp) {
2786fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qp->ecore_qp == NULL\n");
2787fa790ea9SDavid C Somayajulu return -EINVAL;
2788fa790ea9SDavid C Somayajulu }
2789fa790ea9SDavid C Somayajulu
2790fa790ea9SDavid C Somayajulu qp->qp_id = out_params.qp_id;
2791fa790ea9SDavid C Somayajulu qp->icid = out_params.icid;
2792fa790ea9SDavid C Somayajulu
2793fa790ea9SDavid C Somayajulu qlnxr_set_roce_db_info(dev, qp);
2794fa790ea9SDavid C Somayajulu
2795fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2796fa790ea9SDavid C Somayajulu return 0;
2797fa790ea9SDavid C Somayajulu }
2798fa790ea9SDavid C Somayajulu
2799fa790ea9SDavid C Somayajulu static int
qlnxr_iwarp_create_kernel_qp(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct ecore_rdma_create_qp_in_params * in_params,u32 n_sq_elems,u32 n_rq_elems)2800fa790ea9SDavid C Somayajulu qlnxr_iwarp_create_kernel_qp(struct qlnxr_dev *dev,
2801fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
2802fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_in_params *in_params,
2803fa790ea9SDavid C Somayajulu u32 n_sq_elems,
2804fa790ea9SDavid C Somayajulu u32 n_rq_elems)
2805fa790ea9SDavid C Somayajulu {
2806fa790ea9SDavid C Somayajulu struct ecore_rdma_destroy_qp_out_params d_out_params;
2807fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_out_params out_params;
2808fa790ea9SDavid C Somayajulu struct ecore_chain_ext_pbl ext_pbl;
2809fa790ea9SDavid C Somayajulu int rc;
2810fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2811fa790ea9SDavid C Somayajulu
2812fa790ea9SDavid C Somayajulu ha = dev->ha;
2813fa790ea9SDavid C Somayajulu
2814fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2815fa790ea9SDavid C Somayajulu
2816fa790ea9SDavid C Somayajulu in_params->sq_num_pages = ECORE_CHAIN_PAGE_CNT(n_sq_elems,
2817fa790ea9SDavid C Somayajulu QLNXR_SQE_ELEMENT_SIZE,
2818fa790ea9SDavid C Somayajulu ECORE_CHAIN_MODE_PBL);
2819fa790ea9SDavid C Somayajulu in_params->rq_num_pages = ECORE_CHAIN_PAGE_CNT(n_rq_elems,
2820fa790ea9SDavid C Somayajulu QLNXR_RQE_ELEMENT_SIZE,
2821fa790ea9SDavid C Somayajulu ECORE_CHAIN_MODE_PBL);
2822fa790ea9SDavid C Somayajulu
2823fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "n_sq_elems = 0x%x"
2824fa790ea9SDavid C Somayajulu " n_rq_elems = 0x%x in_params\n"
2825fa790ea9SDavid C Somayajulu "\t\t\tqp_handle_lo\t\t= 0x%08x\n"
2826fa790ea9SDavid C Somayajulu "\t\t\tqp_handle_hi\t\t= 0x%08x\n"
2827fa790ea9SDavid C Somayajulu "\t\t\tqp_handle_async_lo\t\t= 0x%08x\n"
2828fa790ea9SDavid C Somayajulu "\t\t\tqp_handle_async_hi\t\t= 0x%08x\n"
2829fa790ea9SDavid C Somayajulu "\t\t\tuse_srq\t\t\t= 0x%x\n"
2830fa790ea9SDavid C Somayajulu "\t\t\tsignal_all\t\t= 0x%x\n"
2831fa790ea9SDavid C Somayajulu "\t\t\tfmr_and_reserved_lkey\t= 0x%x\n"
2832fa790ea9SDavid C Somayajulu "\t\t\tpd\t\t\t= 0x%x\n"
2833fa790ea9SDavid C Somayajulu "\t\t\tdpi\t\t\t= 0x%x\n"
2834fa790ea9SDavid C Somayajulu "\t\t\tsq_cq_id\t\t\t= 0x%x\n"
2835fa790ea9SDavid C Somayajulu "\t\t\tsq_num_pages\t\t= 0x%x\n"
2836fa790ea9SDavid C Somayajulu "\t\t\tsq_pbl_ptr\t\t= %p\n"
2837fa790ea9SDavid C Somayajulu "\t\t\tmax_sq_sges\t\t= 0x%x\n"
2838fa790ea9SDavid C Somayajulu "\t\t\trq_cq_id\t\t\t= 0x%x\n"
2839fa790ea9SDavid C Somayajulu "\t\t\trq_num_pages\t\t= 0x%x\n"
2840fa790ea9SDavid C Somayajulu "\t\t\trq_pbl_ptr\t\t= %p\n"
2841fa790ea9SDavid C Somayajulu "\t\t\tsrq_id\t\t\t= 0x%x\n"
2842fa790ea9SDavid C Somayajulu "\t\t\tstats_queue\t\t= 0x%x\n",
2843fa790ea9SDavid C Somayajulu n_sq_elems, n_rq_elems,
2844fa790ea9SDavid C Somayajulu in_params->qp_handle_lo,
2845fa790ea9SDavid C Somayajulu in_params->qp_handle_hi,
2846fa790ea9SDavid C Somayajulu in_params->qp_handle_async_lo,
2847fa790ea9SDavid C Somayajulu in_params->qp_handle_async_hi,
2848fa790ea9SDavid C Somayajulu in_params->use_srq,
2849fa790ea9SDavid C Somayajulu in_params->signal_all,
2850fa790ea9SDavid C Somayajulu in_params->fmr_and_reserved_lkey,
2851fa790ea9SDavid C Somayajulu in_params->pd,
2852fa790ea9SDavid C Somayajulu in_params->dpi,
2853fa790ea9SDavid C Somayajulu in_params->sq_cq_id,
2854fa790ea9SDavid C Somayajulu in_params->sq_num_pages,
2855fa790ea9SDavid C Somayajulu (void *)in_params->sq_pbl_ptr,
2856fa790ea9SDavid C Somayajulu in_params->max_sq_sges,
2857fa790ea9SDavid C Somayajulu in_params->rq_cq_id,
2858fa790ea9SDavid C Somayajulu in_params->rq_num_pages,
2859fa790ea9SDavid C Somayajulu (void *)in_params->rq_pbl_ptr,
2860fa790ea9SDavid C Somayajulu in_params->srq_id,
2861fa790ea9SDavid C Somayajulu in_params->stats_queue );
2862fa790ea9SDavid C Somayajulu
2863fa790ea9SDavid C Somayajulu memset(&out_params, 0, sizeof (struct ecore_rdma_create_qp_out_params));
2864fa790ea9SDavid C Somayajulu memset(&ext_pbl, 0, sizeof (struct ecore_chain_ext_pbl));
2865fa790ea9SDavid C Somayajulu
2866fa790ea9SDavid C Somayajulu qp->ecore_qp = ecore_rdma_create_qp(dev->rdma_ctx, in_params, &out_params);
2867fa790ea9SDavid C Somayajulu
2868fa790ea9SDavid C Somayajulu if (!qp->ecore_qp) {
2869fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ecore_rdma_create_qp failed\n");
2870fa790ea9SDavid C Somayajulu return -EINVAL;
2871fa790ea9SDavid C Somayajulu }
2872fa790ea9SDavid C Somayajulu
2873fa790ea9SDavid C Somayajulu /* Now we allocate the chain */
2874fa790ea9SDavid C Somayajulu ext_pbl.p_pbl_virt = out_params.sq_pbl_virt;
2875fa790ea9SDavid C Somayajulu ext_pbl.p_pbl_phys = out_params.sq_pbl_phys;
2876fa790ea9SDavid C Somayajulu
2877fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ext_pbl.p_pbl_virt = %p "
2878fa790ea9SDavid C Somayajulu "ext_pbl.p_pbl_phys = %p\n",
2879fa790ea9SDavid C Somayajulu ext_pbl.p_pbl_virt, ext_pbl.p_pbl_phys);
2880fa790ea9SDavid C Somayajulu
2881fa790ea9SDavid C Somayajulu rc = ecore_chain_alloc(
2882fa790ea9SDavid C Somayajulu dev->cdev,
2883fa790ea9SDavid C Somayajulu ECORE_CHAIN_USE_TO_PRODUCE,
2884fa790ea9SDavid C Somayajulu ECORE_CHAIN_MODE_PBL,
2885fa790ea9SDavid C Somayajulu ECORE_CHAIN_CNT_TYPE_U32,
2886fa790ea9SDavid C Somayajulu n_sq_elems,
2887fa790ea9SDavid C Somayajulu QLNXR_SQE_ELEMENT_SIZE,
2888fa790ea9SDavid C Somayajulu &qp->sq.pbl,
2889fa790ea9SDavid C Somayajulu &ext_pbl);
2890fa790ea9SDavid C Somayajulu
2891fa790ea9SDavid C Somayajulu if (rc) {
2892fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,
2893fa790ea9SDavid C Somayajulu "ecore_chain_alloc qp->sq.pbl failed rc = %d\n", rc);
2894fa790ea9SDavid C Somayajulu goto err;
2895fa790ea9SDavid C Somayajulu }
2896fa790ea9SDavid C Somayajulu
2897fa790ea9SDavid C Somayajulu ext_pbl.p_pbl_virt = out_params.rq_pbl_virt;
2898fa790ea9SDavid C Somayajulu ext_pbl.p_pbl_phys = out_params.rq_pbl_phys;
2899fa790ea9SDavid C Somayajulu
2900fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ext_pbl.p_pbl_virt = %p "
2901fa790ea9SDavid C Somayajulu "ext_pbl.p_pbl_phys = %p\n",
2902fa790ea9SDavid C Somayajulu ext_pbl.p_pbl_virt, ext_pbl.p_pbl_phys);
2903fa790ea9SDavid C Somayajulu
2904fa790ea9SDavid C Somayajulu if (!qp->srq) {
2905fa790ea9SDavid C Somayajulu rc = ecore_chain_alloc(
2906fa790ea9SDavid C Somayajulu dev->cdev,
2907fa790ea9SDavid C Somayajulu ECORE_CHAIN_USE_TO_CONSUME_PRODUCE,
2908fa790ea9SDavid C Somayajulu ECORE_CHAIN_MODE_PBL,
2909fa790ea9SDavid C Somayajulu ECORE_CHAIN_CNT_TYPE_U32,
2910fa790ea9SDavid C Somayajulu n_rq_elems,
2911fa790ea9SDavid C Somayajulu QLNXR_RQE_ELEMENT_SIZE,
2912fa790ea9SDavid C Somayajulu &qp->rq.pbl,
2913fa790ea9SDavid C Somayajulu &ext_pbl);
2914fa790ea9SDavid C Somayajulu
2915fa790ea9SDavid C Somayajulu if (rc) {
2916fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,, "ecore_chain_alloc qp->rq.pbl"
2917fa790ea9SDavid C Somayajulu " failed rc = %d\n", rc);
2918fa790ea9SDavid C Somayajulu goto err;
2919fa790ea9SDavid C Somayajulu }
2920fa790ea9SDavid C Somayajulu }
2921fa790ea9SDavid C Somayajulu
2922fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qp_id = 0x%x icid =0x%x\n",
2923fa790ea9SDavid C Somayajulu out_params.qp_id, out_params.icid);
2924fa790ea9SDavid C Somayajulu
2925fa790ea9SDavid C Somayajulu qp->qp_id = out_params.qp_id;
2926fa790ea9SDavid C Somayajulu qp->icid = out_params.icid;
2927fa790ea9SDavid C Somayajulu
2928fa790ea9SDavid C Somayajulu qlnxr_set_iwarp_db_info(dev, qp);
2929fa790ea9SDavid C Somayajulu
2930fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
2931fa790ea9SDavid C Somayajulu return 0;
2932fa790ea9SDavid C Somayajulu
2933fa790ea9SDavid C Somayajulu err:
2934fa790ea9SDavid C Somayajulu ecore_rdma_destroy_qp(dev->rdma_ctx, qp->ecore_qp, &d_out_params);
2935fa790ea9SDavid C Somayajulu
2936fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit rc = %d\n", rc);
2937fa790ea9SDavid C Somayajulu return rc;
2938fa790ea9SDavid C Somayajulu }
2939fa790ea9SDavid C Somayajulu
2940fa790ea9SDavid C Somayajulu static int
qlnxr_create_kernel_qp(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct ib_pd * ibpd,struct ib_qp_init_attr * attrs)2941fa790ea9SDavid C Somayajulu qlnxr_create_kernel_qp(struct qlnxr_dev *dev,
2942fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
2943fa790ea9SDavid C Somayajulu struct ib_pd *ibpd,
2944fa790ea9SDavid C Somayajulu struct ib_qp_init_attr *attrs)
2945fa790ea9SDavid C Somayajulu {
2946fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_in_params in_params;
2947fa790ea9SDavid C Somayajulu struct qlnxr_pd *pd = get_qlnxr_pd(ibpd);
2948fa790ea9SDavid C Somayajulu int rc = -EINVAL;
2949fa790ea9SDavid C Somayajulu u32 n_rq_elems;
2950fa790ea9SDavid C Somayajulu u32 n_sq_elems;
2951fa790ea9SDavid C Somayajulu u32 n_sq_entries;
2952fa790ea9SDavid C Somayajulu struct ecore_rdma_device *qattr = ecore_rdma_query_device(dev->rdma_ctx);
2953fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
2954fa790ea9SDavid C Somayajulu
2955fa790ea9SDavid C Somayajulu ha = dev->ha;
2956fa790ea9SDavid C Somayajulu
2957fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
2958fa790ea9SDavid C Somayajulu
2959fa790ea9SDavid C Somayajulu memset(&in_params, 0, sizeof(in_params));
2960fa790ea9SDavid C Somayajulu
2961fa790ea9SDavid C Somayajulu /* A single work request may take up to MAX_SQ_WQE_SIZE elements in
2962fa790ea9SDavid C Somayajulu * the ring. The ring should allow at least a single WR, even if the
2963fa790ea9SDavid C Somayajulu * user requested none, due to allocation issues.
2964fa790ea9SDavid C Somayajulu * We should add an extra WR since the prod and cons indices of
2965fa790ea9SDavid C Somayajulu * wqe_wr_id are managed in such a way that the WQ is considered full
2966fa790ea9SDavid C Somayajulu * when (prod+1)%max_wr==cons. We currently don't do that because we
2967fa790ea9SDavid C Somayajulu * double the number of entries due an iSER issue that pushes far more
2968fa790ea9SDavid C Somayajulu * WRs than indicated. If we decline its ib_post_send() then we get
2969fa790ea9SDavid C Somayajulu * error prints in the dmesg we'd like to avoid.
2970fa790ea9SDavid C Somayajulu */
2971fa790ea9SDavid C Somayajulu qp->sq.max_wr = min_t(u32, attrs->cap.max_send_wr * dev->wq_multiplier,
2972fa790ea9SDavid C Somayajulu qattr->max_wqe);
2973fa790ea9SDavid C Somayajulu
2974fa790ea9SDavid C Somayajulu qp->wqe_wr_id = kzalloc(qp->sq.max_wr * sizeof(*qp->wqe_wr_id),
2975fa790ea9SDavid C Somayajulu GFP_KERNEL);
2976fa790ea9SDavid C Somayajulu if (!qp->wqe_wr_id) {
2977fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "failed SQ shadow memory allocation\n");
2978fa790ea9SDavid C Somayajulu return -ENOMEM;
2979fa790ea9SDavid C Somayajulu }
2980fa790ea9SDavid C Somayajulu
2981fa790ea9SDavid C Somayajulu /* QP handle to be written in CQE */
2982fa790ea9SDavid C Somayajulu in_params.qp_handle_lo = lower_32_bits((uintptr_t)qp);
2983fa790ea9SDavid C Somayajulu in_params.qp_handle_hi = upper_32_bits((uintptr_t)qp);
2984fa790ea9SDavid C Somayajulu
2985fa790ea9SDavid C Somayajulu /* A single work request may take up to MAX_RQ_WQE_SIZE elements in
2986fa790ea9SDavid C Somayajulu * the ring. There ring should allow at least a single WR, even if the
2987fa790ea9SDavid C Somayajulu * user requested none, due to allocation issues.
2988fa790ea9SDavid C Somayajulu */
2989fa790ea9SDavid C Somayajulu qp->rq.max_wr = (u16)max_t(u32, attrs->cap.max_recv_wr, 1);
2990fa790ea9SDavid C Somayajulu
2991fa790ea9SDavid C Somayajulu /* Allocate driver internal RQ array */
2992fa790ea9SDavid C Somayajulu if (!qp->srq) {
2993fa790ea9SDavid C Somayajulu qp->rqe_wr_id = kzalloc(qp->rq.max_wr * sizeof(*qp->rqe_wr_id),
2994fa790ea9SDavid C Somayajulu GFP_KERNEL);
2995fa790ea9SDavid C Somayajulu if (!qp->rqe_wr_id) {
2996fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "failed RQ shadow memory allocation\n");
2997fa790ea9SDavid C Somayajulu kfree(qp->wqe_wr_id);
2998fa790ea9SDavid C Somayajulu return -ENOMEM;
2999fa790ea9SDavid C Somayajulu }
3000fa790ea9SDavid C Somayajulu }
3001fa790ea9SDavid C Somayajulu
3002fa790ea9SDavid C Somayajulu //qlnxr_init_common_qp_in_params(dev, pd, qp, attrs, true, &in_params);
3003fa790ea9SDavid C Somayajulu
3004fa790ea9SDavid C Somayajulu in_params.qp_handle_async_lo = lower_32_bits((uintptr_t)qp);
3005fa790ea9SDavid C Somayajulu in_params.qp_handle_async_hi = upper_32_bits((uintptr_t)qp);
3006fa790ea9SDavid C Somayajulu
3007fa790ea9SDavid C Somayajulu in_params.signal_all = (attrs->sq_sig_type == IB_SIGNAL_ALL_WR);
3008fa790ea9SDavid C Somayajulu in_params.fmr_and_reserved_lkey = true;
3009fa790ea9SDavid C Somayajulu in_params.pd = pd->pd_id;
3010fa790ea9SDavid C Somayajulu in_params.dpi = pd->uctx ? pd->uctx->dpi : dev->dpi;
3011fa790ea9SDavid C Somayajulu in_params.sq_cq_id = get_qlnxr_cq(attrs->send_cq)->icid;
3012fa790ea9SDavid C Somayajulu in_params.stats_queue = 0;
3013fa790ea9SDavid C Somayajulu
3014fa790ea9SDavid C Somayajulu in_params.rq_cq_id = get_qlnxr_cq(attrs->recv_cq)->icid;
3015fa790ea9SDavid C Somayajulu
3016fa790ea9SDavid C Somayajulu if (qp->srq) {
3017fa790ea9SDavid C Somayajulu /* QP is associated with SRQ instead of RQ */
3018fa790ea9SDavid C Somayajulu in_params.srq_id = qp->srq->srq_id;
3019fa790ea9SDavid C Somayajulu in_params.use_srq = true;
3020fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "exit srq_id = 0x%x use_srq = 0x%x\n",
3021fa790ea9SDavid C Somayajulu in_params.srq_id, in_params.use_srq);
3022fa790ea9SDavid C Somayajulu } else {
3023fa790ea9SDavid C Somayajulu in_params.srq_id = 0;
3024fa790ea9SDavid C Somayajulu in_params.use_srq = false;
3025fa790ea9SDavid C Somayajulu }
3026fa790ea9SDavid C Somayajulu
3027fa790ea9SDavid C Somayajulu n_sq_entries = attrs->cap.max_send_wr;
3028fa790ea9SDavid C Somayajulu n_sq_entries = min_t(u32, n_sq_entries, qattr->max_wqe);
3029fa790ea9SDavid C Somayajulu n_sq_entries = max_t(u32, n_sq_entries, 1);
3030fa790ea9SDavid C Somayajulu n_sq_elems = n_sq_entries * QLNXR_MAX_SQE_ELEMENTS_PER_SQE;
3031fa790ea9SDavid C Somayajulu
3032fa790ea9SDavid C Somayajulu n_rq_elems = qp->rq.max_wr * QLNXR_MAX_RQE_ELEMENTS_PER_RQE;
3033fa790ea9SDavid C Somayajulu
3034fa790ea9SDavid C Somayajulu if (QLNX_IS_ROCE(dev)) {
3035fa790ea9SDavid C Somayajulu rc = qlnxr_roce_create_kernel_qp(dev, qp, &in_params,
3036fa790ea9SDavid C Somayajulu n_sq_elems, n_rq_elems);
3037fa790ea9SDavid C Somayajulu } else {
3038fa790ea9SDavid C Somayajulu rc = qlnxr_iwarp_create_kernel_qp(dev, qp, &in_params,
3039fa790ea9SDavid C Somayajulu n_sq_elems, n_rq_elems);
3040fa790ea9SDavid C Somayajulu }
3041fa790ea9SDavid C Somayajulu
3042fa790ea9SDavid C Somayajulu if (rc)
3043fa790ea9SDavid C Somayajulu qlnxr_cleanup_kernel(dev, qp);
3044fa790ea9SDavid C Somayajulu
3045fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
3046fa790ea9SDavid C Somayajulu return rc;
3047fa790ea9SDavid C Somayajulu }
3048fa790ea9SDavid C Somayajulu
3049fa790ea9SDavid C Somayajulu struct ib_qp *
qlnxr_create_qp(struct ib_pd * ibpd,struct ib_qp_init_attr * attrs,struct ib_udata * udata)3050fa790ea9SDavid C Somayajulu qlnxr_create_qp(struct ib_pd *ibpd,
3051fa790ea9SDavid C Somayajulu struct ib_qp_init_attr *attrs,
3052fa790ea9SDavid C Somayajulu struct ib_udata *udata)
3053fa790ea9SDavid C Somayajulu {
3054fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev(ibpd->device);
3055fa790ea9SDavid C Somayajulu struct qlnxr_pd *pd = get_qlnxr_pd(ibpd);
3056fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp;
3057fa790ea9SDavid C Somayajulu int rc = 0;
3058fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
3059fa790ea9SDavid C Somayajulu
3060fa790ea9SDavid C Somayajulu ha = dev->ha;
3061fa790ea9SDavid C Somayajulu
3062fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
3063fa790ea9SDavid C Somayajulu
3064fa790ea9SDavid C Somayajulu rc = qlnxr_check_qp_attrs(ibpd, dev, attrs, udata);
3065fa790ea9SDavid C Somayajulu if (rc) {
3066fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_check_qp_attrs failed [%d]\n", rc);
3067fa790ea9SDavid C Somayajulu return ERR_PTR(rc);
3068fa790ea9SDavid C Somayajulu }
3069fa790ea9SDavid C Somayajulu
3070fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "called from %s, event_handle=%p,"
3071fa790ea9SDavid C Somayajulu " eepd=%p sq_cq=%p, sq_icid=%d, rq_cq=%p, rq_icid=%d\n",
3072fa790ea9SDavid C Somayajulu (udata ? "user library" : "kernel"),
3073fa790ea9SDavid C Somayajulu attrs->event_handler, pd,
3074fa790ea9SDavid C Somayajulu get_qlnxr_cq(attrs->send_cq),
3075fa790ea9SDavid C Somayajulu get_qlnxr_cq(attrs->send_cq)->icid,
3076fa790ea9SDavid C Somayajulu get_qlnxr_cq(attrs->recv_cq),
3077fa790ea9SDavid C Somayajulu get_qlnxr_cq(attrs->recv_cq)->icid);
3078fa790ea9SDavid C Somayajulu
3079fa790ea9SDavid C Somayajulu qp = qlnx_zalloc(sizeof(struct qlnxr_qp));
3080fa790ea9SDavid C Somayajulu
3081fa790ea9SDavid C Somayajulu if (!qp) {
3082fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "kzalloc(qp) failed\n");
3083fa790ea9SDavid C Somayajulu return ERR_PTR(-ENOMEM);
3084fa790ea9SDavid C Somayajulu }
3085fa790ea9SDavid C Somayajulu
3086fa790ea9SDavid C Somayajulu qlnxr_set_common_qp_params(dev, qp, pd, attrs);
3087fa790ea9SDavid C Somayajulu
3088fa790ea9SDavid C Somayajulu if (attrs->qp_type == IB_QPT_GSI) {
3089fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "calling qlnxr_create_gsi_qp\n");
3090fa790ea9SDavid C Somayajulu return qlnxr_create_gsi_qp(dev, attrs, qp);
3091fa790ea9SDavid C Somayajulu }
3092fa790ea9SDavid C Somayajulu
3093fa790ea9SDavid C Somayajulu if (udata) {
3094fa790ea9SDavid C Somayajulu rc = qlnxr_create_user_qp(dev, qp, ibpd, udata, attrs);
3095fa790ea9SDavid C Somayajulu
3096fa790ea9SDavid C Somayajulu if (rc) {
3097fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_create_user_qp failed\n");
3098fa790ea9SDavid C Somayajulu goto err;
3099fa790ea9SDavid C Somayajulu }
3100fa790ea9SDavid C Somayajulu } else {
3101fa790ea9SDavid C Somayajulu rc = qlnxr_create_kernel_qp(dev, qp, ibpd, attrs);
3102fa790ea9SDavid C Somayajulu
3103fa790ea9SDavid C Somayajulu if (rc) {
3104fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_create_kernel_qp failed\n");
3105fa790ea9SDavid C Somayajulu goto err;
3106fa790ea9SDavid C Somayajulu }
3107fa790ea9SDavid C Somayajulu }
3108fa790ea9SDavid C Somayajulu
3109fa790ea9SDavid C Somayajulu qp->ibqp.qp_num = qp->qp_id;
3110fa790ea9SDavid C Somayajulu
3111fa790ea9SDavid C Somayajulu rc = qlnxr_idr_add(dev, qp, qp->qp_id);
3112fa790ea9SDavid C Somayajulu
3113fa790ea9SDavid C Somayajulu if (rc) {
3114fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_idr_add failed\n");
3115fa790ea9SDavid C Somayajulu goto err;
3116fa790ea9SDavid C Somayajulu }
3117fa790ea9SDavid C Somayajulu
3118fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%p]\n", &qp->ibqp);
3119fa790ea9SDavid C Somayajulu
3120fa790ea9SDavid C Somayajulu return &qp->ibqp;
3121fa790ea9SDavid C Somayajulu err:
3122fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "failed exit\n");
3123fa790ea9SDavid C Somayajulu return ERR_PTR(-EFAULT);
3124fa790ea9SDavid C Somayajulu }
3125fa790ea9SDavid C Somayajulu
3126fa790ea9SDavid C Somayajulu static enum ib_qp_state
qlnxr_get_ibqp_state(enum ecore_roce_qp_state qp_state)3127fa790ea9SDavid C Somayajulu qlnxr_get_ibqp_state(enum ecore_roce_qp_state qp_state)
3128fa790ea9SDavid C Somayajulu {
3129fa790ea9SDavid C Somayajulu enum ib_qp_state state = IB_QPS_ERR;
3130fa790ea9SDavid C Somayajulu
3131fa790ea9SDavid C Somayajulu switch (qp_state) {
3132fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RESET:
3133fa790ea9SDavid C Somayajulu state = IB_QPS_RESET;
3134fa790ea9SDavid C Somayajulu break;
3135fa790ea9SDavid C Somayajulu
3136fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_INIT:
3137fa790ea9SDavid C Somayajulu state = IB_QPS_INIT;
3138fa790ea9SDavid C Somayajulu break;
3139fa790ea9SDavid C Somayajulu
3140fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RTR:
3141fa790ea9SDavid C Somayajulu state = IB_QPS_RTR;
3142fa790ea9SDavid C Somayajulu break;
3143fa790ea9SDavid C Somayajulu
3144fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RTS:
3145fa790ea9SDavid C Somayajulu state = IB_QPS_RTS;
3146fa790ea9SDavid C Somayajulu break;
3147fa790ea9SDavid C Somayajulu
3148fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_SQD:
3149fa790ea9SDavid C Somayajulu state = IB_QPS_SQD;
3150fa790ea9SDavid C Somayajulu break;
3151fa790ea9SDavid C Somayajulu
3152fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_ERR:
3153fa790ea9SDavid C Somayajulu state = IB_QPS_ERR;
3154fa790ea9SDavid C Somayajulu break;
3155fa790ea9SDavid C Somayajulu
3156fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_SQE:
3157fa790ea9SDavid C Somayajulu state = IB_QPS_SQE;
3158fa790ea9SDavid C Somayajulu break;
3159fa790ea9SDavid C Somayajulu }
3160fa790ea9SDavid C Somayajulu return state;
3161fa790ea9SDavid C Somayajulu }
3162fa790ea9SDavid C Somayajulu
3163fa790ea9SDavid C Somayajulu static enum ecore_roce_qp_state
qlnxr_get_state_from_ibqp(enum ib_qp_state qp_state)3164fa790ea9SDavid C Somayajulu qlnxr_get_state_from_ibqp( enum ib_qp_state qp_state)
3165fa790ea9SDavid C Somayajulu {
3166fa790ea9SDavid C Somayajulu enum ecore_roce_qp_state ecore_qp_state;
3167fa790ea9SDavid C Somayajulu
3168fa790ea9SDavid C Somayajulu ecore_qp_state = ECORE_ROCE_QP_STATE_ERR;
3169fa790ea9SDavid C Somayajulu
3170fa790ea9SDavid C Somayajulu switch (qp_state) {
3171fa790ea9SDavid C Somayajulu case IB_QPS_RESET:
3172fa790ea9SDavid C Somayajulu ecore_qp_state = ECORE_ROCE_QP_STATE_RESET;
3173fa790ea9SDavid C Somayajulu break;
3174fa790ea9SDavid C Somayajulu
3175fa790ea9SDavid C Somayajulu case IB_QPS_INIT:
3176fa790ea9SDavid C Somayajulu ecore_qp_state = ECORE_ROCE_QP_STATE_INIT;
3177fa790ea9SDavid C Somayajulu break;
3178fa790ea9SDavid C Somayajulu
3179fa790ea9SDavid C Somayajulu case IB_QPS_RTR:
3180fa790ea9SDavid C Somayajulu ecore_qp_state = ECORE_ROCE_QP_STATE_RTR;
3181fa790ea9SDavid C Somayajulu break;
3182fa790ea9SDavid C Somayajulu
3183fa790ea9SDavid C Somayajulu case IB_QPS_RTS:
3184fa790ea9SDavid C Somayajulu ecore_qp_state = ECORE_ROCE_QP_STATE_RTS;
3185fa790ea9SDavid C Somayajulu break;
3186fa790ea9SDavid C Somayajulu
3187fa790ea9SDavid C Somayajulu case IB_QPS_SQD:
3188fa790ea9SDavid C Somayajulu ecore_qp_state = ECORE_ROCE_QP_STATE_SQD;
3189fa790ea9SDavid C Somayajulu break;
3190fa790ea9SDavid C Somayajulu
3191fa790ea9SDavid C Somayajulu case IB_QPS_ERR:
3192fa790ea9SDavid C Somayajulu ecore_qp_state = ECORE_ROCE_QP_STATE_ERR;
3193fa790ea9SDavid C Somayajulu break;
3194fa790ea9SDavid C Somayajulu
3195fa790ea9SDavid C Somayajulu default:
3196fa790ea9SDavid C Somayajulu ecore_qp_state = ECORE_ROCE_QP_STATE_ERR;
3197fa790ea9SDavid C Somayajulu break;
3198fa790ea9SDavid C Somayajulu }
3199fa790ea9SDavid C Somayajulu
3200fa790ea9SDavid C Somayajulu return (ecore_qp_state);
3201fa790ea9SDavid C Somayajulu }
3202fa790ea9SDavid C Somayajulu
3203fa790ea9SDavid C Somayajulu static void
qlnxr_reset_qp_hwq_info(struct qlnxr_qp_hwq_info * qph)3204fa790ea9SDavid C Somayajulu qlnxr_reset_qp_hwq_info(struct qlnxr_qp_hwq_info *qph)
3205fa790ea9SDavid C Somayajulu {
3206fa790ea9SDavid C Somayajulu ecore_chain_reset(&qph->pbl);
3207fa790ea9SDavid C Somayajulu qph->prod = qph->cons = 0;
3208fa790ea9SDavid C Somayajulu qph->wqe_cons = 0;
3209fa790ea9SDavid C Somayajulu qph->db_data.data.value = cpu_to_le16(0);
3210fa790ea9SDavid C Somayajulu
3211fa790ea9SDavid C Somayajulu return;
3212fa790ea9SDavid C Somayajulu }
3213fa790ea9SDavid C Somayajulu
3214fa790ea9SDavid C Somayajulu static int
qlnxr_update_qp_state(struct qlnxr_dev * dev,struct qlnxr_qp * qp,enum ecore_roce_qp_state new_state)3215fa790ea9SDavid C Somayajulu qlnxr_update_qp_state(struct qlnxr_dev *dev,
3216fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
3217fa790ea9SDavid C Somayajulu enum ecore_roce_qp_state new_state)
3218fa790ea9SDavid C Somayajulu {
3219fa790ea9SDavid C Somayajulu int status = 0;
3220fa790ea9SDavid C Somayajulu uint32_t reg_addr;
3221fa790ea9SDavid C Somayajulu struct ecore_dev *cdev;
3222fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
3223fa790ea9SDavid C Somayajulu
3224fa790ea9SDavid C Somayajulu ha = dev->ha;
3225fa790ea9SDavid C Somayajulu cdev = &ha->cdev;
3226fa790ea9SDavid C Somayajulu
3227fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter qp = %p new_state = 0x%x qp->state = 0x%x\n",
3228fa790ea9SDavid C Somayajulu qp, new_state, qp->state);
3229fa790ea9SDavid C Somayajulu
3230fa790ea9SDavid C Somayajulu if (new_state == qp->state) {
3231fa790ea9SDavid C Somayajulu return 0;
3232fa790ea9SDavid C Somayajulu }
3233fa790ea9SDavid C Somayajulu
3234fa790ea9SDavid C Somayajulu switch (qp->state) {
3235fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RESET:
3236fa790ea9SDavid C Somayajulu switch (new_state) {
3237fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_INIT:
3238fa790ea9SDavid C Somayajulu qp->prev_wqe_size = 0;
3239fa790ea9SDavid C Somayajulu qlnxr_reset_qp_hwq_info(&qp->sq);
3240fa790ea9SDavid C Somayajulu if (!(qp->srq))
3241fa790ea9SDavid C Somayajulu qlnxr_reset_qp_hwq_info(&qp->rq);
3242fa790ea9SDavid C Somayajulu break;
3243fa790ea9SDavid C Somayajulu default:
3244fa790ea9SDavid C Somayajulu status = -EINVAL;
3245fa790ea9SDavid C Somayajulu break;
3246fa790ea9SDavid C Somayajulu };
3247fa790ea9SDavid C Somayajulu break;
3248fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_INIT:
3249fa790ea9SDavid C Somayajulu /* INIT->XXX */
3250fa790ea9SDavid C Somayajulu switch (new_state) {
3251fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RTR:
3252fa790ea9SDavid C Somayajulu /* Update doorbell (in case post_recv was done before move to RTR) */
3253fa790ea9SDavid C Somayajulu if (qp->srq)
3254fa790ea9SDavid C Somayajulu break;
3255fa790ea9SDavid C Somayajulu wmb();
3256fa790ea9SDavid C Somayajulu //writel(qp->rq.db_data.raw, qp->rq.db);
3257fa790ea9SDavid C Somayajulu //if (QLNX_IS_IWARP(dev))
3258fa790ea9SDavid C Somayajulu // writel(qp->rq.iwarp_db2_data.raw,
3259fa790ea9SDavid C Somayajulu // qp->rq.iwarp_db2);
3260fa790ea9SDavid C Somayajulu
3261fa790ea9SDavid C Somayajulu reg_addr = (uint32_t)((uint8_t *)qp->rq.db -
3262fa790ea9SDavid C Somayajulu (uint8_t *)cdev->doorbells);
3263fa790ea9SDavid C Somayajulu
3264fa790ea9SDavid C Somayajulu bus_write_4(ha->pci_dbells, reg_addr, qp->rq.db_data.raw);
3265fa790ea9SDavid C Somayajulu bus_barrier(ha->pci_dbells, 0, 0, BUS_SPACE_BARRIER_READ);
3266fa790ea9SDavid C Somayajulu
3267fa790ea9SDavid C Somayajulu if (QLNX_IS_IWARP(dev)) {
3268fa790ea9SDavid C Somayajulu reg_addr = (uint32_t)((uint8_t *)qp->rq.iwarp_db2 -
3269fa790ea9SDavid C Somayajulu (uint8_t *)cdev->doorbells);
3270fa790ea9SDavid C Somayajulu bus_write_4(ha->pci_dbells, reg_addr,\
3271fa790ea9SDavid C Somayajulu qp->rq.iwarp_db2_data.raw);
3272fa790ea9SDavid C Somayajulu bus_barrier(ha->pci_dbells, 0, 0,\
3273fa790ea9SDavid C Somayajulu BUS_SPACE_BARRIER_READ);
3274fa790ea9SDavid C Somayajulu }
3275fa790ea9SDavid C Somayajulu
3276fa790ea9SDavid C Somayajulu
3277fa790ea9SDavid C Somayajulu mmiowb();
3278fa790ea9SDavid C Somayajulu break;
3279fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_ERR:
3280fa790ea9SDavid C Somayajulu /* TBD:flush qps... */
3281fa790ea9SDavid C Somayajulu break;
3282fa790ea9SDavid C Somayajulu default:
3283fa790ea9SDavid C Somayajulu /* invalid state change. */
3284fa790ea9SDavid C Somayajulu status = -EINVAL;
3285fa790ea9SDavid C Somayajulu break;
3286fa790ea9SDavid C Somayajulu };
3287fa790ea9SDavid C Somayajulu break;
3288fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RTR:
3289fa790ea9SDavid C Somayajulu /* RTR->XXX */
3290fa790ea9SDavid C Somayajulu switch (new_state) {
3291fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RTS:
3292fa790ea9SDavid C Somayajulu break;
3293fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_ERR:
3294fa790ea9SDavid C Somayajulu break;
3295fa790ea9SDavid C Somayajulu default:
3296fa790ea9SDavid C Somayajulu /* invalid state change. */
3297fa790ea9SDavid C Somayajulu status = -EINVAL;
3298fa790ea9SDavid C Somayajulu break;
3299fa790ea9SDavid C Somayajulu };
3300fa790ea9SDavid C Somayajulu break;
3301fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RTS:
3302fa790ea9SDavid C Somayajulu /* RTS->XXX */
3303fa790ea9SDavid C Somayajulu switch (new_state) {
3304fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_SQD:
3305fa790ea9SDavid C Somayajulu break;
3306fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_ERR:
3307fa790ea9SDavid C Somayajulu break;
3308fa790ea9SDavid C Somayajulu default:
3309fa790ea9SDavid C Somayajulu /* invalid state change. */
3310fa790ea9SDavid C Somayajulu status = -EINVAL;
3311fa790ea9SDavid C Somayajulu break;
3312fa790ea9SDavid C Somayajulu };
3313fa790ea9SDavid C Somayajulu break;
3314fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_SQD:
3315fa790ea9SDavid C Somayajulu /* SQD->XXX */
3316fa790ea9SDavid C Somayajulu switch (new_state) {
3317fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RTS:
3318fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_ERR:
3319fa790ea9SDavid C Somayajulu break;
3320fa790ea9SDavid C Somayajulu default:
3321fa790ea9SDavid C Somayajulu /* invalid state change. */
3322fa790ea9SDavid C Somayajulu status = -EINVAL;
3323fa790ea9SDavid C Somayajulu break;
3324fa790ea9SDavid C Somayajulu };
3325fa790ea9SDavid C Somayajulu break;
3326fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_ERR:
3327fa790ea9SDavid C Somayajulu /* ERR->XXX */
3328fa790ea9SDavid C Somayajulu switch (new_state) {
3329fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RESET:
3330fa790ea9SDavid C Somayajulu if ((qp->rq.prod != qp->rq.cons) ||
3331fa790ea9SDavid C Somayajulu (qp->sq.prod != qp->sq.cons)) {
3332fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,
3333fa790ea9SDavid C Somayajulu "Error->Reset with rq/sq "
3334fa790ea9SDavid C Somayajulu "not empty rq.prod=0x%x rq.cons=0x%x"
3335fa790ea9SDavid C Somayajulu " sq.prod=0x%x sq.cons=0x%x\n",
3336fa790ea9SDavid C Somayajulu qp->rq.prod, qp->rq.cons,
3337fa790ea9SDavid C Somayajulu qp->sq.prod, qp->sq.cons);
3338fa790ea9SDavid C Somayajulu status = -EINVAL;
3339fa790ea9SDavid C Somayajulu }
3340fa790ea9SDavid C Somayajulu break;
3341fa790ea9SDavid C Somayajulu default:
3342fa790ea9SDavid C Somayajulu status = -EINVAL;
3343fa790ea9SDavid C Somayajulu break;
3344fa790ea9SDavid C Somayajulu };
3345fa790ea9SDavid C Somayajulu break;
3346fa790ea9SDavid C Somayajulu default:
3347fa790ea9SDavid C Somayajulu status = -EINVAL;
3348fa790ea9SDavid C Somayajulu break;
3349fa790ea9SDavid C Somayajulu };
3350fa790ea9SDavid C Somayajulu
3351fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
3352fa790ea9SDavid C Somayajulu return status;
3353fa790ea9SDavid C Somayajulu }
3354fa790ea9SDavid C Somayajulu
3355fa790ea9SDavid C Somayajulu int
qlnxr_modify_qp(struct ib_qp * ibqp,struct ib_qp_attr * attr,int attr_mask,struct ib_udata * udata)3356fa790ea9SDavid C Somayajulu qlnxr_modify_qp(struct ib_qp *ibqp,
3357fa790ea9SDavid C Somayajulu struct ib_qp_attr *attr,
3358fa790ea9SDavid C Somayajulu int attr_mask,
3359fa790ea9SDavid C Somayajulu struct ib_udata *udata)
3360fa790ea9SDavid C Somayajulu {
3361fa790ea9SDavid C Somayajulu int rc = 0;
3362fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp = get_qlnxr_qp(ibqp);
3363fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev(&qp->dev->ibdev);
3364fa790ea9SDavid C Somayajulu struct ecore_rdma_modify_qp_in_params qp_params = { 0 };
3365fa790ea9SDavid C Somayajulu enum ib_qp_state old_qp_state, new_qp_state;
3366fa790ea9SDavid C Somayajulu struct ecore_rdma_device *qattr = ecore_rdma_query_device(dev->rdma_ctx);
3367fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
3368fa790ea9SDavid C Somayajulu
3369fa790ea9SDavid C Somayajulu ha = dev->ha;
3370fa790ea9SDavid C Somayajulu
3371fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
3372fa790ea9SDavid C Somayajulu "enter qp = %p attr_mask = 0x%x, state = %d udata = %p\n",
3373fa790ea9SDavid C Somayajulu qp, attr_mask, attr->qp_state, udata);
3374fa790ea9SDavid C Somayajulu
3375fa790ea9SDavid C Somayajulu old_qp_state = qlnxr_get_ibqp_state(qp->state);
3376fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_STATE)
3377fa790ea9SDavid C Somayajulu new_qp_state = attr->qp_state;
3378fa790ea9SDavid C Somayajulu else
3379fa790ea9SDavid C Somayajulu new_qp_state = old_qp_state;
3380fa790ea9SDavid C Somayajulu
3381fa790ea9SDavid C Somayajulu if (QLNX_IS_ROCE(dev)) {
3382fa790ea9SDavid C Somayajulu if (!ib_modify_qp_is_ok(old_qp_state,
3383fa790ea9SDavid C Somayajulu new_qp_state,
3384fa790ea9SDavid C Somayajulu ibqp->qp_type,
3385fa790ea9SDavid C Somayajulu attr_mask )) {
3386fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
3387fa790ea9SDavid C Somayajulu "invalid attribute mask=0x%x"
3388fa790ea9SDavid C Somayajulu " specified for qpn=0x%x of type=0x%x \n"
3389fa790ea9SDavid C Somayajulu " old_qp_state=0x%x, new_qp_state=0x%x\n",
3390fa790ea9SDavid C Somayajulu attr_mask, qp->qp_id, ibqp->qp_type,
3391fa790ea9SDavid C Somayajulu old_qp_state, new_qp_state);
3392fa790ea9SDavid C Somayajulu rc = -EINVAL;
3393fa790ea9SDavid C Somayajulu goto err;
3394fa790ea9SDavid C Somayajulu }
3395fa790ea9SDavid C Somayajulu }
3396fa790ea9SDavid C Somayajulu /* translate the masks... */
3397fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_STATE) {
3398fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3399fa790ea9SDavid C Somayajulu ECORE_RDMA_MODIFY_QP_VALID_NEW_STATE, 1);
3400fa790ea9SDavid C Somayajulu qp_params.new_state = qlnxr_get_state_from_ibqp(attr->qp_state);
3401fa790ea9SDavid C Somayajulu }
3402fa790ea9SDavid C Somayajulu
3403fa790ea9SDavid C Somayajulu // TBD consider changing ecore to be a flag as well...
3404fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY)
3405fa790ea9SDavid C Somayajulu qp_params.sqd_async = true;
3406fa790ea9SDavid C Somayajulu
3407fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_PKEY_INDEX) {
3408fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3409fa790ea9SDavid C Somayajulu ECORE_ROCE_MODIFY_QP_VALID_PKEY,
3410fa790ea9SDavid C Somayajulu 1);
3411fa790ea9SDavid C Somayajulu if (attr->pkey_index >= QLNXR_ROCE_PKEY_TABLE_LEN) {
3412fa790ea9SDavid C Somayajulu rc = -EINVAL;
3413fa790ea9SDavid C Somayajulu goto err;
3414fa790ea9SDavid C Somayajulu }
3415fa790ea9SDavid C Somayajulu
3416fa790ea9SDavid C Somayajulu qp_params.pkey = QLNXR_ROCE_PKEY_DEFAULT;
3417fa790ea9SDavid C Somayajulu }
3418fa790ea9SDavid C Somayajulu
3419fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_QKEY) {
3420fa790ea9SDavid C Somayajulu qp->qkey = attr->qkey;
3421fa790ea9SDavid C Somayajulu }
3422fa790ea9SDavid C Somayajulu
3423fa790ea9SDavid C Somayajulu /* tbd consider splitting in ecore.. */
3424fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_ACCESS_FLAGS) {
3425fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3426fa790ea9SDavid C Somayajulu ECORE_RDMA_MODIFY_QP_VALID_RDMA_OPS_EN, 1);
3427fa790ea9SDavid C Somayajulu qp_params.incoming_rdma_read_en =
3428fa790ea9SDavid C Somayajulu attr->qp_access_flags & IB_ACCESS_REMOTE_READ;
3429fa790ea9SDavid C Somayajulu qp_params.incoming_rdma_write_en =
3430fa790ea9SDavid C Somayajulu attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE;
3431fa790ea9SDavid C Somayajulu qp_params.incoming_atomic_en =
3432fa790ea9SDavid C Somayajulu attr->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC;
3433fa790ea9SDavid C Somayajulu }
3434fa790ea9SDavid C Somayajulu
3435fa790ea9SDavid C Somayajulu if (attr_mask & (IB_QP_AV | IB_QP_PATH_MTU)) {
3436fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_PATH_MTU) {
3437fa790ea9SDavid C Somayajulu if (attr->path_mtu < IB_MTU_256 ||
3438fa790ea9SDavid C Somayajulu attr->path_mtu > IB_MTU_4096) {
3439fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
3440fa790ea9SDavid C Somayajulu "Only MTU sizes of 256, 512, 1024,"
3441fa790ea9SDavid C Somayajulu " 2048 and 4096 are supported "
3442fa790ea9SDavid C Somayajulu " attr->path_mtu = [%d]\n",
3443fa790ea9SDavid C Somayajulu attr->path_mtu);
3444fa790ea9SDavid C Somayajulu
3445fa790ea9SDavid C Somayajulu rc = -EINVAL;
3446fa790ea9SDavid C Somayajulu goto err;
3447fa790ea9SDavid C Somayajulu }
3448fa790ea9SDavid C Somayajulu qp->mtu = min(ib_mtu_enum_to_int(attr->path_mtu),
3449fa790ea9SDavid C Somayajulu ib_mtu_enum_to_int(
3450*727bfe38SJustin Hibbits iboe_get_mtu(if_getmtu(dev->ha->ifp))));
3451fa790ea9SDavid C Somayajulu }
3452fa790ea9SDavid C Somayajulu
3453fa790ea9SDavid C Somayajulu if (qp->mtu == 0) {
3454fa790ea9SDavid C Somayajulu qp->mtu = ib_mtu_enum_to_int(
3455*727bfe38SJustin Hibbits iboe_get_mtu(if_getmtu(dev->ha->ifp)));
3456fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "fixing zetoed MTU to qp->mtu = %d\n",
3457fa790ea9SDavid C Somayajulu qp->mtu);
3458fa790ea9SDavid C Somayajulu }
3459fa790ea9SDavid C Somayajulu
3460fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3461fa790ea9SDavid C Somayajulu ECORE_ROCE_MODIFY_QP_VALID_ADDRESS_VECTOR,
3462fa790ea9SDavid C Somayajulu 1);
3463fa790ea9SDavid C Somayajulu
3464fa790ea9SDavid C Somayajulu qp_params.traffic_class_tos = attr->ah_attr.grh.traffic_class;
3465fa790ea9SDavid C Somayajulu qp_params.flow_label = attr->ah_attr.grh.flow_label;
3466fa790ea9SDavid C Somayajulu qp_params.hop_limit_ttl = attr->ah_attr.grh.hop_limit;
3467fa790ea9SDavid C Somayajulu
3468fa790ea9SDavid C Somayajulu qp->sgid_idx = attr->ah_attr.grh.sgid_index;
3469fa790ea9SDavid C Somayajulu
3470fa790ea9SDavid C Somayajulu get_gid_info(ibqp, attr, attr_mask, dev, qp, &qp_params);
3471fa790ea9SDavid C Somayajulu
3472fa790ea9SDavid C Somayajulu rc = qlnxr_get_dmac(dev, &attr->ah_attr, qp_params.remote_mac_addr);
3473fa790ea9SDavid C Somayajulu if (rc)
3474fa790ea9SDavid C Somayajulu return rc;
3475fa790ea9SDavid C Somayajulu
3476fa790ea9SDavid C Somayajulu qp_params.use_local_mac = true;
3477fa790ea9SDavid C Somayajulu memcpy(qp_params.local_mac_addr, dev->ha->primary_mac, ETH_ALEN);
3478fa790ea9SDavid C Somayajulu
3479fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "dgid=0x%x:0x%x:0x%x:0x%x\n",
3480fa790ea9SDavid C Somayajulu qp_params.dgid.dwords[0], qp_params.dgid.dwords[1],
3481fa790ea9SDavid C Somayajulu qp_params.dgid.dwords[2], qp_params.dgid.dwords[3]);
3482fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "sgid=0x%x:0x%x:0x%x:0x%x\n",
3483fa790ea9SDavid C Somayajulu qp_params.sgid.dwords[0], qp_params.sgid.dwords[1],
3484fa790ea9SDavid C Somayajulu qp_params.sgid.dwords[2], qp_params.sgid.dwords[3]);
3485fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
3486fa790ea9SDavid C Somayajulu "remote_mac=[0x%x:0x%x:0x%x:0x%x:0x%x:0x%x]\n",
3487fa790ea9SDavid C Somayajulu qp_params.remote_mac_addr[0],
3488fa790ea9SDavid C Somayajulu qp_params.remote_mac_addr[1],
3489fa790ea9SDavid C Somayajulu qp_params.remote_mac_addr[2],
3490fa790ea9SDavid C Somayajulu qp_params.remote_mac_addr[3],
3491fa790ea9SDavid C Somayajulu qp_params.remote_mac_addr[4],
3492fa790ea9SDavid C Somayajulu qp_params.remote_mac_addr[5]);
3493fa790ea9SDavid C Somayajulu
3494fa790ea9SDavid C Somayajulu qp_params.mtu = qp->mtu;
3495fa790ea9SDavid C Somayajulu }
3496fa790ea9SDavid C Somayajulu
3497fa790ea9SDavid C Somayajulu if (qp_params.mtu == 0) {
3498fa790ea9SDavid C Somayajulu /* stay with current MTU */
3499fa790ea9SDavid C Somayajulu if (qp->mtu) {
3500fa790ea9SDavid C Somayajulu qp_params.mtu = qp->mtu;
3501fa790ea9SDavid C Somayajulu } else {
3502fa790ea9SDavid C Somayajulu qp_params.mtu = ib_mtu_enum_to_int(
3503*727bfe38SJustin Hibbits iboe_get_mtu(if_getmtu(dev->ha->ifp)));
3504fa790ea9SDavid C Somayajulu }
3505fa790ea9SDavid C Somayajulu }
3506fa790ea9SDavid C Somayajulu
3507fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_TIMEOUT) {
3508fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags, \
3509fa790ea9SDavid C Somayajulu ECORE_ROCE_MODIFY_QP_VALID_ACK_TIMEOUT, 1);
3510fa790ea9SDavid C Somayajulu
3511fa790ea9SDavid C Somayajulu qp_params.ack_timeout = attr->timeout;
3512fa790ea9SDavid C Somayajulu if (attr->timeout) {
3513fa790ea9SDavid C Somayajulu u32 temp;
3514fa790ea9SDavid C Somayajulu
3515fa790ea9SDavid C Somayajulu /* 12.7.34 LOCAL ACK TIMEOUT
3516fa790ea9SDavid C Somayajulu * Value representing the transport (ACK) timeout for
3517fa790ea9SDavid C Somayajulu * use by the remote, expressed as (4.096 μS*2Local ACK
3518fa790ea9SDavid C Somayajulu * Timeout)
3519fa790ea9SDavid C Somayajulu */
3520fa790ea9SDavid C Somayajulu /* We use 1UL since the temporal value may be overflow
3521fa790ea9SDavid C Somayajulu * 32 bits
3522fa790ea9SDavid C Somayajulu */
3523fa790ea9SDavid C Somayajulu temp = 4096 * (1UL << attr->timeout) / 1000 / 1000;
3524fa790ea9SDavid C Somayajulu qp_params.ack_timeout = temp; /* FW requires [msec] */
3525fa790ea9SDavid C Somayajulu }
3526fa790ea9SDavid C Somayajulu else
3527fa790ea9SDavid C Somayajulu qp_params.ack_timeout = 0; /* infinite */
3528fa790ea9SDavid C Somayajulu }
3529fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_RETRY_CNT) {
3530fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,\
3531fa790ea9SDavid C Somayajulu ECORE_ROCE_MODIFY_QP_VALID_RETRY_CNT, 1);
3532fa790ea9SDavid C Somayajulu qp_params.retry_cnt = attr->retry_cnt;
3533fa790ea9SDavid C Somayajulu }
3534fa790ea9SDavid C Somayajulu
3535fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_RNR_RETRY) {
3536fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3537fa790ea9SDavid C Somayajulu ECORE_ROCE_MODIFY_QP_VALID_RNR_RETRY_CNT,
3538fa790ea9SDavid C Somayajulu 1);
3539fa790ea9SDavid C Somayajulu qp_params.rnr_retry_cnt = attr->rnr_retry;
3540fa790ea9SDavid C Somayajulu }
3541fa790ea9SDavid C Somayajulu
3542fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_RQ_PSN) {
3543fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3544fa790ea9SDavid C Somayajulu ECORE_ROCE_MODIFY_QP_VALID_RQ_PSN,
3545fa790ea9SDavid C Somayajulu 1);
3546fa790ea9SDavid C Somayajulu qp_params.rq_psn = attr->rq_psn;
3547fa790ea9SDavid C Somayajulu qp->rq_psn = attr->rq_psn;
3548fa790ea9SDavid C Somayajulu }
3549fa790ea9SDavid C Somayajulu
3550fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
3551fa790ea9SDavid C Somayajulu if (attr->max_rd_atomic > qattr->max_qp_req_rd_atomic_resc) {
3552fa790ea9SDavid C Somayajulu rc = -EINVAL;
3553fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
3554fa790ea9SDavid C Somayajulu "unsupported max_rd_atomic=%d, supported=%d\n",
3555fa790ea9SDavid C Somayajulu attr->max_rd_atomic,
3556fa790ea9SDavid C Somayajulu qattr->max_qp_req_rd_atomic_resc);
3557fa790ea9SDavid C Somayajulu goto err;
3558fa790ea9SDavid C Somayajulu }
3559fa790ea9SDavid C Somayajulu
3560fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3561fa790ea9SDavid C Somayajulu ECORE_RDMA_MODIFY_QP_VALID_MAX_RD_ATOMIC_REQ,
3562fa790ea9SDavid C Somayajulu 1);
3563fa790ea9SDavid C Somayajulu qp_params.max_rd_atomic_req = attr->max_rd_atomic;
3564fa790ea9SDavid C Somayajulu }
3565fa790ea9SDavid C Somayajulu
3566fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_MIN_RNR_TIMER) {
3567fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3568fa790ea9SDavid C Somayajulu ECORE_ROCE_MODIFY_QP_VALID_MIN_RNR_NAK_TIMER,
3569fa790ea9SDavid C Somayajulu 1);
3570fa790ea9SDavid C Somayajulu qp_params.min_rnr_nak_timer = attr->min_rnr_timer;
3571fa790ea9SDavid C Somayajulu }
3572fa790ea9SDavid C Somayajulu
3573fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_SQ_PSN) {
3574fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3575fa790ea9SDavid C Somayajulu ECORE_ROCE_MODIFY_QP_VALID_SQ_PSN,
3576fa790ea9SDavid C Somayajulu 1);
3577fa790ea9SDavid C Somayajulu qp_params.sq_psn = attr->sq_psn;
3578fa790ea9SDavid C Somayajulu qp->sq_psn = attr->sq_psn;
3579fa790ea9SDavid C Somayajulu }
3580fa790ea9SDavid C Somayajulu
3581fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
3582fa790ea9SDavid C Somayajulu if (attr->max_dest_rd_atomic >
3583fa790ea9SDavid C Somayajulu qattr->max_qp_resp_rd_atomic_resc) {
3584fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
3585fa790ea9SDavid C Somayajulu "unsupported max_dest_rd_atomic=%d, "
3586fa790ea9SDavid C Somayajulu "supported=%d\n",
3587fa790ea9SDavid C Somayajulu attr->max_dest_rd_atomic,
3588fa790ea9SDavid C Somayajulu qattr->max_qp_resp_rd_atomic_resc);
3589fa790ea9SDavid C Somayajulu
3590fa790ea9SDavid C Somayajulu rc = -EINVAL;
3591fa790ea9SDavid C Somayajulu goto err;
3592fa790ea9SDavid C Somayajulu }
3593fa790ea9SDavid C Somayajulu
3594fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3595fa790ea9SDavid C Somayajulu ECORE_RDMA_MODIFY_QP_VALID_MAX_RD_ATOMIC_RESP,
3596fa790ea9SDavid C Somayajulu 1);
3597fa790ea9SDavid C Somayajulu qp_params.max_rd_atomic_resp = attr->max_dest_rd_atomic;
3598fa790ea9SDavid C Somayajulu }
3599fa790ea9SDavid C Somayajulu
3600fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_DEST_QPN) {
3601fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
3602fa790ea9SDavid C Somayajulu ECORE_ROCE_MODIFY_QP_VALID_DEST_QP,
3603fa790ea9SDavid C Somayajulu 1);
3604fa790ea9SDavid C Somayajulu
3605fa790ea9SDavid C Somayajulu qp_params.dest_qp = attr->dest_qp_num;
3606fa790ea9SDavid C Somayajulu qp->dest_qp_num = attr->dest_qp_num;
3607fa790ea9SDavid C Somayajulu }
3608fa790ea9SDavid C Somayajulu
3609fa790ea9SDavid C Somayajulu /*
3610fa790ea9SDavid C Somayajulu * Update the QP state before the actual ramrod to prevent a race with
3611fa790ea9SDavid C Somayajulu * fast path. Modifying the QP state to error will cause the device to
3612fa790ea9SDavid C Somayajulu * flush the CQEs and while polling the flushed CQEs will considered as
3613fa790ea9SDavid C Somayajulu * a potential issue if the QP isn't in error state.
3614fa790ea9SDavid C Somayajulu */
3615fa790ea9SDavid C Somayajulu if ((attr_mask & IB_QP_STATE) && (qp->qp_type != IB_QPT_GSI) &&
3616fa790ea9SDavid C Somayajulu (!udata) && (qp_params.new_state == ECORE_ROCE_QP_STATE_ERR))
3617fa790ea9SDavid C Somayajulu qp->state = ECORE_ROCE_QP_STATE_ERR;
3618fa790ea9SDavid C Somayajulu
3619fa790ea9SDavid C Somayajulu if (qp->qp_type != IB_QPT_GSI)
3620fa790ea9SDavid C Somayajulu rc = ecore_rdma_modify_qp(dev->rdma_ctx, qp->ecore_qp, &qp_params);
3621fa790ea9SDavid C Somayajulu
3622fa790ea9SDavid C Somayajulu if (attr_mask & IB_QP_STATE) {
3623fa790ea9SDavid C Somayajulu if ((qp->qp_type != IB_QPT_GSI) && (!udata))
3624fa790ea9SDavid C Somayajulu rc = qlnxr_update_qp_state(dev, qp, qp_params.new_state);
3625fa790ea9SDavid C Somayajulu qp->state = qp_params.new_state;
3626fa790ea9SDavid C Somayajulu }
3627fa790ea9SDavid C Somayajulu
3628fa790ea9SDavid C Somayajulu err:
3629fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
3630fa790ea9SDavid C Somayajulu return rc;
3631fa790ea9SDavid C Somayajulu }
3632fa790ea9SDavid C Somayajulu
3633fa790ea9SDavid C Somayajulu static int
qlnxr_to_ib_qp_acc_flags(struct ecore_rdma_query_qp_out_params * params)3634fa790ea9SDavid C Somayajulu qlnxr_to_ib_qp_acc_flags(struct ecore_rdma_query_qp_out_params *params)
3635fa790ea9SDavid C Somayajulu {
3636fa790ea9SDavid C Somayajulu int ib_qp_acc_flags = 0;
3637fa790ea9SDavid C Somayajulu
3638fa790ea9SDavid C Somayajulu if (params->incoming_rdma_write_en)
3639fa790ea9SDavid C Somayajulu ib_qp_acc_flags |= IB_ACCESS_REMOTE_WRITE;
3640fa790ea9SDavid C Somayajulu if (params->incoming_rdma_read_en)
3641fa790ea9SDavid C Somayajulu ib_qp_acc_flags |= IB_ACCESS_REMOTE_READ;
3642fa790ea9SDavid C Somayajulu if (params->incoming_atomic_en)
3643fa790ea9SDavid C Somayajulu ib_qp_acc_flags |= IB_ACCESS_REMOTE_ATOMIC;
3644fa790ea9SDavid C Somayajulu if (true) /* FIXME -> local write ?? */
3645fa790ea9SDavid C Somayajulu ib_qp_acc_flags |= IB_ACCESS_LOCAL_WRITE;
3646fa790ea9SDavid C Somayajulu
3647fa790ea9SDavid C Somayajulu return ib_qp_acc_flags;
3648fa790ea9SDavid C Somayajulu }
3649fa790ea9SDavid C Somayajulu
3650fa790ea9SDavid C Somayajulu static enum ib_mtu
qlnxr_mtu_int_to_enum(u16 mtu)3651fa790ea9SDavid C Somayajulu qlnxr_mtu_int_to_enum(u16 mtu)
3652fa790ea9SDavid C Somayajulu {
3653fa790ea9SDavid C Somayajulu enum ib_mtu ib_mtu_size;
3654fa790ea9SDavid C Somayajulu
3655fa790ea9SDavid C Somayajulu switch (mtu) {
3656fa790ea9SDavid C Somayajulu case 256:
3657fa790ea9SDavid C Somayajulu ib_mtu_size = IB_MTU_256;
3658fa790ea9SDavid C Somayajulu break;
3659fa790ea9SDavid C Somayajulu
3660fa790ea9SDavid C Somayajulu case 512:
3661fa790ea9SDavid C Somayajulu ib_mtu_size = IB_MTU_512;
3662fa790ea9SDavid C Somayajulu break;
3663fa790ea9SDavid C Somayajulu
3664fa790ea9SDavid C Somayajulu case 1024:
3665fa790ea9SDavid C Somayajulu ib_mtu_size = IB_MTU_1024;
3666fa790ea9SDavid C Somayajulu break;
3667fa790ea9SDavid C Somayajulu
3668fa790ea9SDavid C Somayajulu case 2048:
3669fa790ea9SDavid C Somayajulu ib_mtu_size = IB_MTU_2048;
3670fa790ea9SDavid C Somayajulu break;
3671fa790ea9SDavid C Somayajulu
3672fa790ea9SDavid C Somayajulu case 4096:
3673fa790ea9SDavid C Somayajulu ib_mtu_size = IB_MTU_4096;
3674fa790ea9SDavid C Somayajulu break;
3675fa790ea9SDavid C Somayajulu
3676fa790ea9SDavid C Somayajulu default:
3677fa790ea9SDavid C Somayajulu ib_mtu_size = IB_MTU_1024;
3678fa790ea9SDavid C Somayajulu break;
3679fa790ea9SDavid C Somayajulu }
3680fa790ea9SDavid C Somayajulu return (ib_mtu_size);
3681fa790ea9SDavid C Somayajulu }
3682fa790ea9SDavid C Somayajulu
3683fa790ea9SDavid C Somayajulu int
qlnxr_query_qp(struct ib_qp * ibqp,struct ib_qp_attr * qp_attr,int attr_mask,struct ib_qp_init_attr * qp_init_attr)3684fa790ea9SDavid C Somayajulu qlnxr_query_qp(struct ib_qp *ibqp,
3685fa790ea9SDavid C Somayajulu struct ib_qp_attr *qp_attr,
3686fa790ea9SDavid C Somayajulu int attr_mask,
3687fa790ea9SDavid C Somayajulu struct ib_qp_init_attr *qp_init_attr)
3688fa790ea9SDavid C Somayajulu {
3689fa790ea9SDavid C Somayajulu int rc = 0;
3690fa790ea9SDavid C Somayajulu struct ecore_rdma_query_qp_out_params params;
3691fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp = get_qlnxr_qp(ibqp);
3692fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = qp->dev;
3693fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
3694fa790ea9SDavid C Somayajulu
3695fa790ea9SDavid C Somayajulu ha = dev->ha;
3696fa790ea9SDavid C Somayajulu
3697fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
3698fa790ea9SDavid C Somayajulu
3699fa790ea9SDavid C Somayajulu memset(¶ms, 0, sizeof(params));
3700fa790ea9SDavid C Somayajulu
3701fa790ea9SDavid C Somayajulu rc = ecore_rdma_query_qp(dev->rdma_ctx, qp->ecore_qp, ¶ms);
3702fa790ea9SDavid C Somayajulu if (rc)
3703fa790ea9SDavid C Somayajulu goto err;
3704fa790ea9SDavid C Somayajulu
3705fa790ea9SDavid C Somayajulu memset(qp_attr, 0, sizeof(*qp_attr));
3706fa790ea9SDavid C Somayajulu memset(qp_init_attr, 0, sizeof(*qp_init_attr));
3707fa790ea9SDavid C Somayajulu
3708fa790ea9SDavid C Somayajulu qp_attr->qp_state = qlnxr_get_ibqp_state(params.state);
3709fa790ea9SDavid C Somayajulu qp_attr->cur_qp_state = qlnxr_get_ibqp_state(params.state);
3710fa790ea9SDavid C Somayajulu
3711fa790ea9SDavid C Somayajulu /* In some cases in iWARP qelr will ask for the state only */
3712fa790ea9SDavid C Somayajulu if (QLNX_IS_IWARP(dev) && (attr_mask == IB_QP_STATE)) {
3713fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "only state requested\n");
3714fa790ea9SDavid C Somayajulu return 0;
3715fa790ea9SDavid C Somayajulu }
3716fa790ea9SDavid C Somayajulu
3717fa790ea9SDavid C Somayajulu qp_attr->path_mtu = qlnxr_mtu_int_to_enum(params.mtu);
3718fa790ea9SDavid C Somayajulu qp_attr->path_mig_state = IB_MIG_MIGRATED;
3719fa790ea9SDavid C Somayajulu qp_attr->rq_psn = params.rq_psn;
3720fa790ea9SDavid C Somayajulu qp_attr->sq_psn = params.sq_psn;
3721fa790ea9SDavid C Somayajulu qp_attr->dest_qp_num = params.dest_qp;
3722fa790ea9SDavid C Somayajulu
3723fa790ea9SDavid C Somayajulu qp_attr->qp_access_flags = qlnxr_to_ib_qp_acc_flags(¶ms);
3724fa790ea9SDavid C Somayajulu
3725fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "qp_state = 0x%x cur_qp_state = 0x%x "
3726fa790ea9SDavid C Somayajulu "path_mtu = %d qp_access_flags = 0x%x\n",
3727fa790ea9SDavid C Somayajulu qp_attr->qp_state, qp_attr->cur_qp_state, qp_attr->path_mtu,
3728fa790ea9SDavid C Somayajulu qp_attr->qp_access_flags);
3729fa790ea9SDavid C Somayajulu
3730fa790ea9SDavid C Somayajulu qp_attr->cap.max_send_wr = qp->sq.max_wr;
3731fa790ea9SDavid C Somayajulu qp_attr->cap.max_recv_wr = qp->rq.max_wr;
3732fa790ea9SDavid C Somayajulu qp_attr->cap.max_send_sge = qp->sq.max_sges;
3733fa790ea9SDavid C Somayajulu qp_attr->cap.max_recv_sge = qp->rq.max_sges;
3734fa790ea9SDavid C Somayajulu qp_attr->cap.max_inline_data = qp->max_inline_data;
3735fa790ea9SDavid C Somayajulu qp_init_attr->cap = qp_attr->cap;
3736fa790ea9SDavid C Somayajulu
3737fa790ea9SDavid C Somayajulu memcpy(&qp_attr->ah_attr.grh.dgid.raw[0], ¶ms.dgid.bytes[0],
3738fa790ea9SDavid C Somayajulu sizeof(qp_attr->ah_attr.grh.dgid.raw));
3739fa790ea9SDavid C Somayajulu
3740fa790ea9SDavid C Somayajulu qp_attr->ah_attr.grh.flow_label = params.flow_label;
3741fa790ea9SDavid C Somayajulu qp_attr->ah_attr.grh.sgid_index = qp->sgid_idx;
3742fa790ea9SDavid C Somayajulu qp_attr->ah_attr.grh.hop_limit = params.hop_limit_ttl;
3743fa790ea9SDavid C Somayajulu qp_attr->ah_attr.grh.traffic_class = params.traffic_class_tos;
3744fa790ea9SDavid C Somayajulu
3745fa790ea9SDavid C Somayajulu qp_attr->ah_attr.ah_flags = IB_AH_GRH;
3746fa790ea9SDavid C Somayajulu qp_attr->ah_attr.port_num = 1; /* FIXME -> check this */
3747fa790ea9SDavid C Somayajulu qp_attr->ah_attr.sl = 0;/* FIXME -> check this */
3748fa790ea9SDavid C Somayajulu qp_attr->timeout = params.timeout;
3749fa790ea9SDavid C Somayajulu qp_attr->rnr_retry = params.rnr_retry;
3750fa790ea9SDavid C Somayajulu qp_attr->retry_cnt = params.retry_cnt;
3751fa790ea9SDavid C Somayajulu qp_attr->min_rnr_timer = params.min_rnr_nak_timer;
3752fa790ea9SDavid C Somayajulu qp_attr->pkey_index = params.pkey_index;
3753fa790ea9SDavid C Somayajulu qp_attr->port_num = 1; /* FIXME -> check this */
3754fa790ea9SDavid C Somayajulu qp_attr->ah_attr.src_path_bits = 0;
3755fa790ea9SDavid C Somayajulu qp_attr->ah_attr.static_rate = 0;
3756fa790ea9SDavid C Somayajulu qp_attr->alt_pkey_index = 0;
3757fa790ea9SDavid C Somayajulu qp_attr->alt_port_num = 0;
3758fa790ea9SDavid C Somayajulu qp_attr->alt_timeout = 0;
3759fa790ea9SDavid C Somayajulu memset(&qp_attr->alt_ah_attr, 0, sizeof(qp_attr->alt_ah_attr));
3760fa790ea9SDavid C Somayajulu
3761fa790ea9SDavid C Somayajulu qp_attr->sq_draining = (params.state == ECORE_ROCE_QP_STATE_SQD) ? 1 : 0;
3762fa790ea9SDavid C Somayajulu qp_attr->max_dest_rd_atomic = params.max_dest_rd_atomic;
3763fa790ea9SDavid C Somayajulu qp_attr->max_rd_atomic = params.max_rd_atomic;
3764fa790ea9SDavid C Somayajulu qp_attr->en_sqd_async_notify = (params.sqd_async)? 1 : 0;
3765fa790ea9SDavid C Somayajulu
3766fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "max_inline_data=%d\n",
3767fa790ea9SDavid C Somayajulu qp_attr->cap.max_inline_data);
3768fa790ea9SDavid C Somayajulu
3769fa790ea9SDavid C Somayajulu err:
3770fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
3771fa790ea9SDavid C Somayajulu return rc;
3772fa790ea9SDavid C Somayajulu }
3773fa790ea9SDavid C Somayajulu
3774fa790ea9SDavid C Somayajulu static void
qlnxr_cleanup_user(struct qlnxr_dev * dev,struct qlnxr_qp * qp)3775fa790ea9SDavid C Somayajulu qlnxr_cleanup_user(struct qlnxr_dev *dev, struct qlnxr_qp *qp)
3776fa790ea9SDavid C Somayajulu {
3777fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
3778fa790ea9SDavid C Somayajulu
3779fa790ea9SDavid C Somayajulu ha = dev->ha;
3780fa790ea9SDavid C Somayajulu
3781fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
3782fa790ea9SDavid C Somayajulu
3783fa790ea9SDavid C Somayajulu if (qp->usq.umem)
3784fa790ea9SDavid C Somayajulu ib_umem_release(qp->usq.umem);
3785fa790ea9SDavid C Somayajulu
3786fa790ea9SDavid C Somayajulu qp->usq.umem = NULL;
3787fa790ea9SDavid C Somayajulu
3788fa790ea9SDavid C Somayajulu if (qp->urq.umem)
3789fa790ea9SDavid C Somayajulu ib_umem_release(qp->urq.umem);
3790fa790ea9SDavid C Somayajulu
3791fa790ea9SDavid C Somayajulu qp->urq.umem = NULL;
3792fa790ea9SDavid C Somayajulu
3793fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
3794fa790ea9SDavid C Somayajulu return;
3795fa790ea9SDavid C Somayajulu }
3796fa790ea9SDavid C Somayajulu
3797fa790ea9SDavid C Somayajulu static void
qlnxr_cleanup_kernel(struct qlnxr_dev * dev,struct qlnxr_qp * qp)3798fa790ea9SDavid C Somayajulu qlnxr_cleanup_kernel(struct qlnxr_dev *dev, struct qlnxr_qp *qp)
3799fa790ea9SDavid C Somayajulu {
3800fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
3801fa790ea9SDavid C Somayajulu
3802fa790ea9SDavid C Somayajulu ha = dev->ha;
3803fa790ea9SDavid C Somayajulu
3804fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
3805fa790ea9SDavid C Somayajulu
3806fa790ea9SDavid C Somayajulu if (qlnxr_qp_has_sq(qp)) {
3807fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "freeing SQ\n");
3808fa790ea9SDavid C Somayajulu ha->qlnxr_debug = 1;
3809fa790ea9SDavid C Somayajulu // ecore_chain_free(dev->cdev, &qp->sq.pbl);
3810fa790ea9SDavid C Somayajulu ha->qlnxr_debug = 0;
3811fa790ea9SDavid C Somayajulu kfree(qp->wqe_wr_id);
3812fa790ea9SDavid C Somayajulu }
3813fa790ea9SDavid C Somayajulu
3814fa790ea9SDavid C Somayajulu if (qlnxr_qp_has_rq(qp)) {
3815fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "freeing RQ\n");
3816fa790ea9SDavid C Somayajulu ha->qlnxr_debug = 1;
3817fa790ea9SDavid C Somayajulu // ecore_chain_free(dev->cdev, &qp->rq.pbl);
3818fa790ea9SDavid C Somayajulu ha->qlnxr_debug = 0;
3819fa790ea9SDavid C Somayajulu kfree(qp->rqe_wr_id);
3820fa790ea9SDavid C Somayajulu }
3821fa790ea9SDavid C Somayajulu
3822fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
3823fa790ea9SDavid C Somayajulu return;
3824fa790ea9SDavid C Somayajulu }
3825fa790ea9SDavid C Somayajulu
3826b633e08cSHans Petter Selasky static int
qlnxr_free_qp_resources(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct ib_udata * udata)3827fa790ea9SDavid C Somayajulu qlnxr_free_qp_resources(struct qlnxr_dev *dev,
3828b633e08cSHans Petter Selasky struct qlnxr_qp *qp, struct ib_udata *udata)
3829fa790ea9SDavid C Somayajulu {
3830fa790ea9SDavid C Somayajulu int rc = 0;
3831fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
3832fa790ea9SDavid C Somayajulu struct ecore_rdma_destroy_qp_out_params d_out_params;
3833fa790ea9SDavid C Somayajulu
3834fa790ea9SDavid C Somayajulu ha = dev->ha;
3835fa790ea9SDavid C Somayajulu
3836fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
3837fa790ea9SDavid C Somayajulu
3838fa790ea9SDavid C Somayajulu #if 0
3839fa790ea9SDavid C Somayajulu if (qp->qp_type != IB_QPT_GSI) {
3840fa790ea9SDavid C Somayajulu rc = ecore_rdma_destroy_qp(dev->rdma_ctx, qp->ecore_qp,
3841fa790ea9SDavid C Somayajulu &d_out_params);
3842fa790ea9SDavid C Somayajulu if (rc)
3843fa790ea9SDavid C Somayajulu return rc;
3844fa790ea9SDavid C Somayajulu }
3845fa790ea9SDavid C Somayajulu
3846b633e08cSHans Petter Selasky if (udata)
3847fa790ea9SDavid C Somayajulu qlnxr_cleanup_user(dev, qp);
3848fa790ea9SDavid C Somayajulu else
3849fa790ea9SDavid C Somayajulu qlnxr_cleanup_kernel(dev, qp);
3850fa790ea9SDavid C Somayajulu #endif
3851fa790ea9SDavid C Somayajulu
3852b633e08cSHans Petter Selasky if (udata)
3853fa790ea9SDavid C Somayajulu qlnxr_cleanup_user(dev, qp);
3854fa790ea9SDavid C Somayajulu else
3855fa790ea9SDavid C Somayajulu qlnxr_cleanup_kernel(dev, qp);
3856fa790ea9SDavid C Somayajulu
3857fa790ea9SDavid C Somayajulu if (qp->qp_type != IB_QPT_GSI) {
3858fa790ea9SDavid C Somayajulu rc = ecore_rdma_destroy_qp(dev->rdma_ctx, qp->ecore_qp,
3859fa790ea9SDavid C Somayajulu &d_out_params);
3860fa790ea9SDavid C Somayajulu if (rc)
3861fa790ea9SDavid C Somayajulu return rc;
3862fa790ea9SDavid C Somayajulu }
3863fa790ea9SDavid C Somayajulu
3864fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
3865fa790ea9SDavid C Somayajulu return 0;
3866fa790ea9SDavid C Somayajulu }
3867fa790ea9SDavid C Somayajulu
3868fa790ea9SDavid C Somayajulu int
qlnxr_destroy_qp(struct ib_qp * ibqp,struct ib_udata * udata)3869b633e08cSHans Petter Selasky qlnxr_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
3870fa790ea9SDavid C Somayajulu {
3871fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp = get_qlnxr_qp(ibqp);
3872fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = qp->dev;
3873fa790ea9SDavid C Somayajulu int rc = 0;
3874fa790ea9SDavid C Somayajulu struct ib_qp_attr attr;
3875fa790ea9SDavid C Somayajulu int attr_mask = 0;
3876fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
3877fa790ea9SDavid C Somayajulu
3878fa790ea9SDavid C Somayajulu ha = dev->ha;
3879fa790ea9SDavid C Somayajulu
3880fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter qp = %p, qp_type=%d\n", qp, qp->qp_type);
3881fa790ea9SDavid C Somayajulu
3882fa790ea9SDavid C Somayajulu qp->destroyed = 1;
3883fa790ea9SDavid C Somayajulu
3884fa790ea9SDavid C Somayajulu if (QLNX_IS_ROCE(dev) && (qp->state != (ECORE_ROCE_QP_STATE_RESET |
3885fa790ea9SDavid C Somayajulu ECORE_ROCE_QP_STATE_ERR |
3886fa790ea9SDavid C Somayajulu ECORE_ROCE_QP_STATE_INIT))) {
3887fa790ea9SDavid C Somayajulu attr.qp_state = IB_QPS_ERR;
3888fa790ea9SDavid C Somayajulu attr_mask |= IB_QP_STATE;
3889fa790ea9SDavid C Somayajulu
3890fa790ea9SDavid C Somayajulu /* change the QP state to ERROR */
3891fa790ea9SDavid C Somayajulu qlnxr_modify_qp(ibqp, &attr, attr_mask, NULL);
3892fa790ea9SDavid C Somayajulu }
3893fa790ea9SDavid C Somayajulu
3894fa790ea9SDavid C Somayajulu if (qp->qp_type == IB_QPT_GSI)
3895fa790ea9SDavid C Somayajulu qlnxr_destroy_gsi_qp(dev);
3896fa790ea9SDavid C Somayajulu
3897fa790ea9SDavid C Somayajulu qp->sig = ~qp->sig;
3898fa790ea9SDavid C Somayajulu
3899b633e08cSHans Petter Selasky qlnxr_free_qp_resources(dev, qp, udata);
3900fa790ea9SDavid C Somayajulu
3901fa790ea9SDavid C Somayajulu if (atomic_dec_and_test(&qp->refcnt)) {
3902fa790ea9SDavid C Somayajulu /* TODO: only for iWARP? */
3903fa790ea9SDavid C Somayajulu qlnxr_idr_remove(dev, qp->qp_id);
3904fa790ea9SDavid C Somayajulu }
3905fa790ea9SDavid C Somayajulu
3906fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
3907fa790ea9SDavid C Somayajulu return rc;
3908fa790ea9SDavid C Somayajulu }
3909fa790ea9SDavid C Somayajulu
3910fa790ea9SDavid C Somayajulu static inline int
qlnxr_wq_is_full(struct qlnxr_qp_hwq_info * wq)3911fa790ea9SDavid C Somayajulu qlnxr_wq_is_full(struct qlnxr_qp_hwq_info *wq)
3912fa790ea9SDavid C Somayajulu {
3913fa790ea9SDavid C Somayajulu return (((wq->prod + 1) % wq->max_wr) == wq->cons);
3914fa790ea9SDavid C Somayajulu }
3915fa790ea9SDavid C Somayajulu
3916fa790ea9SDavid C Somayajulu static int
sge_data_len(struct ib_sge * sg_list,int num_sge)3917fa790ea9SDavid C Somayajulu sge_data_len(struct ib_sge *sg_list, int num_sge)
3918fa790ea9SDavid C Somayajulu {
3919fa790ea9SDavid C Somayajulu int i, len = 0;
3920fa790ea9SDavid C Somayajulu for (i = 0; i < num_sge; i++)
3921fa790ea9SDavid C Somayajulu len += sg_list[i].length;
3922fa790ea9SDavid C Somayajulu return len;
3923fa790ea9SDavid C Somayajulu }
3924fa790ea9SDavid C Somayajulu
3925fa790ea9SDavid C Somayajulu static void
swap_wqe_data64(u64 * p)3926fa790ea9SDavid C Somayajulu swap_wqe_data64(u64 *p)
3927fa790ea9SDavid C Somayajulu {
3928fa790ea9SDavid C Somayajulu int i;
3929fa790ea9SDavid C Somayajulu
3930fa790ea9SDavid C Somayajulu for (i = 0; i < QLNXR_SQE_ELEMENT_SIZE / sizeof(u64); i++, p++)
3931fa790ea9SDavid C Somayajulu *p = cpu_to_be64(cpu_to_le64(*p));
3932fa790ea9SDavid C Somayajulu }
3933fa790ea9SDavid C Somayajulu
3934fa790ea9SDavid C Somayajulu static u32
qlnxr_prepare_sq_inline_data(struct qlnxr_dev * dev,struct qlnxr_qp * qp,u8 * wqe_size,const struct ib_send_wr * wr,const struct ib_send_wr ** bad_wr,u8 * bits,u8 bit)3935fa790ea9SDavid C Somayajulu qlnxr_prepare_sq_inline_data(struct qlnxr_dev *dev,
3936fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
3937fa790ea9SDavid C Somayajulu u8 *wqe_size,
3938c3987b8eSHans Petter Selasky const struct ib_send_wr *wr,
3939c3987b8eSHans Petter Selasky const struct ib_send_wr **bad_wr,
3940fa790ea9SDavid C Somayajulu u8 *bits,
3941fa790ea9SDavid C Somayajulu u8 bit)
3942fa790ea9SDavid C Somayajulu {
3943fa790ea9SDavid C Somayajulu int i, seg_siz;
3944fa790ea9SDavid C Somayajulu char *seg_prt, *wqe;
3945fa790ea9SDavid C Somayajulu u32 data_size = sge_data_len(wr->sg_list, wr->num_sge);
3946fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
3947fa790ea9SDavid C Somayajulu
3948fa790ea9SDavid C Somayajulu ha = dev->ha;
3949fa790ea9SDavid C Somayajulu
3950fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter[%d]\n", data_size);
3951fa790ea9SDavid C Somayajulu
3952fa790ea9SDavid C Somayajulu if (data_size > ROCE_REQ_MAX_INLINE_DATA_SIZE) {
3953fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
3954fa790ea9SDavid C Somayajulu "Too much inline data in WR:[%d, %d]\n",
3955fa790ea9SDavid C Somayajulu data_size, ROCE_REQ_MAX_INLINE_DATA_SIZE);
3956fa790ea9SDavid C Somayajulu *bad_wr = wr;
3957fa790ea9SDavid C Somayajulu return 0;
3958fa790ea9SDavid C Somayajulu }
3959fa790ea9SDavid C Somayajulu
3960fa790ea9SDavid C Somayajulu if (!data_size)
3961fa790ea9SDavid C Somayajulu return data_size;
3962fa790ea9SDavid C Somayajulu
3963fa790ea9SDavid C Somayajulu /* set the bit */
3964fa790ea9SDavid C Somayajulu *bits |= bit;
3965fa790ea9SDavid C Somayajulu
3966fa790ea9SDavid C Somayajulu seg_prt = wqe = NULL;
3967fa790ea9SDavid C Somayajulu seg_siz = 0;
3968fa790ea9SDavid C Somayajulu
3969fa790ea9SDavid C Somayajulu /* copy data inline */
3970fa790ea9SDavid C Somayajulu for (i = 0; i < wr->num_sge; i++) {
3971fa790ea9SDavid C Somayajulu u32 len = wr->sg_list[i].length;
3972fa790ea9SDavid C Somayajulu void *src = (void *)(uintptr_t)wr->sg_list[i].addr;
3973fa790ea9SDavid C Somayajulu
3974fa790ea9SDavid C Somayajulu while (len > 0) {
3975fa790ea9SDavid C Somayajulu u32 cur;
3976fa790ea9SDavid C Somayajulu
3977fa790ea9SDavid C Somayajulu /* new segment required */
3978fa790ea9SDavid C Somayajulu if (!seg_siz) {
3979fa790ea9SDavid C Somayajulu wqe = (char *)ecore_chain_produce(&qp->sq.pbl);
3980fa790ea9SDavid C Somayajulu seg_prt = wqe;
3981fa790ea9SDavid C Somayajulu seg_siz = sizeof(struct rdma_sq_common_wqe);
3982fa790ea9SDavid C Somayajulu (*wqe_size)++;
3983fa790ea9SDavid C Somayajulu }
3984fa790ea9SDavid C Somayajulu
3985fa790ea9SDavid C Somayajulu /* calculate currently allowed length */
3986fa790ea9SDavid C Somayajulu cur = MIN(len, seg_siz);
3987fa790ea9SDavid C Somayajulu
3988fa790ea9SDavid C Somayajulu memcpy(seg_prt, src, cur);
3989fa790ea9SDavid C Somayajulu
3990fa790ea9SDavid C Somayajulu /* update segment variables */
3991fa790ea9SDavid C Somayajulu seg_prt += cur;
3992fa790ea9SDavid C Somayajulu seg_siz -= cur;
3993fa790ea9SDavid C Somayajulu /* update sge variables */
3994fa790ea9SDavid C Somayajulu src += cur;
3995fa790ea9SDavid C Somayajulu len -= cur;
3996fa790ea9SDavid C Somayajulu
3997fa790ea9SDavid C Somayajulu /* swap fully-completed segments */
3998fa790ea9SDavid C Somayajulu if (!seg_siz)
3999fa790ea9SDavid C Somayajulu swap_wqe_data64((u64 *)wqe);
4000fa790ea9SDavid C Somayajulu }
4001fa790ea9SDavid C Somayajulu }
4002fa790ea9SDavid C Somayajulu
4003fa790ea9SDavid C Somayajulu /* swap last not completed segment */
4004fa790ea9SDavid C Somayajulu if (seg_siz)
4005fa790ea9SDavid C Somayajulu swap_wqe_data64((u64 *)wqe);
4006fa790ea9SDavid C Somayajulu
4007fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
4008fa790ea9SDavid C Somayajulu return data_size;
4009fa790ea9SDavid C Somayajulu }
4010fa790ea9SDavid C Somayajulu
4011fa790ea9SDavid C Somayajulu static u32
qlnxr_prepare_sq_sges(struct qlnxr_dev * dev,struct qlnxr_qp * qp,u8 * wqe_size,const struct ib_send_wr * wr)4012fa790ea9SDavid C Somayajulu qlnxr_prepare_sq_sges(struct qlnxr_dev *dev, struct qlnxr_qp *qp,
4013c3987b8eSHans Petter Selasky u8 *wqe_size, const struct ib_send_wr *wr)
4014fa790ea9SDavid C Somayajulu {
4015fa790ea9SDavid C Somayajulu int i;
4016fa790ea9SDavid C Somayajulu u32 data_size = 0;
4017fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
4018fa790ea9SDavid C Somayajulu
4019fa790ea9SDavid C Somayajulu ha = dev->ha;
4020fa790ea9SDavid C Somayajulu
4021fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter wr->num_sge = %d \n", wr->num_sge);
4022fa790ea9SDavid C Somayajulu
4023fa790ea9SDavid C Somayajulu for (i = 0; i < wr->num_sge; i++) {
4024fa790ea9SDavid C Somayajulu struct rdma_sq_sge *sge = ecore_chain_produce(&qp->sq.pbl);
4025fa790ea9SDavid C Somayajulu
4026fa790ea9SDavid C Somayajulu TYPEPTR_ADDR_SET(sge, addr, wr->sg_list[i].addr);
4027fa790ea9SDavid C Somayajulu sge->l_key = cpu_to_le32(wr->sg_list[i].lkey);
4028fa790ea9SDavid C Somayajulu sge->length = cpu_to_le32(wr->sg_list[i].length);
4029fa790ea9SDavid C Somayajulu data_size += wr->sg_list[i].length;
4030fa790ea9SDavid C Somayajulu }
4031fa790ea9SDavid C Somayajulu
4032fa790ea9SDavid C Somayajulu if (wqe_size)
4033fa790ea9SDavid C Somayajulu *wqe_size += wr->num_sge;
4034fa790ea9SDavid C Somayajulu
4035fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit data_size = %d\n", data_size);
4036fa790ea9SDavid C Somayajulu return data_size;
4037fa790ea9SDavid C Somayajulu }
4038fa790ea9SDavid C Somayajulu
4039fa790ea9SDavid C Somayajulu static u32
qlnxr_prepare_sq_rdma_data(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct rdma_sq_rdma_wqe_1st * rwqe,struct rdma_sq_rdma_wqe_2nd * rwqe2,const struct ib_send_wr * wr,const struct ib_send_wr ** bad_wr)4040fa790ea9SDavid C Somayajulu qlnxr_prepare_sq_rdma_data(struct qlnxr_dev *dev,
4041fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
4042fa790ea9SDavid C Somayajulu struct rdma_sq_rdma_wqe_1st *rwqe,
4043fa790ea9SDavid C Somayajulu struct rdma_sq_rdma_wqe_2nd *rwqe2,
4044c3987b8eSHans Petter Selasky const struct ib_send_wr *wr,
4045c3987b8eSHans Petter Selasky const struct ib_send_wr **bad_wr)
4046fa790ea9SDavid C Somayajulu {
4047fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
4048fa790ea9SDavid C Somayajulu u32 ret = 0;
4049fa790ea9SDavid C Somayajulu
4050fa790ea9SDavid C Somayajulu ha = dev->ha;
4051fa790ea9SDavid C Somayajulu
4052fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
4053fa790ea9SDavid C Somayajulu
4054fa790ea9SDavid C Somayajulu rwqe2->r_key = cpu_to_le32(rdma_wr(wr)->rkey);
4055fa790ea9SDavid C Somayajulu TYPEPTR_ADDR_SET(rwqe2, remote_va, rdma_wr(wr)->remote_addr);
4056fa790ea9SDavid C Somayajulu
4057fa790ea9SDavid C Somayajulu if (wr->send_flags & IB_SEND_INLINE) {
4058fa790ea9SDavid C Somayajulu u8 flags = 0;
4059fa790ea9SDavid C Somayajulu SET_FIELD2(flags, RDMA_SQ_RDMA_WQE_1ST_INLINE_FLG, 1);
4060fa790ea9SDavid C Somayajulu return qlnxr_prepare_sq_inline_data(dev, qp, &rwqe->wqe_size,
4061fa790ea9SDavid C Somayajulu wr, bad_wr, &rwqe->flags, flags);
4062fa790ea9SDavid C Somayajulu }
4063fa790ea9SDavid C Somayajulu
4064fa790ea9SDavid C Somayajulu ret = qlnxr_prepare_sq_sges(dev, qp, &rwqe->wqe_size, wr);
4065fa790ea9SDavid C Somayajulu
4066fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit ret = 0x%x\n", ret);
4067fa790ea9SDavid C Somayajulu
4068fa790ea9SDavid C Somayajulu return (ret);
4069fa790ea9SDavid C Somayajulu }
4070fa790ea9SDavid C Somayajulu
4071fa790ea9SDavid C Somayajulu static u32
qlnxr_prepare_sq_send_data(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct rdma_sq_send_wqe * swqe,struct rdma_sq_send_wqe * swqe2,const struct ib_send_wr * wr,const struct ib_send_wr ** bad_wr)4072fa790ea9SDavid C Somayajulu qlnxr_prepare_sq_send_data(struct qlnxr_dev *dev,
4073fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
4074fa790ea9SDavid C Somayajulu struct rdma_sq_send_wqe *swqe,
4075fa790ea9SDavid C Somayajulu struct rdma_sq_send_wqe *swqe2,
4076c3987b8eSHans Petter Selasky const struct ib_send_wr *wr,
4077c3987b8eSHans Petter Selasky const struct ib_send_wr **bad_wr)
4078fa790ea9SDavid C Somayajulu {
4079fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
4080fa790ea9SDavid C Somayajulu u32 ret = 0;
4081fa790ea9SDavid C Somayajulu
4082fa790ea9SDavid C Somayajulu ha = dev->ha;
4083fa790ea9SDavid C Somayajulu
4084fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
4085fa790ea9SDavid C Somayajulu
4086fa790ea9SDavid C Somayajulu memset(swqe2, 0, sizeof(*swqe2));
4087fa790ea9SDavid C Somayajulu
4088fa790ea9SDavid C Somayajulu if (wr->send_flags & IB_SEND_INLINE) {
4089fa790ea9SDavid C Somayajulu u8 flags = 0;
4090fa790ea9SDavid C Somayajulu SET_FIELD2(flags, RDMA_SQ_SEND_WQE_INLINE_FLG, 1);
4091fa790ea9SDavid C Somayajulu return qlnxr_prepare_sq_inline_data(dev, qp, &swqe->wqe_size,
4092fa790ea9SDavid C Somayajulu wr, bad_wr, &swqe->flags, flags);
4093fa790ea9SDavid C Somayajulu }
4094fa790ea9SDavid C Somayajulu
4095fa790ea9SDavid C Somayajulu ret = qlnxr_prepare_sq_sges(dev, qp, &swqe->wqe_size, wr);
4096fa790ea9SDavid C Somayajulu
4097fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit ret = 0x%x\n", ret);
4098fa790ea9SDavid C Somayajulu
4099fa790ea9SDavid C Somayajulu return (ret);
4100fa790ea9SDavid C Somayajulu }
4101fa790ea9SDavid C Somayajulu
4102fa790ea9SDavid C Somayajulu static void
qlnx_handle_completed_mrs(struct qlnxr_dev * dev,struct mr_info * info)4103fa790ea9SDavid C Somayajulu qlnx_handle_completed_mrs(struct qlnxr_dev *dev, struct mr_info *info)
4104fa790ea9SDavid C Somayajulu {
4105fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
4106fa790ea9SDavid C Somayajulu
4107fa790ea9SDavid C Somayajulu ha = dev->ha;
4108fa790ea9SDavid C Somayajulu
4109fa790ea9SDavid C Somayajulu int work = info->completed - info->completed_handled - 1;
4110fa790ea9SDavid C Somayajulu
4111fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter [%d]\n", work);
4112fa790ea9SDavid C Somayajulu
4113fa790ea9SDavid C Somayajulu while (work-- > 0 && !list_empty(&info->inuse_pbl_list)) {
4114fa790ea9SDavid C Somayajulu struct qlnxr_pbl *pbl;
4115fa790ea9SDavid C Somayajulu
4116fa790ea9SDavid C Somayajulu /* Free all the page list that are possible to be freed
4117fa790ea9SDavid C Somayajulu * (all the ones that were invalidated), under the assumption
4118fa790ea9SDavid C Somayajulu * that if an FMR was completed successfully that means that
4119fa790ea9SDavid C Somayajulu * if there was an invalidate operation before it also ended
4120fa790ea9SDavid C Somayajulu */
4121fa790ea9SDavid C Somayajulu pbl = list_first_entry(&info->inuse_pbl_list,
4122fa790ea9SDavid C Somayajulu struct qlnxr_pbl,
4123fa790ea9SDavid C Somayajulu list_entry);
4124fa790ea9SDavid C Somayajulu list_del(&pbl->list_entry);
4125fa790ea9SDavid C Somayajulu list_add_tail(&pbl->list_entry, &info->free_pbl_list);
4126fa790ea9SDavid C Somayajulu info->completed_handled++;
4127fa790ea9SDavid C Somayajulu }
4128fa790ea9SDavid C Somayajulu
4129fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
4130fa790ea9SDavid C Somayajulu return;
4131fa790ea9SDavid C Somayajulu }
4132fa790ea9SDavid C Somayajulu
qlnxr_prepare_reg(struct qlnxr_qp * qp,struct rdma_sq_fmr_wqe_1st * fwqe1,const struct ib_reg_wr * wr)4133fa790ea9SDavid C Somayajulu static int qlnxr_prepare_reg(struct qlnxr_qp *qp,
4134fa790ea9SDavid C Somayajulu struct rdma_sq_fmr_wqe_1st *fwqe1,
4135c3987b8eSHans Petter Selasky const struct ib_reg_wr *wr)
4136fa790ea9SDavid C Somayajulu {
4137fa790ea9SDavid C Somayajulu struct qlnxr_mr *mr = get_qlnxr_mr(wr->mr);
4138fa790ea9SDavid C Somayajulu struct rdma_sq_fmr_wqe_2nd *fwqe2;
4139fa790ea9SDavid C Somayajulu
4140fa790ea9SDavid C Somayajulu fwqe2 = (struct rdma_sq_fmr_wqe_2nd *)ecore_chain_produce(&qp->sq.pbl);
4141fa790ea9SDavid C Somayajulu fwqe1->addr.hi = upper_32_bits(mr->ibmr.iova);
4142fa790ea9SDavid C Somayajulu fwqe1->addr.lo = lower_32_bits(mr->ibmr.iova);
4143fa790ea9SDavid C Somayajulu fwqe1->l_key = wr->key;
4144fa790ea9SDavid C Somayajulu
4145fa790ea9SDavid C Somayajulu fwqe2->access_ctrl = 0;
4146fa790ea9SDavid C Somayajulu
4147fa790ea9SDavid C Somayajulu SET_FIELD2(fwqe2->access_ctrl, RDMA_SQ_FMR_WQE_2ND_REMOTE_READ,
4148fa790ea9SDavid C Somayajulu !!(wr->access & IB_ACCESS_REMOTE_READ));
4149fa790ea9SDavid C Somayajulu SET_FIELD2(fwqe2->access_ctrl, RDMA_SQ_FMR_WQE_2ND_REMOTE_WRITE,
4150fa790ea9SDavid C Somayajulu !!(wr->access & IB_ACCESS_REMOTE_WRITE));
4151fa790ea9SDavid C Somayajulu SET_FIELD2(fwqe2->access_ctrl, RDMA_SQ_FMR_WQE_2ND_ENABLE_ATOMIC,
4152fa790ea9SDavid C Somayajulu !!(wr->access & IB_ACCESS_REMOTE_ATOMIC));
4153fa790ea9SDavid C Somayajulu SET_FIELD2(fwqe2->access_ctrl, RDMA_SQ_FMR_WQE_2ND_LOCAL_READ, 1);
4154fa790ea9SDavid C Somayajulu SET_FIELD2(fwqe2->access_ctrl, RDMA_SQ_FMR_WQE_2ND_LOCAL_WRITE,
4155fa790ea9SDavid C Somayajulu !!(wr->access & IB_ACCESS_LOCAL_WRITE));
4156fa790ea9SDavid C Somayajulu fwqe2->fmr_ctrl = 0;
4157fa790ea9SDavid C Somayajulu
4158fa790ea9SDavid C Somayajulu SET_FIELD2(fwqe2->fmr_ctrl, RDMA_SQ_FMR_WQE_2ND_PAGE_SIZE_LOG,
4159fa790ea9SDavid C Somayajulu ilog2(mr->ibmr.page_size) - 12);
4160fa790ea9SDavid C Somayajulu
4161fa790ea9SDavid C Somayajulu fwqe2->length_hi = 0; /* TODO - figure out why length is only 32bit.. */
4162fa790ea9SDavid C Somayajulu fwqe2->length_lo = mr->ibmr.length;
4163fa790ea9SDavid C Somayajulu fwqe2->pbl_addr.hi = upper_32_bits(mr->info.pbl_table->pa);
4164fa790ea9SDavid C Somayajulu fwqe2->pbl_addr.lo = lower_32_bits(mr->info.pbl_table->pa);
4165fa790ea9SDavid C Somayajulu
4166fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].mr = mr;
4167fa790ea9SDavid C Somayajulu
4168fa790ea9SDavid C Somayajulu return 0;
4169fa790ea9SDavid C Somayajulu }
4170fa790ea9SDavid C Somayajulu
4171fa790ea9SDavid C Somayajulu static enum ib_wc_opcode
qlnxr_ib_to_wc_opcode(enum ib_wr_opcode opcode)4172fa790ea9SDavid C Somayajulu qlnxr_ib_to_wc_opcode(enum ib_wr_opcode opcode)
4173fa790ea9SDavid C Somayajulu {
4174fa790ea9SDavid C Somayajulu switch (opcode) {
4175fa790ea9SDavid C Somayajulu case IB_WR_RDMA_WRITE:
4176fa790ea9SDavid C Somayajulu case IB_WR_RDMA_WRITE_WITH_IMM:
4177fa790ea9SDavid C Somayajulu return IB_WC_RDMA_WRITE;
4178fa790ea9SDavid C Somayajulu case IB_WR_SEND_WITH_IMM:
4179fa790ea9SDavid C Somayajulu case IB_WR_SEND:
4180fa790ea9SDavid C Somayajulu case IB_WR_SEND_WITH_INV:
4181fa790ea9SDavid C Somayajulu return IB_WC_SEND;
4182fa790ea9SDavid C Somayajulu case IB_WR_RDMA_READ:
4183fa790ea9SDavid C Somayajulu return IB_WC_RDMA_READ;
4184fa790ea9SDavid C Somayajulu case IB_WR_ATOMIC_CMP_AND_SWP:
4185fa790ea9SDavid C Somayajulu return IB_WC_COMP_SWAP;
4186fa790ea9SDavid C Somayajulu case IB_WR_ATOMIC_FETCH_AND_ADD:
4187fa790ea9SDavid C Somayajulu return IB_WC_FETCH_ADD;
4188fa790ea9SDavid C Somayajulu case IB_WR_REG_MR:
4189fa790ea9SDavid C Somayajulu return IB_WC_REG_MR;
4190fa790ea9SDavid C Somayajulu case IB_WR_LOCAL_INV:
4191fa790ea9SDavid C Somayajulu return IB_WC_LOCAL_INV;
4192fa790ea9SDavid C Somayajulu default:
4193fa790ea9SDavid C Somayajulu return IB_WC_SEND;
4194fa790ea9SDavid C Somayajulu }
4195fa790ea9SDavid C Somayajulu }
4196fa790ea9SDavid C Somayajulu static inline bool
qlnxr_can_post_send(struct qlnxr_qp * qp,const struct ib_send_wr * wr)4197c3987b8eSHans Petter Selasky qlnxr_can_post_send(struct qlnxr_qp *qp, const struct ib_send_wr *wr)
4198fa790ea9SDavid C Somayajulu {
4199fa790ea9SDavid C Somayajulu int wq_is_full, err_wr, pbl_is_full;
4200fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = qp->dev;
4201fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
4202fa790ea9SDavid C Somayajulu
4203fa790ea9SDavid C Somayajulu ha = dev->ha;
4204fa790ea9SDavid C Somayajulu
4205fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter[qp, wr] = [%p,%p]\n", qp, wr);
4206fa790ea9SDavid C Somayajulu
4207fa790ea9SDavid C Somayajulu /* prevent SQ overflow and/or processing of a bad WR */
4208fa790ea9SDavid C Somayajulu err_wr = wr->num_sge > qp->sq.max_sges;
4209fa790ea9SDavid C Somayajulu wq_is_full = qlnxr_wq_is_full(&qp->sq);
4210fa790ea9SDavid C Somayajulu pbl_is_full = ecore_chain_get_elem_left_u32(&qp->sq.pbl) <
4211fa790ea9SDavid C Somayajulu QLNXR_MAX_SQE_ELEMENTS_PER_SQE;
4212fa790ea9SDavid C Somayajulu if (wq_is_full || err_wr || pbl_is_full) {
4213fa790ea9SDavid C Somayajulu if (wq_is_full &&
4214fa790ea9SDavid C Somayajulu !(qp->err_bitmap & QLNXR_QP_ERR_SQ_FULL)) {
4215fa790ea9SDavid C Somayajulu qp->err_bitmap |= QLNXR_QP_ERR_SQ_FULL;
4216fa790ea9SDavid C Somayajulu
4217fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
4218fa790ea9SDavid C Somayajulu "error: WQ is full. Post send on QP failed"
4219fa790ea9SDavid C Somayajulu " (this error appears only once) "
4220fa790ea9SDavid C Somayajulu "[qp, wr, qp->err_bitmap]=[%p, %p, 0x%x]\n",
4221fa790ea9SDavid C Somayajulu qp, wr, qp->err_bitmap);
4222fa790ea9SDavid C Somayajulu }
4223fa790ea9SDavid C Somayajulu
4224fa790ea9SDavid C Somayajulu if (err_wr &&
4225fa790ea9SDavid C Somayajulu !(qp->err_bitmap & QLNXR_QP_ERR_BAD_SR)) {
4226fa790ea9SDavid C Somayajulu qp->err_bitmap |= QLNXR_QP_ERR_BAD_SR;
4227fa790ea9SDavid C Somayajulu
4228fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
4229fa790ea9SDavid C Somayajulu "error: WQ is bad. Post send on QP failed"
4230fa790ea9SDavid C Somayajulu " (this error appears only once) "
4231fa790ea9SDavid C Somayajulu "[qp, wr, qp->err_bitmap]=[%p, %p, 0x%x]\n",
4232fa790ea9SDavid C Somayajulu qp, wr, qp->err_bitmap);
4233fa790ea9SDavid C Somayajulu }
4234fa790ea9SDavid C Somayajulu
4235fa790ea9SDavid C Somayajulu if (pbl_is_full &&
4236fa790ea9SDavid C Somayajulu !(qp->err_bitmap & QLNXR_QP_ERR_SQ_PBL_FULL)) {
4237fa790ea9SDavid C Somayajulu qp->err_bitmap |= QLNXR_QP_ERR_SQ_PBL_FULL;
4238fa790ea9SDavid C Somayajulu
4239fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
4240fa790ea9SDavid C Somayajulu "error: WQ PBL is full. Post send on QP failed"
4241fa790ea9SDavid C Somayajulu " (this error appears only once) "
4242fa790ea9SDavid C Somayajulu "[qp, wr, qp->err_bitmap]=[%p, %p, 0x%x]\n",
4243fa790ea9SDavid C Somayajulu qp, wr, qp->err_bitmap);
4244fa790ea9SDavid C Somayajulu }
4245fa790ea9SDavid C Somayajulu return false;
4246fa790ea9SDavid C Somayajulu }
4247fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit[qp, wr] = [%p,%p]\n", qp, wr);
4248fa790ea9SDavid C Somayajulu return true;
4249fa790ea9SDavid C Somayajulu }
4250fa790ea9SDavid C Somayajulu
4251fa790ea9SDavid C Somayajulu int
qlnxr_post_send(struct ib_qp * ibqp,const struct ib_send_wr * wr,const struct ib_send_wr ** bad_wr)4252fa790ea9SDavid C Somayajulu qlnxr_post_send(struct ib_qp *ibqp,
4253c3987b8eSHans Petter Selasky const struct ib_send_wr *wr,
4254c3987b8eSHans Petter Selasky const struct ib_send_wr **bad_wr)
4255fa790ea9SDavid C Somayajulu {
4256fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev(ibqp->device);
4257fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp = get_qlnxr_qp(ibqp);
4258fa790ea9SDavid C Somayajulu unsigned long flags;
4259fa790ea9SDavid C Somayajulu int status = 0, rc = 0;
4260fa790ea9SDavid C Somayajulu bool comp;
4261fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
4262fa790ea9SDavid C Somayajulu uint32_t reg_addr;
4263fa790ea9SDavid C Somayajulu
4264fa790ea9SDavid C Somayajulu *bad_wr = NULL;
4265fa790ea9SDavid C Somayajulu ha = dev->ha;
4266fa790ea9SDavid C Somayajulu
4267fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit[ibqp, wr, bad_wr] = [%p, %p, %p]\n",
4268fa790ea9SDavid C Somayajulu ibqp, wr, bad_wr);
4269fa790ea9SDavid C Somayajulu
4270*727bfe38SJustin Hibbits if (!(if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING))
4271fa790ea9SDavid C Somayajulu return -EINVAL;
4272fa790ea9SDavid C Somayajulu
4273fa790ea9SDavid C Somayajulu if (qp->qp_type == IB_QPT_GSI)
4274fa790ea9SDavid C Somayajulu return qlnxr_gsi_post_send(ibqp, wr, bad_wr);
4275fa790ea9SDavid C Somayajulu
4276fa790ea9SDavid C Somayajulu spin_lock_irqsave(&qp->q_lock, flags);
4277fa790ea9SDavid C Somayajulu
4278fa790ea9SDavid C Somayajulu if (QLNX_IS_ROCE(dev) && (qp->state != ECORE_ROCE_QP_STATE_RTS) &&
4279fa790ea9SDavid C Somayajulu (qp->state != ECORE_ROCE_QP_STATE_ERR) &&
4280fa790ea9SDavid C Somayajulu (qp->state != ECORE_ROCE_QP_STATE_SQD)) {
4281fa790ea9SDavid C Somayajulu spin_unlock_irqrestore(&qp->q_lock, flags);
4282fa790ea9SDavid C Somayajulu *bad_wr = wr;
4283fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "QP in wrong state! QP icid=0x%x state %d\n",
4284fa790ea9SDavid C Somayajulu qp->icid, qp->state);
4285fa790ea9SDavid C Somayajulu return -EINVAL;
4286fa790ea9SDavid C Somayajulu }
4287fa790ea9SDavid C Somayajulu
4288fa790ea9SDavid C Somayajulu if (!wr) {
4289fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "Got an empty post send???\n");
4290fa790ea9SDavid C Somayajulu }
4291fa790ea9SDavid C Somayajulu
4292fa790ea9SDavid C Somayajulu while (wr) {
4293fa790ea9SDavid C Somayajulu struct rdma_sq_common_wqe *wqe;
4294fa790ea9SDavid C Somayajulu struct rdma_sq_send_wqe *swqe;
4295fa790ea9SDavid C Somayajulu struct rdma_sq_send_wqe *swqe2;
4296fa790ea9SDavid C Somayajulu struct rdma_sq_rdma_wqe_1st *rwqe;
4297fa790ea9SDavid C Somayajulu struct rdma_sq_rdma_wqe_2nd *rwqe2;
4298fa790ea9SDavid C Somayajulu struct rdma_sq_local_inv_wqe *iwqe;
4299fa790ea9SDavid C Somayajulu struct rdma_sq_atomic_wqe *awqe1;
4300fa790ea9SDavid C Somayajulu struct rdma_sq_atomic_wqe *awqe2;
4301fa790ea9SDavid C Somayajulu struct rdma_sq_atomic_wqe *awqe3;
4302fa790ea9SDavid C Somayajulu struct rdma_sq_fmr_wqe_1st *fwqe1;
4303fa790ea9SDavid C Somayajulu
4304fa790ea9SDavid C Somayajulu if (!qlnxr_can_post_send(qp, wr)) {
4305fa790ea9SDavid C Somayajulu status = -ENOMEM;
4306fa790ea9SDavid C Somayajulu *bad_wr = wr;
4307fa790ea9SDavid C Somayajulu break;
4308fa790ea9SDavid C Somayajulu }
4309fa790ea9SDavid C Somayajulu
4310fa790ea9SDavid C Somayajulu wqe = ecore_chain_produce(&qp->sq.pbl);
4311fa790ea9SDavid C Somayajulu
4312fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].signaled =
4313fa790ea9SDavid C Somayajulu !!(wr->send_flags & IB_SEND_SIGNALED) || qp->signaled;
4314fa790ea9SDavid C Somayajulu
4315fa790ea9SDavid C Somayajulu /* common fields */
4316fa790ea9SDavid C Somayajulu wqe->flags = 0;
4317fa790ea9SDavid C Somayajulu wqe->flags |= (RDMA_SQ_SEND_WQE_COMP_FLG_MASK <<
4318fa790ea9SDavid C Somayajulu RDMA_SQ_SEND_WQE_COMP_FLG_SHIFT);
4319fa790ea9SDavid C Somayajulu
4320fa790ea9SDavid C Somayajulu SET_FIELD2(wqe->flags, RDMA_SQ_SEND_WQE_SE_FLG, \
4321fa790ea9SDavid C Somayajulu !!(wr->send_flags & IB_SEND_SOLICITED));
4322fa790ea9SDavid C Somayajulu
4323fa790ea9SDavid C Somayajulu comp = (!!(wr->send_flags & IB_SEND_SIGNALED)) ||
4324fa790ea9SDavid C Somayajulu (qp->signaled);
4325fa790ea9SDavid C Somayajulu
4326fa790ea9SDavid C Somayajulu SET_FIELD2(wqe->flags, RDMA_SQ_SEND_WQE_COMP_FLG, comp);
4327fa790ea9SDavid C Somayajulu SET_FIELD2(wqe->flags, RDMA_SQ_SEND_WQE_RD_FENCE_FLG, \
4328fa790ea9SDavid C Somayajulu !!(wr->send_flags & IB_SEND_FENCE));
4329fa790ea9SDavid C Somayajulu
4330fa790ea9SDavid C Somayajulu wqe->prev_wqe_size = qp->prev_wqe_size;
4331fa790ea9SDavid C Somayajulu
4332fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].opcode = qlnxr_ib_to_wc_opcode(wr->opcode);
4333fa790ea9SDavid C Somayajulu
4334fa790ea9SDavid C Somayajulu switch (wr->opcode) {
4335fa790ea9SDavid C Somayajulu case IB_WR_SEND_WITH_IMM:
4336fa790ea9SDavid C Somayajulu
4337fa790ea9SDavid C Somayajulu wqe->req_type = RDMA_SQ_REQ_TYPE_SEND_WITH_IMM;
4338fa790ea9SDavid C Somayajulu swqe = (struct rdma_sq_send_wqe *)wqe;
4339fa790ea9SDavid C Somayajulu swqe->wqe_size = 2;
4340fa790ea9SDavid C Somayajulu swqe2 = (struct rdma_sq_send_wqe *)
4341fa790ea9SDavid C Somayajulu ecore_chain_produce(&qp->sq.pbl);
4342fa790ea9SDavid C Somayajulu swqe->inv_key_or_imm_data =
4343fa790ea9SDavid C Somayajulu cpu_to_le32(wr->ex.imm_data);
4344fa790ea9SDavid C Somayajulu swqe->length = cpu_to_le32(
4345fa790ea9SDavid C Somayajulu qlnxr_prepare_sq_send_data(dev,
4346fa790ea9SDavid C Somayajulu qp, swqe, swqe2, wr,
4347fa790ea9SDavid C Somayajulu bad_wr));
4348fa790ea9SDavid C Somayajulu
4349fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wqe_size = swqe->wqe_size;
4350fa790ea9SDavid C Somayajulu qp->prev_wqe_size = swqe->wqe_size;
4351fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].bytes_len = swqe->length;
4352fa790ea9SDavid C Somayajulu
4353fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "SEND w/ IMM length = %d imm data=%x\n",
4354fa790ea9SDavid C Somayajulu swqe->length, wr->ex.imm_data);
4355fa790ea9SDavid C Somayajulu
4356fa790ea9SDavid C Somayajulu break;
4357fa790ea9SDavid C Somayajulu
4358fa790ea9SDavid C Somayajulu case IB_WR_SEND:
4359fa790ea9SDavid C Somayajulu
4360fa790ea9SDavid C Somayajulu wqe->req_type = RDMA_SQ_REQ_TYPE_SEND;
4361fa790ea9SDavid C Somayajulu swqe = (struct rdma_sq_send_wqe *)wqe;
4362fa790ea9SDavid C Somayajulu
4363fa790ea9SDavid C Somayajulu swqe->wqe_size = 2;
4364fa790ea9SDavid C Somayajulu swqe2 = (struct rdma_sq_send_wqe *)
4365fa790ea9SDavid C Somayajulu ecore_chain_produce(&qp->sq.pbl);
4366fa790ea9SDavid C Somayajulu swqe->length = cpu_to_le32(
4367fa790ea9SDavid C Somayajulu qlnxr_prepare_sq_send_data(dev,
4368fa790ea9SDavid C Somayajulu qp, swqe, swqe2, wr,
4369fa790ea9SDavid C Somayajulu bad_wr));
4370fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wqe_size = swqe->wqe_size;
4371fa790ea9SDavid C Somayajulu qp->prev_wqe_size = swqe->wqe_size;
4372fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].bytes_len = swqe->length;
4373fa790ea9SDavid C Somayajulu
4374fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "SEND w/o IMM length = %d\n",
4375fa790ea9SDavid C Somayajulu swqe->length);
4376fa790ea9SDavid C Somayajulu
4377fa790ea9SDavid C Somayajulu break;
4378fa790ea9SDavid C Somayajulu
4379fa790ea9SDavid C Somayajulu case IB_WR_SEND_WITH_INV:
4380fa790ea9SDavid C Somayajulu
4381fa790ea9SDavid C Somayajulu wqe->req_type = RDMA_SQ_REQ_TYPE_SEND_WITH_INVALIDATE;
4382fa790ea9SDavid C Somayajulu swqe = (struct rdma_sq_send_wqe *)wqe;
4383fa790ea9SDavid C Somayajulu swqe2 = (struct rdma_sq_send_wqe *)
4384fa790ea9SDavid C Somayajulu ecore_chain_produce(&qp->sq.pbl);
4385fa790ea9SDavid C Somayajulu swqe->wqe_size = 2;
4386fa790ea9SDavid C Somayajulu swqe->inv_key_or_imm_data =
4387fa790ea9SDavid C Somayajulu cpu_to_le32(wr->ex.invalidate_rkey);
4388fa790ea9SDavid C Somayajulu swqe->length = cpu_to_le32(qlnxr_prepare_sq_send_data(dev,
4389fa790ea9SDavid C Somayajulu qp, swqe, swqe2, wr, bad_wr));
4390fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wqe_size = swqe->wqe_size;
4391fa790ea9SDavid C Somayajulu qp->prev_wqe_size = swqe->wqe_size;
4392fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].bytes_len = swqe->length;
4393fa790ea9SDavid C Somayajulu
4394fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "SEND w INVALIDATE length = %d\n",
4395fa790ea9SDavid C Somayajulu swqe->length);
4396fa790ea9SDavid C Somayajulu break;
4397fa790ea9SDavid C Somayajulu
4398fa790ea9SDavid C Somayajulu case IB_WR_RDMA_WRITE_WITH_IMM:
4399fa790ea9SDavid C Somayajulu
4400fa790ea9SDavid C Somayajulu wqe->req_type = RDMA_SQ_REQ_TYPE_RDMA_WR_WITH_IMM;
4401fa790ea9SDavid C Somayajulu rwqe = (struct rdma_sq_rdma_wqe_1st *)wqe;
4402fa790ea9SDavid C Somayajulu
4403fa790ea9SDavid C Somayajulu rwqe->wqe_size = 2;
4404fa790ea9SDavid C Somayajulu rwqe->imm_data = htonl(cpu_to_le32(wr->ex.imm_data));
4405fa790ea9SDavid C Somayajulu rwqe2 = (struct rdma_sq_rdma_wqe_2nd *)
4406fa790ea9SDavid C Somayajulu ecore_chain_produce(&qp->sq.pbl);
4407fa790ea9SDavid C Somayajulu rwqe->length = cpu_to_le32(qlnxr_prepare_sq_rdma_data(dev,
4408fa790ea9SDavid C Somayajulu qp, rwqe, rwqe2, wr, bad_wr));
4409fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wqe_size = rwqe->wqe_size;
4410fa790ea9SDavid C Somayajulu qp->prev_wqe_size = rwqe->wqe_size;
4411fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].bytes_len = rwqe->length;
4412fa790ea9SDavid C Somayajulu
4413fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
4414fa790ea9SDavid C Somayajulu "RDMA WRITE w/ IMM length = %d imm data=%x\n",
4415fa790ea9SDavid C Somayajulu rwqe->length, rwqe->imm_data);
4416fa790ea9SDavid C Somayajulu
4417fa790ea9SDavid C Somayajulu break;
4418fa790ea9SDavid C Somayajulu
4419fa790ea9SDavid C Somayajulu case IB_WR_RDMA_WRITE:
4420fa790ea9SDavid C Somayajulu
4421fa790ea9SDavid C Somayajulu wqe->req_type = RDMA_SQ_REQ_TYPE_RDMA_WR;
4422fa790ea9SDavid C Somayajulu rwqe = (struct rdma_sq_rdma_wqe_1st *)wqe;
4423fa790ea9SDavid C Somayajulu
4424fa790ea9SDavid C Somayajulu rwqe->wqe_size = 2;
4425fa790ea9SDavid C Somayajulu rwqe2 = (struct rdma_sq_rdma_wqe_2nd *)
4426fa790ea9SDavid C Somayajulu ecore_chain_produce(&qp->sq.pbl);
4427fa790ea9SDavid C Somayajulu rwqe->length = cpu_to_le32(qlnxr_prepare_sq_rdma_data(dev,
4428fa790ea9SDavid C Somayajulu qp, rwqe, rwqe2, wr, bad_wr));
4429fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wqe_size = rwqe->wqe_size;
4430fa790ea9SDavid C Somayajulu qp->prev_wqe_size = rwqe->wqe_size;
4431fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].bytes_len = rwqe->length;
4432fa790ea9SDavid C Somayajulu
4433fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
4434fa790ea9SDavid C Somayajulu "RDMA WRITE w/o IMM length = %d\n",
4435fa790ea9SDavid C Somayajulu rwqe->length);
4436fa790ea9SDavid C Somayajulu
4437fa790ea9SDavid C Somayajulu break;
4438fa790ea9SDavid C Somayajulu
4439fa790ea9SDavid C Somayajulu case IB_WR_RDMA_READ_WITH_INV:
4440fa790ea9SDavid C Somayajulu
4441fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
4442fa790ea9SDavid C Somayajulu "RDMA READ WITH INVALIDATE not supported\n");
4443fa790ea9SDavid C Somayajulu
4444fa790ea9SDavid C Somayajulu *bad_wr = wr;
4445fa790ea9SDavid C Somayajulu rc = -EINVAL;
4446fa790ea9SDavid C Somayajulu
4447fa790ea9SDavid C Somayajulu break;
4448fa790ea9SDavid C Somayajulu
4449fa790ea9SDavid C Somayajulu case IB_WR_RDMA_READ:
4450fa790ea9SDavid C Somayajulu
4451fa790ea9SDavid C Somayajulu wqe->req_type = RDMA_SQ_REQ_TYPE_RDMA_RD;
4452fa790ea9SDavid C Somayajulu rwqe = (struct rdma_sq_rdma_wqe_1st *)wqe;
4453fa790ea9SDavid C Somayajulu
4454fa790ea9SDavid C Somayajulu rwqe->wqe_size = 2;
4455fa790ea9SDavid C Somayajulu rwqe2 = (struct rdma_sq_rdma_wqe_2nd *)
4456fa790ea9SDavid C Somayajulu ecore_chain_produce(&qp->sq.pbl);
4457fa790ea9SDavid C Somayajulu rwqe->length = cpu_to_le32(qlnxr_prepare_sq_rdma_data(dev,
4458fa790ea9SDavid C Somayajulu qp, rwqe, rwqe2, wr, bad_wr));
4459fa790ea9SDavid C Somayajulu
4460fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wqe_size = rwqe->wqe_size;
4461fa790ea9SDavid C Somayajulu qp->prev_wqe_size = rwqe->wqe_size;
4462fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].bytes_len = rwqe->length;
4463fa790ea9SDavid C Somayajulu
4464fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "RDMA READ length = %d\n",
4465fa790ea9SDavid C Somayajulu rwqe->length);
4466fa790ea9SDavid C Somayajulu
4467fa790ea9SDavid C Somayajulu break;
4468fa790ea9SDavid C Somayajulu
4469fa790ea9SDavid C Somayajulu case IB_WR_ATOMIC_CMP_AND_SWP:
4470fa790ea9SDavid C Somayajulu case IB_WR_ATOMIC_FETCH_AND_ADD:
4471fa790ea9SDavid C Somayajulu
4472fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
4473fa790ea9SDavid C Somayajulu "ATOMIC operation = %s\n",
4474fa790ea9SDavid C Somayajulu ((wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) ?
4475fa790ea9SDavid C Somayajulu "IB_WR_ATOMIC_CMP_AND_SWP" :
4476fa790ea9SDavid C Somayajulu "IB_WR_ATOMIC_FETCH_AND_ADD"));
4477fa790ea9SDavid C Somayajulu
4478fa790ea9SDavid C Somayajulu awqe1 = (struct rdma_sq_atomic_wqe *)wqe;
4479fa790ea9SDavid C Somayajulu awqe1->prev_wqe_size = 4;
4480fa790ea9SDavid C Somayajulu
4481fa790ea9SDavid C Somayajulu awqe2 = (struct rdma_sq_atomic_wqe *)
4482fa790ea9SDavid C Somayajulu ecore_chain_produce(&qp->sq.pbl);
4483fa790ea9SDavid C Somayajulu
4484fa790ea9SDavid C Somayajulu TYPEPTR_ADDR_SET(awqe2, remote_va, \
4485fa790ea9SDavid C Somayajulu atomic_wr(wr)->remote_addr);
4486fa790ea9SDavid C Somayajulu
4487fa790ea9SDavid C Somayajulu awqe2->r_key = cpu_to_le32(atomic_wr(wr)->rkey);
4488fa790ea9SDavid C Somayajulu
4489fa790ea9SDavid C Somayajulu awqe3 = (struct rdma_sq_atomic_wqe *)
4490fa790ea9SDavid C Somayajulu ecore_chain_produce(&qp->sq.pbl);
4491fa790ea9SDavid C Somayajulu
4492fa790ea9SDavid C Somayajulu if (wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) {
4493fa790ea9SDavid C Somayajulu wqe->req_type = RDMA_SQ_REQ_TYPE_ATOMIC_ADD;
4494fa790ea9SDavid C Somayajulu TYPEPTR_ADDR_SET(awqe3, swap_data,
4495fa790ea9SDavid C Somayajulu atomic_wr(wr)->compare_add);
4496fa790ea9SDavid C Somayajulu } else {
4497fa790ea9SDavid C Somayajulu wqe->req_type = RDMA_SQ_REQ_TYPE_ATOMIC_CMP_AND_SWAP;
4498fa790ea9SDavid C Somayajulu TYPEPTR_ADDR_SET(awqe3, swap_data,
4499fa790ea9SDavid C Somayajulu atomic_wr(wr)->swap);
4500fa790ea9SDavid C Somayajulu TYPEPTR_ADDR_SET(awqe3, cmp_data,
4501fa790ea9SDavid C Somayajulu atomic_wr(wr)->compare_add);
4502fa790ea9SDavid C Somayajulu }
4503fa790ea9SDavid C Somayajulu
4504fa790ea9SDavid C Somayajulu qlnxr_prepare_sq_sges(dev, qp, NULL, wr);
4505fa790ea9SDavid C Somayajulu
4506fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wqe_size = awqe1->prev_wqe_size;
4507fa790ea9SDavid C Somayajulu qp->prev_wqe_size = awqe1->prev_wqe_size;
4508fa790ea9SDavid C Somayajulu
4509fa790ea9SDavid C Somayajulu break;
4510fa790ea9SDavid C Somayajulu
4511fa790ea9SDavid C Somayajulu case IB_WR_LOCAL_INV:
4512fa790ea9SDavid C Somayajulu
4513fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
4514fa790ea9SDavid C Somayajulu "INVALIDATE length (IB_WR_LOCAL_INV)\n");
4515fa790ea9SDavid C Somayajulu
4516fa790ea9SDavid C Somayajulu iwqe = (struct rdma_sq_local_inv_wqe *)wqe;
4517fa790ea9SDavid C Somayajulu iwqe->prev_wqe_size = 1;
4518fa790ea9SDavid C Somayajulu
4519fa790ea9SDavid C Somayajulu iwqe->req_type = RDMA_SQ_REQ_TYPE_LOCAL_INVALIDATE;
4520fa790ea9SDavid C Somayajulu iwqe->inv_l_key = wr->ex.invalidate_rkey;
4521fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wqe_size = iwqe->prev_wqe_size;
4522fa790ea9SDavid C Somayajulu qp->prev_wqe_size = iwqe->prev_wqe_size;
4523fa790ea9SDavid C Somayajulu
4524fa790ea9SDavid C Somayajulu break;
4525fa790ea9SDavid C Somayajulu
4526fa790ea9SDavid C Somayajulu case IB_WR_REG_MR:
4527fa790ea9SDavid C Somayajulu
4528fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "IB_WR_REG_MR\n");
4529fa790ea9SDavid C Somayajulu
4530fa790ea9SDavid C Somayajulu wqe->req_type = RDMA_SQ_REQ_TYPE_FAST_MR;
4531fa790ea9SDavid C Somayajulu fwqe1 = (struct rdma_sq_fmr_wqe_1st *)wqe;
4532fa790ea9SDavid C Somayajulu fwqe1->wqe_size = 2;
4533fa790ea9SDavid C Somayajulu
4534fa790ea9SDavid C Somayajulu rc = qlnxr_prepare_reg(qp, fwqe1, reg_wr(wr));
4535fa790ea9SDavid C Somayajulu if (rc) {
4536fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "IB_WR_REG_MR failed rc=%d\n", rc);
4537fa790ea9SDavid C Somayajulu *bad_wr = wr;
4538fa790ea9SDavid C Somayajulu break;
4539fa790ea9SDavid C Somayajulu }
4540fa790ea9SDavid C Somayajulu
4541fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wqe_size = fwqe1->wqe_size;
4542fa790ea9SDavid C Somayajulu qp->prev_wqe_size = fwqe1->wqe_size;
4543fa790ea9SDavid C Somayajulu
4544fa790ea9SDavid C Somayajulu break;
4545fa790ea9SDavid C Somayajulu
4546fa790ea9SDavid C Somayajulu default:
4547fa790ea9SDavid C Somayajulu
4548fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "Invalid Opcode 0x%x!\n", wr->opcode);
4549fa790ea9SDavid C Somayajulu
4550fa790ea9SDavid C Somayajulu rc = -EINVAL;
4551fa790ea9SDavid C Somayajulu *bad_wr = wr;
4552fa790ea9SDavid C Somayajulu break;
4553fa790ea9SDavid C Somayajulu }
4554fa790ea9SDavid C Somayajulu
4555fa790ea9SDavid C Somayajulu if (*bad_wr) {
4556fa790ea9SDavid C Somayajulu /*
4557fa790ea9SDavid C Somayajulu * restore prod to its position before this WR was processed
4558fa790ea9SDavid C Somayajulu */
4559fa790ea9SDavid C Somayajulu ecore_chain_set_prod(&qp->sq.pbl,
4560fa790ea9SDavid C Somayajulu le16_to_cpu(qp->sq.db_data.data.value),
4561fa790ea9SDavid C Somayajulu wqe);
4562fa790ea9SDavid C Somayajulu /* restore prev_wqe_size */
4563fa790ea9SDavid C Somayajulu qp->prev_wqe_size = wqe->prev_wqe_size;
4564fa790ea9SDavid C Somayajulu status = rc;
4565fa790ea9SDavid C Somayajulu
4566fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "failed *bad_wr = %p\n", *bad_wr);
4567fa790ea9SDavid C Somayajulu break; /* out of the loop */
4568fa790ea9SDavid C Somayajulu }
4569fa790ea9SDavid C Somayajulu
4570fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.prod].wr_id = wr->wr_id;
4571fa790ea9SDavid C Somayajulu
4572fa790ea9SDavid C Somayajulu qlnxr_inc_sw_prod(&qp->sq);
4573fa790ea9SDavid C Somayajulu
4574fa790ea9SDavid C Somayajulu qp->sq.db_data.data.value++;
4575fa790ea9SDavid C Somayajulu
4576fa790ea9SDavid C Somayajulu wr = wr->next;
4577fa790ea9SDavid C Somayajulu }
4578fa790ea9SDavid C Somayajulu
4579fa790ea9SDavid C Somayajulu /* Trigger doorbell
4580fa790ea9SDavid C Somayajulu * If there was a failure in the first WR then it will be triggered in
4581fa790ea9SDavid C Somayajulu * vane. However this is not harmful (as long as the producer value is
4582fa790ea9SDavid C Somayajulu * unchanged). For performance reasons we avoid checking for this
4583fa790ea9SDavid C Somayajulu * redundant doorbell.
4584fa790ea9SDavid C Somayajulu */
4585fa790ea9SDavid C Somayajulu wmb();
4586fa790ea9SDavid C Somayajulu //writel(qp->sq.db_data.raw, qp->sq.db);
4587fa790ea9SDavid C Somayajulu
4588fa790ea9SDavid C Somayajulu reg_addr = (uint32_t)((uint8_t *)qp->sq.db - (uint8_t *)ha->cdev.doorbells);
4589fa790ea9SDavid C Somayajulu bus_write_4(ha->pci_dbells, reg_addr, qp->sq.db_data.raw);
4590fa790ea9SDavid C Somayajulu bus_barrier(ha->pci_dbells, 0, 0, BUS_SPACE_BARRIER_READ);
4591fa790ea9SDavid C Somayajulu
4592fa790ea9SDavid C Somayajulu mmiowb();
4593fa790ea9SDavid C Somayajulu
4594fa790ea9SDavid C Somayajulu spin_unlock_irqrestore(&qp->q_lock, flags);
4595fa790ea9SDavid C Somayajulu
4596fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit[ibqp, wr, bad_wr] = [%p, %p, %p]\n",
4597fa790ea9SDavid C Somayajulu ibqp, wr, bad_wr);
4598fa790ea9SDavid C Somayajulu
4599fa790ea9SDavid C Somayajulu return status;
4600fa790ea9SDavid C Somayajulu }
4601fa790ea9SDavid C Somayajulu
4602fa790ea9SDavid C Somayajulu static u32
qlnxr_srq_elem_left(struct qlnxr_srq_hwq_info * hw_srq)4603fa790ea9SDavid C Somayajulu qlnxr_srq_elem_left(struct qlnxr_srq_hwq_info *hw_srq)
4604fa790ea9SDavid C Somayajulu {
4605fa790ea9SDavid C Somayajulu u32 used;
4606fa790ea9SDavid C Somayajulu
4607fa790ea9SDavid C Somayajulu /* Calculate number of elements used based on producer
4608fa790ea9SDavid C Somayajulu * count and consumer count and subtract it from max
4609fa790ea9SDavid C Somayajulu * work request supported so that we get elements left.
4610fa790ea9SDavid C Somayajulu */
4611fa790ea9SDavid C Somayajulu used = hw_srq->wr_prod_cnt - hw_srq->wr_cons_cnt;
4612fa790ea9SDavid C Somayajulu
4613fa790ea9SDavid C Somayajulu return hw_srq->max_wr - used;
4614fa790ea9SDavid C Somayajulu }
4615fa790ea9SDavid C Somayajulu
4616fa790ea9SDavid C Somayajulu int
qlnxr_post_recv(struct ib_qp * ibqp,const struct ib_recv_wr * wr,const struct ib_recv_wr ** bad_wr)4617fa790ea9SDavid C Somayajulu qlnxr_post_recv(struct ib_qp *ibqp,
4618c3987b8eSHans Petter Selasky const struct ib_recv_wr *wr,
4619c3987b8eSHans Petter Selasky const struct ib_recv_wr **bad_wr)
4620fa790ea9SDavid C Somayajulu {
4621fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp = get_qlnxr_qp(ibqp);
4622fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = qp->dev;
4623fa790ea9SDavid C Somayajulu unsigned long flags;
4624fa790ea9SDavid C Somayajulu int status = 0;
4625fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
4626fa790ea9SDavid C Somayajulu uint32_t reg_addr;
4627fa790ea9SDavid C Somayajulu
4628fa790ea9SDavid C Somayajulu ha = dev->ha;
4629fa790ea9SDavid C Somayajulu
4630*727bfe38SJustin Hibbits if (!(if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING))
4631fa790ea9SDavid C Somayajulu return -EINVAL;
4632fa790ea9SDavid C Somayajulu
4633fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
4634fa790ea9SDavid C Somayajulu
4635fa790ea9SDavid C Somayajulu if (qp->qp_type == IB_QPT_GSI) {
4636fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "(qp->qp_type = IB_QPT_GSI)\n");
4637fa790ea9SDavid C Somayajulu return qlnxr_gsi_post_recv(ibqp, wr, bad_wr);
4638fa790ea9SDavid C Somayajulu }
4639fa790ea9SDavid C Somayajulu
4640fa790ea9SDavid C Somayajulu if (qp->srq) {
4641fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qp->srq [%p]"
4642fa790ea9SDavid C Somayajulu " QP is associated with SRQ, cannot post RQ buffers\n",
4643fa790ea9SDavid C Somayajulu qp->srq);
4644fa790ea9SDavid C Somayajulu return -EINVAL;
4645fa790ea9SDavid C Somayajulu }
4646fa790ea9SDavid C Somayajulu
4647fa790ea9SDavid C Somayajulu spin_lock_irqsave(&qp->q_lock, flags);
4648fa790ea9SDavid C Somayajulu
4649fa790ea9SDavid C Somayajulu if (qp->state == ECORE_ROCE_QP_STATE_RESET) {
4650fa790ea9SDavid C Somayajulu spin_unlock_irqrestore(&qp->q_lock, flags);
4651fa790ea9SDavid C Somayajulu *bad_wr = wr;
4652fa790ea9SDavid C Somayajulu
4653fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qp->qp_type = ECORE_ROCE_QP_STATE_RESET\n");
4654fa790ea9SDavid C Somayajulu
4655fa790ea9SDavid C Somayajulu return -EINVAL;
4656fa790ea9SDavid C Somayajulu }
4657fa790ea9SDavid C Somayajulu
4658fa790ea9SDavid C Somayajulu while (wr) {
4659fa790ea9SDavid C Somayajulu int i;
4660fa790ea9SDavid C Somayajulu
4661fa790ea9SDavid C Somayajulu if ((ecore_chain_get_elem_left_u32(&qp->rq.pbl) <
4662fa790ea9SDavid C Somayajulu QLNXR_MAX_RQE_ELEMENTS_PER_RQE) ||
4663fa790ea9SDavid C Somayajulu (wr->num_sge > qp->rq.max_sges)) {
4664fa790ea9SDavid C Somayajulu status = -ENOMEM;
4665fa790ea9SDavid C Somayajulu *bad_wr = wr;
4666fa790ea9SDavid C Somayajulu break;
4667fa790ea9SDavid C Somayajulu }
4668fa790ea9SDavid C Somayajulu for (i = 0; i < wr->num_sge; i++) {
4669fa790ea9SDavid C Somayajulu u32 flags = 0;
4670fa790ea9SDavid C Somayajulu struct rdma_rq_sge *rqe = ecore_chain_produce(&qp->rq.pbl);
4671fa790ea9SDavid C Somayajulu
4672fa790ea9SDavid C Somayajulu /* first one must include the number of SGE in the list */
4673fa790ea9SDavid C Somayajulu if (!i)
4674fa790ea9SDavid C Somayajulu SET_FIELD(flags, RDMA_RQ_SGE_NUM_SGES, wr->num_sge);
4675fa790ea9SDavid C Somayajulu
4676fa790ea9SDavid C Somayajulu SET_FIELD(flags, RDMA_RQ_SGE_L_KEY, wr->sg_list[i].lkey);
4677fa790ea9SDavid C Somayajulu
4678fa790ea9SDavid C Somayajulu RQ_SGE_SET(rqe, wr->sg_list[i].addr, \
4679fa790ea9SDavid C Somayajulu wr->sg_list[i].length, flags);
4680fa790ea9SDavid C Somayajulu }
4681fa790ea9SDavid C Somayajulu /* Special case of no sges. FW requires between 1-4 sges...
4682fa790ea9SDavid C Somayajulu * in this case we need to post 1 sge with length zero. this is
4683fa790ea9SDavid C Somayajulu * because rdma write with immediate consumes an RQ. */
4684fa790ea9SDavid C Somayajulu if (!wr->num_sge) {
4685fa790ea9SDavid C Somayajulu u32 flags = 0;
4686fa790ea9SDavid C Somayajulu struct rdma_rq_sge *rqe = ecore_chain_produce(&qp->rq.pbl);
4687fa790ea9SDavid C Somayajulu
4688fa790ea9SDavid C Somayajulu /* first one must include the number of SGE in the list */
4689fa790ea9SDavid C Somayajulu SET_FIELD(flags, RDMA_RQ_SGE_L_KEY, 0);
4690fa790ea9SDavid C Somayajulu SET_FIELD(flags, RDMA_RQ_SGE_NUM_SGES, 1);
4691fa790ea9SDavid C Somayajulu
4692fa790ea9SDavid C Somayajulu //RQ_SGE_SET(rqe, 0, 0, flags);
4693fa790ea9SDavid C Somayajulu rqe->addr.hi = 0;
4694fa790ea9SDavid C Somayajulu rqe->addr.lo = 0;
4695fa790ea9SDavid C Somayajulu
4696fa790ea9SDavid C Somayajulu rqe->length = 0;
4697fa790ea9SDavid C Somayajulu rqe->flags = cpu_to_le32(flags);
4698fa790ea9SDavid C Somayajulu
4699fa790ea9SDavid C Somayajulu i = 1;
4700fa790ea9SDavid C Somayajulu }
4701fa790ea9SDavid C Somayajulu
4702fa790ea9SDavid C Somayajulu qp->rqe_wr_id[qp->rq.prod].wr_id = wr->wr_id;
4703fa790ea9SDavid C Somayajulu qp->rqe_wr_id[qp->rq.prod].wqe_size = i;
4704fa790ea9SDavid C Somayajulu
4705fa790ea9SDavid C Somayajulu qlnxr_inc_sw_prod(&qp->rq);
4706fa790ea9SDavid C Somayajulu
4707fa790ea9SDavid C Somayajulu wmb();
4708fa790ea9SDavid C Somayajulu
4709fa790ea9SDavid C Somayajulu qp->rq.db_data.data.value++;
4710fa790ea9SDavid C Somayajulu
4711fa790ea9SDavid C Somayajulu // writel(qp->rq.db_data.raw, qp->rq.db);
4712fa790ea9SDavid C Somayajulu mmiowb();
4713fa790ea9SDavid C Somayajulu // if (QLNX_IS_IWARP(dev)) {
4714fa790ea9SDavid C Somayajulu // writel(qp->rq.iwarp_db2_data.raw, qp->rq.iwarp_db2);
4715fa790ea9SDavid C Somayajulu // mmiowb(); /* for second doorbell */
4716fa790ea9SDavid C Somayajulu // }
4717fa790ea9SDavid C Somayajulu
4718fa790ea9SDavid C Somayajulu reg_addr = (uint32_t)((uint8_t *)qp->rq.db -
4719fa790ea9SDavid C Somayajulu (uint8_t *)ha->cdev.doorbells);
4720fa790ea9SDavid C Somayajulu
4721fa790ea9SDavid C Somayajulu bus_write_4(ha->pci_dbells, reg_addr, qp->rq.db_data.raw);
4722fa790ea9SDavid C Somayajulu bus_barrier(ha->pci_dbells, 0, 0, BUS_SPACE_BARRIER_READ);
4723fa790ea9SDavid C Somayajulu
4724fa790ea9SDavid C Somayajulu if (QLNX_IS_IWARP(dev)) {
4725fa790ea9SDavid C Somayajulu reg_addr = (uint32_t)((uint8_t *)qp->rq.iwarp_db2 -
4726fa790ea9SDavid C Somayajulu (uint8_t *)ha->cdev.doorbells);
4727fa790ea9SDavid C Somayajulu bus_write_4(ha->pci_dbells, reg_addr, \
4728fa790ea9SDavid C Somayajulu qp->rq.iwarp_db2_data.raw);
4729fa790ea9SDavid C Somayajulu bus_barrier(ha->pci_dbells, 0, 0, \
4730fa790ea9SDavid C Somayajulu BUS_SPACE_BARRIER_READ);
4731fa790ea9SDavid C Somayajulu }
4732fa790ea9SDavid C Somayajulu
4733fa790ea9SDavid C Somayajulu wr = wr->next;
4734fa790ea9SDavid C Somayajulu }
4735fa790ea9SDavid C Somayajulu
4736fa790ea9SDavid C Somayajulu spin_unlock_irqrestore(&qp->q_lock, flags);
4737fa790ea9SDavid C Somayajulu
4738fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit status = 0x%x\n", status);
4739fa790ea9SDavid C Somayajulu
4740fa790ea9SDavid C Somayajulu return status;
4741fa790ea9SDavid C Somayajulu }
4742fa790ea9SDavid C Somayajulu
4743fa790ea9SDavid C Somayajulu /* In fmr we need to increase the number of fmr completed counter for the fmr
4744fa790ea9SDavid C Somayajulu * algorithm determining whether we can free a pbl or not.
4745fa790ea9SDavid C Somayajulu * we need to perform this whether the work request was signaled or not. for
4746fa790ea9SDavid C Somayajulu * this purpose we call this function from the condition that checks if a wr
4747fa790ea9SDavid C Somayajulu * should be skipped, to make sure we don't miss it ( possibly this fmr
4748fa790ea9SDavid C Somayajulu * operation was not signalted)
4749fa790ea9SDavid C Somayajulu */
4750fa790ea9SDavid C Somayajulu static inline void
qlnxr_chk_if_fmr(struct qlnxr_qp * qp)4751fa790ea9SDavid C Somayajulu qlnxr_chk_if_fmr(struct qlnxr_qp *qp)
4752fa790ea9SDavid C Somayajulu {
4753fa790ea9SDavid C Somayajulu
4754fa790ea9SDavid C Somayajulu if (qp->wqe_wr_id[qp->sq.cons].opcode == IB_WC_REG_MR)
4755fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.cons].mr->info.completed++;
4756fa790ea9SDavid C Somayajulu }
4757fa790ea9SDavid C Somayajulu
4758fa790ea9SDavid C Somayajulu static int
process_req(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct qlnxr_cq * cq,int num_entries,struct ib_wc * wc,u16 hw_cons,enum ib_wc_status status,int force)4759fa790ea9SDavid C Somayajulu process_req(struct qlnxr_dev *dev,
4760fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
4761fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq,
4762fa790ea9SDavid C Somayajulu int num_entries,
4763fa790ea9SDavid C Somayajulu struct ib_wc *wc,
4764fa790ea9SDavid C Somayajulu u16 hw_cons,
4765fa790ea9SDavid C Somayajulu enum ib_wc_status status,
4766fa790ea9SDavid C Somayajulu int force)
4767fa790ea9SDavid C Somayajulu {
4768fa790ea9SDavid C Somayajulu u16 cnt = 0;
4769fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
4770fa790ea9SDavid C Somayajulu
4771fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
4772fa790ea9SDavid C Somayajulu
4773fa790ea9SDavid C Somayajulu while (num_entries && qp->sq.wqe_cons != hw_cons) {
4774fa790ea9SDavid C Somayajulu if (!qp->wqe_wr_id[qp->sq.cons].signaled && !force) {
4775fa790ea9SDavid C Somayajulu qlnxr_chk_if_fmr(qp);
4776fa790ea9SDavid C Somayajulu /* skip WC */
4777fa790ea9SDavid C Somayajulu goto next_cqe;
4778fa790ea9SDavid C Somayajulu }
4779fa790ea9SDavid C Somayajulu
4780fa790ea9SDavid C Somayajulu /* fill WC */
4781fa790ea9SDavid C Somayajulu wc->status = status;
4782fa790ea9SDavid C Somayajulu wc->vendor_err = 0;
4783fa790ea9SDavid C Somayajulu wc->wc_flags = 0;
4784fa790ea9SDavid C Somayajulu wc->src_qp = qp->id;
4785fa790ea9SDavid C Somayajulu wc->qp = &qp->ibqp;
4786fa790ea9SDavid C Somayajulu
4787fa790ea9SDavid C Somayajulu // common section
4788fa790ea9SDavid C Somayajulu wc->wr_id = qp->wqe_wr_id[qp->sq.cons].wr_id;
4789fa790ea9SDavid C Somayajulu wc->opcode = qp->wqe_wr_id[qp->sq.cons].opcode;
4790fa790ea9SDavid C Somayajulu
4791fa790ea9SDavid C Somayajulu switch (wc->opcode) {
4792fa790ea9SDavid C Somayajulu case IB_WC_RDMA_WRITE:
4793fa790ea9SDavid C Somayajulu
4794fa790ea9SDavid C Somayajulu wc->byte_len = qp->wqe_wr_id[qp->sq.cons].bytes_len;
4795fa790ea9SDavid C Somayajulu
4796fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
4797fa790ea9SDavid C Somayajulu "opcode = IB_WC_RDMA_WRITE bytes = %d\n",
4798fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.cons].bytes_len);
4799fa790ea9SDavid C Somayajulu break;
4800fa790ea9SDavid C Somayajulu
4801fa790ea9SDavid C Somayajulu case IB_WC_COMP_SWAP:
4802fa790ea9SDavid C Somayajulu case IB_WC_FETCH_ADD:
4803fa790ea9SDavid C Somayajulu wc->byte_len = 8;
4804fa790ea9SDavid C Somayajulu break;
4805fa790ea9SDavid C Somayajulu
4806fa790ea9SDavid C Somayajulu case IB_WC_REG_MR:
4807fa790ea9SDavid C Somayajulu qp->wqe_wr_id[qp->sq.cons].mr->info.completed++;
4808fa790ea9SDavid C Somayajulu break;
4809fa790ea9SDavid C Somayajulu
4810fa790ea9SDavid C Somayajulu case IB_WC_RDMA_READ:
4811fa790ea9SDavid C Somayajulu case IB_WC_SEND:
4812fa790ea9SDavid C Somayajulu
4813fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "opcode = 0x%x \n", wc->opcode);
4814fa790ea9SDavid C Somayajulu break;
4815fa790ea9SDavid C Somayajulu default:
4816fa790ea9SDavid C Somayajulu ;//DP_ERR("TBD ERROR");
4817fa790ea9SDavid C Somayajulu }
4818fa790ea9SDavid C Somayajulu
4819fa790ea9SDavid C Somayajulu num_entries--;
4820fa790ea9SDavid C Somayajulu wc++;
4821fa790ea9SDavid C Somayajulu cnt++;
4822fa790ea9SDavid C Somayajulu next_cqe:
4823fa790ea9SDavid C Somayajulu while (qp->wqe_wr_id[qp->sq.cons].wqe_size--)
4824fa790ea9SDavid C Somayajulu ecore_chain_consume(&qp->sq.pbl);
4825fa790ea9SDavid C Somayajulu qlnxr_inc_sw_cons(&qp->sq);
4826fa790ea9SDavid C Somayajulu }
4827fa790ea9SDavid C Somayajulu
4828fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit cnt = 0x%x\n", cnt);
4829fa790ea9SDavid C Somayajulu return cnt;
4830fa790ea9SDavid C Somayajulu }
4831fa790ea9SDavid C Somayajulu
4832fa790ea9SDavid C Somayajulu static int
qlnxr_poll_cq_req(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct qlnxr_cq * cq,int num_entries,struct ib_wc * wc,struct rdma_cqe_requester * req)4833fa790ea9SDavid C Somayajulu qlnxr_poll_cq_req(struct qlnxr_dev *dev,
4834fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
4835fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq,
4836fa790ea9SDavid C Somayajulu int num_entries,
4837fa790ea9SDavid C Somayajulu struct ib_wc *wc,
4838fa790ea9SDavid C Somayajulu struct rdma_cqe_requester *req)
4839fa790ea9SDavid C Somayajulu {
4840fa790ea9SDavid C Somayajulu int cnt = 0;
4841fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
4842fa790ea9SDavid C Somayajulu
4843fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter req->status = 0x%x\n", req->status);
4844fa790ea9SDavid C Somayajulu
4845fa790ea9SDavid C Somayajulu switch (req->status) {
4846fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_OK:
4847fa790ea9SDavid C Somayajulu
4848fa790ea9SDavid C Somayajulu cnt = process_req(dev, qp, cq, num_entries, wc, req->sq_cons,
4849fa790ea9SDavid C Somayajulu IB_WC_SUCCESS, 0);
4850fa790ea9SDavid C Somayajulu break;
4851fa790ea9SDavid C Somayajulu
4852fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR:
4853fa790ea9SDavid C Somayajulu
4854fa790ea9SDavid C Somayajulu if (qp->state != ECORE_ROCE_QP_STATE_ERR)
4855fa790ea9SDavid C Somayajulu cnt = process_req(dev, qp, cq, num_entries, wc, req->sq_cons,
4856fa790ea9SDavid C Somayajulu IB_WC_WR_FLUSH_ERR, 1);
4857fa790ea9SDavid C Somayajulu break;
4858fa790ea9SDavid C Somayajulu
4859fa790ea9SDavid C Somayajulu default: /* other errors case */
4860fa790ea9SDavid C Somayajulu
4861fa790ea9SDavid C Somayajulu /* process all WQE before the cosumer */
4862fa790ea9SDavid C Somayajulu qp->state = ECORE_ROCE_QP_STATE_ERR;
4863fa790ea9SDavid C Somayajulu cnt = process_req(dev, qp, cq, num_entries, wc,
4864fa790ea9SDavid C Somayajulu req->sq_cons - 1, IB_WC_SUCCESS, 0);
4865fa790ea9SDavid C Somayajulu wc += cnt;
4866fa790ea9SDavid C Somayajulu /* if we have extra WC fill it with actual error info */
4867fa790ea9SDavid C Somayajulu
4868fa790ea9SDavid C Somayajulu if (cnt < num_entries) {
4869fa790ea9SDavid C Somayajulu enum ib_wc_status wc_status;
4870fa790ea9SDavid C Somayajulu
4871fa790ea9SDavid C Somayajulu switch (req->status) {
4872fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_BAD_RESPONSE_ERR:
4873fa790ea9SDavid C Somayajulu wc_status = IB_WC_BAD_RESP_ERR;
4874fa790ea9SDavid C Somayajulu break;
4875fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_LOCAL_LENGTH_ERR:
4876fa790ea9SDavid C Somayajulu wc_status = IB_WC_LOC_LEN_ERR;
4877fa790ea9SDavid C Somayajulu break;
4878fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_LOCAL_QP_OPERATION_ERR:
4879fa790ea9SDavid C Somayajulu wc_status = IB_WC_LOC_QP_OP_ERR;
4880fa790ea9SDavid C Somayajulu break;
4881fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_LOCAL_PROTECTION_ERR:
4882fa790ea9SDavid C Somayajulu wc_status = IB_WC_LOC_PROT_ERR;
4883fa790ea9SDavid C Somayajulu break;
4884fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_MEMORY_MGT_OPERATION_ERR:
4885fa790ea9SDavid C Somayajulu wc_status = IB_WC_MW_BIND_ERR;
4886fa790ea9SDavid C Somayajulu break;
4887fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_REMOTE_INVALID_REQUEST_ERR:
4888fa790ea9SDavid C Somayajulu wc_status = IB_WC_REM_INV_REQ_ERR;
4889fa790ea9SDavid C Somayajulu break;
4890fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_REMOTE_ACCESS_ERR:
4891fa790ea9SDavid C Somayajulu wc_status = IB_WC_REM_ACCESS_ERR;
4892fa790ea9SDavid C Somayajulu break;
4893fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_REMOTE_OPERATION_ERR:
4894fa790ea9SDavid C Somayajulu wc_status = IB_WC_REM_OP_ERR;
4895fa790ea9SDavid C Somayajulu break;
4896fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_RNR_NAK_RETRY_CNT_ERR:
4897fa790ea9SDavid C Somayajulu wc_status = IB_WC_RNR_RETRY_EXC_ERR;
4898fa790ea9SDavid C Somayajulu break;
4899fa790ea9SDavid C Somayajulu case RDMA_CQE_REQ_STS_TRANSPORT_RETRY_CNT_ERR:
4900fa790ea9SDavid C Somayajulu wc_status = IB_WC_RETRY_EXC_ERR;
4901fa790ea9SDavid C Somayajulu break;
4902fa790ea9SDavid C Somayajulu default:
4903fa790ea9SDavid C Somayajulu wc_status = IB_WC_GENERAL_ERR;
4904fa790ea9SDavid C Somayajulu }
4905fa790ea9SDavid C Somayajulu
4906fa790ea9SDavid C Somayajulu cnt += process_req(dev, qp, cq, 1, wc, req->sq_cons,
4907fa790ea9SDavid C Somayajulu wc_status, 1 /* force use of WC */);
4908fa790ea9SDavid C Somayajulu }
4909fa790ea9SDavid C Somayajulu }
4910fa790ea9SDavid C Somayajulu
4911fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit cnt = %d\n", cnt);
4912fa790ea9SDavid C Somayajulu return cnt;
4913fa790ea9SDavid C Somayajulu }
4914fa790ea9SDavid C Somayajulu
4915fa790ea9SDavid C Somayajulu static void
__process_resp_one(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct qlnxr_cq * cq,struct ib_wc * wc,struct rdma_cqe_responder * resp,u64 wr_id)4916fa790ea9SDavid C Somayajulu __process_resp_one(struct qlnxr_dev *dev,
4917fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
4918fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq,
4919fa790ea9SDavid C Somayajulu struct ib_wc *wc,
4920fa790ea9SDavid C Somayajulu struct rdma_cqe_responder *resp,
4921fa790ea9SDavid C Somayajulu u64 wr_id)
4922fa790ea9SDavid C Somayajulu {
4923fa790ea9SDavid C Somayajulu enum ib_wc_status wc_status = IB_WC_SUCCESS;
4924fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
4925fa790ea9SDavid C Somayajulu
4926fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter qp = %p resp->status = 0x%x\n",
4927fa790ea9SDavid C Somayajulu qp, resp->status);
4928fa790ea9SDavid C Somayajulu
4929fa790ea9SDavid C Somayajulu wc->opcode = IB_WC_RECV;
4930fa790ea9SDavid C Somayajulu wc->wc_flags = 0;
4931fa790ea9SDavid C Somayajulu
4932fa790ea9SDavid C Somayajulu switch (resp->status) {
4933fa790ea9SDavid C Somayajulu case RDMA_CQE_RESP_STS_LOCAL_ACCESS_ERR:
4934fa790ea9SDavid C Somayajulu wc_status = IB_WC_LOC_ACCESS_ERR;
4935fa790ea9SDavid C Somayajulu break;
4936fa790ea9SDavid C Somayajulu
4937fa790ea9SDavid C Somayajulu case RDMA_CQE_RESP_STS_LOCAL_LENGTH_ERR:
4938fa790ea9SDavid C Somayajulu wc_status = IB_WC_LOC_LEN_ERR;
4939fa790ea9SDavid C Somayajulu break;
4940fa790ea9SDavid C Somayajulu
4941fa790ea9SDavid C Somayajulu case RDMA_CQE_RESP_STS_LOCAL_QP_OPERATION_ERR:
4942fa790ea9SDavid C Somayajulu wc_status = IB_WC_LOC_QP_OP_ERR;
4943fa790ea9SDavid C Somayajulu break;
4944fa790ea9SDavid C Somayajulu
4945fa790ea9SDavid C Somayajulu case RDMA_CQE_RESP_STS_LOCAL_PROTECTION_ERR:
4946fa790ea9SDavid C Somayajulu wc_status = IB_WC_LOC_PROT_ERR;
4947fa790ea9SDavid C Somayajulu break;
4948fa790ea9SDavid C Somayajulu
4949fa790ea9SDavid C Somayajulu case RDMA_CQE_RESP_STS_MEMORY_MGT_OPERATION_ERR:
4950fa790ea9SDavid C Somayajulu wc_status = IB_WC_MW_BIND_ERR;
4951fa790ea9SDavid C Somayajulu break;
4952fa790ea9SDavid C Somayajulu
4953fa790ea9SDavid C Somayajulu case RDMA_CQE_RESP_STS_REMOTE_INVALID_REQUEST_ERR:
4954fa790ea9SDavid C Somayajulu wc_status = IB_WC_REM_INV_RD_REQ_ERR;
4955fa790ea9SDavid C Somayajulu break;
4956fa790ea9SDavid C Somayajulu
4957fa790ea9SDavid C Somayajulu case RDMA_CQE_RESP_STS_OK:
4958fa790ea9SDavid C Somayajulu if (resp->flags & QLNXR_RESP_IMM) {
4959fa790ea9SDavid C Somayajulu wc->ex.imm_data =
4960fa790ea9SDavid C Somayajulu le32_to_cpu(resp->imm_data_or_inv_r_Key);
4961fa790ea9SDavid C Somayajulu wc->wc_flags |= IB_WC_WITH_IMM;
4962fa790ea9SDavid C Somayajulu
4963fa790ea9SDavid C Somayajulu if (resp->flags & QLNXR_RESP_RDMA)
4964fa790ea9SDavid C Somayajulu wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
4965fa790ea9SDavid C Somayajulu
4966fa790ea9SDavid C Somayajulu if (resp->flags & QLNXR_RESP_INV) {
4967fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,
4968fa790ea9SDavid C Somayajulu "Invalid flags QLNXR_RESP_INV [0x%x]"
4969fa790ea9SDavid C Somayajulu "qp = %p qp->id = 0x%x cq = %p"
4970fa790ea9SDavid C Somayajulu " cq->icid = 0x%x\n",
4971fa790ea9SDavid C Somayajulu resp->flags, qp, qp->id, cq, cq->icid );
4972fa790ea9SDavid C Somayajulu }
4973fa790ea9SDavid C Somayajulu } else if (resp->flags & QLNXR_RESP_INV) {
4974fa790ea9SDavid C Somayajulu wc->ex.imm_data =
4975fa790ea9SDavid C Somayajulu le32_to_cpu(resp->imm_data_or_inv_r_Key);
4976fa790ea9SDavid C Somayajulu wc->wc_flags |= IB_WC_WITH_INVALIDATE;
4977fa790ea9SDavid C Somayajulu
4978fa790ea9SDavid C Somayajulu if (resp->flags & QLNXR_RESP_RDMA) {
4979fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,
4980fa790ea9SDavid C Somayajulu "Invalid flags QLNXR_RESP_RDMA [0x%x]"
4981fa790ea9SDavid C Somayajulu "qp = %p qp->id = 0x%x cq = %p"
4982fa790ea9SDavid C Somayajulu " cq->icid = 0x%x\n",
4983fa790ea9SDavid C Somayajulu resp->flags, qp, qp->id, cq, cq->icid );
4984fa790ea9SDavid C Somayajulu }
4985fa790ea9SDavid C Somayajulu } else if (resp->flags & QLNXR_RESP_RDMA) {
4986fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "Invalid flags QLNXR_RESP_RDMA [0x%x]"
4987fa790ea9SDavid C Somayajulu "qp = %p qp->id = 0x%x cq = %p cq->icid = 0x%x\n",
4988fa790ea9SDavid C Somayajulu resp->flags, qp, qp->id, cq, cq->icid );
4989fa790ea9SDavid C Somayajulu }
4990fa790ea9SDavid C Somayajulu break;
4991fa790ea9SDavid C Somayajulu
4992fa790ea9SDavid C Somayajulu default:
4993fa790ea9SDavid C Somayajulu wc_status = IB_WC_GENERAL_ERR;
4994fa790ea9SDavid C Somayajulu }
4995fa790ea9SDavid C Somayajulu
4996fa790ea9SDavid C Somayajulu /* fill WC */
4997fa790ea9SDavid C Somayajulu wc->status = wc_status;
4998fa790ea9SDavid C Somayajulu wc->vendor_err = 0;
4999fa790ea9SDavid C Somayajulu wc->src_qp = qp->id;
5000fa790ea9SDavid C Somayajulu wc->qp = &qp->ibqp;
5001fa790ea9SDavid C Somayajulu wc->wr_id = wr_id;
5002fa790ea9SDavid C Somayajulu
5003fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit status = 0x%x\n", wc_status);
5004fa790ea9SDavid C Somayajulu
5005fa790ea9SDavid C Somayajulu return;
5006fa790ea9SDavid C Somayajulu }
5007fa790ea9SDavid C Somayajulu
5008fa790ea9SDavid C Somayajulu static int
process_resp_one_srq(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct qlnxr_cq * cq,struct ib_wc * wc,struct rdma_cqe_responder * resp)5009fa790ea9SDavid C Somayajulu process_resp_one_srq(struct qlnxr_dev *dev,
5010fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
5011fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq,
5012fa790ea9SDavid C Somayajulu struct ib_wc *wc,
5013fa790ea9SDavid C Somayajulu struct rdma_cqe_responder *resp)
5014fa790ea9SDavid C Somayajulu {
5015fa790ea9SDavid C Somayajulu struct qlnxr_srq *srq = qp->srq;
5016fa790ea9SDavid C Somayajulu u64 wr_id;
5017fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
5018fa790ea9SDavid C Somayajulu
5019fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5020fa790ea9SDavid C Somayajulu
5021fa790ea9SDavid C Somayajulu wr_id = HILO_U64(resp->srq_wr_id.hi, resp->srq_wr_id.lo);
5022fa790ea9SDavid C Somayajulu
5023fa790ea9SDavid C Somayajulu if (resp->status == RDMA_CQE_RESP_STS_WORK_REQUEST_FLUSHED_ERR) {
5024fa790ea9SDavid C Somayajulu wc->status = IB_WC_WR_FLUSH_ERR;
5025fa790ea9SDavid C Somayajulu wc->vendor_err = 0;
5026fa790ea9SDavid C Somayajulu wc->wr_id = wr_id;
5027fa790ea9SDavid C Somayajulu wc->byte_len = 0;
5028fa790ea9SDavid C Somayajulu wc->src_qp = qp->id;
5029fa790ea9SDavid C Somayajulu wc->qp = &qp->ibqp;
5030fa790ea9SDavid C Somayajulu wc->wr_id = wr_id;
5031fa790ea9SDavid C Somayajulu } else {
5032fa790ea9SDavid C Somayajulu __process_resp_one(dev, qp, cq, wc, resp, wr_id);
5033fa790ea9SDavid C Somayajulu }
5034fa790ea9SDavid C Somayajulu
5035fa790ea9SDavid C Somayajulu /* PBL is maintained in case of WR granularity.
5036fa790ea9SDavid C Somayajulu * So increment WR consumer after consuming WR
5037fa790ea9SDavid C Somayajulu */
5038fa790ea9SDavid C Somayajulu srq->hw_srq.wr_cons_cnt++;
5039fa790ea9SDavid C Somayajulu
5040fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
5041fa790ea9SDavid C Somayajulu return 1;
5042fa790ea9SDavid C Somayajulu }
5043fa790ea9SDavid C Somayajulu
5044fa790ea9SDavid C Somayajulu static int
process_resp_one(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct qlnxr_cq * cq,struct ib_wc * wc,struct rdma_cqe_responder * resp)5045fa790ea9SDavid C Somayajulu process_resp_one(struct qlnxr_dev *dev,
5046fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
5047fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq,
5048fa790ea9SDavid C Somayajulu struct ib_wc *wc,
5049fa790ea9SDavid C Somayajulu struct rdma_cqe_responder *resp)
5050fa790ea9SDavid C Somayajulu {
5051fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
5052fa790ea9SDavid C Somayajulu u64 wr_id = qp->rqe_wr_id[qp->rq.cons].wr_id;
5053fa790ea9SDavid C Somayajulu
5054fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5055fa790ea9SDavid C Somayajulu
5056fa790ea9SDavid C Somayajulu __process_resp_one(dev, qp, cq, wc, resp, wr_id);
5057fa790ea9SDavid C Somayajulu
5058fa790ea9SDavid C Somayajulu while (qp->rqe_wr_id[qp->rq.cons].wqe_size--)
5059fa790ea9SDavid C Somayajulu ecore_chain_consume(&qp->rq.pbl);
5060fa790ea9SDavid C Somayajulu qlnxr_inc_sw_cons(&qp->rq);
5061fa790ea9SDavid C Somayajulu
5062fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
5063fa790ea9SDavid C Somayajulu return 1;
5064fa790ea9SDavid C Somayajulu }
5065fa790ea9SDavid C Somayajulu
5066fa790ea9SDavid C Somayajulu static int
process_resp_flush(struct qlnxr_qp * qp,int num_entries,struct ib_wc * wc,u16 hw_cons)5067fa790ea9SDavid C Somayajulu process_resp_flush(struct qlnxr_qp *qp,
5068fa790ea9SDavid C Somayajulu int num_entries,
5069fa790ea9SDavid C Somayajulu struct ib_wc *wc,
5070fa790ea9SDavid C Somayajulu u16 hw_cons)
5071fa790ea9SDavid C Somayajulu {
5072fa790ea9SDavid C Somayajulu u16 cnt = 0;
5073fa790ea9SDavid C Somayajulu qlnx_host_t *ha = qp->dev->ha;
5074fa790ea9SDavid C Somayajulu
5075fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5076fa790ea9SDavid C Somayajulu
5077fa790ea9SDavid C Somayajulu while (num_entries && qp->rq.wqe_cons != hw_cons) {
5078fa790ea9SDavid C Somayajulu /* fill WC */
5079fa790ea9SDavid C Somayajulu wc->status = IB_WC_WR_FLUSH_ERR;
5080fa790ea9SDavid C Somayajulu wc->vendor_err = 0;
5081fa790ea9SDavid C Somayajulu wc->wc_flags = 0;
5082fa790ea9SDavid C Somayajulu wc->src_qp = qp->id;
5083fa790ea9SDavid C Somayajulu wc->byte_len = 0;
5084fa790ea9SDavid C Somayajulu wc->wr_id = qp->rqe_wr_id[qp->rq.cons].wr_id;
5085fa790ea9SDavid C Somayajulu wc->qp = &qp->ibqp;
5086fa790ea9SDavid C Somayajulu num_entries--;
5087fa790ea9SDavid C Somayajulu wc++;
5088fa790ea9SDavid C Somayajulu cnt++;
5089fa790ea9SDavid C Somayajulu while (qp->rqe_wr_id[qp->rq.cons].wqe_size--)
5090fa790ea9SDavid C Somayajulu ecore_chain_consume(&qp->rq.pbl);
5091fa790ea9SDavid C Somayajulu qlnxr_inc_sw_cons(&qp->rq);
5092fa790ea9SDavid C Somayajulu }
5093fa790ea9SDavid C Somayajulu
5094fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit cnt = 0x%x\n", cnt);
5095fa790ea9SDavid C Somayajulu return cnt;
5096fa790ea9SDavid C Somayajulu }
5097fa790ea9SDavid C Somayajulu
5098fa790ea9SDavid C Somayajulu static void
try_consume_resp_cqe(struct qlnxr_cq * cq,struct qlnxr_qp * qp,struct rdma_cqe_responder * resp,int * update)5099fa790ea9SDavid C Somayajulu try_consume_resp_cqe(struct qlnxr_cq *cq,
5100fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
5101fa790ea9SDavid C Somayajulu struct rdma_cqe_responder *resp,
5102fa790ea9SDavid C Somayajulu int *update)
5103fa790ea9SDavid C Somayajulu {
5104fa790ea9SDavid C Somayajulu if (le16_to_cpu(resp->rq_cons) == qp->rq.wqe_cons) {
5105fa790ea9SDavid C Somayajulu consume_cqe(cq);
5106fa790ea9SDavid C Somayajulu *update |= 1;
5107fa790ea9SDavid C Somayajulu }
5108fa790ea9SDavid C Somayajulu }
5109fa790ea9SDavid C Somayajulu
5110fa790ea9SDavid C Somayajulu static int
qlnxr_poll_cq_resp_srq(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct qlnxr_cq * cq,int num_entries,struct ib_wc * wc,struct rdma_cqe_responder * resp,int * update)5111fa790ea9SDavid C Somayajulu qlnxr_poll_cq_resp_srq(struct qlnxr_dev *dev,
5112fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
5113fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq,
5114fa790ea9SDavid C Somayajulu int num_entries,
5115fa790ea9SDavid C Somayajulu struct ib_wc *wc,
5116fa790ea9SDavid C Somayajulu struct rdma_cqe_responder *resp,
5117fa790ea9SDavid C Somayajulu int *update)
5118fa790ea9SDavid C Somayajulu {
5119fa790ea9SDavid C Somayajulu int cnt;
5120fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
5121fa790ea9SDavid C Somayajulu
5122fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5123fa790ea9SDavid C Somayajulu
5124fa790ea9SDavid C Somayajulu cnt = process_resp_one_srq(dev, qp, cq, wc, resp);
5125fa790ea9SDavid C Somayajulu consume_cqe(cq);
5126fa790ea9SDavid C Somayajulu *update |= 1;
5127fa790ea9SDavid C Somayajulu
5128fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit cnt = 0x%x\n", cnt);
5129fa790ea9SDavid C Somayajulu return cnt;
5130fa790ea9SDavid C Somayajulu }
5131fa790ea9SDavid C Somayajulu
5132fa790ea9SDavid C Somayajulu static int
qlnxr_poll_cq_resp(struct qlnxr_dev * dev,struct qlnxr_qp * qp,struct qlnxr_cq * cq,int num_entries,struct ib_wc * wc,struct rdma_cqe_responder * resp,int * update)5133fa790ea9SDavid C Somayajulu qlnxr_poll_cq_resp(struct qlnxr_dev *dev,
5134fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp,
5135fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq,
5136fa790ea9SDavid C Somayajulu int num_entries,
5137fa790ea9SDavid C Somayajulu struct ib_wc *wc,
5138fa790ea9SDavid C Somayajulu struct rdma_cqe_responder *resp,
5139fa790ea9SDavid C Somayajulu int *update)
5140fa790ea9SDavid C Somayajulu {
5141fa790ea9SDavid C Somayajulu int cnt;
5142fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
5143fa790ea9SDavid C Somayajulu
5144fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5145fa790ea9SDavid C Somayajulu
5146fa790ea9SDavid C Somayajulu if (resp->status == RDMA_CQE_RESP_STS_WORK_REQUEST_FLUSHED_ERR) {
5147fa790ea9SDavid C Somayajulu cnt = process_resp_flush(qp, num_entries, wc,
5148fa790ea9SDavid C Somayajulu resp->rq_cons);
5149fa790ea9SDavid C Somayajulu try_consume_resp_cqe(cq, qp, resp, update);
5150fa790ea9SDavid C Somayajulu } else {
5151fa790ea9SDavid C Somayajulu cnt = process_resp_one(dev, qp, cq, wc, resp);
5152fa790ea9SDavid C Somayajulu consume_cqe(cq);
5153fa790ea9SDavid C Somayajulu *update |= 1;
5154fa790ea9SDavid C Somayajulu }
5155fa790ea9SDavid C Somayajulu
5156fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit cnt = 0x%x\n", cnt);
5157fa790ea9SDavid C Somayajulu return cnt;
5158fa790ea9SDavid C Somayajulu }
5159fa790ea9SDavid C Somayajulu
5160fa790ea9SDavid C Somayajulu static void
try_consume_req_cqe(struct qlnxr_cq * cq,struct qlnxr_qp * qp,struct rdma_cqe_requester * req,int * update)5161fa790ea9SDavid C Somayajulu try_consume_req_cqe(struct qlnxr_cq *cq, struct qlnxr_qp *qp,
5162fa790ea9SDavid C Somayajulu struct rdma_cqe_requester *req, int *update)
5163fa790ea9SDavid C Somayajulu {
5164fa790ea9SDavid C Somayajulu if (le16_to_cpu(req->sq_cons) == qp->sq.wqe_cons) {
5165fa790ea9SDavid C Somayajulu consume_cqe(cq);
5166fa790ea9SDavid C Somayajulu *update |= 1;
5167fa790ea9SDavid C Somayajulu }
5168fa790ea9SDavid C Somayajulu }
5169fa790ea9SDavid C Somayajulu
5170fa790ea9SDavid C Somayajulu static void
doorbell_cq(struct qlnxr_dev * dev,struct qlnxr_cq * cq,u32 cons,u8 flags)5171fa790ea9SDavid C Somayajulu doorbell_cq(struct qlnxr_dev *dev, struct qlnxr_cq *cq, u32 cons, u8 flags)
5172fa790ea9SDavid C Somayajulu {
5173fa790ea9SDavid C Somayajulu uint64_t reg_addr;
5174fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
5175fa790ea9SDavid C Somayajulu
5176fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5177fa790ea9SDavid C Somayajulu
5178fa790ea9SDavid C Somayajulu wmb();
5179fa790ea9SDavid C Somayajulu cq->db.data.agg_flags = flags;
5180fa790ea9SDavid C Somayajulu cq->db.data.value = cpu_to_le32(cons);
5181fa790ea9SDavid C Somayajulu
5182fa790ea9SDavid C Somayajulu reg_addr = (uint64_t)((uint8_t *)cq->db_addr -
5183fa790ea9SDavid C Somayajulu (uint8_t *)(ha->cdev.doorbells));
5184fa790ea9SDavid C Somayajulu
5185fa790ea9SDavid C Somayajulu bus_write_8(ha->pci_dbells, reg_addr, cq->db.raw);
5186fa790ea9SDavid C Somayajulu bus_barrier(ha->pci_dbells, 0, 0, BUS_SPACE_BARRIER_READ);
5187fa790ea9SDavid C Somayajulu
5188fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
5189fa790ea9SDavid C Somayajulu return;
5190fa790ea9SDavid C Somayajulu
5191fa790ea9SDavid C Somayajulu //#ifdef __LP64__
5192fa790ea9SDavid C Somayajulu // writeq(cq->db.raw, cq->db_addr);
5193fa790ea9SDavid C Somayajulu //#else
5194fa790ea9SDavid C Somayajulu /* Note that since the FW allows 64 bit write only, in 32bit systems
5195fa790ea9SDavid C Somayajulu * the value of db_addr must be low enough. This is currently not
5196fa790ea9SDavid C Somayajulu * enforced.
5197fa790ea9SDavid C Somayajulu */
5198fa790ea9SDavid C Somayajulu // writel(cq->db.raw & 0xffffffff, cq->db_addr);
5199fa790ea9SDavid C Somayajulu // mmiowb();
5200fa790ea9SDavid C Somayajulu //#endif
5201fa790ea9SDavid C Somayajulu }
5202fa790ea9SDavid C Somayajulu
5203fa790ea9SDavid C Somayajulu static int
is_valid_cqe(struct qlnxr_cq * cq,union rdma_cqe * cqe)5204fa790ea9SDavid C Somayajulu is_valid_cqe(struct qlnxr_cq *cq, union rdma_cqe *cqe)
5205fa790ea9SDavid C Somayajulu {
5206fa790ea9SDavid C Somayajulu struct rdma_cqe_requester *resp_cqe = &cqe->req;
5207fa790ea9SDavid C Somayajulu return (resp_cqe->flags & RDMA_RESIZE_CQ_RAMROD_DATA_TOGGLE_BIT_MASK) ==
5208fa790ea9SDavid C Somayajulu cq->pbl_toggle;
5209fa790ea9SDavid C Somayajulu }
5210fa790ea9SDavid C Somayajulu
5211fa790ea9SDavid C Somayajulu int
qlnxr_poll_cq(struct ib_cq * ibcq,int num_entries,struct ib_wc * wc)5212fa790ea9SDavid C Somayajulu qlnxr_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
5213fa790ea9SDavid C Somayajulu {
5214fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq = get_qlnxr_cq(ibcq);
5215fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev((ibcq->device));
5216fa790ea9SDavid C Somayajulu int done = 0;
5217fa790ea9SDavid C Somayajulu union rdma_cqe *cqe = cq->latest_cqe;
5218fa790ea9SDavid C Somayajulu int update = 0;
5219fa790ea9SDavid C Somayajulu u32 old_cons, new_cons;
5220fa790ea9SDavid C Somayajulu unsigned long flags;
5221fa790ea9SDavid C Somayajulu qlnx_host_t *ha = dev->ha;
5222fa790ea9SDavid C Somayajulu
5223fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5224fa790ea9SDavid C Somayajulu
5225*727bfe38SJustin Hibbits if (!(if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING))
5226fa790ea9SDavid C Somayajulu return -EINVAL;
5227fa790ea9SDavid C Somayajulu
5228fa790ea9SDavid C Somayajulu if (cq->destroyed) {
5229fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "called after destroy for cq %p (icid=%d)\n",
5230fa790ea9SDavid C Somayajulu cq, cq->icid);
5231fa790ea9SDavid C Somayajulu return 0;
5232fa790ea9SDavid C Somayajulu }
5233fa790ea9SDavid C Somayajulu
5234fa790ea9SDavid C Somayajulu if (cq->cq_type == QLNXR_CQ_TYPE_GSI)
5235fa790ea9SDavid C Somayajulu return qlnxr_gsi_poll_cq(ibcq, num_entries, wc);
5236fa790ea9SDavid C Somayajulu
5237fa790ea9SDavid C Somayajulu spin_lock_irqsave(&cq->cq_lock, flags);
5238fa790ea9SDavid C Somayajulu
5239fa790ea9SDavid C Somayajulu old_cons = ecore_chain_get_cons_idx_u32(&cq->pbl);
5240fa790ea9SDavid C Somayajulu
5241fa790ea9SDavid C Somayajulu while (num_entries && is_valid_cqe(cq, cqe)) {
5242fa790ea9SDavid C Somayajulu int cnt = 0;
5243fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp;
5244fa790ea9SDavid C Somayajulu struct rdma_cqe_requester *resp_cqe;
5245fa790ea9SDavid C Somayajulu enum rdma_cqe_type cqe_type;
5246fa790ea9SDavid C Somayajulu
5247fa790ea9SDavid C Somayajulu /* prevent speculative reads of any field of CQE */
5248fa790ea9SDavid C Somayajulu rmb();
5249fa790ea9SDavid C Somayajulu
5250fa790ea9SDavid C Somayajulu resp_cqe = &cqe->req;
5251fa790ea9SDavid C Somayajulu qp = (struct qlnxr_qp *)(uintptr_t)HILO_U64(resp_cqe->qp_handle.hi,
5252fa790ea9SDavid C Somayajulu resp_cqe->qp_handle.lo);
5253fa790ea9SDavid C Somayajulu
5254fa790ea9SDavid C Somayajulu if (!qp) {
5255fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qp = NULL\n");
5256fa790ea9SDavid C Somayajulu break;
5257fa790ea9SDavid C Somayajulu }
5258fa790ea9SDavid C Somayajulu
5259fa790ea9SDavid C Somayajulu wc->qp = &qp->ibqp;
5260fa790ea9SDavid C Somayajulu
5261fa790ea9SDavid C Somayajulu cqe_type = GET_FIELD(resp_cqe->flags, RDMA_CQE_REQUESTER_TYPE);
5262fa790ea9SDavid C Somayajulu
5263fa790ea9SDavid C Somayajulu switch (cqe_type) {
5264fa790ea9SDavid C Somayajulu case RDMA_CQE_TYPE_REQUESTER:
5265fa790ea9SDavid C Somayajulu cnt = qlnxr_poll_cq_req(dev, qp, cq, num_entries,
5266fa790ea9SDavid C Somayajulu wc, &cqe->req);
5267fa790ea9SDavid C Somayajulu try_consume_req_cqe(cq, qp, &cqe->req, &update);
5268fa790ea9SDavid C Somayajulu break;
5269fa790ea9SDavid C Somayajulu case RDMA_CQE_TYPE_RESPONDER_RQ:
5270fa790ea9SDavid C Somayajulu cnt = qlnxr_poll_cq_resp(dev, qp, cq, num_entries,
5271fa790ea9SDavid C Somayajulu wc, &cqe->resp, &update);
5272fa790ea9SDavid C Somayajulu break;
5273fa790ea9SDavid C Somayajulu case RDMA_CQE_TYPE_RESPONDER_SRQ:
5274fa790ea9SDavid C Somayajulu cnt = qlnxr_poll_cq_resp_srq(dev, qp, cq, num_entries,
5275fa790ea9SDavid C Somayajulu wc, &cqe->resp, &update);
5276fa790ea9SDavid C Somayajulu break;
5277fa790ea9SDavid C Somayajulu case RDMA_CQE_TYPE_INVALID:
5278fa790ea9SDavid C Somayajulu default:
5279fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "cqe type [0x%x] invalid\n", cqe_type);
5280fa790ea9SDavid C Somayajulu break;
5281fa790ea9SDavid C Somayajulu }
5282fa790ea9SDavid C Somayajulu num_entries -= cnt;
5283fa790ea9SDavid C Somayajulu wc += cnt;
5284fa790ea9SDavid C Somayajulu done += cnt;
5285fa790ea9SDavid C Somayajulu
5286fa790ea9SDavid C Somayajulu cqe = cq->latest_cqe;
5287fa790ea9SDavid C Somayajulu }
5288fa790ea9SDavid C Somayajulu new_cons = ecore_chain_get_cons_idx_u32(&cq->pbl);
5289fa790ea9SDavid C Somayajulu
5290fa790ea9SDavid C Somayajulu cq->cq_cons += new_cons - old_cons;
5291fa790ea9SDavid C Somayajulu
5292fa790ea9SDavid C Somayajulu if (update) {
5293fa790ea9SDavid C Somayajulu /* doorbell notifies abount latest VALID entry,
5294fa790ea9SDavid C Somayajulu * but chain already point to the next INVALID one
5295fa790ea9SDavid C Somayajulu */
5296fa790ea9SDavid C Somayajulu doorbell_cq(dev, cq, cq->cq_cons - 1, cq->arm_flags);
5297fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "cq = %p cons = 0x%x "
5298fa790ea9SDavid C Somayajulu "arm_flags = 0x%x db.icid = 0x%x\n", cq,
5299fa790ea9SDavid C Somayajulu (cq->cq_cons - 1), cq->arm_flags, cq->db.data.icid);
5300fa790ea9SDavid C Somayajulu }
5301fa790ea9SDavid C Somayajulu
5302fa790ea9SDavid C Somayajulu spin_unlock_irqrestore(&cq->cq_lock, flags);
5303fa790ea9SDavid C Somayajulu
5304fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
5305fa790ea9SDavid C Somayajulu
5306fa790ea9SDavid C Somayajulu return done;
5307fa790ea9SDavid C Somayajulu }
5308fa790ea9SDavid C Somayajulu
5309fa790ea9SDavid C Somayajulu int
qlnxr_arm_cq(struct ib_cq * ibcq,enum ib_cq_notify_flags flags)5310fa790ea9SDavid C Somayajulu qlnxr_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
5311fa790ea9SDavid C Somayajulu {
5312fa790ea9SDavid C Somayajulu struct qlnxr_cq *cq = get_qlnxr_cq(ibcq);
5313fa790ea9SDavid C Somayajulu unsigned long sflags;
5314fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
5315fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5316fa790ea9SDavid C Somayajulu
5317fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev((ibcq->device));
5318fa790ea9SDavid C Somayajulu ha = dev->ha;
5319fa790ea9SDavid C Somayajulu
5320fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter ibcq = %p flags = 0x%x "
5321fa790ea9SDavid C Somayajulu "cp = %p cons = 0x%x cq_type = 0x%x\n", ibcq,
5322fa790ea9SDavid C Somayajulu flags, cq, cq->cq_cons, cq->cq_type);
5323fa790ea9SDavid C Somayajulu
5324*727bfe38SJustin Hibbits if (!(if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING))
5325fa790ea9SDavid C Somayajulu return -EINVAL;
5326fa790ea9SDavid C Somayajulu
5327fa790ea9SDavid C Somayajulu if (cq->destroyed) {
5328fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "cq was already destroyed cq = %p icid=%d\n",
5329fa790ea9SDavid C Somayajulu cq, cq->icid);
5330fa790ea9SDavid C Somayajulu return -EINVAL;
5331fa790ea9SDavid C Somayajulu }
5332fa790ea9SDavid C Somayajulu
5333fa790ea9SDavid C Somayajulu if (cq->cq_type == QLNXR_CQ_TYPE_GSI) {
5334fa790ea9SDavid C Somayajulu return 0;
5335fa790ea9SDavid C Somayajulu }
5336fa790ea9SDavid C Somayajulu
5337fa790ea9SDavid C Somayajulu spin_lock_irqsave(&cq->cq_lock, sflags);
5338fa790ea9SDavid C Somayajulu
5339fa790ea9SDavid C Somayajulu cq->arm_flags = 0;
5340fa790ea9SDavid C Somayajulu
5341fa790ea9SDavid C Somayajulu if (flags & IB_CQ_SOLICITED) {
5342fa790ea9SDavid C Somayajulu cq->arm_flags |= DQ_UCM_ROCE_CQ_ARM_SE_CF_CMD;
5343fa790ea9SDavid C Somayajulu }
5344fa790ea9SDavid C Somayajulu if (flags & IB_CQ_NEXT_COMP) {
5345fa790ea9SDavid C Somayajulu cq->arm_flags |= DQ_UCM_ROCE_CQ_ARM_CF_CMD;
5346fa790ea9SDavid C Somayajulu }
5347fa790ea9SDavid C Somayajulu
5348fa790ea9SDavid C Somayajulu doorbell_cq(dev, cq, (cq->cq_cons - 1), cq->arm_flags);
5349fa790ea9SDavid C Somayajulu
5350fa790ea9SDavid C Somayajulu spin_unlock_irqrestore(&cq->cq_lock, sflags);
5351fa790ea9SDavid C Somayajulu
5352fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit ibcq = %p flags = 0x%x\n", ibcq, flags);
5353fa790ea9SDavid C Somayajulu return 0;
5354fa790ea9SDavid C Somayajulu }
5355fa790ea9SDavid C Somayajulu
5356fa790ea9SDavid C Somayajulu static struct qlnxr_mr *
__qlnxr_alloc_mr(struct ib_pd * ibpd,int max_page_list_len)5357fa790ea9SDavid C Somayajulu __qlnxr_alloc_mr(struct ib_pd *ibpd, int max_page_list_len)
5358fa790ea9SDavid C Somayajulu {
5359fa790ea9SDavid C Somayajulu struct qlnxr_pd *pd = get_qlnxr_pd(ibpd);
5360fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev((ibpd->device));
5361fa790ea9SDavid C Somayajulu struct qlnxr_mr *mr;
5362fa790ea9SDavid C Somayajulu int rc = -ENOMEM;
5363fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5364fa790ea9SDavid C Somayajulu
5365fa790ea9SDavid C Somayajulu ha = dev->ha;
5366fa790ea9SDavid C Somayajulu
5367fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter ibpd = %p pd = %p "
5368fa790ea9SDavid C Somayajulu " pd_id = %d max_page_list_len = %d\n",
5369fa790ea9SDavid C Somayajulu ibpd, pd, pd->pd_id, max_page_list_len);
5370fa790ea9SDavid C Somayajulu
5371fa790ea9SDavid C Somayajulu mr = kzalloc(sizeof(*mr), GFP_KERNEL);
5372fa790ea9SDavid C Somayajulu if (!mr) {
5373fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "kzalloc(mr) failed\n");
5374fa790ea9SDavid C Somayajulu return ERR_PTR(rc);
5375fa790ea9SDavid C Somayajulu }
5376fa790ea9SDavid C Somayajulu
5377fa790ea9SDavid C Somayajulu mr->dev = dev;
5378fa790ea9SDavid C Somayajulu mr->type = QLNXR_MR_FRMR;
5379fa790ea9SDavid C Somayajulu
5380fa790ea9SDavid C Somayajulu rc = qlnxr_init_mr_info(dev, &mr->info, max_page_list_len,
5381fa790ea9SDavid C Somayajulu 1 /* allow dual layer pbl */);
5382fa790ea9SDavid C Somayajulu if (rc) {
5383fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_init_mr_info failed\n");
5384fa790ea9SDavid C Somayajulu goto err0;
5385fa790ea9SDavid C Somayajulu }
5386fa790ea9SDavid C Somayajulu
5387fa790ea9SDavid C Somayajulu rc = ecore_rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid);
5388fa790ea9SDavid C Somayajulu if (rc) {
5389fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ecore_rdma_alloc_tid failed\n");
5390fa790ea9SDavid C Somayajulu goto err0;
5391fa790ea9SDavid C Somayajulu }
5392fa790ea9SDavid C Somayajulu
5393fa790ea9SDavid C Somayajulu /* index only, 18 bit long, lkey = itid << 8 | key */
5394fa790ea9SDavid C Somayajulu mr->hw_mr.tid_type = ECORE_RDMA_TID_FMR;
5395fa790ea9SDavid C Somayajulu mr->hw_mr.key = 0;
5396fa790ea9SDavid C Somayajulu mr->hw_mr.pd = pd->pd_id;
5397fa790ea9SDavid C Somayajulu mr->hw_mr.local_read = 1;
5398fa790ea9SDavid C Somayajulu mr->hw_mr.local_write = 0;
5399fa790ea9SDavid C Somayajulu mr->hw_mr.remote_read = 0;
5400fa790ea9SDavid C Somayajulu mr->hw_mr.remote_write = 0;
5401fa790ea9SDavid C Somayajulu mr->hw_mr.remote_atomic = 0;
5402fa790ea9SDavid C Somayajulu mr->hw_mr.mw_bind = false; /* TBD MW BIND */
5403fa790ea9SDavid C Somayajulu mr->hw_mr.pbl_ptr = 0; /* Will be supplied during post */
5404fa790ea9SDavid C Somayajulu mr->hw_mr.pbl_two_level = mr->info.pbl_info.two_layered;
5405fa790ea9SDavid C Somayajulu mr->hw_mr.pbl_page_size_log = ilog2(mr->info.pbl_info.pbl_size);
5406fa790ea9SDavid C Somayajulu mr->hw_mr.fbo = 0;
5407fa790ea9SDavid C Somayajulu mr->hw_mr.length = 0;
5408fa790ea9SDavid C Somayajulu mr->hw_mr.vaddr = 0;
5409fa790ea9SDavid C Somayajulu mr->hw_mr.zbva = false; /* TBD figure when this should be true */
5410fa790ea9SDavid C Somayajulu mr->hw_mr.phy_mr = true; /* Fast MR - True, Regular Register False */
5411fa790ea9SDavid C Somayajulu mr->hw_mr.dma_mr = false;
5412fa790ea9SDavid C Somayajulu
5413fa790ea9SDavid C Somayajulu rc = ecore_rdma_register_tid(dev->rdma_ctx, &mr->hw_mr);
5414fa790ea9SDavid C Somayajulu if (rc) {
5415fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ecore_rdma_register_tid failed\n");
5416fa790ea9SDavid C Somayajulu goto err1;
5417fa790ea9SDavid C Somayajulu }
5418fa790ea9SDavid C Somayajulu
5419fa790ea9SDavid C Somayajulu mr->ibmr.lkey = mr->hw_mr.itid << 8 | mr->hw_mr.key;
5420fa790ea9SDavid C Somayajulu mr->ibmr.rkey = mr->ibmr.lkey;
5421fa790ea9SDavid C Somayajulu
5422fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit mr = %p mr->ibmr.lkey = 0x%x\n",
5423fa790ea9SDavid C Somayajulu mr, mr->ibmr.lkey);
5424fa790ea9SDavid C Somayajulu
5425fa790ea9SDavid C Somayajulu return mr;
5426fa790ea9SDavid C Somayajulu
5427fa790ea9SDavid C Somayajulu err1:
5428fa790ea9SDavid C Somayajulu ecore_rdma_free_tid(dev->rdma_ctx, mr->hw_mr.itid);
5429fa790ea9SDavid C Somayajulu err0:
5430fa790ea9SDavid C Somayajulu kfree(mr);
5431fa790ea9SDavid C Somayajulu
5432fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
5433fa790ea9SDavid C Somayajulu
5434fa790ea9SDavid C Somayajulu return ERR_PTR(rc);
5435fa790ea9SDavid C Somayajulu }
5436fa790ea9SDavid C Somayajulu
5437fa790ea9SDavid C Somayajulu struct ib_mr *
qlnxr_alloc_mr(struct ib_pd * ibpd,enum ib_mr_type mr_type,u32 max_num_sg,struct ib_udata * udata)5438b633e08cSHans Petter Selasky qlnxr_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type,
5439b633e08cSHans Petter Selasky u32 max_num_sg, struct ib_udata *udata)
5440fa790ea9SDavid C Somayajulu {
5441fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
5442fa790ea9SDavid C Somayajulu struct qlnxr_mr *mr;
5443fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5444fa790ea9SDavid C Somayajulu
5445fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibpd->device);
5446fa790ea9SDavid C Somayajulu ha = dev->ha;
5447fa790ea9SDavid C Somayajulu
5448fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5449fa790ea9SDavid C Somayajulu
5450fa790ea9SDavid C Somayajulu if (mr_type != IB_MR_TYPE_MEM_REG)
5451fa790ea9SDavid C Somayajulu return ERR_PTR(-EINVAL);
5452fa790ea9SDavid C Somayajulu
5453fa790ea9SDavid C Somayajulu mr = __qlnxr_alloc_mr(ibpd, max_num_sg);
5454fa790ea9SDavid C Somayajulu
5455fa790ea9SDavid C Somayajulu if (IS_ERR(mr))
5456fa790ea9SDavid C Somayajulu return ERR_PTR(-EINVAL);
5457fa790ea9SDavid C Somayajulu
5458fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit mr = %p &mr->ibmr = %p\n", mr, &mr->ibmr);
5459fa790ea9SDavid C Somayajulu
5460fa790ea9SDavid C Somayajulu return &mr->ibmr;
5461fa790ea9SDavid C Somayajulu }
5462fa790ea9SDavid C Somayajulu
5463fa790ea9SDavid C Somayajulu static int
qlnxr_set_page(struct ib_mr * ibmr,u64 addr)5464fa790ea9SDavid C Somayajulu qlnxr_set_page(struct ib_mr *ibmr, u64 addr)
5465fa790ea9SDavid C Somayajulu {
5466fa790ea9SDavid C Somayajulu struct qlnxr_mr *mr = get_qlnxr_mr(ibmr);
5467fa790ea9SDavid C Somayajulu struct qlnxr_pbl *pbl_table;
5468fa790ea9SDavid C Somayajulu struct regpair *pbe;
5469fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
5470fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5471fa790ea9SDavid C Somayajulu u32 pbes_in_page;
5472fa790ea9SDavid C Somayajulu
5473fa790ea9SDavid C Somayajulu dev = mr->dev;
5474fa790ea9SDavid C Somayajulu ha = dev->ha;
5475fa790ea9SDavid C Somayajulu
5476fa790ea9SDavid C Somayajulu if (unlikely(mr->npages == mr->info.pbl_info.num_pbes)) {
5477fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "fails mr->npages %d\n", mr->npages);
5478fa790ea9SDavid C Somayajulu return -ENOMEM;
5479fa790ea9SDavid C Somayajulu }
5480fa790ea9SDavid C Somayajulu
5481fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "mr->npages %d addr = %p enter\n", mr->npages,
5482fa790ea9SDavid C Somayajulu ((void *)addr));
5483fa790ea9SDavid C Somayajulu
5484fa790ea9SDavid C Somayajulu pbes_in_page = mr->info.pbl_info.pbl_size / sizeof(u64);
5485fa790ea9SDavid C Somayajulu pbl_table = mr->info.pbl_table + (mr->npages / pbes_in_page);
5486fa790ea9SDavid C Somayajulu pbe = (struct regpair *)pbl_table->va;
5487fa790ea9SDavid C Somayajulu pbe += mr->npages % pbes_in_page;
5488fa790ea9SDavid C Somayajulu pbe->lo = cpu_to_le32((u32)addr);
5489fa790ea9SDavid C Somayajulu pbe->hi = cpu_to_le32((u32)upper_32_bits(addr));
5490fa790ea9SDavid C Somayajulu
5491fa790ea9SDavid C Somayajulu mr->npages++;
5492fa790ea9SDavid C Somayajulu
5493fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "mr->npages %d addr = %p exit \n", mr->npages,
5494fa790ea9SDavid C Somayajulu ((void *)addr));
5495fa790ea9SDavid C Somayajulu return 0;
5496fa790ea9SDavid C Somayajulu }
5497fa790ea9SDavid C Somayajulu
5498fa790ea9SDavid C Somayajulu int
qlnxr_map_mr_sg(struct ib_mr * ibmr,struct scatterlist * sg,int sg_nents,unsigned int * sg_offset)5499fa790ea9SDavid C Somayajulu qlnxr_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg,
5500fa790ea9SDavid C Somayajulu int sg_nents, unsigned int *sg_offset)
5501fa790ea9SDavid C Somayajulu {
5502fa790ea9SDavid C Somayajulu int ret;
5503fa790ea9SDavid C Somayajulu struct qlnxr_mr *mr = get_qlnxr_mr(ibmr);
5504fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5505fa790ea9SDavid C Somayajulu
5506fa790ea9SDavid C Somayajulu if (mr == NULL)
5507fa790ea9SDavid C Somayajulu return (-1);
5508fa790ea9SDavid C Somayajulu
5509fa790ea9SDavid C Somayajulu if (mr->dev == NULL)
5510fa790ea9SDavid C Somayajulu return (-1);
5511fa790ea9SDavid C Somayajulu
5512fa790ea9SDavid C Somayajulu ha = mr->dev->ha;
5513fa790ea9SDavid C Somayajulu
5514fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5515fa790ea9SDavid C Somayajulu
5516fa790ea9SDavid C Somayajulu mr->npages = 0;
5517fa790ea9SDavid C Somayajulu qlnx_handle_completed_mrs(mr->dev, &mr->info);
5518fa790ea9SDavid C Somayajulu
5519fa790ea9SDavid C Somayajulu ret = ib_sg_to_pages(ibmr, sg, sg_nents, NULL, qlnxr_set_page);
5520fa790ea9SDavid C Somayajulu
5521fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit ret = %d\n", ret);
5522fa790ea9SDavid C Somayajulu
5523fa790ea9SDavid C Somayajulu return (ret);
5524fa790ea9SDavid C Somayajulu }
5525fa790ea9SDavid C Somayajulu
5526fa790ea9SDavid C Somayajulu int
qlnxr_create_ah(struct ib_ah * ibah,struct ib_ah_attr * attr,u32 flags,struct ib_udata * udata)5527b633e08cSHans Petter Selasky qlnxr_create_ah(struct ib_ah *ibah,
5528b633e08cSHans Petter Selasky struct ib_ah_attr *attr, u32 flags,
5529b633e08cSHans Petter Selasky struct ib_udata *udata)
5530fa790ea9SDavid C Somayajulu {
5531fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
5532fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5533fa790ea9SDavid C Somayajulu struct qlnxr_ah *ah = get_qlnxr_ah(ibah);
5534fa790ea9SDavid C Somayajulu
5535b633e08cSHans Petter Selasky dev = get_qlnxr_dev(ibah->device);
5536fa790ea9SDavid C Somayajulu ha = dev->ha;
5537fa790ea9SDavid C Somayajulu
5538b633e08cSHans Petter Selasky QL_DPRINT12(ha, "in create_ah\n");
5539fa790ea9SDavid C Somayajulu
5540b633e08cSHans Petter Selasky ah->attr = *attr;
5541b633e08cSHans Petter Selasky
5542b633e08cSHans Petter Selasky return (0);
5543b633e08cSHans Petter Selasky }
5544b633e08cSHans Petter Selasky
5545b633e08cSHans Petter Selasky void
qlnxr_destroy_ah(struct ib_ah * ibah,u32 flags)5546b633e08cSHans Petter Selasky qlnxr_destroy_ah(struct ib_ah *ibah, u32 flags)
5547b633e08cSHans Petter Selasky {
5548fa790ea9SDavid C Somayajulu }
5549fa790ea9SDavid C Somayajulu
5550fa790ea9SDavid C Somayajulu int
qlnxr_query_ah(struct ib_ah * ibah,struct ib_ah_attr * attr)5551fa790ea9SDavid C Somayajulu qlnxr_query_ah(struct ib_ah *ibah, struct ib_ah_attr *attr)
5552fa790ea9SDavid C Somayajulu {
5553fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
5554fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5555fa790ea9SDavid C Somayajulu
5556fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev((ibah->device));
5557fa790ea9SDavid C Somayajulu ha = dev->ha;
5558fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "Query AH not supported\n");
5559fa790ea9SDavid C Somayajulu return -EINVAL;
5560fa790ea9SDavid C Somayajulu }
5561fa790ea9SDavid C Somayajulu
5562fa790ea9SDavid C Somayajulu int
qlnxr_modify_ah(struct ib_ah * ibah,struct ib_ah_attr * attr)5563fa790ea9SDavid C Somayajulu qlnxr_modify_ah(struct ib_ah *ibah, struct ib_ah_attr *attr)
5564fa790ea9SDavid C Somayajulu {
5565fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
5566fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5567fa790ea9SDavid C Somayajulu
5568fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev((ibah->device));
5569fa790ea9SDavid C Somayajulu ha = dev->ha;
5570fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "Modify AH not supported\n");
5571fa790ea9SDavid C Somayajulu return -ENOSYS;
5572fa790ea9SDavid C Somayajulu }
5573fa790ea9SDavid C Somayajulu
5574fa790ea9SDavid C Somayajulu int
qlnxr_process_mad(struct ib_device * ibdev,int process_mad_flags,u8 port_num,const struct ib_wc * in_wc,const struct ib_grh * in_grh,const struct ib_mad_hdr * mad_hdr,size_t in_mad_size,struct ib_mad_hdr * out_mad,size_t * out_mad_size,u16 * out_mad_pkey_index)5575fa790ea9SDavid C Somayajulu qlnxr_process_mad(struct ib_device *ibdev,
5576fa790ea9SDavid C Somayajulu int process_mad_flags,
5577fa790ea9SDavid C Somayajulu u8 port_num,
5578fa790ea9SDavid C Somayajulu const struct ib_wc *in_wc,
5579fa790ea9SDavid C Somayajulu const struct ib_grh *in_grh,
5580fa790ea9SDavid C Somayajulu const struct ib_mad_hdr *mad_hdr,
5581fa790ea9SDavid C Somayajulu size_t in_mad_size,
5582fa790ea9SDavid C Somayajulu struct ib_mad_hdr *out_mad,
5583fa790ea9SDavid C Somayajulu size_t *out_mad_size,
5584fa790ea9SDavid C Somayajulu u16 *out_mad_pkey_index)
5585fa790ea9SDavid C Somayajulu {
5586fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
5587fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5588fa790ea9SDavid C Somayajulu
5589fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
5590fa790ea9SDavid C Somayajulu ha = dev->ha;
5591fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "process mad not supported\n");
5592fa790ea9SDavid C Somayajulu
5593fa790ea9SDavid C Somayajulu return -ENOSYS;
5594fa790ea9SDavid C Somayajulu // QL_DPRINT12(ha, "qlnxr_process_mad in_mad %x %x %x %x %x %x %x %x\n",
5595fa790ea9SDavid C Somayajulu // in_mad->mad_hdr.attr_id, in_mad->mad_hdr.base_version,
5596fa790ea9SDavid C Somayajulu // in_mad->mad_hdr.attr_mod, in_mad->mad_hdr.class_specific,
5597fa790ea9SDavid C Somayajulu // in_mad->mad_hdr.class_version, in_mad->mad_hdr.method,
5598fa790ea9SDavid C Somayajulu // in_mad->mad_hdr.mgmt_class, in_mad->mad_hdr.status);
5599fa790ea9SDavid C Somayajulu
5600fa790ea9SDavid C Somayajulu // return IB_MAD_RESULT_SUCCESS;
5601fa790ea9SDavid C Somayajulu }
5602fa790ea9SDavid C Somayajulu
5603fa790ea9SDavid C Somayajulu int
qlnxr_get_port_immutable(struct ib_device * ibdev,u8 port_num,struct ib_port_immutable * immutable)5604fa790ea9SDavid C Somayajulu qlnxr_get_port_immutable(struct ib_device *ibdev, u8 port_num,
5605fa790ea9SDavid C Somayajulu struct ib_port_immutable *immutable)
5606fa790ea9SDavid C Somayajulu {
5607fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
5608fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5609fa790ea9SDavid C Somayajulu struct ib_port_attr attr;
5610fa790ea9SDavid C Somayajulu int err;
5611fa790ea9SDavid C Somayajulu
5612fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev(ibdev);
5613fa790ea9SDavid C Somayajulu ha = dev->ha;
5614fa790ea9SDavid C Somayajulu
5615fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5616fa790ea9SDavid C Somayajulu
5617fa790ea9SDavid C Somayajulu err = qlnxr_query_port(ibdev, port_num, &attr);
5618fa790ea9SDavid C Somayajulu if (err)
5619fa790ea9SDavid C Somayajulu return err;
5620fa790ea9SDavid C Somayajulu
5621fa790ea9SDavid C Somayajulu if (QLNX_IS_IWARP(dev)) {
5622fa790ea9SDavid C Somayajulu immutable->pkey_tbl_len = 1;
5623fa790ea9SDavid C Somayajulu immutable->gid_tbl_len = 1;
5624fa790ea9SDavid C Somayajulu immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
5625fa790ea9SDavid C Somayajulu immutable->max_mad_size = 0;
5626fa790ea9SDavid C Somayajulu } else {
5627fa790ea9SDavid C Somayajulu immutable->pkey_tbl_len = attr.pkey_tbl_len;
5628fa790ea9SDavid C Somayajulu immutable->gid_tbl_len = attr.gid_tbl_len;
5629fa790ea9SDavid C Somayajulu immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE;
5630fa790ea9SDavid C Somayajulu immutable->max_mad_size = IB_MGMT_MAD_SIZE;
5631fa790ea9SDavid C Somayajulu }
5632fa790ea9SDavid C Somayajulu
5633fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
5634fa790ea9SDavid C Somayajulu return 0;
5635fa790ea9SDavid C Somayajulu }
5636fa790ea9SDavid C Somayajulu
5637fa790ea9SDavid C Somayajulu /***** iWARP related functions *************/
5638fa790ea9SDavid C Somayajulu
5639fa790ea9SDavid C Somayajulu static void
qlnxr_iw_mpa_request(void * context,struct ecore_iwarp_cm_event_params * params)5640fa790ea9SDavid C Somayajulu qlnxr_iw_mpa_request(void *context,
5641fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params *params)
5642fa790ea9SDavid C Somayajulu {
5643fa790ea9SDavid C Somayajulu struct qlnxr_iw_listener *listener = (struct qlnxr_iw_listener *)context;
5644fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = listener->dev;
5645fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep;
5646fa790ea9SDavid C Somayajulu struct iw_cm_event event;
5647fa790ea9SDavid C Somayajulu struct sockaddr_in *laddr;
5648fa790ea9SDavid C Somayajulu struct sockaddr_in *raddr;
5649fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5650fa790ea9SDavid C Somayajulu
5651fa790ea9SDavid C Somayajulu ha = dev->ha;
5652fa790ea9SDavid C Somayajulu
5653fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5654fa790ea9SDavid C Somayajulu
5655fa790ea9SDavid C Somayajulu if (params->cm_info->ip_version != ECORE_TCP_IPV4) {
5656fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "only IPv4 supported [0x%x]\n",
5657fa790ea9SDavid C Somayajulu params->cm_info->ip_version);
5658fa790ea9SDavid C Somayajulu return;
5659fa790ea9SDavid C Somayajulu }
5660fa790ea9SDavid C Somayajulu
5661fa790ea9SDavid C Somayajulu ep = kzalloc(sizeof(*ep), GFP_ATOMIC);
5662fa790ea9SDavid C Somayajulu
5663fa790ea9SDavid C Somayajulu if (!ep) {
5664fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "kzalloc{ep) failed\n");
5665fa790ea9SDavid C Somayajulu return;
5666fa790ea9SDavid C Somayajulu }
5667fa790ea9SDavid C Somayajulu
5668fa790ea9SDavid C Somayajulu ep->dev = dev;
5669fa790ea9SDavid C Somayajulu ep->ecore_context = params->ep_context;
5670fa790ea9SDavid C Somayajulu
5671fa790ea9SDavid C Somayajulu memset(&event, 0, sizeof(event));
5672fa790ea9SDavid C Somayajulu
5673fa790ea9SDavid C Somayajulu event.event = IW_CM_EVENT_CONNECT_REQUEST;
5674fa790ea9SDavid C Somayajulu event.status = params->status;
5675fa790ea9SDavid C Somayajulu
5676fa790ea9SDavid C Somayajulu laddr = (struct sockaddr_in *)&event.local_addr;
5677fa790ea9SDavid C Somayajulu raddr = (struct sockaddr_in *)&event.remote_addr;
5678fa790ea9SDavid C Somayajulu
5679fa790ea9SDavid C Somayajulu laddr->sin_family = AF_INET;
5680fa790ea9SDavid C Somayajulu raddr->sin_family = AF_INET;
5681fa790ea9SDavid C Somayajulu
5682fa790ea9SDavid C Somayajulu laddr->sin_port = htons(params->cm_info->local_port);
5683fa790ea9SDavid C Somayajulu raddr->sin_port = htons(params->cm_info->remote_port);
5684fa790ea9SDavid C Somayajulu
5685fa790ea9SDavid C Somayajulu laddr->sin_addr.s_addr = htonl(params->cm_info->local_ip[0]);
5686fa790ea9SDavid C Somayajulu raddr->sin_addr.s_addr = htonl(params->cm_info->remote_ip[0]);
5687fa790ea9SDavid C Somayajulu
5688fa790ea9SDavid C Somayajulu event.provider_data = (void *)ep;
5689fa790ea9SDavid C Somayajulu event.private_data = (void *)params->cm_info->private_data;
5690fa790ea9SDavid C Somayajulu event.private_data_len = (u8)params->cm_info->private_data_len;
5691fa790ea9SDavid C Somayajulu
5692fa790ea9SDavid C Somayajulu event.ord = params->cm_info->ord;
5693fa790ea9SDavid C Somayajulu event.ird = params->cm_info->ird;
5694fa790ea9SDavid C Somayajulu
5695fa790ea9SDavid C Somayajulu listener->cm_id->event_handler(listener->cm_id, &event);
5696fa790ea9SDavid C Somayajulu
5697fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
5698fa790ea9SDavid C Somayajulu
5699fa790ea9SDavid C Somayajulu return;
5700fa790ea9SDavid C Somayajulu }
5701fa790ea9SDavid C Somayajulu
5702fa790ea9SDavid C Somayajulu static void
qlnxr_iw_issue_event(void * context,struct ecore_iwarp_cm_event_params * params,enum iw_cm_event_type event_type,char * str)5703fa790ea9SDavid C Somayajulu qlnxr_iw_issue_event(void *context,
5704fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params *params,
5705fa790ea9SDavid C Somayajulu enum iw_cm_event_type event_type,
5706fa790ea9SDavid C Somayajulu char *str)
5707fa790ea9SDavid C Somayajulu {
5708fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)context;
5709fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
5710fa790ea9SDavid C Somayajulu struct iw_cm_event event;
5711fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5712fa790ea9SDavid C Somayajulu
5713fa790ea9SDavid C Somayajulu ha = dev->ha;
5714fa790ea9SDavid C Somayajulu
5715fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5716fa790ea9SDavid C Somayajulu
5717fa790ea9SDavid C Somayajulu memset(&event, 0, sizeof(event));
5718fa790ea9SDavid C Somayajulu event.status = params->status;
5719fa790ea9SDavid C Somayajulu event.event = event_type;
5720fa790ea9SDavid C Somayajulu
5721fa790ea9SDavid C Somayajulu if (params->cm_info != NULL) {
5722fa790ea9SDavid C Somayajulu event.ird = params->cm_info->ird;
5723fa790ea9SDavid C Somayajulu event.ord = params->cm_info->ord;
5724fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ord=[%d] \n", event.ord);
5725fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ird=[%d] \n", event.ird);
5726fa790ea9SDavid C Somayajulu
5727fa790ea9SDavid C Somayajulu event.private_data_len = params->cm_info->private_data_len;
5728fa790ea9SDavid C Somayajulu event.private_data = (void *)params->cm_info->private_data;
5729fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "private_data_len=[%d] \n",
5730fa790ea9SDavid C Somayajulu event.private_data_len);
5731fa790ea9SDavid C Somayajulu }
5732fa790ea9SDavid C Somayajulu
5733fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "event=[%d] %s\n", event.event, str);
5734fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "status=[%d] \n", event.status);
5735fa790ea9SDavid C Somayajulu
5736fa790ea9SDavid C Somayajulu if (ep) {
5737fa790ea9SDavid C Somayajulu if (ep->cm_id)
5738fa790ea9SDavid C Somayajulu ep->cm_id->event_handler(ep->cm_id, &event);
5739fa790ea9SDavid C Somayajulu else
5740fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ep->cm_id == NULL \n");
5741fa790ea9SDavid C Somayajulu } else {
5742fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ep == NULL \n");
5743fa790ea9SDavid C Somayajulu }
5744fa790ea9SDavid C Somayajulu
5745fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
5746fa790ea9SDavid C Somayajulu
5747fa790ea9SDavid C Somayajulu return;
5748fa790ea9SDavid C Somayajulu }
5749fa790ea9SDavid C Somayajulu
5750fa790ea9SDavid C Somayajulu static void
qlnxr_iw_close_event(void * context,struct ecore_iwarp_cm_event_params * params)5751fa790ea9SDavid C Somayajulu qlnxr_iw_close_event(void *context,
5752fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params *params)
5753fa790ea9SDavid C Somayajulu {
5754fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)context;
5755fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
5756fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5757fa790ea9SDavid C Somayajulu
5758fa790ea9SDavid C Somayajulu ha = dev->ha;
5759fa790ea9SDavid C Somayajulu
5760fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5761fa790ea9SDavid C Somayajulu
5762fa790ea9SDavid C Somayajulu if (ep->cm_id) {
5763fa790ea9SDavid C Somayajulu qlnxr_iw_issue_event(context,
5764fa790ea9SDavid C Somayajulu params,
5765fa790ea9SDavid C Somayajulu IW_CM_EVENT_CLOSE,
5766fa790ea9SDavid C Somayajulu "IW_CM_EVENT_EVENT_CLOSE");
5767fa790ea9SDavid C Somayajulu ep->cm_id->rem_ref(ep->cm_id);
5768fa790ea9SDavid C Somayajulu ep->cm_id = NULL;
5769fa790ea9SDavid C Somayajulu }
5770fa790ea9SDavid C Somayajulu
5771fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
5772fa790ea9SDavid C Somayajulu
5773fa790ea9SDavid C Somayajulu return;
5774fa790ea9SDavid C Somayajulu }
5775fa790ea9SDavid C Somayajulu
5776fa790ea9SDavid C Somayajulu static void
qlnxr_iw_passive_complete(void * context,struct ecore_iwarp_cm_event_params * params)5777fa790ea9SDavid C Somayajulu qlnxr_iw_passive_complete(void *context,
5778fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params *params)
5779fa790ea9SDavid C Somayajulu {
5780fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)context;
5781fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
5782fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5783fa790ea9SDavid C Somayajulu
5784fa790ea9SDavid C Somayajulu ha = dev->ha;
5785fa790ea9SDavid C Somayajulu
5786fa790ea9SDavid C Somayajulu /* We will only reach the following state if MPA_REJECT was called on
5787fa790ea9SDavid C Somayajulu * passive. In this case there will be no associated QP.
5788fa790ea9SDavid C Somayajulu */
5789fa790ea9SDavid C Somayajulu if ((params->status == -ECONNREFUSED) && (ep->qp == NULL)) {
5790fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "PASSIVE connection refused releasing ep...\n");
5791fa790ea9SDavid C Somayajulu kfree(ep);
5792fa790ea9SDavid C Somayajulu return;
5793fa790ea9SDavid C Somayajulu }
5794fa790ea9SDavid C Somayajulu
5795fa790ea9SDavid C Somayajulu /* We always issue an established event, however, ofed does not look
5796fa790ea9SDavid C Somayajulu * at event code for established. So if there was a failure, we follow
5797fa790ea9SDavid C Somayajulu * with close...
5798fa790ea9SDavid C Somayajulu */
5799fa790ea9SDavid C Somayajulu qlnxr_iw_issue_event(context,
5800fa790ea9SDavid C Somayajulu params,
5801fa790ea9SDavid C Somayajulu IW_CM_EVENT_ESTABLISHED,
5802fa790ea9SDavid C Somayajulu "IW_CM_EVENT_ESTABLISHED");
5803fa790ea9SDavid C Somayajulu
5804fa790ea9SDavid C Somayajulu if (params->status < 0) {
5805fa790ea9SDavid C Somayajulu qlnxr_iw_close_event(context, params);
5806fa790ea9SDavid C Somayajulu }
5807fa790ea9SDavid C Somayajulu
5808fa790ea9SDavid C Somayajulu return;
5809fa790ea9SDavid C Somayajulu }
5810fa790ea9SDavid C Somayajulu
5811fa790ea9SDavid C Somayajulu struct qlnxr_discon_work {
5812fa790ea9SDavid C Somayajulu struct work_struct work;
5813fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep;
5814fa790ea9SDavid C Somayajulu enum ecore_iwarp_event_type event;
5815fa790ea9SDavid C Somayajulu int status;
5816fa790ea9SDavid C Somayajulu };
5817fa790ea9SDavid C Somayajulu
5818fa790ea9SDavid C Somayajulu static void
qlnxr_iw_disconnect_worker(struct work_struct * work)5819fa790ea9SDavid C Somayajulu qlnxr_iw_disconnect_worker(struct work_struct *work)
5820fa790ea9SDavid C Somayajulu {
5821fa790ea9SDavid C Somayajulu struct qlnxr_discon_work *dwork =
5822fa790ea9SDavid C Somayajulu container_of(work, struct qlnxr_discon_work, work);
5823fa790ea9SDavid C Somayajulu struct ecore_rdma_modify_qp_in_params qp_params = { 0 };
5824fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = dwork->ep;
5825fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
5826fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp = ep->qp;
5827fa790ea9SDavid C Somayajulu struct iw_cm_event event;
5828fa790ea9SDavid C Somayajulu
5829fa790ea9SDavid C Somayajulu if (qp->destroyed) {
5830fa790ea9SDavid C Somayajulu kfree(dwork);
5831fa790ea9SDavid C Somayajulu qlnxr_iw_qp_rem_ref(&qp->ibqp);
5832fa790ea9SDavid C Somayajulu return;
5833fa790ea9SDavid C Somayajulu }
5834fa790ea9SDavid C Somayajulu
5835fa790ea9SDavid C Somayajulu memset(&event, 0, sizeof(event));
5836fa790ea9SDavid C Somayajulu event.status = dwork->status;
5837fa790ea9SDavid C Somayajulu event.event = IW_CM_EVENT_DISCONNECT;
5838fa790ea9SDavid C Somayajulu
5839fa790ea9SDavid C Somayajulu /* Success means graceful disconnect was requested. modifying
5840fa790ea9SDavid C Somayajulu * to SQD is translated to graceful disconnect. O/w reset is sent
5841fa790ea9SDavid C Somayajulu */
5842fa790ea9SDavid C Somayajulu if (dwork->status)
5843fa790ea9SDavid C Somayajulu qp_params.new_state = ECORE_ROCE_QP_STATE_ERR;
5844fa790ea9SDavid C Somayajulu else
5845fa790ea9SDavid C Somayajulu qp_params.new_state = ECORE_ROCE_QP_STATE_SQD;
5846fa790ea9SDavid C Somayajulu
5847fa790ea9SDavid C Somayajulu kfree(dwork);
5848fa790ea9SDavid C Somayajulu
5849fa790ea9SDavid C Somayajulu if (ep->cm_id)
5850fa790ea9SDavid C Somayajulu ep->cm_id->event_handler(ep->cm_id, &event);
5851fa790ea9SDavid C Somayajulu
5852fa790ea9SDavid C Somayajulu SET_FIELD(qp_params.modify_flags,
5853fa790ea9SDavid C Somayajulu ECORE_RDMA_MODIFY_QP_VALID_NEW_STATE, 1);
5854fa790ea9SDavid C Somayajulu
5855fa790ea9SDavid C Somayajulu ecore_rdma_modify_qp(dev->rdma_ctx, qp->ecore_qp, &qp_params);
5856fa790ea9SDavid C Somayajulu
5857fa790ea9SDavid C Somayajulu qlnxr_iw_qp_rem_ref(&qp->ibqp);
5858fa790ea9SDavid C Somayajulu
5859fa790ea9SDavid C Somayajulu return;
5860fa790ea9SDavid C Somayajulu }
5861fa790ea9SDavid C Somayajulu
5862fa790ea9SDavid C Somayajulu void
qlnxr_iw_disconnect_event(void * context,struct ecore_iwarp_cm_event_params * params)5863fa790ea9SDavid C Somayajulu qlnxr_iw_disconnect_event(void *context,
5864fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params *params)
5865fa790ea9SDavid C Somayajulu {
5866fa790ea9SDavid C Somayajulu struct qlnxr_discon_work *work;
5867fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)context;
5868fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
5869fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp = ep->qp;
5870fa790ea9SDavid C Somayajulu
5871fa790ea9SDavid C Somayajulu work = kzalloc(sizeof(*work), GFP_ATOMIC);
5872fa790ea9SDavid C Somayajulu if (!work)
5873fa790ea9SDavid C Somayajulu return;
5874fa790ea9SDavid C Somayajulu
5875fa790ea9SDavid C Somayajulu qlnxr_iw_qp_add_ref(&qp->ibqp);
5876fa790ea9SDavid C Somayajulu work->ep = ep;
5877fa790ea9SDavid C Somayajulu work->event = params->event;
5878fa790ea9SDavid C Somayajulu work->status = params->status;
5879fa790ea9SDavid C Somayajulu
5880fa790ea9SDavid C Somayajulu INIT_WORK(&work->work, qlnxr_iw_disconnect_worker);
5881fa790ea9SDavid C Somayajulu queue_work(dev->iwarp_wq, &work->work);
5882fa790ea9SDavid C Somayajulu
5883fa790ea9SDavid C Somayajulu return;
5884fa790ea9SDavid C Somayajulu }
5885fa790ea9SDavid C Somayajulu
5886fa790ea9SDavid C Somayajulu static int
qlnxr_iw_mpa_reply(void * context,struct ecore_iwarp_cm_event_params * params)5887fa790ea9SDavid C Somayajulu qlnxr_iw_mpa_reply(void *context,
5888fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params *params)
5889fa790ea9SDavid C Somayajulu {
5890fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)context;
5891fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
5892fa790ea9SDavid C Somayajulu struct ecore_iwarp_send_rtr_in rtr_in;
5893fa790ea9SDavid C Somayajulu int rc;
5894fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5895fa790ea9SDavid C Somayajulu
5896fa790ea9SDavid C Somayajulu ha = dev->ha;
5897fa790ea9SDavid C Somayajulu
5898fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
5899fa790ea9SDavid C Somayajulu
5900*727bfe38SJustin Hibbits if (!(if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING))
5901fa790ea9SDavid C Somayajulu return -EINVAL;
5902fa790ea9SDavid C Somayajulu
5903fa790ea9SDavid C Somayajulu bzero(&rtr_in, sizeof(struct ecore_iwarp_send_rtr_in));
5904fa790ea9SDavid C Somayajulu rtr_in.ep_context = params->ep_context;
5905fa790ea9SDavid C Somayajulu
5906fa790ea9SDavid C Somayajulu rc = ecore_iwarp_send_rtr(dev->rdma_ctx, &rtr_in);
5907fa790ea9SDavid C Somayajulu
5908fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit rc = %d\n", rc);
5909fa790ea9SDavid C Somayajulu return rc;
5910fa790ea9SDavid C Somayajulu }
5911fa790ea9SDavid C Somayajulu
5912fa790ea9SDavid C Somayajulu void
qlnxr_iw_qp_event(void * context,struct ecore_iwarp_cm_event_params * params,enum ib_event_type ib_event,char * str)5913fa790ea9SDavid C Somayajulu qlnxr_iw_qp_event(void *context,
5914fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params *params,
5915fa790ea9SDavid C Somayajulu enum ib_event_type ib_event,
5916fa790ea9SDavid C Somayajulu char *str)
5917fa790ea9SDavid C Somayajulu {
5918fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)context;
5919fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
5920fa790ea9SDavid C Somayajulu struct ib_qp *ibqp = &(ep->qp->ibqp);
5921fa790ea9SDavid C Somayajulu struct ib_event event;
5922fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5923fa790ea9SDavid C Somayajulu
5924fa790ea9SDavid C Somayajulu ha = dev->ha;
5925fa790ea9SDavid C Somayajulu
5926fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
5927fa790ea9SDavid C Somayajulu "[context, event, event_handler] = [%p, 0x%x, %s, %p] enter\n",
5928fa790ea9SDavid C Somayajulu context, params->event, str, ibqp->event_handler);
5929fa790ea9SDavid C Somayajulu
5930fa790ea9SDavid C Somayajulu if (ibqp->event_handler) {
5931fa790ea9SDavid C Somayajulu event.event = ib_event;
5932fa790ea9SDavid C Somayajulu event.device = ibqp->device;
5933fa790ea9SDavid C Somayajulu event.element.qp = ibqp;
5934fa790ea9SDavid C Somayajulu ibqp->event_handler(&event, ibqp->qp_context);
5935fa790ea9SDavid C Somayajulu }
5936fa790ea9SDavid C Somayajulu
5937fa790ea9SDavid C Somayajulu return;
5938fa790ea9SDavid C Somayajulu }
5939fa790ea9SDavid C Somayajulu
5940fa790ea9SDavid C Somayajulu int
qlnxr_iw_event_handler(void * context,struct ecore_iwarp_cm_event_params * params)5941fa790ea9SDavid C Somayajulu qlnxr_iw_event_handler(void *context,
5942fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params *params)
5943fa790ea9SDavid C Somayajulu {
5944fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)context;
5945fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
5946fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
5947fa790ea9SDavid C Somayajulu
5948fa790ea9SDavid C Somayajulu ha = dev->ha;
5949fa790ea9SDavid C Somayajulu
5950fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "[context, event] = [%p, 0x%x] "
5951fa790ea9SDavid C Somayajulu "enter\n", context, params->event);
5952fa790ea9SDavid C Somayajulu
5953fa790ea9SDavid C Somayajulu switch (params->event) {
5954fa790ea9SDavid C Somayajulu /* Passive side request received */
5955fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_MPA_REQUEST:
5956fa790ea9SDavid C Somayajulu qlnxr_iw_mpa_request(context, params);
5957fa790ea9SDavid C Somayajulu break;
5958fa790ea9SDavid C Somayajulu
5959fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_ACTIVE_MPA_REPLY:
5960fa790ea9SDavid C Somayajulu qlnxr_iw_mpa_reply(context, params);
5961fa790ea9SDavid C Somayajulu break;
5962fa790ea9SDavid C Somayajulu
5963fa790ea9SDavid C Somayajulu /* Passive side established ( ack on mpa response ) */
5964fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_PASSIVE_COMPLETE:
5965fa790ea9SDavid C Somayajulu ep->during_connect = 0;
5966fa790ea9SDavid C Somayajulu qlnxr_iw_passive_complete(context, params);
5967fa790ea9SDavid C Somayajulu break;
5968fa790ea9SDavid C Somayajulu
5969fa790ea9SDavid C Somayajulu /* Active side reply received */
5970fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_ACTIVE_COMPLETE:
5971fa790ea9SDavid C Somayajulu ep->during_connect = 0;
5972fa790ea9SDavid C Somayajulu qlnxr_iw_issue_event(context,
5973fa790ea9SDavid C Somayajulu params,
5974fa790ea9SDavid C Somayajulu IW_CM_EVENT_CONNECT_REPLY,
5975fa790ea9SDavid C Somayajulu "IW_CM_EVENT_CONNECT_REPLY");
5976fa790ea9SDavid C Somayajulu if (params->status < 0) {
5977fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)context;
5978fa790ea9SDavid C Somayajulu
5979fa790ea9SDavid C Somayajulu ep->cm_id->rem_ref(ep->cm_id);
5980fa790ea9SDavid C Somayajulu ep->cm_id = NULL;
5981fa790ea9SDavid C Somayajulu }
5982fa790ea9SDavid C Somayajulu break;
5983fa790ea9SDavid C Somayajulu
5984fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_DISCONNECT:
5985fa790ea9SDavid C Somayajulu qlnxr_iw_disconnect_event(context, params);
5986fa790ea9SDavid C Somayajulu break;
5987fa790ea9SDavid C Somayajulu
5988fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_CLOSE:
5989fa790ea9SDavid C Somayajulu ep->during_connect = 0;
5990fa790ea9SDavid C Somayajulu qlnxr_iw_close_event(context, params);
5991fa790ea9SDavid C Somayajulu break;
5992fa790ea9SDavid C Somayajulu
5993fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_RQ_EMPTY:
5994fa790ea9SDavid C Somayajulu qlnxr_iw_qp_event(context, params, IB_EVENT_QP_FATAL,
5995fa790ea9SDavid C Somayajulu "IWARP_EVENT_RQ_EMPTY");
5996fa790ea9SDavid C Somayajulu break;
5997fa790ea9SDavid C Somayajulu
5998fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_IRQ_FULL:
5999fa790ea9SDavid C Somayajulu qlnxr_iw_qp_event(context, params, IB_EVENT_QP_FATAL,
6000fa790ea9SDavid C Somayajulu "IWARP_EVENT_IRQ_FULL");
6001fa790ea9SDavid C Somayajulu break;
6002fa790ea9SDavid C Somayajulu
6003fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_LLP_TIMEOUT:
6004fa790ea9SDavid C Somayajulu qlnxr_iw_qp_event(context, params, IB_EVENT_QP_FATAL,
6005fa790ea9SDavid C Somayajulu "IWARP_EVENT_LLP_TIMEOUT");
6006fa790ea9SDavid C Somayajulu break;
6007fa790ea9SDavid C Somayajulu
6008fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_REMOTE_PROTECTION_ERROR:
6009fa790ea9SDavid C Somayajulu qlnxr_iw_qp_event(context, params, IB_EVENT_QP_ACCESS_ERR,
6010fa790ea9SDavid C Somayajulu "IWARP_EVENT_REMOTE_PROTECTION_ERROR");
6011fa790ea9SDavid C Somayajulu break;
6012fa790ea9SDavid C Somayajulu
6013fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_CQ_OVERFLOW:
6014fa790ea9SDavid C Somayajulu qlnxr_iw_qp_event(context, params, IB_EVENT_QP_FATAL,
6015fa790ea9SDavid C Somayajulu "QED_IWARP_EVENT_CQ_OVERFLOW");
6016fa790ea9SDavid C Somayajulu break;
6017fa790ea9SDavid C Somayajulu
6018fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_QP_CATASTROPHIC:
6019fa790ea9SDavid C Somayajulu qlnxr_iw_qp_event(context, params, IB_EVENT_QP_FATAL,
6020fa790ea9SDavid C Somayajulu "QED_IWARP_EVENT_QP_CATASTROPHIC");
6021fa790ea9SDavid C Somayajulu break;
6022fa790ea9SDavid C Somayajulu
6023fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_LOCAL_ACCESS_ERROR:
6024fa790ea9SDavid C Somayajulu qlnxr_iw_qp_event(context, params, IB_EVENT_QP_ACCESS_ERR,
6025fa790ea9SDavid C Somayajulu "IWARP_EVENT_LOCAL_ACCESS_ERROR");
6026fa790ea9SDavid C Somayajulu break;
6027fa790ea9SDavid C Somayajulu
6028fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_REMOTE_OPERATION_ERROR:
6029fa790ea9SDavid C Somayajulu qlnxr_iw_qp_event(context, params, IB_EVENT_QP_FATAL,
6030fa790ea9SDavid C Somayajulu "IWARP_EVENT_REMOTE_OPERATION_ERROR");
6031fa790ea9SDavid C Somayajulu break;
6032fa790ea9SDavid C Somayajulu
6033fa790ea9SDavid C Somayajulu case ECORE_IWARP_EVENT_TERMINATE_RECEIVED:
6034fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "Got terminate message"
6035fa790ea9SDavid C Somayajulu " ECORE_IWARP_EVENT_TERMINATE_RECEIVED\n");
6036fa790ea9SDavid C Somayajulu break;
6037fa790ea9SDavid C Somayajulu
6038fa790ea9SDavid C Somayajulu default:
6039fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
6040fa790ea9SDavid C Somayajulu "Unknown event [0x%x] received \n", params->event);
6041fa790ea9SDavid C Somayajulu break;
6042fa790ea9SDavid C Somayajulu };
6043fa790ea9SDavid C Somayajulu
6044fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "[context, event] = [%p, 0x%x] "
6045fa790ea9SDavid C Somayajulu "exit\n", context, params->event);
6046fa790ea9SDavid C Somayajulu return 0;
6047fa790ea9SDavid C Somayajulu }
6048fa790ea9SDavid C Somayajulu
6049fa790ea9SDavid C Somayajulu static int
qlnxr_addr4_resolve(struct qlnxr_dev * dev,struct sockaddr_in * src_in,struct sockaddr_in * dst_in,u8 * dst_mac)6050fa790ea9SDavid C Somayajulu qlnxr_addr4_resolve(struct qlnxr_dev *dev,
6051fa790ea9SDavid C Somayajulu struct sockaddr_in *src_in,
6052fa790ea9SDavid C Somayajulu struct sockaddr_in *dst_in,
6053fa790ea9SDavid C Somayajulu u8 *dst_mac)
6054fa790ea9SDavid C Somayajulu {
6055fa790ea9SDavid C Somayajulu int rc;
6056fa790ea9SDavid C Somayajulu
6057fa790ea9SDavid C Somayajulu rc = arpresolve(dev->ha->ifp, 0, NULL, (struct sockaddr *)dst_in,
6058fa790ea9SDavid C Somayajulu dst_mac, NULL, NULL);
6059fa790ea9SDavid C Somayajulu
6060fa790ea9SDavid C Somayajulu QL_DPRINT12(dev->ha, "rc = %d "
6061fa790ea9SDavid C Somayajulu "sa_len = 0x%x sa_family = 0x%x IP Address = %d.%d.%d.%d "
6062fa790ea9SDavid C Somayajulu "Dest MAC %02x:%02x:%02x:%02x:%02x:%02x\n", rc,
6063fa790ea9SDavid C Somayajulu dst_in->sin_len, dst_in->sin_family,
6064fa790ea9SDavid C Somayajulu NIPQUAD((dst_in->sin_addr.s_addr)),
6065fa790ea9SDavid C Somayajulu dst_mac[0], dst_mac[1], dst_mac[2],
6066fa790ea9SDavid C Somayajulu dst_mac[3], dst_mac[4], dst_mac[5]);
6067fa790ea9SDavid C Somayajulu
6068fa790ea9SDavid C Somayajulu return rc;
6069fa790ea9SDavid C Somayajulu }
6070fa790ea9SDavid C Somayajulu
6071fa790ea9SDavid C Somayajulu int
qlnxr_iw_connect(struct iw_cm_id * cm_id,struct iw_cm_conn_param * conn_param)6072fa790ea9SDavid C Somayajulu qlnxr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
6073fa790ea9SDavid C Somayajulu {
6074fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
6075fa790ea9SDavid C Somayajulu struct ecore_iwarp_connect_out out_params;
6076fa790ea9SDavid C Somayajulu struct ecore_iwarp_connect_in in_params;
6077fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep;
6078fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp;
6079fa790ea9SDavid C Somayajulu struct sockaddr_in *laddr;
6080fa790ea9SDavid C Somayajulu struct sockaddr_in *raddr;
6081fa790ea9SDavid C Somayajulu int rc = 0;
6082fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
6083fa790ea9SDavid C Somayajulu
6084fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev((cm_id->device));
6085fa790ea9SDavid C Somayajulu ha = dev->ha;
6086fa790ea9SDavid C Somayajulu
6087fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "[cm_id, conn_param] = [%p, %p] "
6088fa790ea9SDavid C Somayajulu "enter \n", cm_id, conn_param);
6089fa790ea9SDavid C Somayajulu
6090*727bfe38SJustin Hibbits if (!(if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING))
6091fa790ea9SDavid C Somayajulu return -EINVAL;
6092fa790ea9SDavid C Somayajulu
6093fa790ea9SDavid C Somayajulu qp = idr_find(&dev->qpidr, conn_param->qpn);
6094fa790ea9SDavid C Somayajulu
6095fa790ea9SDavid C Somayajulu laddr = (struct sockaddr_in *)&cm_id->local_addr;
6096fa790ea9SDavid C Somayajulu raddr = (struct sockaddr_in *)&cm_id->remote_addr;
6097fa790ea9SDavid C Somayajulu
6098fa790ea9SDavid C Somayajulu QL_DPRINT12(ha,
6099fa790ea9SDavid C Somayajulu "local = [%d.%d.%d.%d, %d] remote = [%d.%d.%d.%d, %d]\n",
6100fa790ea9SDavid C Somayajulu NIPQUAD((laddr->sin_addr.s_addr)), laddr->sin_port,
6101fa790ea9SDavid C Somayajulu NIPQUAD((raddr->sin_addr.s_addr)), raddr->sin_port);
6102fa790ea9SDavid C Somayajulu
6103fa790ea9SDavid C Somayajulu ep = kzalloc(sizeof(*ep), GFP_KERNEL);
6104fa790ea9SDavid C Somayajulu if (!ep) {
6105fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "struct qlnxr_iw_ep "
6106fa790ea9SDavid C Somayajulu "alloc memory failed\n");
6107fa790ea9SDavid C Somayajulu return -ENOMEM;
6108fa790ea9SDavid C Somayajulu }
6109fa790ea9SDavid C Somayajulu
6110fa790ea9SDavid C Somayajulu ep->dev = dev;
6111fa790ea9SDavid C Somayajulu ep->qp = qp;
6112fa790ea9SDavid C Somayajulu cm_id->add_ref(cm_id);
6113fa790ea9SDavid C Somayajulu ep->cm_id = cm_id;
6114fa790ea9SDavid C Somayajulu
6115fa790ea9SDavid C Somayajulu memset(&in_params, 0, sizeof (struct ecore_iwarp_connect_in));
6116fa790ea9SDavid C Somayajulu memset(&out_params, 0, sizeof (struct ecore_iwarp_connect_out));
6117fa790ea9SDavid C Somayajulu
6118fa790ea9SDavid C Somayajulu in_params.event_cb = qlnxr_iw_event_handler;
6119fa790ea9SDavid C Somayajulu in_params.cb_context = ep;
6120fa790ea9SDavid C Somayajulu
6121fa790ea9SDavid C Somayajulu in_params.cm_info.ip_version = ECORE_TCP_IPV4;
6122fa790ea9SDavid C Somayajulu
6123fa790ea9SDavid C Somayajulu in_params.cm_info.remote_ip[0] = ntohl(raddr->sin_addr.s_addr);
6124fa790ea9SDavid C Somayajulu in_params.cm_info.local_ip[0] = ntohl(laddr->sin_addr.s_addr);
6125fa790ea9SDavid C Somayajulu in_params.cm_info.remote_port = ntohs(raddr->sin_port);
6126fa790ea9SDavid C Somayajulu in_params.cm_info.local_port = ntohs(laddr->sin_port);
6127fa790ea9SDavid C Somayajulu in_params.cm_info.vlan = 0;
6128*727bfe38SJustin Hibbits in_params.mss = if_getmtu(dev->ha->ifp) - 40;
6129fa790ea9SDavid C Somayajulu
6130fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "remote_ip = [%d.%d.%d.%d] "
6131fa790ea9SDavid C Somayajulu "local_ip = [%d.%d.%d.%d] remote_port = %d local_port = %d "
6132fa790ea9SDavid C Somayajulu "vlan = %d\n",
6133fa790ea9SDavid C Somayajulu NIPQUAD((in_params.cm_info.remote_ip[0])),
6134fa790ea9SDavid C Somayajulu NIPQUAD((in_params.cm_info.local_ip[0])),
6135fa790ea9SDavid C Somayajulu in_params.cm_info.remote_port, in_params.cm_info.local_port,
6136fa790ea9SDavid C Somayajulu in_params.cm_info.vlan);
6137fa790ea9SDavid C Somayajulu
6138fa790ea9SDavid C Somayajulu rc = qlnxr_addr4_resolve(dev, laddr, raddr, (u8 *)in_params.remote_mac_addr);
6139fa790ea9SDavid C Somayajulu
6140fa790ea9SDavid C Somayajulu if (rc) {
6141fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "qlnxr_addr4_resolve failed\n");
6142fa790ea9SDavid C Somayajulu goto err;
6143fa790ea9SDavid C Somayajulu }
6144fa790ea9SDavid C Somayajulu
6145fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ord = %d ird=%d private_data=%p"
6146fa790ea9SDavid C Somayajulu " private_data_len=%d rq_psn=%d\n",
6147fa790ea9SDavid C Somayajulu conn_param->ord, conn_param->ird, conn_param->private_data,
6148fa790ea9SDavid C Somayajulu conn_param->private_data_len, qp->rq_psn);
6149fa790ea9SDavid C Somayajulu
6150fa790ea9SDavid C Somayajulu in_params.cm_info.ord = conn_param->ord;
6151fa790ea9SDavid C Somayajulu in_params.cm_info.ird = conn_param->ird;
6152fa790ea9SDavid C Somayajulu in_params.cm_info.private_data = conn_param->private_data;
6153fa790ea9SDavid C Somayajulu in_params.cm_info.private_data_len = conn_param->private_data_len;
6154fa790ea9SDavid C Somayajulu in_params.qp = qp->ecore_qp;
6155fa790ea9SDavid C Somayajulu
6156fa790ea9SDavid C Somayajulu memcpy(in_params.local_mac_addr, dev->ha->primary_mac, ETH_ALEN);
6157fa790ea9SDavid C Somayajulu
6158fa790ea9SDavid C Somayajulu rc = ecore_iwarp_connect(dev->rdma_ctx, &in_params, &out_params);
6159fa790ea9SDavid C Somayajulu
6160fa790ea9SDavid C Somayajulu if (rc) {
6161fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "ecore_iwarp_connect failed\n");
6162fa790ea9SDavid C Somayajulu goto err;
6163fa790ea9SDavid C Somayajulu }
6164fa790ea9SDavid C Somayajulu
6165fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
6166fa790ea9SDavid C Somayajulu
6167fa790ea9SDavid C Somayajulu return rc;
6168fa790ea9SDavid C Somayajulu
6169fa790ea9SDavid C Somayajulu err:
6170fa790ea9SDavid C Somayajulu cm_id->rem_ref(cm_id);
6171fa790ea9SDavid C Somayajulu kfree(ep);
6172fa790ea9SDavid C Somayajulu
6173fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
6174fa790ea9SDavid C Somayajulu return rc;
6175fa790ea9SDavid C Somayajulu }
6176fa790ea9SDavid C Somayajulu
6177fa790ea9SDavid C Somayajulu int
qlnxr_iw_create_listen(struct iw_cm_id * cm_id,int backlog)6178fa790ea9SDavid C Somayajulu qlnxr_iw_create_listen(struct iw_cm_id *cm_id, int backlog)
6179fa790ea9SDavid C Somayajulu {
6180fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev;
6181fa790ea9SDavid C Somayajulu struct qlnxr_iw_listener *listener;
6182fa790ea9SDavid C Somayajulu struct ecore_iwarp_listen_in iparams;
6183fa790ea9SDavid C Somayajulu struct ecore_iwarp_listen_out oparams;
6184fa790ea9SDavid C Somayajulu struct sockaddr_in *laddr;
6185fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
6186fa790ea9SDavid C Somayajulu int rc;
6187fa790ea9SDavid C Somayajulu
6188fa790ea9SDavid C Somayajulu dev = get_qlnxr_dev((cm_id->device));
6189fa790ea9SDavid C Somayajulu ha = dev->ha;
6190fa790ea9SDavid C Somayajulu
6191fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
6192fa790ea9SDavid C Somayajulu
6193*727bfe38SJustin Hibbits if (!(if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING))
6194fa790ea9SDavid C Somayajulu return -EINVAL;
6195fa790ea9SDavid C Somayajulu
6196fa790ea9SDavid C Somayajulu laddr = (struct sockaddr_in *)&cm_id->local_addr;
6197fa790ea9SDavid C Somayajulu
6198fa790ea9SDavid C Somayajulu listener = kzalloc(sizeof(*listener), GFP_KERNEL);
6199fa790ea9SDavid C Somayajulu
6200fa790ea9SDavid C Somayajulu if (listener == NULL) {
6201fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "listener memory alloc failed\n");
6202fa790ea9SDavid C Somayajulu return -ENOMEM;
6203fa790ea9SDavid C Somayajulu }
6204fa790ea9SDavid C Somayajulu
6205fa790ea9SDavid C Somayajulu listener->dev = dev;
6206fa790ea9SDavid C Somayajulu cm_id->add_ref(cm_id);
6207fa790ea9SDavid C Somayajulu listener->cm_id = cm_id;
6208fa790ea9SDavid C Somayajulu listener->backlog = backlog;
6209fa790ea9SDavid C Somayajulu
6210fa790ea9SDavid C Somayajulu memset(&iparams, 0, sizeof (struct ecore_iwarp_listen_in));
6211fa790ea9SDavid C Somayajulu memset(&oparams, 0, sizeof (struct ecore_iwarp_listen_out));
6212fa790ea9SDavid C Somayajulu
6213fa790ea9SDavid C Somayajulu iparams.cb_context = listener;
6214fa790ea9SDavid C Somayajulu iparams.event_cb = qlnxr_iw_event_handler;
6215fa790ea9SDavid C Somayajulu iparams.max_backlog = backlog;
6216fa790ea9SDavid C Somayajulu
6217fa790ea9SDavid C Somayajulu iparams.ip_version = ECORE_TCP_IPV4;
6218fa790ea9SDavid C Somayajulu
6219fa790ea9SDavid C Somayajulu iparams.ip_addr[0] = ntohl(laddr->sin_addr.s_addr);
6220fa790ea9SDavid C Somayajulu iparams.port = ntohs(laddr->sin_port);
6221fa790ea9SDavid C Somayajulu iparams.vlan = 0;
6222fa790ea9SDavid C Somayajulu
6223fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "[%d.%d.%d.%d, %d] iparamsport=%d\n",
6224fa790ea9SDavid C Somayajulu NIPQUAD((laddr->sin_addr.s_addr)),
6225fa790ea9SDavid C Somayajulu laddr->sin_port, iparams.port);
6226fa790ea9SDavid C Somayajulu
6227fa790ea9SDavid C Somayajulu rc = ecore_iwarp_create_listen(dev->rdma_ctx, &iparams, &oparams);
6228fa790ea9SDavid C Somayajulu if (rc) {
6229fa790ea9SDavid C Somayajulu QL_DPRINT11(ha,
6230fa790ea9SDavid C Somayajulu "ecore_iwarp_create_listen failed rc = %d\n", rc);
6231fa790ea9SDavid C Somayajulu goto err;
6232fa790ea9SDavid C Somayajulu }
6233fa790ea9SDavid C Somayajulu
6234fa790ea9SDavid C Somayajulu listener->ecore_handle = oparams.handle;
6235fa790ea9SDavid C Somayajulu cm_id->provider_data = listener;
6236fa790ea9SDavid C Somayajulu
6237fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
6238fa790ea9SDavid C Somayajulu return rc;
6239fa790ea9SDavid C Somayajulu
6240fa790ea9SDavid C Somayajulu err:
6241fa790ea9SDavid C Somayajulu cm_id->rem_ref(cm_id);
6242fa790ea9SDavid C Somayajulu kfree(listener);
6243fa790ea9SDavid C Somayajulu
6244fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
6245fa790ea9SDavid C Somayajulu return rc;
6246fa790ea9SDavid C Somayajulu }
6247fa790ea9SDavid C Somayajulu
6248fa790ea9SDavid C Somayajulu void
qlnxr_iw_destroy_listen(struct iw_cm_id * cm_id)6249fa790ea9SDavid C Somayajulu qlnxr_iw_destroy_listen(struct iw_cm_id *cm_id)
6250fa790ea9SDavid C Somayajulu {
6251fa790ea9SDavid C Somayajulu struct qlnxr_iw_listener *listener = cm_id->provider_data;
6252fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev((cm_id->device));
6253fa790ea9SDavid C Somayajulu int rc = 0;
6254fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
6255fa790ea9SDavid C Somayajulu
6256fa790ea9SDavid C Somayajulu ha = dev->ha;
6257fa790ea9SDavid C Somayajulu
6258fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter\n");
6259fa790ea9SDavid C Somayajulu
6260fa790ea9SDavid C Somayajulu if (listener->ecore_handle)
6261fa790ea9SDavid C Somayajulu rc = ecore_iwarp_destroy_listen(dev->rdma_ctx,
6262fa790ea9SDavid C Somayajulu listener->ecore_handle);
6263fa790ea9SDavid C Somayajulu
6264fa790ea9SDavid C Somayajulu cm_id->rem_ref(cm_id);
6265fa790ea9SDavid C Somayajulu
6266fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit [%d]\n", rc);
6267fa790ea9SDavid C Somayajulu return;
6268fa790ea9SDavid C Somayajulu }
6269fa790ea9SDavid C Somayajulu
6270fa790ea9SDavid C Somayajulu int
qlnxr_iw_accept(struct iw_cm_id * cm_id,struct iw_cm_conn_param * conn_param)6271fa790ea9SDavid C Somayajulu qlnxr_iw_accept(struct iw_cm_id *cm_id,
6272fa790ea9SDavid C Somayajulu struct iw_cm_conn_param *conn_param)
6273fa790ea9SDavid C Somayajulu {
6274fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)cm_id->provider_data;
6275fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
6276fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp;
6277fa790ea9SDavid C Somayajulu struct ecore_iwarp_accept_in params;
6278fa790ea9SDavid C Somayajulu int rc;
6279fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
6280fa790ea9SDavid C Somayajulu
6281fa790ea9SDavid C Somayajulu ha = dev->ha;
6282fa790ea9SDavid C Somayajulu
6283fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter qpid=%d\n", conn_param->qpn);
6284fa790ea9SDavid C Somayajulu
6285*727bfe38SJustin Hibbits if (!(if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING))
6286fa790ea9SDavid C Somayajulu return -EINVAL;
6287fa790ea9SDavid C Somayajulu
6288fa790ea9SDavid C Somayajulu qp = idr_find(&dev->qpidr, conn_param->qpn);
6289fa790ea9SDavid C Somayajulu if (!qp) {
6290fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "idr_find failed invalid qpn = %d\n",
6291fa790ea9SDavid C Somayajulu conn_param->qpn);
6292fa790ea9SDavid C Somayajulu return -EINVAL;
6293fa790ea9SDavid C Somayajulu }
6294fa790ea9SDavid C Somayajulu ep->qp = qp;
6295fa790ea9SDavid C Somayajulu qp->ep = ep;
6296fa790ea9SDavid C Somayajulu cm_id->add_ref(cm_id);
6297fa790ea9SDavid C Somayajulu ep->cm_id = cm_id;
6298fa790ea9SDavid C Somayajulu
6299fa790ea9SDavid C Somayajulu params.ep_context = ep->ecore_context;
6300fa790ea9SDavid C Somayajulu params.cb_context = ep;
6301fa790ea9SDavid C Somayajulu params.qp = ep->qp->ecore_qp;
6302fa790ea9SDavid C Somayajulu params.private_data = conn_param->private_data;
6303fa790ea9SDavid C Somayajulu params.private_data_len = conn_param->private_data_len;
6304fa790ea9SDavid C Somayajulu params.ird = conn_param->ird;
6305fa790ea9SDavid C Somayajulu params.ord = conn_param->ord;
6306fa790ea9SDavid C Somayajulu
6307fa790ea9SDavid C Somayajulu rc = ecore_iwarp_accept(dev->rdma_ctx, ¶ms);
6308fa790ea9SDavid C Somayajulu if (rc) {
6309fa790ea9SDavid C Somayajulu QL_DPRINT11(ha, "ecore_iwarp_accept failed %d\n", rc);
6310fa790ea9SDavid C Somayajulu goto err;
6311fa790ea9SDavid C Somayajulu }
6312fa790ea9SDavid C Somayajulu
6313fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit\n");
6314fa790ea9SDavid C Somayajulu return 0;
6315fa790ea9SDavid C Somayajulu err:
6316fa790ea9SDavid C Somayajulu cm_id->rem_ref(cm_id);
6317fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit rc = %d\n", rc);
6318fa790ea9SDavid C Somayajulu return rc;
6319fa790ea9SDavid C Somayajulu }
6320fa790ea9SDavid C Somayajulu
6321fa790ea9SDavid C Somayajulu int
qlnxr_iw_reject(struct iw_cm_id * cm_id,const void * pdata,u8 pdata_len)6322fa790ea9SDavid C Somayajulu qlnxr_iw_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
6323fa790ea9SDavid C Somayajulu {
6324fa790ea9SDavid C Somayajulu struct qlnxr_iw_ep *ep = (struct qlnxr_iw_ep *)cm_id->provider_data;
6325fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = ep->dev;
6326fa790ea9SDavid C Somayajulu struct ecore_iwarp_reject_in params;
6327fa790ea9SDavid C Somayajulu int rc;
6328fa790ea9SDavid C Somayajulu
6329fa790ea9SDavid C Somayajulu params.ep_context = ep->ecore_context;
6330fa790ea9SDavid C Somayajulu params.cb_context = ep;
6331fa790ea9SDavid C Somayajulu params.private_data = pdata;
6332fa790ea9SDavid C Somayajulu params.private_data_len = pdata_len;
6333fa790ea9SDavid C Somayajulu ep->qp = NULL;
6334fa790ea9SDavid C Somayajulu
6335fa790ea9SDavid C Somayajulu rc = ecore_iwarp_reject(dev->rdma_ctx, ¶ms);
6336fa790ea9SDavid C Somayajulu
6337fa790ea9SDavid C Somayajulu return rc;
6338fa790ea9SDavid C Somayajulu }
6339fa790ea9SDavid C Somayajulu
6340fa790ea9SDavid C Somayajulu void
qlnxr_iw_qp_add_ref(struct ib_qp * ibqp)6341fa790ea9SDavid C Somayajulu qlnxr_iw_qp_add_ref(struct ib_qp *ibqp)
6342fa790ea9SDavid C Somayajulu {
6343fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp = get_qlnxr_qp(ibqp);
6344fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
6345fa790ea9SDavid C Somayajulu
6346fa790ea9SDavid C Somayajulu ha = qp->dev->ha;
6347fa790ea9SDavid C Somayajulu
6348fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter ibqp = %p\n", ibqp);
6349fa790ea9SDavid C Somayajulu
6350fa790ea9SDavid C Somayajulu atomic_inc(&qp->refcnt);
6351fa790ea9SDavid C Somayajulu
6352fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit \n");
6353fa790ea9SDavid C Somayajulu return;
6354fa790ea9SDavid C Somayajulu }
6355fa790ea9SDavid C Somayajulu
6356fa790ea9SDavid C Somayajulu void
qlnxr_iw_qp_rem_ref(struct ib_qp * ibqp)6357fa790ea9SDavid C Somayajulu qlnxr_iw_qp_rem_ref(struct ib_qp *ibqp)
6358fa790ea9SDavid C Somayajulu {
6359fa790ea9SDavid C Somayajulu struct qlnxr_qp *qp = get_qlnxr_qp(ibqp);
6360fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
6361fa790ea9SDavid C Somayajulu
6362fa790ea9SDavid C Somayajulu ha = qp->dev->ha;
6363fa790ea9SDavid C Somayajulu
6364fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter ibqp = %p qp = %p\n", ibqp, qp);
6365fa790ea9SDavid C Somayajulu
6366fa790ea9SDavid C Somayajulu if (atomic_dec_and_test(&qp->refcnt)) {
6367fa790ea9SDavid C Somayajulu qlnxr_idr_remove(qp->dev, qp->qp_id);
6368fa790ea9SDavid C Somayajulu }
6369fa790ea9SDavid C Somayajulu
6370fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit \n");
6371fa790ea9SDavid C Somayajulu return;
6372fa790ea9SDavid C Somayajulu }
6373fa790ea9SDavid C Somayajulu
6374fa790ea9SDavid C Somayajulu struct ib_qp *
qlnxr_iw_get_qp(struct ib_device * ibdev,int qpn)6375fa790ea9SDavid C Somayajulu qlnxr_iw_get_qp(struct ib_device *ibdev, int qpn)
6376fa790ea9SDavid C Somayajulu {
6377fa790ea9SDavid C Somayajulu struct qlnxr_dev *dev = get_qlnxr_dev(ibdev);
6378fa790ea9SDavid C Somayajulu struct ib_qp *qp;
6379fa790ea9SDavid C Somayajulu qlnx_host_t *ha;
6380fa790ea9SDavid C Somayajulu
6381fa790ea9SDavid C Somayajulu ha = dev->ha;
6382fa790ea9SDavid C Somayajulu
6383fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "enter dev = %p ibdev = %p qpn = %d\n", dev, ibdev, qpn);
6384fa790ea9SDavid C Somayajulu
6385fa790ea9SDavid C Somayajulu qp = idr_find(&dev->qpidr, qpn);
6386fa790ea9SDavid C Somayajulu
6387fa790ea9SDavid C Somayajulu QL_DPRINT12(ha, "exit qp = %p\n", qp);
6388fa790ea9SDavid C Somayajulu
6389fa790ea9SDavid C Somayajulu return (qp);
6390fa790ea9SDavid C Somayajulu }
6391