Skip to content

Commit

Permalink
drm: document drm_ioctl.[hc]
Browse files Browse the repository at this point in the history
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).

v4: Add missing space in comment (Neil).

Cc: Sergi Granell <xerpi.g.12@gmail.com>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170404095304.17599-4-daniel.vetter@ffwll.ch
  • Loading branch information
Daniel Vetter committed Apr 4, 2017
1 parent e227170 commit 2640981
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 103 deletions.
50 changes: 0 additions & 50 deletions Documentation/gpu/drm-internals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
==============

Expand Down
14 changes: 14 additions & 0 deletions Documentation/gpu/drm-uapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
======================
Expand Down
76 changes: 40 additions & 36 deletions drivers/gpu/drm/drm_ioc32.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* \file drm_ioc32.c
*
* 32-bit ioctl compatibility routines for the DRM.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
{
Expand All @@ -1141,5 +1146,4 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

return ret;
}

EXPORT_SYMBOL(drm_compat_ioctl);
50 changes: 48 additions & 2 deletions drivers/gpu/drm/drm_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,14 +646,60 @@ 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.
Expand Down
Loading

0 comments on commit 2640981

Please sign in to comment.