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 /*
26 * ibtl_chan.c
27 *
28 * This file contains Transport API functions related to Channel Functions
29 * and internal Protection Domain and Address Handle Verbs functions.
30 */
31
32 #include <sys/ib/ibtl/impl/ibtl.h>
33 #include <sys/ib/ibtl/impl/ibtl_cm.h>
34 #include <sys/ib/ib_pkt_hdrs.h>
35
36 static char ibtl_chan[] = "ibtl_chan";
37
38 /*
39 * RC Channel.
40 */
41 /*
42 * Function:
43 * ibt_alloc_rc_channel
44 * Input:
45 * hca_hdl HCA Handle.
46 * flags Channel allocate flags.
47 * args A pointer to an ibt_rc_chan_alloc_args_t struct that
48 * specifies required channel attributes.
49 * Output:
50 * rc_chan_p The returned RC Channel handle.
51 * sizes NULL or a pointer to ibt_chan_sizes_s struct where
52 * new SendQ/RecvQ, and WR SGL sizes are returned.
53 * Returns:
54 * IBT_SUCCESS
55 * IBT_INVALID_PARAM
56 * Description:
57 * Allocates a RC communication channels that satisfy the specified
58 * channel attributes.
59 */
60 ibt_status_t
ibt_alloc_rc_channel(ibt_hca_hdl_t hca_hdl,ibt_chan_alloc_flags_t flags,ibt_rc_chan_alloc_args_t * args,ibt_channel_hdl_t * rc_chan_p,ibt_chan_sizes_t * sizes)61 ibt_alloc_rc_channel(ibt_hca_hdl_t hca_hdl, ibt_chan_alloc_flags_t flags,
62 ibt_rc_chan_alloc_args_t *args, ibt_channel_hdl_t *rc_chan_p,
63 ibt_chan_sizes_t *sizes)
64 {
65 ibt_status_t retval;
66 ibt_qp_alloc_attr_t qp_attr;
67 ibt_qp_info_t qp_modify_attr;
68 ibt_channel_hdl_t chanp;
69
70 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_rc_channel(%p, %x, %p, %p)",
71 hca_hdl, flags, args, sizes);
72
73 bzero(&qp_modify_attr, sizeof (ibt_qp_info_t));
74
75 qp_attr.qp_alloc_flags = IBT_QP_NO_FLAGS;
76 if (flags & IBT_ACHAN_USER_MAP)
77 qp_attr.qp_alloc_flags |= IBT_QP_USER_MAP;
78
79 if (flags & IBT_ACHAN_DEFER_ALLOC)
80 qp_attr.qp_alloc_flags |= IBT_QP_DEFER_ALLOC;
81
82 if (flags & IBT_ACHAN_USES_SRQ) {
83 if (args->rc_srq == NULL) {
84 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
85 "NULL SRQ Handle specified.");
86 return (IBT_INVALID_PARAM);
87 }
88 qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ;
89 }
90
91 /*
92 * Check if this request is to clone the channel, or to allocate a
93 * fresh one.
94 */
95 if (flags & IBT_ACHAN_CLONE) {
96
97 ibt_rc_chan_query_attr_t chan_attrs;
98
99 if (args->rc_clone_chan == NULL) {
100 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
101 "Clone Channel info not available.");
102 return (IBT_INVALID_PARAM);
103 } else if (args->rc_clone_chan->ch_qp.qp_hca != hca_hdl) {
104 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
105 "Clone Channel's & requested HCA Handle mismatch");
106 return (IBT_INVALID_PARAM);
107 }
108
109 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_rc_channel: "
110 "Clone <%p> - RC Channel", args->rc_clone_chan);
111
112 /*
113 * Query the source channel, to obtained the attributes
114 * so that the new channel share the same attributes.
115 */
116 retval = ibt_query_rc_channel(args->rc_clone_chan, &chan_attrs);
117 if (retval != IBT_SUCCESS) {
118 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
119 "Failed to query the source channel: %d", retval);
120 return (retval);
121 }
122
123 /* Setup QP alloc attributes. */
124 qp_attr.qp_scq_hdl = chan_attrs.rc_scq;
125 qp_attr.qp_rcq_hdl = chan_attrs.rc_rcq;
126 qp_attr.qp_pd_hdl = chan_attrs.rc_pd;
127 qp_attr.qp_flags = chan_attrs.rc_flags;
128 qp_attr.qp_srq_hdl = chan_attrs.rc_srq;
129
130 bcopy(&chan_attrs.rc_chan_sizes, &qp_attr.qp_sizes,
131 sizeof (ibt_chan_sizes_t));
132
133 qp_modify_attr.qp_flags = chan_attrs.rc_control;
134 qp_modify_attr.qp_transport.rc.rc_path.cep_hca_port_num =
135 chan_attrs.rc_prim_path.cep_hca_port_num;
136 qp_modify_attr.qp_transport.rc.rc_path.cep_pkey_ix =
137 chan_attrs.rc_prim_path.cep_pkey_ix;
138
139 } else {
140
141 /* Setup QP alloc attributes. */
142 qp_attr.qp_scq_hdl = args->rc_scq;
143 qp_attr.qp_rcq_hdl = args->rc_rcq;
144 qp_attr.qp_pd_hdl = args->rc_pd;
145 qp_attr.qp_flags = args->rc_flags;
146 qp_attr.qp_srq_hdl = args->rc_srq;
147
148 bcopy(&args->rc_sizes, &qp_attr.qp_sizes,
149 sizeof (ibt_chan_sizes_t));
150
151 qp_modify_attr.qp_flags = args->rc_control;
152
153 if ((args->rc_hca_port_num == 0) ||
154 (args->rc_hca_port_num > IBTL_HCA2NPORTS(hca_hdl))) {
155 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
156 "Invalid port_num %d, range is (1 to %d)",
157 args->rc_hca_port_num, IBTL_HCA2NPORTS(hca_hdl));
158 return (IBT_HCA_PORT_INVALID);
159 }
160 qp_modify_attr.qp_transport.rc.rc_path.cep_hca_port_num =
161 args->rc_hca_port_num;
162
163 /*
164 * We allocate the Channel initially with the default PKey,
165 * and later client can update this when the channel is opened
166 * with the pkey returned from a path record lookup.
167 */
168 mutex_enter(&ibtl_clnt_list_mutex);
169 qp_modify_attr.qp_transport.rc.rc_path.cep_pkey_ix =
170 hca_hdl->ha_hca_devp->
171 hd_portinfop[args->rc_hca_port_num - 1].p_def_pkey_ix;
172 mutex_exit(&ibtl_clnt_list_mutex);
173 }
174
175 /* Allocate Channel and Initialize the channel. */
176 retval = ibt_alloc_qp(hca_hdl, IBT_RC_RQP, &qp_attr, sizes, NULL,
177 &chanp);
178 if (retval != IBT_SUCCESS) {
179 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
180 "Failed to allocate QP: %d", retval);
181 *rc_chan_p = NULL;
182 return (retval);
183 }
184
185 qp_modify_attr.qp_trans = IBT_RC_SRV;
186
187 /* Initialize RC Channel by transitioning it to INIT State. */
188 retval = ibt_initialize_qp(chanp, &qp_modify_attr);
189 if (retval != IBT_SUCCESS) {
190 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
191 "Failed to Initialize QP: %d", retval);
192
193 /* Free the QP as we failed to initialize it. */
194 (void) ibt_free_qp(chanp);
195
196 *rc_chan_p = NULL;
197 return (retval);
198 }
199
200 *rc_chan_p = chanp;
201
202 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_rc_channel(%p): - SUCCESS (%p)",
203 hca_hdl, chanp);
204
205 return (IBT_SUCCESS);
206 }
207
208
209 /*
210 * Function:
211 * ibt_query_rc_channel
212 * Input:
213 * rc_chan A previously allocated channel handle.
214 * chan_attrs A pointer to an ibt_rc_chan_query_args_t struct where
215 * Channel's current attributes are returned.
216 * Output:
217 * chan_attrs A pointer to an ibt_rc_chan_query_args_t struct where
218 * Channel's current attributes are returned.
219 * Returns:
220 * IBT_SUCCESS
221 * Description:
222 * Query an RC channel's attributes.
223 */
224 ibt_status_t
ibt_query_rc_channel(ibt_channel_hdl_t rc_chan,ibt_rc_chan_query_attr_t * chan_attrs)225 ibt_query_rc_channel(ibt_channel_hdl_t rc_chan,
226 ibt_rc_chan_query_attr_t *chan_attrs)
227 {
228 ibt_status_t retval;
229 ibt_qp_query_attr_t qp_attr;
230
231 IBTF_DPRINTF_L3(ibtl_chan, "ibt_query_rc_channel(%p, %p)",
232 rc_chan, chan_attrs);
233
234 if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
235 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_rc_channel: "
236 "type of channel (%d) is not RC", rc_chan->ch_qp.qp_type);
237 return (IBT_CHAN_SRV_TYPE_INVALID);
238 }
239
240 bzero(&qp_attr, sizeof (ibt_qp_query_attr_t));
241
242 /* Query the channel (QP) */
243 retval = ibt_query_qp(rc_chan, &qp_attr);
244 if (retval != IBT_SUCCESS) {
245 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_rc_channel: "
246 "ibt_query_qp failed on QP %p: %d", rc_chan, retval);
247 return (retval);
248 }
249
250 chan_attrs->rc_hca_guid = IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(rc_chan));
251
252 chan_attrs->rc_scq = qp_attr.qp_sq_cq;
253 chan_attrs->rc_rcq = qp_attr.qp_rq_cq;
254 chan_attrs->rc_pd = rc_chan->ch_qp.qp_pd_hdl;
255 chan_attrs->rc_state = qp_attr.qp_info.qp_state;
256 chan_attrs->rc_path_mtu = qp_attr.qp_info.qp_transport.rc.rc_path_mtu;
257 chan_attrs->rc_path_retry_cnt =
258 qp_attr.qp_info.qp_transport.rc.rc_retry_cnt;
259 chan_attrs->rc_path_rnr_retry_cnt =
260 qp_attr.qp_info.qp_transport.rc.rc_rnr_retry_cnt;
261 chan_attrs->rc_min_rnr_nak =
262 qp_attr.qp_info.qp_transport.rc.rc_min_rnr_nak;
263
264 chan_attrs->rc_prim_path = qp_attr.qp_info.qp_transport.rc.rc_path;
265 chan_attrs->rc_alt_path = qp_attr.qp_info.qp_transport.rc.rc_alt_path;
266
267 chan_attrs->rc_chan_sizes.cs_sq = qp_attr.qp_info.qp_sq_sz;
268 chan_attrs->rc_chan_sizes.cs_rq = qp_attr.qp_info.qp_rq_sz;
269 chan_attrs->rc_chan_sizes.cs_sq_sgl = qp_attr.qp_sq_sgl;
270 chan_attrs->rc_chan_sizes.cs_rq_sgl = qp_attr.qp_rq_sgl;
271 chan_attrs->rc_srq = qp_attr.qp_srq;
272
273 chan_attrs->rc_rdma_ra_out =
274 qp_attr.qp_info.qp_transport.rc.rc_rdma_ra_out;
275 chan_attrs->rc_rdma_ra_in =
276 qp_attr.qp_info.qp_transport.rc.rc_rdma_ra_in;
277
278 chan_attrs->rc_flags = rc_chan->ch_qp.qp_flags;
279 chan_attrs->rc_control = qp_attr.qp_info.qp_flags;
280 chan_attrs->rc_mig_state = qp_attr.qp_info.qp_transport.rc.rc_mig_state;
281
282 chan_attrs->rc_qpn = qp_attr.qp_qpn & IB_QPN_MASK;
283 chan_attrs->rc_dst_qpn =
284 qp_attr.qp_info.qp_transport.rc.rc_dst_qpn & IB_QPN_MASK;
285
286 return (retval);
287 }
288
289
290 /*
291 * Function:
292 * ibt_modify_rc_channel
293 * Input:
294 * rc_chan A previously allocated channel handle.
295 * flags Specifies which attributes in ibt_rc_chan_modify_attr_t
296 * are to be modified.
297 * attrs Attributes to be modified.
298 * Output:
299 * actual_sz On return contains the new send and receive queue sizes.
300 * Returns:
301 * IBT_SUCCESS
302 * Description:
303 * Modifies an RC channel's attributes, as specified by a
304 * ibt_cep_modify_flags_t parameter to those specified in the
305 * ibt_rc_chan_modify_attr_t structure.
306 */
307 ibt_status_t
ibt_modify_rc_channel(ibt_channel_hdl_t rc_chan,ibt_cep_modify_flags_t flags,ibt_rc_chan_modify_attr_t * attrs,ibt_queue_sizes_t * actual_sz)308 ibt_modify_rc_channel(ibt_channel_hdl_t rc_chan, ibt_cep_modify_flags_t flags,
309 ibt_rc_chan_modify_attr_t *attrs, ibt_queue_sizes_t *actual_sz)
310 {
311 ibt_status_t retval;
312 ibt_qp_info_t qp_info;
313 int retries = 1;
314
315 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_rc_channel(%p, %x, %p, %p)",
316 rc_chan, flags, attrs, actual_sz);
317
318 if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
319 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_rc_channel: "
320 "type of channel (%d) is not RC", rc_chan->ch_qp.qp_type);
321 return (IBT_CHAN_SRV_TYPE_INVALID);
322 }
323
324 retry:
325 bzero(&qp_info, sizeof (ibt_qp_info_t));
326
327 if (flags & IBT_CEP_SET_ADDS_VECT) {
328 bcopy(&attrs->rc_prim_adds_vect,
329 &qp_info.qp_transport.rc.rc_path.cep_adds_vect,
330 sizeof (ibt_adds_vect_t));
331 }
332
333 qp_info.qp_trans = IBT_RC_SRV;
334 qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
335 attrs->rc_prim_port_num;
336 qp_info.qp_transport.rc.rc_retry_cnt = attrs->rc_path_retry_cnt;
337 qp_info.qp_transport.rc.rc_rnr_retry_cnt =
338 attrs->rc_path_rnr_retry_cnt;
339 qp_info.qp_transport.rc.rc_rdma_ra_out = attrs->rc_rdma_ra_out;
340 qp_info.qp_transport.rc.rc_rdma_ra_in = attrs->rc_rdma_ra_in;
341
342 /* Current channel state must be either SQD or RTS. */
343 qp_info.qp_current_state = rc_chan->ch_current_state;
344 qp_info.qp_state = rc_chan->ch_current_state; /* No Change in State */
345
346 qp_info.qp_flags = attrs->rc_control;
347 qp_info.qp_sq_sz = attrs->rc_sq_sz;
348 qp_info.qp_rq_sz = attrs->rc_rq_sz;
349 qp_info.qp_transport.rc.rc_min_rnr_nak = attrs->rc_min_rnr_nak;
350
351 if (flags & IBT_CEP_SET_ALT_PATH) {
352 bcopy(&attrs->rc_alt_adds_vect,
353 &qp_info.qp_transport.rc.rc_alt_path.cep_adds_vect,
354 sizeof (ibt_adds_vect_t));
355 qp_info.qp_transport.rc.rc_alt_path.cep_hca_port_num =
356 attrs->rc_alt_port_num;
357 }
358
359 flags |= IBT_CEP_SET_STATE;
360
361 retval = ibt_modify_qp(rc_chan, flags, &qp_info, actual_sz);
362 if (retval != IBT_SUCCESS) {
363 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_rc_channel: "
364 "ibt_modify_qp failed on QP %p: %d", rc_chan, retval);
365 /* give it one more shot if the old current state was stale */
366 if (qp_info.qp_current_state != rc_chan->ch_current_state &&
367 --retries >= 0 &&
368 (qp_info.qp_current_state == IBT_STATE_RTS ||
369 qp_info.qp_current_state == IBT_STATE_SQD))
370 goto retry;
371 }
372
373 return (retval);
374 }
375
376
377 /*
378 * UD Channel.
379 */
380 /*
381 * Function:
382 * ibt_alloc_ud_channel
383 * Input:
384 * hca_hdl HCA Handle.
385 * flags Channel allocate flags.
386 * args A pointer to an ibt_ud_chan_alloc_args_t struct that
387 * specifies required channel attributes.
388 * Output:
389 * ud_chan_p The returned UD Channel handle.
390 * sizes NULL or a pointer to ibt_chan_sizes_s struct where
391 * new SendQ/RecvQ, and WR SGL sizes are returned.
392 * Returns:
393 * IBT_SUCCESS
394 * IBT_INVALID_PARAM
395 * Description:
396 * Allocate UD channels that satisfy the specified channel attributes.
397 */
398 ibt_status_t
ibt_alloc_ud_channel(ibt_hca_hdl_t hca_hdl,ibt_chan_alloc_flags_t flags,ibt_ud_chan_alloc_args_t * args,ibt_channel_hdl_t * ud_chan_p,ibt_chan_sizes_t * sizes)399 ibt_alloc_ud_channel(ibt_hca_hdl_t hca_hdl, ibt_chan_alloc_flags_t flags,
400 ibt_ud_chan_alloc_args_t *args, ibt_channel_hdl_t *ud_chan_p,
401 ibt_chan_sizes_t *sizes)
402 {
403 ibt_status_t retval;
404 ibt_qp_alloc_attr_t qp_attr;
405 ibt_qp_info_t qp_modify_attr;
406 ibt_channel_hdl_t chanp;
407 ibt_chan_alloc_flags_t variant_flags;
408
409 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel(%p, %x, %p, %p)",
410 hca_hdl, flags, args, sizes);
411
412 if (flags & IBT_ACHAN_USES_FEXCH) {
413 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
414 "FEXCH QPs are allocated by ibt_alloc_ud_channel_range()");
415 return (IBT_CHAN_SRV_TYPE_INVALID);
416 }
417
418 bzero(&qp_modify_attr, sizeof (ibt_qp_info_t));
419 bzero(&qp_attr, sizeof (ibt_qp_alloc_attr_t));
420 qp_attr.qp_alloc_flags = IBT_QP_NO_FLAGS;
421
422 /* allow at most one of these flags */
423 variant_flags = flags & (IBT_ACHAN_USER_MAP | IBT_ACHAN_USES_RSS |
424 IBT_ACHAN_USES_RFCI | IBT_ACHAN_USES_FCMD | IBT_ACHAN_CLONE);
425 switch (variant_flags) {
426 case IBT_ACHAN_USER_MAP:
427 qp_attr.qp_alloc_flags |= IBT_QP_USER_MAP;
428 break;
429 case IBT_ACHAN_USES_RSS:
430 qp_attr.qp_alloc_flags |= IBT_QP_USES_RSS;
431 qp_modify_attr.qp_transport.ud.ud_rss = args->ud_rss;
432 break;
433 case IBT_ACHAN_USES_RFCI:
434 qp_attr.qp_alloc_flags |= IBT_QP_USES_RFCI;
435 qp_modify_attr.qp_transport.ud.ud_fc = qp_attr.qp_fc =
436 args->ud_fc;
437 break;
438 case IBT_ACHAN_USES_FCMD:
439 qp_attr.qp_alloc_flags |= IBT_QP_USES_FCMD;
440 qp_modify_attr.qp_transport.ud.ud_fc = qp_attr.qp_fc =
441 args->ud_fc;
442 break;
443 case IBT_ACHAN_CLONE:
444 case 0:
445 break;
446 default:
447 return (IBT_INVALID_PARAM);
448 }
449
450 if (flags & IBT_ACHAN_DEFER_ALLOC)
451 qp_attr.qp_alloc_flags |= IBT_QP_DEFER_ALLOC;
452
453 if (flags & IBT_ACHAN_USES_SRQ) {
454 if (args->ud_srq == NULL) {
455 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
456 "NULL SRQ Handle specified.");
457 return (IBT_INVALID_PARAM);
458 }
459 if (flags & IBT_ACHAN_USES_RSS) {
460 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
461 "SRQ not allowed with RSS.");
462 return (IBT_INVALID_PARAM);
463 }
464 qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ;
465 }
466
467 /*
468 * Check if this request is to clone the channel, or to allocate a
469 * fresh one.
470 */
471 if (flags & IBT_ACHAN_CLONE) {
472
473 ibt_ud_chan_query_attr_t chan_attrs;
474
475 if (args->ud_clone_chan == NULL) {
476 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
477 "Clone Channel info not available.");
478 return (IBT_INVALID_PARAM);
479 } else if (args->ud_clone_chan->ch_qp.qp_hca != hca_hdl) {
480 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
481 "Clone Channel and HCA Handle mismatch");
482 return (IBT_INVALID_PARAM);
483 }
484
485 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel: "
486 "Clone <%p> - UD Channel", args->ud_clone_chan);
487
488 retval = ibt_query_ud_channel(args->ud_clone_chan, &chan_attrs);
489 if (retval != IBT_SUCCESS) {
490 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
491 "Failed to Query the source channel: %d", retval);
492 return (retval);
493 }
494
495 /* Setup QP alloc attributes. */
496 qp_attr.qp_scq_hdl = chan_attrs.ud_scq;
497 qp_attr.qp_rcq_hdl = chan_attrs.ud_rcq;
498 qp_attr.qp_pd_hdl = chan_attrs.ud_pd;
499 qp_attr.qp_flags = chan_attrs.ud_flags;
500 qp_attr.qp_srq_hdl = chan_attrs.ud_srq;
501
502 bcopy(&chan_attrs.ud_chan_sizes, &qp_attr.qp_sizes,
503 sizeof (ibt_chan_sizes_t));
504
505 qp_modify_attr.qp_transport.ud.ud_port =
506 chan_attrs.ud_hca_port_num;
507 qp_modify_attr.qp_transport.ud.ud_qkey = chan_attrs.ud_qkey;
508 qp_modify_attr.qp_transport.ud.ud_pkey_ix =
509 chan_attrs.ud_pkey_ix;
510 } else {
511 ib_pkey_t tmp_pkey;
512
513 /* Setup QP alloc attributes. */
514 qp_attr.qp_scq_hdl = args->ud_scq;
515 qp_attr.qp_rcq_hdl = args->ud_rcq;
516 qp_attr.qp_pd_hdl = args->ud_pd;
517 qp_attr.qp_flags = args->ud_flags;
518 qp_attr.qp_srq_hdl = args->ud_srq;
519
520 bcopy(&args->ud_sizes, &qp_attr.qp_sizes,
521 sizeof (ibt_chan_sizes_t));
522
523 qp_modify_attr.qp_transport.ud.ud_port = args->ud_hca_port_num;
524 qp_modify_attr.qp_transport.ud.ud_qkey = args->ud_qkey;
525
526 /* Validate input hca_port_num and pkey_ix values. */
527 if ((retval = ibt_index2pkey(hca_hdl, args->ud_hca_port_num,
528 args->ud_pkey_ix, &tmp_pkey)) != IBT_SUCCESS) {
529 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
530 "ibt_index2pkey failed, status: %d", retval);
531 *ud_chan_p = NULL;
532 return (retval);
533 }
534 qp_modify_attr.qp_transport.ud.ud_pkey_ix = args->ud_pkey_ix;
535 }
536
537 /* Allocate Channel and Initialize the channel. */
538 retval = ibt_alloc_qp(hca_hdl, IBT_UD_RQP, &qp_attr, sizes, NULL,
539 &chanp);
540 if (retval != IBT_SUCCESS) {
541 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
542 "Failed to allocate QP: %d", retval);
543 *ud_chan_p = NULL;
544 return (retval);
545 }
546
547 /* Initialize UD Channel by transitioning it to RTS State. */
548 qp_modify_attr.qp_trans = IBT_UD_SRV;
549 qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS;
550 qp_modify_attr.qp_transport.ud.ud_sq_psn = 0;
551
552 retval = ibt_initialize_qp(chanp, &qp_modify_attr);
553 if (retval != IBT_SUCCESS) {
554 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
555 "Failed to Initialize QP: %d", retval);
556
557 /* Free the QP as we failed to initialize it. */
558 (void) ibt_free_qp(chanp);
559
560 *ud_chan_p = NULL;
561 return (retval);
562 }
563
564 *ud_chan_p = chanp;
565
566 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel(%p): - SUCCESS (%p)",
567 hca_hdl, chanp);
568
569 return (IBT_SUCCESS);
570 }
571
572
573 /*
574 * Function:
575 * ibt_alloc_ud_channel_range
576 * Input:
577 * hca_hdl HCA Handle.
578 * log2 Log (base 2) of the number of QPs to allocate.
579 * flags Channel allocate flags.
580 * args A pointer to an ibt_ud_chan_alloc_args_t struct that
581 * specifies required channel attributes.
582 * send_cq A pointer to an array of CQ handles.
583 * recv_cq A pointer to an array of CQ handles.
584 * Output:
585 * base_qpn_p The returned QP number of the base QP.
586 * ud_chan_p The returned UD Channel handle.
587 * sizes NULL or a pointer to ibt_chan_sizes_s struct where
588 * new SendQ/RecvQ, and WR SGL sizes are returned.
589 * Returns:
590 * IBT_SUCCESS
591 * IBT_INVALID_PARAM
592 * Description:
593 * Allocate UD channels that satisfy the specified channel attributes.
594 */
595 ibt_status_t
ibt_alloc_ud_channel_range(ibt_hca_hdl_t hca_hdl,uint_t log2,ibt_chan_alloc_flags_t flags,ibt_ud_chan_alloc_args_t * args,ibt_cq_hdl_t * send_cq,ibt_cq_hdl_t * recv_cq,ib_qpn_t * base_qpn_p,ibt_channel_hdl_t * ud_chan_p,ibt_chan_sizes_t * sizes)596 ibt_alloc_ud_channel_range(ibt_hca_hdl_t hca_hdl, uint_t log2,
597 ibt_chan_alloc_flags_t flags, ibt_ud_chan_alloc_args_t *args,
598 ibt_cq_hdl_t *send_cq, ibt_cq_hdl_t *recv_cq, ib_qpn_t *base_qpn_p,
599 ibt_channel_hdl_t *ud_chan_p, ibt_chan_sizes_t *sizes)
600 {
601 ibt_status_t retval;
602 ibt_qp_alloc_attr_t qp_attr;
603 ibt_qp_info_t qp_modify_attr;
604 ibtl_channel_t *chanp;
605 ibt_cq_hdl_t ibt_cq_hdl;
606 ibc_cq_hdl_t *ibc_send_cq, *ibc_recv_cq;
607 ibc_qp_hdl_t *ibc_qp_hdl_p;
608 int i, n = 1 << log2;
609 ib_pkey_t tmp_pkey;
610
611
612 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel_range(%p, %x, %p, %p)",
613 hca_hdl, flags, args, sizes);
614
615 bzero(&qp_modify_attr, sizeof (ibt_qp_info_t));
616
617 qp_attr.qp_alloc_flags = IBT_QP_NO_FLAGS;
618
619 if (flags & IBT_ACHAN_CLONE)
620 return (IBT_INVALID_PARAM);
621
622 if (flags & IBT_ACHAN_USER_MAP)
623 qp_attr.qp_alloc_flags |= IBT_QP_USER_MAP;
624
625 if (flags & IBT_ACHAN_DEFER_ALLOC)
626 qp_attr.qp_alloc_flags |= IBT_QP_DEFER_ALLOC;
627
628 if (flags & IBT_ACHAN_USES_SRQ) {
629 if (args->ud_srq == NULL) {
630 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
631 "NULL SRQ Handle specified.");
632 return (IBT_INVALID_PARAM);
633 }
634 qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ;
635 }
636
637 if (flags & IBT_ACHAN_USES_FEXCH) {
638 qp_attr.qp_alloc_flags |= IBT_QP_USES_FEXCH;
639 qp_attr.qp_fc = args->ud_fc;
640 qp_modify_attr.qp_transport.ud.ud_fc = qp_attr.qp_fc =
641 args->ud_fc;
642 }
643 if (flags & IBT_ACHAN_USES_RSS) {
644 if (log2 >
645 hca_hdl->ha_hca_devp->hd_hca_attr->hca_rss_max_log2_table)
646 return (IBT_INSUFF_RESOURCE);
647 qp_attr.qp_alloc_flags |= IBT_QP_USES_RSS;
648 }
649
650 ibc_send_cq = kmem_alloc(sizeof (ibc_cq_hdl_t) << log2, KM_SLEEP);
651 ibc_recv_cq = kmem_alloc(sizeof (ibc_cq_hdl_t) << log2, KM_SLEEP);
652 ibc_qp_hdl_p = kmem_alloc(sizeof (ibc_qp_hdl_t) << log2, KM_SLEEP);
653
654 for (i = 0; i < 1 << log2; i++) {
655 ud_chan_p[i] = kmem_zalloc(sizeof (ibtl_channel_t), KM_SLEEP);
656 ibt_cq_hdl = send_cq[i];
657 ibc_send_cq[i] = ibt_cq_hdl ? ibt_cq_hdl->cq_ibc_cq_hdl : NULL;
658 ibt_cq_hdl = recv_cq[i];
659 ibc_recv_cq[i] = ibt_cq_hdl ? ibt_cq_hdl->cq_ibc_cq_hdl : NULL;
660 }
661
662 /* Setup QP alloc attributes. */
663 qp_attr.qp_pd_hdl = args->ud_pd;
664 qp_attr.qp_flags = args->ud_flags;
665 qp_attr.qp_srq_hdl = args->ud_srq;
666
667 bcopy(&args->ud_sizes, &qp_attr.qp_sizes,
668 sizeof (ibt_chan_sizes_t));
669
670 qp_modify_attr.qp_transport.ud.ud_port = args->ud_hca_port_num;
671 qp_modify_attr.qp_transport.ud.ud_qkey = args->ud_qkey;
672
673 /* Validate input hca_port_num and pkey_ix values. */
674 if ((retval = ibt_index2pkey(hca_hdl, args->ud_hca_port_num,
675 args->ud_pkey_ix, &tmp_pkey)) != IBT_SUCCESS) {
676 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range:"
677 " ibt_index2pkey failed, status: %d", retval);
678 goto fail;
679 }
680 qp_modify_attr.qp_transport.ud.ud_pkey_ix = args->ud_pkey_ix;
681
682 /* Allocate Channel and Initialize the channel. */
683 retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_qp_range)(
684 IBTL_HCA2CIHCA(hca_hdl), log2, (ibtl_qp_hdl_t *)ud_chan_p,
685 IBT_UD_RQP, &qp_attr, sizes, ibc_send_cq, ibc_recv_cq,
686 base_qpn_p, ibc_qp_hdl_p);
687 if (retval != IBT_SUCCESS) {
688 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range: "
689 "Failed to allocate QPs: %d", retval);
690 goto fail;
691 }
692
693 /* Initialize UD Channel by transitioning it to RTS State. */
694 qp_modify_attr.qp_trans = IBT_UD_SRV;
695 qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS;
696 qp_modify_attr.qp_transport.ud.ud_sq_psn = 0;
697
698 for (i = 0; i < n; i++) {
699 /* Initialize the internal QP struct. */
700 chanp = ud_chan_p[i];
701 chanp->ch_qp.qp_type = IBT_UD_SRV;
702 chanp->ch_qp.qp_hca = hca_hdl;
703 chanp->ch_qp.qp_ibc_qp_hdl = ibc_qp_hdl_p[i];
704 chanp->ch_qp.qp_send_cq = send_cq[i];
705 chanp->ch_qp.qp_recv_cq = recv_cq[i];
706 chanp->ch_current_state = IBT_STATE_RESET;
707 mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
708 cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
709
710 retval = ibt_initialize_qp(chanp, &qp_modify_attr);
711 if (retval != IBT_SUCCESS) {
712 int j;
713
714 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range:"
715 " Failed to Initialize QP: %d", retval);
716
717 /* Free the QP as we failed to initialize it. */
718 (void) ibt_free_qp(chanp);
719 for (j = 0; j < i; j++) {
720 chanp = ud_chan_p[j];
721 (void) ibt_free_qp(chanp);
722 }
723 goto fail;
724 }
725
726 /*
727 * The IBTA spec does not include the signal type or PD on a QP
728 * query operation. In order to implement the "CLONE" feature
729 * we need to cache these values.
730 */
731 chanp->ch_qp.qp_flags = qp_attr.qp_flags;
732 chanp->ch_qp.qp_pd_hdl = qp_attr.qp_pd_hdl;
733 }
734
735
736 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range(%p): SUCCESS");
737
738 atomic_add_32(&hca_hdl->ha_qp_cnt, n);
739
740 retval = IBT_SUCCESS;
741
742 fail:
743 kmem_free(ibc_send_cq, sizeof (ibc_cq_hdl_t) << log2);
744 kmem_free(ibc_recv_cq, sizeof (ibc_cq_hdl_t) << log2);
745 kmem_free(ibc_qp_hdl_p, sizeof (ibc_qp_hdl_t) << log2);
746 if (retval != IBT_SUCCESS) {
747 for (i = 0; i < 1 << log2; i++) {
748 kmem_free(ud_chan_p[i], sizeof (ibtl_channel_t));
749 ud_chan_p[i] = NULL;
750 }
751 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range(%p): "
752 "failed: %d", retval);
753 }
754 return (retval);
755 }
756
757
758 /*
759 * Function:
760 * ibt_query_ud_channel
761 * Input:
762 * ud_chan A previously allocated UD channel handle.
763 * Output:
764 * chan_attrs Channel's current attributes.
765 * Returns:
766 * IBT_SUCCESS
767 * Description:
768 * Query a UD channel's attributes.
769 */
770 ibt_status_t
ibt_query_ud_channel(ibt_channel_hdl_t ud_chan,ibt_ud_chan_query_attr_t * ud_chan_attrs)771 ibt_query_ud_channel(ibt_channel_hdl_t ud_chan,
772 ibt_ud_chan_query_attr_t *ud_chan_attrs)
773 {
774 ibt_status_t retval;
775 ibt_qp_query_attr_t qp_attr;
776
777 IBTF_DPRINTF_L3(ibtl_chan, "ibt_query_ud_channel(%p, %p)",
778 ud_chan, ud_chan_attrs);
779
780 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
781 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_ud_channel: "
782 "type of channel (%d) is not UD", ud_chan->ch_qp.qp_type);
783 return (IBT_CHAN_SRV_TYPE_INVALID);
784 }
785
786 bzero(&qp_attr, sizeof (ibt_qp_query_attr_t));
787
788 /* Query the channel (QP) */
789 retval = ibt_query_qp(ud_chan, &qp_attr);
790 if (retval != IBT_SUCCESS) {
791 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_ud_channel: "
792 "ibt_query_qp failed on QP %p: %d", ud_chan, retval);
793 return (retval);
794 }
795
796 ud_chan_attrs->ud_qpn = qp_attr.qp_qpn & IB_QPN_MASK;
797 ud_chan_attrs->ud_hca_guid = IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ud_chan));
798
799 ud_chan_attrs->ud_scq = qp_attr.qp_sq_cq;
800 ud_chan_attrs->ud_rcq = qp_attr.qp_rq_cq;
801 ud_chan_attrs->ud_pd = ud_chan->ch_qp.qp_pd_hdl;
802
803 ud_chan_attrs->ud_hca_port_num =
804 qp_attr.qp_info.qp_transport.ud.ud_port;
805
806 ud_chan_attrs->ud_state = qp_attr.qp_info.qp_state;
807 ud_chan_attrs->ud_pkey_ix = qp_attr.qp_info.qp_transport.ud.ud_pkey_ix;
808 ud_chan_attrs->ud_qkey = qp_attr.qp_info.qp_transport.ud.ud_qkey;
809
810 ud_chan_attrs->ud_chan_sizes.cs_sq = qp_attr.qp_info.qp_sq_sz;
811 ud_chan_attrs->ud_chan_sizes.cs_rq = qp_attr.qp_info.qp_rq_sz;
812 ud_chan_attrs->ud_chan_sizes.cs_sq_sgl = qp_attr.qp_sq_sgl;
813 ud_chan_attrs->ud_chan_sizes.cs_rq_sgl = qp_attr.qp_rq_sgl;
814 ud_chan_attrs->ud_srq = qp_attr.qp_srq;
815
816 ud_chan_attrs->ud_flags = ud_chan->ch_qp.qp_flags;
817
818 ud_chan_attrs->ud_query_fc = qp_attr.qp_query_fexch;
819
820 return (retval);
821 }
822
823
824 /*
825 * Function:
826 * ibt_modify_ud_channel
827 * Input:
828 * ud_chan A previously allocated UD channel handle.
829 * flags Specifies which attributes in ibt_ud_chan_modify_attr_t
830 * are to be modified.
831 * attrs Attributes to be modified.
832 * Output:
833 * actual_sz On return contains the new send and receive queue sizes.
834 * Returns:
835 * IBT_SUCCESS
836 * Description:
837 * Modifies an UD channel's attributes, as specified by a
838 * ibt_cep_modify_flags_t parameter to those specified in the
839 * ibt_ud_chan_modify_attr_t structure.
840 */
841 ibt_status_t
ibt_modify_ud_channel(ibt_channel_hdl_t ud_chan,ibt_cep_modify_flags_t flags,ibt_ud_chan_modify_attr_t * attrs,ibt_queue_sizes_t * actual_sz)842 ibt_modify_ud_channel(ibt_channel_hdl_t ud_chan, ibt_cep_modify_flags_t flags,
843 ibt_ud_chan_modify_attr_t *attrs, ibt_queue_sizes_t *actual_sz)
844 {
845 ibt_status_t retval;
846 ibt_qp_info_t qp_info;
847 ibt_cep_modify_flags_t good_flags;
848 int retries = 1;
849
850 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_ud_channel(%p, %x, %p, %p)",
851 ud_chan, flags, attrs, actual_sz);
852
853 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
854 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_channel: "
855 "type of channel (%d) is not UD", ud_chan->ch_qp.qp_type);
856 return (IBT_CHAN_SRV_TYPE_INVALID);
857 }
858
859 good_flags = IBT_CEP_SET_SQ_SIZE | IBT_CEP_SET_RQ_SIZE |
860 IBT_CEP_SET_QKEY;
861
862 if (flags & ~good_flags) {
863 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_channel: "
864 "Invalid Modify Flags: %x", flags);
865 return (IBT_INVALID_PARAM);
866 }
867
868 retry:
869 bzero(&qp_info, sizeof (ibt_qp_info_t));
870
871 qp_info.qp_state = ud_chan->ch_current_state; /* No Change in State */
872 qp_info.qp_current_state = ud_chan->ch_current_state;
873 qp_info.qp_flags = IBT_CEP_NO_FLAGS;
874
875 qp_info.qp_sq_sz = attrs->ud_sq_sz;
876 qp_info.qp_rq_sz = attrs->ud_rq_sz;
877 qp_info.qp_trans = IBT_UD_SRV;
878 qp_info.qp_transport.ud.ud_qkey = attrs->ud_qkey;
879
880 flags |= IBT_CEP_SET_STATE;
881
882 retval = ibt_modify_qp(ud_chan, flags, &qp_info, actual_sz);
883 if (retval != IBT_SUCCESS) {
884 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_channel: "
885 "ibt_modify_qp failed on QP %p: %d", ud_chan, retval);
886 /* give it one more shot if the old current state was stale */
887 if (qp_info.qp_current_state != ud_chan->ch_current_state &&
888 --retries >= 0 &&
889 (qp_info.qp_current_state == IBT_STATE_RTS ||
890 qp_info.qp_current_state == IBT_STATE_SQD))
891 goto retry;
892 }
893
894 return (retval);
895 }
896
897
898 /*
899 * Function:
900 * ibt_recover_ud_channel
901 * Input:
902 * ud_chan An UD channel handle which is in SQError state.
903 * Output:
904 * none.
905 * Returns:
906 * IBT_SUCCESS
907 * IBT_CHAN_HDL_INVALID
908 * IBT_CHAN_SRV_TYPE_INVALID
909 * IBT_CHAN_STATE_INVALID
910 * Description:
911 * Recover an UD Channel which has transitioned to SQ Error state. The
912 * ibt_recover_ud_channel() transitions the channel from SQ Error state
913 * to Ready-To-Send channel state.
914 *
915 * If a work request posted to a UD channel's send queue completes with
916 * an error (see ibt_wc_status_t), the channel gets transitioned to SQ
917 * Error state. In order to reuse this channel, ibt_recover_ud_channel()
918 * can be used to recover the channel to a usable (Ready-to-Send) state.
919 */
920 ibt_status_t
ibt_recover_ud_channel(ibt_channel_hdl_t ud_chan)921 ibt_recover_ud_channel(ibt_channel_hdl_t ud_chan)
922 {
923 ibt_qp_info_t modify_attr;
924 ibt_status_t retval;
925
926 IBTF_DPRINTF_L3(ibtl_chan, "ibt_recover_ud_channel(%p)", ud_chan);
927
928 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
929 IBTF_DPRINTF_L2(ibtl_chan, "ibt_recover_ud_channel: "
930 "Called for non-UD channels<%d>", ud_chan->ch_qp.qp_type);
931 return (IBT_CHAN_SRV_TYPE_INVALID);
932 }
933
934 bzero(&modify_attr, sizeof (ibt_qp_info_t));
935
936 /* Set the channel state to RTS, to activate the send processing. */
937 modify_attr.qp_state = IBT_STATE_RTS;
938 modify_attr.qp_trans = ud_chan->ch_qp.qp_type;
939 modify_attr.qp_current_state = IBT_STATE_SQE;
940
941 retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &modify_attr, NULL);
942
943 if (retval != IBT_SUCCESS)
944 IBTF_DPRINTF_L2(ibtl_chan, "ibt_recover_ud_channel: "
945 "ibt_modify_qp failed on qp %p: status = %d",
946 ud_chan, retval);
947
948 return (retval);
949 }
950
951
952 /*
953 * Function:
954 * ibt_flush_channel
955 * Input:
956 * chan The opaque channel handle returned in a previous call
957 * to ibt_alloc_ud_channel() or ibt_alloc_rc_channel().
958 * Output:
959 * none.
960 * Returns:
961 * IBT_SUCCESS
962 * Description:
963 * Flush the specified channel. Outstanding work requests are flushed
964 * so that the client can do the associated clean up. After that, the
965 * client will usually deregister the previously registered memory,
966 * then free the channel by calling ibt_free_channel(). This function
967 * applies to UD channels, or to RC channels that have not successfully
968 * been opened.
969 */
970 ibt_status_t
ibt_flush_channel(ibt_channel_hdl_t chan)971 ibt_flush_channel(ibt_channel_hdl_t chan)
972 {
973 ibt_status_t retval;
974
975 IBTF_DPRINTF_L3(ibtl_chan, "ibt_flush_channel(%p)", chan);
976
977 retval = ibt_flush_qp(chan);
978 if (retval != IBT_SUCCESS) {
979 IBTF_DPRINTF_L2(ibtl_chan, "ibt_flush_channel: "
980 "ibt_flush_qp failed on QP %p: %d", chan, retval);
981 }
982
983 return (retval);
984 }
985
986
987 /*
988 * Function:
989 * ibt_free_channel
990 * Input:
991 * chan The opaque channel handle returned in a previous
992 * call to ibt_alloc_{ud,rc}_channel().
993 * Output:
994 * none.
995 * Returns:
996 * IBT_SUCCESS
997 * Description:
998 * Releases the resources associated with the specified channel.
999 * It is well assumed that channel has been closed before this.
1000 */
1001 ibt_status_t
ibt_free_channel(ibt_channel_hdl_t chan)1002 ibt_free_channel(ibt_channel_hdl_t chan)
1003 {
1004 return (ibt_free_qp(chan));
1005 }
1006
1007
1008 /*
1009 * UD Destination.
1010 */
1011 /*
1012 * Function:
1013 * ibt_alloc_ud_dest
1014 * Input:
1015 * hca_hdl HCA Handle.
1016 * pd Protection Domain
1017 * Output:
1018 * ud_dest_p Address to store the returned UD destination handle.
1019 * Returns:
1020 * IBT_SUCCESS
1021 * Description:
1022 * Allocate a UD destination handle. The returned UD destination handle
1023 * has no useful contents, but is usable after calling ibt_modify_ud_dest,
1024 * ibt_modify_reply_ud_dest, or ibt_open_ud_dest.
1025 */
1026 ibt_status_t
ibt_alloc_ud_dest(ibt_hca_hdl_t hca_hdl,ibt_ud_dest_flags_t flags,ibt_pd_hdl_t pd,ibt_ud_dest_hdl_t * ud_dest_p)1027 ibt_alloc_ud_dest(ibt_hca_hdl_t hca_hdl, ibt_ud_dest_flags_t flags,
1028 ibt_pd_hdl_t pd, ibt_ud_dest_hdl_t *ud_dest_p)
1029 {
1030 ibt_status_t retval;
1031 ibt_ud_dest_t *ud_destp;
1032 ibt_ah_hdl_t ah;
1033 ibt_adds_vect_t adds_vect;
1034
1035 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_dest(%p, %x, %p)",
1036 hca_hdl, flags, pd);
1037
1038 bzero(&adds_vect, sizeof (adds_vect));
1039 adds_vect.av_port_num = 1;
1040 adds_vect.av_srate = IBT_SRATE_1X; /* assume the minimum */
1041 retval = ibt_alloc_ah(hca_hdl, flags, pd, &adds_vect, &ah);
1042 if (retval != IBT_SUCCESS) {
1043 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_dest: "
1044 "Address Handle Allocation failed: %d", retval);
1045 *ud_dest_p = NULL;
1046 return (retval);
1047 }
1048 ud_destp = kmem_alloc(sizeof (*ud_destp), KM_SLEEP);
1049 ud_destp->ud_ah = ah;
1050 ud_destp->ud_dest_hca = hca_hdl;
1051 ud_destp->ud_dst_qpn = 0;
1052 ud_destp->ud_qkey = 0;
1053 *ud_dest_p = ud_destp;
1054 return (IBT_SUCCESS);
1055 }
1056
1057 /*
1058 * Function:
1059 * ibt_query_ud_dest
1060 * Input:
1061 * ud_dest A previously allocated UD destination handle.
1062 * Output:
1063 * dest_attrs UD destination's current attributes.
1064 * Returns:
1065 * IBT_SUCCESS
1066 * Description:
1067 * Query a UD destination's attributes.
1068 */
1069 ibt_status_t
ibt_query_ud_dest(ibt_ud_dest_hdl_t ud_dest,ibt_ud_dest_query_attr_t * dest_attrs)1070 ibt_query_ud_dest(ibt_ud_dest_hdl_t ud_dest,
1071 ibt_ud_dest_query_attr_t *dest_attrs)
1072 {
1073 ibt_status_t retval;
1074
1075 ASSERT(dest_attrs != NULL);
1076
1077 /* Query Address Handle */
1078 retval = ibt_query_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah,
1079 &dest_attrs->ud_pd, &dest_attrs->ud_addr_vect);
1080
1081 if (retval != IBT_SUCCESS) {
1082 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_ud_dest: "
1083 "Failed to Query Address Handle: %d", retval);
1084 return (retval);
1085 }
1086
1087 /* Update the return struct. */
1088 dest_attrs->ud_hca_hdl = ud_dest->ud_dest_hca;
1089 dest_attrs->ud_dst_qpn = ud_dest->ud_dst_qpn;
1090 dest_attrs->ud_qkey = ud_dest->ud_qkey;
1091
1092 return (retval);
1093 }
1094
1095 /*
1096 * Function:
1097 * ibt_modify_ud_dest
1098 * Input:
1099 * ud_dest A previously allocated UD destination handle
1100 * as returned by ibt_alloc_ud_dest().
1101 * qkey QKey of the destination.
1102 * dest_qpn QPN of the destination.
1103 * adds_vect NULL or Address Vector for the destination.
1104 *
1105 * Output:
1106 * none.
1107 * Returns:
1108 * IBT_SUCCESS
1109 * Description:
1110 * Modify a previously allocated UD destination handle from the
1111 * arguments supplied by the caller.
1112 */
1113 ibt_status_t
ibt_modify_ud_dest(ibt_ud_dest_hdl_t ud_dest,ib_qkey_t qkey,ib_qpn_t dest_qpn,ibt_adds_vect_t * adds_vect)1114 ibt_modify_ud_dest(ibt_ud_dest_hdl_t ud_dest, ib_qkey_t qkey,
1115 ib_qpn_t dest_qpn, ibt_adds_vect_t *adds_vect)
1116 {
1117 ibt_status_t retval;
1118
1119 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_ud_dest(%p, %x, %x, %p) ",
1120 ud_dest, qkey, dest_qpn, adds_vect);
1121
1122 if ((adds_vect != NULL) &&
1123 (retval = ibt_modify_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah,
1124 adds_vect)) != IBT_SUCCESS) {
1125 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_dest: "
1126 "ibt_modify_ah() failed: status = %d", retval);
1127 return (retval);
1128 }
1129 ud_dest->ud_dst_qpn = dest_qpn;
1130 ud_dest->ud_qkey = qkey;
1131 return (IBT_SUCCESS);
1132 }
1133
1134 /*
1135 * Function:
1136 * ibt_free_ud_dest
1137 * Input:
1138 * ud_dest The opaque destination handle returned in a previous
1139 * call to ibt_alloc_ud_dest() or ibt_alloc_mcg_dest().
1140 * Output:
1141 * none.
1142 * Returns:
1143 * IBT_SUCCESS
1144 * Description:
1145 * Releases the resources associated with the specified destination
1146 * handle.
1147 */
1148 ibt_status_t
ibt_free_ud_dest(ibt_ud_dest_hdl_t ud_dest)1149 ibt_free_ud_dest(ibt_ud_dest_hdl_t ud_dest)
1150 {
1151 ibt_status_t retval;
1152
1153 retval = ibt_free_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah);
1154 if (retval != IBT_SUCCESS) {
1155 IBTF_DPRINTF_L2(ibtl_chan, "ibt_free_ud_dest: "
1156 "Address Handle free failed: %d", retval);
1157 return (retval);
1158 }
1159 kmem_free(ud_dest, sizeof (*ud_dest));
1160 return (IBT_SUCCESS);
1161 }
1162
1163 static ibt_status_t
ibtl_find_sgid_ix(ib_gid_t * sgid,ibt_channel_hdl_t ud_chan,uint8_t port,uint_t * sgid_ix_p)1164 ibtl_find_sgid_ix(ib_gid_t *sgid, ibt_channel_hdl_t ud_chan, uint8_t port,
1165 uint_t *sgid_ix_p)
1166 {
1167 ibtl_hca_devinfo_t *hca_devp = ud_chan->ch_qp.qp_hca->ha_hca_devp;
1168 ib_gid_t *sgidp;
1169 uint_t i;
1170 uint_t sgid_tbl_sz;
1171
1172 if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports ||
1173 sgid->gid_prefix == 0 || sgid->gid_guid == 0) {
1174 *sgid_ix_p = 0;
1175 return (IBT_INVALID_PARAM);
1176 }
1177 mutex_enter(&ibtl_clnt_list_mutex);
1178 sgidp = &hca_devp->hd_portinfop[port - 1].p_sgid_tbl[0];
1179 sgid_tbl_sz = hca_devp->hd_portinfop[port - 1].p_sgid_tbl_sz;
1180 for (i = 0; i < sgid_tbl_sz; i++, sgidp++) {
1181 if ((sgid->gid_guid != sgidp->gid_guid) ||
1182 (sgid->gid_prefix != sgidp->gid_prefix))
1183 continue;
1184 mutex_exit(&ibtl_clnt_list_mutex);
1185 *sgid_ix_p = i;
1186 return (IBT_SUCCESS);
1187 }
1188 mutex_exit(&ibtl_clnt_list_mutex);
1189 *sgid_ix_p = 0;
1190 return (IBT_INVALID_PARAM);
1191 }
1192
1193 /*
1194 * Function:
1195 * ibt_modify_reply_ud_dest
1196 * Input:
1197 * ud_dest A previously allocated UD reply destination handle
1198 * as returned by ibt_alloc_ud_dest().
1199 * qkey Qkey. 0 means "not specified", so use the Q_Key
1200 * in the QP context.
1201 * recv_buf Pointer to the first data buffer associated with the
1202 * receive work request.
1203 * Output:
1204 * Returns:
1205 * IBT_SUCCESS
1206 * Description:
1207 * Modify a previously allocated UD destination handle, so that it
1208 * can be used to reply to the sender of the datagram contained in the
1209 * specified work request completion. If the qkey is not supplied (0),
1210 * then use the qkey in the QP (we just set qkey to a privileged QKEY).
1211 */
1212 ibt_status_t
ibt_modify_reply_ud_dest(ibt_channel_hdl_t ud_chan,ibt_ud_dest_hdl_t ud_dest,ib_qkey_t qkey,ibt_wc_t * wc,ib_vaddr_t recv_buf)1213 ibt_modify_reply_ud_dest(ibt_channel_hdl_t ud_chan, ibt_ud_dest_hdl_t ud_dest,
1214 ib_qkey_t qkey, ibt_wc_t *wc, ib_vaddr_t recv_buf)
1215 {
1216 ibt_status_t retval;
1217 ibt_adds_vect_t adds_vect;
1218 ib_grh_t *grh;
1219 uint8_t port;
1220 uint32_t ver_tc_flow;
1221
1222 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_reply_ud_dest(%p, %p, %x, %p, "
1223 "%llx)", ud_chan, ud_dest, qkey, wc, recv_buf);
1224
1225 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
1226 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_reply_ud_dest: "
1227 "type of channel (%d) is not UD",
1228 ud_chan->ch_qp.qp_type);
1229 return (IBT_CHAN_SRV_TYPE_INVALID);
1230 }
1231 if (qkey == 0)
1232 qkey = ud_chan->ch_transport.ud.ud_qkey;
1233 port = ud_chan->ch_transport.ud.ud_port_num;
1234
1235 if (wc->wc_flags & IBT_WC_GRH_PRESENT) {
1236 grh = (ib_grh_t *)(uintptr_t)recv_buf;
1237 adds_vect.av_send_grh = B_TRUE;
1238 adds_vect.av_dgid.gid_prefix = b2h64(grh->SGID.gid_prefix);
1239 adds_vect.av_dgid.gid_guid = b2h64(grh->SGID.gid_guid);
1240 adds_vect.av_sgid.gid_prefix = b2h64(grh->DGID.gid_prefix);
1241 adds_vect.av_sgid.gid_guid = b2h64(grh->DGID.gid_guid);
1242 (void) ibtl_find_sgid_ix(&adds_vect.av_sgid, ud_chan,
1243 port, &adds_vect.av_sgid_ix);
1244 ver_tc_flow = b2h32(grh->IPVer_TC_Flow);
1245 adds_vect.av_flow = ver_tc_flow & IB_GRH_FLOW_LABEL_MASK;
1246 adds_vect.av_tclass = (ver_tc_flow & IB_GRH_TCLASS_MASK) >> 20;
1247 adds_vect.av_hop = grh->HopLmt;
1248 } else {
1249 adds_vect.av_send_grh = B_FALSE;
1250 adds_vect.av_dgid.gid_prefix = 0;
1251 adds_vect.av_sgid.gid_prefix = 0;
1252 adds_vect.av_dgid.gid_guid = 0;
1253 adds_vect.av_sgid.gid_guid = 0;
1254 adds_vect.av_sgid_ix = 0;
1255 adds_vect.av_flow = 0;
1256 adds_vect.av_tclass = 0;
1257 adds_vect.av_hop = 0;
1258 }
1259
1260 adds_vect.av_srate = IBT_SRATE_1X; /* assume the minimum */
1261 adds_vect.av_srvl = wc->wc_sl;
1262 adds_vect.av_dlid = wc->wc_slid;
1263 adds_vect.av_src_path = wc->wc_path_bits;
1264 adds_vect.av_port_num = port;
1265
1266 if ((retval = ibt_modify_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah,
1267 &adds_vect)) != IBT_SUCCESS) {
1268 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_reply_ud_dest: "
1269 "ibt_alloc_ah() failed: status = %d", retval);
1270 return (retval);
1271 }
1272 ud_dest->ud_dst_qpn = wc->wc_qpn & IB_QPN_MASK;
1273 ud_dest->ud_qkey = qkey;
1274
1275 return (IBT_SUCCESS);
1276 }
1277
1278
1279 /*
1280 * Function:
1281 * ibt_is_privileged_ud_dest
1282 * Input:
1283 * ud_dest A previously allocated destination handle.
1284 * Output:
1285 * none
1286 * Returns:
1287 * B_FALSE/B_TRUE
1288 * Description:
1289 * Determine if a UD destination Handle is a privileged handle.
1290 */
1291 boolean_t
ibt_is_privileged_ud_dest(ibt_ud_dest_hdl_t ud_dest)1292 ibt_is_privileged_ud_dest(ibt_ud_dest_hdl_t ud_dest)
1293 {
1294 return ((ud_dest->ud_qkey & IB_PRIVILEGED_QKEY_BIT) ? B_TRUE : B_FALSE);
1295 }
1296
1297
1298 /*
1299 * Function:
1300 * ibt_update_channel_qkey
1301 * Input:
1302 * ud_chan The UD channel handle, that is to be used to
1303 * communicate with the specified destination.
1304 *
1305 * ud_dest A UD destination handle returned from
1306 * ibt_alloc_ud_dest(9F).
1307 * Output:
1308 * none
1309 * Returns:
1310 * IBT_SUCCESS
1311 * Description:
1312 * ibt_update_channel_qkey() sets the Q_Key in the specified channel context
1313 * to the Q_Key in the specified destination handle. This function can be used
1314 * to enable sends to a privileged destination. All posted send work requests
1315 * that contain a privileged destination handle now use the Q_Key in the
1316 * channel context.
1317 *
1318 * ibt_update_channel_qkey() can also be used to enable the caller to receive
1319 * from the specified remote destination on the specified channel.
1320 */
1321 ibt_status_t
ibt_update_channel_qkey(ibt_channel_hdl_t ud_chan,ibt_ud_dest_hdl_t ud_dest)1322 ibt_update_channel_qkey(ibt_channel_hdl_t ud_chan, ibt_ud_dest_hdl_t ud_dest)
1323 {
1324 ibt_status_t retval;
1325 ibt_qp_info_t qp_info;
1326
1327 IBTF_DPRINTF_L3(ibtl_chan, "ibt_update_channel_qkey(%p, %p)",
1328 ud_chan, ud_dest);
1329
1330 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
1331 IBTF_DPRINTF_L2(ibtl_chan, "ibt_update_channel_qkey: "
1332 "type of channel (%d) is not UD",
1333 ud_chan->ch_qp.qp_type);
1334 return (IBT_CHAN_SRV_TYPE_INVALID);
1335 }
1336 bzero(&qp_info, sizeof (ibt_qp_info_t));
1337
1338 qp_info.qp_trans = IBT_UD_SRV;
1339 qp_info.qp_state = ud_chan->ch_current_state;
1340 qp_info.qp_current_state = ud_chan->ch_current_state;
1341 qp_info.qp_transport.ud.ud_qkey = ud_dest->ud_qkey;
1342
1343 retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_QKEY | IBT_CEP_SET_STATE,
1344 &qp_info, NULL);
1345 if (retval != IBT_SUCCESS) {
1346 IBTF_DPRINTF_L2(ibtl_chan, "ibt_update_channel_qkey: "
1347 "Failed to modify QP %p: status %d", ud_chan, retval);
1348 } else {
1349 ud_chan->ch_transport.ud.ud_qkey = ud_dest->ud_qkey;
1350 }
1351
1352 return (retval);
1353 }
1354
1355
1356 /*
1357 * Function:
1358 * ibt_set_chan_private
1359 * Input:
1360 * chan A previously allocated channel handle.
1361 * clnt_private The client private data.
1362 * Output:
1363 * none.
1364 * Returns:
1365 * none.
1366 * Description:
1367 * Set the client private data.
1368 */
1369 void
ibt_set_chan_private(ibt_channel_hdl_t chan,void * clnt_private)1370 ibt_set_chan_private(ibt_channel_hdl_t chan, void *clnt_private)
1371 {
1372 chan->ch_clnt_private = clnt_private;
1373 }
1374
1375
1376 /*
1377 * Function:
1378 * ibt_get_chan_private
1379 * Input:
1380 * chan A previously allocated channel handle.
1381 * Output:
1382 * A pointer to the client private data.
1383 * Returns:
1384 * none.
1385 * Description:
1386 * Get a pointer to client private data.
1387 */
1388 void *
ibt_get_chan_private(ibt_channel_hdl_t chan)1389 ibt_get_chan_private(ibt_channel_hdl_t chan)
1390 {
1391 return (chan->ch_clnt_private);
1392 }
1393
1394 /*
1395 * Function:
1396 * ibt_channel_to_hca_guid
1397 * Input:
1398 * chan Channel Handle.
1399 * Output:
1400 * none.
1401 * Returns:
1402 * hca_guid Returned HCA GUID on which the specified Channel is
1403 * allocated. Valid if it is non-NULL on return.
1404 * Description:
1405 * A helper function to retrieve HCA GUID for the specified Channel.
1406 */
1407 ib_guid_t
ibt_channel_to_hca_guid(ibt_channel_hdl_t chan)1408 ibt_channel_to_hca_guid(ibt_channel_hdl_t chan)
1409 {
1410 IBTF_DPRINTF_L3(ibtl_chan, "ibt_channel_to_hca_guid(%p)", chan);
1411
1412 return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(chan)));
1413 }
1414
1415 /*
1416 * Protection Domain Verbs Functions.
1417 */
1418
1419 /*
1420 * Function:
1421 * ibt_alloc_pd
1422 * Input:
1423 * hca_hdl The IBT HCA handle, the device on which we need
1424 * to create the requested Protection Domain.
1425 * flags IBT_PD_NO_FLAGS, IBT_PD_USER_MAP or IBT_PD_DEFER_ALLOC
1426 * Output:
1427 * pd IBT Protection Domain Handle.
1428 * Returns:
1429 * IBT_SUCCESS
1430 * IBT_HCA_HDL_INVALID
1431 * Description:
1432 * Allocate a Protection Domain.
1433 */
1434 ibt_status_t
ibt_alloc_pd(ibt_hca_hdl_t hca_hdl,ibt_pd_flags_t flags,ibt_pd_hdl_t * pd)1435 ibt_alloc_pd(ibt_hca_hdl_t hca_hdl, ibt_pd_flags_t flags, ibt_pd_hdl_t *pd)
1436 {
1437 ibt_status_t retval;
1438
1439 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_pd(%p, %x)", hca_hdl, flags);
1440
1441 /* re-direct the call to CI's call */
1442 ibtl_qp_flow_control_enter();
1443 retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_pd(
1444 IBTL_HCA2CIHCA(hca_hdl), flags, pd);
1445 ibtl_qp_flow_control_exit();
1446 if (retval != IBT_SUCCESS) {
1447 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_pd: CI PD Alloc Err");
1448 return (retval);
1449 }
1450
1451 /* Update the PDs Resource Count per HCA Device. */
1452 atomic_inc_32(&hca_hdl->ha_pd_cnt);
1453
1454 return (retval);
1455 }
1456
1457 /*
1458 * Function:
1459 * ibt_free_pd
1460 * Input:
1461 * hca_hdl The IBT HCA handle, the device on which we need
1462 * to free the requested Protection Domain.
1463 * pd IBT Protection Domain Handle.
1464 * Output:
1465 * none.
1466 * Returns:
1467 * IBT_SUCCESS
1468 * IBT_HCA_HDL_INVALID
1469 * IBT_MEM_PD_HDL_INVALID
1470 * IBT_MEM_PD_IN_USE
1471 * Description:
1472 * Release/de-allocate a Protection Domain.
1473 */
1474 ibt_status_t
ibt_free_pd(ibt_hca_hdl_t hca_hdl,ibt_pd_hdl_t pd)1475 ibt_free_pd(ibt_hca_hdl_t hca_hdl, ibt_pd_hdl_t pd)
1476 {
1477 ibt_status_t retval;
1478
1479 IBTF_DPRINTF_L3(ibtl_chan, "ibt_free_pd(%p, %p)", hca_hdl, pd);
1480
1481 /* re-direct the call to CI's call */
1482 retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_pd(
1483 IBTL_HCA2CIHCA(hca_hdl), pd);
1484 if (retval != IBT_SUCCESS) {
1485 IBTF_DPRINTF_L2(ibtl_chan, "ibt_free_pd: CI Free PD Failed");
1486 return (retval);
1487 }
1488
1489 /* Update the PDs Resource Count per HCA Device. */
1490 atomic_dec_32(&hca_hdl->ha_pd_cnt);
1491
1492 return (retval);
1493 }
1494
1495
1496 /*
1497 * Address Handle Verbs Functions.
1498 */
1499
1500 /*
1501 * Function:
1502 * ibt_alloc_ah
1503 * Input:
1504 * hca_hdl The IBT HCA Handle.
1505 * pd The IBT Protection Domain to associate with this handle.
1506 * adds_vectp Points to an ibt_adds_vect_t struct.
1507 * Output:
1508 * ah IBT Address Handle.
1509 * Returns:
1510 * IBT_SUCCESS
1511 * IBT_HCA_HDL_INVALID
1512 * IBT_INSUFF_RESOURCE
1513 * IBT_MEM_PD_HDL_INVALID
1514 * Description:
1515 * Allocate and returns an Address Handle.
1516 */
1517 ibt_status_t
ibt_alloc_ah(ibt_hca_hdl_t hca_hdl,ibt_ah_flags_t flags,ibt_pd_hdl_t pd,ibt_adds_vect_t * adds_vectp,ibt_ah_hdl_t * ah)1518 ibt_alloc_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_flags_t flags, ibt_pd_hdl_t pd,
1519 ibt_adds_vect_t *adds_vectp, ibt_ah_hdl_t *ah)
1520 {
1521 ibt_status_t retval;
1522
1523 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ah(%p, %x, %p, %p)",
1524 hca_hdl, flags, pd, adds_vectp);
1525
1526 /* XXX - if av_send_grh, need to compute av_sgid_ix from av_sgid */
1527
1528 /* re-direct the call to CI's call */
1529 retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_ah(
1530 IBTL_HCA2CIHCA(hca_hdl), flags, pd, adds_vectp, ah);
1531
1532 if (retval != IBT_SUCCESS) {
1533 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ah: "
1534 "ibc_alloc_ah failed: status = %d", retval);
1535 return (retval);
1536 }
1537
1538 /* Update the AHs Resource Count per HCA Device. */
1539 atomic_inc_32(&hca_hdl->ha_ah_cnt);
1540
1541 return (retval);
1542 }
1543
1544
1545 /*
1546 * Function:
1547 * ibt_free_ah
1548 * Input:
1549 * hca_hdl The IBT HCA Handle.
1550 * ah IBT Address Handle.
1551 * Output:
1552 * none.
1553 * Returns:
1554 * IBT_SUCCESS
1555 * IBT_HCA_HDL_INVALID
1556 * IBT_AH_HDL_INVALID
1557 * Description:
1558 * Release/de-allocate the specified Address Handle.
1559 */
1560 ibt_status_t
ibt_free_ah(ibt_hca_hdl_t hca_hdl,ibt_ah_hdl_t ah)1561 ibt_free_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_hdl_t ah)
1562 {
1563 ibt_status_t retval;
1564
1565 IBTF_DPRINTF_L3(ibtl_chan, "ibt_free_ah(%p, %p)", hca_hdl, ah);
1566
1567 /* re-direct the call to CI's call */
1568 retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_ah(
1569 IBTL_HCA2CIHCA(hca_hdl), ah);
1570
1571 if (retval != IBT_SUCCESS) {
1572 IBTF_DPRINTF_L2(ibtl_chan, "ibt_free_ah: CI Free AH Failed");
1573 return (retval);
1574 }
1575
1576 /* Update the AHs Resource Count per HCA Device. */
1577 atomic_dec_32(&hca_hdl->ha_ah_cnt);
1578
1579 return (retval);
1580 }
1581
1582
1583 /*
1584 * Function:
1585 * ibt_query_ah
1586 * Input:
1587 * hca_hdl The IBT HCA Handle.
1588 * ah IBT Address Handle.
1589 * Output:
1590 * pd The Protection Domain Handle with which this
1591 * Address Handle is associated.
1592 * adds_vectp Points to an ibt_adds_vect_t struct.
1593 * Returns:
1594 * IBT_SUCCESS/IBT_HCA_HDL_INVALID/IBT_AH_HDL_INVALID
1595 * Description:
1596 * Obtain the address vector information for the specified address handle.
1597 */
1598 ibt_status_t
ibt_query_ah(ibt_hca_hdl_t hca_hdl,ibt_ah_hdl_t ah,ibt_pd_hdl_t * pd,ibt_adds_vect_t * adds_vectp)1599 ibt_query_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_hdl_t ah, ibt_pd_hdl_t *pd,
1600 ibt_adds_vect_t *adds_vectp)
1601 {
1602 ibt_status_t retval;
1603
1604 IBTF_DPRINTF_L3(ibtl_chan, "ibt_query_ah(%p, %p)", hca_hdl, ah);
1605
1606 /* re-direct the call to CI's call */
1607 retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_query_ah(
1608 IBTL_HCA2CIHCA(hca_hdl), ah, pd, adds_vectp));
1609
1610 /*
1611 * We need to fill in av_sgid, as the CI does only saves/restores
1612 * av_sgid_ix.
1613 */
1614 if (retval == IBT_SUCCESS) {
1615 ibtl_hca_devinfo_t *hca_devp = hca_hdl->ha_hca_devp;
1616 uint8_t port = adds_vectp->av_port_num;
1617
1618 mutex_enter(&ibtl_clnt_list_mutex);
1619 if (port > 0 && port <= hca_devp->hd_hca_attr->hca_nports &&
1620 adds_vectp->av_sgid_ix < IBTL_HDIP2SGIDTBLSZ(hca_devp)) {
1621 ib_gid_t *sgidp;
1622
1623 sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl;
1624 adds_vectp->av_sgid = sgidp[adds_vectp->av_sgid_ix];
1625 } else {
1626 adds_vectp->av_sgid.gid_prefix = 0;
1627 adds_vectp->av_sgid.gid_guid = 0;
1628 }
1629 mutex_exit(&ibtl_clnt_list_mutex);
1630 }
1631 return (retval);
1632 }
1633
1634
1635 /*
1636 * Function:
1637 * ibt_modify_ah
1638 * Input:
1639 * hca_hdl The IBT HCA Handle.
1640 * ah IBT Address Handle.
1641 * Output:
1642 * adds_vectp Points to an ibt_adds_vect_t struct. The new address
1643 * vector information is specified is returned in this
1644 * structure.
1645 * Returns:
1646 * IBT_SUCCESS/IBT_HCA_HDL_INVALID/IBT_AH_HDL_INVALID
1647 * Description:
1648 * Modify the address vector information for the specified Address Handle.
1649 */
1650 ibt_status_t
ibt_modify_ah(ibt_hca_hdl_t hca_hdl,ibt_ah_hdl_t ah,ibt_adds_vect_t * adds_vectp)1651 ibt_modify_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_hdl_t ah,
1652 ibt_adds_vect_t *adds_vectp)
1653 {
1654 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_ah(%p, %p)", hca_hdl, ah);
1655
1656 /* XXX - if av_send_grh, need to compute av_sgid_ix from av_sgid */
1657
1658 /* re-direct the call to CI's call */
1659 return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_modify_ah(
1660 IBTL_HCA2CIHCA(hca_hdl), ah, adds_vectp));
1661 }
1662