blob: 0099e419e24f02e350d58a91a4e166423357d718 [file] [log] [blame]
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001/*
Tatyana Nikolovac5488c52011-11-28 14:22:29 -06002 * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 *
32 */
33
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/random.h>
37#include <linux/highmem.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090038#include <linux/slab.h>
Glenn Streiff3c2d7742008-02-04 20:20:45 -080039#include <asm/byteorder.h>
40
41#include <rdma/ib_verbs.h>
42#include <rdma/iw_cm.h>
43#include <rdma/ib_user_verbs.h>
44
45#include "nes.h"
46
47#include <rdma/ib_umem.h>
48
49atomic_t mod_qp_timouts;
50atomic_t qps_created;
51atomic_t sw_qps_destroyed;
52
Roland Dreier1a855fb2008-04-16 21:01:09 -070053static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -080054
55/**
56 * nes_alloc_mw
57 */
Shani Michaeli7083e422013-02-06 16:19:12 +000058static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd, enum ib_mw_type type)
59{
Glenn Streiff3c2d7742008-02-04 20:20:45 -080060 struct nes_pd *nespd = to_nespd(ibpd);
61 struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
62 struct nes_device *nesdev = nesvnic->nesdev;
63 struct nes_adapter *nesadapter = nesdev->nesadapter;
64 struct nes_cqp_request *cqp_request;
65 struct nes_mr *nesmr;
66 struct ib_mw *ibmw;
67 struct nes_hw_cqp_wqe *cqp_wqe;
68 int ret;
69 u32 stag;
70 u32 stag_index = 0;
71 u32 next_stag_index = 0;
72 u32 driver_key = 0;
73 u8 stag_key = 0;
74
Shani Michaeli7083e422013-02-06 16:19:12 +000075 if (type != IB_MW_TYPE_1)
76 return ERR_PTR(-EINVAL);
77
Glenn Streiff3c2d7742008-02-04 20:20:45 -080078 get_random_bytes(&next_stag_index, sizeof(next_stag_index));
79 stag_key = (u8)next_stag_index;
80
81 driver_key = 0;
82
83 next_stag_index >>= 8;
84 next_stag_index %= nesadapter->max_mr;
85
86 ret = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
Tatyana Nikolova81821642012-09-20 21:08:04 +000087 nesadapter->max_mr, &stag_index, &next_stag_index, NES_RESOURCE_MW);
Glenn Streiff3c2d7742008-02-04 20:20:45 -080088 if (ret) {
89 return ERR_PTR(ret);
90 }
91
92 nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
93 if (!nesmr) {
94 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
95 return ERR_PTR(-ENOMEM);
96 }
97
98 stag = stag_index << 8;
99 stag |= driver_key;
100 stag += (u32)stag_key;
101
102 nes_debug(NES_DBG_MR, "Registering STag 0x%08X, index = 0x%08X\n",
103 stag, stag_index);
104
105 /* Register the region with the adapter */
106 cqp_request = nes_get_cqp_request(nesdev);
107 if (cqp_request == NULL) {
108 kfree(nesmr);
109 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
110 return ERR_PTR(-ENOMEM);
111 }
112
113 cqp_request->waiting = 1;
114 cqp_wqe = &cqp_request->cqp_wqe;
115
116 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] =
117 cpu_to_le32( NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_RIGHTS_REMOTE_READ |
118 NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_VA_TO |
119 NES_CQP_STAG_REM_ACC_EN);
120
121 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
122 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX, (nespd->pd_id & 0x00007fff));
123 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);
124
125 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -0700126 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800127
128 /* Wait for CQP */
129 ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
130 NES_EVENT_TIMEOUT);
131 nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u,"
132 " CQP Major:Minor codes = 0x%04X:0x%04X.\n",
133 stag, ret, cqp_request->major_code, cqp_request->minor_code);
134 if ((!ret) || (cqp_request->major_code)) {
Roland Dreier1ff66e82008-07-14 23:48:49 -0700135 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800136 kfree(nesmr);
137 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
138 if (!ret) {
139 return ERR_PTR(-ETIME);
140 } else {
141 return ERR_PTR(-ENOMEM);
142 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800143 }
Roland Dreier1ff66e82008-07-14 23:48:49 -0700144 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800145
146 nesmr->ibmw.rkey = stag;
147 nesmr->mode = IWNES_MEMREG_TYPE_MW;
148 ibmw = &nesmr->ibmw;
149 nesmr->pbl_4k = 0;
150 nesmr->pbls_used = 0;
151
152 return ibmw;
153}
154
155
156/**
157 * nes_dealloc_mw
158 */
159static int nes_dealloc_mw(struct ib_mw *ibmw)
160{
161 struct nes_mr *nesmr = to_nesmw(ibmw);
162 struct nes_vnic *nesvnic = to_nesvnic(ibmw->device);
163 struct nes_device *nesdev = nesvnic->nesdev;
164 struct nes_adapter *nesadapter = nesdev->nesadapter;
165 struct nes_hw_cqp_wqe *cqp_wqe;
166 struct nes_cqp_request *cqp_request;
167 int err = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800168 int ret;
169
170 /* Deallocate the window with the adapter */
171 cqp_request = nes_get_cqp_request(nesdev);
172 if (cqp_request == NULL) {
173 nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");
174 return -ENOMEM;
175 }
176 cqp_request->waiting = 1;
177 cqp_wqe = &cqp_request->cqp_wqe;
178 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
179 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, NES_CQP_DEALLOCATE_STAG);
180 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ibmw->rkey);
181
182 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -0700183 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800184
185 /* Wait for CQP */
186 nes_debug(NES_DBG_MR, "Waiting for deallocate STag 0x%08X to complete.\n",
187 ibmw->rkey);
188 ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),
189 NES_EVENT_TIMEOUT);
190 nes_debug(NES_DBG_MR, "Deallocate STag completed, wait_event_timeout ret = %u,"
191 " CQP Major:Minor codes = 0x%04X:0x%04X.\n",
192 ret, cqp_request->major_code, cqp_request->minor_code);
Roland Dreier1ff66e82008-07-14 23:48:49 -0700193 if (!ret)
194 err = -ETIME;
195 else if (cqp_request->major_code)
196 err = -EIO;
197
198 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800199
200 nes_free_resource(nesadapter, nesadapter->allocated_mrs,
201 (ibmw->rkey & 0x0fffff00) >> 8);
202 kfree(nesmr);
203
204 return err;
205}
206
207
208/**
209 * nes_bind_mw
210 */
211static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw,
212 struct ib_mw_bind *ibmw_bind)
213{
214 u64 u64temp;
215 struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
216 struct nes_device *nesdev = nesvnic->nesdev;
217 /* struct nes_mr *nesmr = to_nesmw(ibmw); */
218 struct nes_qp *nesqp = to_nesqp(ibqp);
219 struct nes_hw_qp_wqe *wqe;
220 unsigned long flags = 0;
221 u32 head;
222 u32 wqe_misc = 0;
223 u32 qsize;
224
225 if (nesqp->ibqp_state > IB_QPS_RTS)
226 return -EINVAL;
227
Ilpo Järvinen5880ff12008-10-30 13:39:43 +0200228 spin_lock_irqsave(&nesqp->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800229
230 head = nesqp->hwqp.sq_head;
231 qsize = nesqp->hwqp.sq_tail;
232
233 /* Check for SQ overflow */
234 if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {
Ilpo Järvinen5880ff12008-10-30 13:39:43 +0200235 spin_unlock_irqrestore(&nesqp->lock, flags);
Or Gerlitz831d06c2010-02-04 11:25:07 +0000236 return -ENOMEM;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800237 }
238
239 wqe = &nesqp->hwqp.sq_vbase[head];
240 /* nes_debug(NES_DBG_MR, "processing sq wqe at %p, head = %u.\n", wqe, head); */
241 nes_fill_init_qp_wqe(wqe, nesqp, head);
242 u64temp = ibmw_bind->wr_id;
243 set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX, u64temp);
244 wqe_misc = NES_IWARP_SQ_OP_BIND;
245
246 wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
247
248 if (ibmw_bind->send_flags & IB_SEND_SIGNALED)
249 wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL;
250
Shani Michaeli7083e422013-02-06 16:19:12 +0000251 if (ibmw_bind->bind_info.mw_access_flags & IB_ACCESS_REMOTE_WRITE)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800252 wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE;
Shani Michaeli7083e422013-02-06 16:19:12 +0000253 if (ibmw_bind->bind_info.mw_access_flags & IB_ACCESS_REMOTE_READ)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800254 wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_READ;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800255
256 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_MISC_IDX, wqe_misc);
Shani Michaeli7083e422013-02-06 16:19:12 +0000257 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MR_IDX,
258 ibmw_bind->bind_info.mr->lkey);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800259 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MW_IDX, ibmw->rkey);
260 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_LENGTH_LOW_IDX,
Shani Michaeli7083e422013-02-06 16:19:12 +0000261 ibmw_bind->bind_info.length);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800262 wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_LENGTH_HIGH_IDX] = 0;
Shani Michaeli7083e422013-02-06 16:19:12 +0000263 u64temp = (u64)ibmw_bind->bind_info.addr;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800264 set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_VA_FBO_LOW_IDX, u64temp);
265
266 head++;
267 if (head >= qsize)
268 head = 0;
269
270 nesqp->hwqp.sq_head = head;
271 barrier();
272
273 nes_write32(nesdev->regs+NES_WQE_ALLOC,
274 (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
275
Ilpo Järvinen5880ff12008-10-30 13:39:43 +0200276 spin_unlock_irqrestore(&nesqp->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800277
278 return 0;
279}
280
281
Chien Tunge293a262009-12-09 15:21:54 -0800282/*
283 * nes_alloc_fast_mr
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800284 */
Chien Tunge293a262009-12-09 15:21:54 -0800285static int alloc_fast_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,
286 u32 stag, u32 page_count)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800287{
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800288 struct nes_hw_cqp_wqe *cqp_wqe;
Chien Tunge293a262009-12-09 15:21:54 -0800289 struct nes_cqp_request *cqp_request;
290 unsigned long flags;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800291 int ret;
Chien Tunge293a262009-12-09 15:21:54 -0800292 struct nes_adapter *nesadapter = nesdev->nesadapter;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800293 u32 opcode = 0;
Chien Tunge293a262009-12-09 15:21:54 -0800294 u16 major_code;
295 u64 region_length = page_count * PAGE_SIZE;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800296
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800297
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800298 cqp_request = nes_get_cqp_request(nesdev);
299 if (cqp_request == NULL) {
300 nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");
Chien Tunge293a262009-12-09 15:21:54 -0800301 return -ENOMEM;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800302 }
Chien Tunge293a262009-12-09 15:21:54 -0800303 nes_debug(NES_DBG_MR, "alloc_fast_reg_mr: page_count = %d, "
304 "region_length = %llu\n",
305 page_count, region_length);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800306 cqp_request->waiting = 1;
307 cqp_wqe = &cqp_request->cqp_wqe;
308
Chien Tunge293a262009-12-09 15:21:54 -0800309 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
310 if (nesadapter->free_4kpbl > 0) {
311 nesadapter->free_4kpbl--;
312 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
313 } else {
314 /* No 4kpbl's available: */
315 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
316 nes_debug(NES_DBG_MR, "Out of Pbls\n");
317 nes_free_cqp_request(nesdev, cqp_request);
318 return -ENOMEM;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800319 }
320
Chien Tunge293a262009-12-09 15:21:54 -0800321 opcode = NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_MR |
322 NES_CQP_STAG_PBL_BLK_SIZE | NES_CQP_STAG_VA_TO |
323 NES_CQP_STAG_REM_ACC_EN;
324 /*
325 * The current OFED API does not support the zero based TO option.
326 * If added then need to changed the NES_CQP_STAG_VA* option. Also,
327 * the API does not support that ability to have the MR set for local
328 * access only when created and not allow the SQ op to override. Given
329 * this the remote enable must be set here.
330 */
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800331
332 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
333 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
Chien Tunge293a262009-12-09 15:21:54 -0800334 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX, 1);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800335
Chien Tunge293a262009-12-09 15:21:54 -0800336 cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] =
337 cpu_to_le32((u32)(region_length >> 8) & 0xff000000);
338 cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] |=
339 cpu_to_le32(nespd->pd_id & 0x00007fff);
340
341 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);
342 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_VA_LOW_IDX, 0);
343 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_LOW_IDX, 0);
344 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, 0);
345 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_LEN_IDX, (page_count * 8));
346 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_STAG_PBL_BLK_SIZE);
347 barrier();
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800348
349 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -0700350 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800351
352 /* Wait for CQP */
Chien Tunge293a262009-12-09 15:21:54 -0800353 ret = wait_event_timeout(cqp_request->waitq,
354 (0 != cqp_request->request_done),
355 NES_EVENT_TIMEOUT);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800356
Chien Tunge293a262009-12-09 15:21:54 -0800357 nes_debug(NES_DBG_MR, "Allocate STag 0x%08X completed, "
358 "wait_event_timeout ret = %u, CQP Major:Minor codes = "
359 "0x%04X:0x%04X.\n", stag, ret, cqp_request->major_code,
360 cqp_request->minor_code);
361 major_code = cqp_request->major_code;
Roland Dreier1ff66e82008-07-14 23:48:49 -0700362 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800363
Chien Tunge293a262009-12-09 15:21:54 -0800364 if (!ret || major_code) {
Chien Tung35c6d692008-11-02 21:37:35 -0800365 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
Chien Tunge293a262009-12-09 15:21:54 -0800366 nesadapter->free_4kpbl++;
Chien Tung35c6d692008-11-02 21:37:35 -0800367 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
368 }
369
Chien Tunge293a262009-12-09 15:21:54 -0800370 if (!ret)
371 return -ETIME;
372 else if (major_code)
373 return -EIO;
374 return 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800375}
376
Chien Tunge293a262009-12-09 15:21:54 -0800377/*
378 * nes_alloc_fast_reg_mr
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800379 */
Roland Dreier53978b42010-04-21 15:58:28 -0700380static struct ib_mr *nes_alloc_fast_reg_mr(struct ib_pd *ibpd, int max_page_list_len)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800381{
Chien Tunge293a262009-12-09 15:21:54 -0800382 struct nes_pd *nespd = to_nespd(ibpd);
383 struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800384 struct nes_device *nesdev = nesvnic->nesdev;
Chien Tung35c6d692008-11-02 21:37:35 -0800385 struct nes_adapter *nesadapter = nesdev->nesadapter;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800386
Chien Tunge293a262009-12-09 15:21:54 -0800387 u32 next_stag_index;
388 u8 stag_key = 0;
389 u32 driver_key = 0;
390 int err = 0;
391 u32 stag_index = 0;
392 struct nes_mr *nesmr;
393 u32 stag;
394 int ret;
395 struct ib_mr *ibmr;
396/*
397 * Note: Set to always use a fixed length single page entry PBL. This is to allow
398 * for the fast_reg_mr operation to always know the size of the PBL.
399 */
400 if (max_page_list_len > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64)))
401 return ERR_PTR(-E2BIG);
402
403 get_random_bytes(&next_stag_index, sizeof(next_stag_index));
404 stag_key = (u8)next_stag_index;
405 next_stag_index >>= 8;
406 next_stag_index %= nesadapter->max_mr;
407
408 err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
409 nesadapter->max_mr, &stag_index,
Tatyana Nikolova81821642012-09-20 21:08:04 +0000410 &next_stag_index, NES_RESOURCE_FAST_MR);
Chien Tunge293a262009-12-09 15:21:54 -0800411 if (err)
412 return ERR_PTR(err);
413
414 nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
415 if (!nesmr) {
416 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
417 return ERR_PTR(-ENOMEM);
418 }
419
420 stag = stag_index << 8;
421 stag |= driver_key;
422 stag += (u32)stag_key;
423
424 nes_debug(NES_DBG_MR, "Allocating STag 0x%08X index = 0x%08X\n",
425 stag, stag_index);
426
427 ret = alloc_fast_reg_mr(nesdev, nespd, stag, max_page_list_len);
428
429 if (ret == 0) {
430 nesmr->ibmr.rkey = stag;
431 nesmr->ibmr.lkey = stag;
432 nesmr->mode = IWNES_MEMREG_TYPE_FMEM;
433 ibmr = &nesmr->ibmr;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800434 } else {
Chien Tunge293a262009-12-09 15:21:54 -0800435 kfree(nesmr);
436 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
437 ibmr = ERR_PTR(-ENOMEM);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800438 }
Chien Tunge293a262009-12-09 15:21:54 -0800439 return ibmr;
440}
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800441
Chien Tunge293a262009-12-09 15:21:54 -0800442/*
443 * nes_alloc_fast_reg_page_list
444 */
445static struct ib_fast_reg_page_list *nes_alloc_fast_reg_page_list(
446 struct ib_device *ibdev,
447 int page_list_len)
448{
449 struct nes_vnic *nesvnic = to_nesvnic(ibdev);
450 struct nes_device *nesdev = nesvnic->nesdev;
451 struct ib_fast_reg_page_list *pifrpl;
452 struct nes_ib_fast_reg_page_list *pnesfrpl;
Don Wooddae5d132009-03-06 15:12:09 -0800453
Chien Tunge293a262009-12-09 15:21:54 -0800454 if (page_list_len > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64)))
455 return ERR_PTR(-E2BIG);
456 /*
457 * Allocate the ib_fast_reg_page_list structure, the
458 * nes_fast_bpl structure, and the PLB table.
459 */
460 pnesfrpl = kmalloc(sizeof(struct nes_ib_fast_reg_page_list) +
461 page_list_len * sizeof(u64), GFP_KERNEL);
462
463 if (!pnesfrpl)
464 return ERR_PTR(-ENOMEM);
465
466 pifrpl = &pnesfrpl->ibfrpl;
467 pifrpl->page_list = &pnesfrpl->pbl;
468 pifrpl->max_page_list_len = page_list_len;
469 /*
470 * Allocate the WQE PBL
471 */
472 pnesfrpl->nes_wqe_pbl.kva = pci_alloc_consistent(nesdev->pcidev,
473 page_list_len * sizeof(u64),
474 &pnesfrpl->nes_wqe_pbl.paddr);
475
476 if (!pnesfrpl->nes_wqe_pbl.kva) {
477 kfree(pnesfrpl);
478 return ERR_PTR(-ENOMEM);
Chien Tung35c6d692008-11-02 21:37:35 -0800479 }
Chien Tunge293a262009-12-09 15:21:54 -0800480 nes_debug(NES_DBG_MR, "nes_alloc_fast_reg_pbl: nes_frpl = %p, "
481 "ibfrpl = %p, ibfrpl.page_list = %p, pbl.kva = %p, "
Roland Dreier183ae742010-09-27 17:51:33 -0700482 "pbl.paddr = %llx\n", pnesfrpl, &pnesfrpl->ibfrpl,
Chien Tunge293a262009-12-09 15:21:54 -0800483 pnesfrpl->ibfrpl.page_list, pnesfrpl->nes_wqe_pbl.kva,
Roland Dreier183ae742010-09-27 17:51:33 -0700484 (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr);
Chien Tung35c6d692008-11-02 21:37:35 -0800485
Chien Tunge293a262009-12-09 15:21:54 -0800486 return pifrpl;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800487}
488
Chien Tunge293a262009-12-09 15:21:54 -0800489/*
490 * nes_free_fast_reg_page_list
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800491 */
Chien Tunge293a262009-12-09 15:21:54 -0800492static void nes_free_fast_reg_page_list(struct ib_fast_reg_page_list *pifrpl)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800493{
Chien Tunge293a262009-12-09 15:21:54 -0800494 struct nes_vnic *nesvnic = to_nesvnic(pifrpl->device);
495 struct nes_device *nesdev = nesvnic->nesdev;
496 struct nes_ib_fast_reg_page_list *pnesfrpl;
497
498 pnesfrpl = container_of(pifrpl, struct nes_ib_fast_reg_page_list, ibfrpl);
499 /*
500 * Free the WQE PBL.
501 */
502 pci_free_consistent(nesdev->pcidev,
503 pifrpl->max_page_list_len * sizeof(u64),
504 pnesfrpl->nes_wqe_pbl.kva,
505 pnesfrpl->nes_wqe_pbl.paddr);
506 /*
507 * Free the PBL structure
508 */
509 kfree(pnesfrpl);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800510}
511
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800512/**
513 * nes_query_device
514 */
515static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
516{
517 struct nes_vnic *nesvnic = to_nesvnic(ibdev);
518 struct nes_device *nesdev = nesvnic->nesdev;
519 struct nes_ib_device *nesibdev = nesvnic->nesibdev;
520
521 memset(props, 0, sizeof(*props));
522 memcpy(&props->sys_image_guid, nesvnic->netdev->dev_addr, 6);
523
Miroslaw Walukiewiczff0380c2010-07-15 14:53:29 +0000524 props->fw_ver = nesdev->nesadapter->firmware_version;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800525 props->device_cap_flags = nesdev->nesadapter->device_cap_flags;
526 props->vendor_id = nesdev->nesadapter->vendor_id;
527 props->vendor_part_id = nesdev->nesadapter->vendor_part_id;
528 props->hw_ver = nesdev->nesadapter->hw_rev;
529 props->max_mr_size = 0x80000000;
530 props->max_qp = nesibdev->max_qp;
531 props->max_qp_wr = nesdev->nesadapter->max_qp_wr - 2;
532 props->max_sge = nesdev->nesadapter->max_sge;
533 props->max_cq = nesibdev->max_cq;
Chien Tung5924aea2009-12-09 15:21:56 -0800534 props->max_cqe = nesdev->nesadapter->max_cqe;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800535 props->max_mr = nesibdev->max_mr;
536 props->max_mw = nesibdev->max_mr;
537 props->max_pd = nesibdev->max_pd;
538 props->max_sge_rd = 1;
539 switch (nesdev->nesadapter->max_irrq_wr) {
540 case 0:
Faisal Latif8ac7f6e2009-12-09 15:53:46 -0800541 props->max_qp_rd_atom = 2;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800542 break;
543 case 1:
Faisal Latif8ac7f6e2009-12-09 15:53:46 -0800544 props->max_qp_rd_atom = 8;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800545 break;
546 case 2:
Faisal Latif8ac7f6e2009-12-09 15:53:46 -0800547 props->max_qp_rd_atom = 32;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800548 break;
549 case 3:
Faisal Latif8ac7f6e2009-12-09 15:53:46 -0800550 props->max_qp_rd_atom = 64;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800551 break;
552 default:
553 props->max_qp_rd_atom = 0;
554 }
Faisal Latif66388d62009-06-22 22:52:30 -0700555 props->max_qp_init_rd_atom = props->max_qp_rd_atom;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800556 props->atomic_cap = IB_ATOMIC_NONE;
557 props->max_map_per_fmr = 1;
558
559 return 0;
560}
561
562
563/**
564 * nes_query_port
565 */
566static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *props)
567{
Chien Tungcd1d3f72009-09-05 20:36:39 -0700568 struct nes_vnic *nesvnic = to_nesvnic(ibdev);
569 struct net_device *netdev = nesvnic->netdev;
570
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800571 memset(props, 0, sizeof(*props));
572
Chien Tungcd1d3f72009-09-05 20:36:39 -0700573 props->max_mtu = IB_MTU_4096;
574
575 if (netdev->mtu >= 4096)
576 props->active_mtu = IB_MTU_4096;
577 else if (netdev->mtu >= 2048)
578 props->active_mtu = IB_MTU_2048;
579 else if (netdev->mtu >= 1024)
580 props->active_mtu = IB_MTU_1024;
581 else if (netdev->mtu >= 512)
582 props->active_mtu = IB_MTU_512;
583 else
584 props->active_mtu = IB_MTU_256;
585
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800586 props->lid = 1;
587 props->lmc = 0;
588 props->sm_lid = 0;
589 props->sm_sl = 0;
Chien Tung29327722010-08-23 14:32:36 +0000590 if (netif_queue_stopped(netdev))
591 props->state = IB_PORT_DOWN;
592 else if (nesvnic->linkup)
Chien Tungcd1d3f72009-09-05 20:36:39 -0700593 props->state = IB_PORT_ACTIVE;
594 else
595 props->state = IB_PORT_DOWN;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800596 props->phys_state = 0;
597 props->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP |
598 IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP;
599 props->gid_tbl_len = 1;
600 props->pkey_tbl_len = 1;
601 props->qkey_viol_cntr = 0;
602 props->active_width = IB_WIDTH_4X;
Or Gerlitz2e966912012-02-28 18:49:50 +0200603 props->active_speed = IB_SPEED_SDR;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800604 props->max_msg_sz = 0x80000000;
605
606 return 0;
607}
608
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800609/**
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800610 * nes_query_pkey
611 */
612static int nes_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
613{
614 *pkey = 0;
615 return 0;
616}
617
618
619/**
620 * nes_query_gid
621 */
622static int nes_query_gid(struct ib_device *ibdev, u8 port,
623 int index, union ib_gid *gid)
624{
625 struct nes_vnic *nesvnic = to_nesvnic(ibdev);
626
627 memset(&(gid->raw[0]), 0, sizeof(gid->raw));
628 memcpy(&(gid->raw[0]), nesvnic->netdev->dev_addr, 6);
629
630 return 0;
631}
632
633
634/**
635 * nes_alloc_ucontext - Allocate the user context data structure. This keeps track
636 * of all objects associated with a particular user-mode client.
637 */
638static struct ib_ucontext *nes_alloc_ucontext(struct ib_device *ibdev,
639 struct ib_udata *udata)
640{
641 struct nes_vnic *nesvnic = to_nesvnic(ibdev);
642 struct nes_device *nesdev = nesvnic->nesdev;
643 struct nes_adapter *nesadapter = nesdev->nesadapter;
644 struct nes_alloc_ucontext_req req;
645 struct nes_alloc_ucontext_resp uresp;
646 struct nes_ucontext *nes_ucontext;
647 struct nes_ib_device *nesibdev = nesvnic->nesibdev;
648
649
650 if (ib_copy_from_udata(&req, udata, sizeof(struct nes_alloc_ucontext_req))) {
651 printk(KERN_ERR PFX "Invalid structure size on allocate user context.\n");
652 return ERR_PTR(-EINVAL);
653 }
654
655 if (req.userspace_ver != NES_ABI_USERSPACE_VER) {
656 printk(KERN_ERR PFX "Invalid userspace driver version detected. Detected version %d, should be %d\n",
657 req.userspace_ver, NES_ABI_USERSPACE_VER);
658 return ERR_PTR(-EINVAL);
659 }
660
661
662 memset(&uresp, 0, sizeof uresp);
663
664 uresp.max_qps = nesibdev->max_qp;
665 uresp.max_pds = nesibdev->max_pd;
666 uresp.wq_size = nesdev->nesadapter->max_qp_wr * 2;
667 uresp.virtwq = nesadapter->virtwq;
668 uresp.kernel_ver = NES_ABI_KERNEL_VER;
669
670 nes_ucontext = kzalloc(sizeof *nes_ucontext, GFP_KERNEL);
671 if (!nes_ucontext)
672 return ERR_PTR(-ENOMEM);
673
674 nes_ucontext->nesdev = nesdev;
675 nes_ucontext->mmap_wq_offset = uresp.max_pds;
676 nes_ucontext->mmap_cq_offset = nes_ucontext->mmap_wq_offset +
677 ((sizeof(struct nes_hw_qp_wqe) * uresp.max_qps * 2) + PAGE_SIZE-1) /
678 PAGE_SIZE;
679
680
681 if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) {
682 kfree(nes_ucontext);
683 return ERR_PTR(-EFAULT);
684 }
685
686 INIT_LIST_HEAD(&nes_ucontext->cq_reg_mem_list);
687 INIT_LIST_HEAD(&nes_ucontext->qp_reg_mem_list);
688 atomic_set(&nes_ucontext->usecnt, 1);
689 return &nes_ucontext->ibucontext;
690}
691
692
693/**
694 * nes_dealloc_ucontext
695 */
696static int nes_dealloc_ucontext(struct ib_ucontext *context)
697{
698 /* struct nes_vnic *nesvnic = to_nesvnic(context->device); */
699 /* struct nes_device *nesdev = nesvnic->nesdev; */
700 struct nes_ucontext *nes_ucontext = to_nesucontext(context);
701
702 if (!atomic_dec_and_test(&nes_ucontext->usecnt))
703 return 0;
704 kfree(nes_ucontext);
705 return 0;
706}
707
708
709/**
710 * nes_mmap
711 */
712static int nes_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
713{
714 unsigned long index;
715 struct nes_vnic *nesvnic = to_nesvnic(context->device);
716 struct nes_device *nesdev = nesvnic->nesdev;
717 /* struct nes_adapter *nesadapter = nesdev->nesadapter; */
718 struct nes_ucontext *nes_ucontext;
719 struct nes_qp *nesqp;
720
721 nes_ucontext = to_nesucontext(context);
722
723
724 if (vma->vm_pgoff >= nes_ucontext->mmap_wq_offset) {
725 index = (vma->vm_pgoff - nes_ucontext->mmap_wq_offset) * PAGE_SIZE;
726 index /= ((sizeof(struct nes_hw_qp_wqe) * nesdev->nesadapter->max_qp_wr * 2) +
727 PAGE_SIZE-1) & (~(PAGE_SIZE-1));
728 if (!test_bit(index, nes_ucontext->allocated_wqs)) {
729 nes_debug(NES_DBG_MMAP, "wq %lu not allocated\n", index);
730 return -EFAULT;
731 }
732 nesqp = nes_ucontext->mmap_nesqp[index];
733 if (nesqp == NULL) {
734 nes_debug(NES_DBG_MMAP, "wq %lu has a NULL QP base.\n", index);
735 return -EFAULT;
736 }
737 if (remap_pfn_range(vma, vma->vm_start,
738 virt_to_phys(nesqp->hwqp.sq_vbase) >> PAGE_SHIFT,
739 vma->vm_end - vma->vm_start,
740 vma->vm_page_prot)) {
741 nes_debug(NES_DBG_MMAP, "remap_pfn_range failed.\n");
742 return -EAGAIN;
743 }
744 vma->vm_private_data = nesqp;
745 return 0;
746 } else {
747 index = vma->vm_pgoff;
748 if (!test_bit(index, nes_ucontext->allocated_doorbells))
749 return -EFAULT;
750
751 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
752 if (io_remap_pfn_range(vma, vma->vm_start,
753 (nesdev->doorbell_start +
754 ((nes_ucontext->mmap_db_index[index] - nesdev->base_doorbell_index) * 4096))
755 >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot))
756 return -EAGAIN;
757 vma->vm_private_data = nes_ucontext;
758 return 0;
759 }
760
761 return -ENOSYS;
762}
763
764
765/**
766 * nes_alloc_pd
767 */
768static struct ib_pd *nes_alloc_pd(struct ib_device *ibdev,
769 struct ib_ucontext *context, struct ib_udata *udata)
770{
771 struct nes_pd *nespd;
772 struct nes_vnic *nesvnic = to_nesvnic(ibdev);
773 struct nes_device *nesdev = nesvnic->nesdev;
774 struct nes_adapter *nesadapter = nesdev->nesadapter;
775 struct nes_ucontext *nesucontext;
776 struct nes_alloc_pd_resp uresp;
777 u32 pd_num = 0;
778 int err;
779
780 nes_debug(NES_DBG_PD, "nesvnic=%p, netdev=%p %s, ibdev=%p, context=%p, netdev refcnt=%u\n",
781 nesvnic, nesdev->netdev[0], nesdev->netdev[0]->name, ibdev, context,
Eric Dumazet29b44332010-10-11 10:22:12 +0000782 netdev_refcnt_read(nesvnic->netdev));
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800783
784 err = nes_alloc_resource(nesadapter, nesadapter->allocated_pds,
Tatyana Nikolova81821642012-09-20 21:08:04 +0000785 nesadapter->max_pd, &pd_num, &nesadapter->next_pd, NES_RESOURCE_PD);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800786 if (err) {
787 return ERR_PTR(err);
788 }
789
790 nespd = kzalloc(sizeof (struct nes_pd), GFP_KERNEL);
791 if (!nespd) {
792 nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num);
793 return ERR_PTR(-ENOMEM);
794 }
795
796 nes_debug(NES_DBG_PD, "Allocating PD (%p) for ib device %s\n",
797 nespd, nesvnic->nesibdev->ibdev.name);
798
799 nespd->pd_id = (pd_num << (PAGE_SHIFT-12)) + nesadapter->base_pd;
800
801 if (context) {
802 nesucontext = to_nesucontext(context);
803 nespd->mmap_db_index = find_next_zero_bit(nesucontext->allocated_doorbells,
804 NES_MAX_USER_DB_REGIONS, nesucontext->first_free_db);
805 nes_debug(NES_DBG_PD, "find_first_zero_biton doorbells returned %u, mapping pd_id %u.\n",
806 nespd->mmap_db_index, nespd->pd_id);
Adrian Bunk65b07ec2008-02-21 08:01:18 -0600807 if (nespd->mmap_db_index >= NES_MAX_USER_DB_REGIONS) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800808 nes_debug(NES_DBG_PD, "mmap_db_index > MAX\n");
809 nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num);
810 kfree(nespd);
811 return ERR_PTR(-ENOMEM);
812 }
813
814 uresp.pd_id = nespd->pd_id;
815 uresp.mmap_db_index = nespd->mmap_db_index;
816 if (ib_copy_to_udata(udata, &uresp, sizeof (struct nes_alloc_pd_resp))) {
817 nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num);
818 kfree(nespd);
819 return ERR_PTR(-EFAULT);
820 }
821
822 set_bit(nespd->mmap_db_index, nesucontext->allocated_doorbells);
823 nesucontext->mmap_db_index[nespd->mmap_db_index] = nespd->pd_id;
824 nesucontext->first_free_db = nespd->mmap_db_index + 1;
825 }
826
827 nes_debug(NES_DBG_PD, "PD%u structure located @%p.\n", nespd->pd_id, nespd);
828 return &nespd->ibpd;
829}
830
831
832/**
833 * nes_dealloc_pd
834 */
835static int nes_dealloc_pd(struct ib_pd *ibpd)
836{
837 struct nes_ucontext *nesucontext;
838 struct nes_pd *nespd = to_nespd(ibpd);
839 struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
840 struct nes_device *nesdev = nesvnic->nesdev;
841 struct nes_adapter *nesadapter = nesdev->nesadapter;
842
843 if ((ibpd->uobject) && (ibpd->uobject->context)) {
844 nesucontext = to_nesucontext(ibpd->uobject->context);
845 nes_debug(NES_DBG_PD, "Clearing bit %u from allocated doorbells\n",
846 nespd->mmap_db_index);
847 clear_bit(nespd->mmap_db_index, nesucontext->allocated_doorbells);
848 nesucontext->mmap_db_index[nespd->mmap_db_index] = 0;
849 if (nesucontext->first_free_db > nespd->mmap_db_index) {
850 nesucontext->first_free_db = nespd->mmap_db_index;
851 }
852 }
853
854 nes_debug(NES_DBG_PD, "Deallocating PD%u structure located @%p.\n",
855 nespd->pd_id, nespd);
856 nes_free_resource(nesadapter, nesadapter->allocated_pds,
857 (nespd->pd_id-nesadapter->base_pd)>>(PAGE_SHIFT-12));
858 kfree(nespd);
859
860 return 0;
861}
862
863
864/**
865 * nes_create_ah
866 */
867static struct ib_ah *nes_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
868{
869 return ERR_PTR(-ENOSYS);
870}
871
872
873/**
874 * nes_destroy_ah
875 */
876static int nes_destroy_ah(struct ib_ah *ah)
877{
878 return -ENOSYS;
879}
880
881
882/**
883 * nes_get_encoded_size
884 */
885static inline u8 nes_get_encoded_size(int *size)
886{
887 u8 encoded_size = 0;
888 if (*size <= 32) {
889 *size = 32;
890 encoded_size = 1;
891 } else if (*size <= 128) {
892 *size = 128;
893 encoded_size = 2;
894 } else if (*size <= 512) {
895 *size = 512;
896 encoded_size = 3;
897 }
898 return (encoded_size);
899}
900
901
902
903/**
904 * nes_setup_virt_qp
905 */
906static int nes_setup_virt_qp(struct nes_qp *nesqp, struct nes_pbl *nespbl,
907 struct nes_vnic *nesvnic, int sq_size, int rq_size)
908{
909 unsigned long flags;
910 void *mem;
911 __le64 *pbl = NULL;
912 __le64 *tpbl;
913 __le64 *pblbuffer;
914 struct nes_device *nesdev = nesvnic->nesdev;
915 struct nes_adapter *nesadapter = nesdev->nesadapter;
916 u32 pbl_entries;
917 u8 rq_pbl_entries;
918 u8 sq_pbl_entries;
919
920 pbl_entries = nespbl->pbl_size >> 3;
Roland Dreier71e09572008-04-16 21:01:09 -0700921 nes_debug(NES_DBG_QP, "Userspace PBL, pbl_size=%u, pbl_entries = %d pbl_vbase=%p, pbl_pbase=%lx\n",
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800922 nespbl->pbl_size, pbl_entries,
923 (void *)nespbl->pbl_vbase,
Roland Dreier71e09572008-04-16 21:01:09 -0700924 (unsigned long) nespbl->pbl_pbase);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800925 pbl = (__le64 *) nespbl->pbl_vbase; /* points to first pbl entry */
926 /* now lets set the sq_vbase as well as rq_vbase addrs we will assign */
927 /* the first pbl to be fro the rq_vbase... */
928 rq_pbl_entries = (rq_size * sizeof(struct nes_hw_qp_wqe)) >> 12;
929 sq_pbl_entries = (sq_size * sizeof(struct nes_hw_qp_wqe)) >> 12;
930 nesqp->hwqp.sq_pbase = (le32_to_cpu(((__le32 *)pbl)[0])) | ((u64)((le32_to_cpu(((__le32 *)pbl)[1]))) << 32);
931 if (!nespbl->page) {
932 nes_debug(NES_DBG_QP, "QP nespbl->page is NULL \n");
933 kfree(nespbl);
934 return -ENOMEM;
935 }
936
937 nesqp->hwqp.sq_vbase = kmap(nespbl->page);
938 nesqp->page = nespbl->page;
939 if (!nesqp->hwqp.sq_vbase) {
940 nes_debug(NES_DBG_QP, "QP sq_vbase kmap failed\n");
941 kfree(nespbl);
942 return -ENOMEM;
943 }
944
945 /* Now to get to sq.. we need to calculate how many */
946 /* PBL entries were used by the rq.. */
947 pbl += sq_pbl_entries;
948 nesqp->hwqp.rq_pbase = (le32_to_cpu(((__le32 *)pbl)[0])) | ((u64)((le32_to_cpu(((__le32 *)pbl)[1]))) << 32);
949 /* nesqp->hwqp.rq_vbase = bus_to_virt(*pbl); */
950 /*nesqp->hwqp.rq_vbase = phys_to_virt(*pbl); */
951
Roland Dreier71e09572008-04-16 21:01:09 -0700952 nes_debug(NES_DBG_QP, "QP sq_vbase= %p sq_pbase=%lx rq_vbase=%p rq_pbase=%lx\n",
953 nesqp->hwqp.sq_vbase, (unsigned long) nesqp->hwqp.sq_pbase,
954 nesqp->hwqp.rq_vbase, (unsigned long) nesqp->hwqp.rq_pbase);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800955 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
956 if (!nesadapter->free_256pbl) {
957 pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
958 nespbl->pbl_pbase);
959 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
960 kunmap(nesqp->page);
961 kfree(nespbl);
962 return -ENOMEM;
963 }
964 nesadapter->free_256pbl--;
965 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
966
967 nesqp->pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 256, &nesqp->pbl_pbase);
968 pblbuffer = nesqp->pbl_vbase;
969 if (!nesqp->pbl_vbase) {
970 /* memory allocated during nes_reg_user_mr() */
971 pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
972 nespbl->pbl_pbase);
973 kfree(nespbl);
974 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
975 nesadapter->free_256pbl++;
976 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
977 kunmap(nesqp->page);
978 return -ENOMEM;
979 }
980 memset(nesqp->pbl_vbase, 0, 256);
981 /* fill in the page address in the pbl buffer.. */
982 tpbl = pblbuffer + 16;
983 pbl = (__le64 *)nespbl->pbl_vbase;
984 while (sq_pbl_entries--)
985 *tpbl++ = *pbl++;
986 tpbl = pblbuffer;
987 while (rq_pbl_entries--)
988 *tpbl++ = *pbl++;
989
990 /* done with memory allocated during nes_reg_user_mr() */
991 pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
992 nespbl->pbl_pbase);
993 kfree(nespbl);
994
995 nesqp->qp_mem_size =
996 max((u32)sizeof(struct nes_qp_context), ((u32)256)) + 256; /* this is Q2 */
997 /* Round up to a multiple of a page */
998 nesqp->qp_mem_size += PAGE_SIZE - 1;
999 nesqp->qp_mem_size &= ~(PAGE_SIZE - 1);
1000
1001 mem = pci_alloc_consistent(nesdev->pcidev, nesqp->qp_mem_size,
1002 &nesqp->hwqp.q2_pbase);
1003
1004 if (!mem) {
1005 pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase);
1006 nesqp->pbl_vbase = NULL;
1007 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
1008 nesadapter->free_256pbl++;
1009 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
1010 kunmap(nesqp->page);
1011 return -ENOMEM;
1012 }
Faisal Latifd2fa9b262009-12-09 15:54:28 -08001013 nesqp->sq_kmapped = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001014 nesqp->hwqp.q2_vbase = mem;
1015 mem += 256;
1016 memset(nesqp->hwqp.q2_vbase, 0, 256);
1017 nesqp->nesqp_context = mem;
1018 memset(nesqp->nesqp_context, 0, sizeof(*nesqp->nesqp_context));
1019 nesqp->nesqp_context_pbase = nesqp->hwqp.q2_pbase + 256;
1020
1021 return 0;
1022}
1023
1024
1025/**
1026 * nes_setup_mmap_qp
1027 */
1028static int nes_setup_mmap_qp(struct nes_qp *nesqp, struct nes_vnic *nesvnic,
1029 int sq_size, int rq_size)
1030{
1031 void *mem;
1032 struct nes_device *nesdev = nesvnic->nesdev;
1033
1034 nesqp->qp_mem_size = (sizeof(struct nes_hw_qp_wqe) * sq_size) +
1035 (sizeof(struct nes_hw_qp_wqe) * rq_size) +
1036 max((u32)sizeof(struct nes_qp_context), ((u32)256)) +
1037 256; /* this is Q2 */
1038 /* Round up to a multiple of a page */
1039 nesqp->qp_mem_size += PAGE_SIZE - 1;
1040 nesqp->qp_mem_size &= ~(PAGE_SIZE - 1);
1041
1042 mem = pci_alloc_consistent(nesdev->pcidev, nesqp->qp_mem_size,
1043 &nesqp->hwqp.sq_pbase);
1044 if (!mem)
1045 return -ENOMEM;
1046 nes_debug(NES_DBG_QP, "PCI consistent memory for "
1047 "host descriptor rings located @ %p (pa = 0x%08lX.) size = %u.\n",
1048 mem, (unsigned long)nesqp->hwqp.sq_pbase, nesqp->qp_mem_size);
1049
1050 memset(mem, 0, nesqp->qp_mem_size);
1051
1052 nesqp->hwqp.sq_vbase = mem;
1053 mem += sizeof(struct nes_hw_qp_wqe) * sq_size;
1054
1055 nesqp->hwqp.rq_vbase = mem;
1056 nesqp->hwqp.rq_pbase = nesqp->hwqp.sq_pbase +
1057 sizeof(struct nes_hw_qp_wqe) * sq_size;
1058 mem += sizeof(struct nes_hw_qp_wqe) * rq_size;
1059
1060 nesqp->hwqp.q2_vbase = mem;
1061 nesqp->hwqp.q2_pbase = nesqp->hwqp.rq_pbase +
1062 sizeof(struct nes_hw_qp_wqe) * rq_size;
1063 mem += 256;
1064 memset(nesqp->hwqp.q2_vbase, 0, 256);
1065
1066 nesqp->nesqp_context = mem;
1067 nesqp->nesqp_context_pbase = nesqp->hwqp.q2_pbase + 256;
1068 memset(nesqp->nesqp_context, 0, sizeof(*nesqp->nesqp_context));
1069 return 0;
1070}
1071
1072
1073/**
1074 * nes_free_qp_mem() is to free up the qp's pci_alloc_consistent() memory.
1075 */
1076static inline void nes_free_qp_mem(struct nes_device *nesdev,
1077 struct nes_qp *nesqp, int virt_wqs)
1078{
1079 unsigned long flags;
1080 struct nes_adapter *nesadapter = nesdev->nesadapter;
1081 if (!virt_wqs) {
1082 pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size,
1083 nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase);
1084 }else {
1085 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
1086 nesadapter->free_256pbl++;
1087 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
1088 pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase);
1089 pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase );
1090 nesqp->pbl_vbase = NULL;
Faisal Latifd2fa9b262009-12-09 15:54:28 -08001091 if (nesqp->sq_kmapped) {
1092 nesqp->sq_kmapped = 0;
1093 kunmap(nesqp->page);
1094 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001095 }
1096}
1097
1098
1099/**
1100 * nes_create_qp
1101 */
1102static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
1103 struct ib_qp_init_attr *init_attr, struct ib_udata *udata)
1104{
1105 u64 u64temp= 0;
1106 u64 u64nesqp = 0;
1107 struct nes_pd *nespd = to_nespd(ibpd);
1108 struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
1109 struct nes_device *nesdev = nesvnic->nesdev;
1110 struct nes_adapter *nesadapter = nesdev->nesadapter;
1111 struct nes_qp *nesqp;
1112 struct nes_cq *nescq;
1113 struct nes_ucontext *nes_ucontext;
1114 struct nes_hw_cqp_wqe *cqp_wqe;
1115 struct nes_cqp_request *cqp_request;
1116 struct nes_create_qp_req req;
1117 struct nes_create_qp_resp uresp;
1118 struct nes_pbl *nespbl = NULL;
1119 u32 qp_num = 0;
1120 u32 opcode = 0;
1121 /* u32 counter = 0; */
1122 void *mem;
1123 unsigned long flags;
1124 int ret;
1125 int err;
1126 int virt_wqs = 0;
1127 int sq_size;
1128 int rq_size;
1129 u8 sq_encoded_size;
1130 u8 rq_encoded_size;
1131 /* int counter; */
1132
Eli Cohenb846f252008-04-16 21:09:27 -07001133 if (init_attr->create_flags)
1134 return ERR_PTR(-EINVAL);
1135
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001136 atomic_inc(&qps_created);
1137 switch (init_attr->qp_type) {
1138 case IB_QPT_RC:
1139 if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) {
1140 init_attr->cap.max_inline_data = 0;
1141 } else {
1142 init_attr->cap.max_inline_data = 64;
1143 }
1144 sq_size = init_attr->cap.max_send_wr;
1145 rq_size = init_attr->cap.max_recv_wr;
1146
Glenn Streiff7495ab62008-04-29 13:46:54 -07001147 /* check if the encoded sizes are OK or not... */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001148 sq_encoded_size = nes_get_encoded_size(&sq_size);
1149 rq_encoded_size = nes_get_encoded_size(&rq_size);
1150
1151 if ((!sq_encoded_size) || (!rq_encoded_size)) {
1152 nes_debug(NES_DBG_QP, "ERROR bad rq (%u) or sq (%u) size\n",
1153 rq_size, sq_size);
1154 return ERR_PTR(-EINVAL);
1155 }
1156
1157 init_attr->cap.max_send_wr = sq_size -2;
1158 init_attr->cap.max_recv_wr = rq_size -1;
1159 nes_debug(NES_DBG_QP, "RQ size=%u, SQ Size=%u\n", rq_size, sq_size);
1160
1161 ret = nes_alloc_resource(nesadapter, nesadapter->allocated_qps,
Tatyana Nikolova81821642012-09-20 21:08:04 +00001162 nesadapter->max_qp, &qp_num, &nesadapter->next_qp, NES_RESOURCE_QP);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001163 if (ret) {
1164 return ERR_PTR(ret);
1165 }
1166
1167 /* Need 512 (actually now 1024) byte alignment on this structure */
1168 mem = kzalloc(sizeof(*nesqp)+NES_SW_CONTEXT_ALIGN-1, GFP_KERNEL);
1169 if (!mem) {
1170 nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
1171 nes_debug(NES_DBG_QP, "Unable to allocate QP\n");
1172 return ERR_PTR(-ENOMEM);
1173 }
1174 u64nesqp = (unsigned long)mem;
1175 u64nesqp += ((u64)NES_SW_CONTEXT_ALIGN) - 1;
1176 u64temp = ((u64)NES_SW_CONTEXT_ALIGN) - 1;
1177 u64nesqp &= ~u64temp;
1178 nesqp = (struct nes_qp *)(unsigned long)u64nesqp;
1179 /* nes_debug(NES_DBG_QP, "nesqp=%p, allocated buffer=%p. Rounded to closest %u\n",
1180 nesqp, mem, NES_SW_CONTEXT_ALIGN); */
1181 nesqp->allocated_buffer = mem;
1182
1183 if (udata) {
1184 if (ib_copy_from_udata(&req, udata, sizeof(struct nes_create_qp_req))) {
1185 nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
1186 kfree(nesqp->allocated_buffer);
1187 nes_debug(NES_DBG_QP, "ib_copy_from_udata() Failed \n");
Yann Droneaud9d194d12014-03-10 23:06:27 +01001188 return ERR_PTR(-EFAULT);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001189 }
1190 if (req.user_wqe_buffers) {
1191 virt_wqs = 1;
1192 }
Tatyana Nikolova43adff32014-03-11 14:20:17 -05001193 if (req.user_qp_buffer)
1194 nesqp->nesuqp_addr = req.user_qp_buffer;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001195 if ((ibpd->uobject) && (ibpd->uobject->context)) {
1196 nesqp->user_mode = 1;
1197 nes_ucontext = to_nesucontext(ibpd->uobject->context);
1198 if (virt_wqs) {
1199 err = 1;
1200 list_for_each_entry(nespbl, &nes_ucontext->qp_reg_mem_list, list) {
1201 if (nespbl->user_base == (unsigned long )req.user_wqe_buffers) {
1202 list_del(&nespbl->list);
1203 err = 0;
1204 nes_debug(NES_DBG_QP, "Found PBL for virtual QP. nespbl=%p. user_base=0x%lx\n",
1205 nespbl, nespbl->user_base);
1206 break;
1207 }
1208 }
1209 if (err) {
1210 nes_debug(NES_DBG_QP, "Didn't Find PBL for virtual QP. address = %llx.\n",
1211 (long long unsigned int)req.user_wqe_buffers);
1212 nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
1213 kfree(nesqp->allocated_buffer);
Chien Tung9300c0c2008-02-21 07:51:17 -06001214 return ERR_PTR(-EFAULT);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001215 }
1216 }
1217
1218 nes_ucontext = to_nesucontext(ibpd->uobject->context);
1219 nesqp->mmap_sq_db_index =
1220 find_next_zero_bit(nes_ucontext->allocated_wqs,
1221 NES_MAX_USER_WQ_REGIONS, nes_ucontext->first_free_wq);
1222 /* nes_debug(NES_DBG_QP, "find_first_zero_biton wqs returned %u\n",
1223 nespd->mmap_db_index); */
Roland Dreier51af33e2008-02-18 10:33:59 -08001224 if (nesqp->mmap_sq_db_index >= NES_MAX_USER_WQ_REGIONS) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001225 nes_debug(NES_DBG_QP,
1226 "db index > max user regions, failing create QP\n");
1227 nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
1228 if (virt_wqs) {
1229 pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
1230 nespbl->pbl_pbase);
1231 kfree(nespbl);
1232 }
1233 kfree(nesqp->allocated_buffer);
1234 return ERR_PTR(-ENOMEM);
1235 }
1236 set_bit(nesqp->mmap_sq_db_index, nes_ucontext->allocated_wqs);
1237 nes_ucontext->mmap_nesqp[nesqp->mmap_sq_db_index] = nesqp;
1238 nes_ucontext->first_free_wq = nesqp->mmap_sq_db_index + 1;
1239 } else {
1240 nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
1241 kfree(nesqp->allocated_buffer);
1242 return ERR_PTR(-EFAULT);
1243 }
1244 }
1245 err = (!virt_wqs) ? nes_setup_mmap_qp(nesqp, nesvnic, sq_size, rq_size) :
1246 nes_setup_virt_qp(nesqp, nespbl, nesvnic, sq_size, rq_size);
1247 if (err) {
1248 nes_debug(NES_DBG_QP,
1249 "error geting qp mem code = %d\n", err);
1250 nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
1251 kfree(nesqp->allocated_buffer);
1252 return ERR_PTR(-ENOMEM);
1253 }
1254
1255 nesqp->hwqp.sq_size = sq_size;
1256 nesqp->hwqp.sq_encoded_size = sq_encoded_size;
1257 nesqp->hwqp.sq_head = 1;
1258 nesqp->hwqp.rq_size = rq_size;
1259 nesqp->hwqp.rq_encoded_size = rq_encoded_size;
1260 /* nes_debug(NES_DBG_QP, "nesqp->nesqp_context_pbase = %p\n",
1261 (void *)nesqp->nesqp_context_pbase);
1262 */
1263 nesqp->hwqp.qp_id = qp_num;
1264 nesqp->ibqp.qp_num = nesqp->hwqp.qp_id;
1265 nesqp->nespd = nespd;
1266
1267 nescq = to_nescq(init_attr->send_cq);
1268 nesqp->nesscq = nescq;
1269 nescq = to_nescq(init_attr->recv_cq);
1270 nesqp->nesrcq = nescq;
1271
1272 nesqp->nesqp_context->misc |= cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) <<
1273 NES_QPCONTEXT_MISC_PCI_FCN_SHIFT);
1274 nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.rq_encoded_size <<
1275 NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT);
1276 nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.sq_encoded_size <<
1277 NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT);
Faisal Latifc12e56e2009-03-12 14:34:59 -07001278 if (!udata) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001279 nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_PRIV_EN);
1280 nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_FAST_REGISTER_EN);
Faisal Latifc12e56e2009-03-12 14:34:59 -07001281 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001282 nesqp->nesqp_context->cqs = cpu_to_le32(nesqp->nesscq->hw_cq.cq_number +
1283 ((u32)nesqp->nesrcq->hw_cq.cq_number << 16));
1284 u64temp = (u64)nesqp->hwqp.sq_pbase;
1285 nesqp->nesqp_context->sq_addr_low = cpu_to_le32((u32)u64temp);
1286 nesqp->nesqp_context->sq_addr_high = cpu_to_le32((u32)(u64temp >> 32));
1287
1288
1289 if (!virt_wqs) {
1290 u64temp = (u64)nesqp->hwqp.sq_pbase;
1291 nesqp->nesqp_context->sq_addr_low = cpu_to_le32((u32)u64temp);
1292 nesqp->nesqp_context->sq_addr_high = cpu_to_le32((u32)(u64temp >> 32));
1293 u64temp = (u64)nesqp->hwqp.rq_pbase;
1294 nesqp->nesqp_context->rq_addr_low = cpu_to_le32((u32)u64temp);
1295 nesqp->nesqp_context->rq_addr_high = cpu_to_le32((u32)(u64temp >> 32));
1296 } else {
1297 u64temp = (u64)nesqp->pbl_pbase;
1298 nesqp->nesqp_context->rq_addr_low = cpu_to_le32((u32)u64temp);
1299 nesqp->nesqp_context->rq_addr_high = cpu_to_le32((u32)(u64temp >> 32));
1300 }
1301
1302 /* nes_debug(NES_DBG_QP, "next_qp_nic_index=%u, using nic_index=%d\n",
1303 nesvnic->next_qp_nic_index,
1304 nesvnic->qp_nic_index[nesvnic->next_qp_nic_index]); */
1305 spin_lock_irqsave(&nesdev->cqp.lock, flags);
1306 nesqp->nesqp_context->misc2 |= cpu_to_le32(
1307 (u32)nesvnic->qp_nic_index[nesvnic->next_qp_nic_index] <<
1308 NES_QPCONTEXT_MISC2_NIC_INDEX_SHIFT);
1309 nesvnic->next_qp_nic_index++;
1310 if ((nesvnic->next_qp_nic_index > 3) ||
1311 (nesvnic->qp_nic_index[nesvnic->next_qp_nic_index] == 0xf)) {
1312 nesvnic->next_qp_nic_index = 0;
1313 }
1314 spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
1315
1316 nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32((u32)nesqp->nespd->pd_id << 16);
1317 u64temp = (u64)nesqp->hwqp.q2_pbase;
1318 nesqp->nesqp_context->q2_addr_low = cpu_to_le32((u32)u64temp);
1319 nesqp->nesqp_context->q2_addr_high = cpu_to_le32((u32)(u64temp >> 32));
1320 nesqp->nesqp_context->aeq_token_low = cpu_to_le32((u32)((unsigned long)(nesqp)));
1321 nesqp->nesqp_context->aeq_token_high = cpu_to_le32((u32)(upper_32_bits((unsigned long)(nesqp))));
1322 nesqp->nesqp_context->ird_ord_sizes = cpu_to_le32(NES_QPCONTEXT_ORDIRD_ALSMM |
Faisal Latif883c6992010-03-02 17:22:51 -06001323 NES_QPCONTEXT_ORDIRD_AAH |
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001324 ((((u32)nesadapter->max_irrq_wr) <<
1325 NES_QPCONTEXT_ORDIRD_IRDSIZE_SHIFT) & NES_QPCONTEXT_ORDIRD_IRDSIZE_MASK));
1326 if (disable_mpa_crc) {
1327 nes_debug(NES_DBG_QP, "Disabling MPA crc checking due to module option.\n");
1328 nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(NES_QPCONTEXT_ORDIRD_RNMC);
1329 }
1330
1331
1332 /* Create the QP */
1333 cqp_request = nes_get_cqp_request(nesdev);
1334 if (cqp_request == NULL) {
1335 nes_debug(NES_DBG_QP, "Failed to get a cqp_request\n");
1336 nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
1337 nes_free_qp_mem(nesdev, nesqp,virt_wqs);
1338 kfree(nesqp->allocated_buffer);
1339 return ERR_PTR(-ENOMEM);
1340 }
1341 cqp_request->waiting = 1;
1342 cqp_wqe = &cqp_request->cqp_wqe;
1343
1344 if (!virt_wqs) {
1345 opcode = NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_IWARP |
1346 NES_CQP_QP_IWARP_STATE_IDLE;
1347 } else {
1348 opcode = NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_VIRT_WQS |
1349 NES_CQP_QP_IWARP_STATE_IDLE;
1350 }
1351 opcode |= NES_CQP_QP_CQS_VALID;
1352 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1353 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
1354 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
1355
1356 u64temp = (u64)nesqp->nesqp_context_pbase;
1357 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
1358
1359 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -07001360 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001361
1362 /* Wait for CQP */
1363 nes_debug(NES_DBG_QP, "Waiting for create iWARP QP%u to complete.\n",
1364 nesqp->hwqp.qp_id);
1365 ret = wait_event_timeout(cqp_request->waitq,
1366 (cqp_request->request_done != 0), NES_EVENT_TIMEOUT);
1367 nes_debug(NES_DBG_QP, "Create iwarp QP%u completed, wait_event_timeout ret=%u,"
1368 " nesdev->cqp_head = %u, nesdev->cqp.sq_tail = %u,"
1369 " CQP Major:Minor codes = 0x%04X:0x%04X.\n",
1370 nesqp->hwqp.qp_id, ret, nesdev->cqp.sq_head, nesdev->cqp.sq_tail,
1371 cqp_request->major_code, cqp_request->minor_code);
1372 if ((!ret) || (cqp_request->major_code)) {
Roland Dreier1ff66e82008-07-14 23:48:49 -07001373 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001374 nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
1375 nes_free_qp_mem(nesdev, nesqp,virt_wqs);
1376 kfree(nesqp->allocated_buffer);
1377 if (!ret) {
1378 return ERR_PTR(-ETIME);
1379 } else {
1380 return ERR_PTR(-EIO);
1381 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001382 }
1383
Roland Dreier1ff66e82008-07-14 23:48:49 -07001384 nes_put_cqp_request(nesdev, cqp_request);
1385
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001386 if (ibpd->uobject) {
1387 uresp.mmap_sq_db_index = nesqp->mmap_sq_db_index;
Dan Carpenter60429632013-07-25 20:04:59 +03001388 uresp.mmap_rq_db_index = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001389 uresp.actual_sq_size = sq_size;
1390 uresp.actual_rq_size = rq_size;
1391 uresp.qp_id = nesqp->hwqp.qp_id;
1392 uresp.nes_drv_opt = nes_drv_opt;
1393 if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) {
1394 nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
1395 nes_free_qp_mem(nesdev, nesqp,virt_wqs);
1396 kfree(nesqp->allocated_buffer);
1397 return ERR_PTR(-EFAULT);
1398 }
1399 }
1400
1401 nes_debug(NES_DBG_QP, "QP%u structure located @%p.Size = %u.\n",
1402 nesqp->hwqp.qp_id, nesqp, (u32)sizeof(*nesqp));
1403 spin_lock_init(&nesqp->lock);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001404 nes_add_ref(&nesqp->ibqp);
1405 break;
1406 default:
1407 nes_debug(NES_DBG_QP, "Invalid QP type: %d\n", init_attr->qp_type);
1408 return ERR_PTR(-EINVAL);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001409 }
1410
Chien Tungd14152d2009-12-09 15:21:56 -08001411 nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR);
Tatyana Nikolova7bfcfa52012-12-06 19:58:27 +00001412 init_timer(&nesqp->terminate_timer);
1413 nesqp->terminate_timer.function = nes_terminate_timeout;
1414 nesqp->terminate_timer.data = (unsigned long)nesqp;
Chien Tungd14152d2009-12-09 15:21:56 -08001415
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001416 /* update the QP table */
1417 nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp;
1418 nes_debug(NES_DBG_QP, "netdev refcnt=%u\n",
Eric Dumazet29b44332010-10-11 10:22:12 +00001419 netdev_refcnt_read(nesvnic->netdev));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001420
1421 return &nesqp->ibqp;
1422}
1423
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001424/**
Don Wood5ee21fe2009-09-05 20:36:37 -07001425 * nes_clean_cq
1426 */
1427static void nes_clean_cq(struct nes_qp *nesqp, struct nes_cq *nescq)
1428{
1429 u32 cq_head;
1430 u32 lo;
1431 u32 hi;
1432 u64 u64temp;
1433 unsigned long flags = 0;
1434
1435 spin_lock_irqsave(&nescq->lock, flags);
1436
1437 cq_head = nescq->hw_cq.cq_head;
1438 while (le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
1439 rmb();
1440 lo = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
1441 hi = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]);
1442 u64temp = (((u64)hi) << 32) | ((u64)lo);
1443 u64temp &= ~(NES_SW_CONTEXT_ALIGN-1);
1444 if (u64temp == (u64)(unsigned long)nesqp) {
1445 /* Zero the context value so cqe will be ignored */
1446 nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] = 0;
1447 nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX] = 0;
1448 }
1449
1450 if (++cq_head >= nescq->hw_cq.cq_size)
1451 cq_head = 0;
1452 }
1453
1454 spin_unlock_irqrestore(&nescq->lock, flags);
1455}
1456
1457
1458/**
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001459 * nes_destroy_qp
1460 */
1461static int nes_destroy_qp(struct ib_qp *ibqp)
1462{
1463 struct nes_qp *nesqp = to_nesqp(ibqp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001464 struct nes_ucontext *nes_ucontext;
1465 struct ib_qp_attr attr;
1466 struct iw_cm_id *cm_id;
1467 struct iw_cm_event cm_event;
Faisal Latif0f0bee82011-09-25 20:34:00 -05001468 int ret = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001469
1470 atomic_inc(&sw_qps_destroyed);
1471 nesqp->destroyed = 1;
1472
1473 /* Blow away the connection if it exists. */
1474 if (nesqp->ibqp_state >= IB_QPS_INIT && nesqp->ibqp_state <= IB_QPS_RTS) {
1475 /* if (nesqp->ibqp_state == IB_QPS_RTS) { */
1476 attr.qp_state = IB_QPS_ERR;
1477 nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
1478 }
1479
1480 if (((nesqp->ibqp_state == IB_QPS_INIT) ||
1481 (nesqp->ibqp_state == IB_QPS_RTR)) && (nesqp->cm_id)) {
1482 cm_id = nesqp->cm_id;
1483 cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
Roland Dreierd0c49bf2011-05-09 22:23:57 -07001484 cm_event.status = -ETIMEDOUT;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001485 cm_event.local_addr = cm_id->local_addr;
1486 cm_event.remote_addr = cm_id->remote_addr;
1487 cm_event.private_data = NULL;
1488 cm_event.private_data_len = 0;
1489
1490 nes_debug(NES_DBG_QP, "Generating a CM Timeout Event for "
1491 "QP%u. cm_id = %p, refcount = %u. \n",
1492 nesqp->hwqp.qp_id, cm_id, atomic_read(&nesqp->refcount));
1493
1494 cm_id->rem_ref(cm_id);
1495 ret = cm_id->event_handler(cm_id, &cm_event);
1496 if (ret)
1497 nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret);
1498 }
1499
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001500 if (nesqp->user_mode) {
1501 if ((ibqp->uobject)&&(ibqp->uobject->context)) {
1502 nes_ucontext = to_nesucontext(ibqp->uobject->context);
1503 clear_bit(nesqp->mmap_sq_db_index, nes_ucontext->allocated_wqs);
1504 nes_ucontext->mmap_nesqp[nesqp->mmap_sq_db_index] = NULL;
1505 if (nes_ucontext->first_free_wq > nesqp->mmap_sq_db_index) {
1506 nes_ucontext->first_free_wq = nesqp->mmap_sq_db_index;
1507 }
1508 }
Faisal Latifd2fa9b262009-12-09 15:54:28 -08001509 if (nesqp->pbl_pbase && nesqp->sq_kmapped) {
1510 nesqp->sq_kmapped = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001511 kunmap(nesqp->page);
Faisal Latifd2fa9b262009-12-09 15:54:28 -08001512 }
Don Wood5ee21fe2009-09-05 20:36:37 -07001513 } else {
1514 /* Clean any pending completions from the cq(s) */
1515 if (nesqp->nesscq)
1516 nes_clean_cq(nesqp, nesqp->nesscq);
1517
1518 if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
1519 nes_clean_cq(nesqp, nesqp->nesrcq);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001520 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001521 nes_rem_ref(&nesqp->ibqp);
1522 return 0;
1523}
1524
1525
1526/**
1527 * nes_create_cq
1528 */
1529static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
1530 int comp_vector,
1531 struct ib_ucontext *context, struct ib_udata *udata)
1532{
1533 u64 u64temp;
1534 struct nes_vnic *nesvnic = to_nesvnic(ibdev);
1535 struct nes_device *nesdev = nesvnic->nesdev;
1536 struct nes_adapter *nesadapter = nesdev->nesadapter;
1537 struct nes_cq *nescq;
1538 struct nes_ucontext *nes_ucontext = NULL;
1539 struct nes_cqp_request *cqp_request;
1540 void *mem = NULL;
1541 struct nes_hw_cqp_wqe *cqp_wqe;
1542 struct nes_pbl *nespbl = NULL;
1543 struct nes_create_cq_req req;
1544 struct nes_create_cq_resp resp;
1545 u32 cq_num = 0;
1546 u32 opcode = 0;
1547 u32 pbl_entries = 1;
1548 int err;
1549 unsigned long flags;
1550 int ret;
1551
Chien Tung5924aea2009-12-09 15:21:56 -08001552 if (entries > nesadapter->max_cqe)
1553 return ERR_PTR(-EINVAL);
1554
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001555 err = nes_alloc_resource(nesadapter, nesadapter->allocated_cqs,
Tatyana Nikolova81821642012-09-20 21:08:04 +00001556 nesadapter->max_cq, &cq_num, &nesadapter->next_cq, NES_RESOURCE_CQ);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001557 if (err) {
1558 return ERR_PTR(err);
1559 }
1560
1561 nescq = kzalloc(sizeof(struct nes_cq), GFP_KERNEL);
1562 if (!nescq) {
1563 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1564 nes_debug(NES_DBG_CQ, "Unable to allocate nes_cq struct\n");
1565 return ERR_PTR(-ENOMEM);
1566 }
1567
1568 nescq->hw_cq.cq_size = max(entries + 1, 5);
1569 nescq->hw_cq.cq_number = cq_num;
1570 nescq->ibcq.cqe = nescq->hw_cq.cq_size - 1;
1571
1572
1573 if (context) {
1574 nes_ucontext = to_nesucontext(context);
1575 if (ib_copy_from_udata(&req, udata, sizeof (struct nes_create_cq_req))) {
1576 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1577 kfree(nescq);
1578 return ERR_PTR(-EFAULT);
1579 }
1580 nesvnic->mcrq_ucontext = nes_ucontext;
1581 nes_ucontext->mcrqf = req.mcrqf;
1582 if (nes_ucontext->mcrqf) {
1583 if (nes_ucontext->mcrqf & 0x80000000)
Vadim Makhervaks2e369542008-11-02 21:39:17 -08001584 nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 28 + 2 * ((nes_ucontext->mcrqf & 0xf) - 1);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001585 else if (nes_ucontext->mcrqf & 0x40000000)
1586 nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff;
1587 else
1588 nescq->hw_cq.cq_number = nesvnic->mcrq_qp_id + nes_ucontext->mcrqf-1;
Miroslaw Walukiewicz5d1af5c2009-04-21 16:16:48 -07001589 nescq->mcrqf = nes_ucontext->mcrqf;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001590 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1591 }
1592 nes_debug(NES_DBG_CQ, "CQ Virtual Address = %08lX, size = %u.\n",
1593 (unsigned long)req.user_cq_buffer, entries);
Chien Tung9300c0c2008-02-21 07:51:17 -06001594 err = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001595 list_for_each_entry(nespbl, &nes_ucontext->cq_reg_mem_list, list) {
1596 if (nespbl->user_base == (unsigned long )req.user_cq_buffer) {
1597 list_del(&nespbl->list);
1598 err = 0;
1599 nes_debug(NES_DBG_CQ, "Found PBL for virtual CQ. nespbl=%p.\n",
1600 nespbl);
1601 break;
1602 }
1603 }
1604 if (err) {
1605 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1606 kfree(nescq);
Chien Tung9300c0c2008-02-21 07:51:17 -06001607 return ERR_PTR(-EFAULT);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001608 }
1609
1610 pbl_entries = nespbl->pbl_size >> 3;
1611 nescq->cq_mem_size = 0;
1612 } else {
1613 nescq->cq_mem_size = nescq->hw_cq.cq_size * sizeof(struct nes_hw_cqe);
1614 nes_debug(NES_DBG_CQ, "Attempting to allocate pci memory (%u entries, %u bytes) for CQ%u.\n",
1615 entries, nescq->cq_mem_size, nescq->hw_cq.cq_number);
1616
1617 /* allocate the physical buffer space */
Joe Perches9011a672014-08-08 14:24:16 -07001618 mem = pci_zalloc_consistent(nesdev->pcidev, nescq->cq_mem_size,
1619 &nescq->hw_cq.cq_pbase);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001620 if (!mem) {
1621 printk(KERN_ERR PFX "Unable to allocate pci memory for cq\n");
1622 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1623 kfree(nescq);
1624 return ERR_PTR(-ENOMEM);
1625 }
1626
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001627 nescq->hw_cq.cq_vbase = mem;
1628 nescq->hw_cq.cq_head = 0;
1629 nes_debug(NES_DBG_CQ, "CQ%u virtual address @ %p, phys = 0x%08X\n",
1630 nescq->hw_cq.cq_number, nescq->hw_cq.cq_vbase,
1631 (u32)nescq->hw_cq.cq_pbase);
1632 }
1633
1634 nescq->hw_cq.ce_handler = nes_iwarp_ce_handler;
1635 spin_lock_init(&nescq->lock);
1636
1637 /* send CreateCQ request to CQP */
1638 cqp_request = nes_get_cqp_request(nesdev);
1639 if (cqp_request == NULL) {
1640 nes_debug(NES_DBG_CQ, "Failed to get a cqp_request.\n");
1641 if (!context)
1642 pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
1643 nescq->hw_cq.cq_pbase);
Miroslaw Walukiewicz5d1af5c2009-04-21 16:16:48 -07001644 else {
1645 pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,
1646 nespbl->pbl_vbase, nespbl->pbl_pbase);
1647 kfree(nespbl);
1648 }
1649
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001650 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1651 kfree(nescq);
1652 return ERR_PTR(-ENOMEM);
1653 }
1654 cqp_request->waiting = 1;
1655 cqp_wqe = &cqp_request->cqp_wqe;
1656
1657 opcode = NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
1658 NES_CQP_CQ_CHK_OVERFLOW |
1659 NES_CQP_CQ_CEQE_MASK | ((u32)nescq->hw_cq.cq_size << 16);
1660
1661 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
1662
1663 if (pbl_entries != 1) {
1664 if (pbl_entries > 32) {
1665 /* use 4k pbl */
1666 nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 4k PBL\n", pbl_entries);
1667 if (nesadapter->free_4kpbl == 0) {
Faisal Latifc5d321e2008-11-21 20:50:38 -06001668 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
1669 nes_free_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001670 if (!context)
1671 pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
1672 nescq->hw_cq.cq_pbase);
Miroslaw Walukiewicz5d1af5c2009-04-21 16:16:48 -07001673 else {
1674 pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,
1675 nespbl->pbl_vbase, nespbl->pbl_pbase);
1676 kfree(nespbl);
1677 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001678 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1679 kfree(nescq);
1680 return ERR_PTR(-ENOMEM);
1681 } else {
1682 opcode |= (NES_CQP_CQ_VIRT | NES_CQP_CQ_4KB_CHUNK);
1683 nescq->virtual_cq = 2;
1684 nesadapter->free_4kpbl--;
1685 }
1686 } else {
1687 /* use 256 byte pbl */
1688 nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 256 byte PBL\n", pbl_entries);
1689 if (nesadapter->free_256pbl == 0) {
Faisal Latifc5d321e2008-11-21 20:50:38 -06001690 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
1691 nes_free_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001692 if (!context)
1693 pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
1694 nescq->hw_cq.cq_pbase);
Miroslaw Walukiewicz5d1af5c2009-04-21 16:16:48 -07001695 else {
1696 pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,
1697 nespbl->pbl_vbase, nespbl->pbl_pbase);
1698 kfree(nespbl);
1699 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001700 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1701 kfree(nescq);
1702 return ERR_PTR(-ENOMEM);
1703 } else {
1704 opcode |= NES_CQP_CQ_VIRT;
1705 nescq->virtual_cq = 1;
1706 nesadapter->free_256pbl--;
1707 }
1708 }
1709 }
1710
1711 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
1712
1713 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1714 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
1715 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1716 (nescq->hw_cq.cq_number | ((u32)nesdev->ceq_index << 16)));
1717
1718 if (context) {
1719 if (pbl_entries != 1)
1720 u64temp = (u64)nespbl->pbl_pbase;
1721 else
1722 u64temp = le64_to_cpu(nespbl->pbl_vbase[0]);
1723 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX,
1724 nes_ucontext->mmap_db_index[0]);
1725 } else {
1726 u64temp = (u64)nescq->hw_cq.cq_pbase;
1727 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
1728 }
1729 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
1730 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
1731 u64temp = (u64)(unsigned long)&nescq->hw_cq;
1732 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] =
1733 cpu_to_le32((u32)(u64temp >> 1));
1734 cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
1735 cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
1736
1737 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -07001738 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001739
1740 /* Wait for CQP */
1741 nes_debug(NES_DBG_CQ, "Waiting for create iWARP CQ%u to complete.\n",
1742 nescq->hw_cq.cq_number);
1743 ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),
1744 NES_EVENT_TIMEOUT * 2);
1745 nes_debug(NES_DBG_CQ, "Create iWARP CQ%u completed, wait_event_timeout ret = %d.\n",
1746 nescq->hw_cq.cq_number, ret);
1747 if ((!ret) || (cqp_request->major_code)) {
Roland Dreier1ff66e82008-07-14 23:48:49 -07001748 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001749 if (!context)
1750 pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
1751 nescq->hw_cq.cq_pbase);
Miroslaw Walukiewicz5d1af5c2009-04-21 16:16:48 -07001752 else {
1753 pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,
1754 nespbl->pbl_vbase, nespbl->pbl_pbase);
1755 kfree(nespbl);
1756 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001757 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1758 kfree(nescq);
1759 return ERR_PTR(-EIO);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001760 }
Roland Dreier1ff66e82008-07-14 23:48:49 -07001761 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001762
1763 if (context) {
1764 /* free the nespbl */
1765 pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
1766 nespbl->pbl_pbase);
1767 kfree(nespbl);
1768 resp.cq_id = nescq->hw_cq.cq_number;
1769 resp.cq_size = nescq->hw_cq.cq_size;
1770 resp.mmap_db_index = 0;
Dan Carpenter60429632013-07-25 20:04:59 +03001771 if (ib_copy_to_udata(udata, &resp, sizeof resp - sizeof resp.reserved)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001772 nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
1773 kfree(nescq);
1774 return ERR_PTR(-EFAULT);
1775 }
1776 }
1777
1778 return &nescq->ibcq;
1779}
1780
1781
1782/**
1783 * nes_destroy_cq
1784 */
1785static int nes_destroy_cq(struct ib_cq *ib_cq)
1786{
1787 struct nes_cq *nescq;
1788 struct nes_device *nesdev;
1789 struct nes_vnic *nesvnic;
1790 struct nes_adapter *nesadapter;
1791 struct nes_hw_cqp_wqe *cqp_wqe;
1792 struct nes_cqp_request *cqp_request;
1793 unsigned long flags;
1794 u32 opcode = 0;
1795 int ret;
1796
1797 if (ib_cq == NULL)
1798 return 0;
1799
1800 nescq = to_nescq(ib_cq);
1801 nesvnic = to_nesvnic(ib_cq->device);
1802 nesdev = nesvnic->nesdev;
1803 nesadapter = nesdev->nesadapter;
1804
1805 nes_debug(NES_DBG_CQ, "Destroy CQ%u\n", nescq->hw_cq.cq_number);
1806
1807 /* Send DestroyCQ request to CQP */
1808 cqp_request = nes_get_cqp_request(nesdev);
1809 if (cqp_request == NULL) {
1810 nes_debug(NES_DBG_CQ, "Failed to get a cqp_request.\n");
1811 return -ENOMEM;
1812 }
1813 cqp_request->waiting = 1;
1814 cqp_wqe = &cqp_request->cqp_wqe;
1815 opcode = NES_CQP_DESTROY_CQ | (nescq->hw_cq.cq_size << 16);
1816 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
1817 if (nescq->virtual_cq == 1) {
1818 nesadapter->free_256pbl++;
1819 if (nesadapter->free_256pbl > nesadapter->max_256pbl) {
1820 printk(KERN_ERR PFX "%s: free 256B PBLs(%u) has exceeded the max(%u)\n",
Harvey Harrison33718362008-04-16 21:01:10 -07001821 __func__, nesadapter->free_256pbl, nesadapter->max_256pbl);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001822 }
1823 } else if (nescq->virtual_cq == 2) {
1824 nesadapter->free_4kpbl++;
1825 if (nesadapter->free_4kpbl > nesadapter->max_4kpbl) {
1826 printk(KERN_ERR PFX "%s: free 4K PBLs(%u) has exceeded the max(%u)\n",
Harvey Harrison33718362008-04-16 21:01:10 -07001827 __func__, nesadapter->free_4kpbl, nesadapter->max_4kpbl);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001828 }
1829 opcode |= NES_CQP_CQ_4KB_CHUNK;
1830 }
1831
1832 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
1833
1834 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
1835 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
1836 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
1837 (nescq->hw_cq.cq_number | ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 16)));
Miroslaw Walukiewicz5d1af5c2009-04-21 16:16:48 -07001838 if (!nescq->mcrqf)
1839 nes_free_resource(nesadapter, nesadapter->allocated_cqs, nescq->hw_cq.cq_number);
1840
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001841 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -07001842 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001843
1844 /* Wait for CQP */
1845 nes_debug(NES_DBG_CQ, "Waiting for destroy iWARP CQ%u to complete.\n",
1846 nescq->hw_cq.cq_number);
1847 ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),
1848 NES_EVENT_TIMEOUT);
1849 nes_debug(NES_DBG_CQ, "Destroy iWARP CQ%u completed, wait_event_timeout ret = %u,"
1850 " CQP Major:Minor codes = 0x%04X:0x%04X.\n",
1851 nescq->hw_cq.cq_number, ret, cqp_request->major_code,
1852 cqp_request->minor_code);
Roland Dreier1ff66e82008-07-14 23:48:49 -07001853 if (!ret) {
1854 nes_debug(NES_DBG_CQ, "iWARP CQ%u destroy timeout expired\n",
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001855 nescq->hw_cq.cq_number);
Roland Dreier1ff66e82008-07-14 23:48:49 -07001856 ret = -ETIME;
1857 } else if (cqp_request->major_code) {
1858 nes_debug(NES_DBG_CQ, "iWARP CQ%u destroy failed\n",
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001859 nescq->hw_cq.cq_number);
Roland Dreier1ff66e82008-07-14 23:48:49 -07001860 ret = -EIO;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001861 } else {
1862 ret = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001863 }
Roland Dreier1ff66e82008-07-14 23:48:49 -07001864 nes_put_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001865
1866 if (nescq->cq_mem_size)
1867 pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size,
Roland Dreier31d1e342008-04-23 11:55:45 -07001868 nescq->hw_cq.cq_vbase, nescq->hw_cq.cq_pbase);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001869 kfree(nescq);
1870
1871 return ret;
1872}
1873
Don Wood0145f342009-03-06 15:15:00 -08001874/**
1875 * root_256
1876 */
1877static u32 root_256(struct nes_device *nesdev,
1878 struct nes_root_vpbl *root_vpbl,
1879 struct nes_root_vpbl *new_root,
Matt Kraaicc005fa2009-04-21 10:43:21 -07001880 u16 pbl_count_4k)
Don Wood0145f342009-03-06 15:15:00 -08001881{
1882 u64 leaf_pbl;
1883 int i, j, k;
1884
1885 if (pbl_count_4k == 1) {
1886 new_root->pbl_vbase = pci_alloc_consistent(nesdev->pcidev,
1887 512, &new_root->pbl_pbase);
1888
1889 if (new_root->pbl_vbase == NULL)
1890 return 0;
1891
1892 leaf_pbl = (u64)root_vpbl->pbl_pbase;
1893 for (i = 0; i < 16; i++) {
1894 new_root->pbl_vbase[i].pa_low =
1895 cpu_to_le32((u32)leaf_pbl);
1896 new_root->pbl_vbase[i].pa_high =
1897 cpu_to_le32((u32)((((u64)leaf_pbl) >> 32)));
1898 leaf_pbl += 256;
1899 }
1900 } else {
1901 for (i = 3; i >= 0; i--) {
1902 j = i * 16;
1903 root_vpbl->pbl_vbase[j] = root_vpbl->pbl_vbase[i];
1904 leaf_pbl = le32_to_cpu(root_vpbl->pbl_vbase[j].pa_low) +
1905 (((u64)le32_to_cpu(root_vpbl->pbl_vbase[j].pa_high))
1906 << 32);
1907 for (k = 1; k < 16; k++) {
1908 leaf_pbl += 256;
1909 root_vpbl->pbl_vbase[j + k].pa_low =
1910 cpu_to_le32((u32)leaf_pbl);
1911 root_vpbl->pbl_vbase[j + k].pa_high =
1912 cpu_to_le32((u32)((((u64)leaf_pbl) >> 32)));
1913 }
1914 }
1915 }
1916
1917 return 1;
1918}
1919
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001920
1921/**
1922 * nes_reg_mr
1923 */
1924static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,
1925 u32 stag, u64 region_length, struct nes_root_vpbl *root_vpbl,
Don Wood0145f342009-03-06 15:15:00 -08001926 dma_addr_t single_buffer, u16 pbl_count_4k,
1927 u16 residual_page_count_4k, int acc, u64 *iova_start,
1928 u16 *actual_pbl_cnt, u8 *used_4k_pbls)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001929{
1930 struct nes_hw_cqp_wqe *cqp_wqe;
1931 struct nes_cqp_request *cqp_request;
1932 unsigned long flags;
1933 int ret;
1934 struct nes_adapter *nesadapter = nesdev->nesadapter;
Don Wood0145f342009-03-06 15:15:00 -08001935 uint pg_cnt = 0;
Chien Tung1af92222009-04-20 14:50:36 -07001936 u16 pbl_count_256 = 0;
Don Wood0145f342009-03-06 15:15:00 -08001937 u16 pbl_count = 0;
1938 u8 use_256_pbls = 0;
1939 u8 use_4k_pbls = 0;
1940 u16 use_two_level = (pbl_count_4k > 1) ? 1 : 0;
Or Gerlitz812d8672010-07-20 12:00:20 +00001941 struct nes_root_vpbl new_root = { 0, NULL, NULL };
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001942 u32 opcode = 0;
1943 u16 major_code;
1944
1945 /* Register the region with the adapter */
1946 cqp_request = nes_get_cqp_request(nesdev);
1947 if (cqp_request == NULL) {
1948 nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");
1949 return -ENOMEM;
1950 }
1951 cqp_request->waiting = 1;
1952 cqp_wqe = &cqp_request->cqp_wqe;
1953
Don Wood0145f342009-03-06 15:15:00 -08001954 if (pbl_count_4k) {
1955 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
1956
1957 pg_cnt = ((pbl_count_4k - 1) * 512) + residual_page_count_4k;
1958 pbl_count_256 = (pg_cnt + 31) / 32;
1959 if (pg_cnt <= 32) {
1960 if (pbl_count_256 <= nesadapter->free_256pbl)
1961 use_256_pbls = 1;
1962 else if (pbl_count_4k <= nesadapter->free_4kpbl)
1963 use_4k_pbls = 1;
1964 } else if (pg_cnt <= 2048) {
1965 if (((pbl_count_4k + use_two_level) <= nesadapter->free_4kpbl) &&
1966 (nesadapter->free_4kpbl > (nesadapter->max_4kpbl >> 1))) {
1967 use_4k_pbls = 1;
1968 } else if ((pbl_count_256 + 1) <= nesadapter->free_256pbl) {
1969 use_256_pbls = 1;
1970 use_two_level = 1;
1971 } else if ((pbl_count_4k + use_two_level) <= nesadapter->free_4kpbl) {
1972 use_4k_pbls = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001973 }
1974 } else {
Don Wood0145f342009-03-06 15:15:00 -08001975 if ((pbl_count_4k + 1) <= nesadapter->free_4kpbl)
1976 use_4k_pbls = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001977 }
Don Wood0145f342009-03-06 15:15:00 -08001978
1979 if (use_256_pbls) {
1980 pbl_count = pbl_count_256;
1981 nesadapter->free_256pbl -= pbl_count + use_two_level;
1982 } else if (use_4k_pbls) {
1983 pbl_count = pbl_count_4k;
1984 nesadapter->free_4kpbl -= pbl_count + use_two_level;
1985 } else {
1986 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
1987 nes_debug(NES_DBG_MR, "Out of Pbls\n");
1988 nes_free_cqp_request(nesdev, cqp_request);
1989 return -ENOMEM;
1990 }
1991
1992 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001993 }
1994
Don Wood0145f342009-03-06 15:15:00 -08001995 if (use_256_pbls && use_two_level) {
Matt Kraaicc005fa2009-04-21 10:43:21 -07001996 if (root_256(nesdev, root_vpbl, &new_root, pbl_count_4k) == 1) {
Don Wood0145f342009-03-06 15:15:00 -08001997 if (new_root.pbl_pbase != 0)
1998 root_vpbl = &new_root;
1999 } else {
2000 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
2001 nesadapter->free_256pbl += pbl_count_256 + use_two_level;
2002 use_256_pbls = 0;
2003
2004 if (pbl_count_4k == 1)
2005 use_two_level = 0;
2006 pbl_count = pbl_count_4k;
2007
2008 if ((pbl_count_4k + use_two_level) <= nesadapter->free_4kpbl) {
2009 nesadapter->free_4kpbl -= pbl_count + use_two_level;
2010 use_4k_pbls = 1;
2011 }
2012 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
2013
2014 if (use_4k_pbls == 0)
2015 return -ENOMEM;
2016 }
2017 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002018
2019 opcode = NES_CQP_REGISTER_STAG | NES_CQP_STAG_RIGHTS_LOCAL_READ |
2020 NES_CQP_STAG_VA_TO | NES_CQP_STAG_MR;
2021 if (acc & IB_ACCESS_LOCAL_WRITE)
2022 opcode |= NES_CQP_STAG_RIGHTS_LOCAL_WRITE;
2023 if (acc & IB_ACCESS_REMOTE_WRITE)
2024 opcode |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_REM_ACC_EN;
2025 if (acc & IB_ACCESS_REMOTE_READ)
2026 opcode |= NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_REM_ACC_EN;
2027 if (acc & IB_ACCESS_MW_BIND)
2028 opcode |= NES_CQP_STAG_RIGHTS_WINDOW_BIND | NES_CQP_STAG_REM_ACC_EN;
2029
2030 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
2031 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
2032 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_VA_LOW_IDX, *iova_start);
2033 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_LOW_IDX, region_length);
2034
2035 cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] =
2036 cpu_to_le32((u32)(region_length >> 8) & 0xff000000);
2037 cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] |=
2038 cpu_to_le32(nespd->pd_id & 0x00007fff);
2039 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);
2040
2041 if (pbl_count == 0) {
2042 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, single_buffer);
2043 } else {
2044 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, root_vpbl->pbl_pbase);
2045 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX, pbl_count);
Don Wood0145f342009-03-06 15:15:00 -08002046 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_LEN_IDX, (pg_cnt * 8));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002047
Don Wood0145f342009-03-06 15:15:00 -08002048 if (use_4k_pbls)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002049 cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_STAG_PBL_BLK_SIZE);
2050 }
2051 barrier();
2052
2053 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -07002054 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002055
2056 /* Wait for CQP */
2057 ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),
2058 NES_EVENT_TIMEOUT);
2059 nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u,"
2060 " CQP Major:Minor codes = 0x%04X:0x%04X.\n",
2061 stag, ret, cqp_request->major_code, cqp_request->minor_code);
2062 major_code = cqp_request->major_code;
Roland Dreier1ff66e82008-07-14 23:48:49 -07002063 nes_put_cqp_request(nesdev, cqp_request);
2064
Don Wooddae5d132009-03-06 15:12:09 -08002065 if ((!ret || major_code) && pbl_count != 0) {
2066 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
Don Wood0145f342009-03-06 15:15:00 -08002067 if (use_256_pbls)
2068 nesadapter->free_256pbl += pbl_count + use_two_level;
2069 else if (use_4k_pbls)
2070 nesadapter->free_4kpbl += pbl_count + use_two_level;
Don Wooddae5d132009-03-06 15:12:09 -08002071 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
2072 }
Don Wood0145f342009-03-06 15:15:00 -08002073 if (new_root.pbl_pbase)
2074 pci_free_consistent(nesdev->pcidev, 512, new_root.pbl_vbase,
2075 new_root.pbl_pbase);
2076
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002077 if (!ret)
2078 return -ETIME;
2079 else if (major_code)
2080 return -EIO;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002081
Don Wood0145f342009-03-06 15:15:00 -08002082 *actual_pbl_cnt = pbl_count + use_two_level;
2083 *used_4k_pbls = use_4k_pbls;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002084 return 0;
2085}
2086
2087
2088/**
2089 * nes_reg_phys_mr
2090 */
2091static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
2092 struct ib_phys_buf *buffer_list, int num_phys_buf, int acc,
2093 u64 * iova_start)
2094{
2095 u64 region_length;
2096 struct nes_pd *nespd = to_nespd(ib_pd);
2097 struct nes_vnic *nesvnic = to_nesvnic(ib_pd->device);
2098 struct nes_device *nesdev = nesvnic->nesdev;
2099 struct nes_adapter *nesadapter = nesdev->nesadapter;
2100 struct nes_mr *nesmr;
2101 struct ib_mr *ibmr;
2102 struct nes_vpbl vpbl;
2103 struct nes_root_vpbl root_vpbl;
2104 u32 stag;
2105 u32 i;
Don Wood3f32eb12009-04-20 14:53:00 -07002106 unsigned long mask;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002107 u32 stag_index = 0;
2108 u32 next_stag_index = 0;
2109 u32 driver_key = 0;
2110 u32 root_pbl_index = 0;
2111 u32 cur_pbl_index = 0;
Roland Dreier69d51022010-08-04 14:25:40 -07002112 int err = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002113 int ret = 0;
2114 u16 pbl_count = 0;
2115 u8 single_page = 1;
2116 u8 stag_key = 0;
2117
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002118 region_length = 0;
2119 vpbl.pbl_vbase = NULL;
2120 root_vpbl.pbl_vbase = NULL;
2121 root_vpbl.pbl_pbase = 0;
2122
2123 get_random_bytes(&next_stag_index, sizeof(next_stag_index));
2124 stag_key = (u8)next_stag_index;
2125
2126 driver_key = 0;
2127
2128 next_stag_index >>= 8;
2129 next_stag_index %= nesadapter->max_mr;
2130 if (num_phys_buf > (1024*512)) {
2131 return ERR_PTR(-E2BIG);
2132 }
2133
Don Wood3f32eb12009-04-20 14:53:00 -07002134 if ((buffer_list[0].addr ^ *iova_start) & ~PAGE_MASK)
2135 return ERR_PTR(-EINVAL);
2136
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002137 err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr,
Tatyana Nikolova81821642012-09-20 21:08:04 +00002138 &stag_index, &next_stag_index, NES_RESOURCE_PHYS_MR);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002139 if (err) {
2140 return ERR_PTR(err);
2141 }
2142
2143 nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
2144 if (!nesmr) {
2145 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
2146 return ERR_PTR(-ENOMEM);
2147 }
2148
2149 for (i = 0; i < num_phys_buf; i++) {
2150
2151 if ((i & 0x01FF) == 0) {
2152 if (root_pbl_index == 1) {
2153 /* Allocate the root PBL */
2154 root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 8192,
2155 &root_vpbl.pbl_pbase);
2156 nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n",
2157 root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase);
2158 if (!root_vpbl.pbl_vbase) {
2159 pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
2160 vpbl.pbl_pbase);
2161 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
2162 kfree(nesmr);
2163 return ERR_PTR(-ENOMEM);
2164 }
2165 root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, GFP_KERNEL);
2166 if (!root_vpbl.leaf_vpbl) {
2167 pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,
2168 root_vpbl.pbl_pbase);
2169 pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
2170 vpbl.pbl_pbase);
2171 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
2172 kfree(nesmr);
2173 return ERR_PTR(-ENOMEM);
2174 }
2175 root_vpbl.pbl_vbase[0].pa_low = cpu_to_le32((u32)vpbl.pbl_pbase);
2176 root_vpbl.pbl_vbase[0].pa_high =
2177 cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32)));
2178 root_vpbl.leaf_vpbl[0] = vpbl;
2179 }
2180 /* Allocate a 4K buffer for the PBL */
2181 vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,
2182 &vpbl.pbl_pbase);
2183 nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%016lX\n",
2184 vpbl.pbl_vbase, (unsigned long)vpbl.pbl_pbase);
2185 if (!vpbl.pbl_vbase) {
2186 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
2187 ibmr = ERR_PTR(-ENOMEM);
2188 kfree(nesmr);
2189 goto reg_phys_err;
2190 }
2191 /* Fill in the root table */
2192 if (1 <= root_pbl_index) {
2193 root_vpbl.pbl_vbase[root_pbl_index].pa_low =
2194 cpu_to_le32((u32)vpbl.pbl_pbase);
2195 root_vpbl.pbl_vbase[root_pbl_index].pa_high =
2196 cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32)));
2197 root_vpbl.leaf_vpbl[root_pbl_index] = vpbl;
2198 }
2199 root_pbl_index++;
2200 cur_pbl_index = 0;
2201 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002202
Don Wood3f32eb12009-04-20 14:53:00 -07002203 mask = !buffer_list[i].size;
2204 if (i != 0)
2205 mask |= buffer_list[i].addr;
2206 if (i != num_phys_buf - 1)
2207 mask |= buffer_list[i].addr + buffer_list[i].size;
2208
2209 if (mask & ~PAGE_MASK) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002210 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
Don Wood3f32eb12009-04-20 14:53:00 -07002211 nes_debug(NES_DBG_MR, "Invalid buffer addr or size\n");
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002212 ibmr = ERR_PTR(-EINVAL);
2213 kfree(nesmr);
2214 goto reg_phys_err;
2215 }
2216
2217 region_length += buffer_list[i].size;
2218 if ((i != 0) && (single_page)) {
2219 if ((buffer_list[i-1].addr+PAGE_SIZE) != buffer_list[i].addr)
2220 single_page = 0;
2221 }
Don Wood3f32eb12009-04-20 14:53:00 -07002222 vpbl.pbl_vbase[cur_pbl_index].pa_low = cpu_to_le32((u32)buffer_list[i].addr & PAGE_MASK);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002223 vpbl.pbl_vbase[cur_pbl_index++].pa_high =
2224 cpu_to_le32((u32)((((u64)buffer_list[i].addr) >> 32)));
2225 }
2226
2227 stag = stag_index << 8;
2228 stag |= driver_key;
2229 stag += (u32)stag_key;
2230
2231 nes_debug(NES_DBG_MR, "Registering STag 0x%08X, VA = 0x%016lX,"
2232 " length = 0x%016lX, index = 0x%08X\n",
2233 stag, (unsigned long)*iova_start, (unsigned long)region_length, stag_index);
2234
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002235 /* Make the leaf PBL the root if only one PBL */
2236 if (root_pbl_index == 1) {
2237 root_vpbl.pbl_pbase = vpbl.pbl_pbase;
2238 }
2239
2240 if (single_page) {
2241 pbl_count = 0;
2242 } else {
2243 pbl_count = root_pbl_index;
2244 }
2245 ret = nes_reg_mr(nesdev, nespd, stag, region_length, &root_vpbl,
Don Wood0145f342009-03-06 15:15:00 -08002246 buffer_list[0].addr, pbl_count, (u16)cur_pbl_index, acc, iova_start,
2247 &nesmr->pbls_used, &nesmr->pbl_4k);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002248
2249 if (ret == 0) {
2250 nesmr->ibmr.rkey = stag;
2251 nesmr->ibmr.lkey = stag;
2252 nesmr->mode = IWNES_MEMREG_TYPE_MEM;
2253 ibmr = &nesmr->ibmr;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002254 } else {
2255 kfree(nesmr);
2256 ibmr = ERR_PTR(-ENOMEM);
2257 }
2258
2259 reg_phys_err:
2260 /* free the resources */
2261 if (root_pbl_index == 1) {
2262 /* single PBL case */
2263 pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, vpbl.pbl_pbase);
2264 } else {
2265 for (i=0; i<root_pbl_index; i++) {
2266 pci_free_consistent(nesdev->pcidev, 4096, root_vpbl.leaf_vpbl[i].pbl_vbase,
2267 root_vpbl.leaf_vpbl[i].pbl_pbase);
2268 }
2269 kfree(root_vpbl.leaf_vpbl);
2270 pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,
2271 root_vpbl.pbl_pbase);
2272 }
2273
2274 return ibmr;
2275}
2276
2277
2278/**
2279 * nes_get_dma_mr
2280 */
2281static struct ib_mr *nes_get_dma_mr(struct ib_pd *pd, int acc)
2282{
2283 struct ib_phys_buf bl;
2284 u64 kva = 0;
2285
2286 nes_debug(NES_DBG_MR, "\n");
2287
2288 bl.size = (u64)0xffffffffffULL;
2289 bl.addr = 0;
2290 return nes_reg_phys_mr(pd, &bl, 1, acc, &kva);
2291}
2292
2293
2294/**
2295 * nes_reg_user_mr
2296 */
2297static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
2298 u64 virt, int acc, struct ib_udata *udata)
2299{
2300 u64 iova_start;
2301 __le64 *pbl;
2302 u64 region_length;
2303 dma_addr_t last_dma_addr = 0;
2304 dma_addr_t first_dma_addr = 0;
2305 struct nes_pd *nespd = to_nespd(pd);
2306 struct nes_vnic *nesvnic = to_nesvnic(pd->device);
2307 struct nes_device *nesdev = nesvnic->nesdev;
2308 struct nes_adapter *nesadapter = nesdev->nesadapter;
2309 struct ib_mr *ibmr = ERR_PTR(-EINVAL);
Yishai Hadaseeb84612014-01-28 13:40:15 +02002310 struct scatterlist *sg;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002311 struct nes_ucontext *nes_ucontext;
2312 struct nes_pbl *nespbl;
2313 struct nes_mr *nesmr;
2314 struct ib_umem *region;
2315 struct nes_mem_reg_req req;
2316 struct nes_vpbl vpbl;
2317 struct nes_root_vpbl root_vpbl;
Yishai Hadaseeb84612014-01-28 13:40:15 +02002318 int entry, page_index;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002319 int page_count = 0;
2320 int err, pbl_depth = 0;
2321 int chunk_pages;
2322 int ret;
2323 u32 stag;
2324 u32 stag_index = 0;
2325 u32 next_stag_index;
2326 u32 driver_key;
2327 u32 root_pbl_index = 0;
2328 u32 cur_pbl_index = 0;
2329 u32 skip_pages;
2330 u16 pbl_count;
2331 u8 single_page = 1;
2332 u8 stag_key;
Yishai Hadaseeb84612014-01-28 13:40:15 +02002333 int first_page = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002334
Arthur Kepnercb9fbc52008-04-29 01:00:34 -07002335 region = ib_umem_get(pd->uobject->context, start, length, acc, 0);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002336 if (IS_ERR(region)) {
2337 return (struct ib_mr *)region;
2338 }
2339
2340 nes_debug(NES_DBG_MR, "User base = 0x%lX, Virt base = 0x%lX, length = %u,"
2341 " offset = %u, page size = %u.\n",
2342 (unsigned long int)start, (unsigned long int)virt, (u32)length,
Haggai Eran406f9e52014-12-11 17:04:12 +02002343 ib_umem_offset(region), region->page_size);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002344
Haggai Eran406f9e52014-12-11 17:04:12 +02002345 skip_pages = ((u32)ib_umem_offset(region)) >> 12;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002346
Julia Lawalle2e435f2011-10-06 09:33:24 -07002347 if (ib_copy_from_udata(&req, udata, sizeof(req))) {
2348 ib_umem_release(region);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002349 return ERR_PTR(-EFAULT);
Julia Lawalle2e435f2011-10-06 09:33:24 -07002350 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002351 nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type);
2352
2353 switch (req.reg_type) {
2354 case IWNES_MEMREG_TYPE_MEM:
2355 pbl_depth = 0;
2356 region_length = 0;
2357 vpbl.pbl_vbase = NULL;
2358 root_vpbl.pbl_vbase = NULL;
2359 root_vpbl.pbl_pbase = 0;
2360
2361 get_random_bytes(&next_stag_index, sizeof(next_stag_index));
2362 stag_key = (u8)next_stag_index;
2363
2364 driver_key = next_stag_index & 0x70000000;
2365
2366 next_stag_index >>= 8;
2367 next_stag_index %= nesadapter->max_mr;
2368
2369 err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
Tatyana Nikolova81821642012-09-20 21:08:04 +00002370 nesadapter->max_mr, &stag_index, &next_stag_index, NES_RESOURCE_USER_MR);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002371 if (err) {
2372 ib_umem_release(region);
2373 return ERR_PTR(err);
2374 }
2375
2376 nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
2377 if (!nesmr) {
2378 ib_umem_release(region);
2379 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
2380 return ERR_PTR(-ENOMEM);
2381 }
2382 nesmr->region = region;
2383
Yishai Hadaseeb84612014-01-28 13:40:15 +02002384 for_each_sg(region->sg_head.sgl, sg, region->nmap, entry) {
2385 if (sg_dma_address(sg) & ~PAGE_MASK) {
2386 ib_umem_release(region);
2387 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
2388 nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n",
2389 (unsigned int) sg_dma_address(sg));
2390 ibmr = ERR_PTR(-EINVAL);
2391 kfree(nesmr);
2392 goto reg_user_mr_err;
2393 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002394
Yishai Hadaseeb84612014-01-28 13:40:15 +02002395 if (!sg_dma_len(sg)) {
2396 ib_umem_release(region);
2397 nes_free_resource(nesadapter, nesadapter->allocated_mrs,
2398 stag_index);
2399 nes_debug(NES_DBG_MR, "Invalid Buffer Size\n");
2400 ibmr = ERR_PTR(-EINVAL);
2401 kfree(nesmr);
2402 goto reg_user_mr_err;
2403 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002404
Yishai Hadaseeb84612014-01-28 13:40:15 +02002405 region_length += sg_dma_len(sg);
2406 chunk_pages = sg_dma_len(sg) >> 12;
2407 region_length -= skip_pages << 12;
2408 for (page_index = skip_pages; page_index < chunk_pages; page_index++) {
2409 skip_pages = 0;
Haggai Eran406f9e52014-12-11 17:04:12 +02002410 if ((page_count != 0) && (page_count << 12) - (ib_umem_offset(region) & (4096 - 1)) >= region->length)
Yishai Hadaseeb84612014-01-28 13:40:15 +02002411 goto enough_pages;
2412 if ((page_count&0x01FF) == 0) {
2413 if (page_count >= 1024 * 512) {
2414 ib_umem_release(region);
2415 nes_free_resource(nesadapter,
2416 nesadapter->allocated_mrs, stag_index);
2417 kfree(nesmr);
2418 ibmr = ERR_PTR(-E2BIG);
2419 goto reg_user_mr_err;
2420 }
2421 if (root_pbl_index == 1) {
2422 root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev,
2423 8192, &root_vpbl.pbl_pbase);
2424 nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n",
2425 root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase);
2426 if (!root_vpbl.pbl_vbase) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002427 ib_umem_release(region);
Yishai Hadaseeb84612014-01-28 13:40:15 +02002428 pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
2429 vpbl.pbl_pbase);
2430 nes_free_resource(nesadapter, nesadapter->allocated_mrs,
2431 stag_index);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002432 kfree(nesmr);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002433 ibmr = ERR_PTR(-ENOMEM);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002434 goto reg_user_mr_err;
2435 }
Yishai Hadaseeb84612014-01-28 13:40:15 +02002436 root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024,
2437 GFP_KERNEL);
2438 if (!root_vpbl.leaf_vpbl) {
2439 ib_umem_release(region);
2440 pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,
2441 root_vpbl.pbl_pbase);
2442 pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
2443 vpbl.pbl_pbase);
2444 nes_free_resource(nesadapter, nesadapter->allocated_mrs,
2445 stag_index);
2446 kfree(nesmr);
2447 ibmr = ERR_PTR(-ENOMEM);
2448 goto reg_user_mr_err;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002449 }
Yishai Hadaseeb84612014-01-28 13:40:15 +02002450 root_vpbl.pbl_vbase[0].pa_low =
2451 cpu_to_le32((u32)vpbl.pbl_pbase);
2452 root_vpbl.pbl_vbase[0].pa_high =
2453 cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32)));
2454 root_vpbl.leaf_vpbl[0] = vpbl;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002455 }
Yishai Hadaseeb84612014-01-28 13:40:15 +02002456 vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,
2457 &vpbl.pbl_pbase);
2458 nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%08X\n",
2459 vpbl.pbl_vbase, (unsigned int)vpbl.pbl_pbase);
2460 if (!vpbl.pbl_vbase) {
2461 ib_umem_release(region);
2462 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
2463 ibmr = ERR_PTR(-ENOMEM);
2464 kfree(nesmr);
2465 goto reg_user_mr_err;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002466 }
Yishai Hadaseeb84612014-01-28 13:40:15 +02002467 if (1 <= root_pbl_index) {
2468 root_vpbl.pbl_vbase[root_pbl_index].pa_low =
2469 cpu_to_le32((u32)vpbl.pbl_pbase);
2470 root_vpbl.pbl_vbase[root_pbl_index].pa_high =
2471 cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32)));
2472 root_vpbl.leaf_vpbl[root_pbl_index] = vpbl;
2473 }
2474 root_pbl_index++;
2475 cur_pbl_index = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002476 }
Yishai Hadaseeb84612014-01-28 13:40:15 +02002477 if (single_page) {
2478 if (page_count != 0) {
2479 if ((last_dma_addr+4096) !=
2480 (sg_dma_address(sg)+
2481 (page_index*4096)))
2482 single_page = 0;
2483 last_dma_addr = sg_dma_address(sg)+
2484 (page_index*4096);
2485 } else {
2486 first_dma_addr = sg_dma_address(sg)+
2487 (page_index*4096);
2488 last_dma_addr = first_dma_addr;
2489 }
2490 }
2491
2492 vpbl.pbl_vbase[cur_pbl_index].pa_low =
2493 cpu_to_le32((u32)(sg_dma_address(sg)+
2494 (page_index*4096)));
2495 vpbl.pbl_vbase[cur_pbl_index].pa_high =
2496 cpu_to_le32((u32)((((u64)(sg_dma_address(sg)+
2497 (page_index*4096))) >> 32)));
2498 cur_pbl_index++;
2499 page_count++;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002500 }
2501 }
Yishai Hadaseeb84612014-01-28 13:40:15 +02002502
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002503 enough_pages:
2504 nes_debug(NES_DBG_MR, "calculating stag, stag_index=0x%08x, driver_key=0x%08x,"
2505 " stag_key=0x%08x\n",
2506 stag_index, driver_key, stag_key);
2507 stag = stag_index << 8;
2508 stag |= driver_key;
2509 stag += (u32)stag_key;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002510
2511 iova_start = virt;
2512 /* Make the leaf PBL the root if only one PBL */
2513 if (root_pbl_index == 1) {
2514 root_vpbl.pbl_pbase = vpbl.pbl_pbase;
2515 }
2516
2517 if (single_page) {
2518 pbl_count = 0;
2519 } else {
2520 pbl_count = root_pbl_index;
2521 first_dma_addr = 0;
2522 }
2523 nes_debug(NES_DBG_MR, "Registering STag 0x%08X, VA = 0x%08X, length = 0x%08X,"
2524 " index = 0x%08X, region->length=0x%08llx, pbl_count = %u\n",
2525 stag, (unsigned int)iova_start,
2526 (unsigned int)region_length, stag_index,
2527 (unsigned long long)region->length, pbl_count);
Don Wood0145f342009-03-06 15:15:00 -08002528 ret = nes_reg_mr(nesdev, nespd, stag, region->length, &root_vpbl,
2529 first_dma_addr, pbl_count, (u16)cur_pbl_index, acc,
2530 &iova_start, &nesmr->pbls_used, &nesmr->pbl_4k);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002531
2532 nes_debug(NES_DBG_MR, "ret=%d\n", ret);
2533
2534 if (ret == 0) {
2535 nesmr->ibmr.rkey = stag;
2536 nesmr->ibmr.lkey = stag;
2537 nesmr->mode = IWNES_MEMREG_TYPE_MEM;
2538 ibmr = &nesmr->ibmr;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002539 } else {
2540 ib_umem_release(region);
2541 kfree(nesmr);
2542 ibmr = ERR_PTR(-ENOMEM);
2543 }
2544
2545 reg_user_mr_err:
2546 /* free the resources */
2547 if (root_pbl_index == 1) {
2548 pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
2549 vpbl.pbl_pbase);
2550 } else {
2551 for (page_index=0; page_index<root_pbl_index; page_index++) {
2552 pci_free_consistent(nesdev->pcidev, 4096,
2553 root_vpbl.leaf_vpbl[page_index].pbl_vbase,
2554 root_vpbl.leaf_vpbl[page_index].pbl_pbase);
2555 }
2556 kfree(root_vpbl.leaf_vpbl);
2557 pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,
2558 root_vpbl.pbl_pbase);
2559 }
2560
2561 nes_debug(NES_DBG_MR, "Leaving, ibmr=%p", ibmr);
2562
2563 return ibmr;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002564 case IWNES_MEMREG_TYPE_QP:
2565 case IWNES_MEMREG_TYPE_CQ:
Tatyana Nikolova7d9c1992012-12-06 20:05:02 +00002566 if (!region->length) {
2567 nes_debug(NES_DBG_MR, "Unable to register zero length region for CQ\n");
2568 ib_umem_release(region);
2569 return ERR_PTR(-EINVAL);
2570 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002571 nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL);
2572 if (!nespbl) {
2573 nes_debug(NES_DBG_MR, "Unable to allocate PBL\n");
2574 ib_umem_release(region);
2575 return ERR_PTR(-ENOMEM);
2576 }
2577 nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
2578 if (!nesmr) {
2579 ib_umem_release(region);
2580 kfree(nespbl);
2581 nes_debug(NES_DBG_MR, "Unable to allocate nesmr\n");
2582 return ERR_PTR(-ENOMEM);
2583 }
2584 nesmr->region = region;
2585 nes_ucontext = to_nesucontext(pd->uobject->context);
2586 pbl_depth = region->length >> 12;
2587 pbl_depth += (region->length & (4096-1)) ? 1 : 0;
2588 nespbl->pbl_size = pbl_depth*sizeof(u64);
2589 if (req.reg_type == IWNES_MEMREG_TYPE_QP) {
2590 nes_debug(NES_DBG_MR, "Attempting to allocate QP PBL memory");
2591 } else {
2592 nes_debug(NES_DBG_MR, "Attempting to allocate CP PBL memory");
2593 }
2594
2595 nes_debug(NES_DBG_MR, " %u bytes, %u entries.\n",
2596 nespbl->pbl_size, pbl_depth);
2597 pbl = pci_alloc_consistent(nesdev->pcidev, nespbl->pbl_size,
2598 &nespbl->pbl_pbase);
2599 if (!pbl) {
2600 ib_umem_release(region);
2601 kfree(nesmr);
2602 kfree(nespbl);
2603 nes_debug(NES_DBG_MR, "Unable to allocate PBL memory\n");
2604 return ERR_PTR(-ENOMEM);
2605 }
2606
2607 nespbl->pbl_vbase = (u64 *)pbl;
2608 nespbl->user_base = start;
Roland Dreier71e09572008-04-16 21:01:09 -07002609 nes_debug(NES_DBG_MR, "Allocated PBL memory, %u bytes, pbl_pbase=%lx,"
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002610 " pbl_vbase=%p user_base=0x%lx\n",
Roland Dreier71e09572008-04-16 21:01:09 -07002611 nespbl->pbl_size, (unsigned long) nespbl->pbl_pbase,
2612 (void *) nespbl->pbl_vbase, nespbl->user_base);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002613
Yishai Hadaseeb84612014-01-28 13:40:15 +02002614 for_each_sg(region->sg_head.sgl, sg, region->nmap, entry) {
2615 chunk_pages = sg_dma_len(sg) >> 12;
2616 chunk_pages += (sg_dma_len(sg) & (4096-1)) ? 1 : 0;
2617 if (first_page) {
2618 nespbl->page = sg_page(sg);
2619 first_page = 0;
2620 }
2621
2622 for (page_index = 0; page_index < chunk_pages; page_index++) {
2623 ((__le32 *)pbl)[0] = cpu_to_le32((u32)
2624 (sg_dma_address(sg)+
2625 (page_index*4096)));
2626 ((__le32 *)pbl)[1] = cpu_to_le32(((u64)
2627 (sg_dma_address(sg)+
2628 (page_index*4096)))>>32);
2629 nes_debug(NES_DBG_MR, "pbl=%p, *pbl=0x%016llx, 0x%08x%08x\n", pbl,
2630 (unsigned long long)*pbl,
2631 le32_to_cpu(((__le32 *)pbl)[1]), le32_to_cpu(((__le32 *)pbl)[0]));
2632 pbl++;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002633 }
2634 }
Yishai Hadaseeb84612014-01-28 13:40:15 +02002635
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002636 if (req.reg_type == IWNES_MEMREG_TYPE_QP) {
2637 list_add_tail(&nespbl->list, &nes_ucontext->qp_reg_mem_list);
2638 } else {
2639 list_add_tail(&nespbl->list, &nes_ucontext->cq_reg_mem_list);
2640 }
2641 nesmr->ibmr.rkey = -1;
2642 nesmr->ibmr.lkey = -1;
2643 nesmr->mode = req.reg_type;
2644 return &nesmr->ibmr;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002645 }
2646
Julia Lawalle2e435f2011-10-06 09:33:24 -07002647 ib_umem_release(region);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002648 return ERR_PTR(-ENOSYS);
2649}
2650
2651
2652/**
2653 * nes_dereg_mr
2654 */
2655static int nes_dereg_mr(struct ib_mr *ib_mr)
2656{
2657 struct nes_mr *nesmr = to_nesmr(ib_mr);
2658 struct nes_vnic *nesvnic = to_nesvnic(ib_mr->device);
2659 struct nes_device *nesdev = nesvnic->nesdev;
2660 struct nes_adapter *nesadapter = nesdev->nesadapter;
2661 struct nes_hw_cqp_wqe *cqp_wqe;
2662 struct nes_cqp_request *cqp_request;
2663 unsigned long flags;
2664 int ret;
2665 u16 major_code;
2666 u16 minor_code;
2667
2668 if (nesmr->region) {
2669 ib_umem_release(nesmr->region);
2670 }
2671 if (nesmr->mode != IWNES_MEMREG_TYPE_MEM) {
2672 kfree(nesmr);
2673 return 0;
2674 }
2675
2676 /* Deallocate the region with the adapter */
2677
2678 cqp_request = nes_get_cqp_request(nesdev);
2679 if (cqp_request == NULL) {
2680 nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");
2681 return -ENOMEM;
2682 }
2683 cqp_request->waiting = 1;
2684 cqp_wqe = &cqp_request->cqp_wqe;
2685
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002686 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
2687 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
2688 NES_CQP_DEALLOCATE_STAG | NES_CQP_STAG_VA_TO |
2689 NES_CQP_STAG_DEALLOC_PBLS | NES_CQP_STAG_MR);
2690 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ib_mr->rkey);
2691
2692 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -07002693 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002694
2695 /* Wait for CQP */
2696 nes_debug(NES_DBG_MR, "Waiting for deallocate STag 0x%08X completed\n", ib_mr->rkey);
2697 ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
2698 NES_EVENT_TIMEOUT);
2699 nes_debug(NES_DBG_MR, "Deallocate STag 0x%08X completed, wait_event_timeout ret = %u,"
2700 " CQP Major:Minor codes = 0x%04X:0x%04X\n",
2701 ib_mr->rkey, ret, cqp_request->major_code, cqp_request->minor_code);
2702
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002703 major_code = cqp_request->major_code;
2704 minor_code = cqp_request->minor_code;
Roland Dreier1ff66e82008-07-14 23:48:49 -07002705
2706 nes_put_cqp_request(nesdev, cqp_request);
2707
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002708 if (!ret) {
2709 nes_debug(NES_DBG_MR, "Timeout waiting to destroy STag,"
2710 " ib_mr=%p, rkey = 0x%08X\n",
2711 ib_mr, ib_mr->rkey);
2712 return -ETIME;
2713 } else if (major_code) {
2714 nes_debug(NES_DBG_MR, "Error (0x%04X:0x%04X) while attempting"
2715 " to destroy STag, ib_mr=%p, rkey = 0x%08X\n",
2716 major_code, minor_code, ib_mr, ib_mr->rkey);
2717 return -EIO;
Don Wooddae5d132009-03-06 15:12:09 -08002718 }
2719
2720 if (nesmr->pbls_used != 0) {
2721 spin_lock_irqsave(&nesadapter->pbl_lock, flags);
2722 if (nesmr->pbl_4k) {
2723 nesadapter->free_4kpbl += nesmr->pbls_used;
2724 if (nesadapter->free_4kpbl > nesadapter->max_4kpbl)
2725 printk(KERN_ERR PFX "free 4KB PBLs(%u) has "
2726 "exceeded the max(%u)\n",
2727 nesadapter->free_4kpbl,
2728 nesadapter->max_4kpbl);
2729 } else {
2730 nesadapter->free_256pbl += nesmr->pbls_used;
2731 if (nesadapter->free_256pbl > nesadapter->max_256pbl)
2732 printk(KERN_ERR PFX "free 256B PBLs(%u) has "
2733 "exceeded the max(%u)\n",
2734 nesadapter->free_256pbl,
2735 nesadapter->max_256pbl);
2736 }
2737 spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
2738 }
2739 nes_free_resource(nesadapter, nesadapter->allocated_mrs,
2740 (ib_mr->rkey & 0x0fffff00) >> 8);
2741
2742 kfree(nesmr);
2743
2744 return 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002745}
2746
2747
2748/**
2749 * show_rev
2750 */
Tony Jonesf4e91eb2008-02-22 00:13:36 +01002751static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
2752 char *buf)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002753{
2754 struct nes_ib_device *nesibdev =
Tony Jonesf4e91eb2008-02-22 00:13:36 +01002755 container_of(dev, struct nes_ib_device, ibdev.dev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002756 struct nes_vnic *nesvnic = nesibdev->nesvnic;
2757
2758 nes_debug(NES_DBG_INIT, "\n");
2759 return sprintf(buf, "%x\n", nesvnic->nesdev->nesadapter->hw_rev);
2760}
2761
2762
2763/**
2764 * show_fw_ver
2765 */
Tony Jonesf4e91eb2008-02-22 00:13:36 +01002766static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
2767 char *buf)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002768{
2769 struct nes_ib_device *nesibdev =
Tony Jonesf4e91eb2008-02-22 00:13:36 +01002770 container_of(dev, struct nes_ib_device, ibdev.dev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002771 struct nes_vnic *nesvnic = nesibdev->nesvnic;
2772
2773 nes_debug(NES_DBG_INIT, "\n");
Chien Tung0e4562d2009-04-27 13:33:48 -07002774 return sprintf(buf, "%u.%u\n",
2775 (nesvnic->nesdev->nesadapter->firmware_version >> 16),
2776 (nesvnic->nesdev->nesadapter->firmware_version & 0x000000ff));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002777}
2778
2779
2780/**
2781 * show_hca
2782 */
Tony Jonesf4e91eb2008-02-22 00:13:36 +01002783static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
2784 char *buf)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002785{
2786 nes_debug(NES_DBG_INIT, "\n");
2787 return sprintf(buf, "NES020\n");
2788}
2789
2790
2791/**
2792 * show_board
2793 */
Tony Jonesf4e91eb2008-02-22 00:13:36 +01002794static ssize_t show_board(struct device *dev, struct device_attribute *attr,
2795 char *buf)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002796{
2797 nes_debug(NES_DBG_INIT, "\n");
2798 return sprintf(buf, "%.*s\n", 32, "NES020 Board ID");
2799}
2800
2801
Tony Jonesf4e91eb2008-02-22 00:13:36 +01002802static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
2803static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
2804static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
2805static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002806
Tony Jonesf4e91eb2008-02-22 00:13:36 +01002807static struct device_attribute *nes_dev_attributes[] = {
2808 &dev_attr_hw_rev,
2809 &dev_attr_fw_ver,
2810 &dev_attr_hca_type,
2811 &dev_attr_board_id
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002812};
2813
2814
2815/**
2816 * nes_query_qp
2817 */
2818static int nes_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
2819 int attr_mask, struct ib_qp_init_attr *init_attr)
2820{
2821 struct nes_qp *nesqp = to_nesqp(ibqp);
2822
2823 nes_debug(NES_DBG_QP, "\n");
2824
2825 attr->qp_access_flags = 0;
2826 attr->cap.max_send_wr = nesqp->hwqp.sq_size;
2827 attr->cap.max_recv_wr = nesqp->hwqp.rq_size;
2828 attr->cap.max_recv_sge = 1;
Chien Tungeadde3a2010-03-25 13:39:50 +00002829 if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA)
2830 attr->cap.max_inline_data = 0;
2831 else
2832 attr->cap.max_inline_data = 64;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002833
2834 init_attr->event_handler = nesqp->ibqp.event_handler;
2835 init_attr->qp_context = nesqp->ibqp.qp_context;
2836 init_attr->send_cq = nesqp->ibqp.send_cq;
2837 init_attr->recv_cq = nesqp->ibqp.recv_cq;
Dave Jones4127c362013-09-17 17:45:54 -04002838 init_attr->srq = nesqp->ibqp.srq;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002839 init_attr->cap = attr->cap;
2840
2841 return 0;
2842}
2843
2844
2845/**
2846 * nes_hw_modify_qp
2847 */
2848int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp,
Don Wood8b1c9dc2009-09-05 20:36:38 -07002849 u32 next_iwarp_state, u32 termlen, u32 wait_completion)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002850{
2851 struct nes_hw_cqp_wqe *cqp_wqe;
2852 /* struct iw_cm_id *cm_id = nesqp->cm_id; */
2853 /* struct iw_cm_event cm_event; */
2854 struct nes_cqp_request *cqp_request;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002855 int ret;
2856 u16 major_code;
2857
2858 nes_debug(NES_DBG_MOD_QP, "QP%u, refcount=%d\n",
2859 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
2860
2861 cqp_request = nes_get_cqp_request(nesdev);
2862 if (cqp_request == NULL) {
2863 nes_debug(NES_DBG_MOD_QP, "Failed to get a cqp_request.\n");
2864 return -ENOMEM;
2865 }
2866 if (wait_completion) {
2867 cqp_request->waiting = 1;
2868 } else {
2869 cqp_request->waiting = 0;
2870 }
2871 cqp_wqe = &cqp_request->cqp_wqe;
2872
2873 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
2874 NES_CQP_MODIFY_QP | NES_CQP_QP_TYPE_IWARP | next_iwarp_state);
2875 nes_debug(NES_DBG_MOD_QP, "using next_iwarp_state=%08x, wqe_words=%08x\n",
2876 next_iwarp_state, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]));
2877 nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
2878 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
2879 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, (u64)nesqp->nesqp_context_pbase);
2880
Don Wood8b1c9dc2009-09-05 20:36:38 -07002881 /* If sending a terminate message, fill in the length (in words) */
2882 if (((next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) == NES_CQP_QP_IWARP_STATE_TERMINATE) &&
2883 !(next_iwarp_state & NES_CQP_QP_TERM_DONT_SEND_TERM_MSG)) {
2884 termlen = ((termlen + 3) >> 2) << NES_CQP_OP_TERMLEN_SHIFT;
2885 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_NEW_MSS_IDX, termlen);
2886 }
2887
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002888 atomic_set(&cqp_request->refcount, 2);
Roland Dreier8294f292008-07-14 23:48:49 -07002889 nes_post_cqp_request(nesdev, cqp_request);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002890
2891 /* Wait for CQP */
2892 if (wait_completion) {
2893 /* nes_debug(NES_DBG_MOD_QP, "Waiting for modify iWARP QP%u to complete.\n",
2894 nesqp->hwqp.qp_id); */
2895 ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
2896 NES_EVENT_TIMEOUT);
2897 nes_debug(NES_DBG_MOD_QP, "Modify iwarp QP%u completed, wait_event_timeout ret=%u, "
2898 "CQP Major:Minor codes = 0x%04X:0x%04X.\n",
2899 nesqp->hwqp.qp_id, ret, cqp_request->major_code, cqp_request->minor_code);
2900 major_code = cqp_request->major_code;
2901 if (major_code) {
2902 nes_debug(NES_DBG_MOD_QP, "Modify iwarp QP%u failed"
2903 "CQP Major:Minor codes = 0x%04X:0x%04X, intended next state = 0x%08X.\n",
2904 nesqp->hwqp.qp_id, cqp_request->major_code,
2905 cqp_request->minor_code, next_iwarp_state);
2906 }
Roland Dreier1ff66e82008-07-14 23:48:49 -07002907
2908 nes_put_cqp_request(nesdev, cqp_request);
2909
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002910 if (!ret)
2911 return -ETIME;
2912 else if (major_code)
2913 return -EIO;
2914 else
2915 return 0;
2916 } else {
2917 return 0;
2918 }
2919}
2920
2921
2922/**
2923 * nes_modify_qp
2924 */
2925int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
2926 int attr_mask, struct ib_udata *udata)
2927{
2928 struct nes_qp *nesqp = to_nesqp(ibqp);
2929 struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
2930 struct nes_device *nesdev = nesvnic->nesdev;
2931 /* u32 cqp_head; */
2932 /* u32 counter; */
2933 u32 next_iwarp_state = 0;
2934 int err;
2935 unsigned long qplockflags;
2936 int ret;
2937 u16 original_last_aeq;
2938 u8 issue_modify_qp = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002939 u8 dont_wait = 0;
2940
2941 nes_debug(NES_DBG_MOD_QP, "QP%u: QP State=%u, cur QP State=%u,"
2942 " iwarp_state=0x%X, refcount=%d\n",
2943 nesqp->hwqp.qp_id, attr->qp_state, nesqp->ibqp_state,
2944 nesqp->iwarp_state, atomic_read(&nesqp->refcount));
2945
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002946 spin_lock_irqsave(&nesqp->lock, qplockflags);
2947
2948 nes_debug(NES_DBG_MOD_QP, "QP%u: hw_iwarp_state=0x%X, hw_tcp_state=0x%X,"
2949 " QP Access Flags=0x%X, attr_mask = 0x%0x\n",
2950 nesqp->hwqp.qp_id, nesqp->hw_iwarp_state,
2951 nesqp->hw_tcp_state, attr->qp_access_flags, attr_mask);
2952
2953 if (attr_mask & IB_QP_STATE) {
2954 switch (attr->qp_state) {
2955 case IB_QPS_INIT:
2956 nes_debug(NES_DBG_MOD_QP, "QP%u: new state = init\n",
2957 nesqp->hwqp.qp_id);
2958 if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_IDLE) {
2959 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002960 return -EINVAL;
2961 }
2962 next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE;
2963 issue_modify_qp = 1;
2964 break;
2965 case IB_QPS_RTR:
2966 nes_debug(NES_DBG_MOD_QP, "QP%u: new state = rtr\n",
2967 nesqp->hwqp.qp_id);
2968 if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_IDLE) {
2969 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002970 return -EINVAL;
2971 }
2972 next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE;
2973 issue_modify_qp = 1;
2974 break;
2975 case IB_QPS_RTS:
2976 nes_debug(NES_DBG_MOD_QP, "QP%u: new state = rts\n",
2977 nesqp->hwqp.qp_id);
2978 if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_RTS) {
2979 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002980 return -EINVAL;
2981 }
2982 if (nesqp->cm_id == NULL) {
2983 nes_debug(NES_DBG_MOD_QP, "QP%u: Failing attempt to move QP to RTS without a CM_ID. \n",
2984 nesqp->hwqp.qp_id );
2985 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08002986 return -EINVAL;
2987 }
2988 next_iwarp_state = NES_CQP_QP_IWARP_STATE_RTS;
2989 if (nesqp->iwarp_state != NES_CQP_QP_IWARP_STATE_RTS)
2990 next_iwarp_state |= NES_CQP_QP_CONTEXT_VALID |
2991 NES_CQP_QP_ARP_VALID | NES_CQP_QP_ORD_VALID;
2992 issue_modify_qp = 1;
2993 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_ESTABLISHED;
2994 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_RTS;
2995 nesqp->hte_added = 1;
2996 break;
2997 case IB_QPS_SQD:
2998 issue_modify_qp = 1;
2999 nes_debug(NES_DBG_MOD_QP, "QP%u: new state=closing. SQ head=%u, SQ tail=%u\n",
3000 nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail);
3001 if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_CLOSING) {
3002 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003003 return 0;
3004 } else {
3005 if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_CLOSING) {
3006 nes_debug(NES_DBG_MOD_QP, "QP%u: State change to closing"
3007 " ignored due to current iWARP state\n",
3008 nesqp->hwqp.qp_id);
3009 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003010 return -EINVAL;
3011 }
3012 if (nesqp->hw_iwarp_state != NES_AEQE_IWARP_STATE_RTS) {
3013 nes_debug(NES_DBG_MOD_QP, "QP%u: State change to closing"
3014 " already done based on hw state.\n",
3015 nesqp->hwqp.qp_id);
3016 issue_modify_qp = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003017 }
3018 switch (nesqp->hw_iwarp_state) {
3019 case NES_AEQE_IWARP_STATE_CLOSING:
3020 next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
Tatyana Nikolovad5fb4762012-10-02 16:38:12 +00003021 break;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003022 case NES_AEQE_IWARP_STATE_TERMINATE:
3023 next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;
3024 break;
3025 case NES_AEQE_IWARP_STATE_ERROR:
3026 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;
3027 break;
3028 default:
3029 next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003030 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
3031 break;
3032 }
3033 }
3034 break;
3035 case IB_QPS_SQE:
3036 nes_debug(NES_DBG_MOD_QP, "QP%u: new state = terminate\n",
3037 nesqp->hwqp.qp_id);
3038 if (nesqp->iwarp_state>=(u32)NES_CQP_QP_IWARP_STATE_TERMINATE) {
3039 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003040 return -EINVAL;
3041 }
3042 /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */
3043 next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;
3044 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_TERMINATE;
3045 issue_modify_qp = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003046 break;
3047 case IB_QPS_ERR:
3048 case IB_QPS_RESET:
3049 if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_ERROR) {
3050 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003051 return -EINVAL;
3052 }
3053 nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n",
3054 nesqp->hwqp.qp_id);
Don Wood8b1c9dc2009-09-05 20:36:38 -07003055 if (nesqp->term_flags)
3056 del_timer(&nesqp->terminate_timer);
3057
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003058 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;
3059 /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */
3060 if (nesqp->hte_added) {
3061 nes_debug(NES_DBG_MOD_QP, "set CQP_QP_DEL_HTE\n");
3062 next_iwarp_state |= NES_CQP_QP_DEL_HTE;
3063 nesqp->hte_added = 0;
3064 }
3065 if ((nesqp->hw_tcp_state > NES_AEQE_TCP_STATE_CLOSED) &&
Faisal Latifcd6860e2010-07-04 00:17:59 +00003066 (nesdev->iw_status) &&
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003067 (nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) {
3068 next_iwarp_state |= NES_CQP_QP_RESET;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003069 } else {
3070 nes_debug(NES_DBG_MOD_QP, "QP%u NOT setting NES_CQP_QP_RESET since TCP state = %u\n",
3071 nesqp->hwqp.qp_id, nesqp->hw_tcp_state);
3072 dont_wait = 1;
3073 }
3074 issue_modify_qp = 1;
3075 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR;
3076 break;
3077 default:
3078 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003079 return -EINVAL;
3080 break;
3081 }
3082
3083 nesqp->ibqp_state = attr->qp_state;
Tatyana Nikolovaa67b0782012-10-02 16:40:33 +00003084 nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK;
3085 nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n",
3086 nesqp->iwarp_state);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003087 }
3088
3089 if (attr_mask & IB_QP_ACCESS_FLAGS) {
3090 if (attr->qp_access_flags & IB_ACCESS_LOCAL_WRITE) {
3091 nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN |
3092 NES_QPCONTEXT_MISC_RDMA_READ_EN);
3093 issue_modify_qp = 1;
3094 }
3095 if (attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE) {
3096 nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN);
3097 issue_modify_qp = 1;
3098 }
3099 if (attr->qp_access_flags & IB_ACCESS_REMOTE_READ) {
3100 nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_READ_EN);
3101 issue_modify_qp = 1;
3102 }
3103 if (attr->qp_access_flags & IB_ACCESS_MW_BIND) {
3104 nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WBIND_EN);
3105 issue_modify_qp = 1;
3106 }
3107
3108 if (nesqp->user_mode) {
3109 nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN |
3110 NES_QPCONTEXT_MISC_RDMA_READ_EN);
3111 issue_modify_qp = 1;
3112 }
3113 }
3114
3115 original_last_aeq = nesqp->last_aeq;
3116 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
3117
3118 nes_debug(NES_DBG_MOD_QP, "issue_modify_qp=%u\n", issue_modify_qp);
3119
3120 ret = 0;
3121
3122
3123 if (issue_modify_qp) {
3124 nes_debug(NES_DBG_MOD_QP, "call nes_hw_modify_qp\n");
Don Wood8b1c9dc2009-09-05 20:36:38 -07003125 ret = nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 1);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003126 if (ret)
3127 nes_debug(NES_DBG_MOD_QP, "nes_hw_modify_qp (next_iwarp_state = 0x%08X)"
3128 " failed for QP%u.\n",
3129 next_iwarp_state, nesqp->hwqp.qp_id);
3130
3131 }
3132
3133 if ((issue_modify_qp) && (nesqp->ibqp_state > IB_QPS_RTS)) {
3134 nes_debug(NES_DBG_MOD_QP, "QP%u Issued ModifyQP refcount (%d),"
3135 " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
3136 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
3137 original_last_aeq, nesqp->last_aeq);
Dan Carpenter349850f2014-02-06 15:48:23 +03003138 if (!ret || original_last_aeq != NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003139 if (dont_wait) {
3140 if (nesqp->cm_id && nesqp->hw_tcp_state != 0) {
3141 nes_debug(NES_DBG_MOD_QP, "QP%u Queuing fake disconnect for QP refcount (%d),"
3142 " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
3143 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
3144 original_last_aeq, nesqp->last_aeq);
3145 /* this one is for the cm_disconnect thread */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003146 spin_lock_irqsave(&nesqp->lock, qplockflags);
3147 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3148 nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
3149 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
3150 nes_cm_disconn(nesqp);
3151 } else {
3152 nes_debug(NES_DBG_MOD_QP, "QP%u No fake disconnect, QP refcount=%d\n",
3153 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003154 }
3155 } else {
3156 spin_lock_irqsave(&nesqp->lock, qplockflags);
3157 if (nesqp->cm_id) {
3158 /* These two are for the timer thread */
3159 if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003160 nesqp->cm_id->add_ref(nesqp->cm_id);
3161 nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"
3162 " need ae to finish up, original_last_aeq = 0x%04X."
3163 " last_aeq = 0x%04X, scheduling timer.\n",
3164 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
3165 original_last_aeq, nesqp->last_aeq);
3166 schedule_nes_timer(nesqp->cm_node, (struct sk_buff *) nesqp, NES_TIMER_TYPE_CLOSE, 1, 0);
3167 }
3168 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
3169 } else {
3170 spin_unlock_irqrestore(&nesqp->lock, qplockflags);
3171 nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"
3172 " need ae to finish up, original_last_aeq = 0x%04X."
3173 " last_aeq = 0x%04X.\n",
3174 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
3175 original_last_aeq, nesqp->last_aeq);
3176 }
3177 }
3178 } else {
3179 nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up,"
3180 " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
3181 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
3182 original_last_aeq, nesqp->last_aeq);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003183 }
3184 } else {
3185 nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up,"
3186 " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
3187 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
3188 original_last_aeq, nesqp->last_aeq);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003189 }
3190
3191 err = 0;
3192
3193 nes_debug(NES_DBG_MOD_QP, "QP%u Leaving, refcount=%d\n",
3194 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
3195
3196 return err;
3197}
3198
3199
3200/**
3201 * nes_muticast_attach
3202 */
3203static int nes_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
3204{
3205 nes_debug(NES_DBG_INIT, "\n");
3206 return -ENOSYS;
3207}
3208
3209
3210/**
3211 * nes_multicast_detach
3212 */
3213static int nes_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
3214{
3215 nes_debug(NES_DBG_INIT, "\n");
3216 return -ENOSYS;
3217}
3218
3219
3220/**
3221 * nes_process_mad
3222 */
3223static int nes_process_mad(struct ib_device *ibdev, int mad_flags,
Ira Weinya97e2d82015-05-31 17:15:30 -04003224 u8 port_num, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
3225 const struct ib_mad *in_mad, struct ib_mad *out_mad)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003226{
3227 nes_debug(NES_DBG_INIT, "\n");
3228 return -ENOSYS;
3229}
3230
3231static inline void
3232fill_wqe_sg_send(struct nes_hw_qp_wqe *wqe, struct ib_send_wr *ib_wr, u32 uselkey)
3233{
3234 int sge_index;
3235 int total_payload_length = 0;
3236 for (sge_index = 0; sge_index < ib_wr->num_sge; sge_index++) {
3237 set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX+(sge_index*4),
3238 ib_wr->sg_list[sge_index].addr);
3239 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_LENGTH0_IDX + (sge_index*4),
3240 ib_wr->sg_list[sge_index].length);
3241 if (uselkey)
3242 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX + (sge_index*4),
3243 (ib_wr->sg_list[sge_index].lkey));
3244 else
3245 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX + (sge_index*4), 0);
3246
3247 total_payload_length += ib_wr->sg_list[sge_index].length;
3248 }
3249 nes_debug(NES_DBG_IW_TX, "UC UC UC, sending total_payload_length=%u \n",
3250 total_payload_length);
3251 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
3252 total_payload_length);
3253}
3254
3255/**
3256 * nes_post_send
3257 */
3258static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
3259 struct ib_send_wr **bad_wr)
3260{
3261 u64 u64temp;
3262 unsigned long flags = 0;
3263 struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
3264 struct nes_device *nesdev = nesvnic->nesdev;
3265 struct nes_qp *nesqp = to_nesqp(ibqp);
3266 struct nes_hw_qp_wqe *wqe;
Chien Tung649fe4a2009-12-09 13:51:37 -08003267 int err = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003268 u32 qsize = nesqp->hwqp.sq_size;
3269 u32 head;
Chien Tung649fe4a2009-12-09 13:51:37 -08003270 u32 wqe_misc = 0;
3271 u32 wqe_count = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003272 u32 counter;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003273
Frank Zagoe5dec392009-12-09 13:51:36 -08003274 if (nesqp->ibqp_state > IB_QPS_RTS) {
3275 err = -EINVAL;
3276 goto out;
3277 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003278
Ilpo Järvinen5880ff12008-10-30 13:39:43 +02003279 spin_lock_irqsave(&nesqp->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003280
3281 head = nesqp->hwqp.sq_head;
3282
3283 while (ib_wr) {
Don Wood8b1c9dc2009-09-05 20:36:38 -07003284 /* Check for QP error */
3285 if (nesqp->term_flags) {
3286 err = -EINVAL;
3287 break;
3288 }
3289
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003290 /* Check for SQ overflow */
3291 if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {
Or Gerlitz831d06c2010-02-04 11:25:07 +00003292 err = -ENOMEM;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003293 break;
3294 }
3295
3296 wqe = &nesqp->hwqp.sq_vbase[head];
3297 /* nes_debug(NES_DBG_IW_TX, "processing sq wqe for QP%u at %p, head = %u.\n",
3298 nesqp->hwqp.qp_id, wqe, head); */
3299 nes_fill_init_qp_wqe(wqe, nesqp, head);
3300 u64temp = (u64)(ib_wr->wr_id);
3301 set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX,
3302 u64temp);
Chien Tung649fe4a2009-12-09 13:51:37 -08003303 switch (ib_wr->opcode) {
3304 case IB_WR_SEND:
3305 case IB_WR_SEND_WITH_INV:
3306 if (IB_WR_SEND == ib_wr->opcode) {
3307 if (ib_wr->send_flags & IB_SEND_SOLICITED)
3308 wqe_misc = NES_IWARP_SQ_OP_SENDSE;
3309 else
3310 wqe_misc = NES_IWARP_SQ_OP_SEND;
3311 } else {
3312 if (ib_wr->send_flags & IB_SEND_SOLICITED)
3313 wqe_misc = NES_IWARP_SQ_OP_SENDSEINV;
3314 else
3315 wqe_misc = NES_IWARP_SQ_OP_SENDINV;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003316
Chien Tung649fe4a2009-12-09 13:51:37 -08003317 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_INV_STAG_LOW_IDX,
3318 ib_wr->ex.invalidate_rkey);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003319 }
3320
Chien Tung649fe4a2009-12-09 13:51:37 -08003321 if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
3322 err = -EINVAL;
3323 break;
3324 }
3325
3326 if (ib_wr->send_flags & IB_SEND_FENCE)
3327 wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
3328
3329 if ((ib_wr->send_flags & IB_SEND_INLINE) &&
3330 ((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&
3331 (ib_wr->sg_list[0].length <= 64)) {
3332 memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],
3333 (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);
3334 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
3335 ib_wr->sg_list[0].length);
3336 wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;
3337 } else {
3338 fill_wqe_sg_send(wqe, ib_wr, 1);
3339 }
3340
3341 break;
3342 case IB_WR_RDMA_WRITE:
3343 wqe_misc = NES_IWARP_SQ_OP_RDMAW;
3344 if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
3345 nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=%u\n",
3346 ib_wr->num_sge, nesdev->nesadapter->max_sge);
3347 err = -EINVAL;
3348 break;
3349 }
3350
3351 if (ib_wr->send_flags & IB_SEND_FENCE)
3352 wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
3353
3354 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
3355 ib_wr->wr.rdma.rkey);
3356 set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
3357 ib_wr->wr.rdma.remote_addr);
3358
3359 if ((ib_wr->send_flags & IB_SEND_INLINE) &&
3360 ((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&
3361 (ib_wr->sg_list[0].length <= 64)) {
3362 memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],
3363 (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);
3364 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
3365 ib_wr->sg_list[0].length);
3366 wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;
3367 } else {
3368 fill_wqe_sg_send(wqe, ib_wr, 1);
3369 }
3370
3371 wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] =
3372 wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX];
3373 break;
3374 case IB_WR_RDMA_READ:
3375 case IB_WR_RDMA_READ_WITH_INV:
3376 /* iWARP only supports 1 sge for RDMA reads */
3377 if (ib_wr->num_sge > 1) {
3378 nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=1\n",
3379 ib_wr->num_sge);
3380 err = -EINVAL;
3381 break;
3382 }
3383 if (ib_wr->opcode == IB_WR_RDMA_READ) {
3384 wqe_misc = NES_IWARP_SQ_OP_RDMAR;
3385 } else {
3386 wqe_misc = NES_IWARP_SQ_OP_RDMAR_LOCINV;
3387 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_INV_STAG_LOW_IDX,
3388 ib_wr->ex.invalidate_rkey);
3389 }
3390
3391 set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
3392 ib_wr->wr.rdma.remote_addr);
3393 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
3394 ib_wr->wr.rdma.rkey);
3395 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX,
3396 ib_wr->sg_list->length);
3397 set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
3398 ib_wr->sg_list->addr);
3399 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX,
3400 ib_wr->sg_list->lkey);
3401 break;
3402 case IB_WR_LOCAL_INV:
3403 wqe_misc = NES_IWARP_SQ_OP_LOCINV;
3404 set_wqe_32bit_value(wqe->wqe_words,
3405 NES_IWARP_SQ_LOCINV_WQE_INV_STAG_IDX,
3406 ib_wr->ex.invalidate_rkey);
3407 break;
Chien Tunge293a262009-12-09 15:21:54 -08003408 case IB_WR_FAST_REG_MR:
3409 {
3410 int i;
3411 int flags = ib_wr->wr.fast_reg.access_flags;
3412 struct nes_ib_fast_reg_page_list *pnesfrpl =
3413 container_of(ib_wr->wr.fast_reg.page_list,
3414 struct nes_ib_fast_reg_page_list,
3415 ibfrpl);
3416 u64 *src_page_list = pnesfrpl->ibfrpl.page_list;
3417 u64 *dst_page_list = pnesfrpl->nes_wqe_pbl.kva;
3418
3419 if (ib_wr->wr.fast_reg.page_list_len >
3420 (NES_4K_PBL_CHUNK_SIZE / sizeof(u64))) {
3421 nes_debug(NES_DBG_IW_TX, "SQ_FMR: bad page_list_len\n");
3422 err = -EINVAL;
3423 break;
3424 }
3425 wqe_misc = NES_IWARP_SQ_OP_FAST_REG;
3426 set_wqe_64bit_value(wqe->wqe_words,
3427 NES_IWARP_SQ_FMR_WQE_VA_FBO_LOW_IDX,
3428 ib_wr->wr.fast_reg.iova_start);
3429 set_wqe_32bit_value(wqe->wqe_words,
3430 NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
3431 ib_wr->wr.fast_reg.length);
3432 set_wqe_32bit_value(wqe->wqe_words,
Tatyana Nikolova94f622b2012-01-06 18:15:01 -06003433 NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0);
3434 set_wqe_32bit_value(wqe->wqe_words,
Chien Tunge293a262009-12-09 15:21:54 -08003435 NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,
3436 ib_wr->wr.fast_reg.rkey);
3437 /* Set page size: */
3438 if (ib_wr->wr.fast_reg.page_shift == 12) {
3439 wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_4K;
3440 } else if (ib_wr->wr.fast_reg.page_shift == 21) {
3441 wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_2M;
3442 } else {
3443 nes_debug(NES_DBG_IW_TX, "Invalid page shift,"
3444 " ib_wr=%u, max=1\n", ib_wr->num_sge);
3445 err = -EINVAL;
3446 break;
3447 }
3448 /* Set access_flags */
3449 wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_READ;
3450 if (flags & IB_ACCESS_LOCAL_WRITE)
3451 wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_WRITE;
3452
3453 if (flags & IB_ACCESS_REMOTE_WRITE)
3454 wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_WRITE;
3455
3456 if (flags & IB_ACCESS_REMOTE_READ)
3457 wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_READ;
3458
3459 if (flags & IB_ACCESS_MW_BIND)
3460 wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_WINDOW_BIND;
3461
3462 /* Fill in PBL info: */
3463 if (ib_wr->wr.fast_reg.page_list_len >
3464 pnesfrpl->ibfrpl.max_page_list_len) {
3465 nes_debug(NES_DBG_IW_TX, "Invalid page list length,"
3466 " ib_wr=%p, value=%u, max=%u\n",
3467 ib_wr, ib_wr->wr.fast_reg.page_list_len,
3468 pnesfrpl->ibfrpl.max_page_list_len);
3469 err = -EINVAL;
3470 break;
3471 }
3472
3473 set_wqe_64bit_value(wqe->wqe_words,
3474 NES_IWARP_SQ_FMR_WQE_PBL_ADDR_LOW_IDX,
3475 pnesfrpl->nes_wqe_pbl.paddr);
3476
3477 set_wqe_32bit_value(wqe->wqe_words,
3478 NES_IWARP_SQ_FMR_WQE_PBL_LENGTH_IDX,
3479 ib_wr->wr.fast_reg.page_list_len * 8);
3480
3481 for (i = 0; i < ib_wr->wr.fast_reg.page_list_len; i++)
3482 dst_page_list[i] = cpu_to_le64(src_page_list[i]);
3483
Roland Dreier183ae742010-09-27 17:51:33 -07003484 nes_debug(NES_DBG_IW_TX, "SQ_FMR: iova_start: %llx, "
3485 "length: %d, rkey: %0x, pgl_paddr: %llx, "
Chien Tunge293a262009-12-09 15:21:54 -08003486 "page_list_len: %u, wqe_misc: %x\n",
Roland Dreier183ae742010-09-27 17:51:33 -07003487 (unsigned long long) ib_wr->wr.fast_reg.iova_start,
Chien Tunge293a262009-12-09 15:21:54 -08003488 ib_wr->wr.fast_reg.length,
3489 ib_wr->wr.fast_reg.rkey,
Roland Dreier183ae742010-09-27 17:51:33 -07003490 (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr,
Chien Tunge293a262009-12-09 15:21:54 -08003491 ib_wr->wr.fast_reg.page_list_len,
3492 wqe_misc);
3493 break;
3494 }
Chien Tung649fe4a2009-12-09 13:51:37 -08003495 default:
3496 /* error */
3497 err = -EINVAL;
3498 break;
3499 }
3500
Frank Zagoe5dec392009-12-09 13:51:36 -08003501 if (err)
3502 break;
3503
Chien Tungd14152d2009-12-09 15:21:56 -08003504 if ((ib_wr->send_flags & IB_SEND_SIGNALED) || nesqp->sig_all)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003505 wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL;
Chien Tungd14152d2009-12-09 15:21:56 -08003506
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003507 wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(wqe_misc);
3508
3509 ib_wr = ib_wr->next;
3510 head++;
3511 wqe_count++;
3512 if (head >= qsize)
3513 head = 0;
3514
3515 }
3516
3517 nesqp->hwqp.sq_head = head;
3518 barrier();
3519 while (wqe_count) {
3520 counter = min(wqe_count, ((u32)255));
3521 wqe_count -= counter;
3522 nes_write32(nesdev->regs + NES_WQE_ALLOC,
3523 (counter << 24) | 0x00800000 | nesqp->hwqp.qp_id);
3524 }
3525
Ilpo Järvinen5880ff12008-10-30 13:39:43 +02003526 spin_unlock_irqrestore(&nesqp->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003527
Frank Zagoe5dec392009-12-09 13:51:36 -08003528out:
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003529 if (err)
3530 *bad_wr = ib_wr;
3531 return err;
3532}
3533
3534
3535/**
3536 * nes_post_recv
3537 */
3538static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr,
3539 struct ib_recv_wr **bad_wr)
3540{
3541 u64 u64temp;
3542 unsigned long flags = 0;
3543 struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
3544 struct nes_device *nesdev = nesvnic->nesdev;
3545 struct nes_qp *nesqp = to_nesqp(ibqp);
3546 struct nes_hw_qp_wqe *wqe;
3547 int err = 0;
3548 int sge_index;
3549 u32 qsize = nesqp->hwqp.rq_size;
3550 u32 head;
3551 u32 wqe_count = 0;
3552 u32 counter;
3553 u32 total_payload_length;
3554
Frank Zago4293fdc12009-12-09 13:51:36 -08003555 if (nesqp->ibqp_state > IB_QPS_RTS) {
3556 err = -EINVAL;
3557 goto out;
3558 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003559
Ilpo Järvinen5880ff12008-10-30 13:39:43 +02003560 spin_lock_irqsave(&nesqp->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003561
3562 head = nesqp->hwqp.rq_head;
3563
3564 while (ib_wr) {
Don Wood8b1c9dc2009-09-05 20:36:38 -07003565 /* Check for QP error */
3566 if (nesqp->term_flags) {
3567 err = -EINVAL;
3568 break;
3569 }
3570
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003571 if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
3572 err = -EINVAL;
3573 break;
3574 }
3575 /* Check for RQ overflow */
3576 if (((head + (2 * qsize) - nesqp->hwqp.rq_tail) % qsize) == (qsize - 1)) {
Or Gerlitz831d06c2010-02-04 11:25:07 +00003577 err = -ENOMEM;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003578 break;
3579 }
3580
3581 nes_debug(NES_DBG_IW_RX, "ibwr sge count = %u.\n", ib_wr->num_sge);
3582 wqe = &nesqp->hwqp.rq_vbase[head];
3583
3584 /* nes_debug(NES_DBG_IW_RX, "QP%u:processing rq wqe at %p, head = %u.\n",
3585 nesqp->hwqp.qp_id, wqe, head); */
3586 nes_fill_init_qp_wqe(wqe, nesqp, head);
3587 u64temp = (u64)(ib_wr->wr_id);
3588 set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX,
3589 u64temp);
3590 total_payload_length = 0;
3591 for (sge_index=0; sge_index < ib_wr->num_sge; sge_index++) {
3592 set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_FRAG0_LOW_IDX+(sge_index*4),
3593 ib_wr->sg_list[sge_index].addr);
3594 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_LENGTH0_IDX+(sge_index*4),
3595 ib_wr->sg_list[sge_index].length);
3596 set_wqe_32bit_value(wqe->wqe_words,NES_IWARP_RQ_WQE_STAG0_IDX+(sge_index*4),
3597 ib_wr->sg_list[sge_index].lkey);
3598
3599 total_payload_length += ib_wr->sg_list[sge_index].length;
3600 }
3601 set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_TOTAL_PAYLOAD_IDX,
3602 total_payload_length);
3603
3604 ib_wr = ib_wr->next;
3605 head++;
3606 wqe_count++;
3607 if (head >= qsize)
3608 head = 0;
3609 }
3610
3611 nesqp->hwqp.rq_head = head;
3612 barrier();
3613 while (wqe_count) {
3614 counter = min(wqe_count, ((u32)255));
3615 wqe_count -= counter;
3616 nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter<<24) | nesqp->hwqp.qp_id);
3617 }
3618
Ilpo Järvinen5880ff12008-10-30 13:39:43 +02003619 spin_unlock_irqrestore(&nesqp->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003620
Frank Zago4293fdc12009-12-09 13:51:36 -08003621out:
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003622 if (err)
3623 *bad_wr = ib_wr;
3624 return err;
3625}
3626
3627
3628/**
3629 * nes_poll_cq
3630 */
3631static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
3632{
3633 u64 u64temp;
3634 u64 wrid;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003635 unsigned long flags = 0;
3636 struct nes_vnic *nesvnic = to_nesvnic(ibcq->device);
3637 struct nes_device *nesdev = nesvnic->nesdev;
3638 struct nes_cq *nescq = to_nescq(ibcq);
3639 struct nes_qp *nesqp;
3640 struct nes_hw_cqe cqe;
3641 u32 head;
Don Wood6eed5e72009-09-05 20:36:39 -07003642 u32 wq_tail = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003643 u32 cq_size;
3644 u32 cqe_count = 0;
3645 u32 wqe_index;
3646 u32 u32temp;
Don Wood6eed5e72009-09-05 20:36:39 -07003647 u32 move_cq_head = 1;
3648 u32 err_code;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003649
3650 nes_debug(NES_DBG_CQ, "\n");
3651
Ilpo Järvinen5880ff12008-10-30 13:39:43 +02003652 spin_lock_irqsave(&nescq->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003653
3654 head = nescq->hw_cq.cq_head;
3655 cq_size = nescq->hw_cq.cq_size;
3656
3657 while (cqe_count < num_entries) {
Don Wood5ee21fe2009-09-05 20:36:37 -07003658 if ((le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) &
3659 NES_CQE_VALID) == 0)
3660 break;
Roland Dreier31d1e342008-04-23 11:55:45 -07003661
Don Wood5ee21fe2009-09-05 20:36:37 -07003662 /*
3663 * Make sure we read CQ entry contents *after*
3664 * we've checked the valid bit.
3665 */
3666 rmb();
3667
3668 cqe = nescq->hw_cq.cq_vbase[head];
Don Wood5ee21fe2009-09-05 20:36:37 -07003669 u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
3670 wqe_index = u32temp & (nesdev->nesadapter->max_qp_wr - 1);
3671 u32temp &= ~(NES_SW_CONTEXT_ALIGN-1);
3672 /* parse CQE, get completion context from WQE (either rq or sq) */
3673 u64temp = (((u64)(le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) |
3674 ((u64)u32temp);
3675
3676 if (u64temp) {
3677 nesqp = (struct nes_qp *)(unsigned long)u64temp;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003678 memset(entry, 0, sizeof *entry);
3679 if (cqe.cqe_words[NES_CQE_ERROR_CODE_IDX] == 0) {
3680 entry->status = IB_WC_SUCCESS;
3681 } else {
Don Wood320cdfd2009-09-05 20:36:39 -07003682 err_code = le32_to_cpu(cqe.cqe_words[NES_CQE_ERROR_CODE_IDX]);
3683 if (NES_IWARP_CQE_MAJOR_DRV == (err_code >> 16)) {
3684 entry->status = err_code & 0x0000ffff;
3685
3686 /* The rest of the cqe's will be marked as flushed */
3687 nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX] =
3688 cpu_to_le32((NES_IWARP_CQE_MAJOR_FLUSH << 16) |
3689 NES_IWARP_CQE_MINOR_FLUSH);
3690 } else
3691 entry->status = IB_WC_WR_FLUSH_ERR;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003692 }
3693
3694 entry->qp = &nesqp->ibqp;
3695 entry->src_qp = nesqp->hwqp.qp_id;
3696
3697 if (le32_to_cpu(cqe.cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_SQ) {
3698 if (nesqp->skip_lsmm) {
3699 nesqp->skip_lsmm = 0;
Don Wood5ee21fe2009-09-05 20:36:37 -07003700 nesqp->hwqp.sq_tail++;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003701 }
3702
3703 /* Working on a SQ Completion*/
Don Wood6eed5e72009-09-05 20:36:39 -07003704 wrid = (((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wqe_index].
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003705 wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
Don Wood6eed5e72009-09-05 20:36:39 -07003706 ((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wqe_index].
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003707 wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX])));
Don Wood6eed5e72009-09-05 20:36:39 -07003708 entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wqe_index].
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003709 wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX]);
3710
Don Wood6eed5e72009-09-05 20:36:39 -07003711 switch (le32_to_cpu(nesqp->hwqp.sq_vbase[wqe_index].
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003712 wqe_words[NES_IWARP_SQ_WQE_MISC_IDX]) & 0x3f) {
3713 case NES_IWARP_SQ_OP_RDMAW:
3714 nes_debug(NES_DBG_CQ, "Operation = RDMA WRITE.\n");
3715 entry->opcode = IB_WC_RDMA_WRITE;
3716 break;
3717 case NES_IWARP_SQ_OP_RDMAR:
3718 nes_debug(NES_DBG_CQ, "Operation = RDMA READ.\n");
3719 entry->opcode = IB_WC_RDMA_READ;
Don Wood6eed5e72009-09-05 20:36:39 -07003720 entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wqe_index].
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003721 wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX]);
3722 break;
3723 case NES_IWARP_SQ_OP_SENDINV:
3724 case NES_IWARP_SQ_OP_SENDSEINV:
3725 case NES_IWARP_SQ_OP_SEND:
3726 case NES_IWARP_SQ_OP_SENDSE:
3727 nes_debug(NES_DBG_CQ, "Operation = Send.\n");
3728 entry->opcode = IB_WC_SEND;
3729 break;
Chien Tung649fe4a2009-12-09 13:51:37 -08003730 case NES_IWARP_SQ_OP_LOCINV:
Tatyana Nikolova4a4b03f2012-01-06 18:17:19 -06003731 entry->opcode = IB_WC_LOCAL_INV;
Chien Tung649fe4a2009-12-09 13:51:37 -08003732 break;
Chien Tunge293a262009-12-09 15:21:54 -08003733 case NES_IWARP_SQ_OP_FAST_REG:
3734 entry->opcode = IB_WC_FAST_REG_MR;
3735 break;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003736 }
Don Wood6eed5e72009-09-05 20:36:39 -07003737
3738 nesqp->hwqp.sq_tail = (wqe_index+1)&(nesqp->hwqp.sq_size - 1);
3739 if ((entry->status != IB_WC_SUCCESS) && (nesqp->hwqp.sq_tail != nesqp->hwqp.sq_head)) {
3740 move_cq_head = 0;
3741 wq_tail = nesqp->hwqp.sq_tail;
3742 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003743 } else {
3744 /* Working on a RQ Completion*/
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003745 entry->byte_len = le32_to_cpu(cqe.cqe_words[NES_CQE_PAYLOAD_LENGTH_IDX]);
Don Wood6eed5e72009-09-05 20:36:39 -07003746 wrid = ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wqe_index].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_LOW_IDX]))) |
3747 ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wqe_index].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX]))<<32);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003748 entry->opcode = IB_WC_RECV;
Don Wood6eed5e72009-09-05 20:36:39 -07003749
3750 nesqp->hwqp.rq_tail = (wqe_index+1)&(nesqp->hwqp.rq_size - 1);
3751 if ((entry->status != IB_WC_SUCCESS) && (nesqp->hwqp.rq_tail != nesqp->hwqp.rq_head)) {
3752 move_cq_head = 0;
3753 wq_tail = nesqp->hwqp.rq_tail;
3754 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003755 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003756
Don Wood5ee21fe2009-09-05 20:36:37 -07003757 entry->wr_id = wrid;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003758 entry++;
Don Wood5ee21fe2009-09-05 20:36:37 -07003759 cqe_count++;
3760 }
3761
Don Wood6eed5e72009-09-05 20:36:39 -07003762 if (move_cq_head) {
3763 nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
3764 if (++head >= cq_size)
3765 head = 0;
3766 nescq->polled_completions++;
Don Wood5ee21fe2009-09-05 20:36:37 -07003767
Don Wood6eed5e72009-09-05 20:36:39 -07003768 if ((nescq->polled_completions > (cq_size / 2)) ||
3769 (nescq->polled_completions == 255)) {
3770 nes_debug(NES_DBG_CQ, "CQ%u Issuing CQE Allocate since more than half of cqes"
Don Wood5ee21fe2009-09-05 20:36:37 -07003771 " are pending %u of %u.\n",
3772 nescq->hw_cq.cq_number, nescq->polled_completions, cq_size);
Don Wood6eed5e72009-09-05 20:36:39 -07003773 nes_write32(nesdev->regs+NES_CQE_ALLOC,
Don Wood5ee21fe2009-09-05 20:36:37 -07003774 nescq->hw_cq.cq_number | (nescq->polled_completions << 16));
Don Wood6eed5e72009-09-05 20:36:39 -07003775 nescq->polled_completions = 0;
3776 }
3777 } else {
3778 /* Update the wqe index and set status to flush */
3779 wqe_index = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
3780 wqe_index = (wqe_index & (~(nesdev->nesadapter->max_qp_wr - 1))) | wq_tail;
3781 nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] =
3782 cpu_to_le32(wqe_index);
3783 move_cq_head = 1; /* ready for next pass */
Don Wood5ee21fe2009-09-05 20:36:37 -07003784 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003785 }
3786
3787 if (nescq->polled_completions) {
3788 nes_write32(nesdev->regs+NES_CQE_ALLOC,
3789 nescq->hw_cq.cq_number | (nescq->polled_completions << 16));
3790 nescq->polled_completions = 0;
3791 }
3792
3793 nescq->hw_cq.cq_head = head;
3794 nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n",
3795 cqe_count, nescq->hw_cq.cq_number);
3796
Ilpo Järvinen5880ff12008-10-30 13:39:43 +02003797 spin_unlock_irqrestore(&nescq->lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003798
3799 return cqe_count;
3800}
3801
3802
3803/**
3804 * nes_req_notify_cq
3805 */
3806static int nes_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags)
3807 {
3808 struct nes_vnic *nesvnic = to_nesvnic(ibcq->device);
3809 struct nes_device *nesdev = nesvnic->nesdev;
3810 struct nes_cq *nescq = to_nescq(ibcq);
3811 u32 cq_arm;
3812
3813 nes_debug(NES_DBG_CQ, "Requesting notification for CQ%u.\n",
3814 nescq->hw_cq.cq_number);
3815
3816 cq_arm = nescq->hw_cq.cq_number;
3817 if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_NEXT_COMP)
3818 cq_arm |= NES_CQE_ALLOC_NOTIFY_NEXT;
3819 else if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED)
3820 cq_arm |= NES_CQE_ALLOC_NOTIFY_SE;
3821 else
3822 return -EINVAL;
3823
3824 nes_write32(nesdev->regs+NES_CQE_ALLOC, cq_arm);
3825 nes_read32(nesdev->regs+NES_CQE_ALLOC);
3826
3827 return 0;
3828}
3829
Ira Weiny77386132015-05-13 20:02:58 -04003830static int nes_port_immutable(struct ib_device *ibdev, u8 port_num,
3831 struct ib_port_immutable *immutable)
3832{
3833 struct ib_port_attr attr;
3834 int err;
3835
3836 err = nes_query_port(ibdev, port_num, &attr);
3837 if (err)
3838 return err;
3839
3840 immutable->pkey_tbl_len = attr.pkey_tbl_len;
3841 immutable->gid_tbl_len = attr.gid_tbl_len;
Ira Weinyf9b22e32015-05-13 20:02:59 -04003842 immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
Ira Weiny77386132015-05-13 20:02:58 -04003843
3844 return 0;
3845}
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003846
3847/**
3848 * nes_init_ofa_device
3849 */
3850struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
3851{
3852 struct nes_ib_device *nesibdev;
3853 struct nes_vnic *nesvnic = netdev_priv(netdev);
3854 struct nes_device *nesdev = nesvnic->nesdev;
3855
3856 nesibdev = (struct nes_ib_device *)ib_alloc_device(sizeof(struct nes_ib_device));
3857 if (nesibdev == NULL) {
3858 return NULL;
3859 }
3860 strlcpy(nesibdev->ibdev.name, "nes%d", IB_DEVICE_NAME_MAX);
3861 nesibdev->ibdev.owner = THIS_MODULE;
3862
3863 nesibdev->ibdev.node_type = RDMA_NODE_RNIC;
3864 memset(&nesibdev->ibdev.node_guid, 0, sizeof(nesibdev->ibdev.node_guid));
3865 memcpy(&nesibdev->ibdev.node_guid, netdev->dev_addr, 6);
3866
3867 nesibdev->ibdev.uverbs_cmd_mask =
3868 (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
3869 (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
3870 (1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
3871 (1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
3872 (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
3873 (1ull << IB_USER_VERBS_CMD_REG_MR) |
3874 (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
3875 (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
3876 (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
3877 (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
3878 (1ull << IB_USER_VERBS_CMD_CREATE_AH) |
3879 (1ull << IB_USER_VERBS_CMD_DESTROY_AH) |
3880 (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
3881 (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
3882 (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
3883 (1ull << IB_USER_VERBS_CMD_POLL_CQ) |
3884 (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
3885 (1ull << IB_USER_VERBS_CMD_ALLOC_MW) |
3886 (1ull << IB_USER_VERBS_CMD_BIND_MW) |
3887 (1ull << IB_USER_VERBS_CMD_DEALLOC_MW) |
3888 (1ull << IB_USER_VERBS_CMD_POST_RECV) |
3889 (1ull << IB_USER_VERBS_CMD_POST_SEND);
3890
3891 nesibdev->ibdev.phys_port_cnt = 1;
3892 nesibdev->ibdev.num_comp_vectors = 1;
3893 nesibdev->ibdev.dma_device = &nesdev->pcidev->dev;
Tony Jonesf4e91eb2008-02-22 00:13:36 +01003894 nesibdev->ibdev.dev.parent = &nesdev->pcidev->dev;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003895 nesibdev->ibdev.query_device = nes_query_device;
3896 nesibdev->ibdev.query_port = nes_query_port;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003897 nesibdev->ibdev.query_pkey = nes_query_pkey;
3898 nesibdev->ibdev.query_gid = nes_query_gid;
3899 nesibdev->ibdev.alloc_ucontext = nes_alloc_ucontext;
3900 nesibdev->ibdev.dealloc_ucontext = nes_dealloc_ucontext;
3901 nesibdev->ibdev.mmap = nes_mmap;
3902 nesibdev->ibdev.alloc_pd = nes_alloc_pd;
3903 nesibdev->ibdev.dealloc_pd = nes_dealloc_pd;
3904 nesibdev->ibdev.create_ah = nes_create_ah;
3905 nesibdev->ibdev.destroy_ah = nes_destroy_ah;
3906 nesibdev->ibdev.create_qp = nes_create_qp;
3907 nesibdev->ibdev.modify_qp = nes_modify_qp;
3908 nesibdev->ibdev.query_qp = nes_query_qp;
3909 nesibdev->ibdev.destroy_qp = nes_destroy_qp;
3910 nesibdev->ibdev.create_cq = nes_create_cq;
3911 nesibdev->ibdev.destroy_cq = nes_destroy_cq;
3912 nesibdev->ibdev.poll_cq = nes_poll_cq;
3913 nesibdev->ibdev.get_dma_mr = nes_get_dma_mr;
3914 nesibdev->ibdev.reg_phys_mr = nes_reg_phys_mr;
3915 nesibdev->ibdev.reg_user_mr = nes_reg_user_mr;
3916 nesibdev->ibdev.dereg_mr = nes_dereg_mr;
3917 nesibdev->ibdev.alloc_mw = nes_alloc_mw;
3918 nesibdev->ibdev.dealloc_mw = nes_dealloc_mw;
3919 nesibdev->ibdev.bind_mw = nes_bind_mw;
3920
Chien Tunge293a262009-12-09 15:21:54 -08003921 nesibdev->ibdev.alloc_fast_reg_mr = nes_alloc_fast_reg_mr;
3922 nesibdev->ibdev.alloc_fast_reg_page_list = nes_alloc_fast_reg_page_list;
3923 nesibdev->ibdev.free_fast_reg_page_list = nes_free_fast_reg_page_list;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003924
3925 nesibdev->ibdev.attach_mcast = nes_multicast_attach;
3926 nesibdev->ibdev.detach_mcast = nes_multicast_detach;
3927 nesibdev->ibdev.process_mad = nes_process_mad;
3928
3929 nesibdev->ibdev.req_notify_cq = nes_req_notify_cq;
3930 nesibdev->ibdev.post_send = nes_post_send;
3931 nesibdev->ibdev.post_recv = nes_post_recv;
3932
3933 nesibdev->ibdev.iwcm = kzalloc(sizeof(*nesibdev->ibdev.iwcm), GFP_KERNEL);
3934 if (nesibdev->ibdev.iwcm == NULL) {
3935 ib_dealloc_device(&nesibdev->ibdev);
3936 return NULL;
3937 }
3938 nesibdev->ibdev.iwcm->add_ref = nes_add_ref;
3939 nesibdev->ibdev.iwcm->rem_ref = nes_rem_ref;
3940 nesibdev->ibdev.iwcm->get_qp = nes_get_qp;
3941 nesibdev->ibdev.iwcm->connect = nes_connect;
3942 nesibdev->ibdev.iwcm->accept = nes_accept;
3943 nesibdev->ibdev.iwcm->reject = nes_reject;
3944 nesibdev->ibdev.iwcm->create_listen = nes_create_listen;
3945 nesibdev->ibdev.iwcm->destroy_listen = nes_destroy_listen;
Ira Weiny77386132015-05-13 20:02:58 -04003946 nesibdev->ibdev.get_port_immutable = nes_port_immutable;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003947
3948 return nesibdev;
3949}
3950
Maciej Sosnowskiea623452010-11-24 17:29:38 +00003951
3952/**
3953 * nes_handle_delayed_event
3954 */
3955static void nes_handle_delayed_event(unsigned long data)
3956{
3957 struct nes_vnic *nesvnic = (void *) data;
3958
3959 if (nesvnic->delayed_event != nesvnic->last_dispatched_event) {
3960 struct ib_event event;
3961
3962 event.device = &nesvnic->nesibdev->ibdev;
3963 if (!event.device)
3964 goto stop_timer;
3965 event.event = nesvnic->delayed_event;
3966 event.element.port_num = nesvnic->logical_port + 1;
3967 ib_dispatch_event(&event);
3968 }
3969
3970stop_timer:
3971 nesvnic->event_timer.function = NULL;
3972}
3973
3974
Faisal Latifcd6860e2010-07-04 00:17:59 +00003975void nes_port_ibevent(struct nes_vnic *nesvnic)
3976{
3977 struct nes_ib_device *nesibdev = nesvnic->nesibdev;
3978 struct nes_device *nesdev = nesvnic->nesdev;
3979 struct ib_event event;
3980 event.device = &nesibdev->ibdev;
3981 event.element.port_num = nesvnic->logical_port + 1;
3982 event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
Maciej Sosnowskiea623452010-11-24 17:29:38 +00003983
3984 if (!nesvnic->event_timer.function) {
3985 ib_dispatch_event(&event);
3986 nesvnic->last_dispatched_event = event.event;
3987 nesvnic->event_timer.function = nes_handle_delayed_event;
3988 nesvnic->event_timer.data = (unsigned long) nesvnic;
3989 nesvnic->event_timer.expires = jiffies + NES_EVENT_DELAY;
3990 add_timer(&nesvnic->event_timer);
3991 } else {
3992 mod_timer(&nesvnic->event_timer, jiffies + NES_EVENT_DELAY);
3993 }
3994 nesvnic->delayed_event = event.event;
Faisal Latifcd6860e2010-07-04 00:17:59 +00003995}
3996
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003997
3998/**
3999 * nes_destroy_ofa_device
4000 */
4001void nes_destroy_ofa_device(struct nes_ib_device *nesibdev)
4002{
4003 if (nesibdev == NULL)
4004 return;
4005
4006 nes_unregister_ofa_device(nesibdev);
4007
4008 kfree(nesibdev->ibdev.iwcm);
4009 ib_dealloc_device(&nesibdev->ibdev);
4010}
4011
4012
4013/**
4014 * nes_register_ofa_device
4015 */
4016int nes_register_ofa_device(struct nes_ib_device *nesibdev)
4017{
4018 struct nes_vnic *nesvnic = nesibdev->nesvnic;
4019 struct nes_device *nesdev = nesvnic->nesdev;
4020 struct nes_adapter *nesadapter = nesdev->nesadapter;
4021 int i, ret;
4022
Ralph Campbell9a6edb62010-05-06 17:03:25 -07004023 ret = ib_register_device(&nesvnic->nesibdev->ibdev, NULL);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08004024 if (ret) {
4025 return ret;
4026 }
4027
4028 /* Get the resources allocated to this device */
4029 nesibdev->max_cq = (nesadapter->max_cq-NES_FIRST_QPN) / nesadapter->port_count;
4030 nesibdev->max_mr = nesadapter->max_mr / nesadapter->port_count;
4031 nesibdev->max_qp = (nesadapter->max_qp-NES_FIRST_QPN) / nesadapter->port_count;
4032 nesibdev->max_pd = nesadapter->max_pd / nesadapter->port_count;
4033
Tony Jonesf4e91eb2008-02-22 00:13:36 +01004034 for (i = 0; i < ARRAY_SIZE(nes_dev_attributes); ++i) {
4035 ret = device_create_file(&nesibdev->ibdev.dev, nes_dev_attributes[i]);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08004036 if (ret) {
4037 while (i > 0) {
4038 i--;
Tony Jonesf4e91eb2008-02-22 00:13:36 +01004039 device_remove_file(&nesibdev->ibdev.dev,
4040 nes_dev_attributes[i]);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08004041 }
4042 ib_unregister_device(&nesibdev->ibdev);
4043 return ret;
4044 }
4045 }
4046
4047 nesvnic->of_device_registered = 1;
4048
4049 return 0;
4050}
4051
4052
4053/**
4054 * nes_unregister_ofa_device
4055 */
Roland Dreier1a855fb2008-04-16 21:01:09 -07004056static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08004057{
4058 struct nes_vnic *nesvnic = nesibdev->nesvnic;
4059 int i;
4060
Tony Jonesf4e91eb2008-02-22 00:13:36 +01004061 for (i = 0; i < ARRAY_SIZE(nes_dev_attributes); ++i) {
4062 device_remove_file(&nesibdev->ibdev.dev, nes_dev_attributes[i]);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08004063 }
4064
4065 if (nesvnic->of_device_registered) {
4066 ib_unregister_device(&nesibdev->ibdev);
4067 }
4068
4069 nesvnic->of_device_registered = 0;
4070}