Similar in principle to DRM_IOCTL_AMDGPU_GEM_LIST_HANDLES, we need a new ioctl to list any contexts created by the client.
Lets add it as DRM_IOCTL_AMDGPU_GEM_LIST_CONTEXTS, and the respective uapi data structures. Structures contain all information required to re-create the context, modulo the handle id replication, which will be handled in a following patch. Signed-off-by: Tvrtko Ursulin <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 102 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h | 2 + include/uapi/drm/amdgpu_drm.h | 33 ++++++++ 4 files changed, 138 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 7af86a32c0c5..15bf247c38f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -734,6 +734,108 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, return r; } +/** + * amdgpu_gem_list_contexts_ioctl - get information about clients contexts + * + * @dev: drm device pointer + * @data: drm_amdgpu_gem_list_handles + * @filp: drm file pointer + * + * Returns: + * 0 for success, -errno for errors. + */ +int amdgpu_gem_list_contexts_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct drm_amdgpu_gem_list_contexts *args = data; + struct drm_amdgpu_gem_list_contexts_entry *contexts; + struct amdgpu_fpriv *fpriv = filp->driver_priv; + struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr; + struct amdgpu_device *adev = mgr->adev; + unsigned long num = 0, idx = 0; + struct amdgpu_ctx *ctx; + int ret = 0; + u32 id; + + if (args->padding) + return -EINVAL; + + mutex_lock(&mgr->lock); + idr_for_each_entry(&mgr->ctx_handles, ctx, id) + num++; + mutex_unlock(&mgr->lock); + + if (num == 0 || args->num_contexts < num) { + args->num_contexts = num; + return 0; + } + + contexts = kvzalloc_objs(*contexts, num); + if (!contexts) + return -ENOMEM; + + mutex_lock(&mgr->lock); + idr_for_each_entry(&mgr->ctx_handles, ctx, id) { + struct drm_amdgpu_gem_list_contexts_entry *context; + enum amd_dpm_forced_level level; + + if (idx >= num) { + ret = -EAGAIN; + break; + } + + context = &contexts[idx]; + + context->handle = id; + context->init_priority = ctx->init_priority; + context->override_priority = ctx->override_priority; + if (atomic_read(&ctx->guilty)) + context->flags = AMDGPU_GEM_LIST_CONTEXTS_FLAG_GUILTY; + + mutex_lock(&adev->pm.stable_pstate_ctx_lock); + if (ctx == adev->pm.stable_pstate_ctx) { + level = amdgpu_dpm_get_performance_level(adev); + + switch (level) { + case AMD_DPM_FORCED_LEVEL_AUTO: + context->pstate_flags = AMDGPU_CTX_STABLE_PSTATE_NONE; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + context->pstate_flags = AMDGPU_CTX_STABLE_PSTATE_STANDARD; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + context->pstate_flags = AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + context->pstate_flags = AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + context->pstate_flags = AMDGPU_CTX_STABLE_PSTATE_PEAK; + break; + default: + ret = -EIO; + break; + }; + + } + mutex_unlock(&adev->pm.stable_pstate_ctx_lock); + + idx++; + } + mutex_unlock(&mgr->lock); + + args->num_contexts = idx; + + if (!ret) + if (copy_to_user(u64_to_user_ptr(args->contexts), contexts, + num * sizeof(*contexts))) + ret = -EFAULT; + + kvfree(contexts); + + return ret; +} + struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id) { struct amdgpu_ctx *ctx; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 46aae3fad4bf..2b971de3c189 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -3065,6 +3065,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { DRM_IOCTL_DEF_DRV(AMDGPU_USERQ_SIGNAL, amdgpu_userq_signal_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_USERQ_WAIT, amdgpu_userq_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_GEM_LIST_HANDLES, amdgpu_gem_list_handles_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(AMDGPU_GEM_LIST_CONTEXTS, amdgpu_gem_list_contexts_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), }; static const struct drm_driver amdgpu_kms_driver = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h index b558336bc4c6..0e17d9fc665f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h @@ -69,6 +69,8 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); int amdgpu_gem_list_handles_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); +int amdgpu_gem_list_contexts_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 8a6f4c558102..15da4d9c44fd 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -58,6 +58,7 @@ extern "C" { #define DRM_AMDGPU_USERQ_SIGNAL 0x17 #define DRM_AMDGPU_USERQ_WAIT 0x18 #define DRM_AMDGPU_GEM_LIST_HANDLES 0x19 +#define DRM_AMDGPU_GEM_LIST_CONTEXTS 0x20 #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create) #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap) @@ -79,6 +80,7 @@ extern "C" { #define DRM_IOCTL_AMDGPU_USERQ_SIGNAL DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_USERQ_SIGNAL, struct drm_amdgpu_userq_signal) #define DRM_IOCTL_AMDGPU_USERQ_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_USERQ_WAIT, struct drm_amdgpu_userq_wait) #define DRM_IOCTL_AMDGPU_GEM_LIST_HANDLES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_LIST_HANDLES, struct drm_amdgpu_gem_list_handles) +#define DRM_IOCTL_AMDGPU_GEM_LIST_CONTEXTS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_LIST_CONTEXTS, struct drm_amdgpu_gem_list_contexts) /** * DOC: memory domains @@ -871,6 +873,37 @@ struct drm_amdgpu_gem_list_handles_entry { __u64 alignment; }; +#define AMDGPU_GEM_LIST_CONTEXTS_FLAG_GUILTY (1 << 0) + +struct drm_amdgpu_gem_list_contexts { + /* User pointer to array of drm_amdgpu_gem_list_contexts_entry */ + __u64 contexts; + + /* Size of the contexts buffer / Number of contexts in the client (if larger than size of buffer, must retry) */ + __u32 num_contexts; + + __u32 padding; +}; + +struct drm_amdgpu_gem_list_contexts_entry { + /* gem context handle */ + __u32 handle; + + /* AMDGPU_GEM_LIST_CONTEXTS_FLAG_* */ + __u32 flags; + + /* context initial priority */ + __s32 init_priority; + + /* context override priority */ + __s32 override_priority; + + /* pstate flags */ + __u32 pstate_flags; + + __u32 padding; +}; + #define AMDGPU_VA_OP_MAP 1 #define AMDGPU_VA_OP_UNMAP 2 #define AMDGPU_VA_OP_CLEAR 3 -- 2.54.0
