All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] DRM: Random Cleanups
@ 2014-07-23 15:26 David Herrmann
  2014-07-23 15:26 ` [PATCH 01/12] drm: remove unused "struct drm_freelist" David Herrmann
                   ` (12 more replies)
  0 siblings, 13 replies; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

Hi

A bunch of random cleanups I stumbled on when reworking the init-logic. Most of
them should be fairly trivial.

Also available in my fdo-repository:
   http://cgit.freedesktop.org/~dvdhrm/linux/log/?h=drm-next

Comments welcome!
David

David Herrmann (12):
  drm: remove unused "struct drm_freelist"
  drm: drop unused "struct drm_queue"
  drm: call ->firstopen() before ->open()
  drm: extract legacy ctxbitmap flushing
  drm: drop i386 verification
  drm: fix __alpha__ PCI lookup
  drm: drop redundant drm_file->is_master
  drm: don't de-authenticate clients on master-close
  drm: move module initialization to drm_stub.c
  drm: merge drm_drv.c into drm_ioctl.c
  drm: make minor->index available early
  drm: make sysfs device always available for minors

 drivers/gpu/drm/drm_bufs.c                 |  17 +-
 drivers/gpu/drm/drm_context.c              |  30 ++
 drivers/gpu/drm/drm_crtc.c                 |   2 +-
 drivers/gpu/drm/drm_drv.c                  | 471 -----------------------------
 drivers/gpu/drm/drm_fops.c                 | 227 +++++---------
 drivers/gpu/drm/drm_info.c                 |   2 +-
 drivers/gpu/drm/drm_ioctl.c                | 369 +++++++++++++++++++++-
 drivers/gpu/drm/drm_lock.c                 |   2 +-
 drivers/gpu/drm/drm_stub.c                 | 231 ++++++++++----
 drivers/gpu/drm/drm_sysfs.c                |  90 +++---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   4 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c        |   2 +-
 include/drm/drmP.h                         |  52 +---
 13 files changed, 705 insertions(+), 794 deletions(-)
 delete mode 100644 drivers/gpu/drm/drm_drv.c

-- 
2.0.2

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 01/12] drm: remove unused "struct drm_freelist"
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-23 19:17   ` Daniel Vetter
  2014-07-23 15:26 ` [PATCH 02/12] drm: drop unused "struct drm_queue" David Herrmann
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

This object is not used except for static fields in drm_bufs *cough*.
Inline the watermark fields and drop the unused structure definition.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_bufs.c | 17 ++++++++---------
 drivers/gpu/drm/drm_info.c |  2 +-
 include/drm/drmP.h         | 15 ++-------------
 3 files changed, 11 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 68175b5..61acb8f 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -1217,7 +1217,6 @@ int drm_infobufs(struct drm_device *dev, void *data,
 				struct drm_buf_desc __user *to =
 				    &request->list[count];
 				struct drm_buf_entry *from = &dma->bufs[i];
-				struct drm_freelist *list = &dma->bufs[i].freelist;
 				if (copy_to_user(&to->count,
 						 &from->buf_count,
 						 sizeof(from->buf_count)) ||
@@ -1225,19 +1224,19 @@ int drm_infobufs(struct drm_device *dev, void *data,
 						 &from->buf_size,
 						 sizeof(from->buf_size)) ||
 				    copy_to_user(&to->low_mark,
-						 &list->low_mark,
-						 sizeof(list->low_mark)) ||
+						 &from->low_mark,
+						 sizeof(from->low_mark)) ||
 				    copy_to_user(&to->high_mark,
-						 &list->high_mark,
-						 sizeof(list->high_mark)))
+						 &from->high_mark,
+						 sizeof(from->high_mark)))
 					return -EFAULT;
 
 				DRM_DEBUG("%d %d %d %d %d\n",
 					  i,
 					  dma->bufs[i].buf_count,
 					  dma->bufs[i].buf_size,
-					  dma->bufs[i].freelist.low_mark,
-					  dma->bufs[i].freelist.high_mark);
+					  dma->bufs[i].low_mark,
+					  dma->bufs[i].high_mark);
 				++count;
 			}
 		}
@@ -1290,8 +1289,8 @@ int drm_markbufs(struct drm_device *dev, void *data,
 	if (request->high_mark < 0 || request->high_mark > entry->buf_count)
 		return -EINVAL;
 
-	entry->freelist.low_mark = request->low_mark;
-	entry->freelist.high_mark = request->high_mark;
+	entry->low_mark = request->low_mark;
+	entry->high_mark = request->high_mark;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index 86feedd..ecaf0fa 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -132,7 +132,7 @@ int drm_bufs_info(struct seq_file *m, void *data)
 				   i,
 				   dma->bufs[i].buf_size,
 				   dma->bufs[i].buf_count,
-				   atomic_read(&dma->bufs[i].freelist.count),
+				   0,
 				   dma->bufs[i].seg_count,
 				   seg_pages,
 				   seg_pages * PAGE_SIZE / 1024);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 9b6a445..335b7b8 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -346,18 +346,6 @@ struct drm_waitlist {
 	spinlock_t write_lock;
 };
 
-struct drm_freelist {
-	int initialized;	       /**< Freelist in use */
-	atomic_t count;		       /**< Number of free buffers */
-	struct drm_buf *next;	       /**< End pointer */
-
-	wait_queue_head_t waiting;     /**< Processes waiting on free bufs */
-	int low_mark;		       /**< Low water mark */
-	int high_mark;		       /**< High water mark */
-	atomic_t wfh;		       /**< If waiting for high mark */
-	spinlock_t lock;
-};
-
 typedef struct drm_dma_handle {
 	dma_addr_t busaddr;
 	void *vaddr;
@@ -375,7 +363,8 @@ struct drm_buf_entry {
 	int page_order;
 	struct drm_dma_handle **seglist;
 
-	struct drm_freelist freelist;
+	int low_mark;			/**< Low water mark */
+	int high_mark;			/**< High water mark */
 };
 
 /* Event queued up for userspace to read */
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 02/12] drm: drop unused "struct drm_queue"
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
  2014-07-23 15:26 ` [PATCH 01/12] drm: remove unused "struct drm_freelist" David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-23 19:35   ` Daniel Vetter
  2014-07-23 15:26 ` [PATCH 03/12] drm: call ->firstopen() before ->open() David Herrmann
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

This object is unused, drop it.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 include/drm/drmP.h | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 335b7b8..d3d9be6 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -430,23 +430,6 @@ struct drm_file {
 	struct drm_prime_file_private prime;
 };
 
-/** Wait queue */
-struct drm_queue {
-	atomic_t use_count;		/**< Outstanding uses (+1) */
-	atomic_t finalization;		/**< Finalization in progress */
-	atomic_t block_count;		/**< Count of processes waiting */
-	atomic_t block_read;		/**< Queue blocked for reads */
-	wait_queue_head_t read_queue;	/**< Processes waiting on block_read */
-	atomic_t block_write;		/**< Queue blocked for writes */
-	wait_queue_head_t write_queue;	/**< Processes waiting on block_write */
-	atomic_t total_queued;		/**< Total queued statistic */
-	atomic_t total_flushed;		/**< Total flushes statistic */
-	atomic_t total_locks;		/**< Total locks statistics */
-	enum drm_ctx_flags flags;	/**< Context preserving and 2D-only */
-	struct drm_waitlist waitlist;	/**< Pending buffers */
-	wait_queue_head_t flush_queue;	/**< Processes waiting until flush */
-};
-
 /**
  * Lock data.
  */
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 03/12] drm: call ->firstopen() before ->open()
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
  2014-07-23 15:26 ` [PATCH 01/12] drm: remove unused "struct drm_freelist" David Herrmann
  2014-07-23 15:26 ` [PATCH 02/12] drm: drop unused "struct drm_queue" David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-23 19:25   ` Daniel Vetter
  2014-07-23 15:26 ` [PATCH 04/12] drm: extract legacy ctxbitmap flushing David Herrmann
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

Lets order things correctly:
 ->load()
   ->fistopen()
     ->open()
     ->close()
   ->lastclose()
 ->unload()

This doesn't change much as only savage and radeon use ->firstopen() and
they just do map-initialization. Therefore, the global drm mutex makes
sure there cannot be any other f_op between ->open() and ->firstopen().
However, once we get rid of that lock, we really want ->firstopen() to
initialize the device before ->open() is called.

Furthermore, this fixes the clean-up path in drm_open(). We currently
don't cleanup the drm_file object if ->firstopen() fails.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_fops.c | 139 +++++++++++++++++++++------------------------
 include/drm/drmP.h         |   2 +-
 2 files changed, 66 insertions(+), 75 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 021fe5d..8e73519 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -45,7 +45,7 @@ EXPORT_SYMBOL(drm_global_mutex);
 
 static int drm_open_helper(struct file *filp, struct drm_minor *minor);
 
-static int drm_setup(struct drm_device * dev)
+static int drm_firstopen(struct drm_device * dev)
 {
 	int ret;
 
@@ -66,6 +66,57 @@ static int drm_setup(struct drm_device * dev)
 }
 
 /**
+ * drm_legacy_dev_reinit
+ *
+ * Reinitializes a legacy/ums drm device in it's lastclose function.
+ */
+static void drm_legacy_dev_reinit(struct drm_device *dev)
+{
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		return;
+
+	dev->sigdata.lock = NULL;
+
+	dev->context_flag = 0;
+	dev->last_context = 0;
+	dev->if_version = 0;
+}
+
+void drm_lastclose(struct drm_device * dev)
+{
+	struct drm_vma_entry *vma, *vma_temp;
+
+	DRM_DEBUG("\n");
+
+	if (dev->driver->lastclose)
+		dev->driver->lastclose(dev);
+	DRM_DEBUG("driver lastclose completed\n");
+
+	if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_irq_uninstall(dev);
+
+	mutex_lock(&dev->struct_mutex);
+
+	drm_agp_clear(dev);
+
+	drm_legacy_sg_cleanup(dev);
+
+	/* Clear vma list (only built for debugging) */
+	list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
+		list_del(&vma->head);
+		kfree(vma);
+	}
+
+	drm_legacy_dma_takedown(dev);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	drm_legacy_dev_reinit(dev);
+
+	DRM_DEBUG("lastclose completed\n");
+}
+
+/**
  * Open file.
  *
  * \param inode device inode
@@ -81,31 +132,33 @@ int drm_open(struct inode *inode, struct file *filp)
 	struct drm_device *dev;
 	struct drm_minor *minor;
 	int retcode;
-	int need_setup = 0;
 
 	minor = drm_minor_acquire(iminor(inode));
 	if (IS_ERR(minor))
 		return PTR_ERR(minor);
 
 	dev = minor->dev;
-	if (!dev->open_count++)
-		need_setup = 1;
 
 	/* share address_space across all char-devs of a single device */
 	filp->f_mapping = dev->anon_inode->i_mapping;
 
+	if (!dev->open_count) {
+		retcode = drm_firstopen(dev);
+		if (retcode)
+			goto err_minor;
+	}
+	++dev->open_count;
+
 	retcode = drm_open_helper(filp, minor);
 	if (retcode)
 		goto err_undo;
-	if (need_setup) {
-		retcode = drm_setup(dev);
-		if (retcode)
-			goto err_undo;
-	}
+
 	return 0;
 
 err_undo:
-	dev->open_count--;
+	if (!--dev->open_count)
+		drm_lastclose(dev);
+err_minor:
 	drm_minor_release(minor);
 	return retcode;
 }
@@ -346,67 +399,6 @@ static void drm_events_release(struct drm_file *file_priv)
 }
 
 /**
- * drm_legacy_dev_reinit
- *
- * Reinitializes a legacy/ums drm device in it's lastclose function.
- */
-static void drm_legacy_dev_reinit(struct drm_device *dev)
-{
-	if (drm_core_check_feature(dev, DRIVER_MODESET))
-		return;
-
-	dev->sigdata.lock = NULL;
-
-	dev->context_flag = 0;
-	dev->last_context = 0;
-	dev->if_version = 0;
-}
-
-/**
- * Take down the DRM device.
- *
- * \param dev DRM device structure.
- *
- * Frees every resource in \p dev.
- *
- * \sa drm_device
- */
-int drm_lastclose(struct drm_device * dev)
-{
-	struct drm_vma_entry *vma, *vma_temp;
-
-	DRM_DEBUG("\n");
-
-	if (dev->driver->lastclose)
-		dev->driver->lastclose(dev);
-	DRM_DEBUG("driver lastclose completed\n");
-
-	if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
-		drm_irq_uninstall(dev);
-
-	mutex_lock(&dev->struct_mutex);
-
-	drm_agp_clear(dev);
-
-	drm_legacy_sg_cleanup(dev);
-
-	/* Clear vma list (only built for debugging) */
-	list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
-		list_del(&vma->head);
-		kfree(vma);
-	}
-
-	drm_legacy_dma_takedown(dev);
-
-	mutex_unlock(&dev->struct_mutex);
-
-	drm_legacy_dev_reinit(dev);
-
-	DRM_DEBUG("lastclose completed\n");
-	return 0;
-}
-
-/**
  * Release file.
  *
  * \param inode device inode
@@ -423,7 +415,6 @@ int drm_release(struct inode *inode, struct file *filp)
 	struct drm_file *file_priv = filp->private_data;
 	struct drm_minor *minor = file_priv->minor;
 	struct drm_device *dev = minor->dev;
-	int retcode = 0;
 
 	mutex_lock(&drm_global_mutex);
 
@@ -541,7 +532,7 @@ int drm_release(struct inode *inode, struct file *filp)
 	 */
 
 	if (!--dev->open_count) {
-		retcode = drm_lastclose(dev);
+		drm_lastclose(dev);
 		if (drm_device_is_unplugged(dev))
 			drm_put_dev(dev);
 	}
@@ -549,7 +540,7 @@ int drm_release(struct inode *inode, struct file *filp)
 
 	drm_minor_release(minor);
 
-	return retcode;
+	return 0;
 }
 EXPORT_SYMBOL(drm_release);
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index d3d9be6..d1730c5 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1181,7 +1181,7 @@ extern long drm_ioctl(struct file *filp,
 		      unsigned int cmd, unsigned long arg);
 extern long drm_compat_ioctl(struct file *filp,
 			     unsigned int cmd, unsigned long arg);
-extern int drm_lastclose(struct drm_device *dev);
+extern void drm_lastclose(struct drm_device *dev);
 extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
 
 				/* Device support (drm_fops.h) */
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 04/12] drm: extract legacy ctxbitmap flushing
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (2 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 03/12] drm: call ->firstopen() before ->open() David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-23 19:26   ` Daniel Vetter
  2014-07-23 15:26 ` [PATCH 05/12] drm: drop i386 verification David Herrmann
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

The ctxbitmap code is only used by legacy drivers so lets try to keep it
as separated as possible. Furthermore, the locking is non-obvious and
kinda weird with ctxlist_mutex *and* struct_mutex. Keeping all ctxbitmap
access in one file is much easier to review and makes drm_release() more
readable.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_context.c | 30 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_fops.c    | 20 +-------------------
 include/drm/drmP.h            |  1 +
 3 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c
index a4b017b..c045505 100644
--- a/drivers/gpu/drm/drm_context.c
+++ b/drivers/gpu/drm/drm_context.c
@@ -111,6 +111,36 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev)
 	mutex_unlock(&dev->struct_mutex);
 }
 
+/**
+ * drm_ctxbitmap_flush() - Flush all contexts owned by a file
+ * @dev: DRM device to operate on
+ * @file: Open file to flush contexts for
+ *
+ * This iterates over all contexts on @dev and drops them if they're owned by
+ * @file. Note that after this call returns, new contexts might be added if
+ * the file is still alive.
+ */
+void drm_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file)
+{
+	struct drm_ctx_list *pos, *tmp;
+
+	mutex_lock(&dev->ctxlist_mutex);
+
+	list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) {
+		if (pos->tag == file &&
+		    pos->handle != DRM_KERNEL_CONTEXT) {
+			if (dev->driver->context_dtor)
+				dev->driver->context_dtor(dev, pos->handle);
+
+			drm_ctxbitmap_free(dev, pos->handle);
+			list_del(&pos->head);
+			kfree(pos);
+		}
+	}
+
+	mutex_unlock(&dev->ctxlist_mutex);
+}
+
 /*@}*/
 
 /******************************************************************/
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 8e73519..fb81d1c 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -452,25 +452,7 @@ int drm_release(struct inode *inode, struct file *filp)
 	if (dev->driver->driver_features & DRIVER_GEM)
 		drm_gem_release(dev, file_priv);
 
-	mutex_lock(&dev->ctxlist_mutex);
-	if (!list_empty(&dev->ctxlist)) {
-		struct drm_ctx_list *pos, *n;
-
-		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
-			if (pos->tag == file_priv &&
-			    pos->handle != DRM_KERNEL_CONTEXT) {
-				if (dev->driver->context_dtor)
-					dev->driver->context_dtor(dev,
-								  pos->handle);
-
-				drm_ctxbitmap_free(dev, pos->handle);
-
-				list_del(&pos->head);
-				kfree(pos);
-			}
-		}
-	}
-	mutex_unlock(&dev->ctxlist_mutex);
+	drm_ctxbitmap_flush(dev, file_priv);
 
 	mutex_lock(&dev->master_mutex);
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index d1730c5..d91e09f 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1242,6 +1242,7 @@ extern int drm_rmctx(struct drm_device *dev, void *data,
 extern int drm_ctxbitmap_init(struct drm_device *dev);
 extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
 extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
+extern void drm_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file);
 
 extern int drm_setsareactx(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv);
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 05/12] drm: drop i386 verification
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (3 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 04/12] drm: extract legacy ctxbitmap flushing David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-23 15:26 ` [PATCH 06/12] drm: fix __alpha__ PCI lookup David Herrmann
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

Linux doesn't run on i386, anymore. See:

    commit d55c5a93db2d5fa95f233ab153f594365d95b777
    Author: H. Peter Anvin <hpa@linux.intel.com>
    Date:   Wed Nov 28 11:50:24 2012 -0800

        x86, 386 removal: Remove CONFIG_CMPXCHG

        All 486+ CPUs support CMPXCHG, so remove the fallback 386 support
        code.

Furthermore, as the commit-message states, all 486+ CPUs support the
CMPXCHG instruction and thus even legacy DRM can run fine.

Drop the now superfluous "x86 == 3" check.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_fops.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index fb81d1c..a402061 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -210,10 +210,6 @@ out_unlock:
  */
 static int drm_cpu_valid(void)
 {
-#if defined(__i386__)
-	if (boot_cpu_data.x86 == 3)
-		return 0;	/* No cmpxchg on a 386 */
-#endif
 #if defined(__sparc__) && !defined(__sparc_v9__)
 	return 0;		/* No cmpxchg before v9 sparc. */
 #endif
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 06/12] drm: fix __alpha__ PCI lookup
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (4 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 05/12] drm: drop i386 verification David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-23 19:29   ` Daniel Vetter
  2014-07-23 15:26 ` [PATCH 07/12] drm: drop redundant drm_file->is_master David Herrmann
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

Testing the return value of list_entry() for NULL is a no-op (as it is
just a fancy container_of() / offsetof()). Drop the superfluous if-clause
and instead verify the actual root-node is available. This is probably
what it was meant to test for from the beginning, anyway.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_fops.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index a402061..afba0bf 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -330,11 +330,11 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 			dev->hose = pci_dev->sysdata;
 			pci_dev_put(pci_dev);
 		}
-		if (!dev->hose) {
+
+		if (!dev->hose && pci_root_buses.next) {
 			struct pci_bus *b = list_entry(pci_root_buses.next,
-				struct pci_bus, node);
-			if (b)
-				dev->hose = b->sysdata;
+						       struct pci_bus, node);
+			dev->hose = b->sysdata;
 		}
 	}
 #endif
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 07/12] drm: drop redundant drm_file->is_master
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (5 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 06/12] drm: fix __alpha__ PCI lookup David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-24  9:52   ` Daniel Vetter
  2014-07-23 15:26 ` [PATCH 08/12] drm: don't de-authenticate clients on master-close David Herrmann
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

The drm_file->is_master field is redundant as it's equivalent to:
    drm_file->master && drm_file->master == drm_file->minor->master

1) "=>"
  Whenever we set drm_file->is_master, we also set:
      drm_file->minor->master = drm_file->master;

  Whenever we clear drm_file->is_master, we also call:
      drm_master_put(&drm_file->minor->master);
  which implicitly clears it to NULL.

2) "<="
  minor->master cannot be set if it is non-NULL. Therefore, it stays as
  is unless a file drops it.

  If minor->master is NULL, it is only set by places that also adjust
  drm_file->is_master.

