2005-04-17 02:20:36 +04:00
/*
* Created : Fri Jan 8 09 : 01 : 26 1999 by faith @ valinux . com
*
* Copyright 1999 Precision Insight , Inc . , Cedar Park , Texas .
* Copyright 2000 VA Linux Systems , Inc . , Sunnyvale , California .
* All Rights Reserved .
*
2014-07-23 16:14:53 +04:00
* Author Rickard E . ( Rik ) Faith < faith @ valinux . com >
* Author Gareth Hughes < gareth @ valinux . com >
*
2005-04-17 02:20:36 +04:00
* 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 .
*/
2012-10-02 21:01:07 +04:00
# include <drm/drmP.h>
# include <drm/drm_core.h>
2014-07-24 14:10:04 +04:00
# include "drm_legacy.h"
2014-09-10 10:16:10 +04:00
# include "drm_internal.h"
2014-12-19 00:49:02 +03:00
# include "drm_crtc_internal.h"
2005-04-17 02:20:36 +04:00
2012-10-02 21:01:07 +04:00
# include <linux/pci.h>
# include <linux/export.h>
2005-04-17 02:20:36 +04:00
2014-07-23 16:14:53 +04:00
static int drm_version ( struct drm_device * dev , void * data ,
struct drm_file * file_priv ) ;
2015-09-08 14:56:27 +03:00
/*
2005-04-17 02:20:36 +04:00
* Get the bus id .
2005-09-25 08:28:13 +04:00
*
2005-04-17 02:20:36 +04:00
* \ param inode device inode .
2007-08-25 14:23:09 +04:00
* \ param file_priv DRM file private .
2005-04-17 02:20:36 +04:00
* \ param cmd command .
* \ param arg user argument , pointing to a drm_unique structure .
* \ return zero on success or a negative number on failure .
*
* Copies the bus id from drm_device : : unique into user space .
*/
2014-09-10 14:43:55 +04:00
static int drm_getunique ( struct drm_device * dev , void * data ,
2007-09-03 06:06:45 +04:00
struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-09-03 06:06:45 +04:00
struct drm_unique * u = data ;
2008-11-28 07:22:24 +03:00
struct drm_master * master = file_priv - > master ;
2005-04-17 02:20:36 +04:00
2008-11-28 07:22:24 +03:00
if ( u - > unique_len > = master - > unique_len ) {
if ( copy_to_user ( u - > unique , master - > unique , master - > unique_len ) )
2005-04-17 02:20:36 +04:00
return - EFAULT ;
}
2008-11-28 07:22:24 +03:00
u - > unique_len = master - > unique_len ;
2007-09-03 06:06:45 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
2010-08-04 14:09:42 +04:00
static void
drm_unset_busid ( struct drm_device * dev ,
struct drm_master * master )
{
kfree ( master - > unique ) ;
master - > unique = NULL ;
master - > unique_len = 0 ;
}
2015-09-08 14:56:27 +03:00
/*
2005-04-17 02:20:36 +04:00
* Set the bus id .
2005-09-25 08:28:13 +04:00
*
2005-04-17 02:20:36 +04:00
* \ param inode device inode .
2007-08-25 14:23:09 +04:00
* \ param file_priv DRM file private .
2005-04-17 02:20:36 +04:00
* \ param cmd command .
* \ param arg user argument , pointing to a drm_unique structure .
* \ return zero on success or a negative number on failure .
*
* Copies the bus id from userspace into drm_device : : unique , and verifies that
* it matches the device this DRM is attached to ( EINVAL otherwise ) . Deprecated
* in interface version 1.1 and will return EBUSY when setversion has requested
2013-11-04 00:47:18 +04:00
* version 1.1 or greater . Also note that KMS is all version 1.1 and later and
* UMS was only ever supported on pci devices .
2005-04-17 02:20:36 +04:00
*/
2014-09-10 14:43:55 +04:00
static int drm_setunique ( struct drm_device * dev , void * data ,
2007-09-03 06:06:45 +04:00
struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-09-03 06:06:45 +04:00
struct drm_unique * u = data ;
2008-11-28 07:22:24 +03:00
struct drm_master * master = file_priv - > master ;
2010-12-14 20:16:38 +03:00
int ret ;
2005-04-17 02:20:36 +04:00
2008-11-28 07:22:24 +03:00
if ( master - > unique_len | | master - > unique )
2005-09-25 08:28:13 +04:00
return - EBUSY ;
2005-04-17 02:20:36 +04:00
2007-09-03 06:06:45 +04:00
if ( ! u - > unique_len | | u - > unique_len > 1024 )
2005-09-25 08:28:13 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
2013-11-04 00:47:18 +04:00
if ( drm_core_check_feature ( dev , DRIVER_MODESET ) )
return 0 ;
if ( WARN_ON ( ! dev - > pdev ) )
2010-12-14 20:16:38 +03:00
return - EINVAL ;
2005-09-25 08:28:13 +04:00
2013-11-04 00:47:18 +04:00
ret = drm_pci_set_unique ( dev , master , u ) ;
2010-12-14 20:16:38 +03:00
if ( ret )
2010-08-04 14:09:42 +04:00
goto err ;
2005-04-17 02:20:36 +04:00
return 0 ;
2010-08-04 14:09:42 +04:00
err :
drm_unset_busid ( dev , master ) ;
return ret ;
2005-04-17 02:20:36 +04:00
}
2008-11-28 07:22:24 +03:00
static int drm_set_busid ( struct drm_device * dev , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2008-11-28 07:22:24 +03:00
struct drm_master * master = file_priv - > master ;
2010-12-14 20:16:38 +03:00
int ret ;
2010-08-04 14:09:42 +04:00
if ( master - > unique ! = NULL )
drm_unset_busid ( dev , master ) ;
2006-01-02 13:19:39 +03:00
2014-08-29 14:12:43 +04:00
if ( dev - > driver - > set_busid ) {
ret = dev - > driver - > set_busid ( dev , master ) ;
if ( ret ) {
drm_unset_busid ( dev , master ) ;
return ret ;
}
2014-04-11 17:23:00 +04:00
} else {
if ( WARN ( dev - > unique = = NULL ,
2014-08-29 14:12:44 +04:00
" No drm_driver.set_busid() implementation provided by "
2014-04-11 17:23:00 +04:00
" %ps. Use drm_dev_set_unique() to set the unique "
" name explicitly. " , dev - > driver ) )
return - EINVAL ;
master - > unique = kstrdup ( dev - > unique , GFP_KERNEL ) ;
if ( master - > unique )
master - > unique_len = strlen ( dev - > unique ) ;
}
2005-04-17 02:20:36 +04:00
return 0 ;
}
2015-09-08 14:56:27 +03:00
/*
2005-04-17 02:20:36 +04:00
* Get a mapping information .
*
* \ param inode device inode .
2007-08-25 14:23:09 +04:00
* \ param file_priv DRM file private .
2005-04-17 02:20:36 +04:00
* \ param cmd command .
* \ param arg user argument , pointing to a drm_map structure .
2005-09-25 08:28:13 +04:00
*
2005-04-17 02:20:36 +04:00
* \ return zero on success or a negative number on failure .
*
* Searches for the mapping with the specified offset and copies its information
* into userspace
*/
2014-09-10 14:43:55 +04:00
static int drm_getmap ( struct drm_device * dev , void * data ,
2007-09-03 06:06:45 +04:00
struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-09-03 06:06:45 +04:00
struct drm_map * map = data ;
2007-07-11 10:53:40 +04:00
struct drm_map_list * r_list = NULL ;
2005-04-17 02:20:36 +04:00
struct list_head * list ;
2005-09-25 08:28:13 +04:00
int idx ;
int i ;
2005-04-17 02:20:36 +04:00
2007-09-03 06:06:45 +04:00
idx = map - > offset ;
drm: make DRM_UNLOCKED ioctls with their own mutex
drm_getclient, drm_getstats and drm_getmap (with a few minor
adjustments) do not need global mutex, so fix that and
make the said ioctls DRM_UNLOCKED. Details:
drm_getclient: the only thing that should be protected here
is dev->filelist and that is already protected everywhere with
dev->struct_mutex.
drm_getstats: there is no need for any mutex here because the
loop runs through quasi-static (set at load time only)
data, and the actual count access is done with atomic_read()
drm_getmap already uses dev->struct_mutex to protect
dev->maplist, which also used to protect the same structure
everywhere else except at three places:
* drm_getsarea, which doesn't grab *any* mutex before
touching dev->maplist (so no drm_global_mutex doesn't help
here either; different issue for a different patch).
However, drivers seem to call it only at
initialization time so it probably doesn't matter
* drm_master_destroy, which is called from drm_master_put,
which in turn is protected with dev->struct_mutex
everywhere else in drm module, so we are good here too.
* drm_getsareactx, which releases the dev->struct_mutex
too early, but this patch includes the fix for that.
v2: * incorporate comments received from Daniel Vetter
* include the (long) explanation above to make it clear what
we are doing (and why), also at Daniel Vetter's request
* tighten up mutex grab/release locations to only
encompass real critical sections, rather than some
random code around them
Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2011-10-29 01:43:28 +04:00
if ( idx < 0 )
2005-04-17 02:20:36 +04:00
return - EINVAL ;
i = 0 ;
drm: make DRM_UNLOCKED ioctls with their own mutex
drm_getclient, drm_getstats and drm_getmap (with a few minor
adjustments) do not need global mutex, so fix that and
make the said ioctls DRM_UNLOCKED. Details:
drm_getclient: the only thing that should be protected here
is dev->filelist and that is already protected everywhere with
dev->struct_mutex.
drm_getstats: there is no need for any mutex here because the
loop runs through quasi-static (set at load time only)
data, and the actual count access is done with atomic_read()
drm_getmap already uses dev->struct_mutex to protect
dev->maplist, which also used to protect the same structure
everywhere else except at three places:
* drm_getsarea, which doesn't grab *any* mutex before
touching dev->maplist (so no drm_global_mutex doesn't help
here either; different issue for a different patch).
However, drivers seem to call it only at
initialization time so it probably doesn't matter
* drm_master_destroy, which is called from drm_master_put,
which in turn is protected with dev->struct_mutex
everywhere else in drm module, so we are good here too.
* drm_getsareactx, which releases the dev->struct_mutex
too early, but this patch includes the fix for that.
v2: * incorporate comments received from Daniel Vetter
* include the (long) explanation above to make it clear what
we are doing (and why), also at Daniel Vetter's request
* tighten up mutex grab/release locations to only
encompass real critical sections, rather than some
random code around them
Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2011-10-29 01:43:28 +04:00
mutex_lock ( & dev - > struct_mutex ) ;
2007-05-25 23:01:51 +04:00
list_for_each ( list , & dev - > maplist ) {
2005-09-25 08:28:13 +04:00
if ( i = = idx ) {
2007-07-11 10:53:40 +04:00
r_list = list_entry ( list , struct drm_map_list , head ) ;
2005-04-17 02:20:36 +04:00
break ;
}
i + + ;
}
2005-09-25 08:28:13 +04:00
if ( ! r_list | | ! r_list - > map ) {
2006-02-02 11:37:46 +03:00
mutex_unlock ( & dev - > struct_mutex ) ;
2005-04-17 02:20:36 +04:00
return - EINVAL ;
}
2007-09-03 06:06:45 +04:00
map - > offset = r_list - > map - > offset ;
map - > size = r_list - > map - > size ;
map - > type = r_list - > map - > type ;
map - > flags = r_list - > map - > flags ;
map - > handle = ( void * ) ( unsigned long ) r_list - > user_token ;
2015-05-26 11:28:13 +03:00
map - > mtrr = arch_phys_wc_index ( r_list - > map - > mtrr ) ;
2013-05-14 03:58:48 +04:00
2006-02-02 11:37:46 +03:00
mutex_unlock ( & dev - > struct_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2015-09-08 14:56:27 +03:00
/*
2005-04-17 02:20:36 +04:00
* Get client information .
*
* \ param inode device inode .
2007-08-25 14:23:09 +04:00
* \ param file_priv DRM file private .
2005-04-17 02:20:36 +04:00
* \ param cmd command .
* \ param arg user argument , pointing to a drm_client structure .
2005-09-25 08:28:13 +04:00
*
2005-04-17 02:20:36 +04:00
* \ return zero on success or a negative number on failure .
*
* Searches for the client with the specified index and copies its information
* into userspace
*/
2014-09-10 14:43:55 +04:00
static int drm_getclient ( struct drm_device * dev , void * data ,
2007-09-03 06:06:45 +04:00
struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-09-03 06:06:45 +04:00
struct drm_client * client = data ;
drm: make DRM_UNLOCKED ioctls with their own mutex
drm_getclient, drm_getstats and drm_getmap (with a few minor
adjustments) do not need global mutex, so fix that and
make the said ioctls DRM_UNLOCKED. Details:
drm_getclient: the only thing that should be protected here
is dev->filelist and that is already protected everywhere with
dev->struct_mutex.
drm_getstats: there is no need for any mutex here because the
loop runs through quasi-static (set at load time only)
data, and the actual count access is done with atomic_read()
drm_getmap already uses dev->struct_mutex to protect
dev->maplist, which also used to protect the same structure
everywhere else except at three places:
* drm_getsarea, which doesn't grab *any* mutex before
touching dev->maplist (so no drm_global_mutex doesn't help
here either; different issue for a different patch).
However, drivers seem to call it only at
initialization time so it probably doesn't matter
* drm_master_destroy, which is called from drm_master_put,
which in turn is protected with dev->struct_mutex
everywhere else in drm module, so we are good here too.
* drm_getsareactx, which releases the dev->struct_mutex
too early, but this patch includes the fix for that.
v2: * incorporate comments received from Daniel Vetter
* include the (long) explanation above to make it clear what
we are doing (and why), also at Daniel Vetter's request
* tighten up mutex grab/release locations to only
encompass real critical sections, rather than some
random code around them
Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2011-10-29 01:43:28 +04:00
2013-08-08 17:41:31 +04:00
/*
* Hollowed - out getclient ioctl to keep some dead old drm tests / tools
* not breaking completely . Userspace tools stop enumerating one they
* get - EINVAL , hence this is the return value we need to hand back for
* no clients tracked .
*
* Unfortunately some clients ( * cough * libva * cough * ) use this in a fun
* attempt to figure out whether they ' re authenticated or not . Since
* that ' s the only thing they care about , give it to the directly
* instead of walking one giant list .
*/
if ( client - > idx = = 0 ) {
client - > auth = file_priv - > authenticated ;
client - > pid = pid_vnr ( file_priv - > pid ) ;
client - > uid = from_kuid_munged ( current_user_ns ( ) ,
file_priv - > uid ) ;
client - > magic = 0 ;
client - > iocs = 0 ;
return 0 ;
} else {
return - EINVAL ;
2007-05-25 23:01:51 +04:00
}
2005-04-17 02:20:36 +04:00
}
2015-09-08 14:56:27 +03:00
/*
2005-09-25 08:28:13 +04:00
* Get statistics information .
*
2005-04-17 02:20:36 +04:00
* \ param inode device inode .
2007-08-25 14:23:09 +04:00
* \ param file_priv DRM file private .
2005-04-17 02:20:36 +04:00
* \ param cmd command .
* \ param arg user argument , pointing to a drm_stats structure .
2005-09-25 08:28:13 +04:00
*
2005-04-17 02:20:36 +04:00
* \ return zero on success or a negative number on failure .
*/
2014-09-10 14:43:55 +04:00
static int drm_getstats ( struct drm_device * dev , void * data ,
2007-09-03 06:06:45 +04:00
struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-09-03 06:06:45 +04:00
struct drm_stats * stats = data ;
2005-04-17 02:20:36 +04:00
2013-08-08 17:41:32 +04:00
/* Clear stats to prevent userspace from eating its stack garbage. */
2007-11-05 05:53:09 +03:00
memset ( stats , 0 , sizeof ( * stats ) ) ;
2005-09-25 08:28:13 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
2015-09-08 14:56:27 +03:00
/*
2011-02-21 04:17:35 +03:00
* Get device / driver capabilities
*/
2014-09-10 14:43:55 +04:00
static int drm_getcap ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2011-02-21 04:17:35 +03:00
{
struct drm_get_cap * req = data ;
req - > value = 0 ;
2011-03-04 07:50:28 +03:00
switch ( req - > capability ) {
case DRM_CAP_DUMB_BUFFER :
if ( dev - > driver - > dumb_create )
req - > value = 1 ;
break ;
2011-03-24 13:54:35 +03:00
case DRM_CAP_VBLANK_HIGH_CRTC :
2011-03-19 00:58:04 +03:00
req - > value = 1 ;
break ;
2011-09-29 19:20:42 +04:00
case DRM_CAP_DUMB_PREFERRED_DEPTH :
req - > value = dev - > mode_config . preferred_depth ;
break ;
case DRM_CAP_DUMB_PREFER_SHADOW :
req - > value = dev - > mode_config . prefer_shadow ;
break ;
2012-04-02 17:11:50 +04:00
case DRM_CAP_PRIME :
req - > value | = dev - > driver - > prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0 ;
req - > value | = dev - > driver - > prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0 ;
break ;
2012-10-23 22:53:26 +04:00
case DRM_CAP_TIMESTAMP_MONOTONIC :
req - > value = drm_timestamp_monotonic ;
break ;
2013-07-23 05:50:00 +04:00
case DRM_CAP_ASYNC_PAGE_FLIP :
req - > value = dev - > mode_config . async_page_flip ;
break ;
2014-02-12 21:48:23 +04:00
case DRM_CAP_CURSOR_WIDTH :
if ( dev - > mode_config . cursor_width )
req - > value = dev - > mode_config . cursor_width ;
else
req - > value = 64 ;
break ;
case DRM_CAP_CURSOR_HEIGHT :
if ( dev - > mode_config . cursor_height )
req - > value = dev - > mode_config . cursor_height ;
else
req - > value = 64 ;
break ;
2015-02-05 17:41:52 +03:00
case DRM_CAP_ADDFB2_MODIFIERS :
req - > value = dev - > mode_config . allow_fb_modifiers ;
break ;
2011-03-04 07:50:28 +03:00
default :
return - EINVAL ;
}
2011-02-21 04:17:35 +03:00
return 0 ;
}
2015-09-08 14:56:27 +03:00
/*
2013-09-25 19:45:20 +04:00
* Set device / driver capabilities
*/
2014-09-10 14:43:55 +04:00
static int
2013-09-25 19:45:20 +04:00
drm_setclientcap ( struct drm_device * dev , void * data , struct drm_file * file_priv )
{
2013-09-25 19:45:22 +04:00
struct drm_set_client_cap * req = data ;
switch ( req - > capability ) {
case DRM_CLIENT_CAP_STEREO_3D :
if ( req - > value > 1 )
return - EINVAL ;
file_priv - > stereo_allowed = req - > value ;
break ;
2014-04-02 02:22:42 +04:00
case DRM_CLIENT_CAP_UNIVERSAL_PLANES :
if ( req - > value > 1 )
return - EINVAL ;
file_priv - > universal_planes = req - > value ;
break ;
2014-12-19 00:01:50 +03:00
case DRM_CLIENT_CAP_ATOMIC :
if ( ! drm_core_check_feature ( dev , DRIVER_ATOMIC ) )
return - EINVAL ;
if ( req - > value > 1 )
return - EINVAL ;
file_priv - > atomic = req - > value ;
2014-12-19 12:33:52 +03:00
file_priv - > universal_planes = req - > value ;
2014-12-19 00:01:50 +03:00
break ;
2013-09-25 19:45:22 +04:00
default :
return - EINVAL ;
}
return 0 ;
2013-09-25 19:45:20 +04:00
}
2015-09-08 14:56:27 +03:00
/*
2005-04-17 02:20:36 +04:00
* Setversion ioctl .
*
* \ param inode device inode .
2007-08-25 14:23:09 +04:00
* \ param file_priv DRM file private .
2005-04-17 02:20:36 +04:00
* \ param cmd command .
* \ param arg user argument , pointing to a drm_lock structure .
* \ return zero on success or negative number on failure .
*
* Sets the requested interface version
*/
2014-09-10 14:43:55 +04:00
static int drm_setversion ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-09-03 06:06:45 +04:00
struct drm_set_version * sv = data ;
int if_version , retcode = 0 ;
if ( sv - > drm_di_major ! = - 1 ) {
if ( sv - > drm_di_major ! = DRM_IF_MAJOR | |
sv - > drm_di_minor < 0 | | sv - > drm_di_minor > DRM_IF_MINOR ) {
retcode = - EINVAL ;
goto done ;
}
if_version = DRM_IF_VERSION ( sv - > drm_di_major ,
sv - > drm_di_minor ) ;
2006-08-07 14:07:43 +04:00
dev - > if_version = max ( if_version , dev - > if_version ) ;
2007-09-03 06:06:45 +04:00
if ( sv - > drm_di_minor > = 1 ) {
2005-04-17 02:20:36 +04:00
/*
* Version 1.1 includes tying of DRM to specific device
2010-08-06 07:55:10 +04:00
* Version 1.4 has proper PCI domain support
2005-04-17 02:20:36 +04:00
*/
2010-08-04 14:09:42 +04:00
retcode = drm_set_busid ( dev , file_priv ) ;
if ( retcode )
goto done ;
2005-04-17 02:20:36 +04:00
}
}
2007-09-03 06:06:45 +04:00
if ( sv - > drm_dd_major ! = - 1 ) {
if ( sv - > drm_dd_major ! = dev - > driver - > major | |
sv - > drm_dd_minor < 0 | | sv - > drm_dd_minor >
dev - > driver - > minor ) {
retcode = - EINVAL ;
goto done ;
}
2005-04-17 02:20:36 +04:00
}
2007-09-03 06:06:45 +04:00
done :
sv - > drm_di_major = DRM_IF_MAJOR ;
sv - > drm_di_minor = DRM_IF_MINOR ;
sv - > drm_dd_major = dev - > driver - > major ;
sv - > drm_dd_minor = dev - > driver - > minor ;
return retcode ;
2005-04-17 02:20:36 +04:00
}
2015-09-08 14:56:27 +03:00
/**
* drm_noop - DRM no - op ioctl implemntation
* @ dev : DRM device for the ioctl
* @ data : data pointer for the ioctl
* @ file_priv : DRM file for the ioctl call
*
* This no - op implementation for drm ioctls is useful for deprecated
* functionality where we can ' t return a failure code because existing userspace
* checks the result of the ioctl , but doesn ' t care about the action .
*
* Always returns successfully with 0.
*/
2007-09-03 06:06:45 +04:00
int drm_noop ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
DRM_DEBUG ( " \n " ) ;
return 0 ;
}
2012-01-17 15:50:12 +04:00
EXPORT_SYMBOL ( drm_noop ) ;
2014-07-23 16:14:53 +04:00
2015-09-08 14:56:27 +03:00
/**
* drm_invalid_op - DRM invalid ioctl implemntation
* @ dev : DRM device for the ioctl
* @ data : data pointer for the ioctl
* @ file_priv : DRM file for the ioctl call
*
* This no - op implementation for drm ioctls is useful for deprecated
* functionality where we really don ' t want to allow userspace to call the ioctl
* any more . This is the case for old ums interfaces for drivers that
* transitioned to kms gradually and so kept the old legacy tables around . This
* only applies to radeon and i915 kms drivers , other drivers shouldn ' t need to
* use this function .
*
* Always fails with a return value of - EINVAL .
*/
2015-09-08 14:56:26 +03:00
int drm_invalid_op ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
return - EINVAL ;
}
EXPORT_SYMBOL ( drm_invalid_op ) ;
2015-09-08 14:56:27 +03:00
/*
2014-07-23 16:14:53 +04:00
* 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 ;
}
2015-09-08 14:56:27 +03:00
/*
2014-07-23 16:14:53 +04:00
* 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 ;
}
2015-09-08 14:56:27 +03:00
/*
2014-07-23 16:14:53 +04:00
* 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 .
*/
2015-07-11 08:31:08 +03:00
int drm_ioctl_permit ( u32 flags , struct drm_file * file_priv )
2014-07-23 16:14:53 +04:00
{
/* 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 */
2014-08-08 01:30:53 +04:00
if ( unlikely ( ( flags & DRM_MASTER ) & & ! file_priv - > is_master & &
2014-07-23 16:14:53 +04:00
! 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 ;
}
2015-07-11 08:31:08 +03:00
EXPORT_SYMBOL ( drm_ioctl_permit ) ;
2014-07-23 16:14:53 +04:00
2015-03-30 20:10:36 +03:00
# define DRM_IOCTL_DEF(ioctl, _func, _flags) \
[ DRM_IOCTL_NR ( ioctl ) ] = { \
. cmd = ioctl , \
. func = _func , \
. flags = _flags , \
. name = # ioctl \
}
2014-09-10 14:43:55 +04:00
2015-09-08 14:56:27 +03:00
/* Ioctl table */
2014-09-10 14:43:55 +04:00
static const struct drm_ioctl_desc drm_ioctls [ ] = {
2015-09-15 11:11:42 +03:00
DRM_IOCTL_DEF ( DRM_IOCTL_VERSION , drm_version ,
DRM_UNLOCKED | DRM_RENDER_ALLOW | DRM_CONTROL_ALLOW ) ,
2014-09-10 14:43:55 +04:00
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_legacy_addmap_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_RM_MAP , drm_legacy_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_legacy_lock , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_UNLOCK , drm_legacy_unlock , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_FINISH , drm_noop , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_ADD_BUFS , drm_legacy_addbufs , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MARK_BUFS , drm_legacy_markbufs , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_INFO_BUFS , drm_legacy_infobufs , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MAP_BUFS , drm_legacy_mapbufs , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_FREE_BUFS , drm_legacy_freebufs , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_DMA , drm_legacy_dma_ioctl , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_CONTROL , drm_control , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
2015-09-09 17:45:52 +03:00
# if IS_ENABLED(CONFIG_AGP)
2014-09-10 14:43:55 +04:00
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_legacy_sg_alloc , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_SG_FREE , drm_legacy_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 ) ,
2014-12-19 00:01:56 +03:00
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_ATOMIC , drm_mode_atomic_ioctl , DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED ) ,
2015-05-22 15:34:51 +03:00
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_CREATEPROPBLOB , drm_mode_createblob_ioctl , DRM_CONTROL_ALLOW | DRM_UNLOCKED ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_DESTROYPROPBLOB , drm_mode_destroyblob_ioctl , DRM_CONTROL_ALLOW | DRM_UNLOCKED ) ,
2014-09-10 14:43:55 +04:00
} ;
# define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
2014-07-23 16:14:53 +04:00
/**
2015-09-08 14:56:27 +03:00
* drm_ioctl - ioctl callback implementation for DRM drivers
* @ filp : file this ioctl is called on
* @ cmd : ioctl cmd number
* @ arg : user argument
2014-07-23 16:14:53 +04:00
*
* Looks up the ioctl function in the : : ioctls table , checking for root
* previleges if so required , and dispatches to the respective function .
2015-09-08 14:56:27 +03:00
*
* Returns :
* Zero on success , negative error code on failure .
2014-07-23 16:14:53 +04:00
*/
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 ;
2015-03-27 16:51:58 +03:00
unsigned int usize , asize , drv_size ;
2015-09-28 22:42:40 +03:00
bool is_driver_ioctl ;
2014-07-23 16:14:53 +04:00
dev = file_priv - > minor - > dev ;
if ( drm_device_is_unplugged ( dev ) )
return - ENODEV ;
2015-09-28 22:42:40 +03:00
is_driver_ioctl = nr > = DRM_COMMAND_BASE & & nr < DRM_COMMAND_END ;
if ( is_driver_ioctl ) {
2015-03-27 16:51:58 +03:00
/* driver ioctl */
if ( nr - DRM_COMMAND_BASE > = dev - > driver - > num_ioctls )
goto err_i1 ;
2014-07-23 16:14:53 +04:00
ioctl = & dev - > driver - > ioctls [ nr - DRM_COMMAND_BASE ] ;
2015-03-27 16:51:58 +03:00
} else {
/* core ioctl */
if ( nr > = DRM_CORE_IOCTL_COUNT )
goto err_i1 ;
2014-07-23 16:14:53 +04:00
ioctl = & drm_ioctls [ nr ] ;
2015-03-27 16:51:58 +03:00
}
2014-07-23 16:14:53 +04:00
2015-03-27 16:51:58 +03:00
drv_size = _IOC_SIZE ( ioctl - > cmd ) ;
2015-03-27 16:51:59 +03:00
usize = _IOC_SIZE ( cmd ) ;
asize = max ( usize , drv_size ) ;
2015-03-27 16:51:58 +03:00
cmd = ioctl - > cmd ;
2014-07-23 16:14:53 +04:00
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 ) ;
}
2015-09-28 22:42:40 +03:00
/* Enforce sane locking for kms driver ioctls. Core ioctls are
* too messy still . */
if ( ( drm_core_check_feature ( dev , DRIVER_MODESET ) & & is_driver_ioctl ) | |
( ioctl - > flags & DRM_UNLOCKED ) )
2014-07-23 16:14:53 +04:00
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
2015-09-08 14:56:27 +03:00
* @ nr : ioctl number
* @ flags : where to return the ioctl permission flags
*
* This ioctl is only used by the vmwgfx driver to augment the access checks
* done by the drm core and insofar a pretty decent layering violation . This
* shouldn ' t be used by any drivers .
2014-07-23 16:14:53 +04:00
*
2015-09-08 14:56:27 +03:00
* Returns :
* True if the @ nr corresponds to a DRM core ioctl numer , false otherwise .
2014-07-23 16:14:53 +04:00
*/
bool drm_ioctl_flags ( unsigned int nr , unsigned int * flags )
{
2015-03-27 16:52:00 +03:00
if ( nr > = DRM_COMMAND_BASE & & nr < DRM_COMMAND_END )
return false ;
if ( nr > = DRM_CORE_IOCTL_COUNT )
return false ;
2014-07-23 16:14:53 +04:00
2015-03-27 16:52:00 +03:00
* flags = drm_ioctls [ nr ] . flags ;
return true ;
2014-07-23 16:14:53 +04:00
}
EXPORT_SYMBOL ( drm_ioctl_flags ) ;