xref: /aosp_15_r20/external/igt-gpu-tools/tests/kms_lease.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2017 Keith Packard
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  */
23*d83cc019SAndroid Build Coastguard Worker 
24*d83cc019SAndroid Build Coastguard Worker /** @file kms_lease.c
25*d83cc019SAndroid Build Coastguard Worker  *
26*d83cc019SAndroid Build Coastguard Worker  * This is a test of DRM leases
27*d83cc019SAndroid Build Coastguard Worker  */
28*d83cc019SAndroid Build Coastguard Worker 
29*d83cc019SAndroid Build Coastguard Worker 
30*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
31*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
32*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
33*d83cc019SAndroid Build Coastguard Worker #include <string.h>
34*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
35*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
36*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
37*d83cc019SAndroid Build Coastguard Worker #include <time.h>
38*d83cc019SAndroid Build Coastguard Worker #include <sys/poll.h>
39*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
40*d83cc019SAndroid Build Coastguard Worker #include <sys/time.h>
41*d83cc019SAndroid Build Coastguard Worker #include <sys/wait.h>
42*d83cc019SAndroid Build Coastguard Worker 
43*d83cc019SAndroid Build Coastguard Worker #include <libudev.h>
44*d83cc019SAndroid Build Coastguard Worker 
45*d83cc019SAndroid Build Coastguard Worker #include <drm.h>
46*d83cc019SAndroid Build Coastguard Worker #include "igt_device.h"
47*d83cc019SAndroid Build Coastguard Worker 
48*d83cc019SAndroid Build Coastguard Worker IGT_TEST_DESCRIPTION("Test of CreateLease.");
49*d83cc019SAndroid Build Coastguard Worker 
50*d83cc019SAndroid Build Coastguard Worker struct local_drm_mode_create_lease {
51*d83cc019SAndroid Build Coastguard Worker         /** Pointer to array of object ids (__u32) */
52*d83cc019SAndroid Build Coastguard Worker         __u64 object_ids;
53*d83cc019SAndroid Build Coastguard Worker         /** Number of object ids */
54*d83cc019SAndroid Build Coastguard Worker         __u32 object_count;
55*d83cc019SAndroid Build Coastguard Worker         /** flags for new FD (O_CLOEXEC, etc) */
56*d83cc019SAndroid Build Coastguard Worker         __u32 flags;
57*d83cc019SAndroid Build Coastguard Worker 
58*d83cc019SAndroid Build Coastguard Worker         /** Return: unique identifier for lessee. */
59*d83cc019SAndroid Build Coastguard Worker         __u32 lessee_id;
60*d83cc019SAndroid Build Coastguard Worker         /** Return: file descriptor to new drm_master file */
61*d83cc019SAndroid Build Coastguard Worker         __u32 fd;
62*d83cc019SAndroid Build Coastguard Worker };
63*d83cc019SAndroid Build Coastguard Worker 
64*d83cc019SAndroid Build Coastguard Worker struct local_drm_mode_list_lessees {
65*d83cc019SAndroid Build Coastguard Worker         /** Number of lessees.
66*d83cc019SAndroid Build Coastguard Worker          * On input, provides length of the array.
67*d83cc019SAndroid Build Coastguard Worker          * On output, provides total number. No
68*d83cc019SAndroid Build Coastguard Worker          * more than the input number will be written
69*d83cc019SAndroid Build Coastguard Worker          * back, so two calls can be used to get
70*d83cc019SAndroid Build Coastguard Worker          * the size and then the data.
71*d83cc019SAndroid Build Coastguard Worker          */
72*d83cc019SAndroid Build Coastguard Worker         __u32 count_lessees;
73*d83cc019SAndroid Build Coastguard Worker         __u32 pad;
74*d83cc019SAndroid Build Coastguard Worker 
75*d83cc019SAndroid Build Coastguard Worker         /** Pointer to lessees.
76*d83cc019SAndroid Build Coastguard Worker          * pointer to __u64 array of lessee ids
77*d83cc019SAndroid Build Coastguard Worker          */
78*d83cc019SAndroid Build Coastguard Worker         __u64 lessees_ptr;
79*d83cc019SAndroid Build Coastguard Worker };
80*d83cc019SAndroid Build Coastguard Worker 
81*d83cc019SAndroid Build Coastguard Worker struct local_drm_mode_get_lease {
82*d83cc019SAndroid Build Coastguard Worker         /** Number of leased objects.
83*d83cc019SAndroid Build Coastguard Worker          * On input, provides length of the array.
84*d83cc019SAndroid Build Coastguard Worker          * On output, provides total number. No
85*d83cc019SAndroid Build Coastguard Worker          * more than the input number will be written
86*d83cc019SAndroid Build Coastguard Worker          * back, so two calls can be used to get
87*d83cc019SAndroid Build Coastguard Worker          * the size and then the data.
88*d83cc019SAndroid Build Coastguard Worker          */
89*d83cc019SAndroid Build Coastguard Worker         __u32 count_objects;
90*d83cc019SAndroid Build Coastguard Worker         __u32 pad;
91*d83cc019SAndroid Build Coastguard Worker 
92*d83cc019SAndroid Build Coastguard Worker         /** Pointer to objects.
93*d83cc019SAndroid Build Coastguard Worker          * pointer to __u32 array of object ids
94*d83cc019SAndroid Build Coastguard Worker          */
95*d83cc019SAndroid Build Coastguard Worker         __u64 objects_ptr;
96*d83cc019SAndroid Build Coastguard Worker };
97*d83cc019SAndroid Build Coastguard Worker 
98*d83cc019SAndroid Build Coastguard Worker /**
99*d83cc019SAndroid Build Coastguard Worker  * Revoke lease
100*d83cc019SAndroid Build Coastguard Worker  */
101*d83cc019SAndroid Build Coastguard Worker struct local_drm_mode_revoke_lease {
102*d83cc019SAndroid Build Coastguard Worker         /** Unique ID of lessee
103*d83cc019SAndroid Build Coastguard Worker          */
104*d83cc019SAndroid Build Coastguard Worker         __u32 lessee_id;
105*d83cc019SAndroid Build Coastguard Worker };
106*d83cc019SAndroid Build Coastguard Worker 
107*d83cc019SAndroid Build Coastguard Worker 
108*d83cc019SAndroid Build Coastguard Worker #define LOCAL_DRM_IOCTL_MODE_CREATE_LEASE     DRM_IOWR(0xC6, struct local_drm_mode_create_lease)
109*d83cc019SAndroid Build Coastguard Worker #define LOCAL_DRM_IOCTL_MODE_LIST_LESSEES     DRM_IOWR(0xC7, struct local_drm_mode_list_lessees)
110*d83cc019SAndroid Build Coastguard Worker #define LOCAL_DRM_IOCTL_MODE_GET_LEASE        DRM_IOWR(0xC8, struct local_drm_mode_get_lease)
111*d83cc019SAndroid Build Coastguard Worker #define LOCAL_DRM_IOCTL_MODE_REVOKE_LEASE     DRM_IOWR(0xC9, struct local_drm_mode_revoke_lease)
112*d83cc019SAndroid Build Coastguard Worker 
113*d83cc019SAndroid Build Coastguard Worker typedef struct {
114*d83cc019SAndroid Build Coastguard Worker 	int fd;
115*d83cc019SAndroid Build Coastguard Worker 	uint32_t lessee_id;
116*d83cc019SAndroid Build Coastguard Worker 	igt_display_t display;
117*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb primary_fb;
118*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *output;
119*d83cc019SAndroid Build Coastguard Worker 	drmModeModeInfo *mode;
120*d83cc019SAndroid Build Coastguard Worker } lease_t;
121*d83cc019SAndroid Build Coastguard Worker 
122*d83cc019SAndroid Build Coastguard Worker typedef struct {
123*d83cc019SAndroid Build Coastguard Worker 	lease_t master;
124*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe;
125*d83cc019SAndroid Build Coastguard Worker 	uint32_t crtc_id;
126*d83cc019SAndroid Build Coastguard Worker 	uint32_t connector_id;
127*d83cc019SAndroid Build Coastguard Worker 	uint32_t plane_id;
128*d83cc019SAndroid Build Coastguard Worker } data_t;
129*d83cc019SAndroid Build Coastguard Worker 
pipe_to_crtc_id(igt_display_t * display,enum pipe pipe)130*d83cc019SAndroid Build Coastguard Worker static uint32_t pipe_to_crtc_id(igt_display_t *display, enum pipe pipe)
131*d83cc019SAndroid Build Coastguard Worker {
132*d83cc019SAndroid Build Coastguard Worker 	return display->pipes[pipe].crtc_id;
133*d83cc019SAndroid Build Coastguard Worker }
134*d83cc019SAndroid Build Coastguard Worker 
crtc_id_to_pipe(igt_display_t * display,uint32_t crtc_id)135*d83cc019SAndroid Build Coastguard Worker static enum pipe crtc_id_to_pipe(igt_display_t *display, uint32_t crtc_id)
136*d83cc019SAndroid Build Coastguard Worker {
137*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe;
138*d83cc019SAndroid Build Coastguard Worker 
139*d83cc019SAndroid Build Coastguard Worker 	for (pipe = 0; pipe < display->n_pipes; pipe++)
140*d83cc019SAndroid Build Coastguard Worker 		if (display->pipes[pipe].crtc_id == crtc_id)
141*d83cc019SAndroid Build Coastguard Worker 			return pipe;
142*d83cc019SAndroid Build Coastguard Worker 	return -1;
143*d83cc019SAndroid Build Coastguard Worker }
144*d83cc019SAndroid Build Coastguard Worker 
connector_id_to_output(igt_display_t * display,uint32_t connector_id)145*d83cc019SAndroid Build Coastguard Worker static igt_output_t *connector_id_to_output(igt_display_t *display, uint32_t connector_id)
146*d83cc019SAndroid Build Coastguard Worker {
147*d83cc019SAndroid Build Coastguard Worker 	drmModeConnector		connector;
148*d83cc019SAndroid Build Coastguard Worker 
149*d83cc019SAndroid Build Coastguard Worker 	connector.connector_id = connector_id;
150*d83cc019SAndroid Build Coastguard Worker 	return igt_output_from_connector(display, &connector);
151*d83cc019SAndroid Build Coastguard Worker }
152*d83cc019SAndroid Build Coastguard Worker 
prepare_crtc(lease_t * lease,uint32_t connector_id,uint32_t crtc_id)153*d83cc019SAndroid Build Coastguard Worker static int prepare_crtc(lease_t *lease, uint32_t connector_id, uint32_t crtc_id)
154*d83cc019SAndroid Build Coastguard Worker {
155*d83cc019SAndroid Build Coastguard Worker 	drmModeModeInfo *mode;
156*d83cc019SAndroid Build Coastguard Worker 	igt_display_t *display = &lease->display;
157*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *output = connector_id_to_output(display, connector_id);
158*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe = crtc_id_to_pipe(display, crtc_id);
159*d83cc019SAndroid Build Coastguard Worker 	igt_plane_t *primary;
160*d83cc019SAndroid Build Coastguard Worker 	int ret;
161*d83cc019SAndroid Build Coastguard Worker 
162*d83cc019SAndroid Build Coastguard Worker 	if (!output)
163*d83cc019SAndroid Build Coastguard Worker 		return -ENOENT;
164*d83cc019SAndroid Build Coastguard Worker 
165*d83cc019SAndroid Build Coastguard Worker 	/* select the pipe we want to use */
166*d83cc019SAndroid Build Coastguard Worker 	igt_output_set_pipe(output, pipe);
167*d83cc019SAndroid Build Coastguard Worker 
168*d83cc019SAndroid Build Coastguard Worker 	/* create and set the primary plane fb */
169*d83cc019SAndroid Build Coastguard Worker 	mode = igt_output_get_mode(output);
170*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(lease->fd, mode->hdisplay, mode->vdisplay,
171*d83cc019SAndroid Build Coastguard Worker 			    DRM_FORMAT_XRGB8888,
172*d83cc019SAndroid Build Coastguard Worker 			    LOCAL_DRM_FORMAT_MOD_NONE,
173*d83cc019SAndroid Build Coastguard Worker 			    0.0, 0.0, 0.0,
174*d83cc019SAndroid Build Coastguard Worker 			    &lease->primary_fb);
175*d83cc019SAndroid Build Coastguard Worker 
176*d83cc019SAndroid Build Coastguard Worker 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
177*d83cc019SAndroid Build Coastguard Worker 	igt_plane_set_fb(primary, &lease->primary_fb);
178*d83cc019SAndroid Build Coastguard Worker 
179*d83cc019SAndroid Build Coastguard Worker 	ret = igt_display_try_commit2(display, COMMIT_LEGACY);
180*d83cc019SAndroid Build Coastguard Worker 
181*d83cc019SAndroid Build Coastguard Worker 	if (ret)
182*d83cc019SAndroid Build Coastguard Worker 		return ret;
183*d83cc019SAndroid Build Coastguard Worker 
184*d83cc019SAndroid Build Coastguard Worker 	igt_wait_for_vblank(lease->fd, pipe);
185*d83cc019SAndroid Build Coastguard Worker 
186*d83cc019SAndroid Build Coastguard Worker 	lease->output = output;
187*d83cc019SAndroid Build Coastguard Worker 	lease->mode = mode;
188*d83cc019SAndroid Build Coastguard Worker 	return 0;
189*d83cc019SAndroid Build Coastguard Worker }
190*d83cc019SAndroid Build Coastguard Worker 
cleanup_crtc(lease_t * lease,igt_output_t * output)191*d83cc019SAndroid Build Coastguard Worker static void cleanup_crtc(lease_t *lease, igt_output_t *output)
192*d83cc019SAndroid Build Coastguard Worker {
193*d83cc019SAndroid Build Coastguard Worker 	igt_display_t *display = &lease->display;
194*d83cc019SAndroid Build Coastguard Worker 	igt_plane_t *primary;
195*d83cc019SAndroid Build Coastguard Worker 
196*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(lease->fd, &lease->primary_fb);
197*d83cc019SAndroid Build Coastguard Worker 
198*d83cc019SAndroid Build Coastguard Worker 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
199*d83cc019SAndroid Build Coastguard Worker 	igt_plane_set_fb(primary, NULL);
200*d83cc019SAndroid Build Coastguard Worker 
201*d83cc019SAndroid Build Coastguard Worker 	igt_output_set_pipe(output, PIPE_ANY);
202*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit(display);
203*d83cc019SAndroid Build Coastguard Worker }
204*d83cc019SAndroid Build Coastguard Worker 
create_lease(int fd,struct local_drm_mode_create_lease * mcl)205*d83cc019SAndroid Build Coastguard Worker static int create_lease(int fd, struct local_drm_mode_create_lease *mcl)
206*d83cc019SAndroid Build Coastguard Worker {
207*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
208*d83cc019SAndroid Build Coastguard Worker 
209*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, LOCAL_DRM_IOCTL_MODE_CREATE_LEASE, mcl))
210*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
211*d83cc019SAndroid Build Coastguard Worker 	return err;
212*d83cc019SAndroid Build Coastguard Worker }
213*d83cc019SAndroid Build Coastguard Worker 
revoke_lease(int fd,struct local_drm_mode_revoke_lease * mrl)214*d83cc019SAndroid Build Coastguard Worker static int revoke_lease(int fd, struct local_drm_mode_revoke_lease *mrl)
215*d83cc019SAndroid Build Coastguard Worker {
216*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
217*d83cc019SAndroid Build Coastguard Worker 
218*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, LOCAL_DRM_IOCTL_MODE_REVOKE_LEASE, mrl))
219*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
220*d83cc019SAndroid Build Coastguard Worker 	return err;
221*d83cc019SAndroid Build Coastguard Worker }
222*d83cc019SAndroid Build Coastguard Worker 
list_lessees(int fd,struct local_drm_mode_list_lessees * mll)223*d83cc019SAndroid Build Coastguard Worker static int list_lessees(int fd, struct local_drm_mode_list_lessees *mll)
224*d83cc019SAndroid Build Coastguard Worker {
225*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
226*d83cc019SAndroid Build Coastguard Worker 
227*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, LOCAL_DRM_IOCTL_MODE_LIST_LESSEES, mll))
228*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
229*d83cc019SAndroid Build Coastguard Worker 	return err;
230*d83cc019SAndroid Build Coastguard Worker }
231*d83cc019SAndroid Build Coastguard Worker 
get_lease(int fd,struct local_drm_mode_get_lease * mgl)232*d83cc019SAndroid Build Coastguard Worker static int get_lease(int fd, struct local_drm_mode_get_lease *mgl)
233*d83cc019SAndroid Build Coastguard Worker {
234*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
235*d83cc019SAndroid Build Coastguard Worker 
236*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, LOCAL_DRM_IOCTL_MODE_GET_LEASE, mgl))
237*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
238*d83cc019SAndroid Build Coastguard Worker 	return err;
239*d83cc019SAndroid Build Coastguard Worker }
240*d83cc019SAndroid Build Coastguard Worker 
make_lease(data_t * data,lease_t * lease)241*d83cc019SAndroid Build Coastguard Worker static int make_lease(data_t *data, lease_t *lease)
242*d83cc019SAndroid Build Coastguard Worker {
243*d83cc019SAndroid Build Coastguard Worker 	uint32_t object_ids[3];
244*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_create_lease mcl;
245*d83cc019SAndroid Build Coastguard Worker 	int ret;
246*d83cc019SAndroid Build Coastguard Worker 
247*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = (uint64_t) (uintptr_t) &object_ids[0];
248*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 0;
249*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
250*d83cc019SAndroid Build Coastguard Worker 
251*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->connector_id;
252*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->crtc_id;
253*d83cc019SAndroid Build Coastguard Worker 	/* We use universal planes, must add the primary plane */
254*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->plane_id;
255*d83cc019SAndroid Build Coastguard Worker 
256*d83cc019SAndroid Build Coastguard Worker 	ret = create_lease(data->master.fd, &mcl);
257*d83cc019SAndroid Build Coastguard Worker 
258*d83cc019SAndroid Build Coastguard Worker 	if (ret)
259*d83cc019SAndroid Build Coastguard Worker 		return ret;
260*d83cc019SAndroid Build Coastguard Worker 
261*d83cc019SAndroid Build Coastguard Worker 	lease->fd = mcl.fd;
262*d83cc019SAndroid Build Coastguard Worker 	lease->lessee_id = mcl.lessee_id;
263*d83cc019SAndroid Build Coastguard Worker 	return 0;
264*d83cc019SAndroid Build Coastguard Worker }
265*d83cc019SAndroid Build Coastguard Worker 
terminate_lease(lease_t * lease)266*d83cc019SAndroid Build Coastguard Worker static void terminate_lease(lease_t *lease)
267*d83cc019SAndroid Build Coastguard Worker {
268*d83cc019SAndroid Build Coastguard Worker 	close(lease->fd);
269*d83cc019SAndroid Build Coastguard Worker }
270*d83cc019SAndroid Build Coastguard Worker 
paint_fb(int drm_fd,struct igt_fb * fb,const char * test_name,const char * mode_format_str,const char * connector_str,const char * pipe_str)271*d83cc019SAndroid Build Coastguard Worker static int paint_fb(int drm_fd, struct igt_fb *fb, const char *test_name,
272*d83cc019SAndroid Build Coastguard Worker 		    const char *mode_format_str, const char *connector_str, const char *pipe_str)
273*d83cc019SAndroid Build Coastguard Worker {
274*d83cc019SAndroid Build Coastguard Worker 	cairo_t *cr;
275*d83cc019SAndroid Build Coastguard Worker 
276*d83cc019SAndroid Build Coastguard Worker 	cr = igt_get_cairo_ctx(drm_fd, fb);
277*d83cc019SAndroid Build Coastguard Worker 
278*d83cc019SAndroid Build Coastguard Worker 	igt_paint_color_gradient(cr, 0, 0, fb->width, fb->height, 1, 1, 1);
279*d83cc019SAndroid Build Coastguard Worker 	igt_paint_test_pattern(cr, fb->width, fb->height);
280*d83cc019SAndroid Build Coastguard Worker 
281*d83cc019SAndroid Build Coastguard Worker 	cairo_move_to(cr, fb->width / 2, fb->height / 2);
282*d83cc019SAndroid Build Coastguard Worker 	cairo_set_font_size(cr, 36);
283*d83cc019SAndroid Build Coastguard Worker 	igt_cairo_printf_line(cr, align_hcenter, 10, "%s", test_name);
284*d83cc019SAndroid Build Coastguard Worker 	igt_cairo_printf_line(cr, align_hcenter, 10, "%s", mode_format_str);
285*d83cc019SAndroid Build Coastguard Worker 	igt_cairo_printf_line(cr, align_hcenter, 10, "%s", connector_str);
286*d83cc019SAndroid Build Coastguard Worker 	igt_cairo_printf_line(cr, align_hcenter, 10, "%s", pipe_str);
287*d83cc019SAndroid Build Coastguard Worker 
288*d83cc019SAndroid Build Coastguard Worker 	cairo_destroy(cr);
289*d83cc019SAndroid Build Coastguard Worker 
290*d83cc019SAndroid Build Coastguard Worker 	return 0;
291*d83cc019SAndroid Build Coastguard Worker }
292*d83cc019SAndroid Build Coastguard Worker 
simple_lease(data_t * data)293*d83cc019SAndroid Build Coastguard Worker static void simple_lease(data_t *data)
294*d83cc019SAndroid Build Coastguard Worker {
295*d83cc019SAndroid Build Coastguard Worker 	lease_t lease;
296*d83cc019SAndroid Build Coastguard Worker 
297*d83cc019SAndroid Build Coastguard Worker 	/* Create a valid lease */
298*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(make_lease(data, &lease), 0);
299*d83cc019SAndroid Build Coastguard Worker 
300*d83cc019SAndroid Build Coastguard Worker 	igt_display_require(&lease.display, lease.fd);
301*d83cc019SAndroid Build Coastguard Worker 
302*d83cc019SAndroid Build Coastguard Worker 	/* Set a mode on the leased output */
303*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(0, prepare_crtc(&lease, data->connector_id, data->crtc_id));
304*d83cc019SAndroid Build Coastguard Worker 
305*d83cc019SAndroid Build Coastguard Worker 	/* Paint something attractive */
306*d83cc019SAndroid Build Coastguard Worker 	paint_fb(lease.fd, &lease.primary_fb, "simple_lease",
307*d83cc019SAndroid Build Coastguard Worker 		 lease.mode->name, igt_output_name(lease.output), kmstest_pipe_name(data->pipe));
308*d83cc019SAndroid Build Coastguard Worker 	igt_debug_wait_for_keypress("lease");
309*d83cc019SAndroid Build Coastguard Worker 	cleanup_crtc(&lease,
310*d83cc019SAndroid Build Coastguard Worker 		     connector_id_to_output(&lease.display, data->connector_id));
311*d83cc019SAndroid Build Coastguard Worker 
312*d83cc019SAndroid Build Coastguard Worker 	terminate_lease(&lease);
313*d83cc019SAndroid Build Coastguard Worker }
314*d83cc019SAndroid Build Coastguard Worker 
page_flip_implicit_plane(data_t * data)315*d83cc019SAndroid Build Coastguard Worker static void page_flip_implicit_plane(data_t *data)
316*d83cc019SAndroid Build Coastguard Worker {
317*d83cc019SAndroid Build Coastguard Worker 	uint32_t object_ids[3];
318*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_create_lease mcl;
319*d83cc019SAndroid Build Coastguard Worker 	drmModePlaneRes *plane_resources;
320*d83cc019SAndroid Build Coastguard Worker 	uint32_t wrong_plane_id = 0;
321*d83cc019SAndroid Build Coastguard Worker 	int i;
322*d83cc019SAndroid Build Coastguard Worker 
323*d83cc019SAndroid Build Coastguard Worker 	/* find a plane which isn't the primary one for us */
324*d83cc019SAndroid Build Coastguard Worker 	plane_resources = drmModeGetPlaneResources(data->master.fd);
325*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < plane_resources->count_planes; i++) {
326*d83cc019SAndroid Build Coastguard Worker 		if (plane_resources->planes[i] != data->plane_id) {
327*d83cc019SAndroid Build Coastguard Worker 			wrong_plane_id = plane_resources->planes[i];
328*d83cc019SAndroid Build Coastguard Worker 			break;
329*d83cc019SAndroid Build Coastguard Worker 		}
330*d83cc019SAndroid Build Coastguard Worker 	}
331*d83cc019SAndroid Build Coastguard Worker 	drmModeFreePlaneResources(plane_resources);
332*d83cc019SAndroid Build Coastguard Worker 	igt_require(wrong_plane_id);
333*d83cc019SAndroid Build Coastguard Worker 
334*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = (uint64_t) (uintptr_t) &object_ids[0];
335*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 0;
336*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
337*d83cc019SAndroid Build Coastguard Worker 
338*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->connector_id;
339*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->crtc_id;
340*d83cc019SAndroid Build Coastguard Worker 
341*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 0);
342*d83cc019SAndroid Build Coastguard Worker 	do_or_die(create_lease(data->master.fd, &mcl));
343*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
344*d83cc019SAndroid Build Coastguard Worker 
345*d83cc019SAndroid Build Coastguard Worker 	/* Set a mode on the leased output */
346*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(0, prepare_crtc(&data->master, data->connector_id, data->crtc_id));
347*d83cc019SAndroid Build Coastguard Worker 
348*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
349*d83cc019SAndroid Build Coastguard Worker 	do_or_die(drmModePageFlip(data->master.fd, data->crtc_id,
350*d83cc019SAndroid Build Coastguard Worker 			      data->master.primary_fb.fb_id,
351*d83cc019SAndroid Build Coastguard Worker 			      0, NULL));
352*d83cc019SAndroid Build Coastguard Worker 	igt_wait_for_vblank_count(data->master.fd,
353*d83cc019SAndroid Build Coastguard Worker 				  crtc_id_to_pipe(&data->master.display, data->crtc_id),
354*d83cc019SAndroid Build Coastguard Worker 				  1);
355*d83cc019SAndroid Build Coastguard Worker 	do_or_die(drmModePageFlip(mcl.fd, data->crtc_id,
356*d83cc019SAndroid Build Coastguard Worker 			      data->master.primary_fb.fb_id,
357*d83cc019SAndroid Build Coastguard Worker 			      0, NULL));
358*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
359*d83cc019SAndroid Build Coastguard Worker 
360*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = wrong_plane_id;
361*d83cc019SAndroid Build Coastguard Worker 	do_or_die(create_lease(data->master.fd, &mcl));
362*d83cc019SAndroid Build Coastguard Worker 
363*d83cc019SAndroid Build Coastguard Worker 	igt_wait_for_vblank_count(data->master.fd,
364*d83cc019SAndroid Build Coastguard Worker 				  crtc_id_to_pipe(&data->master.display, data->crtc_id),
365*d83cc019SAndroid Build Coastguard Worker 				  1);
366*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(drmModePageFlip(mcl.fd, data->crtc_id,
367*d83cc019SAndroid Build Coastguard Worker 				      data->master.primary_fb.fb_id,
368*d83cc019SAndroid Build Coastguard Worker 				      0, NULL),
369*d83cc019SAndroid Build Coastguard Worker 		      -EACCES);
370*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
371*d83cc019SAndroid Build Coastguard Worker 
372*d83cc019SAndroid Build Coastguard Worker 	cleanup_crtc(&data->master,
373*d83cc019SAndroid Build Coastguard Worker 		     connector_id_to_output(&data->master.display, data->connector_id));
374*d83cc019SAndroid Build Coastguard Worker }
375*d83cc019SAndroid Build Coastguard Worker 
setcrtc_implicit_plane(data_t * data)376*d83cc019SAndroid Build Coastguard Worker static void setcrtc_implicit_plane(data_t *data)
377*d83cc019SAndroid Build Coastguard Worker {
378*d83cc019SAndroid Build Coastguard Worker 	uint32_t object_ids[3];
379*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_create_lease mcl;
380*d83cc019SAndroid Build Coastguard Worker 	drmModePlaneRes *plane_resources;
381*d83cc019SAndroid Build Coastguard Worker 	uint32_t wrong_plane_id = 0;
382*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *output =
383*d83cc019SAndroid Build Coastguard Worker 		connector_id_to_output(&data->master.display,
384*d83cc019SAndroid Build Coastguard Worker 				       data->connector_id);
385*d83cc019SAndroid Build Coastguard Worker 	drmModeModeInfo *mode = igt_output_get_mode(output);
386*d83cc019SAndroid Build Coastguard Worker 	int i;
387*d83cc019SAndroid Build Coastguard Worker 
388*d83cc019SAndroid Build Coastguard Worker 	/* find a plane which isn't the primary one for us */
389*d83cc019SAndroid Build Coastguard Worker 	plane_resources = drmModeGetPlaneResources(data->master.fd);
390*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < plane_resources->count_planes; i++) {
391*d83cc019SAndroid Build Coastguard Worker 		if (plane_resources->planes[i] != data->plane_id) {
392*d83cc019SAndroid Build Coastguard Worker 			wrong_plane_id = plane_resources->planes[i];
393*d83cc019SAndroid Build Coastguard Worker 			break;
394*d83cc019SAndroid Build Coastguard Worker 		}
395*d83cc019SAndroid Build Coastguard Worker 	}
396*d83cc019SAndroid Build Coastguard Worker 	drmModeFreePlaneResources(plane_resources);
397*d83cc019SAndroid Build Coastguard Worker 	igt_require(wrong_plane_id);
398*d83cc019SAndroid Build Coastguard Worker 
399*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = (uint64_t) (uintptr_t) &object_ids[0];
400*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 0;
401*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
402*d83cc019SAndroid Build Coastguard Worker 
403*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->connector_id;
404*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->crtc_id;
405*d83cc019SAndroid Build Coastguard Worker 
406*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 0);
407*d83cc019SAndroid Build Coastguard Worker 	do_or_die(create_lease(data->master.fd, &mcl));
408*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
409*d83cc019SAndroid Build Coastguard Worker 
410*d83cc019SAndroid Build Coastguard Worker 	/* Set a mode on the leased output */
411*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(0, prepare_crtc(&data->master, data->connector_id, data->crtc_id));
412*d83cc019SAndroid Build Coastguard Worker 
413*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
414*d83cc019SAndroid Build Coastguard Worker 	do_or_die(drmModeSetCrtc(data->master.fd, data->crtc_id, -1,
415*d83cc019SAndroid Build Coastguard Worker 				 0, 0, object_ids, 1, mode));
416*d83cc019SAndroid Build Coastguard Worker 	do_or_die(drmModeSetCrtc(mcl.fd, data->crtc_id, -1,
417*d83cc019SAndroid Build Coastguard Worker 				 0, 0, object_ids, 1, mode));
418*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
419*d83cc019SAndroid Build Coastguard Worker 
420*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = wrong_plane_id;
421*d83cc019SAndroid Build Coastguard Worker 	do_or_die(create_lease(data->master.fd, &mcl));
422*d83cc019SAndroid Build Coastguard Worker 
423*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(drmModeSetCrtc(mcl.fd, data->crtc_id, -1,
424*d83cc019SAndroid Build Coastguard Worker 				     0, 0, object_ids, 1, mode),
425*d83cc019SAndroid Build Coastguard Worker 		      -EACCES);
426*d83cc019SAndroid Build Coastguard Worker 	/* make sure we are allowed to turn the CRTC off */
427*d83cc019SAndroid Build Coastguard Worker 	do_or_die(drmModeSetCrtc(mcl.fd, data->crtc_id,
428*d83cc019SAndroid Build Coastguard Worker 				 0, 0, 0, NULL, 0, NULL));
429*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
430*d83cc019SAndroid Build Coastguard Worker 
431*d83cc019SAndroid Build Coastguard Worker 	cleanup_crtc(&data->master,
432*d83cc019SAndroid Build Coastguard Worker 		     connector_id_to_output(&data->master.display, data->connector_id));
433*d83cc019SAndroid Build Coastguard Worker }
434*d83cc019SAndroid Build Coastguard Worker 
cursor_implicit_plane(data_t * data)435*d83cc019SAndroid Build Coastguard Worker static void cursor_implicit_plane(data_t *data)
436*d83cc019SAndroid Build Coastguard Worker {
437*d83cc019SAndroid Build Coastguard Worker 	uint32_t object_ids[3];
438*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_create_lease mcl;
439*d83cc019SAndroid Build Coastguard Worker 
440*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = (uint64_t) (uintptr_t) &object_ids[0];
441*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 0;
442*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
443*d83cc019SAndroid Build Coastguard Worker 
444*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->connector_id;
445*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->crtc_id;
446*d83cc019SAndroid Build Coastguard Worker 
447*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 0);
448*d83cc019SAndroid Build Coastguard Worker 	do_or_die(create_lease(data->master.fd, &mcl));
449*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
450*d83cc019SAndroid Build Coastguard Worker 
451*d83cc019SAndroid Build Coastguard Worker 	/* Set a mode on the leased output */
452*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(0, prepare_crtc(&data->master, data->connector_id, data->crtc_id));
453*d83cc019SAndroid Build Coastguard Worker 
454*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
455*d83cc019SAndroid Build Coastguard Worker 	do_or_die(drmModeSetCursor(data->master.fd, data->crtc_id, 0, 0, 0));
456*d83cc019SAndroid Build Coastguard Worker 	do_or_die(drmModeSetCursor(mcl.fd, data->crtc_id, 0, 0, 0));
457*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
458*d83cc019SAndroid Build Coastguard Worker 
459*d83cc019SAndroid Build Coastguard Worker 	/* primary plane is never the cursor */
460*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->plane_id;
461*d83cc019SAndroid Build Coastguard Worker 	do_or_die(create_lease(data->master.fd, &mcl));
462*d83cc019SAndroid Build Coastguard Worker 
463*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(drmModeSetCursor(mcl.fd, data->crtc_id, 0, 0, 0),
464*d83cc019SAndroid Build Coastguard Worker 		      -EACCES);
465*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
466*d83cc019SAndroid Build Coastguard Worker 
467*d83cc019SAndroid Build Coastguard Worker 	cleanup_crtc(&data->master,
468*d83cc019SAndroid Build Coastguard Worker 		     connector_id_to_output(&data->master.display, data->connector_id));
469*d83cc019SAndroid Build Coastguard Worker }
470*d83cc019SAndroid Build Coastguard Worker 
atomic_implicit_crtc(data_t * data)471*d83cc019SAndroid Build Coastguard Worker static void atomic_implicit_crtc(data_t *data)
472*d83cc019SAndroid Build Coastguard Worker {
473*d83cc019SAndroid Build Coastguard Worker 	uint32_t object_ids[3];
474*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_create_lease mcl;
475*d83cc019SAndroid Build Coastguard Worker 	drmModeRes *resources;
476*d83cc019SAndroid Build Coastguard Worker 	drmModeObjectPropertiesPtr props;
477*d83cc019SAndroid Build Coastguard Worker 	uint32_t wrong_crtc_id = 0;
478*d83cc019SAndroid Build Coastguard Worker 	uint32_t crtc_id_prop = 0;
479*d83cc019SAndroid Build Coastguard Worker 	drmModeAtomicReqPtr req = NULL;
480*d83cc019SAndroid Build Coastguard Worker 	int ret;
481*d83cc019SAndroid Build Coastguard Worker 
482*d83cc019SAndroid Build Coastguard Worker 	igt_require(data->master.display.is_atomic);
483*d83cc019SAndroid Build Coastguard Worker 
484*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = (uint64_t) (uintptr_t) &object_ids[0];
485*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 0;
486*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
487*d83cc019SAndroid Build Coastguard Worker 
488*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->connector_id;
489*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = data->plane_id;
490*d83cc019SAndroid Build Coastguard Worker 
491*d83cc019SAndroid Build Coastguard Worker 	/* find a plane which isn't the primary one for us */
492*d83cc019SAndroid Build Coastguard Worker 	resources = drmModeGetResources(data->master.fd);
493*d83cc019SAndroid Build Coastguard Worker 	igt_assert(resources);
494*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < resources->count_crtcs; i++) {
495*d83cc019SAndroid Build Coastguard Worker 		if (resources->crtcs[i] != data->crtc_id) {
496*d83cc019SAndroid Build Coastguard Worker 			wrong_crtc_id = resources->crtcs[i];
497*d83cc019SAndroid Build Coastguard Worker 			break;
498*d83cc019SAndroid Build Coastguard Worker 		}
499*d83cc019SAndroid Build Coastguard Worker 	}
500*d83cc019SAndroid Build Coastguard Worker 	drmModeFreeResources(resources);
501*d83cc019SAndroid Build Coastguard Worker 	igt_require(wrong_crtc_id);
502*d83cc019SAndroid Build Coastguard Worker 	object_ids[mcl.object_count++] = wrong_crtc_id;
503*d83cc019SAndroid Build Coastguard Worker 
504*d83cc019SAndroid Build Coastguard Worker 	/* find the CRTC_ID prop, it's global */
505*d83cc019SAndroid Build Coastguard Worker 	props = drmModeObjectGetProperties(data->master.fd, data->plane_id,
506*d83cc019SAndroid Build Coastguard Worker 					   DRM_MODE_OBJECT_PLANE);
507*d83cc019SAndroid Build Coastguard Worker 	igt_assert(props);
508*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < props->count_props; i++) {
509*d83cc019SAndroid Build Coastguard Worker 		drmModePropertyPtr prop = drmModeGetProperty(data->master.fd,
510*d83cc019SAndroid Build Coastguard Worker 							     props->props[i]);
511*d83cc019SAndroid Build Coastguard Worker 		if (strcmp(prop->name, "CRTC_ID") == 0)
512*d83cc019SAndroid Build Coastguard Worker 			crtc_id_prop = props->props[i];
513*d83cc019SAndroid Build Coastguard Worker 
514*d83cc019SAndroid Build Coastguard Worker 		printf("prop name %s, prop id %u, prop id %u\n",
515*d83cc019SAndroid Build Coastguard Worker 		       prop->name, props->props[i], prop->prop_id);
516*d83cc019SAndroid Build Coastguard Worker 		drmModeFreeProperty(prop);
517*d83cc019SAndroid Build Coastguard Worker 		if (crtc_id_prop)
518*d83cc019SAndroid Build Coastguard Worker 			break;
519*d83cc019SAndroid Build Coastguard Worker 	}
520*d83cc019SAndroid Build Coastguard Worker 	drmModeFreeObjectProperties(props);
521*d83cc019SAndroid Build Coastguard Worker 	igt_assert(crtc_id_prop);
522*d83cc019SAndroid Build Coastguard Worker 
523*d83cc019SAndroid Build Coastguard Worker 	do_or_die(create_lease(data->master.fd, &mcl));
524*d83cc019SAndroid Build Coastguard Worker 	do_or_die(drmSetClientCap(mcl.fd, DRM_CLIENT_CAP_ATOMIC, 1));
525*d83cc019SAndroid Build Coastguard Worker 
526*d83cc019SAndroid Build Coastguard Worker 	/* check CRTC_ID property on the plane */
527*d83cc019SAndroid Build Coastguard Worker 	req = drmModeAtomicAlloc();
528*d83cc019SAndroid Build Coastguard Worker 	igt_assert(req);
529*d83cc019SAndroid Build Coastguard Worker 	ret = drmModeAtomicAddProperty(req, data->plane_id,
530*d83cc019SAndroid Build Coastguard Worker 				       crtc_id_prop, data->crtc_id);
531*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ret >= 0);
532*d83cc019SAndroid Build Coastguard Worker 
533*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
534*d83cc019SAndroid Build Coastguard Worker 	ret = drmModeAtomicCommit(data->master.fd, req, DRM_MODE_ATOMIC_TEST_ONLY, NULL);
535*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ret == 0 || ret == -EINVAL);
536*d83cc019SAndroid Build Coastguard Worker 
537*d83cc019SAndroid Build Coastguard Worker 	ret = drmModeAtomicCommit(mcl.fd, req, DRM_MODE_ATOMIC_TEST_ONLY, NULL);
538*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ret == -EACCES);
539*d83cc019SAndroid Build Coastguard Worker 	drmModeAtomicFree(req);
540*d83cc019SAndroid Build Coastguard Worker 
541*d83cc019SAndroid Build Coastguard Worker 	/* check CRTC_ID property on the connector */
542*d83cc019SAndroid Build Coastguard Worker 	req = drmModeAtomicAlloc();
543*d83cc019SAndroid Build Coastguard Worker 	igt_assert(req);
544*d83cc019SAndroid Build Coastguard Worker 	ret = drmModeAtomicAddProperty(req, data->connector_id,
545*d83cc019SAndroid Build Coastguard Worker 				       crtc_id_prop, data->crtc_id);
546*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ret >= 0);
547*d83cc019SAndroid Build Coastguard Worker 
548*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
549*d83cc019SAndroid Build Coastguard Worker 	ret = drmModeAtomicCommit(data->master.fd, req, DRM_MODE_ATOMIC_TEST_ONLY, NULL);
550*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ret == 0 || ret == -EINVAL);
551*d83cc019SAndroid Build Coastguard Worker 
552*d83cc019SAndroid Build Coastguard Worker 	ret = drmModeAtomicCommit(mcl.fd, req, DRM_MODE_ATOMIC_TEST_ONLY, NULL);
553*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ret == -EACCES);
554*d83cc019SAndroid Build Coastguard Worker 	drmModeAtomicFree(req);
555*d83cc019SAndroid Build Coastguard Worker 
556*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
557*d83cc019SAndroid Build Coastguard Worker }
558*d83cc019SAndroid Build Coastguard Worker 
559*d83cc019SAndroid Build Coastguard Worker /* Test listing lessees */
lessee_list(data_t * data)560*d83cc019SAndroid Build Coastguard Worker static void lessee_list(data_t *data)
561*d83cc019SAndroid Build Coastguard Worker {
562*d83cc019SAndroid Build Coastguard Worker 	lease_t lease;
563*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_list_lessees mll;
564*d83cc019SAndroid Build Coastguard Worker 	uint32_t lessees[1];
565*d83cc019SAndroid Build Coastguard Worker 
566*d83cc019SAndroid Build Coastguard Worker 	mll.pad = 0;
567*d83cc019SAndroid Build Coastguard Worker 
568*d83cc019SAndroid Build Coastguard Worker 	/* Create a valid lease */
569*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(make_lease(data, &lease), 0);
570*d83cc019SAndroid Build Coastguard Worker 
571*d83cc019SAndroid Build Coastguard Worker 	/* check for nested leases */
572*d83cc019SAndroid Build Coastguard Worker 	mll.count_lessees = 0;
573*d83cc019SAndroid Build Coastguard Worker 	mll.lessees_ptr = 0;
574*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(list_lessees(lease.fd, &mll), 0);
575*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mll.count_lessees, 0);
576*d83cc019SAndroid Build Coastguard Worker 
577*d83cc019SAndroid Build Coastguard Worker 	/* Get the number of lessees */
578*d83cc019SAndroid Build Coastguard Worker 	mll.count_lessees = 0;
579*d83cc019SAndroid Build Coastguard Worker 	mll.lessees_ptr = 0;
580*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(list_lessees(data->master.fd, &mll), 0);
581*d83cc019SAndroid Build Coastguard Worker 
582*d83cc019SAndroid Build Coastguard Worker 	/* Make sure there's a single lessee */
583*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mll.count_lessees, 1);
584*d83cc019SAndroid Build Coastguard Worker 
585*d83cc019SAndroid Build Coastguard Worker 	/* invalid ptr */
586*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(list_lessees(data->master.fd, &mll), -EFAULT);
587*d83cc019SAndroid Build Coastguard Worker 
588*d83cc019SAndroid Build Coastguard Worker 	mll.lessees_ptr = (uint64_t) (uintptr_t) &lessees[0];
589*d83cc019SAndroid Build Coastguard Worker 
590*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(list_lessees(data->master.fd, &mll), 0);
591*d83cc019SAndroid Build Coastguard Worker 
592*d83cc019SAndroid Build Coastguard Worker 	/* Make sure there's a single lessee */
593*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mll.count_lessees, 1);
594*d83cc019SAndroid Build Coastguard Worker 
595*d83cc019SAndroid Build Coastguard Worker 	/* Make sure the listed lease is the same as the one we created */
596*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(lessees[0], lease.lessee_id);
597*d83cc019SAndroid Build Coastguard Worker 
598*d83cc019SAndroid Build Coastguard Worker 	/* invalid pad */
599*d83cc019SAndroid Build Coastguard Worker 	mll.pad = -1;
600*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(list_lessees(data->master.fd, &mll), -EINVAL);
601*d83cc019SAndroid Build Coastguard Worker 	mll.pad = 0;
602*d83cc019SAndroid Build Coastguard Worker 
603*d83cc019SAndroid Build Coastguard Worker 	terminate_lease(&lease);
604*d83cc019SAndroid Build Coastguard Worker 
605*d83cc019SAndroid Build Coastguard Worker 	/* Make sure the lease is gone */
606*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(list_lessees(data->master.fd, &mll), 0);
607*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mll.count_lessees, 0);
608*d83cc019SAndroid Build Coastguard Worker }
609*d83cc019SAndroid Build Coastguard Worker 
610*d83cc019SAndroid Build Coastguard Worker /* Test getting the contents of a lease */
lease_get(data_t * data)611*d83cc019SAndroid Build Coastguard Worker static void lease_get(data_t *data)
612*d83cc019SAndroid Build Coastguard Worker {
613*d83cc019SAndroid Build Coastguard Worker 	lease_t lease;
614*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_get_lease mgl;
615*d83cc019SAndroid Build Coastguard Worker 	int num_leased_obj = 3;
616*d83cc019SAndroid Build Coastguard Worker 	uint32_t objects[num_leased_obj];
617*d83cc019SAndroid Build Coastguard Worker 	int o;
618*d83cc019SAndroid Build Coastguard Worker 
619*d83cc019SAndroid Build Coastguard Worker 	mgl.pad = 0;
620*d83cc019SAndroid Build Coastguard Worker 
621*d83cc019SAndroid Build Coastguard Worker 	/* Create a valid lease */
622*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(make_lease(data, &lease), 0);
623*d83cc019SAndroid Build Coastguard Worker 
624*d83cc019SAndroid Build Coastguard Worker 	/* Get the number of objects */
625*d83cc019SAndroid Build Coastguard Worker 	mgl.count_objects = 0;
626*d83cc019SAndroid Build Coastguard Worker 	mgl.objects_ptr = 0;
627*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(get_lease(lease.fd, &mgl), 0);
628*d83cc019SAndroid Build Coastguard Worker 
629*d83cc019SAndroid Build Coastguard Worker 	/* Make sure it's 2 */
630*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mgl.count_objects, num_leased_obj);
631*d83cc019SAndroid Build Coastguard Worker 
632*d83cc019SAndroid Build Coastguard Worker 	/* Get the objects */
633*d83cc019SAndroid Build Coastguard Worker 	mgl.objects_ptr = (uint64_t) (uintptr_t) objects;
634*d83cc019SAndroid Build Coastguard Worker 
635*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(get_lease(lease.fd, &mgl), 0);
636*d83cc019SAndroid Build Coastguard Worker 
637*d83cc019SAndroid Build Coastguard Worker 	/* Make sure it's 2 */
638*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mgl.count_objects, num_leased_obj);
639*d83cc019SAndroid Build Coastguard Worker 
640*d83cc019SAndroid Build Coastguard Worker 	/* Make sure we got the connector, crtc and plane back */
641*d83cc019SAndroid Build Coastguard Worker 	for (o = 0; o < num_leased_obj; o++)
642*d83cc019SAndroid Build Coastguard Worker 		if (objects[o] == data->connector_id)
643*d83cc019SAndroid Build Coastguard Worker 			break;
644*d83cc019SAndroid Build Coastguard Worker 
645*d83cc019SAndroid Build Coastguard Worker 	igt_assert_neq(o, num_leased_obj);
646*d83cc019SAndroid Build Coastguard Worker 
647*d83cc019SAndroid Build Coastguard Worker 	for (o = 0; o < num_leased_obj; o++)
648*d83cc019SAndroid Build Coastguard Worker 		if (objects[o] == data->crtc_id)
649*d83cc019SAndroid Build Coastguard Worker 			break;
650*d83cc019SAndroid Build Coastguard Worker 
651*d83cc019SAndroid Build Coastguard Worker 	igt_assert_neq(o, num_leased_obj);
652*d83cc019SAndroid Build Coastguard Worker 
653*d83cc019SAndroid Build Coastguard Worker 	for (o = 0; o < num_leased_obj; o++)
654*d83cc019SAndroid Build Coastguard Worker 		if (objects[o] == data->plane_id)
655*d83cc019SAndroid Build Coastguard Worker 			break;
656*d83cc019SAndroid Build Coastguard Worker 
657*d83cc019SAndroid Build Coastguard Worker 	igt_assert_neq(o, num_leased_obj);
658*d83cc019SAndroid Build Coastguard Worker 
659*d83cc019SAndroid Build Coastguard Worker 	/* invalid pad */
660*d83cc019SAndroid Build Coastguard Worker 	mgl.pad = -1;
661*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(get_lease(lease.fd, &mgl), -EINVAL);
662*d83cc019SAndroid Build Coastguard Worker 	mgl.pad = 0;
663*d83cc019SAndroid Build Coastguard Worker 
664*d83cc019SAndroid Build Coastguard Worker 	/* invalid pointer */
665*d83cc019SAndroid Build Coastguard Worker 	mgl.objects_ptr = 0;
666*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(get_lease(lease.fd, &mgl), -EFAULT);
667*d83cc019SAndroid Build Coastguard Worker 
668*d83cc019SAndroid Build Coastguard Worker 	terminate_lease(&lease);
669*d83cc019SAndroid Build Coastguard Worker }
670*d83cc019SAndroid Build Coastguard Worker 
lease_unleased_crtc(data_t * data)671*d83cc019SAndroid Build Coastguard Worker static void lease_unleased_crtc(data_t *data)
672*d83cc019SAndroid Build Coastguard Worker {
673*d83cc019SAndroid Build Coastguard Worker 	lease_t lease;
674*d83cc019SAndroid Build Coastguard Worker 	enum pipe p;
675*d83cc019SAndroid Build Coastguard Worker 	uint32_t bad_crtc_id;
676*d83cc019SAndroid Build Coastguard Worker 	drmModeCrtc *crtc;
677*d83cc019SAndroid Build Coastguard Worker 	int ret;
678*d83cc019SAndroid Build Coastguard Worker 
679*d83cc019SAndroid Build Coastguard Worker 	/* Create a valid lease */
680*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(make_lease(data, &lease), 0);
681*d83cc019SAndroid Build Coastguard Worker 
682*d83cc019SAndroid Build Coastguard Worker 	igt_display_require(&lease.display, lease.fd);
683*d83cc019SAndroid Build Coastguard Worker 
684*d83cc019SAndroid Build Coastguard Worker 	/* Find another CRTC that we don't control */
685*d83cc019SAndroid Build Coastguard Worker 	bad_crtc_id = 0;
686*d83cc019SAndroid Build Coastguard Worker 	for (p = 0; bad_crtc_id == 0 && p < data->master.display.n_pipes; p++) {
687*d83cc019SAndroid Build Coastguard Worker 		if (pipe_to_crtc_id(&data->master.display, p) != data->crtc_id)
688*d83cc019SAndroid Build Coastguard Worker 			bad_crtc_id = pipe_to_crtc_id(&data->master.display, p);
689*d83cc019SAndroid Build Coastguard Worker 	}
690*d83cc019SAndroid Build Coastguard Worker 
691*d83cc019SAndroid Build Coastguard Worker 	/* Give up if there isn't another crtc */
692*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on(bad_crtc_id == 0);
693*d83cc019SAndroid Build Coastguard Worker 
694*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
695*d83cc019SAndroid Build Coastguard Worker 	ret = drmModeSetCrtc(lease.fd, data->crtc_id, 0, 0, 0, NULL, 0, NULL);
696*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(ret, 0);
697*d83cc019SAndroid Build Coastguard Worker 	crtc = drmModeGetCrtc(lease.fd, data->crtc_id);
698*d83cc019SAndroid Build Coastguard Worker 	igt_assert(crtc);
699*d83cc019SAndroid Build Coastguard Worker 	drmModeFreeCrtc(crtc);
700*d83cc019SAndroid Build Coastguard Worker 
701*d83cc019SAndroid Build Coastguard Worker 	/* Attempt to use the unleased crtc id. We need raw ioctl to bypass the
702*d83cc019SAndroid Build Coastguard Worker 	 * igt_kms helpers.
703*d83cc019SAndroid Build Coastguard Worker 	 */
704*d83cc019SAndroid Build Coastguard Worker 	ret = drmModeSetCrtc(lease.fd, bad_crtc_id, 0, 0, 0, NULL, 0, NULL);
705*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(ret, -ENOENT);
706*d83cc019SAndroid Build Coastguard Worker 	crtc = drmModeGetCrtc(lease.fd, bad_crtc_id);
707*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!crtc);
708*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(errno, ENOENT);
709*d83cc019SAndroid Build Coastguard Worker 	drmModeFreeCrtc(crtc);
710*d83cc019SAndroid Build Coastguard Worker 
711*d83cc019SAndroid Build Coastguard Worker 	terminate_lease(&lease);
712*d83cc019SAndroid Build Coastguard Worker }
713*d83cc019SAndroid Build Coastguard Worker 
lease_unleased_connector(data_t * data)714*d83cc019SAndroid Build Coastguard Worker static void lease_unleased_connector(data_t *data)
715*d83cc019SAndroid Build Coastguard Worker {
716*d83cc019SAndroid Build Coastguard Worker 	lease_t lease;
717*d83cc019SAndroid Build Coastguard Worker 	int o;
718*d83cc019SAndroid Build Coastguard Worker 	uint32_t bad_connector_id;
719*d83cc019SAndroid Build Coastguard Worker 	drmModeConnector *c;
720*d83cc019SAndroid Build Coastguard Worker 
721*d83cc019SAndroid Build Coastguard Worker 	/* Create a valid lease */
722*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(make_lease(data, &lease), 0);
723*d83cc019SAndroid Build Coastguard Worker 
724*d83cc019SAndroid Build Coastguard Worker 	igt_display_require(&lease.display, lease.fd);
725*d83cc019SAndroid Build Coastguard Worker 
726*d83cc019SAndroid Build Coastguard Worker 	/* Find another connector that we don't control */
727*d83cc019SAndroid Build Coastguard Worker 	bad_connector_id = 0;
728*d83cc019SAndroid Build Coastguard Worker 	for (o = 0; bad_connector_id == 0 && o < data->master.display.n_outputs; o++) {
729*d83cc019SAndroid Build Coastguard Worker 		if (data->master.display.outputs[o].id != data->connector_id)
730*d83cc019SAndroid Build Coastguard Worker 			bad_connector_id = data->master.display.outputs[o].id;
731*d83cc019SAndroid Build Coastguard Worker 	}
732*d83cc019SAndroid Build Coastguard Worker 
733*d83cc019SAndroid Build Coastguard Worker 	/* Give up if there isn't another connector */
734*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on(bad_connector_id == 0);
735*d83cc019SAndroid Build Coastguard Worker 
736*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
737*d83cc019SAndroid Build Coastguard Worker 	c = drmModeGetConnector(lease.fd, data->connector_id);
738*d83cc019SAndroid Build Coastguard Worker 	igt_assert(c);
739*d83cc019SAndroid Build Coastguard Worker 
740*d83cc019SAndroid Build Coastguard Worker 	/* Attempt to use the unleased connector id. Note that the
741*d83cc019SAndroid Build Coastguard Worker 	 */
742*d83cc019SAndroid Build Coastguard Worker 	c = drmModeGetConnector(lease.fd, bad_connector_id);
743*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!c);
744*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(errno, ENOENT);
745*d83cc019SAndroid Build Coastguard Worker 
746*d83cc019SAndroid Build Coastguard Worker 	terminate_lease(&lease);
747*d83cc019SAndroid Build Coastguard Worker }
748*d83cc019SAndroid Build Coastguard Worker 
749*d83cc019SAndroid Build Coastguard Worker /* Test revocation of lease */
lease_revoke(data_t * data)750*d83cc019SAndroid Build Coastguard Worker static void lease_revoke(data_t *data)
751*d83cc019SAndroid Build Coastguard Worker {
752*d83cc019SAndroid Build Coastguard Worker 	lease_t lease;
753*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_revoke_lease mrl;
754*d83cc019SAndroid Build Coastguard Worker 	int ret;
755*d83cc019SAndroid Build Coastguard Worker 
756*d83cc019SAndroid Build Coastguard Worker 	/* Create a valid lease */
757*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(make_lease(data, &lease), 0);
758*d83cc019SAndroid Build Coastguard Worker 
759*d83cc019SAndroid Build Coastguard Worker 	igt_display_require(&lease.display, lease.fd);
760*d83cc019SAndroid Build Coastguard Worker 
761*d83cc019SAndroid Build Coastguard Worker 	/* try to revoke an invalid lease */
762*d83cc019SAndroid Build Coastguard Worker 	mrl.lessee_id = 0;
763*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(revoke_lease(data->master.fd, &mrl), -ENOENT);
764*d83cc019SAndroid Build Coastguard Worker 
765*d83cc019SAndroid Build Coastguard Worker 	/* try to revoke with the wrong fd */
766*d83cc019SAndroid Build Coastguard Worker 	mrl.lessee_id = lease.lessee_id;
767*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(revoke_lease(lease.fd, &mrl), -EACCES);
768*d83cc019SAndroid Build Coastguard Worker 
769*d83cc019SAndroid Build Coastguard Worker 	/* Revoke the lease using the master fd */
770*d83cc019SAndroid Build Coastguard Worker 	mrl.lessee_id = lease.lessee_id;
771*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(revoke_lease(data->master.fd, &mrl), 0);
772*d83cc019SAndroid Build Coastguard Worker 
773*d83cc019SAndroid Build Coastguard Worker 	/* Try to use the leased objects */
774*d83cc019SAndroid Build Coastguard Worker 	ret = prepare_crtc(&lease, data->connector_id, data->crtc_id);
775*d83cc019SAndroid Build Coastguard Worker 
776*d83cc019SAndroid Build Coastguard Worker 	/* Ensure that the expected error is returned */
777*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(ret, -ENOENT);
778*d83cc019SAndroid Build Coastguard Worker 
779*d83cc019SAndroid Build Coastguard Worker 	terminate_lease(&lease);
780*d83cc019SAndroid Build Coastguard Worker 
781*d83cc019SAndroid Build Coastguard Worker 	/* make sure the lease is gone */
782*d83cc019SAndroid Build Coastguard Worker 	mrl.lessee_id = lease.lessee_id;
783*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(revoke_lease(data->master.fd, &mrl), -ENOENT);
784*d83cc019SAndroid Build Coastguard Worker }
785*d83cc019SAndroid Build Coastguard Worker 
786*d83cc019SAndroid Build Coastguard Worker /* Test leasing objects more than once */
lease_again(data_t * data)787*d83cc019SAndroid Build Coastguard Worker static void lease_again(data_t *data)
788*d83cc019SAndroid Build Coastguard Worker {
789*d83cc019SAndroid Build Coastguard Worker 	lease_t lease_a, lease_b;
790*d83cc019SAndroid Build Coastguard Worker 
791*d83cc019SAndroid Build Coastguard Worker 	/* Create a valid lease */
792*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(make_lease(data, &lease_a), 0);
793*d83cc019SAndroid Build Coastguard Worker 
794*d83cc019SAndroid Build Coastguard Worker 	/* Attempt to re-lease the same objects */
795*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(make_lease(data, &lease_b), -EBUSY);
796*d83cc019SAndroid Build Coastguard Worker 
797*d83cc019SAndroid Build Coastguard Worker 	terminate_lease(&lease_a);
798*d83cc019SAndroid Build Coastguard Worker 
799*d83cc019SAndroid Build Coastguard Worker 	/* Now attempt to lease the same objects */
800*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(make_lease(data, &lease_b), 0);
801*d83cc019SAndroid Build Coastguard Worker 
802*d83cc019SAndroid Build Coastguard Worker 	terminate_lease(&lease_b);
803*d83cc019SAndroid Build Coastguard Worker }
804*d83cc019SAndroid Build Coastguard Worker 
805*d83cc019SAndroid Build Coastguard Worker #define assert_unleased(ret) \
806*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f((ret) == -EINVAL || (ret) == -ENOENT, \
807*d83cc019SAndroid Build Coastguard Worker 		     "wrong return code %i, %s\n", ret, \
808*d83cc019SAndroid Build Coastguard Worker 		     strerror(ret))
809*d83cc019SAndroid Build Coastguard Worker /* Test leasing an invalid connector */
lease_invalid_connector(data_t * data)810*d83cc019SAndroid Build Coastguard Worker static void lease_invalid_connector(data_t *data)
811*d83cc019SAndroid Build Coastguard Worker {
812*d83cc019SAndroid Build Coastguard Worker 	lease_t lease;
813*d83cc019SAndroid Build Coastguard Worker 	uint32_t save_connector_id;
814*d83cc019SAndroid Build Coastguard Worker 	int ret;
815*d83cc019SAndroid Build Coastguard Worker 
816*d83cc019SAndroid Build Coastguard Worker 	/* Create an invalid lease */
817*d83cc019SAndroid Build Coastguard Worker 	save_connector_id = data->connector_id;
818*d83cc019SAndroid Build Coastguard Worker 	data->connector_id = 0xbaadf00d;
819*d83cc019SAndroid Build Coastguard Worker 	ret = make_lease(data, &lease);
820*d83cc019SAndroid Build Coastguard Worker 	data->connector_id = save_connector_id;
821*d83cc019SAndroid Build Coastguard Worker 	assert_unleased(ret);
822*d83cc019SAndroid Build Coastguard Worker }
823*d83cc019SAndroid Build Coastguard Worker 
824*d83cc019SAndroid Build Coastguard Worker /* Test leasing an invalid crtc */
lease_invalid_crtc(data_t * data)825*d83cc019SAndroid Build Coastguard Worker static void lease_invalid_crtc(data_t *data)
826*d83cc019SAndroid Build Coastguard Worker {
827*d83cc019SAndroid Build Coastguard Worker 	lease_t lease;
828*d83cc019SAndroid Build Coastguard Worker 	uint32_t save_crtc_id;
829*d83cc019SAndroid Build Coastguard Worker 	int ret;
830*d83cc019SAndroid Build Coastguard Worker 
831*d83cc019SAndroid Build Coastguard Worker 	/* Create an invalid lease */
832*d83cc019SAndroid Build Coastguard Worker 	save_crtc_id = data->crtc_id;
833*d83cc019SAndroid Build Coastguard Worker 	data->crtc_id = 0xbaadf00d;
834*d83cc019SAndroid Build Coastguard Worker 	ret = make_lease(data, &lease);
835*d83cc019SAndroid Build Coastguard Worker 	data->crtc_id = save_crtc_id;
836*d83cc019SAndroid Build Coastguard Worker 	assert_unleased(ret);
837*d83cc019SAndroid Build Coastguard Worker }
838*d83cc019SAndroid Build Coastguard Worker 
lease_invalid_plane(data_t * data)839*d83cc019SAndroid Build Coastguard Worker static void lease_invalid_plane(data_t *data)
840*d83cc019SAndroid Build Coastguard Worker {
841*d83cc019SAndroid Build Coastguard Worker 	lease_t lease;
842*d83cc019SAndroid Build Coastguard Worker 	uint32_t save_plane_id;
843*d83cc019SAndroid Build Coastguard Worker 	int ret;
844*d83cc019SAndroid Build Coastguard Worker 
845*d83cc019SAndroid Build Coastguard Worker 	/* Create an invalid lease */
846*d83cc019SAndroid Build Coastguard Worker 	save_plane_id = data->plane_id;
847*d83cc019SAndroid Build Coastguard Worker 	data->plane_id = 0xbaadf00d;
848*d83cc019SAndroid Build Coastguard Worker 	ret = make_lease(data, &lease);
849*d83cc019SAndroid Build Coastguard Worker 	data->plane_id = save_plane_id;
850*d83cc019SAndroid Build Coastguard Worker 	assert_unleased(ret);
851*d83cc019SAndroid Build Coastguard Worker }
852*d83cc019SAndroid Build Coastguard Worker 
853*d83cc019SAndroid Build Coastguard Worker 
run_test(data_t * data,void (* testfunc)(data_t *))854*d83cc019SAndroid Build Coastguard Worker static void run_test(data_t *data, void (*testfunc)(data_t *))
855*d83cc019SAndroid Build Coastguard Worker {
856*d83cc019SAndroid Build Coastguard Worker 	lease_t *master = &data->master;
857*d83cc019SAndroid Build Coastguard Worker 	igt_display_t *display = &master->display;
858*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *output;
859*d83cc019SAndroid Build Coastguard Worker 	enum pipe p;
860*d83cc019SAndroid Build Coastguard Worker 	unsigned int valid_tests = 0;
861*d83cc019SAndroid Build Coastguard Worker 
862*d83cc019SAndroid Build Coastguard Worker 	for_each_pipe_with_valid_output(display, p, output) {
863*d83cc019SAndroid Build Coastguard Worker 		igt_info("Beginning %s on pipe %s, connector %s\n",
864*d83cc019SAndroid Build Coastguard Worker 			 igt_subtest_name(),
865*d83cc019SAndroid Build Coastguard Worker 			 kmstest_pipe_name(p),
866*d83cc019SAndroid Build Coastguard Worker 			 igt_output_name(output));
867*d83cc019SAndroid Build Coastguard Worker 
868*d83cc019SAndroid Build Coastguard Worker 		data->pipe = p;
869*d83cc019SAndroid Build Coastguard Worker 		data->crtc_id = pipe_to_crtc_id(display, p);
870*d83cc019SAndroid Build Coastguard Worker 		data->connector_id = output->id;
871*d83cc019SAndroid Build Coastguard Worker 		data->plane_id =
872*d83cc019SAndroid Build Coastguard Worker 			igt_pipe_get_plane_type(&data->master.display.pipes[data->pipe],
873*d83cc019SAndroid Build Coastguard Worker 						DRM_PLANE_TYPE_PRIMARY)->drm_plane->plane_id;
874*d83cc019SAndroid Build Coastguard Worker 
875*d83cc019SAndroid Build Coastguard Worker 		testfunc(data);
876*d83cc019SAndroid Build Coastguard Worker 
877*d83cc019SAndroid Build Coastguard Worker 		igt_info("\n%s on pipe %s, connector %s: PASSED\n\n",
878*d83cc019SAndroid Build Coastguard Worker 			 igt_subtest_name(),
879*d83cc019SAndroid Build Coastguard Worker 			 kmstest_pipe_name(p),
880*d83cc019SAndroid Build Coastguard Worker 			 igt_output_name(output));
881*d83cc019SAndroid Build Coastguard Worker 
882*d83cc019SAndroid Build Coastguard Worker 		valid_tests++;
883*d83cc019SAndroid Build Coastguard Worker 	}
884*d83cc019SAndroid Build Coastguard Worker 
885*d83cc019SAndroid Build Coastguard Worker 	igt_require_f(valid_tests,
886*d83cc019SAndroid Build Coastguard Worker 		      "no valid crtc/connector combinations found\n");
887*d83cc019SAndroid Build Coastguard Worker }
888*d83cc019SAndroid Build Coastguard Worker 
889*d83cc019SAndroid Build Coastguard Worker #define assert_double_id_err(ret) \
890*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f((ret) == -EBUSY || (ret) == -ENOSPC, \
891*d83cc019SAndroid Build Coastguard Worker 		     "wrong return code %i, %s\n", ret, \
892*d83cc019SAndroid Build Coastguard Worker 		     strerror(ret))
invalid_create_leases(data_t * data)893*d83cc019SAndroid Build Coastguard Worker static void invalid_create_leases(data_t *data)
894*d83cc019SAndroid Build Coastguard Worker {
895*d83cc019SAndroid Build Coastguard Worker 	uint32_t object_ids[4];
896*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_create_lease mcl;
897*d83cc019SAndroid Build Coastguard Worker 	drmModeRes *resources;
898*d83cc019SAndroid Build Coastguard Worker 	int tmp_fd, ret;
899*d83cc019SAndroid Build Coastguard Worker 
900*d83cc019SAndroid Build Coastguard Worker 	/* empty lease */
901*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = 0;
902*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 0;
903*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
904*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), -EINVAL);
905*d83cc019SAndroid Build Coastguard Worker 
906*d83cc019SAndroid Build Coastguard Worker 	/* NULL array pointer */
907*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 1;
908*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), -EFAULT);
909*d83cc019SAndroid Build Coastguard Worker 
910*d83cc019SAndroid Build Coastguard Worker 	/* nil object */
911*d83cc019SAndroid Build Coastguard Worker 	object_ids[0] = 0;
912*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = (uint64_t) (uintptr_t) object_ids;
913*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 1;
914*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), -ENOENT);
915*d83cc019SAndroid Build Coastguard Worker 
916*d83cc019SAndroid Build Coastguard Worker 	/* no crtc, non-universal_plane */
917*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 0);
918*d83cc019SAndroid Build Coastguard Worker 	object_ids[0] = data->master.display.outputs[0].id;
919*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), -EINVAL);
920*d83cc019SAndroid Build Coastguard Worker 
921*d83cc019SAndroid Build Coastguard Worker 	/* no connector, non-universal_plane */
922*d83cc019SAndroid Build Coastguard Worker 	object_ids[0] = data->master.display.pipes[0].crtc_id;
923*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), -EINVAL);
924*d83cc019SAndroid Build Coastguard Worker 
925*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
926*d83cc019SAndroid Build Coastguard Worker 	object_ids[0] = data->master.display.pipes[0].crtc_id;
927*d83cc019SAndroid Build Coastguard Worker 	object_ids[1] = data->master.display.outputs[0].id;
928*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 2;
929*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), 0);
930*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
931*d83cc019SAndroid Build Coastguard Worker 
932*d83cc019SAndroid Build Coastguard Worker 	/* no plane, universal planes */
933*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
934*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), -EINVAL);
935*d83cc019SAndroid Build Coastguard Worker 
936*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
937*d83cc019SAndroid Build Coastguard Worker 	object_ids[2] = igt_pipe_get_plane_type(&data->master.display.pipes[0],
938*d83cc019SAndroid Build Coastguard Worker 						DRM_PLANE_TYPE_PRIMARY)->drm_plane->plane_id;
939*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 3;
940*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), 0);
941*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
942*d83cc019SAndroid Build Coastguard Worker 
943*d83cc019SAndroid Build Coastguard Worker 	/* array overflow, do a small scan around overflow sizes */
944*d83cc019SAndroid Build Coastguard Worker 	for (int i = 1; i <= 4; i++) {
945*d83cc019SAndroid Build Coastguard Worker 		mcl.object_count = UINT32_MAX / sizeof(object_ids[0]) + i;
946*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(create_lease(data->master.fd, &mcl), -ENOMEM);
947*d83cc019SAndroid Build Coastguard Worker 	}
948*d83cc019SAndroid Build Coastguard Worker 
949*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
950*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 3;
951*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = O_CLOEXEC | O_NONBLOCK;
952*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), 0);
953*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
954*d83cc019SAndroid Build Coastguard Worker 
955*d83cc019SAndroid Build Coastguard Worker 	/* invalid flags */
956*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = -1;
957*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), -EINVAL);
958*d83cc019SAndroid Build Coastguard Worker 
959*d83cc019SAndroid Build Coastguard Worker 	/* no subleasing */
960*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 3;
961*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
962*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), 0);
963*d83cc019SAndroid Build Coastguard Worker 	tmp_fd = mcl.fd;
964*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(tmp_fd, &mcl), -EINVAL);
965*d83cc019SAndroid Build Coastguard Worker 	close(tmp_fd);
966*d83cc019SAndroid Build Coastguard Worker 
967*d83cc019SAndroid Build Coastguard Worker 	/* no double-leasing */
968*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), 0);
969*d83cc019SAndroid Build Coastguard Worker 	tmp_fd = mcl.fd;
970*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), -EBUSY);
971*d83cc019SAndroid Build Coastguard Worker 	close(tmp_fd);
972*d83cc019SAndroid Build Coastguard Worker 
973*d83cc019SAndroid Build Coastguard Worker 	/* no double leasing */
974*d83cc019SAndroid Build Coastguard Worker 	object_ids[3] = object_ids[2];
975*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 4;
976*d83cc019SAndroid Build Coastguard Worker 	/* Note: the ENOSPC is from idr double-insertion failing */
977*d83cc019SAndroid Build Coastguard Worker 	ret = create_lease(data->master.fd, &mcl);
978*d83cc019SAndroid Build Coastguard Worker 	assert_double_id_err(ret);
979*d83cc019SAndroid Build Coastguard Worker 
980*d83cc019SAndroid Build Coastguard Worker 	/* no encoder leasing */
981*d83cc019SAndroid Build Coastguard Worker 	resources = drmModeGetResources(data->master.fd);
982*d83cc019SAndroid Build Coastguard Worker 	igt_assert(resources);
983*d83cc019SAndroid Build Coastguard Worker 	igt_assert(resources->count_encoders > 0);
984*d83cc019SAndroid Build Coastguard Worker 	object_ids[3] = resources->encoders[0];
985*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), -EINVAL);
986*d83cc019SAndroid Build Coastguard Worker 	drmModeFreeResources(resources);
987*d83cc019SAndroid Build Coastguard Worker }
988*d83cc019SAndroid Build Coastguard Worker 
check_crtc_masks(int master_fd,int lease_fd,uint32_t crtc_mask)989*d83cc019SAndroid Build Coastguard Worker static void check_crtc_masks(int master_fd, int lease_fd, uint32_t crtc_mask)
990*d83cc019SAndroid Build Coastguard Worker {
991*d83cc019SAndroid Build Coastguard Worker 	drmModeRes *resources;
992*d83cc019SAndroid Build Coastguard Worker 	drmModePlaneRes *plane_resources;
993*d83cc019SAndroid Build Coastguard Worker 	int i;
994*d83cc019SAndroid Build Coastguard Worker 
995*d83cc019SAndroid Build Coastguard Worker 	resources = drmModeGetResources(master_fd);
996*d83cc019SAndroid Build Coastguard Worker 	igt_assert(resources);
997*d83cc019SAndroid Build Coastguard Worker 	plane_resources = drmModeGetPlaneResources(master_fd);
998*d83cc019SAndroid Build Coastguard Worker 	igt_assert(plane_resources);
999*d83cc019SAndroid Build Coastguard Worker 
1000*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < resources->count_encoders; i++) {
1001*d83cc019SAndroid Build Coastguard Worker 		drmModeEncoder *master_e, *lease_e;
1002*d83cc019SAndroid Build Coastguard Worker 		bool possible;
1003*d83cc019SAndroid Build Coastguard Worker 
1004*d83cc019SAndroid Build Coastguard Worker 		master_e = drmModeGetEncoder(master_fd, resources->encoders[i]);
1005*d83cc019SAndroid Build Coastguard Worker 		igt_assert(master_e);
1006*d83cc019SAndroid Build Coastguard Worker 		lease_e = drmModeGetEncoder(lease_fd, resources->encoders[i]);
1007*d83cc019SAndroid Build Coastguard Worker 		igt_assert(lease_e);
1008*d83cc019SAndroid Build Coastguard Worker 
1009*d83cc019SAndroid Build Coastguard Worker 		possible = master_e->possible_crtcs & crtc_mask;
1010*d83cc019SAndroid Build Coastguard Worker 
1011*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(lease_e->possible_crtcs,
1012*d83cc019SAndroid Build Coastguard Worker 			      possible ? 1 : 0);
1013*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(master_e->possible_crtcs & crtc_mask,
1014*d83cc019SAndroid Build Coastguard Worker 			      possible ? crtc_mask : 0);
1015*d83cc019SAndroid Build Coastguard Worker 		drmModeFreeEncoder(master_e);
1016*d83cc019SAndroid Build Coastguard Worker 		drmModeFreeEncoder(lease_e);
1017*d83cc019SAndroid Build Coastguard Worker 	}
1018*d83cc019SAndroid Build Coastguard Worker 
1019*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < plane_resources->count_planes; i++) {
1020*d83cc019SAndroid Build Coastguard Worker 		drmModePlane *master_p, *lease_p;
1021*d83cc019SAndroid Build Coastguard Worker 		bool possible;
1022*d83cc019SAndroid Build Coastguard Worker 
1023*d83cc019SAndroid Build Coastguard Worker 		master_p = drmModeGetPlane(master_fd, plane_resources->planes[i]);
1024*d83cc019SAndroid Build Coastguard Worker 		igt_assert(master_p);
1025*d83cc019SAndroid Build Coastguard Worker 		lease_p = drmModeGetPlane(lease_fd, plane_resources->planes[i]);
1026*d83cc019SAndroid Build Coastguard Worker 		igt_assert(lease_p);
1027*d83cc019SAndroid Build Coastguard Worker 
1028*d83cc019SAndroid Build Coastguard Worker 		possible = master_p->possible_crtcs & crtc_mask;
1029*d83cc019SAndroid Build Coastguard Worker 
1030*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(lease_p->possible_crtcs,
1031*d83cc019SAndroid Build Coastguard Worker 			      possible ? 1 : 0);
1032*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(master_p->possible_crtcs & crtc_mask,
1033*d83cc019SAndroid Build Coastguard Worker 			      possible ? crtc_mask : 0);
1034*d83cc019SAndroid Build Coastguard Worker 		drmModeFreePlane(master_p);
1035*d83cc019SAndroid Build Coastguard Worker 		drmModeFreePlane(lease_p);
1036*d83cc019SAndroid Build Coastguard Worker 	}
1037*d83cc019SAndroid Build Coastguard Worker 
1038*d83cc019SAndroid Build Coastguard Worker 	drmModeFreePlaneResources(plane_resources);
1039*d83cc019SAndroid Build Coastguard Worker 	drmModeFreeResources(resources);
1040*d83cc019SAndroid Build Coastguard Worker }
1041*d83cc019SAndroid Build Coastguard Worker 
possible_crtcs_filtering(data_t * data)1042*d83cc019SAndroid Build Coastguard Worker static void possible_crtcs_filtering(data_t *data)
1043*d83cc019SAndroid Build Coastguard Worker {
1044*d83cc019SAndroid Build Coastguard Worker 	uint32_t *object_ids;
1045*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_create_lease mcl;
1046*d83cc019SAndroid Build Coastguard Worker 	drmModeRes *resources;
1047*d83cc019SAndroid Build Coastguard Worker 	drmModePlaneRes *plane_resources;
1048*d83cc019SAndroid Build Coastguard Worker 	int i;
1049*d83cc019SAndroid Build Coastguard Worker 	int master_fd = data->master.fd;
1050*d83cc019SAndroid Build Coastguard Worker 
1051*d83cc019SAndroid Build Coastguard Worker 	resources = drmModeGetResources(master_fd);
1052*d83cc019SAndroid Build Coastguard Worker 	igt_assert(resources);
1053*d83cc019SAndroid Build Coastguard Worker 	plane_resources = drmModeGetPlaneResources(master_fd);
1054*d83cc019SAndroid Build Coastguard Worker 	igt_assert(plane_resources);
1055*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = resources->count_connectors +
1056*d83cc019SAndroid Build Coastguard Worker 		plane_resources->count_planes + 1;
1057*d83cc019SAndroid Build Coastguard Worker 	object_ids = calloc(mcl.object_count, sizeof(*object_ids));
1058*d83cc019SAndroid Build Coastguard Worker 	igt_assert(object_ids);
1059*d83cc019SAndroid Build Coastguard Worker 
1060*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < resources->count_connectors; i++)
1061*d83cc019SAndroid Build Coastguard Worker 		object_ids[i] = resources->connectors[i];
1062*d83cc019SAndroid Build Coastguard Worker 
1063*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < plane_resources->count_planes; i++)
1064*d83cc019SAndroid Build Coastguard Worker 		object_ids[i + resources->count_connectors] =
1065*d83cc019SAndroid Build Coastguard Worker 			plane_resources->planes[i];
1066*d83cc019SAndroid Build Coastguard Worker 
1067*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = (uint64_t) (uintptr_t) object_ids;
1068*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
1069*d83cc019SAndroid Build Coastguard Worker 
1070*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < resources->count_crtcs; i++) {
1071*d83cc019SAndroid Build Coastguard Worker 		int lease_fd;
1072*d83cc019SAndroid Build Coastguard Worker 
1073*d83cc019SAndroid Build Coastguard Worker 		object_ids[mcl.object_count - 1] =
1074*d83cc019SAndroid Build Coastguard Worker 			resources->crtcs[i];
1075*d83cc019SAndroid Build Coastguard Worker 
1076*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(create_lease(master_fd, &mcl), 0);
1077*d83cc019SAndroid Build Coastguard Worker 		lease_fd = mcl.fd;
1078*d83cc019SAndroid Build Coastguard Worker 
1079*d83cc019SAndroid Build Coastguard Worker 		drmSetClientCap(lease_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
1080*d83cc019SAndroid Build Coastguard Worker 
1081*d83cc019SAndroid Build Coastguard Worker 		check_crtc_masks(master_fd, lease_fd, 1 << i);
1082*d83cc019SAndroid Build Coastguard Worker 
1083*d83cc019SAndroid Build Coastguard Worker 		close(lease_fd);
1084*d83cc019SAndroid Build Coastguard Worker 	}
1085*d83cc019SAndroid Build Coastguard Worker 
1086*d83cc019SAndroid Build Coastguard Worker 	free(object_ids);
1087*d83cc019SAndroid Build Coastguard Worker 	drmModeFreePlaneResources(plane_resources);
1088*d83cc019SAndroid Build Coastguard Worker 	drmModeFreeResources(resources);
1089*d83cc019SAndroid Build Coastguard Worker }
1090*d83cc019SAndroid Build Coastguard Worker 
is_master(int fd)1091*d83cc019SAndroid Build Coastguard Worker static bool is_master(int fd)
1092*d83cc019SAndroid Build Coastguard Worker {
1093*d83cc019SAndroid Build Coastguard Worker 	/* FIXME: replace with drmIsMaster once we bumped libdrm version */
1094*d83cc019SAndroid Build Coastguard Worker 	return drmAuthMagic(fd, 0) != -EACCES;
1095*d83cc019SAndroid Build Coastguard Worker }
1096*d83cc019SAndroid Build Coastguard Worker 
_create_simple_lease(int master_fd,data_t * data,int expected_ret)1097*d83cc019SAndroid Build Coastguard Worker static int _create_simple_lease(int master_fd, data_t *data, int expected_ret)
1098*d83cc019SAndroid Build Coastguard Worker {
1099*d83cc019SAndroid Build Coastguard Worker 	uint32_t object_ids[3];
1100*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_create_lease mcl;
1101*d83cc019SAndroid Build Coastguard Worker 
1102*d83cc019SAndroid Build Coastguard Worker 	object_ids[0] = data->master.display.pipes[0].crtc_id;
1103*d83cc019SAndroid Build Coastguard Worker 	object_ids[1] = data->master.display.outputs[0].id;
1104*d83cc019SAndroid Build Coastguard Worker 	object_ids[2] = igt_pipe_get_plane_type(&data->master.display.pipes[0],
1105*d83cc019SAndroid Build Coastguard Worker 						DRM_PLANE_TYPE_PRIMARY)->drm_plane->plane_id;
1106*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = (uint64_t) (uintptr_t) object_ids;
1107*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 3;
1108*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
1109*d83cc019SAndroid Build Coastguard Worker 
1110*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(master_fd, &mcl), expected_ret);
1111*d83cc019SAndroid Build Coastguard Worker 
1112*d83cc019SAndroid Build Coastguard Worker 	return expected_ret == 0 ? mcl.fd : 0;
1113*d83cc019SAndroid Build Coastguard Worker }
1114*d83cc019SAndroid Build Coastguard Worker 
create_simple_lease(int master_fd,data_t * data)1115*d83cc019SAndroid Build Coastguard Worker static int create_simple_lease(int master_fd, data_t *data)
1116*d83cc019SAndroid Build Coastguard Worker {
1117*d83cc019SAndroid Build Coastguard Worker 	return _create_simple_lease(master_fd, data, 0);
1118*d83cc019SAndroid Build Coastguard Worker }
1119*d83cc019SAndroid Build Coastguard Worker 
1120*d83cc019SAndroid Build Coastguard Worker /* check lease master status in lockdep with lessors, but can't change it
1121*d83cc019SAndroid Build Coastguard Worker  * themselves */
master_vs_lease(data_t * data)1122*d83cc019SAndroid Build Coastguard Worker static void master_vs_lease(data_t *data)
1123*d83cc019SAndroid Build Coastguard Worker {
1124*d83cc019SAndroid Build Coastguard Worker 	int lease_fd;
1125*d83cc019SAndroid Build Coastguard Worker 
1126*d83cc019SAndroid Build Coastguard Worker 	lease_fd = create_simple_lease(data->master.fd, data);
1127*d83cc019SAndroid Build Coastguard Worker 
1128*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(drmDropMaster(lease_fd), -1);
1129*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(errno, EINVAL);
1130*d83cc019SAndroid Build Coastguard Worker 
1131*d83cc019SAndroid Build Coastguard Worker 	igt_assert(is_master(data->master.fd));
1132*d83cc019SAndroid Build Coastguard Worker 	igt_assert(is_master(lease_fd));
1133*d83cc019SAndroid Build Coastguard Worker 
1134*d83cc019SAndroid Build Coastguard Worker 	igt_device_drop_master(data->master.fd);
1135*d83cc019SAndroid Build Coastguard Worker 
1136*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!is_master(data->master.fd));
1137*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!is_master(lease_fd));
1138*d83cc019SAndroid Build Coastguard Worker 
1139*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(drmSetMaster(lease_fd), -1);
1140*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(errno, EINVAL);
1141*d83cc019SAndroid Build Coastguard Worker 
1142*d83cc019SAndroid Build Coastguard Worker 	igt_device_set_master(data->master.fd);
1143*d83cc019SAndroid Build Coastguard Worker 
1144*d83cc019SAndroid Build Coastguard Worker 	igt_assert(is_master(data->master.fd));
1145*d83cc019SAndroid Build Coastguard Worker 	igt_assert(is_master(lease_fd));
1146*d83cc019SAndroid Build Coastguard Worker 
1147*d83cc019SAndroid Build Coastguard Worker 	close(lease_fd);
1148*d83cc019SAndroid Build Coastguard Worker }
1149*d83cc019SAndroid Build Coastguard Worker 
multimaster_lease(data_t * data)1150*d83cc019SAndroid Build Coastguard Worker static void multimaster_lease(data_t *data)
1151*d83cc019SAndroid Build Coastguard Worker {
1152*d83cc019SAndroid Build Coastguard Worker 	int lease_fd, master2_fd, lease2_fd;
1153*d83cc019SAndroid Build Coastguard Worker 
1154*d83cc019SAndroid Build Coastguard Worker 	lease_fd = create_simple_lease(data->master.fd, data);
1155*d83cc019SAndroid Build Coastguard Worker 
1156*d83cc019SAndroid Build Coastguard Worker 	igt_assert(is_master(data->master.fd));
1157*d83cc019SAndroid Build Coastguard Worker 	igt_assert(is_master(lease_fd));
1158*d83cc019SAndroid Build Coastguard Worker 
1159*d83cc019SAndroid Build Coastguard Worker 	master2_fd = drm_open_driver(DRIVER_ANY);
1160*d83cc019SAndroid Build Coastguard Worker 
1161*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!is_master(master2_fd));
1162*d83cc019SAndroid Build Coastguard Worker 
1163*d83cc019SAndroid Build Coastguard Worker 	_create_simple_lease(master2_fd, data, -EACCES);
1164*d83cc019SAndroid Build Coastguard Worker 
1165*d83cc019SAndroid Build Coastguard Worker 	igt_device_drop_master(data->master.fd);
1166*d83cc019SAndroid Build Coastguard Worker 	igt_device_set_master(master2_fd);
1167*d83cc019SAndroid Build Coastguard Worker 
1168*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!is_master(data->master.fd));
1169*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!is_master(lease_fd));
1170*d83cc019SAndroid Build Coastguard Worker 	igt_assert(is_master(master2_fd));
1171*d83cc019SAndroid Build Coastguard Worker 
1172*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(master2_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
1173*d83cc019SAndroid Build Coastguard Worker 	lease2_fd = create_simple_lease(master2_fd, data);
1174*d83cc019SAndroid Build Coastguard Worker 
1175*d83cc019SAndroid Build Coastguard Worker 	close(master2_fd); /* close is an implicit DropMaster */
1176*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!is_master(lease2_fd));
1177*d83cc019SAndroid Build Coastguard Worker 
1178*d83cc019SAndroid Build Coastguard Worker 	igt_device_set_master(data->master.fd);
1179*d83cc019SAndroid Build Coastguard Worker 	igt_assert(is_master(data->master.fd));
1180*d83cc019SAndroid Build Coastguard Worker 	igt_assert(is_master(lease_fd));
1181*d83cc019SAndroid Build Coastguard Worker 
1182*d83cc019SAndroid Build Coastguard Worker 	close(lease2_fd);
1183*d83cc019SAndroid Build Coastguard Worker 	close(lease_fd);
1184*d83cc019SAndroid Build Coastguard Worker }
1185*d83cc019SAndroid Build Coastguard Worker 
implicit_plane_lease(data_t * data)1186*d83cc019SAndroid Build Coastguard Worker static void implicit_plane_lease(data_t *data)
1187*d83cc019SAndroid Build Coastguard Worker {
1188*d83cc019SAndroid Build Coastguard Worker 	uint32_t object_ids[3];
1189*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_create_lease mcl;
1190*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_get_lease mgl;
1191*d83cc019SAndroid Build Coastguard Worker 	int ret;
1192*d83cc019SAndroid Build Coastguard Worker 	uint32_t cursor_id = igt_pipe_get_plane_type(&data->master.display.pipes[0],
1193*d83cc019SAndroid Build Coastguard Worker 						     DRM_PLANE_TYPE_CURSOR)->drm_plane->plane_id;
1194*d83cc019SAndroid Build Coastguard Worker 
1195*d83cc019SAndroid Build Coastguard Worker 	object_ids[0] = data->master.display.pipes[0].crtc_id;
1196*d83cc019SAndroid Build Coastguard Worker 	object_ids[1] = data->master.display.outputs[0].id;
1197*d83cc019SAndroid Build Coastguard Worker 	object_ids[2] = igt_pipe_get_plane_type(&data->master.display.pipes[0],
1198*d83cc019SAndroid Build Coastguard Worker 						DRM_PLANE_TYPE_PRIMARY)->drm_plane->plane_id;
1199*d83cc019SAndroid Build Coastguard Worker 	mcl.object_ids = (uint64_t) (uintptr_t) object_ids;
1200*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 3;
1201*d83cc019SAndroid Build Coastguard Worker 	mcl.flags = 0;
1202*d83cc019SAndroid Build Coastguard Worker 
1203*d83cc019SAndroid Build Coastguard Worker 	/* sanity check */
1204*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), 0);
1205*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
1206*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 0);
1207*d83cc019SAndroid Build Coastguard Worker 
1208*d83cc019SAndroid Build Coastguard Worker 	/* non universal plane automatically adds primary/cursor plane */
1209*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 2;
1210*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(create_lease(data->master.fd, &mcl), 0);
1211*d83cc019SAndroid Build Coastguard Worker 
1212*d83cc019SAndroid Build Coastguard Worker 	mgl.pad = 0;
1213*d83cc019SAndroid Build Coastguard Worker 	mgl.count_objects = 0;
1214*d83cc019SAndroid Build Coastguard Worker 	mgl.objects_ptr = 0;
1215*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(get_lease(mcl.fd, &mgl), 0);
1216*d83cc019SAndroid Build Coastguard Worker 
1217*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mgl.count_objects, 3 + (cursor_id ? 1 : 0));
1218*d83cc019SAndroid Build Coastguard Worker 
1219*d83cc019SAndroid Build Coastguard Worker 	close(mcl.fd);
1220*d83cc019SAndroid Build Coastguard Worker 
1221*d83cc019SAndroid Build Coastguard Worker 	/* check that implicit lease doesn't lead to confusion when
1222*d83cc019SAndroid Build Coastguard Worker 	 * explicitly adding primary plane */
1223*d83cc019SAndroid Build Coastguard Worker 	mcl.object_count = 3;
1224*d83cc019SAndroid Build Coastguard Worker 	ret = create_lease(data->master.fd, &mcl);
1225*d83cc019SAndroid Build Coastguard Worker 	assert_double_id_err(ret);
1226*d83cc019SAndroid Build Coastguard Worker 
1227*d83cc019SAndroid Build Coastguard Worker 	/* same for the cursor */
1228*d83cc019SAndroid Build Coastguard Worker 	object_ids[2] = cursor_id;
1229*d83cc019SAndroid Build Coastguard Worker 	ret = create_lease(data->master.fd, &mcl);
1230*d83cc019SAndroid Build Coastguard Worker 	assert_double_id_err(ret);
1231*d83cc019SAndroid Build Coastguard Worker 
1232*d83cc019SAndroid Build Coastguard Worker 	drmSetClientCap(data->master.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
1233*d83cc019SAndroid Build Coastguard Worker }
1234*d83cc019SAndroid Build Coastguard Worker 
lease_uevent(data_t * data)1235*d83cc019SAndroid Build Coastguard Worker static void lease_uevent(data_t *data)
1236*d83cc019SAndroid Build Coastguard Worker {
1237*d83cc019SAndroid Build Coastguard Worker 	int lease_fd;
1238*d83cc019SAndroid Build Coastguard Worker 	struct local_drm_mode_list_lessees mll;
1239*d83cc019SAndroid Build Coastguard Worker 	struct udev_monitor *uevent_monitor;
1240*d83cc019SAndroid Build Coastguard Worker 
1241*d83cc019SAndroid Build Coastguard Worker 	uevent_monitor = igt_watch_hotplug();
1242*d83cc019SAndroid Build Coastguard Worker 
1243*d83cc019SAndroid Build Coastguard Worker 	igt_flush_hotplugs(uevent_monitor);
1244*d83cc019SAndroid Build Coastguard Worker 
1245*d83cc019SAndroid Build Coastguard Worker 	lease_fd = create_simple_lease(data->master.fd, data);
1246*d83cc019SAndroid Build Coastguard Worker 
1247*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!igt_lease_change_detected(uevent_monitor, 1));
1248*d83cc019SAndroid Build Coastguard Worker 
1249*d83cc019SAndroid Build Coastguard Worker 	mll.pad = 0;
1250*d83cc019SAndroid Build Coastguard Worker 	mll.count_lessees = 0;
1251*d83cc019SAndroid Build Coastguard Worker 	mll.lessees_ptr = 0;
1252*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(list_lessees(data->master.fd, &mll), 0);
1253*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mll.count_lessees, 1);
1254*d83cc019SAndroid Build Coastguard Worker 
1255*d83cc019SAndroid Build Coastguard Worker 	close(lease_fd);
1256*d83cc019SAndroid Build Coastguard Worker 
1257*d83cc019SAndroid Build Coastguard Worker 	igt_assert(igt_lease_change_detected(uevent_monitor, 1));
1258*d83cc019SAndroid Build Coastguard Worker 
1259*d83cc019SAndroid Build Coastguard Worker 	mll.lessees_ptr = 0;
1260*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(list_lessees(data->master.fd, &mll), 0);
1261*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(mll.count_lessees, 0);
1262*d83cc019SAndroid Build Coastguard Worker 
1263*d83cc019SAndroid Build Coastguard Worker 	igt_cleanup_hotplug(uevent_monitor);
1264*d83cc019SAndroid Build Coastguard Worker }
1265*d83cc019SAndroid Build Coastguard Worker 
1266*d83cc019SAndroid Build Coastguard Worker igt_main
1267*d83cc019SAndroid Build Coastguard Worker {
1268*d83cc019SAndroid Build Coastguard Worker 	data_t data;
1269*d83cc019SAndroid Build Coastguard Worker 	const struct {
1270*d83cc019SAndroid Build Coastguard Worker 		const char *name;
1271*d83cc019SAndroid Build Coastguard Worker 		void (*func)(data_t *);
1272*d83cc019SAndroid Build Coastguard Worker 	} funcs[] = {
1273*d83cc019SAndroid Build Coastguard Worker 		{ "simple_lease", simple_lease },
1274*d83cc019SAndroid Build Coastguard Worker 		{ "lessee_list", lessee_list },
1275*d83cc019SAndroid Build Coastguard Worker 		{ "lease_get", lease_get },
1276*d83cc019SAndroid Build Coastguard Worker 		{ "lease_unleased_connector", lease_unleased_connector },
1277*d83cc019SAndroid Build Coastguard Worker 		{ "lease_unleased_crtc", lease_unleased_crtc },
1278*d83cc019SAndroid Build Coastguard Worker 		{ "lease_revoke", lease_revoke },
1279*d83cc019SAndroid Build Coastguard Worker 		{ "lease_again", lease_again },
1280*d83cc019SAndroid Build Coastguard Worker 		{ "lease_invalid_connector", lease_invalid_connector },
1281*d83cc019SAndroid Build Coastguard Worker 		{ "lease_invalid_crtc", lease_invalid_crtc },
1282*d83cc019SAndroid Build Coastguard Worker 		{ "lease_invalid_plane", lease_invalid_plane },
1283*d83cc019SAndroid Build Coastguard Worker 		{ "page_flip_implicit_plane", page_flip_implicit_plane },
1284*d83cc019SAndroid Build Coastguard Worker 		{ "setcrtc_implicit_plane", setcrtc_implicit_plane },
1285*d83cc019SAndroid Build Coastguard Worker 		{ "cursor_implicit_plane", cursor_implicit_plane },
1286*d83cc019SAndroid Build Coastguard Worker 		{ "atomic_implicit_crtc", atomic_implicit_crtc },
1287*d83cc019SAndroid Build Coastguard Worker 		{ }
1288*d83cc019SAndroid Build Coastguard Worker 	}, *f;
1289*d83cc019SAndroid Build Coastguard Worker 
1290*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
1291*d83cc019SAndroid Build Coastguard Worker 		data.master.fd = drm_open_driver_master(DRIVER_ANY);
1292*d83cc019SAndroid Build Coastguard Worker 		kmstest_set_vt_graphics_mode();
1293*d83cc019SAndroid Build Coastguard Worker 		igt_display_require(&data.master.display, data.master.fd);
1294*d83cc019SAndroid Build Coastguard Worker 	}
1295*d83cc019SAndroid Build Coastguard Worker 
1296*d83cc019SAndroid Build Coastguard Worker 	for (f = funcs; f->name; f++) {
1297*d83cc019SAndroid Build Coastguard Worker 
1298*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("%s", f->name) {
1299*d83cc019SAndroid Build Coastguard Worker 			run_test(&data, f->func);
1300*d83cc019SAndroid Build Coastguard Worker 		}
1301*d83cc019SAndroid Build Coastguard Worker 	}
1302*d83cc019SAndroid Build Coastguard Worker 
1303*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("invalid-create-leases")
1304*d83cc019SAndroid Build Coastguard Worker 		invalid_create_leases(&data);
1305*d83cc019SAndroid Build Coastguard Worker 
1306*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("possible-crtcs-filtering")
1307*d83cc019SAndroid Build Coastguard Worker 		possible_crtcs_filtering(&data);
1308*d83cc019SAndroid Build Coastguard Worker 
1309*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("master-vs-lease")
1310*d83cc019SAndroid Build Coastguard Worker 		master_vs_lease(&data);
1311*d83cc019SAndroid Build Coastguard Worker 
1312*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("multimaster-lease")
1313*d83cc019SAndroid Build Coastguard Worker 		multimaster_lease(&data);
1314*d83cc019SAndroid Build Coastguard Worker 
1315*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("implicit-plane-lease")
1316*d83cc019SAndroid Build Coastguard Worker 		implicit_plane_lease(&data);
1317*d83cc019SAndroid Build Coastguard Worker 
1318*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("lease-uevent")
1319*d83cc019SAndroid Build Coastguard Worker 		lease_uevent(&data);
1320*d83cc019SAndroid Build Coastguard Worker }
1321