Therefore, we can safely drop is_master and replace it by an inline helper
that matches:
    drm_file->master && drm_file->master == drm_file->minor->master

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_crtc.c                 |  2 +-
 drivers/gpu/drm/drm_drv.c                  |  2 +-
 drivers/gpu/drm/drm_fops.c                 |  4 +---
 drivers/gpu/drm/drm_lock.c                 |  2 +-
 drivers/gpu/drm/drm_stub.c                 | 10 +++-------
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  4 ++--
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c        |  2 +-
 include/drm/drmP.h                         |  9 ++++++---
 8 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 1ccf5cb..dec0c77 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3188,7 +3188,7 @@ int drm_mode_getfb(struct drm_device *dev,
 	r->bpp = fb->bits_per_pixel;
 	r->pitch = fb->pitches[0];
 	if (fb->funcs->create_handle) {
-		if (file_priv->is_master || capable(CAP_SYS_ADMIN) ||
+		if (drm_is_master(file_priv) || capable(CAP_SYS_ADMIN) ||
 		    drm_is_control_client(file_priv)) {
 			ret = fb->funcs->create_handle(fb, file_priv,
 						       &r->handle);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 0cc1827..7aa8121 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -307,7 +307,7 @@ static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
 		return -EACCES;
 
 	/* MASTER is only for master or control clients */
-	if (unlikely((flags & DRM_MASTER) && !file_priv->is_master &&
+	if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) &&
 		     !drm_is_control_client(file_priv)))
 		return -EACCES;
 
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index afba0bf..f65087e 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -286,7 +286,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 			goto out_close;
 		}
 
-		priv->is_master = 1;
 		/* take another reference for the copy in the local file priv */
 		priv->master = drm_master_get(priv->minor->master);
 		priv->authenticated = 1;
@@ -452,7 +451,7 @@ int drm_release(struct inode *inode, struct file *filp)
 
 	mutex_lock(&dev->master_mutex);
 
-	if (file_priv->is_master) {
+	if (drm_is_master(file_priv)) {
 		struct drm_master *master = file_priv->master;
 		struct drm_file *temp;
 
@@ -488,7 +487,6 @@ int drm_release(struct inode *inode, struct file *filp)
 	/* drop the master reference held by the file priv */
 	if (file_priv->master)
 		drm_master_put(&file_priv->master);
-	file_priv->is_master = 0;
 	mutex_unlock(&dev->master_mutex);
 
 	mutex_lock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
index f645268..786401c 100644
--- a/drivers/gpu/drm/drm_lock.c
+++ b/drivers/gpu/drm/drm_lock.c
@@ -111,7 +111,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 	/* don't set the block all signals on the master process for now 
 	 * really probably not the correct answer but lets us debug xkb
  	 * xserver for now */
-	if (!file_priv->is_master) {
+	if (!drm_is_master(file_priv)) {
 		sigemptyset(&dev->sigmask);
 		sigaddset(&dev->sigmask, SIGSTOP);
 		sigaddset(&dev->sigmask, SIGTSTP);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 233ea20..18c9b3d 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -177,7 +177,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
 	int ret = 0;
 
 	mutex_lock(&dev->master_mutex);
-	if (file_priv->is_master)
+	if (drm_is_master(file_priv))
 		goto out_unlock;
 
 	if (file_priv->minor->master) {
@@ -191,13 +191,10 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
 	}
 
 	file_priv->minor->master = drm_master_get(file_priv->master);
-	file_priv->is_master = 1;
 	if (dev->driver->master_set) {
 		ret = dev->driver->master_set(dev, file_priv, false);
-		if (unlikely(ret != 0)) {
-			file_priv->is_master = 0;
+		if (unlikely(ret != 0))
 			drm_master_put(&file_priv->minor->master);
-		}
 	}
 
 out_unlock:
@@ -211,7 +208,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
 	int ret = -EINVAL;
 
 	mutex_lock(&dev->master_mutex);
-	if (!file_priv->is_master)
+	if (!drm_is_master(file_priv))
 		goto out_unlock;
 
 	if (!file_priv->minor->master)
@@ -221,7 +218,6 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
 	if (dev->driver->master_drop)
 		dev->driver->master_drop(dev, file_priv, false);
 	drm_master_put(&file_priv->minor->master);
-	file_priv->is_master = 0;
 
 out_unlock:
 	mutex_unlock(&dev->master_mutex);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 60998fc..2dd19da 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1260,7 +1260,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
 	flags = 0;
 	if (args->flags & I915_EXEC_SECURE) {
-		if (!file->is_master || !capable(CAP_SYS_ADMIN))
+		if (!drm_is_master(file) || !capable(CAP_SYS_ADMIN))
 		    return -EPERM;
 
 		flags |= I915_DISPATCH_SECURE;
@@ -1369,7 +1369,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		ret = i915_parse_cmds(ring,
 				      batch_obj,
 				      args->batch_start_offset,
-				      file->is_master);
+				      drm_is_master(file));
 		if (ret)
 			goto err;
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 18b54ac..63c4d6f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -990,7 +990,7 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev,
 	if (unlikely(ret != 0))
 		return ERR_PTR(-ERESTARTSYS);
 
-	if (file_priv->is_master) {
+	if (drm_is_master(file_priv)) {
 		mutex_unlock(&dev->master_mutex);
 		return NULL;
 	}
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index d91e09f..e1bb585 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -387,8 +387,6 @@ struct drm_prime_file_private {
 struct drm_file {
 	unsigned always_authenticated :1;
 	unsigned authenticated :1;
-	/* Whether we're master for a minor. Protected by master_mutex */
-	unsigned is_master :1;
 	/* true when the client has asked us to expose stereo 3D mode flags */
 	unsigned stereo_allowed :1;
 	/*
@@ -1034,7 +1032,7 @@ struct drm_device {
 	/** \name Locks */
 	/*@{ */
 	struct mutex struct_mutex;	/**< For others */
-	struct mutex master_mutex;      /**< For drm_minor::master and drm_file::is_master */
+	struct mutex master_mutex;      /**< For drm_minor::master */
 	/*@} */
 
 	/** \name Usage Counters */
@@ -1172,6 +1170,11 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv)
 	return file_priv->minor->type == DRM_MINOR_LEGACY;
 }
 
+static inline bool drm_is_master(const struct drm_file *file)
+{
+	return file->master && file->master == file->minor->master;
+}
+
 /******************************************************************/
 /** \name Internal function definitions */
 /*@{*/
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 08/12] drm: don't de-authenticate clients on master-close
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (6 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 07/12] drm: drop redundant drm_file->is_master David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-24  9:57   ` Daniel Vetter
  2014-07-23 15:26 ` [PATCH 09/12] drm: move module initialization to drm_stub.c David Herrmann
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

If an active DRM-Master closes its device, we deauthenticate all clients
on that master. However, if an inactive DRM-Master closes its device, we
do nothing. This is quite inconsistent and breaks several scenarios:

 1) If this was used as security mechanism, it fails horribly if a master
    closes a device while VT switched away. Furthermore, none of the few
    drivers using ->master_*() callbacks seems to require it, anyway.

 2) If you spawn weston (or any other non-UMS compositor) in background
    while another compositor is active, both will get assigned to the
    same "drm_master" object. If the foreground compositor now exits, all
    clients of both the foreground AND background compositor will be
    de-authenticated leading to unexpected behavior.

Stop this non-sense and keep clients authenticated. We don't do this when
dropping DRM-Master (i.e., switching VTs) so don't do it on active-close
either!

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_fops.c | 13 ++-----------
 include/drm/drmP.h         |  1 -
 2 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index f65087e..ff0a13f 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -252,8 +252,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 	priv->minor = minor;
 
 	/* for compatibility root is always authenticated */
-	priv->always_authenticated = capable(CAP_SYS_ADMIN);
-	priv->authenticated = priv->always_authenticated;
+	priv->authenticated = capable(CAP_SYS_ADMIN);
 	priv->lock_count = 0;
 
 	INIT_LIST_HEAD(&priv->lhead);
@@ -453,20 +452,12 @@ int drm_release(struct inode *inode, struct file *filp)
 
 	if (drm_is_master(file_priv)) {
 		struct drm_master *master = file_priv->master;
-		struct drm_file *temp;
-
-		mutex_lock(&dev->struct_mutex);
-		list_for_each_entry(temp, &dev->filelist, lhead) {
-			if ((temp->master == file_priv->master) &&
-			    (temp != file_priv))
-				temp->authenticated = temp->always_authenticated;
-		}
 
 		/**
 		 * Since the master is disappearing, so is the
 		 * possibility to lock.
 		 */
-
+		mutex_lock(&dev->struct_mutex);
 		if (master->lock.hw_lock) {
 			if (dev->sigdata.lock == master->lock.hw_lock)
 				dev->sigdata.lock = NULL;
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index e1bb585..48d2fe7 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -385,7 +385,6 @@ struct drm_prime_file_private {
 
 /** File private data */
 struct drm_file {
-	unsigned always_authenticated :1;
 	unsigned authenticated :1;
 	/* true when the client has asked us to expose stereo 3D mode flags */
 	unsigned stereo_allowed :1;
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 09/12] drm: move module initialization to drm_stub.c
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (7 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 08/12] drm: don't de-authenticate clients on master-close David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-23 15:26 ` [PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c David Herrmann
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

Most of the new DRM management functions are nowadays in drm_stub.c. By
moving the core module initialization to drm_stub.c we can make several
global variables static and keep the stub-open helper local.

The core files now look like this:
  drm_stub.c: Core management
   drm_drv.c: Ioctl dispatcher
 drm_ioctl.c: Actual ioctl backends
  drm_fops.c: Char-dev file-operations

A follow-up patch will move what is left from drm_drv.c into drm_ioctl.c.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_drv.c  |  59 -----------------------
 drivers/gpu/drm/drm_fops.c |  39 ---------------
 drivers/gpu/drm/drm_stub.c | 117 ++++++++++++++++++++++++++++++++++++++++++++-
 include/drm/drmP.h         |   4 --
 4 files changed, 115 insertions(+), 104 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7aa8121..190df83 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -171,65 +171,6 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
 
-/** File operations structure */
-static const struct file_operations drm_stub_fops = {
-	.owner = THIS_MODULE,
-	.open = drm_stub_open,
-	.llseek = noop_llseek,
-};
-
-static int __init drm_core_init(void)
-{
-	int ret = -ENOMEM;
-
-	drm_global_init();
-	drm_connector_ida_init();
-	idr_init(&drm_minors_idr);
-
-	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
-		goto err_p1;
-
-	drm_class = drm_sysfs_create(THIS_MODULE, "drm");
-	if (IS_ERR(drm_class)) {
-		printk(KERN_ERR "DRM: Error creating drm class.\n");
-		ret = PTR_ERR(drm_class);
-		goto err_p2;
-	}
-
-	drm_debugfs_root = debugfs_create_dir("dri", NULL);
-	if (!drm_debugfs_root) {
-		DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
-		ret = -1;
-		goto err_p3;
-	}
-
-	DRM_INFO("Initialized %s %d.%d.%d %s\n",
-		 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
-	return 0;
-err_p3:
-	drm_sysfs_destroy();
-err_p2:
-	unregister_chrdev(DRM_MAJOR, "drm");
-
-	idr_destroy(&drm_minors_idr);
-err_p1:
-	return ret;
-}
-
-static void __exit drm_core_exit(void)
-{
-	debugfs_remove(drm_debugfs_root);
-	drm_sysfs_destroy();
-
-	unregister_chrdev(DRM_MAJOR, "drm");
-
-	drm_connector_ida_destroy();
-	idr_destroy(&drm_minors_idr);
-}
-
-module_init(drm_core_init);
-module_exit(drm_core_exit);
-
 /**
  * Copy and IOCTL return string to user space
  */
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index ff0a13f..a3bf155 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -165,45 +165,6 @@ err_minor:
 EXPORT_SYMBOL(drm_open);
 
 /**
- * File \c open operation.
- *
- * \param inode device inode.
- * \param filp file pointer.
- *
- * Puts the dev->fops corresponding to the device minor number into
- * \p filp, call the \c open method, and restore the file operations.
- */
-int drm_stub_open(struct inode *inode, struct file *filp)
-{
-	struct drm_device *dev;
-	struct drm_minor *minor;
-	int err = -ENODEV;
-	const struct file_operations *new_fops;
-
-	DRM_DEBUG("\n");
-
-	mutex_lock(&drm_global_mutex);
-	minor = drm_minor_acquire(iminor(inode));
-	if (IS_ERR(minor))
-		goto out_unlock;
-
-	dev = minor->dev;
-	new_fops = fops_get(dev->driver->fops);
-	if (!new_fops)
-		goto out_release;
-
-	replace_fops(filp, new_fops);
-	if (filp->f_op->open)
-		err = filp->f_op->open(inode, filp);
-
-out_release:
-	drm_minor_release(minor);
-out_unlock:
-	mutex_unlock(&drm_global_mutex);
-	return err;
-}
-
-/**
  * Check whether DRI will run on this CPU.
  *
  * \return non-zero if the DRI will run on this CPU, or zero otherwise.
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 18c9b3d..b249f14 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -26,6 +26,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/debugfs.h>
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -61,10 +62,10 @@ module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600)
 module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
 
 static DEFINE_SPINLOCK(drm_minor_lock);
-struct idr drm_minors_idr;
+static struct idr drm_minors_idr;
 
 struct class *drm_class;
-struct dentry *drm_debugfs_root;
+static struct dentry *drm_debugfs_root;
 
 int drm_err(const char *func, const char *format, ...)
 {
@@ -787,3 +788,115 @@ int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...)
 	return dev->unique ? 0 : -ENOMEM;
 }
 EXPORT_SYMBOL(drm_dev_set_unique);
+
+/*
+ * DRM Core
+ * The DRM core module initializes all global DRM objects and makes them
+ * available to drivers. Once setup, drivers can probe their respective
+ * devices.
+ * Currently, core management includes:
+ *  - The "DRM-Global" key/value database
+ *  - Global ID management for connectors
+ *  - DRM major number allocation
+ *  - DRM minor management
+ *  - DRM sysfs class
+ *  - DRM debugfs root
+ *
+ * Furthermore, the DRM core provides dynamic char-dev lookups. For each
+ * interface registered on a DRM device, you can request minor numbers from DRM
+ * core. DRM core takes care of major-number management and char-dev
+ * registration. A stub ->open() callback forwards any open() requests to the
+ * registered minor.
+ */
+
+static int drm_stub_open(struct inode *inode, struct file *filp)
+{
+	const struct file_operations *new_fops;
+	struct drm_minor *minor;
+	int err;
+
+	DRM_DEBUG("\n");
+
+	mutex_lock(&drm_global_mutex);
+	minor = drm_minor_acquire(iminor(inode));
+	if (IS_ERR(minor)) {
+		err = PTR_ERR(minor);
+		goto out_unlock;
+	}
+
+	new_fops = fops_get(minor->dev->driver->fops);
+	if (!new_fops) {
+		err = -ENODEV;
+		goto out_release;
+	}
+
+	replace_fops(filp, new_fops);
+	if (filp->f_op->open)
+		err = filp->f_op->open(inode, filp);
+	else
+		err = 0;
+
+out_release:
+	drm_minor_release(minor);
+out_unlock:
+	mutex_unlock(&drm_global_mutex);
+	return err;
+}
+
+static const struct file_operations drm_stub_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_stub_open,
+	.llseek = noop_llseek,
+};
+
+static int __init drm_core_init(void)
+{
+	int ret = -ENOMEM;
+
+	drm_global_init();
+	drm_connector_ida_init();
+	idr_init(&drm_minors_idr);
+
+	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
+		goto err_p1;
+
+	drm_class = drm_sysfs_create(THIS_MODULE, "drm");
+	if (IS_ERR(drm_class)) {
+		printk(KERN_ERR "DRM: Error creating drm class.\n");
+		ret = PTR_ERR(drm_class);
+		goto err_p2;
+	}
+
+	drm_debugfs_root = debugfs_create_dir("dri", NULL);
+	if (!drm_debugfs_root) {
+		DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
+		ret = -1;
+		goto err_p3;
+	}
+
+	DRM_INFO("Initialized %s %d.%d.%d %s\n",
+		 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
+	return 0;
+err_p3:
+	drm_sysfs_destroy();
+err_p2:
+	unregister_chrdev(DRM_MAJOR, "drm");
+
+	idr_destroy(&drm_minors_idr);
+err_p1:
+	return ret;
+}
+
+static void __exit drm_core_exit(void)
+{
+	debugfs_remove(drm_debugfs_root);
+	drm_sysfs_destroy();
+
+	unregister_chrdev(DRM_MAJOR, "drm");
+
+	drm_connector_ida_destroy();
+	idr_destroy(&drm_minors_idr);
+}
+
+module_init(drm_core_init);
+module_exit(drm_core_exit);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 48d2fe7..17dd67a 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1189,7 +1189,6 @@ extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
 				/* Device support (drm_fops.h) */
 extern struct mutex drm_global_mutex;
 extern int drm_open(struct inode *inode, struct file *filp);
-extern int drm_stub_open(struct inode *inode, struct file *filp);
 extern ssize_t drm_read(struct file *filp, char __user *buffer,
 			size_t count, loff_t *offset);
 extern int drm_release(struct inode *inode, struct file *filp);
@@ -1376,9 +1375,6 @@ extern unsigned int drm_timestamp_precision;
 extern unsigned int drm_timestamp_monotonic;
 
 extern struct class *drm_class;
-extern struct dentry *drm_debugfs_root;
-
-extern struct idr drm_minors_idr;
 
 extern struct drm_local_map *drm_getsarea(struct drm_device *dev);
 
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (8 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 09/12] drm: move module initialization to drm_stub.c David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-23 16:16   ` David Herrmann
  2014-07-23 19:33   ` Daniel Vetter
  2014-07-23 15:26 ` [PATCH 11/12] drm: make minor->index available early David Herrmann
                   ` (2 subsequent siblings)
  12 siblings, 2 replies; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

All that is left in drm_drv.c is ioctl management. Merge it into
drm_ioctl.c so we have all ioctl management in one file (and the name is
much more fitting).

Maybe we should now rename drm_stub.c to drm_drv.c again?

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_drv.c   | 412 --------------------------------------------
 drivers/gpu/drm/drm_ioctl.c | 369 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 361 insertions(+), 420 deletions(-)
 delete mode 100644 drivers/gpu/drm/drm_drv.c

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
deleted file mode 100644
index 190df83..0000000
--- a/drivers/gpu/drm/drm_drv.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/**
- * \file drm_drv.c
- * Generic driver template
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- *
- * To use this template, you must at least define the following (samples
- * given for the MGA driver):
- *
- * \code
- * #define DRIVER_AUTHOR	"VA Linux Systems, Inc."
- *
- * #define DRIVER_NAME		"mga"
- * #define DRIVER_DESC		"Matrox G200/G400"
- * #define DRIVER_DATE		"20001127"
- *
- * #define drm_x		mga_##x
- * \endcode
- */
-
-/*
- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <drm/drmP.h>
-#include <drm/drm_core.h>
-
-
-static int drm_version(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv);
-
-#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
-	[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
-
-/** Ioctl table */
-static const struct drm_ioctl_desc drm_ioctls[] = {
-	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
-	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-#if __OS_HAS_AGP
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-#endif
-
-	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
-
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-};
-
-#define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
-
-/**
- * Copy and IOCTL return string to user space
- */
-static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
-{
-	int len;
-
-	/* don't overflow userbuf */
-	len = strlen(value);
-	if (len > *buf_len)
-		len = *buf_len;
-
-	/* let userspace know exact length of driver value (which could be
-	 * larger than the userspace-supplied buffer) */
-	*buf_len = strlen(value);
-
-	/* finally, try filling in the userbuf */
-	if (len && buf)
-		if (copy_to_user(buf, value, len))
-			return -EFAULT;
-	return 0;
-}
-
-/**
- * Get version information
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_version structure.
- * \return zero on success or negative number on failure.
- *
- * Fills in the version information in \p arg.
- */
-static int drm_version(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	struct drm_version *version = data;
-	int err;
-
-	version->version_major = dev->driver->major;
-	version->version_minor = dev->driver->minor;
-	version->version_patchlevel = dev->driver->patchlevel;
-	err = drm_copy_field(version->name, &version->name_len,
-			dev->driver->name);
-	if (!err)
-		err = drm_copy_field(version->date, &version->date_len,
-				dev->driver->date);
-	if (!err)
-		err = drm_copy_field(version->desc, &version->desc_len,
-				dev->driver->desc);
-
-	return err;
-}
-
-/**
- * drm_ioctl_permit - Check ioctl permissions against caller
- *
- * @flags: ioctl permission flags.
- * @file_priv: Pointer to struct drm_file identifying the caller.
- *
- * Checks whether the caller is allowed to run an ioctl with the
- * indicated permissions. If so, returns zero. Otherwise returns an
- * error code suitable for ioctl return.
- */
-static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
-{
-	/* ROOT_ONLY is only for CAP_SYS_ADMIN */
-	if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
-		return -EACCES;
-
-	/* AUTH is only for authenticated or render client */
-	if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
-		     !file_priv->authenticated))
-		return -EACCES;
-
-	/* MASTER is only for master or control clients */
-	if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) &&
-		     !drm_is_control_client(file_priv)))
-		return -EACCES;
-
-	/* Control clients must be explicitly allowed */
-	if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
-		     drm_is_control_client(file_priv)))
-		return -EACCES;
-
-	/* Render clients must be explicitly allowed */
-	if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
-		     drm_is_render_client(file_priv)))
-		return -EACCES;
-
-	return 0;
-}
-
-/**
- * Called whenever a process performs an ioctl on /dev/drm.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
- *
- * Looks up the ioctl function in the ::ioctls table, checking for root
- * previleges if so required, and dispatches to the respective function.
- */
-long drm_ioctl(struct file *filp,
-	      unsigned int cmd, unsigned long arg)
-{
-	struct drm_file *file_priv = filp->private_data;
-	struct drm_device *dev;
-	const struct drm_ioctl_desc *ioctl = NULL;
-	drm_ioctl_t *func;
-	unsigned int nr = DRM_IOCTL_NR(cmd);
-	int retcode = -EINVAL;
-	char stack_kdata[128];
-	char *kdata = NULL;
-	unsigned int usize, asize;
-
-	dev = file_priv->minor->dev;
-
-	if (drm_device_is_unplugged(dev))
-		return -ENODEV;
-
-	if ((nr >= DRM_CORE_IOCTL_COUNT) &&
-	    ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
-		goto err_i1;
-	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
-	    (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
-		u32 drv_size;
-		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
-		drv_size = _IOC_SIZE(ioctl->cmd_drv);
-		usize = asize = _IOC_SIZE(cmd);
-		if (drv_size > asize)
-			asize = drv_size;
-		cmd = ioctl->cmd_drv;
-	}
-	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
-		u32 drv_size;
-
-		ioctl = &drm_ioctls[nr];
-
-		drv_size = _IOC_SIZE(ioctl->cmd);
-		usize = asize = _IOC_SIZE(cmd);
-		if (drv_size > asize)
-			asize = drv_size;
-
-		cmd = ioctl->cmd;
-	} else
-		goto err_i1;
-
-	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
-		  task_pid_nr(current),
-		  (long)old_encode_dev(file_priv->minor->kdev->devt),
-		  file_priv->authenticated, ioctl->name);
-
-	/* Do not trust userspace, use our own definition */
-	func = ioctl->func;
-
-	if (unlikely(!func)) {
-		DRM_DEBUG("no function\n");
-		retcode = -EINVAL;
-		goto err_i1;
-	}
-
-	retcode = drm_ioctl_permit(ioctl->flags, file_priv);
-	if (unlikely(retcode))
-		goto err_i1;
-
-	if (cmd & (IOC_IN | IOC_OUT)) {
-		if (asize <= sizeof(stack_kdata)) {
-			kdata = stack_kdata;
-		} else {
-			kdata = kmalloc(asize, GFP_KERNEL);
-			if (!kdata) {
-				retcode = -ENOMEM;
-				goto err_i1;
-			}
-		}
-		if (asize > usize)
-			memset(kdata + usize, 0, asize - usize);
-	}
-
-	if (cmd & IOC_IN) {
-		if (copy_from_user(kdata, (void __user *)arg,
-				   usize) != 0) {
-			retcode = -EFAULT;
-			goto err_i1;
-		}
-	} else if (cmd & IOC_OUT) {
-		memset(kdata, 0, usize);
-	}
-
-	if (ioctl->flags & DRM_UNLOCKED)
-		retcode = func(dev, kdata, file_priv);
-	else {
-		mutex_lock(&drm_global_mutex);
-		retcode = func(dev, kdata, file_priv);
-		mutex_unlock(&drm_global_mutex);
-	}
-
-	if (cmd & IOC_OUT) {
-		if (copy_to_user((void __user *)arg, kdata,
-				 usize) != 0)
-			retcode = -EFAULT;
-	}
-
-      err_i1:
-	if (!ioctl)
-		DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
-			  task_pid_nr(current),
-			  (long)old_encode_dev(file_priv->minor->kdev->devt),
-			  file_priv->authenticated, cmd, nr);
-
-	if (kdata != stack_kdata)
-		kfree(kdata);
-	if (retcode)
-		DRM_DEBUG("ret = %d\n", retcode);
-	return retcode;
-}
-EXPORT_SYMBOL(drm_ioctl);
-
-/**
- * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
- *
- * @nr: Ioctl number.
- * @flags: Where to return the ioctl permission flags
- */
-bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
-{
-	if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
-	    (nr < DRM_COMMAND_BASE)) {
-		*flags = drm_ioctls[nr].flags;
-		return true;
-	}
-
-	return false;
-}
-EXPORT_SYMBOL(drm_ioctl_flags);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index ad66f96..22ca14d 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -1,11 +1,3 @@
-/**
- * \file drm_ioctl.c
- * IOCTL processing for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
 /*
  * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
  *
@@ -13,6 +5,9 @@
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
+ * Author Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author Gareth Hughes <gareth@valinux.com>
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -42,6 +37,124 @@
 #include <asm/mtrr.h>
 #endif
 
+static int drm_version(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv);
+
+#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
+	[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
+
+/** Ioctl table */
+static const struct drm_ioctl_desc drm_ioctls[] = {
+	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+#if __OS_HAS_AGP
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+#endif
+
+	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+};
+
+#define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
+
 /**
  * Get the bus id.
  *
@@ -415,3 +528,243 @@ int drm_noop(struct drm_device *dev, void *data,
 	return 0;
 }
 EXPORT_SYMBOL(drm_noop);
+
+/**
+ * Copy and IOCTL return string to user space
+ */
+static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
+{
+	int len;
+
+	/* don't overflow userbuf */
+	len = strlen(value);
+	if (len > *buf_len)
+		len = *buf_len;
+
+	/* let userspace know exact length of driver value (which could be
+	 * larger than the userspace-supplied buffer) */
+	*buf_len = strlen(value);
+
+	/* finally, try filling in the userbuf */
+	if (len && buf)
+		if (copy_to_user(buf, value, len))
+			return -EFAULT;
+	return 0;
+}
+
+/**
+ * Get version information
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_version structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Fills in the version information in \p arg.
+ */
+static int drm_version(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	struct drm_version *version = data;
+	int err;
+
+	version->version_major = dev->driver->major;
+	version->version_minor = dev->driver->minor;
+	version->version_patchlevel = dev->driver->patchlevel;
+	err = drm_copy_field(version->name, &version->name_len,
+			dev->driver->name);
+	if (!err)
+		err = drm_copy_field(version->date, &version->date_len,
+				dev->driver->date);
+	if (!err)
+		err = drm_copy_field(version->desc, &version->desc_len,
+				dev->driver->desc);
+
+	return err;
+}
+
+/**
+ * drm_ioctl_permit - Check ioctl permissions against caller
+ *
+ * @flags: ioctl permission flags.
+ * @file_priv: Pointer to struct drm_file identifying the caller.
+ *
+ * Checks whether the caller is allowed to run an ioctl with the
+ * indicated permissions. If so, returns zero. Otherwise returns an
+ * error code suitable for ioctl return.
+ */
+static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
+{
+	/* ROOT_ONLY is only for CAP_SYS_ADMIN */
+	if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
+		return -EACCES;
+
+	/* AUTH is only for authenticated or render client */
+	if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
+		     !file_priv->authenticated))
+		return -EACCES;
+
+	/* MASTER is only for master or control clients */
+	if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) &&
+		     !drm_is_control_client(file_priv)))
+		return -EACCES;
+
+	/* Control clients must be explicitly allowed */
+	if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
+		     drm_is_control_client(file_priv)))
+		return -EACCES;
+
+	/* Render clients must be explicitly allowed */
+	if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
+		     drm_is_render_client(file_priv)))
+		return -EACCES;
+
+	return 0;
+}
+
+/**
+ * Called whenever a process performs an ioctl on /dev/drm.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ *
+ * Looks up the ioctl function in the ::ioctls table, checking for root
+ * previleges if so required, and dispatches to the respective function.
+ */
+long drm_ioctl(struct file *filp,
+	      unsigned int cmd, unsigned long arg)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct drm_device *dev;
+	const struct drm_ioctl_desc *ioctl = NULL;
+	drm_ioctl_t *func;
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+	int retcode = -EINVAL;
+	char stack_kdata[128];
+	char *kdata = NULL;
+	unsigned int usize, asize;
+
+	dev = file_priv->minor->dev;
+
+	if (drm_device_is_unplugged(dev))
+		return -ENODEV;
+
+	if ((nr >= DRM_CORE_IOCTL_COUNT) &&
+	    ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
+		goto err_i1;
+	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
+	    (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+		u32 drv_size;
+		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+		drv_size = _IOC_SIZE(ioctl->cmd_drv);
+		usize = asize = _IOC_SIZE(cmd);
+		if (drv_size > asize)
+			asize = drv_size;
+		cmd = ioctl->cmd_drv;
+	}
+	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
+		u32 drv_size;
+
+		ioctl = &drm_ioctls[nr];
+
+		drv_size = _IOC_SIZE(ioctl->cmd);
+		usize = asize = _IOC_SIZE(cmd);
+		if (drv_size > asize)
+			asize = drv_size;
+
+		cmd = ioctl->cmd;
+	} else
+		goto err_i1;
+
+	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
+		  task_pid_nr(current),
+		  (long)old_encode_dev(file_priv->minor->kdev->devt),
+		  file_priv->authenticated, ioctl->name);
+
+	/* Do not trust userspace, use our own definition */
+	func = ioctl->func;
+
+	if (unlikely(!func)) {
+		DRM_DEBUG("no function\n");
+		retcode = -EINVAL;
+		goto err_i1;
+	}
+
+	retcode = drm_ioctl_permit(ioctl->flags, file_priv);
+	if (unlikely(retcode))
+		goto err_i1;
+
+	if (cmd & (IOC_IN | IOC_OUT)) {
+		if (asize <= sizeof(stack_kdata)) {
+			kdata = stack_kdata;
+		} else {
+			kdata = kmalloc(asize, GFP_KERNEL);
+			if (!kdata) {
+				retcode = -ENOMEM;
+				goto err_i1;
+			}
+		}
+		if (asize > usize)
+			memset(kdata + usize, 0, asize - usize);
+	}
+
+	if (cmd & IOC_IN) {
+		if (copy_from_user(kdata, (void __user *)arg,
+				   usize) != 0) {
+			retcode = -EFAULT;
+			goto err_i1;
+		}
+	} else if (cmd & IOC_OUT) {
+		memset(kdata, 0, usize);
+	}
+
+	if (ioctl->flags & DRM_UNLOCKED)
+		retcode = func(dev, kdata, file_priv);
+	else {
+		mutex_lock(&drm_global_mutex);
+		retcode = func(dev, kdata, file_priv);
+		mutex_unlock(&drm_global_mutex);
+	}
+
+	if (cmd & IOC_OUT) {
+		if (copy_to_user((void __user *)arg, kdata,
+				 usize) != 0)
+			retcode = -EFAULT;
+	}
+
+      err_i1:
+	if (!ioctl)
+		DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
+			  task_pid_nr(current),
+			  (long)old_encode_dev(file_priv->minor->kdev->devt),
+			  file_priv->authenticated, cmd, nr);
+
+	if (kdata != stack_kdata)
+		kfree(kdata);
+	if (retcode)
+		DRM_DEBUG("ret = %d\n", retcode);
+	return retcode;
+}
+EXPORT_SYMBOL(drm_ioctl);
+
+/**
+ * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
+ *
+ * @nr: Ioctl number.
+ * @flags: Where to return the ioctl permission flags
+ */
+bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
+{
+	if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
+	    (nr < DRM_COMMAND_BASE)) {
+		*flags = drm_ioctls[nr].flags;
+		return true;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL(drm_ioctl_flags);
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 11/12] drm: make minor->index available early
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (9 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-24 10:03   ` Daniel Vetter
  2014-07-23 15:26 ` [PATCH 12/12] drm: make sysfs device always available for minors David Herrmann
  2014-07-23 16:24 ` [PATCH 00/12] DRM: Random Cleanups Alex Deucher
  12 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

Instead of allocating the minor-index during registration, we now do this
during allocation. This way, debug-messages between minor-allocation and
minor-registration will now use the correct minor instead of 0. Same is
done for unregistration vs. free, so debug-messages between
device-shutdown and device-destruction show proper indices.

Even though minor-indices are allocated early, we don't enable minor
lookup early. Instead, we keep the entry set to NULL and replace it during
registration / unregistration. This way, the index is allocated but lookup
only works if registered.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_stub.c | 84 +++++++++++++++++++++++++---------------------
 1 file changed, 46 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index b249f14..8b24db5 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -256,6 +256,8 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
 static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
 {
 	struct drm_minor *minor;
+	unsigned long flags;
+	int r;
 
 	minor = kzalloc(sizeof(*minor), GFP_KERNEL);
 	if (!minor)
@@ -264,57 +266,68 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
 	minor->type = type;
 	minor->dev = dev;
 
+	idr_preload(GFP_KERNEL);
+	spin_lock_irqsave(&drm_minor_lock, flags);
+	r = idr_alloc(&drm_minors_idr,
+		      NULL,
+		      64 * type,
+		      64 * (type + 1),
+		      GFP_NOWAIT);
+	spin_unlock_irqrestore(&drm_minor_lock, flags);
+	idr_preload_end();
+
+	if (r < 0)
+		goto err_free;
+
+	minor->index = r;
+
 	*drm_minor_get_slot(dev, type) = minor;
 	return 0;
+
+err_free:
+	kfree(minor);
+	return r;
 }
 
 static void drm_minor_free(struct drm_device *dev, unsigned int type)
 {
-	struct drm_minor **slot;
+	struct drm_minor **slot, *minor;
+	unsigned long flags;
 
 	slot = drm_minor_get_slot(dev, type);
-	if (*slot) {
-		drm_mode_group_destroy(&(*slot)->mode_group);
-		kfree(*slot);
-		*slot = NULL;
-	}
+	minor = *slot;
+	if (!minor)
+		return;
+
+	drm_mode_group_destroy(&minor->mode_group);
+
+	spin_lock_irqsave(&drm_minor_lock, flags);
+	idr_remove(&drm_minors_idr, minor->index);
+	spin_unlock_irqrestore(&drm_minor_lock, flags);
+
+	kfree(minor);
+	*slot = NULL;
 }
 
 static int drm_minor_register(struct drm_device *dev, unsigned int type)
 {
-	struct drm_minor *new_minor;
+	struct drm_minor *minor;
 	unsigned long flags;
 	int ret;
-	int minor_id;
 
 	DRM_DEBUG("\n");
 
-	new_minor = *drm_minor_get_slot(dev, type);
-	if (!new_minor)
+	minor = *drm_minor_get_slot(dev, type);
+	if (!minor)
 		return 0;
 
-	idr_preload(GFP_KERNEL);
-	spin_lock_irqsave(&drm_minor_lock, flags);
-	minor_id = idr_alloc(&drm_minors_idr,
-			     NULL,
-			     64 * type,
-			     64 * (type + 1),
-			     GFP_NOWAIT);
-	spin_unlock_irqrestore(&drm_minor_lock, flags);
-	idr_preload_end();
-
-	if (minor_id < 0)
-		return minor_id;
-
-	new_minor->index = minor_id;
-
-	ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
+	ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
 	if (ret) {
 		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
-		goto err_id;
+		return ret;
 	}
 
-	ret = drm_sysfs_device_add(new_minor);
+	ret = drm_sysfs_device_add(minor);
 	if (ret) {
 		DRM_ERROR("DRM: Error sysfs_device_add.\n");
 		goto err_debugfs;
@@ -322,19 +335,14 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
 
 	/* replace NULL with @minor so lookups will succeed from now on */
 	spin_lock_irqsave(&drm_minor_lock, flags);
-	idr_replace(&drm_minors_idr, new_minor, new_minor->index);
+	idr_replace(&drm_minors_idr, minor, minor->index);
 	spin_unlock_irqrestore(&drm_minor_lock, flags);
 
-	DRM_DEBUG("new minor assigned %d\n", minor_id);
+	DRM_DEBUG("new minor registered %d\n", minor->index);
 	return 0;
 
 err_debugfs:
-	drm_debugfs_cleanup(new_minor);
-err_id:
-	spin_lock_irqsave(&drm_minor_lock, flags);
-	idr_remove(&drm_minors_idr, minor_id);
-	spin_unlock_irqrestore(&drm_minor_lock, flags);
-	new_minor->index = 0;
+	drm_debugfs_cleanup(minor);
 	return ret;
 }
 
@@ -347,10 +355,10 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
 	if (!minor || !minor->kdev)
 		return;
 
+	/* replace @minor with NULL so lookups will fail from now on */
 	spin_lock_irqsave(&drm_minor_lock, flags);
-	idr_remove(&drm_minors_idr, minor->index);
+	idr_replace(&drm_minors_idr, NULL, minor->index);
 	spin_unlock_irqrestore(&drm_minor_lock, flags);
-	minor->index = 0;
 
 	drm_debugfs_cleanup(minor);
 	drm_sysfs_device_remove(minor);
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 12/12] drm: make sysfs device always available for minors
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (10 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 11/12] drm: make minor->index available early David Herrmann
@ 2014-07-23 15:26 ` David Herrmann
  2014-07-24 10:36   ` Daniel Vetter
  2014-07-23 16:24 ` [PATCH 00/12] DRM: Random Cleanups Alex Deucher
  12 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-23 15:26 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

For each minor we allocate a sysfs device as minor->kdev. Currently, this
is allocated and registered in drm_minor_register(). This makes it
impossible to add sysfs-attributes to the device before it is registered.
Therefore, they are not added atomically, nor can we move device_add()
*after* ->load() is called.

This patch makes minor->kdev available early, but only adds the device
during minor-registration.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_stub.c  | 22 ++++++++---
 drivers/gpu/drm/drm_sysfs.c | 90 +++++++++++++++++++--------------------------
 include/drm/drmP.h          |  3 +-
 3 files changed, 54 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 8b24db5..09c6bfb 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -281,9 +281,19 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
 
 	minor->index = r;
 
+	minor->kdev = drm_sysfs_minor_alloc(minor);
+	if (IS_ERR(minor->kdev)) {
+		r = PTR_ERR(minor->kdev);
+		goto err_index;
+	}
+
 	*drm_minor_get_slot(dev, type) = minor;
 	return 0;
 
+err_index:
+	spin_lock_irqsave(&drm_minor_lock, flags);
+	idr_remove(&drm_minors_idr, minor->index);
+	spin_unlock_irqrestore(&drm_minor_lock, flags);
 err_free:
 	kfree(minor);
 	return r;
@@ -300,6 +310,7 @@ static void drm_minor_free(struct drm_device *dev, unsigned int type)
 		return;
 
 	drm_mode_group_destroy(&minor->mode_group);
+	put_device(minor->kdev);
 
 	spin_lock_irqsave(&drm_minor_lock, flags);
 	idr_remove(&drm_minors_idr, minor->index);
@@ -327,11 +338,9 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
 		return ret;
 	}
 
