* 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.
*/
#ifndef UT_TEST
#include "prof_adapt_h2d.h"
#include "prof_adapt.h"
#include "prof_buff.h"
#include "prof_event_master.h"
#include "prof_urma.h"
drvError_t prof_urma_kernel_get_channels(uint32_t dev_id, struct prof_channel_list *channels)
{
return prof_urma_get_channels(dev_id, channels);
}
struct prof_urma_chan_priv {
uint8_t *buff;
struct prof_urma_chan_info *urma_chan_info;
};
static drvError_t prof_urma_chan_init(uint32_t dev_id, uint32_t chan_id, bool event_flag, char **priv)
{
struct prof_urma_chan_priv *chan_priv = NULL;
drvError_t ret;
chan_priv = (struct prof_urma_chan_priv *)malloc(sizeof(struct prof_urma_chan_priv));
if (chan_priv == NULL) {
PROF_ERR("Failed to alloc chan_priv. (dev_id=%u, chan_id=%u)\n", dev_id, chan_id);
return DRV_ERROR_MALLOC_FAIL;
}
chan_priv->urma_chan_info = prof_urma_chan_info_creat(dev_id, chan_id);
if (chan_priv->urma_chan_info == NULL) {
free(chan_priv);
PROF_ERR("Failed to create urma_info. (dev_id=%u, dev_id=%u)\n", dev_id, chan_id);
return DRV_ERROR_PARA_ERROR;
}
ret = prof_buff_init(chan_id, &chan_priv->buff);
if (ret != DRV_ERROR_NONE) {
prof_urma_chan_info_destroy(chan_priv->urma_chan_info);
free(chan_priv);
PROF_ERR("Failed to init buff. (dev_id=%u, dev_id=%u)\n", dev_id, chan_id);
return ret;
}
*priv = (char *)chan_priv;
return DRV_ERROR_NONE;
}
static void prof_urma_chan_uninit(char **priv)
{
struct prof_urma_chan_priv *chan_priv = (struct prof_urma_chan_priv *)(*priv);
prof_buff_uninit(&chan_priv->buff);
prof_urma_chan_info_destroy(chan_priv->urma_chan_info);
free(chan_priv);
*priv = NULL;
}
static drvError_t prof_urma_chan_start(uint32_t dev_id, uint32_t chan_id, struct prof_user_start_para *para, char *priv)
{
struct prof_urma_chan_priv *chan_priv = (struct prof_urma_chan_priv *)priv;
struct prof_urma_start_para urma_start_para = {0};
struct prof_user_stop_para stop_para = {0};
drvError_t ret;
urma_start_para.data_buff_addr = (uint64_t)(uintptr_t)prof_buff_get_buf_addr(chan_priv->buff);
urma_start_para.data_buff_len = prof_buff_get_buf_size(chan_priv->buff);
urma_start_para.rptr_addr = (uint64_t)(uintptr_t)prof_buff_get_readptr_addr(chan_priv->buff);
urma_start_para.rptr_size = prof_buff_get_readptr_size(chan_priv->buff);
ret = prof_urma_start(dev_id, chan_id, para, &urma_start_para, chan_priv->urma_chan_info);
if (ret != DRV_ERROR_NONE) {
PROF_ERR("Failed to start prof by urma. (dev_id=%u, chan_id=%u, ret=%d)\n", dev_id, chan_id, (int)ret);
return ret;
}
if (para->remote_pid != 0) {
ret = prof_event_start(dev_id, chan_id, para);
if (ret != DRV_ERROR_NONE) {
stop_para.remote_pid = para->remote_pid;
(void)prof_urma_stop(dev_id, chan_id, &stop_para, chan_priv->urma_chan_info);
PROF_ERR("Failed to send start event. (devid=%u, chan_id=%u, ret=%d)\n", dev_id, chan_id, (int)ret);
return ret;
}
}
return DRV_ERROR_NONE;
}
static drvError_t prof_urma_chan_stop(uint32_t dev_id, uint32_t chan_id, struct prof_user_stop_para *para, char *priv)
{
struct prof_urma_chan_priv *chan_priv = (struct prof_urma_chan_priv *)priv;
drvError_t ret;
if (para->remote_pid != 0) {
ret = prof_event_stop(dev_id, chan_id, para);
if (ret != DRV_ERROR_NONE) {
PROF_ERR("Failed to send stop event. (devid=%u, chan_id=%u, ret=%d)\n", dev_id, chan_id, (int)ret);
return ret;
}
}
ret = prof_urma_stop(dev_id, chan_id, para, chan_priv->urma_chan_info);
prof_buff_wait_read_empty(chan_priv->buff, dev_id, chan_id);
return DRV_ERROR_NONE;
}
static drvError_t prof_urma_chan_flush(uint32_t dev_id, uint32_t chan_id, uint32_t *data_len, char *priv)
{
struct prof_urma_chan_priv *chan_priv = (struct prof_urma_chan_priv *)priv;
drvError_t ret;
ret = prof_urma_flush(dev_id, chan_id);
if (ret != DRV_ERROR_NONE) {
return ret;
}
*data_len = prof_buff_get_data_len(chan_priv->buff);
return DRV_ERROR_NONE;
}
static int prof_urma_chan_read(uint32_t dev_id, uint32_t chan_id, prof_user_read_para_t *read_para, char *priv)
{
struct prof_urma_chan_priv *chan_priv = (struct prof_urma_chan_priv *)priv;
drvError_t ret;
int read_len;
read_len = prof_buff_read(chan_priv->buff, read_para->out_buf, read_para->buf_size);
if (read_len <= 0) {
return read_len;
}
if (read_para->write_rptr_flag == false) {
PROF_WARN("The channel is not ready yet, don't write remote rptr. (dev_id=%u, chan_id=%u)\n", dev_id, chan_id);
return read_len;
}
ret = prof_urma_write_remote_r_ptr(dev_id, chan_id, chan_priv->urma_chan_info);
if (ret != DRV_ERROR_NONE) {
PROF_ERR("Failed to write remote r_ptr. (dev_id=%u, chan_id=%u, ret=%d)\n", dev_id, chan_id, (int)ret);
}
return read_len;
}
static drvError_t prof_urma_chan_query(uint32_t dev_id, uint32_t chan_id, uint32_t *avail_len, char *priv)
{
return DRV_ERROR_NOT_SUPPORT;
}
static drvError_t prof_urma_chan_report(uint32_t dev_id, uint32_t chan_id, void *data, uint32_t data_len, char *priv)
{
struct prof_urma_chan_priv *chan_priv = (struct prof_urma_chan_priv *)priv;
struct prof_adapt_core_notifier *notifier = prof_adapt_get_notifier();
struct prof_urma_chan_info *urma_chan_info = NULL;
uint32_t new_wptr = *((uint32_t *)data);
uint32_t old_wptr;
old_wptr = prof_buff_get_writeptr(chan_priv->buff);
if (new_wptr != old_wptr) {
prof_buff_update_writeptr(chan_priv->buff, new_wptr);
notifier->poll_report(dev_id, chan_id);
}
urma_chan_info = chan_priv->urma_chan_info;
return prof_urma_post_recv(urma_chan_info, 1);
}
static struct prof_chan_ops prof_urma_chan_ops = {
.init = prof_urma_chan_init,
.uninit = prof_urma_chan_uninit,
.start = prof_urma_chan_start,
.stop = prof_urma_chan_stop,
.flush = prof_urma_chan_flush,
.read = prof_urma_chan_read,
.query = prof_urma_chan_query,
.report = prof_urma_chan_report,
};
drvError_t prof_urma_get_chan_ops(struct prof_chan_ops **ops)
{
*ops = &prof_urma_chan_ops;
return DRV_ERROR_NONE;
}
STATIC void __attribute__((constructor)) prof_urma_h2d_register(void)
{
struct prof_h2d_ops urma_ops = {
.get_channels = prof_urma_kernel_get_channels,
.get_chan_ops = prof_urma_get_chan_ops,
};
prof_h2d_regiser_urma_ops(&urma_ops);
}
#else
int prof_adapt_urma_ut_test(void)
{
return 0;
}
#endif