* 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 "dms_define.h"
#include "dms_common.h"
#include "dms/dms_notifier.h"
#include "dms_sensor_type.h"
#include "soft_fault_define.h"
#include "pbl_mem_alloc_interface.h"
#include "davinci_interface.h"
#include "ka_base_pub.h"
#include "ka_list_pub.h"
#include "ka_memory_pub.h"
#include "ka_task_pub.h"
void os_reset_report(u32 devid)
{
int ret;
int data_len;
struct soft_fault os_init;
const char *info = "OS init";
data_len = ka_base_strlen(info) + 1;
ret = strcpy_s(os_init.data, DMS_MAX_EVENT_DATA_LENGTH, info);
if (ret != 0) {
soft_drv_err("String copy failed! (device=%u) \n", devid);
return;
}
os_init.data_len = data_len;
os_init.dev_id = devid;
os_init.sensor_type = DMS_SEN_TYPE_GENERAL_SOFTWARE_FAULT;
os_init.user_id = SF_SENSOR_OS;
os_init.node_type = HAL_DMS_DEV_TYPE_OS_LINUX;
os_init.node_id = SF_USER_NODE_OS;
os_init.sub_id = SF_SUB_ID0;
os_init.err_type = OS_INIT;
os_init.assertion = GENERAL_EVENT_TYPE_ONE_TIME;
ret = soft_fault_event_handler(&os_init);
if (ret != 0) {
soft_drv_err("Soft fault report failed! (device=%u) \n", devid);
}
return;
}
STATIC int os_dev_node_config(unsigned int user_id, struct soft_dev *s_dev)
{
int pid = ka_task_get_current_tgid();
struct dms_node_operations *soft_ops = soft_get_ops();
struct dms_node s_node = SOFT_NODE_DEF(HAL_DMS_DEV_TYPE_OS_LINUX, "OS Linux", s_dev->dev_id,
s_dev->node_id, soft_ops);
struct dms_sensor_object_cfg s_cfg = SOFT_SENSOR_DEF(DMS_SEN_TYPE_GENERAL_SOFTWARE_FAULT, "OS init", 0UL,
user_id, SF_SUB_ID0, 0xFFFF, 0xFDFF, SF_SENSOR_SCAN_TIME, soft_fault_event_scan, pid);
s_cfg.private_data =
soft_combine_private_data(s_dev->dev_id, user_id, HAL_DMS_DEV_TYPE_OS_LINUX, s_dev->node_id, SF_SUB_ID0);
s_cfg.pid = -1;
s_node.pid = -1;
s_dev->sensor_obj_num++;
s_dev->sensor_obj_table[SF_SUB_ID0] = s_cfg;
s_dev->dev_node = s_node;
return 0;
}
int os_dev_register(u32 devid)
{
int ret;
unsigned int user_id = SF_SENSOR_OS;
struct soft_dev_client *client = NULL;
struct soft_dev *s_dev = NULL;
struct drv_soft_ctrl *soft_ctrl = soft_get_ctrl();
ka_task_mutex_lock(&soft_ctrl->mutex[devid]);
client = soft_ctrl->s_dev_t[devid][user_id];
if (client->registered == 1) {
soft_drv_warn("Node OS-Linux already registered, return. (dev_id=%u; registered=%u)\n",
devid, client->registered);
ka_task_mutex_unlock(&soft_ctrl->mutex[devid]);
return 0;
}
s_dev = dbl_kzalloc(sizeof(struct soft_dev), KA_GFP_KERNEL | __KA_GFP_ACCOUNT);
if (s_dev == NULL) {
soft_drv_err("ka_mm_kzalloc soft_dev failed.\n");
ka_task_mutex_unlock(&soft_ctrl->mutex[devid]);
return -ENOMEM;
}
soft_one_dev_init(s_dev);
s_dev->dev_id = devid;
s_dev->node_id = SF_USER_NODE_OS;
ret = os_dev_node_config(user_id, s_dev);
if (ret != 0) {
soft_drv_err("soft_fault configure one node failed. (dev_id=%u; ret=%d)\n", devid, ret);
goto ERROR;
}
ret = soft_register_one_node(s_dev);
if (ret != 0) {
soft_drv_err("soft_fault register one node failed. (dev_id=%u; ret=%d)\n", devid, ret);
goto ERROR;
}
ka_list_add(&s_dev->list, &client->head);
client->user_id = user_id;
client->registered = 1;
client->node_num++;
soft_ctrl->user_num[devid]++;
ka_task_mutex_unlock(&soft_ctrl->mutex[devid]);
return 0;
ERROR:
dbl_kfree(s_dev);
s_dev = NULL;
ka_task_mutex_unlock(&soft_ctrl->mutex[devid]);
return ret;
}
void os_dev_unregister(void)
{
int i;
struct soft_dev_client *client = NULL;
struct drv_soft_ctrl *soft_ctrl = soft_get_ctrl();
for (i = 0; i < ASCEND_DEV_MAX_NUM; i++) {
client = soft_ctrl->s_dev_t[i][SF_SENSOR_OS];
soft_free_one_node(client, HAL_DMS_DEV_TYPE_OS_LINUX);
soft_ctrl->user_num[i]--;
}
return;
}
int os_device_notifier_func(u32 devid)
{
int ret = 0;
if (devid >= ASCEND_PDEV_MAX_NUM) {
return 0;
}
ret = os_dev_register(devid);
os_reset_report(devid);
return ret;
}