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