Skip to content

Commit

Permalink
drm/syncobj: add timeline payload query ioctl v6
Browse files Browse the repository at this point in the history
user mode can query timeline payload.
v2: check return value of copy_to_user
v3: handle querying entry by entry
v4: rebase on new chain container, simplify interface
v5: query last signaled timeline point, not last point.
v6: add unorder point check

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/295784/?series=58813&rev=1
  • Loading branch information
Chunming Zhou authored and Christian König committed Apr 1, 2019
1 parent 01d6c35 commit 27b575a
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 0 deletions.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/drm_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,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_query_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private);

/* drm_framebuffer.c */
void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent,
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/drm_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,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_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),
DRM_IOCTL_DEF(DRM_IOCTL_CRTC_QUEUE_SEQUENCE, drm_crtc_queue_sequence_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER|DRM_UNLOCKED),
Expand Down
62 changes: 62 additions & 0 deletions drivers/gpu/drm/drm_syncobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -1065,3 +1065,65 @@ drm_syncobj_signal_ioctl(struct drm_device *dev, void *data,

return ret;
}

int drm_syncobj_query_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private)
{
struct drm_syncobj_timeline_array *args = data;
struct drm_syncobj **syncobjs;
uint64_t __user *points = u64_to_user_ptr(args->points);
uint32_t i;
int ret;

if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
return -ENODEV;

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;

for (i = 0; i < args->count_handles; i++) {
struct dma_fence_chain *chain;
struct dma_fence *fence;
uint64_t point;

fence = drm_syncobj_fence_get(syncobjs[i]);
chain = to_dma_fence_chain(fence);
if (chain) {
struct dma_fence *iter, *last_signaled = NULL;

dma_fence_chain_for_each(iter, fence) {
if (!iter)
break;
dma_fence_put(last_signaled);
last_signaled = dma_fence_get(iter);
if (!to_dma_fence_chain(last_signaled)->prev_seqno)
/* It is most likely that timeline has
* unorder points. */
break;
}
point = dma_fence_is_signaled(last_signaled) ?
last_signaled->seqno :
to_dma_fence_chain(last_signaled)->prev_seqno;
dma_fence_put(last_signaled);
} else {
point = 0;
}
ret = copy_to_user(&points[i], &point, sizeof(uint64_t));
ret = ret ? -EFAULT : 0;
if (ret)
break;
}
drm_syncobj_array_free(syncobjs, args->count_handles);

return ret;
}
10 changes: 10 additions & 0 deletions include/uapi/drm/drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,14 @@ struct drm_syncobj_array {
__u32 pad;
};

struct drm_syncobj_timeline_array {
__u64 handles;
__u64 points;
__u32 count_handles;
__u32 pad;
};


/* Query current scanout sequence number */
struct drm_crtc_get_sequence {
__u32 crtc_id; /* requested crtc_id */
Expand Down Expand Up @@ -924,6 +932,8 @@ extern "C" {
#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease)

#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)

/**
* Device specific ioctls should only be in their respective headers
* The device specific ioctl range is from 0x40 to 0x9f.
Expand Down

0 comments on commit 27b575a

Please sign in to comment.