diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-09-01 15:24:37 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-09-24 16:23:34 +1000 |
commit | eb9bcbdc45369105bc004a82c7bed60655aae926 (patch) | |
tree | cd5202c0e963342610eae7f2b1b63d3fcf30a35b /drivers | |
parent | dac790080467eb12f1049ddca1c101eb0dcc9f0c (diff) | |
download | op-kernel-dev-eb9bcbdc45369105bc004a82c7bed60655aae926.zip op-kernel-dev-eb9bcbdc45369105bc004a82c7bed60655aae926.tar.gz |
drm/nouveau: fix gpuobj refcount to use atomics
Reviewed-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_object.c | 33 |
2 files changed, 12 insertions, 23 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 71e2708..8ee854a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -137,6 +137,7 @@ enum nouveau_flags { #define NVOBJ_FLAG_ZERO_FREE (1 << 2) struct nouveau_gpuobj { struct drm_device *dev; + struct kref refcount; struct list_head list; struct drm_mm_node *im_pramin; @@ -145,7 +146,6 @@ struct nouveau_gpuobj { int im_bound; uint32_t flags; - int refcount; u32 size; u32 pinst; diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index 198c251..02a0151 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c @@ -90,7 +90,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, NV_DEBUG(dev, "gpuobj %p\n", gpuobj); gpuobj->dev = dev; gpuobj->flags = flags; - gpuobj->refcount = 1; + kref_init(&gpuobj->refcount); gpuobj->size = size; list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); @@ -198,25 +198,15 @@ void nouveau_gpuobj_late_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = NULL; - struct list_head *entry, *tmp; - - NV_DEBUG(dev, "\n"); - - list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) { - gpuobj = list_entry(entry, struct nouveau_gpuobj, list); - NV_ERROR(dev, "gpuobj %p still exists at takedown, refs=%d\n", - gpuobj, gpuobj->refcount); - - gpuobj->refcount = 1; - nouveau_gpuobj_ref(NULL, &gpuobj); - } + BUG_ON(!list_empty(&dev_priv->gpuobj_list)); } -static int -nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj) +static void +nouveau_gpuobj_del(struct kref *ref) { + struct nouveau_gpuobj *gpuobj = + container_of(ref, struct nouveau_gpuobj, refcount); struct drm_device *dev = gpuobj->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; @@ -242,17 +232,16 @@ nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj) list_del(&gpuobj->list); kfree(gpuobj); - return 0; } void nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr) { if (ref) - ref->refcount++; + kref_get(&ref->refcount); - if (*ptr && --(*ptr)->refcount == 0) - nouveau_gpuobj_del(*ptr); + if (*ptr) + kref_put(&(*ptr)->refcount, nouveau_gpuobj_del); *ptr = ref; } @@ -275,7 +264,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst, NV_DEBUG(dev, "gpuobj %p\n", gpuobj); gpuobj->dev = dev; gpuobj->flags = flags; - gpuobj->refcount = 1; + kref_init(&gpuobj->refcount); gpuobj->size = size; gpuobj->pinst = pinst; gpuobj->cinst = 0xdeadbeef; @@ -561,7 +550,7 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, gpuobj->dev = chan->dev; gpuobj->engine = NVOBJ_ENGINE_SW; gpuobj->class = class; - gpuobj->refcount = 1; + kref_init(&gpuobj->refcount); gpuobj->cinst = 0x40; list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); |