All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: DRI Development <dri-devel@lists.freedesktop.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>,
	Intel Graphics Development <intel-gfx@lists.freedesktop.org>,
	Sergi Granell <xerpi.g.12@gmail.com>,
	Daniel Vetter <daniel.vetter@intel.com>
Subject: [PATCH 04/11] drm: document drm_ioctl.[hc]
Date: Tue,  4 Apr 2017 11:52:57 +0200	[thread overview]
Message-ID: <20170404095304.17599-4-daniel.vetter@ffwll.ch> (raw)
In-Reply-To: <20170404095304.17599-1-daniel.vetter@ffwll.ch>

Also unify/merge with the existing stuff.

I was a bit torn where to put this, but in the end I decided to put
all the ioctl/sysfs/debugfs stuff into drm-uapi.rst. That means we
have a bit a split with the other uapi related stuff used internally,
like drm_file.[hc], but I think overall this makes more sense.

If it's too confusing we can always add more cross-links to make it
more discoverable. But the auto-sprinkling of links kernel-doc already
does seems sufficient.

Also for prettier docs and more cross-links, switch the internal
defines over to an enum, as usual.

v2: Update kerneldoc fro drm_compat_ioctl too (caught by 0day), plus a
bit more drive-by polish.

v3: Fix typo, spotted by xerpi on irc (Sergi).

Cc: Sergi Granell <xerpi.g.12@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-internals.rst |  50 ----------------
 Documentation/gpu/drm-uapi.rst      |  14 +++++
 drivers/gpu/drm/drm_ioc32.c         |  76 ++++++++++++-----------
 drivers/gpu/drm/drm_ioctl.c         |  50 +++++++++++++++-
 include/drm/drm_ioctl.h             | 116 +++++++++++++++++++++++++++++++-----
 5 files changed, 203 insertions(+), 103 deletions(-)

diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst
index a09c721f9e89..babfb6143bd9 100644
--- a/Documentation/gpu/drm-internals.rst
+++ b/Documentation/gpu/drm-internals.rst
@@ -255,56 +255,6 @@ File Operations
 .. kernel-doc:: drivers/gpu/drm/drm_file.c
    :export:
 
-IOCTLs
-------
-
-struct drm_ioctl_desc \*ioctls; int num_ioctls;
-    Driver-specific ioctls descriptors table.
-
-Driver-specific ioctls numbers start at DRM_COMMAND_BASE. The ioctls
-descriptors table is indexed by the ioctl number offset from the base
-value. Drivers can use the DRM_IOCTL_DEF_DRV() macro to initialize
-the table entries.
-
-::
-
-    DRM_IOCTL_DEF_DRV(ioctl, func, flags)
-
-``ioctl`` is the ioctl name. Drivers must define the DRM_##ioctl and
-DRM_IOCTL_##ioctl macros to the ioctl number offset from
-DRM_COMMAND_BASE and the ioctl number respectively. The first macro is
-private to the device while the second must be exposed to userspace in a
-public header.
-
-``func`` is a pointer to the ioctl handler function compatible with the
-``drm_ioctl_t`` type.
-
-::
-
-    typedef int drm_ioctl_t(struct drm_device *dev, void *data,
-            struct drm_file *file_priv);
-
-``flags`` is a bitmask combination of the following values. It restricts
-how the ioctl is allowed to be called.
-
--  DRM_AUTH - Only authenticated callers allowed
-
--  DRM_MASTER - The ioctl can only be called on the master file handle
-
--  DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed
-
--  DRM_CONTROL_ALLOW - The ioctl can only be called on a control
-   device
-
--  DRM_UNLOCKED - The ioctl handler will be called without locking the
-   DRM global mutex. This is the enforced default for kms drivers (i.e.
-   using the DRIVER_MODESET flag) and hence shouldn't be used any more
-   for new drivers.
-
-.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
-   :export:
-
-
 Misc Utilities
 ==============
 
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index 8b0f0e403f0c..858457567d3d 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -160,6 +160,20 @@ other hand, a driver requires shared state between clients which is
 visible to user-space and accessible beyond open-file boundaries, they
 cannot support render nodes.
 
