* 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_task_pub.h"
#include "ka_list_pub.h"
#include "ka_memory_pub.h"
#include "ka_hashtable_pub.h"
#include "ka_system_pub.h"
#include "ascend_hal_define.h"
#include "securec.h"
#include "comm_kernel_interface.h"
#include "trs_core.h"
#include "trs_shr_id_node.h"
#include "trs_shr_id.h"
#include "trs_core_adapt.h"
#define TSDRV_WAKEUP_TIMEINTERVAL 500
static KA_TASK_DEFINE_RWLOCK(proc_lock);
#define PROC_HASH_TABLE_BIT 4
#define PROC_HASH_TABLE_MASK ((1 << PROC_HASH_TABLE_BIT) - 1)
static KA_DECLARE_HASHTABLE(proc_htable, PROC_HASH_TABLE_BIT);
struct shr_id_proc_node {
char name[SHR_ID_NSM_NAME_SIZE];
int res_type;
int type;
ka_list_head_t list;
struct trs_id_inst inst;
int id;
u32 ref;
u32 flag;
u32 opened_devid;
};
static int shr_id_type_trans[SHR_ID_TYPE_MAX] = {
[SHR_ID_NOTIFY_TYPE] = TRS_NOTIFY,
[SHR_ID_EVENT_TYPE] = TRS_EVENT,
};
static void shr_id_proc_num_inc(struct shr_id_proc_ctx *proc_ctx, int op, u32 num)
{
(op == 0) ? (proc_ctx->create_node_num += num) : (proc_ctx->open_node_num += num);
}
static void shr_id_proc_num_dec(struct shr_id_proc_ctx *proc_ctx, int op, u32 num)
{
(op == 0) ? (proc_ctx->create_node_num -= num) : (proc_ctx->open_node_num -= num);
}
static void _shr_id_proc_add(struct shr_id_proc_ctx *proc_ctx)
{
int key = proc_ctx->pid & PROC_HASH_TABLE_MASK;
ka_hash_add(proc_htable, &proc_ctx->link, key);
}
static void shr_id_hash_table_clean(struct shr_id_proc_ctx *proc_ctx)
{
u32 bkt = 0;
struct shr_id_hash_node *cur = NULL;
ka_hlist_node_t *tmp = NULL;
ka_hash_for_each_safe(proc_ctx->abnormal_ht.htable, bkt, tmp, cur, link) {
ka_hash_del(&cur->link);
ka_mm_kfree(cur);
}
}
static void _shr_id_proc_del(struct shr_id_proc_ctx *proc_ctx)
{
ka_task_write_lock(&proc_lock);
ka_hash_del(&proc_ctx->link);
ka_task_write_unlock(&proc_lock);
}
struct shr_id_proc_ctx *shr_id_proc_create(ka_pid_t pid)
{
size_t ctx_size = sizeof(struct shr_id_proc_ctx);
struct shr_id_proc_ctx *proc_ctx = NULL;
proc_ctx = (struct shr_id_proc_ctx *)trs_kzalloc(ctx_size, KA_GFP_KERNEL | __KA_GFP_ACCOUNT);
if (proc_ctx == NULL) {
trs_err("Kmalloc fail. (size=%ld)\n", ctx_size);
return NULL;
}
proc_ctx->pid = ka_task_get_current_tgid();
proc_ctx->start_time = ka_task_get_current_group_starttime();
kref_safe_init(&proc_ctx->ref);
KA_INIT_LIST_HEAD(&proc_ctx->create_list_head);
KA_INIT_LIST_HEAD(&proc_ctx->open_list_head);
ka_task_rwlock_init(&proc_ctx->lock);
ka_task_mutex_init(&proc_ctx->mutex);
ka_base_atomic_set(&proc_ctx->proc_in_release, 0);
ka_hash_init(proc_ctx->abnormal_ht.htable);
ka_task_rwlock_init(&proc_ctx->abnormal_ht.lock);
return proc_ctx;
}
void shr_id_proc_destroy(struct shr_id_proc_ctx *proc_ctx)
{
shr_id_hash_table_clean(proc_ctx);
ka_task_mutex_destroy(&proc_ctx->mutex);
trs_kfree(proc_ctx);
}
struct shr_id_proc_ctx *shr_id_find_proc(ka_pid_t pid)
{
struct shr_id_proc_ctx *proc_ctx = NULL;
int key = pid & PROC_HASH_TABLE_MASK;
ka_hash_for_each_possible(proc_htable, proc_ctx, link, key) {
if (proc_ctx->pid == pid) {
return proc_ctx;
}
}
return NULL;
}
static struct shr_id_proc_node *shr_id_creat_proc_node(const char *name, struct shr_id_node_op_attr *attr)
{
struct shr_id_proc_node *proc_node = NULL;
int i;
proc_node = trs_kvzalloc(sizeof(struct shr_id_proc_node), KA_GFP_KERNEL | __KA_GFP_ACCOUNT);
if (proc_node == NULL) {
return NULL;
}
proc_node->res_type = attr->res_type;
proc_node->inst = attr->inst;
proc_node->id = (int)attr->id;
proc_node->type = attr->type;
for (i = 0; i < SHR_ID_NSM_NAME_SIZE; i++) {
proc_node->name[i] = name[i];
}
proc_node->ref = 1;
return proc_node;
}
static void shr_id_destroy_proc_node(struct shr_id_proc_node *proc_node)
{
if (proc_node != NULL) {
trs_kvfree(proc_node);
}
}
static void shr_id_recycle_opened(struct shr_id_proc_ctx *proc_ctx)
{
struct shr_id_proc_node *proc_node = NULL, *n = NULL;
int ret = 0;
u32 i;
trs_debug("Opened start recycle. (pid=%d; open_num=%u)\n", proc_ctx->pid, proc_ctx->open_node_num);
ka_list_for_each_entry_safe(proc_node, n, &proc_ctx->open_list_head, list) {
for (i = 0; i < proc_node->ref; i++) {
ret |= shr_id_node_close(proc_node->name, proc_node->type, proc_ctx->pid);
if (ka_task_need_resched()) {
ka_task_cond_resched();
}
}
if (ret == 0) {
shr_id_proc_num_dec(proc_ctx, 1, proc_node->ref);
} else {
trs_warn("Opened recycle warn. (name=%s; type=%d; ret=%d)\n", proc_node->name, proc_node->type, ret);
}
ka_list_del(&proc_node->list);
shr_id_destroy_proc_node(proc_node);
trs_debug("Opened recycle. (pid=%d; open_num=%u)\n", proc_ctx->pid, proc_ctx->open_node_num);
}
}
static void tsdrv_try_cond_resched_by_time(u32 *pre_stamp, u32 time)
{
u32 timeinterval;
timeinterval = ka_system_jiffies_to_msecs(ka_jiffies - *pre_stamp);
if ((timeinterval > time) && !ka_base_in_atomic()) {
ka_task_cond_resched();
*pre_stamp = (u32)ka_jiffies;
}
}
static void tsdrv_try_cond_resched(u32 *pre_stamp)
{
tsdrv_try_cond_resched_by_time(pre_stamp, TSDRV_WAKEUP_TIMEINTERVAL);
}
static void shr_id_recycle_created(struct shr_id_proc_ctx *proc_ctx)
{
struct shr_id_proc_node *proc_node = NULL, *n = NULL;
u32 stamp = (u32)ka_jiffies;
trs_debug("Create start recycle. (pid=%d; create_num=%u)\n", proc_ctx->pid, proc_ctx->create_node_num);
ka_list_for_each_entry_safe(proc_node, n, &proc_ctx->create_list_head, list) {
#ifdef CFG_FEATURE_SUPPORT_XCOM
int ret = shr_id_node_destroy(proc_node->name, proc_node->type, proc_ctx->pid, DEVDRV_S2S_SYNC_MODE);
#else
int ret = shr_id_node_destroy(proc_node->name, proc_node->type, proc_ctx->pid, DEVDRV_S2S_ASYNC_MODE);
#endif
if (ret == 0) {
shr_id_proc_num_dec(proc_ctx, 0, proc_node->ref);
} else {
trs_warn("Create recycle warn. (name=%s; type=%d; ret=%d)\n", proc_node->name, proc_node->type, ret);
}
ka_list_del(&proc_node->list);
shr_id_destroy_proc_node(proc_node);
tsdrv_try_cond_resched(&stamp);
}
}
static void shr_id_node_recycle(struct shr_id_proc_ctx *proc_ctx)
{
shr_id_recycle_opened(proc_ctx);
shr_id_recycle_created(proc_ctx);
}
static void shr_id_proc_release(struct kref_safe *kref)
{
struct shr_id_proc_ctx *proc_ctx = ka_container_of(kref, struct shr_id_proc_ctx, ref);
* After the recovery is complete, delete the process context from the hash table
* This sequence cooperates with shr_id_wait_for_proc_exit to ensure that
* only one process with the same pid exists at the same time
*/
ka_base_atomic_set(&proc_ctx->proc_in_release, 1);
shr_id_node_recycle(proc_ctx);
_shr_id_proc_del(proc_ctx);
shr_id_proc_destroy(proc_ctx);
}
static struct shr_id_proc_ctx *shr_id_proc_get(ka_pid_t pid)
{
struct shr_id_proc_ctx *proc_ctx = NULL;
ka_task_read_lock(&proc_lock);
proc_ctx = shr_id_find_proc(pid);
if (proc_ctx != NULL) {
if (kref_safe_get_unless_zero(&proc_ctx->ref) == 0) {
ka_task_read_unlock(&proc_lock);
return NULL;
}
}
ka_task_read_unlock(&proc_lock);
return proc_ctx;
}
* When a process's reference count reaches zero, it triggers the release process,
* making it impossible to get process.
*/
struct shr_id_proc_ctx *shr_id_proc_ctx_find(ka_pid_t pid)
{
struct shr_id_proc_ctx *proc_ctx = NULL;
ka_task_read_lock(&proc_lock);
proc_ctx = shr_id_find_proc(pid);
ka_task_read_unlock(&proc_lock);
return proc_ctx;
}
static void shr_id_proc_put(struct shr_id_proc_ctx *proc_ctx)
{
kref_safe_put(&proc_ctx->ref, shr_id_proc_release);
}
static int shr_id_name_generate(struct trs_id_inst *inst, int pid, int id_type, u32 shr_id, char *name)
{
int offset = snprintf_s(name, SHR_ID_NSM_NAME_SIZE, SHR_ID_NSM_NAME_SIZE - 1, "%08x%08x%08x%08x%08x",
pid, inst->devid, inst->tsid, id_type, shr_id);
if (offset < 0) {
trs_err("Snprintf failed. (offset=%d)\n", offset);
return -EINVAL;
}
name[offset] = '\0';
return 0;
}
static ka_list_head_t *shr_id_get_list_head(struct shr_id_proc_ctx *proc_ctx, int op)
{
return (op == 0) ? &proc_ctx->create_list_head : &proc_ctx->open_list_head;
}
static struct shr_id_proc_node *shr_id_find_proc_node(struct shr_id_proc_ctx *proc_ctx, const char *name, int op)
{
struct shr_id_proc_node *proc_node = NULL, *n = NULL;
ka_list_head_t *head;
head = shr_id_get_list_head(proc_ctx, op);
ka_task_read_lock(&proc_ctx->lock);
ka_list_for_each_entry_safe(proc_node, n, head, list) {
if (ka_base_strcmp(proc_node->name, name) == 0) {
ka_task_read_unlock(&proc_ctx->lock);
return proc_node;
}
}
ka_task_read_unlock(&proc_ctx->lock);
return NULL;
}
static int shr_id_add_to_proc(struct shr_id_proc_ctx *proc_ctx, struct shr_id_ioctl_info *ioctl_info,
struct shr_id_node_op_attr *attr, int op)
{
struct shr_id_proc_node *proc_node = NULL;
ka_task_mutex_lock(&proc_ctx->mutex);
proc_node = shr_id_find_proc_node(proc_ctx, ioctl_info->name, op);
if (proc_node != NULL) {
if ((ioctl_info->flag & TSDRV_FLAG_REMOTE_ID) != 0) {
ioctl_info->flag &= ~TSDRV_FLAG_REMOTE_ID;
}
if ((attr->flag & TSDRV_FLAG_SHR_ID_SHADOW) != 0) {
ioctl_info->flag |= TSDRV_FLAG_SHR_ID_SHADOW;
}
proc_node->ref++;
shr_id_proc_num_inc(proc_ctx, op, 1);
ka_task_mutex_unlock(&proc_ctx->mutex);
return 0;
}
proc_node = shr_id_creat_proc_node(ioctl_info->name, attr);
if (proc_node == NULL) {
ka_task_mutex_unlock(&proc_ctx->mutex);
return -ENOMEM;
}
if ((ioctl_info->flag & TSDRV_FLAG_REMOTE_ID) != 0) {
proc_node->opened_devid = ioctl_info->opened_devid;
proc_node->flag |= TSDRV_FLAG_REMOTE_ID;
ioctl_info->flag |= TSDRV_FLAG_REMOTE_ID;
}
if ((attr->flag & TSDRV_FLAG_SHR_ID_SHADOW) != 0) {
proc_node->flag |= TSDRV_FLAG_SHR_ID_SHADOW;
ioctl_info->flag |= TSDRV_FLAG_SHR_ID_SHADOW;
}
trs_debug("Add info. (devid=%u; tsid=%u; type=%d; id=%u; flag=%u; node_flag=0x%x; op=%d)\n",
attr->inst.devid, attr->inst.tsid, attr->res_type, attr->id, ioctl_info->flag, proc_node->flag, op);
ka_task_write_lock(&proc_ctx->lock);
ka_list_add_tail(&proc_node->list, shr_id_get_list_head(proc_ctx, op));
ka_task_write_unlock(&proc_ctx->lock);
shr_id_proc_num_inc(proc_ctx, op, 1);
ka_task_mutex_unlock(&proc_ctx->mutex);
return 0;
}
static void shr_id_del_from_proc(struct shr_id_proc_ctx *proc_ctx,
struct shr_id_ioctl_info *ioctl_info, int op)
{
struct shr_id_proc_node *proc_node = NULL;
ka_task_mutex_lock(&proc_ctx->mutex);
proc_node = shr_id_find_proc_node(proc_ctx, ioctl_info->name, op);
if (proc_node == NULL) {
ka_task_mutex_unlock(&proc_ctx->mutex);
return;
}
trs_debug("Del info. (devid=%u; tsid=%u; type=%d; id=%u; flag=%u; node_flag=%u; op=%d)\n",
proc_node->inst.devid, proc_node->inst.devid, proc_node->type, proc_node->id,
ioctl_info->flag, proc_node->flag, op);
shr_id_proc_num_dec(proc_ctx, op, 1);
proc_node->ref--;
if (proc_node->ref == 0) {
if ((proc_node->flag & TSDRV_FLAG_REMOTE_ID) != 0) {
ioctl_info->opened_devid = proc_node->opened_devid;
ioctl_info->flag |= TSDRV_FLAG_REMOTE_ID;
ioctl_info->devid = proc_node->inst.devid;
ioctl_info->tsid = proc_node->inst.tsid;
ioctl_info->id_type = (u32)proc_node->type;
ioctl_info->shr_id = (u32)proc_node->id;
if ((proc_node->flag & TSDRV_FLAG_SHR_ID_SHADOW) != 0) {
ioctl_info->flag |= TSDRV_FLAG_SHR_ID_SHADOW;
}
}
ka_task_write_lock(&proc_ctx->lock);
ka_list_del(&proc_node->list);
ka_task_write_unlock(&proc_ctx->lock);
shr_id_destroy_proc_node(proc_node);
}
ka_task_mutex_unlock(&proc_ctx->mutex);
}
int shr_id_wait_for_proc_exit(ka_pid_t pid)
{
int loop = 0;
do {
* First 100 times, sleep 1 ms, then sleep 1000 ms
* The waiting time must be greater than or equal to the recycle time
*/
unsigned long timeout = (loop < 100) ? 1 : 1000;
struct shr_id_proc_ctx *proc_ctx = NULL;
ka_task_read_lock(&proc_lock);
proc_ctx = shr_id_find_proc(pid);
ka_task_read_unlock(&proc_lock);
if (proc_ctx == NULL) {
return 0;
}
if (timeout <= 1) {
ka_system_usleep_range(timeout * USEC_PER_MSEC, timeout * USEC_PER_MSEC + 100);
} else {
if (ka_system_msleep_interruptible(timeout) != 0) {
return -EINTR;
}
}
} while (++loop < 400);
return -EEXIST;
}
int shr_id_proc_add(struct shr_id_proc_ctx *proc_ctx)
{
ka_task_write_lock(&proc_lock);
if (shr_id_find_proc(proc_ctx->pid) != NULL) {
ka_task_write_unlock(&proc_lock);
trs_err("Proc add fail. (pid=%d)\n", proc_ctx->pid);
return -EINVAL;
}
_shr_id_proc_add(proc_ctx);
ka_task_write_unlock(&proc_lock);
return 0;
}
void shr_id_proc_del(struct shr_id_proc_ctx *proc_ctx)
{
shr_id_proc_put(proc_ctx);
}
bool shr_id_is_belong_to_proc(struct trs_id_inst *inst, int pid, int res_type, u32 res_id)
{
struct shr_id_proc_node *proc_node = NULL, *n = NULL;
struct shr_id_proc_ctx *proc_ctx = NULL;
bool is_belong = false;
proc_ctx = shr_id_proc_get(pid);
if (proc_ctx == NULL) {
return false;
}
ka_task_read_lock(&proc_ctx->lock);
ka_list_for_each_entry_safe(proc_node, n, &proc_ctx->open_list_head, list) {
if ((proc_node->inst.devid == inst->devid) && (proc_node->inst.tsid == inst->tsid) &&
(proc_node->res_type == res_type) && (proc_node->id == res_id)) {
is_belong = true;
break;
}
}
* so host app need call halShridCreate.
*/
ka_list_for_each_entry_safe(proc_node, n, &proc_ctx->create_list_head, list) {
if ((proc_node->inst.devid == inst->devid) && (proc_node->inst.tsid == inst->tsid) &&
(proc_node->res_type == res_type) && (proc_node->id == res_id)) {
is_belong = true;
break;
}
}
ka_task_read_unlock(&proc_ctx->lock);
shr_id_proc_put(proc_ctx);
trs_debug("Id info. (devid=%u; tsid=%u; pid=%d; type=%d; shrid=%u; is=%u)\n",
inst->devid, inst->tsid, ka_task_get_current_tgid(), res_type, res_id, is_belong);
return is_belong;
}
static int shr_id_res_get(struct trs_id_inst *inst, int res_type, u32 res_id)
{
return trs_res_id_get(inst, res_type, res_id);
}
static int shr_id_res_put(struct trs_id_inst *inst, int res_type, u32 res_id)
{
return trs_res_id_put(inst, res_type, res_id);
}
static int shr_id_reomote_res_check(struct trs_id_inst *inst, int res_type, u32 res_id)
{
return trs_res_id_check(inst, res_type, res_id);
}
static int shr_id_set_stars_die_id(u32 devid, u32 tsid, struct shr_id_node_op_attr *attr)
{
int ret;
ret = trs_core_get_stars_die_id(devid, tsid, &attr->stars_die_id);
if (ret != 0) {
trs_err("Set stars die id failed. (devid=%u; tsid=%u; ret=%d)\n", devid, tsid, ret);
return -EINVAL;
}
trs_debug("Set stars die id. (devid=%u; tsid=%u; stars_die_id=%d)\n", devid, tsid, attr->stars_die_id);
return 0;
}
static int shr_id_node_attr_pack(struct shr_id_node_op_attr *attr, ka_pid_t pid, u64 start_time,
struct shr_id_ioctl_info *ioctl_info)
{
u32 type = ioctl_info->id_type;
int ret, i;
attr->res_type = shr_id_type_trans[type];
attr->type = (int)type;
attr->id = ioctl_info->shr_id;
attr->flag = ioctl_info->flag;
attr->pid = pid;
attr->start_time = start_time;
if ((attr->flag & TSDRV_FLAG_REMOTE_ID) != 0) {
attr->res_get = shr_id_reomote_res_check;
attr->res_put = NULL;
} else {
attr->res_get = shr_id_res_get;
attr->res_put = shr_id_res_put;
}
ret = shr_id_set_stars_die_id(ioctl_info->devid, ioctl_info->tsid, attr);
if (ret != 0) {
return ret;
}
trs_id_inst_pack(&attr->inst, ioctl_info->devid, ioctl_info->tsid);
ret = shr_id_name_generate(&attr->inst, pid, (int)type, ioctl_info->shr_id, attr->name);
if (ret != 0) {
return ret;
}
ret = shr_id_name_update(attr->inst.devid, attr->name);
if (ret != 0) {
return ret;
}
for (i = 0; i < SHR_ID_NSM_NAME_SIZE; i++) {
ioctl_info->name[i] = attr->name[i];
}
return ret;
}
int shr_id_create(struct shr_id_proc_ctx *proc_ctx, unsigned long arg)
{
struct shr_id_ioctl_info ioctl_info;
struct shr_id_node_op_attr attr = { { 0 } };
int ret;
if (ka_base_copy_from_user(&ioctl_info, (void *)(uintptr_t)arg, sizeof(struct shr_id_ioctl_info)) != 0) {
trs_err("Copy from user fail.\n");
return -EFAULT;
}
if (uda_can_access_udevid(ioctl_info.devid) == false) {
trs_err("Device is not in container. (devid=%u)\n", ioctl_info.devid);
return -EINVAL;
}
if (ioctl_info.id_type >= SHR_ID_TYPE_MAX) {
trs_err("Para invalid. (devid=%u; tsid=%u; idtype=%u)\n",
ioctl_info.devid, ioctl_info.tsid, ioctl_info.id_type);
return -EINVAL;
}
ret = shr_id_node_attr_pack(&attr, proc_ctx->pid, proc_ctx->start_time, &ioctl_info);
if (ret != 0) {
return ret;
}
ret = shr_id_node_create(&attr);
if (ret != 0) {
return ret;
}
ret = shr_id_add_to_proc(proc_ctx, &ioctl_info, &attr, 0);
if (ret != 0) {
(void)shr_id_node_destroy(ioctl_info.name, (int)ioctl_info.id_type, proc_ctx->pid, DEVDRV_S2S_SYNC_MODE);
return ret;
}
if (ka_base_copy_to_user((void *)(uintptr_t)arg, &ioctl_info, sizeof(struct shr_id_ioctl_info)) != 0) {
trs_err("Copy to user fail.\n");
shr_id_del_from_proc(proc_ctx, &ioctl_info, 0);
(void)shr_id_node_destroy(ioctl_info.name, (int)ioctl_info.id_type, proc_ctx->pid, DEVDRV_S2S_SYNC_MODE);
return -EFAULT;
}
return ret;
}
int shr_id_destroy(struct shr_id_proc_ctx *proc_ctx, unsigned long arg)
{
struct shr_id_ioctl_info ioctl_info;
int ret, type;
if (ka_base_copy_from_user(&ioctl_info, (void *)(uintptr_t)arg, sizeof(struct shr_id_ioctl_info)) != 0) {
trs_err("Copy from user fail.\n");
return -EFAULT;
}
ret = shr_id_get_type_by_name(ioctl_info.name, &type);
if (ret != 0) {
return ret;
}
ret = shr_id_node_destroy(ioctl_info.name, type, proc_ctx->pid, DEVDRV_S2S_SYNC_MODE);
if (ret != 0) {
trs_err("Destroy shr id node fail. (type=%d; ret=%d)\n", type, ret);
return ret;
}
shr_id_del_from_proc(proc_ctx, &ioctl_info, 0);
return 0;
}
int shr_id_set_attr(struct shr_id_proc_ctx *proc_ctx, unsigned long arg)
{
struct shr_id_ioctl_info ioctl_info;
int ret, type;
ret = ka_base_copy_from_user(&ioctl_info, (void *)(uintptr_t)arg, sizeof(struct shr_id_ioctl_info));
if (ret != 0) {
trs_err("Copy from user fail.\n");
return -EFAULT;
}
ret = shr_id_get_type_by_name(ioctl_info.name, &type);
if (ret != 0) {
return ret;
}
ret = shr_id_node_set_attr(ioctl_info.name, type, proc_ctx->pid);
return ret;
}
int shr_id_get_attr(struct shr_id_proc_ctx *proc_ctx, unsigned long arg)
{
struct shr_id_ioctl_info ioctl_info = { 0 };
int ret, type;
ret = ka_base_copy_from_user(&ioctl_info, (void *)(uintptr_t)arg, sizeof(struct shr_id_ioctl_info));
if (ret != 0) {
trs_err("Copy from user fail.\n");
return -EFAULT;
}
ret = shr_id_get_type_by_name(ioctl_info.name, &type);
if (ret != 0) {
return ret;
}
ret = shr_id_node_get_attribute(ioctl_info.name, type, &ioctl_info);
if (ret != 0) {
trs_err("Get shr id info fail.\n");
return ret;
}
ret = ka_base_copy_to_user((void *)(uintptr_t)arg, &ioctl_info, sizeof(struct shr_id_ioctl_info));
if (ret != 0) {
trs_err("Copy to user fail.\n");
return -EFAULT;
}
return 0;
}
int shr_id_get_info(struct shr_id_proc_ctx *proc_ctx, unsigned long arg)
{
struct shr_id_ioctl_info ioctl_info = { 0 };
int ret, type;
ret = ka_base_copy_from_user(&ioctl_info, (void *)(uintptr_t)arg, sizeof(struct shr_id_ioctl_info));
if (ret != 0) {
trs_err("Copy from user fail.\n");
return -EFAULT;
}
ret = shr_id_get_type_by_name(ioctl_info.name, &type);
if (ret != 0) {
return ret;
}
ret = shr_id_node_get_info(ioctl_info.name, type, &ioctl_info);
if (ret != 0) {
trs_err("Get shr id info fail.\n");
return ret;
}
ret = ka_base_copy_to_user((void *)(uintptr_t)arg, &ioctl_info, sizeof(struct shr_id_ioctl_info));
if (ret != 0) {
trs_err("Copy to user fail.\n");
return -EFAULT;
}
return 0;
}
int shr_id_open(struct shr_id_proc_ctx *proc_ctx, unsigned long arg)
{
struct shr_id_ioctl_info ioctl_info;
struct shr_id_node_op_attr attr;
int ret, type;
if (ka_base_copy_from_user(&ioctl_info, (void *)(uintptr_t)arg, sizeof(struct shr_id_ioctl_info)) != 0) {
trs_err("Copy from user fail.\n");
return -EFAULT;
}
ret = shr_id_get_type_by_name(ioctl_info.name, &type);
if (ret != 0) {
return ret;
}
attr.res_type = shr_id_type_trans[type];
attr.type = type;
ret = shr_id_node_open(ioctl_info.name, proc_ctx->pid, proc_ctx->start_time, &attr);
if (ret != 0) {
return ret;
}
ret = shr_id_add_to_proc(proc_ctx, &ioctl_info, &attr, 1);
if (ret != 0) {
(void)shr_id_node_close(ioctl_info.name, type, proc_ctx->pid);
return ret;
}
ioctl_info.devid = attr.inst.devid;
ioctl_info.tsid = attr.inst.tsid;
ioctl_info.id_type = (u32)attr.type;
ioctl_info.shr_id = (u32)attr.id;
ioctl_info.rsv[0] = attr.stars_die_id;
if (ka_base_copy_to_user((void *)(uintptr_t)arg, &ioctl_info, sizeof(struct shr_id_ioctl_info)) != 0) {
trs_err("Copy to user fail.\n");
shr_id_del_from_proc(proc_ctx, &ioctl_info, 1);
(void)shr_id_node_close(ioctl_info.name, type, proc_ctx->pid);
return -EFAULT;
}
return 0;
}
int shr_id_close(struct shr_id_proc_ctx *proc_ctx, unsigned long arg)
{
struct shr_id_ioctl_info ioctl_info;
int ret, type;
if (ka_base_copy_from_user(&ioctl_info, (void *)(uintptr_t)arg, sizeof(struct shr_id_ioctl_info)) != 0) {
trs_err("Copy from user fail.\n");
return -EFAULT;
}
ret = shr_id_get_type_by_name(ioctl_info.name, &type);
if (ret != 0) {
return ret;
}
ret = shr_id_node_close(ioctl_info.name, type, proc_ctx->pid);
if (ret != 0) {
return ret;
}
shr_id_del_from_proc(proc_ctx, &ioctl_info, 1);
if (ka_base_copy_to_user((void *)(uintptr_t)arg, &ioctl_info, sizeof(struct shr_id_ioctl_info)) != 0) {
trs_err("Copy to user fail.\n");
return -EFAULT;
}
return 0;
}
int shr_id_set_pid(struct shr_id_proc_ctx *proc_ctx, unsigned long arg)
{
struct shr_id_ioctl_info ioctl_info;
int ret, type;
if (ka_base_copy_from_user(&ioctl_info, (void *)(uintptr_t)arg, sizeof(struct shr_id_ioctl_info)) != 0) {
trs_err("Copy from user fail.\n");
return -EFAULT;
}
ret = shr_id_get_type_by_name(ioctl_info.name, &type);
if (ret != 0) {
return ret;
}
return shr_id_node_set_pids(ioctl_info.name, type, proc_ctx->pid, ioctl_info.pid, SHR_ID_PID_MAX_NUM);
}
int shr_id_record(struct shr_id_proc_ctx *proc_ctx, unsigned long arg)
{
struct shr_id_ioctl_info ioctl_info;
int ret, type;
if (ka_base_copy_from_user(&ioctl_info, (void *)(uintptr_t)arg, sizeof(struct shr_id_ioctl_info)) != 0) {
trs_err("Copy from user fail.\n");
return -EFAULT;
}
ret = shr_id_get_type_by_name(ioctl_info.name, &type);
if (ret != 0) {
return ret;
}
ret = shr_id_node_record(ioctl_info.name, type, proc_ctx->pid);
if (ret != 0) {
return ret;
}
return 0;
}
return val:
true: shrid is destroyed by ioctl cmd: SHR_ID_DESTROY
false: shrid is destroyed by shr_id_file_release
*/
bool shr_id_is_destroyed_in_process(int pid, unsigned long start_time)
{
struct shr_id_proc_ctx *proc_ctx = NULL;
bool in_process = false;
proc_ctx = shr_id_proc_get(pid);
if (proc_ctx == NULL) {
return false;
}
if (ka_system_time_before_eq((unsigned long)proc_ctx->start_time, start_time)) {
if (ka_base_atomic_read(&proc_ctx->proc_in_release) == 0) {
in_process = true;
}
}
shr_id_proc_put(proc_ctx);
return in_process;
}