-	ret = drm_sysfs_device_add(minor);
-	if (ret) {
-		DRM_ERROR("DRM: Error sysfs_device_add.\n");
+	ret = device_add(minor->kdev);
+	if (ret)
 		goto err_debugfs;
-	}
 
 	/* replace NULL with @minor so lookups will succeed from now on */
 	spin_lock_irqsave(&drm_minor_lock, flags);
@@ -352,7 +361,7 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
 	unsigned long flags;
 
 	minor = *drm_minor_get_slot(dev, type);
-	if (!minor || !minor->kdev)
+	if (!minor || !device_is_registered(minor->kdev))
 		return;
 
 	/* replace @minor with NULL so lookups will fail from now on */
@@ -360,8 +369,9 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
 	idr_replace(&drm_minors_idr, NULL, minor->index);
 	spin_unlock_irqrestore(&drm_minor_lock, flags);
 
+	device_del(minor->kdev);
+	dev_set_drvdata(minor->kdev, NULL); /* safety belt */
 	drm_debugfs_cleanup(minor);
-	drm_sysfs_device_remove(minor);
 }
 
 /**
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 7827dad..ab1a5f6 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -493,71 +493,55 @@ static void drm_sysfs_release(struct device *dev)
 }
 
 /**
- * drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @dev: DRM device to be added
- * @head: DRM head in question
+ * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
+ * @minor: minor to allocate sysfs device for
  *
- * Add a DRM device to the DRM's device model class.  We use @dev's PCI device
- * as the parent for the Linux device, and make sure it has a file containing
- * the driver we're using (for userspace compatibility).
+ * This allocates a new sysfs device for @minor and returns it. The device is
+ * not registered nor linked. The caller has to use device_add() and
+ * device_del() to register and unregister it.
+ *
+ * Note that dev_get_drvdata() on the new device will return the minor.
+ * However, the device does not hold a ref-count to the minor nor to the
+ * underlying drm_device. This is unproblematic as long as you access the
+ * private data only in sysfs callbacks. device_del() disables those
+ * synchronously, so they cannot be called after you cleanup a minor.
  */
-int drm_sysfs_device_add(struct drm_minor *minor)
+struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
 {
-	char *minor_str;
+	const char *minor_str;
+	struct device *kdev;
 	int r;
 
 	if (minor->type == DRM_MINOR_CONTROL)
 		minor_str = "controlD%d";
-        else if (minor->type == DRM_MINOR_RENDER)
-                minor_str = "renderD%d";
-        else
-                minor_str = "card%d";
-
-	minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
-	if (!minor->kdev) {
-		r = -ENOMEM;
-		goto error;
-	}
-
-	device_initialize(minor->kdev);
-	minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index);
-	minor->kdev->class = drm_class;
-	minor->kdev->type = &drm_sysfs_device_minor;
-	minor->kdev->parent = minor->dev->dev;
-	minor->kdev->release = drm_sysfs_release;
-	dev_set_drvdata(minor->kdev, minor);
-
-	r = dev_set_name(minor->kdev, minor_str, minor->index);
+	else if (minor->type == DRM_MINOR_RENDER)
+		minor_str = "renderD%d";
+	else
+		minor_str = "card%d";
+
+	kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
+	if (!kdev)
+		return ERR_PTR(-ENOMEM);
+
+	device_initialize(kdev);
+	kdev->devt = MKDEV(DRM_MAJOR, minor->index);
+	kdev->class = drm_class;
+	kdev->type = &drm_sysfs_device_minor;
+	kdev->parent = minor->dev->dev;
+	kdev->release = drm_sysfs_release;
+	dev_set_drvdata(kdev, minor);
+
+	r = dev_set_name(kdev, minor_str, minor->index);
 	if (r < 0)
-		goto error;
-
-	r = device_add(minor->kdev);
-	if (r < 0)
-		goto error;
-
-	return 0;
+		goto err_free;
 
-error:
-	DRM_ERROR("device create failed %d\n", r);
-	put_device(minor->kdev);
-	return r;
-}
+	return kdev;
 
-/**
- * drm_sysfs_device_remove - remove DRM device
- * @dev: DRM device to remove
- *
- * This call unregisters and cleans up a class device that was created with a
- * call to drm_sysfs_device_add()
- */
-void drm_sysfs_device_remove(struct drm_minor *minor)
-{
-	if (minor->kdev)
-		device_unregister(minor->kdev);
-	minor->kdev = NULL;
+err_free:
+	put_device(kdev);
+	return ERR_PTR(r);
 }
 
