Restore pre-idr semantics for drawable information.

There's a difference between a drawable ID not having valid drawable
information and not being allocated at all. Not making the distinction would
break i915 DRM swap scheduling with older X servers that don't push drawable
cliprect information to the DRM.
main
Michel Dänzer 2007-07-03 11:41:44 +02:00
parent c9d752ff4f
commit 8d96ba9805
1 changed files with 25 additions and 18 deletions

View File

@ -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;
}