+IOCTL Support on Device Nodes
+=============================
+
+.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
+   :doc: driver specific ioctls
+
+.. kernel-doc:: include/drm/drm_ioctl.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
+   :export:
+
+.. kernel-doc:: drivers/gpu/drm/drm_ioc32.c
+   :export:
 
 Testing and validation
 ======================
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index b134482f4022..0fa7827cb0fd 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -1,4 +1,4 @@
-/**
+/*
  * \file drm_ioc32.c
  *
  * 32-bit ioctl compatibility routines for the DRM.
@@ -72,15 +72,15 @@
 #define DRM_IOCTL_MODE_ADDFB232		DRM_IOWR(0xb8, drm_mode_fb_cmd232_t)
 
 typedef struct drm_version_32 {
-	int version_major;	  /**< Major version */
-	int version_minor;	  /**< Minor version */
-	int version_patchlevel;	   /**< Patch level */
-	u32 name_len;		  /**< Length of name buffer */
-	u32 name;		  /**< Name of driver */
-	u32 date_len;		  /**< Length of date buffer */
-	u32 date;		  /**< User-space buffer to hold date */
-	u32 desc_len;		  /**< Length of desc buffer */
-	u32 desc;		  /**< User-space buffer to hold desc */
+	int version_major;	  /* Major version */
+	int version_minor;	  /* Minor version */
+	int version_patchlevel;	   /* Patch level */
+	u32 name_len;		  /* Length of name buffer */
+	u32 name;		  /* Name of driver */
+	u32 date_len;		  /* Length of date buffer */
+	u32 date;		  /* User-space buffer to hold date */
+	u32 desc_len;		  /* Length of desc buffer */
+	u32 desc;		  /* User-space buffer to hold desc */
 } drm_version32_t;
 
 static int compat_drm_version(struct file *file, unsigned int cmd,
@@ -126,8 +126,8 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
 }
 
 typedef struct drm_unique32 {
-	u32 unique_len;	/**< Length of unique */
-	u32 unique;	/**< Unique name for driver instantiation */
+	u32 unique_len;	/* Length of unique */
+	u32 unique;	/* Unique name for driver instantiation */
 } drm_unique32_t;
 
 static int compat_drm_getunique(struct file *file, unsigned int cmd,
@@ -180,12 +180,12 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
 }
 
 typedef struct drm_map32 {
-	u32 offset;		/**< Requested physical address (0 for SAREA)*/
-	u32 size;		/**< Requested physical size (bytes) */
-	enum drm_map_type type;	/**< Type of memory to map */
-	enum drm_map_flags flags;	/**< Flags */
-	u32 handle;		/**< User-space: "Handle" to pass to mmap() */
-	int mtrr;		/**< MTRR slot used */
+	u32 offset;		/* Requested physical address (0 for SAREA)*/
+	u32 size;		/* Requested physical size (bytes) */
+	enum drm_map_type type;	/* Type of memory to map */
+	enum drm_map_flags flags;	/* Flags */
+	u32 handle;		/* User-space: "Handle" to pass to mmap() */
+	int mtrr;		/* MTRR slot used */
 } drm_map32_t;
 
 static int compat_drm_getmap(struct file *file, unsigned int cmd,
@@ -286,12 +286,12 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
 }
 
 typedef struct drm_client32 {
-	int idx;	/**< Which client desired? */
-	int auth;	/**< Is client authenticated? */
-	u32 pid;	/**< Process ID */
-	u32 uid;	/**< User ID */
-	u32 magic;	/**< Magic */
-	u32 iocs;	/**< Ioctl count */
+	int idx;	/* Which client desired? */
+	int auth;	/* Is client authenticated? */
+	u32 pid;	/* Process ID */
+	u32 uid;	/* User ID */
+	u32 magic;	/* Magic */
+	u32 iocs;	/* Ioctl count */
 } drm_client32_t;
 
 static int compat_drm_getclient(struct file *file, unsigned int cmd,
@@ -366,12 +366,12 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
 }
 
 typedef struct drm_buf_desc32 {
-	int count;		 /**< Number of buffers of this size */
-	int size;		 /**< Size in bytes */
-	int low_mark;		 /**< Low water mark */
-	int high_mark;		 /**< High water mark */
+	int count;		 /* Number of buffers of this size */
+	int size;		 /* Size in bytes */
+	int low_mark;		 /* Low water mark */
+	int high_mark;		 /* High water mark */
 	int flags;
-	u32 agp_start;		 /**< Start address in the AGP aperture */
+	u32 agp_start;		 /* Start address in the AGP aperture */
 } drm_buf_desc32_t;
 
 static int compat_drm_addbufs(struct file *file, unsigned int cmd,
@@ -1111,13 +1111,18 @@ static drm_ioctl_compat_t *drm_compat_ioctls[] = {
 };
 
 /**
- * Called whenever a 32-bit process running under a 64-bit kernel
- * performs an ioctl on /dev/drm.
+ * drm_compat_ioctl - 32bit IOCTL compatibility handler for DRM drivers
+ * @filp: file this ioctl is called on
+ * @cmd: ioctl cmd number
+ * @arg: user argument
+ *
+ * Compatibility handler for 32 bit userspace running on 64 kernels. All actual
+ * IOCTL handling is forwarded to drm_ioctl(), while marshalling structures as
+ * appropriate. Note that this only handles DRM core IOCTLs, if the driver has
+ * botched IOCTL itself, it must handle those by wrapping this function.
  *
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
+ * Returns:
+ * Zero on success, negative error code on failure.
  */
 long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
@@ -1141,5 +1146,4 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
 	return ret;
 }
