Lines Matching +full:single +full:- +full:master

1 // SPDX-License-Identifier: GPL-2.0-or-later
21 * DRM leases provide information about whether a DRM master may control a DRM
25 * The original DRM master of a device 'owns' the available drm resources. It
27 * to the new DRM master. This gives the new DRM master control over the
28 * leased resources until the owner revokes the lease, or the new DRM master
31 * - An 'owner' is a &struct drm_master that is not leasing objects from
35 * - A 'lessor' is a &struct drm_master which is leasing objects to one or more
37 * create sub-leases, hence the lessor is the same as the owner.
39 * - A 'lessee' is a &struct drm_master which is leasing objects from some
40 * other &struct drm_master. Each lessee only leases resources from a single
44 * - A 'lease' is a contract between the lessor and lessee that identifies
58 * Since each lessee may lease objects from a single lessor, display resource
60 * allowed to create sub-leases, the tree depth is limited to 1. All of
62 * through the SETMASTER or DROPMASTER IOCTL, so &drm_device.master points to
70 list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
74 struct drm_master *drm_lease_owner(struct drm_master *master) in drm_lease_owner() argument
76 while (master->lessor != NULL) in drm_lease_owner()
77 master = master->lessor; in drm_lease_owner()
78 return master; in drm_lease_owner()
82 _drm_find_lessee(struct drm_master *master, int lessee_id) in _drm_find_lessee() argument
84 lockdep_assert_held(&master->dev->mode_config.idr_mutex); in _drm_find_lessee()
85 return idr_find(&drm_lease_owner(master)->lessee_idr, lessee_id); in _drm_find_lessee()
88 static int _drm_lease_held_master(struct drm_master *master, int id) in _drm_lease_held_master() argument
90 lockdep_assert_held(&master->dev->mode_config.idr_mutex); in _drm_lease_held_master()
91 if (master->lessor) in _drm_lease_held_master()
92 return idr_find(&master->leases, id) != NULL; in _drm_lease_held_master()
97 static bool _drm_has_leased(struct drm_master *master, int id) in _drm_has_leased() argument
101 lockdep_assert_held(&master->dev->mode_config.idr_mutex); in _drm_has_leased()
102 drm_for_each_lessee(lessee, master) in _drm_has_leased()
112 struct drm_master *master; in _drm_lease_held() local
117 master = drm_file_get_master(file_priv); in _drm_lease_held()
118 if (!master) in _drm_lease_held()
120 ret = _drm_lease_held_master(master, id); in _drm_lease_held()
121 drm_master_put(&master); in _drm_lease_held()
128 struct drm_master *master; in drm_lease_held() local
134 master = drm_file_get_master(file_priv); in drm_lease_held()
135 if (!master) in drm_lease_held()
137 if (!master->lessor) { in drm_lease_held()
141 mutex_lock(&master->dev->mode_config.idr_mutex); in drm_lease_held()
142 ret = _drm_lease_held_master(master, id); in drm_lease_held()
143 mutex_unlock(&master->dev->mode_config.idr_mutex); in drm_lease_held()
146 drm_master_put(&master); in drm_lease_held()
156 struct drm_master *master; in drm_lease_filter_crtcs() local
165 master = drm_file_get_master(file_priv); in drm_lease_filter_crtcs()
166 if (!master) in drm_lease_filter_crtcs()
168 if (!master->lessor) { in drm_lease_filter_crtcs()
172 dev = master->dev; in drm_lease_filter_crtcs()
175 mutex_lock(&master->dev->mode_config.idr_mutex); in drm_lease_filter_crtcs()
176 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { in drm_lease_filter_crtcs()
177 if (_drm_lease_held_master(master, crtc->base.id)) { in drm_lease_filter_crtcs()
189 mutex_unlock(&master->dev->mode_config.idr_mutex); in drm_lease_filter_crtcs()
192 drm_master_put(&master); in drm_lease_filter_crtcs()
201 * ERR_PTR(-EACCES) some other master holds the title to any object
202 * ERR_PTR(-ENOENT) some object is not a valid DRM object for this device
203 * ERR_PTR(-EBUSY) some other lessee holds title to this object
204 * ERR_PTR(-EEXIST) same object specified more than once in the provided list
205 * ERR_PTR(-ENOMEM) allocation failed
209 struct drm_device *dev = lessor->dev; in drm_lease_create()
216 drm_dbg_lease(dev, "lessor %d\n", lessor->lessee_id); in drm_lease_create()
218 lessee = drm_master_create(lessor->dev); in drm_lease_create()
221 return ERR_PTR(-ENOMEM); in drm_lease_create()
224 mutex_lock(&dev->mode_config.idr_mutex); in drm_lease_create()
228 if (!idr_find(&dev->mode_config.object_idr, object)) in drm_lease_create()
229 error = -ENOENT; in drm_lease_create()
231 error = -EBUSY; in drm_lease_create()
240 id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL); in drm_lease_create()
246 lessee->lessee_id = id; in drm_lease_create()
247 lessee->lessor = drm_master_get(lessor); in drm_lease_create()
248 list_add_tail(&lessee->lessee_list, &lessor->lessees); in drm_lease_create()
251 lessee->leases = *leases; in drm_lease_create()
253 lessee->lessee_id, lessee, lessor->lessee_id, lessor); in drm_lease_create()
255 mutex_unlock(&dev->mode_config.idr_mutex); in drm_lease_create()
259 mutex_unlock(&dev->mode_config.idr_mutex); in drm_lease_create()
266 void drm_lease_destroy(struct drm_master *master) in drm_lease_destroy() argument
268 struct drm_device *dev = master->dev; in drm_lease_destroy()
270 mutex_lock(&dev->mode_config.idr_mutex); in drm_lease_destroy()
272 drm_dbg_lease(dev, "drm_lease_destroy %d\n", master->lessee_id); in drm_lease_destroy()
274 /* This master is referenced by all lessees, hence it cannot be destroyed in drm_lease_destroy()
277 WARN_ON(!list_empty(&master->lessees)); in drm_lease_destroy()
279 /* Remove this master from the lessee idr in the owner */ in drm_lease_destroy()
280 if (master->lessee_id != 0) { in drm_lease_destroy()
281 drm_dbg_lease(dev, "remove master %d from device list of lessees\n", in drm_lease_destroy()
282 master->lessee_id); in drm_lease_destroy()
283 idr_remove(&(drm_lease_owner(master)->lessee_idr), master->lessee_id); in drm_lease_destroy()
286 /* Remove this master from any lessee list it may be on */ in drm_lease_destroy()
287 list_del(&master->lessee_list); in drm_lease_destroy()
289 mutex_unlock(&dev->mode_config.idr_mutex); in drm_lease_destroy()
291 if (master->lessor) { in drm_lease_destroy()
292 /* Tell the master to check the lessee list */ in drm_lease_destroy()
294 drm_master_put(&master->lessor); in drm_lease_destroy()
297 drm_dbg_lease(dev, "drm_lease_destroy done %d\n", master->lessee_id); in drm_lease_destroy()
304 struct drm_master *master = top; in _drm_lease_revoke() local
306 lockdep_assert_held(&top->dev->mode_config.idr_mutex); in _drm_lease_revoke()
313 drm_dbg_lease(master->dev, "revoke leases for %p %d\n", in _drm_lease_revoke()
314 master, master->lessee_id); in _drm_lease_revoke()
317 idr_for_each_entry(&master->leases, entry, object) in _drm_lease_revoke()
318 idr_remove(&master->leases, object); in _drm_lease_revoke()
320 /* Depth-first list walk */ in _drm_lease_revoke()
323 if (!list_empty(&master->lessees)) { in _drm_lease_revoke()
324 master = list_first_entry(&master->lessees, struct drm_master, lessee_list); in _drm_lease_revoke()
327 …while (master != top && master == list_last_entry(&master->lessor->lessees, struct drm_master, les… in _drm_lease_revoke()
328 master = master->lessor; in _drm_lease_revoke()
330 if (master == top) in _drm_lease_revoke()
334 master = list_next_entry(master, lessee_list); in _drm_lease_revoke()
341 mutex_lock(&top->dev->mode_config.idr_mutex); in drm_lease_revoke()
343 mutex_unlock(&top->dev->mode_config.idr_mutex); in drm_lease_revoke()
352 int has_crtc = -1; in validate_lease()
353 int has_connector = -1; in validate_lease()
354 int has_plane = -1; in validate_lease()
360 if (objects[o]->type == DRM_MODE_OBJECT_CRTC && has_crtc == -1) { in validate_lease()
363 if (objects[o]->type == DRM_MODE_OBJECT_CONNECTOR && has_connector == -1) in validate_lease()
367 if (objects[o]->type == DRM_MODE_OBJECT_PLANE && has_plane == -1) in validate_lease()
371 if (has_crtc == -1 || has_connector == -1) in validate_lease()
372 return -EINVAL; in validate_lease()
373 if (universal_planes && has_plane == -1) in validate_lease()
374 return -EINVAL; in validate_lease()
387 bool universal_planes = READ_ONCE(lessor_priv->universal_planes); in fill_object_idr()
392 return -ENOMEM; in fill_object_idr()
394 /* step one - get references to all the mode objects in fill_object_idr()
401 ret = -ENOENT; in fill_object_idr()
405 if (!drm_mode_object_lease_required(objects[o]->type)) { in fill_object_idr()
407 ret = -EINVAL; in fill_object_idr()
418 /* add their IDs to the lease request - taking into account in fill_object_idr()
422 u32 object_id = objects[o]->id; in fill_object_idr()
431 * really want is a 'leased/not-leased' result, for in fill_object_idr()
432 * which any non-NULL pointer will work fine. in fill_object_idr()
440 if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) { in fill_object_idr()
443 …ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1,… in fill_object_idr()
449 if (crtc->cursor) { in fill_object_idr()
450 …ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, G… in fill_object_idr()
471 * The master associated with the specified file will have a lease
486 struct file *lessor_file = lessor_priv->filp; in drm_mode_create_lease_ioctl()
488 int fd = -1; in drm_mode_create_lease_ioctl()
493 return -EOPNOTSUPP; in drm_mode_create_lease_ioctl()
495 if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) { in drm_mode_create_lease_ioctl()
497 return -EINVAL; in drm_mode_create_lease_ioctl()
501 /* Do not allow sub-leases */ in drm_mode_create_lease_ioctl()
502 if (lessor->lessor) { in drm_mode_create_lease_ioctl()
504 ret = -EINVAL; in drm_mode_create_lease_ioctl()
508 object_count = cl->object_count; in drm_mode_create_lease_ioctl()
513 object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids), in drm_mode_create_lease_ioctl()
533 fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK)); in drm_mode_create_lease_ioctl()
558 lessee_priv = lessee_file->private_data; in drm_mode_create_lease_ioctl()
559 /* Change the file to a master one */ in drm_mode_create_lease_ioctl()
560 drm_master_put(&lessee_priv->master); in drm_mode_create_lease_ioctl()
561 lessee_priv->master = lessee; in drm_mode_create_lease_ioctl()
562 lessee_priv->is_master = 1; in drm_mode_create_lease_ioctl()
563 lessee_priv->authenticated = 1; in drm_mode_create_lease_ioctl()
566 drm_dbg_lease(dev, "Returning fd %d id %d\n", fd, lessee->lessee_id); in drm_mode_create_lease_ioctl()
567 cl->fd = fd; in drm_mode_create_lease_ioctl()
568 cl->lessee_id = lessee->lessee_id; in drm_mode_create_lease_ioctl()
593 __u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr); in drm_mode_list_lessees_ioctl()
594 __u32 count_lessees = arg->count_lessees; in drm_mode_list_lessees_ioctl()
599 if (arg->pad) in drm_mode_list_lessees_ioctl()
600 return -EINVAL; in drm_mode_list_lessees_ioctl()
604 return -EOPNOTSUPP; in drm_mode_list_lessees_ioctl()
607 drm_dbg_lease(dev, "List lessees for %d\n", lessor->lessee_id); in drm_mode_list_lessees_ioctl()
609 mutex_lock(&dev->mode_config.idr_mutex); in drm_mode_list_lessees_ioctl()
613 /* Only list un-revoked leases */ in drm_mode_list_lessees_ioctl()
614 if (!idr_is_empty(&lessee->leases)) { in drm_mode_list_lessees_ioctl()
617 lessee->lessee_id); in drm_mode_list_lessees_ioctl()
618 ret = put_user(lessee->lessee_id, lessee_ids + count); in drm_mode_list_lessees_ioctl()
628 arg->count_lessees = count; in drm_mode_list_lessees_ioctl()
630 mutex_unlock(&dev->mode_config.idr_mutex); in drm_mode_list_lessees_ioctl()
641 __u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr); in drm_mode_get_lease_ioctl()
642 __u32 count_objects = arg->count_objects; in drm_mode_get_lease_ioctl()
650 if (arg->pad) in drm_mode_get_lease_ioctl()
651 return -EINVAL; in drm_mode_get_lease_ioctl()
655 return -EOPNOTSUPP; in drm_mode_get_lease_ioctl()
658 drm_dbg_lease(dev, "get lease for %d\n", lessee->lessee_id); in drm_mode_get_lease_ioctl()
660 mutex_lock(&dev->mode_config.idr_mutex); in drm_mode_get_lease_ioctl()
662 if (lessee->lessor == NULL) in drm_mode_get_lease_ioctl()
664 object_idr = &lessee->dev->mode_config.object_idr; in drm_mode_get_lease_ioctl()
667 object_idr = &lessee->leases; in drm_mode_get_lease_ioctl()
682 arg->count_objects = count; in drm_mode_get_lease_ioctl()
684 mutex_unlock(&dev->mode_config.idr_mutex); in drm_mode_get_lease_ioctl()
703 drm_dbg_lease(dev, "revoke lease for %d\n", arg->lessee_id); in drm_mode_revoke_lease_ioctl()
707 return -EOPNOTSUPP; in drm_mode_revoke_lease_ioctl()
710 mutex_lock(&dev->mode_config.idr_mutex); in drm_mode_revoke_lease_ioctl()
712 lessee = _drm_find_lessee(lessor, arg->lessee_id); in drm_mode_revoke_lease_ioctl()
716 ret = -ENOENT; in drm_mode_revoke_lease_ioctl()
721 if (lessee->lessor != lessor) { in drm_mode_revoke_lease_ioctl()
722 ret = -EACCES; in drm_mode_revoke_lease_ioctl()
729 mutex_unlock(&dev->mode_config.idr_mutex); in drm_mode_revoke_lease_ioctl()