XXXX introduce drv_sectohz
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24 /*
25 * Copyright (c) 2005 SilverStorm Technologies, Inc. All rights reserved.
26 *
27 * This software is available to you under a choice of one of two
28 * licenses. You may choose to be licensed under the terms of the GNU
29 * General Public License (GPL) Version 2, available from the file
30 * COPYING in the main directory of this source tree, or the
31 * OpenIB.org BSD license below:
32 *
33 * Redistribution and use in source and binary forms, with or
34 * without modification, are permitted provided that the following
35 * conditions are met:
36 *
37 * - Redistributions of source code must retain the above
38 * copyright notice, this list of conditions and the following
39 * disclaimer.
40 *
41 * - Redistributions in binary form must reproduce the above
42 * copyright notice, this list of conditions and the following
43 * disclaimer in the documentation and/or other materials
44 * provided with the distribution.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
50 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
51 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
52 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
53 * SOFTWARE.
54 *
55 */
56 /*
57 * Sun elects to include this software in Sun product
58 * under the OpenIB BSD license.
59 *
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
62 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
65 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
66 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
67 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
68 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
69 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
70 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
71 * POSSIBILITY OF SUCH DAMAGE.
72 */
73
74 #include <sys/types.h>
75 #include <sys/ddi.h>
76 #include <sys/sunddi.h>
77 #include <sys/ib/clients/rds/rdsib_cm.h>
78 #include <sys/ib/clients/rds/rdsib_ib.h>
79 #include <sys/ib/clients/rds/rdsib_buf.h>
80 #include <sys/ib/clients/rds/rdsib_ep.h>
81 #include <sys/ib/clients/rds/rds_kstat.h>
82
83 static void rds_async_handler(void *clntp, ibt_hca_hdl_t hdl,
84 ibt_async_code_t code, ibt_async_event_t *event);
85
86 static struct ibt_clnt_modinfo_s rds_ib_modinfo = {
87 IBTI_V_CURR,
88 IBT_NETWORK,
89 rds_async_handler,
90 NULL,
91 "RDS"
92 };
93
94 /* performance tunables */
95 uint_t rds_no_interrupts = 0;
96 uint_t rds_poll_percent_full = 25;
97 uint_t rds_wc_signal = IBT_NEXT_SOLICITED;
98 uint_t rds_waittime_ms = 100; /* ms */
99
100 extern dev_info_t *rdsib_dev_info;
101 extern void rds_close_sessions();
102
103 static void
104 rdsib_validate_chan_sizes(ibt_hca_attr_t *hattrp)
105 {
106 /* The SQ size should not be more than that supported by the HCA */
107 if (((MaxDataSendBuffers + RDS_NUM_ACKS) > hattrp->hca_max_chan_sz) ||
108 ((MaxDataSendBuffers + RDS_NUM_ACKS) > hattrp->hca_max_cq_sz)) {
109 RDS_DPRINTF2("RDSIB", "MaxDataSendBuffers + %d is greater "
110 "than that supported by the HCA driver "
111 "(%d + %d > %d or %d), lowering it to a supported value.",
112 RDS_NUM_ACKS, MaxDataSendBuffers, RDS_NUM_ACKS,
113 hattrp->hca_max_chan_sz, hattrp->hca_max_cq_sz);
114
115 MaxDataSendBuffers = (hattrp->hca_max_chan_sz >
116 hattrp->hca_max_cq_sz) ?
117 hattrp->hca_max_cq_sz - RDS_NUM_ACKS :
118 hattrp->hca_max_chan_sz - RDS_NUM_ACKS;
119 }
120
121 /* The RQ size should not be more than that supported by the HCA */
122 if ((MaxDataRecvBuffers > hattrp->hca_max_chan_sz) ||
123 (MaxDataRecvBuffers > hattrp->hca_max_cq_sz)) {
124 RDS_DPRINTF2("RDSIB", "MaxDataRecvBuffers is greater than that "
125 "supported by the HCA driver (%d > %d or %d), lowering it "
126 "to a supported value.", MaxDataRecvBuffers,
127 hattrp->hca_max_chan_sz, hattrp->hca_max_cq_sz);
128
129 MaxDataRecvBuffers = (hattrp->hca_max_chan_sz >
130 hattrp->hca_max_cq_sz) ? hattrp->hca_max_cq_sz :
131 hattrp->hca_max_chan_sz;
132 }
133
134 /* The SQ size should not be more than that supported by the HCA */
135 if ((MaxCtrlSendBuffers > hattrp->hca_max_chan_sz) ||
136 (MaxCtrlSendBuffers > hattrp->hca_max_cq_sz)) {
137 RDS_DPRINTF2("RDSIB", "MaxCtrlSendBuffers is greater than that "
138 "supported by the HCA driver (%d > %d or %d), lowering it "
139 "to a supported value.", MaxCtrlSendBuffers,
140 hattrp->hca_max_chan_sz, hattrp->hca_max_cq_sz);
141
142 MaxCtrlSendBuffers = (hattrp->hca_max_chan_sz >
143 hattrp->hca_max_cq_sz) ? hattrp->hca_max_cq_sz :
144 hattrp->hca_max_chan_sz;
145 }
146
147 /* The RQ size should not be more than that supported by the HCA */
148 if ((MaxCtrlRecvBuffers > hattrp->hca_max_chan_sz) ||
149 (MaxCtrlRecvBuffers > hattrp->hca_max_cq_sz)) {
150 RDS_DPRINTF2("RDSIB", "MaxCtrlRecvBuffers is greater than that "
151 "supported by the HCA driver (%d > %d or %d), lowering it "
152 "to a supported value.", MaxCtrlRecvBuffers,
153 hattrp->hca_max_chan_sz, hattrp->hca_max_cq_sz);
154
155 MaxCtrlRecvBuffers = (hattrp->hca_max_chan_sz >
156 hattrp->hca_max_cq_sz) ? hattrp->hca_max_cq_sz :
157 hattrp->hca_max_chan_sz;
158 }
159
160 /* The MaxRecvMemory should be less than that supported by the HCA */
161 if ((NDataRX * RdsPktSize) > hattrp->hca_max_memr_len) {
162 RDS_DPRINTF2("RDSIB", "MaxRecvMemory is greater than that "
163 "supported by the HCA driver (%d > %d), lowering it to %d",
164 NDataRX * RdsPktSize, hattrp->hca_max_memr_len,
165 hattrp->hca_max_memr_len);
166
167 NDataRX = hattrp->hca_max_memr_len/RdsPktSize;
168 }
169 }
170
171 /* Return hcap, given the hca guid */
172 rds_hca_t *
173 rds_lkup_hca(ib_guid_t hca_guid)
174 {
175 rds_hca_t *hcap;
176
177 RDS_DPRINTF4("rds_lkup_hca", "Enter: statep: 0x%p "
178 "guid: %llx", rdsib_statep, hca_guid);
179
180 rw_enter(&rdsib_statep->rds_hca_lock, RW_READER);
181
182 hcap = rdsib_statep->rds_hcalistp;
183 while ((hcap != NULL) && (hcap->hca_guid != hca_guid)) {
184 hcap = hcap->hca_nextp;
185 }
186
187 rw_exit(&rdsib_statep->rds_hca_lock);
188
189 RDS_DPRINTF4("rds_lkup_hca", "return");
190
191 return (hcap);
192 }
193
194 void rds_randomize_qps(rds_hca_t *hcap);
195
196 static rds_hca_t *
197 rdsib_init_hca(ib_guid_t hca_guid)
198 {
199 rds_hca_t *hcap;
200 boolean_t alloc = B_FALSE;
201 int ret;
202
203 RDS_DPRINTF2("rdsib_init_hca", "enter: HCA 0x%llx", hca_guid);
204
205 /* Do a HCA lookup */
206 hcap = rds_lkup_hca(hca_guid);
207
208 if (hcap != NULL && hcap->hca_hdl != NULL) {
209 /*
210 * This can happen if we get IBT_HCA_ATTACH_EVENT on an HCA
211 * that we have already opened. Just return NULL so that
212 * we'll not end up reinitializing the HCA again.
213 */
214 RDS_DPRINTF2("rdsib_init_hca", "HCA already initialized");
215 return (NULL);
216 }
217
218 if (hcap == NULL) {
219 RDS_DPRINTF2("rdsib_init_hca", "New HCA is added");
220 hcap = (rds_hca_t *)kmem_zalloc(sizeof (rds_hca_t), KM_SLEEP);
221 alloc = B_TRUE;
222 }
223
224 hcap->hca_guid = hca_guid;
225 ret = ibt_open_hca(rdsib_statep->rds_ibhdl, hca_guid,
226 &hcap->hca_hdl);
227 if (ret != IBT_SUCCESS) {
228 if (ret == IBT_HCA_IN_USE) {
229 RDS_DPRINTF2("rdsib_init_hca",
230 "ibt_open_hca: 0x%llx returned IBT_HCA_IN_USE",
231 hca_guid);
232 } else {
233 RDS_DPRINTF2("rdsib_init_hca",
234 "ibt_open_hca: 0x%llx failed: %d", hca_guid, ret);
235 }
236 if (alloc == B_TRUE) {
237 kmem_free(hcap, sizeof (rds_hca_t));
238 }
239 return (NULL);
240 }
241
242 ret = ibt_query_hca(hcap->hca_hdl, &hcap->hca_attr);
243 if (ret != IBT_SUCCESS) {
244 RDS_DPRINTF2("rdsib_init_hca",
245 "Query HCA: 0x%llx failed: %d", hca_guid, ret);
246 ret = ibt_close_hca(hcap->hca_hdl);
247 ASSERT(ret == IBT_SUCCESS);
248 if (alloc == B_TRUE) {
249 kmem_free(hcap, sizeof (rds_hca_t));
250 } else {
251 hcap->hca_hdl = NULL;
252 }
253 return (NULL);
254 }
255
256 ret = ibt_query_hca_ports(hcap->hca_hdl, 0,
257 &hcap->hca_pinfop, &hcap->hca_nports, &hcap->hca_pinfo_sz);
258 if (ret != IBT_SUCCESS) {
259 RDS_DPRINTF2("rdsib_init_hca",
260 "Query HCA 0x%llx ports failed: %d", hca_guid,
261 ret);
262 ret = ibt_close_hca(hcap->hca_hdl);
263 hcap->hca_hdl = NULL;
264 ASSERT(ret == IBT_SUCCESS);
265 if (alloc == B_TRUE) {
266 kmem_free(hcap, sizeof (rds_hca_t));
267 } else {
268 hcap->hca_hdl = NULL;
269 }
270 return (NULL);
271 }
272
273 /* Only one PD per HCA is allocated, so do it here */
274 ret = ibt_alloc_pd(hcap->hca_hdl, IBT_PD_NO_FLAGS,
275 &hcap->hca_pdhdl);
276 if (ret != IBT_SUCCESS) {
277 RDS_DPRINTF2("rdsib_init_hca",
278 "ibt_alloc_pd 0x%llx failed: %d", hca_guid, ret);
279 (void) ibt_free_portinfo(hcap->hca_pinfop,
280 hcap->hca_pinfo_sz);
281 ret = ibt_close_hca(hcap->hca_hdl);
282 ASSERT(ret == IBT_SUCCESS);
283 hcap->hca_hdl = NULL;
284 if (alloc == B_TRUE) {
285 kmem_free(hcap, sizeof (rds_hca_t));
286 } else {
287 hcap->hca_hdl = NULL;
288 }
289 return (NULL);
290 }
291
292 rdsib_validate_chan_sizes(&hcap->hca_attr);
293
294 /* To minimize stale connections after ungraceful reboots */
295 rds_randomize_qps(hcap);
296
297 rw_enter(&rdsib_statep->rds_hca_lock, RW_WRITER);
298 hcap->hca_state = RDS_HCA_STATE_OPEN;
299 if (alloc == B_TRUE) {
300 /* this is a new HCA, add it to the list */
301 rdsib_statep->rds_nhcas++;
302 hcap->hca_nextp = rdsib_statep->rds_hcalistp;
303 rdsib_statep->rds_hcalistp = hcap;
304 }
305 rw_exit(&rdsib_statep->rds_hca_lock);
306
307 RDS_DPRINTF2("rdsib_init_hca", "return: HCA 0x%llx", hca_guid);
308
309 return (hcap);
310 }
311
312 /*
313 * Called from attach
314 */
315 int
316 rdsib_initialize_ib()
317 {
318 ib_guid_t *guidp;
319 rds_hca_t *hcap;
320 uint_t ix, hcaix, nhcas;
321 int ret;
322
323 RDS_DPRINTF2("rdsib_initialize_ib", "enter: statep %p", rdsib_statep);
324
325 ASSERT(rdsib_statep != NULL);
326 if (rdsib_statep == NULL) {
327 RDS_DPRINTF1("rdsib_initialize_ib",
328 "RDS Statep not initialized");
329 return (-1);
330 }
331
332 /* How many hcas are there? */
333 nhcas = ibt_get_hca_list(&guidp);
334 if (nhcas == 0) {
335 RDS_DPRINTF2("rdsib_initialize_ib", "No IB HCAs Available");
336 return (-1);
337 }
338
339 RDS_DPRINTF3("rdsib_initialize_ib", "Number of HCAs: %d", nhcas);
340
341 /* Register with IBTF */
342 ret = ibt_attach(&rds_ib_modinfo, rdsib_dev_info, rdsib_statep,
343 &rdsib_statep->rds_ibhdl);
344 if (ret != IBT_SUCCESS) {
345 RDS_DPRINTF2("rdsib_initialize_ib", "ibt_attach failed: %d",
346 ret);
347 (void) ibt_free_hca_list(guidp, nhcas);
348 return (-1);
349 }
350
351 /*
352 * Open each HCA and gather its information. Don't care about HCAs
353 * that cannot be opened. It is OK as long as atleast one HCA can be
354 * opened.
355 * Initialize a HCA only if all the information is available.
356 */
357 for (ix = 0, hcaix = 0; ix < nhcas; ix++) {
358 RDS_DPRINTF3(LABEL, "Open HCA: 0x%llx", guidp[ix]);
359
360 hcap = rdsib_init_hca(guidp[ix]);
361 if (hcap != NULL) hcaix++;
362 }
363
364 /* free the HCA list, we are done with it */
365 (void) ibt_free_hca_list(guidp, nhcas);
366
367 if (hcaix == 0) {
368 /* Failed to Initialize even one HCA */
369 RDS_DPRINTF2("rdsib_initialize_ib", "No HCAs are initialized");
370 (void) ibt_detach(rdsib_statep->rds_ibhdl);
371 rdsib_statep->rds_ibhdl = NULL;
372 return (-1);
373 }
374
375 if (hcaix < nhcas) {
376 RDS_DPRINTF2("rdsib_open_ib", "HCAs %d/%d failed to initialize",
377 (nhcas - hcaix), nhcas);
378 }
379
380 RDS_DPRINTF2("rdsib_initialize_ib", "return: statep %p", rdsib_statep);
381
382 return (0);
383 }
384
385 /*
386 * Called from detach
387 */
388 void
389 rdsib_deinitialize_ib()
390 {
391 rds_hca_t *hcap, *nextp;
392 int ret;
393
394 RDS_DPRINTF2("rdsib_deinitialize_ib", "enter: statep %p", rdsib_statep);
395
396 /* close and destroy all the sessions */
397 rds_close_sessions(NULL);
398
399 /* Release all HCA resources */
400 rw_enter(&rdsib_statep->rds_hca_lock, RW_WRITER);
401 RDS_DPRINTF2("rdsib_deinitialize_ib", "HCA List: %p, NHCA: %d",
402 rdsib_statep->rds_hcalistp, rdsib_statep->rds_nhcas);
403 hcap = rdsib_statep->rds_hcalistp;
404 rdsib_statep->rds_hcalistp = NULL;
405 rdsib_statep->rds_nhcas = 0;
406 rw_exit(&rdsib_statep->rds_hca_lock);
407
408 while (hcap != NULL) {
409 nextp = hcap->hca_nextp;
410
411 if (hcap->hca_hdl != NULL) {
412 ret = ibt_free_pd(hcap->hca_hdl, hcap->hca_pdhdl);
413 ASSERT(ret == IBT_SUCCESS);
414
415 (void) ibt_free_portinfo(hcap->hca_pinfop,
416 hcap->hca_pinfo_sz);
417
418 ret = ibt_close_hca(hcap->hca_hdl);
419 ASSERT(ret == IBT_SUCCESS);
420 }
421
422 kmem_free(hcap, sizeof (rds_hca_t));
423 hcap = nextp;
424 }
425
426 /* Deregister with IBTF */
427 if (rdsib_statep->rds_ibhdl != NULL) {
428 (void) ibt_detach(rdsib_statep->rds_ibhdl);
429 rdsib_statep->rds_ibhdl = NULL;
430 }
431
432 RDS_DPRINTF2("rdsib_deinitialize_ib", "return: statep %p",
433 rdsib_statep);
434 }
435
436 /*
437 * Called on open of first RDS socket
438 */
439 int
440 rdsib_open_ib()
441 {
442 int ret;
443
444 RDS_DPRINTF2("rdsib_open_ib", "enter: statep %p", rdsib_statep);
445
446 /* Enable incoming connection requests */
447 if (rdsib_statep->rds_srvhdl == NULL) {
448 rdsib_statep->rds_srvhdl =
449 rds_register_service(rdsib_statep->rds_ibhdl);
450 if (rdsib_statep->rds_srvhdl == NULL) {
451 RDS_DPRINTF2("rdsib_open_ib",
452 "Service registration failed");
453 return (-1);
454 } else {
455 /* bind the service on all available ports */
456 ret = rds_bind_service(rdsib_statep);
457 if (ret != 0) {
458 RDS_DPRINTF2("rdsib_open_ib",
459 "Bind service failed: %d", ret);
460 }
461 }
462 }
463
464 RDS_DPRINTF2("rdsib_open_ib", "return: statep %p", rdsib_statep);
465
466 return (0);
467 }
468
469 /*
470 * Called when all ports are closed.
471 */
472 void
473 rdsib_close_ib()
474 {
475 int ret;
476
477 RDS_DPRINTF2("rdsib_close_ib", "enter: statep %p", rdsib_statep);
478
479 /* Disable incoming connection requests */
480 if (rdsib_statep->rds_srvhdl != NULL) {
481 ret = ibt_unbind_all_services(rdsib_statep->rds_srvhdl);
482 if (ret != 0) {
483 RDS_DPRINTF2("rdsib_close_ib",
484 "ibt_unbind_all_services failed: %d\n", ret);
485 }
486 ret = ibt_deregister_service(rdsib_statep->rds_ibhdl,
487 rdsib_statep->rds_srvhdl);
488 if (ret != 0) {
489 RDS_DPRINTF2("rdsib_close_ib",
490 "ibt_deregister_service failed: %d\n", ret);
491 } else {
492 rdsib_statep->rds_srvhdl = NULL;
493 }
494 }
495
496 RDS_DPRINTF2("rdsib_close_ib", "return: statep %p", rdsib_statep);
497 }
498
499 /* Return hcap, given the hca guid */
500 rds_hca_t *
501 rds_get_hcap(rds_state_t *statep, ib_guid_t hca_guid)
502 {
503 rds_hca_t *hcap;
504
505 RDS_DPRINTF4("rds_get_hcap", "rds_get_hcap: Enter: statep: 0x%p "
506 "guid: %llx", statep, hca_guid);
507
508 rw_enter(&statep->rds_hca_lock, RW_READER);
509
510 hcap = statep->rds_hcalistp;
511 while ((hcap != NULL) && (hcap->hca_guid != hca_guid)) {
512 hcap = hcap->hca_nextp;
513 }
514
515 /*
516 * don't let anyone use this HCA until the RECV memory
517 * is registered with this HCA
518 */
519 if ((hcap != NULL) &&
520 (hcap->hca_state == RDS_HCA_STATE_MEM_REGISTERED)) {
521 ASSERT(hcap->hca_mrhdl != NULL);
522 rw_exit(&statep->rds_hca_lock);
523 return (hcap);
524 }
525
526 RDS_DPRINTF2("rds_get_hcap",
527 "HCA (0x%p, 0x%llx) is not initialized", hcap, hca_guid);
528 rw_exit(&statep->rds_hca_lock);
529
530 RDS_DPRINTF4("rds_get_hcap", "rds_get_hcap: return");
531
532 return (NULL);
533 }
534
535 /* Return hcap, given a gid */
536 rds_hca_t *
537 rds_gid_to_hcap(rds_state_t *statep, ib_gid_t gid)
538 {
539 rds_hca_t *hcap;
540 uint_t ix;
541
542 RDS_DPRINTF4("rds_gid_to_hcap", "Enter: statep: 0x%p gid: %llx:%llx",
543 statep, gid.gid_prefix, gid.gid_guid);
544
545 rw_enter(&statep->rds_hca_lock, RW_READER);
546
547 hcap = statep->rds_hcalistp;
548 while (hcap != NULL) {
549
550 /*
551 * don't let anyone use this HCA until the RECV memory
552 * is registered with this HCA
553 */
554 if (hcap->hca_state != RDS_HCA_STATE_MEM_REGISTERED) {
555 RDS_DPRINTF3("rds_gid_to_hcap",
556 "HCA (0x%p, 0x%llx) is not initialized",
557 hcap, gid.gid_guid);
558 hcap = hcap->hca_nextp;
559 continue;
560 }
561
562 for (ix = 0; ix < hcap->hca_nports; ix++) {
563 if ((hcap->hca_pinfop[ix].p_sgid_tbl[0].gid_prefix ==
564 gid.gid_prefix) &&
565 (hcap->hca_pinfop[ix].p_sgid_tbl[0].gid_guid ==
566 gid.gid_guid)) {
567 RDS_DPRINTF4("rds_gid_to_hcap",
568 "gid found in hcap: 0x%p", hcap);
569 rw_exit(&statep->rds_hca_lock);
570 return (hcap);
571 }
572 }
573 hcap = hcap->hca_nextp;
574 }
575
576 rw_exit(&statep->rds_hca_lock);
577
578 return (NULL);
579 }
580
581 /* This is called from the send CQ handler */
582 void
583 rds_send_acknowledgement(rds_ep_t *ep)
584 {
585 int ret;
586 uint_t ix;
587
588 RDS_DPRINTF4("rds_send_acknowledgement", "Enter EP(%p)", ep);
589
590 mutex_enter(&ep->ep_lock);
591
592 ASSERT(ep->ep_rdmacnt != 0);
593
594 /*
595 * The previous ACK completed successfully, send the next one
596 * if more messages were received after sending the last ACK
597 */
598 if (ep->ep_rbufid != *(uintptr_t *)(uintptr_t)ep->ep_ackds.ds_va) {
599 *(uintptr_t *)(uintptr_t)ep->ep_ackds.ds_va = ep->ep_rbufid;
600 mutex_exit(&ep->ep_lock);
601
602 /* send acknowledgement */
603 RDS_INCR_TXACKS();
604 ret = ibt_post_send(ep->ep_chanhdl, &ep->ep_ackwr, 1, &ix);
605 if (ret != IBT_SUCCESS) {
606 RDS_DPRINTF2("rds_send_acknowledgement",
607 "EP(%p): ibt_post_send for acknowledgement "
608 "failed: %d, SQ depth: %d",
609 ep, ret, ep->ep_sndpool.pool_nbusy);
610 mutex_enter(&ep->ep_lock);
611 ep->ep_rdmacnt--;
612 mutex_exit(&ep->ep_lock);
613 }
614 } else {
615 /* ACKed all messages, no more to ACK */
616 ep->ep_rdmacnt--;
617 mutex_exit(&ep->ep_lock);
618 return;
619 }
620
621 RDS_DPRINTF4("rds_send_acknowledgement", "Return EP(%p)", ep);
622 }
623
624 static int
625 rds_poll_ctrl_completions(ibt_cq_hdl_t cq, rds_ep_t *ep)
626 {
627 ibt_wc_t wc;
628 uint_t npolled;
629 rds_buf_t *bp;
630 rds_ctrl_pkt_t *cpkt;
631 rds_qp_t *recvqp;
632 int ret = IBT_SUCCESS;
633
634 RDS_DPRINTF4("rds_poll_ctrl_completions", "Enter: EP(%p)", ep);
635
636 bzero(&wc, sizeof (ibt_wc_t));
637 ret = ibt_poll_cq(cq, &wc, 1, &npolled);
638 if (ret != IBT_SUCCESS) {
639 if (ret != IBT_CQ_EMPTY) {
640 RDS_DPRINTF2(LABEL, "EP(%p) CQ(%p): ibt_poll_cq "
641 "returned: %d", ep, cq, ret);
642 } else {
643 RDS_DPRINTF5(LABEL, "EP(%p) CQ(%p): ibt_poll_cq "
644 "returned: IBT_CQ_EMPTY", ep, cq);
645 }
646 return (ret);
647 }
648
649 bp = (rds_buf_t *)(uintptr_t)wc.wc_id;
650
651 if (wc.wc_status != IBT_WC_SUCCESS) {
652 mutex_enter(&ep->ep_recvqp.qp_lock);
653 ep->ep_recvqp.qp_level--;
654 mutex_exit(&ep->ep_recvqp.qp_lock);
655
656 /* Free the buffer */
657 bp->buf_state = RDS_RCVBUF_FREE;
658 rds_free_recv_buf(bp, 1);
659
660 /* Receive completion failure */
661 if (wc.wc_status != IBT_WC_WR_FLUSHED_ERR) {
662 RDS_DPRINTF2("rds_poll_ctrl_completions",
663 "EP(%p) CQ(%p) BP(%p): WC Error Status: %d",
664 ep, cq, wc.wc_id, wc.wc_status);
665 }
666 return (ret);
667 }
668
669 /* there is one less in the RQ */
670 recvqp = &ep->ep_recvqp;
671 mutex_enter(&recvqp->qp_lock);
672 recvqp->qp_level--;
673 if ((recvqp->qp_taskqpending == B_FALSE) &&
674 (recvqp->qp_level <= recvqp->qp_lwm)) {
675 /* Time to post more buffers into the RQ */
676 recvqp->qp_taskqpending = B_TRUE;
677 mutex_exit(&recvqp->qp_lock);
678
679 ret = ddi_taskq_dispatch(rds_taskq,
680 rds_post_recv_buf, (void *)ep->ep_chanhdl, DDI_NOSLEEP);
681 if (ret != DDI_SUCCESS) {
682 RDS_DPRINTF2(LABEL, "ddi_taskq_dispatch failed: %d",
683 ret);
684 mutex_enter(&recvqp->qp_lock);
685 recvqp->qp_taskqpending = B_FALSE;
686 mutex_exit(&recvqp->qp_lock);
687 }
688 } else {
689 mutex_exit(&recvqp->qp_lock);
690 }
691
692 cpkt = (rds_ctrl_pkt_t *)(uintptr_t)bp->buf_ds.ds_va;
693 rds_handle_control_message(ep->ep_sp, cpkt);
694
695 bp->buf_state = RDS_RCVBUF_FREE;
696 rds_free_recv_buf(bp, 1);
697
698 RDS_DPRINTF4("rds_poll_ctrl_completions", "Return: EP(%p)", ep);
699
700 return (ret);
701 }
702
703 #define RDS_POST_FEW_ATATIME 100
704 /* Post recv WRs into the RQ. Assumes the ep->refcnt is already incremented */
705 void
706 rds_post_recv_buf(void *arg)
707 {
708 ibt_channel_hdl_t chanhdl;
709 rds_ep_t *ep;
710 rds_session_t *sp;
711 rds_qp_t *recvqp;
712 rds_bufpool_t *gp;
713 rds_buf_t *bp, *bp1;
714 ibt_recv_wr_t *wrp, wr[RDS_POST_FEW_ATATIME];
715 rds_hca_t *hcap;
716 uint_t npost, nspace, rcv_len;
717 uint_t ix, jx, kx;
718 int ret;
719
720 chanhdl = (ibt_channel_hdl_t)arg;
721 RDS_DPRINTF4("rds_post_recv_buf", "Enter: CHAN(%p)", chanhdl);
722 RDS_INCR_POST_RCV_BUF_CALLS();
723
724 ep = (rds_ep_t *)ibt_get_chan_private(chanhdl);
725 ASSERT(ep != NULL);
726 sp = ep->ep_sp;
727 recvqp = &ep->ep_recvqp;
728
729 RDS_DPRINTF5("rds_post_recv_buf", "EP(%p)", ep);
730
731 /* get the hcap for the HCA hosting this channel */
732 hcap = rds_lkup_hca(ep->ep_hca_guid);
733 if (hcap == NULL) {
734 RDS_DPRINTF2("rds_post_recv_buf", "HCA (0x%llx) not found",
735 ep->ep_hca_guid);
736 return;
737 }
738
739 /* Make sure the session is still connected */
740 rw_enter(&sp->session_lock, RW_READER);
741 if ((sp->session_state != RDS_SESSION_STATE_INIT) &&
742 (sp->session_state != RDS_SESSION_STATE_CONNECTED) &&
743 (sp->session_state != RDS_SESSION_STATE_HCA_CLOSING)) {
744 RDS_DPRINTF2("rds_post_recv_buf", "EP(%p): Session is not "
745 "in active state (%d)", ep, sp->session_state);
746 rw_exit(&sp->session_lock);
747 return;
748 }
749 rw_exit(&sp->session_lock);
750
751 /* how many can be posted */
752 mutex_enter(&recvqp->qp_lock);
753 nspace = recvqp->qp_depth - recvqp->qp_level;
754 if (nspace == 0) {
755 RDS_DPRINTF2("rds_post_recv_buf", "RQ is FULL");
756 recvqp->qp_taskqpending = B_FALSE;
757 mutex_exit(&recvqp->qp_lock);
758 return;
759 }
760 mutex_exit(&recvqp->qp_lock);
761
762 if (ep->ep_type == RDS_EP_TYPE_DATA) {
763 gp = &rds_dpool;
764 rcv_len = RdsPktSize;
765 } else {
766 gp = &rds_cpool;
767 rcv_len = RDS_CTRLPKT_SIZE;
768 }
769
770 bp = rds_get_buf(gp, nspace, &jx);
771 if (bp == NULL) {
772 RDS_DPRINTF2(LABEL, "EP(%p): No Recv buffers available", ep);
773 /* try again later */
774 ret = ddi_taskq_dispatch(rds_taskq, rds_post_recv_buf,
775 (void *)chanhdl, DDI_NOSLEEP);
776 if (ret != DDI_SUCCESS) {
777 RDS_DPRINTF2(LABEL, "ddi_taskq_dispatch failed: %d",
778 ret);
779 mutex_enter(&recvqp->qp_lock);
780 recvqp->qp_taskqpending = B_FALSE;
781 mutex_exit(&recvqp->qp_lock);
782 }
783 return;
784 }
785
786 if (jx != nspace) {
787 RDS_DPRINTF2(LABEL, "EP(%p): Recv buffers "
788 "needed: %d available: %d", ep, nspace, jx);
789 nspace = jx;
790 }
791
792 bp1 = bp;
793 for (ix = 0; ix < nspace; ix++) {
794 bp1->buf_ep = ep;
795 ASSERT(bp1->buf_state == RDS_RCVBUF_FREE);
796 bp1->buf_state = RDS_RCVBUF_POSTED;
797 bp1->buf_ds.ds_key = hcap->hca_lkey;
798 bp1->buf_ds.ds_len = rcv_len;
799 bp1 = bp1->buf_nextp;
800 }
801
802 #if 0
803 wrp = kmem_zalloc(RDS_POST_FEW_ATATIME * sizeof (ibt_recv_wr_t),
804 KM_SLEEP);
805 #else
806 wrp = &wr[0];
807 #endif
808
809 npost = nspace;
810 while (npost) {
811 jx = (npost > RDS_POST_FEW_ATATIME) ?
812 RDS_POST_FEW_ATATIME : npost;
813 for (ix = 0; ix < jx; ix++) {
814 wrp[ix].wr_id = (uintptr_t)bp;
815 wrp[ix].wr_nds = 1;
816 wrp[ix].wr_sgl = &bp->buf_ds;
817 bp = bp->buf_nextp;
818 }
819
820 ret = ibt_post_recv(chanhdl, wrp, jx, &kx);
821 if ((ret != IBT_SUCCESS) || (kx != jx)) {
822 RDS_DPRINTF2(LABEL, "ibt_post_recv for %d WRs failed: "
823 "%d", npost, ret);
824 npost -= kx;
825 break;
826 }
827
828 npost -= jx;
829 }
830
831 mutex_enter(&recvqp->qp_lock);
832 if (npost != 0) {
833 RDS_DPRINTF2("rds_post_recv_buf",
834 "EP(%p) Failed to post %d WRs", ep, npost);
835 recvqp->qp_level += (nspace - npost);
836 } else {
837 recvqp->qp_level += nspace;
838 }
839
840 /*
841 * sometimes, the recv WRs can get consumed as soon as they are
842 * posted. In that case, taskq thread to post more WRs to the RQ will
843 * not be scheduled as the taskqpending flag is still set.
844 */
845 if (recvqp->qp_level == 0) {
846 mutex_exit(&recvqp->qp_lock);
847 ret = ddi_taskq_dispatch(rds_taskq,
848 rds_post_recv_buf, (void *)chanhdl, DDI_NOSLEEP);
849 if (ret != DDI_SUCCESS) {
850 RDS_DPRINTF2("rds_post_recv_buf",
851 "ddi_taskq_dispatch failed: %d", ret);
852 mutex_enter(&recvqp->qp_lock);
853 recvqp->qp_taskqpending = B_FALSE;
854 mutex_exit(&recvqp->qp_lock);
855 }
856 } else {
857 recvqp->qp_taskqpending = B_FALSE;
858 mutex_exit(&recvqp->qp_lock);
859 }
860
861 #if 0
862 kmem_free(wrp, RDS_POST_FEW_ATATIME * sizeof (ibt_recv_wr_t));
863 #endif
864
865 RDS_DPRINTF4("rds_post_recv_buf", "Return: EP(%p)", ep);
866 }
867
868 static int
869 rds_poll_data_completions(ibt_cq_hdl_t cq, rds_ep_t *ep)
870 {
871 ibt_wc_t wc;
872 rds_buf_t *bp;
873 rds_data_hdr_t *pktp;
874 rds_qp_t *recvqp;
875 uint_t npolled;
876 int ret = IBT_SUCCESS;
877
878
879 RDS_DPRINTF4("rds_poll_data_completions", "Enter: EP(%p)", ep);
880
881 bzero(&wc, sizeof (ibt_wc_t));
882 ret = ibt_poll_cq(cq, &wc, 1, &npolled);
883 if (ret != IBT_SUCCESS) {
884 if (ret != IBT_CQ_EMPTY) {
885 RDS_DPRINTF2(LABEL, "EP(%p) CQ(%p): ibt_poll_cq "
886 "returned: %d", ep, cq, ret);
887 } else {
888 RDS_DPRINTF5(LABEL, "EP(%p) CQ(%p): ibt_poll_cq "
889 "returned: IBT_CQ_EMPTY", ep, cq);
890 }
891 return (ret);
892 }
893
894 bp = (rds_buf_t *)(uintptr_t)wc.wc_id;
895 ASSERT(bp->buf_state == RDS_RCVBUF_POSTED);
896 bp->buf_state = RDS_RCVBUF_ONSOCKQ;
897 bp->buf_nextp = NULL;
898
899 if (wc.wc_status != IBT_WC_SUCCESS) {
900 mutex_enter(&ep->ep_recvqp.qp_lock);
901 ep->ep_recvqp.qp_level--;
902 mutex_exit(&ep->ep_recvqp.qp_lock);
903
904 /* free the buffer */
905 bp->buf_state = RDS_RCVBUF_FREE;
906 rds_free_recv_buf(bp, 1);
907
908 /* Receive completion failure */
909 if (wc.wc_status != IBT_WC_WR_FLUSHED_ERR) {
910 RDS_DPRINTF2("rds_poll_data_completions",
911 "EP(%p) CQ(%p) BP(%p): WC Error Status: %d",
912 ep, cq, wc.wc_id, wc.wc_status);
913 RDS_INCR_RXERRS();
914 }
915 return (ret);
916 }
917
918 /* there is one less in the RQ */
919 recvqp = &ep->ep_recvqp;
920 mutex_enter(&recvqp->qp_lock);
921 recvqp->qp_level--;
922 if ((recvqp->qp_taskqpending == B_FALSE) &&
923 (recvqp->qp_level <= recvqp->qp_lwm)) {
924 /* Time to post more buffers into the RQ */
925 recvqp->qp_taskqpending = B_TRUE;
926 mutex_exit(&recvqp->qp_lock);
927
928 ret = ddi_taskq_dispatch(rds_taskq,
929 rds_post_recv_buf, (void *)ep->ep_chanhdl, DDI_NOSLEEP);
930 if (ret != DDI_SUCCESS) {
931 RDS_DPRINTF2(LABEL, "ddi_taskq_dispatch failed: %d",
932 ret);
933 mutex_enter(&recvqp->qp_lock);
934 recvqp->qp_taskqpending = B_FALSE;
935 mutex_exit(&recvqp->qp_lock);
936 }
937 } else {
938 mutex_exit(&recvqp->qp_lock);
939 }
940
941 pktp = (rds_data_hdr_t *)(uintptr_t)bp->buf_ds.ds_va;
942 ASSERT(pktp->dh_datalen != 0);
943
944 RDS_DPRINTF5(LABEL, "Message Received: sendIP: 0x%x recvIP: 0x%x "
945 "sendport: %d recvport: %d npkts: %d pktno: %d", ep->ep_remip,
946 ep->ep_myip, pktp->dh_sendport, pktp->dh_recvport,
947 pktp->dh_npkts, pktp->dh_psn);
948
949 RDS_DPRINTF3(LABEL, "BP(%p): npkts: %d psn: %d", bp,
950 pktp->dh_npkts, pktp->dh_psn);
951
952 if (pktp->dh_npkts == 1) {
953 /* single pkt or last packet */
954 if (pktp->dh_psn != 0) {
955 /* last packet of a segmented message */
956 ASSERT(ep->ep_seglbp != NULL);
957 ep->ep_seglbp->buf_nextp = bp;
958 ep->ep_seglbp = bp;
959 rds_received_msg(ep, ep->ep_segfbp);
960 ep->ep_segfbp = NULL;
961 ep->ep_seglbp = NULL;
962 } else {
963 /* single packet */
964 rds_received_msg(ep, bp);
965 }
966 } else {
967 /* multi-pkt msg */
968 if (pktp->dh_psn == 0) {
969 /* first packet */
970 ASSERT(ep->ep_segfbp == NULL);
971 ep->ep_segfbp = bp;
972 ep->ep_seglbp = bp;
973 } else {
974 /* intermediate packet */
975 ASSERT(ep->ep_segfbp != NULL);
976 ep->ep_seglbp->buf_nextp = bp;
977 ep->ep_seglbp = bp;
978 }
979 }
980
981 RDS_DPRINTF4("rds_poll_data_completions", "Return: EP(%p)", ep);
982
983 return (ret);
984 }
985
986 void
987 rds_recvcq_handler(ibt_cq_hdl_t cq, void *arg)
988 {
989 rds_ep_t *ep;
990 int ret = IBT_SUCCESS;
991 int (*func)(ibt_cq_hdl_t, rds_ep_t *);
992
993 ep = (rds_ep_t *)arg;
994
995 RDS_DPRINTF4("rds_recvcq_handler", "enter: EP(%p)", ep);
996
997 if (ep->ep_type == RDS_EP_TYPE_DATA) {
998 func = rds_poll_data_completions;
999 } else {
1000 func = rds_poll_ctrl_completions;
1001 }
1002
1003 do {
1004 ret = func(cq, ep);
1005 } while (ret != IBT_CQ_EMPTY);
1006
1007 /* enable the CQ */
1008 ret = ibt_enable_cq_notify(cq, rds_wc_signal);
1009 if (ret != IBT_SUCCESS) {
1010 RDS_DPRINTF2(LABEL, "EP(%p) CQ(%p): ibt_enable_cq_notify "
1011 "failed: %d", ep, cq, ret);
1012 return;
1013 }
1014
1015 do {
1016 ret = func(cq, ep);
1017 } while (ret != IBT_CQ_EMPTY);
1018
1019 RDS_DPRINTF4("rds_recvcq_handler", "Return: EP(%p)", ep);
1020 }
1021
1022 void
1023 rds_poll_send_completions(ibt_cq_hdl_t cq, rds_ep_t *ep, boolean_t lock)
1024 {
1025 ibt_wc_t wc[RDS_NUM_DATA_SEND_WCS];
1026 uint_t npolled, nret, send_error = 0;
1027 rds_buf_t *headp, *tailp, *bp;
1028 int ret, ix;
1029
1030 RDS_DPRINTF4("rds_poll_send_completions", "Enter EP(%p)", ep);
1031
1032 headp = NULL;
1033 tailp = NULL;
1034 npolled = 0;
1035 do {
1036 ret = ibt_poll_cq(cq, wc, RDS_NUM_DATA_SEND_WCS, &nret);
1037 if (ret != IBT_SUCCESS) {
1038 if (ret != IBT_CQ_EMPTY) {
1039 RDS_DPRINTF2(LABEL, "EP(%p) CQ(%p): "
1040 "ibt_poll_cq returned: %d", ep, cq, ret);
1041 } else {
1042 RDS_DPRINTF5(LABEL, "EP(%p) CQ(%p): "
1043 "ibt_poll_cq returned: IBT_CQ_EMPTY",
1044 ep, cq);
1045 }
1046
1047 break;
1048 }
1049
1050 for (ix = 0; ix < nret; ix++) {
1051 if (wc[ix].wc_status == IBT_WC_SUCCESS) {
1052 if (wc[ix].wc_type == IBT_WRC_RDMAW) {
1053 rds_send_acknowledgement(ep);
1054 continue;
1055 }
1056
1057 bp = (rds_buf_t *)(uintptr_t)wc[ix].wc_id;
1058 ASSERT(bp->buf_state == RDS_SNDBUF_PENDING);
1059 bp->buf_state = RDS_SNDBUF_FREE;
1060 } else if (wc[ix].wc_status == IBT_WC_WR_FLUSHED_ERR) {
1061 RDS_INCR_TXERRS();
1062 RDS_DPRINTF5("rds_poll_send_completions",
1063 "EP(%p): WC ID: %p ERROR: %d", ep,
1064 wc[ix].wc_id, wc[ix].wc_status);
1065
1066 send_error = 1;
1067
1068 if (wc[ix].wc_id == RDS_RDMAW_WRID) {
1069 mutex_enter(&ep->ep_lock);
1070 ep->ep_rdmacnt--;
1071 mutex_exit(&ep->ep_lock);
1072 continue;
1073 }
1074
1075 bp = (rds_buf_t *)(uintptr_t)wc[ix].wc_id;
1076 ASSERT(bp->buf_state == RDS_SNDBUF_PENDING);
1077 bp->buf_state = RDS_SNDBUF_FREE;
1078 } else {
1079 RDS_INCR_TXERRS();
1080 RDS_DPRINTF2("rds_poll_send_completions",
1081 "EP(%p): WC ID: %p ERROR: %d", ep,
1082 wc[ix].wc_id, wc[ix].wc_status);
1083 if (send_error == 0) {
1084 rds_session_t *sp = ep->ep_sp;
1085
1086 /* don't let anyone send anymore */
1087 rw_enter(&sp->session_lock, RW_WRITER);
1088 if (sp->session_state !=
1089 RDS_SESSION_STATE_ERROR) {
1090 sp->session_state =
1091 RDS_SESSION_STATE_ERROR;
1092 /* Make this the active end */
1093 sp->session_type =
1094 RDS_SESSION_ACTIVE;
1095 }
1096 rw_exit(&sp->session_lock);
1097 }
1098
1099 send_error = 1;
1100
1101 if (wc[ix].wc_id == RDS_RDMAW_WRID) {
1102 mutex_enter(&ep->ep_lock);
1103 ep->ep_rdmacnt--;
1104 mutex_exit(&ep->ep_lock);
1105 continue;
1106 }
1107
1108 bp = (rds_buf_t *)(uintptr_t)wc[ix].wc_id;
1109 ASSERT(bp->buf_state == RDS_SNDBUF_PENDING);
1110 bp->buf_state = RDS_SNDBUF_FREE;
1111 }
1112
1113 bp->buf_nextp = NULL;
1114 if (headp) {
1115 tailp->buf_nextp = bp;
1116 tailp = bp;
1117 } else {
1118 headp = bp;
1119 tailp = bp;
1120 }
1121
1122 npolled++;
1123 }
1124
1125 if (rds_no_interrupts && (npolled > 100)) {
1126 break;
1127 }
1128
1129 if (rds_no_interrupts == 1) {
1130 break;
1131 }
1132 } while (ret != IBT_CQ_EMPTY);
1133
1134 RDS_DPRINTF5("rds_poll_send_completions", "Npolled: %d send_error: %d",
1135 npolled, send_error);
1136
1137 /* put the buffers to the pool */
1138 if (npolled != 0) {
1139 rds_free_send_buf(ep, headp, tailp, npolled, lock);
1140 }
1141
1142 if (send_error != 0) {
1143 rds_handle_send_error(ep);
1144 }
1145
1146 RDS_DPRINTF4("rds_poll_send_completions", "Return EP(%p)", ep);
1147 }
1148
1149 void
1150 rds_sendcq_handler(ibt_cq_hdl_t cq, void *arg)
1151 {
1152 rds_ep_t *ep;
1153 int ret;
1154
1155 ep = (rds_ep_t *)arg;
1156
1157 RDS_DPRINTF4("rds_sendcq_handler", "Enter: EP(%p)", ep);
1158
1159 /* enable the CQ */
1160 ret = ibt_enable_cq_notify(cq, IBT_NEXT_COMPLETION);
1161 if (ret != IBT_SUCCESS) {
1162 RDS_DPRINTF2(LABEL, "EP(%p) CQ(%p): ibt_enable_cq_notify "
1163 "failed: %d", ep, cq, ret);
1164 return;
1165 }
1166
1167 rds_poll_send_completions(cq, ep, B_FALSE);
1168
1169 RDS_DPRINTF4("rds_sendcq_handler", "Return: EP(%p)", ep);
1170 }
1171
1172 void
1173 rds_ep_free_rc_channel(rds_ep_t *ep)
1174 {
1175 int ret;
1176
1177 RDS_DPRINTF2("rds_ep_free_rc_channel", "EP(%p) - Enter", ep);
1178
1179 ASSERT(mutex_owned(&ep->ep_lock));
1180
1181 /* free the QP */
1182 if (ep->ep_chanhdl != NULL) {
1183 /* wait until the RQ is empty */
1184 (void) ibt_flush_channel(ep->ep_chanhdl);
1185 (void) rds_is_recvq_empty(ep, B_TRUE);
1186 ret = ibt_free_channel(ep->ep_chanhdl);
1187 if (ret != IBT_SUCCESS) {
1188 RDS_DPRINTF2("rds_ep_free_rc_channel", "EP(%p) "
1189 "ibt_free_channel returned: %d", ep, ret);
1190 }
1191 ep->ep_chanhdl = NULL;
1192 } else {
1193 RDS_DPRINTF2("rds_ep_free_rc_channel",
1194 "EP(%p) Channel is ALREADY FREE", ep);
1195 }
1196
1197 /* free the Send CQ */
1198 if (ep->ep_sendcq != NULL) {
1199 ret = ibt_free_cq(ep->ep_sendcq);
1200 if (ret != IBT_SUCCESS) {
1201 RDS_DPRINTF2("rds_ep_free_rc_channel",
1202 "EP(%p) - for sendcq, ibt_free_cq returned %d",
1203 ep, ret);
1204 }
1205 ep->ep_sendcq = NULL;
1206 } else {
1207 RDS_DPRINTF2("rds_ep_free_rc_channel",
1208 "EP(%p) SendCQ is ALREADY FREE", ep);
1209 }
1210
1211 /* free the Recv CQ */
1212 if (ep->ep_recvcq != NULL) {
1213 ret = ibt_free_cq(ep->ep_recvcq);
1214 if (ret != IBT_SUCCESS) {
1215 RDS_DPRINTF2("rds_ep_free_rc_channel",
1216 "EP(%p) - for recvcq, ibt_free_cq returned %d",
1217 ep, ret);
1218 }
1219 ep->ep_recvcq = NULL;
1220 } else {
1221 RDS_DPRINTF2("rds_ep_free_rc_channel",
1222 "EP(%p) RecvCQ is ALREADY FREE", ep);
1223 }
1224
1225 RDS_DPRINTF2("rds_ep_free_rc_channel", "EP(%p) - Return", ep);
1226 }
1227
1228 /* Allocate resources for RC channel */
1229 ibt_channel_hdl_t
1230 rds_ep_alloc_rc_channel(rds_ep_t *ep, uint8_t hca_port)
1231 {
1232 int ret = IBT_SUCCESS;
1233 ibt_cq_attr_t scqattr, rcqattr;
1234 ibt_rc_chan_alloc_args_t chanargs;
1235 ibt_channel_hdl_t chanhdl;
1236 rds_session_t *sp;
1237 rds_hca_t *hcap;
1238
1239 RDS_DPRINTF4("rds_ep_alloc_rc_channel", "Enter: 0x%p port: %d",
1240 ep, hca_port);
1241
1242 /* Update the EP with the right IP address and HCA guid */
1243 sp = ep->ep_sp;
1244 ASSERT(sp != NULL);
1245 rw_enter(&sp->session_lock, RW_READER);
1246 mutex_enter(&ep->ep_lock);
1247 ep->ep_myip = sp->session_myip;
1248 ep->ep_remip = sp->session_remip;
1249 hcap = rds_gid_to_hcap(rdsib_statep, sp->session_lgid);
1250 ep->ep_hca_guid = hcap->hca_guid;
1251 mutex_exit(&ep->ep_lock);
1252 rw_exit(&sp->session_lock);
1253
1254 /* reset taskqpending flag here */
1255 ep->ep_recvqp.qp_taskqpending = B_FALSE;
1256
1257 if (ep->ep_type == RDS_EP_TYPE_CTRL) {
1258 scqattr.cq_size = MaxCtrlSendBuffers;
1259 scqattr.cq_sched = NULL;
1260 scqattr.cq_flags = IBT_CQ_NO_FLAGS;
1261
1262 rcqattr.cq_size = MaxCtrlRecvBuffers;
1263 rcqattr.cq_sched = NULL;
1264 rcqattr.cq_flags = IBT_CQ_NO_FLAGS;
1265
1266 chanargs.rc_sizes.cs_sq = MaxCtrlSendBuffers;
1267 chanargs.rc_sizes.cs_rq = MaxCtrlRecvBuffers;
1268 chanargs.rc_sizes.cs_sq_sgl = 1;
1269 chanargs.rc_sizes.cs_rq_sgl = 1;
1270 } else {
1271 scqattr.cq_size = MaxDataSendBuffers + RDS_NUM_ACKS;
1272 scqattr.cq_sched = NULL;
1273 scqattr.cq_flags = IBT_CQ_NO_FLAGS;
1274
1275 rcqattr.cq_size = MaxDataRecvBuffers;
1276 rcqattr.cq_sched = NULL;
1277 rcqattr.cq_flags = IBT_CQ_NO_FLAGS;
1278
1279 chanargs.rc_sizes.cs_sq = MaxDataSendBuffers + RDS_NUM_ACKS;
1280 chanargs.rc_sizes.cs_rq = MaxDataRecvBuffers;
1281 chanargs.rc_sizes.cs_sq_sgl = 1;
1282 chanargs.rc_sizes.cs_rq_sgl = 1;
1283 }
1284
1285 mutex_enter(&ep->ep_lock);
1286 if (ep->ep_sendcq == NULL) {
1287 /* returned size is always greater than the requested size */
1288 ret = ibt_alloc_cq(hcap->hca_hdl, &scqattr,
1289 &ep->ep_sendcq, NULL);
1290 if (ret != IBT_SUCCESS) {
1291 RDS_DPRINTF2(LABEL, "ibt_alloc_cq for sendCQ "
1292 "failed, size = %d: %d", scqattr.cq_size, ret);
1293 mutex_exit(&ep->ep_lock);
1294 return (NULL);
1295 }
1296
1297 (void) ibt_set_cq_handler(ep->ep_sendcq, rds_sendcq_handler,
1298 ep);
1299
1300 if (rds_no_interrupts == 0) {
1301 ret = ibt_enable_cq_notify(ep->ep_sendcq,
1302 IBT_NEXT_COMPLETION);
1303 if (ret != IBT_SUCCESS) {
1304 RDS_DPRINTF2(LABEL,
1305 "ibt_enable_cq_notify failed: %d", ret);
1306 (void) ibt_free_cq(ep->ep_sendcq);
1307 ep->ep_sendcq = NULL;
1308 mutex_exit(&ep->ep_lock);
1309 return (NULL);
1310 }
1311 }
1312 }
1313
1314 if (ep->ep_recvcq == NULL) {
1315 /* returned size is always greater than the requested size */
1316 ret = ibt_alloc_cq(hcap->hca_hdl, &rcqattr,
1317 &ep->ep_recvcq, NULL);
1318 if (ret != IBT_SUCCESS) {
1319 RDS_DPRINTF2(LABEL, "ibt_alloc_cq for recvCQ "
1320 "failed, size = %d: %d", rcqattr.cq_size, ret);
1321 (void) ibt_free_cq(ep->ep_sendcq);
1322 ep->ep_sendcq = NULL;
1323 mutex_exit(&ep->ep_lock);
1324 return (NULL);
1325 }
1326
1327 (void) ibt_set_cq_handler(ep->ep_recvcq, rds_recvcq_handler,
1328 ep);
1329
1330 ret = ibt_enable_cq_notify(ep->ep_recvcq, rds_wc_signal);
1331 if (ret != IBT_SUCCESS) {
1332 RDS_DPRINTF2(LABEL,
1333 "ibt_enable_cq_notify failed: %d", ret);
1334 (void) ibt_free_cq(ep->ep_recvcq);
1335 ep->ep_recvcq = NULL;
1336 (void) ibt_free_cq(ep->ep_sendcq);
1337 ep->ep_sendcq = NULL;
1338 mutex_exit(&ep->ep_lock);
1339 return (NULL);
1340 }
1341 }
1342
1343 chanargs.rc_flags = IBT_ALL_SIGNALED;
1344 chanargs.rc_control = IBT_CEP_RDMA_RD | IBT_CEP_RDMA_WR |
1345 IBT_CEP_ATOMIC;
1346 chanargs.rc_hca_port_num = hca_port;
1347 chanargs.rc_scq = ep->ep_sendcq;
1348 chanargs.rc_rcq = ep->ep_recvcq;
1349 chanargs.rc_pd = hcap->hca_pdhdl;
1350 chanargs.rc_srq = NULL;
1351
1352 ret = ibt_alloc_rc_channel(hcap->hca_hdl,
1353 IBT_ACHAN_NO_FLAGS, &chanargs, &chanhdl, NULL);
1354 if (ret != IBT_SUCCESS) {
1355 RDS_DPRINTF2(LABEL, "ibt_alloc_rc_channel fail: %d",
1356 ret);
1357 (void) ibt_free_cq(ep->ep_recvcq);
1358 ep->ep_recvcq = NULL;
1359 (void) ibt_free_cq(ep->ep_sendcq);
1360 ep->ep_sendcq = NULL;
1361 mutex_exit(&ep->ep_lock);
1362 return (NULL);
1363 }
1364 mutex_exit(&ep->ep_lock);
1365
1366 /* Chan private should contain the ep */
1367 (void) ibt_set_chan_private(chanhdl, ep);
1368
1369 RDS_DPRINTF4("rds_ep_alloc_rc_channel", "Return: 0x%p", chanhdl);
1370
1371 return (chanhdl);
1372 }
1373
1374
1375 #if 0
1376
1377 /* Return node guid given a port gid */
1378 ib_guid_t
1379 rds_gid_to_node_guid(ib_gid_t gid)
1380 {
1381 ibt_node_info_t nodeinfo;
1382 int ret;
1383
1384 RDS_DPRINTF4("rds_gid_to_node_guid", "Enter: gid: %llx:%llx",
1385 gid.gid_prefix, gid.gid_guid);
1386
1387 ret = ibt_gid_to_node_info(gid, &nodeinfo);
1388 if (ret != IBT_SUCCESS) {
1389 RDS_DPRINTF2(LABEL, "ibt_gid_node_info for gid: %llx:%llx "
1390 "failed", gid.gid_prefix, gid.gid_guid);
1391 return (0LL);
1392 }
1393
1394 RDS_DPRINTF4("rds_gid_to_node_guid", "Return: Node guid: %llx",
1395 nodeinfo.n_node_guid);
1396
1397 return (nodeinfo.n_node_guid);
1398 }
1399
1400 #endif
1401
1402 static void
1403 rds_handle_portup_event(rds_state_t *statep, ibt_hca_hdl_t hdl,
1404 ibt_async_event_t *event)
1405 {
1406 rds_hca_t *hcap;
1407 ibt_hca_portinfo_t *newpinfop, *oldpinfop;
1408 uint_t newsize, oldsize, nport;
1409 ib_gid_t gid;
1410 int ret;
1411
1412 RDS_DPRINTF2("rds_handle_portup_event",
1413 "Enter: GUID: 0x%llx Statep: %p", event->ev_hca_guid, statep);
1414
1415 rw_enter(&statep->rds_hca_lock, RW_WRITER);
1416
1417 hcap = statep->rds_hcalistp;
1418 while ((hcap != NULL) && (hcap->hca_guid != event->ev_hca_guid)) {
1419 hcap = hcap->hca_nextp;
1420 }
1421
1422 if (hcap == NULL) {
1423 RDS_DPRINTF2("rds_handle_portup_event", "HCA: 0x%llx is "
1424 "not in our list", event->ev_hca_guid);
1425 rw_exit(&statep->rds_hca_lock);
1426 return;
1427 }
1428
1429 ret = ibt_query_hca_ports(hdl, 0, &newpinfop, &nport, &newsize);
1430 if (ret != IBT_SUCCESS) {
1431 RDS_DPRINTF2(LABEL, "ibt_query_hca_ports failed: %d", ret);
1432 rw_exit(&statep->rds_hca_lock);
1433 return;
1434 }
1435
1436 oldpinfop = hcap->hca_pinfop;
1437 oldsize = hcap->hca_pinfo_sz;
1438 hcap->hca_pinfop = newpinfop;
1439 hcap->hca_pinfo_sz = newsize;
1440
1441 (void) ibt_free_portinfo(oldpinfop, oldsize);
1442
1443 /* If RDS service is not registered then no bind is needed */
1444 if (statep->rds_srvhdl == NULL) {
1445 RDS_DPRINTF2("rds_handle_portup_event",
1446 "RDS Service is not registered, so no action needed");
1447 rw_exit(&statep->rds_hca_lock);
1448 return;
1449 }
1450
1451 /*
1452 * If the service was previously bound on this port and
1453 * if this port has changed state down and now up, we do not
1454 * need to bind the service again. The bind is expected to
1455 * persist across state changes. If the service was never bound
1456 * before then we bind it this time.
1457 */
1458 if (hcap->hca_bindhdl[event->ev_port - 1] == NULL) {
1459
1460 /* structure copy */
1461 gid = newpinfop[event->ev_port - 1].p_sgid_tbl[0];
1462
1463 /* bind RDS service on the port, pass statep as cm_private */
1464 ret = ibt_bind_service(statep->rds_srvhdl, gid, NULL, statep,
1465 &hcap->hca_bindhdl[event->ev_port - 1]);
1466 if (ret != IBT_SUCCESS) {
1467 RDS_DPRINTF2("rds_handle_portup_event",
1468 "Bind service for HCA: 0x%llx Port: %d "
1469 "gid %llx:%llx returned: %d", event->ev_hca_guid,
1470 event->ev_port, gid.gid_prefix, gid.gid_guid, ret);
1471 }
1472 }
1473
1474 rw_exit(&statep->rds_hca_lock);
1475
1476 RDS_DPRINTF2("rds_handle_portup_event", "Return: GUID: 0x%llx",
1477 event->ev_hca_guid);
1478 }
1479
1480 static void
1481 rdsib_add_hca(ib_guid_t hca_guid)
1482 {
1483 rds_hca_t *hcap;
1484 ibt_mr_attr_t mem_attr;
1485 ibt_mr_desc_t mem_desc;
1486 int ret;
1487
1488 RDS_DPRINTF2("rdsib_add_hca", "Enter: GUID: 0x%llx", hca_guid);
1489
1490 hcap = rdsib_init_hca(hca_guid);
1491 if (hcap == NULL)
1492 return;
1493
1494 /* register the recv memory with this hca */
1495 mutex_enter(&rds_dpool.pool_lock);
1496 if (rds_dpool.pool_memp == NULL) {
1497 /* no memory to register */
1498 RDS_DPRINTF2("rdsib_add_hca", "No memory to register");
1499 mutex_exit(&rds_dpool.pool_lock);
1500 return;
1501 }
1502
1503 mem_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)rds_dpool.pool_memp;
1504 mem_attr.mr_len = rds_dpool.pool_memsize;
1505 mem_attr.mr_as = NULL;
1506 mem_attr.mr_flags = IBT_MR_ENABLE_LOCAL_WRITE;
1507
1508 ret = ibt_register_mr(hcap->hca_hdl, hcap->hca_pdhdl, &mem_attr,
1509 &hcap->hca_mrhdl, &mem_desc);
1510
1511 mutex_exit(&rds_dpool.pool_lock);
1512
1513 if (ret != IBT_SUCCESS) {
1514 RDS_DPRINTF2("rdsib_add_hca", "ibt_register_mr failed: %d",
1515 ret);
1516 } else {
1517 rw_enter(&rdsib_statep->rds_hca_lock, RW_WRITER);
1518 hcap->hca_state = RDS_HCA_STATE_MEM_REGISTERED;
1519 hcap->hca_lkey = mem_desc.md_lkey;
1520 hcap->hca_rkey = mem_desc.md_rkey;
1521 rw_exit(&rdsib_statep->rds_hca_lock);
1522 }
1523
1524 RDS_DPRINTF2("rdsib_add_hca", "Retrun: GUID: 0x%llx", hca_guid);
1525 }
1526
1527 void rds_close_this_session(rds_session_t *sp, uint8_t wait);
1528 int rds_post_control_message(rds_session_t *sp, uint8_t code, in_port_t port);
1529
1530 static void
1531 rdsib_del_hca(rds_state_t *statep, ib_guid_t hca_guid)
1532 {
1533 rds_session_t *sp;
1534 rds_hca_t *hcap;
1535 rds_hca_state_t saved_state;
1536 int ret, ix;
1537
1538 RDS_DPRINTF2("rdsib_del_hca", "Enter: GUID: 0x%llx", hca_guid);
1539
1540 /*
1541 * This should be a write lock as we don't want anyone to get access
1542 * to the hcap while we are modifing its contents
1543 */
1544 rw_enter(&statep->rds_hca_lock, RW_WRITER);
1545
1546 hcap = statep->rds_hcalistp;
1547 while ((hcap != NULL) && (hcap->hca_guid != hca_guid)) {
1548 hcap = hcap->hca_nextp;
1549 }
1550
1551 /* Prevent initiating any new activity on this HCA */
1552 ASSERT(hcap != NULL);
1553 saved_state = hcap->hca_state;
1554 hcap->hca_state = RDS_HCA_STATE_STOPPING;
1555
1556 rw_exit(&statep->rds_hca_lock);
1557
1558 /*
1559 * stop the outgoing traffic and close any active sessions on this hca.
1560 * Any pending messages in the SQ will be allowed to complete.
1561 */
1562 rw_enter(&statep->rds_sessionlock, RW_READER);
1563 sp = statep->rds_sessionlistp;
1564 while (sp) {
1565 if (sp->session_hca_guid != hca_guid) {
1566 sp = sp->session_nextp;
1567 continue;
1568 }
1569
1570 rw_enter(&sp->session_lock, RW_WRITER);
1571 RDS_DPRINTF2("rdsib_del_hca", "SP(%p) State: %d", sp,
1572 sp->session_state);
1573 /*
1574 * We are changing the session state in advance. This prevents
1575 * further messages to be posted to the SQ. We then
1576 * send a control message to the remote and tell it close
1577 * the session.
1578 */
1579 sp->session_state = RDS_SESSION_STATE_HCA_CLOSING;
1580 RDS_DPRINTF3("rds_handle_cm_conn_closed", "SP(%p) State "
1581 "RDS_SESSION_STATE_PASSIVE_CLOSING", sp);
1582 rw_exit(&sp->session_lock);
1583
1584 /*
1585 * wait until the sendq is empty then tell the remote to
1586 * close this session. This enables for graceful shutdown of
1587 * the session
1588 */
1589 (void) rds_is_sendq_empty(&sp->session_dataep, 2);
1590 (void) rds_post_control_message(sp,
1591 RDS_CTRL_CODE_CLOSE_SESSION, 0);
1592
1593 sp = sp->session_nextp;
1594 }
1595
1596 /* wait until all the sessions are off this HCA */
1597 sp = statep->rds_sessionlistp;
1598 while (sp) {
1599 if (sp->session_hca_guid != hca_guid) {
1600 sp = sp->session_nextp;
1601 continue;
1602 }
1603
1604 rw_enter(&sp->session_lock, RW_READER);
1605 RDS_DPRINTF2("rdsib_del_hca", "SP(%p) State: %d", sp,
1606 sp->session_state);
1607
1608 while ((sp->session_state == RDS_SESSION_STATE_HCA_CLOSING) ||
1609 (sp->session_state == RDS_SESSION_STATE_ERROR) ||
1610 (sp->session_state == RDS_SESSION_STATE_PASSIVE_CLOSING) ||
1611 (sp->session_state == RDS_SESSION_STATE_CLOSED)) {
1612 rw_exit(&sp->session_lock);
1613 delay(drv_usectohz(1000000));
1614 rw_enter(&sp->session_lock, RW_READER);
1615 RDS_DPRINTF2("rdsib_del_hca", "SP(%p) State: %d", sp,
1616 sp->session_state);
1617 }
1618
1619 rw_exit(&sp->session_lock);
1620
1621 sp = sp->session_nextp;
1622 }
1623 rw_exit(&statep->rds_sessionlock);
1624
1625 /*
1626 * if rdsib_close_ib was called before this, then that would have
1627 * unbound the service on all ports. In that case, the HCA structs
1628 * will contain stale bindhdls. Hence, we do not call unbind unless
1629 * the service is still registered.
1630 */
1631 if (statep->rds_srvhdl != NULL) {
1632 /* unbind RDS service on all ports on this HCA */
1633 for (ix = 0; ix < hcap->hca_nports; ix++) {
1634 if (hcap->hca_bindhdl[ix] == NULL) {
1635 continue;
1636 }
1637
1638 RDS_DPRINTF2("rdsib_del_hca",
1639 "Unbinding Service: port: %d, bindhdl: %p",
1640 ix + 1, hcap->hca_bindhdl[ix]);
1641 (void) ibt_unbind_service(rdsib_statep->rds_srvhdl,
1642 hcap->hca_bindhdl[ix]);
1643 hcap->hca_bindhdl[ix] = NULL;
1644 }
1645 }
1646
1647 RDS_DPRINTF2("rdsib_del_hca", "HCA(%p) State: %d", hcap,
1648 hcap->hca_state);
1649
1650 switch (saved_state) {
1651 case RDS_HCA_STATE_MEM_REGISTERED:
1652 ASSERT(hcap->hca_mrhdl != NULL);
1653 ret = ibt_deregister_mr(hcap->hca_hdl, hcap->hca_mrhdl);
1654 if (ret != IBT_SUCCESS) {
1655 RDS_DPRINTF2("rdsib_del_hca",
1656 "ibt_deregister_mr failed: %d", ret);
1657 return;
1658 }
1659 hcap->hca_mrhdl = NULL;
1660 /* FALLTHRU */
1661 case RDS_HCA_STATE_OPEN:
1662 ASSERT(hcap->hca_hdl != NULL);
1663 ASSERT(hcap->hca_pdhdl != NULL);
1664
1665
1666 ret = ibt_free_pd(hcap->hca_hdl, hcap->hca_pdhdl);
1667 if (ret != IBT_SUCCESS) {
1668 RDS_DPRINTF2("rdsib_del_hca",
1669 "ibt_free_pd failed: %d", ret);
1670 }
1671
1672 (void) ibt_free_portinfo(hcap->hca_pinfop, hcap->hca_pinfo_sz);
1673
1674 ret = ibt_close_hca(hcap->hca_hdl);
1675 if (ret != IBT_SUCCESS) {
1676 RDS_DPRINTF2("rdsib_del_hca",
1677 "ibt_close_hca failed: %d", ret);
1678 }
1679
1680 hcap->hca_hdl = NULL;
1681 hcap->hca_pdhdl = NULL;
1682 hcap->hca_lkey = 0;
1683 hcap->hca_rkey = 0;
1684 }
1685
1686 /*
1687 * This should be a write lock as we don't want anyone to get access
1688 * to the hcap while we are modifing its contents
1689 */
1690 rw_enter(&statep->rds_hca_lock, RW_WRITER);
1691 hcap->hca_state = RDS_HCA_STATE_REMOVED;
1692 rw_exit(&statep->rds_hca_lock);
1693
1694 RDS_DPRINTF2("rdsib_del_hca", "Return: GUID: 0x%llx", hca_guid);
1695 }
1696
1697 static void
1698 rds_async_handler(void *clntp, ibt_hca_hdl_t hdl, ibt_async_code_t code,
1699 ibt_async_event_t *event)
1700 {
1701 rds_state_t *statep = (rds_state_t *)clntp;
1702
1703 RDS_DPRINTF2("rds_async_handler", "Async code: %d", code);
1704
1705 switch (code) {
1706 case IBT_EVENT_PORT_UP:
1707 rds_handle_portup_event(statep, hdl, event);
1708 break;
1709 case IBT_HCA_ATTACH_EVENT:
1710 /*
1711 * NOTE: In some error recovery paths, it is possible to
1712 * receive IBT_HCA_ATTACH_EVENTs on already known HCAs.
1713 */
1714 (void) rdsib_add_hca(event->ev_hca_guid);
1715 break;
1716 case IBT_HCA_DETACH_EVENT:
1717 (void) rdsib_del_hca(statep, event->ev_hca_guid);
1718 break;
1719
1720 default:
1721 RDS_DPRINTF2(LABEL, "Async event: %d not handled", code);
1722 }
1723
1724 RDS_DPRINTF2("rds_async_handler", "Return: code: %d", code);
1725 }
1726
1727 /*
1728 * This routine exists to minimize stale connections across ungraceful
1729 * reboots of nodes in a cluster.
1730 */
1731 void
1732 rds_randomize_qps(rds_hca_t *hcap)
1733 {
1734 ibt_cq_attr_t cqattr;
1735 ibt_rc_chan_alloc_args_t chanargs;
1736 ibt_channel_hdl_t qp1, qp2;
1737 ibt_cq_hdl_t cq_hdl;
1738 hrtime_t nsec;
1739 uint8_t i, j, rand1, rand2;
1740 int ret;
1741
1742 bzero(&cqattr, sizeof (ibt_cq_attr_t));
1743 cqattr.cq_size = 1;
1744 cqattr.cq_sched = NULL;
1745 cqattr.cq_flags = IBT_CQ_NO_FLAGS;
1746 ret = ibt_alloc_cq(hcap->hca_hdl, &cqattr, &cq_hdl, NULL);
1747 if (ret != IBT_SUCCESS) {
1748 RDS_DPRINTF2("rds_randomize_qps",
1749 "ibt_alloc_cq failed: %d", ret);
1750 return;
1751 }
1752
1753 bzero(&chanargs, sizeof (ibt_rc_chan_alloc_args_t));
1754 chanargs.rc_flags = IBT_ALL_SIGNALED;
1755 chanargs.rc_control = IBT_CEP_RDMA_RD | IBT_CEP_RDMA_WR |
1756 IBT_CEP_ATOMIC;
1757 chanargs.rc_hca_port_num = 1;
1758 chanargs.rc_scq = cq_hdl;
1759 chanargs.rc_rcq = cq_hdl;
1760 chanargs.rc_pd = hcap->hca_pdhdl;
1761 chanargs.rc_srq = NULL;
1762
1763 nsec = gethrtime();
1764 rand1 = (nsec & 0xF);
1765 rand2 = (nsec >> 4) & 0xF;
1766 RDS_DPRINTF2("rds_randomize_qps", "rand1: %d rand2: %d",
1767 rand1, rand2);
1768
1769 for (i = 0; i < rand1 + 3; i++) {
1770 if (ibt_alloc_rc_channel(hcap->hca_hdl,
1771 IBT_ACHAN_NO_FLAGS, &chanargs, &qp1, NULL) !=
1772 IBT_SUCCESS) {
1773 RDS_DPRINTF2("rds_randomize_qps",
1774 "Bailing at i: %d", i);
1775 (void) ibt_free_cq(cq_hdl);
1776 return;
1777 }
1778 for (j = 0; j < rand2 + 3; j++) {
1779 if (ibt_alloc_rc_channel(hcap->hca_hdl,
1780 IBT_ACHAN_NO_FLAGS, &chanargs, &qp2,
1781 NULL) != IBT_SUCCESS) {
1782 RDS_DPRINTF2("rds_randomize_qps",
1783 "Bailing at i: %d j: %d", i, j);
1784 (void) ibt_free_channel(qp1);
1785 (void) ibt_free_cq(cq_hdl);
1786 return;
1787 }
1788 (void) ibt_free_channel(qp2);
1789 }
1790 (void) ibt_free_channel(qp1);
1791 }
1792
1793 (void) ibt_free_cq(cq_hdl);
1794 }
--- EOF ---