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