Skip to content

Commit

Permalink
drm/nouveau: fix gpuobj refcount to use atomics
Browse files Browse the repository at this point in the history
Reviewed-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Sep 24, 2010
1 parent dac7900 commit eb9bcbd
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 23 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -145,7 +146,6 @@ struct nouveau_gpuobj {
int im_bound;

uint32_t flags;
int refcount;

u32 size;
u32 pinst;
Expand Down
33 changes: 11 additions & 22 deletions drivers/gpu/drm/nouveau/nouveau_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit eb9bcbd

Please sign in to comment.