-
 EXPORT_SYMBOL(drm_compat_ioctl);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 7f4f4f48e390..f908ea94b784 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -647,13 +647,59 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
 
 /**
+ * DOC: driver specific ioctls
+ *
+ * First things first, driver private IOCTLs should only be needed for drivers
+ * supporting rendering. Kernel modesetting is all standardized, and extended
+ * through properties. There are a few exceptions in some existing drivers,
+ * which define IOCTL for use by the display DRM master, but they all predate
+ * properties.
+ *
+ * Now if you do have a render driver you always have to support it through
+ * driver private properties. There's a few steps needed to wire all the things
+ * up.
+ *
+ * First you need to define the structure for your IOCTL in your driver private
+ * UAPI header in ``include/uapi/drm/my_driver_drm.h``::
+ *
+ *     struct my_driver_operation {
+ *             u32 some_thing;
+ *             u32 another_thing;
+ *     };
+ *
+ * Please make sure that you follow all the best practices from
+ * ``Documentation/ioctl/botching-up-ioctls.txt``. Note that drm_ioctl()
+ * automatically zero-extends structures, hence make sure you can add more stuff
+ * at the end, i.e. don't put a variable sized array there.
+ *
+ * Then you need to define your IOCTL number, using one of DRM_IO(), DRM_IOR(),
+ * DRM_IOW() or DRM_IOWR(). It must start with the DRM_IOCTL\_ prefix::
+ *
+ *     ##define DRM_IOCTL_MY_DRIVER_OPERATION \
+ *         DRM_IOW(DRM_COMMAND_BASE, struct my_driver_operation)
+ * 
+ * DRM driver private IOCTL must be in the range from DRM_COMMAND_BASE to
+ * DRM_COMMAND_END. Finally you need an array of &struct drm_ioctl_desc to wire
+ * up the handlers and set the access rights:
+ *
+ *     static const struct drm_ioctl_desc my_driver_ioctls[] = {
+ *         DRM_IOCTL_DEF_DRV(MY_DRIVER_OPERATION, my_driver_operation,
+ *                 DRM_AUTH|DRM_RENDER_ALLOW),
+ *     };
+ *
+ * And then assign this to the &drm_driver.ioctls field in your driver
+ * structure.
+ */
+
+/**
  * drm_ioctl - ioctl callback implementation for DRM drivers
  * @filp: file this ioctl is called on
  * @cmd: ioctl cmd number
  * @arg: user argument
  *
- * Looks up the ioctl function in the ::ioctls table, checking for root
- * previleges if so required, and dispatches to the respective function.
+ * Looks up the ioctl function in the DRM core and the driver dispatch table,
+ * stored in &drm_driver.ioctls. It checks for necessary permission by calling
+ * drm_ioctl_permit(), and dispatches to the respective function.
  *
  * Returns:
  * Zero on success, negative error code on failure.
diff --git a/include/drm/drm_ioctl.h b/include/drm/drm_ioctl.h
index f17ee077f649..ee03b3c44b3b 100644
--- a/include/drm/drm_ioctl.h
+++ b/include/drm/drm_ioctl.h
@@ -33,6 +33,7 @@
 #define _DRM_IOCTL_H_
 
 #include <linux/types.h>
+#include <linux/bitops.h>
 
 #include <asm/ioctl.h>
 
@@ -41,41 +42,126 @@ struct drm_file;
 struct file;
 
 /**
- * Ioctl function type.
+ * drm_ioctl_t - DRM ioctl function type.
+ * @dev: DRM device inode
+ * @data: private pointer of the ioctl call
+ * @file_priv: DRM file this ioctl was made on
  *
- * \param inode device inode.
- * \param file_priv DRM file private pointer.
- * \param cmd command.
- * \param arg argument.
+ * This is the DRM ioctl typedef. Note that drm_ioctl() has alrady copied @data
+ * into kernel-space, and will also copy it back, depending upon the read/write
+ * settings in the ioctl command code.
  */
 typedef int drm_ioctl_t(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 
+/**
+ * drm_ioctl_compat_t - compatibility DRM ioctl function type.
+ * @filp: file pointer
+ * @cmd: ioctl command code
+ * @arg: DRM file this ioctl was made on
+ *
+ * Just a typedef to make declaring an array of compatibility handlers easier.
+ * New drivers shouldn't screw up the structure layout for their ioctl
+ * structures and hence never need this.
+ */
 typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
 			       unsigned long arg);
 
 #define DRM_IOCTL_NR(n)                _IOC_NR(n)
 #define DRM_MAJOR       226
 
