Add drm mode lease ioctl wrappers [v3]

    drmModeCreateLease
    drmModeListLessees
    drmModeGetLease
    drmModeRevokeLease

    Changes for v2:

    Remove lessee id from GetLease
    Remove lessor_id from ListLeases
    Add revoke
    Renumber to track kernel rebase on drm-next

Taken from git://people.freedesktop.org/~keithp/drm @ 468446f96883c.

Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Marius Vlad <marius-cristian.vlad@nxp.com>
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 4737261..16b8efb 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -857,6 +857,11 @@
 #define DRM_IOCTL_SYNCOBJ_RESET		DRM_IOWR(0xC4, struct drm_syncobj_array)
 #define DRM_IOCTL_SYNCOBJ_SIGNAL	DRM_IOWR(0xC5, struct drm_syncobj_array)
 
+#define DRM_IOCTL_MODE_CREATE_LEASE    DRM_IOWR(0xC6, struct drm_mode_create_lease)
+#define DRM_IOCTL_MODE_LIST_LESSEES    DRM_IOWR(0xC7, struct drm_mode_list_lessees)
+#define DRM_IOCTL_MODE_GET_LEASE       DRM_IOWR(0xC8, struct drm_mode_get_lease)
+#define DRM_IOCTL_MODE_REVOKE_LEASE    DRM_IOWR(0xC9, struct drm_mode_revoke_lease)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index e01f129..6ff6185 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -774,6 +774,73 @@
 	__u32 blob_id;
 };
 
+/**
+ * Lease mode resources to another user.
+ */
+struct drm_mode_create_lease {
+	/** Pointer to array of object ids (__u32) */
+	__u64 object_ids;
+	/** Number of object ids */
+	__u32 object_count;
+	/** flags for new FD (O_CLOEXEC, etc) */
+	__u32 flags;
+
+	/** Return: unique identifier for lessee. */
+	__u32 lessee_id;
+	/** Return: file descriptor to new drm_master file */
+	__u32 fd;
+};
+
+/**
+ * List lesses from a drm_master
+ */
+struct drm_mode_list_lessees {
+	/** Number of lessees.
+	 * On input, provides length of the array.
+	 * On output, provides total number. No
+	 * more than the input number will be written
+	 * back, so two calls can be used to get
+	 * the size and then the data.
+	 */
+	__u32 count_lessees;
+	__u32 pad;
+
+	/** Pointer to lessees.
+	 * pointer to __u64 array of lessee ids
+	 */
+	__u64 lessees_ptr;
+};
+
+/**
+ * Get leased objects for a lessee
+ */
+struct drm_mode_get_lease {
+	/** Number of leased objects.
+	 * On input, provides length of the array.
+	 * On output, provides total number. No
+	 * more than the input number will be written
+	 * back, so two calls can be used to get
+	 * the size and then the data.
+	 */
+	__u32 count_objects;
+	__u32 pad;
+
+	/** Pointer to objects.
+	 * pointer to __u32 array of object ids
+	 */
+	__u64 objects_ptr;
+};
+
+/**
+ * Revoke lease
+ */
+struct drm_mode_revoke_lease {
+	/** Unique ID of lessee
+	*/
+	__u32 lessee_id;
+};
+
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/xf86drmMode.c b/xf86drmMode.c
index d3bc20e..bcae27d 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1485,3 +1485,93 @@
 	destroy.blob_id = id;
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy);
 }
+
+int
+drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id)
+{
+	struct drm_mode_create_lease create;
+	int ret;
+
+	memclear(create);
+	create.object_ids = (uintptr_t) objects;
+	create.object_count = num_objects;
+	create.flags = flags;
+
+	ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_CREATE_LEASE, &create);
+	if (ret == 0) {
+		*lessee_id = create.lessee_id;
+		return create.fd;
+	}
+	return -errno;
+}
+
+drmModeLesseeListPtr
+drmModeListLessees(int fd)
+{
+	struct drm_mode_list_lessees list;
+	uint32_t count;
+	drmModeLesseeListPtr ret;
+
+	memclear(list);
+
+	if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list))
+		return NULL;
+
+	count = list.count_lessees;
+	ret = drmMalloc(sizeof (drmModeLesseeListRes) + count * sizeof (ret->lessees[0]));
+	if (!ret)
+		return NULL;
+
+	list.lessees_ptr = VOID2U64(&ret->lessees[0]);
+	if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list)) {
+		drmFree(ret);
+		return NULL;
+	}
+
+	ret->count = count;
+	return ret;
+}
+
+drmModeObjectListPtr
+drmModeGetLease(int fd)
+{
+	struct drm_mode_get_lease get;
+	uint32_t count;
+	drmModeObjectListPtr ret;
+
+	memclear(get);
+
+	if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get))
+		return NULL;
+
+	count = get.count_objects;
+	ret = drmMalloc(sizeof (drmModeObjectListRes) + count * sizeof (ret->objects[0]));
+	if (!ret)
+		return NULL;
+
+	get.objects_ptr = VOID2U64(&ret->objects[0]);
+	if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get)) {
+		drmFree(ret);
+		return NULL;
+	}
+
+	ret->count = count;
+	return ret;
+}
+
+int
+drmModeRevokeLease(int fd, uint32_t lessee_id)
+{
+	struct drm_mode_revoke_lease revoke;
+	int ret;
+
+	memclear(revoke);
+
+	revoke.lessee_id = lessee_id;
+
+	ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_REVOKE_LEASE, &revoke);
+	if (ret == 0)
+		return 0;
+	return -errno;
+}
+
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 5b390d9..8b6df49 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -520,6 +520,30 @@
 				     uint32_t *id);
 extern int drmModeDestroyPropertyBlob(int fd, uint32_t id);
 
+/*
+ * DRM mode lease APIs. These create and manage new drm_masters with
+ * access to a subset of the available DRM resources
+ */
+
+extern int drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id);
+
+typedef struct drmModeLesseeList {
+	uint32_t count;
+	uint32_t lessees[0];
+} drmModeLesseeListRes, *drmModeLesseeListPtr;
+
+extern drmModeLesseeListPtr drmModeListLessees(int fd);
+
+typedef struct drmModeObjectList {
+	uint32_t count;
+	uint32_t objects[0];
+} drmModeObjectListRes, *drmModeObjectListPtr;
+
+extern drmModeObjectListPtr drmModeGetLease(int fd);
+
+extern int drmModeRevokeLease(int fd, uint32_t lessee_id);
+
+
 
 #if defined(__cplusplus)
 }