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 /*
23 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
24 */
25
26 /*
27 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30
31 /*
32 *
33 * MODULE: dapl_ep_util.c
34 *
35 * PURPOSE: Manage EP Info structure
36 *
37 * $Id: dapl_ep_util.c,v 1.36 2003/08/04 16:50:27 sjs2 Exp $
38 */
39
40 #include "dapl_ep_util.h"
41 #include "dapl_ring_buffer_util.h"
42 #include "dapl_cookie.h"
43 #include "dapl_adapter_util.h"
44 #include "dapl_evd_util.h"
45 #include "dapl_ia_util.h"
46
47 /*
48 * Local definitions
49 */
50 /*
51 * Default number of I/O operations on an end point
52 */
53 #define IB_IO_DEFAULT 16
54 /*
55 * Default number of scatter/gather entries available to a single
56 * post send/recv
57 */
58 #define IB_IOV_DEFAULT 4
59
60 /*
61 * Default number of RDMA operations in progress at a time
62 */
63 #define IB_RDMA_DEFAULT 4
64
65 extern void dapli_ep_default_attrs(
66 IN DAPL_EP *ep_ptr);
67
68
69 /*
70 * dapl_ep_alloc
71 *
72 * alloc and initialize an EP INFO struct
73 *
74 * Input:
75 * IA INFO struct ptr
76 *
77 * Output:
78 * ep_ptr
79 *
80 * Returns:
81 * none
82 *
83 */
84 DAPL_EP *
dapl_ep_alloc(IN DAPL_IA * ia_ptr,IN const DAT_EP_ATTR * ep_attr,IN DAT_BOOLEAN srq_attached)85 dapl_ep_alloc(
86 IN DAPL_IA *ia_ptr,
87 IN const DAT_EP_ATTR *ep_attr,
88 IN DAT_BOOLEAN srq_attached)
89 {
90 DAPL_EP *ep_ptr;
91
92 /* Allocate EP */
93 ep_ptr = (DAPL_EP *)dapl_os_alloc(sizeof (DAPL_EP));
94 if (ep_ptr == NULL) {
95 goto bail;
96 }
97
98 /* zero the structure */
99 (void) dapl_os_memzero(ep_ptr, sizeof (DAPL_EP));
100
101 /*
102 * initialize the header
103 */
104 ep_ptr->header.provider = ia_ptr->header.provider;
105 ep_ptr->header.magic = DAPL_MAGIC_EP;
106 ep_ptr->header.handle_type = DAT_HANDLE_TYPE_EP;
107 ep_ptr->header.owner_ia = ia_ptr;
108 ep_ptr->header.user_context.as_64 = 0;
109 ep_ptr->header.user_context.as_ptr = NULL;
110 dapl_llist_init_entry(&ep_ptr->header.ia_list_entry);
111 dapl_os_lock_init(&ep_ptr->header.lock);
112
113 /*
114 * Initialize the body
115 */
116 (void) dapl_os_memzero(&ep_ptr->param, sizeof (DAT_EP_PARAM));
117 ep_ptr->param.ep_state = DAT_EP_STATE_UNCONNECTED;
118 ep_ptr->param.local_ia_address_ptr =
119 (DAT_IA_ADDRESS_PTR)&ia_ptr->hca_ptr->hca_address;
120
121 /* Set the remote address pointer */
122 ep_ptr->param.remote_ia_address_ptr =
123 (DAT_IA_ADDRESS_PTR) &ep_ptr->remote_ia_address;
124
125 /*
126 * Set up default parameters if the user passed in a NULL
127 */
128 if (ep_attr == NULL) {
129 dapli_ep_default_attrs(ep_ptr);
130 } else {
131 ep_ptr->param.ep_attr = *ep_attr;
132 }
133
134 /*
135 * IBM OS API specific fields
136 */
137 ep_ptr->qp_handle = IB_INVALID_HANDLE;
138 ep_ptr->qpn = 0;
139 ep_ptr->qp_state = DAPL_QP_STATE_UNATTACHED;
140 ep_ptr->cm_handle = IB_INVALID_HANDLE;
141
142 ep_ptr->req_count = 0;
143 ep_ptr->recv_count = 0;
144
145 ep_ptr->srq_attached = srq_attached;
146
147 if (DAT_SUCCESS != dapls_cb_create(&ep_ptr->req_buffer, ep_ptr,
148 DAPL_COOKIE_QUEUE_EP, ep_ptr->param.ep_attr.max_request_dtos)) {
149 dapl_ep_dealloc(ep_ptr);
150 ep_ptr = NULL;
151 goto bail;
152 }
153
154 if (!srq_attached) {
155 if (DAT_SUCCESS != dapls_cb_create(&ep_ptr->recv_buffer, ep_ptr,
156 DAPL_COOKIE_QUEUE_EP,
157 ep_ptr->param.ep_attr.max_recv_dtos)) {
158 dapl_ep_dealloc(ep_ptr);
159 ep_ptr = NULL;
160 goto bail;
161 }
162 }
163
164 bail:
165 return (ep_ptr);
166 }
167
168
169 /*
170 * dapl_ep_dealloc
171 *
172 * Free the passed in EP structure.
173 *
174 * Input:
175 * entry point pointer
176 *
177 * Output:
178 * none
179 *
180 * Returns:
181 * none
182 *
183 */
184 void
dapl_ep_dealloc(IN DAPL_EP * ep_ptr)185 dapl_ep_dealloc(
186 IN DAPL_EP *ep_ptr)
187 {
188 dapl_os_assert(ep_ptr->header.magic == DAPL_MAGIC_EP ||
189 ep_ptr->header.magic == DAPL_MAGIC_EP_EXIT);
190
191 /* reset magic to prevent reuse */
192 ep_ptr->header.magic = DAPL_MAGIC_INVALID;
193
194 dapls_cb_free(&ep_ptr->req_buffer);
195 dapls_cb_free(&ep_ptr->recv_buffer);
196
197 dapl_os_free(ep_ptr, sizeof (DAPL_EP));
198 }
199
200
201 /*
202 * dapl_ep_default_attrs
203 *
204 * Set default values in the parameter fields
205 *
206 * Input:
207 * entry point pointer
208 *
209 * Output:
210 * none
211 *
212 * Returns:
213 * none
214 *
215 */
216 void
dapli_ep_default_attrs(IN DAPL_EP * ep_ptr)217 dapli_ep_default_attrs(
218 IN DAPL_EP *ep_ptr)
219 {
220 DAT_EP_ATTR *ep_attr;
221
222 ep_attr = &ep_ptr->param.ep_attr;
223 /* Set up defaults */
224 (void) dapl_os_memzero(ep_attr, sizeof (DAT_EP_ATTR));
225
226 /*
227 * mtu and rdma sizes fixed in IB as per IBTA 1.1, 9.4.3, 9.4.4,
228 * 9.7.7.
229 */
230 ep_attr->max_mtu_size = 0x80000000;
231 ep_attr->max_rdma_size = 0x80000000;
232
233 ep_attr->qos = DAT_QOS_BEST_EFFORT;
234 ep_attr->service_type = DAT_SERVICE_TYPE_RC;
235 ep_attr->max_recv_dtos = IB_IO_DEFAULT;
236 ep_attr->max_request_dtos = IB_IO_DEFAULT;
237 ep_attr->max_recv_iov = IB_IOV_DEFAULT;
238 ep_attr->max_request_iov = IB_IOV_DEFAULT;
239 ep_attr->max_rdma_read_in = IB_RDMA_DEFAULT;
240 ep_attr->max_rdma_read_out = IB_RDMA_DEFAULT;
241
242 ep_attr->request_completion_flags = DAT_COMPLETION_EVD_THRESHOLD_FLAG;
243 ep_attr->recv_completion_flags = DAT_COMPLETION_EVD_THRESHOLD_FLAG;
244 /*
245 * Unspecified defaults:
246 * - ep_privileges: No RDMA capabilities
247 * - num_transport_specific_params: none
248 * - transport_specific_params: none
249 * - num_provider_specific_params: 0
250 * - provider_specific_params: 0
251 */
252 }
253
254
255 DAT_RETURN
dapl_ep_check_recv_completion_flags(DAT_COMPLETION_FLAGS flags)256 dapl_ep_check_recv_completion_flags(
257 DAT_COMPLETION_FLAGS flags)
258 {
259
260 /*
261 * InfiniBand will not allow unsignaled/suppressed RECV completions,
262 * see the 1.0.1 spec section 10.7.3.1, 10.8.6
263 */
264
265 if ((flags & DAT_COMPLETION_UNSIGNALLED_FLAG) ||
266 (flags & DAT_COMPLETION_SUPPRESS_FLAG)) {
267 return (DAT_INVALID_PARAMETER);
268 }
269
270 return (DAT_SUCCESS);
271 }
272
273 /* ARGSUSED */
274 DAT_RETURN
dapl_ep_check_request_completion_flags(DAT_COMPLETION_FLAGS flags)275 dapl_ep_check_request_completion_flags(
276 DAT_COMPLETION_FLAGS flags)
277 {
278 return (DAT_SUCCESS);
279 }
280
281 DAT_RETURN
dapl_ep_check_qos(DAT_QOS qos)282 dapl_ep_check_qos(
283 DAT_QOS qos)
284 {
285 if (qos & ~(DAT_QOS_BEST_EFFORT | DAT_QOS_HIGH_THROUGHPUT |
286 DAT_QOS_LOW_LATENCY | DAT_QOS_ECONOMY | DAT_QOS_PREMIUM)) {
287 return (DAT_INVALID_PARAMETER);
288 }
289 return (DAT_SUCCESS);
290 }
291
292 DAT_RETURN
dapl_ep_post_send_req(IN DAT_EP_HANDLE ep_handle,IN DAT_COUNT num_segments,IN DAT_LMR_TRIPLET * local_iov,IN DAT_DTO_COOKIE user_cookie,IN const DAT_RMR_TRIPLET * remote_iov,IN DAT_COMPLETION_FLAGS completion_flags,IN DAPL_DTO_TYPE dto_type,IN ib_send_op_type_t op_type)293 dapl_ep_post_send_req(
294 IN DAT_EP_HANDLE ep_handle,
295 IN DAT_COUNT num_segments,
296 IN DAT_LMR_TRIPLET *local_iov,
297 IN DAT_DTO_COOKIE user_cookie,
298 IN const DAT_RMR_TRIPLET *remote_iov,
299 IN DAT_COMPLETION_FLAGS completion_flags,
300 IN DAPL_DTO_TYPE dto_type,
301 IN ib_send_op_type_t op_type)
302 {
303 DAPL_EP *ep;
304 DAPL_COOKIE *cookie;
305 DAT_RETURN dat_status;
306
307 if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) {
308 dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
309 DAT_INVALID_HANDLE_EP);
310 goto bail;
311 }
312
313 ep = (DAPL_EP *)ep_handle;
314
315 /*
316 * Synchronization ok since this buffer is only used for send
317 * requests, which aren't allowed to race with each other.
318 */
319 dat_status = dapls_dto_cookie_alloc(&ep->req_buffer,
320 dto_type,
321 user_cookie,
322 &cookie);
323 if (dat_status != DAT_SUCCESS) {
324 goto bail;
325 }
326
327 /*
328 * Invoke provider specific routine to post DTO
329 */
330 if (num_segments != 1 ||
331 completion_flags != DAT_COMPLETION_DEFAULT_FLAG)
332 dat_status = dapls_ib_post_send(ep,
333 op_type,
334 cookie,
335 num_segments,
336 local_iov,
337 remote_iov,
338 completion_flags);
339 else
340 dat_status = dapls_ib_post_send_one(ep,
341 op_type,
342 cookie,
343 local_iov,
344 remote_iov);
345
346 if (dat_status != DAT_SUCCESS) {
347 dapls_cookie_dealloc(&ep->req_buffer, cookie);
348 } else {
349 dapl_os_atomic_inc(&ep->req_count);
350 }
351
352 bail:
353 return (dat_status);
354 }
355
356
357 /*
358 * dapli_ep_timeout
359 *
360 * If this routine is invoked before a connection occurs, generate an
361 * event
362 */
363 void
dapls_ep_timeout(unsigned long arg)364 dapls_ep_timeout(
365 unsigned long arg)
366 {
367 DAPL_EP *ep_ptr;
368
369 dapl_dbg_log(DAPL_DBG_TYPE_CM, "--> dapls_ep_timeout! ep %lx\n", arg);
370
371 ep_ptr = (DAPL_EP *)arg;
372
373 /* reset the EP state */
374 ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
375
376 (void) dapls_evd_post_connection_event(
377 (DAPL_EVD *)ep_ptr->param.connect_evd_handle,
378 DAT_CONNECTION_EVENT_TIMED_OUT,
379 (DAT_HANDLE) ep_ptr,
380 0,
381 0);
382 }
383
384
385 /*
386 * dapls_ep_state_subtype
387 *
388 * Return the INVALID_STATE connection subtype associated with an
389 * INVALID_STATE on an EP. Strictly for error reporting.
390 */
391 DAT_RETURN_SUBTYPE
dapls_ep_state_subtype(IN DAPL_EP * ep_ptr)392 dapls_ep_state_subtype(
393 IN DAPL_EP *ep_ptr)
394 {
395 DAT_RETURN_SUBTYPE dat_status;
396
397 switch (ep_ptr->param.ep_state) {
398 case DAT_EP_STATE_RESERVED:
399 {
400 dat_status = DAT_INVALID_STATE_EP_RESERVED;
401 break;
402 }
403 case DAT_EP_STATE_PASSIVE_CONNECTION_PENDING:
404 {
405 dat_status = DAT_INVALID_STATE_EP_PASSCONNPENDING;
406 break;
407 }
408 case DAT_EP_STATE_ACTIVE_CONNECTION_PENDING:
409 {
410 dat_status = DAT_INVALID_STATE_EP_ACTCONNPENDING;
411 break;
412 }
413 case DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING:
414 {
415 dat_status = DAT_INVALID_STATE_EP_TENTCONNPENDING;
416 break;
417 }
418 case DAT_EP_STATE_CONNECTED:
419 {
420 dat_status = DAT_INVALID_STATE_EP_CONNECTED;
421 break;
422 }
423 case DAT_EP_STATE_DISCONNECT_PENDING:
424 {
425 dat_status = DAT_INVALID_STATE_EP_DISCPENDING;
426 break;
427 }
428 case DAT_EP_STATE_DISCONNECTED:
429 {
430 dat_status = DAT_INVALID_STATE_EP_DISCONNECTED;
431 break;
432 }
433 case DAT_EP_STATE_COMPLETION_PENDING:
434 {
435 dat_status = DAT_INVALID_STATE_EP_COMPLPENDING;
436 break;
437 }
438 default:
439 {
440 dat_status = 0;
441 break;
442 }
443 }
444
445 return (dat_status);
446 }
447
448
449 /*
450 * dapl_ep_create_common
451 *
452 * Common code used by dapl_ep_create and dapl_ep_create_srq
453 *
454 * Input:
455 * ia_handle
456 * pz_handle
457 * recv_evd_handle (recv DTOs)
458 * request_evd_handle (xmit DTOs)
459 * connect_evd_handle
460 * srq_handle
461 * ep_attrs
462 *
463 * Output:
464 * ep_handle
465 *
466 * Returns:
467 * DAT_SUCCESS
468 * DAT_INSUFFICIENT_RESOURCES
469 * DAT_INVALID_PARAMETER
470 * DAT_INVALID_ATTRIBUTE
471 * DAT_MODEL_NOT_SUPPORTED
472 */
473 DAT_RETURN
dapl_ep_create_common(IN DAT_IA_HANDLE ia_handle,IN DAT_PZ_HANDLE pz_handle,IN DAT_EVD_HANDLE recv_evd_handle,IN DAT_EVD_HANDLE request_evd_handle,IN DAT_EVD_HANDLE connect_evd_handle,IN DAT_SRQ_HANDLE srq_handle,IN const DAT_EP_ATTR * ep_attr_arg,OUT DAT_EP_HANDLE * ep_handle)474 dapl_ep_create_common(
475 IN DAT_IA_HANDLE ia_handle,
476 IN DAT_PZ_HANDLE pz_handle,
477 IN DAT_EVD_HANDLE recv_evd_handle,
478 IN DAT_EVD_HANDLE request_evd_handle,
479 IN DAT_EVD_HANDLE connect_evd_handle,
480 IN DAT_SRQ_HANDLE srq_handle,
481 IN const DAT_EP_ATTR *ep_attr_arg,
482 OUT DAT_EP_HANDLE *ep_handle)
483 {
484 DAPL_IA *ia_ptr;
485 DAPL_EP *ep_ptr;
486 DAT_EP_ATTR ep_attr_limit;
487 DAPL_EVD *evd_ptr;
488 DAT_RETURN dat_status;
489 DAT_BOOLEAN srq_attached;
490 DAT_EP_ATTR *ep_attr, epa;
491
492 if (ep_attr_arg) {
493 epa = *ep_attr_arg;
494 ep_attr = &epa;
495 } else
496 ep_attr = NULL;
497
498 ia_ptr = (DAPL_IA *)ia_handle;
499 dat_status = DAT_SUCCESS;
500 /*
501 * Verify parameters
502 */
503 if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) {
504 dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
505 DAT_INVALID_HANDLE_IA);
506 goto bail;
507 }
508
509 /*
510 * Verify non-required parameters.
511 * N.B. Assumption: any parameter that can be
512 * modified by dat_ep_modify() is not strictly
513 * required when the EP is created
514 */
515 if (pz_handle != NULL &&
516 DAPL_BAD_HANDLE(pz_handle, DAPL_MAGIC_PZ)) {
517 dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
518 DAT_INVALID_HANDLE_PZ);
519 goto bail;
520 }
521
522 /* If connect handle is !NULL verify handle is good */
523 if (connect_evd_handle != DAT_HANDLE_NULL &&
524 (DAPL_BAD_HANDLE(connect_evd_handle, DAPL_MAGIC_EVD) ||
525 !(((DAPL_EVD *)connect_evd_handle)->evd_flags &
526 DAT_EVD_CONNECTION_FLAG))) {
527 dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
528 DAT_INVALID_HANDLE_EVD_CONN);
529 goto bail;
530 }
531 /* If recv_evd is !NULL, verify handle is good and flags are valid */
532 if ((recv_evd_handle != DAT_HANDLE_NULL) &&
533 (DAPL_BAD_HANDLE(recv_evd_handle, DAPL_MAGIC_EVD) ||
534 !(((DAPL_EVD *)recv_evd_handle)->evd_flags & DAT_EVD_DTO_FLAG))) {
535 dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
536 DAT_INVALID_HANDLE_EVD_RECV);
537 goto bail;
538 }
539
540 /* If req_evd is !NULL, verify handle is good and flags are valid */
541 if ((request_evd_handle != DAT_HANDLE_NULL) &&
542 (DAPL_BAD_HANDLE(request_evd_handle, DAPL_MAGIC_EVD) ||
543 !(((DAPL_EVD *)request_evd_handle)->evd_flags &
544 DAT_EVD_DTO_FLAG))) {
545 dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
546 DAT_INVALID_HANDLE_EVD_REQUEST);
547 goto bail;
548 }
549
550 srq_attached = DAT_FALSE;
551
552 /* if srq_handle is not null validate it */
553 if (srq_handle != DAT_HANDLE_NULL) {
554 if (DAPL_BAD_HANDLE(srq_handle, DAPL_MAGIC_SRQ)) {
555 dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
556 DAT_INVALID_HANDLE_SRQ);
557 goto bail;
558 } else if (pz_handle !=
559 ((DAPL_SRQ *)srq_handle)->param.pz_handle) {
560 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
561 DAT_INVALID_ARG2);
562 goto bail;
563 }
564 srq_attached = DAT_TRUE;
565 }
566
567 if (ep_handle == NULL) {
568 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
569 (srq_attached ? DAT_INVALID_ARG8 : DAT_INVALID_ARG7));
570 goto bail;
571 }
572
573 /* For EPs with SRQ ep_attr is required */
574 if ((srq_attached && (ep_attr == NULL)) || (uintptr_t)ep_attr & 3) {
575 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
576 (srq_attached ? DAT_INVALID_ARG7 : DAT_INVALID_ARG6));
577 goto bail;
578 }
579
580 /*
581 * Qualify EP Attributes are legal and make sense. Note that if one
582 * or both of the DTO handles are NULL, then the corresponding
583 * max_*_dtos must 0 as the user will not be able to post dto ops on
584 * the respective queue.
585 */
586 if (ep_attr != NULL) {
587 if (ep_attr->service_type != DAT_SERVICE_TYPE_RC ||
588 (request_evd_handle == DAT_HANDLE_NULL &&
589 ep_attr->max_request_dtos != 0) ||
590 (request_evd_handle != DAT_HANDLE_NULL &&
591 ep_attr->max_request_dtos == 0) ||
592 ep_attr->max_request_iov == 0 ||
593 (DAT_SUCCESS != dapl_ep_check_qos(ep_attr->qos)) ||
594 (DAT_SUCCESS != dapl_ep_check_recv_completion_flags(
595 ep_attr->recv_completion_flags))) {
596 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
597 (srq_attached ? DAT_INVALID_ARG7 :
598 DAT_INVALID_ARG6));
599 goto bail;
600 }
601
602 if (srq_attached) {
603 if ((ep_attr->max_recv_dtos != DAT_HW_DEFAULT) ||
604 (ep_attr->srq_soft_hw != DAT_HW_DEFAULT)) {
605 dat_status = DAT_ERROR(DAT_MODEL_NOT_SUPPORTED,
606 0);
607 goto bail;
608 }
609 } else {
610 /* These checks are needed only for EPs without SRQ */
611 if ((recv_evd_handle == DAT_HANDLE_NULL &&
612 ep_attr->max_recv_dtos != 0) ||
613 (recv_evd_handle != DAT_HANDLE_NULL &&
614 ep_attr->max_recv_dtos == 0) ||
615 ep_attr->max_recv_iov == 0) {
616 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
617 DAT_INVALID_ARG6);
618 goto bail;
619 }
620 }
621 }
622
623 /* Verify the attributes against the transport */
624 if (ep_attr != NULL) {
625 (void) dapl_os_memzero(&ep_attr_limit, sizeof (DAT_EP_ATTR));
626 dat_status = dapls_ib_query_hca(ia_ptr->hca_ptr,
627 NULL, &ep_attr_limit, NULL, NULL);
628 if (dat_status != DAT_SUCCESS) {
629 goto bail;
630 }
631 if (ep_attr->max_mtu_size > ep_attr_limit.max_mtu_size ||
632 ep_attr->max_rdma_size > ep_attr_limit.max_rdma_size ||
633 (ep_attr->max_request_dtos >
634 ep_attr_limit.max_request_dtos) ||
635 ep_attr->max_request_iov > ep_attr_limit.max_request_iov) {
636 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
637 (srq_attached ? DAT_INVALID_ARG7 :
638 DAT_INVALID_ARG6));
639 goto bail;
640 }
641 /* if inlining enabled, recompute max_request_iov */
642 if (ia_ptr->hca_ptr->max_inline_send)
643 ep_attr->max_request_iov = dapls_ib_max_request_iov(
644 ep_attr->max_request_iov,
645 ep_attr->max_request_dtos,
646 ep_attr_limit.max_request_iov,
647 ia_ptr->hca_ptr->max_inline_send);
648
649 /* Only EPs without SRQ need the following check */
650 if ((!srq_attached) &&
651 (ep_attr->max_recv_dtos > ep_attr_limit.max_recv_dtos) ||
652 (ep_attr->max_recv_iov > ep_attr_limit.max_recv_iov)) {
653 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
654 DAT_INVALID_ARG6);
655 goto bail;
656 }
657
658
659 }
660 /*
661 * Verify the completion flags for the EVD and the EP
662 */
663
664 evd_ptr = (DAPL_EVD *)recv_evd_handle;
665 if (evd_ptr->completion_type == DAPL_EVD_STATE_INIT) {
666 if (ep_attr != NULL &&
667 (ep_attr->recv_completion_flags ==
668 DAT_COMPLETION_DEFAULT_FLAG)) {
669 evd_ptr->completion_type = DAPL_EVD_STATE_THRESHOLD;
670 } else {
671 /*
672 * Currently we support only thresholds -
673 * eventually it'll depend on
674 * ep_attr->recv_completion_flags;
675 */
676 evd_ptr->completion_type = DAPL_EVD_STATE_THRESHOLD;
677 }
678 }
679 evd_ptr = (DAPL_EVD *)request_evd_handle;
680 if (evd_ptr->completion_type == DAPL_EVD_STATE_INIT) {
681 if (ep_attr != NULL &&
682 (ep_attr->recv_completion_flags ==
683 DAT_COMPLETION_DEFAULT_FLAG)) {
684 evd_ptr->completion_type = DAPL_EVD_STATE_THRESHOLD;
685 } else {
686 /*
687 * Currently we support only thresholds -
688 * eventually it'll depend on
689 * ep_attr->recv_completion_flags;
690 */
691 evd_ptr->completion_type = DAPL_EVD_STATE_THRESHOLD;
692 }
693 }
694
695 /* Allocate EP */
696 ep_ptr = dapl_ep_alloc(ia_ptr, ep_attr, srq_attached);
697 if (ep_ptr == NULL) {
698 dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
699 DAT_RESOURCE_MEMORY);
700 goto bail;
701 }
702
703 /*
704 * Fill in the EP
705 */
706 ep_ptr->param.ia_handle = ia_handle;
707 ep_ptr->param.pz_handle = pz_handle;
708 ep_ptr->param.recv_evd_handle = recv_evd_handle;
709 ep_ptr->param.request_evd_handle = request_evd_handle;
710 ep_ptr->param.connect_evd_handle = connect_evd_handle;
711 ep_ptr->param.srq_handle = srq_handle;
712
713 ep_ptr->srq_attached = srq_attached;
714
715 /*
716 * Make sure we handle the NULL DTO EVDs
717 */
718 if (recv_evd_handle == DAT_HANDLE_NULL && ep_attr == NULL) {
719 ep_ptr->param.ep_attr.max_recv_dtos = 0;
720 }
721
722 if (request_evd_handle == DAT_HANDLE_NULL && ep_attr == NULL) {
723 ep_ptr->param.ep_attr.max_request_dtos = 0;
724 }
725
726 /*
727 * If the user has specified a PZ handle we allocate a QP for
728 * this EP; else we defer until it is assigned via ep_modify().
729 * As much as possible we try to keep QP creation out of the
730 * connect path to avoid resource errors in strange places.
731 */
732 if (pz_handle != DAT_HANDLE_NULL) {
733 /* Take a reference on the PZ handle */
734 dapl_os_atomic_inc(&((DAPL_PZ *)pz_handle)->pz_ref_count);
735
736 /*
737 * Get a QP from the IB provider
738 */
739 dat_status = dapls_ib_qp_alloc(ia_ptr, ep_ptr, ep_ptr);
740
741 if (dat_status != DAT_SUCCESS) {
742 dapl_os_atomic_dec(&((DAPL_PZ *)pz_handle)->
743 pz_ref_count);
744 dapl_ep_dealloc(ep_ptr);
745 goto bail;
746 }
747 } else {
748 ep_ptr->qp_state = DAPL_QP_STATE_UNATTACHED;
749 }
750
751 /*
752 * Update ref counts. See the spec where the endpoint marks
753 * a data object as 'in use'
754 * pz_handle: dat_pz_free, uDAPL Document, 6.6.1.2
755 * evd_handles:
756 *
757 * N.B. This should really be done by a util routine.
758 */
759 dapl_os_atomic_inc(&((DAPL_EVD *)connect_evd_handle)->evd_ref_count);
760 /* Optional handles */
761 if (recv_evd_handle != NULL) {
762 dapl_os_atomic_inc(&((DAPL_EVD *)recv_evd_handle)->
763 evd_ref_count);
764 }
765 if (request_evd_handle != NULL) {
766 dapl_os_atomic_inc(&((DAPL_EVD *)request_evd_handle)->
767 evd_ref_count);
768 }
769 if (srq_handle != NULL) {
770 dapl_os_atomic_inc(&((DAPL_SRQ *)srq_handle)->srq_ref_count);
771 }
772
773 /* Link it onto the IA */
774 dapl_ia_link_ep(ia_ptr, ep_ptr);
775
776 *ep_handle = ep_ptr;
777
778 bail:
779 return (dat_status);
780 }
781
782 /*
783 * Local variables:
784 * c-indent-level: 4
785 * c-basic-offset: 4
786 * tab-width: 8
787 * End:
788 */
789