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
dapl_ep_modify(IN DAT_EP_HANDLE ep_handle,IN DAT_EP_PARAM_MASK ep_param_mask,IN const DAT_EP_PARAM * ep_param)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
dapli_ep_modify_validate_parameters(IN DAT_EP_HANDLE ep_handle,IN DAT_EP_PARAM_MASK ep_param_mask,IN const DAT_EP_PARAM * ep_param,OUT DAPL_IA ** ia_ptr,OUT DAPL_EP ** ep_ptr,OUT DAT_EP_ATTR * ep_attr_ptr)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