-
 /**
  * drm_class_device_register - Register a struct device in the drm class.
  *
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 17dd67a..d28d337 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1492,9 +1492,8 @@ extern int drm_pci_set_unique(struct drm_device *dev,
 struct drm_sysfs_class;
 extern struct class *drm_sysfs_create(struct module *owner, char *name);
 extern void drm_sysfs_destroy(void);
-extern int drm_sysfs_device_add(struct drm_minor *minor);
+extern struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
 extern void drm_sysfs_hotplug_event(struct drm_device *dev);
-extern void drm_sysfs_device_remove(struct drm_minor *minor);
 extern int drm_sysfs_connector_add(struct drm_connector *connector);
 extern void drm_sysfs_connector_remove(struct drm_connector *connector);
 
-- 
2.0.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c
  2014-07-23 15:26 ` [PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c David Herrmann
@ 2014-07-23 16:16   ` David Herrmann
  2014-07-23 19:33   ` Daniel Vetter
  1 sibling, 0 replies; 39+ messages in thread
From: David Herrmann @ 2014-07-23 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter

Hi

On Wed, Jul 23, 2014 at 5:26 PM, David Herrmann <dh.herrmann@gmail.com> wrote:
> All that is left in drm_drv.c is ioctl management. Merge it into
> drm_ioctl.c so we have all ioctl management in one file (and the name is
> much more fitting).
>
> Maybe we should now rename drm_stub.c to drm_drv.c again?
>
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

This patch is missing:

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 61d9e9c..9dd9db9 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -6,7 +6,7 @@ ccflags-y := -Iinclude/drm
drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
drm_context.o drm_dma.o \
- drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
+ drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
drm_lock.o drm_memory.o drm_stub.o drm_vm.o \
drm_agpsupport.o drm_scatter.o drm_pci.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \


Thanks
David

> ---
>  drivers/gpu/drm/drm_drv.c   | 412 --------------------------------------------
>  drivers/gpu/drm/drm_ioctl.c | 369 ++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 361 insertions(+), 420 deletions(-)
>  delete mode 100644 drivers/gpu/drm/drm_drv.c
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> deleted file mode 100644
> index 190df83..0000000
> --- a/drivers/gpu/drm/drm_drv.c
> +++ /dev/null
> @@ -1,412 +0,0 @@
> -/**
> - * \file drm_drv.c
> - * Generic driver template
> - *
> - * \author Rickard E. (Rik) Faith <faith@valinux.com>
> - * \author Gareth Hughes <gareth@valinux.com>
> - *
> - * To use this template, you must at least define the following (samples
> - * given for the MGA driver):
> - *
> - * \code
> - * #define DRIVER_AUTHOR       "VA Linux Systems, Inc."
> - *
> - * #define DRIVER_NAME         "mga"
> - * #define DRIVER_DESC         "Matrox G200/G400"
> - * #define DRIVER_DATE         "20001127"
> - *
> - * #define drm_x               mga_##x
> - * \endcode
> - */
> -
> -/*
> - * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
> - *
> - * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
> - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
> - * All Rights Reserved.
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a
> - * copy of this software and associated documentation files (the "Software"),
> - * to deal in the Software without restriction, including without limitation
> - * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> - * and/or sell copies of the Software, and to permit persons to whom the
> - * Software is furnished to do so, subject to the following conditions:
> - *
> - * The above copyright notice and this permission notice (including the next
> - * paragraph) shall be included in all copies or substantial portions of the
> - * Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> - * OTHER DEALINGS IN THE SOFTWARE.
> - */
> -
> -#include <linux/debugfs.h>
> -#include <linux/slab.h>
> -#include <linux/export.h>
> -#include <drm/drmP.h>
> -#include <drm/drm_core.h>
> -
> -
> -static int drm_version(struct drm_device *dev, void *data,
> -                      struct drm_file *file_priv);
> -
> -#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
> -       [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
> -
> -/** Ioctl table */
> -static const struct drm_ioctl_desc drm_ioctls[] = {
> -       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
> -       DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -       DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
> -       DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
> -       DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
> -       DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
> -       DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
> -       DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -
> -#if __OS_HAS_AGP
> -       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
> -       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -#endif
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -       DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -};
> -
> -#define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
> -
> -/**
> - * Copy and IOCTL return string to user space
> - */
> -static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
> -{
> -       int len;
> -
> -       /* don't overflow userbuf */
> -       len = strlen(value);
> -       if (len > *buf_len)
> -               len = *buf_len;
> -
> -       /* let userspace know exact length of driver value (which could be
> -        * larger than the userspace-supplied buffer) */
> -       *buf_len = strlen(value);
> -
> -       /* finally, try filling in the userbuf */
> -       if (len && buf)
> -               if (copy_to_user(buf, value, len))
> -                       return -EFAULT;
> -       return 0;
> -}
> -
> -/**
> - * Get version information
> - *
> - * \param inode device inode.
> - * \param filp file pointer.
> - * \param cmd command.
> - * \param arg user argument, pointing to a drm_version structure.
> - * \return zero on success or negative number on failure.
> - *
> - * Fills in the version information in \p arg.
> - */
> -static int drm_version(struct drm_device *dev, void *data,
> -                      struct drm_file *file_priv)
> -{
> -       struct drm_version *version = data;
> -       int err;
> -
> -       version->version_major = dev->driver->major;
> -       version->version_minor = dev->driver->minor;
> -       version->version_patchlevel = dev->driver->patchlevel;
> -       err = drm_copy_field(version->name, &version->name_len,
> -                       dev->driver->name);
> -       if (!err)
> -               err = drm_copy_field(version->date, &version->date_len,
> -                               dev->driver->date);
> -       if (!err)
> -               err = drm_copy_field(version->desc, &version->desc_len,
> -                               dev->driver->desc);
> -
> -       return err;
> -}
> -
> -/**
> - * drm_ioctl_permit - Check ioctl permissions against caller
> - *
> - * @flags: ioctl permission flags.
> - * @file_priv: Pointer to struct drm_file identifying the caller.
> - *
> - * Checks whether the caller is allowed to run an ioctl with the
> - * indicated permissions. If so, returns zero. Otherwise returns an
> - * error code suitable for ioctl return.
> - */
> -static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
> -{
> -       /* ROOT_ONLY is only for CAP_SYS_ADMIN */
> -       if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
> -               return -EACCES;
> -
> -       /* AUTH is only for authenticated or render client */
> -       if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
> -                    !file_priv->authenticated))
> -               return -EACCES;
> -
> -       /* MASTER is only for master or control clients */
> -       if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) &&
> -                    !drm_is_control_client(file_priv)))
> -               return -EACCES;
> -
> -       /* Control clients must be explicitly allowed */
> -       if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
> -                    drm_is_control_client(file_priv)))
> -               return -EACCES;
> -
> -       /* Render clients must be explicitly allowed */
> -       if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
> -                    drm_is_render_client(file_priv)))
> -               return -EACCES;
> -
> -       return 0;
> -}
> -
> -/**
> - * Called whenever a process performs an ioctl on /dev/drm.
> - *
> - * \param inode device inode.
> - * \param file_priv DRM file private.
> - * \param cmd command.
> - * \param arg user argument.
> - * \return zero on success or negative number on failure.
> - *
> - * Looks up the ioctl function in the ::ioctls table, checking for root
> - * previleges if so required, and dispatches to the respective function.
> - */
> -long drm_ioctl(struct file *filp,
> -             unsigned int cmd, unsigned long arg)
> -{
> -       struct drm_file *file_priv = filp->private_data;
> -       struct drm_device *dev;
> -       const struct drm_ioctl_desc *ioctl = NULL;
> -       drm_ioctl_t *func;
> -       unsigned int nr = DRM_IOCTL_NR(cmd);
> -       int retcode = -EINVAL;
> -       char stack_kdata[128];
> -       char *kdata = NULL;
> -       unsigned int usize, asize;
> -
> -       dev = file_priv->minor->dev;
> -
> -       if (drm_device_is_unplugged(dev))
> -               return -ENODEV;
> -
> -       if ((nr >= DRM_CORE_IOCTL_COUNT) &&
> -           ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
> -               goto err_i1;
> -       if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
> -           (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
> -               u32 drv_size;
> -               ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
> -               drv_size = _IOC_SIZE(ioctl->cmd_drv);
> -               usize = asize = _IOC_SIZE(cmd);
> -               if (drv_size > asize)
> -                       asize = drv_size;
> -               cmd = ioctl->cmd_drv;
> -       }
> -       else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
> -               u32 drv_size;
> -
> -               ioctl = &drm_ioctls[nr];
> -
> -               drv_size = _IOC_SIZE(ioctl->cmd);
> -               usize = asize = _IOC_SIZE(cmd);
> -               if (drv_size > asize)
> -                       asize = drv_size;
> -
> -               cmd = ioctl->cmd;
> -       } else
> -               goto err_i1;
> -
> -       DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
> -                 task_pid_nr(current),
> -                 (long)old_encode_dev(file_priv->minor->kdev->devt),
> -                 file_priv->authenticated, ioctl->name);
> -
> -       /* Do not trust userspace, use our own definition */
> -       func = ioctl->func;
> -
> -       if (unlikely(!func)) {
> -               DRM_DEBUG("no function\n");
> -               retcode = -EINVAL;
> -               goto err_i1;
> -       }
> -
> -       retcode = drm_ioctl_permit(ioctl->flags, file_priv);
> -       if (unlikely(retcode))
> -               goto err_i1;
> -
> -       if (cmd & (IOC_IN | IOC_OUT)) {
> -               if (asize <= sizeof(stack_kdata)) {
> -                       kdata = stack_kdata;
> -               } else {
> -                       kdata = kmalloc(asize, GFP_KERNEL);
> -                       if (!kdata) {
> -                               retcode = -ENOMEM;
> -                               goto err_i1;
> -                       }
> -               }
> -               if (asize > usize)
> -                       memset(kdata + usize, 0, asize - usize);
> -       }
> -
> -       if (cmd & IOC_IN) {
> -               if (copy_from_user(kdata, (void __user *)arg,
> -                                  usize) != 0) {
> -                       retcode = -EFAULT;
> -                       goto err_i1;
> -               }
> -       } else if (cmd & IOC_OUT) {
> -               memset(kdata, 0, usize);
> -       }
> -
> -       if (ioctl->flags & DRM_UNLOCKED)
> -               retcode = func(dev, kdata, file_priv);
> -       else {
> -               mutex_lock(&drm_global_mutex);
> -               retcode = func(dev, kdata, file_priv);
> -               mutex_unlock(&drm_global_mutex);
> -       }
> -
> -       if (cmd & IOC_OUT) {
> -               if (copy_to_user((void __user *)arg, kdata,
> -                                usize) != 0)
> -                       retcode = -EFAULT;
> -       }
> -
> -      err_i1:
> -       if (!ioctl)
> -               DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
> -                         task_pid_nr(current),
> -                         (long)old_encode_dev(file_priv->minor->kdev->devt),
> -                         file_priv->authenticated, cmd, nr);
> -
> -       if (kdata != stack_kdata)
> -               kfree(kdata);
> -       if (retcode)
> -               DRM_DEBUG("ret = %d\n", retcode);
> -       return retcode;
> -}
> -EXPORT_SYMBOL(drm_ioctl);
> -
> -/**
> - * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
> - *
> - * @nr: Ioctl number.
> - * @flags: Where to return the ioctl permission flags
> - */
> -bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
> -{
> -       if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
> -           (nr < DRM_COMMAND_BASE)) {
> -               *flags = drm_ioctls[nr].flags;
> -               return true;
> -       }
> -
> -       return false;
> -}
> -EXPORT_SYMBOL(drm_ioctl_flags);
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index ad66f96..22ca14d 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -1,11 +1,3 @@
> -/**
> - * \file drm_ioctl.c
> - * IOCTL processing for DRM
> - *
> - * \author Rickard E. (Rik) Faith <faith@valinux.com>
> - * \author Gareth Hughes <gareth@valinux.com>
> - */
> -
>  /*
>   * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
>   *
> @@ -13,6 +5,9 @@
>   * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
>   * All Rights Reserved.
>   *
> + * Author Rickard E. (Rik) Faith <faith@valinux.com>
> + * Author Gareth Hughes <gareth@valinux.com>
> + *
>   * Permission is hereby granted, free of charge, to any person obtaining a
>   * copy of this software and associated documentation files (the "Software"),
>   * to deal in the Software without restriction, including without limitation
> @@ -42,6 +37,124 @@
>  #include <asm/mtrr.h>
>  #endif
>
> +static int drm_version(struct drm_device *dev, void *data,
> +                      struct drm_file *file_priv);
> +
> +#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
> +       [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
> +
> +/** Ioctl table */
> +static const struct drm_ioctl_desc drm_ioctls[] = {
> +       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
> +       DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
> +       DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
> +       DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
> +       DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
> +       DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
> +       DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +
> +#if __OS_HAS_AGP
> +       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
> +       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +#endif
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +       DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +};
> +
> +#define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
> +
>  /**
>   * Get the bus id.
>   *
> @@ -415,3 +528,243 @@ int drm_noop(struct drm_device *dev, void *data,
>         return 0;
>  }
>  EXPORT_SYMBOL(drm_noop);
> +
> +/**
> + * Copy and IOCTL return string to user space
> + */
> +static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
> +{
> +       int len;
> +
> +       /* don't overflow userbuf */
> +       len = strlen(value);
> +       if (len > *buf_len)
> +               len = *buf_len;
> +
> +       /* let userspace know exact length of driver value (which could be
> +        * larger than the userspace-supplied buffer) */
> +       *buf_len = strlen(value);
> +
> +       /* finally, try filling in the userbuf */
> +       if (len && buf)
> +               if (copy_to_user(buf, value, len))
> +                       return -EFAULT;
> +       return 0;
> +}
> +
> +/**
> + * Get version information
> + *
> + * \param inode device inode.
> + * \param filp file pointer.
> + * \param cmd command.
> + * \param arg user argument, pointing to a drm_version structure.
> + * \return zero on success or negative number on failure.
> + *
> + * Fills in the version information in \p arg.
> + */
> +static int drm_version(struct drm_device *dev, void *data,
> +                      struct drm_file *file_priv)
> +{
> +       struct drm_version *version = data;
> +       int err;
> +
> +       version->version_major = dev->driver->major;
> +       version->version_minor = dev->driver->minor;
> +       version->version_patchlevel = dev->driver->patchlevel;
> +       err = drm_copy_field(version->name, &version->name_len,
> +                       dev->driver->name);
> +       if (!err)
> +               err = drm_copy_field(version->date, &version->date_len,
> +                               dev->driver->date);
> +       if (!err)
> +               err = drm_copy_field(version->desc, &version->desc_len,
> +                               dev->driver->desc);
> +
> +       return err;
> +}
> +
> +/**
> + * drm_ioctl_permit - Check ioctl permissions against caller
> + *
> + * @flags: ioctl permission flags.
> + * @file_priv: Pointer to struct drm_file identifying the caller.
> + *
> + * Checks whether the caller is allowed to run an ioctl with the
> + * indicated permissions. If so, returns zero. Otherwise returns an
> + * error code suitable for ioctl return.
> + */
> +static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
> +{
> +       /* ROOT_ONLY is only for CAP_SYS_ADMIN */
> +       if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
> +               return -EACCES;
> +
> +       /* AUTH is only for authenticated or render client */
> +       if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
> +                    !file_priv->authenticated))
> +               return -EACCES;
> +
> +       /* MASTER is only for master or control clients */
> +       if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) &&
> +                    !drm_is_control_client(file_priv)))
> +               return -EACCES;
> +
> +       /* Control clients must be explicitly allowed */
> +       if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
> +                    drm_is_control_client(file_priv)))
> +               return -EACCES;
> +
> +       /* Render clients must be explicitly allowed */
> +       if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
> +                    drm_is_render_client(file_priv)))
> +               return -EACCES;
> +
> +       return 0;
> +}
> +
> +/**
> + * Called whenever a process performs an ioctl on /dev/drm.
> + *
> + * \param inode device inode.
> + * \param file_priv DRM file private.
> + * \param cmd command.
> + * \param arg user argument.
> + * \return zero on success or negative number on failure.
> + *
> + * Looks up the ioctl function in the ::ioctls table, checking for root
> + * previleges if so required, and dispatches to the respective function.
> + */
> +long drm_ioctl(struct file *filp,
> +             unsigned int cmd, unsigned long arg)
> +{
> +       struct drm_file *file_priv = filp->private_data;
> +       struct drm_device *dev;
> +       const struct drm_ioctl_desc *ioctl = NULL;
> +       drm_ioctl_t *func;
> +       unsigned int nr = DRM_IOCTL_NR(cmd);
> +       int retcode = -EINVAL;
> +       char stack_kdata[128];
> +       char *kdata = NULL;
> +       unsigned int usize, asize;
> +
> +       dev = file_priv->minor->dev;
> +
> +       if (drm_device_is_unplugged(dev))
> +               return -ENODEV;
> +
> +       if ((nr >= DRM_CORE_IOCTL_COUNT) &&
> +           ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
> +               goto err_i1;
> +       if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
> +           (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
> +               u32 drv_size;
> +               ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
> +               drv_size = _IOC_SIZE(ioctl->cmd_drv);
> +               usize = asize = _IOC_SIZE(cmd);
> +               if (drv_size > asize)
> +                       asize = drv_size;
> +               cmd = ioctl->cmd_drv;
> +       }
> +       else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
> +               u32 drv_size;
> +
> +               ioctl = &drm_ioctls[nr];
> +
> +               drv_size = _IOC_SIZE(ioctl->cmd);
> +               usize = asize = _IOC_SIZE(cmd);
> +               if (drv_size > asize)
> +                       asize = drv_size;
> +
> +               cmd = ioctl->cmd;
> +       } else
> +               goto err_i1;
> +
> +       DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
> +                 task_pid_nr(current),
> +                 (long)old_encode_dev(file_priv->minor->kdev->devt),
> +                 file_priv->authenticated, ioctl->name);
> +
> +       /* Do not trust userspace, use our own definition */
> +       func = ioctl->func;
> +
> +       if (unlikely(!func)) {
> +               DRM_DEBUG("no function\n");
> +               retcode = -EINVAL;
> +               goto err_i1;
> +       }
> +
> +       retcode = drm_ioctl_permit(ioctl->flags, file_priv);
> +       if (unlikely(retcode))
> +               goto err_i1;
> +
> +       if (cmd & (IOC_IN | IOC_OUT)) {
> +               if (asize <= sizeof(stack_kdata)) {
> +                       kdata = stack_kdata;
> +               } else {
> +                       kdata = kmalloc(asize, GFP_KERNEL);
> +                       if (!kdata) {
> +                               retcode = -ENOMEM;
> +                               goto err_i1;
> +                       }
> +               }
> +               if (asize > usize)
> +                       memset(kdata + usize, 0, asize - usize);
> +       }
> +
> +       if (cmd & IOC_IN) {
> +               if (copy_from_user(kdata, (void __user *)arg,
> +                                  usize) != 0) {
> +                       retcode = -EFAULT;
> +                       goto err_i1;
> +               }
> +       } else if (cmd & IOC_OUT) {
> +               memset(kdata, 0, usize);
> +       }
> +
> +       if (ioctl->flags & DRM_UNLOCKED)
> +               retcode = func(dev, kdata, file_priv);
> +       else {
> +               mutex_lock(&drm_global_mutex);
> +               retcode = func(dev, kdata, file_priv);
> +               mutex_unlock(&drm_global_mutex);
> +       }
> +
> +       if (cmd & IOC_OUT) {
> +               if (copy_to_user((void __user *)arg, kdata,
> +                                usize) != 0)
> +                       retcode = -EFAULT;
> +       }
> +
> +      err_i1:
> +       if (!ioctl)
> +               DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
> +                         task_pid_nr(current),
> +                         (long)old_encode_dev(file_priv->minor->kdev->devt),
> +                         file_priv->authenticated, cmd, nr);
> +
> +       if (kdata != stack_kdata)
> +               kfree(kdata);
> +       if (retcode)
> +               DRM_DEBUG("ret = %d\n", retcode);
> +       return retcode;
> +}
> +EXPORT_SYMBOL(drm_ioctl);
> +
> +/**
> + * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
> + *
> + * @nr: Ioctl number.
> + * @flags: Where to return the ioctl permission flags
> + */
> +bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
> +{
> +       if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
> +           (nr < DRM_COMMAND_BASE)) {
> +               *flags = drm_ioctls[nr].flags;
> +               return true;
> +       }
> +
> +       return false;
> +}
> +EXPORT_SYMBOL(drm_ioctl_flags);
> --
> 2.0.2
>

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH 00/12] DRM: Random Cleanups
  2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
                   ` (11 preceding siblings ...)
  2014-07-23 15:26 ` [PATCH 12/12] drm: make sysfs device always available for minors David Herrmann
@ 2014-07-23 16:24 ` Alex Deucher
  12 siblings, 0 replies; 39+ messages in thread
From: Alex Deucher @ 2014-07-23 16:24 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, Maling list - DRI developers

On Wed, Jul 23, 2014 at 11:26 AM, David Herrmann <dh.herrmann@gmail.com> wrote:
> Hi
>
> A bunch of random cleanups I stumbled on when reworking the init-logic. Most of
> them should be fairly trivial.
>
> Also available in my fdo-repository:
>    http://cgit.freedesktop.org/~dvdhrm/linux/log/?h=drm-next
>
> Comments welcome!
> David

Series is:

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

I agree that drm_stub.c should be renamed to drm_drv.c for clarity.

Alex

>
> David Herrmann (12):
>   drm: remove unused "struct drm_freelist"
>   drm: drop unused "struct drm_queue"
>   drm: call ->firstopen() before ->open()
>   drm: extract legacy ctxbitmap flushing
>   drm: drop i386 verification
>   drm: fix __alpha__ PCI lookup
>   drm: drop redundant drm_file->is_master
>   drm: don't de-authenticate clients on master-close
>   drm: move module initialization to drm_stub.c
>   drm: merge drm_drv.c into drm_ioctl.c
>   drm: make minor->index available early
>   drm: make sysfs device always available for minors
>
>  drivers/gpu/drm/drm_bufs.c                 |  17 +-
>  drivers/gpu/drm/drm_context.c              |  30 ++
>  drivers/gpu/drm/drm_crtc.c                 |   2 +-
>  drivers/gpu/drm/drm_drv.c                  | 471 -----------------------------
>  drivers/gpu/drm/drm_fops.c                 | 227 +++++---------
>  drivers/gpu/drm/drm_info.c                 |   2 +-
>  drivers/gpu/drm/drm_ioctl.c                | 369 +++++++++++++++++++++-
>  drivers/gpu/drm/drm_lock.c                 |   2 +-
>  drivers/gpu/drm/drm_stub.c                 | 231 ++++++++++----
>  drivers/gpu/drm/drm_sysfs.c                |  90 +++---
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |   4 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_drv.c        |   2 +-
>  include/drm/drmP.h                         |  52 +---
>  13 files changed, 705 insertions(+), 794 deletions(-)
>  delete mode 100644 drivers/gpu/drm/drm_drv.c
>
> --
> 2.0.2
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 01/12] drm: remove unused "struct drm_freelist"
  2014-07-23 15:26 ` [PATCH 01/12] drm: remove unused "struct drm_freelist" David Herrmann
@ 2014-07-23 19:17   ` Daniel Vetter
  0 siblings, 0 replies; 39+ messages in thread
From: Daniel Vetter @ 2014-07-23 19:17 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:36PM +0200, David Herrmann wrote:
> This object is not used except for static fields in drm_bufs *cough*.
> Inline the watermark fields and drop the unused structure definition.
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/drm_bufs.c | 17 ++++++++---------
>  drivers/gpu/drm/drm_info.c |  2 +-
>  include/drm/drmP.h         | 15 ++-------------
>  3 files changed, 11 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
> index 68175b5..61acb8f 100644
> --- a/drivers/gpu/drm/drm_bufs.c
> +++ b/drivers/gpu/drm/drm_bufs.c
> @@ -1217,7 +1217,6 @@ int drm_infobufs(struct drm_device *dev, void *data,
>  				struct drm_buf_desc __user *to =
>  				    &request->list[count];
>  				struct drm_buf_entry *from = &dma->bufs[i];
> -				struct drm_freelist *list = &dma->bufs[i].freelist;
>  				if (copy_to_user(&to->count,
>  						 &from->buf_count,
>  						 sizeof(from->buf_count)) ||
> @@ -1225,19 +1224,19 @@ int drm_infobufs(struct drm_device *dev, void *data,
>  						 &from->buf_size,
>  						 sizeof(from->buf_size)) ||
>  				    copy_to_user(&to->low_mark,
> -						 &list->low_mark,
> -						 sizeof(list->low_mark)) ||
> +						 &from->low_mark,
> +						 sizeof(from->low_mark)) ||
>  				    copy_to_user(&to->high_mark,
> -						 &list->high_mark,
> -						 sizeof(list->high_mark)))
> +						 &from->high_mark,
> +						 sizeof(from->high_mark)))
>  					return -EFAULT;
>  
>  				DRM_DEBUG("%d %d %d %d %d\n",
>  					  i,
>  					  dma->bufs[i].buf_count,
>  					  dma->bufs[i].buf_size,
> -					  dma->bufs[i].freelist.low_mark,
> -					  dma->bufs[i].freelist.high_mark);
> +					  dma->bufs[i].low_mark,
> +					  dma->bufs[i].high_mark);
>  				++count;
>  			}
>  		}
> @@ -1290,8 +1289,8 @@ int drm_markbufs(struct drm_device *dev, void *data,
>  	if (request->high_mark < 0 || request->high_mark > entry->buf_count)
>  		return -EINVAL;
>  
> -	entry->freelist.low_mark = request->low_mark;
> -	entry->freelist.high_mark = request->high_mark;
> +	entry->low_mark = request->low_mark;
> +	entry->high_mark = request->high_mark;
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
> index 86feedd..ecaf0fa 100644
> --- a/drivers/gpu/drm/drm_info.c
> +++ b/drivers/gpu/drm/drm_info.c
> @@ -132,7 +132,7 @@ int drm_bufs_info(struct seq_file *m, void *data)
>  				   i,
>  				   dma->bufs[i].buf_size,
>  				   dma->bufs[i].buf_count,
> -				   atomic_read(&dma->bufs[i].freelist.count),
> +				   0,
>  				   dma->bufs[i].seg_count,
>  				   seg_pages,
>  				   seg_pages * PAGE_SIZE / 1024);
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 9b6a445..335b7b8 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -346,18 +346,6 @@ struct drm_waitlist {
>  	spinlock_t write_lock;
>  };
>  
> -struct drm_freelist {
> -	int initialized;	       /**< Freelist in use */
> -	atomic_t count;		       /**< Number of free buffers */
> -	struct drm_buf *next;	       /**< End pointer */
> -
> -	wait_queue_head_t waiting;     /**< Processes waiting on free bufs */
> -	int low_mark;		       /**< Low water mark */
> -	int high_mark;		       /**< High water mark */
> -	atomic_t wfh;		       /**< If waiting for high mark */
> -	spinlock_t lock;
> -};
> -
>  typedef struct drm_dma_handle {
>  	dma_addr_t busaddr;
>  	void *vaddr;
> @@ -375,7 +363,8 @@ struct drm_buf_entry {
>  	int page_order;
>  	struct drm_dma_handle **seglist;
>  
> -	struct drm_freelist freelist;
> +	int low_mark;			/**< Low water mark */
> +	int high_mark;			/**< High water mark */
>  };
>  
>  /* Event queued up for userspace to read */
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 03/12] drm: call ->firstopen() before ->open()
  2014-07-23 15:26 ` [PATCH 03/12] drm: call ->firstopen() before ->open() David Herrmann
@ 2014-07-23 19:25   ` Daniel Vetter
  2014-07-24  9:31     ` David Herrmann
  0 siblings, 1 reply; 39+ messages in thread
From: Daniel Vetter @ 2014-07-23 19:25 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:38PM +0200, David Herrmann wrote:
> Lets order things correctly:
>  ->load()
>    ->fistopen()
>      ->open()
>      ->close()
>    ->lastclose()
>  ->unload()
> 
> This doesn't change much as only savage and radeon use ->firstopen() and
> they just do map-initialization. Therefore, the global drm mutex makes
> sure there cannot be any other f_op between ->open() and ->firstopen().
> However, once we get rid of that lock, we really want ->firstopen() to
> initialize the device before ->open() is called.
> 
> Furthermore, this fixes the clean-up path in drm_open(). We currently
> don't cleanup the drm_file object if ->firstopen() fails.
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> ---
>  drivers/gpu/drm/drm_fops.c | 139 +++++++++++++++++++++------------------------
>  include/drm/drmP.h         |   2 +-
>  2 files changed, 66 insertions(+), 75 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index 021fe5d..8e73519 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -45,7 +45,7 @@ EXPORT_SYMBOL(drm_global_mutex);
>  
>  static int drm_open_helper(struct file *filp, struct drm_minor *minor);
>  
> -static int drm_setup(struct drm_device * dev)
> +static int drm_firstopen(struct drm_device * dev)

All the stuff in here is only for legacy drivers. Imo we should rename
this to drm_legacy_setup and hide it harder.

Also touching the init ordering for ums drivers is a bit risky, I'd advise
against it. firstopen is officially dead for kms driver and really there's
nothing legit you can do in there. imx abused until they've switched over
to the component framework.

I'd just drop this one tbh.
-Daniel

