* 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 "securec.h"
#include "ka_base_pub.h"
#include "ka_list_pub.h"
#include "pbl_mem_alloc_interface.h"
#include "udis_log.h"
#include "udis_management.h"
struct udis_node *udis_addr_list_find_node(const struct udis_ctrl_block *udis_cb, UDIS_MODULE_TYPE module_type,
const char *name)
{
int i;
struct udis_node *addr_node, *next = NULL;
for (i = UPDATE_ONLY_ONCE; i < UPDATE_TYPE_MAX; ++i) {
ka_list_for_each_entry_safe(addr_node, next, &udis_cb->addr_list[i], list) {
if ((addr_node->module_type == module_type) && (ka_base_strcmp(addr_node->name, name) == 0)) {
return addr_node;
}
}
}
return NULL;
}
int udis_addr_list_add_node(unsigned int udevid, struct udis_ctrl_block *udis_cb,
const struct udis_node *addr_node)
{
int ret;
struct udis_node *new_node = NULL;
new_node = dbl_kzalloc(sizeof(struct udis_node), KA_GFP_KERNEL | __KA_GFP_ACCOUNT);
if (new_node == NULL) {
udis_err("Failed to malloc for udis_node. (udevid=%u; module_type=%u; name=%s)\n",
udevid, addr_node->module_type, addr_node->name);
return -ENOMEM;
}
ret = strcpy_s(new_node->name, UDIS_MAX_NAME_LEN, addr_node->name);
if (ret != 0) {
udis_err("strncpy_s failed. (module_type=%u; name=%s; ret=%d)\n",
addr_node->module_type, addr_node->name, ret);
dbl_kfree(new_node);
return -ENOMEM;
}
ret = strcpy_s(new_node->device_segment, UDIS_SEGMENT_MAX_LEN, addr_node->device_segment);
if (ret != 0) {
udis_err("strncpy_s failed. (module_type=%u; name=%s; ret=%d)\n",
addr_node->module_type, addr_node->name, ret);
dbl_kfree(new_node);
return -ENOMEM;
}
new_node->module_type = addr_node->module_type;
new_node->update_type = addr_node->update_type;
new_node->dev_dma_addr = addr_node->dev_dma_addr;
new_node->host_dma_addr = addr_node->host_dma_addr;
new_node->data_len = addr_node->data_len;
new_node->host_va_addr = addr_node->host_va_addr;
new_node->dev_va_addr = addr_node->dev_va_addr;
new_node->dev_va_addr_attr = addr_node->dev_va_addr_attr;
new_node->host_segment = addr_node->host_segment;
new_node->device_segment_import = addr_node->device_segment_import;
new_node->host_segment_len = addr_node->host_segment_len;
new_node->device_segment_import_len = addr_node->device_segment_import_len;
new_node->token_value = addr_node->token_value;
new_node->device_segment_len = addr_node->device_segment_len;
ka_list_add(&new_node->list, &udis_cb->addr_list[addr_node->update_type]);
return 0;
}
void udis_addr_list_remove_node(unsigned int udevid, struct udis_ctrl_block *udis_cb,
const struct udis_node *addr_node)
{
struct udis_node *node = NULL;
node = udis_addr_list_find_node(udis_cb, addr_node->module_type, addr_node->name);
if (node == NULL) {
udis_err("No matched node found. (udevid=%u; module_type=%u; name=%s)\n", udevid, addr_node->module_type,
addr_node->name);
return;
}
ka_list_del(&node->list);
dbl_kfree(node);
node = NULL;
return;
}