Merge tag 'arc-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
[sfrench/cifs-2.6.git] / drivers / gpu / drm / drm_auth.c
index 7ff697389d744220bd7fffcd9a6f68b4487c5775..aad468d170a7e786fb5c460b6dd01ecff015ef3a 100644 (file)
@@ -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
@@ -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;
 
@@ -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;
 }
 
@@ -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);
@@ -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);
@@ -288,7 +310,7 @@ out:
  */
 bool drm_is_current_master(struct drm_file *fpriv)
 {
-       return fpriv->is_master && fpriv->master == fpriv->minor->dev->master;
+       return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master;
 }
 EXPORT_SYMBOL(drm_is_current_master);
 
@@ -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);
 }