-#define DRM_AUTH	0x1
-#define	DRM_MASTER	0x2
-#define DRM_ROOT_ONLY	0x4
-#define DRM_CONTROL_ALLOW 0x8
-#define DRM_UNLOCKED	0x10
-#define DRM_RENDER_ALLOW 0x20
+/**
+ * enum drm_ioctl_flags - DRM ioctl flags
+ *
+ * Various flags that can be set in &drm_ioctl_desc.flags to control how
+ * userspace can use a given ioctl.
+ */
+enum drm_ioctl_flags {
+	/**
+	 * @DRM_AUTH:
+	 *
+	 * This is for ioctl which are used for rendering, and require that the
+	 * file descriptor is either for a render node, or if it's a
+	 * legacy/primary node, then it must be authenticated.
+	 */
+	DRM_AUTH		= BIT(0),
+	/**
+	 * @DRM_MASTER:
+	 *
+	 * This must be set for any ioctl which can change the modeset or
+	 * display state. Userspace must call the ioctl through a primary node,
+	 * while it is the active master.
+	 *
+	 * Note that read-only modeset ioctl can also be called by
+	 * unauthenticated clients, or when a master is not the currently active
+	 * one.
+	 */
+	DRM_MASTER		= BIT(1),
+	/**
+	 * @DRM_ROOT_ONLY:
+	 *
+	 * Anything that could potentially wreak a master file descriptor needs
+	 * to have this flag set. Current that's only for the SETMASTER and
+	 * DROPMASTER ioctl, which e.g. logind can call to force a non-behaving
+	 * master (display compositor) into compliance.
+	 *
+	 * This is equivalent to callers with the SYSADMIN capability.
+	 */
+	DRM_ROOT_ONLY		= BIT(2),
+	/**
+	 * @DRM_CONTROL_ALLOW:
+	 *
+	 * Deprecated, do not use. Control nodes are in the process of getting
+	 * removed.
+	 */
+	DRM_CONTROL_ALLOW	= BIT(3),
+	/**
+	 * @DRM_UNLOCKED:
+	 *
+	 * Whether &drm_ioctl_desc.func should be called with the DRM BKL held
+	 * or not. Enforced as the default for all modern drivers, hence there
+	 * should never be a need to set this flag.
+	 */
+	DRM_UNLOCKED		= BIT(4),
+	/**
+	 * @DRM_RENDER_ALLOW:
+	 *
+	 * This is used for all ioctl needed for rendering only, for drivers
+	 * which support render nodes. This should be all new render drivers,
+	 * and hence it should be always set for any ioctl with DRM_AUTH set.
+	 * Note though that read-only query ioctl might have this set, but have
+	 * not set DRM_AUTH because they do not require authentication.
+	 */
+	DRM_RENDER_ALLOW	= BIT(5),
+};
 
