/**
* Copyright (C) Mellanox Technologies Ltd. 2001-2015. ALL RIGHTS RESERVED.
* Copyright (c) UT-Battelle, LLC. 2014-2015. ALL RIGHTS RESERVED.
*
* See file LICENSE for terms.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "mm_md.h"
#include <ucs/debug/log.h>
#include <inttypes.h>
#include <limits.h>
ucs_config_field_t uct_mm_md_config_table[] = {
{"", "", NULL,
ucs_offsetof(uct_mm_md_config_t, super), UCS_CONFIG_TYPE_TABLE(uct_md_config_table)},
{"HUGETLB_MODE", "try",
"Enable using huge pages for internal buffers. "
"Possible values are:\n"
" y - Allocate memory using huge pages only.\n"
" n - Allocate memory using regular pages only.\n"
" try - Try to allocate memory using huge pages and if it fails, allocate regular pages.\n",
ucs_offsetof(uct_mm_md_config_t, hugetlb_mode), UCS_CONFIG_TYPE_TERNARY},
{NULL}
};
ucs_status_t uct_mm_query_md_resources(uct_component_t *component,
uct_md_resource_desc_t **resources_p,
unsigned *num_resources_p)
{
ucs_status_t status;
status = uct_mm_mdc_mapper_ops(component)->query();
switch (status) {
case UCS_OK:
return uct_md_query_single_md_resource(component, resources_p,
num_resources_p);
case UCS_ERR_UNSUPPORTED:
return uct_md_query_empty_md_resource(resources_p, num_resources_p);
default:
return status;
}
}
ucs_status_t uct_mm_seg_new(void *address, size_t length, uct_mm_seg_t **seg_p)
{
uct_mm_seg_t *seg;
seg = ucs_malloc(sizeof(*seg), "mm_seg");
if (seg == NULL) {
ucs_error("failed to allocate mm segment");
return UCS_ERR_NO_MEMORY;
}
seg->address = address;
seg->length = length;
seg->seg_id = 0;
*seg_p = seg;
return UCS_OK;
}
void uct_mm_md_query(uct_md_h md, uct_md_attr_t *md_attr, int support_alloc)
{
memset(md_attr, 0, sizeof(*md_attr));
md_attr->cap.flags = UCT_MD_FLAG_RKEY_PTR |
UCT_MD_FLAG_NEED_RKEY;
md_attr->cap.max_reg = 0;
md_attr->cap.max_alloc = 0;
md_attr->cap.access_mem_type = UCS_MEMORY_TYPE_HOST;
md_attr->cap.detect_mem_types = 0;
if (support_alloc) {
md_attr->cap.flags |= UCT_MD_FLAG_ALLOC | UCT_MD_FLAG_FIXED;
md_attr->cap.max_alloc = ULONG_MAX;
}
memset(&md_attr->local_cpus, 0xff, sizeof(md_attr->local_cpus));
}
ucs_status_t uct_mm_rkey_ptr(uct_component_t *component, uct_rkey_t rkey,
void *handle, uint64_t raddr, void **laddr_p)
{
/* rkey stores offset from the remote va */
*laddr_p = UCS_PTR_BYTE_OFFSET(raddr, (ptrdiff_t)rkey);
return UCS_OK;
}
ucs_status_t uct_mm_md_open(uct_component_t *component, const char *md_name,
const uct_md_config_t *config, uct_md_h *md_p)
{
uct_mm_component_t *mmc = ucs_derived_of(component, uct_mm_component_t);
ucs_status_t status;
uct_mm_md_t *md;
md = ucs_malloc(sizeof(*md), "uct_mm_md_t");
if (md == NULL) {
ucs_error("Failed to allocate memory for uct_mm_md_t");
status = UCS_ERR_NO_MEMORY;
goto err;
}
md->config = ucs_malloc(mmc->super.md_config.size, "mm_md config");
if (md->config == NULL) {
ucs_error("Failed to allocate memory for mm_md config");
status = UCS_ERR_NO_MEMORY;
goto err_free_mm_md;
}
status = ucs_config_parser_clone_opts(config, md->config,
mmc->super.md_config.table);
if (status != UCS_OK) {
ucs_error("Failed to clone opts");
goto err_free_mm_md_config;
}
md->super.ops = &mmc->md_ops->super;
md->super.component = &mmc->super;
md->iface_addr_len = mmc->md_ops->iface_addr_length(md);
/* cppcheck-suppress autoVariables */
*md_p = &md->super;
return UCS_OK;
err_free_mm_md_config:
ucs_free(md->config);
err_free_mm_md:
ucs_free(md);
err:
return status;
}
void uct_mm_md_close(uct_md_h md)
{
uct_mm_md_t *mm_md = ucs_derived_of(md, uct_mm_md_t);
ucs_config_parser_release_opts(mm_md->config,
md->component->md_config.table);
ucs_free(mm_md->config);
ucs_free(mm_md);
}