aboutsummaryrefslogtreecommitdiff
path: root/drivers/char/drm/drm_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm/drm_context.c')
-rw-r--r--drivers/char/drm/drm_context.c226
1 files changed, 77 insertions, 149 deletions
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index 83094c73da6..61ad986baa8 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -53,26 +53,14 @@
* \param ctx_handle context handle.
*
* Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::context_sareas, while holding the drm_device::struct_mutex
+ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
* lock.
*/
-void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
+void drm_ctxbitmap_free(struct drm_device * 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);
- return;
+ mutex_lock(&dev->struct_mutex);
+ idr_remove(&dev->ctx_idr, ctx_handle);
+ mutex_unlock(&dev->struct_mutex);
}
/**
@@ -81,62 +69,28 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
* \param dev DRM device.
* \return (non-negative) context handle on success or a negative number on failure.
*
- * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
- * drm_device::context_sareas to accommodate the new entry while holding the
+ * Allocate a new idr from drm_device::ctx_idr while holding the
* drm_device::struct_mutex lock.
*/
-static int drm_ctxbitmap_next(drm_device_t * dev)
+static int drm_ctxbitmap_next(struct drm_device * dev)
{
- int bit;
-
- if (!dev->ctx_bitmap)
- return -1;
+ int new_id;
+ int ret;
+again:
+ if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
+ DRM_ERROR("Out of memory expanding drawable idr\n");
+ 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, NULL,
+ DRM_RESERVED_CONTEXTS, &new_id);
+ if (ret == -EAGAIN) {
mutex_unlock(&dev->struct_mutex);
- return bit;
+ goto again;
}
mutex_unlock(&dev->struct_mutex);
- return -1;
+ return new_id;
}
/**
@@ -144,31 +98,11 @@ static int drm_ctxbitmap_next(drm_device_t * dev)
*
* \param dev DRM device.
*
- * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Initialise the drm_device::ctx_idr
*/
-int drm_ctxbitmap_init(drm_device_t * dev)
+int drm_ctxbitmap_init(struct drm_device * 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);
return 0;
}
@@ -177,17 +111,13 @@ int drm_ctxbitmap_init(drm_device_t * dev)
*
* \param dev DRM device.
*
- * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Free all idr members using drm_ctx_sarea_free helper function
+ * while holding the drm_device::struct_mutex lock.
*/
-void drm_ctxbitmap_cleanup(drm_device_t * dev)
+void drm_ctxbitmap_cleanup(struct drm_device * dev)
{
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);
+ idr_remove_all(&dev->ctx_idr);
mutex_unlock(&dev->struct_mutex);
}
@@ -206,34 +136,34 @@ void drm_ctxbitmap_cleanup(drm_device_t * dev)
* \param arg user argument pointing to a drm_ctx_priv_map structure.
* \return zero on success or a negative number on failure.
*
- * Gets the map from drm_device::context_sareas with the handle specified and
+ * Gets the map from drm_device::ctx_idr with the handle specified and
* returns its handle.
*/
int drm_getsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_priv_map_t __user *argp = (void __user *)arg;
- drm_ctx_priv_map_t request;
- drm_map_t *map;
- drm_map_list_t *_entry;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx_priv_map __user *argp = (void __user *)arg;
+ struct drm_ctx_priv_map request;
+ struct drm_map *map;
+ struct drm_map_list *_entry;
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) {
+
+ map = idr_find(&dev->ctx_idr, request.ctx_id);
+ if (!map) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
- map = dev->context_sareas[request.ctx_id];
mutex_unlock(&dev->struct_mutex);
request.handle = NULL;
- list_for_each_entry(_entry, &dev->maplist->head, head) {
+ list_for_each_entry(_entry, &dev->maplist, head) {
if (_entry->map == map) {
request.handle =
(void *)(unsigned long)_entry->user_token;
@@ -258,25 +188,24 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
* \return zero on success or a negative number on failure.
*
* Searches the mapping specified in \p arg and update the entry in
- * drm_device::context_sareas with it.
+ * drm_device::ctx_idr with it.
*/
int drm_setsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_priv_map_t request;
- drm_map_t *map = NULL;
- drm_map_list_t *r_list = NULL;
- struct list_head *list;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx_priv_map request;
+ struct drm_map *map = NULL;
+ struct drm_map_list *r_list = NULL;
if (copy_from_user(&request,
- (drm_ctx_priv_map_t __user *) arg, sizeof(request)))
+ (struct drm_ctx_priv_map __user *) arg,
+ sizeof(request)))
return -EFAULT;
mutex_lock(&dev->struct_mutex);
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map
&& r_list->user_token == (unsigned long)request.handle)
goto found;
@@ -289,11 +218,10 @@ 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)
+
+ if (IS_ERR(idr_replace(&dev->ctx_idr, map, request.ctx_id)))
goto bad;
- dev->context_sareas[request.ctx_id] = map;
+
mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -314,7 +242,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
*
* Attempt to set drm_device::context_flag.
*/
-static int drm_context_switch(drm_device_t * dev, int old, int new)
+static int drm_context_switch(struct drm_device * dev, int old, int new)
{
if (test_and_set_bit(0, &dev->context_flag)) {
DRM_ERROR("Reentering -- FIXME\n");
@@ -342,7 +270,7 @@ static int drm_context_switch(drm_device_t * dev, int old, int new)
* hardware lock is held, clears the drm_device::context_flag and wakes up
* drm_device::context_wait.
*/
-static int drm_context_switch_complete(drm_device_t * dev, int new)
+static int drm_context_switch_complete(struct drm_device * dev, int new)
{
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
dev->last_switch = jiffies;
@@ -372,9 +300,9 @@ static int drm_context_switch_complete(drm_device_t * dev, int new)
int drm_resctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_ctx_res_t res;
- drm_ctx_t __user *argp = (void __user *)arg;
- drm_ctx_t ctx;
+ struct drm_ctx_res res;
+ struct drm_ctx_res __user *argp = (void __user *)arg;
+ struct drm_ctx ctx;
int i;
if (copy_from_user(&res, argp, sizeof(res)))
@@ -409,11 +337,11 @@ int drm_resctx(struct inode *inode, struct file *filp,
int drm_addctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_list_t *ctx_entry;
- drm_ctx_t __user *argp = (void __user *)arg;
- drm_ctx_t ctx;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx_list *ctx_entry;
+ struct drm_ctx __user *argp = (void __user *)arg;
+ struct drm_ctx ctx;
if (copy_from_user(&ctx, argp, sizeof(ctx)))
return -EFAULT;
@@ -449,7 +377,7 @@ int drm_addctx(struct inode *inode, struct file *filp,
ctx_entry->tag = priv;
mutex_lock(&dev->ctxlist_mutex);
- list_add(&ctx_entry->head, &dev->ctxlist->head);
+ list_add(&ctx_entry->head, &dev->ctxlist);
++dev->ctx_count;
mutex_unlock(&dev->ctxlist_mutex);
@@ -477,8 +405,8 @@ int drm_modctx(struct inode *inode, struct file *filp,
int drm_getctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_ctx_t __user *argp = (void __user *)arg;
- drm_ctx_t ctx;
+ struct drm_ctx __user *argp = (void __user *)arg;
+ struct drm_ctx ctx;
if (copy_from_user(&ctx, argp, sizeof(ctx)))
return -EFAULT;
@@ -505,11 +433,11 @@ int drm_getctx(struct inode *inode, struct file *filp,
int drm_switchctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_t ctx;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx ctx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -530,11 +458,11 @@ int drm_switchctx(struct inode *inode, struct file *filp,
int drm_newctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_t ctx;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx ctx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -557,11 +485,11 @@ int drm_newctx(struct inode *inode, struct file *filp,
int drm_rmctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_t ctx;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx ctx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -575,10 +503,10 @@ int drm_rmctx(struct inode *inode, struct file *filp,
}
mutex_lock(&dev->ctxlist_mutex);
- if (!list_empty(&dev->ctxlist->head)) {
- drm_ctx_list_t *pos, *n;
+ if (!list_empty(&dev->ctxlist)) {
+ struct drm_ctx_list *pos, *n;
- list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+ list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
if (pos->handle == ctx.handle) {
list_del(&pos->head);
drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);