+/**
+ * struct drm_ioctl_desc - DRM driver ioctl entry
+ * @cmd: ioctl command number, without flags
+ * @flags: a bitmask of &enum drm_ioctl_flags
+ * @func: handler for this ioctl
+ * @name: user-readable name for debug output
+ *
+ * For convenience it's easier to create these using the DRM_IOCTL_DEF_DRV()
+ * macro.
+ */
 struct drm_ioctl_desc {
 	unsigned int cmd;
-	int flags;
+	enum drm_ioctl_flags flags;
 	drm_ioctl_t *func;
 	const char *name;
 };
 
 /**
- * Creates a driver or general drm_ioctl_desc array entry for the given
- * ioctl, for use by drm_ioctl().
+ * DRM_IOCTL_DEF_DRV() - helper macro to fill out a &struct drm_ioctl_desc
+ * @ioctl: ioctl command suffix
+ * @_func: handler for the ioctl
+ * @_flags: a bitmask of &enum drm_ioctl_flags
+ *
+ * Small helper macro to create a &struct drm_ioctl_desc entry. The ioctl
+ * command number is constructed by prepending ``DRM_IOCTL\_`` and passing that
+ * to DRM_IOCTL_NR().
  */
-
 #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)				\
 	[DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {	\
 		.cmd = DRM_IOCTL_##ioctl,				\
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2017-04-04  9:52 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-04  9:52 [PATCH 01/11] drm: update todo.rst Daniel Vetter
2017-04-04  9:52 ` [PATCH 02/11] drm: Consolidate and document sysfs support Daniel Vetter
2017-04-04 14:46   ` Neil Armstrong
2017-04-04  9:52 ` [PATCH 03/11] drm: Extract drm_ioctl.h Daniel Vetter
2017-04-04 14:46   ` Neil Armstrong
2017-04-04 18:41     ` Daniel Vetter
2017-04-04  9:52 ` Daniel Vetter [this message]
2017-04-04 14:56   ` [PATCH 04/11] drm: document drm_ioctl.[hc] Neil Armstrong
2017-04-04  9:52 ` [PATCH 05/11] drm/vblank: Switch drm_driver->get_vblank_timestamp to return a bool Daniel Vetter
2017-04-04 15:00   ` Neil Armstrong
2017-04-04  9:53 ` [PATCH 07/11] drm/vblank: Add FIXME comments about moving the vblank ts hooks Daniel Vetter
2017-04-04 15:02   ` Neil Armstrong
     [not found] ` <20170404095304.17599-1-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
2017-04-04  9:52   ` [PATCH 06/11] drm/vblank: Switch to bool in_vblank_irq in get_vblank_timestamp Daniel Vetter
2017-04-04 15:02     ` Neil Armstrong
2017-04-04  9:53   ` [PATCH 08/11] drm/vblank: drop the mode argument from drm_calc_vbltimestamp_from_scanoutpos Daniel Vetter
2017-04-04 15:06     ` Neil Armstrong
2017-04-04  9:53   ` [PATCH 09/11] drm/vblank: Simplify the get_scanout_position helper hook Daniel Vetter
2017-04-04 15:11     ` Neil Armstrong
2017-04-04  9:53 ` [PATCH 10/11] drm/vblank: Lock down vblank->hwmode more Daniel Vetter
2017-04-04 15:12   ` Neil Armstrong
2017-04-04  9:53 ` [PATCH 11/11] drm/doc: Small markup fixup Daniel Vetter
2017-04-04 15:12   ` Neil Armstrong
2017-04-04 18:49     ` Daniel Vetter
2017-04-04 10:17 ` ✓ Fi.CI.BAT: success for series starting with [01/11] drm: update todo.rst Patchwork
2017-04-04 15:13 ` [PATCH 01/11] " Neil Armstrong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170404095304.17599-4-daniel.vetter@ffwll.ch \
    --to=daniel.vetter@ffwll.ch \
    --cc=daniel.vetter@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=xerpi.g.12@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.