diff --git a/drivers/misc/ethosn/ethosn_asset_allocator.c b/drivers/misc/ethosn/ethosn_asset_allocator.c index 2f3c6acd6ffd..790ba1dd08ab 100644 --- a/drivers/misc/ethosn/ethosn_asset_allocator.c +++ b/drivers/misc/ethosn/ethosn_asset_allocator.c @@ -39,6 +39,7 @@ static void ethosn_asset_allocator_unreserve(struct ethosn_dma_allocator *asset_ asset_allocator->pid = ETHOSN_INVALID_PID; } +// 引用计数清空时的回调函数: 重置绑定的进程, 使当前 asset_allocator 可用 static void asset_allocator_kref_release(struct kref *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); } +// 将当前 asset_allocator 引用计数 + 1 void ethosn_asset_allocator_get(struct ethosn_dma_allocator *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. * * 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) { if (WARN_ON_ONCE(!asset_allocator)) diff --git a/drivers/misc/ethosn/ethosn_dma.h b/drivers/misc/ethosn/ethosn_dma.h index 0ce8938fa16f..77e659da1362 100644 --- a/drivers/misc/ethosn/ethosn_dma.h +++ b/drivers/misc/ethosn/ethosn_dma.h @@ -105,9 +105,9 @@ struct ethosn_dma_allocator { enum ethosn_alloc_type type; uint32_t alloc_id; struct device *dev; - struct kref kref; - pid_t pid; - __u8 is_protected; + struct kref kref; // 引用计数, 标识当前allocator需要被其他进程占用 + pid_t pid; // 占用当前allocator的进程id + __u8 is_protected; // 当前allocator是否允许被同一进程重复占用 }; /** diff --git a/drivers/misc/ethosn/ethosn_network.c b/drivers/misc/ethosn/ethosn_network.c index c737e40284f4..10212693b13b 100644 --- a/drivers/misc/ethosn/ethosn_network.c +++ b/drivers/misc/ethosn/ethosn_network.c @@ -651,7 +651,7 @@ static int ethosn_inference_register(struct ethosn_network *network, struct etho if (ret_fd < 0) 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(ðosn->queue.inference_queue_mutex); /* 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; struct device *dev = net_to_dev(network); + // total buffer nums num_bindings = req->cu_buffers.num; num_bindings += req->dma_buffers.num; num_bindings += req->intermediate_desc.buffers.num; num_bindings += req->input_buffers.num; num_bindings += req->output_buffers.num; + // 构造 ethos 设备可识别的 buffer 阵列 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 * ethosn_buffer_array. */ + // 推理数据需要每一个 core 单独构造: 不同的 core 可能有不同的中间数据入口 network->inference_data = devm_kzalloc(dev, (sizeof(*(network->inference_data)) * num_cores), GFP_KERNEL); if (!network->inference_data) return ret; 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"); if (IS_ERR_OR_NULL(network->inference_data[i])) { 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; goto out_free_inference_data; } - + // 如果请求中存在中间层数据描述信息表明需要缓冲区, 则按照要求为其分配或者导入 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) ret = import_intermediate_data(network, req, num_bindings); else @@ -1131,10 +1133,11 @@ static struct ethosn_network *create_network(struct ethosn_device *ethosn, struc 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) 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)) { dev_err(dev, "Error reading constant dma data\n"); ret = -EINVAL; @@ -1158,6 +1161,7 @@ static struct ethosn_network *create_network(struct ethosn_device *ethosn, struc goto err_unmap_const_cu_data; } + // 这里我们看到 net_req 只给了推理数据的 IO buffer 的描述 ret = alloc_init_inference_data(network, net_req); if (ret) 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) 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; } diff --git a/drivers/misc/ethosn/ethosn_network.h b/drivers/misc/ethosn/ethosn_network.h index a1def9def93b..e953fb827f99 100644 --- a/drivers/misc/ethosn/ethosn_network.h +++ b/drivers/misc/ethosn/ethosn_network.h @@ -47,7 +47,7 @@ struct ethosn_network { u32 num_inputs; struct ethosn_buffer_info *inputs; - + u32 num_outputs; struct ethosn_buffer_info *outputs; diff --git a/drivers/misc/ethosn/ethosn_proc_mem_allocator.c b/drivers/misc/ethosn/ethosn_proc_mem_allocator.c index f62135c2f05d..e186e0f1210d 100644 --- a/drivers/misc/ethosn/ethosn_proc_mem_allocator.c +++ b/drivers/misc/ethosn/ethosn_proc_mem_allocator.c @@ -271,7 +271,7 @@ int ethosn_process_mem_allocator_create(struct ethosn_device *ethosn, pid_t pid, int ret = 0; int fd; 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) { 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; 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); 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; + // 创建一个匿名的inode节点, 并关联一个文件描述符和文件的io操作 fd = anon_inode_getfd("ethosn-memory-allocator", &allocator_fops, proc_mem_allocator, O_RDONLY | O_CLOEXEC); if (fd < 0) { ret = -ENOMEM;