Skip to content

Commit

Permalink
drm: Add drm_object lease infrastructure [v5]
Browse files Browse the repository at this point in the history
This provides new data structures to hold "lease" information about
drm mode setting objects, and provides for creating new drm_masters
which have access to a subset of the available drm resources.

An 'owner' is a drm_master which is not leasing the objects from
another drm_master, and hence 'owns' them.

A 'lessee' is a drm_master which is leasing objects from some other
drm_master. Each lessee holds the set of objects which it is leasing
from the lessor.

A 'lessor' is a drm_master which is leasing objects to another
drm_master. This is the same as the owner in the current code.

The set of objects any drm_master 'controls' is limited to the set of
objects it leases (for lessees) or all objects (for owners).

Objects not controlled by a drm_master cannot be modified through the
various state manipulating ioctls, and any state reported back to user
space will be edited to make them appear idle and/or unusable. For
instance, connectors always report 'disconnected', while encoders
report no possible crtcs or clones.

The full list of lessees leasing objects from an owner (either
directly, or indirectly through another lessee), can be searched from
an idr in the drm_master of the owner.

Changes for v2 as suggested by Daniel Vetter <daniel.vetter@ffwll.ch>:

* Sub-leasing has been disabled.

* BUG_ON for lock checking replaced with lockdep_assert_held

* 'change' ioctl has been removed.

* Leased objects can always be controlled by the lessor; the
  'mask_lease' flag has been removed

* Checking for leased status has been simplified, replacing
  the drm_lease_check function with drm_lease_held.

Changes in v3, some suggested by Dave Airlie <airlied@gmail.com>

* Add revocation. This allows leases to be effectively revoked by
  removing all of the objects they have access to. The lease itself
  hangs around as it's hanging off a file.

* Free the leases IDR when the master is destroyed

* _drm_lease_held should look at lessees, not lessor

* Allow non-master files to check for lease status

Changes in v4, suggested by Dave Airlie <airlied@gmail.com>

* Formatting and whitespace changes

Changes in v5 (airlied)

* check DRIVER_MODESET before lease destroy call
* check DRIVER_MODESET for lease revoke (Chris)
* Use idr_mutex uniformly for all lease elements of struct drm_master. (Keith)

Signed-off-by: Keith Packard <keithp@keithp.com>
  • Loading branch information
Keith Packard authored and Dave Airlie committed Oct 25, 2017
1 parent e7646f8 commit 2ed077e
Show file tree
Hide file tree
Showing 6 changed files with 443 additions and 2 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_encoder.o drm_mode_object.o drm_property.o \
drm_plane.o drm_color_mgmt.o drm_print.o \
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
drm_syncobj.o
drm_syncobj.o drm_lease.o

drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
drm-$(CONFIG_DRM_VM) += drm_vm.o
Expand Down
30 changes: 29 additions & 1 deletion drivers/gpu/drm/drm_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <drm/drmP.h>
#include "drm_internal.h"
#include "drm_legacy.h"
#include <drm/drm_lease.h>

/**
* DOC: master and authentication
Expand Down Expand Up @@ -93,7 +94,7 @@ int drm_authmagic(struct drm_device *dev, void *data,
return file ? 0 : -EINVAL;
}

static struct drm_master *drm_master_create(struct drm_device *dev)
struct drm_master *drm_master_create(struct drm_device *dev)
{
struct drm_master *master;

Expand All @@ -107,6 +108,14 @@ static struct drm_master *drm_master_create(struct drm_device *dev)
idr_init(&master->magic_map);
master->dev = dev;

/* initialize the tree of output resource lessees */
master->lessor = NULL;
master->lessee_id = 0;
INIT_LIST_HEAD(&master->lessees);
INIT_LIST_HEAD(&master->lessee_list);
idr_init(&master->leases);
idr_init(&master->lessee_idr);

return master;
}

Expand Down Expand Up @@ -189,6 +198,12 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
goto out_unlock;
}

if (file_priv->master->lessor != NULL) {
DRM_DEBUG_LEASE("Attempt to set lessee %d as master\n", file_priv->master->lessee_id);
ret = -EINVAL;
goto out_unlock;
}

ret = drm_set_master(dev, file_priv, false);
out_unlock:
mutex_unlock(&dev->master_mutex);
Expand Down Expand Up @@ -270,6 +285,13 @@ void drm_master_release(struct drm_file *file_priv)
if (dev->master == file_priv->master)
drm_drop_master(dev, file_priv);
out:
if (drm_core_check_feature(dev, DRIVER_MODESET) && file_priv->is_master) {
/* Revoke any leases held by this or lessees, but only if
* this is the "real" master
*/
drm_lease_revoke(master);
}

/* drop the master reference held by the file priv */
if (file_priv->master)
drm_master_put(&file_priv->master);
Expand Down Expand Up @@ -310,12 +332,18 @@ static void drm_master_destroy(struct kref *kref)
struct drm_master *master = container_of(kref, struct drm_master, refcount);
struct drm_device *dev = master->dev;

if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_lease_destroy(master);

if (dev->driver->master_destroy)
dev->driver->master_destroy(dev, master);

drm_legacy_master_rmmaps(dev, master);

idr_destroy(&master->magic_map);
idr_destroy(&master->leases);
idr_destroy(&master->lessee_idr);

kfree(master->unique);
kfree(master);
}
Expand Down
Loading

0 comments on commit 2ed077e

Please sign in to comment.