mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
Merge branch 'drm-next' of git://people.freedesktop.org/~dvdhrm/linux into drm-next
bunch of cleanups * 'drm-next' of git://people.freedesktop.org/~dvdhrm/linux: drm: mark drm_context support as legacy drm: make sysfs device always available for minors drm: make minor->index available early drm: merge drm_drv.c into drm_ioctl.c drm: move module initialization to drm_stub.c drm: don't de-authenticate clients on master-close drm: drop redundant drm_file->is_master drm: extract legacy ctxbitmap flushing
This commit is contained in:
commit
acf8294fec
@ -6,7 +6,7 @@ ccflags-y := -Iinclude/drm
|
|||||||
|
|
||||||
drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
|
drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
|
||||||
drm_context.o drm_dma.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_lock.o drm_memory.o drm_stub.o drm_vm.o \
|
||||||
drm_agpsupport.o drm_scatter.o drm_pci.o \
|
drm_agpsupport.o drm_scatter.o drm_pci.o \
|
||||||
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
|
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
|
||||||
|
@ -1,18 +1,13 @@
|
|||||||
/**
|
|
||||||
* \file drm_context.c
|
|
||||||
* IOCTLs for generic contexts
|
|
||||||
*
|
|
||||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
|
||||||
* \author Gareth Hughes <gareth@valinux.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
|
* Legacy: Generic DRM Contexts
|
||||||
*
|
*
|
||||||
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||||
* All Rights Reserved.
|
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
* to deal in the Software without restriction, including without limitation
|
* to deal in the Software without restriction, including without limitation
|
||||||
@ -33,14 +28,14 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* ChangeLog:
|
|
||||||
* 2001-11-16 Torsten Duwe <duwe@caldera.de>
|
|
||||||
* added context constructor/destructor hooks,
|
|
||||||
* needed by SiS driver's memory management.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
|
#include "drm_legacy.h"
|
||||||
|
|
||||||
|
struct drm_ctx_list {
|
||||||
|
struct list_head head;
|
||||||
|
drm_context_t handle;
|
||||||
|
struct drm_file *tag;
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
/** \name Context bitmap support */
|
/** \name Context bitmap support */
|
||||||
@ -56,7 +51,7 @@
|
|||||||
* in drm_device::ctx_idr, while holding the drm_device::struct_mutex
|
* in drm_device::ctx_idr, while holding the drm_device::struct_mutex
|
||||||
* lock.
|
* lock.
|
||||||
*/
|
*/
|
||||||
void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
|
void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
|
||||||
{
|
{
|
||||||
mutex_lock(&dev->struct_mutex);
|
mutex_lock(&dev->struct_mutex);
|
||||||
idr_remove(&dev->ctx_idr, ctx_handle);
|
idr_remove(&dev->ctx_idr, ctx_handle);
|
||||||
@ -72,7 +67,7 @@ void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
|
|||||||
* Allocate a new idr from drm_device::ctx_idr while holding the
|
* Allocate a new idr from drm_device::ctx_idr while holding the
|
||||||
* drm_device::struct_mutex lock.
|
* drm_device::struct_mutex lock.
|
||||||
*/
|
*/
|
||||||
static int drm_ctxbitmap_next(struct drm_device * dev)
|
static int drm_legacy_ctxbitmap_next(struct drm_device * dev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -90,7 +85,7 @@ static int drm_ctxbitmap_next(struct drm_device * dev)
|
|||||||
*
|
*
|
||||||
* Initialise the drm_device::ctx_idr
|
* Initialise the drm_device::ctx_idr
|
||||||
*/
|
*/
|
||||||
int drm_ctxbitmap_init(struct drm_device * dev)
|
int drm_legacy_ctxbitmap_init(struct drm_device * dev)
|
||||||
{
|
{
|
||||||
idr_init(&dev->ctx_idr);
|
idr_init(&dev->ctx_idr);
|
||||||
return 0;
|
return 0;
|
||||||
@ -104,13 +99,43 @@ int drm_ctxbitmap_init(struct drm_device * dev)
|
|||||||
* Free all idr members using drm_ctx_sarea_free helper function
|
* Free all idr members using drm_ctx_sarea_free helper function
|
||||||
* while holding the drm_device::struct_mutex lock.
|
* while holding the drm_device::struct_mutex lock.
|
||||||
*/
|
*/
|
||||||
void drm_ctxbitmap_cleanup(struct drm_device * dev)
|
void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev)
|
||||||
{
|
{
|
||||||
mutex_lock(&dev->struct_mutex);
|
mutex_lock(&dev->struct_mutex);
|
||||||
idr_destroy(&dev->ctx_idr);
|
idr_destroy(&dev->ctx_idr);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
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_legacy_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_legacy_ctxbitmap_free(dev, pos->handle);
|
||||||
|
list_del(&pos->head);
|
||||||
|
kfree(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&dev->ctxlist_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
@ -129,8 +154,8 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev)
|
|||||||
* Gets the map from drm_device::ctx_idr with the handle specified and
|
* Gets the map from drm_device::ctx_idr with the handle specified and
|
||||||
* returns its handle.
|
* returns its handle.
|
||||||
*/
|
*/
|
||||||
int drm_getsareactx(struct drm_device *dev, void *data,
|
int drm_legacy_getsareactx(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv)
|
struct drm_file *file_priv)
|
||||||
{
|
{
|
||||||
struct drm_ctx_priv_map *request = data;
|
struct drm_ctx_priv_map *request = data;
|
||||||
struct drm_local_map *map;
|
struct drm_local_map *map;
|
||||||
@ -173,8 +198,8 @@ int drm_getsareactx(struct drm_device *dev, void *data,
|
|||||||
* Searches the mapping specified in \p arg and update the entry in
|
* Searches the mapping specified in \p arg and update the entry in
|
||||||
* drm_device::ctx_idr with it.
|
* drm_device::ctx_idr with it.
|
||||||
*/
|
*/
|
||||||
int drm_setsareactx(struct drm_device *dev, void *data,
|
int drm_legacy_setsareactx(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv)
|
struct drm_file *file_priv)
|
||||||
{
|
{
|
||||||
struct drm_ctx_priv_map *request = data;
|
struct drm_ctx_priv_map *request = data;
|
||||||
struct drm_local_map *map = NULL;
|
struct drm_local_map *map = NULL;
|
||||||
@ -273,8 +298,8 @@ static int drm_context_switch_complete(struct drm_device *dev,
|
|||||||
* \param arg user argument pointing to a drm_ctx_res structure.
|
* \param arg user argument pointing to a drm_ctx_res structure.
|
||||||
* \return zero on success or a negative number on failure.
|
* \return zero on success or a negative number on failure.
|
||||||
*/
|
*/
|
||||||
int drm_resctx(struct drm_device *dev, void *data,
|
int drm_legacy_resctx(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv)
|
struct drm_file *file_priv)
|
||||||
{
|
{
|
||||||
struct drm_ctx_res *res = data;
|
struct drm_ctx_res *res = data;
|
||||||
struct drm_ctx ctx;
|
struct drm_ctx ctx;
|
||||||
@ -304,16 +329,16 @@ int drm_resctx(struct drm_device *dev, void *data,
|
|||||||
*
|
*
|
||||||
* Get a new handle for the context and copy to userspace.
|
* Get a new handle for the context and copy to userspace.
|
||||||
*/
|
*/
|
||||||
int drm_addctx(struct drm_device *dev, void *data,
|
int drm_legacy_addctx(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv)
|
struct drm_file *file_priv)
|
||||||
{
|
{
|
||||||
struct drm_ctx_list *ctx_entry;
|
struct drm_ctx_list *ctx_entry;
|
||||||
struct drm_ctx *ctx = data;
|
struct drm_ctx *ctx = data;
|
||||||
|
|
||||||
ctx->handle = drm_ctxbitmap_next(dev);
|
ctx->handle = drm_legacy_ctxbitmap_next(dev);
|
||||||
if (ctx->handle == DRM_KERNEL_CONTEXT) {
|
if (ctx->handle == DRM_KERNEL_CONTEXT) {
|
||||||
/* Skip kernel's context and get a new one. */
|
/* Skip kernel's context and get a new one. */
|
||||||
ctx->handle = drm_ctxbitmap_next(dev);
|
ctx->handle = drm_legacy_ctxbitmap_next(dev);
|
||||||
}
|
}
|
||||||
DRM_DEBUG("%d\n", ctx->handle);
|
DRM_DEBUG("%d\n", ctx->handle);
|
||||||
if (ctx->handle == -1) {
|
if (ctx->handle == -1) {
|
||||||
@ -348,7 +373,8 @@ int drm_addctx(struct drm_device *dev, void *data,
|
|||||||
* \param arg user argument pointing to a drm_ctx structure.
|
* \param arg user argument pointing to a drm_ctx structure.
|
||||||
* \return zero on success or a negative number on failure.
|
* \return zero on success or a negative number on failure.
|
||||||
*/
|
*/
|
||||||
int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
int drm_legacy_getctx(struct drm_device *dev, void *data,
|
||||||
|
struct drm_file *file_priv)
|
||||||
{
|
{
|
||||||
struct drm_ctx *ctx = data;
|
struct drm_ctx *ctx = data;
|
||||||
|
|
||||||
@ -369,8 +395,8 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||||||
*
|
*
|
||||||
* Calls context_switch().
|
* Calls context_switch().
|
||||||
*/
|
*/
|
||||||
int drm_switchctx(struct drm_device *dev, void *data,
|
int drm_legacy_switchctx(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv)
|
struct drm_file *file_priv)
|
||||||
{
|
{
|
||||||
struct drm_ctx *ctx = data;
|
struct drm_ctx *ctx = data;
|
||||||
|
|
||||||
@ -389,8 +415,8 @@ int drm_switchctx(struct drm_device *dev, void *data,
|
|||||||
*
|
*
|
||||||
* Calls context_switch_complete().
|
* Calls context_switch_complete().
|
||||||
*/
|
*/
|
||||||
int drm_newctx(struct drm_device *dev, void *data,
|
int drm_legacy_newctx(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv)
|
struct drm_file *file_priv)
|
||||||
{
|
{
|
||||||
struct drm_ctx *ctx = data;
|
struct drm_ctx *ctx = data;
|
||||||
|
|
||||||
@ -411,8 +437,8 @@ int drm_newctx(struct drm_device *dev, void *data,
|
|||||||
*
|
*
|
||||||
* If not the special kernel context, calls ctxbitmap_free() to free the specified context.
|
* If not the special kernel context, calls ctxbitmap_free() to free the specified context.
|
||||||
*/
|
*/
|
||||||
int drm_rmctx(struct drm_device *dev, void *data,
|
int drm_legacy_rmctx(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv)
|
struct drm_file *file_priv)
|
||||||
{
|
{
|
||||||
struct drm_ctx *ctx = data;
|
struct drm_ctx *ctx = data;
|
||||||
|
|
||||||
@ -420,7 +446,7 @@ int drm_rmctx(struct drm_device *dev, void *data,
|
|||||||
if (ctx->handle != DRM_KERNEL_CONTEXT) {
|
if (ctx->handle != DRM_KERNEL_CONTEXT) {
|
||||||
if (dev->driver->context_dtor)
|
if (dev->driver->context_dtor)
|
||||||
dev->driver->context_dtor(dev, ctx->handle);
|
dev->driver->context_dtor(dev, ctx->handle);
|
||||||
drm_ctxbitmap_free(dev, ctx->handle);
|
drm_legacy_ctxbitmap_free(dev, ctx->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&dev->ctxlist_mutex);
|
mutex_lock(&dev->ctxlist_mutex);
|
||||||
|
@ -3244,7 +3244,7 @@ int drm_mode_getfb(struct drm_device *dev,
|
|||||||
r->bpp = fb->bits_per_pixel;
|
r->bpp = fb->bits_per_pixel;
|
||||||
r->pitch = fb->pitches[0];
|
r->pitch = fb->pitches[0];
|
||||||
if (fb->funcs->create_handle) {
|
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)) {
|
drm_is_control_client(file_priv)) {
|
||||||
ret = fb->funcs->create_handle(fb, file_priv,
|
ret = fb->funcs->create_handle(fb, file_priv,
|
||||||
&r->handle);
|
&r->handle);
|
||||||
|
@ -1,471 +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 )
|
|
||||||
|
|
||||||
/** 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
|
|
||||||
*/
|
|
||||||
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) && !file_priv->is_master &&
|
|
||||||
!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);
|
|
@ -38,6 +38,7 @@
|
|||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include "drm_legacy.h"
|
||||||
|
|
||||||
/* from BKL pushdown */
|
/* from BKL pushdown */
|
||||||
DEFINE_MUTEX(drm_global_mutex);
|
DEFINE_MUTEX(drm_global_mutex);
|
||||||
@ -111,45 +112,6 @@ err_undo:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_open);
|
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.
|
* Check whether DRI will run on this CPU.
|
||||||
*
|
*
|
||||||
@ -199,8 +161,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
|||||||
priv->minor = minor;
|
priv->minor = minor;
|
||||||
|
|
||||||
/* for compatibility root is always authenticated */
|
/* for compatibility root is always authenticated */
|
||||||
priv->always_authenticated = capable(CAP_SYS_ADMIN);
|
priv->authenticated = capable(CAP_SYS_ADMIN);
|
||||||
priv->authenticated = priv->always_authenticated;
|
|
||||||
priv->lock_count = 0;
|
priv->lock_count = 0;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&priv->lhead);
|
INIT_LIST_HEAD(&priv->lhead);
|
||||||
@ -233,7 +194,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
|||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->is_master = 1;
|
|
||||||
/* take another reference for the copy in the local file priv */
|
/* take another reference for the copy in the local file priv */
|
||||||
priv->master = drm_master_get(priv->minor->master);
|
priv->master = drm_master_get(priv->minor->master);
|
||||||
priv->authenticated = 1;
|
priv->authenticated = 1;
|
||||||
@ -461,44 +421,18 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||||||
if (dev->driver->driver_features & DRIVER_GEM)
|
if (dev->driver->driver_features & DRIVER_GEM)
|
||||||
drm_gem_release(dev, file_priv);
|
drm_gem_release(dev, file_priv);
|
||||||
|
|
||||||
mutex_lock(&dev->ctxlist_mutex);
|
drm_legacy_ctxbitmap_flush(dev, file_priv);
|
||||||
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);
|
|
||||||
|
|
||||||
mutex_lock(&dev->master_mutex);
|
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_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
|
* Since the master is disappearing, so is the
|
||||||
* possibility to lock.
|
* possibility to lock.
|
||||||
*/
|
*/
|
||||||
|
mutex_lock(&dev->struct_mutex);
|
||||||
if (master->lock.hw_lock) {
|
if (master->lock.hw_lock) {
|
||||||
if (dev->sigdata.lock == master->lock.hw_lock)
|
if (dev->sigdata.lock == master->lock.hw_lock)
|
||||||
dev->sigdata.lock = NULL;
|
dev->sigdata.lock = NULL;
|
||||||
@ -519,7 +453,6 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||||||
/* drop the master reference held by the file priv */
|
/* drop the master reference held by the file priv */
|
||||||
if (file_priv->master)
|
if (file_priv->master)
|
||||||
drm_master_put(&file_priv->master);
|
drm_master_put(&file_priv->master);
|
||||||
file_priv->is_master = 0;
|
|
||||||
mutex_unlock(&dev->master_mutex);
|
mutex_unlock(&dev->master_mutex);
|
||||||
|
|
||||||
if (dev->driver->postclose)
|
if (dev->driver->postclose)
|
||||||
|
@ -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
|
* Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
|
||||||
*
|
*
|
||||||
@ -13,6 +5,9 @@
|
|||||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||||
* All Rights Reserved.
|
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
* to deal in the Software without restriction, including without limitation
|
* to deal in the Software without restriction, including without limitation
|
||||||
@ -35,6 +30,7 @@
|
|||||||
|
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
#include <drm/drm_core.h>
|
#include <drm/drm_core.h>
|
||||||
|
#include "drm_legacy.h"
|
||||||
|
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
@ -42,6 +38,124 @@
|
|||||||
#include <asm/mtrr.h>
|
#include <asm/mtrr.h>
|
||||||
#endif
|
#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_legacy_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||||
|
DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_legacy_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_legacy_addctx, DRM_AUTH|DRM_ROOT_ONLY),
|
||||||
|
DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_legacy_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_legacy_getctx, DRM_AUTH),
|
||||||
|
DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_legacy_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||||
|
DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_legacy_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||||
|
DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_legacy_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.
|
* Get the bus id.
|
||||||
*
|
*
|
||||||
@ -415,3 +529,243 @@ int drm_noop(struct drm_device *dev, void *data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_noop);
|
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);
|
||||||
|
51
drivers/gpu/drm/drm_legacy.h
Normal file
51
drivers/gpu/drm/drm_legacy.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#ifndef __DRM_LEGACY_H__
|
||||||
|
#define __DRM_LEGACY_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014 David Herrmann <dh.herrmann@gmail.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
|
||||||
|
* 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 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
|
||||||
|
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct drm_device;
|
||||||
|
struct drm_file;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic DRM Contexts
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DRM_KERNEL_CONTEXT 0
|
||||||
|
#define DRM_RESERVED_CONTEXTS 1
|
||||||
|
|
||||||
|
int drm_legacy_ctxbitmap_init(struct drm_device *dev);
|
||||||
|
void drm_legacy_ctxbitmap_cleanup(struct drm_device *dev);
|
||||||
|
void drm_legacy_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
|
||||||
|
void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file);
|
||||||
|
|
||||||
|
int drm_legacy_resctx(struct drm_device *d, void *v, struct drm_file *f);
|
||||||
|
int drm_legacy_addctx(struct drm_device *d, void *v, struct drm_file *f);
|
||||||
|
int drm_legacy_getctx(struct drm_device *d, void *v, struct drm_file *f);
|
||||||
|
int drm_legacy_switchctx(struct drm_device *d, void *v, struct drm_file *f);
|
||||||
|
int drm_legacy_newctx(struct drm_device *d, void *v, struct drm_file *f);
|
||||||
|
int drm_legacy_rmctx(struct drm_device *d, void *v, struct drm_file *f);
|
||||||
|
|
||||||
|
int drm_legacy_setsareactx(struct drm_device *d, void *v, struct drm_file *f);
|
||||||
|
int drm_legacy_getsareactx(struct drm_device *d, void *v, struct drm_file *f);
|
||||||
|
|
||||||
|
#endif /* __DRM_LEGACY_H__ */
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
|
#include "drm_legacy.h"
|
||||||
|
|
||||||
static int drm_notifier(void *priv);
|
static int drm_notifier(void *priv);
|
||||||
|
|
||||||
@ -111,7 +112,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
|
/* don't set the block all signals on the master process for now
|
||||||
* really probably not the correct answer but lets us debug xkb
|
* really probably not the correct answer but lets us debug xkb
|
||||||
* xserver for now */
|
* xserver for now */
|
||||||
if (!file_priv->is_master) {
|
if (!drm_is_master(file_priv)) {
|
||||||
sigemptyset(&dev->sigmask);
|
sigemptyset(&dev->sigmask);
|
||||||
sigaddset(&dev->sigmask, SIGSTOP);
|
sigaddset(&dev->sigmask, SIGSTOP);
|
||||||
sigaddset(&dev->sigmask, SIGTSTP);
|
sigaddset(&dev->sigmask, SIGTSTP);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/debugfs.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
@ -33,6 +34,7 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
#include <drm/drm_core.h>
|
#include <drm/drm_core.h>
|
||||||
|
#include "drm_legacy.h"
|
||||||
|
|
||||||
unsigned int drm_debug = 0; /* 1 to enable debug output */
|
unsigned int drm_debug = 0; /* 1 to enable debug output */
|
||||||
EXPORT_SYMBOL(drm_debug);
|
EXPORT_SYMBOL(drm_debug);
|
||||||
@ -61,10 +63,10 @@ module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600)
|
|||||||
module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
|
module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(drm_minor_lock);
|
static DEFINE_SPINLOCK(drm_minor_lock);
|
||||||
struct idr drm_minors_idr;
|
static struct idr drm_minors_idr;
|
||||||
|
|
||||||
struct class *drm_class;
|
struct class *drm_class;
|
||||||
struct dentry *drm_debugfs_root;
|
static struct dentry *drm_debugfs_root;
|
||||||
|
|
||||||
int drm_err(const char *func, const char *format, ...)
|
int drm_err(const char *func, const char *format, ...)
|
||||||
{
|
{
|
||||||
@ -177,7 +179,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
mutex_lock(&dev->master_mutex);
|
mutex_lock(&dev->master_mutex);
|
||||||
if (file_priv->is_master)
|
if (drm_is_master(file_priv))
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
if (file_priv->minor->master) {
|
if (file_priv->minor->master) {
|
||||||
@ -191,13 +193,10 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
file_priv->minor->master = drm_master_get(file_priv->master);
|
file_priv->minor->master = drm_master_get(file_priv->master);
|
||||||
file_priv->is_master = 1;
|
|
||||||
if (dev->driver->master_set) {
|
if (dev->driver->master_set) {
|
||||||
ret = dev->driver->master_set(dev, file_priv, false);
|
ret = dev->driver->master_set(dev, file_priv, false);
|
||||||
if (unlikely(ret != 0)) {
|
if (unlikely(ret != 0))
|
||||||
file_priv->is_master = 0;
|
|
||||||
drm_master_put(&file_priv->minor->master);
|
drm_master_put(&file_priv->minor->master);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
@ -211,7 +210,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
|||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&dev->master_mutex);
|
mutex_lock(&dev->master_mutex);
|
||||||
if (!file_priv->is_master)
|
if (!drm_is_master(file_priv))
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
if (!file_priv->minor->master)
|
if (!file_priv->minor->master)
|
||||||
@ -221,7 +220,6 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
|||||||
if (dev->driver->master_drop)
|
if (dev->driver->master_drop)
|
||||||
dev->driver->master_drop(dev, file_priv, false);
|
dev->driver->master_drop(dev, file_priv, false);
|
||||||
drm_master_put(&file_priv->minor->master);
|
drm_master_put(&file_priv->minor->master);
|
||||||
file_priv->is_master = 0;
|
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&dev->master_mutex);
|
mutex_unlock(&dev->master_mutex);
|
||||||
@ -259,6 +257,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)
|
static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
|
||||||
{
|
{
|
||||||
struct drm_minor *minor;
|
struct drm_minor *minor;
|
||||||
|
unsigned long flags;
|
||||||
|
int r;
|
||||||
|
|
||||||
minor = kzalloc(sizeof(*minor), GFP_KERNEL);
|
minor = kzalloc(sizeof(*minor), GFP_KERNEL);
|
||||||
if (!minor)
|
if (!minor)
|
||||||
@ -267,77 +267,92 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
|
|||||||
minor->type = type;
|
minor->type = type;
|
||||||
minor->dev = dev;
|
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;
|
||||||
|
|
||||||
|
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;
|
*drm_minor_get_slot(dev, type) = minor;
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drm_minor_free(struct drm_device *dev, unsigned int type)
|
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);
|
slot = drm_minor_get_slot(dev, type);
|
||||||
if (*slot) {
|
minor = *slot;
|
||||||
drm_mode_group_destroy(&(*slot)->mode_group);
|
if (!minor)
|
||||||
kfree(*slot);
|
return;
|
||||||
*slot = NULL;
|
|
||||||
}
|
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);
|
||||||
|
spin_unlock_irqrestore(&drm_minor_lock, flags);
|
||||||
|
|
||||||
|
kfree(minor);
|
||||||
|
*slot = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drm_minor_register(struct drm_device *dev, unsigned int type)
|
static int drm_minor_register(struct drm_device *dev, unsigned int type)
|
||||||
{
|
{
|
||||||
struct drm_minor *new_minor;
|
struct drm_minor *minor;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
int minor_id;
|
|
||||||
|
|
||||||
DRM_DEBUG("\n");
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
new_minor = *drm_minor_get_slot(dev, type);
|
minor = *drm_minor_get_slot(dev, type);
|
||||||
if (!new_minor)
|
if (!minor)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
idr_preload(GFP_KERNEL);
|
ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
|
||||||
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);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
|
DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
|
||||||
goto err_id;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = drm_sysfs_device_add(new_minor);
|
ret = device_add(minor->kdev);
|
||||||
if (ret) {
|
if (ret)
|
||||||
DRM_ERROR("DRM: Error sysfs_device_add.\n");
|
|
||||||
goto err_debugfs;
|
goto err_debugfs;
|
||||||
}
|
|
||||||
|
|
||||||
/* replace NULL with @minor so lookups will succeed from now on */
|
/* replace NULL with @minor so lookups will succeed from now on */
|
||||||
spin_lock_irqsave(&drm_minor_lock, flags);
|
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);
|
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;
|
return 0;
|
||||||
|
|
||||||
err_debugfs:
|
err_debugfs:
|
||||||
drm_debugfs_cleanup(new_minor);
|
drm_debugfs_cleanup(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;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,16 +362,17 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
minor = *drm_minor_get_slot(dev, type);
|
minor = *drm_minor_get_slot(dev, type);
|
||||||
if (!minor || !minor->kdev)
|
if (!minor || !device_is_registered(minor->kdev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* replace @minor with NULL so lookups will fail from now on */
|
||||||
spin_lock_irqsave(&drm_minor_lock, flags);
|
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);
|
spin_unlock_irqrestore(&drm_minor_lock, flags);
|
||||||
minor->index = 0;
|
|
||||||
|
|
||||||
|
device_del(minor->kdev);
|
||||||
|
dev_set_drvdata(minor->kdev, NULL); /* safety belt */
|
||||||
drm_debugfs_cleanup(minor);
|
drm_debugfs_cleanup(minor);
|
||||||
drm_sysfs_device_remove(minor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -589,7 +605,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
|
|||||||
if (drm_ht_create(&dev->map_hash, 12))
|
if (drm_ht_create(&dev->map_hash, 12))
|
||||||
goto err_minors;
|
goto err_minors;
|
||||||
|
|
||||||
ret = drm_ctxbitmap_init(dev);
|
ret = drm_legacy_ctxbitmap_init(dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
|
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
|
||||||
goto err_ht;
|
goto err_ht;
|
||||||
@ -606,7 +622,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
|
|||||||
return dev;
|
return dev;
|
||||||
|
|
||||||
err_ctxbitmap:
|
err_ctxbitmap:
|
||||||
drm_ctxbitmap_cleanup(dev);
|
drm_legacy_ctxbitmap_cleanup(dev);
|
||||||
err_ht:
|
err_ht:
|
||||||
drm_ht_remove(&dev->map_hash);
|
drm_ht_remove(&dev->map_hash);
|
||||||
err_minors:
|
err_minors:
|
||||||
@ -628,7 +644,7 @@ static void drm_dev_release(struct kref *ref)
|
|||||||
if (dev->driver->driver_features & DRIVER_GEM)
|
if (dev->driver->driver_features & DRIVER_GEM)
|
||||||
drm_gem_destroy(dev);
|
drm_gem_destroy(dev);
|
||||||
|
|
||||||
drm_ctxbitmap_cleanup(dev);
|
drm_legacy_ctxbitmap_cleanup(dev);
|
||||||
drm_ht_remove(&dev->map_hash);
|
drm_ht_remove(&dev->map_hash);
|
||||||
drm_fs_inode_free(dev->anon_inode);
|
drm_fs_inode_free(dev->anon_inode);
|
||||||
|
|
||||||
@ -791,3 +807,115 @@ int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...)
|
|||||||
return dev->unique ? 0 : -ENOMEM;
|
return dev->unique ? 0 : -ENOMEM;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_dev_set_unique);
|
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);
|
||||||
|
@ -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
|
* drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
|
||||||
* @dev: DRM device to be added
|
* @minor: minor to allocate sysfs device for
|
||||||
* @head: DRM head in question
|
|
||||||
*
|
*
|
||||||
* Add a DRM device to the DRM's device model class. We use @dev's PCI device
|
* This allocates a new sysfs device for @minor and returns it. The device is
|
||||||
* as the parent for the Linux device, and make sure it has a file containing
|
* not registered nor linked. The caller has to use device_add() and
|
||||||
* the driver we're using (for userspace compatibility).
|
* 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;
|
int r;
|
||||||
|
|
||||||
if (minor->type == DRM_MINOR_CONTROL)
|
if (minor->type == DRM_MINOR_CONTROL)
|
||||||
minor_str = "controlD%d";
|
minor_str = "controlD%d";
|
||||||
else if (minor->type == DRM_MINOR_RENDER)
|
else if (minor->type == DRM_MINOR_RENDER)
|
||||||
minor_str = "renderD%d";
|
minor_str = "renderD%d";
|
||||||
else
|
else
|
||||||
minor_str = "card%d";
|
minor_str = "card%d";
|
||||||
|
|
||||||
minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
|
kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
|
||||||
if (!minor->kdev) {
|
if (!kdev)
|
||||||
r = -ENOMEM;
|
return ERR_PTR(-ENOMEM);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
device_initialize(minor->kdev);
|
device_initialize(kdev);
|
||||||
minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index);
|
kdev->devt = MKDEV(DRM_MAJOR, minor->index);
|
||||||
minor->kdev->class = drm_class;
|
kdev->class = drm_class;
|
||||||
minor->kdev->type = &drm_sysfs_device_minor;
|
kdev->type = &drm_sysfs_device_minor;
|
||||||
minor->kdev->parent = minor->dev->dev;
|
kdev->parent = minor->dev->dev;
|
||||||
minor->kdev->release = drm_sysfs_release;
|
kdev->release = drm_sysfs_release;
|
||||||
dev_set_drvdata(minor->kdev, minor);
|
dev_set_drvdata(kdev, minor);
|
||||||
|
|
||||||
r = dev_set_name(minor->kdev, minor_str, minor->index);
|
r = dev_set_name(kdev, minor_str, minor->index);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto error;
|
goto err_free;
|
||||||
|
|
||||||
r = device_add(minor->kdev);
|
return kdev;
|
||||||
if (r < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
return 0;
|
err_free:
|
||||||
|
put_device(kdev);
|
||||||
error:
|
return ERR_PTR(r);
|
||||||
DRM_ERROR("device create failed %d\n", r);
|
|
||||||
put_device(minor->kdev);
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_class_device_register - Register a struct device in the drm class.
|
* drm_class_device_register - Register a struct device in the drm class.
|
||||||
*
|
*
|
||||||
|
@ -1260,7 +1260,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (args->flags & I915_EXEC_SECURE) {
|
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;
|
return -EPERM;
|
||||||
|
|
||||||
flags |= I915_DISPATCH_SECURE;
|
flags |= I915_DISPATCH_SECURE;
|
||||||
@ -1369,7 +1369,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
ret = i915_parse_cmds(ring,
|
ret = i915_parse_cmds(ring,
|
||||||
batch_obj,
|
batch_obj,
|
||||||
args->batch_start_offset,
|
args->batch_start_offset,
|
||||||
file->is_master);
|
drm_is_master(file));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -990,7 +990,7 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev,
|
|||||||
if (unlikely(ret != 0))
|
if (unlikely(ret != 0))
|
||||||
return ERR_PTR(-ERESTARTSYS);
|
return ERR_PTR(-ERESTARTSYS);
|
||||||
|
|
||||||
if (file_priv->is_master) {
|
if (drm_is_master(file_priv)) {
|
||||||
mutex_unlock(&dev->master_mutex);
|
mutex_unlock(&dev->master_mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ static void imx_drm_driver_preclose(struct drm_device *drm,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!file->is_master)
|
if (!drm_is_master(file))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < MAX_CRTC; i++)
|
for (i = 0; i < MAX_CRTC; i++)
|
||||||
|
@ -151,8 +151,6 @@ int drm_err(const char *func, const char *format, ...);
|
|||||||
also include looping detection. */
|
also include looping detection. */
|
||||||
|
|
||||||
#define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */
|
#define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */
|
||||||
#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
|
|
||||||
#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
|
|
||||||
|
|
||||||
#define DRM_MAP_HASH_OFFSET 0x10000000
|
#define DRM_MAP_HASH_OFFSET 0x10000000
|
||||||
|
|
||||||
@ -385,10 +383,7 @@ struct drm_prime_file_private {
|
|||||||
|
|
||||||
/** File private data */
|
/** File private data */
|
||||||
struct drm_file {
|
struct drm_file {
|
||||||
unsigned always_authenticated :1;
|
|
||||||
unsigned 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 */
|
/* true when the client has asked us to expose stereo 3D mode flags */
|
||||||
unsigned stereo_allowed :1;
|
unsigned stereo_allowed :1;
|
||||||
/*
|
/*
|
||||||
@ -538,15 +533,6 @@ struct drm_map_list {
|
|||||||
struct drm_master *master;
|
struct drm_master *master;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Context handle list
|
|
||||||
*/
|
|
||||||
struct drm_ctx_list {
|
|
||||||
struct list_head head; /**< list head */
|
|
||||||
drm_context_t handle; /**< context handle */
|
|
||||||
struct drm_file *tag; /**< associated fd private data */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* location of GART table */
|
/* location of GART table */
|
||||||
#define DRM_ATI_GART_MAIN 1
|
#define DRM_ATI_GART_MAIN 1
|
||||||
#define DRM_ATI_GART_FB 2
|
#define DRM_ATI_GART_FB 2
|
||||||
@ -1034,7 +1020,7 @@ struct drm_device {
|
|||||||
/** \name Locks */
|
/** \name Locks */
|
||||||
/*@{ */
|
/*@{ */
|
||||||
struct mutex struct_mutex; /**< For others */
|
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 */
|
/** \name Usage Counters */
|
||||||
@ -1172,6 +1158,21 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv)
|
|||||||
return file_priv->minor->type == DRM_MINOR_LEGACY;
|
return file_priv->minor->type == DRM_MINOR_LEGACY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_is_master() - Check whether a DRM open-file is DRM-Master
|
||||||
|
* @file: DRM open-file context
|
||||||
|
*
|
||||||
|
* This checks whether a DRM open-file context is owner of the master context
|
||||||
|
* attached to it. If a file owns a master context, it's called DRM-Master.
|
||||||
|
* Per DRM device, only one such file can be DRM-Master at a time.
|
||||||
|
*
|
||||||
|
* Returns: True if the file is DRM-Master, otherwise false.
|
||||||
|
*/
|
||||||
|
static inline bool drm_is_master(const struct drm_file *file)
|
||||||
|
{
|
||||||
|
return file->master && file->master == file->minor->master;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
/** \name Internal function definitions */
|
/** \name Internal function definitions */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
@ -1187,7 +1188,6 @@ extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
|
|||||||
/* Device support (drm_fops.h) */
|
/* Device support (drm_fops.h) */
|
||||||
extern struct mutex drm_global_mutex;
|
extern struct mutex drm_global_mutex;
|
||||||
extern int drm_open(struct inode *inode, struct file *filp);
|
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,
|
extern ssize_t drm_read(struct file *filp, char __user *buffer,
|
||||||
size_t count, loff_t *offset);
|
size_t count, loff_t *offset);
|
||||||
extern int drm_release(struct inode *inode, struct file *filp);
|
extern int drm_release(struct inode *inode, struct file *filp);
|
||||||
@ -1225,29 +1225,6 @@ extern int drm_setversion(struct drm_device *dev, void *data,
|
|||||||
extern int drm_noop(struct drm_device *dev, void *data,
|
extern int drm_noop(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
|
|
||||||
/* Context IOCTL support (drm_context.h) */
|
|
||||||
extern int drm_resctx(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
extern int drm_addctx(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
extern int drm_getctx(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
extern int drm_switchctx(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
extern int drm_newctx(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
extern int drm_rmctx(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
|
|
||||||
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 int drm_setsareactx(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
extern int drm_getsareactx(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
|
|
||||||
/* Authentication IOCTL support (drm_auth.h) */
|
/* Authentication IOCTL support (drm_auth.h) */
|
||||||
extern int drm_getmagic(struct drm_device *dev, void *data,
|
extern int drm_getmagic(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
@ -1373,9 +1350,6 @@ extern unsigned int drm_timestamp_precision;
|
|||||||
extern unsigned int drm_timestamp_monotonic;
|
extern unsigned int drm_timestamp_monotonic;
|
||||||
|
|
||||||
extern struct class *drm_class;
|
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);
|
extern struct drm_local_map *drm_getsarea(struct drm_device *dev);
|
||||||
|
|
||||||
@ -1493,9 +1467,8 @@ extern int drm_pci_set_unique(struct drm_device *dev,
|
|||||||
struct drm_sysfs_class;
|
struct drm_sysfs_class;
|
||||||
extern struct class *drm_sysfs_create(struct module *owner, char *name);
|
extern struct class *drm_sysfs_create(struct module *owner, char *name);
|
||||||
extern void drm_sysfs_destroy(void);
|
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_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 int drm_sysfs_connector_add(struct drm_connector *connector);
|
||||||
extern void drm_sysfs_connector_remove(struct drm_connector *connector);
|
extern void drm_sysfs_connector_remove(struct drm_connector *connector);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user