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) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <sys/ib/ibtl/impl/ibtl.h>
26 #include <sys/ib/ibtl/impl/ibtl_cm.h>
27
28 /*
29 * ibtl_qp.c
30 * These routines implement (most of) the verbs related to
31 * Queue Pairs.
32 */
33
34 /* Globals. */
35 static char ibtf_qp[] = "ibtl";
36
37 /* This table indirectly initializes the ibt_cep_next_state[] table. */
38 typedef struct ibt_cep_next_state_s {
39 ibt_cep_state_t next_state;
40 ibt_cep_modify_flags_t modify_flags;
41 } ibt_cep_next_state_t;
42
43 struct {
44 ibt_cep_state_t current_state;
45 ibt_cep_state_t next_state;
46 ibt_cep_modify_flags_t modify_flags;
47 } ibt_cep_next_state_inits[] = {
48 { IBT_STATE_RESET, IBT_STATE_INIT, IBT_CEP_SET_RESET_INIT},
49 { IBT_STATE_INIT, IBT_STATE_RTR, IBT_CEP_SET_INIT_RTR},
50 { IBT_STATE_RTR, IBT_STATE_RTS, IBT_CEP_SET_RTR_RTS}
51 };
52
53 ibt_cep_next_state_t ibt_cep_next_state[IBT_STATE_NUM];
54
55 /* The following data and functions can increase system stability. */
56
57 int ibtl_qp_calls_curr;
58 int ibtl_qp_calls_max = 128; /* limit on # of simultaneous QP verb calls */
59 kmutex_t ibtl_qp_mutex;
60 kcondvar_t ibtl_qp_cv;
61
62 void
63 ibtl_qp_flow_control_enter(void)
64 {
65 mutex_enter(&ibtl_qp_mutex);
66 while (ibtl_qp_calls_curr >= ibtl_qp_calls_max) {
67 cv_wait(&ibtl_qp_cv, &ibtl_qp_mutex);
68 }
69 ++ibtl_qp_calls_curr;
70 mutex_exit(&ibtl_qp_mutex);
71 }
72
73 void
74 ibtl_qp_flow_control_exit(void)
75 {
76 mutex_enter(&ibtl_qp_mutex);
77 cv_signal(&ibtl_qp_cv);
78 --ibtl_qp_calls_curr;
79 mutex_exit(&ibtl_qp_mutex);
80 }
81
82 /*
83 * Function:
84 * ibt_alloc_qp
85 * Input:
86 * hca_hdl HCA Handle.
87 * type Specifies the type of QP to alloc in ibt_alloc_qp()
88 * qp_attrp Specifies the ibt_qp_alloc_attr_t that are needed to
89 * allocate a QP and transition it to the RTS state for
90 * UDs and INIT state for all other QPs.
91 * Output:
92 * queue_sizes_p Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
93 * WR SGL elements.
94 * qpn_p Returned QP Number of the allocated QP.
95 * ibt_qp_p The ibt_qp_hdl_t of the allocated QP.
96 * Returns:
97 * IBT_SUCCESS
98 * Description:
99 * Allocate a QP with specified attributes.
100 */
101 ibt_status_t
102 ibt_alloc_qp(ibt_hca_hdl_t hca_hdl, ibt_qp_type_t type,
103 ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
104 ib_qpn_t *qpn_p, ibt_qp_hdl_t *ibt_qp_p)
105 {
106 ibt_status_t retval;
107 ibtl_channel_t *chanp;
108 ibt_tran_srv_t qp_type;
109
110 IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_qp(%p, %d, %p, %p, %p, %p) ",
111 hca_hdl, type, qp_attrp, queue_sizes_p, qpn_p, ibt_qp_p);
112
113 switch (type) {
114 case IBT_UD_RQP:
115 qp_type = IBT_UD_SRV;
116 break;
117 case IBT_RC_RQP:
118 qp_type = IBT_RC_SRV;
119 break;
120 case IBT_UC_RQP:
121 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Unreliable Connected "
122 "Transport Type is not supported.");
123 *ibt_qp_p = NULL;
124 return (IBT_NOT_SUPPORTED);
125 case IBT_RD_RQP:
126 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Reliable Datagram "
127 "Transport Type is not supported.");
128 *ibt_qp_p = NULL;
129 return (IBT_NOT_SUPPORTED);
130 default:
131 /* shouldn't happen ILLEGAL Type */
132 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Illegal Transport Type "
133 "%d", type);
134 *ibt_qp_p = NULL;
135 return (IBT_QP_SRV_TYPE_INVALID);
136 }
137
138 /* Get CI CQ handles */
139 qp_attrp->qp_ibc_scq_hdl = (qp_attrp->qp_scq_hdl == NULL) ? NULL :
140 qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
141 qp_attrp->qp_ibc_rcq_hdl = (qp_attrp->qp_rcq_hdl == NULL) ? NULL :
142 qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
143
144 /* Get CI SRQ handle */
145 if ((qp_attrp->qp_alloc_flags & IBT_QP_USES_SRQ) &&
146 (qp_attrp->qp_srq_hdl != NULL))
147 qp_attrp->qp_ibc_srq_hdl =
148 qp_attrp->qp_srq_hdl->srq_ibc_srq_hdl;
149 else
150 qp_attrp->qp_ibc_srq_hdl = NULL;
151
152 /* Allocate Channel structure */
153 chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
154
155 ibtl_qp_flow_control_enter();
156 retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_qp)(
157 IBTL_HCA2CIHCA(hca_hdl), &chanp->ch_qp, type, qp_attrp,
158 queue_sizes_p, qpn_p, &chanp->ch_qp.qp_ibc_qp_hdl);
159 ibtl_qp_flow_control_exit();
160 if (retval != IBT_SUCCESS) {
161 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: "
162 "Failed to allocate QP: %d", retval);
163 kmem_free(chanp, sizeof (*chanp));
164 *ibt_qp_p = NULL;
165 return (retval);
166 }
167
168 /* Initialize the internal QP struct. */
169 chanp->ch_qp.qp_type = qp_type;
170 chanp->ch_qp.qp_hca = hca_hdl;
171 chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
172 chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
173 chanp->ch_current_state = IBT_STATE_RESET;
174 /*
175 * The IBTA spec does not include the signal type or PD on a QP
176 * query operation. In order to implement the "CLONE" feature
177 * we need to cache these values. Mostly used by TI client.
178 */
179 chanp->ch_qp.qp_flags = qp_attrp->qp_flags;
180 chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl;
181 mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
182 cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
183
184 atomic_inc_32(&hca_hdl->ha_qp_cnt);
185
186 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: SUCCESS: qp %p owned by '%s'",
187 chanp, hca_hdl->ha_clnt_devp->clnt_name);
188
189 *ibt_qp_p = chanp;
190
191 return (retval);
192 }
193
194
195 /*
196 * Function:
197 * ibt_initialize_qp
198 * Input:
199 * ibt_qp The previously allocated IBT QP Handle.
200 * modify_attrp Specifies the QP Modify attributes that to transition
201 * the QP to the RTS state for UDs (including special QPs)
202 * and INIT state for all other QPs.
203 * Output:
204 * none.
205 * Returns:
206 * IBT_SUCCESS
207 * Description:
208 * Transition the QP to the RTS state for UDs (including special QPs)
209 * and INIT state for all other QPs.
210 */
211 ibt_status_t
212 ibt_initialize_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_info_t *modify_attrp)
213 {
214 ibt_status_t status;
215 ibt_cep_state_t state;
216 ibc_hca_hdl_t ibc_hca_hdl = IBTL_CHAN2CIHCA(ibt_qp);
217 ibc_qp_hdl_t ibc_qp_hdl = IBTL_CHAN2CIQP(ibt_qp);
218 ibc_operations_t *hca_ops_p = IBTL_CHAN2CIHCAOPS_P(ibt_qp);
219 ibt_cep_modify_flags_t modify_flags;
220
221 IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp(%p, %p)",
222 ibt_qp, modify_attrp);
223
224 /*
225 * Validate the QP Type from the channel with QP Type from the
226 * modify attribute struct.
227 */
228 if (ibt_qp->ch_qp.qp_type != modify_attrp->qp_trans) {
229 IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
230 "QP Type mismatch: Chan QP Type<%d>, Modify QP Type<%d>",
231 ibt_qp->ch_qp.qp_type, modify_attrp->qp_trans);
232 return (IBT_QP_SRV_TYPE_INVALID);
233 }
234 if (ibt_qp->ch_current_state != IBT_STATE_RESET) {
235 IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
236 "QP needs to be in RESET state: Chan QP State<%d>",
237 ibt_qp->ch_current_state);
238 return (IBT_CHAN_STATE_INVALID);
239 }
240
241 /*
242 * Initialize the QP to the RTS state for UDs
243 * and INIT state for all other QPs.
244 */
245 switch (modify_attrp->qp_trans) {
246 case IBT_UD_SRV:
247
248 /*
249 * Bring the QP to the RTS state.
250 */
251 state = IBT_STATE_RESET;
252 ibtl_qp_flow_control_enter();
253 do {
254 modify_attrp->qp_current_state = state;
255 modify_flags = ibt_cep_next_state[state].modify_flags;
256 modify_attrp->qp_state = state =
257 ibt_cep_next_state[state].next_state;
258
259 IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp: "
260 "modifying qp state to 0x%x", state);
261 status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl,
262 ibc_qp_hdl, modify_flags, modify_attrp, NULL);
263 } while ((state != IBT_STATE_RTS) && (status == IBT_SUCCESS));
264 ibtl_qp_flow_control_exit();
265
266 if (status == IBT_SUCCESS) {
267 ibt_qp->ch_current_state = state;
268 ibt_qp->ch_transport.ud.ud_port_num =
269 modify_attrp->qp_transport.ud.ud_port;
270 ibt_qp->ch_transport.ud.ud_qkey =
271 modify_attrp->qp_transport.ud.ud_qkey;
272 }
273 break;
274 case IBT_UC_SRV:
275 case IBT_RD_SRV:
276 case IBT_RC_SRV:
277
278 /*
279 * Bring the QP to the INIT state.
280 */
281 modify_attrp->qp_state = IBT_STATE_INIT;
282
283 ibtl_qp_flow_control_enter();
284 status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl, ibc_qp_hdl,
285 IBT_CEP_SET_RESET_INIT, modify_attrp, NULL);
286 ibtl_qp_flow_control_exit();
287 if (status == IBT_SUCCESS)
288 ibt_qp->ch_current_state = IBT_STATE_INIT;
289 break;
290 default:
291 /* shouldn't happen ILLEGAL Type */
292 IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: Illegal Type %d",
293 modify_attrp->qp_trans);
294 return (IBT_QP_SRV_TYPE_INVALID);
295 } /* End switch */
296
297 return (status);
298 }
299
300
301 /*
302 * Function:
303 * ibt_alloc_special_qp
304 * Input:
305 * hca_hdl HCA Handle.
306 * type Specifies the type of Special QP to be allocated.
307 * qp_attrp Specifies the ibt_qp_alloc_attr_t that are needed to
308 * allocate a special QP.
309 * Output:
310 * queue_sizes_p Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
311 * WR SGL elements.
312 * qpn_p Returned qpn of the allocated QP.
313 * ibt_qp_p The ibt_qp_hdl_t of the allocated QP.
314 * Returns:
315 * IBT_SUCCESS
316 * Description:
317 * Allocate a special QP with specified attributes.
318 */
319 ibt_status_t
320 ibt_alloc_special_qp(ibt_hca_hdl_t hca_hdl, uint8_t port, ibt_sqp_type_t type,
321 ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
322 ibt_qp_hdl_t *ibt_qp_p)
323 {
324 ibt_qp_hdl_t chanp;
325 ibt_status_t retval;
326 ibt_tran_srv_t sqp_type;
327
328 IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_special_qp(%p, %d, %x, %p, %p, %p)",
329 hca_hdl, port, type, qp_attrp, queue_sizes_p, ibt_qp_p);
330
331 switch (type) {
332 case IBT_SMI_SQP:
333 case IBT_GSI_SQP:
334 sqp_type = IBT_UD_SRV;
335 break;
336
337 case IBT_RAWIP_SQP:
338 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw IP "
339 "Transport Type is not supported.");
340 *ibt_qp_p = NULL;
341 return (IBT_NOT_SUPPORTED);
342
343 case IBT_RAWETHER_SQP:
344 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw Ethernet "
345 "Transport Type is not supported.");
346 *ibt_qp_p = NULL;
347 return (IBT_NOT_SUPPORTED);
348
349 default:
350 /* Shouldn't happen */
351 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
352 "Illegal Type 0x%x", type);
353 *ibt_qp_p = NULL;
354 return (IBT_QP_SPECIAL_TYPE_INVALID);
355 }
356
357 /* convert the CQ handles for the CI */
358 qp_attrp->qp_ibc_scq_hdl = qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
359 qp_attrp->qp_ibc_rcq_hdl = qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
360
361 /* Allocate Channel structure */
362 chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
363
364 ibtl_qp_flow_control_enter();
365 retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_special_qp)(
366 IBTL_HCA2CIHCA(hca_hdl), port, &chanp->ch_qp, type, qp_attrp,
367 queue_sizes_p, &chanp->ch_qp.qp_ibc_qp_hdl);
368 ibtl_qp_flow_control_exit();
369 if (retval != IBT_SUCCESS) {
370 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
371 "Failed to allocate Special QP: %d", retval);
372 kmem_free(chanp, sizeof (*chanp));
373 *ibt_qp_p = NULL;
374 return (retval);
375 }
376
377 /* Initialize the internal QP struct. */
378 chanp->ch_qp.qp_type = sqp_type;
379 chanp->ch_qp.qp_hca = hca_hdl;
380 chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
381 chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
382 chanp->ch_current_state = IBT_STATE_RESET;
383 mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
384 cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
385
386 /* Updating these variable, so that debugger shows correct values. */
387 chanp->ch_qp.qp_flags = qp_attrp->qp_flags;
388 chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl;
389
390 atomic_inc_32(&hca_hdl->ha_qp_cnt);
391
392 *ibt_qp_p = chanp;
393
394 return (retval);
395 }
396
397
398 /*
399 * Function:
400 * ibt_flush_qp
401 * Input:
402 * ibtl_qp Handle for QP that needs to be flushed.
403 * Output:
404 * none.
405 * Returns:
406 * IBT_SUCCESS
407 * IBT_QP_HDL_INVALID
408 * Description:
409 * Put the QP into error state to flush out work requests.
410 */
411 ibt_status_t
412 ibt_flush_qp(ibt_qp_hdl_t ibt_qp)
413 {
414 ibt_qp_info_t modify_attr;
415 ibt_status_t retval;
416
417 IBTF_DPRINTF_L3(ibtf_qp, "ibt_flush_qp(%p)", ibt_qp);
418
419 if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
420 mutex_enter(&ibtl_free_qp_mutex);
421 if ((ibt_qp->ch_transport.rc.rc_free_flags &
422 (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
423 IBTL_RC_QP_CONNECTED) {
424 mutex_exit(&ibtl_free_qp_mutex);
425 IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp(%p): "
426 "called with a connected RC QP", ibt_qp);
427 return (IBT_CHAN_STATE_INVALID);
428 }
429 mutex_exit(&ibtl_free_qp_mutex);
430 }
431
432 bzero(&modify_attr, sizeof (ibt_qp_info_t));
433
434 /*
435 * Set the QP state to error to flush any uncompleted WRs.
436 */
437 modify_attr.qp_state = IBT_STATE_ERROR;
438 modify_attr.qp_trans = ibt_qp->ch_qp.qp_type;
439
440 retval = ibt_modify_qp(ibt_qp, IBT_CEP_SET_STATE, &modify_attr, NULL);
441
442 if (retval != IBT_SUCCESS) {
443 IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp: "
444 "failed on chan %p: %d", ibt_qp, retval);
445 }
446 return (retval);
447 }
448
449
450 /*
451 * ibtl_cm_chan_is_opening()
452 *
453 * Inform IBTL that the connection established process is in progress
454 * on this channel so that care need to be taken while free'ing when
455 * open is NOT yet complete.
456 *
457 * chan Channel Handle
458 */
459 void
460 ibtl_cm_chan_is_opening(ibt_channel_hdl_t chan)
461 {
462 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_opening(%p)", chan);
463 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
464 mutex_enter(&ibtl_free_qp_mutex);
465 ASSERT(chan->ch_transport.rc.rc_free_flags == 0);
466 chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTING;
467 mutex_exit(&ibtl_free_qp_mutex);
468 }
469
470 /*
471 * ibtl_cm_chan_open_is_aborted()
472 *
473 * Inform IBTL that the connection established on this channel has
474 * aborted. So undo what was done in ibtl_cm_chan_is_opening().
475 *
476 * chan Channel Handle
477 */
478 void
479 ibtl_cm_chan_open_is_aborted(ibt_channel_hdl_t chan)
480 {
481 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_open_is_aborted(%p)", chan);
482 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
483 mutex_enter(&ibtl_free_qp_mutex);
484 chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING;
485 mutex_exit(&ibtl_free_qp_mutex);
486 }
487
488 /*
489 * ibtl_cm_chan_is_open()
490 *
491 * Inform IBTL that the connection has been established on this
492 * channel so that a later call to ibtl_cm_chan_is_closed()
493 * will be required to free the QPN used by this channel.
494 *
495 * chan Channel Handle
496 */
497 void
498 ibtl_cm_chan_is_open(ibt_channel_hdl_t chan)
499 {
500 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_open(%p)", chan);
501 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
502 mutex_enter(&ibtl_free_qp_mutex);
503 chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING;
504 chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTED;
505 mutex_exit(&ibtl_free_qp_mutex);
506 }
507
508 /*
509 * ibtl_cm_is_chan_closing()
510 *
511 * Returns 1, if the connection that has been
512 * started for this channel has moved to TIMEWAIT
513 * If not, returns 0
514 *
515 * chan Channel Handle
516 */
517 int
518 ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan)
519 {
520 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closing(%p)", chan);
521 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
522 mutex_enter(&ibtl_free_qp_mutex);
523 if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSING) {
524 mutex_exit(&ibtl_free_qp_mutex);
525 return (1);
526 }
527 mutex_exit(&ibtl_free_qp_mutex);
528 return (0);
529 }
530
531 /*
532 * ibtl_cm_is_chan_closed()
533 *
534 * Returns 1, if the connection that has been
535 * started for this channel has completed TIMEWAIT
536 * If not, returns 0
537 *
538 * chan Channel Handle
539 */
540 int
541 ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan)
542 {
543 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closed(%p)", chan);
544 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
545 mutex_enter(&ibtl_free_qp_mutex);
546 if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSED) {
547 mutex_exit(&ibtl_free_qp_mutex);
548 return (1);
549 }
550 mutex_exit(&ibtl_free_qp_mutex);
551 return (0);
552 }
553 /*
554 * ibtl_cm_chan_is_closing()
555 *
556 * Inform IBTL that the TIMEWAIT delay for the connection has been
557 * started for this channel so that the QP can be freed.
558 *
559 * chan Channel Handle
560 */
561 void
562 ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan)
563 {
564 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closing(%p)", chan);
565 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
566 mutex_enter(&ibtl_free_qp_mutex);
567 ASSERT(chan->ch_transport.rc.rc_free_flags == IBTL_RC_QP_CONNECTED);
568 chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSING;
569 mutex_exit(&ibtl_free_qp_mutex);
570 }
571 /*
572 * ibtl_cm_chan_is_closed()
573 *
574 * Inform IBTL that the TIMEWAIT delay for the connection has been
575 * reached for this channel so that the QPN can be reused.
576 *
577 * chan Channel Handle
578 */
579 void
580 ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan)
581 {
582 ibt_status_t status;
583 ibtl_hca_t *ibtl_hca = chan->ch_qp.qp_hca;
584
585 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closed(%p)", chan);
586 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
587 mutex_enter(&ibtl_free_qp_mutex);
588 ASSERT((chan->ch_transport.rc.rc_free_flags &
589 (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
590 (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING));
591
592 chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTED;
593 chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CLOSING;
594 chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSED;
595
596 ibtl_cm_set_chan_private(chan, NULL);
597
598 if ((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_FREED) == 0) {
599 mutex_exit(&ibtl_free_qp_mutex);
600 return;
601 }
602 mutex_exit(&ibtl_free_qp_mutex);
603 ibtl_qp_flow_control_enter();
604 if ((status = (IBTL_CHAN2CIHCAOPS_P(chan)->ibc_release_qpn)
605 (IBTL_CHAN2CIHCA(chan), chan->ch_transport.rc.rc_qpn_hdl)) ==
606 IBT_SUCCESS) {
607 /* effectively, this is kmem_free(chan); */
608 ibtl_free_qp_async_check(&chan->ch_qp);
609
610 /* decrement ha_qpn_cnt and check for close in progress */
611 ibtl_close_hca_check(ibtl_hca);
612 } else
613 IBTF_DPRINTF_L2(ibtf_qp, "ibtl_cm_chan_is_closed: "
614 "ibc_release_qpn failed: status = %d\n", status);
615 ibtl_qp_flow_control_exit();
616 }
617
618 /*
619 * ibtl_cm_chan_is_reused()
620 *
621 * Inform IBTL that the channel is going to be re-used
622 * chan Channel Handle
623 */
624 void
625 ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan)
626 {
627 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_reused(%p)", chan);
628 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
629 mutex_enter(&ibtl_free_qp_mutex);
630 ASSERT(((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CONNECTED) !=
631 IBTL_RC_QP_CONNECTED));
632
633 /* channel is no longer in closed state, shall be re-used */
634 chan->ch_transport.rc.rc_free_flags = 0;
635
636 mutex_exit(&ibtl_free_qp_mutex);
637
638 }
639
640 /*
641 * Function: ibt_free_qp()
642 *
643 * Input: ibt_qp Handle for Channel(QP) that needs to be freed.
644 *
645 * Output: NONE.
646 *
647 * Returns: IBT_SUCCESS
648 * IBT_QP_STATE_INVALID
649 * IBT_QP_HDL_INVALID
650 *
651 * Description:
652 * Free a previously allocated QP.
653 */
654 ibt_status_t
655 ibt_free_qp(ibt_qp_hdl_t ibt_qp)
656 {
657 ibt_status_t status;
658 ibtl_hca_t *ibtl_hca = ibt_qp->ch_qp.qp_hca;
659
660 IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p)", ibt_qp);
661
662 if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
663 ibtl_qp_flow_control_enter();
664 mutex_enter(&ibtl_free_qp_mutex);
665 if (ibt_qp->ch_transport.rc.rc_free_flags &
666 IBTL_RC_QP_CONNECTING) {
667 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
668 "Channel establishment is still in PROGRESS.");
669 mutex_exit(&ibtl_free_qp_mutex);
670 ibtl_qp_flow_control_exit();
671 return (IBT_CHAN_STATE_INVALID);
672 }
673 if (ibt_qp->ch_transport.rc.rc_free_flags &
674 IBTL_RC_QP_CONNECTED) {
675 if ((ibt_qp->ch_transport.rc.rc_free_flags &
676 IBTL_RC_QP_CLOSING) == 0) {
677 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
678 "need to call ibt_close_rc_channel");
679 mutex_exit(&ibtl_free_qp_mutex);
680 ibtl_qp_flow_control_exit();
681 return (IBT_CHAN_STATE_INVALID);
682 }
683 ibt_qp->ch_transport.rc.rc_free_flags |=
684 IBTL_RC_QP_FREED;
685 status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
686 (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
687 IBC_FREE_QP_ONLY,
688 &ibt_qp->ch_transport.rc.rc_qpn_hdl);
689 mutex_exit(&ibtl_free_qp_mutex);
690 ibtl_qp_flow_control_exit();
691
692 if (status == IBT_SUCCESS) {
693 mutex_enter(&ibtl_clnt_list_mutex);
694 ibtl_hca->ha_qpn_cnt++;
695 mutex_exit(&ibtl_clnt_list_mutex);
696 atomic_dec_32(&ibtl_hca->ha_qp_cnt);
697 IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - "
698 "SUCCESS", ibt_qp);
699 } else
700 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
701 "ibc_free_qp failed: status = %d", status);
702 return (status);
703 }
704 mutex_exit(&ibtl_free_qp_mutex);
705 } else
706 ibtl_qp_flow_control_enter();
707
708 status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
709 (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
710 IBC_FREE_QP_AND_QPN, NULL);
711 ibtl_qp_flow_control_exit();
712
713 if (status == IBT_SUCCESS) {
714 /* effectively, this is kmem_free(ibt_qp); */
715 ibtl_free_qp_async_check(&ibt_qp->ch_qp);
716
717 atomic_dec_32(&ibtl_hca->ha_qp_cnt);
718 IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - SUCCESS", ibt_qp);
719 } else {
720 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
721 "ibc_free_qp failed with error %d", status);
722 }
723
724 return (status);
725 }
726
727
728 /* helper function for ibt_query_qp */
729 static void
730 ibtl_fillin_sgid(ibt_cep_path_t *pathp, ibtl_hca_devinfo_t *hca_devp)
731 {
732 uint8_t port;
733 uint32_t sgid_ix;
734 ib_gid_t *sgidp;
735
736 port = pathp->cep_hca_port_num;
737 sgid_ix = pathp->cep_adds_vect.av_sgid_ix;
738 if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports ||
739 sgid_ix >= IBTL_HDIP2SGIDTBLSZ(hca_devp)) {
740 pathp->cep_adds_vect.av_sgid.gid_prefix = 0;
741 pathp->cep_adds_vect.av_sgid.gid_guid = 0;
742 } else {
743 mutex_enter(&ibtl_clnt_list_mutex);
744 sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl;
745 pathp->cep_adds_vect.av_sgid = sgidp[sgid_ix];
746 mutex_exit(&ibtl_clnt_list_mutex);
747 }
748 }
749
750
751 /*
752 * Function: ibt_query_qp
753 *
754 * Input: ibt_qp - The IBT QP Handle.
755 *
756 * Output: ibt_qp_query_attrp - Points to a ibt_qp_query_attr_t
757 * that on return contains all the
758 * attributes of the specified qp.
759 *
760 * Returns: IBT_SUCCESS
761 * IBT_QP_HDL_INVALID
762 *
763 * Description:
764 * Query QP attributes
765 *
766 */
767 ibt_status_t
768 ibt_query_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_query_attr_t *qp_query_attrp)
769 {
770 ibt_status_t retval;
771 ibtl_hca_devinfo_t *hca_devp;
772 ibt_qp_info_t *qp_infop;
773
774 IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_qp(%p, %p)",
775 ibt_qp, qp_query_attrp);
776
777 ibtl_qp_flow_control_enter();
778 retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_query_qp(
779 IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), qp_query_attrp));
780 ibtl_qp_flow_control_exit();
781 if (retval == IBT_SUCCESS) {
782 ibt_qp->ch_current_state = qp_query_attrp->qp_info.qp_state;
783
784 /* need to fill in sgid from port and sgid_ix for RC and UC */
785 hca_devp = ibt_qp->ch_qp.qp_hca->ha_hca_devp;
786 qp_infop = &qp_query_attrp->qp_info;
787
788 switch (qp_infop->qp_trans) {
789 case IBT_RC_SRV:
790 ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_path,
791 hca_devp);
792 ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_alt_path,
793 hca_devp);
794 break;
795 case IBT_UC_SRV:
796 ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_path,
797 hca_devp);
798 ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_alt_path,
799 hca_devp);
800 break;
801 }
802 } else {
803 IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_qp: "
804 "failed on chan %p: %d", ibt_qp, retval);
805 }
806
807 return (retval);
808 }
809
810
811 /*
812 * Function:
813 * ibt_modify_qp
814 * Input:
815 * ibt_qp The IBT QP Handle.
816 * flags Specifies which attributes in ibt_qp_mod_attr_t
817 * are to be modified.
818 * qp_attrp Points to an ibt_qp_mod_attr_t struct that contains all
819 * the attributes of the specified QP that a client is
820 * allowed to modify after a QP has been allocated
821 * Output:
822 * actual_sz Returned actual queue sizes.
823 * Returns:
824 * IBT_SUCCESS
825 * Description:
826 * Modify the attributes of an existing QP.
827 */
828 ibt_status_t
829 ibt_modify_qp(ibt_qp_hdl_t ibt_qp, ibt_cep_modify_flags_t flags,
830 ibt_qp_info_t *modify_attrp, ibt_queue_sizes_t *actual_sz)
831 {
832 ibt_status_t retval;
833
834 IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_qp(%p, %d, %p, %p)",
835 ibt_qp, flags, modify_attrp, actual_sz);
836
837 ibtl_qp_flow_control_enter();
838 retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_modify_qp)(
839 IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), flags,
840 modify_attrp, actual_sz);
841 ibtl_qp_flow_control_exit();
842 if (retval == IBT_SUCCESS) {
843 ibt_qp->ch_current_state = modify_attrp->qp_state;
844 if (ibt_qp->ch_qp.qp_type == IBT_UD_SRV) {
845 if (flags & (IBT_CEP_SET_PORT | IBT_CEP_SET_RESET_INIT))
846 ibt_qp->ch_transport.ud.ud_port_num =
847 modify_attrp->qp_transport.ud.ud_port;
848 if (flags & (IBT_CEP_SET_QKEY | IBT_CEP_SET_RESET_INIT))
849 ibt_qp->ch_transport.ud.ud_qkey =
850 modify_attrp->qp_transport.ud.ud_qkey;
851 }
852 } else {
853 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_qp: failed on chan %p: %d",
854 ibt_qp, retval);
855
856 if (retval == IBT_CHAN_STATE_INVALID) {
857 /* That means our cache had invalid QP state value. */
858 ibt_qp_query_attr_t qp_attr;
859
860 /* Query the channel (QP) */
861 if (ibt_query_qp(ibt_qp, &qp_attr) == IBT_SUCCESS)
862 ibt_qp->ch_current_state =
863 qp_attr.qp_info.qp_state;
864 }
865 }
866 return (retval);
867 }
868
869
870 /*
871 * Function:
872 * ibt_migrate_path
873 * Input:
874 * rc_chan A previously allocated RC channel handle.
875 * Output:
876 * none.
877 * Returns:
878 * IBT_SUCCESS on Success else appropriate error.
879 * Description:
880 * Force the CI to use the alternate path. The alternate path becomes
881 * the primary path. A new alternate path should be loaded and enabled.
882 * Assumes that the given channel is in RTS/SQD state
883 */
884 ibt_status_t
885 ibt_migrate_path(ibt_channel_hdl_t rc_chan)
886 {
887 ibt_status_t retval;
888 ibt_qp_info_t qp_info;
889 ibt_qp_query_attr_t qp_attr;
890 ibt_cep_modify_flags_t cep_flags;
891 int retries = 1;
892
893 IBTF_DPRINTF_L3(ibtf_qp, "ibt_migrate_path: channel %p", rc_chan);
894
895 if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
896 IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path: "
897 "Invalid Channel type: Applicable only to RC Channel");
898 return (IBT_CHAN_SRV_TYPE_INVALID);
899 }
900
901 if (rc_chan->ch_current_state != IBT_STATE_RTS &&
902 rc_chan->ch_current_state != IBT_STATE_SQD) {
903 if (ibt_query_qp(rc_chan, &qp_attr) == IBT_SUCCESS) {
904 /* ch_current_state is fixed by ibt_query_qp */
905 if (rc_chan->ch_current_state != IBT_STATE_RTS &&
906 rc_chan->ch_current_state != IBT_STATE_SQD)
907 return (IBT_CHAN_STATE_INVALID);
908 retries = 0;
909 } else /* query_qp should never really fail */
910 return (IBT_CHAN_STATE_INVALID);
911 }
912
913 retry:
914 /* Call modify_qp */
915 cep_flags = IBT_CEP_SET_MIG | IBT_CEP_SET_STATE;
916 qp_info.qp_state = rc_chan->ch_current_state;
917 qp_info.qp_current_state = rc_chan->ch_current_state;
918 qp_info.qp_trans = IBT_RC_SRV;
919 qp_info.qp_transport.rc.rc_mig_state = IBT_STATE_MIGRATED;
920 retval = ibt_modify_qp(rc_chan, cep_flags, &qp_info, NULL);
921
922 if (retval != IBT_SUCCESS) {
923 IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
924 " ibt_modify_qp() returned = %d", retval);
925 if (rc_chan->ch_current_state != qp_info.qp_state &&
926 --retries >= 0) {
927 /*
928 * That means our cached 'state' was invalid.
929 * We know ibt_modify_qp() fixed it up, so it
930 * might be worth retrying.
931 */
932 if (rc_chan->ch_current_state != IBT_STATE_RTS &&
933 rc_chan->ch_current_state != IBT_STATE_SQD)
934 return (IBT_CHAN_STATE_INVALID);
935 IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
936 " retrying after 'state' fixed");
937 goto retry;
938 }
939 }
940 return (retval);
941 }
942
943
944 /*
945 * Function:
946 * ibt_set_qp_private
947 * Input:
948 * ibt_qp The ibt_qp_hdl_t of the allocated QP.
949 * clnt_private The client private data.
950 * Output:
951 * none.
952 * Returns:
953 * none.
954 * Description:
955 * Set the client private data.
956 */
957 void
958 ibt_set_qp_private(ibt_qp_hdl_t ibt_qp, void *clnt_private)
959 {
960 ibt_qp->ch_clnt_private = clnt_private;
961 }
962
963
964 /*
965 * Function:
966 * ibt_get_qp_private
967 * Input:
968 * ibt_qp The ibt_qp_hdl_t of the allocated QP.
969 * Output:
970 * none.
971 * Returns:
972 * The client private data.
973 * Description:
974 * Get the client private data.
975 */
976 void *
977 ibt_get_qp_private(ibt_qp_hdl_t ibt_qp)
978 {
979 return (ibt_qp->ch_clnt_private);
980 }
981
982
983 /*
984 * Function:
985 * ibt_qp_to_hca_guid
986 * Input:
987 * ibt_qp The ibt_qp_hdl_t of the allocated QP.
988 * Output:
989 * none.
990 * Returns:
991 * hca_guid Returned HCA GUID on which the specified QP is
992 * allocated. Valid if it is non-NULL on return.
993 * Description:
994 * A helper function to retrieve HCA GUID for the specified QP.
995 */
996 ib_guid_t
997 ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp)
998 {
999 IBTF_DPRINTF_L3(ibtf_qp, "ibt_qp_to_hca_guid(%p)", ibt_qp);
1000
1001 return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ibt_qp)));
1002 }
1003
1004
1005 /*
1006 * Function:
1007 * ibt_recover_ud_qp
1008 * Input:
1009 * ibt_qp An QP Handle which is in SQError state.
1010 * Output:
1011 * none.
1012 * Returns:
1013 * IBT_SUCCESS
1014 * IBT_QP_SRV_TYPE_INVALID
1015 * IBT_QP_STATE_INVALID.
1016 * Description:
1017 * Recover an UD QP which has transitioned to SQ Error state. The
1018 * ibt_recover_ud_qp() transitions the QP from SQ Error state to
1019 * Ready-To-Send QP state.
1020 *
1021 * If a work request posted to a UD QP's send queue completes with an
1022 * error (see ibt_wc_status_t), the QP gets transitioned to SQ Error state.
1023 * In order to reuse this QP, ibt_recover_ud_qp() can be used to recover
1024 * the QP to a usable (Ready-to-Send) state.
1025 */
1026 ibt_status_t
1027 ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp)
1028 {
1029 IBTF_DPRINTF_L3(ibtf_qp, "ibt_recover_ud_qp(%p)", ibt_qp);
1030
1031 return (ibt_recover_ud_channel(IBTL_QP2CHAN(ibt_qp)));
1032 }
1033
1034
1035 /*
1036 * Function:
1037 * ibt_recycle_ud
1038 * Input:
1039 * ud_chan The IBT UD QP Handle.
1040 * various attributes
1041 *
1042 * Output:
1043 * none
1044 * Returns:
1045 * IBT_SUCCESS
1046 * IBT_CHAN_SRV_TYPE_INVALID
1047 * IBT_CHAN_STATE_INVALID
1048 *
1049 * Description:
1050 * Revert the UD QP back to a usable state.
1051 */
1052 ibt_status_t
1053 ibt_recycle_ud(ibt_channel_hdl_t ud_chan, uint8_t hca_port_num,
1054 uint16_t pkey_ix, ib_qkey_t qkey)
1055 {
1056 ibt_qp_query_attr_t qp_attr;
1057 ibt_status_t retval;
1058
1059 IBTF_DPRINTF_L3(ibtf_qp, "ibt_recycle_ud(%p, %d, %x, %x): ",
1060 ud_chan, hca_port_num, pkey_ix, qkey);
1061
1062 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
1063 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1064 "chan %p is not a UD channel", ud_chan);
1065 return (IBT_CHAN_SRV_TYPE_INVALID);
1066 }
1067
1068 retval = ibt_query_qp(ud_chan, &qp_attr);
1069 if (retval != IBT_SUCCESS) {
1070 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1071 "ibt_query_qp failed on chan %p: %d", ud_chan, retval);
1072 return (retval);
1073 }
1074 if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR) {
1075 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1076 "chan %p is in state %d (not in ERROR state)",
1077 ud_chan, qp_attr.qp_info.qp_state);
1078 ud_chan->ch_current_state = qp_attr.qp_info.qp_state;
1079 return (IBT_CHAN_STATE_INVALID);
1080 }
1081
1082 /* transition the QP from ERROR to RESET */
1083 qp_attr.qp_info.qp_state = IBT_STATE_RESET;
1084 qp_attr.qp_info.qp_trans = ud_chan->ch_qp.qp_type;
1085 retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &qp_attr.qp_info,
1086 NULL);
1087 if (retval != IBT_SUCCESS) {
1088 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1089 "ibt_modify_qp(ERROR=>RESET) failed on chan %p: %d",
1090 ud_chan, retval);
1091 return (retval);
1092 }
1093 ud_chan->ch_current_state = IBT_STATE_RESET;
1094
1095 /* transition the QP back to RTS */
1096 qp_attr.qp_info.qp_transport.ud.ud_port = hca_port_num;
1097 qp_attr.qp_info.qp_transport.ud.ud_qkey = qkey;
1098 qp_attr.qp_info.qp_transport.ud.ud_pkey_ix = pkey_ix;
1099 retval = ibt_initialize_qp(ud_chan, &qp_attr.qp_info);
1100 if (retval != IBT_SUCCESS) {
1101 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1102 "ibt_initialize_qp failed on chan %p: %d", ud_chan, retval);
1103 /* the man page says the QP should be left in ERROR state */
1104 (void) ibt_flush_qp(ud_chan);
1105 }
1106 return (retval);
1107 }
1108
1109 /*
1110 * Function:
1111 * ibt_pause_sendq
1112 * Input:
1113 * chan The IBT QP Handle.
1114 * modify_flags IBT_CEP_SET_NOTHING or IBT_CEP_SET_SQD_EVENT
1115 *
1116 * Output:
1117 * none.
1118 * Returns:
1119 * IBT_SUCCESS
1120 * IBT_CHAN_HDL_INVALID
1121 * IBT_CHAN_STATE_INVALID
1122 * IBT_INVALID_PARAM
1123 *
1124 * Description:
1125 * Place the send queue of the specified channel into the send queue
1126 * drained (SQD) state.
1127 *
1128 */
1129 ibt_status_t
1130 ibt_pause_sendq(ibt_channel_hdl_t chan, ibt_cep_modify_flags_t modify_flags)
1131 {
1132 ibt_qp_info_t modify_attr;
1133 ibt_status_t retval;
1134
1135 IBTF_DPRINTF_L3(ibtf_qp, "ibt_pause_sendq(%p, %x)", chan, modify_flags);
1136
1137 modify_flags &= IBT_CEP_SET_SQD_EVENT; /* ignore other bits */
1138 modify_flags |= IBT_CEP_SET_STATE;
1139
1140 bzero(&modify_attr, sizeof (ibt_qp_info_t));
1141 /*
1142 * Set the QP state to SQD.
1143 */
1144 modify_attr.qp_state = IBT_STATE_SQD;
1145 modify_attr.qp_trans = chan->ch_qp.qp_type;
1146
1147 retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
1148
1149 if (retval != IBT_SUCCESS) {
1150 IBTF_DPRINTF_L2(ibtf_qp, "ibt_pause_sendq: "
1151 "failed on chan %p: %d", chan, retval);
1152 }
1153 return (retval);
1154 }
1155
1156
1157 /*
1158 * Function:
1159 * ibt_unpause_sendq
1160 * Input:
1161 * chan The IBT Channel Handle.
1162 * Output:
1163 * none.
1164 * Returns:
1165 * IBT_SUCCESS
1166 * IBT_CHAN_HDL_INVALID
1167 * IBT_CHAN_STATE_INVALID
1168 * Description:
1169 * Un-pauses the previously paused channel. This call will transition the
1170 * QP from SQD to RTS state.
1171 */
1172 ibt_status_t
1173 ibt_unpause_sendq(ibt_channel_hdl_t chan)
1174 {
1175 ibt_qp_info_t modify_attr;
1176 ibt_status_t retval;
1177
1178 IBTF_DPRINTF_L3(ibtf_qp, "ibt_unpause_sendq(%p)", chan);
1179
1180 bzero(&modify_attr, sizeof (ibt_qp_info_t));
1181
1182 /*
1183 * Set the QP state to RTS.
1184 */
1185 modify_attr.qp_current_state = IBT_STATE_SQD;
1186 modify_attr.qp_state = IBT_STATE_RTS;
1187 modify_attr.qp_trans = chan->ch_qp.qp_type;
1188
1189 retval = ibt_modify_qp(chan, IBT_CEP_SET_STATE, &modify_attr, NULL);
1190 if (retval != IBT_SUCCESS) {
1191 IBTF_DPRINTF_L2(ibtf_qp, "ibt_unpause_sendq: "
1192 "failed on chan %p: %d", chan, retval);
1193 }
1194 return (retval);
1195 }
1196
1197
1198 /*
1199 * Function:
1200 * ibt_resize_queues
1201 * Input:
1202 * chan A previously allocated channel handle.
1203 * flags QP Flags
1204 * IBT_SEND_Q
1205 * IBT_RECV_Q
1206 * request_sz Requested new sizes.
1207 * Output:
1208 * actual_sz Returned actual sizes.
1209 * Returns:
1210 * IBT_SUCCESS
1211 * Description:
1212 * Resize the SendQ/RecvQ sizes of a channel. Can only be called on
1213 * a previously opened channel.
1214 */
1215 ibt_status_t
1216 ibt_resize_queues(ibt_channel_hdl_t chan, ibt_qflags_t flags,
1217 ibt_queue_sizes_t *request_sz, ibt_queue_sizes_t *actual_sz)
1218 {
1219 ibt_cep_modify_flags_t modify_flags = IBT_CEP_SET_STATE;
1220 ibt_qp_info_t modify_attr;
1221 ibt_status_t retval;
1222
1223 IBTF_DPRINTF_L3(ibtf_qp, "ibt_resize_queues(%p, 0x%X, %p, %p)",
1224 chan, flags, request_sz, actual_sz);
1225
1226 if ((flags & (IBT_SEND_Q | IBT_RECV_Q)) == 0) {
1227 IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
1228 "Flags <0x%X> not set", flags);
1229 return (IBT_INVALID_PARAM);
1230 }
1231
1232 bzero(&modify_attr, sizeof (ibt_qp_info_t));
1233
1234 modify_attr.qp_current_state = chan->ch_current_state;
1235 modify_attr.qp_trans = chan->ch_qp.qp_type;
1236 modify_attr.qp_state = chan->ch_current_state;
1237
1238 if (flags & IBT_SEND_Q) {
1239 modify_attr.qp_sq_sz = request_sz->qs_sq;
1240 modify_flags |= IBT_CEP_SET_SQ_SIZE;
1241 }
1242
1243 if (flags & IBT_RECV_Q) {
1244 modify_attr.qp_rq_sz = request_sz->qs_rq;
1245 modify_flags |= IBT_CEP_SET_RQ_SIZE;
1246 }
1247
1248 retval = ibt_modify_qp(chan, modify_flags, &modify_attr, actual_sz);
1249 if (retval != IBT_SUCCESS) {
1250 IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
1251 "failed on QP %p: %d", chan, retval);
1252 }
1253
1254 return (retval);
1255 }
1256
1257
1258 /*
1259 * Function:
1260 * ibt_query_queues
1261 * Input:
1262 * chan A previously allocated channel handle.
1263 * Output:
1264 * actual_sz Returned actual sizes.
1265 * Returns:
1266 * IBT_SUCCESS
1267 * Description:
1268 * Query the SendQ/RecvQ sizes of a channel.
1269 */
1270 ibt_status_t
1271 ibt_query_queues(ibt_channel_hdl_t chan, ibt_queue_sizes_t *actual_sz)
1272 {
1273 ibt_status_t retval;
1274 ibt_qp_query_attr_t qp_query_attr;
1275
1276 IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_queues(%p)", chan);
1277
1278 /* Perform Query QP and retrieve QP sizes. */
1279 retval = ibt_query_qp(chan, &qp_query_attr);
1280 if (retval != IBT_SUCCESS) {
1281 IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_queues: "
1282 "ibt_query_qp failed: qp %p: %d", chan, retval);
1283 return (retval);
1284 }
1285
1286 actual_sz->qs_sq = qp_query_attr.qp_info.qp_sq_sz;
1287 actual_sz->qs_rq = qp_query_attr.qp_info.qp_rq_sz;
1288 chan->ch_current_state = qp_query_attr.qp_info.qp_state;
1289
1290 return (retval);
1291 }
1292
1293
1294 /*
1295 * Function:
1296 * ibt_modify_rdma
1297 * Input:
1298 * rc_chan A previously allocated channel handle.
1299 *
1300 * modify_flags Bitwise "or" of any of the following:
1301 * IBT_CEP_SET_RDMA_R Enable/Disable RDMA RD
1302 * IBT_CEP_SET_RDMA_W Enable/Disable RDMA WR
1303 * IBT_CEP_SET_ATOMIC Enable/Disable Atomics
1304 *
1305 * flags Channel End Point (CEP) Disable Flags (0 => enable).
1306 * IBT_CEP_NO_RDMA_RD Disable incoming RDMA RD's
1307 * IBT_CEP_NO_RDMA_WR Disable incoming RDMA WR's
1308 * IBT_CEP_NO_ATOMIC Disable incoming Atomics.
1309 * Output:
1310 * none.
1311 * Returns:
1312 * IBT_SUCCESS
1313 * IBT_QP_SRV_TYPE_INVALID
1314 * IBT_CHAN_HDL_INVALID
1315 * IBT_CHAN_ATOMICS_NOT_SUPPORTED
1316 * IBT_CHAN_STATE_INVALID
1317 * Description:
1318 * Enable/disable RDMA operations. To enable an operation clear the
1319 * "disable" flag. Can call this function when the channel is in
1320 * INIT, RTS or SQD states. If called in any other state
1321 * IBT_CHAN_STATE_INVALID is returned. When the operation completes the
1322 * channel state is left unchanged.
1323 */
1324 ibt_status_t
1325 ibt_modify_rdma(ibt_channel_hdl_t rc_chan,
1326 ibt_cep_modify_flags_t modify_flags, ibt_cep_flags_t flags)
1327 {
1328 ibt_status_t retval;
1329 ibt_qp_info_t modify_attr;
1330
1331 IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_rdma(%p, 0x%x, 0x%x)",
1332 rc_chan, modify_flags, flags);
1333
1334 if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
1335 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
1336 "Invalid Channel type: 0x%X, Applicable only to RC Channel",
1337 rc_chan->ch_qp.qp_type);
1338 return (IBT_QP_SRV_TYPE_INVALID);
1339 }
1340
1341 bzero(&modify_attr, sizeof (ibt_qp_info_t));
1342
1343 /*
1344 * Can only call this function when the channel in INIT, RTS or SQD
1345 * states.
1346 */
1347 if ((rc_chan->ch_current_state != IBT_STATE_INIT) &&
1348 (rc_chan->ch_current_state != IBT_STATE_RTS) &&
1349 (rc_chan->ch_current_state != IBT_STATE_SQD)) {
1350 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: Invalid Channel "
1351 "state: 0x%X", rc_chan->ch_current_state);
1352 return (IBT_CHAN_STATE_INVALID);
1353 }
1354
1355 modify_attr.qp_state = modify_attr.qp_current_state =
1356 rc_chan->ch_current_state;
1357 modify_attr.qp_trans = rc_chan->ch_qp.qp_type;
1358 modify_attr.qp_flags = flags;
1359
1360 modify_flags &= (IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
1361 IBT_CEP_SET_ATOMIC);
1362 modify_flags |= IBT_CEP_SET_STATE;
1363
1364 retval = ibt_modify_qp(rc_chan, modify_flags, &modify_attr, NULL);
1365 if (retval != IBT_SUCCESS) {
1366 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
1367 "failed on chan %p: %d", rc_chan, retval);
1368 }
1369 return (retval);
1370 }
1371
1372
1373 /*
1374 * Function:
1375 * ibt_set_rdma_resource
1376 * Input:
1377 * chan A previously allocated RC channel handle.
1378 * modify_flags Bitwise "or" of any of the following:
1379 * IBT_CEP_SET_RDMARA_OUT Initiator depth (rdma_ra_out)
1380 * IBT_CEP_SET_RDMARA_IN Responder Resources
1381 * (rdma_ra_in)
1382 * rdma_ra_out Outgoing RDMA Reads/Atomics
1383 * rdma_ra_in Incoming RDMA Reads/Atomics
1384 * Output:
1385 * none.
1386 * Returns:
1387 * IBT_SUCCESS
1388 * Description:
1389 * Change the number of resources to be used for incoming and outgoing
1390 * RDMA reads & Atomics. Can only be called on a previously opened
1391 * RC channel. Can only be called on a paused channel, and this will
1392 * un-pause that channel.
1393 */
1394 ibt_status_t
1395 ibt_set_rdma_resource(ibt_channel_hdl_t chan,
1396 ibt_cep_modify_flags_t modify_flags, uint8_t rdma_ra_out,
1397 uint8_t resp_rdma_ra_out)
1398 {
1399 ibt_qp_info_t modify_attr;
1400 ibt_status_t retval;
1401
1402 IBTF_DPRINTF_L3(ibtf_qp, "ibt_set_rdma_resource(%p, 0x%x, %d, %d)",
1403 chan, modify_flags, rdma_ra_out, resp_rdma_ra_out);
1404
1405 if (chan->ch_qp.qp_type != IBT_RC_SRV) {
1406 IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
1407 "Invalid Channel type: 0x%X, Applicable only to RC Channel",
1408 chan->ch_qp.qp_type);
1409 return (IBT_CHAN_SRV_TYPE_INVALID);
1410 }
1411
1412 bzero(&modify_attr, sizeof (ibt_qp_info_t));
1413
1414 modify_attr.qp_trans = chan->ch_qp.qp_type;
1415 modify_attr.qp_state = IBT_STATE_SQD;
1416
1417 modify_attr.qp_transport.rc.rc_rdma_ra_out = rdma_ra_out;
1418 modify_attr.qp_transport.rc.rc_rdma_ra_in = resp_rdma_ra_out;
1419 modify_flags &= (IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN);
1420 modify_flags |= IBT_CEP_SET_STATE;
1421
1422 retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
1423 if (retval != IBT_SUCCESS) {
1424 IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
1425 "failed on chan %p: %d", chan, retval);
1426 }
1427 return (retval);
1428 }
1429
1430
1431 /*
1432 * Function:
1433 * ibt_change_port
1434 * Input:
1435 * rc_chan A previously allocated RC channel handle.
1436 * port_num New HCA port.
1437 * Output:
1438 * none.
1439 * Returns:
1440 * IBT_SUCCESS
1441 * Description:
1442 * Change the primary physical port of a channel. (This is done only if
1443 * HCA supports this capability).
1444 */
1445 ibt_status_t
1446 ibt_change_port(ibt_channel_hdl_t chan, uint8_t port_num)
1447 {
1448 ibt_cep_modify_flags_t modify_flags;
1449 ibt_qp_info_t modify_attr;
1450 ibt_status_t retval;
1451
1452 IBTF_DPRINTF_L3(ibtf_qp, "ibt_change_port(%p, %d)", chan, port_num);
1453
1454 if (chan->ch_qp.qp_type != IBT_RC_SRV) {
1455 IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
1456 "Invalid Channel type: 0x%X, Applicable only to RC Channel",
1457 chan->ch_qp.qp_type);
1458 return (IBT_CHAN_SRV_TYPE_INVALID);
1459 }
1460 bzero(&modify_attr, sizeof (ibt_qp_info_t));
1461
1462 modify_attr.qp_state = IBT_STATE_SQD;
1463 modify_attr.qp_trans = chan->ch_qp.qp_type;
1464 modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = port_num;
1465
1466 modify_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
1467
1468 retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
1469 if (retval != IBT_SUCCESS) {
1470 IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
1471 "failed on chan %p: %d", chan, retval);
1472 }
1473 return (retval);
1474 }
1475
1476
1477 void
1478 ibtl_init_cep_states(void)
1479 {
1480 int index;
1481 int ibt_nstate_inits;
1482
1483 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_init_cep_states()");
1484
1485 ibt_nstate_inits = sizeof (ibt_cep_next_state_inits) /
1486 sizeof (ibt_cep_next_state_inits[0]);
1487
1488 /*
1489 * Initialize CEP next state table, using an indirect lookup table so
1490 * that this code isn't dependent on the ibt_cep_state_t enum values.
1491 */
1492 for (index = 0; index < ibt_nstate_inits; index++) {
1493 ibt_cep_state_t state;
1494
1495 state = ibt_cep_next_state_inits[index].current_state;
1496
1497 ibt_cep_next_state[state].next_state =
1498 ibt_cep_next_state_inits[index].next_state;
1499
1500 ibt_cep_next_state[state].modify_flags =
1501 ibt_cep_next_state_inits[index].modify_flags;
1502 }
1503 }