>  {
>  	int ret;
>  
> @@ -66,6 +66,57 @@ static int drm_setup(struct drm_device * dev)
>  }
>  
>  /**
> + * drm_legacy_dev_reinit
> + *
> + * Reinitializes a legacy/ums drm device in it's lastclose function.
> + */
> +static void drm_legacy_dev_reinit(struct drm_device *dev)
> +{
> +	if (drm_core_check_feature(dev, DRIVER_MODESET))
> +		return;
> +
> +	dev->sigdata.lock = NULL;
> +
> +	dev->context_flag = 0;
> +	dev->last_context = 0;
> +	dev->if_version = 0;
> +}
> +
> +void drm_lastclose(struct drm_device * dev)
> +{
> +	struct drm_vma_entry *vma, *vma_temp;
> +
> +	DRM_DEBUG("\n");
> +
> +	if (dev->driver->lastclose)
> +		dev->driver->lastclose(dev);
> +	DRM_DEBUG("driver lastclose completed\n");
> +
> +	if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
> +		drm_irq_uninstall(dev);
> +
> +	mutex_lock(&dev->struct_mutex);
> +
> +	drm_agp_clear(dev);
> +
> +	drm_legacy_sg_cleanup(dev);
> +
> +	/* Clear vma list (only built for debugging) */
> +	list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
> +		list_del(&vma->head);
> +		kfree(vma);
> +	}
> +
> +	drm_legacy_dma_takedown(dev);
> +
> +	mutex_unlock(&dev->struct_mutex);
> +
> +	drm_legacy_dev_reinit(dev);
> +
> +	DRM_DEBUG("lastclose completed\n");
> +}
> +
> +/**
>   * Open file.
>   *
>   * \param inode device inode
> @@ -81,31 +132,33 @@ int drm_open(struct inode *inode, struct file *filp)
>  	struct drm_device *dev;
>  	struct drm_minor *minor;
>  	int retcode;
> -	int need_setup = 0;
>  
>  	minor = drm_minor_acquire(iminor(inode));
>  	if (IS_ERR(minor))
>  		return PTR_ERR(minor);
>  
>  	dev = minor->dev;
> -	if (!dev->open_count++)
> -		need_setup = 1;
>  
>  	/* share address_space across all char-devs of a single device */
>  	filp->f_mapping = dev->anon_inode->i_mapping;
>  
> +	if (!dev->open_count) {
> +		retcode = drm_firstopen(dev);
> +		if (retcode)
> +			goto err_minor;
> +	}
> +	++dev->open_count;
> +
>  	retcode = drm_open_helper(filp, minor);
>  	if (retcode)
>  		goto err_undo;
> -	if (need_setup) {
> -		retcode = drm_setup(dev);
> -		if (retcode)
> -			goto err_undo;
> -	}
> +
>  	return 0;
>  
>  err_undo:
> -	dev->open_count--;
> +	if (!--dev->open_count)
> +		drm_lastclose(dev);
> +err_minor:
>  	drm_minor_release(minor);
>  	return retcode;
>  }
> @@ -346,67 +399,6 @@ static void drm_events_release(struct drm_file *file_priv)
>  }
>  
>  /**
> - * drm_legacy_dev_reinit
> - *
> - * Reinitializes a legacy/ums drm device in it's lastclose function.
> - */
> -static void drm_legacy_dev_reinit(struct drm_device *dev)
> -{
> -	if (drm_core_check_feature(dev, DRIVER_MODESET))
> -		return;
> -
> -	dev->sigdata.lock = NULL;
> -
> -	dev->context_flag = 0;
> -	dev->last_context = 0;
> -	dev->if_version = 0;
> -}
> -
> -/**
> - * Take down the DRM device.
> - *
> - * \param dev DRM device structure.
> - *
> - * Frees every resource in \p dev.
> - *
> - * \sa drm_device
> - */
> -int drm_lastclose(struct drm_device * dev)
> -{
> -	struct drm_vma_entry *vma, *vma_temp;
> -
> -	DRM_DEBUG("\n");
> -
> -	if (dev->driver->lastclose)
> -		dev->driver->lastclose(dev);
> -	DRM_DEBUG("driver lastclose completed\n");
> -
> -	if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
> -		drm_irq_uninstall(dev);
> -
> -	mutex_lock(&dev->struct_mutex);
> -
> -	drm_agp_clear(dev);
> -
> -	drm_legacy_sg_cleanup(dev);
> -
> -	/* Clear vma list (only built for debugging) */
> -	list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
> -		list_del(&vma->head);
> -		kfree(vma);
> -	}
> -
> -	drm_legacy_dma_takedown(dev);
> -
> -	mutex_unlock(&dev->struct_mutex);
> -
> -	drm_legacy_dev_reinit(dev);
> -
> -	DRM_DEBUG("lastclose completed\n");
> -	return 0;
> -}
> -
> -/**
>   * Release file.
>   *
>   * \param inode device inode
> @@ -423,7 +415,6 @@ int drm_release(struct inode *inode, struct file *filp)
>  	struct drm_file *file_priv = filp->private_data;
>  	struct drm_minor *minor = file_priv->minor;
>  	struct drm_device *dev = minor->dev;
> -	int retcode = 0;
>  
>  	mutex_lock(&drm_global_mutex);
>  
> @@ -541,7 +532,7 @@ int drm_release(struct inode *inode, struct file *filp)
>  	 */
>  
>  	if (!--dev->open_count) {
> -		retcode = drm_lastclose(dev);
> +		drm_lastclose(dev);
>  		if (drm_device_is_unplugged(dev))
>  			drm_put_dev(dev);
>  	}
> @@ -549,7 +540,7 @@ int drm_release(struct inode *inode, struct file *filp)
>  
>  	drm_minor_release(minor);
>  
> -	return retcode;
> +	return 0;
>  }
>  EXPORT_SYMBOL(drm_release);
>  
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index d3d9be6..d1730c5 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1181,7 +1181,7 @@ extern long drm_ioctl(struct file *filp,
>  		      unsigned int cmd, unsigned long arg);
>  extern long drm_compat_ioctl(struct file *filp,
>  			     unsigned int cmd, unsigned long arg);
> -extern int drm_lastclose(struct drm_device *dev);
> +extern void drm_lastclose(struct drm_device *dev);
>  extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
>  
>  				/* Device support (drm_fops.h) */
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 04/12] drm: extract legacy ctxbitmap flushing
  2014-07-23 15:26 ` [PATCH 04/12] drm: extract legacy ctxbitmap flushing David Herrmann
@ 2014-07-23 19:26   ` Daniel Vetter
  2014-07-24  9:34     ` David Herrmann
  0 siblings, 1 reply; 39+ messages in thread
From: Daniel Vetter @ 2014-07-23 19:26 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:39PM +0200, David Herrmann wrote:
> The ctxbitmap code is only used by legacy drivers so lets try to keep it
> as separated as possible. Furthermore, the locking is non-obvious and
> kinda weird with ctxlist_mutex *and* struct_mutex. Keeping all ctxbitmap
> access in one file is much easier to review and makes drm_release() more
> readable.
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

I've started to sprinkle _legacy_ over all the functions only used for
non-kms drivers, so that the dragon dungeons are clearly marked off. With
that this is Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>.
-Daniel

> ---
>  drivers/gpu/drm/drm_context.c | 30 ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/drm_fops.c    | 20 +-------------------
>  include/drm/drmP.h            |  1 +
>  3 files changed, 32 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c
> index a4b017b..c045505 100644
> --- a/drivers/gpu/drm/drm_context.c
> +++ b/drivers/gpu/drm/drm_context.c
> @@ -111,6 +111,36 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev)
>  	mutex_unlock(&dev->struct_mutex);
>  }
>  
> +/**
> + * drm_ctxbitmap_flush() - Flush all contexts owned by a file
> + * @dev: DRM device to operate on
> + * @file: Open file to flush contexts for
> + *
> + * This iterates over all contexts on @dev and drops them if they're owned by
> + * @file. Note that after this call returns, new contexts might be added if
> + * the file is still alive.
> + */
> +void drm_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file)
> +{
> +	struct drm_ctx_list *pos, *tmp;
> +
> +	mutex_lock(&dev->ctxlist_mutex);
> +
> +	list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) {
> +		if (pos->tag == file &&
> +		    pos->handle != DRM_KERNEL_CONTEXT) {
> +			if (dev->driver->context_dtor)
> +				dev->driver->context_dtor(dev, pos->handle);
> +
> +			drm_ctxbitmap_free(dev, pos->handle);
> +			list_del(&pos->head);
> +			kfree(pos);
> +		}
> +	}
> +
> +	mutex_unlock(&dev->ctxlist_mutex);
> +}
> +
>  /*@}*/
>  
>  /******************************************************************/
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index 8e73519..fb81d1c 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -452,25 +452,7 @@ int drm_release(struct inode *inode, struct file *filp)
>  	if (dev->driver->driver_features & DRIVER_GEM)
>  		drm_gem_release(dev, file_priv);
>  
> -	mutex_lock(&dev->ctxlist_mutex);
> -	if (!list_empty(&dev->ctxlist)) {
> -		struct drm_ctx_list *pos, *n;
> -
> -		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
> -			if (pos->tag == file_priv &&
> -			    pos->handle != DRM_KERNEL_CONTEXT) {
> -				if (dev->driver->context_dtor)
> -					dev->driver->context_dtor(dev,
> -								  pos->handle);
> -
> -				drm_ctxbitmap_free(dev, pos->handle);
> -
> -				list_del(&pos->head);
> -				kfree(pos);
> -			}
> -		}
> -	}
> -	mutex_unlock(&dev->ctxlist_mutex);
> +	drm_ctxbitmap_flush(dev, file_priv);
>  
>  	mutex_lock(&dev->master_mutex);
>  
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index d1730c5..d91e09f 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1242,6 +1242,7 @@ extern int drm_rmctx(struct drm_device *dev, void *data,
>  extern int drm_ctxbitmap_init(struct drm_device *dev);
>  extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
>  extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
> +extern void drm_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file);
>  
>  extern int drm_setsareactx(struct drm_device *dev, void *data,
>  			   struct drm_file *file_priv);
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 06/12] drm: fix __alpha__ PCI lookup
  2014-07-23 15:26 ` [PATCH 06/12] drm: fix __alpha__ PCI lookup David Herrmann
@ 2014-07-23 19:29   ` Daniel Vetter
  2014-07-23 19:36     ` Daniel Vetter
  0 siblings, 1 reply; 39+ messages in thread
From: Daniel Vetter @ 2014-07-23 19:29 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:41PM +0200, David Herrmann wrote:
> Testing the return value of list_entry() for NULL is a no-op (as it is
> just a fancy container_of() / offsetof()). Drop the superfluous if-clause
> and instead verify the actual root-node is available. This is probably
> what it was meant to test for from the beginning, anyway.
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

Oh drm handling of alpha. I've tried to dig out how this all works
together and it's dangerous. drm totally ignored this thing called dma api
so needed to handle cpu phys address vs. bus address offsets itself. If
you munge around also in the agp code (which is really only used by drm)
then you'll notice that it's handled completely differently on alpha vs.
ppc.

Tbh I'd wait until this is all officially dead and then rip it all out.
-Daniel

> ---
>  drivers/gpu/drm/drm_fops.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index a402061..afba0bf 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -330,11 +330,11 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
>  			dev->hose = pci_dev->sysdata;
>  			pci_dev_put(pci_dev);
>  		}
> -		if (!dev->hose) {
> +
> +		if (!dev->hose && pci_root_buses.next) {
>  			struct pci_bus *b = list_entry(pci_root_buses.next,
> -				struct pci_bus, node);
> -			if (b)
> -				dev->hose = b->sysdata;
> +						       struct pci_bus, node);
> +			dev->hose = b->sysdata;
>  		}
>  	}
>  #endif
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c
  2014-07-23 15:26 ` [PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c David Herrmann
  2014-07-23 16:16   ` David Herrmann
@ 2014-07-23 19:33   ` Daniel Vetter
  1 sibling, 0 replies; 39+ messages in thread
From: Daniel Vetter @ 2014-07-23 19:33 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:45PM +0200, David Herrmann wrote:
> All that is left in drm_drv.c is ioctl management. Merge it into
> drm_ioctl.c so we have all ioctl management in one file (and the name is
> much more fitting).
> 
> Maybe we should now rename drm_stub.c to drm_drv.c again?
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

Ack on this one (with the fixup) and the previous patch, too lazy to
double-check it.
-Daniel

> ---
>  drivers/gpu/drm/drm_drv.c   | 412 --------------------------------------------
>  drivers/gpu/drm/drm_ioctl.c | 369 ++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 361 insertions(+), 420 deletions(-)
>  delete mode 100644 drivers/gpu/drm/drm_drv.c
> 
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> deleted file mode 100644
> index 190df83..0000000
> --- a/drivers/gpu/drm/drm_drv.c
> +++ /dev/null
> @@ -1,412 +0,0 @@
> -/**
> - * \file drm_drv.c
> - * Generic driver template
> - *
> - * \author Rickard E. (Rik) Faith <faith@valinux.com>
> - * \author Gareth Hughes <gareth@valinux.com>
> - *
> - * To use this template, you must at least define the following (samples
> - * given for the MGA driver):
> - *
> - * \code
> - * #define DRIVER_AUTHOR	"VA Linux Systems, Inc."
> - *
> - * #define DRIVER_NAME		"mga"
> - * #define DRIVER_DESC		"Matrox G200/G400"
> - * #define DRIVER_DATE		"20001127"
> - *
> - * #define drm_x		mga_##x
> - * \endcode
> - */
> -
> -/*
> - * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
> - *
> - * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
> - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
> - * All Rights Reserved.
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a
> - * copy of this software and associated documentation files (the "Software"),
> - * to deal in the Software without restriction, including without limitation
> - * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> - * and/or sell copies of the Software, and to permit persons to whom the
> - * Software is furnished to do so, subject to the following conditions:
> - *
> - * The above copyright notice and this permission notice (including the next
> - * paragraph) shall be included in all copies or substantial portions of the
> - * Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> - * OTHER DEALINGS IN THE SOFTWARE.
> - */
> -
> -#include <linux/debugfs.h>
> -#include <linux/slab.h>
> -#include <linux/export.h>
> -#include <drm/drmP.h>
> -#include <drm/drm_core.h>
> -
> -
> -static int drm_version(struct drm_device *dev, void *data,
> -		       struct drm_file *file_priv);
> -
> -#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
> -	[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
> -
> -/** Ioctl table */
> -static const struct drm_ioctl_desc drm_ioctls[] = {
> -	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
> -	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -	DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
> -	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
> -	DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
> -	DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
> -	DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
> -	DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -
> -#if __OS_HAS_AGP
> -	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
> -	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -#endif
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
> -
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> -};
> -
> -#define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
> -
> -/**
> - * Copy and IOCTL return string to user space
> - */
> -static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
> -{
> -	int len;
> -
> -	/* don't overflow userbuf */
> -	len = strlen(value);
> -	if (len > *buf_len)
> -		len = *buf_len;
> -
> -	/* let userspace know exact length of driver value (which could be
> -	 * larger than the userspace-supplied buffer) */
> -	*buf_len = strlen(value);
> -
> -	/* finally, try filling in the userbuf */
> -	if (len && buf)
> -		if (copy_to_user(buf, value, len))
> -			return -EFAULT;
> -	return 0;
> -}
> -
> -/**
> - * Get version information
> - *
> - * \param inode device inode.
> - * \param filp file pointer.
> - * \param cmd command.
> - * \param arg user argument, pointing to a drm_version structure.
> - * \return zero on success or negative number on failure.
> - *
> - * Fills in the version information in \p arg.
> - */
> -static int drm_version(struct drm_device *dev, void *data,
> -		       struct drm_file *file_priv)
> -{
> -	struct drm_version *version = data;
> -	int err;
> -
> -	version->version_major = dev->driver->major;
> -	version->version_minor = dev->driver->minor;
> -	version->version_patchlevel = dev->driver->patchlevel;
> -	err = drm_copy_field(version->name, &version->name_len,
> -			dev->driver->name);
> -	if (!err)
> -		err = drm_copy_field(version->date, &version->date_len,
> -				dev->driver->date);
> -	if (!err)
> -		err = drm_copy_field(version->desc, &version->desc_len,
> -				dev->driver->desc);
> -
> -	return err;
> -}
> -
> -/**
> - * drm_ioctl_permit - Check ioctl permissions against caller
> - *
> - * @flags: ioctl permission flags.
> - * @file_priv: Pointer to struct drm_file identifying the caller.
> - *
> - * Checks whether the caller is allowed to run an ioctl with the
> - * indicated permissions. If so, returns zero. Otherwise returns an
> - * error code suitable for ioctl return.
> - */
> -static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
> -{
> -	/* ROOT_ONLY is only for CAP_SYS_ADMIN */
> -	if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
> -		return -EACCES;
> -
> -	/* AUTH is only for authenticated or render client */
> -	if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
> -		     !file_priv->authenticated))
> -		return -EACCES;
> -
> -	/* MASTER is only for master or control clients */
> -	if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) &&
> -		     !drm_is_control_client(file_priv)))
> -		return -EACCES;
> -
> -	/* Control clients must be explicitly allowed */
> -	if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
> -		     drm_is_control_client(file_priv)))
> -		return -EACCES;
> -
> -	/* Render clients must be explicitly allowed */
> -	if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
> -		     drm_is_render_client(file_priv)))
> -		return -EACCES;
> -
> -	return 0;
> -}
> -
> -/**
> - * Called whenever a process performs an ioctl on /dev/drm.
> - *
> - * \param inode device inode.
> - * \param file_priv DRM file private.
> - * \param cmd command.
> - * \param arg user argument.
> - * \return zero on success or negative number on failure.
> - *
> - * Looks up the ioctl function in the ::ioctls table, checking for root
> - * previleges if so required, and dispatches to the respective function.
> - */
> -long drm_ioctl(struct file *filp,
> -	      unsigned int cmd, unsigned long arg)
> -{
> -	struct drm_file *file_priv = filp->private_data;
> -	struct drm_device *dev;
> -	const struct drm_ioctl_desc *ioctl = NULL;
> -	drm_ioctl_t *func;
> -	unsigned int nr = DRM_IOCTL_NR(cmd);
> -	int retcode = -EINVAL;
> -	char stack_kdata[128];
> -	char *kdata = NULL;
> -	unsigned int usize, asize;
> -
> -	dev = file_priv->minor->dev;
> -
> -	if (drm_device_is_unplugged(dev))
> -		return -ENODEV;
> -
> -	if ((nr >= DRM_CORE_IOCTL_COUNT) &&
> -	    ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
> -		goto err_i1;
> -	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
> -	    (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
> -		u32 drv_size;
> -		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
> -		drv_size = _IOC_SIZE(ioctl->cmd_drv);
> -		usize = asize = _IOC_SIZE(cmd);
> -		if (drv_size > asize)
> -			asize = drv_size;
> -		cmd = ioctl->cmd_drv;
> -	}
> -	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
> -		u32 drv_size;
> -
> -		ioctl = &drm_ioctls[nr];
> -
> -		drv_size = _IOC_SIZE(ioctl->cmd);
> -		usize = asize = _IOC_SIZE(cmd);
> -		if (drv_size > asize)
> -			asize = drv_size;
> -
> -		cmd = ioctl->cmd;
> -	} else
> -		goto err_i1;
> -
> -	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
> -		  task_pid_nr(current),
> -		  (long)old_encode_dev(file_priv->minor->kdev->devt),
> -		  file_priv->authenticated, ioctl->name);
> -
> -	/* Do not trust userspace, use our own definition */
> -	func = ioctl->func;
> -
> -	if (unlikely(!func)) {
> -		DRM_DEBUG("no function\n");
> -		retcode = -EINVAL;
> -		goto err_i1;
> -	}
> -
> -	retcode = drm_ioctl_permit(ioctl->flags, file_priv);
> -	if (unlikely(retcode))
> -		goto err_i1;
> -
> -	if (cmd & (IOC_IN | IOC_OUT)) {
> -		if (asize <= sizeof(stack_kdata)) {
> -			kdata = stack_kdata;
> -		} else {
> -			kdata = kmalloc(asize, GFP_KERNEL);
> -			if (!kdata) {
> -				retcode = -ENOMEM;
> -				goto err_i1;
> -			}
> -		}
> -		if (asize > usize)
> -			memset(kdata + usize, 0, asize - usize);
> -	}
> -
> -	if (cmd & IOC_IN) {
> -		if (copy_from_user(kdata, (void __user *)arg,
> -				   usize) != 0) {
> -			retcode = -EFAULT;
> -			goto err_i1;
> -		}
> -	} else if (cmd & IOC_OUT) {
> -		memset(kdata, 0, usize);
> -	}
> -
> -	if (ioctl->flags & DRM_UNLOCKED)
> -		retcode = func(dev, kdata, file_priv);
> -	else {
> -		mutex_lock(&drm_global_mutex);
> -		retcode = func(dev, kdata, file_priv);
> -		mutex_unlock(&drm_global_mutex);
> -	}
> -
> -	if (cmd & IOC_OUT) {
> -		if (copy_to_user((void __user *)arg, kdata,
> -				 usize) != 0)
> -			retcode = -EFAULT;
> -	}
> -
> -      err_i1:
> -	if (!ioctl)
> -		DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
> -			  task_pid_nr(current),
> -			  (long)old_encode_dev(file_priv->minor->kdev->devt),
> -			  file_priv->authenticated, cmd, nr);
> -
> -	if (kdata != stack_kdata)
> -		kfree(kdata);
> -	if (retcode)
> -		DRM_DEBUG("ret = %d\n", retcode);
> -	return retcode;
> -}
> -EXPORT_SYMBOL(drm_ioctl);
> -
> -/**
> - * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
> - *
> - * @nr: Ioctl number.
> - * @flags: Where to return the ioctl permission flags
> - */
> -bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
> -{
> -	if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
> -	    (nr < DRM_COMMAND_BASE)) {
> -		*flags = drm_ioctls[nr].flags;
> -		return true;
> -	}
> -
> -	return false;
> -}
> -EXPORT_SYMBOL(drm_ioctl_flags);
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index ad66f96..22ca14d 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -1,11 +1,3 @@
> -/**
> - * \file drm_ioctl.c
> - * IOCTL processing for DRM
> - *
> - * \author Rickard E. (Rik) Faith <faith@valinux.com>
> - * \author Gareth Hughes <gareth@valinux.com>
> - */
> -
>  /*
>   * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
>   *
> @@ -13,6 +5,9 @@
>   * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
>   * All Rights Reserved.
>   *
> + * Author Rickard E. (Rik) Faith <faith@valinux.com>
> + * Author Gareth Hughes <gareth@valinux.com>
> + *
>   * Permission is hereby granted, free of charge, to any person obtaining a
>   * copy of this software and associated documentation files (the "Software"),
>   * to deal in the Software without restriction, including without limitation
> @@ -42,6 +37,124 @@
>  #include <asm/mtrr.h>
>  #endif
>  
> +static int drm_version(struct drm_device *dev, void *data,
> +		       struct drm_file *file_priv);
> +
> +#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
> +	[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
> +
> +/** Ioctl table */
> +static const struct drm_ioctl_desc drm_ioctls[] = {
> +	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
> +	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
> +	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
> +	DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
> +	DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
> +	DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
> +	DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +
> +#if __OS_HAS_AGP
> +	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
> +	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +#endif
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +};
> +
> +#define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
> +
>  /**
>   * Get the bus id.
>   *
> @@ -415,3 +528,243 @@ int drm_noop(struct drm_device *dev, void *data,
>  	return 0;
>  }
>  EXPORT_SYMBOL(drm_noop);
> +
> +/**
> + * Copy and IOCTL return string to user space
> + */
> +static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
> +{
> +	int len;
> +
> +	/* don't overflow userbuf */
> +	len = strlen(value);
> +	if (len > *buf_len)
> +		len = *buf_len;
> +
> +	/* let userspace know exact length of driver value (which could be
> +	 * larger than the userspace-supplied buffer) */
> +	*buf_len = strlen(value);
> +
> +	/* finally, try filling in the userbuf */
> +	if (len && buf)
> +		if (copy_to_user(buf, value, len))
> +			return -EFAULT;
> +	return 0;
> +}
> +
> +/**
> + * Get version information
> + *
> + * \param inode device inode.
> + * \param filp file pointer.
> + * \param cmd command.
> + * \param arg user argument, pointing to a drm_version structure.
> + * \return zero on success or negative number on failure.
> + *
> + * Fills in the version information in \p arg.
> + */
> +static int drm_version(struct drm_device *dev, void *data,
> +		       struct drm_file *file_priv)
> +{
> +	struct drm_version *version = data;
> +	int err;
> +
> +	version->version_major = dev->driver->major;
> +	version->version_minor = dev->driver->minor;
> +	version->version_patchlevel = dev->driver->patchlevel;
> +	err = drm_copy_field(version->name, &version->name_len,
> +			dev->driver->name);
> +	if (!err)
> +		err = drm_copy_field(version->date, &version->date_len,
> +				dev->driver->date);
> +	if (!err)
> +		err = drm_copy_field(version->desc, &version->desc_len,
> +				dev->driver->desc);
> +
> +	return err;
> +}
> +
> +/**
> + * drm_ioctl_permit - Check ioctl permissions against caller
> + *
> + * @flags: ioctl permission flags.
> + * @file_priv: Pointer to struct drm_file identifying the caller.
> + *
> + * Checks whether the caller is allowed to run an ioctl with the
> + * indicated permissions. If so, returns zero. Otherwise returns an
> + * error code suitable for ioctl return.
> + */
> +static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
> +{
> +	/* ROOT_ONLY is only for CAP_SYS_ADMIN */
> +	if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
> +		return -EACCES;
> +
> +	/* AUTH is only for authenticated or render client */
> +	if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
> +		     !file_priv->authenticated))
> +		return -EACCES;
> +
> +	/* MASTER is only for master or control clients */
> +	if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) &&
> +		     !drm_is_control_client(file_priv)))
> +		return -EACCES;
> +
> +	/* Control clients must be explicitly allowed */
> +	if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
> +		     drm_is_control_client(file_priv)))
> +		return -EACCES;
> +
> +	/* Render clients must be explicitly allowed */
> +	if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
> +		     drm_is_render_client(file_priv)))
> +		return -EACCES;
> +
> +	return 0;
> +}
> +
> +/**
> + * Called whenever a process performs an ioctl on /dev/drm.
> + *
> + * \param inode device inode.
> + * \param file_priv DRM file private.
> + * \param cmd command.
> + * \param arg user argument.
> + * \return zero on success or negative number on failure.
> + *
> + * Looks up the ioctl function in the ::ioctls table, checking for root
> + * previleges if so required, and dispatches to the respective function.
> + */
> +long drm_ioctl(struct file *filp,
> +	      unsigned int cmd, unsigned long arg)
> +{
> +	struct drm_file *file_priv = filp->private_data;
> +	struct drm_device *dev;
> +	const struct drm_ioctl_desc *ioctl = NULL;
> +	drm_ioctl_t *func;
> +	unsigned int nr = DRM_IOCTL_NR(cmd);
> +	int retcode = -EINVAL;
> +	char stack_kdata[128];
> +	char *kdata = NULL;
> +	unsigned int usize, asize;
> +
> +	dev = file_priv->minor->dev;
> +
> +	if (drm_device_is_unplugged(dev))
> +		return -ENODEV;
> +
> +	if ((nr >= DRM_CORE_IOCTL_COUNT) &&
> +	    ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
> +		goto err_i1;
> +	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
> +	    (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
> +		u32 drv_size;
> +		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
> +		drv_size = _IOC_SIZE(ioctl->cmd_drv);
> +		usize = asize = _IOC_SIZE(cmd);
> +		if (drv_size > asize)
> +			asize = drv_size;
> +		cmd = ioctl->cmd_drv;
> +	}
> +	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
> +		u32 drv_size;
> +
> +		ioctl = &drm_ioctls[nr];
> +
> +		drv_size = _IOC_SIZE(ioctl->cmd);
> +		usize = asize = _IOC_SIZE(cmd);
> +		if (drv_size > asize)
> +			asize = drv_size;
> +
> +		cmd = ioctl->cmd;
> +	} else
> +		goto err_i1;
> +
> +	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
> +		  task_pid_nr(current),
> +		  (long)old_encode_dev(file_priv->minor->kdev->devt),
> +		  file_priv->authenticated, ioctl->name);
> +
> +	/* Do not trust userspace, use our own definition */
> +	func = ioctl->func;
> +
> +	if (unlikely(!func)) {
> +		DRM_DEBUG("no function\n");
> +		retcode = -EINVAL;
> +		goto err_i1;
> +	}
> +
> +	retcode = drm_ioctl_permit(ioctl->flags, file_priv);
> +	if (unlikely(retcode))
> +		goto err_i1;
> +
> +	if (cmd & (IOC_IN | IOC_OUT)) {
> +		if (asize <= sizeof(stack_kdata)) {
> +			kdata = stack_kdata;
> +		} else {
> +			kdata = kmalloc(asize, GFP_KERNEL);
> +			if (!kdata) {
> +				retcode = -ENOMEM;
> +				goto err_i1;
> +			}
> +		}
> +		if (asize > usize)
> +			memset(kdata + usize, 0, asize - usize);
> +	}
> +
> +	if (cmd & IOC_IN) {
> +		if (copy_from_user(kdata, (void __user *)arg,
> +				   usize) != 0) {
> +			retcode = -EFAULT;
> +			goto err_i1;
> +		}
> +	} else if (cmd & IOC_OUT) {
> +		memset(kdata, 0, usize);
> +	}
> +
> +	if (ioctl->flags & DRM_UNLOCKED)
> +		retcode = func(dev, kdata, file_priv);
> +	else {
> +		mutex_lock(&drm_global_mutex);
> +		retcode = func(dev, kdata, file_priv);
> +		mutex_unlock(&drm_global_mutex);
> +	}
> +
> +	if (cmd & IOC_OUT) {
> +		if (copy_to_user((void __user *)arg, kdata,
> +				 usize) != 0)
> +			retcode = -EFAULT;
> +	}
> +
> +      err_i1:
> +	if (!ioctl)
> +		DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
> +			  task_pid_nr(current),
> +			  (long)old_encode_dev(file_priv->minor->kdev->devt),
> +			  file_priv->authenticated, cmd, nr);
> +
> +	if (kdata != stack_kdata)
> +		kfree(kdata);
> +	if (retcode)
> +		DRM_DEBUG("ret = %d\n", retcode);
> +	return retcode;
> +}
> +EXPORT_SYMBOL(drm_ioctl);
> +
> +/**
> + * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
> + *
> + * @nr: Ioctl number.
> + * @flags: Where to return the ioctl permission flags
> + */
> +bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
> +{
> +	if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
> +	    (nr < DRM_COMMAND_BASE)) {
> +		*flags = drm_ioctls[nr].flags;
> +		return true;
> +	}
> +
> +	return false;
> +}
> +EXPORT_SYMBOL(drm_ioctl_flags);
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 02/12] drm: drop unused "struct drm_queue"
  2014-07-23 15:26 ` [PATCH 02/12] drm: drop unused "struct drm_queue" David Herrmann
