* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <stdlib.h>
#include <pthread.h>
#include "securec.h"
#include "urma_api.h"
#include "ascend_hal_error.h"
#include "uref.h"
#include "queue.h"
#include "que_compiler.h"
#include "dms_user_interface.h"
#include "queue_interface.h"
#include "que_urma.h"
#define QUE_URMA_MAX_DEVNUM MAX_DEVICE
struct que_urma_ctx {
unsigned int urma_devid;
urma_device_t *urma_dev[TRANS_TYPE_MAX];
urma_context_t *context[TRANS_TYPE_MAX];
uint32_t eid_index[TRANS_TYPE_MAX];
struct que_urma_token token_info[TRANS_TYPE_MAX];
urma_target_seg_t *tseg[TRANS_TYPE_MAX];
size_t page_size;
struct uref ref;
};
static struct que_urma_ctx *g_urma_ctx[QUE_URMA_MAX_DEVNUM] = {NULL};
static pthread_mutex_t g_urma_ctx_lock = PTHREAD_MUTEX_INITIALIZER;
static inline void que_urma_ctx_lock(void)
{
(void)pthread_mutex_lock(&g_urma_ctx_lock);
}
static inline void que_urma_ctx_unlock(void)
{
(void)pthread_mutex_unlock(&g_urma_ctx_lock);
}
static unsigned int que_devid_to_urma_devid(unsigned int devid)
{
return devid;
}
static struct que_urma_ctx *_que_urma_ctx_create(unsigned int urma_devid)
{
struct que_urma_ctx *urma_ctx = NULL;
urma_ctx = calloc(1, sizeof(struct que_urma_ctx));
if (que_unlikely(urma_ctx == NULL)) {
return NULL;
}
urma_ctx->page_size = (size_t)getpagesize();
urma_ctx->urma_devid = urma_devid;
uref_init(&urma_ctx->ref);
return urma_ctx;
}
static inline void _que_urma_ctx_destroy(struct que_urma_ctx *urma_ctx)
{
free(urma_ctx);
}
static int que_get_trans_num(void)
{
#ifdef DRV_HOST
return TRANS_HOST_MAX;
#else
return TRANS_TYPE_MAX;
#endif
}
static void que_urma_dev_eid_uninit(struct que_urma_ctx *urma_ctx)
{
int trans_type, trans_num;
trans_num = que_get_trans_num();
for (trans_type = TRANS_D2H_H2D; trans_type < trans_num; trans_type++) {
urma_ctx->urma_dev[trans_type] = NULL;
}
}
#ifndef EMU_ST
#ifndef DRV_HOST
#ifndef CFG_SOC_PLATFORM_910_96
STATIC int que_cmp_urma_eid(urma_eid_t *eid1, urma_eid_t *eid2)
{
int i;
for (i = 0; i < URMA_EID_SIZE; i++) {
if (eid1->raw[i] != eid2->raw[i]) {
return DRV_ERROR_INVALID_VALUE;
}
}
return DRV_ERROR_NONE;
}
static int que_get_ub_d2d_dev_info(unsigned int dev_id, struct dms_ub_dev_info *eid_info)
{
int ret;
urma_eid_t eid;
urma_eid_info_t *eid_list;
uint32_t eid_cnt, i;
urma_device_t *urma_dev = NULL;
struct dms_ub_d2d_eid d2d_eid = {0};
ret = dms_get_ub_d2d_eid(dev_id, &d2d_eid);
if (ret != DRV_ERROR_NONE) {
QUEUE_LOG_ERR("get ub d2d eid failed. (ret=%d, devid=%u)\n", ret, dev_id);
return ret;
}
ret = memcpy_s(&eid, sizeof(urma_eid_t), &d2d_eid.d2d_eid, sizeof(urma_eid_t));
if (ret != DRV_ERROR_NONE) {
QUEUE_LOG_ERR("memcpy_s failed. (ret=%d, devid=%u)\n", ret, dev_id);
return ret;
}
urma_dev = urma_get_device_by_eid(eid, URMA_TRANSPORT_UB);
if (urma_dev == NULL) {
QUEUE_LOG_ERR("urma_get_device_by_eid failed.(devid=%u)\n", dev_id);
return DRV_ERROR_NO_RESOURCES;
}
eid_list = urma_get_eid_list(urma_dev, &eid_cnt);
if (eid_list == NULL) {
QUEUE_LOG_ERR("urma_get_eid_list failed.(devid=%u)\n", dev_id);
return DRV_ERROR_NO_RESOURCES;
}
for (i = 0; i < eid_cnt; i++) {
if (que_cmp_urma_eid(&eid_list[i].eid, &eid) == 0) {
eid_info->eid_index[0] = eid_list[i].eid_index;
break;
}
}
if (i == eid_cnt) {
QUEUE_LOG_ERR("urma_dev find eid_index failed.(devid=%u; eid="EID_FMT")\n", dev_id, EID_ARGS(eid));
urma_free_eid_list(eid_list);
return DRV_ERROR_NO_RESOURCES;
}
eid_info->urma_dev[0] = (void *)urma_dev;
urma_free_eid_list(eid_list);
return DRV_ERROR_NONE;
}
#endif
#endif
#endif
static int que_urma_dev_eid_init(struct que_urma_ctx *urma_ctx)
{
int num, trans_num, ret = 0;
int trans_idx;
struct dms_ub_dev_info dev_info[TRANS_TYPE_MAX];
#ifndef EMU_ST
trans_num = que_get_trans_num();
ret = dms_get_ub_dev_info(urma_ctx->urma_devid, &dev_info[TRANS_D2H_H2D], &num);
if (que_unlikely((ret != 0) || (num == 0))) {
QUEUE_LOG_ERR("que dms get ub dev info failed.(dev_id=%u; ret=%d; num=%d)\n", urma_ctx->urma_devid, ret, num);
return ret;
}
#ifndef DRV_HOST
#if defined(CFG_SOC_PLATFORM_910_96)
dev_info[TRANS_D2D].urma_dev[0] = dev_info[TRANS_D2H_H2D].urma_dev[0];
dev_info[TRANS_D2D].eid_index[0] = dev_info[TRANS_D2H_H2D].eid_index[0];
#else
ret = que_get_ub_d2d_dev_info(urma_ctx->urma_devid, &dev_info[TRANS_D2D]);
#endif
if (que_unlikely(ret != 0)) {
QUEUE_LOG_ERR("que dms get ub d2d dev info failed.(dev_id=%u; ret=%d)\n", urma_ctx->urma_devid, ret);
return ret;
}
#endif
for (trans_idx = TRANS_D2H_H2D; trans_idx < trans_num; trans_idx++) {
urma_ctx->urma_dev[trans_idx] = dev_info[trans_idx].urma_dev[0];
urma_ctx->eid_index[trans_idx] = dev_info[trans_idx].eid_index[0];
}
#endif
return DRV_ERROR_NONE;
}
#ifndef EMU_ST
#ifndef DRV_HOST
static int que_register_share_urma_seg(struct que_urma_ctx *urma_ctx, int trans_idx)
{
urma_target_seg_t *tseg = NULL;
urma_seg_cfg_t seg_cfg = {0};
seg_cfg.flag.bs.token_policy = URMA_TOKEN_PLAIN_TEXT;
seg_cfg.flag.bs.cacheable = URMA_NON_CACHEABLE;
seg_cfg.flag.bs.access = URMA_ACCESS_READ | URMA_ACCESS_WRITE;
seg_cfg.flag.bs.reserved = 0;
seg_cfg.flag.bs.token_id_valid = 1;
seg_cfg.flag.bs.non_pin = 1;
seg_cfg.va = QUE_SP_VA_START;
seg_cfg.len = QUE_SP_VA_SIZE;
seg_cfg.token_value.token = urma_ctx->token_info[trans_idx].token.token;
seg_cfg.user_ctx = (uintptr_t)NULL;
seg_cfg.iova = 0;
seg_cfg.token_id = urma_ctx->token_info[trans_idx].token_id;
tseg = urma_register_seg(urma_ctx->context[trans_idx], &seg_cfg);
if (tseg == NULL) {
QUEUE_LOG_ERR("que share mem urma register seg failed. \n");
return DRV_ERROR_INNER_ERR;
}
urma_ctx->tseg[trans_idx] = tseg;
return DRV_ERROR_NONE;
}
static void que_unregister_share_urma_seg(urma_target_seg_t *tseg)
{
if (tseg == NULL) {
return;
}
(void)urma_unregister_seg(tseg);
}
#endif
#endif
static int que_urma_token_init(struct que_urma_ctx *urma_ctx)
{
int ret, trans_idx, trans_num;
unsigned int token_val;
urma_token_id_t *token_id[TRANS_TYPE_MAX] = {0};
trans_num = que_get_trans_num();
for(trans_idx = TRANS_D2H_H2D; trans_idx < trans_num; trans_idx++) {
token_id[trans_idx] = urma_alloc_token_id(urma_ctx->context[trans_idx]);
if (que_unlikely(token_id[trans_idx] == NULL)) {
goto cleanup;
}
}
#ifndef EMU_ST
ret = dms_get_token_val(urma_ctx->urma_devid, SHARED_TOKEN_VAL, &token_val);
if (ret != 0) {
QUEUE_LOG_ERR("Failed to get token_val. (ret=%d, devid=%u)\n", ret, urma_ctx->urma_devid);
goto cleanup;
}
#endif
for(trans_idx = TRANS_D2H_H2D; trans_idx < trans_num; trans_idx++) {
urma_ctx->token_info[trans_idx].token_id = token_id[trans_idx];
urma_ctx->token_info[trans_idx].token.token = token_val;
#ifndef EMU_ST
#ifndef DRV_HOST
ret = que_register_share_urma_seg(urma_ctx, trans_idx);
if (que_unlikely(ret != DRV_ERROR_NONE)) {
QUEUE_LOG_ERR("que register share urma seg failed. (ret=%d, devid=%u, trans_idx=%d)\n", ret, urma_ctx->urma_devid, trans_idx);
goto cleanup;
}
#endif
#endif
}
return DRV_ERROR_NONE;
cleanup:
for (trans_idx = TRANS_D2H_H2D; trans_idx < trans_num; trans_idx++) {
if (token_id[trans_idx] != NULL) {
urma_free_token_id(token_id[trans_idx]);
}
}
return DRV_ERROR_INNER_ERR;
}
static void que_urma_token_uninit(struct que_urma_ctx *urma_ctx)
{
int trans_idx, trans_num;
trans_num = que_get_trans_num();
for (trans_idx = TRANS_D2H_H2D; trans_idx < trans_num; trans_idx++) {
#ifndef EMU_ST
#ifndef DRV_HOST
que_unregister_share_urma_seg(urma_ctx->tseg[trans_idx]);
#endif
#endif
if (urma_ctx->token_info[trans_idx].token_id != NULL) {
urma_status_t status = urma_free_token_id(urma_ctx->token_info[trans_idx].token_id);
if (que_unlikely(status != URMA_SUCCESS)) {
QUEUE_LOG_WARN("urma free token id abnormal. (urma_devid=%u; trans_idx=%d; status=%d)\n", urma_ctx->urma_devid, trans_idx, status);
}
urma_ctx->token_info[trans_idx].token_id = NULL;
}
urma_ctx->token_info[trans_idx].token.token = 0;
}
return;
}
static int que_urma_context_init(struct que_urma_ctx *urma_ctx)
{
urma_context_t *context = NULL;
int trans_type, trans_num;
trans_num = que_get_trans_num();
for (trans_type = TRANS_D2H_H2D; trans_type < trans_num; trans_type++) {
context = urma_create_context(urma_ctx->urma_dev[trans_type], urma_ctx->eid_index[trans_type]);
if (que_unlikely(context == NULL)) {
QUEUE_LOG_ERR("urma context create fail. (urma_devid=%u; eid_index=%u)\n",
urma_ctx->urma_devid, urma_ctx->eid_index[trans_type]);
return DRV_ERROR_INNER_ERR;
}
urma_ctx->context[trans_type] = context;
}
return DRV_ERROR_NONE;
}
static void que_urma_context_uninit(struct que_urma_ctx *urma_ctx)
{
int trans_type, trans_num;
trans_num = que_get_trans_num();
for (trans_type = TRANS_D2H_H2D; trans_type < trans_num; trans_type++) {
urma_status_t status = urma_delete_context(urma_ctx->context[trans_type]);
if (que_unlikely(status != URMA_SUCCESS)) {
QUEUE_LOG_WARN("urma context delete abnormal. (urma_devid=%u; status=%d)\n", urma_ctx->urma_devid, status);
}
urma_ctx->context[trans_type] = NULL;
}
}
static int que_urma_ctx_init(struct que_urma_ctx *urma_ctx)
{
int ret;
ret = que_urma_dev_eid_init(urma_ctx);
if (que_unlikely(ret != DRV_ERROR_NONE)) {
QUEUE_LOG_ERR("urma dev and eid init fail. (ret=%d; urma_devid=%u)\n", ret, urma_ctx->urma_devid);
return ret;
}
ret = que_urma_context_init(urma_ctx);
if (que_unlikely(ret != DRV_ERROR_NONE)) {
QUEUE_LOG_ERR("urma context init fail. (ret=%d; urma_devid=%u)\n", ret, urma_ctx->urma_devid);
goto err_context_init;
}
ret = que_urma_token_init(urma_ctx);
if (que_unlikely(ret != DRV_ERROR_NONE)) {
QUEUE_LOG_ERR("urma token init fail. (ret=%d; urma_devid=%u)\n", ret, urma_ctx->urma_devid);
goto err_token_init;
}
return DRV_ERROR_NONE;
err_token_init:
que_urma_context_uninit(urma_ctx);
err_context_init:
que_urma_dev_eid_uninit(urma_ctx);
return ret;
}
static void que_urma_ctx_uninit(struct que_urma_ctx *urma_ctx)
{
que_urma_token_uninit(urma_ctx);
que_urma_context_uninit(urma_ctx);
que_urma_dev_eid_uninit(urma_ctx);
}
static int _que_urma_ctx_add(struct que_urma_ctx *urma_ctx)
{
if (que_unlikely(g_urma_ctx[urma_ctx->urma_devid] != NULL)) {
return DRV_ERROR_REPEATED_INIT;
}
g_urma_ctx[urma_ctx->urma_devid] = urma_ctx;
return DRV_ERROR_NONE;
}
static void _que_urma_ctx_del(struct que_urma_ctx *urma_ctx)
{
if (que_likely(g_urma_ctx[urma_ctx->urma_devid] == urma_ctx)) {
g_urma_ctx[urma_ctx->urma_devid] = NULL;
}
}
struct que_urma_ctx *que_urma_ctx_create(unsigned int urma_devid)
{
struct que_urma_ctx *urma_ctx = NULL;
int ret;
urma_ctx = _que_urma_ctx_create(urma_devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("urma ctx create fail. (urma_devid=%u)\n", urma_devid);
return NULL;
}
ret = que_urma_ctx_init(urma_ctx);
if (que_unlikely(ret != DRV_ERROR_NONE)) {
_que_urma_ctx_destroy(urma_ctx);
QUEUE_LOG_ERR("urma ctx init fail. (urma_devid=%u)\n", urma_devid);
return NULL;
}
ret = _que_urma_ctx_add(urma_ctx);
if (que_unlikely(ret != DRV_ERROR_NONE)) {
que_urma_ctx_uninit(urma_ctx);
_que_urma_ctx_destroy(urma_ctx);
return NULL;
}
return urma_ctx;
}
void que_urma_ctx_destroy(struct que_urma_ctx *urma_ctx)
{
_que_urma_ctx_del(urma_ctx);
que_urma_ctx_uninit(urma_ctx);
_que_urma_ctx_destroy(urma_ctx);
}
static inline struct que_urma_ctx *que_urma_ctx_find(unsigned int urma_devid)
{
return g_urma_ctx[urma_devid];
}
static void que_urma_ctx_release(struct uref *uref)
{
struct que_urma_ctx *urma_ctx = container_of(uref, struct que_urma_ctx, ref);
que_urma_ctx_destroy(urma_ctx);
}
static struct que_urma_ctx *que_urma_ctx_get(unsigned int devid)
{
struct que_urma_ctx *urma_ctx = NULL;
unsigned int urma_devid;
urma_devid = que_devid_to_urma_devid(devid);
if (que_unlikely(urma_devid >= QUE_URMA_MAX_DEVNUM)) {
QUEUE_LOG_ERR("devid to udmaid fail. (devid=%u; urma_devid=%u)\n", devid, urma_devid);
return NULL;
}
que_urma_ctx_lock();
urma_ctx = que_urma_ctx_find(urma_devid);
if (urma_ctx != NULL) {
if (uref_get_unless_zero(&urma_ctx->ref) == 0) {
que_urma_ctx_unlock();
return NULL;
}
} else {
urma_ctx = que_urma_ctx_find(urma_devid);
if (urma_ctx == NULL) {
urma_ctx = que_urma_ctx_create(urma_devid);
if (urma_ctx != NULL) {
if (uref_get_unless_zero(&urma_ctx->ref) == 0) {
que_urma_ctx_unlock();
return NULL;
}
}
} else {
if (uref_get_unless_zero(&urma_ctx->ref) == 0) {
que_urma_ctx_unlock();
return NULL;
}
}
}
que_urma_ctx_unlock();
return urma_ctx;
}
static void que_urma_ctx_put(struct que_urma_ctx *urma_ctx)
{
uref_put(&urma_ctx->ref, que_urma_ctx_release);
}
urma_target_seg_t *que_get_urma_ctx_tseg(unsigned int devid, unsigned int d2d_flag)
{
urma_target_seg_t *tseg = NULL;
struct que_urma_ctx *urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return NULL;
}
tseg = urma_ctx->tseg[d2d_flag];
que_urma_ctx_put(urma_ctx);
return tseg;
}
int que_fill_ctx_token(unsigned int devid, urma_token_t *token, unsigned int d2d_flag)
{
struct que_urma_ctx *urma_ctx = NULL;
urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return DRV_ERROR_INNER_ERR;
}
token->token = urma_ctx->token_info[d2d_flag].token.token;
que_urma_ctx_put(urma_ctx);
return DRV_ERROR_NONE;
}
int que_urma_token_alloc(unsigned int devid, struct que_urma_token *token_info, unsigned int d2d_flag)
{
struct que_urma_ctx *urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return DRV_ERROR_UNINIT;
}
urma_token_id_t *token_id = urma_alloc_token_id(urma_ctx->context[d2d_flag]);
if (que_unlikely(token_id == NULL)) {
que_urma_ctx_put(urma_ctx);
return DRV_ERROR_INNER_ERR;
}
token_info->token_id = token_id;
token_info->token.token = urma_ctx->token_info[d2d_flag].token.token;
que_urma_ctx_put(urma_ctx);
return DRV_ERROR_NONE;
}
void que_urma_token_free(unsigned int devid, struct que_urma_token *token_info)
{
if (token_info->token_id == NULL) {
token_info->token.token = 0;
return;
}
urma_status_t status = urma_free_token_id(token_info->token_id);
if (que_unlikely(status != URMA_SUCCESS)) {
QUEUE_LOG_WARN("urma free token id abnormal. (devid=%u; status=%d)\n", devid, status);
}
token_info->token_id = NULL;
token_info->token.token = 0;
return;
}
#ifndef EMU_ST
void que_urma_ctx_put_ex(unsigned int devid)
{
struct que_urma_ctx *urma_ctx = NULL;
unsigned int urma_devid;
urma_devid = que_devid_to_urma_devid(devid);
if (que_unlikely(urma_devid >= QUE_URMA_MAX_DEVNUM)) {
QUEUE_LOG_ERR("devid to udmaid fail. (devid=%u; urma_devid=%u)\n", devid, urma_devid);
return;
}
que_urma_ctx_lock();
urma_ctx = que_urma_ctx_find(urma_devid);
if (urma_ctx != NULL) {
que_urma_ctx_put(urma_ctx);
}
que_urma_ctx_unlock();
}
#endif
urma_jfce_t *que_urma_jfce_create(unsigned int devid, unsigned int d2d_flag)
{
struct que_urma_ctx *urma_ctx = NULL;
urma_jfce_t *jfce = NULL;
urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return NULL;
}
jfce = urma_create_jfce(urma_ctx->context[d2d_flag]);
que_urma_ctx_put(urma_ctx);
return jfce;
}
void que_urma_jfce_destroy(urma_jfce_t *jfce)
{
(void)urma_delete_jfce(jfce);
}
urma_jfc_t *que_urma_jfc_create(unsigned int devid, urma_jfc_cfg_t *cfg, unsigned int d2d_flag)
{
struct que_urma_ctx *urma_ctx = NULL;
urma_jfc_t *jfc = NULL;
urma_status_t status;
urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return NULL;
}
jfc = urma_create_jfc(urma_ctx->context[d2d_flag], cfg);
if (que_unlikely(jfc == NULL)) {
QUEUE_LOG_ERR("create jfc fail. (devid=%u)\n", devid);
goto err_create_jfc;
}
status = urma_rearm_jfc(jfc, false);
if (que_unlikely(status != URMA_SUCCESS)) {
QUEUE_LOG_ERR("rearm jfc fail. (status=%d; devid=%u)\n", status, devid);
goto err_rearm_jfc;
}
que_urma_ctx_put(urma_ctx);
return jfc;
err_rearm_jfc:
urma_delete_jfc(jfc);
err_create_jfc:
que_urma_ctx_put(urma_ctx);
return NULL;
}
void que_urma_jfc_destroy(urma_jfc_t *jfc)
{
(void)urma_delete_jfc(jfc);
}
urma_jfs_t *que_urma_jfs_create(unsigned int devid, urma_jfs_cfg_t *cfg, unsigned int d2d_flag)
{
struct que_urma_ctx *urma_ctx = NULL;
urma_jfs_t *jfs = NULL;
urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return NULL;
}
jfs = urma_create_jfs(urma_ctx->context[d2d_flag], cfg);
que_urma_ctx_put(urma_ctx);
if (que_unlikely(jfs == NULL)) {
QUEUE_LOG_ERR("urma create jfs fail. (devid=%u)\n", devid);
}
return jfs;
}
void que_urma_jfs_destroy(urma_jfs_t *jfs)
{
urma_status_t status = urma_delete_jfs(jfs);
if (que_unlikely(status != URMA_SUCCESS)) {
QUEUE_LOG_WARN("delete jfs abnormal. (status=%d)\n", status);
}
}
urma_jfr_t *que_urma_jfr_create(unsigned int devid, urma_jfr_cfg_t *cfg, unsigned int d2d_flag)
{
struct que_urma_ctx *urma_ctx = NULL;
urma_jfr_t *jfr = NULL;
urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return NULL;
}
cfg->token_value = urma_ctx->token_info[d2d_flag].token;
jfr = urma_create_jfr(urma_ctx->context[d2d_flag], cfg);
que_urma_ctx_put(urma_ctx);
if (que_unlikely(jfr == NULL)) {
QUEUE_LOG_ERR("urma create jfr fail. (devid=%u)\n", devid);
}
return jfr;
}
void que_urma_jfr_destroy(urma_jfr_t *jfr)
{
urma_status_t status = urma_delete_jfr(jfr);
if (que_unlikely(status != URMA_SUCCESS)) {
QUEUE_LOG_WARN("delete jfr abnormal. (status=%d)\n", status);
}
}
urma_target_jetty_t *que_jfr_import(unsigned int devid, urma_jfr_id_t *jfr_id, urma_token_t *token, unsigned int d2d_flag)
{
#ifdef SSAPI_USE_MAMI
uint32_t tp_cnt = 1;
urma_tp_info_t tpid_info = {0};
urma_status_t status;
urma_active_tp_cfg_t active_tp_cfg = {0};
#endif
urma_rjfr_t rjfr = {.jfr_id = *jfr_id, .trans_mode = URMA_TM_RM, .flag.bs.token_policy = URMA_TOKEN_PLAIN_TEXT};
struct que_urma_ctx *urma_ctx = NULL;
urma_target_jetty_t *tjetty = NULL;
urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return NULL;
}
#ifdef SSAPI_USE_MAMI
urma_get_tp_cfg_t tpid_cfg = {
.trans_mode = URMA_TM_RM,
.local_eid = urma_ctx->context[d2d_flag]->eid,
.peer_eid = jfr_id->eid,
.flag.bs.ctp = true,
};
status = urma_get_tp_list(urma_ctx->context[d2d_flag], &tpid_cfg, &tp_cnt, &tpid_info);
if ((status != 0) || (tp_cnt == 0)) {
QUEUE_LOG_ERR("urma get tp list failed (status=%d; tp_cnt=%u)\n", status, tp_cnt);
que_urma_ctx_put(urma_ctx);
return tjetty;
}
active_tp_cfg.tp_handle = tpid_info.tp_handle;
rjfr.tp_type = URMA_CTP;
tjetty = urma_import_jfr_ex(urma_ctx->context[d2d_flag], &rjfr, token, &active_tp_cfg);
#else
tjetty = urma_import_jfr(urma_ctx->context[d2d_flag], &rjfr, token);
#endif
que_urma_ctx_put(urma_ctx);
return tjetty;
}
void que_jfr_unimport(urma_target_jetty_t *tjetty)
{
urma_status_t status = urma_unimport_jfr(tjetty);
if (que_unlikely(status != URMA_SUCCESS)) {
QUEUE_LOG_WARN("unimport jfr abnormal. (status=%d)\n", status);
}
}
static void que_seg_cfg_pack_template(struct que_urma_ctx *urma_ctx,
unsigned long long va, unsigned long long size, unsigned int access, unsigned int pin_flag, urma_seg_cfg_t *seg_cfg, unsigned int d2d_flag)
{
static urma_reg_seg_flag_t flag = {0};
flag.bs.cacheable = URMA_NON_CACHEABLE;
flag.bs.access = access;
flag.bs.token_id_valid = URMA_TOKEN_ID_VALID;
flag.bs.token_policy = URMA_TOKEN_PLAIN_TEXT;
flag.bs.non_pin = ((pin_flag == QUE_PIN) ? 0 : 1);
seg_cfg->va = que_align_down(va, urma_ctx->page_size);
seg_cfg->len = que_align_up(va + size, urma_ctx->page_size) - seg_cfg->va;
seg_cfg->token_value = urma_ctx->token_info[d2d_flag].token;
seg_cfg->token_id = urma_ctx->token_info[d2d_flag].token_id;
seg_cfg->flag = flag;
}
static void que_update_seg_cfg_token(struct que_urma_token *token, urma_seg_cfg_t *seg_cfg)
{
if (que_unlikely(token == NULL)) {
return;
}
if (que_unlikely(token->token_id == NULL)) {
return;
}
seg_cfg->token_id = token->token_id;
seg_cfg->token_value = token->token;
}
urma_target_seg_t *que_pin_seg_create(unsigned int devid, unsigned long long va, unsigned long long size,
unsigned int access, struct que_urma_token *token, unsigned int d2d_flag)
{
struct que_urma_ctx *urma_ctx = NULL;
urma_target_seg_t *tseg = NULL;
urma_seg_cfg_t seg_cfg = {0};
urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return NULL;
}
que_seg_cfg_pack_template(urma_ctx, va, size, access, QUE_PIN, &seg_cfg, d2d_flag);
que_update_seg_cfg_token(token, &seg_cfg);
tseg = urma_register_seg(urma_ctx->context[d2d_flag], &seg_cfg);
que_urma_ctx_put(urma_ctx);
return tseg;
}
urma_target_seg_t *que_nonpin_seg_create(unsigned int devid, unsigned long long va, unsigned long long size,
unsigned int access, struct que_urma_token *token, unsigned int d2d_flag)
{
struct que_urma_ctx *urma_ctx = NULL;
urma_target_seg_t *tseg = NULL;
urma_seg_cfg_t seg_cfg = {0};
urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return NULL;
}
que_seg_cfg_pack_template(urma_ctx, va, size, access, QUE_NON_PIN, &seg_cfg, d2d_flag);
que_update_seg_cfg_token(token, &seg_cfg);
tseg = urma_register_seg(urma_ctx->context[d2d_flag], &seg_cfg);
que_urma_ctx_put(urma_ctx);
return tseg;
}
void que_seg_destroy(urma_target_seg_t *tseg)
{
(void)urma_unregister_seg(tseg);
}
urma_target_seg_t *que_seg_import(unsigned int devid, unsigned int d2d_flag, struct urma_seg *seg, unsigned int access, urma_token_t *token)
{
struct que_urma_ctx *urma_ctx = NULL;
urma_import_seg_flag_t flag = {
.bs.cacheable = URMA_NON_CACHEABLE,
.bs.access = access,
.bs.mapping = URMA_SEG_NOMAP,
.bs.reserved = 0
};
urma_target_seg_t *tseg = NULL;
urma_ctx = que_urma_ctx_get(devid);
if (que_unlikely(urma_ctx == NULL)) {
QUEUE_LOG_ERR("get urma ctx fail. (devid=%u)\n", devid);
return NULL;
}
tseg = urma_import_seg(urma_ctx->context[d2d_flag], seg, token, 0, flag);
que_urma_ctx_put(urma_ctx);
return tseg;
}
void que_seg_unimport(urma_target_seg_t *tseg)
{
urma_status_t status = urma_unimport_seg(tseg);
if (que_unlikely(status != URMA_SUCCESS)) {
QUEUE_LOG_WARN("unimport seg abnormal. (status=%d)\n", status);
}
}
struct que_jfs_rw_wr *que_jfs_rw_wr_create(struct que_jfs_rw_wr_attr *attr)
{
urma_sge_t *src_sge = NULL, *dst_sge = NULL;
struct que_jfs_rw_wr *rw_wr = NULL;
urma_jfs_wr_t *wr = NULL;
unsigned int i;
rw_wr = (struct que_jfs_rw_wr *)malloc(sizeof(struct que_jfs_rw_wr));
if (que_unlikely(rw_wr == NULL)) {
return NULL;
}
wr = calloc(attr->wr_num, sizeof(urma_jfs_wr_t));
if (que_unlikely(wr == NULL)) {
free(rw_wr);
return NULL;
}
src_sge = calloc(attr->wr_num, sizeof(urma_sge_t));
if (que_unlikely(src_sge == NULL)) {
free(wr);
free(rw_wr);
return NULL;
}
dst_sge = calloc(attr->wr_num, sizeof(urma_sge_t));
if (que_unlikely(dst_sge == NULL)) {
free(src_sge);
free(wr);
free(rw_wr);
return NULL;
}
for (i = 0; i < attr->wr_num; i++) {
wr[i].flag.bs.complete_enable = URMA_COMPLETE_ENABLE;
wr[i].opcode = attr->opcode;
wr[i].rw.src.sge = &src_sge[i];
wr[i].rw.src.num_sge = 1;
wr[i].rw.dst.sge = &dst_sge[i];
wr[i].rw.dst.num_sge = 1;
wr[i].next = NULL;
}
rw_wr->attr = *attr;
rw_wr->wr = wr;
return rw_wr;
}
void que_jfs_rw_wr_destroy(struct que_jfs_rw_wr *rw_wr)
{
if (rw_wr == NULL) {
return;
}
if (rw_wr->wr != NULL) {
if (rw_wr->wr[0].rw.src.sge != NULL) {
free(rw_wr->wr[0].rw.src.sge);
rw_wr->wr[0].rw.src.sge = NULL;
}
if (rw_wr->wr[0].rw.dst.sge != NULL) {
free(rw_wr->wr[0].rw.dst.sge);
rw_wr->wr[0].rw.dst.sge = NULL;
}
free(rw_wr->wr);
rw_wr->wr = NULL;
}
free(rw_wr);
}