mirror of https://gitee.com/openkylin/linux.git
drm/syncobj: add timeline signal ioctl for syncobj v5
v2: individually allocate chain array, since chain node is free independently. v3: all existing points must be already signaled before cpu perform signal operation, so add check condition for that. v4: remove v3 change and add checking to prevent out-of-order v5: unify binary and timeline Signed-off-by: Chunming Zhou <david1.zhou@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Cc: Tobias Hector <Tobias.Hector@amd.com> Cc: Jason Ekstrand <jason@jlekstrand.net> Cc: Dave Airlie <airlied@redhat.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Link: https://patchwork.freedesktop.org/patch/295792/?series=58813&rev=1
This commit is contained in:
parent
ea569910cb
commit
50d1ebef79
|
@ -190,6 +190,8 @@ int drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_private);
|
||||
int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_private);
|
||||
int drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_private);
|
||||
int drm_syncobj_query_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_private);
|
||||
|
||||
|
|
|
@ -696,6 +696,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
|
|||
DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl,
|
||||
DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, drm_syncobj_timeline_signal_ioctl,
|
||||
DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_QUERY, drm_syncobj_query_ioctl,
|
||||
DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, DRM_UNLOCKED),
|
||||
|
|
|
@ -1184,6 +1184,79 @@ drm_syncobj_signal_ioctl(struct drm_device *dev, void *data,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_private)
|
||||
{
|
||||
struct drm_syncobj_timeline_array *args = data;
|
||||
struct drm_syncobj **syncobjs;
|
||||
struct dma_fence_chain **chains;
|
||||
uint64_t *points;
|
||||
uint32_t i, j;
|
||||
int ret;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (args->pad != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (args->count_handles == 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = drm_syncobj_array_find(file_private,
|
||||
u64_to_user_ptr(args->handles),
|
||||
args->count_handles,
|
||||
&syncobjs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
points = kmalloc_array(args->count_handles, sizeof(*points),
|
||||
GFP_KERNEL);
|
||||
if (!points) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!u64_to_user_ptr(args->points)) {
|
||||
memset(points, 0, args->count_handles * sizeof(uint64_t));
|
||||
} else if (copy_from_user(points, u64_to_user_ptr(args->points),
|
||||
sizeof(uint64_t) * args->count_handles)) {
|
||||
ret = -EFAULT;
|
||||
goto err_points;
|
||||
}
|
||||
|
||||
chains = kmalloc_array(args->count_handles, sizeof(void *), GFP_KERNEL);
|
||||
if (!chains) {
|
||||
ret = -ENOMEM;
|
||||
goto err_points;
|
||||
}
|
||||
for (i = 0; i < args->count_handles; i++) {
|
||||
chains[i] = kzalloc(sizeof(struct dma_fence_chain), GFP_KERNEL);
|
||||
if (!chains[i]) {
|
||||
for (j = 0; j < i; j++)
|
||||
kfree(chains[j]);
|
||||
ret = -ENOMEM;
|
||||
goto err_chains;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < args->count_handles; i++) {
|
||||
struct dma_fence *fence = dma_fence_get_stub();
|
||||
|
||||
drm_syncobj_add_point(syncobjs[i], chains[i],
|
||||
fence, points[i]);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
err_chains:
|
||||
kfree(chains);
|
||||
err_points:
|
||||
kfree(points);
|
||||
out:
|
||||
drm_syncobj_array_free(syncobjs, args->count_handles);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int drm_syncobj_query_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_private)
|
||||
{
|
||||
|
|
|
@ -943,6 +943,7 @@ extern "C" {
|
|||
#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait)
|
||||
#define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array)
|
||||
#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer)
|
||||
#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array)
|
||||
|
||||
/**
|
||||
* Device specific ioctls should only be in their respective headers
|
||||
|
|
Loading…
Reference in New Issue