many modifications

This commit is contained in:
penn 2024-10-31 18:24:11 +08:00
parent 0075e53985
commit bbc161cfd6
5 changed files with 21 additions and 13 deletions

View file

@ -39,6 +39,7 @@ static void ethosn_asset_allocator_unreserve(struct ethosn_dma_allocator *asset_
asset_allocator->pid = ETHOSN_INVALID_PID; asset_allocator->pid = ETHOSN_INVALID_PID;
} }
// 引用计数清空时的回调函数: 重置绑定的进程, 使当前 asset_allocator 可用
static void asset_allocator_kref_release(struct kref *kref) static void asset_allocator_kref_release(struct kref *kref)
{ {
struct ethosn_dma_allocator *const asset_allocator = container_of(kref, struct ethosn_dma_allocator, kref); struct ethosn_dma_allocator *const asset_allocator = container_of(kref, struct ethosn_dma_allocator, kref);
@ -46,6 +47,7 @@ static void asset_allocator_kref_release(struct kref *kref)
ethosn_asset_allocator_unreserve(asset_allocator); ethosn_asset_allocator_unreserve(asset_allocator);
} }
// 将当前 asset_allocator 引用计数 + 1
void ethosn_asset_allocator_get(struct ethosn_dma_allocator *asset_allocator) void ethosn_asset_allocator_get(struct ethosn_dma_allocator *asset_allocator)
{ {
if (WARN_ON_ONCE(!asset_allocator)) if (WARN_ON_ONCE(!asset_allocator))
@ -72,6 +74,7 @@ void ethosn_asset_allocator_get(struct ethosn_dma_allocator *asset_allocator)
* * -EINVAL: If asset_allocator is NULL. * * -EINVAL: If asset_allocator is NULL.
* * 1 if the object was released and 0 otherwise. * * 1 if the object was released and 0 otherwise.
*/ */
// 当前 asset_allocator 引用计数 - 1
int __must_check ethosn_asset_allocator_put(struct ethosn_dma_allocator *asset_allocator) int __must_check ethosn_asset_allocator_put(struct ethosn_dma_allocator *asset_allocator)
{ {
if (WARN_ON_ONCE(!asset_allocator)) if (WARN_ON_ONCE(!asset_allocator))

View file

@ -105,9 +105,9 @@ struct ethosn_dma_allocator {
enum ethosn_alloc_type type; enum ethosn_alloc_type type;
uint32_t alloc_id; uint32_t alloc_id;
struct device *dev; struct device *dev;
struct kref kref; struct kref kref; // 引用计数, 标识当前allocator需要被其他进程占用
pid_t pid; pid_t pid; // 占用当前allocator的进程id
__u8 is_protected; __u8 is_protected; // 当前allocator是否允许被同一进程重复占用
}; };
/** /**

View file

@ -651,7 +651,7 @@ static int ethosn_inference_register(struct ethosn_network *network, struct etho
if (ret_fd < 0) if (ret_fd < 0)
goto err_free_inference; goto err_free_inference;
dev_dbg(dev, "Registered %sprotected inference. handle=0x%pK\n", network->asset_allocator->is_protected ? "" : "non-", inference); dev_dbg(dev, "Registered %sprotected inference. handle=0x%pK\n", network->asset_allocator->is_protected ? "":"non-", inference);
ret = mutex_lock_interruptible(&ethosn->queue.inference_queue_mutex); ret = mutex_lock_interruptible(&ethosn->queue.inference_queue_mutex);
/* Return the file descriptor */ /* Return the file descriptor */
@ -955,12 +955,14 @@ static int alloc_init_inference_data(struct ethosn_network *network, struct etho
int num_cores = network->ethosn->num_cores; int num_cores = network->ethosn->num_cores;
struct device *dev = net_to_dev(network); struct device *dev = net_to_dev(network);
// total buffer nums
num_bindings = req->cu_buffers.num; num_bindings = req->cu_buffers.num;
num_bindings += req->dma_buffers.num; num_bindings += req->dma_buffers.num;
num_bindings += req->intermediate_desc.buffers.num; num_bindings += req->intermediate_desc.buffers.num;
num_bindings += req->input_buffers.num; num_bindings += req->input_buffers.num;
num_bindings += req->output_buffers.num; num_bindings += req->output_buffers.num;
// 构造 ethos 设备可识别的 buffer 阵列
size = sizeof(struct ethosn_buffer_array) + num_bindings * sizeof(struct ethosn_buffer_desc); size = sizeof(struct ethosn_buffer_array) + num_bindings * sizeof(struct ethosn_buffer_desc);
/* /*
@ -969,11 +971,14 @@ static int alloc_init_inference_data(struct ethosn_network *network, struct etho
* unique entry for the "intermediate data" inside the * unique entry for the "intermediate data" inside the
* ethosn_buffer_array. * ethosn_buffer_array.
*/ */
// 推理数据需要每一个 core 单独构造: 不同的 core 可能有不同的中间数据入口
network->inference_data = devm_kzalloc(dev, (sizeof(*(network->inference_data)) * num_cores), GFP_KERNEL); network->inference_data = devm_kzalloc(dev, (sizeof(*(network->inference_data)) * num_cores), GFP_KERNEL);
if (!network->inference_data) if (!network->inference_data)
return ret; return ret;
for (i = 0; i < num_cores; i++) { for (i = 0; i < num_cores; i++) {
// 每一个 core 都构造一段用来保存全部 buffer 信息的 ethosn_buffer_array, 注意到 ethosn_buffer_array 只是描述了每一段 buffer 的起点长度和类型以及这些 buffer 有多少个, 这样就完成了整个数据的串化
// core 只需要根据 ethosn_buffer_array 取出这些 buffer 的内容即可完成数据的恢复
network->inference_data[i] = ethosn_dma_alloc_and_map(network->asset_allocator, size, ETHOSN_PROT_READ, ETHOSN_STREAM_COMMAND_STREAM, GFP_KERNEL, "network-inference-data"); network->inference_data[i] = ethosn_dma_alloc_and_map(network->asset_allocator, size, ETHOSN_PROT_READ, ETHOSN_STREAM_COMMAND_STREAM, GFP_KERNEL, "network-inference-data");
if (IS_ERR_OR_NULL(network->inference_data[i])) { if (IS_ERR_OR_NULL(network->inference_data[i])) {
dev_dbg(dev, "DMA alloc and map of network-inference-data failed\n"); dev_dbg(dev, "DMA alloc and map of network-inference-data failed\n");
@ -993,11 +998,8 @@ static int alloc_init_inference_data(struct ethosn_network *network, struct etho
ret = -ENOMEM; ret = -ENOMEM;
goto out_free_inference_data; goto out_free_inference_data;
} }
// 如果请求中存在中间层数据描述信息表明需要缓冲区, 则按照要求为其分配或者导入
if (req->intermediate_desc.buffers.num) { if (req->intermediate_desc.buffers.num) {
/* If there are intermediate buffers, then allocate or import
* memory for them.
*/
if (req->intermediate_desc.memory.type == IMPORT) if (req->intermediate_desc.memory.type == IMPORT)
ret = import_intermediate_data(network, req, num_bindings); ret = import_intermediate_data(network, req, num_bindings);
else else
@ -1131,10 +1133,11 @@ static struct ethosn_network *create_network(struct ethosn_device *ethosn, struc
goto err_free_network; goto err_free_network;
} }
ret = ethosn_dma_map(asset_alloc, network->constant_dma_data, ETHOSN_PROT_READ); ret = ethosn_dma_map(asset_alloc, network->constant_dma_data, ETHOSN_PROT_READ); // 映射到 IOVA 地址空间之后, 权重数据是只读的
if (ret) if (ret)
goto err_free_const_dma_data; goto err_free_const_dma_data;
// 从用户空间拷贝到 DMA 内存空间
if (copy_from_user(network->constant_dma_data->cpu_addr, net_req->dma_data.data, net_req->dma_data.size)) { if (copy_from_user(network->constant_dma_data->cpu_addr, net_req->dma_data.data, net_req->dma_data.size)) {
dev_err(dev, "Error reading constant dma data\n"); dev_err(dev, "Error reading constant dma data\n");
ret = -EINVAL; ret = -EINVAL;
@ -1158,6 +1161,7 @@ static struct ethosn_network *create_network(struct ethosn_device *ethosn, struc
goto err_unmap_const_cu_data; goto err_unmap_const_cu_data;
} }
// 这里我们看到 net_req 只给了推理数据的 IO buffer 的描述
ret = alloc_init_inference_data(network, net_req); ret = alloc_init_inference_data(network, net_req);
if (ret) if (ret)
goto err_unmap_const_cu_data; goto err_unmap_const_cu_data;
@ -1257,7 +1261,7 @@ int ethosn_network_register(struct ethosn_device *ethosn, struct ethosn_dma_allo
if (asset_allocator->pid != ETHOSN_INVALID_PID) if (asset_allocator->pid != ETHOSN_INVALID_PID)
ethosn_asset_allocator_get(asset_allocator); ethosn_asset_allocator_get(asset_allocator);
dev_dbg(ethosn->dev, "Registered %sprotected network. handle=0x%pK\n", network->asset_allocator->is_protected ? "" : "non-", network); dev_dbg(ethosn->dev, "Registered %sprotected network. handle=0x%pK\n", network->asset_allocator->is_protected ? "":"non-", network);
return fd; return fd;
} }

View file

@ -47,7 +47,7 @@ struct ethosn_network {
u32 num_inputs; u32 num_inputs;
struct ethosn_buffer_info *inputs; struct ethosn_buffer_info *inputs;
u32 num_outputs; u32 num_outputs;
struct ethosn_buffer_info *outputs; struct ethosn_buffer_info *outputs;

View file

@ -271,7 +271,7 @@ int ethosn_process_mem_allocator_create(struct ethosn_device *ethosn, pid_t pid,
int ret = 0; int ret = 0;
int fd; int fd;
struct ethosn_allocator *proc_mem_allocator; struct ethosn_allocator *proc_mem_allocator;
struct ethosn_dma_allocator *asset_allocator = ethosn_asset_allocator_find(ethosn, pid); // pid 的主要用来索引 asset_allocator, 一个 pid 对应一个 asset_allocator struct ethosn_dma_allocator *asset_allocator = ethosn_asset_allocator_find(ethosn, pid); // 当前进程是否正占用设备的asset_allocator?
if (pid <= 0) { if (pid <= 0) {
dev_err(ethosn->dev, "%s: Unsupported pid=%d, must be >0\n", __func__, pid); dev_err(ethosn->dev, "%s: Unsupported pid=%d, must be >0\n", __func__, pid);
@ -298,7 +298,7 @@ int ethosn_process_mem_allocator_create(struct ethosn_device *ethosn, pid_t pid,
proc_mem_allocator->ethosn = ethosn; proc_mem_allocator->ethosn = ethosn;
if (IS_ERR_OR_NULL(asset_allocator)) { if (IS_ERR_OR_NULL(asset_allocator)) {
/* No existing allocator for process */ // 当前进程并未占用任何asset_allocator: 找一个可用的占用
proc_mem_allocator->asset_allocator = ethosn_asset_allocator_reserve(ethosn, pid); proc_mem_allocator->asset_allocator = ethosn_asset_allocator_reserve(ethosn, pid);
if (!proc_mem_allocator->asset_allocator) { if (!proc_mem_allocator->asset_allocator) {
@ -323,6 +323,7 @@ int ethosn_process_mem_allocator_create(struct ethosn_device *ethosn, pid_t pid,
proc_mem_allocator->asset_allocator->is_protected = protected; proc_mem_allocator->asset_allocator->is_protected = protected;
// 创建一个匿名的inode节点, 并关联一个文件描述符和文件的io操作
fd = anon_inode_getfd("ethosn-memory-allocator", &allocator_fops, proc_mem_allocator, O_RDONLY | O_CLOEXEC); fd = anon_inode_getfd("ethosn-memory-allocator", &allocator_fops, proc_mem_allocator, O_RDONLY | O_CLOEXEC);
if (fd < 0) { if (fd < 0) {
ret = -ENOMEM; ret = -ENOMEM;