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