Skip to content

Commit

Permalink
drm: convert drm context code to use Linux idr
Browse files Browse the repository at this point in the history
This converts the drm context allocator to an idr, using the new idr
interface features from Kristian.

Fixes from Kristian Hoegsberg <krh@redhat.com>

Signed-off-by: Dave Airlie <airlied@linux.ie>
  • Loading branch information
Dave Airlie committed Jul 17, 2007
1 parent 7608a86 commit 6296814
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 103 deletions.
5 changes: 3 additions & 2 deletions drivers/char/drm/drmP.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
#include <asm/pgalloc.h>
#include "drm.h"

#include <linux/idr.h>

#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
#define __OS_HAS_MTRR (defined(CONFIG_MTRR))

Expand Down Expand Up @@ -676,8 +678,7 @@ struct drm_device {
int ctx_count; /**< Number of context handles */
struct mutex ctxlist_mutex; /**< For ctxlist */

struct drm_map **context_sareas; /**< per-context SAREA's */
int max_context;
struct idr ctx_idr;

struct list_head vmalist; /**< List of vmas (for debugging) */
struct drm_lock_data lock; /**< Information on hardware lock */
Expand Down
131 changes: 30 additions & 101 deletions drivers/char/drm/drm_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -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(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);
}

/**
Expand All @@ -81,94 +69,40 @@ void drm_ctxbitmap_free(struct drm_device * 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(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) {
struct drm_map **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;
}

/**
* Context bitmap initialization.
*
* \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(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;
}

Expand All @@ -177,17 +111,13 @@ int drm_ctxbitmap_init(struct drm_device * 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(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);
}

Expand All @@ -206,7 +136,7 @@ void drm_ctxbitmap_cleanup(struct drm_device * 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,
Expand All @@ -223,13 +153,13 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
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;
Expand Down Expand Up @@ -258,7 +188,7 @@ 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)
Expand Down Expand Up @@ -288,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;
}
Expand Down

0 comments on commit 6296814

Please sign in to comment.