* 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_dfx_pub.h"
#include "ka_system_pub.h"
#include "ka_list_pub.h"
#include "ka_memory_pub.h"
#include "ka_errno_pub.h"
#include "ka_task_pub.h"
#include "ka_base_pub.h"
#include "ka_kernel_def_pub.h"
#include "dms_kernel_version_adapt.h"
#include "urd_feature.h"
#include "dms_template.h"
#include "devdrv_user_common.h"
#include "dms_event_distribute.h"
#include "dms_event_converge.h"
#include "dms_event_distribute_proc.h"
#include "pbl_mem_alloc_interface.h"
#include "smf_event_adapt.h"
#include "urd_acc_ctrl.h"
#include "pbl/pbl_uda.h"
#include "dms/dms_cmd_def.h"
#include "dms/dms_notifier.h"
#include "kernel_version_adapt.h"
#include "drv_systime.h"
#ifdef CFG_FEATURE_BIND_CORE
#include "kthread_affinity.h"
#endif
#include "devdrv_common.h"
#include "dms_event.h"
#define DMS_EVENT_KFIFO_CELL (sizeof(struct dms_event_obj))
#define DMS_EVENT_KFIFO_SIZE (DMS_EVENT_KFIFO_CELL * DMS_MAX_EVENT_NUM)
#define DMS_EVENT_NUM_KERNEL ((DMS_MAX_EVENT_NUM * 80) / 100)
#define DMS_EVENT_POLL_WAIT_TIME 500
#define DMS_EVENT_TASK_WAIT_TIMEOUT_MS 200
#define DMS_EVENT_FRESH_TO_BAR 500
struct {
ka_task_struct_t *poll_task;
ka_atomic_t poll_flag;
ka_kfifo_t kfifo;
u32 event_num;
ka_mutex_t lock;
ka_wait_queue_head_t wait;
} g_event_task;
int dms_event_get_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len);
int dms_event_get_history_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len);
int dms_get_error_code(void *feature, char *in, u32 in_len,
char *out, u32 out_len);
int dms_get_device_health(void *feature, char *in, u32 in_len,
char *out, u32 out_len);
int dms_query_error_str(void *feature, char *in, u32 in_len,
char *out, u32 out_len);
int dms_event_clear_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len);
int dms_event_disable_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len);
int dms_event_enable_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len);
int dms_event_get_current_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len);
int dms_get_device_state(void *feature, char *in, u32 in_len, char *out, u32 out_len);
INIT_MODULE_FUNC(DMS_EVENT_CMD_NAME);
EXIT_MODULE_FUNC(DMS_EVENT_CMD_NAME);
BEGIN_DMS_MODULE_DECLARATION(DMS_EVENT_CMD_NAME)
BEGIN_FEATURE_COMMAND()
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_GET_FAULT_EVENT, NULL, NULL,
DMS_ACC_NOT_LIMIT_USER | DMS_ENV_ALL | DMS_VDEV_PHYSICAL, dms_event_get_fault_event)
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_GET_HISTORY_FAULT_EVENT, NULL, NULL,
DMS_ACC_NOT_LIMIT_USER | DMS_ENV_NOT_DOCKER | DMS_VDEV_PHYSICAL, dms_event_get_history_fault_event)
#ifdef CFG_FEATURE_GET_CURRENT_EVENTINFO
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_GET_FAULT_EVENT_OBJ, NULL, NULL,
DMS_ACC_ALL | DMS_ENV_ALL | DMS_VDEV_NOTSUPPORT, dms_event_get_current_fault_event)
#endif
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_GET_EVENT_CODE, NULL, NULL,
DMS_ACC_NOT_LIMIT_USER | DMS_ENV_ALL | DMS_VDEV_ALL, dms_get_error_code)
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_GET_HEALTH_CODE, NULL, NULL,
DMS_ACC_NOT_LIMIT_USER | DMS_ENV_ALL | DMS_VDEV_ALL, dms_get_device_health)
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_QUERY_STR, NULL, NULL,
DMS_ACC_NOT_LIMIT_USER | DMS_ENV_ALL | DMS_VDEV_ALL, dms_query_error_str)
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_CLEAR_EVENT, NULL, NULL,
DMS_ACC_ROOT_ONLY | DMS_ENV_NOT_DOCKER | DMS_VDEV_PHYSICAL, dms_event_clear_fault_event)
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_DISABLE_EVENT, NULL, NULL,
DMS_ACC_ROOT_ONLY | DMS_ENV_NOT_DOCKER | DMS_VDEV_PHYSICAL, dms_event_disable_fault_event)
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_ENABLE_EVENT, NULL, NULL,
DMS_ACC_ROOT_ONLY | DMS_ENV_NOT_DOCKER | DMS_VDEV_PHYSICAL, dms_event_enable_fault_event)
#ifdef CFG_FEATURE_DEVICE_STATE_TABLE
ADD_FEATURE_COMMAND(DMS_EVENT_CMD_NAME, DMS_MAIN_CMD_BASIC, DMS_SUBCMD_GET_DEVICE_STATE, NULL, "dmp_daemon",
DMS_SUPPORT_ALL, dms_get_device_state)
#endif
END_FEATURE_COMMAND()
END_MODULE_DECLARATION()
static int dms_event_add_recv_to_dfx(struct dms_event_obj *event_obj)
{
struct dms_event_dfx_table *dfx_table = NULL;
struct dms_dev_ctrl_block *dev_cb = NULL;
unsigned char assertion;
dev_cb = dms_get_dev_cb(event_obj->deviceid);
if (dev_cb == NULL) {
dms_err("Get dev ctrl block failed. (dev_id=%u)\n", event_obj->deviceid);
return DRV_ERROR_NO_DEVICE;
}
dfx_table = &dev_cb->dev_event_cb.dfx_table;
assertion = event_obj->event.sensor_event.assertion;
if (assertion < DMS_EVENT_TYPE_MAX) {
ka_base_atomic_inc(&dfx_table->recv_from_sensor[assertion]);
return DRV_ERROR_NONE;
}
dms_err("Invalid parameter. (assertion=%u)\n", assertion);
return DRV_ERROR_PARA_ERROR;
}
int dms_event_report(struct dms_event_obj *event_obj)
{
struct dms_event_obj obj_buf;
u32 event_num = ka_base_kfifo_len(&g_event_task.kfifo) / DMS_EVENT_KFIFO_CELL;
if ((event_obj == NULL) || dms_event_add_recv_to_dfx(event_obj)) {
dms_err("The pointer of event_obj is null or add to dfx failed. (event_obj='%s')\n",
event_obj == NULL ? "NULL" : "OK");
return DRV_ERROR_PARA_ERROR;
}
if ((DMS_EVENT_OBJ_TYPE(event_obj->node_type) != DMS_EVENT_OBJ_KERNEL) && (event_num >= DMS_EVENT_NUM_KERNEL)) {
dms_event("Dms event kfifo is over 80 percent, drop user event. (dev_id=%u; node_type=0x%X; node_id=0x%X; \
sensor_type=0x%X; event_state=%u; assertion=%u; alarm_serial_num=%u; event_num=%u)\n",
event_obj->deviceid, event_obj->node_type, event_obj->node_id,
event_obj->event.sensor_event.sensor_type, event_obj->event.sensor_event.event_state,
event_obj->event.sensor_event.assertion, event_obj->alarm_serial_num, event_num);
return DRV_ERROR_NONE;
}
ka_task_mutex_lock(&g_event_task.lock);
while (ka_base_kfifo_avail(&g_event_task.kfifo) < DMS_EVENT_KFIFO_CELL) {
if (!ka_base_kfifo_out(&g_event_task.kfifo, &obj_buf, DMS_EVENT_KFIFO_CELL)) {
dms_warn("ka_base_kfifo_out warn.\n");
}
dms_event("Dms event is covered. (dev_id=%u; node_type=0x%X; node_id=0x%X; "
"sensor_type=0x%X; event_state=%u; assertion=%u; alarm_serial_num=%u)\n",
obj_buf.deviceid, obj_buf.node_type, obj_buf.node_id,
obj_buf.event.sensor_event.sensor_type, obj_buf.event.sensor_event.event_state,
obj_buf.event.sensor_event.assertion, obj_buf.alarm_serial_num);
}
ka_base_kfifo_in(&g_event_task.kfifo, event_obj, DMS_EVENT_KFIFO_CELL);
g_event_task.event_num = ka_base_kfifo_len(&g_event_task.kfifo) / DMS_EVENT_KFIFO_CELL;
ka_task_mutex_unlock(&g_event_task.lock);
ka_task_wake_up(&g_event_task.wait);
return DRV_ERROR_NONE;
}
KA_EXPORT_SYMBOL(dms_event_report);
static inline unsigned char dms_event_convert_assertion(const struct dms_sensor_object_cb *p_sensor_obj_cb,
unsigned char event_state)
{
const struct dms_sensor_object_cfg *obj_cfg = &p_sensor_obj_cb->sensor_object_cfg;
if ((obj_cfg->assert_event_mask & (1 << event_state)) &&
!(obj_cfg->deassert_event_mask & (1 << event_state))) {
return DMS_EVENT_TYPE_ONE_TIME;
}
return DMS_EVENT_TYPE_OCCUR;
}
STATIC int dms_event_get_events_by_sensor(const struct dms_sensor_object_cb *psensor_obj_cb,
struct dms_event_para *fault_event_buf, int max_event_num, int *curr_event_num)
{
DMS_EVENT_LIST_ITEM *event_item = psensor_obj_cb->p_event_list;
DMS_EVENT_NODE_STRU exception_node;
struct dms_event_obj sensor_event;
unsigned char assertion = 0;
int event_index = (*curr_event_num);
int ret;
while (event_item != NULL) {
if (event_index >= max_event_num) {
dms_info("has get(%d) fault event number. not need to get continue.\n", max_event_num);
return 0;
}
assertion = dms_event_convert_assertion(psensor_obj_cb, event_item->event_data);
ret = dms_fill_event_data(psensor_obj_cb, event_item, assertion, &sensor_event);
if (ret != DRV_ERROR_NONE) {
dms_err("dms_fill_event_data failed, ret = %d.\n", ret);
return ret;
}
ret = dms_event_obj_to_exception(&sensor_event, &exception_node);
if (ret != DRV_ERROR_NONE) {
dms_err("dms_event_obj_to_exception failed, ret = %d.\n", ret);
return ret;
}
ret = memcpy_s((void *)&fault_event_buf[event_index], sizeof(struct dms_event_para),
(void *)&exception_node.event, sizeof(struct dms_event_para));
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
return ret;
}
*curr_event_num = (++event_index);
event_item = event_item->p_next;
}
return 0;
}
STATIC int dms_event_get_events_by_node(const struct dms_node_sensor_cb *pnode_sensor_cb,
struct dms_event_para *fault_event_buf, int max_event_num, int *curr_event_num)
{
struct dms_sensor_object_cb *tmp_sensor_ctl = NULL;
struct dms_sensor_object_cb *psensor_obj_cb = NULL;
int ret;
ka_list_for_each_entry_safe(psensor_obj_cb, tmp_sensor_ctl, &(pnode_sensor_cb->sensor_object_table), list) {
if ((psensor_obj_cb == NULL) || (psensor_obj_cb->p_event_list == NULL)) {
continue;
}
dms_debug("get event by sensor. (node_type=0x%x, node_id=%u, sensor type=0x%x)\n",
pnode_sensor_cb->node_type, pnode_sensor_cb->node_id,
psensor_obj_cb->sensor_object_cfg.sensor_type);
ret = dms_event_get_events_by_sensor(psensor_obj_cb, fault_event_buf, max_event_num, curr_event_num);
if (ret != 0) {
dms_err("get event by sensor failed. (node_type=0x%x, node_id=%u, sensor=0x%x, ret=%d)\n",
pnode_sensor_cb->node_type, pnode_sensor_cb->node_id,
psensor_obj_cb->sensor_object_cfg.sensor_type, ret);
return ret;
}
}
return 0;
}
STATIC int dms_event_get_history_fault_events(int dev_id, struct dms_event_para *fault_event_buf, int max_event_num)
{
struct dms_dev_ctrl_block *dev_cb;
struct dms_dev_sensor_cb *dev_sensor_cb;
struct dms_node_sensor_cb *pnode_sensor_cb = NULL;
struct dms_node_sensor_cb *tmp_ctl = NULL;
int event_count = 0;
int ret = DRV_ERROR_NONE;
if (dev_id != 0) {
dms_err("only support dev_id = 0, but now is %d .\n", dev_id);
return DRV_ERROR_PARA_ERROR;
}
dev_cb = dms_get_dev_cb(dev_id);
if (dev_cb == NULL) {
dms_err("dms_get_dev_cb(devid=%d) failed.\n", dev_id);
return DRV_ERROR_INNER_ERR;
}
dev_sensor_cb = &dev_cb->dev_sensor_cb;
ka_task_mutex_lock(&dev_sensor_cb->dms_sensor_mutex);
ka_list_for_each_entry_safe(pnode_sensor_cb, tmp_ctl, &(dev_sensor_cb->dms_node_sensor_cb_list), list) {
if (event_count >= max_event_num) {
dms_info("has get(%d) fault event number. not need to get continue.\n", max_event_num);
goto out;
}
dms_debug("get events from one dms node. (node_type=0x%x, node id=%u)\n",
pnode_sensor_cb->node_type, pnode_sensor_cb->node_id);
ret = dms_event_get_events_by_node(pnode_sensor_cb, fault_event_buf, max_event_num, &event_count);
if (ret != 0) {
dms_err("get events from one dms node failed. (node_type=0x%x, node id=%u, ret=%d)\n",
pnode_sensor_cb->node_type, pnode_sensor_cb->node_id, ret);
goto out;
}
}
if (event_count < max_event_num) {
fault_event_buf[event_count].event_id = 0xFFFFFFFFU;
dms_debug("The number of %d fault event is invalid.\n", event_count);
}
dms_info("There is %d fault events.\n", event_count);
out:
ka_task_mutex_unlock(&dev_sensor_cb->dms_sensor_mutex);
return ret;
}
#define MAX_EVENT_COUNT_OF_GET_FAULT_EVENT (1024)
#define MIN_EVENT_COUNT_OF_GET_FAULT_EVENT (1)
int dms_event_get_history_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len)
{
struct dms_event_para *event_para_buf;
int event_buf_size = 0;
int dev_id = 0;
int ret;
if ((in == NULL) || (out == NULL) || (in_len != sizeof(int))) {
dms_err("Invalid parameter. (in_buff=%s; out_buff=%s; in_len=%u)\n",
(in == NULL) ? "NULL" : "OK", (out == NULL) ? "NULL" : "OK", in_len);
return DRV_ERROR_PARA_ERROR;
}
ret = memcpy_s((void *)&dev_id, sizeof(int), (void *)in, in_len);
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
return DRV_ERROR_INNER_ERR;
}
event_buf_size = out_len / sizeof(struct dms_event_para);
if (event_buf_size < MIN_EVENT_COUNT_OF_GET_FAULT_EVENT ||
event_buf_size > MAX_EVENT_COUNT_OF_GET_FAULT_EVENT) {
dms_err("history_max_event_size(%d) is invalid.\n", event_buf_size);
return DRV_ERROR_PARA_ERROR;
}
if ((unsigned long)event_buf_size * sizeof(struct dms_event_para) != out_len) {
dms_err("out_len(%d) is not equal to expect(%d).\n", out_len,
(int)(event_buf_size * sizeof(struct dms_event_para)));
return DRV_ERROR_PARA_ERROR;
}
dms_info("history_max_event_size is %d.\n", event_buf_size);
event_para_buf = (struct dms_event_para*)out;
ret = dms_event_get_history_fault_events(dev_id, event_para_buf, event_buf_size);
if (ret != DRV_ERROR_NONE) {
return DRV_ERROR_INNER_ERR;
}
return DRV_ERROR_NONE;
}
int dms_event_get_fault_event(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
struct dms_event_para fault_event = {0};
struct dms_read_event_ioctl input = {0};
u64 start_syscnt;
int ret;
if ((in == NULL) || (out == NULL) ||
(in_len != sizeof(struct dms_read_event_ioctl)) || (out_len != sizeof(struct dms_event_para))) {
dms_err("Invalid parameter. (in_buff=%s; in_len=%u;out_buff=%s; out_len=%u)\n",
(in == NULL) ? "NULL" : "OK", in_len, (out == NULL) ? "NULL" : "OK", out_len);
return DRV_ERROR_PARA_ERROR;
}
start_syscnt = get_syscnt();
ret = memcpy_s((void *)&input, sizeof(struct dms_read_event_ioctl), (void *)in, in_len);
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d start_syscnt=%llu)\n", ret, start_syscnt);
return DRV_ERROR_INNER_ERR;
}
if ((input.cmd_src != FROM_DSMI) && (input.cmd_src != FROM_HAL)) {
dms_err("Invalid parameter. (cmd_srouce=%d)\n", input.cmd_src);
return DRV_ERROR_PARA_ERROR;
}
ret = dms_event_get_exception(&fault_event, input.timeout, input.cmd_src);
if (ret == -ETIMEDOUT) {
return ret;
} else if (ret == -ERESTARTSYS) {
dms_warn("Get exception is interrupted. (timeout=%dms; ret=%d)\n", input.timeout, ret);
return ret;
} else if (ret != 0) {
dms_err("Get exception failed. (timeout=%dms; ret=%d)\n", input.timeout, ret);
return ret;
}
ret = memcpy_s((void *)out, out_len, (void *)&fault_event, sizeof(struct dms_event_para));
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
return DRV_ERROR_INNER_ERR;
}
dms_warn("read fault event success.(dev_id=%u; event_id=0x%x; start=%llu; end=%llu)\n",
fault_event.deviceid, fault_event.event_id, start_syscnt, get_syscnt());
return DRV_ERROR_NONE;
}
STATIC int check_and_trans_devid(char *in, u32 in_len, u32 *phy_id)
{
int ret;
u32 dev_id = 0;
u32 fid = 0xFFFFFFFFU;
ret = memcpy_s(&dev_id, sizeof(int), in, in_len);
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
return DRV_ERROR_INNER_ERR;
}
ret = smf_logical_id_to_physical_id(dev_id, phy_id, &fid);
if (ret != 0 || (fid >= VMNG_VDEV_MAX_PER_PDEV)) {
dms_err("Transform logical id to physical id failed. "
"(devid=%u; phyid=%u; fid=%u; ret=%d)\n",
dev_id, *phy_id, fid, ret);
return DRV_ERROR_NO_DEVICE;
}
return 0;
}
STATIC int add_events_to_event_para(struct dms_event_para *dms_event, u32 event_num,
struct devdrv_event_obj_para *event_para)
{
int ret;
u32 i;
u32 num = event_para->event_count;
for (i = 0; i < event_num; i++) {
if (num >= DMS_MAX_EVENT_ARRAY_LENGTH) {
return 0;
}
ret = memcpy_s(&event_para->dms_event[num], sizeof(struct dms_event_para),
&dms_event[i], sizeof(struct dms_event_para));
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
return ret;
}
num++;
}
event_para->event_count = num;
return 0;
}
#ifdef CFG_EDGE_HOST
STATIC int dms_get_remote_fault_event(u32 phy_id, struct devdrv_event_obj_para *event_para)
{
struct dms_event_para *dms_event_remote = NULL;
u32 event_num_remote = 0;
int ret;
dms_event_remote = (struct dms_event_para *)dbl_vmalloc(sizeof(struct dms_event_para) * DMS_MAX_EVENT_ARRAY_LENGTH,
KA_GFP_KERNEL | __KA_GFP_ZERO | __KA_GFP_ACCOUNT, KA_PAGE_KERNEL);
if (dms_event_remote == NULL) {
dms_err("Call ka_vmalloc failed. (phy_id=%u)\n", phy_id);
return DRV_ERROR_OUT_OF_MEMORY;
}
ret = smf_get_remote_event_para(phy_id, dms_event_remote, DMS_MAX_EVENT_ARRAY_LENGTH, &event_num_remote);
if (ret != 0) {
dms_err("Get fault event para failed. (phy_id=%u; ret=%d)\n", phy_id, ret);
goto GET_EVENT_FAIL;
}
ret = add_events_to_event_para(dms_event_remote, event_num_remote, event_para);
if (ret != 0) {
dms_err("Add remote events to event_pars failed. (phy_id=%u; ret=%d)\n", phy_id, ret);
}
GET_EVENT_FAIL:
dbl_vfree(dms_event_remote);
dms_event_remote = NULL;
return ret;
}
#else
STATIC int dms_get_event_para_from_local_sensor(int dev_id, struct dms_event_para *dms_event,
u32 in_cnt, u32 *event_num)
{
struct dms_dev_ctrl_block *dev_cb = NULL;
struct dms_event_obj *event_buff = NULL;
DMS_EVENT_NODE_STRU exception_node = {{0}, {0}};
u32 out_cnt = 0;
int ret;
int i;
dev_cb = dms_get_dev_cb(dev_id);
if (dev_cb == NULL) {
dms_err("Get dev_ctrl block failed. (dev_id=%u)\n", dev_id);
return DRV_ERROR_NO_DEVICE;
}
event_buff = (struct dms_event_obj *)dbl_kzalloc(sizeof(struct dms_event_obj) *
DMS_EVENT_ERROR_ARRAY_NUM, KA_GFP_KERNEL | __KA_GFP_ACCOUNT);
if (event_buff == NULL) {
dms_err("Call ka_mm_kzalloc failed. (dev_id=%u)\n", dev_id);
return DRV_ERROR_OUT_OF_MEMORY;
}
ret = dms_sensor_get_health_events(&dev_cb->dev_sensor_cb, event_buff, DMS_EVENT_ERROR_ARRAY_NUM, &out_cnt);
if (ret != 0) {
dms_err("Get health events failed. (dev_id=%u; ret=%d)\n", dev_id, ret);
goto FREE_BUFF;
}
if (out_cnt > in_cnt) {
out_cnt = in_cnt;
}
for (i = 0 ; i < out_cnt; i++) {
ret = dms_event_obj_to_exception(&event_buff[i], &exception_node);
if (ret != 0) {
dms_err("dms_event_obj_to_exception failed. (dev_id=%u; ret=%d)\n", dev_id, ret);
goto FREE_BUFF;
}
ret = memcpy_s(&dms_event[i], sizeof(struct dms_event_para), &exception_node.event,
sizeof(struct dms_event_para));
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
ret = DRV_ERROR_INNER_ERR;
goto FREE_BUFF;
}
}
*event_num = out_cnt;
FREE_BUFF:
dbl_kfree(event_buff);
event_buff = NULL;
return ret;
}
STATIC int dms_get_local_fault_event(u32 phy_id, struct devdrv_event_obj_para *event_para)
{
struct dms_event_para *dms_event_local = NULL;
u32 event_num_local = 0;
int ret;
dms_event_local = (struct dms_event_para *)dbl_vmalloc(sizeof(struct dms_event_para) * DMS_MAX_EVENT_ARRAY_LENGTH,
KA_GFP_KERNEL | __KA_GFP_ZERO | __KA_GFP_ACCOUNT, KA_PAGE_KERNEL);
if (dms_event_local == NULL) {
dms_err("Call ka_vmalloc failed. (phy_id=%u)\n", phy_id);
return DRV_ERROR_OUT_OF_MEMORY;
}
ret = dms_get_event_para_from_local_sensor(phy_id, dms_event_local, DMS_MAX_EVENT_ARRAY_LENGTH, &event_num_local);
if (ret != 0) {
dms_err("Get fault event para failed. (phy_id=%u; ret=%d)\n", phy_id, ret);
goto GET_EVENT_FAIL;
}
ret = add_events_to_event_para(dms_event_local, event_num_local, event_para);
if (ret != 0) {
dms_err("Add local events to event_para failed. (phy_id=%u; ret=%d)\n", phy_id, ret);
}
GET_EVENT_FAIL:
dbl_vfree(dms_event_local);
dms_event_local = NULL;
return ret;
}
#endif
STATIC int dms_get_all_fault_event(u32 phy_id, struct devdrv_event_obj_para *event_para)
{
int ret;
#ifdef CFG_EDGE_HOST
ret = dms_get_remote_fault_event(phy_id, event_para);
if (ret != 0) {
dms_err("Get remote event failed. (phy_id=%u)\n", phy_id);
return ret;
}
#else
ret = dms_get_local_fault_event(phy_id, event_para);
if (ret != 0) {
dms_err("Get local event failed. (phy_id=%u)\n", phy_id);
return ret;
}
#endif
return ret;
}
int dms_event_get_current_fault_event(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
struct devdrv_event_obj_para *event_para = NULL;
unsigned int phy_id = 0;
int ret = 0;
if ((in == NULL) || (out == NULL)) {
dms_err("Invalid parameter. (in_buff=%s; out_buff=%s)\n",
(in == NULL) ? "NULL" : "OK", (out == NULL) ? "NULL" : "OK");
return DRV_ERROR_PARA_ERROR;
}
if ((in_len != sizeof(int)) || (out_len != sizeof(struct devdrv_event_obj_para))) {
dms_err("Invalid parameter. (expected in_len=%lu; in_len=%u; expected out_len=%lu; out_len=%u)\n",
sizeof(int), in_len, sizeof(struct devdrv_event_obj_para), out_len);
return DRV_ERROR_PARA_ERROR;
}
ret = check_and_trans_devid(in, in_len, &phy_id);
if (ret != 0) {
dms_err("check or transform device id failed. (ret=%d)\n", ret);
return ret;
}
event_para = (struct devdrv_event_obj_para *)out;
event_para->event_count = 0;
ret = dms_get_all_fault_event(phy_id, event_para);
if (ret != 0) {
dms_err("Get events failed. (phy_id=%u; ret=%d)", phy_id, ret);
return ret;
}
return 0;
}
int dms_event_clear_by_phyid(u32 phyid)
{
struct dms_dev_ctrl_block *dev_cb = NULL;
int ret;
dev_cb = dms_get_dev_cb(phyid);
if (dev_cb == NULL) {
dms_err("Get dev_ctrl block failed. (phyid=%u)\n", phyid);
return DRV_ERROR_NO_DEVICE;
}
ret = dms_event_clear_exception(phyid);
if (ret != 0) {
dms_err("Clear exception failed. (phyid=%u; ret=%d)\n", phyid, ret);
return ret;
}
if (dms_event_is_converge() != 0) {
ret = dms_event_convergent_diagrams_clear(phyid, false);
if (ret != 0) {
dms_err("Clear convergent diagrams failed. (phyid=%u; ret=%d)\n", phyid, ret);
return ret;
}
}
ret = dms_sensor_clean_health_events(&dev_cb->dev_sensor_cb);
if (ret != 0) {
dms_err("Clean health event failed. (phyid=%u; ret=%d)\n", phyid, ret);
return ret;
}
#if defined(CFG_FEATURE_GET_CURRENT_EVENTINFO) && defined(CFG_EDGE_HOST)
dms_release_one_device_remote_event(phyid);
#endif
if (smf_event_distribute_to_bar(phyid) != 0) {
dms_err("Distribute event to bar failed. (dev_id=%u)\n", phyid);
return DRV_ERROR_INNER_ERR;
}
dms_event("Clear event success. (phyid=%u)\n", phyid);
return DRV_ERROR_NONE;
}
KA_EXPORT_SYMBOL(dms_event_clear_by_phyid);
static int dms_event_get_logic_id_and_covert_to_phy_id(char *in, u32 in_len, u32 *logic_id, u32 *phy_id, u32 *fid)
{
int ret;
ret = memcpy_s((void *)logic_id, sizeof(u32), (void *)in, in_len);
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
return ret;
}
ret = smf_logical_id_to_physical_id(*logic_id, phy_id, fid);
if (ret || (*fid >= VMNG_VDEV_MAX_PER_PDEV)) {
dms_err("Transform logical id to physical id failed. "
"(devid=%u; phyid=%u; fid=%u; ret=%d)\n",
*logic_id, *phy_id, *fid, ret);
return DRV_ERROR_NO_DEVICE;
}
return DRV_ERROR_NONE;
}
int dms_event_clear_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len)
{
u32 devid = 0;
u32 phyid = 0;
u32 fid = 0;
int ret;
if ((in == NULL) || (in_len != sizeof(u32))) {
dms_err("Invalid parameter. (in_buff=%s; in_len=%u)\n", (in == NULL) ? "NULL" : "OK", in_len);
return DRV_ERROR_PARA_ERROR;
}
ret = dms_event_get_logic_id_and_covert_to_phy_id(in, in_len, &devid, &phyid, &fid);
if (ret != 0) {
dms_err("Get logical id or convert to physical id failed. (ret=%d)\n", ret);
return ret;
}
ret = smf_event_clean_to_device(phyid);
if (ret != 0) {
dms_err("Clean event to device failed. (phyid=%u)\n", phyid);
return ret;
}
ret = dms_event_clear_by_phyid(phyid);
if (ret != 0) {
dms_err("Clear exception failed. (phyid=%u; ret=%d)\n", phyid, ret);
return ret;
}
return DRV_ERROR_NONE;
}
int dms_event_mask_by_phyid(u32 phyid, u32 event_id, u8 mask)
{
struct dms_dev_ctrl_block *dev_cb = NULL;
u32 node_type, sensor_type, event_state;
int ret;
if (dms_event_code_validity_check(event_id) != 0) {
return DRV_ERROR_NO_EVENT;
}
dev_cb = dms_get_dev_cb(phyid);
if (dev_cb == NULL) {
dms_err("Get dev_ctrl block failed. (phyid=%u)\n", phyid);
return DRV_ERROR_NO_DEVICE;
}
node_type = DMS_EVENT_ID_TO_NODE_TYPE(event_id);
sensor_type = DMS_EVENT_ID_TO_SENSOR_TYPE(event_id);
event_state = DMS_EVENT_ID_TO_EVENT_STATE(event_id);
ret = dms_sensor_mask_events(&dev_cb->dev_sensor_cb, mask, (u16)node_type, (u8)sensor_type, (u8)event_state);
if (ret != 0) {
dms_err("Mask event code failed. (phyid=%u; event_id=0x%x; mask=%u; ret=%d)\n",
phyid, event_id, mask, ret);
return ret;
}
if (dms_event_is_converge() != 0) {
if (mask == EVENT_CONVERGE_NODE_DISENABLE) {
dms_event_mask_del_to_event_cb(phyid, dev_cb, event_id);
dms_event_add_to_mask_list(dev_cb, event_id);
} else if (mask == EVENT_CONVERGE_NODE_ENABLE) {
dms_event_mask_add_to_event_cb(phyid, dev_cb, event_id);
dms_event_del_to_mask_list(dev_cb, event_id);
}
dms_event_convergent_diagrams_mask(phyid, event_id, mask);
}
if (smf_event_distribute_to_bar(phyid) != 0) {
dms_err("Distribute event to bar failed. (dev_id=%u)\n", phyid);
return DRV_ERROR_INNER_ERR;
}
dms_event("Mask event_id success. (phyid=%u; event_id=0x%X; mask=%u; ret=%d)\n",
phyid, event_id, mask, ret);
return DRV_ERROR_NONE;
}
KA_EXPORT_SYMBOL(dms_event_mask_by_phyid);
int dms_event_disable_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len)
{
struct dms_event_ioctrl para = {0};
u32 locid, phyid, fid;
int ret;
if ((in == NULL) || (in_len != sizeof(struct dms_event_ioctrl))) {
dms_err("Invalid parameter. (in_buff=%s; in_len=%u)\n", (in == NULL) ? "NULL" : "OK", in_len);
return DRV_ERROR_PARA_ERROR;
}
ret = memcpy_s((void *)¶, sizeof(struct dms_event_ioctrl), (void *)in, in_len);
if (ret != 0) {
dms_err("Disable memcpy_s failed. (ret=%d)\n", ret);
return ret;
}
ret = dms_event_get_logic_id_and_covert_to_phy_id((char *)¶.devid,
sizeof(para.devid), &locid, &phyid, &fid);
if (ret != 0) {
dms_err("Disable logical id or convert to physical id failed. (ret=%d)\n", ret);
return ret;
}
ret = smf_event_mask_event_code(phyid, para.event_code, EVENT_CONVERGE_NODE_DISENABLE);
if (ret != 0) {
dms_err("Disable event code failed. (phyid=%u; event_code=0x%x; ret=%d)\n",
phyid, para.event_code, ret);
return ret;
}
return DRV_ERROR_NONE;
}
int dms_event_enable_fault_event(void *feature, char *in, u32 in_len,
char *out, u32 out_len)
{
struct dms_event_ioctrl para = {0};
u32 locid, phyid, fid;
int ret;
if ((in == NULL) || (in_len != sizeof(struct dms_event_ioctrl))) {
dms_err("Invalid parameter. (in_buff=%s; in_len=%u)\n", (in == NULL) ? "NULL" : "OK", in_len);
return DRV_ERROR_PARA_ERROR;
}
ret = memcpy_s((void *)¶, sizeof(struct dms_event_ioctrl), (void *)in, in_len);
if (ret != 0) {
dms_err("Enable memcpy_s failed. (ret=%d)\n", ret);
return ret;
}
ret = dms_event_get_logic_id_and_covert_to_phy_id((char *)¶.devid,
sizeof(para.devid), &locid, &phyid, &fid);
if (ret != 0) {
dms_err("Enable logical id or convert to physical id failed. (ret=%d)\n", ret);
return ret;
}
ret = smf_event_mask_event_code(phyid, para.event_code, EVENT_CONVERGE_NODE_ENABLE);
if (ret != 0) {
dms_err("Enable event code failed. (phyid=%u; event_code=0x%x; ret=%d)\n",
phyid, para.event_code, ret);
return ret;
}
return DRV_ERROR_NONE;
}
int dms_get_code_from_sensor_check(u32 devid, u32 *health_code, u32 health_len,
struct shm_event_code *event_code, u32 event_len)
{
if ((devid >= ASCEND_DEV_MAX_NUM) || (health_code == NULL) ||
(health_len != VMNG_VDEV_MAX_PER_PDEV) || (event_code == NULL) ||
(event_len != DEVMNG_SHM_INFO_EVENT_CODE_LEN)) {
dms_err("Invalid parameter. (devid=%u; health_code=\"%s\"; health_len=%u; "
"event_code=\"%s\"; event_len=%u;)\n", devid, (health_code == NULL) ? "NULL" : "OK",
health_len, (event_code == NULL) ? "NULL" : "OK", event_len);
return DRV_ERROR_PARA_ERROR;
}
(void)memset_s(event_code, sizeof(struct shm_event_code) * event_len,
0, sizeof(struct shm_event_code) * event_len);
(void)memset_s(health_code, sizeof(u32) * health_len, 0, sizeof(u32) * health_len);
return DRV_ERROR_NONE;
}
static int dms_event_obj_to_health_code(struct dms_event_obj *event_buff,
u32 event_cnt, u32 *health_code, struct shm_event_code *event_code)
{
u32 fid_buf = 0;
u32 i, severity;
if (event_cnt > DEVMNG_SHM_INFO_EVENT_CODE_LEN) {
dms_err("The number of events is invalid. (cnt=%u)\n", event_cnt);
return DRV_ERROR_INNER_ERR;
}
for (i = 0; i < event_cnt; i++) {
if (fid_buf >= VMNG_VDEV_MAX_PER_PDEV) {
dms_err("The fid is invalid. (fid=%u)\n", fid_buf);
continue;
}
(void)dms_event_obj_to_error_code(event_buff[i], &event_code[i].event_code);
severity = event_buff[i].severity;
health_code[fid_buf] = (severity > health_code[fid_buf]) ? severity : health_code[fid_buf];
event_code[i].fid = (u8)fid_buf;
}
for (i = 0; i < VMNG_VDEV_MAX_PER_PDEV; i++) {
health_code[0] = (health_code[i] > health_code[0]) ? health_code[i] : health_code[0];
}
return DRV_ERROR_NONE;
}
int dms_get_event_code_from_sensor(u32 devid, u32 *health_code, u32 health_len,
struct shm_event_code *event_code, u32 event_len)
{
struct dms_dev_ctrl_block *dev_cb = NULL;
struct dms_event_obj *event_buff = NULL;
u32 out_cnt = 0;
int ret;
if (dms_get_code_from_sensor_check(devid, health_code, health_len, event_code, event_len) != 0) {
dms_err("Invalid parameter.\n");
return DRV_ERROR_PARA_ERROR;
}
dev_cb = dms_get_dev_cb(devid);
if (dev_cb == NULL) {
dms_err("Get dev_ctrl block failed. (dev_id=%u)\n", devid);
return DRV_ERROR_NO_DEVICE;
}
event_buff = (struct dms_event_obj *)dbl_kzalloc(sizeof(struct dms_event_obj) *
DMS_EVENT_ERROR_ARRAY_NUM, KA_GFP_KERNEL | __KA_GFP_ACCOUNT);
if (event_buff == NULL) {
dms_err("Call ka_mm_kzalloc failed. (dev_id=%u)\n", devid);
return DRV_ERROR_OUT_OF_MEMORY;
}
ret = dms_sensor_get_health_events(&dev_cb->dev_sensor_cb, event_buff, (unsigned int)DMS_EVENT_ERROR_ARRAY_NUM, &out_cnt);
if (ret != 0) {
dms_err("Get health events failed. (dev_id=%u; ret=%d)\n", devid, ret);
goto free_buff;
}
ret = dms_event_obj_to_health_code(event_buff, out_cnt, health_code, event_code);
if (ret != 0) {
dms_err("Transform event_obj to health code failed. (dev_id=%u; ret=%d)\n",
devid, ret);
goto free_buff;
}
free_buff:
dbl_kfree(event_buff);
event_buff = NULL;
return ret;
}
KA_EXPORT_SYMBOL(dms_get_event_code_from_sensor);
static int dms_get_event_code_para_check(u32 devid, u32 fid, u32 *health_code,
struct devdrv_error_code_para *code_para)
{
if ((devid >= ASCEND_DEV_MAX_NUM) || (fid >= VMNG_VDEV_MAX_PER_PDEV) ||
(health_code == NULL) || (code_para == NULL)) {
dms_err("Invalid parameter. (dev_id=%u; fid=%u; health_code=\"%s\"; code_para=\"%s\")\n",
devid, fid, (health_code == NULL) ? "NULL" : "OK", (code_para == NULL) ? "NULL" : "OK");
return DRV_ERROR_PARA_ERROR;
}
(void)memset_s(code_para, sizeof(struct devdrv_error_code_para),
0, sizeof(struct devdrv_error_code_para));
return DRV_ERROR_NONE;
}
STATIC int smf_get_event_code(u32 devid, u32 *sensor_health, u32 *dev_health,
struct shm_event_code *sensor_event, struct shm_event_code *dev_event)
{
int connect_type = CONNECT_PROTOCOL_UNKNOWN;
int ret = 0;
connect_type = smf_get_connect_protocol(devid);
if (connect_type < 0) {
dms_err("Get host device connect type failed. (dev_id=%u; ret=%d)\n", devid, connect_type);
return -EINVAL;
} else if (connect_type == CONNECT_PROTOCOL_UB) {
ret = smf_get_event_code_from_local(devid, dev_health, dev_event, DEVMNG_SHM_INFO_EVENT_CODE_LEN);
} else {
if (dms_event_is_converge() != 0) {
ret = dms_get_event_code_from_event_cb(devid, sensor_health, VMNG_VDEV_MAX_PER_PDEV,
sensor_event, DEVMNG_SHM_INFO_EVENT_CODE_LEN);
if (ret != 0) {
dms_err("Get event code from event cb failed. (dev_id=%u; ret=%d)\n", devid, ret);
return ret;
}
} else {
ret = dms_get_event_code_from_sensor(devid, sensor_health, VMNG_VDEV_MAX_PER_PDEV,
sensor_event, DEVMNG_SHM_INFO_EVENT_CODE_LEN);
if (ret != 0) {
dms_err("Get event code from sensor manager failed. (dev_id=%u; ret=%d)\n", devid, ret);
return ret;
}
}
ret = smf_get_event_code_from_bar(devid, dev_health, VMNG_VDEV_MAX_PER_PDEV,
dev_event, DEVMNG_SHM_INFO_EVENT_CODE_LEN);
}
if (ret != 0) {
dms_err("Get event code failed. (dev_id=%u; ret=%d)\n", devid, ret);
}
return ret;
}
STATIC int smf_get_health_code(u32 devid, u32 *health_code, u32 health_len)
{
int connect_type = CONNECT_PROTOCOL_UNKNOWN;
connect_type = smf_get_connect_protocol(devid);
if (connect_type < 0) {
dms_err("Get host device connect type failed. (dev_id=%u; ret=%d)\n", devid, connect_type);
return -EINVAL;
} else if (connect_type == CONNECT_PROTOCOL_UB) {
return smf_get_health_code_from_local(devid, health_code);
} else {
return smf_get_health_code_from_bar(devid, health_code, health_len);
}
}
static void dms_event_combine_event_code(u32 fid, struct shm_event_code *sensor_event,
struct shm_event_code *bar_event, struct devdrv_error_code_para *code_para)
{
int sum_cnt = 0;
int i;
for (i = 0; (i < DEVMNG_SHM_INFO_EVENT_CODE_LEN) &&
(sum_cnt < DMANAGE_ERROR_ARRAY_NUM); i++) {
if (sensor_event[i].event_code == 0) {
break;
}
if ((fid == 0) || (fid == sensor_event[i].fid)) {
code_para->error_code[sum_cnt++] = sensor_event[i].event_code;
}
}
for (i = 0; (i < DEVMNG_SHM_INFO_EVENT_CODE_LEN) &&
(sum_cnt < DMANAGE_ERROR_ARRAY_NUM); i++) {
if (bar_event[i].event_code == 0) {
break;
}
if ((fid == 0) || (fid == bar_event[i].fid)) {
code_para->error_code[sum_cnt++] = bar_event[i].event_code;
}
}
code_para->error_code_count = sum_cnt;
}
STATIC int dms_get_event_code(u32 devid, u32 fid, u32 *health_code,
struct devdrv_error_code_para *code_para)
{
struct shm_event_code *sensor_event, *bar_event;
u32 sensor_health[VMNG_VDEV_MAX_PER_PDEV] = {0};
u32 bar_health[VMNG_VDEV_MAX_PER_PDEV] = {0};
int ret;
if (dms_get_event_code_para_check(devid, fid, health_code, code_para) != 0) {
dms_err("Invalid parameter.\n");
return DRV_ERROR_PARA_ERROR;
}
sensor_event = (struct shm_event_code *)dbl_kzalloc(sizeof(struct shm_event_code) * \
DEVMNG_SHM_INFO_EVENT_CODE_LEN, KA_GFP_KERNEL | __KA_GFP_ACCOUNT);
if (sensor_event == NULL) {
dms_err("Call ka_mm_kzalloc sensor_event failed. (dev_id=%u)\n", devid);
return DRV_ERROR_OUT_OF_MEMORY;
}
bar_event = (struct shm_event_code *)dbl_kzalloc(sizeof(struct shm_event_code) * \
DEVMNG_SHM_INFO_EVENT_CODE_LEN, KA_GFP_KERNEL | __KA_GFP_ACCOUNT);
if (bar_event == NULL) {
dbl_kfree(sensor_event);
dms_err("Call ka_mm_kzalloc bar_event failed. (dev_id=%u)\n", devid);
return DRV_ERROR_OUT_OF_MEMORY;
}
ret = smf_get_event_code(devid, sensor_health, bar_health, sensor_event, bar_event);
if (ret != 0) {
dms_err("Get event code from bar zone failed. (dev_id=%u; ret=%d)\n", devid, ret);
goto out;
}
dms_event_combine_event_code(fid, sensor_event, bar_event, code_para);
*health_code = (sensor_health[fid] > bar_health[fid]) ? sensor_health[fid] : bar_health[fid];
out:
dbl_kfree(sensor_event);
dbl_kfree(bar_event);
return ret;
}
int dms_get_error_code(void *feature, char *in, u32 in_len,
char *out, u32 out_len)
{
int ret;
u32 devid = 0;
u32 phyid = 0;
u32 fid = 0;
u32 health_code = 0;
struct devdrv_error_code_para code_para = {0};
if ((in == NULL) || (out == NULL) || (in_len != sizeof(u32)) ||
(out_len != sizeof(struct devdrv_error_code_para))) {
dms_err("Invalid parameter. (in_buff=%s; in_len=%u;out_buff=%s; out_len=%u)\n",
(in == NULL) ? "NULL" : "OK", in_len, (out == NULL) ? "NULL" : "OK", out_len);
return DRV_ERROR_PARA_ERROR;
}
ret = dms_event_get_logic_id_and_covert_to_phy_id(in, in_len, &devid, &phyid, &fid);
if (ret != 0) {
dms_err("Get logical id or convert to physical id failed. (ret=%d)\n", ret);
return ret;
}
fid = 0;
ret = dms_get_event_code(phyid, fid, &health_code, &code_para);
if (ret != 0) {
dms_err("Get event code failed. (phyid=%u; fid=%u; ret=%d)\n", phyid, fid, ret);
return ret;
}
ret = memcpy_s((void *)out, out_len, (void *)&code_para, sizeof(struct devdrv_error_code_para));
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
return ret;
}
return DRV_ERROR_NONE;
}
static int dms_get_health_code(u32 phyid, u32 fid, u32 *health_code)
{
u32 bar_health[VMNG_VDEV_MAX_PER_PDEV] = {0};
struct dms_dev_ctrl_block *dev_cb = NULL;
int ret;
ret = smf_get_health_code(phyid, bar_health, VMNG_VDEV_MAX_PER_PDEV);
if (ret != 0) {
dms_err("Get health code failed. (phyid=%u; fid=%u; ret=%d)\n", phyid, fid, ret);
return ret;
}
dev_cb = dms_get_dev_cb(phyid);
if (dev_cb == NULL) {
dms_err("Get dev_ctrl block failed. (phyid=%u)\n", phyid);
return DRV_ERROR_NO_DEVICE;
}
if (dms_event_is_converge() != 0) {
*health_code = dev_cb->dev_event_cb.event_list.health_code;
} else {
*health_code = dms_sensor_get_dev_health(&dev_cb->dev_sensor_cb);
}
*health_code = (bar_health[fid] > *health_code) ? bar_health[fid] : *health_code;
return DRV_ERROR_NONE;
}
int dms_get_device_health(void *feature, char *in, u32 in_len,
char *out, u32 out_len)
{
int ret;
u32 devid = 0;
u32 phyid = 0;
u32 fid = 0;
u32 health_code = 0;
if ((in == NULL) || (out == NULL) || (in_len != sizeof(u32)) || (out_len != sizeof(u32))) {
dms_err("Invalid parameter. (in_buff=%s; in_len=%u;out_buff=%s; out_len=%u)\n",
(in == NULL) ? "NULL" : "OK", in_len, (out == NULL) ? "NULL" : "OK", out_len);
return DRV_ERROR_PARA_ERROR;
}
ret = dms_event_get_logic_id_and_covert_to_phy_id(in, in_len, &devid, &phyid, &fid);
if (ret != 0) {
dms_err("Get logical id or convert to physical id failed. (ret=%d)\n", ret);
return ret;
}
fid = 0;
ret = dms_get_health_code(phyid, fid, &health_code);
if (ret != 0) {
dms_err("Get health code failed. (phyid=%u; fid=%u; ret=%d)\n", phyid, fid, ret);
return ret;
}
ret = memcpy_s((void *)out, out_len, (void *)&health_code, sizeof(u32));
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
return ret;
}
return DRV_ERROR_NONE;
}
int dms_query_error_str(void *feature, char *in, u32 in_len,
char *out, u32 out_len)
{
struct dms_event_ioctrl para = {0};
u32 locid, phyid, fid;
int ret;
if ((in == NULL) || (out == NULL) || (in_len != sizeof(struct dms_event_ioctrl))) {
dms_err("Invalid parameter. (in_buff=%s; out_buff=%s; in_len=%u)\n",
(in == NULL) ? "NULL" : "OK", (out == NULL) ? "NULL" : "OK", in_len);
return DRV_ERROR_PARA_ERROR;
}
ret = memcpy_s((void *)¶, sizeof(struct dms_event_ioctrl), (void *)in, in_len);
if (ret != 0) {
dms_err("Call memcpy_s failed. (ret=%d)\n", ret);
return ret;
}
if (DMS_EVENT_ID_IS_BBOX_CODE(para.event_code) != 0) {
dms_debug("The event code is bbox code. (devi_id=%u; event_code=0x%x)\n", para.devid, para.event_code);
return DRV_ERROR_NO_EVENT;
}
ret = dms_event_get_logic_id_and_covert_to_phy_id((char *)¶.devid,
sizeof(para.devid), &locid, &phyid, &fid);
if (ret != 0) {
dms_err("Get logical id or convert to physical id failed. (ret=%d)\n", ret);
return ret;
}
ret = dms_event_id_to_error_string(phyid, para.event_code, out, out_len);
if (ret != 0) {
dms_err("Transform event_id to event_name failed. "
"(devid=%u; phyid=%u; event_id=%u; ret=%d)\n",
para.devid, phyid, para.event_code, ret);
return ret;
}
return DRV_ERROR_NONE;
}
#ifdef CFG_FEATURE_DEVICE_STATE_TABLE
struct dms_node_state {
unsigned int node_type;
unsigned int node_id;
unsigned int init_state;
unsigned int current_state;
unsigned int resv[2];
};
STATIC int dms_get_device_table_para_check(struct dms_device_state_out *state_out, u32 out_len)
{
if (state_out == NULL) {
dms_err("para is null.\n");
return -EINVAL;
}
if ((size_t)out_len < sizeof(struct dms_device_state_out)) {
dms_err("out len error. (out_len=%u; target=%zu)\n", out_len, sizeof(struct dms_device_state_out));
return -EINVAL;
}
return 0;
}
STATIC int dms_get_item_state(struct dms_node_state *state, struct state_item *item, uint32_t out_num)
{
struct dms_dev_ctrl_block *dev_cb = NULL;
struct dms_node *node = NULL;
uint32_t i;
int ret;
dev_cb = dms_get_dev_cb(0);
if (dev_cb == NULL) {
dms_err("state table get dev cb failed\n");
return -EINVAL;
}
ka_task_mutex_lock(&dev_cb->node_lock);
for (i = 0; i < out_num; i++) {
state[i].node_type = item[i].node_type;
state[i].node_id = item[i].node_id;
node = item[i].node;
if (node == NULL) {
state[i].init_state = (uint32_t)DMS_DEV_INIT_NOT_REGISTER;
continue;
}
state[i].current_state = node->state;
if ((node->ops == NULL) || (node->ops->get_init_state == NULL)) {
state[i].init_state = (uint32_t)DMS_DEV_INIT_NOT_REGISTER;
continue;
}
ret = node->ops->get_init_state(node, &state[i].init_state);
if (ret != 0) {
dms_warn("state table call init func warn, (node_type=%d; node_id=%d; ret=%d)\n", node->node_type, node->node_id, ret);
state[i].init_state = (uint32_t)DMS_DEV_INIT_NOT_REGISTER;
}
}
ka_task_mutex_unlock(&dev_cb->node_lock);
return 0;
}
STATIC int dms_get_device_state_table(struct dms_device_state_out *state_out, uint32_t out_len)
{
struct dms_node_state *state = NULL;
struct dms_state_table *table = dms_get_state_table();
struct state_item *item = table->item;
size_t state_size;
int ret;
unsigned int max_num, out_num;
if (table->num == 0) {
state_out->buf_size = 0;
return 0;
}
max_num = (out_len - sizeof(unsigned long))/ sizeof(struct dms_node_state);
out_num = (max_num < table->num) ? max_num : table->num;
state_size = out_num * sizeof(struct dms_node_state);
state = (struct dms_node_state *)(state_out->buf);
ret = dms_get_item_state(state, item, out_num);
if (ret != 0) {
return ret;
}
state_out->buf_size = state_size;
return 0;
}
int dms_get_device_state(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
struct dms_device_state_out *state_out = (struct dms_device_state_out *)out;
int ret;
ret = dms_get_device_table_para_check(state_out, out_len);
if (ret != 0) {
return ret;
}
ret = dms_get_device_state_table(state_out, out_len);
return ret;
}
#endif
static int dms_event_poll_event(struct dms_event_obj *event_obj, u32 wait_time, u32 *event_num)
{
if (ka_task_wait_event_interruptible_timeout(g_event_task.wait, (g_event_task.event_num > 0), wait_time) == 0) {
return ETIMEDOUT;
}
if (ka_base_atomic_read(&g_event_task.poll_flag) != (int)EVENT_POLL_WORK) {
ka_system_msleep(DMS_EVENT_TASK_WAIT_TIMEOUT_MS);
return DRV_ERROR_UNINIT;
}
ka_task_mutex_lock(&g_event_task.lock);
if (ka_base_kfifo_len(&g_event_task.kfifo) < DMS_EVENT_KFIFO_CELL) {
g_event_task.event_num = ka_base_kfifo_len(&g_event_task.kfifo) / DMS_EVENT_KFIFO_CELL;
ka_task_mutex_unlock(&g_event_task.lock);
dms_warn("There is no event in event fifo.\n");
return DRV_ERROR_INNER_ERR;
}
if (!ka_base_kfifo_out(&g_event_task.kfifo, event_obj, DMS_EVENT_KFIFO_CELL)) {
g_event_task.event_num = ka_base_kfifo_len(&g_event_task.kfifo) / DMS_EVENT_KFIFO_CELL;
ka_task_mutex_unlock(&g_event_task.lock);
dms_err("ka_base_kfifo_out failed.\n");
return DRV_ERROR_INNER_ERR;
}
g_event_task.event_num = ka_base_kfifo_len(&g_event_task.kfifo) / DMS_EVENT_KFIFO_CELL;
*event_num = g_event_task.event_num;
ka_task_mutex_unlock(&g_event_task.lock);
return DRV_ERROR_NONE;
}
#ifdef CFG_FEATURE_LOG_STANDARD_FAULT_EVENT
static const char *g_event_severity_name[DMS_EVENT_MAX] = {
"OK",
"Warning",
"Alarm",
"Critical"
};
static const char *g_event_assertion_name[DMS_EVENT_TYPE_MAX] = {
"Event resume",
"Event occur",
"One time event"
};
static void dms_get_assertion_name(unsigned char assertion, char *assertion_name, unsigned int buf_len)
{
if (assertion >= DMS_EVENT_TYPE_MAX || buf_len == 0 || assertion_name == NULL) {
dms_err("Invalid para. (assertion=%u; buf_len=%u; assertion_name is NULL=%d)\n",
assertion, buf_len, assertion_name == NULL);
return;
}
if (strcpy_s(assertion_name, buf_len, g_event_assertion_name[assertion]) != 0) {
dms_err("Call strcpy_s failed. (assertion_name=\"%s\")\n", g_event_assertion_name[assertion]);
return;
}
return;
}
static void dms_get_severity_name(unsigned int severity, char *severity_name, unsigned int buf_len)
{
if (severity >= DMS_EVENT_MAX || buf_len == 0 || severity_name == NULL) {
dms_err("Invalid severity. (severity=%u; buf_len=%u; severity_name is NULL=%d)\n",
severity, buf_len, severity_name == NULL);
return;
}
if (strcpy_s(severity_name, buf_len, g_event_severity_name[severity]) != 0) {
dms_err("Call strcpy_s failed. (event_str_len=\"%s\")\n", g_event_severity_name[severity]);
return;
}
return;
}
#define DMS_MAX_NODE_TYPE_LEN 32
#define DMS_MAX_EVENT_TYPE_LEN 128
#define DMS_MAX_SEVERITY_LEN 12
#define DMS_MAX_ASSERTION_LEN 32
static void dms_record_fault_event_log(DMS_EVENT_NODE_STRU *exception_node)
{
char node_type_name[DMS_MAX_NODE_TYPE_LEN] = {0};
char event_type_string[DMS_MAX_EVENT_TYPE_LEN] = {0};
char severity_name[DMS_MAX_SEVERITY_LEN] = {0};
char assertion_name[DMS_MAX_ASSERTION_LEN] = {0};
struct dms_event_para event = exception_node->event;
u8 sensor_type = DMS_EVENT_ID_TO_SENSOR_TYPE(exception_node->event.event_id);
u8 event_type = DMS_EVENT_ID_TO_EVENT_STATE(exception_node->event.event_id);
u32 os_id = 0;
int ret;
ret = dms_get_node_type_str(event.node_type, node_type_name, DMS_MAX_NODE_TYPE_LEN);
if (ret != 0) {
dms_err("Get node type name failed. (ret=%d)\n", ret);
}
ret = dms_get_event_string(sensor_type, event_type, event_type_string, DMS_MAX_EVENT_TYPE_LEN);
if (ret != 0) {
dms_err("Get event string failed. (ret=%d)\n", ret);
}
dms_get_severity_name(event.severity, severity_name, DMS_MAX_SEVERITY_LEN);
dms_get_assertion_name(event.assertion, assertion_name, DMS_MAX_ASSERTION_LEN);
dms_fault_mng_event(event.assertion, "event_id=0x%x; device_id=%u; node_type=0x%x[%s]; node_id=%u; sub_node_id=%u; "
"event_type=0x%x[%s]; severity=%u[%s]; assertion=%u[%s]; description=[%s]; os_id=%u; event_serial_num=%d; "
"notify_serial_num=%d; event_raised_time=%llu ms.\n",
event.event_id, event.deviceid, event.node_type, node_type_name, event.node_id, event.sub_node_id,
event_type, event_type_string, event.severity, severity_name, event.assertion, assertion_name,
event.additional_info, os_id, event.event_serial_num, event.notify_serial_num, event.alarm_raised_time);
}
#endif
void dms_event_set_poll_task_flag(enum dms_event_poll_flag flag)
{
ka_base_atomic_set(&g_event_task.poll_flag, flag);
}
KA_EXPORT_SYMBOL(dms_event_set_poll_task_flag);
static int dms_event_poll_task(void *arg)
{
DMS_EVENT_NODE_STRU exception_node = {{0}, {0}};
struct dms_event_obj event_obj = {0};
u32 time_old = 0;
u32 time_new = 0;
u32 wait_time, event_num = 0;
wait_time = ka_system_msecs_to_jiffies(DMS_EVENT_TASK_WAIT_TIMEOUT_MS);
dms_info("Dms event poll task start.\n");
while (!ka_task_kthread_should_stop()) {
time_new = ka_system_jiffies_to_msecs(ka_jiffies);
if ((time_new < time_old) || ((time_new - time_old) > DMS_EVENT_FRESH_TO_BAR)) {
if (smf_distribute_all_devices_event_to_bar() != 0) {
dms_err("Distribute event to bar failed.\n");
}
time_old = time_new;
}
if (dms_event_poll_event(&event_obj, wait_time, &event_num) != 0) {
continue;
}
dms_debug("Dms poll event success. (event_num=%u; dev_id=%u; node_type=0x%X; node_id=0x%X; "
"sensor_type=0x%X; event_state=%u; assertion=%u; alarm_serial_num=%u)\n",
event_num, event_obj.deviceid, event_obj.node_type, event_obj.node_id,
event_obj.event.sensor_event.sensor_type, event_obj.event.sensor_event.event_state,
event_obj.event.sensor_event.assertion, event_obj.alarm_serial_num);
if (dms_event_converge_to_exception(&event_obj, &exception_node) != 0) {
continue;
}
if (dms_event_converge_add_to_event_cb(&exception_node) != 0) {
continue;
}
#ifdef CFG_FEATURE_LOG_STANDARD_FAULT_EVENT
dms_record_fault_event_log(&exception_node);
#endif
if (dms_event_distribute_handle(&exception_node, DMS_DISTRIBUTE_PRIORITY0) != 0) {
dms_err("Distribute exception failed. (dev_id=%u; event_id=0x%X; assertion=%u)\n",
exception_node.event.deviceid, exception_node.event.event_id, exception_node.event.assertion);
}
}
ka_base_atomic_set(&g_event_task.poll_flag, EVENT_POLL_EXIT);
dms_info("Dms event poll task exited.\n");
return DRV_ERROR_NONE;
}
static int dms_event_task_init(void)
{
ka_task_init_waitqueue_head(&g_event_task.wait);
ka_task_mutex_init(&g_event_task.lock);
ka_task_mutex_lock(&g_event_task.lock);
g_event_task.event_num = 0;
if (ka_base_kfifo_alloc(&g_event_task.kfifo, DMS_EVENT_KFIFO_SIZE, KA_GFP_KERNEL) != 0) {
ka_task_mutex_unlock(&g_event_task.lock);
ka_task_mutex_destroy(&g_event_task.lock);
dms_err("ka_base_kfifo_alloc failed.\n");
return DRV_ERROR_INNER_ERR;
}
ka_base_kfifo_reset(&g_event_task.kfifo);
ka_task_mutex_unlock(&g_event_task.lock);
#if defined(CFG_FEATURE_EP_MODE) && !defined (CFG_EDGE_HOST)
ka_base_atomic_set(&g_event_task.poll_flag, EVENT_POLL_EXIT);
#else
ka_base_atomic_set(&g_event_task.poll_flag, EVENT_POLL_WORK);
#endif
g_event_task.poll_task = ka_task_kthread_create(dms_event_poll_task, (void *)NULL, "dms_poll_task");
if (KA_IS_ERR(g_event_task.poll_task)) {
ka_task_mutex_lock(&g_event_task.lock);
ka_base_kfifo_free(&g_event_task.kfifo);
ka_task_mutex_unlock(&g_event_task.lock);
ka_task_mutex_destroy(&g_event_task.lock);
dms_err("ka_task_kthread_create failed.\n");
return DRV_ERROR_INNER_ERR;
}
#ifdef CFG_FEATURE_BIND_CORE
kthread_bind_to_ctrl_cpu(g_event_task.poll_task);
#endif
(void)ka_task_wake_up_process(g_event_task.poll_task);
return DRV_ERROR_NONE;
}
static void dms_event_task_exit(void)
{
int wait_time = 0;
ka_base_atomic_set(&g_event_task.poll_flag, EVENT_POLL_STOP);
ka_task_mutex_lock(&g_event_task.lock);
g_event_task.event_num = DMS_MAX_EVENT_NUM;
ka_task_mutex_unlock(&g_event_task.lock);
if (!KA_IS_ERR(g_event_task.poll_task)) {
(void)ka_task_kthread_stop(g_event_task.poll_task);
}
ka_task_wake_up(&g_event_task.wait);
while (ka_base_atomic_read(&g_event_task.poll_flag) != EVENT_POLL_EXIT) {
ka_system_msleep(1);
if (++wait_time >= DMS_EVENT_POLL_WAIT_TIME) {
dms_err("Wait dms_event_poll_task exit timeout.\n");
goto out;
}
}
dms_info("Dms_event_poll_task exit success.\n");
out:
ka_task_mutex_lock(&g_event_task.lock);
ka_base_kfifo_free(&g_event_task.kfifo);
g_event_task.event_num = 0;
ka_task_mutex_unlock(&g_event_task.lock);
ka_task_mutex_destroy(&g_event_task.lock);
g_event_task.poll_task = NULL;
return;
}
void dms_event_ctrl_converge_list_free(struct dms_converge_event_list *event_list)
{
DMS_EVENT_NODE_STRU *exception_node = NULL;
ka_list_head_t *pos = NULL, *n = NULL;
ka_task_mutex_lock(&event_list->lock);
event_list->event_num = 0;
event_list->health_code = 0;
if (!ka_list_empty_careful(&event_list->head)) {
ka_list_for_each_safe(pos, n, &event_list->head) {
exception_node = ka_list_entry(pos, DMS_EVENT_NODE_STRU, node);
ka_list_del(&exception_node->node);
dbl_kfree(exception_node);
exception_node = NULL;
}
}
KA_INIT_LIST_HEAD(&event_list->head);
ka_task_mutex_unlock(&event_list->lock);
}
void dms_event_sensor_reported_list_free(struct dms_sensor_reported_list *reported_list)
{
struct dms_event_sensor_reported *event_node = NULL;
ka_list_head_t *pos = NULL, *n = NULL;
ka_task_mutex_lock(&reported_list->lock);
reported_list->reported_num = 0;
if (!ka_list_empty_careful(&reported_list->head)) {
ka_list_for_each_safe(pos, n, &reported_list->head) {
event_node = ka_list_entry(pos, struct dms_event_sensor_reported, node);
ka_list_del(&event_node->node);
dbl_kfree(event_node);
event_node = NULL;
}
}
KA_INIT_LIST_HEAD(&reported_list->head);
ka_task_mutex_unlock(&reported_list->lock);
}
static int dms_event_ctrl_init(void)
{
struct dms_dev_ctrl_block *dev_cb = NULL;
u32 i;
for (i = 0; i < ASCEND_DEV_MAX_NUM; i++) {
dev_cb = dms_get_dev_cb(i);
if (dev_cb == NULL) {
dms_err("Get dev_ctrl block failed. (dev_id=%u)\n", i);
return DRV_ERROR_NO_DEVICE;
}
ka_task_mutex_lock(&dev_cb->node_lock);
ka_task_mutex_init(&dev_cb->dev_event_cb.event_list.lock);
KA_INIT_LIST_HEAD(&dev_cb->dev_event_cb.event_list.head);
ka_task_mutex_init(&dev_cb->dev_event_cb.reported_list.lock);
KA_INIT_LIST_HEAD(&dev_cb->dev_event_cb.reported_list.head);
ka_task_mutex_init(&dev_cb->dev_event_cb.dfx_table.lock);
KA_INIT_LIST_HEAD(&dev_cb->dev_event_cb.dfx_table.mask_list);
ka_task_mutex_unlock(&dev_cb->node_lock);
}
return DRV_ERROR_NONE;
}
static void dms_event_ctrl_uninit(void)
{
struct dms_dev_ctrl_block *dev_cb = NULL;
u32 i;
for (i = 0; i < ASCEND_DEV_MAX_NUM; i++) {
dev_cb = dms_get_dev_cb(i);
if (dev_cb == NULL) {
dms_err("Get dev_ctrl block failed. (dev_id=%u)\n", i);
continue;
}
ka_task_mutex_lock(&dev_cb->node_lock);
dms_event_ctrl_converge_list_free(&dev_cb->dev_event_cb.event_list);
ka_task_mutex_destroy(&dev_cb->dev_event_cb.event_list.lock);
dms_event_sensor_reported_list_free(&dev_cb->dev_event_cb.reported_list);
ka_task_mutex_destroy(&dev_cb->dev_event_cb.reported_list.lock);
dms_event_mask_list_clear(dev_cb);
ka_task_mutex_destroy(&dev_cb->dev_event_cb.dfx_table.lock);
ka_task_mutex_unlock(&dev_cb->node_lock);
}
}
static int dms_event_ctrl_up(u32 devid)
{
struct dms_dev_ctrl_block *dev_cb = NULL;
struct dms_event_ctrl *event_ctrl = NULL;
u32 i;
dev_cb = dms_get_dev_cb(devid);
if (dev_cb == NULL) {
dms_err("Get dev_ctrl block failed. (dev_id=%u)\n", devid);
return DRV_ERROR_NO_DEVICE;
}
event_ctrl = &dev_cb->dev_event_cb;
(void)dms_event_convergent_diagrams_clear(devid, true);
for (i = 0; i < DMS_EVENT_TYPE_MAX; i++) {
ka_base_atomic_set(&event_ctrl->dfx_table.recv_from_sensor[i], 0);
ka_base_atomic_set(&event_ctrl->dfx_table.report_to_consumer[i], 0);
}
dms_event_mask_list_clear(dev_cb);
return DRV_ERROR_NONE;
}
STATIC void dms_event_ctrl_down(u32 devid)
{
struct dms_dev_ctrl_block *dev_cb = NULL;
struct dms_event_ctrl *event_ctrl = NULL;
u32 i;
dev_cb = dms_get_dev_cb(devid);
if (dev_cb == NULL) {
return;
}
event_ctrl = &dev_cb->dev_event_cb;
(void)dms_event_convergent_diagrams_clear(devid, true);
for (i = 0; i < DMS_EVENT_TYPE_MAX; i++) {
ka_base_atomic_set(&event_ctrl->dfx_table.recv_from_sensor[i], 0);
ka_base_atomic_set(&event_ctrl->dfx_table.report_to_consumer[i], 0);
}
dms_event_mask_list_clear(dev_cb);
}
static int dms_event_device_up2(struct devdrv_info *dev_info)
{
int ret;
ret = dms_event_ctrl_up(dev_info->dev_id);
if (ret != 0) {
dms_err("Dms event ctrl init failed. (dev_id=%u)\n", dev_info->dev_id);
return ret;
}
return DRV_ERROR_NONE;
}
static int dms_event_device_up3(struct devdrv_info *dev_info)
{
int ret;
ret = smf_event_subscribe_from_device(dev_info->dev_id);
if (ret != 0) {
dms_err("Subscribe from device failed. (dev_id=%u)\n", dev_info->dev_id);
return ret;
}
return DRV_ERROR_NONE;
}
static int dms_event_device_down2(struct devdrv_info *dev_info)
{
dms_event_ctrl_down(dev_info->dev_id);
return DRV_ERROR_NONE;
}
static int (*const dms_event_notifier_handle_func[DMS_DEVICE_NOTIFIER_MAX]) \
(struct devdrv_info *dev_info) = {
[DMS_DEVICE_REBOOT] = NULL,
[DMS_DRIVER_REMOVE] = NULL,
[DMS_DEVICE_SUSPEND] = NULL,
[DMS_DEVICE_RESUME] = NULL,
[DMS_DEVICE_UP0] = NULL,
[DMS_DEVICE_UP1] = NULL,
[DMS_DEVICE_UP2] = dms_event_device_up2,
[DMS_DEVICE_UP3] = dms_event_device_up3,
[DMS_DEVICE_DOWN0] = NULL,
[DMS_DEVICE_DOWN1] = NULL,
[DMS_DEVICE_DOWN2] = dms_event_device_down2,
[DMS_DEVICE_DOWN3] = NULL,
};
static int dms_event_notifier_handle(ka_notifier_block_t *self,
unsigned long event, void *data)
{
struct devdrv_info *dev_info = (struct devdrv_info *)data;
int ret;
if ((data == NULL) || (event <= DMS_DEVICE_NOTIFIER_MIN) ||
(event >= DMS_DEVICE_NOTIFIER_MAX)) {
dms_err("Invalid parameter. (event=0x%lx; data=\"%s\")\n",
event, data == NULL ? "NULL" : "OK");
return KA_NOTIFY_BAD;
}
if (dms_event_notifier_handle_func[event] == NULL) {
return KA_NOTIFY_DONE;
}
ret = dms_event_notifier_handle_func[event](dev_info);
if (ret != 0) {
dms_err("Notifier handle failed. (event=0x%lx; dev_id=%u)\n",
event, dev_info->dev_id);
return KA_NOTIFY_BAD;
}
dms_debug("Notifier handle success. (event=0x%lx; dev_id=%u)\n",
event, dev_info->dev_id);
return KA_NOTIFY_DONE;
}
static ka_notifier_block_t dms_event_notifier = {
.notifier_call = dms_event_notifier_handle,
};
int dms_event_init(void)
{
int ret;
ret = dms_event_convergent_diagrams_init();
if (ret != 0) {
dms_event_convergent_diagrams_exit();
dms_warn("Convergent diagrams init warn. (ret=%d)\n", ret);
}
ret = dms_event_ctrl_init();
if (ret != 0) {
dms_err("Event ctrl init failed. (ret=%d)\n", ret);
goto event_ctrl_init_fail;
}
dms_event_distribute_stru_init();
ret = dms_event_distribute_handle_init();
if (ret != 0) {
dms_err("Distribute handle init failed. (ret=%d)\n", ret);
goto distribute_handle_init_fail;
}
ret = dms_event_task_init();
if (ret != 0) {
dms_err("Dms event task init failed. (ret=%d)\n", ret);
goto event_task_init_fail;
}
ret = dms_register_notifier(&dms_event_notifier);
if (ret != 0) {
dms_err("Dms event register notifier failed. (ret=%d)\n", ret);
goto register_notifier_fail;
}
#if defined(CFG_FEATURE_GET_CURRENT_EVENTINFO) && defined(CFG_EDGE_HOST)
dms_device_fault_event_init();
#endif
CALL_INIT_MODULE(DMS_EVENT_CMD_NAME);
dms_debug("Dms event init successful.\n");
return DRV_ERROR_NONE;
register_notifier_fail:
dms_event_task_exit();
event_task_init_fail:
dms_event_subscribe_unregister_all();
distribute_handle_init_fail:
dms_event_distribute_stru_exit();
dms_event_ctrl_uninit();
event_ctrl_init_fail:
dms_event_convergent_diagrams_exit();
return ret;
}
void dms_event_exit(void)
{
CALL_EXIT_MODULE(DMS_EVENT_CMD_NAME);
#if defined(CFG_FEATURE_GET_CURRENT_EVENTINFO) && defined(CFG_EDGE_HOST)
dms_device_fault_event_exit();
#endif
(void)dms_unregister_notifier(&dms_event_notifier);
dms_event_task_exit();
dms_event_subscribe_unregister_all();
dms_event_distribute_stru_exit();
dms_event_ctrl_uninit();
dms_event_convergent_diagrams_exit();
}