@ 2014-07-23 19:35   ` Daniel Vetter
  2014-07-24 11:35     ` David Herrmann
  0 siblings, 1 reply; 39+ messages in thread
From: Daniel Vetter @ 2014-07-23 19:35 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:37PM +0200, David Herrmann wrote:
> This object is unused, drop it.
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

Funny how after even all my "kill stuff with fire" series there's still
such low hanging fruit left ;-)

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> 
> ---
>  include/drm/drmP.h | 17 -----------------
>  1 file changed, 17 deletions(-)
> 
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 335b7b8..d3d9be6 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -430,23 +430,6 @@ struct drm_file {
>  	struct drm_prime_file_private prime;
>  };
>  
> -/** Wait queue */
> -struct drm_queue {
> -	atomic_t use_count;		/**< Outstanding uses (+1) */
> -	atomic_t finalization;		/**< Finalization in progress */
> -	atomic_t block_count;		/**< Count of processes waiting */
> -	atomic_t block_read;		/**< Queue blocked for reads */
> -	wait_queue_head_t read_queue;	/**< Processes waiting on block_read */
> -	atomic_t block_write;		/**< Queue blocked for writes */
> -	wait_queue_head_t write_queue;	/**< Processes waiting on block_write */
> -	atomic_t total_queued;		/**< Total queued statistic */
> -	atomic_t total_flushed;		/**< Total flushes statistic */
> -	atomic_t total_locks;		/**< Total locks statistics */
> -	enum drm_ctx_flags flags;	/**< Context preserving and 2D-only */
> -	struct drm_waitlist waitlist;	/**< Pending buffers */
> -	wait_queue_head_t flush_queue;	/**< Processes waiting until flush */
> -};
> -
>  /**
>   * Lock data.
>   */
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 06/12] drm: fix __alpha__ PCI lookup
  2014-07-23 19:29   ` Daniel Vetter
@ 2014-07-23 19:36     ` Daniel Vetter
  0 siblings, 0 replies; 39+ messages in thread
From: Daniel Vetter @ 2014-07-23 19:36 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 09:29:48PM +0200, Daniel Vetter wrote:
> On Wed, Jul 23, 2014 at 05:26:41PM +0200, David Herrmann wrote:
> > Testing the return value of list_entry() for NULL is a no-op (as it is
> > just a fancy container_of() / offsetof()). Drop the superfluous if-clause
> > and instead verify the actual root-node is available. This is probably
> > what it was meant to test for from the beginning, anyway.
> > 
> > Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> 
> Oh drm handling of alpha. I've tried to dig out how this all works
> together and it's dangerous. drm totally ignored this thing called dma api
> so needed to handle cpu phys address vs. bus address offsets itself. If
> you munge around also in the agp code (which is really only used by drm)
> then you'll notice that it's handled completely differently on alpha vs.
> ppc.
> 
> Tbh I'd wait until this is all officially dead and then rip it all out.

I dare you for a patch to rip out alpha drm handling completely though ;-)
ppc probably needs to stay a bit longer, there's still lots of apple
hardware with radeons around.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 03/12] drm: call ->firstopen() before ->open()
  2014-07-23 19:25   ` Daniel Vetter
@ 2014-07-24  9:31     ` David Herrmann
  2014-07-24 10:18       ` Daniel Vetter
  2014-07-24 13:47       ` Alex Deucher
  0 siblings, 2 replies; 39+ messages in thread
From: David Herrmann @ 2014-07-24  9:31 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, dri-devel

Hi

On Wed, Jul 23, 2014 at 9:25 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Wed, Jul 23, 2014 at 05:26:38PM +0200, David Herrmann wrote:
>> Lets order things correctly:
>>  ->load()
>>    ->fistopen()
>>      ->open()
>>      ->close()
>>    ->lastclose()
>>  ->unload()
>>
>> This doesn't change much as only savage and radeon use ->firstopen() and
>> they just do map-initialization. Therefore, the global drm mutex makes
>> sure there cannot be any other f_op between ->open() and ->firstopen().
>> However, once we get rid of that lock, we really want ->firstopen() to
>> initialize the device before ->open() is called.
>>
>> Furthermore, this fixes the clean-up path in drm_open(). We currently
>> don't cleanup the drm_file object if ->firstopen() fails.
>>
>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>> ---
>>  drivers/gpu/drm/drm_fops.c | 139 +++++++++++++++++++++------------------------
>>  include/drm/drmP.h         |   2 +-
>>  2 files changed, 66 insertions(+), 75 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
>> index 021fe5d..8e73519 100644
>> --- a/drivers/gpu/drm/drm_fops.c
>> +++ b/drivers/gpu/drm/drm_fops.c
>> @@ -45,7 +45,7 @@ EXPORT_SYMBOL(drm_global_mutex);
>>
>>  static int drm_open_helper(struct file *filp, struct drm_minor *minor);
>>
>> -static int drm_setup(struct drm_device * dev)
>> +static int drm_firstopen(struct drm_device * dev)
>
> All the stuff in here is only for legacy drivers. Imo we should rename
> this to drm_legacy_setup and hide it harder.
>
> Also touching the init ordering for ums drivers is a bit risky, I'd advise
> against it. firstopen is officially dead for kms driver and really there's
> nothing legit you can do in there. imx abused until they've switched over
> to the component framework.
>
> I'd just drop this one tbh.

I did a driver audit when writing this patch, there're only 2 drivers
using firstopen:

 * radeon_cp: sets two fields of dev_private and calls drm_addmap() on
those. In lastclose(), it calls drm_rmmap()
 * savage: sets several fields in dev_private, calls
arch_phys_wc_add() for some regions and requests a drm-map for those
via drm_addmap(). On lastclose(), it reverts exactly those steps.

Taking into account that firstopen() just runs with drm_device
context, not with drm_file context, I really think we should be
calling it _before_ doing ->open(). I even think the drivers would
fail horribly if we don't do this patch and some other user-context
sneaks in between both calls (currently impossible thanks to
drm_global_mutex).

Both ->firstopen() callbacks are fairly trivial. In favor of making
the error-paths work in drm_open() I'd really like to get this in.
This patch is preparing for my drm_file rework that can make
drm_dev_unregister() stop all open files immediately.

But I honestly don't care much for UMS drivers, so if you NACK this,
I'd just ignore the error code and add a comment that we don't do
error-handling for UMS.

Cheers
David

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 04/12] drm: extract legacy ctxbitmap flushing
  2014-07-23 19:26   ` Daniel Vetter
@ 2014-07-24  9:34     ` David Herrmann
  2014-07-24 10:19       ` Daniel Vetter
  0 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-24  9:34 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, dri-devel

Hi

On Wed, Jul 23, 2014 at 9:26 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Wed, Jul 23, 2014 at 05:26:39PM +0200, David Herrmann wrote:
>> The ctxbitmap code is only used by legacy drivers so lets try to keep it
>> as separated as possible. Furthermore, the locking is non-obvious and
>> kinda weird with ctxlist_mutex *and* struct_mutex. Keeping all ctxbitmap
>> access in one file is much easier to review and makes drm_release() more
>> readable.
>>
>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>
> I've started to sprinkle _legacy_ over all the functions only used for
> non-kms drivers, so that the dragon dungeons are clearly marked off. With
> that this is Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>.

Yeah, that sounds good. But I'd prefer if we keep this patch as-is and
I will send a follow-up which renames all "drm_ctxbitmap_*" functions
to "drm_legacy_ctxbitmap_*". All those are internal to DRM-core so I
can rename them all together and add drivers/gpu/drm/drm-legacy.h.

Comments?
David

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 07/12] drm: drop redundant drm_file->is_master
  2014-07-23 15:26 ` [PATCH 07/12] drm: drop redundant drm_file->is_master David Herrmann
@ 2014-07-24  9:52   ` Daniel Vetter
  2014-07-24 21:38     ` David Herrmann
  0 siblings, 1 reply; 39+ messages in thread
From: Daniel Vetter @ 2014-07-24  9:52 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:42PM +0200, David Herrmann wrote:
> The drm_file->is_master field is redundant as it's equivalent to:
>     drm_file->master && drm_file->master == drm_file->minor->master
> 
> 1) "=>"
>   Whenever we set drm_file->is_master, we also set:
>       drm_file->minor->master = drm_file->master;
> 
>   Whenever we clear drm_file->is_master, we also call:
>       drm_master_put(&drm_file->minor->master);
>   which implicitly clears it to NULL.
> 
> 2) "<="
>   minor->master cannot be set if it is non-NULL. Therefore, it stays as
>   is unless a file drops it.
> 
>   If minor->master is NULL, it is only set by places that also adjust
>   drm_file->is_master.
> 
> Therefore, we can safely drop is_master and replace it by an inline helper
> that matches:
>     drm_file->master && drm_file->master == drm_file->minor->master
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

Docbook for drm_is_master is missing, otherwise Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

And one question below which doesn't really matter for this patch here.
See below
-Daniel

[snip]

> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index d91e09f..e1bb585 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -387,8 +387,6 @@ struct drm_prime_file_private {
>  struct drm_file {
>  	unsigned always_authenticated :1;
>  	unsigned authenticated :1;
> -	/* Whether we're master for a minor. Protected by master_mutex */
> -	unsigned is_master :1;
>  	/* true when the client has asked us to expose stereo 3D mode flags */
>  	unsigned stereo_allowed :1;
>  	/*
> @@ -1034,7 +1032,7 @@ struct drm_device {
>  	/** \name Locks */
>  	/*@{ */
>  	struct mutex struct_mutex;	/**< For others */
> -	struct mutex master_mutex;      /**< For drm_minor::master and drm_file::is_master */
> +	struct mutex master_mutex;      /**< For drm_minor::master */
>  	/*@} */
>  
>  	/** \name Usage Counters */
> @@ -1172,6 +1170,11 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv)
>  	return file_priv->minor->type == DRM_MINOR_LEGACY;
>  }
>  

Docbook here please ...
> +static inline bool drm_is_master(const struct drm_file *file)
> +{

Hm, we don't have any means to synchronize is_master checks with
concurrent ioctls and stuff. Do we care? Orthogonal issue really.

> +	return file->master && file->master == file->minor->master;
> +}
> +
>  /******************************************************************/
>  /** \name Internal function definitions */
>  /*@{*/
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 08/12] drm: don't de-authenticate clients on master-close
  2014-07-23 15:26 ` [PATCH 08/12] drm: don't de-authenticate clients on master-close David Herrmann
@ 2014-07-24  9:57   ` Daniel Vetter
  0 siblings, 0 replies; 39+ messages in thread
From: Daniel Vetter @ 2014-07-24  9:57 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:43PM +0200, David Herrmann wrote:
> If an active DRM-Master closes its device, we deauthenticate all clients
> on that master. However, if an inactive DRM-Master closes its device, we
> do nothing. This is quite inconsistent and breaks several scenarios:
> 
>  1) If this was used as security mechanism, it fails horribly if a master
>     closes a device while VT switched away. Furthermore, none of the few
>     drivers using ->master_*() callbacks seems to require it, anyway.
> 
>  2) If you spawn weston (or any other non-UMS compositor) in background
>     while another compositor is active, both will get assigned to the
>     same "drm_master" object. If the foreground compositor now exits, all
>     clients of both the foreground AND background compositor will be
>     de-authenticated leading to unexpected behavior.
> 
> Stop this non-sense and keep clients authenticated. We don't do this when
> dropping DRM-Master (i.e., switching VTs) so don't do it on active-close
> either!
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

