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 * 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 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 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 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 275 dapl_ep_check_request_completion_flags( 276 DAT_COMPLETION_FLAGS flags) 277 { 278 return (DAT_SUCCESS); 279 } 280 281 DAT_RETURN 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 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 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 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 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