From 0d67356de4e0c9e0d068ea9c16cf33df4fd13776 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 28 Aug 2006 16:36:37 +0200 Subject: Proper TTM dereferencing Initial buffer object creation. --- linux-core/drm_ttm.c | 56 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 15 deletions(-) (limited to 'linux-core/drm_ttm.c') diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index e76b41fb..cda3ec29 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -752,7 +752,6 @@ int drm_user_create_region(drm_device_t * dev, unsigned long start, int len, /* * dev->struct_mutex locked. */ - static void drm_ttm_object_remove(drm_device_t *dev, drm_ttm_object_t *object) { drm_map_list_t *list = &object->map_list; @@ -777,17 +776,24 @@ static void drm_ttm_object_remove(drm_device_t *dev, drm_ttm_object_t *object) drm_free(object, sizeof(*object), DRM_MEM_TTM); } + +void drm_ttm_object_deref_locked(drm_device_t *dev, drm_ttm_object_t *to) +{ + if (atomic_dec_and_test(&to->usage)) { + drm_ttm_object_remove(dev, to); + } +} + + /* * dev->struct_mutex locked. */ -static void drm_ttm_user_object_remove(drm_file_t *priv, drm_user_object_t *base) +static void drm_ttm_user_deref_locked(drm_file_t *priv, drm_user_object_t *base) { - drm_ttm_object_t *object; - drm_device_t *dev = priv->head->dev; - - object = drm_user_object_entry(base, drm_ttm_object_t, base); - if (atomic_dec_and_test(&object->usage)) - drm_ttm_object_remove(dev, object); + DRM_ERROR("User deref ttm\n"); + drm_ttm_object_deref_locked(priv->head->dev, + drm_user_object_entry(base, drm_ttm_object_t, + base)); } @@ -840,16 +846,33 @@ int drm_ttm_object_create(drm_device_t *dev, unsigned long size, } list->user_token = list->hash.key; - object->base.remove = drm_ttm_user_object_remove; - object->base.type = drm_ttm_type; - object->base.ref_struct_locked = NULL; - object->base.unref = NULL; atomic_set(&object->usage, 1); *ttm_object = object; return 0; } +drm_ttm_object_t *drm_lookup_ttm_object(drm_file_t *priv, uint32_t handle, + int check_owner) +{ + drm_user_object_t *uo; + drm_ttm_object_t *to; + + uo = drm_lookup_user_object(priv, handle); + + if (!uo || (uo->type != drm_ttm_type)) + return NULL; + + if (check_owner && priv != uo->owner) { + if (!drm_lookup_ref_object(priv, uo, _DRM_REF_USE)) + return NULL; + } + + to = drm_user_object_entry(uo, drm_ttm_object_t, base); + atomic_inc(&to->usage); + return to; +} + int drm_ttm_ioctl(DRM_IOCTL_ARGS) { @@ -878,6 +901,10 @@ int drm_ttm_ioctl(DRM_IOCTL_ARGS) mutex_unlock(&dev->struct_mutex); return ret; } + entry->base.remove = drm_ttm_user_deref_locked; + entry->base.type = drm_ttm_type; + entry->base.ref_struct_locked = NULL; + entry->base.unref = NULL; atomic_inc(&entry->usage); break; case drm_ttm_reference: @@ -885,8 +912,7 @@ int drm_ttm_ioctl(DRM_IOCTL_ARGS) if (ret) return ret; mutex_lock(&dev->struct_mutex); - uo = drm_lookup_user_object(priv, arg.handle); - entry = drm_user_object_entry(uo, drm_ttm_object_t, base); + entry = drm_lookup_ttm_object(priv, arg.handle , 0); break; case drm_ttm_unreference: return drm_user_object_unref(priv, arg.handle, drm_ttm_type); @@ -904,7 +930,7 @@ int drm_ttm_ioctl(DRM_IOCTL_ARGS) arg.handle = entry->base.hash.key; arg.user_token = entry->map_list.user_token; arg.size = drm_u64(entry->map_list.map->size); - atomic_dec(&entry->usage); + drm_ttm_object_deref_locked(dev, entry); mutex_unlock(&dev->struct_mutex); DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); -- cgit v1.2.3