Yeah, we have a bit a confusion about what master does. Iirc back in the
dri days the idea was that the master completely gates access for clients,
but we've long since moved away from this model (if it ever really was
fully implemented in the drm core). Dropping this and making master a pure
priv flag for certain compositor operations (modeset, flink_open, ...)
makes a lot of sense.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/drm_fops.c | 13 ++-----------
>  include/drm/drmP.h         |  1 -
>  2 files changed, 2 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index f65087e..ff0a13f 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -252,8 +252,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
>  	priv->minor = minor;
>  
>  	/* for compatibility root is always authenticated */
> -	priv->always_authenticated = capable(CAP_SYS_ADMIN);
> -	priv->authenticated = priv->always_authenticated;
> +	priv->authenticated = capable(CAP_SYS_ADMIN);
>  	priv->lock_count = 0;
>  
>  	INIT_LIST_HEAD(&priv->lhead);
> @@ -453,20 +452,12 @@ int drm_release(struct inode *inode, struct file *filp)
>  
>  	if (drm_is_master(file_priv)) {
>  		struct drm_master *master = file_priv->master;
> -		struct drm_file *temp;
> -
> -		mutex_lock(&dev->struct_mutex);
> -		list_for_each_entry(temp, &dev->filelist, lhead) {
> -			if ((temp->master == file_priv->master) &&
> -			    (temp != file_priv))
> -				temp->authenticated = temp->always_authenticated;
> -		}
>  
>  		/**
>  		 * Since the master is disappearing, so is the
>  		 * possibility to lock.
>  		 */
> -
> +		mutex_lock(&dev->struct_mutex);
>  		if (master->lock.hw_lock) {
>  			if (dev->sigdata.lock == master->lock.hw_lock)
>  				dev->sigdata.lock = NULL;
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index e1bb585..48d2fe7 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -385,7 +385,6 @@ struct drm_prime_file_private {
>  
>  /** File private data */
>  struct drm_file {
> -	unsigned always_authenticated :1;
>  	unsigned authenticated :1;
>  	/* true when the client has asked us to expose stereo 3D mode flags */
>  	unsigned stereo_allowed :1;
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 11/12] drm: make minor->index available early
  2014-07-23 15:26 ` [PATCH 11/12] drm: make minor->index available early David Herrmann
@ 2014-07-24 10:03   ` Daniel Vetter
  2014-07-24 10:16     ` David Herrmann
  0 siblings, 1 reply; 39+ messages in thread
From: Daniel Vetter @ 2014-07-24 10:03 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:46PM +0200, David Herrmann wrote:
> Instead of allocating the minor-index during registration, we now do this
> during allocation. This way, debug-messages between minor-allocation and
> minor-registration will now use the correct minor instead of 0. Same is
> done for unregistration vs. free, so debug-messages between
> device-shutdown and device-destruction show proper indices.
> 
> Even though minor-indices are allocated early, we don't enable minor
> lookup early. Instead, we keep the entry set to NULL and replace it during
> registration / unregistration. This way, the index is allocated but lookup
> only works if registered.
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> ---
>  drivers/gpu/drm/drm_stub.c | 84 +++++++++++++++++++++++++---------------------
>  1 file changed, 46 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
> index b249f14..8b24db5 100644
> --- a/drivers/gpu/drm/drm_stub.c
> +++ b/drivers/gpu/drm/drm_stub.c
> @@ -256,6 +256,8 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
>  static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
>  {
>  	struct drm_minor *minor;
> +	unsigned long flags;
> +	int r;
>  
>  	minor = kzalloc(sizeof(*minor), GFP_KERNEL);
>  	if (!minor)
> @@ -264,57 +266,68 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
>  	minor->type = type;
>  	minor->dev = dev;
>  
> +	idr_preload(GFP_KERNEL);
> +	spin_lock_irqsave(&drm_minor_lock, flags);
> +	r = idr_alloc(&drm_minors_idr,
> +		      NULL,
> +		      64 * type,
> +		      64 * (type + 1),
> +		      GFP_NOWAIT);
> +	spin_unlock_irqrestore(&drm_minor_lock, flags);
> +	idr_preload_end();
> +
> +	if (r < 0)
> +		goto err_free;
> +
> +	minor->index = r;
> +
>  	*drm_minor_get_slot(dev, type) = minor;
>  	return 0;
> +
> +err_free:
> +	kfree(minor);
> +	return r;
>  }
>  
>  static void drm_minor_free(struct drm_device *dev, unsigned int type)
>  {
> -	struct drm_minor **slot;
> +	struct drm_minor **slot, *minor;
> +	unsigned long flags;
>  
>  	slot = drm_minor_get_slot(dev, type);
> -	if (*slot) {
> -		drm_mode_group_destroy(&(*slot)->mode_group);
> -		kfree(*slot);
> -		*slot = NULL;
> -	}
> +	minor = *slot;
> +	if (!minor)
> +		return;
> +
> +	drm_mode_group_destroy(&minor->mode_group);
> +
> +	spin_lock_irqsave(&drm_minor_lock, flags);
> +	idr_remove(&drm_minors_idr, minor->index);
> +	spin_unlock_irqrestore(&drm_minor_lock, flags);

I don't understand why you do the idr removal in stages too. Otherwise
this looks good.

Aside: If two drivers load concurrently (i.e. in the brave new world
withou drm_global_mutex) we might end up with interleaved minor ids. Dunno
whether we'll care since userspace should use udev/sysfs lookups anyway.
igt sometimes doesn't ;-)

> +
> +	kfree(minor);
> +	*slot = NULL;
>  }
>  
>  static int drm_minor_register(struct drm_device *dev, unsigned int type)
>  {
> -	struct drm_minor *new_minor;
> +	struct drm_minor *minor;
>  	unsigned long flags;
>  	int ret;
> -	int minor_id;
>  
>  	DRM_DEBUG("\n");
>  
> -	new_minor = *drm_minor_get_slot(dev, type);
> -	if (!new_minor)
> +	minor = *drm_minor_get_slot(dev, type);
> +	if (!minor)
>  		return 0;
>  
> -	idr_preload(GFP_KERNEL);
> -	spin_lock_irqsave(&drm_minor_lock, flags);
> -	minor_id = idr_alloc(&drm_minors_idr,
> -			     NULL,
> -			     64 * type,
> -			     64 * (type + 1),
> -			     GFP_NOWAIT);
> -	spin_unlock_irqrestore(&drm_minor_lock, flags);
> -	idr_preload_end();
> -
> -	if (minor_id < 0)
> -		return minor_id;
> -
> -	new_minor->index = minor_id;
> -
> -	ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
> +	ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
>  	if (ret) {
>  		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
> -		goto err_id;
> +		return ret;
>  	}
>  
> -	ret = drm_sysfs_device_add(new_minor);
> +	ret = drm_sysfs_device_add(minor);
>  	if (ret) {
>  		DRM_ERROR("DRM: Error sysfs_device_add.\n");
>  		goto err_debugfs;
> @@ -322,19 +335,14 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
>  
>  	/* replace NULL with @minor so lookups will succeed from now on */
>  	spin_lock_irqsave(&drm_minor_lock, flags);
> -	idr_replace(&drm_minors_idr, new_minor, new_minor->index);
> +	idr_replace(&drm_minors_idr, minor, minor->index);
>  	spin_unlock_irqrestore(&drm_minor_lock, flags);
>  
> -	DRM_DEBUG("new minor assigned %d\n", minor_id);
> +	DRM_DEBUG("new minor registered %d\n", minor->index);
>  	return 0;
>  
>  err_debugfs:
> -	drm_debugfs_cleanup(new_minor);
> -err_id:
> -	spin_lock_irqsave(&drm_minor_lock, flags);
> -	idr_remove(&drm_minors_idr, minor_id);
> -	spin_unlock_irqrestore(&drm_minor_lock, flags);
> -	new_minor->index = 0;
> +	drm_debugfs_cleanup(minor);
>  	return ret;
>  }
>  
> @@ -347,10 +355,10 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
>  	if (!minor || !minor->kdev)
>  		return;
>  
> +	/* replace @minor with NULL so lookups will fail from now on */
>  	spin_lock_irqsave(&drm_minor_lock, flags);
> -	idr_remove(&drm_minors_idr, minor->index);
> +	idr_replace(&drm_minors_idr, NULL, minor->index);
>  	spin_unlock_irqrestore(&drm_minor_lock, flags);
> -	minor->index = 0;
>  
>  	drm_debugfs_cleanup(minor);
>  	drm_sysfs_device_remove(minor);
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 11/12] drm: make minor->index available early
  2014-07-24 10:03   ` Daniel Vetter
@ 2014-07-24 10:16     ` David Herrmann
  2014-07-24 12:30       ` Daniel Vetter
  0 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-24 10:16 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, dri-devel

Hi

On Thu, Jul 24, 2014 at 12:03 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Wed, Jul 23, 2014 at 05:26:46PM +0200, David Herrmann wrote:
>> Instead of allocating the minor-index during registration, we now do this
>> during allocation. This way, debug-messages between minor-allocation and
>> minor-registration will now use the correct minor instead of 0. Same is
>> done for unregistration vs. free, so debug-messages between
>> device-shutdown and device-destruction show proper indices.
>>
>> Even though minor-indices are allocated early, we don't enable minor
>> lookup early. Instead, we keep the entry set to NULL and replace it during
>> registration / unregistration. This way, the index is allocated but lookup
>> only works if registered.
>>
>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>> ---
>>  drivers/gpu/drm/drm_stub.c | 84 +++++++++++++++++++++++++---------------------
>>  1 file changed, 46 insertions(+), 38 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
>> index b249f14..8b24db5 100644
>> --- a/drivers/gpu/drm/drm_stub.c
>> +++ b/drivers/gpu/drm/drm_stub.c
>> @@ -256,6 +256,8 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
>>  static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
>>  {
>>       struct drm_minor *minor;
>> +     unsigned long flags;
>> +     int r;
>>
>>       minor = kzalloc(sizeof(*minor), GFP_KERNEL);
>>       if (!minor)
>> @@ -264,57 +266,68 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
>>       minor->type = type;
>>       minor->dev = dev;
>>
>> +     idr_preload(GFP_KERNEL);
>> +     spin_lock_irqsave(&drm_minor_lock, flags);
>> +     r = idr_alloc(&drm_minors_idr,
>> +                   NULL,
>> +                   64 * type,
>> +                   64 * (type + 1),
>> +                   GFP_NOWAIT);
>> +     spin_unlock_irqrestore(&drm_minor_lock, flags);
>> +     idr_preload_end();
>> +
>> +     if (r < 0)
>> +             goto err_free;
>> +
>> +     minor->index = r;
>> +
>>       *drm_minor_get_slot(dev, type) = minor;
>>       return 0;
>> +
>> +err_free:
>> +     kfree(minor);
>> +     return r;
>>  }
>>
>>  static void drm_minor_free(struct drm_device *dev, unsigned int type)
>>  {
>> -     struct drm_minor **slot;
>> +     struct drm_minor **slot, *minor;
>> +     unsigned long flags;
>>
>>       slot = drm_minor_get_slot(dev, type);
>> -     if (*slot) {
>> -             drm_mode_group_destroy(&(*slot)->mode_group);
>> -             kfree(*slot);
>> -             *slot = NULL;
>> -     }
>> +     minor = *slot;
>> +     if (!minor)
>> +             return;
>> +
>> +     drm_mode_group_destroy(&minor->mode_group);
>> +
>> +     spin_lock_irqsave(&drm_minor_lock, flags);
>> +     idr_remove(&drm_minors_idr, minor->index);
>> +     spin_unlock_irqrestore(&drm_minor_lock, flags);
>
> I don't understand why you do the idr removal in stages too. Otherwise
> this looks good.

If you call drm_minor_unregister(), we now disable lookup but keep
minor->index. If I also released the ID, a new drm_minor might get
access to it before we call drm_minor_free on the old one. This might
cause misleading debug-messages as both minor objects have the same
index. This is not really a problem, but kinda ugly.

> Aside: If two drivers load concurrently (i.e. in the brave new world
> withou drm_global_mutex) we might end up with interleaved minor ids. Dunno
> whether we'll care since userspace should use udev/sysfs lookups anyway.
> igt sometimes doesn't ;-)

I did post a patch some time ago that makes minor-ID allocations
predictable. I got a NACK from you, so this one is one you ;) But I
agree, we really should fix user-space instead of making random IDs
predictable.

Thanks
David

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 03/12] drm: call ->firstopen() before ->open()
  2014-07-24  9:31     ` David Herrmann
@ 2014-07-24 10:18       ` Daniel Vetter
  2014-07-24 13:47       ` Alex Deucher
  1 sibling, 0 replies; 39+ messages in thread
From: Daniel Vetter @ 2014-07-24 10:18 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Thu, Jul 24, 2014 at 11:31:05AM +0200, David Herrmann wrote:
> Hi
> 
> On Wed, Jul 23, 2014 at 9:25 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Wed, Jul 23, 2014 at 05:26:38PM +0200, David Herrmann wrote:
> >> Lets order things correctly:
> >>  ->load()
> >>    ->fistopen()
> >>      ->open()
> >>      ->close()
> >>    ->lastclose()
> >>  ->unload()
> >>
> >> This doesn't change much as only savage and radeon use ->firstopen() and
> >> they just do map-initialization. Therefore, the global drm mutex makes
> >> sure there cannot be any other f_op between ->open() and ->firstopen().
> >> However, once we get rid of that lock, we really want ->firstopen() to
> >> initialize the device before ->open() is called.
> >>
> >> Furthermore, this fixes the clean-up path in drm_open(). We currently
> >> don't cleanup the drm_file object if ->firstopen() fails.
> >>
> >> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> >> ---
> >>  drivers/gpu/drm/drm_fops.c | 139 +++++++++++++++++++++------------------------
> >>  include/drm/drmP.h         |   2 +-
> >>  2 files changed, 66 insertions(+), 75 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> >> index 021fe5d..8e73519 100644
> >> --- a/drivers/gpu/drm/drm_fops.c
> >> +++ b/drivers/gpu/drm/drm_fops.c
> >> @@ -45,7 +45,7 @@ EXPORT_SYMBOL(drm_global_mutex);
> >>
> >>  static int drm_open_helper(struct file *filp, struct drm_minor *minor);
> >>
> >> -static int drm_setup(struct drm_device * dev)
> >> +static int drm_firstopen(struct drm_device * dev)
> >
> > All the stuff in here is only for legacy drivers. Imo we should rename
> > this to drm_legacy_setup and hide it harder.
> >
> > Also touching the init ordering for ums drivers is a bit risky, I'd advise
> > against it. firstopen is officially dead for kms driver and really there's
> > nothing legit you can do in there. imx abused until they've switched over
> > to the component framework.
> >
> > I'd just drop this one tbh.
> 
> I did a driver audit when writing this patch, there're only 2 drivers
> using firstopen:
> 
>  * radeon_cp: sets two fields of dev_private and calls drm_addmap() on
> those. In lastclose(), it calls drm_rmmap()
>  * savage: sets several fields in dev_private, calls
> arch_phys_wc_add() for some regions and requests a drm-map for those
> via drm_addmap(). On lastclose(), it reverts exactly those steps.
> 
> Taking into account that firstopen() just runs with drm_device
> context, not with drm_file context, I really think we should be
> calling it _before_ doing ->open(). I even think the drivers would
> fail horribly if we don't do this patch and some other user-context
> sneaks in between both calls (currently impossible thanks to
> drm_global_mutex).
> 
> Both ->firstopen() callbacks are fairly trivial. In favor of making
> the error-paths work in drm_open() I'd really like to get this in.
> This patch is preparing for my drm_file rework that can make
> drm_dev_unregister() stop all open files immediately.
> 
> But I honestly don't care much for UMS drivers, so if you NACK this,
> I'd just ignore the error code and add a comment that we don't do
> error-handling for UMS.

Yeah, I prefer just labels for dragons instead of poking them ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 04/12] drm: extract legacy ctxbitmap flushing
  2014-07-24  9:34     ` David Herrmann
@ 2014-07-24 10:19       ` Daniel Vetter
  0 siblings, 0 replies; 39+ messages in thread
From: Daniel Vetter @ 2014-07-24 10:19 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Thu, Jul 24, 2014 at 11:34:45AM +0200, David Herrmann wrote:
> Hi
> 
> On Wed, Jul 23, 2014 at 9:26 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Wed, Jul 23, 2014 at 05:26:39PM +0200, David Herrmann wrote:
> >> The ctxbitmap code is only used by legacy drivers so lets try to keep it
> >> as separated as possible. Furthermore, the locking is non-obvious and
> >> kinda weird with ctxlist_mutex *and* struct_mutex. Keeping all ctxbitmap
> >> access in one file is much easier to review and makes drm_release() more
> >> readable.
> >>
> >> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> >
> > I've started to sprinkle _legacy_ over all the functions only used for
> > non-kms drivers, so that the dragon dungeons are clearly marked off. With
> > that this is Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>.
> 
> Yeah, that sounds good. But I'd prefer if we keep this patch as-is and
> I will send a follow-up which renames all "drm_ctxbitmap_*" functions
> to "drm_legacy_ctxbitmap_*". All those are internal to DRM-core so I
> can rename them all together and add drivers/gpu/drm/drm-legacy.h.

Sounds like a good plan, so r-b on the patch as-is.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 12/12] drm: make sysfs device always available for minors
  2014-07-23 15:26 ` [PATCH 12/12] drm: make sysfs device always available for minors David Herrmann
@ 2014-07-24 10:36   ` Daniel Vetter
  2014-07-24 10:48     ` David Herrmann
  0 siblings, 1 reply; 39+ messages in thread
From: Daniel Vetter @ 2014-07-24 10:36 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Wed, Jul 23, 2014 at 05:26:47PM +0200, David Herrmann wrote:
> For each minor we allocate a sysfs device as minor->kdev. Currently, this
> is allocated and registered in drm_minor_register(). This makes it
> impossible to add sysfs-attributes to the device before it is registered.
> Therefore, they are not added atomically, nor can we move device_add()
> *after* ->load() is called.
> 
> This patch makes minor->kdev available early, but only adds the device
> during minor-registration.
> 
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

Some diff got confused with this one. One comment below, but this is

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/drm_stub.c  | 22 ++++++++---
>  drivers/gpu/drm/drm_sysfs.c | 90 +++++++++++++++++++--------------------------
>  include/drm/drmP.h          |  3 +-
>  3 files changed, 54 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
> index 8b24db5..09c6bfb 100644
> --- a/drivers/gpu/drm/drm_stub.c
> +++ b/drivers/gpu/drm/drm_stub.c
> @@ -281,9 +281,19 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
>  
>  	minor->index = r;
>  
> +	minor->kdev = drm_sysfs_minor_alloc(minor);
> +	if (IS_ERR(minor->kdev)) {
> +		r = PTR_ERR(minor->kdev);
> +		goto err_index;
> +	}
> +
>  	*drm_minor_get_slot(dev, type) = minor;
>  	return 0;
>  
> +err_index:
> +	spin_lock_irqsave(&drm_minor_lock, flags);
> +	idr_remove(&drm_minors_idr, minor->index);
> +	spin_unlock_irqrestore(&drm_minor_lock, flags);
>  err_free:
>  	kfree(minor);
>  	return r;
> @@ -300,6 +310,7 @@ static void drm_minor_free(struct drm_device *dev, unsigned int type)
>  		return;
>  
>  	drm_mode_group_destroy(&minor->mode_group);
> +	put_device(minor->kdev);
>  
>  	spin_lock_irqsave(&drm_minor_lock, flags);
>  	idr_remove(&drm_minors_idr, minor->index);
> @@ -327,11 +338,9 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
>  		return ret;
>  	}
>  
> -	ret = drm_sysfs_device_add(minor);
> -	if (ret) {
> -		DRM_ERROR("DRM: Error sysfs_device_add.\n");
> +	ret = device_add(minor->kdev);
> +	if (ret)
>  		goto err_debugfs;
> -	}
>  
>  	/* replace NULL with @minor so lookups will succeed from now on */
>  	spin_lock_irqsave(&drm_minor_lock, flags);
> @@ -352,7 +361,7 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
>  	unsigned long flags;
>  
>  	minor = *drm_minor_get_slot(dev, type);
> -	if (!minor || !minor->kdev)
> +	if (!minor || !device_is_registered(minor->kdev))
>  		return;
>  
>  	/* replace @minor with NULL so lookups will fail from now on */
> @@ -360,8 +369,9 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
>  	idr_replace(&drm_minors_idr, NULL, minor->index);
>  	spin_unlock_irqrestore(&drm_minor_lock, flags);
>  
> +	device_del(minor->kdev);
> +	dev_set_drvdata(minor->kdev, NULL); /* safety belt */
>  	drm_debugfs_cleanup(minor);
> -	drm_sysfs_device_remove(minor);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
> index 7827dad..ab1a5f6 100644
> --- a/drivers/gpu/drm/drm_sysfs.c
> +++ b/drivers/gpu/drm/drm_sysfs.c
> @@ -493,71 +493,55 @@ static void drm_sysfs_release(struct device *dev)
>  }
>  
>  /**
> - * drm_sysfs_device_add - adds a class device to sysfs for a character driver
> - * @dev: DRM device to be added
> - * @head: DRM head in question
> + * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
> + * @minor: minor to allocate sysfs device for
>   *
> - * Add a DRM device to the DRM's device model class.  We use @dev's PCI device
> - * as the parent for the Linux device, and make sure it has a file containing
> - * the driver we're using (for userspace compatibility).
> + * This allocates a new sysfs device for @minor and returns it. The device is
> + * not registered nor linked. The caller has to use device_add() and
> + * device_del() to register and unregister it.
> + *
> + * Note that dev_get_drvdata() on the new device will return the minor.
> + * However, the device does not hold a ref-count to the minor nor to the
> + * underlying drm_device. This is unproblematic as long as you access the
> + * private data only in sysfs callbacks. device_del() disables those
> + * synchronously, so they cannot be called after you cleanup a minor.
>   */
> -int drm_sysfs_device_add(struct drm_minor *minor)
> +struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
>  {
> -	char *minor_str;
> +	const char *minor_str;
> +	struct device *kdev;
>  	int r;
>  
>  	if (minor->type == DRM_MINOR_CONTROL)
>  		minor_str = "controlD%d";
> -        else if (minor->type == DRM_MINOR_RENDER)
> -                minor_str = "renderD%d";
> -        else
> -                minor_str = "card%d";
> -
> -	minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
> -	if (!minor->kdev) {
> -		r = -ENOMEM;
> -		goto error;
> -	}
> -
> -	device_initialize(minor->kdev);
> -	minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index);
> -	minor->kdev->class = drm_class;
> -	minor->kdev->type = &drm_sysfs_device_minor;
> -	minor->kdev->parent = minor->dev->dev;
> -	minor->kdev->release = drm_sysfs_release;
> -	dev_set_drvdata(minor->kdev, minor);
> -
> -	r = dev_set_name(minor->kdev, minor_str, minor->index);
> +	else if (minor->type == DRM_MINOR_RENDER)
> +		minor_str = "renderD%d";
> +	else
> +		minor_str = "card%d";
> +
> +	kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
> +	if (!kdev)
> +		return ERR_PTR(-ENOMEM);

Not sure about the device model, but could we just embedded the kdev into
struct drm_minor? Separate patch ofc.

> +
> +	device_initialize(kdev);
> +	kdev->devt = MKDEV(DRM_MAJOR, minor->index);
> +	kdev->class = drm_class;
> +	kdev->type = &drm_sysfs_device_minor;
> +	kdev->parent = minor->dev->dev;
> +	kdev->release = drm_sysfs_release;
> +	dev_set_drvdata(kdev, minor);
> +
> +	r = dev_set_name(kdev, minor_str, minor->index);
>  	if (r < 0)
> -		goto error;
> -
> -	r = device_add(minor->kdev);
> -	if (r < 0)
> -		goto error;
> -
> -	return 0;
> +		goto err_free;
>  
> -error:
> -	DRM_ERROR("device create failed %d\n", r);
> -	put_device(minor->kdev);
> -	return r;
> -}
> +	return kdev;
>  
> -/**
> - * drm_sysfs_device_remove - remove DRM device
> - * @dev: DRM device to remove
> - *
> - * This call unregisters and cleans up a class device that was created with a
> - * call to drm_sysfs_device_add()
> - */
> -void drm_sysfs_device_remove(struct drm_minor *minor)
> -{
> -	if (minor->kdev)
> -		device_unregister(minor->kdev);
> -	minor->kdev = NULL;
> +err_free:
> +	put_device(kdev);
> +	return ERR_PTR(r);
>  }
>  
> -
>  /**
>   * drm_class_device_register - Register a struct device in the drm class.
>   *
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 17dd67a..d28d337 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1492,9 +1492,8 @@ extern int drm_pci_set_unique(struct drm_device *dev,
>  struct drm_sysfs_class;
>  extern struct class *drm_sysfs_create(struct module *owner, char *name);
>  extern void drm_sysfs_destroy(void);
> -extern int drm_sysfs_device_add(struct drm_minor *minor);
> +extern struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
>  extern void drm_sysfs_hotplug_event(struct drm_device *dev);
> -extern void drm_sysfs_device_remove(struct drm_minor *minor);
>  extern int drm_sysfs_connector_add(struct drm_connector *connector);
>  extern void drm_sysfs_connector_remove(struct drm_connector *connector);
>  
> -- 
> 2.0.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 12/12] drm: make sysfs device always available for minors
  2014-07-24 10:36   ` Daniel Vetter
@ 2014-07-24 10:48     ` David Herrmann
  2014-07-24 12:31       ` Daniel Vetter
  0 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-24 10:48 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, dri-devel

Hi

On Thu, Jul 24, 2014 at 12:36 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Wed, Jul 23, 2014 at 05:26:47PM +0200, David Herrmann wrote:
>> For each minor we allocate a sysfs device as minor->kdev. Currently, this
>> is allocated and registered in drm_minor_register(). This makes it
>> impossible to add sysfs-attributes to the device before it is registered.
>> Therefore, they are not added atomically, nor can we move device_add()
>> *after* ->load() is called.
>>
>> This patch makes minor->kdev available early, but only adds the device
>> during minor-registration.
>>
>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>
> Some diff got confused with this one. One comment below, but this is
>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
>> ---
>>  drivers/gpu/drm/drm_stub.c  | 22 ++++++++---
>>  drivers/gpu/drm/drm_sysfs.c | 90 +++++++++++++++++++--------------------------
>>  include/drm/drmP.h          |  3 +-
>>  3 files changed, 54 insertions(+), 61 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
>> index 8b24db5..09c6bfb 100644
>> --- a/drivers/gpu/drm/drm_stub.c
>> +++ b/drivers/gpu/drm/drm_stub.c
>> @@ -281,9 +281,19 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
>>
>>       minor->index = r;
>>
>> +     minor->kdev = drm_sysfs_minor_alloc(minor);
>> +     if (IS_ERR(minor->kdev)) {
>> +             r = PTR_ERR(minor->kdev);
>> +             goto err_index;
>> +     }
>> +
>>       *drm_minor_get_slot(dev, type) = minor;
>>       return 0;
>>
>> +err_index:
>> +     spin_lock_irqsave(&drm_minor_lock, flags);
>> +     idr_remove(&drm_minors_idr, minor->index);
>> +     spin_unlock_irqrestore(&drm_minor_lock, flags);
>>  err_free:
>>       kfree(minor);
>>       return r;
>> @@ -300,6 +310,7 @@ static void drm_minor_free(struct drm_device *dev, unsigned int type)
>>               return;
>>
>>       drm_mode_group_destroy(&minor->mode_group);
>> +     put_device(minor->kdev);
>>
>>       spin_lock_irqsave(&drm_minor_lock, flags);
>>       idr_remove(&drm_minors_idr, minor->index);
>> @@ -327,11 +338,9 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
>>               return ret;
>>       }
>>
>> -     ret = drm_sysfs_device_add(minor);
>> -     if (ret) {
>> -             DRM_ERROR("DRM: Error sysfs_device_add.\n");
>> +     ret = device_add(minor->kdev);
>> +     if (ret)
>>               goto err_debugfs;
>> -     }
>>
>>       /* replace NULL with @minor so lookups will succeed from now on */
>>       spin_lock_irqsave(&drm_minor_lock, flags);
>> @@ -352,7 +361,7 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
>>       unsigned long flags;
>>
>>       minor = *drm_minor_get_slot(dev, type);
>> -     if (!minor || !minor->kdev)
>> +     if (!minor || !device_is_registered(minor->kdev))
>>               return;
>>
>>       /* replace @minor with NULL so lookups will fail from now on */
>> @@ -360,8 +369,9 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
>>       idr_replace(&drm_minors_idr, NULL, minor->index);
>>       spin_unlock_irqrestore(&drm_minor_lock, flags);
>>
>> +     device_del(minor->kdev);
>> +     dev_set_drvdata(minor->kdev, NULL); /* safety belt */
>>       drm_debugfs_cleanup(minor);
>> -     drm_sysfs_device_remove(minor);
>>  }
>>
>>  /**
>> diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
>> index 7827dad..ab1a5f6 100644
>> --- a/drivers/gpu/drm/drm_sysfs.c
>> +++ b/drivers/gpu/drm/drm_sysfs.c
>> @@ -493,71 +493,55 @@ static void drm_sysfs_release(struct device *dev)
>>  }
>>
>>  /**
>> - * drm_sysfs_device_add - adds a class device to sysfs for a character driver
>> - * @dev: DRM device to be added
>> - * @head: DRM head in question
>> + * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
>> + * @minor: minor to allocate sysfs device for
>>   *
>> - * Add a DRM device to the DRM's device model class.  We use @dev's PCI device
>> - * as the parent for the Linux device, and make sure it has a file containing
>> - * the driver we're using (for userspace compatibility).
>> + * This allocates a new sysfs device for @minor and returns it. The device is
>> + * not registered nor linked. The caller has to use device_add() and
>> + * device_del() to register and unregister it.
>> + *
>> + * Note that dev_get_drvdata() on the new device will return the minor.
>> + * However, the device does not hold a ref-count to the minor nor to the
>> + * underlying drm_device. This is unproblematic as long as you access the
>> + * private data only in sysfs callbacks. device_del() disables those
>> + * synchronously, so they cannot be called after you cleanup a minor.
>>   */
>> -int drm_sysfs_device_add(struct drm_minor *minor)
>> +struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
>>  {
>> -     char *minor_str;
>> +     const char *minor_str;
>> +     struct device *kdev;
>>       int r;
>>
>>       if (minor->type == DRM_MINOR_CONTROL)
>>               minor_str = "controlD%d";
>> -        else if (minor->type == DRM_MINOR_RENDER)
>> -                minor_str = "renderD%d";
>> -        else
>> -                minor_str = "card%d";
>> -
>> -     minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
>> -     if (!minor->kdev) {
>> -             r = -ENOMEM;
>> -             goto error;
>> -     }
>> -
>> -     device_initialize(minor->kdev);
>> -     minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index);
>> -     minor->kdev->class = drm_class;
>> -     minor->kdev->type = &drm_sysfs_device_minor;
>> -     minor->kdev->parent = minor->dev->dev;
>> -     minor->kdev->release = drm_sysfs_release;
>> -     dev_set_drvdata(minor->kdev, minor);
>> -
>> -     r = dev_set_name(minor->kdev, minor_str, minor->index);
>> +     else if (minor->type == DRM_MINOR_RENDER)
>> +             minor_str = "renderD%d";
>> +     else
>> +             minor_str = "card%d";
>> +
>> +     kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
>> +     if (!kdev)
>> +             return ERR_PTR(-ENOMEM);
>
> Not sure about the device model, but could we just embedded the kdev into
> struct drm_minor? Separate patch ofc.

I wouldn't do that. If we embed "struct device", then we _have_ to use
the ref-counting of it (get_device(), put_device()) as all generic
devices are ref-counted. I'd really like to avoid that. We make sure
no-one uses dev_get_drvdata() on a device except for sysfs attribute
handlers. Those handlers are removed synchronously during
device_del(). Therefore, we can be sure even if the device lives
longer than it's parent "struct drm_minor", no-one accesses the
private data. We can thus release the kdev and free the minor early.
The kdev will hang around until all refs are dropped, but it's
detached from our drm_minor (that's why I do the drm_set_drvdata(kdev,
NULL) after device_del() as safety-belt).

Thanks
David

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 02/12] drm: drop unused "struct drm_queue"
  2014-07-23 19:35   ` Daniel Vetter
@ 2014-07-24 11:35     ` David Herrmann
  0 siblings, 0 replies; 39+ messages in thread
From: David Herrmann @ 2014-07-24 11:35 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, dri-devel

Hi

On Wed, Jul 23, 2014 at 9:35 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Wed, Jul 23, 2014 at 05:26:37PM +0200, David Herrmann wrote:
>> This object is unused, drop it.
>>
>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>
> Funny how after even all my "kill stuff with fire" series there's still
> such low hanging fruit left ;-)
>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

I think the problem is, they all depend on each other. With this patch
applied, "drm_waitlist" becomes unused.. noticed it just now. I
already have a followup.

Thanks
David

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 11/12] drm: make minor->index available early
  2014-07-24 10:16     ` David Herrmann
@ 2014-07-24 12:30       ` Daniel Vetter
  0 siblings, 0 replies; 39+ messages in thread
From: Daniel Vetter @ 2014-07-24 12:30 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Thu, Jul 24, 2014 at 12:16:59PM +0200, David Herrmann wrote:
> Hi
> 
> On Thu, Jul 24, 2014 at 12:03 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Wed, Jul 23, 2014 at 05:26:46PM +0200, David Herrmann wrote:
> >> Instead of allocating the minor-index during registration, we now do this
> >> during allocation. This way, debug-messages between minor-allocation and
> >> minor-registration will now use the correct minor instead of 0. Same is
> >> done for unregistration vs. free, so debug-messages between
> >> device-shutdown and device-destruction show proper indices.
> >>
> >> Even though minor-indices are allocated early, we don't enable minor
> >> lookup early. Instead, we keep the entry set to NULL and replace it during
> >> registration / unregistration. This way, the index is allocated but lookup
> >> only works if registered.
> >>
> >> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> >> ---
> >>  drivers/gpu/drm/drm_stub.c | 84 +++++++++++++++++++++++++---------------------
> >>  1 file changed, 46 insertions(+), 38 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
> >> index b249f14..8b24db5 100644
> >> --- a/drivers/gpu/drm/drm_stub.c
> >> +++ b/drivers/gpu/drm/drm_stub.c
> >> @@ -256,6 +256,8 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
> >>  static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
> >>  {
> >>       struct drm_minor *minor;
> >> +     unsigned long flags;
> >> +     int r;
> >>
> >>       minor = kzalloc(sizeof(*minor), GFP_KERNEL);
> >>       if (!minor)
> >> @@ -264,57 +266,68 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
> >>       minor->type = type;
> >>       minor->dev = dev;
> >>
> >> +     idr_preload(GFP_KERNEL);
> >> +     spin_lock_irqsave(&drm_minor_lock, flags);
> >> +     r = idr_alloc(&drm_minors_idr,
> >> +                   NULL,
> >> +                   64 * type,
> >> +                   64 * (type + 1),
> >> +                   GFP_NOWAIT);
> >> +     spin_unlock_irqrestore(&drm_minor_lock, flags);
> >> +     idr_preload_end();
> >> +
> >> +     if (r < 0)
> >> +             goto err_free;
> >> +
> >> +     minor->index = r;
> >> +
> >>       *drm_minor_get_slot(dev, type) = minor;
> >>       return 0;
> >> +
> >> +err_free:
> >> +     kfree(minor);
> >> +     return r;
> >>  }
> >>
> >>  static void drm_minor_free(struct drm_device *dev, unsigned int type)
> >>  {
> >> -     struct drm_minor **slot;
> >> +     struct drm_minor **slot, *minor;
> >> +     unsigned long flags;
> >>
> >>       slot = drm_minor_get_slot(dev, type);
> >> -     if (*slot) {
> >> -             drm_mode_group_destroy(&(*slot)->mode_group);
> >> -             kfree(*slot);
> >> -             *slot = NULL;
> >> -     }
> >> +     minor = *slot;
> >> +     if (!minor)
> >> +             return;
> >> +
> >> +     drm_mode_group_destroy(&minor->mode_group);
> >> +
> >> +     spin_lock_irqsave(&drm_minor_lock, flags);
> >> +     idr_remove(&drm_minors_idr, minor->index);
> >> +     spin_unlock_irqrestore(&drm_minor_lock, flags);
> >
> > I don't understand why you do the idr removal in stages too. Otherwise
> > this looks good.
> 
> If you call drm_minor_unregister(), we now disable lookup but keep
> minor->index. If I also released the ID, a new drm_minor might get
> access to it before we call drm_minor_free on the old one. This might
> cause misleading debug-messages as both minor objects have the same
> index. This is not really a problem, but kinda ugly.

Ah, I see. Makes sense. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> > Aside: If two drivers load concurrently (i.e. in the brave new world
> > withou drm_global_mutex) we might end up with interleaved minor ids. Dunno
> > whether we'll care since userspace should use udev/sysfs lookups anyway.
> > igt sometimes doesn't ;-)
> 
> I did post a patch some time ago that makes minor-ID allocations
> predictable. I got a NACK from you, so this one is one you ;) But I
> agree, we really should fix user-space instead of making random IDs
> predictable.

