summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-05-01 20:12:39 -0700
committerKeith Packard <keithp@keithp.com>2008-05-01 20:12:39 -0700
commitabc896638fdcd8ccb457ad7b43dbe7ad229ba501 (patch)
tree157a7961a250a9e443ef4a1e9a89320ecab8990b /linux-core
parentc10695bb7ab44494badc21c822eac3140cf4e117 (diff)
Use krefs for refcounting.
krefs are way easier than a custom-coded spinlock+int combo.
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drmP.h12
-rw-r--r--linux-core/drm_gem.c31
2 files changed, 24 insertions, 19 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 2ed17b81..0df9f19b 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -54,6 +54,7 @@
#include <linux/smp_lock.h> /* For (un)lock_kernel */
#include <linux/dma-mapping.h>
#include <linux/mm.h>
+#include <linux/kref.h>
#include <linux/pagemap.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
#include <linux/mutex.h>
@@ -614,20 +615,21 @@ struct drm_ati_pcigart_info {
* DRM for its buffer objects.
*/
struct drm_gem_object {
+ /** Reference count of this object */
+ struct kref refcount;
+
+ /** Related drm device */
+ struct drm_device *dev;
+
/** File representing the shmem storage */
struct file *filp;
- spinlock_t lock;
-
/**
* Size of the object, in bytes. Immutable over the object's
* lifetime.
*/
size_t size;
- /** Reference count of this object, protected by object_lock */
- int refcount;
-
void *driver_private;
};
diff --git a/linux-core/drm_gem.c b/linux-core/drm_gem.c
index ee3dbe47..d39585e9 100644
--- a/linux-core/drm_gem.c
+++ b/linux-core/drm_gem.c
@@ -73,13 +73,14 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
+ obj->dev = dev;
obj->filp = shmem_file_setup("drm mm object", size, 0);
if (IS_ERR(obj->filp)) {
kfree(obj);
return NULL;
}
- obj->refcount = 1;
+ kref_init (&obj->refcount);
obj->size = size;
if (dev->driver->gem_init_object != NULL &&
@@ -352,27 +353,29 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
void
drm_gem_object_reference(struct drm_device *dev, struct drm_gem_object *obj)
{
- spin_lock(&obj->lock);
- obj->refcount++;
- spin_unlock(&obj->lock);
+ kref_get(&obj->refcount);
}
EXPORT_SYMBOL(drm_gem_object_reference);
+static void
+drm_gem_object_free (struct kref *kref)
+{
+ struct drm_gem_object *obj = (struct drm_gem_object *) kref;
+ struct drm_device *dev = obj->dev;
+
+ if (dev->driver->gem_free_object != NULL)
+ dev->driver->gem_free_object(dev, obj);
+
+ fput(obj->filp);
+ kfree(obj);
+}
+
void
drm_gem_object_unreference(struct drm_device *dev, struct drm_gem_object *obj)
{
if (obj == NULL)
return;
- spin_lock(&obj->lock);
- obj->refcount--;
- spin_unlock(&obj->lock);
- if (obj->refcount == 0) {
- if (dev->driver->gem_free_object != NULL)
- dev->driver->gem_free_object(dev, obj);
-
- fput(obj->filp);
- kfree(obj);
- }
+ kref_put (&obj->refcount, drm_gem_object_free);
}
EXPORT_SYMBOL(drm_gem_object_unreference);