xref: /openbmc/linux/drivers/gpu/drm/drm_lease.c (revision f519f0be)
1 /*
2  * Copyright © 2017 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  */
14 #include <linux/file.h>
15 #include <linux/uaccess.h>
16 
17 #include <drm/drm_auth.h>
18 #include <drm/drm_crtc_helper.h>
19 #include <drm/drm_drv.h>
20 #include <drm/drm_file.h>
21 #include <drm/drm_lease.h>
22 #include <drm/drm_print.h>
23 
24 #include "drm_crtc_internal.h"
25 #include "drm_internal.h"
26 #include "drm_legacy.h"
27 
28 #define drm_for_each_lessee(lessee, lessor) \
29 	list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
30 
31 static uint64_t drm_lease_idr_object;
32 
33 /**
34  * drm_lease_owner - return ancestor owner drm_master
35  * @master: drm_master somewhere within tree of lessees and lessors
36  *
37  * RETURN:
38  *
39  * drm_master at the top of the tree (i.e, with lessor NULL
40  */
41 struct drm_master *drm_lease_owner(struct drm_master *master)
42 {
43 	while (master->lessor != NULL)
44 		master = master->lessor;
45 	return master;
46 }
47 
48 /**
49  * _drm_find_lessee - find lessee by id (idr_mutex held)
50  * @master: drm_master of lessor
51  * @lessee_id: id
52  *
53  * RETURN:
54  *
55  * drm_master of the lessee if valid, NULL otherwise
56  */
57 
58 static struct drm_master*
59 _drm_find_lessee(struct drm_master *master, int lessee_id)
60 {
61 	lockdep_assert_held(&master->dev->mode_config.idr_mutex);
62 	return idr_find(&drm_lease_owner(master)->lessee_idr, lessee_id);
63 }
64 
65 /**
66  * _drm_lease_held_master - check to see if an object is leased (or owned) by master (idr_mutex held)
67  * @master: the master to check the lease status of
68  * @id: the id to check
69  *
70  * Checks if the specified master holds a lease on the object. Return
71  * value:
72  *
73  *	true		'master' holds a lease on (or owns) the object
74  *	false		'master' does not hold a lease.
75  */
76 static int _drm_lease_held_master(struct drm_master *master, int id)
77 {
78 	lockdep_assert_held(&master->dev->mode_config.idr_mutex);
79 	if (master->lessor)
80 		return idr_find(&master->leases, id) != NULL;
81 	return true;
82 }
83 
84 /**
85  * _drm_has_leased - check to see if an object has been leased (idr_mutex held)
86  * @master: the master to check the lease status of
87  * @id: the id to check
88  *
89  * Checks if any lessee of 'master' holds a lease on 'id'. Return
90  * value:
91  *
92  *	true		Some lessee holds a lease on the object.
93  *	false		No lessee has a lease on the object.
94  */
95 static bool _drm_has_leased(struct drm_master *master, int id)
96 {
97 	struct drm_master *lessee;
98 
99 	lockdep_assert_held(&master->dev->mode_config.idr_mutex);
100 	drm_for_each_lessee(lessee, master)
101 		if (_drm_lease_held_master(lessee, id))
102 			return true;
103 	return false;
104 }
105 
106 /**
107  * _drm_lease_held - check drm_mode_object lease status (idr_mutex held)
108  * @file_priv: the master drm_file
109  * @id: the object id
110  *
111  * Checks if the specified master holds a lease on the object. Return
112  * value:
113  *
114  *	true		'master' holds a lease on (or owns) the object
115  *	false		'master' does not hold a lease.
116  */
117 bool _drm_lease_held(struct drm_file *file_priv, int id)
118 {
119 	if (!file_priv || !file_priv->master)
120 		return true;
121 
122 	return _drm_lease_held_master(file_priv->master, id);
123 }
124 
125 /**
126  * drm_lease_held - check drm_mode_object lease status (idr_mutex not held)
127  * @file_priv: the master drm_file
128  * @id: the object id
129  *
130  * Checks if the specified master holds a lease on the object. Return
131  * value:
132  *
133  *	true		'master' holds a lease on (or owns) the object
134  *	false		'master' does not hold a lease.
135  */
136 bool drm_lease_held(struct drm_file *file_priv, int id)
137 {
138 	struct drm_master *master;
139 	bool ret;
140 
141 	if (!file_priv || !file_priv->master || !file_priv->master->lessor)
142 		return true;
143 
144 	master = file_priv->master;
145 	mutex_lock(&master->dev->mode_config.idr_mutex);
146 	ret = _drm_lease_held_master(master, id);
147 	mutex_unlock(&master->dev->mode_config.idr_mutex);
148 	return ret;
149 }
150 
151 /**
152  * drm_lease_filter_crtcs - restricted crtc set to leased values (idr_mutex not held)
153  * @file_priv: requestor file
154  * @crtcs_in: bitmask of crtcs to check
155  *
156  * Reconstructs a crtc mask based on the crtcs which are visible
157  * through the specified file.
158  */
159 uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in)
160 {
161 	struct drm_master *master;
162 	struct drm_device *dev;
163 	struct drm_crtc *crtc;
164 	int count_in, count_out;
165 	uint32_t crtcs_out = 0;
166 
167 	if (!file_priv || !file_priv->master || !file_priv->master->lessor)
168 		return crtcs_in;
169 
170 	master = file_priv->master;
171 	dev = master->dev;
172 
173 	count_in = count_out = 0;
174 	mutex_lock(&master->dev->mode_config.idr_mutex);
175 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
176 		if (_drm_lease_held_master(master, crtc->base.id)) {
177 			uint32_t mask_in = 1ul << count_in;
178 			if ((crtcs_in & mask_in) != 0) {
179 				uint32_t mask_out = 1ul << count_out;
180 				crtcs_out |= mask_out;
181 			}
182 			count_out++;
183 		}
184 		count_in++;
185 	}
186 	mutex_unlock(&master->dev->mode_config.idr_mutex);
187 	return crtcs_out;
188 }
189 
190 /*
191  * drm_lease_create - create a new drm_master with leased objects (idr_mutex not held)
192  * @lessor: lease holder (or owner) of objects
193  * @leases: objects to lease to the new drm_master
194  *
195  * Uses drm_master_create to allocate a new drm_master, then checks to
196  * make sure all of the desired objects can be leased, atomically
197  * leasing them to the new drmmaster.
198  *
199  * 	ERR_PTR(-EACCES)	some other master holds the title to any object
200  * 	ERR_PTR(-ENOENT)	some object is not a valid DRM object for this device
201  * 	ERR_PTR(-EBUSY)		some other lessee holds title to this object
202  *	ERR_PTR(-EEXIST)	same object specified more than once in the provided list
203  *	ERR_PTR(-ENOMEM)	allocation failed
204  */
205 static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr *leases)
206 {
207 	struct drm_device *dev = lessor->dev;
208 	int error;
209 	struct drm_master *lessee;
210 	int object;
211 	int id;
212 	void *entry;
213 
214 	DRM_DEBUG_LEASE("lessor %d\n", lessor->lessee_id);
215 
216 	lessee = drm_master_create(lessor->dev);
217 	if (!lessee) {
218 		DRM_DEBUG_LEASE("drm_master_create failed\n");
219 		return ERR_PTR(-ENOMEM);
220 	}
221 
222 	mutex_lock(&dev->mode_config.idr_mutex);
223 
224 	idr_for_each_entry(leases, entry, object) {
225 		error = 0;
226 		if (!idr_find(&dev->mode_config.object_idr, object))
227 			error = -ENOENT;
228 		else if (_drm_has_leased(lessor, object))
229 			error = -EBUSY;
230 
231 		if (error != 0) {
232 			DRM_DEBUG_LEASE("object %d failed %d\n", object, error);
233 			goto out_lessee;
234 		}
235 	}
236 
237 	/* Insert the new lessee into the tree */
238 	id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL);
239 	if (id < 0) {
240 		error = id;
241 		goto out_lessee;
242 	}
243 
244 	lessee->lessee_id = id;
245 	lessee->lessor = drm_master_get(lessor);
246 	list_add_tail(&lessee->lessee_list, &lessor->lessees);
247 
248 	/* Move the leases over */
249 	lessee->leases = *leases;
250 	DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor);
251 
252 	mutex_unlock(&dev->mode_config.idr_mutex);
253 	return lessee;
254 
255 out_lessee:
256 	mutex_unlock(&dev->mode_config.idr_mutex);
257 
258 	drm_master_put(&lessee);
259 
260 	return ERR_PTR(error);
261 }
262 
263 /**
264  * drm_lease_destroy - a master is going away (idr_mutex not held)
265  * @master: the drm_master being destroyed
266  *
267  * All lessees will have been destroyed as they
268  * hold a reference on their lessor. Notify any
269  * lessor for this master so that it can check
270  * the list of lessees.
271  */
272 void drm_lease_destroy(struct drm_master *master)
273 {
274 	struct drm_device *dev = master->dev;
275 
276 	mutex_lock(&dev->mode_config.idr_mutex);
277 
278 	DRM_DEBUG_LEASE("drm_lease_destroy %d\n", master->lessee_id);
279 
280 	/* This master is referenced by all lessees, hence it cannot be destroyed
281 	 * until all of them have been
282 	 */
283 	WARN_ON(!list_empty(&master->lessees));
284 
285 	/* Remove this master from the lessee idr in the owner */
286 	if (master->lessee_id != 0) {
287 		DRM_DEBUG_LEASE("remove master %d from device list of lessees\n", master->lessee_id);
288 		idr_remove(&(drm_lease_owner(master)->lessee_idr), master->lessee_id);
289 	}
290 
291 	/* Remove this master from any lessee list it may be on */
292 	list_del(&master->lessee_list);
293 
294 	mutex_unlock(&dev->mode_config.idr_mutex);
295 
296 	if (master->lessor) {
297 		/* Tell the master to check the lessee list */
298 		drm_sysfs_lease_event(dev);
299 		drm_master_put(&master->lessor);
300 	}
301 
302 	DRM_DEBUG_LEASE("drm_lease_destroy done %d\n", master->lessee_id);
303 }
304 
305 /**
306  * _drm_lease_revoke - revoke access to all leased objects (idr_mutex held)
307  * @top: the master losing its lease
308  */
309 static void _drm_lease_revoke(struct drm_master *top)
310 {
311 	int object;
312 	void *entry;
313 	struct drm_master *master = top;
314 
315 	lockdep_assert_held(&top->dev->mode_config.idr_mutex);
316 
317 	/*
318 	 * Walk the tree starting at 'top' emptying all leases. Because
319 	 * the tree is fully connected, we can do this without recursing
320 	 */
321 	for (;;) {
322 		DRM_DEBUG_LEASE("revoke leases for %p %d\n", master, master->lessee_id);
323 
324 		/* Evacuate the lease */
325 		idr_for_each_entry(&master->leases, entry, object)
326 			idr_remove(&master->leases, object);
327 
328 		/* Depth-first list walk */
329 
330 		/* Down */
331 		if (!list_empty(&master->lessees)) {
332 			master = list_first_entry(&master->lessees, struct drm_master, lessee_list);
333 		} else {
334 			/* Up */
335 			while (master != top && master == list_last_entry(&master->lessor->lessees, struct drm_master, lessee_list))
336 				master = master->lessor;
337 
338 			if (master == top)
339 				break;
340 
341 			/* Over */
342 			master = list_next_entry(master, lessee_list);
343 		}
344 	}
345 }
346 
347 /**
348  * drm_lease_revoke - revoke access to all leased objects (idr_mutex not held)
349  * @top: the master losing its lease
350  */
351 void drm_lease_revoke(struct drm_master *top)
352 {
353 	mutex_lock(&top->dev->mode_config.idr_mutex);
354 	_drm_lease_revoke(top);
355 	mutex_unlock(&top->dev->mode_config.idr_mutex);
356 }
357 
358 static int validate_lease(struct drm_device *dev,
359 			  int object_count,
360 			  struct drm_mode_object **objects,
361 			  bool universal_planes)
362 {
363 	int o;
364 	int has_crtc = -1;
365 	int has_connector = -1;
366 	int has_plane = -1;
367 
368 	/* we want to confirm that there is at least one crtc, plane
369 	   connector object. */
370 
371 	for (o = 0; o < object_count; o++) {
372 		if (objects[o]->type == DRM_MODE_OBJECT_CRTC && has_crtc == -1) {
373 			has_crtc = o;
374 		}
375 		if (objects[o]->type == DRM_MODE_OBJECT_CONNECTOR && has_connector == -1)
376 			has_connector = o;
377 
378 		if (universal_planes) {
379 			if (objects[o]->type == DRM_MODE_OBJECT_PLANE && has_plane == -1)
380 				has_plane = o;
381 		}
382 	}
383 	if (has_crtc == -1 || has_connector == -1)
384 		return -EINVAL;
385 	if (universal_planes && has_plane == -1)
386 		return -EINVAL;
387 	return 0;
388 }
389 
390 static int fill_object_idr(struct drm_device *dev,
391 			   struct drm_file *lessor_priv,
392 			   struct idr *leases,
393 			   int object_count,
394 			   u32 *object_ids)
395 {
396 	struct drm_mode_object **objects;
397 	u32 o;
398 	int ret;
399 	bool universal_planes = READ_ONCE(lessor_priv->universal_planes);
400 
401 	objects = kcalloc(object_count, sizeof(struct drm_mode_object *),
402 			  GFP_KERNEL);
403 	if (!objects)
404 		return -ENOMEM;
405 
406 	/* step one - get references to all the mode objects
407 	   and check for validity. */
408 	for (o = 0; o < object_count; o++) {
409 		objects[o] = drm_mode_object_find(dev, lessor_priv,
410 						  object_ids[o],
411 						  DRM_MODE_OBJECT_ANY);
412 		if (!objects[o]) {
413 			ret = -ENOENT;
414 			goto out_free_objects;
415 		}
416 
417 		if (!drm_mode_object_lease_required(objects[o]->type)) {
418 			DRM_DEBUG_KMS("invalid object for lease\n");
419 			ret = -EINVAL;
420 			goto out_free_objects;
421 		}
422 	}
423 
424 	ret = validate_lease(dev, object_count, objects, universal_planes);
425 	if (ret) {
426 		DRM_DEBUG_LEASE("lease validation failed\n");
427 		goto out_free_objects;
428 	}
429 
430 	/* add their IDs to the lease request - taking into account
431 	   universal planes */
432 	for (o = 0; o < object_count; o++) {
433 		struct drm_mode_object *obj = objects[o];
434 		u32 object_id = objects[o]->id;
435 		DRM_DEBUG_LEASE("Adding object %d to lease\n", object_id);
436 
437 		/*
438 		 * We're using an IDR to hold the set of leased
439 		 * objects, but we don't need to point at the object's
440 		 * data structure from the lease as the main object_idr
441 		 * will be used to actually find that. Instead, all we
442 		 * really want is a 'leased/not-leased' result, for
443 		 * which any non-NULL pointer will work fine.
444 		 */
445 		ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
446 		if (ret < 0) {
447 			DRM_DEBUG_LEASE("Object %d cannot be inserted into leases (%d)\n",
448 					object_id, ret);
449 			goto out_free_objects;
450 		}
451 		if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) {
452 			struct drm_crtc *crtc = obj_to_crtc(obj);
453 			ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
454 			if (ret < 0) {
455 				DRM_DEBUG_LEASE("Object primary plane %d cannot be inserted into leases (%d)\n",
456 						object_id, ret);
457 				goto out_free_objects;
458 			}
459 			if (crtc->cursor) {
460 				ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL);
461 				if (ret < 0) {
462 					DRM_DEBUG_LEASE("Object cursor plane %d cannot be inserted into leases (%d)\n",
463 							object_id, ret);
464 					goto out_free_objects;
465 				}
466 			}
467 		}
468 	}
469 
470 	ret = 0;
471 out_free_objects:
472 	for (o = 0; o < object_count; o++) {
473 		if (objects[o])
474 			drm_mode_object_put(objects[o]);
475 	}
476 	kfree(objects);
477 	return ret;
478 }
479 
480 /**
481  * drm_mode_create_lease_ioctl - create a new lease
482  * @dev: the drm device
483  * @data: pointer to struct drm_mode_create_lease
484  * @lessor_priv: the file being manipulated
485  *
486  * The master associated with the specified file will have a lease
487  * created containing the objects specified in the ioctl structure.
488  * A file descriptor will be allocated for that and returned to the
489  * application.
490  */
491 int drm_mode_create_lease_ioctl(struct drm_device *dev,
492 				void *data, struct drm_file *lessor_priv)
493 {
494 	struct drm_mode_create_lease *cl = data;
495 	size_t object_count;
496 	int ret = 0;
497 	struct idr leases;
498 	struct drm_master *lessor = lessor_priv->master;
499 	struct drm_master *lessee = NULL;
500 	struct file *lessee_file = NULL;
501 	struct file *lessor_file = lessor_priv->filp;
502 	struct drm_file *lessee_priv;
503 	int fd = -1;
504 	uint32_t *object_ids;
505 
506 	/* Can't lease without MODESET */
507 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
508 		return -EOPNOTSUPP;
509 
510 	/* Do not allow sub-leases */
511 	if (lessor->lessor) {
512 		DRM_DEBUG_LEASE("recursive leasing not allowed\n");
513 		return -EINVAL;
514 	}
515 
516 	/* need some objects */
517 	if (cl->object_count == 0) {
518 		DRM_DEBUG_LEASE("no objects in lease\n");
519 		return -EINVAL;
520 	}
521 
522 	if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) {
523 		DRM_DEBUG_LEASE("invalid flags\n");
524 		return -EINVAL;
525 	}
526 
527 	object_count = cl->object_count;
528 
529 	object_ids = memdup_user(u64_to_user_ptr(cl->object_ids),
530 			array_size(object_count, sizeof(__u32)));
531 	if (IS_ERR(object_ids))
532 		return PTR_ERR(object_ids);
533 
534 	idr_init(&leases);
535 
536 	/* fill and validate the object idr */
537 	ret = fill_object_idr(dev, lessor_priv, &leases,
538 			      object_count, object_ids);
539 	kfree(object_ids);
540 	if (ret) {
541 		DRM_DEBUG_LEASE("lease object lookup failed: %i\n", ret);
542 		idr_destroy(&leases);
543 		return ret;
544 	}
545 
546 	/* Allocate a file descriptor for the lease */
547 	fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
548 	if (fd < 0) {
549 		idr_destroy(&leases);
550 		return fd;
551 	}
552 
553 	DRM_DEBUG_LEASE("Creating lease\n");
554 	lessee = drm_lease_create(lessor, &leases);
555 
556 	if (IS_ERR(lessee)) {
557 		ret = PTR_ERR(lessee);
558 		goto out_leases;
559 	}
560 
561 	/* Clone the lessor file to create a new file for us */
562 	DRM_DEBUG_LEASE("Allocating lease file\n");
563 	lessee_file = file_clone_open(lessor_file);
564 	if (IS_ERR(lessee_file)) {
565 		ret = PTR_ERR(lessee_file);
566 		goto out_lessee;
567 	}
568 
569 	lessee_priv = lessee_file->private_data;
570 	/* Change the file to a master one */
571 	drm_master_put(&lessee_priv->master);
572 	lessee_priv->master = lessee;
573 	lessee_priv->is_master = 1;
574 	lessee_priv->authenticated = 1;
575 
576 	/* Pass fd back to userspace */
577 	DRM_DEBUG_LEASE("Returning fd %d id %d\n", fd, lessee->lessee_id);
578 	cl->fd = fd;
579 	cl->lessee_id = lessee->lessee_id;
580 
581 	/* Hook up the fd */
582 	fd_install(fd, lessee_file);
583 
584 	DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
585 	return 0;
586 
587 out_lessee:
588 	drm_master_put(&lessee);
589 
590 out_leases:
591 	put_unused_fd(fd);
592 	idr_destroy(&leases);
593 
594 	DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret);
595 	return ret;
596 }
597 
598 /**
599  * drm_mode_list_lessees_ioctl - list lessee ids
600  * @dev: the drm device
601  * @data: pointer to struct drm_mode_list_lessees
602  * @lessor_priv: the file being manipulated
603  *
604  * Starting from the master associated with the specified file,
605  * the master with the provided lessee_id is found, and then
606  * an array of lessee ids associated with leases from that master
607  * are returned.
608  */
609 
610 int drm_mode_list_lessees_ioctl(struct drm_device *dev,
611 			       void *data, struct drm_file *lessor_priv)
612 {
613 	struct drm_mode_list_lessees *arg = data;
614 	__u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr);
615 	__u32 count_lessees = arg->count_lessees;
616 	struct drm_master *lessor = lessor_priv->master, *lessee;
617 	int count;
618 	int ret = 0;
619 
620 	if (arg->pad)
621 		return -EINVAL;
622 
623 	/* Can't lease without MODESET */
624 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
625 		return -EOPNOTSUPP;
626 
627 	DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id);
628 
629 	mutex_lock(&dev->mode_config.idr_mutex);
630 
631 	count = 0;
632 	drm_for_each_lessee(lessee, lessor) {
633 		/* Only list un-revoked leases */
634 		if (!idr_is_empty(&lessee->leases)) {
635 			if (count_lessees > count) {
636 				DRM_DEBUG_LEASE("Add lessee %d\n", lessee->lessee_id);
637 				ret = put_user(lessee->lessee_id, lessee_ids + count);
638 				if (ret)
639 					break;
640 			}
641 			count++;
642 		}
643 	}
644 
645 	DRM_DEBUG_LEASE("Lessor leases to %d\n", count);
646 	if (ret == 0)
647 		arg->count_lessees = count;
648 
649 	mutex_unlock(&dev->mode_config.idr_mutex);
650 
651 	return ret;
652 }
653 
654 /**
655  * drm_mode_get_lease_ioctl - list leased objects
656  * @dev: the drm device
657  * @data: pointer to struct drm_mode_get_lease
658  * @lessee_priv: the file being manipulated
659  *
660  * Return the list of leased objects for the specified lessee
661  */
662 
663 int drm_mode_get_lease_ioctl(struct drm_device *dev,
664 			     void *data, struct drm_file *lessee_priv)
665 {
666 	struct drm_mode_get_lease *arg = data;
667 	__u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr);
668 	__u32 count_objects = arg->count_objects;
669 	struct drm_master *lessee = lessee_priv->master;
670 	struct idr *object_idr;
671 	int count;
672 	void *entry;
673 	int object;
674 	int ret = 0;
675 
676 	if (arg->pad)
677 		return -EINVAL;
678 
679 	/* Can't lease without MODESET */
680 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
681 		return -EOPNOTSUPP;
682 
683 	DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id);
684 
685 	mutex_lock(&dev->mode_config.idr_mutex);
686 
687 	if (lessee->lessor == NULL)
688 		/* owner can use all objects */
689 		object_idr = &lessee->dev->mode_config.object_idr;
690 	else
691 		/* lessee can only use allowed object */
692 		object_idr = &lessee->leases;
693 
694 	count = 0;
695 	idr_for_each_entry(object_idr, entry, object) {
696 		if (count_objects > count) {
697 			DRM_DEBUG_LEASE("adding object %d\n", object);
698 			ret = put_user(object, object_ids + count);
699 			if (ret)
700 				break;
701 		}
702 		count++;
703 	}
704 
705 	DRM_DEBUG("lease holds %d objects\n", count);
706 	if (ret == 0)
707 		arg->count_objects = count;
708 
709 	mutex_unlock(&dev->mode_config.idr_mutex);
710 
711 	return ret;
712 }
713 
714 /**
715  * drm_mode_revoke_lease_ioctl - revoke lease
716  * @dev: the drm device
717  * @data: pointer to struct drm_mode_revoke_lease
718  * @lessor_priv: the file being manipulated
719  *
720  * This removes all of the objects from the lease without
721  * actually getting rid of the lease itself; that way all
722  * references to it still work correctly
723  */
724 int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
725 				void *data, struct drm_file *lessor_priv)
726 {
727 	struct drm_mode_revoke_lease *arg = data;
728 	struct drm_master *lessor = lessor_priv->master;
729 	struct drm_master *lessee;
730 	int ret = 0;
731 
732 	DRM_DEBUG_LEASE("revoke lease for %d\n", arg->lessee_id);
733 
734 	/* Can't lease without MODESET */
735 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
736 		return -EOPNOTSUPP;
737 
738 	mutex_lock(&dev->mode_config.idr_mutex);
739 
740 	lessee = _drm_find_lessee(lessor, arg->lessee_id);
741 
742 	/* No such lessee */
743 	if (!lessee) {
744 		ret = -ENOENT;
745 		goto fail;
746 	}
747 
748 	/* Lease is not held by lessor */
749 	if (lessee->lessor != lessor) {
750 		ret = -EACCES;
751 		goto fail;
752 	}
753 
754 	_drm_lease_revoke(lessee);
755 
756 fail:
757 	mutex_unlock(&dev->mode_config.idr_mutex);
758 
759 	return ret;
760 }
761