aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_object.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-09-01 01:24:37 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-09-24 02:23:34 -0400
commiteb9bcbdc45369105bc004a82c7bed60655aae926 (patch)
treecd5202c0e963342610eae7f2b1b63d3fcf30a35b /drivers/gpu/drm/nouveau/nouveau_object.c
parentdac790080467eb12f1049ddca1c101eb0dcc9f0c (diff)
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/gpu/drm/nouveau/nouveau_object.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_object.c33
1 files changed, 11 insertions, 22 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 198c2514f893..02a0151b0738 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,
90 NV_DEBUG(dev, "gpuobj %p\n", gpuobj); 90 NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
91 gpuobj->dev = dev; 91 gpuobj->dev = dev;
92 gpuobj->flags = flags; 92 gpuobj->flags = flags;
93 gpuobj->refcount = 1; 93 kref_init(&gpuobj->refcount);
94 gpuobj->size = size; 94 gpuobj->size = size;
95 95
96 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); 96 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
@@ -198,25 +198,15 @@ void
198nouveau_gpuobj_late_takedown(struct drm_device *dev) 198nouveau_gpuobj_late_takedown(struct drm_device *dev)
199{ 199{
200 struct drm_nouveau_private *dev_priv = dev->dev_private; 200 struct drm_nouveau_private *dev_priv = dev->dev_private;
201 struct nouveau_gpuobj *gpuobj = NULL;
202 struct list_head *entry, *tmp;
203
204 NV_DEBUG(dev, "\n");
205
206 list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) {
207 gpuobj = list_entry(entry, struct nouveau_gpuobj, list);
208 201
209 NV_ERROR(dev, "gpuobj %p still exists at takedown, refs=%d\n", 202 BUG_ON(!list_empty(&dev_priv->gpuobj_list));
210 gpuobj, gpuobj->refcount);
211
212 gpuobj->refcount = 1;
213 nouveau_gpuobj_ref(NULL, &gpuobj);
214 }
215} 203}
216 204
217static int 205static void
218nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj) 206nouveau_gpuobj_del(struct kref *ref)
219{ 207{
208 struct nouveau_gpuobj *gpuobj =
209 container_of(ref, struct nouveau_gpuobj, refcount);
220 struct drm_device *dev = gpuobj->dev; 210 struct drm_device *dev = gpuobj->dev;
221 struct drm_nouveau_private *dev_priv = dev->dev_private; 211 struct drm_nouveau_private *dev_priv = dev->dev_private;
222 struct nouveau_engine *engine = &dev_priv->engine; 212 struct nouveau_engine *engine = &dev_priv->engine;
@@ -242,17 +232,16 @@ nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj)
242 list_del(&gpuobj->list); 232 list_del(&gpuobj->list);
243 233
244 kfree(gpuobj); 234 kfree(gpuobj);
245 return 0;
246} 235}
247 236
248void 237void
249nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr) 238nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr)
250{ 239{
251 if (ref) 240 if (ref)
252 ref->refcount++; 241 kref_get(&ref->refcount);
253 242
254 if (*ptr && --(*ptr)->refcount == 0) 243 if (*ptr)
255 nouveau_gpuobj_del(*ptr); 244 kref_put(&(*ptr)->refcount, nouveau_gpuobj_del);
256 245
257 *ptr = ref; 246 *ptr = ref;
258} 247}
@@ -275,7 +264,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
275 NV_DEBUG(dev, "gpuobj %p\n", gpuobj); 264 NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
276 gpuobj->dev = dev; 265 gpuobj->dev = dev;
277 gpuobj->flags = flags; 266 gpuobj->flags = flags;
278 gpuobj->refcount = 1; 267 kref_init(&gpuobj->refcount);
279 gpuobj->size = size; 268 gpuobj->size = size;
280 gpuobj->pinst = pinst; 269 gpuobj->pinst = pinst;
281 gpuobj->cinst = 0xdeadbeef; 270 gpuobj->cinst = 0xdeadbeef;
@@ -561,7 +550,7 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
561 gpuobj->dev = chan->dev; 550 gpuobj->dev = chan->dev;
562 gpuobj->engine = NVOBJ_ENGINE_SW; 551 gpuobj->engine = NVOBJ_ENGINE_SW;
563 gpuobj->class = class; 552 gpuobj->class = class;
564 gpuobj->refcount = 1; 553 kref_init(&gpuobj->refcount);
565 gpuobj->cinst = 0x40; 554 gpuobj->cinst = 0x40;
566 555
567 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); 556 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);