1 /*
2 * Copyright (c) 2015-2016 Intel Corporation. All rights reserved.
3 * Copyright (c) 2018, Cisco Systems, Inc. All rights reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * BSD license below:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34 #include <stdio.h>
35
36 #include <shared/ofi_str.h>
37 #include <ofi_util.h>
38
39 #define OFI_MSG_DIRECTION_CAPS (FI_SEND | FI_RECV)
40 #define OFI_RMA_DIRECTION_CAPS (FI_READ | FI_WRITE | \
41 FI_REMOTE_READ | FI_REMOTE_WRITE)
42
fi_valid_addr_format(uint32_t prov_format,uint32_t user_format)43 static int fi_valid_addr_format(uint32_t prov_format, uint32_t user_format)
44 {
45 if (user_format == FI_FORMAT_UNSPEC || prov_format == FI_FORMAT_UNSPEC)
46 return 1;
47
48 switch (prov_format) {
49 case FI_SOCKADDR:
50 /* Provider supports INET and INET6 */
51 return user_format <= FI_SOCKADDR_IN6;
52 case FI_SOCKADDR_IN:
53 /* Provider supports INET only */
54 return user_format <= FI_SOCKADDR_IN;
55 case FI_SOCKADDR_IN6:
56 /* Provider supports INET6 only */
57 return user_format <= FI_SOCKADDR_IN6;
58 case FI_SOCKADDR_IB:
59 /* Provider must support IB, INET, and INET6 */
60 return user_format <= FI_SOCKADDR_IB;
61 default:
62 return prov_format == user_format;
63 }
64 }
65
66 /*
67 char *ofi_strdup_head(const char *str)
68 {
69 char *delim;
70 delim = strchr(str, OFI_NAME_DELIM);
71 return delim ? strndup(str, delim - str) : strdup(str);
72 }
73
74 char *ofi_strdup_tail(const char *str)
75 {
76 char *delim;
77 delim = strchr(str, OFI_NAME_DELIM);
78 return delim ? strup(delim + 1) : strdup(str);
79 }
80 */
81
ofi_strdup_append(const char * head,const char * tail)82 char *ofi_strdup_append(const char *head, const char *tail)
83 {
84 char *str;
85 size_t len;
86
87 len = strlen(head) + strlen(tail) + 2;
88 str = malloc(len);
89 if (str)
90 sprintf(str, "%s%c%s", head, OFI_NAME_DELIM, tail);
91 return str;
92 }
93
ofi_exclude_prov_name(char ** prov_name_list,const char * util_prov_name)94 int ofi_exclude_prov_name(char **prov_name_list, const char *util_prov_name)
95 {
96 char *exclude, *name, *temp;
97
98 exclude = malloc(strlen(util_prov_name) + 2);
99 if (!exclude)
100 return -FI_ENOMEM;
101
102 exclude[0] = '^';
103 strcpy(&exclude[1], util_prov_name);
104
105 if (!*prov_name_list)
106 goto out;
107
108 name = strdup(*prov_name_list);
109 if (!name)
110 goto err1;
111
112 ofi_rm_substr_delim(name, util_prov_name, OFI_NAME_DELIM);
113
114 if (strlen(name)) {
115 temp = ofi_strdup_append(name, exclude);
116 if (!temp)
117 goto err2;
118 free(exclude);
119 exclude = temp;
120 }
121 free(name);
122 free(*prov_name_list);
123 out:
124 *prov_name_list = exclude;
125 return 0;
126 err2:
127 free(name);
128 err1:
129 free(exclude);
130 return -FI_ENOMEM;
131 }
132
ofi_dup_addr(const struct fi_info * info,struct fi_info * dup)133 static int ofi_dup_addr(const struct fi_info *info, struct fi_info *dup)
134 {
135 dup->addr_format = info->addr_format;
136 if (info->src_addr) {
137 dup->src_addrlen = info->src_addrlen;
138 dup->src_addr = mem_dup(info->src_addr, info->src_addrlen);
139 if (dup->src_addr == NULL)
140 return -FI_ENOMEM;
141 }
142 if (info->dest_addr) {
143 dup->dest_addrlen = info->dest_addrlen;
144 dup->dest_addr = mem_dup(info->dest_addr, info->dest_addrlen);
145 if (dup->dest_addr == NULL) {
146 free(dup->src_addr);
147 dup->src_addr = NULL;
148 return -FI_ENOMEM;
149 }
150 }
151 return 0;
152 }
153
ofi_info_to_core(uint32_t version,const struct fi_provider * prov,const struct fi_info * util_info,ofi_alter_info_t info_to_core,struct fi_info ** core_hints)154 static int ofi_info_to_core(uint32_t version, const struct fi_provider *prov,
155 const struct fi_info *util_info,
156 ofi_alter_info_t info_to_core,
157 struct fi_info **core_hints)
158 {
159 int ret = -FI_ENOMEM;
160
161 if (!(*core_hints = fi_allocinfo()))
162 return -FI_ENOMEM;
163
164 if (info_to_core(version, util_info, *core_hints))
165 goto err;
166
167 if (!util_info)
168 return 0;
169
170 if (ofi_dup_addr(util_info, *core_hints))
171 goto err;
172
173 if (util_info->fabric_attr) {
174 if (util_info->fabric_attr->name) {
175 (*core_hints)->fabric_attr->name =
176 strdup(util_info->fabric_attr->name);
177 if (!(*core_hints)->fabric_attr->name) {
178 FI_WARN(prov, FI_LOG_FABRIC,
179 "Unable to allocate fabric name\n");
180 goto err;
181 }
182 }
183
184 if (util_info->fabric_attr->prov_name) {
185 (*core_hints)->fabric_attr->prov_name =
186 strdup(util_info->fabric_attr->prov_name);
187 if (!(*core_hints)->fabric_attr->prov_name) {
188 FI_WARN(prov, FI_LOG_FABRIC,
189 "Unable to alloc prov name\n");
190 goto err;
191 }
192 ret = ofi_exclude_prov_name(
193 &(*core_hints)->fabric_attr->prov_name,
194 prov->name);
195 if (ret)
196 goto err;
197 }
198 }
199
200 if (util_info->domain_attr && util_info->domain_attr->name) {
201 (*core_hints)->domain_attr->name =
202 strdup(util_info->domain_attr->name);
203 if (!(*core_hints)->domain_attr->name) {
204 FI_WARN(prov, FI_LOG_FABRIC,
205 "Unable to allocate domain name\n");
206 goto err;
207 }
208 }
209 return 0;
210
211 err:
212 fi_freeinfo(*core_hints);
213 return ret;
214 }
215
ofi_info_to_util(uint32_t version,const struct fi_provider * prov,struct fi_info * core_info,ofi_alter_info_t info_to_util,struct fi_info ** util_info)216 static int ofi_info_to_util(uint32_t version, const struct fi_provider *prov,
217 struct fi_info *core_info,
218 ofi_alter_info_t info_to_util,
219 struct fi_info **util_info)
220 {
221 if (!(*util_info = fi_allocinfo()))
222 return -FI_ENOMEM;
223
224 if (info_to_util(version, core_info, *util_info))
225 goto err;
226
227 if (ofi_dup_addr(core_info, *util_info))
228 goto err;
229
230 /* Release 1.4 brought standardized domain names across IP based
231 * providers. Before this release, the usNIC provider would return a
232 * NULL domain name from fi_getinfo. For compatibility reasons, allow a
233 * NULL domain name when apps are requesting version < 1.4.
234 */
235 assert(FI_VERSION_LT(1, 4) || core_info->domain_attr->name);
236
237 if (core_info->domain_attr->name) {
238 (*util_info)->domain_attr->name =
239 strdup(core_info->domain_attr->name);
240
241 if (!(*util_info)->domain_attr->name) {
242 FI_WARN(prov, FI_LOG_FABRIC,
243 "Unable to allocate domain name\n");
244 goto err;
245 }
246 }
247
248 (*util_info)->fabric_attr->name = strdup(core_info->fabric_attr->name);
249 if (!(*util_info)->fabric_attr->name) {
250 FI_WARN(prov, FI_LOG_FABRIC,
251 "Unable to allocate fabric name\n");
252 goto err;
253 }
254
255 (*util_info)->fabric_attr->prov_name = strdup(core_info->fabric_attr->
256 prov_name);
257 if (!(*util_info)->fabric_attr->prov_name) {
258 FI_WARN(prov, FI_LOG_FABRIC,
259 "Unable to allocate fabric name\n");
260 goto err;
261 }
262
263 return 0;
264 err:
265 fi_freeinfo(*util_info);
266 return -FI_ENOMEM;
267 }
268
ofi_get_core_info(uint32_t version,const char * node,const char * service,uint64_t flags,const struct util_prov * util_prov,const struct fi_info * util_hints,ofi_alter_info_t info_to_core,struct fi_info ** core_info)269 int ofi_get_core_info(uint32_t version, const char *node, const char *service,
270 uint64_t flags, const struct util_prov *util_prov,
271 const struct fi_info *util_hints, ofi_alter_info_t info_to_core,
272 struct fi_info **core_info)
273 {
274 struct fi_info *core_hints = NULL;
275 int ret;
276
277 ret = ofi_prov_check_info(util_prov, version, util_hints);
278 if (ret)
279 return ret;
280
281 ret = ofi_info_to_core(version, util_prov->prov, util_hints, info_to_core,
282 &core_hints);
283 if (ret)
284 return ret;
285
286 FI_DBG(util_prov->prov, FI_LOG_CORE, "--- Begin ofi_get_core_info ---\n");
287
288 ret = fi_getinfo(version, node, service, flags | OFI_CORE_PROV_ONLY,
289 core_hints, core_info);
290
291 FI_DBG(util_prov->prov, FI_LOG_CORE, "--- End ofi_get_core_info ---\n");
292
293 fi_freeinfo(core_hints);
294 return ret;
295 }
296
ofix_getinfo(uint32_t version,const char * node,const char * service,uint64_t flags,const struct util_prov * util_prov,const struct fi_info * hints,ofi_alter_info_t info_to_core,ofi_alter_info_t info_to_util,struct fi_info ** info)297 int ofix_getinfo(uint32_t version, const char *node, const char *service,
298 uint64_t flags, const struct util_prov *util_prov,
299 const struct fi_info *hints, ofi_alter_info_t info_to_core,
300 ofi_alter_info_t info_to_util, struct fi_info **info)
301 {
302 struct fi_info *core_info, *util_info, *cur, *tail;
303 int ret;
304
305 ret = ofi_get_core_info(version, node, service, flags, util_prov,
306 hints, info_to_core, &core_info);
307 if (ret)
308 return ret;
309
310 *info = tail = NULL;
311 for (cur = core_info; cur; cur = cur->next) {
312 ret = ofi_info_to_util(version, util_prov->prov, cur,
313 info_to_util, &util_info);
314 if (ret) {
315 fi_freeinfo(*info);
316 break;
317 }
318
319 ofi_alter_info(util_info, hints, version);
320 if (!*info)
321 *info = util_info;
322 else
323 tail->next = util_info;
324 tail = util_info;
325 }
326 fi_freeinfo(core_info);
327 return ret;
328 }
329
330 /* Caller should use only fabric_attr in returned core_info */
ofi_get_core_info_fabric(const struct fi_provider * prov,const struct fi_fabric_attr * util_attr,struct fi_info ** core_info)331 int ofi_get_core_info_fabric(const struct fi_provider *prov,
332 const struct fi_fabric_attr *util_attr,
333 struct fi_info **core_info)
334 {
335 struct fi_info hints;
336 int ret;
337
338 /* ofix_getinfo() would append utility provider name after core / lower
339 * layer provider name */
340 if (!strstr(util_attr->prov_name, prov->name))
341 return -FI_ENODATA;
342
343 memset(&hints, 0, sizeof hints);
344 if (!(hints.fabric_attr = calloc(1, sizeof(*hints.fabric_attr))))
345 return -FI_ENOMEM;
346
347 hints.fabric_attr->prov_name = strdup(util_attr->prov_name);
348 if (!hints.fabric_attr->prov_name) {
349 ret = -FI_ENOMEM;
350 goto out;
351 }
352
353 ret = ofi_exclude_prov_name(&hints.fabric_attr->prov_name, prov->name);
354 if (ret)
355 goto out;
356
357 hints.fabric_attr->name = util_attr->name;
358 hints.fabric_attr->api_version = util_attr->api_version;
359 hints.mode = ~0;
360
361 ret = fi_getinfo(util_attr->api_version, NULL, NULL, OFI_CORE_PROV_ONLY,
362 &hints, core_info);
363
364 free(hints.fabric_attr->prov_name);
365 out:
366 free(hints.fabric_attr);
367 return ret;
368 }
369
ofi_check_fabric_attr(const struct fi_provider * prov,const struct fi_fabric_attr * prov_attr,const struct fi_fabric_attr * user_attr)370 int ofi_check_fabric_attr(const struct fi_provider *prov,
371 const struct fi_fabric_attr *prov_attr,
372 const struct fi_fabric_attr *user_attr)
373 {
374 /* Provider names are checked by the framework */
375
376 if (user_attr->prov_version > prov_attr->prov_version) {
377 FI_INFO(prov, FI_LOG_CORE, "Unsupported provider version\n");
378 return -FI_ENODATA;
379 }
380
381 if (FI_VERSION_LT(user_attr->api_version, prov_attr->api_version)) {
382 FI_INFO(prov, FI_LOG_CORE, "Unsupported api version\n");
383 return -FI_ENODATA;
384 }
385
386 return 0;
387 }
388
389 /*
390 * Threading models ranked by order of parallelism.
391 */
fi_thread_level(enum fi_threading thread_model)392 static int fi_thread_level(enum fi_threading thread_model)
393 {
394 switch (thread_model) {
395 case FI_THREAD_SAFE:
396 return 1;
397 case FI_THREAD_FID:
398 return 2;
399 case FI_THREAD_ENDPOINT:
400 return 3;
401 case FI_THREAD_COMPLETION:
402 return 4;
403 case FI_THREAD_DOMAIN:
404 return 5;
405 case FI_THREAD_UNSPEC:
406 return 6;
407 default:
408 return -1;
409 }
410 }
411
412 /*
413 * Progress models ranked by order of automation.
414 */
fi_progress_level(enum fi_progress progress_model)415 static int fi_progress_level(enum fi_progress progress_model)
416 {
417 switch (progress_model) {
418 case FI_PROGRESS_AUTO:
419 return 1;
420 case FI_PROGRESS_MANUAL:
421 return 2;
422 case FI_PROGRESS_UNSPEC:
423 return 3;
424 default:
425 return -1;
426 }
427 }
428
429 /*
430 * Resource management models ranked by order of enablement.
431 */
fi_resource_mgmt_level(enum fi_resource_mgmt rm_model)432 static int fi_resource_mgmt_level(enum fi_resource_mgmt rm_model)
433 {
434 switch (rm_model) {
435 case FI_RM_ENABLED:
436 return 1;
437 case FI_RM_DISABLED:
438 return 2;
439 case FI_RM_UNSPEC:
440 return 3;
441 default:
442 return -1;
443 }
444 }
445
446 /*
447 * Remove unneeded MR mode bits based on the requested capability bits.
448 */
ofi_cap_mr_mode(uint64_t info_caps,int mr_mode)449 static int ofi_cap_mr_mode(uint64_t info_caps, int mr_mode)
450 {
451 if (!ofi_rma_target_allowed(info_caps)) {
452 if (!(mr_mode & (FI_MR_LOCAL | FI_MR_HMEM)))
453 return 0;
454
455 mr_mode &= ~OFI_MR_MODE_RMA_TARGET;
456 }
457
458 return mr_mode & ~(FI_MR_BASIC | FI_MR_SCALABLE);
459 }
460
461 /*
462 * Providers should set v1.0 registration modes (FI_MR_BASIC and
463 * FI_MR_SCALABLE) that they support, along with all required modes.
464 */
ofi_check_mr_mode(const struct fi_provider * prov,uint32_t api_version,int prov_mode,const struct fi_info * user_info)465 int ofi_check_mr_mode(const struct fi_provider *prov, uint32_t api_version,
466 int prov_mode, const struct fi_info *user_info)
467 {
468 int user_mode = user_info->domain_attr->mr_mode;
469 int ret = -FI_ENODATA;
470
471 if ((prov_mode & FI_MR_LOCAL) &&
472 !((user_info->mode & FI_LOCAL_MR) || (user_mode & FI_MR_LOCAL)))
473 goto out;
474
475 if (FI_VERSION_LT(api_version, FI_VERSION(1, 5))) {
476 switch (user_mode) {
477 case FI_MR_UNSPEC:
478 if (!(prov_mode & (FI_MR_SCALABLE | FI_MR_BASIC)))
479 goto out;
480 break;
481 case FI_MR_BASIC:
482 if (!(prov_mode & FI_MR_BASIC))
483 goto out;
484 break;
485 case FI_MR_SCALABLE:
486 if (!(prov_mode & FI_MR_SCALABLE))
487 goto out;
488 break;
489 default:
490 goto out;
491 }
492 } else {
493 if (user_mode & FI_MR_BASIC) {
494 if ((user_mode & ~FI_MR_BASIC) ||
495 !(prov_mode & FI_MR_BASIC))
496 goto out;
497 } else if (user_mode & FI_MR_SCALABLE) {
498 if ((user_mode & ~FI_MR_SCALABLE) ||
499 !(prov_mode & FI_MR_SCALABLE))
500 goto out;
501 } else {
502 prov_mode = ofi_cap_mr_mode(user_info->caps, prov_mode);
503 if ((user_mode & prov_mode) != prov_mode)
504 goto out;
505 }
506 }
507
508 ret = 0;
509 out:
510 if (ret) {
511 FI_INFO(prov, FI_LOG_CORE, "Invalid memory registration mode\n");
512 FI_INFO_MR_MODE(prov, prov_mode, user_mode);
513 }
514
515 return ret;
516 }
517
ofi_check_domain_attr(const struct fi_provider * prov,uint32_t api_version,const struct fi_domain_attr * prov_attr,const struct fi_info * user_info)518 int ofi_check_domain_attr(const struct fi_provider *prov, uint32_t api_version,
519 const struct fi_domain_attr *prov_attr,
520 const struct fi_info *user_info)
521 {
522 const struct fi_domain_attr *user_attr = user_info->domain_attr;
523
524 if (fi_thread_level(user_attr->threading) <
525 fi_thread_level(prov_attr->threading)) {
526 FI_INFO(prov, FI_LOG_CORE, "Invalid threading model\n");
527 return -FI_ENODATA;
528 }
529
530 if (fi_progress_level(user_attr->control_progress) <
531 fi_progress_level(prov_attr->control_progress)) {
532 FI_INFO(prov, FI_LOG_CORE, "Invalid control progress model\n");
533 return -FI_ENODATA;
534 }
535
536 if (fi_progress_level(user_attr->data_progress) <
537 fi_progress_level(prov_attr->data_progress)) {
538 FI_INFO(prov, FI_LOG_CORE, "Invalid data progress model\n");
539 return -FI_ENODATA;
540 }
541
542 if (fi_resource_mgmt_level(user_attr->resource_mgmt) <
543 fi_resource_mgmt_level(prov_attr->resource_mgmt)) {
544 FI_INFO(prov, FI_LOG_CORE, "Invalid resource mgmt model\n");
545 return -FI_ENODATA;
546 }
547
548 if ((prov_attr->av_type != FI_AV_UNSPEC) &&
549 (user_attr->av_type != FI_AV_UNSPEC) &&
550 (prov_attr->av_type != user_attr->av_type)) {
551 FI_INFO(prov, FI_LOG_CORE, "Invalid AV type\n");
552 return -FI_ENODATA;
553 }
554
555 if (user_attr->cq_data_size > prov_attr->cq_data_size) {
556 FI_INFO(prov, FI_LOG_CORE, "CQ data size too large\n");
557 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, cq_data_size);
558 return -FI_ENODATA;
559 }
560
561 if (ofi_check_mr_mode(prov, api_version, prov_attr->mr_mode, user_info))
562 return -FI_ENODATA;
563
564 if (user_attr->max_ep_stx_ctx > prov_attr->max_ep_stx_ctx) {
565 FI_INFO(prov, FI_LOG_CORE, "max_ep_stx_ctx greater than supported\n");
566 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, max_ep_stx_ctx);
567 }
568
569 if (user_attr->max_ep_srx_ctx > prov_attr->max_ep_srx_ctx) {
570 FI_INFO(prov, FI_LOG_CORE, "max_ep_srx_ctx greater than supported\n");
571 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, max_ep_srx_ctx);
572 }
573
574 /* following checks only apply to api 1.5 and beyond */
575 if (FI_VERSION_LT(api_version, FI_VERSION(1, 5)))
576 return 0;
577
578 if (user_attr->cntr_cnt > prov_attr->cntr_cnt) {
579 FI_INFO(prov, FI_LOG_CORE, "Cntr count too large\n");
580 return -FI_ENODATA;
581 }
582
583 if (user_attr->mr_iov_limit > prov_attr->mr_iov_limit) {
584 FI_INFO(prov, FI_LOG_CORE, "MR iov limit too large\n");
585 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, mr_iov_limit);
586 return -FI_ENODATA;
587 }
588
589 if (user_attr->caps & ~(prov_attr->caps)) {
590 FI_INFO(prov, FI_LOG_CORE, "Requested domain caps not supported\n");
591 FI_INFO_CHECK(prov, prov_attr, user_attr, caps, FI_TYPE_CAPS);
592 return -FI_ENODATA;
593 }
594
595 if ((user_attr->mode & prov_attr->mode) != prov_attr->mode) {
596 FI_INFO(prov, FI_LOG_CORE, "Required domain mode missing\n");
597 FI_INFO_MODE(prov, prov_attr->mode, user_attr->mode);
598 return -FI_ENODATA;
599 }
600
601 if (user_attr->max_err_data > prov_attr->max_err_data) {
602 FI_INFO(prov, FI_LOG_CORE, "Max err data too large\n");
603 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, max_err_data);
604 return -FI_ENODATA;
605 }
606
607 if (user_attr->mr_cnt > prov_attr->mr_cnt) {
608 FI_INFO(prov, FI_LOG_CORE, "MR count too large\n");
609 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, mr_cnt);
610 return -FI_ENODATA;
611 }
612
613 return 0;
614 }
615
ofi_check_ep_type(const struct fi_provider * prov,const struct fi_ep_attr * prov_attr,const struct fi_ep_attr * user_attr)616 int ofi_check_ep_type(const struct fi_provider *prov,
617 const struct fi_ep_attr *prov_attr,
618 const struct fi_ep_attr *user_attr)
619 {
620 if ((user_attr->type != FI_EP_UNSPEC) &&
621 (prov_attr->type != FI_EP_UNSPEC) &&
622 (user_attr->type != prov_attr->type)) {
623 FI_INFO(prov, FI_LOG_CORE, "unsupported endpoint type\n");
624 FI_INFO_CHECK(prov, prov_attr, user_attr, type, FI_TYPE_EP_TYPE);
625 return -FI_ENODATA;
626 }
627 return 0;
628 }
629
ofi_check_ep_attr(const struct util_prov * util_prov,uint32_t api_version,const struct fi_info * prov_info,const struct fi_info * user_info)630 int ofi_check_ep_attr(const struct util_prov *util_prov, uint32_t api_version,
631 const struct fi_info *prov_info,
632 const struct fi_info *user_info)
633 {
634 const struct fi_ep_attr *prov_attr = prov_info->ep_attr;
635 const struct fi_ep_attr *user_attr = user_info->ep_attr;
636 const struct fi_provider *prov = util_prov->prov;
637 int ret;
638
639 ret = ofi_check_ep_type(prov, prov_attr, user_attr);
640 if (ret)
641 return ret;
642
643 if ((user_attr->protocol != FI_PROTO_UNSPEC) &&
644 (user_attr->protocol != prov_attr->protocol)) {
645 FI_INFO(prov, FI_LOG_CORE, "Unsupported protocol\n");
646 FI_INFO_CHECK(prov, prov_attr, user_attr, protocol, FI_TYPE_PROTOCOL);
647 return -FI_ENODATA;
648 }
649
650 if (user_attr->protocol_version &&
651 (user_attr->protocol_version > prov_attr->protocol_version)) {
652 FI_INFO(prov, FI_LOG_CORE, "Unsupported protocol version\n");
653 return -FI_ENODATA;
654 }
655
656 if (user_attr->max_msg_size > prov_attr->max_msg_size) {
657 FI_INFO(prov, FI_LOG_CORE, "Max message size too large\n");
658 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, max_msg_size);
659 return -FI_ENODATA;
660 }
661
662 if (user_attr->tx_ctx_cnt > prov_info->domain_attr->max_ep_tx_ctx) {
663 if (user_attr->tx_ctx_cnt == FI_SHARED_CONTEXT) {
664 if (!prov_info->domain_attr->max_ep_stx_ctx) {
665 FI_INFO(prov, FI_LOG_CORE,
666 "Shared tx context not supported\n");
667 return -FI_ENODATA;
668 }
669 } else {
670 FI_INFO(prov, FI_LOG_CORE,
671 "Requested tx_ctx_cnt exceeds supported."
672 " Expected:%zd, Requested%zd\n",
673 prov_info->domain_attr->max_ep_tx_ctx,
674 user_attr->tx_ctx_cnt);
675 return -FI_ENODATA;
676 }
677 }
678
679 if (user_attr->rx_ctx_cnt > prov_info->domain_attr->max_ep_rx_ctx) {
680 if (user_attr->rx_ctx_cnt == FI_SHARED_CONTEXT) {
681 if (!prov_info->domain_attr->max_ep_srx_ctx) {
682 FI_INFO(prov, FI_LOG_CORE,
683 "Shared rx context not supported\n");
684 return -FI_ENODATA;
685 }
686 } else {
687 FI_INFO(prov, FI_LOG_CORE,
688 "Requested rx_ctx_cnt exceeds supported."
689 " Expected: %zd, Requested:%zd\n",
690 prov_info->domain_attr->max_ep_rx_ctx,
691 user_attr->rx_ctx_cnt);
692 return -FI_ENODATA;
693 }
694 }
695
696 if (user_info->caps & (FI_RMA | FI_ATOMIC)) {
697 if (user_attr->max_order_raw_size >
698 prov_attr->max_order_raw_size) {
699 FI_INFO(prov, FI_LOG_CORE,
700 "Max order RAW size exceeds supported size\n");
701 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr,
702 max_order_raw_size);
703 return -FI_ENODATA;
704 }
705
706 if (user_attr->max_order_war_size >
707 prov_attr->max_order_war_size) {
708 FI_INFO(prov, FI_LOG_CORE,
709 "Max order WAR size exceeds supported size\n");
710 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr,
711 max_order_war_size);
712 return -FI_ENODATA;
713 }
714
715 if (user_attr->max_order_waw_size >
716 prov_attr->max_order_waw_size) {
717 FI_INFO(prov, FI_LOG_CORE,
718 "Max order WAW size exceeds supported size\n");
719 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr,
720 max_order_waw_size);
721 return -FI_ENODATA;
722 }
723 }
724
725 if (user_attr->auth_key_size &&
726 (user_attr->auth_key_size != prov_attr->auth_key_size)) {
727 FI_INFO(prov, FI_LOG_CORE, "Unsupported authentication size.");
728 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, auth_key_size);
729 return -FI_ENODATA;
730 }
731
732 return 0;
733 }
734
ofi_check_rx_attr(const struct fi_provider * prov,const struct fi_info * prov_info,const struct fi_rx_attr * user_attr,uint64_t info_mode)735 int ofi_check_rx_attr(const struct fi_provider *prov,
736 const struct fi_info *prov_info,
737 const struct fi_rx_attr *user_attr, uint64_t info_mode)
738 {
739 const struct fi_rx_attr *prov_attr = prov_info->rx_attr;
740 int rm_enabled = (prov_info->domain_attr->resource_mgmt == FI_RM_ENABLED);
741
742 if (user_attr->caps & ~OFI_IGNORED_RX_CAPS)
743 FI_INFO(prov, FI_LOG_CORE, "Tx only caps ignored in Rx caps\n");
744
745 if ((user_attr->caps & ~OFI_IGNORED_RX_CAPS) & ~(prov_attr->caps)) {
746 FI_INFO(prov, FI_LOG_CORE, "caps not supported\n");
747 FI_INFO_CHECK(prov, prov_attr, user_attr, caps, FI_TYPE_CAPS);
748 return -FI_ENODATA;
749 }
750
751 info_mode = user_attr->mode ? user_attr->mode : info_mode;
752 if ((info_mode & prov_attr->mode) != prov_attr->mode) {
753 FI_INFO(prov, FI_LOG_CORE, "needed mode not set\n");
754 FI_INFO_MODE(prov, prov_attr->mode, user_attr->mode);
755 return -FI_ENODATA;
756 }
757
758 if (user_attr->op_flags & ~(prov_attr->op_flags)) {
759 FI_INFO(prov, FI_LOG_CORE, "op_flags not supported\n");
760 FI_INFO_CHECK(prov, prov_attr, user_attr, op_flags,
761 FI_TYPE_OP_FLAGS);
762 return -FI_ENODATA;
763 }
764
765 if (user_attr->msg_order & ~(prov_attr->msg_order)) {
766 FI_INFO(prov, FI_LOG_CORE, "msg_order not supported\n");
767 FI_INFO_CHECK(prov, prov_attr, user_attr, msg_order,
768 FI_TYPE_MSG_ORDER);
769 return -FI_ENODATA;
770 }
771
772 if (user_attr->comp_order & ~(prov_attr->comp_order)) {
773 FI_INFO(prov, FI_LOG_CORE, "comp_order not supported\n");
774 FI_INFO_CHECK(prov, prov_attr, user_attr, comp_order,
775 FI_TYPE_MSG_ORDER);
776 return -FI_ENODATA;
777 }
778
779 if (user_attr->total_buffered_recv > prov_attr->total_buffered_recv) {
780 FI_INFO(prov, FI_LOG_CORE, "total_buffered_recv too large\n");
781 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr,
782 total_buffered_recv);
783 return -FI_ENODATA;
784 }
785
786 if (user_attr->size > prov_attr->size) {
787 FI_INFO(prov, FI_LOG_CORE, "size is greater than supported\n");
788 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, size);
789 return -FI_ENODATA;
790 }
791
792 if (user_attr->iov_limit > prov_attr->iov_limit) {
793 FI_INFO(prov, FI_LOG_CORE, "iov_limit too large\n");
794 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, iov_limit);
795 return -FI_ENODATA;
796 }
797
798 if (!rm_enabled &&
799 user_attr->total_buffered_recv > prov_attr->total_buffered_recv) {
800 /* Just log a notification, but ignore the value */
801 FI_INFO(prov, FI_LOG_CORE,
802 "Total buffered recv size exceeds supported size\n");
803 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr,
804 total_buffered_recv);
805 }
806
807 return 0;
808 }
809
ofi_check_attr_subset(const struct fi_provider * prov,uint64_t base_caps,uint64_t requested_caps)810 int ofi_check_attr_subset(const struct fi_provider *prov,
811 uint64_t base_caps, uint64_t requested_caps)
812 {
813 uint64_t expanded_caps;
814
815 expanded_caps = base_caps;
816 if (base_caps & (FI_MSG | FI_TAGGED)) {
817 if (!(base_caps & OFI_MSG_DIRECTION_CAPS))
818 expanded_caps |= OFI_MSG_DIRECTION_CAPS;
819 }
820 if (base_caps & (FI_RMA | FI_ATOMIC)) {
821 if (!(base_caps & OFI_RMA_DIRECTION_CAPS))
822 expanded_caps |= OFI_RMA_DIRECTION_CAPS;
823 }
824
825 if (~expanded_caps & requested_caps) {
826 FI_INFO(prov, FI_LOG_CORE,
827 "requested caps not subset of base endpoint caps\n");
828 FI_INFO_FIELD(prov, expanded_caps, requested_caps,
829 "Supported", "Requested", FI_TYPE_CAPS);
830 return -FI_ENODATA;
831 }
832
833 return 0;
834 }
835
ofi_check_tx_attr(const struct fi_provider * prov,const struct fi_tx_attr * prov_attr,const struct fi_tx_attr * user_attr,uint64_t info_mode)836 int ofi_check_tx_attr(const struct fi_provider *prov,
837 const struct fi_tx_attr *prov_attr,
838 const struct fi_tx_attr *user_attr, uint64_t info_mode)
839 {
840 if (user_attr->caps & ~OFI_IGNORED_TX_CAPS)
841 FI_INFO(prov, FI_LOG_CORE, "Rx only caps ignored in Tx caps\n");
842
843 if ((user_attr->caps & ~OFI_IGNORED_TX_CAPS) & ~(prov_attr->caps)) {
844 FI_INFO(prov, FI_LOG_CORE, "caps not supported\n");
845 FI_INFO_CHECK(prov, prov_attr, user_attr, caps, FI_TYPE_CAPS);
846 return -FI_ENODATA;
847 }
848
849 info_mode = user_attr->mode ? user_attr->mode : info_mode;
850 if ((info_mode & prov_attr->mode) != prov_attr->mode) {
851 FI_INFO(prov, FI_LOG_CORE, "needed mode not set\n");
852 FI_INFO_MODE(prov, prov_attr->mode, user_attr->mode);
853 return -FI_ENODATA;
854 }
855
856 if (user_attr->op_flags & ~(prov_attr->op_flags)) {
857 FI_INFO(prov, FI_LOG_CORE, "op_flags not supported\n");
858 FI_INFO_CHECK(prov, prov_attr, user_attr, op_flags,
859 FI_TYPE_OP_FLAGS);
860 return -FI_ENODATA;
861 }
862
863 if (user_attr->msg_order & ~(prov_attr->msg_order)) {
864 FI_INFO(prov, FI_LOG_CORE, "msg_order not supported\n");
865 FI_INFO_CHECK(prov, prov_attr, user_attr, msg_order,
866 FI_TYPE_MSG_ORDER);
867 return -FI_ENODATA;
868 }
869
870 if (user_attr->comp_order & ~(prov_attr->comp_order)) {
871 FI_INFO(prov, FI_LOG_CORE, "comp_order not supported\n");
872 FI_INFO_CHECK(prov, prov_attr, user_attr, comp_order,
873 FI_TYPE_MSG_ORDER);
874 return -FI_ENODATA;
875 }
876
877 if (user_attr->inject_size > prov_attr->inject_size) {
878 FI_INFO(prov, FI_LOG_CORE, "inject_size too large\n");
879 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, inject_size);
880 return -FI_ENODATA;
881 }
882
883 if (user_attr->size > prov_attr->size) {
884 FI_INFO(prov, FI_LOG_CORE, "size is greater than supported\n");
885 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, size);
886 return -FI_ENODATA;
887 }
888
889 if (user_attr->iov_limit > prov_attr->iov_limit) {
890 FI_INFO(prov, FI_LOG_CORE, "iov_limit too large\n");
891 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, iov_limit);
892 return -FI_ENODATA;
893 }
894
895 if (user_attr->rma_iov_limit > prov_attr->rma_iov_limit) {
896 FI_INFO(prov, FI_LOG_CORE, "rma_iov_limit too large\n");
897 FI_INFO_CHECK_VAL(prov, prov_attr, user_attr, rma_iov_limit);
898 return -FI_ENODATA;
899 }
900
901 return 0;
902 }
903
904 /* Use if there are multiple fi_info in the provider:
905 * check provider's info */
ofi_prov_check_info(const struct util_prov * util_prov,uint32_t api_version,const struct fi_info * user_info)906 int ofi_prov_check_info(const struct util_prov *util_prov,
907 uint32_t api_version,
908 const struct fi_info *user_info)
909 {
910 const struct fi_info *prov_info = util_prov->info;
911 size_t success_info = 0;
912 int ret;
913
914 if (!user_info)
915 return FI_SUCCESS;
916
917 for ( ; prov_info; prov_info = prov_info->next) {
918 ret = ofi_check_info(util_prov, prov_info,
919 api_version, user_info);
920 if (!ret)
921 success_info++;
922 }
923
924 return (!success_info ? -FI_ENODATA : FI_SUCCESS);
925 }
926
927 /* Use if there are multiple fi_info in the provider:
928 * check and duplicate provider's info */
ofi_prov_check_dup_info(const struct util_prov * util_prov,uint32_t api_version,const struct fi_info * user_info,struct fi_info ** info)929 int ofi_prov_check_dup_info(const struct util_prov *util_prov,
930 uint32_t api_version,
931 const struct fi_info *user_info,
932 struct fi_info **info)
933 {
934 const struct fi_info *prov_info = util_prov->info;
935 const struct fi_provider *prov = util_prov->prov;
936 struct fi_info *fi, *tail;
937 int ret;
938
939 if (!info)
940 return -FI_EINVAL;
941
942 *info = tail = NULL;
943
944 for ( ; prov_info; prov_info = prov_info->next) {
945 ret = ofi_check_info(util_prov, prov_info,
946 api_version, user_info);
947 if (ret)
948 continue;
949 if (!(fi = fi_dupinfo(prov_info))) {
950 ret = -FI_ENOMEM;
951 goto err;
952 }
953 if (!*info)
954 *info = fi;
955 else
956 tail->next = fi;
957 tail = fi;
958 }
959
960 return !*info ? -FI_ENODATA : FI_SUCCESS;
961 err:
962 fi_freeinfo(*info);
963 FI_INFO(prov, FI_LOG_CORE,
964 "cannot copy info\n");
965 return ret;
966 }
967
968 /* Use if there is only single fi_info in the provider */
ofi_check_info(const struct util_prov * util_prov,const struct fi_info * prov_info,uint32_t api_version,const struct fi_info * user_info)969 int ofi_check_info(const struct util_prov *util_prov,
970 const struct fi_info *prov_info, uint32_t api_version,
971 const struct fi_info *user_info)
972 {
973 const struct fi_provider *prov = util_prov->prov;
974 uint64_t prov_mode;
975 int ret;
976
977 if (!user_info)
978 return 0;
979
980 /* Check oft-used endpoint type attribute first to avoid any other
981 * unnecessary check */
982 if (user_info->ep_attr) {
983 ret = ofi_check_ep_type(prov, prov_info->ep_attr,
984 user_info->ep_attr);
985 if (ret)
986 return ret;
987 }
988
989 if (user_info->caps & ~(prov_info->caps)) {
990 FI_INFO(prov, FI_LOG_CORE, "Unsupported capabilities\n");
991 FI_INFO_CHECK(prov, prov_info, user_info, caps, FI_TYPE_CAPS);
992 return -FI_ENODATA;
993 }
994
995 prov_mode = ofi_mr_get_prov_mode(api_version, user_info, prov_info);
996
997 if ((user_info->mode & prov_mode) != prov_mode) {
998 FI_INFO(prov, FI_LOG_CORE, "needed mode not set\n");
999 FI_INFO_MODE(prov, prov_mode, user_info->mode);
1000 return -FI_ENODATA;
1001 }
1002
1003 if (!fi_valid_addr_format(prov_info->addr_format,
1004 user_info->addr_format)) {
1005 FI_INFO(prov, FI_LOG_CORE, "address format not supported\n");
1006 FI_INFO_CHECK(prov, prov_info, user_info, addr_format,
1007 FI_TYPE_ADDR_FORMAT);
1008 return -FI_ENODATA;
1009 }
1010
1011 if (user_info->fabric_attr) {
1012 ret = ofi_check_fabric_attr(prov, prov_info->fabric_attr,
1013 user_info->fabric_attr);
1014 if (ret)
1015 return ret;
1016 }
1017
1018 if (user_info->domain_attr) {
1019 ret = ofi_check_domain_attr(prov, api_version,
1020 prov_info->domain_attr,
1021 user_info);
1022 if (ret)
1023 return ret;
1024 }
1025
1026 if (user_info->ep_attr) {
1027 ret = ofi_check_ep_attr(util_prov, api_version,
1028 prov_info, user_info);
1029 if (ret)
1030 return ret;
1031 }
1032
1033 if (user_info->rx_attr) {
1034 ret = ofi_check_rx_attr(prov, prov_info,
1035 user_info->rx_attr, user_info->mode);
1036 if (ret)
1037 return ret;
1038 }
1039
1040 if (user_info->tx_attr) {
1041 ret = ofi_check_tx_attr(prov, prov_info->tx_attr,
1042 user_info->tx_attr, user_info->mode);
1043 if (ret)
1044 return ret;
1045 }
1046 return 0;
1047 }
1048
ofi_get_caps(uint64_t info_caps,uint64_t hint_caps,uint64_t attr_caps)1049 static uint64_t ofi_get_caps(uint64_t info_caps, uint64_t hint_caps,
1050 uint64_t attr_caps)
1051 {
1052 uint64_t caps;
1053
1054 if (!hint_caps) {
1055 caps = (info_caps & attr_caps & FI_PRIMARY_CAPS) |
1056 (attr_caps & FI_SECONDARY_CAPS);
1057 } else {
1058 caps = (hint_caps & FI_PRIMARY_CAPS) |
1059 (attr_caps & FI_SECONDARY_CAPS);
1060 }
1061
1062 if (caps & (FI_MSG | FI_TAGGED) && !(caps & OFI_MSG_DIRECTION_CAPS))
1063 caps |= (attr_caps & OFI_MSG_DIRECTION_CAPS);
1064 if (caps & (FI_RMA | FI_ATOMICS) && !(caps & OFI_RMA_DIRECTION_CAPS))
1065 caps |= (attr_caps & OFI_RMA_DIRECTION_CAPS);
1066
1067 return caps;
1068 }
1069
fi_alter_domain_attr(struct fi_domain_attr * attr,const struct fi_domain_attr * hints,uint64_t info_caps,uint32_t api_version)1070 static void fi_alter_domain_attr(struct fi_domain_attr *attr,
1071 const struct fi_domain_attr *hints,
1072 uint64_t info_caps, uint32_t api_version)
1073 {
1074 int hints_mr_mode;
1075
1076 hints_mr_mode = hints ? hints->mr_mode : 0;
1077 if (hints_mr_mode & (FI_MR_BASIC | FI_MR_SCALABLE)) {
1078 attr->mr_mode = hints_mr_mode;
1079 } else if (FI_VERSION_LT(api_version, FI_VERSION(1, 5))) {
1080 attr->mr_mode = (attr->mr_mode && attr->mr_mode != FI_MR_SCALABLE) ?
1081 FI_MR_BASIC : FI_MR_SCALABLE;
1082 } else {
1083 if ((hints_mr_mode & attr->mr_mode) != attr->mr_mode) {
1084 attr->mr_mode = ofi_cap_mr_mode(info_caps,
1085 attr->mr_mode & hints_mr_mode);
1086 }
1087 }
1088
1089 attr->caps = ofi_get_caps(info_caps, hints ? hints->caps : 0, attr->caps);
1090 if (!hints)
1091 return;
1092
1093 if (hints->threading)
1094 attr->threading = hints->threading;
1095 if (hints->control_progress)
1096 attr->control_progress = hints->control_progress;
1097 if (hints->data_progress)
1098 attr->data_progress = hints->data_progress;
1099 if (hints->av_type)
1100 attr->av_type = hints->av_type;
1101 }
1102
fi_alter_ep_attr(struct fi_ep_attr * attr,const struct fi_ep_attr * hints,uint64_t info_caps)1103 static void fi_alter_ep_attr(struct fi_ep_attr *attr,
1104 const struct fi_ep_attr *hints,
1105 uint64_t info_caps)
1106 {
1107 if (!hints)
1108 return;
1109
1110 if (info_caps & (FI_RMA | FI_ATOMIC)) {
1111 if (hints->max_order_raw_size)
1112 attr->max_order_raw_size = hints->max_order_raw_size;
1113 if (hints->max_order_war_size)
1114 attr->max_order_war_size = hints->max_order_war_size;
1115 if (hints->max_order_waw_size)
1116 attr->max_order_waw_size = hints->max_order_waw_size;
1117 }
1118 if (hints->tx_ctx_cnt)
1119 attr->tx_ctx_cnt = hints->tx_ctx_cnt;
1120 if (hints->rx_ctx_cnt)
1121 attr->rx_ctx_cnt = hints->rx_ctx_cnt;
1122 }
1123
fi_alter_rx_attr(struct fi_rx_attr * attr,const struct fi_rx_attr * hints,uint64_t info_caps)1124 static void fi_alter_rx_attr(struct fi_rx_attr *attr,
1125 const struct fi_rx_attr *hints,
1126 uint64_t info_caps)
1127 {
1128 attr->caps = ofi_get_caps(info_caps, hints ? hints->caps : 0, attr->caps);
1129 if (!hints)
1130 return;
1131
1132 attr->op_flags = hints->op_flags;
1133 attr->total_buffered_recv = hints->total_buffered_recv;
1134 if (hints->size)
1135 attr->size = hints->size;
1136 if (hints->iov_limit)
1137 attr->iov_limit = hints->iov_limit;
1138 }
1139
fi_alter_tx_attr(struct fi_tx_attr * attr,const struct fi_tx_attr * hints,uint64_t info_caps)1140 static void fi_alter_tx_attr(struct fi_tx_attr *attr,
1141 const struct fi_tx_attr *hints,
1142 uint64_t info_caps)
1143 {
1144 attr->caps = ofi_get_caps(info_caps, hints ? hints->caps : 0, attr->caps);
1145 if (!hints)
1146 return;
1147
1148 attr->op_flags = hints->op_flags;
1149 if (hints->inject_size)
1150 attr->inject_size = hints->inject_size;
1151 if (hints->size)
1152 attr->size = hints->size;
1153 if (hints->iov_limit)
1154 attr->iov_limit = hints->iov_limit;
1155 if (hints->rma_iov_limit)
1156 attr->rma_iov_limit = hints->rma_iov_limit;
1157 }
1158
ofi_get_info_caps(const struct fi_info * prov_info,const struct fi_info * user_info,uint32_t api_version)1159 static uint64_t ofi_get_info_caps(const struct fi_info *prov_info,
1160 const struct fi_info *user_info,
1161 uint32_t api_version)
1162 {
1163 int prov_mode, user_mode;
1164 uint64_t caps;
1165
1166 assert(user_info);
1167
1168 caps = ofi_get_caps(prov_info->caps, user_info->caps, prov_info->caps);
1169
1170 prov_mode = prov_info->domain_attr->mr_mode;
1171
1172 if (!ofi_rma_target_allowed(caps) ||
1173 !(prov_mode & OFI_MR_MODE_RMA_TARGET))
1174 return caps;
1175
1176 if (!user_info->domain_attr)
1177 goto trim_caps;
1178
1179 user_mode = user_info->domain_attr->mr_mode;
1180
1181 if ((FI_VERSION_LT(api_version, FI_VERSION(1,5)) &&
1182 (user_mode == FI_MR_UNSPEC)) ||
1183 (user_mode == FI_MR_BASIC) ||
1184 ((user_mode & prov_mode & OFI_MR_MODE_RMA_TARGET) ==
1185 (prov_mode & OFI_MR_MODE_RMA_TARGET)))
1186 return caps;
1187
1188 trim_caps:
1189 return caps & ~(FI_REMOTE_WRITE | FI_REMOTE_READ);
1190 }
1191
1192 /*
1193 * Alter the returned fi_info based on the user hints. We assume that
1194 * the hints have been validated and the starting fi_info is properly
1195 * configured by the provider.
1196 */
ofi_alter_info(struct fi_info * info,const struct fi_info * hints,uint32_t api_version)1197 void ofi_alter_info(struct fi_info *info, const struct fi_info *hints,
1198 uint32_t api_version)
1199 {
1200 if (!hints)
1201 return;
1202
1203 for (; info; info = info->next) {
1204 /* This should stay before call to fi_alter_domain_attr as
1205 * the checks depend on unmodified provider mr_mode attr */
1206 info->caps = ofi_get_info_caps(info, hints, api_version);
1207
1208 if ((info->domain_attr->mr_mode & FI_MR_LOCAL) &&
1209 (FI_VERSION_LT(api_version, FI_VERSION(1, 5)) ||
1210 (hints && hints->domain_attr &&
1211 (hints->domain_attr->mr_mode & (FI_MR_BASIC | FI_MR_SCALABLE)))))
1212 info->mode |= FI_LOCAL_MR;
1213
1214 info->handle = hints->handle;
1215
1216 fi_alter_domain_attr(info->domain_attr, hints->domain_attr,
1217 info->caps, api_version);
1218 fi_alter_ep_attr(info->ep_attr, hints->ep_attr, info->caps);
1219 fi_alter_rx_attr(info->rx_attr, hints->rx_attr, info->caps);
1220 fi_alter_tx_attr(info->tx_attr, hints->tx_attr, info->caps);
1221 }
1222 }
1223