diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c index 56b4d9477..39581eb2d 100644 --- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c @@ -674,6 +674,69 @@ clean_up: return err; } +static int nvgpu_gpu_get_engine_info( + struct gk20a *g, + struct nvgpu_gpu_get_engine_info_args *args) +{ + int err = 0; + u32 engine_enum = ENGINE_INVAL_GK20A; + u32 report_index = 0; + u32 engine_id_idx; + const u32 max_buffer_engines = args->engine_info_buf_size / + sizeof(struct nvgpu_gpu_get_engine_info_item); + struct nvgpu_gpu_get_engine_info_item __user *dst_item_list = + (void __user *)(uintptr_t)args->engine_info_buf_addr; + + for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines; + ++engine_id_idx) { + u32 active_engine_id = g->fifo.active_engines_list[engine_id_idx]; + const struct fifo_engine_info_gk20a *src_info = + &g->fifo.engine_info[active_engine_id]; + struct nvgpu_gpu_get_engine_info_item dst_info; + + memset(&dst_info, 0, sizeof(dst_info)); + + engine_enum = src_info->engine_enum; + + switch (engine_enum) { + case ENGINE_GR_GK20A: + dst_info.engine_id = NVGPU_GPU_ENGINE_ID_GR; + break; + + case ENGINE_GRCE_GK20A: + dst_info.engine_id = NVGPU_GPU_ENGINE_ID_GR_COPY; + break; + + case ENGINE_ASYNC_CE_GK20A: + dst_info.engine_id = NVGPU_GPU_ENGINE_ID_ASYNC_COPY; + break; + + default: + gk20a_err(dev_from_gk20a(g), "Unmapped engine enum %u\n", + engine_enum); + continue; + } + + dst_info.engine_instance = src_info->inst_id; + dst_info.runlist_id = src_info->runlist_id; + + if (report_index < max_buffer_engines) { + err = copy_to_user(&dst_item_list[report_index], + &dst_info, sizeof(dst_info)); + if (err) + goto clean_up; + } + + ++report_index; + } + + args->engine_info_buf_size = + report_index * sizeof(struct nvgpu_gpu_get_engine_info_item); + +clean_up: + return err; +} + long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct device *dev = filp->private_data; @@ -916,6 +979,11 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg (struct nvgpu_gpu_get_gpu_time_args *)buf); break; + case NVGPU_GPU_IOCTL_GET_ENGINE_INFO: + err = nvgpu_gpu_get_engine_info(g, + (struct nvgpu_gpu_get_engine_info_args *)buf); + break; + default: dev_dbg(dev_from_gk20a(g), "unrecognized gpu ioctl cmd: 0x%x", cmd); err = -ENOTTY; diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h index 03173339b..9d6495366 100644 --- a/include/uapi/linux/nvgpu.h +++ b/include/uapi/linux/nvgpu.h @@ -394,6 +394,33 @@ struct nvgpu_gpu_get_gpu_time_args { __u64 reserved; }; +struct nvgpu_gpu_get_engine_info_item { + +#define NVGPU_GPU_ENGINE_ID_GR 0 +#define NVGPU_GPU_ENGINE_ID_GR_COPY 1 +#define NVGPU_GPU_ENGINE_ID_ASYNC_COPY 2 + __u32 engine_id; + + __u32 engine_instance; + + /* runlist id for opening channels to the engine, or -1 if + * channels are not supported */ + __s32 runlist_id; + + __u32 reserved; +}; + +struct nvgpu_gpu_get_engine_info_args { + /* [in] Buffer size reserved by userspace. + * + * [out] Full kernel buffer size. Multiple of sizeof(struct + * nvgpu_gpu_get_engine_info_item) + */ + __u32 engine_info_buf_size; + __u32 reserved; + __u64 engine_info_buf_addr; +}; + #define NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE \ _IOR(NVGPU_GPU_IOCTL_MAGIC, 1, struct nvgpu_gpu_zcull_get_ctx_size_args) #define NVGPU_GPU_IOCTL_ZCULL_GET_INFO \ @@ -446,8 +473,11 @@ struct nvgpu_gpu_get_gpu_time_args { #define NVGPU_GPU_IOCTL_GET_GPU_TIME \ _IOWR(NVGPU_GPU_IOCTL_MAGIC, 25, \ struct nvgpu_gpu_get_gpu_time_args) +#define NVGPU_GPU_IOCTL_GET_ENGINE_INFO \ + _IOWR(NVGPU_GPU_IOCTL_MAGIC, 26, \ + struct nvgpu_gpu_get_engine_info_args) #define NVGPU_GPU_IOCTL_LAST \ - _IOC_NR(NVGPU_GPU_IOCTL_GET_GPU_TIME) + _IOC_NR(NVGPU_GPU_IOCTL_GET_ENGINE_INFO) #define NVGPU_GPU_IOCTL_MAX_ARG_SIZE \ sizeof(struct nvgpu_gpu_get_cpu_time_correlation_info_args)