1 /**
2 * Copyright (C) Mellanox Technologies Ltd. 2001-2015.  ALL RIGHTS RESERVED.
3 * Copyright (c) UT-Battelle, LLC. 2014-2015. ALL RIGHTS RESERVED.
4 *
5 * See file LICENSE for terms.
6 */
7 
8 #ifdef HAVE_CONFIG_H
9 #  include "config.h"
10 #endif
11 
12 #include "mm_md.h"
13 
14 #include <ucs/debug/log.h>
15 #include <inttypes.h>
16 #include <limits.h>
17 
18 
19 ucs_config_field_t uct_mm_md_config_table[] = {
20   {"", "", NULL,
21    ucs_offsetof(uct_mm_md_config_t, super), UCS_CONFIG_TYPE_TABLE(uct_md_config_table)},
22 
23   {"HUGETLB_MODE", "try",
24    "Enable using huge pages for internal buffers. "
25    "Possible values are:\n"
26    " y   - Allocate memory using huge pages only.\n"
27    " n   - Allocate memory using regular pages only.\n"
28    " try - Try to allocate memory using huge pages and if it fails, allocate regular pages.\n",
29    ucs_offsetof(uct_mm_md_config_t, hugetlb_mode), UCS_CONFIG_TYPE_TERNARY},
30 
31   {NULL}
32 };
33 
uct_mm_query_md_resources(uct_component_t * component,uct_md_resource_desc_t ** resources_p,unsigned * num_resources_p)34 ucs_status_t uct_mm_query_md_resources(uct_component_t *component,
35                                        uct_md_resource_desc_t **resources_p,
36                                        unsigned *num_resources_p)
37 {
38     ucs_status_t status;
39 
40     status = uct_mm_mdc_mapper_ops(component)->query();
41     switch (status) {
42     case UCS_OK:
43         return uct_md_query_single_md_resource(component, resources_p,
44                                                num_resources_p);
45     case UCS_ERR_UNSUPPORTED:
46         return uct_md_query_empty_md_resource(resources_p, num_resources_p);
47     default:
48         return status;
49     }
50 }
51 
uct_mm_seg_new(void * address,size_t length,uct_mm_seg_t ** seg_p)52 ucs_status_t uct_mm_seg_new(void *address, size_t length, uct_mm_seg_t **seg_p)
53 {
54     uct_mm_seg_t *seg;
55 
56     seg = ucs_malloc(sizeof(*seg), "mm_seg");
57     if (seg == NULL) {
58         ucs_error("failed to allocate mm segment");
59         return UCS_ERR_NO_MEMORY;
60     }
61 
62     seg->address = address;
63     seg->length  = length;
64     seg->seg_id  = 0;
65     *seg_p       = seg;
66     return UCS_OK;
67 }
68 
uct_mm_md_query(uct_md_h md,uct_md_attr_t * md_attr,int support_alloc)69 void uct_mm_md_query(uct_md_h md, uct_md_attr_t *md_attr, int support_alloc)
70 {
71     memset(md_attr, 0, sizeof(*md_attr));
72 
73     md_attr->cap.flags            = UCT_MD_FLAG_RKEY_PTR |
74                                     UCT_MD_FLAG_NEED_RKEY;
75     md_attr->cap.max_reg          = 0;
76     md_attr->cap.max_alloc        = 0;
77     md_attr->cap.access_mem_type  = UCS_MEMORY_TYPE_HOST;
78     md_attr->cap.detect_mem_types = 0;
79 
80     if (support_alloc) {
81         md_attr->cap.flags       |= UCT_MD_FLAG_ALLOC | UCT_MD_FLAG_FIXED;
82         md_attr->cap.max_alloc    = ULONG_MAX;
83     }
84 
85     memset(&md_attr->local_cpus, 0xff, sizeof(md_attr->local_cpus));
86 }
87 
uct_mm_rkey_ptr(uct_component_t * component,uct_rkey_t rkey,void * handle,uint64_t raddr,void ** laddr_p)88 ucs_status_t uct_mm_rkey_ptr(uct_component_t *component, uct_rkey_t rkey,
89                              void *handle, uint64_t raddr, void **laddr_p)
90 {
91     /* rkey stores offset from the remote va */
92     *laddr_p = UCS_PTR_BYTE_OFFSET(raddr, (ptrdiff_t)rkey);
93     return UCS_OK;
94 }
95 
uct_mm_md_open(uct_component_t * component,const char * md_name,const uct_md_config_t * config,uct_md_h * md_p)96 ucs_status_t uct_mm_md_open(uct_component_t *component, const char *md_name,
97                             const uct_md_config_t *config, uct_md_h *md_p)
98 {
99     uct_mm_component_t *mmc = ucs_derived_of(component, uct_mm_component_t);
100     ucs_status_t status;
101     uct_mm_md_t *md;
102 
103     md = ucs_malloc(sizeof(*md), "uct_mm_md_t");
104     if (md == NULL) {
105         ucs_error("Failed to allocate memory for uct_mm_md_t");
106         status = UCS_ERR_NO_MEMORY;
107         goto err;
108     }
109 
110     md->config = ucs_malloc(mmc->super.md_config.size, "mm_md config");
111     if (md->config == NULL) {
112         ucs_error("Failed to allocate memory for mm_md config");
113         status = UCS_ERR_NO_MEMORY;
114         goto err_free_mm_md;
115     }
116 
117     status = ucs_config_parser_clone_opts(config, md->config,
118                                           mmc->super.md_config.table);
119     if (status != UCS_OK) {
120         ucs_error("Failed to clone opts");
121         goto err_free_mm_md_config;
122     }
123 
124     md->super.ops       = &mmc->md_ops->super;
125     md->super.component = &mmc->super;
126     md->iface_addr_len  = mmc->md_ops->iface_addr_length(md);
127 
128     /* cppcheck-suppress autoVariables */
129     *md_p = &md->super;
130     return UCS_OK;
131 
132 err_free_mm_md_config:
133     ucs_free(md->config);
134 err_free_mm_md:
135     ucs_free(md);
136 err:
137     return status;
138 }
139 
uct_mm_md_close(uct_md_h md)140 void uct_mm_md_close(uct_md_h md)
141 {
142     uct_mm_md_t *mm_md = ucs_derived_of(md, uct_mm_md_t);
143 
144     ucs_config_parser_release_opts(mm_md->config,
145                                    md->component->md_config.table);
146     ucs_free(mm_md->config);
147     ucs_free(mm_md);
148 }
149