* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ka_list_pub.h"
#include "ka_memory_pub.h"
#include "ka_system_pub.h"
#include "ka_driver_pub.h"
#include "hdcdrv_cmd.h"
#include "hdcdrv_sysfs.h"
#include "hdcdrv_cmd_ioctl.h"
#include "hdcdrv_cmd_msg.h"
#ifdef DRV_UT
#define STATIC
#else
#define STATIC static
#endif
#define HDC_DFX_LIST_SESSION 1
#define HDC_DFX_NOT_LIST_SESSION 0
u32 g_chan_id = 0;
u32 g_dev_id = 0;
u32 g_fid = 0;
u32 g_session_fd = 0;
u32 g_server_type = 0;
static const char *g_hdc_ctrl_msg_status_str[HDCDRV_LINK_CTRL_MSG_STATUS_MAX] = {
"send_succ ",
"send_fail ",
"recv_succ ",
"recv_fail ",
"wait_succ ",
"wait_timeout"
};
STATIC void hdcdrv_add_stat(struct hdcdrv_stats *stat_all, const struct hdcdrv_stats *stat)
{
stat_all->tx += stat->tx;
stat_all->tx_bytes += stat->tx_bytes;
stat_all->rx += stat->rx;
stat_all->rx_bytes += stat->rx_bytes;
stat_all->tx_finish += stat->tx_finish;
stat_all->tx_full += stat->tx_full;
stat_all->tx_fail += stat->tx_fail;
stat_all->rx_fail += stat->rx_fail;
stat_all->rx_full += stat->rx_full;
stat_all->rx_total += stat->rx_total;
stat_all->alloc_mem_err += stat->alloc_mem_err;
}
STATIC int hdcdrv_get_dev_check(const struct hdcdrv_cmd_get_stat *cmd)
{
if ((cmd->dev_id >= hdcdrv_get_max_support_dev()) || (cmd->dev_id < 0)) {
hdcdrv_err("Input parameter is error. (dev_id=%d)\n", cmd->dev_id);
return HDCDRV_PARA_ERR;
}
if (cmd->outbuf == NULL) {
hdcdrv_err("Input parameter is error. (dev_id=%d)\n", cmd->dev_id);
return HDCDRV_PARA_ERR;
}
return HDCDRV_OK;
}
STATIC void hdcdrv_get_mem_pool_stat(struct hdcdrv_dev *hdc_dev, struct hdcdrv_cmd_stat_dev_service *stat)
{
struct hdcdrv_mem_info *mem_info = NULL;
struct hdcdrv_mem_pool *mem_pool = NULL;
int i;
for (i = 0; i < HDCDRV_MEM_POOL_TYPE_NUM; i++) {
if (i == HDCDRV_MEM_POOL_TYPE_TX) {
mem_info = &stat->tx_mem_info;
} else {
mem_info = &stat->rx_mem_info;
}
mem_pool = &hdc_dev->huge_mem_pool[i];
#ifdef CFG_FEATURE_MIRROR
mem_info->huge_pool_size = HDCDRV_HUGE_PAGE_NUM * HDCDRV_PAGE_BLOCK_NUM;
mem_info->huge_pool_remain_size = (unsigned int)(mem_info->huge_pool_size - mem_pool->used_block_all);
#else
mem_info->huge_pool_size = mem_pool->size;
mem_info->huge_pool_remain_size = (unsigned int)(mem_pool->tail - mem_pool->head);
#endif
mem_pool = &hdc_dev->small_mem_pool[i];
mem_info->small_pool_size = mem_pool->size;
mem_info->small_pool_remain_size = (unsigned int)(mem_pool->tail - mem_pool->head);
}
}
STATIC void hdcdrv_fill_dev_stat(const struct hdcdrv_cmd_get_stat *cmd, struct hdcdrv_cmd_stat_dev_service *stat)
{
int i, j;
int status;
struct hdcdrv_service *serv = NULL;
#ifdef CFG_FEATURE_VFIO
struct vhdch_vdev *hdc_dev = &hdc_ctrl->vdev[cmd->dev_id][cmd->fid];
stat->s_brief.cur_alloc_long_session = hdc_dev->cur_alloc_long_session;
stat->s_brief.cur_alloc_short_session = hdc_dev->cur_alloc_short_session;
#else
struct hdcdrv_dev *hdc_dev = &hdc_ctrl->devices[cmd->dev_id];
#endif
for (j = 0; j < HDCDRV_SUPPORT_MAX_SERVICE; j++) {
if ((cmd->service_type != -1) && (cmd->service_type != j)) {
continue;
}
serv = &hdc_dev->service[j];
stat->s_brief.accept_num += (int)serv->service_stat.accept_session_num;
stat->s_brief.connect_num += (int)serv->service_stat.connect_session_num;
stat->s_brief.close_num += (int)serv->service_stat.close_session_num;
hdcdrv_add_stat(&stat->stat, &serv->data_stat);
}
for (i = 0; i < HDCDRV_REAL_MAX_SESSION; i++) {
status = hdcdrv_get_session_status(&hdc_ctrl->sessions[i]);
if (status == HDCDRV_SESSION_STATUS_IDLE) {
stat->s_brief.total_idle_session_num++;
}
if (hdc_ctrl->sessions[i].dev_id != cmd->dev_id) {
continue;
}
if ((cmd->vf_flag == 1) && (hdc_ctrl->sessions[i].local_fid != cmd->fid)) {
continue;
}
if (status == HDCDRV_SESSION_STATUS_CONN) {
stat->s_brief.active_list[stat->s_brief.active_num++] = i;
} else if (status == HDCDRV_SESSION_STATUS_REMOTE_CLOSED) {
stat->s_brief.remote_close_list[stat->s_brief.remote_close_num++] = i;
} else if (status == HDCDRV_SESSION_STATUS_IDLE) {
stat->s_brief.idle_list[stat->s_brief.idle_num++] = i;
}
}
}
STATIC struct hdcdrv_cmd_stat_dev_service* hdcdrv_alloc_stat_list(void)
{
struct hdcdrv_cmd_stat_dev_service *stat = NULL;
stat = (struct hdcdrv_cmd_stat_dev_service *)hdcdrv_kzalloc(sizeof(struct hdcdrv_cmd_stat_dev_service),
KA_GFP_KERNEL | __KA_GFP_ACCOUNT, KA_SUB_MODULE_TYPE_4);
if (stat == NULL) {
goto stat_alloc_fail;
}
stat->s_brief.active_list = (int*)hdcdrv_kvmalloc(sizeof(int) * (u64)HDCDRV_REAL_MAX_SESSION, KA_SUB_MODULE_TYPE_4);
if (stat->s_brief.active_list == NULL) {
goto active_alloc_fail;
}
(void)memset_s(stat->s_brief.active_list, sizeof(int) * (u64)HDCDRV_REAL_MAX_SESSION, 0,
sizeof(int) * (u64)HDCDRV_REAL_MAX_SESSION);
stat->s_brief.remote_close_list = (int*)hdcdrv_kvmalloc(sizeof(int) * (u64)HDCDRV_REAL_MAX_SESSION,
KA_SUB_MODULE_TYPE_4);
if (stat->s_brief.remote_close_list == NULL) {
goto remote_alloc_fail;
}
(void)memset_s(stat->s_brief.remote_close_list, sizeof(int) * (u64)HDCDRV_REAL_MAX_SESSION, 0,
sizeof(int) * (u64)HDCDRV_REAL_MAX_SESSION);
stat->s_brief.idle_list = (int*)hdcdrv_kvmalloc(sizeof(int) * (u64)HDCDRV_REAL_MAX_SESSION, KA_SUB_MODULE_TYPE_4);
if (stat->s_brief.idle_list == NULL) {
goto idle_alloc_fail;
}
(void)memset_s(stat->s_brief.idle_list, sizeof(int) * (u64)HDCDRV_REAL_MAX_SESSION, 0,
sizeof(int) * (u64)HDCDRV_REAL_MAX_SESSION);
return stat;
idle_alloc_fail:
hdcdrv_kvfree((void **)&stat->s_brief.remote_close_list, KA_SUB_MODULE_TYPE_4);
stat->s_brief.remote_close_list = NULL;
remote_alloc_fail:
hdcdrv_kvfree((void **)&stat->s_brief.active_list, KA_SUB_MODULE_TYPE_4);
stat->s_brief.active_list = NULL;
active_alloc_fail:
hdcdrv_kfree(stat, KA_SUB_MODULE_TYPE_4);
stat = NULL;
stat_alloc_fail:
return NULL;
}
STATIC void hdcdrv_free_stat_list(struct hdcdrv_cmd_stat_dev_service *stat)
{
hdcdrv_kvfree((void **)&stat->s_brief.idle_list, KA_SUB_MODULE_TYPE_4);
stat->s_brief.idle_list = NULL;
hdcdrv_kvfree((void **)&stat->s_brief.remote_close_list, KA_SUB_MODULE_TYPE_4);
stat->s_brief.remote_close_list = NULL;
hdcdrv_kvfree((void **)&stat->s_brief.active_list, KA_SUB_MODULE_TYPE_4);
stat->s_brief.active_list = NULL;
hdcdrv_kfree(stat, KA_SUB_MODULE_TYPE_4);
}
STATIC long hdcdrv_get_dev_stat(struct hdcdrv_cmd_get_stat *cmd)
{
struct hdcdrv_cmd_stat_dev_service *stat = NULL;
struct hdcdrv_dev *hdc_dev = NULL;
if (hdcdrv_get_dev_check(cmd) != HDCDRV_OK) {
hdcdrv_err("Calling hdcdrv_get_dev_check failed. (dev_id=%d)\n", cmd->dev_id);
return HDCDRV_PARA_ERR;
}
hdc_dev = &hdc_ctrl->devices[cmd->dev_id];
if (hdc_dev->valid != HDCDRV_VALID) {
hdcdrv_err("Device ID is invalid. (dev_id=%d)\n", cmd->dev_id);
return HDCDRV_PARA_ERR;
}
stat = cmd->outbuf;
hdcdrv_fill_dev_stat(cmd, stat);
hdcdrv_get_mem_pool_stat(hdc_dev, stat);
return HDCDRV_OK;
}
STATIC void hdcdrv_fill_service_stat(const struct hdcdrv_cmd_get_stat *cmd, struct hdcdrv_cmd_stat_dev_service *stat)
{
int i, j;
int status;
struct hdcdrv_service *serv = NULL;
for (j = 0; j < hdcdrv_get_max_support_dev(); j++) {
if (hdc_ctrl->devices[j].valid != HDCDRV_VALID) {
continue;
}
serv = &hdc_ctrl->devices[j].service[cmd->service_type];
stat->s_brief.accept_num += (int)serv->service_stat.accept_session_num;
stat->s_brief.connect_num += (int)serv->service_stat.connect_session_num;
stat->s_brief.close_num += (int)serv->service_stat.close_session_num;
hdcdrv_add_stat(&stat->stat, &serv->data_stat);
}
for (i = 0; i < HDCDRV_REAL_MAX_SESSION; i++) {
if (cmd->service_type != hdc_ctrl->sessions[i].service_type) {
continue;
}
status = hdcdrv_get_session_status(&hdc_ctrl->sessions[i]);
if (status == HDCDRV_SESSION_STATUS_CONN) {
stat->s_brief.active_list[stat->s_brief.active_num++] = i;
} else if (status == HDCDRV_SESSION_STATUS_REMOTE_CLOSED) {
stat->s_brief.remote_close_list[stat->s_brief.remote_close_num++] = i;
} else if ((status == HDCDRV_SESSION_STATUS_IDLE) && (cmd->service_type != 0)) {
stat->s_brief.idle_list[stat->s_brief.idle_num++] = i;
} else {
continue;
}
}
}
STATIC long hdcdrv_get_service_stat(const struct hdcdrv_cmd_get_stat *cmd)
{
struct hdcdrv_cmd_stat_dev_service *stat = NULL;
if ((cmd->service_type >= HDCDRV_SUPPORT_MAX_SERVICE) || (cmd->service_type < 0) ||
(cmd->outbuf == NULL)) {
hdcdrv_err("Input parameter is error. (service_type=%d)\n", cmd->service_type);
return HDCDRV_PARA_ERR;
}
stat = cmd->outbuf;
hdcdrv_fill_service_stat(cmd, stat);
return HDCDRV_OK;
}
STATIC long hdcdrv_get_chan_stat(struct hdcdrv_cmd_get_stat *cmd)
{
struct hdcdrv_cmd_stat_chan stat;
struct hdcdrv_dev *hdc_dev = NULL;
struct hdcdrv_msg_chan *msg_chan = NULL;
int chan_id = cmd->chan_id;
int dev_id = cmd->dev_id;
if (dev_id == HDCDRV_INVALID_VALUE) {
dev_id = 0;
}
if ((dev_id >= hdcdrv_get_max_support_dev()) || (dev_id < 0) || (cmd->outbuf == NULL)) {
hdcdrv_err("Input parameter is error. (dev_id=%d)\n", dev_id);
return HDCDRV_PARA_ERR;
}
hdc_dev = &hdc_ctrl->devices[dev_id];
if ((chan_id >= hdc_dev->msg_chan_cnt) || (chan_id < 0)) {
hdcdrv_err("chan_id is illegal. (dev=%u; chan_id=%d; msg_chan_num=%d)\n",
hdc_dev->dev_id, chan_id, hdc_dev->msg_chan_cnt);
return HDCDRV_PARA_ERR;
}
msg_chan = hdc_dev->msg_chan[chan_id];
if (msg_chan == NULL) {
hdcdrv_err("Calling msg_chan is null.\n");
return HDCDRV_SAFE_MEM_OP_FAIL;
}
if (memset_s((void *)&stat, sizeof(stat), 0, sizeof(stat)) != EOK) {
hdcdrv_err("Calling memset_s failed.\n");
return HDCDRV_SAFE_MEM_OP_FAIL;
}
stat.stat = msg_chan->stat;
stat.dbg_stat = msg_chan->dbg_stat;
stat.dma_head = msg_chan->dma_head;
stat.rx_head = msg_chan->rx_head;
stat.w_sq_head = msg_chan->sq_head;
stat.submit_dma_head = msg_chan->submit_dma_head;
(void)hdcdrv_get_w_sq_desc(msg_chan->chan, (u32 *)(&stat.w_sq_tail));
(void)hdcdrv_get_r_sq_desc(msg_chan->chan, (u32 *)(&stat.r_sq_head));
if (memcpy_s(cmd->outbuf, sizeof(struct hdcdrv_cmd_stat_chan), &stat,
sizeof(struct hdcdrv_cmd_stat_chan)) != EOK) {
hdcdrv_err("Calling memcpy_s failed.\n");
return HDCDRV_ERR;
}
return HDCDRV_OK;
}
STATIC long hdcdrv_get_session_stat(const struct hdcdrv_cmd_get_stat *cmd)
{
struct hdcdrv_cmd_stat_session stat;
struct hdcdrv_session *session = NULL;
struct hdcdrv_session_fast_rx *fast_rx = NULL;
int session_fd = cmd->session;
if ((session_fd >= HDCDRV_REAL_MAX_SESSION) || (session_fd < 0) || (cmd->outbuf == NULL)) {
hdcdrv_err("Input parameter is error. (session_fd=%d)\n", session_fd);
return HDCDRV_PARA_ERR;
}
session = &hdc_ctrl->sessions[session_fd];
fast_rx = &hdc_ctrl->sessions[session_fd].fast_rx;
if (memset_s((void *)&stat, sizeof(stat), 0, sizeof(stat)) != EOK) {
hdcdrv_err("Calling memset_s failed.\n");
return HDCDRV_SAFE_MEM_OP_FAIL;
}
stat.status = hdcdrv_get_session_status(session);
stat.local_session = session->local_session_fd;
stat.remote_session = session->remote_session_fd;
stat.dev_id = session->dev_id;
stat.service_type = session->service_type;
stat.chan_id = (int)session->chan_id;
stat.fast_chan_id = (int)session->fast_chan_id;
if (fast_rx != NULL) {
stat.pkts_in_fast_list = (fast_rx->tail + HDCDRV_BUF_MAX_CNT - fast_rx->head) % HDCDRV_BUF_MAX_CNT;
}
stat.pkts_in_list = (session->normal_rx.tail + HDCDRV_SESSION_RX_LIST_MAX_PKT - session->normal_rx.head) %
HDCDRV_SESSION_RX_LIST_MAX_PKT;
stat.stat = session->stat;
stat.remote_close_state = session->remote_close_state;
stat.local_close_state = session->local_close_state;
stat.local_fid = session->local_fid;
stat.container_id = session->container_id;
stat.create_pid = session->create_pid;
stat.peer_create_pid = session->peer_create_pid;
stat.owner_pid = session->owner_pid;
stat.timeout.send_timeout = ka_system_jiffies_to_msecs(session->timeout_jiffies.send_timeout);
stat.timeout.fast_send_timeout = ka_system_jiffies_to_msecs(session->timeout_jiffies.fast_send_timeout);
stat.dbg_stat = session->dbg_stat;
if (memcpy_s(cmd->outbuf, sizeof(struct hdcdrv_cmd_stat_session), &stat,
sizeof(struct hdcdrv_cmd_stat_session)) != EOK) {
hdcdrv_err("Calling memcpy_s failed.\n");
return HDCDRV_ERR;
}
return HDCDRV_OK;
}
STATIC ssize_t hdcdrv_fill_buf_mem_info(char *buf, u32 buf_len, const struct hdcdrv_mem_info* mem_info)
{
int ret;
ssize_t offset = 0;
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\tHuge mem pool's total num: %u, remain num: %u\n"
"\tSmall mem pool's total num: %u, remain num: %u\n\n", mem_info->huge_pool_size,
mem_info->huge_pool_remain_size, mem_info->small_pool_size, mem_info->small_pool_remain_size);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_fill_buf_session_brief(char *buf, u32 buf_len,
const struct hdcdrv_cmd_stat_session_brief *s_brief, int list_session_flag)
{
int ret, i;
ssize_t offset = 0;
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\tTotal session number: %d\t shared device num: %d\t total_idle_session_num: %d\n"
"\tTotal active session number: %d\n",
(int)HDCDRV_REAL_MAX_SESSION, (int)hdcdrv_dev_num,
s_brief->total_idle_session_num, s_brief->active_num);
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\n\tTotal remote closed session number: %d\n", s_brief->remote_close_num);
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\n\tTotal idle session number: %d\n", s_brief->idle_num);
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\n\tAccept session: %d, Connect session: %d, Close session: %d\n",
s_brief->accept_num, s_brief->connect_num, s_brief->close_num);
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\tcurrent_alloc_long_session: %d, current_alloc_short_session: %d\n\n",
s_brief->cur_alloc_long_session, s_brief->cur_alloc_short_session);
if (ret >= 0) {
offset += ret;
}
if (!list_session_flag) {
return offset;
}
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\n\tactive session list: ");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < s_brief->active_num; i++) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"%d ", s_brief->active_list[i]);
if (ret >= 0) {
offset += ret;
}
}
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\n\tremote closed session list: ");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < s_brief->remote_close_num; i++) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"%d ", s_brief->remote_close_list[i]);
if (ret >= 0) {
offset += ret;
}
}
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\n");
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_fill_buf_tx_rx(char *buf, u32 buf_len, const struct hdcdrv_stats *stat,
enum hdc_dfx_print_type type)
{
int ret = 0;
ssize_t offset = 0;
if (type == HDC_DFX_PRINT_IN_SYSFS) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\tTx packets: %llu Bytes: %llu\n"
"\tTx finish: %llu\n"
"\tTx full: %llu\n"
"\tTx fail: %llu\n"
"\tTx alloc mem err: %llu\n\n"
"\tRx packets: %llu Bytes: %llu\n"
"\tRx finish: %llu\n"
"\tRx full: %llu\n"
"\tRx fail: %llu\n"
"\tRx user recv cnt: %llu\n\n",
stat->tx, stat->tx_bytes, stat->tx_finish, stat->tx_full, stat->tx_fail, stat->alloc_mem_err,
stat->rx, stat->rx_bytes, stat->rx_finish, stat->rx_full, stat->rx_fail, stat->rx_total);
} else {
hdcdrv_event("Tx packets:%llu; Bytes:%llu; finish:%llu; full:%llu; fail:%llu; alloc mem err:%llu\n",
stat->tx, stat->tx_bytes, stat->tx_finish, stat->tx_full, stat->tx_fail, stat->alloc_mem_err);
hdcdrv_event("Rx packets:%llu; Bytes:%llu; finish:%llu; full:%llu; fail:%llu; user recv cnt:%llu\n",
stat->rx, stat->rx_bytes, stat->rx_finish, stat->rx_full, stat->rx_fail, stat->rx_total);
}
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_fill_buf_chan_head_info(char *buf, u32 buf_len, u32 dev_id, u32 chan_id,
const struct hdcdrv_cmd_stat_chan *chan_stat)
{
int ret;
ssize_t offset = 0;
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"HDC dev %u chan %u statistics:\n"
"\tTx w_sq head : %d (send sq, remote read)\n"
"\t w_sq tail : %d (send sq, local write)\n"
"\t r_sq head : %d (recv sq, local read)\n"
"\tRx dma_head : %d (dma completed index)\n"
"\t rx_head : %d (dispatch task received index)\n"
"\t submit_dma_head : %d (dma request_index)\n\n",
dev_id, chan_id, chan_stat->w_sq_head, chan_stat->w_sq_tail,
chan_stat->r_sq_head, chan_stat->dma_head, chan_stat->rx_head, chan_stat->submit_dma_head);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_fill_buf_session_head_info(char *buf, u32 buf_len, const struct hdcdrv_cmd_stat_session *stat,
enum hdc_dfx_print_type type)
{
int ret = 0;
ssize_t offset = 0;
if (type == HDC_DFX_PRINT_IN_SYSFS) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"HDC session %d statistics:\n"
"Device id: %d\n"
"Service type: %d \n"
"Trans chan: %d, Fast chan: %d\n"
"Session status: %d\n"
"Local close state: %d, remote close state: %d\n"
"local_fid: %u, container_id:%u, create_pid:%llu, peer_create_pid:%llu, owner_pid:%llu\n"
"Remote session: %d\n\n"
"Session rx_list cnt: %d, fast rx_list cnt: %d, work_cancel_cnt: %d\n\n",
stat->local_session, stat->dev_id, stat->service_type, stat->chan_id, stat->fast_chan_id,
stat->status, stat->local_close_state, stat->remote_close_state,
stat->local_fid, stat->container_id, stat->create_pid, stat->peer_create_pid, stat->owner_pid,
stat->remote_session, stat->pkts_in_list, stat->pkts_in_fast_list, stat->work_cancel_cnt);
} else {
hdcdrv_event("HDC session:%d; devid:%d; server:%d; trans chan:%d; fast chan:%d; status:%d\n",
stat->local_session, stat->dev_id, stat->service_type, stat->chan_id, stat->fast_chan_id, stat->status);
hdcdrv_event("l_close:%d; r_close:%d; l_fid:%u; container_id:%u; c_pid:%llu; p_pid:%llu; o_pid:%llu\n",
stat->local_close_state, stat->remote_close_state, stat->local_fid, stat->container_id,
stat->create_pid, stat->peer_create_pid, stat->owner_pid);
hdcdrv_event("remote session:%d; rx_list cnt:%d; fast rx_list cnt:%d; work_cancel_cnt:%d\n",
stat->remote_session, stat->pkts_in_list, stat->pkts_in_fast_list, stat->work_cancel_cnt);
}
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_fill_buf_session_chan_info(char *buf, u32 buf_len, const struct hdcdrv_dbg_stats *stat,
enum hdc_dfx_print_type type)
{
int ret = 0;
ssize_t offset = 0;
if (type == HDC_DFX_PRINT_IN_SYSFS) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"msg_chan_send: %llu \trx_msg_notify_task2: %llu\n"
"rx_msg_notify_task4: %llu \trx_msg_notify_task5: %llu\n"
"rx_msg_notify_task6: %llu \trx_msg_notify_task7: %llu\n"
"rx_msg_notify_task8: %llu \trx_msg_notify_task9: %llu\n"
"normal_dma_copy: %llu \trx_msg_callback1: %llu\n"
"rx_msg_callback3: %llu \tmsg_chan_recv_task5: %llu\n"
"msg_chan_recv_task6: %llu \tmsg_chan_recv_task7: %llu\n"
"tx_finish_notify_task5: %llu \tx_finish_notify_task7: %llu\n"
"tx_finish_notify_task8: %llu \trecv_data_times: %llu\n"
"hdcdrv_wait_mem_normal: %llu \thdcdrv_wait_mem_fifo_full: %llu\n",
stat->hdcdrv_msg_chan_send1, stat->hdcdrv_rx_msg_notify_task2,
stat->hdcdrv_rx_msg_notify_task4, stat->hdcdrv_rx_msg_notify_task5,
stat->hdcdrv_rx_msg_notify_task6, stat->hdcdrv_rx_msg_notify_task7,
stat->hdcdrv_rx_msg_notify_task8, stat->hdcdrv_rx_msg_notify_task9,
stat->hdcdrv_normal_dma_copy1, stat->hdcdrv_rx_msg_callback1,
stat->hdcdrv_rx_msg_callback3, stat->hdcdrv_msg_chan_recv_task5,
stat->hdcdrv_msg_chan_recv_task6, stat->hdcdrv_msg_chan_recv_task7,
stat->hdcdrv_tx_finish_notify_task5, stat->hdcdrv_tx_finish_notify_task7,
stat->hdcdrv_tx_finish_notify_task8, stat->hdcdrv_recv_data_times,
stat->hdcdrv_wait_mem_normal, stat->hdcdrv_wait_mem_fifo_full);
} else {
hdcdrv_event("send:%llu; RX task2:%llu; task4:%llu; task5:%llu; task6:%llu; task7:%llu; task8:%llu; task9:%llu\n",
stat->hdcdrv_msg_chan_send1, stat->hdcdrv_rx_msg_notify_task2, stat->hdcdrv_rx_msg_notify_task4,
stat->hdcdrv_rx_msg_notify_task5, stat->hdcdrv_rx_msg_notify_task6, stat->hdcdrv_rx_msg_notify_task7,
stat->hdcdrv_rx_msg_notify_task8, stat->hdcdrv_rx_msg_notify_task9);
hdcdrv_event("dma_copy:%llu; rx_cb1:%llu; rx_cb3:%llu; recv_task5:%llu; recv_task6:%llu; recv_task7:%llu\n",
stat->hdcdrv_normal_dma_copy1, stat->hdcdrv_rx_msg_callback1, stat->hdcdrv_rx_msg_callback3,
stat->hdcdrv_msg_chan_recv_task5, stat->hdcdrv_msg_chan_recv_task6, stat->hdcdrv_msg_chan_recv_task7);
hdcdrv_event("tx_task5:%llu; tx_task7:%llu; tx_task8:%llu; recv_times:%llu; wait_normal:%llu; fifo_full:%llu\n",
stat->hdcdrv_tx_finish_notify_task5, stat->hdcdrv_tx_finish_notify_task7, stat->hdcdrv_tx_finish_notify_task8,
stat->hdcdrv_recv_data_times, stat->hdcdrv_wait_mem_normal, stat->hdcdrv_wait_mem_fifo_full);
}
if (ret >= 0) {
offset += ret;
}
return offset;
}
ssize_t hdcdrv_fill_buf_chan_info(char *buf, u32 buf_len, const struct hdcdrv_dbg_stats *stat)
{
int ret;
ssize_t offset = 0;
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"msg_chan_send1 :%llu\n"
"msg_chan_send2 :%llu\n"
"rx_msg_notify :%llu\n"
"rx_msg_notify_task_check1:%llu\n"
"rx_msg_notify_task_check2:%llu\n"
"rx_msg_task_delay_over2ms:%llu\n"
"rx_msg_task_delay_over4ms:%llu\n"
"rx_msg_task_delay_new :%llu\n"
"rx_msg_task_delay_max :%llu\n"
"rx_msg_notify_task1 :%llu\n"
"rx_msg_notify_task2 :%llu\n"
"rx_msg_notify_task3 :%llu\n"
"rx_msg_notify_task4 :%llu\n"
"rx_msg_notify_task5 :%llu\n"
"rx_msg_notify_task6 :%llu\n"
"rx_msg_notify_task7 :%llu\n"
"rx_msg_notify_task8 :%llu\n"
"rx_msg_notify_task9 :%llu\n"
"normal_dma_copy :%llu\n"
"rx_msg_callback1 :%llu\n"
"rx_msg_callback2 :%llu\n"
"rx_msg_callback3 :%llu\n"
"rx_msg_task_check1 :%llu\n"
"rx_msg_task_check2 :%llu\n"
"msg_chan_recv_task1 :%llu\n"
"msg_chan_recv_task2 :%llu\n"
"msg_chan_recv_task3 :%llu\n"
"msg_chan_recv_task4 :%llu\n"
"msg_chan_recv_task5 :%llu\n"
"msg_chan_recv_task6 :%llu\n"
"msg_chan_recv_task7 :%llu\n"
"msg_chan_recv_task8 :%llu\n"
"tx_finish_notify :%llu\n"
"tx_finish_task_check1 :%llu\n"
"tx_finish_task_check2 :%llu\n"
"tx_finish_task_over2ms :%llu\n"
"tx_finish_task_over4ms :%llu\n"
"tx_finish_task_new :%llu\n"
"tx_finish_task_max :%llu\n"
"tx_finish_notify_task1 :%llu\n"
"tx_finish_notify_task2 :%llu\n"
"tx_finish_notify_task3 :%llu\n"
"tx_finish_notify_task4 :%llu\n"
"tx_finish_notify_task5 :%llu\n"
"tx_finish_notify_task6 :%llu\n"
"tx_finish_notify_task7 :%llu\n"
"tx_finish_notify_task8 :%llu\n"
"tx_finish_notify_session :%llu\n"
"tx_finish_notify_sq_head :%llu\n"
"mem_avail1 :%llu\n"
"recv_data_times :%llu\n",
stat->hdcdrv_msg_chan_send1, stat->hdcdrv_msg_chan_send2,
stat->hdcdrv_rx_msg_notify1, stat->hdcdrv_rx_msg_notify_task_check1,
stat->hdcdrv_rx_msg_notify_task_check2, stat->hdcdrv_rx_msg_notify_task_delay_over2ms,
stat->hdcdrv_rx_msg_notify_task_delay_over4ms, stat->hdcdrv_rx_msg_notify_task_delay_new,
stat->hdcdrv_rx_msg_notify_task_delay_max, stat->hdcdrv_rx_msg_notify_task1, stat->hdcdrv_rx_msg_notify_task2,
stat->hdcdrv_rx_msg_notify_task3, stat->hdcdrv_rx_msg_notify_task4, stat->hdcdrv_rx_msg_notify_task5,
stat->hdcdrv_rx_msg_notify_task6, stat->hdcdrv_rx_msg_notify_task7, stat->hdcdrv_rx_msg_notify_task8,
stat->hdcdrv_rx_msg_notify_task9, stat->hdcdrv_normal_dma_copy1, stat->hdcdrv_rx_msg_callback1,
stat->hdcdrv_rx_msg_callback2, stat->hdcdrv_rx_msg_callback3, stat->hdcdrv_rx_msg_task_check1,
stat->hdcdrv_rx_msg_task_check2, stat->hdcdrv_msg_chan_recv_task1, stat->hdcdrv_msg_chan_recv_task2,
stat->hdcdrv_msg_chan_recv_task3, stat->hdcdrv_msg_chan_recv_task4, stat->hdcdrv_msg_chan_recv_task5,
stat->hdcdrv_msg_chan_recv_task6, stat->hdcdrv_msg_chan_recv_task7, stat->hdcdrv_msg_chan_recv_task8,
stat->hdcdrv_tx_finish_notify1, stat->hdcdrv_tx_finish_task_check1,
stat->hdcdrv_tx_finish_task_check2, stat->hdcdrv_tx_finish_notify_task_delay_over2ms,
stat->hdcdrv_tx_finish_notify_task_delay_over4ms, stat->hdcdrv_tx_finish_notify_task_delay_new,
stat->hdcdrv_tx_finish_notify_task_delay_max, stat->hdcdrv_tx_finish_notify_task1,
stat->hdcdrv_tx_finish_notify_task2, stat->hdcdrv_tx_finish_notify_task3, stat->hdcdrv_tx_finish_notify_task4,
stat->hdcdrv_tx_finish_notify_task5, stat->hdcdrv_tx_finish_notify_task6, stat->hdcdrv_tx_finish_notify_task7,
stat->hdcdrv_tx_finish_notify_task8, stat->hdcdrv_tx_finish_notify_session_no_update,
stat->hdcdrv_tx_finish_notify_sq_head_no_update, stat->hdcdrv_mem_avail1, stat->hdcdrv_recv_data_times);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_sysfs_get_chan_id(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
int ret;
(void)attr;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "chan id %u\n", g_chan_id);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_sysfs_get_session_fd(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
int ret;
(void)attr;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "session id %u\n", g_session_fd);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_sysfs_get_server_type(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
int ret;
(void)attr;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "server type %u\n",
g_server_type);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_sysfs_get_dev_id(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
int ret;
(void)attr;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "dev id %u\n", g_dev_id);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_sysfs_set_chan_id(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
hdcdrv_err("Calling ka_base_kstrtou32 failed.\n");
return -EINVAL;
}
if (val >= HDCDRV_SUPPORT_MAX_DEV_MSG_CHAN) {
hdcdrv_err("Parameter is invalid. (msg_chan=%u)\n", val);
return -EINVAL;
}
g_chan_id = val;
return (ssize_t)count;
}
STATIC ssize_t hdcdrv_sysfs_set_session_fd(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
hdcdrv_err("Calling ka_base_kstrtou32 failed.\n");
return -EINVAL;
}
if (val >= (u32)HDCDRV_REAL_MAX_SESSION) {
hdcdrv_err("Parameter is invalid. (session=%u)\n", val);
return -EINVAL;
}
g_session_fd = val;
return (ssize_t)count;
}
STATIC ssize_t hdcdrv_sysfs_set_server_type(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
hdcdrv_err("Calling ka_base_kstrtou32 failed.\n");
return -EINVAL;
}
if (val >= HDCDRV_SUPPORT_MAX_SERVICE) {
hdcdrv_err("Parameter is invalid. (server_type=%u)\n", val);
return -EINVAL;
}
g_server_type = val;
return (ssize_t)count;
}
STATIC ssize_t hdcdrv_sysfs_set_dev_id(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
hdcdrv_err("Calling ka_base_kstrtou32 failed.\n");
return -EINVAL;
}
if (val >= (u32)hdcdrv_get_max_support_dev()) {
hdcdrv_err("Parameter is invalid. (dev_id=%u)\n", val);
return -EINVAL;
}
g_dev_id = val;
return (ssize_t)count;
}
STATIC int hdcdrv_sysfs_get_chan_inner(char *buf, u32 buf_len, u32 dev_id, u32 chan_id, ssize_t *len)
{
struct hdcdrv_cmd_stat_chan *chan_stat = NULL;
struct hdcdrv_cmd_get_stat cmd;
ssize_t offset = 0;
cmd.chan_id = (int)chan_id;
cmd.dev_id = (int)dev_id;
cmd.outbuf = hdcdrv_kzalloc(sizeof(struct hdcdrv_cmd_stat_chan), KA_GFP_KERNEL | __KA_GFP_ACCOUNT, KA_SUB_MODULE_TYPE_4);
if (cmd.outbuf == NULL) {
hdcdrv_err("Calling ka_mm_kzalloc failed. (chan_id=%u)\n", chan_id);
return HDCDRV_MEM_ALLOC_FAIL;
}
if (hdcdrv_get_chan_stat(&cmd) != HDCDRV_OK) {
hdcdrv_err("get chan stat failed. (chan_id=%u)\n", chan_id);
hdcdrv_kfree(cmd.outbuf, KA_SUB_MODULE_TYPE_4);
cmd.outbuf = NULL;
return HDCDRV_ERR;
}
chan_stat = (struct hdcdrv_cmd_stat_chan *)cmd.outbuf;
offset += hdcdrv_fill_buf_chan_head_info(buf + offset, (u32)(buf_len - offset), dev_id, chan_id, chan_stat);
offset += hdcdrv_fill_buf_tx_rx(buf + offset, (u32)(buf_len - offset), &(chan_stat->stat), HDC_DFX_PRINT_IN_SYSFS);
offset += hdcdrv_fill_buf_chan_info(buf + offset, (u32)(buf_len - offset), &(chan_stat->dbg_stat));
*len = offset;
hdcdrv_kfree(cmd.outbuf, KA_SUB_MODULE_TYPE_4);
cmd.outbuf = NULL;
return HDCDRV_OK;
}
STATIC ssize_t hdcdrv_sysfs_get_remote_chan_stat(char *buf, u32 buf_len, u32 dev_id, u32 chan_id)
{
ssize_t offset = 0;
int ret;
u32 msg_len;
u32 out_len;
struct hdcdrv_sysfs_ctrl_msg *msg = NULL;
msg_len = (u32)sizeof(struct hdcdrv_sysfs_ctrl_msg) + HDCDRV_SYSFS_DATA_MAX_LEN;
msg = (struct hdcdrv_sysfs_ctrl_msg *)hdcdrv_kvmalloc(msg_len, KA_SUB_MODULE_TYPE_4);
if (msg == NULL) {
hdcdrv_err("Calling ka_mm_kzalloc failed.\n");
return offset;
}
msg->head.type = HDCDRV_CTRL_MSG_TYPE_GET_DEV_CHAN_STAT;
msg->head.error_code = HDCDRV_OK;
msg->head.para = chan_id;
msg->head.msg_len = msg_len;
ret = (int)hdcdrv_ctrl_msg_send(dev_id, (void *)msg, msg_len, msg_len, &out_len);
if ((ret == 0) && (msg->head.msg_len < buf_len - offset)) {
msg->data[HDCDRV_SYSFS_DATA_MAX_LEN - 1] = '\0';
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1), "%s\n", msg->data);
if (ret >= 0) {
offset += ret;
}
}
hdcdrv_kvfree((void **)&msg, KA_SUB_MODULE_TYPE_4);
msg = NULL;
return offset;
}
STATIC ssize_t hdcdrv_sysfs_get_chan_stat(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
int ret;
(void)attr;
ret = hdcdrv_sysfs_get_chan_inner(buf, KA_MM_PAGE_SIZE, g_dev_id, g_chan_id, &offset);
if (ret != HDCDRV_OK) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "\ndevice chan stat:\n");
if (ret >= 0) {
offset += ret;
}
offset += hdcdrv_sysfs_get_remote_chan_stat(buf + offset, KA_MM_PAGE_SIZE - offset, g_dev_id, g_chan_id);
return offset;
}
int hdcdrv_sysfs_get_session_inner(char *buf, u32 buf_len, u32 session_fd, ssize_t *len, enum hdc_dfx_print_type type)
{
struct hdcdrv_cmd_stat_session *stat = NULL;
struct hdcdrv_cmd_get_stat cmd = {0};
ssize_t offset = 0;
cmd.session = (int)session_fd;
cmd.outbuf = hdcdrv_kzalloc(sizeof(struct hdcdrv_cmd_stat_session), KA_GFP_KERNEL | __KA_GFP_ACCOUNT,
KA_SUB_MODULE_TYPE_4);
if (cmd.outbuf == NULL) {
hdcdrv_err("Calling ka_mm_kzalloc failed. (g_session_fd=%u)\n", session_fd);
return HDCDRV_MEM_ALLOC_FAIL;
}
if (hdcdrv_get_session_stat(&cmd) != HDCDRV_OK) {
hdcdrv_err("Get session stat failed. (g_session_fd=%u)\n", session_fd);
hdcdrv_kfree(cmd.outbuf, KA_SUB_MODULE_TYPE_4);
cmd.outbuf = NULL;
return HDCDRV_ERR;
}
stat = (struct hdcdrv_cmd_stat_session *)cmd.outbuf;
offset += hdcdrv_fill_buf_session_head_info(buf + offset, (u32)(buf_len - offset), stat, type);
offset += hdcdrv_fill_buf_tx_rx(buf + offset, (u32)(buf_len - offset), &stat->stat, type);
offset += hdcdrv_fill_buf_session_chan_info(buf + offset, (u32)(buf_len - offset), &stat->dbg_stat, type);
*len = offset;
hdcdrv_kfree(cmd.outbuf, KA_SUB_MODULE_TYPE_4);
cmd.outbuf = NULL;
return HDCDRV_OK;
}
STATIC ssize_t hdcdrv_sysfs_get_session_stat(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
int ret;
u32 msg_len;
u32 out_len;
struct hdcdrv_sysfs_ctrl_msg *msg = NULL;
struct hdcdrv_session *session = NULL;
(void)attr;
ret = hdcdrv_sysfs_get_session_inner(buf, KA_MM_PAGE_SIZE, g_session_fd, &offset, HDC_DFX_PRINT_IN_SYSFS);
if (ret != HDCDRV_OK) {
return offset;
}
session = &hdc_ctrl->sessions[g_session_fd];
msg_len = (u32)sizeof(struct hdcdrv_sysfs_ctrl_msg) + HDCDRV_SYSFS_DATA_MAX_LEN;
msg = (struct hdcdrv_sysfs_ctrl_msg *)hdcdrv_kvmalloc(msg_len, KA_SUB_MODULE_TYPE_4);
if (msg == NULL) {
hdcdrv_err("Calling ka_mm_kzalloc failed.\n");
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "\nRemote session stat:\n");
if (ret >= 0) {
offset += ret;
}
msg->head.type = HDCDRV_CTRL_MSG_TYPE_GET_DEV_SESSION_STAT;
msg->head.error_code = HDCDRV_OK;
msg->head.para = (u32)session->remote_session_fd;
msg->head.msg_len = msg_len;
msg->head.print_type = HDC_DFX_PRINT_IN_SYSFS;
ret = (int)hdcdrv_ctrl_msg_send((u32)session->dev_id, (void *)msg, msg_len, msg_len, &out_len);
if ((ret == 0) && (msg->head.msg_len < KA_MM_PAGE_SIZE - offset)) {
msg->data[HDCDRV_SYSFS_DATA_MAX_LEN - 1] = '\0';
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%s\n", msg->data);
if (ret >= 0) {
offset += ret;
}
}
hdcdrv_kvfree((void **)&msg, KA_SUB_MODULE_TYPE_4);
msg = NULL;
return offset;
}
STATIC ssize_t hdcdrv_sysfs_get_server_stat(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
long ret;
struct hdcdrv_cmd_get_stat cmd;
struct hdcdrv_cmd_stat_dev_service *server_stat = NULL;
(void)attr;
cmd.service_type = (int)g_server_type;
cmd.dev_id = (int)g_dev_id;
cmd.outbuf = hdcdrv_alloc_stat_list();
if (cmd.outbuf == NULL) {
hdcdrv_err("Calling ka_mm_kzalloc failed. (g_server_type=%u)\n", g_server_type);
return offset;
}
ret = hdcdrv_get_service_stat(&cmd);
if (ret != HDCDRV_OK) {
hdcdrv_err("Get server stat failed. (g_server_type=%u)\n", g_server_type);
hdcdrv_free_stat_list((struct hdcdrv_cmd_stat_dev_service *)cmd.outbuf);
cmd.outbuf = NULL;
return offset;
}
server_stat = (struct hdcdrv_cmd_stat_dev_service *)cmd.outbuf;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"HDC service %u statistics:\n", g_server_type);
if (ret >= 0) {
offset += ret;
}
offset += hdcdrv_fill_buf_tx_rx(buf + offset, KA_MM_PAGE_SIZE - offset, &server_stat->stat, HDC_DFX_PRINT_IN_SYSFS);
offset += hdcdrv_fill_buf_session_brief(buf + offset, KA_MM_PAGE_SIZE - offset, &server_stat->s_brief, HDC_DFX_LIST_SESSION);
hdcdrv_free_stat_list((struct hdcdrv_cmd_stat_dev_service *)cmd.outbuf);
cmd.outbuf = NULL;
return offset;
}
STATIC ssize_t hdcdrv_sysfs_print_dev_stat(struct hdcdrv_cmd_get_stat cmd, char *buf)
{
ssize_t offset = 0;
long ret;
struct hdcdrv_cmd_stat_dev_service *dev_stat = NULL;
cmd.outbuf = hdcdrv_alloc_stat_list();
if (cmd.outbuf == NULL) {
hdcdrv_err("Calling ka_mm_kzalloc failed. (dev_id=%d)\n", cmd.dev_id);
return offset;
}
ret = hdcdrv_get_dev_stat(&cmd);
if (ret != HDCDRV_OK) {
hdcdrv_err("Get dev stat failed. (dev_id=%d)\n", cmd.dev_id);
hdcdrv_free_stat_list((struct hdcdrv_cmd_stat_dev_service *)cmd.outbuf);
cmd.outbuf = NULL;
return offset;
}
dev_stat = (struct hdcdrv_cmd_stat_dev_service *)cmd.outbuf;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"HDC device %u fid %u statistics:\n", g_dev_id, g_fid);
if (ret >= 0) {
offset += ret;
}
offset += hdcdrv_fill_buf_session_brief(buf + offset, KA_MM_PAGE_SIZE - offset, &dev_stat->s_brief, HDC_DFX_NOT_LIST_SESSION);
offset += hdcdrv_fill_buf_tx_rx(buf + offset, KA_MM_PAGE_SIZE - offset, &dev_stat->stat, HDC_DFX_PRINT_IN_SYSFS);
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "\ttx mem pool:\n");
if (ret >= 0) {
offset += ret;
}
offset += hdcdrv_fill_buf_mem_info(buf + offset, KA_MM_PAGE_SIZE - offset, &dev_stat->tx_mem_info);
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "\trx mem pool:\n");
if (ret >= 0) {
offset += ret;
}
offset += hdcdrv_fill_buf_mem_info(buf + offset, KA_MM_PAGE_SIZE - offset, &dev_stat->rx_mem_info);
hdcdrv_free_stat_list((struct hdcdrv_cmd_stat_dev_service *)cmd.outbuf);
cmd.outbuf = NULL;
return offset;
}
STATIC ssize_t hdcdrv_sysfs_get_dev_stat(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
struct hdcdrv_cmd_get_stat cmd;
cmd.service_type = -1;
cmd.dev_id = (int)g_dev_id;
cmd.fid = 0;
cmd.vf_flag = 0;
return hdcdrv_sysfs_print_dev_stat(cmd, buf);
}
int hdcdrv_sysfs_ctrl_msg_get_session_stat(u32 dev_id, void *data, u32 *real_out_len)
{
struct hdcdrv_sysfs_ctrl_msg *msg = (struct hdcdrv_sysfs_ctrl_msg *)data;
ssize_t offset = 0;
int ret;
ret = hdcdrv_sysfs_get_session_inner(msg->data, HDCDRV_SYSFS_DATA_MAX_LEN, msg->head.para, &offset,
msg->head.print_type);
if (msg->head.print_type == HDC_DFX_PRINT_IN_SYSFS) {
*real_out_len = (u32)(offset + sizeof(struct hdcdrv_sysfs_ctrl_msg));
msg->head.msg_len = (u32)offset;
} else {
*real_out_len = (u32)sizeof(struct hdcdrv_sysfs_ctrl_msg);
}
return ret;
}
int hdcdrv_sysfs_ctrl_msg_get_chan_stat(u32 dev_id, void *data, u32 *real_out_len)
{
struct hdcdrv_sysfs_ctrl_msg *msg = (struct hdcdrv_sysfs_ctrl_msg *)data;
ssize_t offset = 0;
int ret;
ret = hdcdrv_sysfs_get_chan_inner(msg->data, HDCDRV_SYSFS_DATA_MAX_LEN, dev_id, msg->head.para, &offset);
*real_out_len = (u32)(offset + sizeof(struct hdcdrv_sysfs_ctrl_msg));
msg->head.msg_len = (u32)offset;
return ret;
}
STATIC int hdcdrv_sysfs_get_link_inner(char *buf, u32 buf_len, u32 dev_id, u32 server_type, ssize_t *len)
{
struct hdcdrv_link_ctrl_msg_stats *connect_msg_stat, *reply_msg_stat, *close_msg_stat;
struct hdcdrv_dev *dev = NULL;
int status_type, ret;
ssize_t offset = 0;
if (hdcdrv_dev_para_check((int)dev_id, (int)server_type) != HDCDRV_OK) {
return HDCDRV_ERR;
}
dev = &hdc_ctrl->devices[dev_id];
connect_msg_stat = &dev->service[server_type].service_stat.connect_msg_stat;
reply_msg_stat = &dev->service[server_type].service_stat.reply_msg_stat;
close_msg_stat = &dev->service[server_type].service_stat.close_msg_stat;
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"Msg type\tMsg status\tlast_err\tcount\n");
if (ret >= 0) {
offset += ret;
}
for (status_type = HDCDRV_LINK_CTRL_MSG_SEND_SUCC; status_type < HDCDRV_LINK_CTRL_MSG_STATUS_MAX;
status_type++) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"connect \t%s\t%d\t\t%u\n", g_hdc_ctrl_msg_status_str[status_type],
connect_msg_stat->last_err[status_type], connect_msg_stat->count[status_type]);
if (ret >= 0) {
offset += ret;
}
}
for (status_type = HDCDRV_LINK_CTRL_MSG_SEND_SUCC; status_type < HDCDRV_LINK_CTRL_MSG_STATUS_MAX;
status_type++) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"connect_reply \t%s\t%d\t\t%u\n", g_hdc_ctrl_msg_status_str[status_type],
reply_msg_stat->last_err[status_type], reply_msg_stat->count[status_type]);
if (ret >= 0) {
offset += ret;
}
}
for (status_type = HDCDRV_LINK_CTRL_MSG_SEND_SUCC; status_type < HDCDRV_LINK_CTRL_MSG_STATUS_MAX;
status_type++) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"close \t%s\t%d\t\t%u\n", g_hdc_ctrl_msg_status_str[status_type],
close_msg_stat->last_err[status_type], close_msg_stat->count[status_type]);
if (ret >= 0) {
offset += ret;
}
}
*len = offset;
return HDCDRV_OK;
}
int hdcdrv_sysfs_ctrl_msg_get_connect_stat(u32 dev_id, void *data, u32 *real_out_len)
{
struct hdcdrv_sysfs_ctrl_msg *msg = (struct hdcdrv_sysfs_ctrl_msg *)data;
ssize_t offset = 0;
int ret;
ret = hdcdrv_sysfs_get_link_inner(msg->data, HDCDRV_SYSFS_DATA_MAX_LEN, dev_id, msg->head.para, &offset);
*real_out_len = (u32)(offset + sizeof(struct hdcdrv_sysfs_ctrl_msg));
msg->head.msg_len = (u32)offset;
return ret;
}
STATIC ssize_t hdcdrv_sysfs_get_remote_link_stat(char *buf, u32 buf_len, u32 dev_id, u32 server_type)
{
ssize_t offset = 0;
int ret;
u32 msg_len;
u32 out_len;
struct hdcdrv_sysfs_ctrl_msg *msg = NULL;
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"HDC device %u server_type %u remote statistics:\n", dev_id, server_type);
if (ret >= 0) {
offset += ret;
}
msg_len = (u32)sizeof(struct hdcdrv_sysfs_ctrl_msg) + HDCDRV_SYSFS_DATA_MAX_LEN;
msg = (struct hdcdrv_sysfs_ctrl_msg *)hdcdrv_kvmalloc(msg_len, KA_SUB_MODULE_TYPE_4);
if (msg == NULL) {
hdcdrv_err("Calling ka_mm_kzalloc failed. (dev_id=%u; server_type=%u)\n", dev_id, server_type);
return offset;
}
msg->head.type = HDCDRV_CTRL_MSG_TYPE_GET_DEV_LINK_STAT;
msg->head.error_code = HDCDRV_OK;
msg->head.para = server_type;
msg->head.msg_len = msg_len;
ret = (int)hdcdrv_ctrl_msg_send(dev_id, (void *)msg, msg_len, msg_len, &out_len);
if ((ret == 0) && (msg->head.msg_len < buf_len - offset)) {
msg->data[HDCDRV_SYSFS_DATA_MAX_LEN - 1] = '\0';
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1), "%s\n", msg->data);
if (ret >= 0) {
offset += ret;
}
}
hdcdrv_kvfree((void **)&msg, KA_SUB_MODULE_TYPE_4);
msg = NULL;
return offset;
}
STATIC ssize_t hdcdrv_sysfs_get_link_stat(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t buf_size = KA_MM_PAGE_SIZE;
ssize_t offset = 0;
ssize_t len = 0;
int ret;
(void)attr;
ret = snprintf_s(buf, (size_t)buf_size, (size_t)(buf_size - 1),
"HDC device %u server_type %u local statistics:\n", g_dev_id, g_server_type);
if (ret >= 0) {
offset += ret;
}
ret = hdcdrv_sysfs_get_link_inner(buf + offset, (u32)(buf_size - offset), g_dev_id, g_server_type, &len);
if (ret != HDCDRV_OK) {
return offset;
}
offset += len;
offset += hdcdrv_sysfs_get_remote_link_stat(buf + offset, (u32)(buf_size - offset), g_dev_id, g_server_type);
return offset;
}
STATIC ssize_t hdcdrv_sysfs_get_fid(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
int ret;
(void)attr;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "fid %u\n", g_fid);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t hdcdrv_sysfs_set_fid(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
hdcdrv_err("Calling ka_base_kstrtou32 failed.\n");
return -EINVAL;
}
if (val >= VMNG_VDEV_MAX_PER_PDEV) {
hdcdrv_err("Parameter is invalid. (fid=%u)\n", val);
return -EINVAL;
}
g_fid = val;
return (ssize_t)count;
}
STATIC ssize_t hdcdrv_sysfs_get_vdev_stat(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
#ifdef CFG_FEATURE_VFIO
struct hdcdrv_cmd_get_stat cmd;
cmd.service_type = -1;
cmd.dev_id = (int)g_dev_id;
cmd.fid = (int)g_fid;
cmd.vf_flag = 1;
if ((cmd.dev_id >= hdcdrv_get_max_support_dev()) || (cmd.dev_id < 0) ||
(cmd.dev_id >= VMNG_PDEV_MAX) || (cmd.fid < 0) || (cmd.fid >= VMNG_VDEV_MAX_PER_PDEV)) {
hdcdrv_err("Input parameter is error. (dev_id=%d; fid=%d)\n", cmd.dev_id, cmd.fid);
return offset;
}
offset = hdcdrv_sysfs_print_dev_stat(cmd, buf);
#endif
return offset;
}
STATIC int hdcdrv_sysfs_get_timetaken_inner(char *buf, u32 buf_len, u32 session_fd, ssize_t *len)
{
struct hdcdrv_dbg_time *dbg_time = NULL;
ssize_t offset = 0;
int ret, i;
const char *conn_title[CONN_TIME_TAKEN_MAX] = {"alloc session", "recv connect reply", "wake up wq conn"};
const char *accept_title[ACCEPT_TIME_TAKEN_MAX] = {"alloc session", "wake up wq conn avail"};
const char *tx_title[TX_TIME_TAKEN_MAX] = {
"alloc tx mem",
"copy tx data from user",
"wait SQ not full",
"copy sq desc",
"peer recv data",
"update sq head",
"wake up send wait"};
const char *rx_title[RX_TIME_TAKEN_MAX] = {
"copy rx data",
"insert into session list",
"user get data",
"copy rx data to user"};
if (session_fd >= (u32)HDCDRV_REAL_MAX_SESSION) {
hdcdrv_err("Input parameter is error. (session_fd=%u)\n", session_fd);
return HDCDRV_PARA_ERR;
}
dbg_time = &hdc_ctrl->sessions[session_fd].dbg_time;
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"session fd: %u\n", session_fd);
if (ret >= 0) {
offset += ret;
}
if (dbg_time->conn_type == DBG_TIME_OP_CONN) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\nconnection timetaken(us):\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < CONN_TIME_TAKEN_MAX; i++) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"%-24s: %llu\n", conn_title[i], dbg_time->conn_time_taken[i]);
if (ret >= 0) {
offset += ret;
}
}
} else if (dbg_time->conn_type == DBG_TIME_OP_ACCEPT) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\nacceptance timetaken(us):\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < ACCEPT_TIME_TAKEN_MAX; i++) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"%-24s: %llu\n", accept_title[i], dbg_time->accept_time_taken[i]);
if (ret >= 0) {
offset += ret;
}
}
}
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\ntx timetaken(last/max(us) [timeout 1ms/10ms/100ms/1s]):\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < TX_TIME_TAKEN_MAX; i++) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"%-24s: %llu/%llu [%u/%u/%u/%u]\n", tx_title[i],
dbg_time->tx_last_time_taken[i], dbg_time->tx_max_time_taken[i],
dbg_time->tx_timeout_cnt[i].timeout_1ms_cnt, dbg_time->tx_timeout_cnt[i].timeout_10ms_cnt,
dbg_time->tx_timeout_cnt[i].timeout_100ms_cnt, dbg_time->tx_timeout_cnt[i].timeout_1s_cnt);
if (ret >= 0) {
offset += ret;
}
}
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"\nrx timetaken(last/max(us) [timeout 1ms/10ms/100ms/1s]):\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < RX_TIME_TAKEN_MAX; i++) {
ret = snprintf_s(buf + offset, (size_t)(buf_len - offset), (size_t)(buf_len - offset - 1),
"%-24s: %llu/%llu [%u/%u/%u/%u]\n", rx_title[i],
dbg_time->rx_last_time_taken[i], dbg_time->rx_max_time_taken[i],
dbg_time->rx_timeout_cnt[i].timeout_1ms_cnt, dbg_time->rx_timeout_cnt[i].timeout_10ms_cnt,
dbg_time->rx_timeout_cnt[i].timeout_100ms_cnt, dbg_time->rx_timeout_cnt[i].timeout_1s_cnt);
if (ret >= 0) {
offset += ret;
}
}
*len = offset;
return HDCDRV_OK;
}
int hdcdrv_sysfs_ctrl_msg_get_dbg_time_taken(u32 dev_id, void *data, u32 *real_out_len)
{
struct hdcdrv_sysfs_ctrl_msg *msg = (struct hdcdrv_sysfs_ctrl_msg *)data;
ssize_t offset = 0;
int ret;
ret = hdcdrv_sysfs_get_timetaken_inner(msg->data, HDCDRV_SYSFS_DATA_MAX_LEN, msg->head.para, &offset);
*real_out_len = (u32)(offset + sizeof(struct hdcdrv_sysfs_ctrl_msg));
msg->head.msg_len = (u32)offset;
return ret;
}
STATIC ssize_t hdcdrv_sysfs_get_session_timetaken(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0, offset_buf = 0;
int ret;
u32 msg_len, out_len;
struct hdcdrv_sysfs_ctrl_msg *msg = NULL;
struct hdcdrv_session *session = NULL;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "Local session:\n");
if (ret >= 0) {
offset += ret;
}
ret = hdcdrv_sysfs_get_timetaken_inner(buf + offset, KA_MM_PAGE_SIZE - offset, g_session_fd, &offset_buf);
offset += offset_buf;
msg_len = (u32)sizeof(struct hdcdrv_sysfs_ctrl_msg) + HDCDRV_SYSFS_DATA_MAX_LEN;
msg = (struct hdcdrv_sysfs_ctrl_msg *)hdcdrv_kvmalloc(msg_len, KA_SUB_MODULE_TYPE_4);
if (msg == NULL) {
hdcdrv_err("Calling ka_mm_kzalloc failed.\n");
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "\nRemote session:\n");
if (ret >= 0) {
offset += ret;
}
session = &hdc_ctrl->sessions[g_session_fd];
msg->head.type = HDCDRV_CTRL_MSG_TYPE_GET_DEV_DBG_TIME_TAKEN;
msg->head.error_code = HDCDRV_OK;
msg->head.para = (u32)session->remote_session_fd;
msg->head.msg_len = msg_len;
ret = (int)hdcdrv_ctrl_msg_send((u32)session->dev_id, (void *)msg, msg_len, msg_len, &out_len);
if ((ret == 0) && (msg->head.msg_len < KA_MM_PAGE_SIZE - offset)) {
msg->data[HDCDRV_SYSFS_DATA_MAX_LEN - 1] = '\0';
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%s\n", msg->data);
} else {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "ctrl msg send failed: ret = %d\n", ret);
}
if (ret >= 0) {
offset += ret;
}
hdcdrv_kvfree((void **)&msg, KA_SUB_MODULE_TYPE_4);
msg = NULL;
return offset;
}
static KA_DRIVER_DEVICE_ATTR(chan, HDCDRV_ATTR_RW, hdcdrv_sysfs_get_chan_id, hdcdrv_sysfs_set_chan_id);
static KA_DRIVER_DEVICE_ATTR(session, HDCDRV_ATTR_RW, hdcdrv_sysfs_get_session_fd, hdcdrv_sysfs_set_session_fd);
static KA_DRIVER_DEVICE_ATTR(server, HDCDRV_ATTR_RW, hdcdrv_sysfs_get_server_type, hdcdrv_sysfs_set_server_type);
static KA_DRIVER_DEVICE_ATTR(dev, HDCDRV_ATTR_RW, hdcdrv_sysfs_get_dev_id, hdcdrv_sysfs_set_dev_id);
static KA_DRIVER_DEVICE_ATTR(fid, HDCDRV_ATTR_RW, hdcdrv_sysfs_get_fid, hdcdrv_sysfs_set_fid);
static KA_DRIVER_DEVICE_ATTR(chan_stat, HDCDRV_ATTR_RD, hdcdrv_sysfs_get_chan_stat, NULL);
static KA_DRIVER_DEVICE_ATTR(session_stat, HDCDRV_ATTR_RD, hdcdrv_sysfs_get_session_stat, NULL);
static KA_DRIVER_DEVICE_ATTR(server_stat, HDCDRV_ATTR_RD, hdcdrv_sysfs_get_server_stat, NULL);
static KA_DRIVER_DEVICE_ATTR(dev_stat, HDCDRV_ATTR_RD, hdcdrv_sysfs_get_dev_stat, NULL);
static KA_DRIVER_DEVICE_ATTR(link_stat, HDCDRV_ATTR_RD, hdcdrv_sysfs_get_link_stat, NULL);
static KA_DRIVER_DEVICE_ATTR(vdev_stat, HDCDRV_ATTR_RD, hdcdrv_sysfs_get_vdev_stat, NULL);
static KA_DRIVER_DEVICE_ATTR(session_timetaken, HDCDRV_ATTR_RD, hdcdrv_sysfs_get_session_timetaken, NULL);
static ka_attribute_t *g_hdcdrv_sysfs_attrs[] = {
ka_fs_get_dev_attr(dev_attr_chan)
ka_fs_get_dev_attr(dev_attr_session)
ka_fs_get_dev_attr(dev_attr_server)
ka_fs_get_dev_attr(dev_attr_dev)
ka_fs_get_dev_attr(dev_attr_fid)
ka_fs_get_dev_attr(dev_attr_chan_stat)
ka_fs_get_dev_attr(dev_attr_session_stat)
ka_fs_get_dev_attr(dev_attr_server_stat)
ka_fs_get_dev_attr(dev_attr_dev_stat)
ka_fs_get_dev_attr(dev_attr_link_stat)
ka_fs_get_dev_attr(dev_attr_vdev_stat)
ka_fs_get_dev_attr(dev_attr_session_timetaken)
NULL,
};
static const ka_attribute_group_t g_hdcdrv_sysfs_group = {
ka_fs_init_ag_attrs(g_hdcdrv_sysfs_attrs)
ka_fs_init_ag_name("hdc")
};
void hdcdrv_sysfs_init(ka_device_t *dev)
{
int ret;
ret = ka_sysfs_create_group(ka_base_get_device_kobj(dev), &g_hdcdrv_sysfs_group);
if (ret != 0) {
hdcdrv_warn("Calling ka_sysfs_create_group not success. (ret=%d)\n", ret);
}
}
void hdcdrv_sysfs_uninit(ka_device_t *dev)
{
ka_sysfs_remove_group(ka_base_get_device_kobj(dev), &g_hdcdrv_sysfs_group);
}