* 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_base_pub.h"
#include "ka_list_pub.h"
#include "ka_memory_pub.h"
#include "ka_task_pub.h"
#include "soft_fault_define.h"
#include "devdrv_user_common.h"
#include "pbl_mem_alloc_interface.h"
#include "dms_sensor_interface.h"
#include "ascend_dev_num.h"
#define SOFT_PARSE_HANDLE(node_type, sensor_idx, sensor_type, handle) \
do { \
node_type = (handle) >> SF_OFFSET_32BIT; \
sensor_idx = ((handle) & SF_MASK_32BIT) >> SF_OFFSET_16BIT; \
sensor_type = (handle) & SF_MASK_16BIT; \
} while (0) \
#define SOFT_PRINT_REGISTER_LOG(client, user_node, cfg, handle, user_num, flag) \
soft_drv_event("soft node register success. (dev_id=%u; name=%s; pid=%d; user_id=%u; node_id=%u; node_type=0x%x;" \
" sensor_type=0x%x; assert_event_mask=0x%x; deassert_event_mask=0x%x; user_num=%u; node_num=%u;" \
" handle=0x%llx; sensor_obj_num=%u; first_register=%d)\n", \
(user_node)->dev_id, (cfg)->name, (client)->pid, (client)->user_id, (user_node)->node_id, (cfg)->node_type, \
(cfg)->sensor_type, (cfg)->assert_event_mask, (cfg)->deassert_event_mask, (user_num), (client)->node_num, \
*(handle), (user_node)->sensor_obj_num, (flag))
STATIC DMS_SENSOR_TYPE_T g_sensor_type_list[] = {
DMS_SEN_TYPE_HEARTBEAT, DMS_SEN_TYPE_GENERAL_SOFTWARE_FAULT, DMS_SEN_TYPE_SAFETY_SENSOR};
STATIC int soft_sensor_whitelist_check(struct dms_sensor_node_cfg cfg)
{
int i;
if ((cfg.node_type < HAL_DMS_DEV_TYPE_BASE_SERVCIE) || (cfg.node_type >= HAL_DMS_DEV_TYPE_MAX)) {
return -EINVAL;
}
for (i = 0; i < sizeof(g_sensor_type_list) / sizeof(g_sensor_type_list[0]); i++) {
if (g_sensor_type_list[i] == cfg.sensor_type) {
return 0;
}
}
return -EINVAL;
}
STATIC int soft_trans_and_check_id(u32 logic_id, u32 *phy_id, u32 *vfid)
{
int ret;
if (logic_id >= ASCEND_DEV_MAX_NUM) {
soft_drv_err("Wrong logic id. (logic_id=%u)\n", logic_id);
return -EINVAL;
}
ret = devdrv_manager_container_logical_id_to_physical_id(logic_id, phy_id, vfid);
if (ret != 0) {
soft_drv_err("Transfer logic id to phy id failed. (logic_id=%u; ret=%d)\n", logic_id, ret);
return ret;
}
if (*phy_id >= ASCEND_DEV_MAX_NUM) {
soft_drv_err("wrong phy id. (logic_id=%u; phy_id=%u)\n", logic_id, *phy_id);
return -EINVAL;
}
return 0;
}
STATIC void soft_get_default_event_mask(
unsigned int sensor_type, unsigned int *assert_event_mask, unsigned int *deassert_event_mask)
{
if (sensor_type == DMS_SEN_TYPE_GENERAL_SOFTWARE_FAULT) {
*assert_event_mask = 0x3FF;
*deassert_event_mask = 0x3FF;
} else if (sensor_type == DMS_SEN_TYPE_SAFETY_SENSOR) {
*assert_event_mask = 0x3FF;
*deassert_event_mask = DST_MASK;
} else {
*assert_event_mask = AST_MASK;
*deassert_event_mask = DST_MASK;
}
return;
}
STATIC int user_sensor_register(struct soft_dev *user_node, struct dms_sensor_node_cfg *cfg,
unsigned int user_id, unsigned int sub_id)
{
int ret;
int pid = ka_task_get_current_tgid();
unsigned int assert_event_mask = cfg->assert_event_mask;
unsigned int deassert_event_mask = cfg->deassert_event_mask;
struct dms_sensor_object_cfg *obj = &user_node->sensor_obj_table[sub_id];
struct dms_sensor_object_cfg s_cfg = SOFT_SENSOR_DEF(cfg->sensor_type, "hb", 0UL, user_id, SF_SUB_ID0,
assert_event_mask, deassert_event_mask, SF_SENSOR_SCAN_TIME, soft_fault_event_scan, pid);
* set default event mask */
if ((assert_event_mask == 0) && (deassert_event_mask == 0)) {
soft_get_default_event_mask(cfg->sensor_type, &assert_event_mask, &deassert_event_mask);
s_cfg.assert_event_mask = assert_event_mask;
s_cfg.deassert_event_mask = deassert_event_mask;
}
*obj = s_cfg;
obj->private_data =
soft_combine_private_data(user_node->dev_id, user_id, cfg->node_type, user_node->node_id, sub_id);
ret = snprintf_s(obj->sensor_name, DMS_SENSOR_DESCRIPT_LENGTH, DMS_SENSOR_DESCRIPT_LENGTH, "%s", cfg->name);
if (ret <= 0) {
soft_drv_err("snprintf_s sensor_name failed. (name=%s; ret=%d)\n", cfg->name, ret);
return ret;
}
ret = dms_sensor_register_for_userspace(&user_node->dev_node, obj);
if (ret != 0) {
soft_drv_err("Register sensor failed. (dev_id=%u; user_name=%s; node_type=0x%x; sensor_type=0x%x; ret=%d)\n",
user_node->dev_id, ka_task_get_current_comm(), cfg->node_type, cfg->sensor_type, ret);
return ret;
}
return 0;
}
STATIC int user_dev_node_register(unsigned int dev_id, unsigned int user_id, struct soft_dev *user_node,
struct dms_sensor_node_cfg *cfg, uint64_t *handle)
{
int ret;
unsigned int sensor_idx;
struct dms_node_operations *soft_ops = soft_get_ops();
struct dms_node s_node = SOFT_NODE_DEF(cfg->node_type, "user", dev_id, user_node->node_id, soft_ops);
if (user_node->sensor_obj_num >= SF_SUB_ID_MAX) {
soft_drv_warn("exceed max sensor num. (dev_id=%u; sensor_obj_num=%u)\n", dev_id, user_node->sensor_obj_num);
return -EBUSY;
}
if (user_node->registered == 0) {
user_node->dev_node = s_node;
ret = snprintf_s(user_node->dev_node.node_name, DMS_MAX_DEV_NAME_LEN, DMS_MAX_DEV_NAME_LEN,
"%02u_%02d_%03x_%.5s", dev_id, user_node->node_id, cfg->node_type, cfg->name);
if (ret <= 0) {
soft_drv_err("snprintf_s failed. (dev_id=%u; node_id=%u; ret=%d)\n", dev_id, user_node->node_id, ret);
return ret;
}
ret = dms_register_dev_node(&user_node->dev_node);
if (ret != 0) {
soft_drv_err("register dev_node failed. (dev_id=%u; user_name=%s; node_type=%u; ret=%d)\n",
dev_id, ka_task_get_current_comm(), cfg->node_type, ret);
return ret;
}
}
for (sensor_idx = 0; sensor_idx < SF_SUB_ID_MAX; sensor_idx++) {
if ((user_node->sensor_obj_registered[sensor_idx]) &&
(user_node->sensor_obj_table[sensor_idx].sensor_type == cfg->sensor_type) &&
(ka_base_strcmp(user_node->sensor_obj_table[sensor_idx].sensor_name, cfg->name) == 0)) {
soft_drv_warn("sensor already register. (dev_id=%u; sensor_type=0x%x; name=%s)\n",
dev_id, cfg->sensor_type, cfg->name);
goto OUT;
}
}
for (sensor_idx = 0; sensor_idx < SF_SUB_ID_MAX; sensor_idx++) {
if (user_node->sensor_obj_registered[sensor_idx] == 0) {
break;
}
}
if (sensor_idx >= SF_SUB_ID_MAX) {
soft_drv_warn("exceed max sensor num. (dev_id=%u; sensor_idx=%u)\n", dev_id, sensor_idx);
return -EBUSY;
}
ret = user_sensor_register(user_node, cfg, user_id, sensor_idx);
if (ret != 0) {
soft_drv_err("user sensor register failed. "
"(dev_id=%u, node_type=0x%x, sensor_type=0x%x, sensor_id=%u; ret=%d)\n",
dev_id, cfg->node_type, cfg->sensor_type, sensor_idx, ret);
goto ERROR;
}
user_node->sensor_obj_registered[sensor_idx] = 1;
user_node->sensor_obj_num++;
user_node->registered = 1;
OUT:
*handle = ((uint64_t)cfg->node_type << SF_OFFSET_32BIT) |
(sensor_idx << SF_OFFSET_16BIT) | cfg->sensor_type;
return 0;
ERROR:
if (user_node->registered == 0) {
(void)dms_unregister_dev_node(&user_node->dev_node);
}
return ret;
}
STATIC struct soft_dev *soft_dev_node_get(unsigned int dev_id, struct soft_dev_client *client,
struct dms_sensor_node_cfg *cfg, unsigned int user_id, int *first_register)
{
struct soft_dev *pos = NULL;
struct soft_dev *n = NULL;
struct soft_dev *s_dev = NULL;
*first_register = 1;
ka_list_for_each_entry_safe(pos, n, &client->head, list) {
if ((pos->registered == 1) && (pos->dev_node.node_type == cfg->node_type)) {
*first_register = 0;
break;
}
}
if (*first_register) {
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. (user_name=%s)\n", ka_task_get_current_comm());
return NULL;
}
soft_one_dev_init(s_dev);
s_dev->dev_id = dev_id;
s_dev->node_id = user_id;
} else {
s_dev = pos;
}
return s_dev;
}
STATIC void soft_dev_client_add(struct soft_dev_client *client, struct soft_dev *user_node, uint32_t user_id,
uint32_t *user_num, int first_register)
{
if (client->registered == 0) {
client->pid = ka_task_get_current_tgid();
client->user_id = user_id;
client->registered = 1;
(*user_num)++;
}
if (first_register != 0) {
ka_list_add(&user_node->list, &client->head);
client->node_num++;
}
return;
}
STATIC struct soft_dev_client* dms_soft_get_client(u32 dev_id, struct drv_soft_ctrl *soft_ctrl,
u32 *user_id)
{
int i;
for (i = SF_SENSOR_USER; i < SF_USER_MAX; i++) {
if (soft_ctrl->s_dev_t[dev_id][i]->pid == ka_task_get_current_tgid()) {
*user_id = i;
return soft_ctrl->s_dev_t[dev_id][i];
}
}
for (i = SF_SENSOR_USER; i < SF_USER_MAX; i++) {
if (soft_ctrl->s_dev_t[dev_id][i]->registered == 0) {
*user_id = i;
return soft_ctrl->s_dev_t[dev_id][i];
}
}
return NULL;
}
STATIC int dms_soft_node_register(unsigned int dev_id, struct dms_sensor_node_cfg *cfg, uint64_t *handle)
{
int ret;
int first_register = 0;
unsigned int user_id = 0;
struct soft_dev_client *client = NULL;
struct soft_dev *user_node = NULL;
struct drv_soft_ctrl *soft_ctrl = soft_get_ctrl();
ka_task_mutex_lock(&soft_ctrl->mutex[dev_id]);
client = dms_soft_get_client(dev_id, soft_ctrl, &user_id);
if (client == NULL) {
soft_drv_warn("exceed max user num. (dev_id=%u; user_num=%u)\n", dev_id, soft_ctrl->user_num[dev_id]);
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return -EBUSY;
}
if (client->node_num >= SF_USER_NODE_MAX) {
soft_drv_warn("Exceed max user node num. (dev_id=%u; node_num=%u)\n", dev_id, client->node_num);
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return -EBUSY;
}
user_node = soft_dev_node_get(dev_id, client, cfg, user_id, &first_register);
if (user_node == NULL) {
soft_drv_err("get new user soft_dev failed. (user_name=%s)\n", ka_task_get_current_comm());
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return -ENOMEM;
}
ret = user_dev_node_register(dev_id, user_id, user_node, cfg, handle);
if (ret != 0) {
soft_drv_err("register user dev_node failed. (dev_id=%u; user_name=%s; node_id=%u; ret=%d)\n",
dev_id, ka_task_get_current_comm(), user_node->node_id, ret);
if (first_register != 0) {
dbl_kfree(user_node);
user_node = NULL;
}
goto out;
}
soft_dev_client_add(client, user_node, user_id, &soft_ctrl->user_num[dev_id], first_register);
SOFT_PRINT_REGISTER_LOG(client, user_node, cfg, handle, soft_ctrl->user_num[dev_id], first_register);
out:
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return ret;
}
STATIC int user_sensor_object_unregister(struct soft_dev *pos, unsigned int sensor_idx)
{
struct dms_sensor_object_cfg *obj = NULL;
int ret;
obj = &pos->sensor_obj_table[sensor_idx];
ret = dms_sensor_object_unregister(&pos->dev_node, obj);
if (ret != 0) {
soft_drv_err("User sensor object unregister failed. (sensor_index=%u)\n", sensor_idx);
return ret;
}
pos->sensor_obj_registered[sensor_idx] = 0;
soft_fault_event_free(&pos->sensor_event_queue[sensor_idx]);
pos->sensor_obj_num--;
return DRV_ERROR_NONE;
}
STATIC struct soft_dev* dms_soft_dev_node_get(struct soft_dev_client *client, unsigned int node_type)
{
struct soft_dev *pos = NULL;
struct soft_dev *pos_temp = NULL;
struct soft_dev *n = NULL;
ka_list_for_each_entry_safe(pos_temp, n, &client->head, list) {
if ((pos_temp->registered == 1) && (pos_temp->dev_node.node_type == node_type)) {
pos = pos_temp;
break;
}
}
return pos;
}
STATIC int dms_soft_node_unregister(unsigned int dev_id, uint64_t handle)
{
int i;
int ret;
unsigned int node_type, sensor_idx, sensor_type;
struct soft_dev_client *client = NULL;
struct soft_dev *pos = NULL;
struct drv_soft_ctrl *soft_ctrl = soft_get_ctrl();
ka_task_mutex_lock(&soft_ctrl->mutex[dev_id]);
for (i = SF_SENSOR_USER; i < SF_USER_MAX; i++) {
if ((soft_ctrl->s_dev_t[dev_id][i]->pid == ka_task_get_current_tgid()) && (soft_ctrl->s_dev_t[dev_id][i]->registered == 1)) {
client = soft_ctrl->s_dev_t[dev_id][i];
break;
}
}
SOFT_PARSE_HANDLE(node_type, sensor_idx, sensor_type, handle);
if ((client == NULL) || (sensor_idx >= SF_SUB_ID_MAX)) {
soft_drv_err("Invalid para. (dev_id=%u; handle=0x%llx)\n", dev_id, handle);
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return -EINVAL;
}
pos = dms_soft_dev_node_get(client, node_type);
if (pos == NULL) {
soft_drv_err("Invalid para. (node_type=%u; sensor_index=%u)\n", node_type, sensor_idx);
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return DRV_ERROR_PARA_ERROR;
}
ret = user_sensor_object_unregister(pos, sensor_idx);
if (ret != 0) {
soft_drv_err("user sensor object unregister failed."
" (dev_id=%u; pid=%d; user_id=%u; node_type=%u; sensor_idx=%u; sensor_type=%u)\n",
dev_id, client->pid, client->user_id, node_type, sensor_idx, sensor_type);
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return ret;
}
if (pos->sensor_obj_num == 0) {
soft_free_one_node(client, node_type);
}
soft_ctrl->user_num[dev_id] -= (client->node_num == 0) ? (1) : (0);
soft_drv_event("soft node unregister success. (dev_id=%u; pid=%d; user_id=%u; node_type=0x%llx;"
" sensor_type=0x%x; user_num=%u; handle=0x%llx)\n", dev_id, client->pid, client->user_id,
handle >> SF_OFFSET_32BIT, sensor_type, soft_ctrl->user_num[dev_id], handle);
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return DRV_ERROR_NONE;
}
static inline int sensor_event_state_convert_assertion(struct dms_sensor_object_cfg *obj_cfg, int event_data)
{
if ((obj_cfg->assert_event_mask & (1 << event_data)) && !(obj_cfg->deassert_event_mask & (1 << event_data))) {
return GENERAL_EVENT_TYPE_ONE_TIME;
}
return GENERAL_EVENT_TYPE_OCCUR;
}
STATIC int dms_update_sensor_state(unsigned int dev_id, uint64_t handle, int val, int assertion)
{
int i, ret, event_type;
unsigned int node_type, sensor_idx, sensor_type;
struct soft_fault event = {0};
struct dms_sensor_object_cfg *p_cfg = NULL;
struct soft_dev_client *client = NULL;
struct soft_dev *pos = NULL;
struct soft_dev *n = NULL;
struct soft_dev *user_node = NULL;
struct drv_soft_ctrl *soft_ctrl = soft_get_ctrl();
ka_task_mutex_lock(&soft_ctrl->mutex[dev_id]);
for (i = SF_SENSOR_USER; i < SF_USER_MAX; i++) {
if ((soft_ctrl->s_dev_t[dev_id][i]->pid == ka_task_get_current_tgid()) && (soft_ctrl->s_dev_t[dev_id][i]->registered == 1)) {
client = soft_ctrl->s_dev_t[dev_id][i];
break;
}
}
SOFT_PARSE_HANDLE(node_type, sensor_idx, sensor_type, handle);
if ((client == NULL) || (sensor_idx >= SF_SUB_ID_MAX)) {
soft_drv_err("Invalid para. (dev_id=%u; handle=0x%llx; client=%u)\n", dev_id, handle, (client != NULL));
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return -EINVAL;
}
ka_list_for_each_entry_safe(pos, n, &client->head, list) {
if ((pos->dev_node.node_type == node_type) && (pos->registered == 1)) {
user_node = pos;
break;
}
}
if (user_node == NULL) {
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
soft_drv_err("Can not find a matching node. (handle=%llu; node_type=0x%x; sensor_type=0x%x; sensor_idx=%u)\n",
handle, node_type, sensor_type, sensor_idx);
return -EINVAL;
}
for (i = 0; i < SF_SUB_ID_MAX; i++) {
if (!pos->sensor_obj_registered[i]) {
continue;
}
p_cfg = &user_node->sensor_obj_table[i];
if ((p_cfg->sensor_type != sensor_type) || (i != sensor_idx)) {
continue;
}
event_type = sensor_event_state_convert_assertion(p_cfg, val);
if ((assertion != GENERAL_EVENT_TYPE_RESUME) && (event_type != assertion)) {
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
soft_drv_err("The assertion type is mismatched. "
"(devid=%u; handle=%llu; node_type=0x%x; sensor_type=0x%x; sensor_idx=%u; type0=0x%x; type1=0x%x)\n",
dev_id, handle, node_type, sensor_type, sensor_idx, event_type, assertion);
return -EINVAL;
}
event.sensor_type = p_cfg->sensor_type;
event.dev_id = dev_id;
event.user_id = client->user_id;
event.node_type = node_type;
event.node_id = user_node->node_id;
event.sub_id = i;
event.err_type = val;
event.assertion = (unsigned int)assertion;
ret = soft_fault_event_handler(&event);
if (ret == 0) {
soft_drv_event("soft node update state success. (dev_id=%u; pid=%d; sensor_name=%s; user_id=%u;"
" node_id=%u; node_type=0x%x; sensor_type=0x%x; val=%d; assertion=%d; handle=0x%llx)\n",
dev_id, client->pid, p_cfg->sensor_name, client->user_id, user_node->node_id, node_type,
sensor_type, val, assertion, handle);
}
break;
}
ka_task_mutex_unlock(&soft_ctrl->mutex[dev_id]);
return 0;
}
int soft_node_register(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
int ret;
size_t name_len = 0;
uint64_t handle = 0;
u32 dev_id, phy_id, vfid;
struct dms_sensor_user *arg = NULL;
struct dms_sensor_node_cfg cfg;
if ((in == NULL) || (in_len != sizeof(struct dms_sensor_user)) || (out == NULL) || (out_len != sizeof(uint64_t))) {
soft_drv_err("Invalid para. (in_len=%u; out_len=%u)\n", in_len, out_len);
return -EINVAL;
}
arg = (struct dms_sensor_user *)in;
dev_id = arg->dev_id;
cfg = arg->cfg;
name_len = ka_base_strnlen(cfg.name, CFG_NAME_MAX_LENGTH);
if (name_len >= CFG_NAME_MAX_LENGTH) {
soft_drv_err("Cfg name is invalid, length of name should be less than 20. (len=%zu)\n", name_len);
return -EINVAL;
}
ret = soft_sensor_whitelist_check(cfg);
if (ret != 0) {
soft_drv_err("Sensor cfg check failed. (dev_id=%u; node_type=%d; sensor_type=%d; ret=%d;)\n",
dev_id, cfg.node_type, cfg.sensor_type, ret);
return ret;
}
ret = soft_trans_and_check_id(dev_id, &phy_id, &vfid);
if (ret != 0) {
soft_drv_err("can't transform dev_id. (dev_id=%u; ret=%d)\n", dev_id, ret);
return ret;
}
ret = dms_soft_node_register(phy_id, &cfg, &handle);
if (ret != 0) {
soft_drv_err("register soft node failed. (dev_id=%u; ret=%d)\n", dev_id, ret);
return ret;
}
*(uint64_t *)out = handle;
return 0;
}
int soft_node_unregister(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
int ret;
uint64_t handle;
unsigned int phy_id, vfid;
struct dms_sensor_user *arg = NULL;
if ((in == NULL) || (in_len != sizeof(struct dms_sensor_user))) {
soft_drv_err("Invalid para. (in_len=%u)\n", in_len);
return -EINVAL;
}
arg = (struct dms_sensor_user *)in;
handle = arg->handle;
ret = soft_trans_and_check_id(arg->dev_id, &phy_id, &vfid);
if (ret != 0) {
soft_drv_err("can't transform dev_id. (dev_id=%u; ret=%d)\n", arg->dev_id, ret);
return ret;
}
return dms_soft_node_unregister(phy_id, handle);
}
int soft_node_update_state(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
int ret, val, assertion;
uint64_t handle;
unsigned int phy_id, vfid;
struct dms_sensor_user *arg = NULL;
if ((in == NULL) || (in_len != sizeof(struct dms_sensor_user))) {
soft_drv_err("Invalid para. (in_is_null=%d; in_len=%u; valid_in_len=%zd)\n",
(in == NULL), in_len, sizeof(struct dms_sensor_user));
return -EINVAL;
}
arg = (struct dms_sensor_user *)in;
val = arg->value;
assertion = arg->assertion;
handle = arg->handle;
if (assertion >= GENERAL_EVENT_TYPE_MAX) {
soft_drv_err("Invalid para. (dev_id=%u; assertion=%d; max=%d)\n",
arg->dev_id, assertion, GENERAL_EVENT_TYPE_MAX - 1);
return -EINVAL;
}
ret = soft_trans_and_check_id(arg->dev_id, &phy_id, &vfid);
if (ret != 0) {
soft_drv_err("can't transform dev_id. (dev_id=%u; ret=%d)\n", arg->dev_id, ret);
return ret;
}
return dms_update_sensor_state(phy_id, handle, val, assertion);
}
STATIC void soft_dev_free_registered_dev(struct soft_dev_client *client)
{
int i;
struct soft_dev *pos = NULL;
struct soft_dev *n = NULL;
ka_list_for_each_entry_safe(pos, n, &client->head, list) {
if (pos->registered == 0) {
continue;
}
soft_unregister_one_node(pos);
for (i = 0; i < SF_SUB_ID_MAX; i++) {
if (pos->sensor_obj_registered[i] == 1) {
soft_fault_event_free(&pos->sensor_event_queue[i]);
}
}
soft_one_dev_exit(pos);
ka_list_del(&pos->list);
dbl_kfree(pos);
pos = NULL;
}
}
void soft_dev_exit(void)
{
int i, j;
struct soft_dev_client *client = NULL;
struct drv_soft_ctrl *soft_ctrl = soft_get_ctrl();
for (i = 0; i < ASCEND_DEV_MAX_NUM; i++) {
ka_task_mutex_lock(&soft_ctrl->mutex[i]);
for (j = SF_SENSOR_USER; j < SF_USER_MAX; j++) {
client = soft_ctrl->s_dev_t[i][j];
soft_dev_free_registered_dev(client);
client->registered = 0;
client->node_num = 0;
client->pid = -1;
}
soft_ctrl->user_num[i] = 0;
ka_task_mutex_unlock(&soft_ctrl->mutex[i]);
}
return;
}
void soft_client_release(int owner_pid)
{
int i, j;
unsigned int user_num;
struct soft_dev_client *client = NULL;
struct drv_soft_ctrl *soft_ctrl = soft_get_ctrl();
for (i = 0; i < ASCEND_DEV_MAX_NUM; i++) {
ka_task_mutex_lock(&soft_ctrl->mutex[i]);
user_num = soft_ctrl->user_num[i];
if (user_num == 0) {
ka_task_mutex_unlock(&soft_ctrl->mutex[i]);
continue;
}
for (j = SF_SENSOR_USER; j < SF_USER_MAX; j++) {
client = soft_ctrl->s_dev_t[i][j];
if ((client->registered == 0) || (client->pid != owner_pid)) {
continue;
}
soft_dev_free_registered_dev(client);
soft_drv_event("release one process success. (dev_id=%d; user_id=%d; owner_pid=%d)\n", i, j, owner_pid);
client->registered = 0;
client->node_num = 0;
client->pid = -1;
soft_ctrl->user_num[i]--;
break;
}
ka_task_mutex_unlock(&soft_ctrl->mutex[i]);
}
return;
}
BEGIN_DMS_MODULE_DECLARATION(soft_fault)
BEGIN_FEATURE_COMMAND()
ADD_FEATURE_COMMAND(DMS_MODULE_SOFT_FAULT,
DMS_MAIN_CMD_SOFT_FAULT,
DMS_SUBCMD_SENSOR_NODE_REGISTER,
NULL,
NULL,
DMS_SUPPORT_ALL,
soft_node_register)
ADD_FEATURE_COMMAND(DMS_MODULE_SOFT_FAULT,
DMS_MAIN_CMD_SOFT_FAULT,
DMS_SUBCMD_SENSOR_NODE_UNREGISTER,
NULL,
NULL,
DMS_SUPPORT_ALL,
soft_node_unregister)
ADD_FEATURE_COMMAND(DMS_MODULE_SOFT_FAULT,
DMS_MAIN_CMD_SOFT_FAULT,
DMS_SUBCMD_SENSOR_NODE_UPDATE_VAL,
NULL,
NULL,
DMS_SUPPORT_ALL,
soft_node_update_state)
END_FEATURE_COMMAND()
END_MODULE_DECLARATION()