mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-30 07:36:44 +07: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_context.o drm_dma.o \
|
||||
drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
|
||||
drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
|
||||
drm_lock.o drm_memory.o drm_stub.o drm_vm.o \
|
||||
drm_agpsupport.o drm_scatter.o drm_pci.o \
|
||||
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
|
||||
|
@ -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 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Author: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Author: Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
@ -33,14 +28,14 @@
|
||||
* 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_legacy.h"
|
||||
|
||||
struct drm_ctx_list {
|
||||
struct list_head head;
|
||||
drm_context_t handle;
|
||||
struct drm_file *tag;
|
||||
};
|
||||
|
||||
/******************************************************************/
|
||||
/** \name Context bitmap support */
|
||||
@ -56,7 +51,7 @@
|
||||
* in drm_device::ctx_idr, while holding the drm_device::struct_mutex
|
||||
* 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);
|
||||
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
|
||||
* 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;
|
||||
|
||||
@ -90,7 +85,7 @@ static int drm_ctxbitmap_next(struct drm_device * dev)
|
||||
*
|
||||
* 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);
|
||||
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
|
||||
* 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);
|
||||
idr_destroy(&dev->ctx_idr);
|
||||
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
|
||||
* returns its handle.
|
||||
*/
|
||||
int drm_getsareactx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
int drm_legacy_getsareactx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx_priv_map *request = data;
|
||||
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
|
||||
* drm_device::ctx_idr with it.
|
||||
*/
|
||||
int drm_setsareactx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
int drm_legacy_setsareactx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx_priv_map *request = data;
|
||||
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.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*/
|
||||
int drm_resctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
int drm_legacy_resctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx_res *res = data;
|
||||
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.
|
||||
*/
|
||||
int drm_addctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
int drm_legacy_addctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx_list *ctx_entry;
|
||||
struct drm_ctx *ctx = data;
|
||||
|
||||
ctx->handle = drm_ctxbitmap_next(dev);
|
||||
ctx->handle = drm_legacy_ctxbitmap_next(dev);
|
||||
if (ctx->handle == DRM_KERNEL_CONTEXT) {
|
||||
/* 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);
|
||||
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.
|
||||
* \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;
|
||||
|
||||
@ -369,8 +395,8 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
*
|
||||
* Calls context_switch().
|
||||
*/
|
||||
int drm_switchctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
int drm_legacy_switchctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx *ctx = data;
|
||||
|
||||
@ -389,8 +415,8 @@ int drm_switchctx(struct drm_device *dev, void *data,
|
||||
*
|
||||
* Calls context_switch_complete().
|
||||
*/
|
||||
int drm_newctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
int drm_legacy_newctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
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.
|
||||
*/
|
||||
int drm_rmctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
int drm_legacy_rmctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
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 (dev->driver->context_dtor)
|
||||
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);
|
||||
|
@ -3244,7 +3244,7 @@ int drm_mode_getfb(struct drm_device *dev,
|
||||
r->bpp = fb->bits_per_pixel;
|
||||
r->pitch = fb->pitches[0];
|
||||
if (fb->funcs->create_handle) {
|
||||
if (file_priv->is_master || capable(CAP_SYS_ADMIN) ||
|
||||
if (drm_is_master(file_priv) || capable(CAP_SYS_ADMIN) ||
|
||||
drm_is_control_client(file_priv)) {
|
||||
ret = fb->funcs->create_handle(fb, file_priv,
|
||||
&r->handle);
|
||||
|
@ -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/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include "drm_legacy.h"
|
||||
|
||||
/* from BKL pushdown */
|
||||
DEFINE_MUTEX(drm_global_mutex);
|
||||
@ -111,45 +112,6 @@ int drm_open(struct inode *inode, struct file *filp)
|
||||
}
|
||||
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.
|
||||
*
|
||||
@ -199,8 +161,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
||||
priv->minor = minor;
|
||||
|
||||
/* for compatibility root is always authenticated */
|
||||
priv->always_authenticated = capable(CAP_SYS_ADMIN);
|
||||
priv->authenticated = priv->always_authenticated;
|
||||
priv->authenticated = capable(CAP_SYS_ADMIN);
|
||||
priv->lock_count = 0;
|
||||
|
||||
INIT_LIST_HEAD(&priv->lhead);
|
||||
@ -233,7 +194,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
priv->is_master = 1;
|
||||
/* take another reference for the copy in the local file priv */
|
||||
priv->master = drm_master_get(priv->minor->master);
|
||||
priv->authenticated = 1;
|
||||
@ -461,44 +421,18 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
if (dev->driver->driver_features & DRIVER_GEM)
|
||||
drm_gem_release(dev, file_priv);
|
||||
|
||||
mutex_lock(&dev->ctxlist_mutex);
|
||||
if (!list_empty(&dev->ctxlist)) {
|
||||
struct drm_ctx_list *pos, *n;
|
||||
|
||||
list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
|
||||
if (pos->tag == file_priv &&
|
||||
pos->handle != DRM_KERNEL_CONTEXT) {
|
||||
if (dev->driver->context_dtor)
|
||||
dev->driver->context_dtor(dev,
|
||||
pos->handle);
|
||||
|
||||
drm_ctxbitmap_free(dev, pos->handle);
|
||||
|
||||
list_del(&pos->head);
|
||||
kfree(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex_unlock(&dev->ctxlist_mutex);
|
||||
drm_legacy_ctxbitmap_flush(dev, file_priv);
|
||||
|
||||
mutex_lock(&dev->master_mutex);
|
||||
|
||||
if (file_priv->is_master) {
|
||||
if (drm_is_master(file_priv)) {
|
||||
struct drm_master *master = file_priv->master;
|
||||
struct drm_file *temp;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
list_for_each_entry(temp, &dev->filelist, lhead) {
|
||||
if ((temp->master == file_priv->master) &&
|
||||
(temp != file_priv))
|
||||
temp->authenticated = temp->always_authenticated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since the master is disappearing, so is the
|
||||
* possibility to lock.
|
||||
*/
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (master->lock.hw_lock) {
|
||||
if (dev->sigdata.lock == master->lock.hw_lock)
|
||||
dev->sigdata.lock = NULL;
|
||||
@ -519,7 +453,6 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
/* drop the master reference held by the file priv */
|
||||
if (file_priv->master)
|
||||
drm_master_put(&file_priv->master);
|
||||
file_priv->is_master = 0;
|
||||
mutex_unlock(&dev->master_mutex);
|
||||
|
||||
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
|
||||
*
|
||||
@ -13,6 +5,9 @@
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Author Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
@ -35,6 +30,7 @@
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_core.h>
|
||||
#include "drm_legacy.h"
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/export.h>
|
||||
@ -42,6 +38,124 @@
|
||||
#include <asm/mtrr.h>
|
||||
#endif
|
||||
|
||||
static int drm_version(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
|
||||
[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
|
||||
|
||||
/** Ioctl table */
|
||||
static const struct drm_ioctl_desc drm_ioctls[] = {
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_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.
|
||||
*
|
||||
@ -415,3 +529,243 @@ int drm_noop(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_noop);
|
||||
|
||||
/**
|
||||
* Copy and IOCTL return string to user space
|
||||
*/
|
||||
static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
|
||||
{
|
||||
int len;
|
||||
|
||||
/* don't overflow userbuf */
|
||||
len = strlen(value);
|
||||
if (len > *buf_len)
|
||||
len = *buf_len;
|
||||
|
||||
/* let userspace know exact length of driver value (which could be
|
||||
* larger than the userspace-supplied buffer) */
|
||||
*buf_len = strlen(value);
|
||||
|
||||
/* finally, try filling in the userbuf */
|
||||
if (len && buf)
|
||||
if (copy_to_user(buf, value, len))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get version information
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
* \param arg user argument, pointing to a drm_version structure.
|
||||
* \return zero on success or negative number on failure.
|
||||
*
|
||||
* Fills in the version information in \p arg.
|
||||
*/
|
||||
static int drm_version(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_version *version = data;
|
||||
int err;
|
||||
|
||||
version->version_major = dev->driver->major;
|
||||
version->version_minor = dev->driver->minor;
|
||||
version->version_patchlevel = dev->driver->patchlevel;
|
||||
err = drm_copy_field(version->name, &version->name_len,
|
||||
dev->driver->name);
|
||||
if (!err)
|
||||
err = drm_copy_field(version->date, &version->date_len,
|
||||
dev->driver->date);
|
||||
if (!err)
|
||||
err = drm_copy_field(version->desc, &version->desc_len,
|
||||
dev->driver->desc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_ioctl_permit - Check ioctl permissions against caller
|
||||
*
|
||||
* @flags: ioctl permission flags.
|
||||
* @file_priv: Pointer to struct drm_file identifying the caller.
|
||||
*
|
||||
* Checks whether the caller is allowed to run an ioctl with the
|
||||
* indicated permissions. If so, returns zero. Otherwise returns an
|
||||
* error code suitable for ioctl return.
|
||||
*/
|
||||
static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
|
||||
{
|
||||
/* ROOT_ONLY is only for CAP_SYS_ADMIN */
|
||||
if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
|
||||
return -EACCES;
|
||||
|
||||
/* AUTH is only for authenticated or render client */
|
||||
if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
|
||||
!file_priv->authenticated))
|
||||
return -EACCES;
|
||||
|
||||
/* MASTER is only for master or control clients */
|
||||
if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) &&
|
||||
!drm_is_control_client(file_priv)))
|
||||
return -EACCES;
|
||||
|
||||
/* Control clients must be explicitly allowed */
|
||||
if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
|
||||
drm_is_control_client(file_priv)))
|
||||
return -EACCES;
|
||||
|
||||
/* Render clients must be explicitly allowed */
|
||||
if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
|
||||
drm_is_render_client(file_priv)))
|
||||
return -EACCES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever a process performs an ioctl on /dev/drm.
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param file_priv DRM file private.
|
||||
* \param cmd command.
|
||||
* \param arg user argument.
|
||||
* \return zero on success or negative number on failure.
|
||||
*
|
||||
* Looks up the ioctl function in the ::ioctls table, checking for root
|
||||
* previleges if so required, and dispatches to the respective function.
|
||||
*/
|
||||
long drm_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct drm_file *file_priv = filp->private_data;
|
||||
struct drm_device *dev;
|
||||
const struct drm_ioctl_desc *ioctl = NULL;
|
||||
drm_ioctl_t *func;
|
||||
unsigned int nr = DRM_IOCTL_NR(cmd);
|
||||
int retcode = -EINVAL;
|
||||
char stack_kdata[128];
|
||||
char *kdata = NULL;
|
||||
unsigned int usize, asize;
|
||||
|
||||
dev = file_priv->minor->dev;
|
||||
|
||||
if (drm_device_is_unplugged(dev))
|
||||
return -ENODEV;
|
||||
|
||||
if ((nr >= DRM_CORE_IOCTL_COUNT) &&
|
||||
((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
|
||||
goto err_i1;
|
||||
if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
|
||||
(nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
|
||||
u32 drv_size;
|
||||
ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
|
||||
drv_size = _IOC_SIZE(ioctl->cmd_drv);
|
||||
usize = asize = _IOC_SIZE(cmd);
|
||||
if (drv_size > asize)
|
||||
asize = drv_size;
|
||||
cmd = ioctl->cmd_drv;
|
||||
}
|
||||
else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
|
||||
u32 drv_size;
|
||||
|
||||
ioctl = &drm_ioctls[nr];
|
||||
|
||||
drv_size = _IOC_SIZE(ioctl->cmd);
|
||||
usize = asize = _IOC_SIZE(cmd);
|
||||
if (drv_size > asize)
|
||||
asize = drv_size;
|
||||
|
||||
cmd = ioctl->cmd;
|
||||
} else
|
||||
goto err_i1;
|
||||
|
||||
DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
|
||||
task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated, ioctl->name);
|
||||
|
||||
/* Do not trust userspace, use our own definition */
|
||||
func = ioctl->func;
|
||||
|
||||
if (unlikely(!func)) {
|
||||
DRM_DEBUG("no function\n");
|
||||
retcode = -EINVAL;
|
||||
goto err_i1;
|
||||
}
|
||||
|
||||
retcode = drm_ioctl_permit(ioctl->flags, file_priv);
|
||||
if (unlikely(retcode))
|
||||
goto err_i1;
|
||||
|
||||
if (cmd & (IOC_IN | IOC_OUT)) {
|
||||
if (asize <= sizeof(stack_kdata)) {
|
||||
kdata = stack_kdata;
|
||||
} else {
|
||||
kdata = kmalloc(asize, GFP_KERNEL);
|
||||
if (!kdata) {
|
||||
retcode = -ENOMEM;
|
||||
goto err_i1;
|
||||
}
|
||||
}
|
||||
if (asize > usize)
|
||||
memset(kdata + usize, 0, asize - usize);
|
||||
}
|
||||
|
||||
if (cmd & IOC_IN) {
|
||||
if (copy_from_user(kdata, (void __user *)arg,
|
||||
usize) != 0) {
|
||||
retcode = -EFAULT;
|
||||
goto err_i1;
|
||||
}
|
||||
} else if (cmd & IOC_OUT) {
|
||||
memset(kdata, 0, usize);
|
||||
}
|
||||
|
||||
if (ioctl->flags & DRM_UNLOCKED)
|
||||
retcode = func(dev, kdata, file_priv);
|
||||
else {
|
||||
mutex_lock(&drm_global_mutex);
|
||||
retcode = func(dev, kdata, file_priv);
|
||||
mutex_unlock(&drm_global_mutex);
|
||||
}
|
||||
|
||||
if (cmd & IOC_OUT) {
|
||||
if (copy_to_user((void __user *)arg, kdata,
|
||||
usize) != 0)
|
||||
retcode = -EFAULT;
|
||||
}
|
||||
|
||||
err_i1:
|
||||
if (!ioctl)
|
||||
DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
|
||||
task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated, cmd, nr);
|
||||
|
||||
if (kdata != stack_kdata)
|
||||
kfree(kdata);
|
||||
if (retcode)
|
||||
DRM_DEBUG("ret = %d\n", retcode);
|
||||
return retcode;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ioctl);
|
||||
|
||||
/**
|
||||
* drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
|
||||
*
|
||||
* @nr: Ioctl number.
|
||||
* @flags: Where to return the ioctl permission flags
|
||||
*/
|
||||
bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
|
||||
{
|
||||
if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
|
||||
(nr < DRM_COMMAND_BASE)) {
|
||||
*flags = drm_ioctls[nr].flags;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ioctl_flags);
|
||||
|
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 <drm/drmP.h>
|
||||
#include "drm_legacy.h"
|
||||
|
||||
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
|
||||
* really probably not the correct answer but lets us debug xkb
|
||||
* xserver for now */
|
||||
if (!file_priv->is_master) {
|
||||
if (!drm_is_master(file_priv)) {
|
||||
sigemptyset(&dev->sigmask);
|
||||
sigaddset(&dev->sigmask, SIGSTOP);
|
||||
sigaddset(&dev->sigmask, SIGTSTP);
|
||||
|
@ -26,6 +26,7 @@
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
@ -33,6 +34,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_core.h>
|
||||
#include "drm_legacy.h"
|
||||
|
||||
unsigned int drm_debug = 0; /* 1 to enable debug output */
|
||||
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);
|
||||
|
||||
static DEFINE_SPINLOCK(drm_minor_lock);
|
||||
struct idr drm_minors_idr;
|
||||
static struct idr drm_minors_idr;
|
||||
|
||||
struct class *drm_class;
|
||||
struct dentry *drm_debugfs_root;
|
||||
static struct dentry *drm_debugfs_root;
|
||||
|
||||
int drm_err(const char *func, const char *format, ...)
|
||||
{
|
||||
@ -177,7 +179,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dev->master_mutex);
|
||||
if (file_priv->is_master)
|
||||
if (drm_is_master(file_priv))
|
||||
goto out_unlock;
|
||||
|
||||
if (file_priv->minor->master) {
|
||||
@ -191,13 +193,10 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
file_priv->minor->master = drm_master_get(file_priv->master);
|
||||
file_priv->is_master = 1;
|
||||
if (dev->driver->master_set) {
|
||||
ret = dev->driver->master_set(dev, file_priv, false);
|
||||
if (unlikely(ret != 0)) {
|
||||
file_priv->is_master = 0;
|
||||
if (unlikely(ret != 0))
|
||||
drm_master_put(&file_priv->minor->master);
|
||||
}
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
@ -211,7 +210,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
int ret = -EINVAL;
|
||||
|
||||
mutex_lock(&dev->master_mutex);
|
||||
if (!file_priv->is_master)
|
||||
if (!drm_is_master(file_priv))
|
||||
goto out_unlock;
|
||||
|
||||
if (!file_priv->minor->master)
|
||||
@ -221,7 +220,6 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
if (dev->driver->master_drop)
|
||||
dev->driver->master_drop(dev, file_priv, false);
|
||||
drm_master_put(&file_priv->minor->master);
|
||||
file_priv->is_master = 0;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->master_mutex);
|
||||
@ -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)
|
||||
{
|
||||
struct drm_minor *minor;
|
||||
unsigned long flags;
|
||||
int r;
|
||||
|
||||
minor = kzalloc(sizeof(*minor), GFP_KERNEL);
|
||||
if (!minor)
|
||||
@ -267,77 +267,92 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
|
||||
minor->type = type;
|
||||
minor->dev = dev;
|
||||
|
||||
idr_preload(GFP_KERNEL);
|
||||
spin_lock_irqsave(&drm_minor_lock, flags);
|
||||
r = idr_alloc(&drm_minors_idr,
|
||||
NULL,
|
||||
64 * type,
|
||||
64 * (type + 1),
|
||||
GFP_NOWAIT);
|
||||
spin_unlock_irqrestore(&drm_minor_lock, flags);
|
||||
idr_preload_end();
|
||||
|
||||
if (r < 0)
|
||||
goto err_free;
|
||||
|
||||
minor->index = r;
|
||||
|
||||
minor->kdev = drm_sysfs_minor_alloc(minor);
|
||||
if (IS_ERR(minor->kdev)) {
|
||||
r = PTR_ERR(minor->kdev);
|
||||
goto err_index;
|
||||
}
|
||||
|
||||
*drm_minor_get_slot(dev, type) = minor;
|
||||
return 0;
|
||||
|
||||
err_index:
|
||||
spin_lock_irqsave(&drm_minor_lock, flags);
|
||||
idr_remove(&drm_minors_idr, minor->index);
|
||||
spin_unlock_irqrestore(&drm_minor_lock, flags);
|
||||
err_free:
|
||||
kfree(minor);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void drm_minor_free(struct drm_device *dev, unsigned int type)
|
||||
{
|
||||
struct drm_minor **slot;
|
||||
struct drm_minor **slot, *minor;
|
||||
unsigned long flags;
|
||||
|
||||
slot = drm_minor_get_slot(dev, type);
|
||||
if (*slot) {
|
||||
drm_mode_group_destroy(&(*slot)->mode_group);
|
||||
kfree(*slot);
|
||||
*slot = NULL;
|
||||
}
|
||||
minor = *slot;
|
||||
if (!minor)
|
||||
return;
|
||||
|
||||
drm_mode_group_destroy(&minor->mode_group);
|
||||
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)
|
||||
{
|
||||
struct drm_minor *new_minor;
|
||||
struct drm_minor *minor;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
int minor_id;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
new_minor = *drm_minor_get_slot(dev, type);
|
||||
if (!new_minor)
|
||||
minor = *drm_minor_get_slot(dev, type);
|
||||
if (!minor)
|
||||
return 0;
|
||||
|
||||
idr_preload(GFP_KERNEL);
|
||||
spin_lock_irqsave(&drm_minor_lock, flags);
|
||||
minor_id = idr_alloc(&drm_minors_idr,
|
||||
NULL,
|
||||
64 * type,
|
||||
64 * (type + 1),
|
||||
GFP_NOWAIT);
|
||||
spin_unlock_irqrestore(&drm_minor_lock, flags);
|
||||
idr_preload_end();
|
||||
|
||||
if (minor_id < 0)
|
||||
return minor_id;
|
||||
|
||||
new_minor->index = minor_id;
|
||||
|
||||
ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
|
||||
ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
|
||||
if (ret) {
|
||||
DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
|
||||
goto err_id;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_sysfs_device_add(new_minor);
|
||||
if (ret) {
|
||||
DRM_ERROR("DRM: Error sysfs_device_add.\n");
|
||||
ret = device_add(minor->kdev);
|
||||
if (ret)
|
||||
goto err_debugfs;
|
||||
}
|
||||
|
||||
/* replace NULL with @minor so lookups will succeed from now on */
|
||||
spin_lock_irqsave(&drm_minor_lock, flags);
|
||||
idr_replace(&drm_minors_idr, new_minor, new_minor->index);
|
||||
idr_replace(&drm_minors_idr, minor, minor->index);
|
||||
spin_unlock_irqrestore(&drm_minor_lock, flags);
|
||||
|
||||
DRM_DEBUG("new minor assigned %d\n", minor_id);
|
||||
DRM_DEBUG("new minor registered %d\n", minor->index);
|
||||
return 0;
|
||||
|
||||
err_debugfs:
|
||||
drm_debugfs_cleanup(new_minor);
|
||||
err_id:
|
||||
spin_lock_irqsave(&drm_minor_lock, flags);
|
||||
idr_remove(&drm_minors_idr, minor_id);
|
||||
spin_unlock_irqrestore(&drm_minor_lock, flags);
|
||||
new_minor->index = 0;
|
||||
drm_debugfs_cleanup(minor);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -347,16 +362,17 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
|
||||
unsigned long flags;
|
||||
|
||||
minor = *drm_minor_get_slot(dev, type);
|
||||
if (!minor || !minor->kdev)
|
||||
if (!minor || !device_is_registered(minor->kdev))
|
||||
return;
|
||||
|
||||
/* replace @minor with NULL so lookups will fail from now on */
|
||||
spin_lock_irqsave(&drm_minor_lock, flags);
|
||||
idr_remove(&drm_minors_idr, minor->index);
|
||||
idr_replace(&drm_minors_idr, NULL, minor->index);
|
||||
spin_unlock_irqrestore(&drm_minor_lock, flags);
|
||||
minor->index = 0;
|
||||
|
||||
device_del(minor->kdev);
|
||||
dev_set_drvdata(minor->kdev, NULL); /* safety belt */
|
||||
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))
|
||||
goto err_minors;
|
||||
|
||||
ret = drm_ctxbitmap_init(dev);
|
||||
ret = drm_legacy_ctxbitmap_init(dev);
|
||||
if (ret) {
|
||||
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
|
||||
goto err_ht;
|
||||
@ -606,7 +622,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
|
||||
return dev;
|
||||
|
||||
err_ctxbitmap:
|
||||
drm_ctxbitmap_cleanup(dev);
|
||||
drm_legacy_ctxbitmap_cleanup(dev);
|
||||
err_ht:
|
||||
drm_ht_remove(&dev->map_hash);
|
||||
err_minors:
|
||||
@ -628,7 +644,7 @@ static void drm_dev_release(struct kref *ref)
|
||||
if (dev->driver->driver_features & DRIVER_GEM)
|
||||
drm_gem_destroy(dev);
|
||||
|
||||
drm_ctxbitmap_cleanup(dev);
|
||||
drm_legacy_ctxbitmap_cleanup(dev);
|
||||
drm_ht_remove(&dev->map_hash);
|
||||
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;
|
||||
}
|
||||
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
|
||||
* @dev: DRM device to be added
|
||||
* @head: DRM head in question
|
||||
* drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
|
||||
* @minor: minor to allocate sysfs device for
|
||||
*
|
||||
* Add a DRM device to the DRM's device model class. We use @dev's PCI device
|
||||
* as the parent for the Linux device, and make sure it has a file containing
|
||||
* the driver we're using (for userspace compatibility).
|
||||
* This allocates a new sysfs device for @minor and returns it. The device is
|
||||
* not registered nor linked. The caller has to use device_add() and
|
||||
* device_del() to register and unregister it.
|
||||
*
|
||||
* Note that dev_get_drvdata() on the new device will return the minor.
|
||||
* However, the device does not hold a ref-count to the minor nor to the
|
||||
* underlying drm_device. This is unproblematic as long as you access the
|
||||
* private data only in sysfs callbacks. device_del() disables those
|
||||
* synchronously, so they cannot be called after you cleanup a minor.
|
||||
*/
|
||||
int drm_sysfs_device_add(struct drm_minor *minor)
|
||||
struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
|
||||
{
|
||||
char *minor_str;
|
||||
const char *minor_str;
|
||||
struct device *kdev;
|
||||
int r;
|
||||
|
||||
if (minor->type == DRM_MINOR_CONTROL)
|
||||
minor_str = "controlD%d";
|
||||
else if (minor->type == DRM_MINOR_RENDER)
|
||||
minor_str = "renderD%d";
|
||||
else
|
||||
minor_str = "card%d";
|
||||
else if (minor->type == DRM_MINOR_RENDER)
|
||||
minor_str = "renderD%d";
|
||||
else
|
||||
minor_str = "card%d";
|
||||
|
||||
minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
|
||||
if (!minor->kdev) {
|
||||
r = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
|
||||
if (!kdev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
device_initialize(minor->kdev);
|
||||
minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index);
|
||||
minor->kdev->class = drm_class;
|
||||
minor->kdev->type = &drm_sysfs_device_minor;
|
||||
minor->kdev->parent = minor->dev->dev;
|
||||
minor->kdev->release = drm_sysfs_release;
|
||||
dev_set_drvdata(minor->kdev, minor);
|
||||
device_initialize(kdev);
|
||||
kdev->devt = MKDEV(DRM_MAJOR, minor->index);
|
||||
kdev->class = drm_class;
|
||||
kdev->type = &drm_sysfs_device_minor;
|
||||
kdev->parent = minor->dev->dev;
|
||||
kdev->release = drm_sysfs_release;
|
||||
dev_set_drvdata(kdev, minor);
|
||||
|
||||
r = dev_set_name(minor->kdev, minor_str, minor->index);
|
||||
r = dev_set_name(kdev, minor_str, minor->index);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
goto err_free;
|
||||
|
||||
r = device_add(minor->kdev);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
return kdev;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
DRM_ERROR("device create failed %d\n", r);
|
||||
put_device(minor->kdev);
|
||||
return r;
|
||||
err_free:
|
||||
put_device(kdev);
|
||||
return ERR_PTR(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.
|
||||
*
|
||||
|
@ -1260,7 +1260,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
|
||||
flags = 0;
|
||||
if (args->flags & I915_EXEC_SECURE) {
|
||||
if (!file->is_master || !capable(CAP_SYS_ADMIN))
|
||||
if (!drm_is_master(file) || !capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
flags |= I915_DISPATCH_SECURE;
|
||||
@ -1369,7 +1369,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
ret = i915_parse_cmds(ring,
|
||||
batch_obj,
|
||||
args->batch_start_offset,
|
||||
file->is_master);
|
||||
drm_is_master(file));
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
@ -990,7 +990,7 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev,
|
||||
if (unlikely(ret != 0))
|
||||
return ERR_PTR(-ERESTARTSYS);
|
||||
|
||||
if (file_priv->is_master) {
|
||||
if (drm_is_master(file_priv)) {
|
||||
mutex_unlock(&dev->master_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ static void imx_drm_driver_preclose(struct drm_device *drm,
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!file->is_master)
|
||||
if (!drm_is_master(file))
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_CRTC; i++)
|
||||
|
@ -151,8 +151,6 @@ int drm_err(const char *func, const char *format, ...);
|
||||
also include looping detection. */
|
||||
|
||||
#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
|
||||
|
||||
@ -385,10 +383,7 @@ struct drm_prime_file_private {
|
||||
|
||||
/** File private data */
|
||||
struct drm_file {
|
||||
unsigned always_authenticated :1;
|
||||
unsigned authenticated :1;
|
||||
/* Whether we're master for a minor. Protected by master_mutex */
|
||||
unsigned is_master :1;
|
||||
/* true when the client has asked us to expose stereo 3D mode flags */
|
||||
unsigned stereo_allowed :1;
|
||||
/*
|
||||
@ -538,15 +533,6 @@ struct drm_map_list {
|
||||
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 */
|
||||
#define DRM_ATI_GART_MAIN 1
|
||||
#define DRM_ATI_GART_FB 2
|
||||
@ -1034,7 +1020,7 @@ struct drm_device {
|
||||
/** \name Locks */
|
||||
/*@{ */
|
||||
struct mutex struct_mutex; /**< For others */
|
||||
struct mutex master_mutex; /**< For drm_minor::master and drm_file::is_master */
|
||||
struct mutex master_mutex; /**< For drm_minor::master */
|
||||
/*@} */
|
||||
|
||||
/** \name Usage Counters */
|
||||
@ -1172,6 +1158,21 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv)
|
||||
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 */
|
||||
/*@{*/
|
||||
@ -1187,7 +1188,6 @@ extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
|
||||
/* Device support (drm_fops.h) */
|
||||
extern struct mutex drm_global_mutex;
|
||||
extern int drm_open(struct inode *inode, struct file *filp);
|
||||
extern int drm_stub_open(struct inode *inode, struct file *filp);
|
||||
extern ssize_t drm_read(struct file *filp, char __user *buffer,
|
||||
size_t count, loff_t *offset);
|
||||
extern int drm_release(struct inode *inode, struct file *filp);
|
||||
@ -1225,29 +1225,6 @@ extern int drm_setversion(struct drm_device *dev, void *data,
|
||||
extern int drm_noop(struct drm_device *dev, void *data,
|
||||
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) */
|
||||
extern int drm_getmagic(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
@ -1373,9 +1350,6 @@ extern unsigned int drm_timestamp_precision;
|
||||
extern unsigned int drm_timestamp_monotonic;
|
||||
|
||||
extern struct class *drm_class;
|
||||
extern struct dentry *drm_debugfs_root;
|
||||
|
||||
extern struct idr drm_minors_idr;
|
||||
|
||||
extern struct drm_local_map *drm_getsarea(struct drm_device *dev);
|
||||
|
||||
@ -1493,9 +1467,8 @@ extern int drm_pci_set_unique(struct drm_device *dev,
|
||||
struct drm_sysfs_class;
|
||||
extern struct class *drm_sysfs_create(struct module *owner, char *name);
|
||||
extern void drm_sysfs_destroy(void);
|
||||
extern int drm_sysfs_device_add(struct drm_minor *minor);
|
||||
extern struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
|
||||
extern void drm_sysfs_hotplug_event(struct drm_device *dev);
|
||||
extern void drm_sysfs_device_remove(struct drm_minor *minor);
|
||||
extern int drm_sysfs_connector_add(struct drm_connector *connector);
|
||||
extern void drm_sysfs_connector_remove(struct drm_connector *connector);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user