Commit 27b575a9 authored by Chunming Zhou's avatar Chunming Zhou Committed by Christian König
Browse files

drm/syncobj: add timeline payload query ioctl v6



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: default avatarChunming Zhou <david1.zhou@amd.com>
Signed-off-by: default avatarChristian 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: default avatarLionel Landwerlin <lionel.g.landwerlin@intel.com>
Link: https://patchwork.freedesktop.org/patch/295784/?series=58813&rev=1
parent 01d6c357
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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),
+62 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -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.