/me remembers again ...

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 12/12] drm: make sysfs device always available for minors
  2014-07-24 10:48     ` David Herrmann
@ 2014-07-24 12:31       ` Daniel Vetter
  0 siblings, 0 replies; 39+ messages in thread
From: Daniel Vetter @ 2014-07-24 12:31 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Thu, Jul 24, 2014 at 12:48:49PM +0200, David Herrmann wrote:
> Hi
> 
> On Thu, Jul 24, 2014 at 12:36 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Wed, Jul 23, 2014 at 05:26:47PM +0200, David Herrmann wrote:
> >> For each minor we allocate a sysfs device as minor->kdev. Currently, this
> >> is allocated and registered in drm_minor_register(). This makes it
> >> impossible to add sysfs-attributes to the device before it is registered.
> >> Therefore, they are not added atomically, nor can we move device_add()
> >> *after* ->load() is called.
> >>
> >> This patch makes minor->kdev available early, but only adds the device
> >> during minor-registration.
> >>
> >> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> >
> > Some diff got confused with this one. One comment below, but this is
> >
> > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> >
> >> ---
> >>  drivers/gpu/drm/drm_stub.c  | 22 ++++++++---
> >>  drivers/gpu/drm/drm_sysfs.c | 90 +++++++++++++++++++--------------------------
> >>  include/drm/drmP.h          |  3 +-
> >>  3 files changed, 54 insertions(+), 61 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
> >> index 8b24db5..09c6bfb 100644
> >> --- a/drivers/gpu/drm/drm_stub.c
> >> +++ b/drivers/gpu/drm/drm_stub.c
> >> @@ -281,9 +281,19 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
> >>
> >>       minor->index = r;
> >>
> >> +     minor->kdev = drm_sysfs_minor_alloc(minor);
> >> +     if (IS_ERR(minor->kdev)) {
> >> +             r = PTR_ERR(minor->kdev);
> >> +             goto err_index;
> >> +     }
> >> +
> >>       *drm_minor_get_slot(dev, type) = minor;
> >>       return 0;
> >>
> >> +err_index:
> >> +     spin_lock_irqsave(&drm_minor_lock, flags);
> >> +     idr_remove(&drm_minors_idr, minor->index);
> >> +     spin_unlock_irqrestore(&drm_minor_lock, flags);
> >>  err_free:
> >>       kfree(minor);
> >>       return r;
> >> @@ -300,6 +310,7 @@ static void drm_minor_free(struct drm_device *dev, unsigned int type)
> >>               return;
> >>
> >>       drm_mode_group_destroy(&minor->mode_group);
> >> +     put_device(minor->kdev);
> >>
> >>       spin_lock_irqsave(&drm_minor_lock, flags);
> >>       idr_remove(&drm_minors_idr, minor->index);
> >> @@ -327,11 +338,9 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
> >>               return ret;
> >>       }
> >>
> >> -     ret = drm_sysfs_device_add(minor);
> >> -     if (ret) {
> >> -             DRM_ERROR("DRM: Error sysfs_device_add.\n");
> >> +     ret = device_add(minor->kdev);
> >> +     if (ret)
> >>               goto err_debugfs;
> >> -     }
> >>
> >>       /* replace NULL with @minor so lookups will succeed from now on */
> >>       spin_lock_irqsave(&drm_minor_lock, flags);
> >> @@ -352,7 +361,7 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
> >>       unsigned long flags;
> >>
> >>       minor = *drm_minor_get_slot(dev, type);
> >> -     if (!minor || !minor->kdev)
> >> +     if (!minor || !device_is_registered(minor->kdev))
> >>               return;
> >>
> >>       /* replace @minor with NULL so lookups will fail from now on */
> >> @@ -360,8 +369,9 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
> >>       idr_replace(&drm_minors_idr, NULL, minor->index);
> >>       spin_unlock_irqrestore(&drm_minor_lock, flags);
> >>
> >> +     device_del(minor->kdev);
> >> +     dev_set_drvdata(minor->kdev, NULL); /* safety belt */
> >>       drm_debugfs_cleanup(minor);
> >> -     drm_sysfs_device_remove(minor);
> >>  }
> >>
> >>  /**
> >> diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
> >> index 7827dad..ab1a5f6 100644
> >> --- a/drivers/gpu/drm/drm_sysfs.c
> >> +++ b/drivers/gpu/drm/drm_sysfs.c
> >> @@ -493,71 +493,55 @@ static void drm_sysfs_release(struct device *dev)
> >>  }
> >>
> >>  /**
> >> - * drm_sysfs_device_add - adds a class device to sysfs for a character driver
> >> - * @dev: DRM device to be added
> >> - * @head: DRM head in question
> >> + * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
> >> + * @minor: minor to allocate sysfs device for
> >>   *
> >> - * Add a DRM device to the DRM's device model class.  We use @dev's PCI device
> >> - * as the parent for the Linux device, and make sure it has a file containing
> >> - * the driver we're using (for userspace compatibility).
> >> + * This allocates a new sysfs device for @minor and returns it. The device is
> >> + * not registered nor linked. The caller has to use device_add() and
> >> + * device_del() to register and unregister it.
> >> + *
> >> + * Note that dev_get_drvdata() on the new device will return the minor.
> >> + * However, the device does not hold a ref-count to the minor nor to the
> >> + * underlying drm_device. This is unproblematic as long as you access the
> >> + * private data only in sysfs callbacks. device_del() disables those
> >> + * synchronously, so they cannot be called after you cleanup a minor.
> >>   */
> >> -int drm_sysfs_device_add(struct drm_minor *minor)
> >> +struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
> >>  {
> >> -     char *minor_str;
> >> +     const char *minor_str;
> >> +     struct device *kdev;
> >>       int r;
> >>
> >>       if (minor->type == DRM_MINOR_CONTROL)
> >>               minor_str = "controlD%d";
> >> -        else if (minor->type == DRM_MINOR_RENDER)
> >> -                minor_str = "renderD%d";
> >> -        else
> >> -                minor_str = "card%d";
> >> -
> >> -     minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
> >> -     if (!minor->kdev) {
> >> -             r = -ENOMEM;
> >> -             goto error;
> >> -     }
> >> -
> >> -     device_initialize(minor->kdev);
> >> -     minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index);
> >> -     minor->kdev->class = drm_class;
> >> -     minor->kdev->type = &drm_sysfs_device_minor;
> >> -     minor->kdev->parent = minor->dev->dev;
> >> -     minor->kdev->release = drm_sysfs_release;
> >> -     dev_set_drvdata(minor->kdev, minor);
> >> -
> >> -     r = dev_set_name(minor->kdev, minor_str, minor->index);
> >> +     else if (minor->type == DRM_MINOR_RENDER)
> >> +             minor_str = "renderD%d";
> >> +     else
> >> +             minor_str = "card%d";
> >> +
> >> +     kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
> >> +     if (!kdev)
> >> +             return ERR_PTR(-ENOMEM);
> >
> > Not sure about the device model, but could we just embedded the kdev into
> > struct drm_minor? Separate patch ofc.
> 
> I wouldn't do that. If we embed "struct device", then we _have_ to use
> the ref-counting of it (get_device(), put_device()) as all generic
> devices are ref-counted. I'd really like to avoid that. We make sure
> no-one uses dev_get_drvdata() on a device except for sysfs attribute
> handlers. Those handlers are removed synchronously during
> device_del(). Therefore, we can be sure even if the device lives
> longer than it's parent "struct drm_minor", no-one accesses the
> private data. We can thus release the kdev and free the minor early.
> The kdev will hang around until all refs are dropped, but it's
> detached from our drm_minor (that's why I do the drm_set_drvdata(kdev,
> NULL) after device_del() as safety-belt).

Hm yeah, makes sense. r-b still applies ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 03/12] drm: call ->firstopen() before ->open()
  2014-07-24  9:31     ` David Herrmann
  2014-07-24 10:18       ` Daniel Vetter
@ 2014-07-24 13:47       ` Alex Deucher
  1 sibling, 0 replies; 39+ messages in thread
From: Alex Deucher @ 2014-07-24 13:47 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Thu, Jul 24, 2014 at 5:31 AM, David Herrmann <dh.herrmann@gmail.com> wrote:
> Hi
>
> On Wed, Jul 23, 2014 at 9:25 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>> On Wed, Jul 23, 2014 at 05:26:38PM +0200, David Herrmann wrote:
>>> Lets order things correctly:
>>>  ->load()
>>>    ->fistopen()
>>>      ->open()
>>>      ->close()
>>>    ->lastclose()
>>>  ->unload()
>>>
>>> This doesn't change much as only savage and radeon use ->firstopen() and
>>> they just do map-initialization. Therefore, the global drm mutex makes
>>> sure there cannot be any other f_op between ->open() and ->firstopen().
>>> However, once we get rid of that lock, we really want ->firstopen() to
>>> initialize the device before ->open() is called.
>>>
>>> Furthermore, this fixes the clean-up path in drm_open(). We currently
>>> don't cleanup the drm_file object if ->firstopen() fails.
>>>
>>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>>> ---
>>>  drivers/gpu/drm/drm_fops.c | 139 +++++++++++++++++++++------------------------
>>>  include/drm/drmP.h         |   2 +-
>>>  2 files changed, 66 insertions(+), 75 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
>>> index 021fe5d..8e73519 100644
>>> --- a/drivers/gpu/drm/drm_fops.c
>>> +++ b/drivers/gpu/drm/drm_fops.c
>>> @@ -45,7 +45,7 @@ EXPORT_SYMBOL(drm_global_mutex);
>>>
>>>  static int drm_open_helper(struct file *filp, struct drm_minor *minor);
>>>
>>> -static int drm_setup(struct drm_device * dev)
>>> +static int drm_firstopen(struct drm_device * dev)
>>
>> All the stuff in here is only for legacy drivers. Imo we should rename
>> this to drm_legacy_setup and hide it harder.
>>
>> Also touching the init ordering for ums drivers is a bit risky, I'd advise
>> against it. firstopen is officially dead for kms driver and really there's
>> nothing legit you can do in there. imx abused until they've switched over
>> to the component framework.
>>
>> I'd just drop this one tbh.
>
> I did a driver audit when writing this patch, there're only 2 drivers
> using firstopen:
>
>  * radeon_cp: sets two fields of dev_private and calls drm_addmap() on
> those. In lastclose(), it calls drm_rmmap()
>  * savage: sets several fields in dev_private, calls
> arch_phys_wc_add() for some regions and requests a drm-map for those
> via drm_addmap(). On lastclose(), it reverts exactly those steps.
>
> Taking into account that firstopen() just runs with drm_device
> context, not with drm_file context, I really think we should be
> calling it _before_ doing ->open(). I even think the drivers would
> fail horribly if we don't do this patch and some other user-context
> sneaks in between both calls (currently impossible thanks to
> drm_global_mutex).
>
> Both ->firstopen() callbacks are fairly trivial. In favor of making
> the error-paths work in drm_open() I'd really like to get this in.
> This patch is preparing for my drm_file rework that can make
> drm_dev_unregister() stop all open files immediately.
>
> But I honestly don't care much for UMS drivers, so if you NACK this,
> I'd just ignore the error code and add a comment that we don't do
> error-handling for UMS.

Well, radeon UMS support is in the kernel deprecated and hasn't been
built by default for a while and I doubt anyone has tested it in
years.  I'm not sure what the current state of savage is.  I'm fine
either way.

Alex


>
> Cheers
> David
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 07/12] drm: drop redundant drm_file->is_master
  2014-07-24  9:52   ` Daniel Vetter
@ 2014-07-24 21:38     ` David Herrmann
  2014-07-25  7:56       ` Daniel Vetter
  0 siblings, 1 reply; 39+ messages in thread
From: David Herrmann @ 2014-07-24 21:38 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, dri-devel

Hi

On Thu, Jul 24, 2014 at 11:52 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Wed, Jul 23, 2014 at 05:26:42PM +0200, David Herrmann wrote:
>> The drm_file->is_master field is redundant as it's equivalent to:
>>     drm_file->master && drm_file->master == drm_file->minor->master
>>
>> 1) "=>"
>>   Whenever we set drm_file->is_master, we also set:
>>       drm_file->minor->master = drm_file->master;
>>
>>   Whenever we clear drm_file->is_master, we also call:
>>       drm_master_put(&drm_file->minor->master);
>>   which implicitly clears it to NULL.
>>
>> 2) "<="
>>   minor->master cannot be set if it is non-NULL. Therefore, it stays as
>>   is unless a file drops it.
>>
>>   If minor->master is NULL, it is only set by places that also adjust
>>   drm_file->is_master.
>>
>> Therefore, we can safely drop is_master and replace it by an inline helper
>> that matches:
>>     drm_file->master && drm_file->master == drm_file->minor->master
>>
>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>
> Docbook for drm_is_master is missing, otherwise Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
> And one question below which doesn't really matter for this patch here.
> See below

Fixed, thanks!

> [snip]
>
>> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
>> index d91e09f..e1bb585 100644
>> --- a/include/drm/drmP.h
>> +++ b/include/drm/drmP.h
>> @@ -387,8 +387,6 @@ struct drm_prime_file_private {
>>  struct drm_file {
>>       unsigned always_authenticated :1;
>>       unsigned authenticated :1;
>> -     /* Whether we're master for a minor. Protected by master_mutex */
>> -     unsigned is_master :1;
>>       /* true when the client has asked us to expose stereo 3D mode flags */
>>       unsigned stereo_allowed :1;
>>       /*
>> @@ -1034,7 +1032,7 @@ struct drm_device {
>>       /** \name Locks */
>>       /*@{ */
>>       struct mutex struct_mutex;      /**< For others */
>> -     struct mutex master_mutex;      /**< For drm_minor::master and drm_file::is_master */
>> +     struct mutex master_mutex;      /**< For drm_minor::master */
>>       /*@} */
>>
>>       /** \name Usage Counters */
>> @@ -1172,6 +1170,11 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv)
>>       return file_priv->minor->type == DRM_MINOR_LEGACY;
>>  }
>>
>
> Docbook here please ...
>> +static inline bool drm_is_master(const struct drm_file *file)
>> +{
>
> Hm, we don't have any means to synchronize is_master checks with
> concurrent ioctls and stuff. Do we care? Orthogonal issue really.

We don't.. My drm-master reworks contains a comment about that. It's
not really problematic as all ioctls run for a determinate time in
kernel-code except for drm_read(), but drm_read() is per-file, not
per-device, so we're fine. However, with unfortunate timings, we might
really end up with problems.

vmwgfx solves this by using separate locks and verifying them against
the current master. it's not perfect and I'm not sure I like it better
than no locks, but at least they were aware of the problem.

Btw., the only thing I know how to solve it properly is to make
"master_mutex" an rwlock and all f_op entries take the read-lock,
while master modifications take the write-lock. Not sure it's worth
it, though.

Thanks
David

>> +     return file->master && file->master == file->minor->master;
>> +}
>> +
>>  /******************************************************************/
>>  /** \name Internal function definitions */
>>  /*@{*/
>> --
>> 2.0.2
>>
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 07/12] drm: drop redundant drm_file->is_master
  2014-07-24 21:38     ` David Herrmann
@ 2014-07-25  7:56       ` Daniel Vetter
  2014-07-28 15:26         ` David Herrmann
  0 siblings, 1 reply; 39+ messages in thread
From: Daniel Vetter @ 2014-07-25  7:56 UTC (permalink / raw)
  To: David Herrmann; +Cc: Daniel Vetter, dri-devel

On Thu, Jul 24, 2014 at 11:38:28PM +0200, David Herrmann wrote:
> On Thu, Jul 24, 2014 at 11:52 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Wed, Jul 23, 2014 at 05:26:42PM +0200, David Herrmann wrote:
> >> +static inline bool drm_is_master(const struct drm_file *file)
> >> +{
> >
> > Hm, we don't have any means to synchronize is_master checks with
> > concurrent ioctls and stuff. Do we care? Orthogonal issue really.
> 
> We don't.. My drm-master reworks contains a comment about that. It's
> not really problematic as all ioctls run for a determinate time in
> kernel-code except for drm_read(), but drm_read() is per-file, not
> per-device, so we're fine. However, with unfortunate timings, we might
> really end up with problems.
> 
> vmwgfx solves this by using separate locks and verifying them against
> the current master. it's not perfect and I'm not sure I like it better
> than no locks, but at least they were aware of the problem.
> 
> Btw., the only thing I know how to solve it properly is to make
> "master_mutex" an rwlock and all f_op entries take the read-lock,
> while master modifications take the write-lock. Not sure it's worth
> it, though.

Imo that's terrible. And I'm not even sure we need to care, e.g. if we do
a master switch to a different compositor any ioctl the new compositor
does will grab some locks, which will force the old ioctl to complete.

Well mostly, and only if we don't do lockless tricks or lock-dropping and
it's racy.

I guess a proper fix would be to wait for all ioctls on a device to
complete. The vfs doesn't have any cool infrastructure for this as part of
the general revoke work that we could reuse?
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 07/12] drm: drop redundant drm_file->is_master
  2014-07-25  7:56       ` Daniel Vetter
@ 2014-07-28 15:26         ` David Herrmann
  0 siblings, 0 replies; 39+ messages in thread
From: David Herrmann @ 2014-07-28 15:26 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, dri-devel

Hi

On Fri, Jul 25, 2014 at 9:56 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Thu, Jul 24, 2014 at 11:38:28PM +0200, David Herrmann wrote:
>> On Thu, Jul 24, 2014 at 11:52 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
>> > On Wed, Jul 23, 2014 at 05:26:42PM +0200, David Herrmann wrote:
>> >> +static inline bool drm_is_master(const struct drm_file *file)
>> >> +{
>> >
>> > Hm, we don't have any means to synchronize is_master checks with
>> > concurrent ioctls and stuff. Do we care? Orthogonal issue really.
>>
>> We don't.. My drm-master reworks contains a comment about that. It's
>> not really problematic as all ioctls run for a determinate time in
>> kernel-code except for drm_read(), but drm_read() is per-file, not
>> per-device, so we're fine. However, with unfortunate timings, we might
>> really end up with problems.
>>
>> vmwgfx solves this by using separate locks and verifying them against
>> the current master. it's not perfect and I'm not sure I like it better
>> than no locks, but at least they were aware of the problem.
>>
>> Btw., the only thing I know how to solve it properly is to make
>> "master_mutex" an rwlock and all f_op entries take the read-lock,
>> while master modifications take the write-lock. Not sure it's worth
>> it, though.
>
> Imo that's terrible. And I'm not even sure we need to care, e.g. if we do
> a master switch to a different compositor any ioctl the new compositor
> does will grab some locks, which will force the old ioctl to complete.
>
> Well mostly, and only if we don't do lockless tricks or lock-dropping and
> it's racy.

There is always a race! Like this:

CPU A:
1: enter drm_ioctl()
2: check file->is_master
3: enter drm_some_ioctl()
4: acquire some DRM internal locks

If CPU B acquires DRM-Master between step 2 and 3, CPU A might execute
an ioctl with an arbitrary delay. Maybe CPU B even executed some ioctl
after acquiring DRM-Master before CPU A had the chance to enter the
ioctl it's about to execute.

Not that I care much, but we have to remember that those races always
exist. Given that DRM-Master is privileged, this is not really
high-priority to fix..

> I guess a proper fix would be to wait for all ioctls on a device to
> complete. The vfs doesn't have any cool infrastructure for this as part of
> the general revoke work that we could reuse?

What the VFS rework does is this:

if (!atomic_inc_unless_negative(file->sth))
        return -ENODEV;
ret = file->f_op->some_op();
atomic_dec(file->sth);
return ret;

That is, it wraps all calls to a file-operation with an
atomic-counter. However, there's only one counter per open-file, not
one per file-operation. If we'd want that for DRM-Master, we couldn't
use it as otherwise all file-operations would be blocked. Furthermore,
VFS only allows disabling an open-file. Once disabled, you cannot
enable it again.

So I don't think a read/write lock is a bad idea. RCU doesn't work as
our ioctls are way to heavy for rcu_read_lock(), SRCU is basically
rw-sem for our use-case. A hand-crafted atomic counter is also
equivalent to rw-sem. So yeah, it might lock nasty, but any other
solution will just hide the fact that we have a read/write lock.

Anyhow, I'm not working on a fix, so if no-one else looks at it, we
can just ignore it.

Thanks
David

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2014-07-28 15:26 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-23 15:26 [PATCH 00/12] DRM: Random Cleanups David Herrmann
2014-07-23 15:26 ` [PATCH 01/12] drm: remove unused "struct drm_freelist" David Herrmann
2014-07-23 19:17   ` Daniel Vetter
2014-07-23 15:26 ` [PATCH 02/12] drm: drop unused "struct drm_queue" David Herrmann
2014-07-23 19:35   ` Daniel Vetter
2014-07-24 11:35     ` David Herrmann
2014-07-23 15:26 ` [PATCH 03/12] drm: call ->firstopen() before ->open() David Herrmann
2014-07-23 19:25   ` Daniel Vetter
2014-07-24  9:31     ` David Herrmann
2014-07-24 10:18       ` Daniel Vetter
2014-07-24 13:47       ` Alex Deucher
2014-07-23 15:26 ` [PATCH 04/12] drm: extract legacy ctxbitmap flushing David Herrmann
2014-07-23 19:26   ` Daniel Vetter
2014-07-24  9:34     ` David Herrmann
2014-07-24 10:19       ` Daniel Vetter
2014-07-23 15:26 ` [PATCH 05/12] drm: drop i386 verification David Herrmann
2014-07-23 15:26 ` [PATCH 06/12] drm: fix __alpha__ PCI lookup David Herrmann
2014-07-23 19:29   ` Daniel Vetter
2014-07-23 19:36     ` Daniel Vetter
2014-07-23 15:26 ` [PATCH 07/12] drm: drop redundant drm_file->is_master David Herrmann
2014-07-24  9:52   ` Daniel Vetter
2014-07-24 21:38     ` David Herrmann
2014-07-25  7:56       ` Daniel Vetter
2014-07-28 15:26         ` David Herrmann
2014-07-23 15:26 ` [PATCH 08/12] drm: don't de-authenticate clients on master-close David Herrmann
2014-07-24  9:57   ` Daniel Vetter
2014-07-23 15:26 ` [PATCH 09/12] drm: move module initialization to drm_stub.c David Herrmann
2014-07-23 15:26 ` [PATCH 10/12] drm: merge drm_drv.c into drm_ioctl.c David Herrmann
2014-07-23 16:16   ` David Herrmann
2014-07-23 19:33   ` Daniel Vetter
2014-07-23 15:26 ` [PATCH 11/12] drm: make minor->index available early David Herrmann
2014-07-24 10:03   ` Daniel Vetter
2014-07-24 10:16     ` David Herrmann
2014-07-24 12:30       ` Daniel Vetter
2014-07-23 15:26 ` [PATCH 12/12] drm: make sysfs device always available for minors David Herrmann
2014-07-24 10:36   ` Daniel Vetter
2014-07-24 10:48     ` David Herrmann
2014-07-24 12:31       ` Daniel Vetter
2014-07-23 16:24 ` [PATCH 00/12] DRM: Random Cleanups Alex Deucher

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.