* 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 "pbl_feature_loader.h"
#include "pbl_soc_res.h"
#include "pbl_uda.h"
#include "svm_pub.h"
#include "svm_kern_log.h"
#include "svm_sub_event_type.h"
#include "va_reserve_msg.h"
#include "linear_mem.h"
#define AIC_ATU_CFG_NAME "AIC_ATU_CFG_BASE"
int linear_mem_enable(u32 udevid, int tgid, void *start_time)
{
static bool linear_mem_enable_flag = false;
int ret;
if (linear_mem_enable_flag == false) {
ret = uda_dev_ctrl(udevid, UDA_CTRL_AIC_ATU_CFG);
if (ret != 0) {
svm_err("uda_dev_ctrl_ex failed. (ret=%d; udevid=%u)\n", ret, udevid);
return ret;
}
linear_mem_enable_flag = true;
}
return 0;
}
DECLAER_FEATURE_AUTO_INIT_TASK(linear_mem_enable, FEATURE_LOADER_STAGE_2);
static int linear_mem_set_addr_info(u32 udevid, u64 va, u64 size)
{
struct soc_reg_base_info io_base;
int ret;
ret = soc_resmng_dev_get_reg_base(udevid, AIC_ATU_CFG_NAME, &io_base);
if (ret == 0) {
if ((io_base.io_base == va) && (io_base.io_base_size == size)) {
return 0;
}
svm_warn("Repeat set different base. (udevid=%u)\n", udevid);
}
io_base.io_base = va;
io_base.io_base_size = size;
ret = soc_resmng_dev_set_reg_base(udevid, AIC_ATU_CFG_NAME, &io_base);
if (ret != 0) {
svm_err("Set linear_mem_base failed. (ret=%d; udevid=%u)\n", ret, udevid);
return ret;
}
return 0;
}
static int um_va_reserve_post_handle(u32 udevid, int master_tgid, int slave_tgid, void *msg, u32 msg_len)
{
struct svm_va_reserve_msg *reserve_msg = (struct svm_va_reserve_msg *)msg;
int ret = 0;
if (msg_len != sizeof(*reserve_msg)) {
svm_err("Invalid para. (udevid=%u; master_tgid=%d; slave_tgid=%d; msg_len=%u)\n",
udevid, master_tgid, slave_tgid, msg_len);
return -EINVAL;
}
if (reserve_msg->status != VA_RESERVE_STATUS_OK) {
return 0;
}
if (((reserve_msg->flag & SVM_MMAP_FLAG_PRIVATE) != 0) && (reserve_msg->size > SVM_BYTES_PER_TB)) {
ret = linear_mem_set_addr_info(udevid, reserve_msg->va, reserve_msg->size);
}
return ret;
}
int linear_mem_device_um_handle_init(void)
{
svm_um_register_handle(SVM_VA_RESERVE_EVENT, NULL, NULL, um_va_reserve_post_handle);
return 0;
}
DECLAER_FEATURE_AUTO_INIT(linear_mem_device_um_handle_init, FEATURE_LOADER_STAGE_2);