2005-04-17 02:20:36 +04:00
/**
2005-09-25 08:28:13 +04:00
* \ file drm_drawable . c
2005-04-17 02:20:36 +04:00
* IOCTLs for drawables
*
* \ author Rickard E . ( Rik ) Faith < faith @ valinux . com >
* \ author Gareth Hughes < gareth @ valinux . com >
2006-10-24 17:04:19 +04:00
* \ author Michel Dänzer < michel @ tungstengraphics . com >
2005-04-17 02:20:36 +04:00
*/
/*
* Created : Tue Feb 2 08 : 37 : 54 1999 by faith @ valinux . com
*
* Copyright 1999 Precision Insight , Inc . , Cedar Park , Texas .
* Copyright 2000 VA Linux Systems , Inc . , Sunnyvale , California .
2006-10-24 17:18:49 +04:00
* Copyright 2006 Tungsten Graphics , Inc . , Bismarck , North Dakota .
2005-04-17 02:20:36 +04:00
* 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 "drmP.h"
2006-10-24 17:18:49 +04:00
/**
* Allocate drawable ID and memory to store information about it .
*/
2007-09-03 06:06:45 +04:00
int drm_adddraw ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2006-10-24 17:04:19 +04:00
unsigned long irqflags ;
2007-09-03 06:06:45 +04:00
struct drm_draw * draw = data ;
2007-07-17 04:55:47 +04:00
int new_id = 0 ;
int ret ;
2005-04-17 02:20:36 +04:00
2007-07-17 04:55:47 +04:00
again :
if ( idr_pre_get ( & dev - > drw_idr , GFP_KERNEL ) = = 0 ) {
DRM_ERROR ( " Out of memory expanding drawable idr \n " ) ;
return - ENOMEM ;
2006-10-24 17:04:19 +04:00
}
2006-10-24 17:18:49 +04:00
spin_lock_irqsave ( & dev - > drw_lock , irqflags ) ;
2007-07-17 04:55:47 +04:00
ret = idr_get_new_above ( & dev - > drw_idr , NULL , 1 , & new_id ) ;
if ( ret = = - EAGAIN ) {
spin_unlock_irqrestore ( & dev - > drw_lock , irqflags ) ;
goto again ;
2006-10-24 17:18:49 +04:00
}
2006-10-24 17:04:19 +04:00
spin_unlock_irqrestore ( & dev - > drw_lock , irqflags ) ;
2007-09-03 06:06:45 +04:00
draw - > handle = new_id ;
2007-07-17 04:55:47 +04:00
2007-09-03 06:06:45 +04:00
DRM_DEBUG ( " %d \n " , draw - > handle ) ;
2006-10-24 17:04:19 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
2006-10-24 17:18:49 +04:00
/**
* Free drawable ID and memory to store information about it .
*/
2007-09-03 06:06:45 +04:00
int drm_rmdraw ( 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_draw * draw = data ;
2006-10-24 17:04:19 +04:00
unsigned long irqflags ;
2008-10-17 11:48:44 +04:00
struct drm_drawable_info * info ;
2006-10-24 17:04:19 +04:00
2006-10-24 17:18:49 +04:00
spin_lock_irqsave ( & dev - > drw_lock , irqflags ) ;
2008-10-17 11:48:44 +04:00
info = drm_get_drawable_info ( dev , draw - > handle ) ;
2008-10-21 22:53:01 +04:00
if ( info = = NULL ) {
spin_unlock_irqrestore ( & dev - > drw_lock , irqflags ) ;
return - EINVAL ;
}
2009-03-24 22:23:04 +03:00
kfree ( info - > rects ) ;
kfree ( info ) ;
2006-10-24 17:18:49 +04:00
2007-09-03 06:06:45 +04:00
idr_remove ( & dev - > drw_idr , draw - > handle ) ;
2006-10-24 17:04:19 +04:00
2007-07-17 04:55:47 +04:00
spin_unlock_irqrestore ( & dev - > drw_lock , irqflags ) ;
2007-09-03 06:06:45 +04:00
DRM_DEBUG ( " %d \n " , draw - > handle ) ;
2006-10-24 17:04:19 +04:00
return 0 ;
}
2007-09-03 06:06:45 +04:00
int drm_update_drawable_info ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2007-07-17 04:55:47 +04:00
{
2007-09-03 06:06:45 +04:00
struct drm_update_draw * update = data ;
2007-07-17 04:55:47 +04:00
unsigned long irqflags ;
2007-07-11 09:27:12 +04:00
struct drm_clip_rect * rects ;
2007-07-17 04:55:47 +04:00
struct drm_drawable_info * info ;
2006-10-24 17:18:49 +04:00
int err ;
2006-10-24 17:04:19 +04:00
2007-09-03 06:06:45 +04:00
info = idr_find ( & dev - > drw_idr , update - > handle ) ;
2006-10-24 17:04:19 +04:00
if ( ! info ) {
2009-03-24 22:23:04 +03:00
info = kzalloc ( sizeof ( * info ) , GFP_KERNEL ) ;
2007-07-17 04:55:47 +04:00
if ( ! info )
return - ENOMEM ;
2007-09-03 06:06:45 +04:00
if ( IS_ERR ( idr_replace ( & dev - > drw_idr , info , update - > handle ) ) ) {
DRM_ERROR ( " No such drawable %d \n " , update - > handle ) ;
2009-03-24 22:23:04 +03:00
kfree ( info ) ;
2007-07-17 04:55:47 +04:00
return - EINVAL ;
2006-10-24 17:04:19 +04:00
}
}
2007-09-03 06:06:45 +04:00
switch ( update - > type ) {
2006-10-24 17:04:19 +04:00
case DRM_DRAWABLE_CLIPRECTS :
2008-10-17 09:15:48 +04:00
if ( update - > num = = 0 )
rects = NULL ;
else if ( update - > num ! = info - > num_rects ) {
2009-03-24 22:23:04 +03:00
rects = kmalloc ( update - > num *
sizeof ( struct drm_clip_rect ) ,
GFP_KERNEL ) ;
2006-10-24 17:18:49 +04:00
} else
rects = info - > rects ;
2007-09-03 06:06:45 +04:00
if ( update - > num & & ! rects ) {
2006-10-24 17:18:49 +04:00
DRM_ERROR ( " Failed to allocate cliprect memory \n " ) ;
2007-08-25 13:22:43 +04:00
err = - ENOMEM ;
2006-10-24 17:18:49 +04:00
goto error ;
2006-10-24 17:04:19 +04:00
}
2007-09-03 06:06:45 +04:00
if ( update - > num & & DRM_COPY_FROM_USER ( rects ,
2007-07-11 09:27:12 +04:00
( struct drm_clip_rect __user * )
2007-09-03 06:06:45 +04:00
( unsigned long ) update - > data ,
update - > num *
2006-10-24 17:18:49 +04:00
sizeof ( * rects ) ) ) {
DRM_ERROR ( " Failed to copy cliprects from userspace \n " ) ;
2007-08-25 13:22:43 +04:00
err = - EFAULT ;
2006-10-24 17:18:49 +04:00
goto error ;
2006-10-24 17:04:19 +04:00
}
2006-10-24 17:18:49 +04:00
spin_lock_irqsave ( & dev - > drw_lock , irqflags ) ;
if ( rects ! = info - > rects ) {
2009-03-24 22:23:04 +03:00
kfree ( info - > rects ) ;
2006-10-24 17:04:19 +04:00
}
2006-10-24 17:18:49 +04:00
info - > rects = rects ;
2007-09-03 06:06:45 +04:00
info - > num_rects = update - > num ;
2006-10-24 17:18:49 +04:00
spin_unlock_irqrestore ( & dev - > drw_lock , irqflags ) ;
2006-10-24 17:04:19 +04:00
DRM_DEBUG ( " Updated %d cliprects for drawable %d \n " ,
2007-09-03 06:06:45 +04:00
info - > num_rects , update - > handle ) ;
2006-10-24 17:04:19 +04:00
break ;
default :
2007-09-03 06:06:45 +04:00
DRM_ERROR ( " Invalid update type %d \n " , update - > type ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2006-10-24 17:04:19 +04:00
}
return 0 ;
2006-10-24 17:18:49 +04:00
error :
2007-07-17 04:55:47 +04:00
if ( rects ! = info - > rects )
2009-03-24 22:23:04 +03:00
kfree ( rects ) ;
2006-10-24 17:18:49 +04:00
return err ;
2006-10-24 17:04:19 +04:00
}
/**
* Caller must hold the drawable spinlock !
*/
2007-07-17 04:55:47 +04:00
struct drm_drawable_info * drm_get_drawable_info ( struct drm_device * dev , drm_drawable_t id )
{
return idr_find ( & dev - > drw_idr , id ) ;
}
EXPORT_SYMBOL ( drm_get_drawable_info ) ;
static int drm_drawable_free ( int idr , void * p , void * data )
{
struct drm_drawable_info * info = p ;
if ( info ) {
2009-03-24 22:23:04 +03:00
kfree ( info - > rects ) ;
kfree ( info ) ;
2006-10-24 17:04:19 +04:00
}
2007-07-17 04:55:47 +04:00
return 0 ;
}
void drm_drawable_free_all ( struct drm_device * dev )
{
idr_for_each ( & dev - > drw_idr , drm_drawable_free , NULL ) ;
idr_remove_all ( & dev - > drw_idr ) ;
2005-04-17 02:20:36 +04:00
}