diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/drm_drawable.c | 43 | 
1 files changed, 25 insertions, 18 deletions
diff --git a/linux-core/drm_drawable.c b/linux-core/drm_drawable.c index 74f0bb5d..7657e954 100644 --- a/linux-core/drm_drawable.c +++ b/linux-core/drm_drawable.c @@ -37,6 +37,8 @@  #include "drmP.h" +#define NO_DRW_INFO (void*)1 +  /**   * Allocate drawable ID and memory to store information about it.   */ @@ -44,24 +46,18 @@ int drm_adddraw(DRM_IOCTL_ARGS)  {  	DRM_DEVICE;  	unsigned long irqflags; -	struct drm_drawable_info *draw_info;  	drm_draw_t draw;  	int new_id = 0;  	int ret; -	draw_info = drm_calloc(1, sizeof(*draw_info), DRM_MEM_BUFS); -	if (!draw_info) -		return -ENOMEM; -  again:  	if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {  		DRM_ERROR("Out of memory expanding drawable idr\n"); -		drm_free(draw_info, sizeof(struct drm_drawable_info), DRM_MEM_BUFS);  		return -ENOMEM;  	}  	spin_lock_irqsave(&dev->drw_lock, irqflags); -	ret = idr_get_new_above(&dev->drw_idr, draw_info, 1, &new_id); +	ret = idr_get_new_above(&dev->drw_idr, NO_DRW_INFO, 1, &new_id);  	if (ret == -EAGAIN) {  		spin_unlock_irqrestore(&dev->drw_lock, irqflags);  		goto again; @@ -86,21 +82,16 @@ int drm_rmdraw(DRM_IOCTL_ARGS)  	DRM_DEVICE;  	drm_draw_t draw;  	unsigned long irqflags; -	struct drm_drawable_info *draw_info;  	DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,  				 sizeof(draw)); -	draw_info = idr_find(&dev->drw_idr, draw.handle); -	if (!draw_info) { -		DRM_DEBUG("No such drawable %d\n", draw.handle); -		return -EINVAL; -	} -  	spin_lock_irqsave(&dev->drw_lock, irqflags); +	drm_free(drm_get_drawable_info(dev, draw.handle), +		 sizeof(struct drm_drawable_info), DRM_MEM_BUFS); +  	idr_remove(&dev->drw_idr, draw.handle); -	drm_free(draw_info, sizeof(struct drm_drawable_info), DRM_MEM_BUFS);  	spin_unlock_irqrestore(&dev->drw_lock, irqflags);  	DRM_DEBUG("%d\n", draw.handle); @@ -125,6 +116,13 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS)  		return DRM_ERR(EINVAL);  	} +	if (info == NO_DRW_INFO) { +		info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS); +		if (!info) +			return -ENOMEM; +		idr_replace(&dev->drw_idr, info, update.handle); +	} +  	switch (update.type) {  	case DRM_DRAWABLE_CLIPRECTS:  		if (update.num != info->num_rects) { @@ -187,11 +185,17 @@ drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id)  	struct drm_drawable_info *info;  	info = idr_find(&dev->drw_idr, id); +  	if (!info) {  		DRM_DEBUG("No such drawable %d\n", id);  		return NULL;  	} +	if (info == NO_DRW_INFO) { +		DRM_DEBUG("No information for drawable %d\n", id); +		return NULL; +	} +  	return info;  }  EXPORT_SYMBOL(drm_get_drawable_info); @@ -200,9 +204,12 @@ static int drm_drawable_free(int idr, void *p, void *data)  {  	struct drm_drawable_info *info = p; -	drm_free(info->rects, info->num_rects * -		 sizeof(drm_clip_rect_t), DRM_MEM_BUFS); -	drm_free(info, sizeof(struct drm_drawable_info), DRM_MEM_BUFS); +	if (info != NO_DRW_INFO) { +		drm_free(info->rects, info->num_rects * +			 sizeof(drm_clip_rect_t), DRM_MEM_BUFS); +		drm_free(info, sizeof(*info), DRM_MEM_BUFS); +	} +  	return 0;  }  | 
