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_modify.c 34 * 35 * PURPOSE: Endpoint management 36 * Description: Interfaces in this file are completely described in 37 * the DAPL 1.0 API, Chapter 6, section 5 38 * 39 * $Id: dapl_ep_modify.c,v 1.23 2003/07/11 18:42:17 hobie16 Exp $ 40 */ 41 42 #include "dapl.h" 43 #include "dapl_cookie.h" 44 #include "dapl_ep_util.h" 45 #include "dapl_adapter_util.h" 46 47 /* 48 * Internal prototypes 49 */ 50 51 static _INLINE_ DAT_RETURN 52 dapli_ep_modify_validate_parameters( 53 IN DAT_EP_HANDLE ep_handle, 54 IN DAT_EP_PARAM_MASK ep_param_mask, 55 IN const DAT_EP_PARAM *ep_param, 56 OUT DAPL_IA **ia_ptr, 57 OUT DAPL_EP **ep_ptr, 58 OUT DAT_EP_ATTR *ep_attr_ptr); 59 60 /* 61 * dapl_ep_modify 62 * 63 * DAPL Requirements Version xxx, 6.5.6 64 * 65 * Provide the consumer parameters, including attributes and status of 66 * the Endpoint. 67 * 68 * Input: 69 * ep_handle 70 * ep_args_mask 71 * 72 * Output: 73 * ep_args 74 * 75 * Returns: 76 * DAT_SUCCESS 77 * DAT_INVALID_PARAMETER 78 * DAT_INVALID_ATTRIBUTE 79 * DAT_INVALID_STATE 80 */ 81 DAT_RETURN 82 dapl_ep_modify( 83 IN DAT_EP_HANDLE ep_handle, 84 IN DAT_EP_PARAM_MASK ep_param_mask, 85 IN const DAT_EP_PARAM *ep_param) 86 { 87 DAPL_IA *ia; 88 DAPL_EP *ep1, *ep2; 89 DAT_EP_ATTR ep_attr1, ep_attr2; 90 DAPL_EP new_ep, copy_of_old_ep; 91 DAPL_EP alloc_ep; /* Holder for resources. */ 92 DAPL_PZ *tmp_pz; 93 DAPL_EVD *tmp_evd; 94 DAT_RETURN dat_status; 95 96 /* Flag indicating we've allocated a new one of these. */ 97 DAT_BOOLEAN qp_allocated = DAT_FALSE; 98 DAT_BOOLEAN rqst_cb_allocated = DAT_FALSE; 99 DAT_BOOLEAN recv_cb_allocated = DAT_FALSE; 100 101 /* Flag indicating we've used (assigned to QP) a new one of these. */ 102 DAT_BOOLEAN qp_used = DAT_FALSE; 103 DAT_BOOLEAN rqst_cb_used = DAT_FALSE; 104 DAT_BOOLEAN recv_cb_used = DAT_FALSE; 105 106 dat_status = dapli_ep_modify_validate_parameters(ep_handle, 107 ep_param_mask, ep_param, &ia, &ep1, &ep_attr1); 108 if (DAT_SUCCESS != dat_status) { 109 goto bail; 110 } 111 112 /* 113 * Setup the alloc_ep with the appropriate parameters (primarily 114 * for allocating the QP. 115 */ 116 alloc_ep = *ep1; 117 alloc_ep.param.ep_attr = ep_attr1; 118 if (ep_param_mask & DAT_EP_FIELD_PZ_HANDLE) { 119 alloc_ep.param.pz_handle = ep_param->pz_handle; 120 } 121 122 if (ep_param_mask & DAT_EP_FIELD_RECV_EVD_HANDLE) { 123 alloc_ep.param.recv_evd_handle = ep_param->recv_evd_handle; 124 } 125 126 if (ep_param_mask & DAT_EP_FIELD_REQUEST_EVD_HANDLE) { 127 alloc_ep.param.request_evd_handle = 128 ep_param->request_evd_handle; 129 } 130 131 if (ep_param_mask & DAT_EP_FIELD_CONNECT_EVD_HANDLE) { 132 alloc_ep.param.connect_evd_handle = 133 ep_param->connect_evd_handle; 134 } 135 136 /* 137 * Allocate everything that might be needed. 138 * We allocate separately, and into a different "holding" 139 * ep, since we a) want the copy of the old ep into the new ep to 140 * be atomic with the assignment back (under lock), b) want the 141 * assignment of the allocated materials to be after the copy of the 142 * old ep into the new ep, and c) don't want the allocation done 143 * under lock. 144 */ 145 dat_status = dapls_cb_create( 146 &alloc_ep.req_buffer, ep1, DAPL_COOKIE_QUEUE_EP, 147 ep_attr1.max_request_dtos); 148 if (DAT_SUCCESS != dat_status) { 149 goto bail; 150 } 151 rqst_cb_allocated = DAT_TRUE; 152 153 if (!ep1->srq_attached) { 154 dat_status = dapls_cb_create(&alloc_ep.recv_buffer, ep1, 155 DAPL_COOKIE_QUEUE_EP, ep_attr1.max_recv_dtos); 156 if (DAT_SUCCESS != dat_status) { 157 goto bail; 158 } 159 recv_cb_allocated = DAT_TRUE; 160 } 161 162 dat_status = dapls_ib_qp_alloc(ia, &alloc_ep, ep1); 163 if (dat_status != DAT_SUCCESS) { 164 goto bail; 165 } 166 qp_allocated = DAT_TRUE; 167 168 /* 169 * Now we atomically modify the EP, under lock 170 * There's a lot of work done here, but there should be no 171 * allocation or blocking. 172 */ 173 dapl_os_lock(&ep1->header.lock); 174 175 /* 176 * Revalidate parameters; make sure that races haven't 177 * changed anything important. 178 */ 179 dat_status = dapli_ep_modify_validate_parameters(ep_handle, 180 ep_param_mask, ep_param, &ia, &ep2, &ep_attr2); 181 if (DAT_SUCCESS != dat_status) { 182 dapl_os_unlock(&ep2->header.lock); 183 goto bail; 184 } 185 186 /* 187 * All of the following should be impossible, if validation 188 * occurred. But they're important to the logic of this routine, 189 * so we check. 190 */ 191 dapl_os_assert(ep1 == ep2); 192 dapl_os_assert(ep_attr2.max_recv_dtos == ep_attr1.max_recv_dtos); 193 dapl_os_assert(ep_attr2.max_request_dtos == ep_attr1.max_request_dtos); 194 195 copy_of_old_ep = *ep2; 196 197 /* 198 * Setup new ep. 199 */ 200 new_ep = *ep2; 201 new_ep.param.ep_attr = ep_attr2; 202 203 /* 204 * We can initialize the PZ and EVD handles from the alloc_ep because 205 * the only thing that could have changed since we setup the alloc_ep 206 * is stuff changed by dapl_cr_accept, and neither PZ nor EVD is in that 207 * list. 208 */ 209 new_ep.param.pz_handle = alloc_ep.param.pz_handle; 210 new_ep.param.recv_evd_handle = alloc_ep.param.recv_evd_handle; 211 new_ep.param.request_evd_handle = alloc_ep.param.request_evd_handle; 212 new_ep.param.connect_evd_handle = alloc_ep.param.connect_evd_handle; 213 214 /* Deal with each of the allocation fields. */ 215 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_RECV_DTOS && 216 (ep_param->ep_attr.max_recv_dtos != 217 ep2->param.ep_attr.max_recv_dtos)) { 218 new_ep.recv_buffer = alloc_ep.recv_buffer; 219 recv_cb_used = DAT_TRUE; 220 } 221 222 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_DTOS && 223 (ep_param->ep_attr.max_request_dtos != 224 ep2->param.ep_attr.max_request_dtos)) { 225 new_ep.req_buffer = alloc_ep.req_buffer; 226 rqst_cb_used = DAT_TRUE; 227 } 228 229 /* 230 * We need to change the QP only if there already was a QP 231 * (leave things the way you found them!) and one of the 232 * following has changed: send/recv EVD, send/recv reqs/IOV max. 233 */ 234 if (DAPL_QP_STATE_UNATTACHED != new_ep.qp_state && (ep_param_mask 235 & (DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_IOV | 236 DAT_EP_FIELD_EP_ATTR_MAX_RECV_IOV | 237 DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_DTOS | 238 DAT_EP_FIELD_EP_ATTR_MAX_RECV_DTOS | 239 DAT_EP_FIELD_RECV_EVD_HANDLE | 240 DAT_EP_FIELD_REQUEST_EVD_HANDLE))) { 241 /* 242 * We shouldn't be racing with connection establishment 243 * because the parameter validate routine should protect us, 244 * but it's an important enough point that we assert it. 245 */ 246 dapl_os_assert((ep2->param.ep_state != 247 DAT_EP_STATE_PASSIVE_CONNECTION_PENDING) && 248 (ep2->param.ep_state != 249 DAT_EP_STATE_ACTIVE_CONNECTION_PENDING)); 250 251 new_ep.qp_handle = alloc_ep.qp_handle; 252 new_ep.qpn = alloc_ep.qpn; 253 qp_used = DAT_TRUE; 254 } 255 256 /* 257 * The actual assignment, including modifying QP parameters. 258 * Modifying QP parameters needs to come first, as if it fails 259 * we need to exit. 260 */ 261 if (DAPL_QP_STATE_UNATTACHED != new_ep.qp_state) { 262 dat_status = dapls_ib_qp_modify(ia, ep2, &ep_attr2); 263 if (dat_status != DAT_SUCCESS) { 264 dapl_os_unlock(& ep2->header.lock); 265 goto bail; 266 } 267 } 268 *ep2 = new_ep; 269 270 dapl_os_unlock(&ep2->header.lock); 271 272 /* 273 * Modify reference counts, incrementing new ones 274 * and then decrementing old ones (so if they're the same 275 * the refcount never drops to zero). 276 */ 277 tmp_pz = (DAPL_PZ *) new_ep.param.pz_handle; 278 if (NULL != tmp_pz) { 279 dapl_os_atomic_inc(&tmp_pz->pz_ref_count); 280 } 281 282 tmp_evd = (DAPL_EVD *) new_ep.param.recv_evd_handle; 283 if (NULL != tmp_evd) { 284 dapl_os_atomic_inc(&tmp_evd->evd_ref_count); 285 } 286 287 tmp_evd = (DAPL_EVD *) new_ep.param.request_evd_handle; 288 if (NULL != tmp_evd) { 289 dapl_os_atomic_inc(&tmp_evd->evd_ref_count); 290 } 291 292 tmp_evd = (DAPL_EVD *) new_ep.param.connect_evd_handle; 293 if (NULL != tmp_evd) { 294 dapl_os_atomic_inc(&tmp_evd->evd_ref_count); 295 } 296 297 /* decreament the old reference counts */ 298 tmp_pz = (DAPL_PZ *) copy_of_old_ep.param.pz_handle; 299 if (NULL != tmp_pz) { 300 dapl_os_atomic_dec(&tmp_pz->pz_ref_count); 301 } 302 303 tmp_evd = (DAPL_EVD *) copy_of_old_ep.param.recv_evd_handle; 304 if (NULL != tmp_evd) { 305 dapl_os_atomic_dec(&tmp_evd->evd_ref_count); 306 } 307 308 tmp_evd = (DAPL_EVD *) copy_of_old_ep.param.request_evd_handle; 309 if (NULL != tmp_evd) { 310 dapl_os_atomic_dec(&tmp_evd->evd_ref_count); 311 } 312 313 tmp_evd = (DAPL_EVD *) copy_of_old_ep.param.connect_evd_handle; 314 if (NULL != tmp_evd) { 315 dapl_os_atomic_dec(&tmp_evd->evd_ref_count); 316 } 317 318 bail: 319 if (qp_allocated) { 320 DAT_RETURN local_dat_status; 321 if (dat_status != DAT_SUCCESS || !qp_used) { 322 local_dat_status = dapls_ib_qp_free(ia, &alloc_ep); 323 } else { 324 local_dat_status = dapls_ib_qp_free(ia, 325 ©_of_old_ep); 326 } 327 if (local_dat_status != DAT_SUCCESS) { 328 dapl_dbg_log(DAPL_DBG_TYPE_WARN, 329 "ep_modify: Failed to free QP; status %x\n", 330 local_dat_status); 331 } 332 } 333 334 if (rqst_cb_allocated) { 335 if (dat_status != DAT_SUCCESS || !rqst_cb_used) { 336 dapls_cb_free(&alloc_ep.req_buffer); 337 } else { 338 dapls_cb_free(©_of_old_ep.req_buffer); 339 } 340 } 341 342 if (recv_cb_allocated) { 343 if (dat_status != DAT_SUCCESS || !recv_cb_used) { 344 dapls_cb_free(&alloc_ep.recv_buffer); 345 } else { 346 dapls_cb_free(©_of_old_ep.recv_buffer); 347 } 348 } 349 350 return (dat_status); 351 } 352 353 354 /* 355 * dapli_ep_modify_validate_parameters 356 * 357 * Validate parameters 358 * 359 * The space for the ep_attr_ptr parameter should be allocated by the 360 * consumer. Upon success, this parameter will contain the current ep 361 * attribute values with the requested modifications made. 362 * 363 */ 364 365 static DAT_RETURN 366 dapli_ep_modify_validate_parameters( 367 IN DAT_EP_HANDLE ep_handle, 368 IN DAT_EP_PARAM_MASK ep_param_mask, 369 IN const DAT_EP_PARAM *ep_param, 370 OUT DAPL_IA **ia_ptr, 371 OUT DAPL_EP **ep_ptr, 372 OUT DAT_EP_ATTR *ep_attr_ptr) 373 { 374 DAPL_IA *ia; 375 DAPL_EP *ep; 376 DAT_EP_ATTR ep_attr; 377 DAT_EP_ATTR ep_attr_limit; 378 DAT_EP_ATTR ep_attr_request; 379 DAT_RETURN dat_status; 380 381 *ia_ptr = NULL; 382 *ep_ptr = NULL; 383 dat_status = DAT_SUCCESS; 384 385 if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) { 386 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 387 DAT_INVALID_HANDLE_EP); 388 goto bail; 389 } 390 391 ep = (DAPL_EP *) ep_handle; 392 ia = ep->header.owner_ia; 393 394 /* 395 * Verify parameters valid in current EP state 396 */ 397 if (ep_param_mask & (DAT_EP_FIELD_IA_HANDLE | 398 DAT_EP_FIELD_EP_STATE | 399 DAT_EP_FIELD_LOCAL_IA_ADDRESS_PTR | 400 DAT_EP_FIELD_LOCAL_PORT_QUAL | 401 DAT_EP_FIELD_REMOTE_IA_ADDRESS_PTR | 402 DAT_EP_FIELD_REMOTE_PORT_QUAL | 403 DAT_EP_FIELD_SRQ_HANDLE | 404 DAT_EP_FIELD_EP_ATTR_SRQ_SOFT_HW)) { 405 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); 406 goto bail; 407 } 408 409 /* 410 * Can only change the PZ handle if we are UNCONNECTED or 411 * TENTATIVE_CONNECTION_PENDING(psp PROVIDER allocated EP) 412 */ 413 if ((ep_param_mask & DAT_EP_FIELD_PZ_HANDLE) && 414 (ep->param.ep_state != DAT_EP_STATE_UNCONNECTED && 415 ep->param.ep_state != 416 DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING)) { 417 dat_status = DAT_ERROR(DAT_INVALID_STATE, 418 dapls_ep_state_subtype(ep)); 419 goto bail; 420 } 421 422 if ((ep_param_mask & (DAT_EP_FIELD_RECV_EVD_HANDLE | 423 DAT_EP_FIELD_REQUEST_EVD_HANDLE | 424 DAT_EP_FIELD_CONNECT_EVD_HANDLE | 425 DAT_EP_FIELD_EP_ATTR_SERVICE_TYPE | 426 DAT_EP_FIELD_EP_ATTR_MAX_MESSAGE_SIZE | 427 DAT_EP_FIELD_EP_ATTR_MAX_RDMA_SIZE | 428 DAT_EP_FIELD_EP_ATTR_QOS | 429 DAT_EP_FIELD_EP_ATTR_REQUEST_COMPLETION_FLAGS | 430 DAT_EP_FIELD_EP_ATTR_RECV_COMPLETION_FLAGS | 431 DAT_EP_FIELD_EP_ATTR_MAX_RECV_DTOS | 432 DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_DTOS | 433 DAT_EP_FIELD_EP_ATTR_MAX_RECV_IOV | 434 DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_IOV)) && 435 (ep->param.ep_state != DAT_EP_STATE_UNCONNECTED && 436 ep->param.ep_state != DAT_EP_STATE_RESERVED && 437 ep->param.ep_state != 438 DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING)) { 439 dat_status = DAT_ERROR(DAT_INVALID_STATE, 440 dapls_ep_state_subtype(ep)); 441 goto bail; 442 } 443 444 /* 445 * Validate handles being modified 446 */ 447 if (ep_param_mask & DAT_EP_FIELD_PZ_HANDLE) { 448 if (ep_param->pz_handle != NULL && 449 DAPL_BAD_HANDLE(ep_param->pz_handle, DAPL_MAGIC_PZ)) { 450 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 451 DAT_INVALID_ARG3); 452 goto bail; 453 } 454 } 455 456 if (ep_param_mask & DAT_EP_FIELD_RECV_EVD_HANDLE) { 457 if (ep_param->recv_evd_handle != NULL && 458 (DAPL_BAD_HANDLE(ep_param->recv_evd_handle, 459 DAPL_MAGIC_EVD) || 460 !((DAPL_EVD *)ep_param->recv_evd_handle)->evd_flags & 461 DAT_EVD_DTO_FLAG)) { 462 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 463 DAT_INVALID_ARG3); 464 goto bail; 465 } 466 } 467 468 if (ep_param_mask & DAT_EP_FIELD_REQUEST_EVD_HANDLE) { 469 if (ep_param->request_evd_handle != NULL && 470 DAPL_BAD_HANDLE(ep_param->request_evd_handle, 471 DAPL_MAGIC_EVD)) { 472 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 473 DAT_INVALID_ARG3); 474 goto bail; 475 } 476 } 477 478 if (ep_param_mask & DAT_EP_FIELD_CONNECT_EVD_HANDLE) { 479 if (ep_param->connect_evd_handle != NULL && 480 DAPL_BAD_HANDLE(ep_param->connect_evd_handle, 481 DAPL_MAGIC_EVD) && 482 !(((DAPL_EVD *)ep_param->connect_evd_handle)->evd_flags & 483 DAT_EVD_CONNECTION_FLAG)) { 484 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 485 DAT_INVALID_ARG3); 486 goto bail; 487 } 488 } 489 490 /* 491 * Validate the attributes against the HCA limits 492 */ 493 ep_attr = ep->param.ep_attr; 494 495 (void) dapl_os_memzero(&ep_attr_limit, sizeof (DAT_EP_ATTR)); 496 dat_status = dapls_ib_query_hca(ia->hca_ptr, NULL, 497 &ep_attr_limit, NULL, NULL); 498 if (dat_status != DAT_SUCCESS) { 499 goto bail; 500 } 501 502 ep_attr_request = ep_param->ep_attr; 503 504 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_SERVICE_TYPE) { 505 if (ep_attr_request.service_type != DAT_SERVICE_TYPE_RC) { 506 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 507 DAT_INVALID_ARG3); 508 goto bail; 509 } 510 } 511 512 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_MESSAGE_SIZE) { 513 if (ep_attr_request.max_mtu_size > ep_attr_limit.max_mtu_size) { 514 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 515 DAT_INVALID_ARG3); 516 goto bail; 517 } else { 518 ep_attr.max_mtu_size = ep_attr_request.max_mtu_size; 519 } 520 } 521 522 /* 523 * Do nothing if the DAT_EP_FIELD_EP_ATTR_MAX_RDMA_SIZE flag is 524 * set. Each RDMA transport/provider may or may not have a limit 525 * on the size of an RDMA DTO. For InfiniBand, this parameter is 526 * validated in the implementation of the dapls_ib_qp_modify() 527 * function. 528 */ 529 /* LINTED: E_NOP_IF_STMT */ 530 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_QOS) { 531 /* Do nothing, not defined in the spec yet */ 532 } 533 534 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_RECV_COMPLETION_FLAGS) { 535 dat_status = dapl_ep_check_recv_completion_flags( 536 ep_attr_request.recv_completion_flags); 537 if (dat_status != DAT_SUCCESS) { 538 goto bail; 539 } else { 540 ep_attr.recv_completion_flags = 541 ep_attr_request.recv_completion_flags; 542 } 543 } 544 545 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_REQUEST_COMPLETION_FLAGS) { 546 dat_status = dapl_ep_check_request_completion_flags( 547 ep_attr_request.request_completion_flags); 548 if (dat_status != DAT_SUCCESS) { 549 goto bail; 550 } else { 551 ep_attr.request_completion_flags = 552 ep_attr_request.request_completion_flags; 553 } 554 } 555 556 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_RECV_DTOS) { 557 if ((ep->param.srq_handle != NULL) || 558 (ep_attr_request.max_recv_dtos > 559 ep_attr_limit.max_recv_dtos) || 560 (ep_param->recv_evd_handle == DAT_HANDLE_NULL && 561 (ep_attr_request.max_recv_dtos > 0))) { 562 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 563 DAT_INVALID_ARG3); 564 goto bail; 565 } else { 566 ep_attr.max_recv_dtos = ep_attr_request.max_recv_dtos; 567 } 568 } 569 570 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_DTOS) { 571 if (ep_attr_request.max_request_dtos > 572 ep_attr_limit.max_request_dtos || 573 (ep_param->request_evd_handle == DAT_HANDLE_NULL && 574 (ep_attr_request.max_request_dtos > 0))) { 575 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 576 DAT_INVALID_ARG3); 577 goto bail; 578 } else { 579 ep_attr.max_request_dtos = 580 ep_attr_request.max_request_dtos; 581 } 582 } 583 584 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_RECV_IOV) { 585 if ((ep->param.srq_handle != NULL) || 586 (ep_attr_request.max_recv_iov > 587 ep_attr_limit.max_recv_iov)) { 588 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 589 DAT_INVALID_ARG3); 590 goto bail; 591 } else { 592 ep_attr.max_recv_iov = ep_attr_request.max_recv_iov; 593 } 594 } 595 596 if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_IOV) { 597 if (ep_attr_request.max_request_iov > 598 ep_attr_limit.max_request_iov) { 599 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 600 DAT_INVALID_ARG3); 601 goto bail; 602 } else { 603 ep_attr.max_request_iov = 604 ep_attr_request.max_request_iov; 605 } 606 } 607 608 *ia_ptr = ia; 609 *ep_ptr = ep; 610 *ep_attr_ptr = ep_attr; 611 612 bail: 613 return (dat_status); 614 } 615