diff options
Diffstat (limited to 'linux-core')
-rw-r--r-- | linux-core/drmP.h | 11 | ||||
-rw-r--r-- | linux-core/drm_context.c | 142 |
2 files changed, 61 insertions, 92 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 16d7dbbf..f988db35 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -570,6 +570,12 @@ typedef struct drm_ctx_list { drm_file_t *tag; /**< associated fd private data */ } drm_ctx_list_t; +struct drm_ctx_sarea_list { + struct list_head head; + int ctx_id; + drm_map_t *map; +}; + typedef struct drm_vbl_sig { struct list_head head; unsigned int sequence; @@ -746,8 +752,8 @@ typedef struct drm_device { int ctx_count; /**< Number of context handles */ struct mutex ctxlist_mutex; /**< For ctxlist */ - drm_map_t **context_sareas; /**< per-context SAREA's */ - int max_context; + struct idr ctx_idr; + struct list_head context_sarealist; struct list_head vmalist; /**< List of vmas (for debugging) */ drm_lock_data_t lock; /**< Information on hardware lock */ @@ -808,7 +814,6 @@ typedef struct drm_device { struct pci_controller *hose; #endif drm_sg_mem_t *sg; /**< Scatter gather memory */ - unsigned long *ctx_bitmap; /**< context bitmap */ void *dev_private; /**< device private data */ drm_sigdata_t sigdata; /**< For block_all_signals */ sigset_t sigmask; diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c index 3bfee127..5cb79b14 100644 --- a/linux-core/drm_context.c +++ b/linux-core/drm_context.c @@ -58,20 +58,17 @@ */ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) { - if (ctx_handle < 0) - goto failed; - if (!dev->ctx_bitmap) - goto failed; - - if (ctx_handle < DRM_MAX_CTXBITMAP) { - mutex_lock(&dev->struct_mutex); - clear_bit(ctx_handle, dev->ctx_bitmap); - dev->context_sareas[ctx_handle] = NULL; - mutex_unlock(&dev->struct_mutex); - return; - } - failed: - DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle); + struct drm_ctx_sarea_list *ctx_sarea; + + mutex_lock(&dev->struct_mutex); + ctx_sarea = idr_find(&dev->ctx_idr, ctx_handle); + if (ctx_sarea) { + idr_remove(&dev->ctx_idr, ctx_handle); + list_del(&ctx_sarea->head); + drm_free(ctx_sarea, sizeof(struct drm_ctx_sarea_list), DRM_MEM_BUFS); + } else + DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle); + mutex_unlock(&dev->struct_mutex); return; } @@ -87,56 +84,32 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) */ static int drm_ctxbitmap_next(drm_device_t * dev) { - int bit; + int new_id; + int ret; + struct drm_ctx_sarea_list *new_ctx; - if (!dev->ctx_bitmap) + new_ctx = drm_calloc(1, sizeof(struct drm_ctx_sarea_list), DRM_MEM_BUFS); + if (!new_ctx) return -1; +again: + if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) { + DRM_ERROR("Out of memory expanding drawable idr\n"); + drm_free(new_ctx, sizeof(struct drm_ctx_sarea_list), DRM_MEM_BUFS); + return -ENOMEM; + } mutex_lock(&dev->struct_mutex); - bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP); - if (bit < DRM_MAX_CTXBITMAP) { - set_bit(bit, dev->ctx_bitmap); - DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit); - if ((bit + 1) > dev->max_context) { - dev->max_context = (bit + 1); - if (dev->context_sareas) { - drm_map_t **ctx_sareas; - - ctx_sareas = drm_realloc(dev->context_sareas, - (dev->max_context - - 1) * - sizeof(*dev-> - context_sareas), - dev->max_context * - sizeof(*dev-> - context_sareas), - DRM_MEM_MAPS); - if (!ctx_sareas) { - clear_bit(bit, dev->ctx_bitmap); - mutex_unlock(&dev->struct_mutex); - return -1; - } - dev->context_sareas = ctx_sareas; - dev->context_sareas[bit] = NULL; - } else { - /* max_context == 1 at this point */ - dev->context_sareas = - drm_alloc(dev->max_context * - sizeof(*dev->context_sareas), - DRM_MEM_MAPS); - if (!dev->context_sareas) { - clear_bit(bit, dev->ctx_bitmap); - mutex_unlock(&dev->struct_mutex); - return -1; - } - dev->context_sareas[bit] = NULL; - } - } + ret = idr_get_new_above(&dev->ctx_idr, new_ctx, DRM_RESERVED_CONTEXTS, &new_id); + if (ret == -EAGAIN) { mutex_unlock(&dev->struct_mutex); - return bit; + goto again; } + mutex_unlock(&dev->struct_mutex); - return -1; + + new_ctx->ctx_id = new_id; + list_add(&new_ctx->head, &dev->context_sarealist); + return new_id; } /** @@ -149,25 +122,8 @@ static int drm_ctxbitmap_next(drm_device_t * dev) */ int drm_ctxbitmap_init(drm_device_t * dev) { - int i; - int temp; - - mutex_lock(&dev->struct_mutex); - dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE, - DRM_MEM_CTXBITMAP); - if (dev->ctx_bitmap == NULL) { - mutex_unlock(&dev->struct_mutex); - return -ENOMEM; - } - memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE); - dev->context_sareas = NULL; - dev->max_context = -1; - mutex_unlock(&dev->struct_mutex); - - for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { - temp = drm_ctxbitmap_next(dev); - DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp); - } + idr_init(&dev->ctx_idr); + INIT_LIST_HEAD(&dev->context_sarealist); return 0; } @@ -182,12 +138,13 @@ int drm_ctxbitmap_init(drm_device_t * dev) */ void drm_ctxbitmap_cleanup(drm_device_t * dev) { + struct drm_ctx_sarea_list *ctx_entry, *ctx_temp; + mutex_lock(&dev->struct_mutex); - if (dev->context_sareas) - drm_free(dev->context_sareas, - sizeof(*dev->context_sareas) * - dev->max_context, DRM_MEM_MAPS); - drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP); + list_for_each_entry_safe(ctx_entry, ctx_temp, &dev->context_sarealist, head) { + idr_remove(&dev->ctx_idr, ctx_entry->ctx_id); + drm_free(ctx_entry, sizeof(struct drm_ctx_sarea_list), DRM_MEM_MAPS); + } mutex_unlock(&dev->struct_mutex); } @@ -218,18 +175,20 @@ int drm_getsareactx(struct inode *inode, struct file *filp, drm_ctx_priv_map_t request; drm_map_t *map; drm_map_list_t *_entry; + struct drm_ctx_sarea_list *ctx_sarea; if (copy_from_user(&request, argp, sizeof(request))) return -EFAULT; mutex_lock(&dev->struct_mutex); - if (dev->max_context < 0 - || request.ctx_id >= (unsigned)dev->max_context) { + + ctx_sarea = idr_find(&dev->ctx_idr, request.ctx_id); + if (!ctx_sarea) { mutex_unlock(&dev->struct_mutex); return -EINVAL; } - - map = dev->context_sareas[request.ctx_id]; + + map = ctx_sarea->map; mutex_unlock(&dev->struct_mutex); request.handle = NULL; @@ -268,6 +227,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp, drm_ctx_priv_map_t request; drm_map_t *map = NULL; drm_map_list_t *r_list = NULL; + struct drm_ctx_sarea_list *ctx_sarea; if (copy_from_user(&request, (drm_ctx_priv_map_t __user *) arg, sizeof(request))) @@ -287,11 +247,15 @@ int drm_setsareactx(struct inode *inode, struct file *filp, map = r_list->map; if (!map) goto bad; - if (dev->max_context < 0) - goto bad; - if (request.ctx_id >= (unsigned)dev->max_context) + + mutex_lock(&dev->struct_mutex); + + ctx_sarea = idr_find(&dev->ctx_idr, request.ctx_id); + if (!ctx_sarea) { goto bad; - dev->context_sareas[request.ctx_id] = map; + } + + ctx_sarea->map = map; mutex_unlock(&dev->struct_mutex); return 0; } |