diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-09-01 01:24:37 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-09-24 02:23:34 -0400 |
commit | eb9bcbdc45369105bc004a82c7bed60655aae926 (patch) | |
tree | cd5202c0e963342610eae7f2b1b63d3fcf30a35b /drivers/gpu/drm/nouveau/nouveau_object.c | |
parent | dac790080467eb12f1049ddca1c101eb0dcc9f0c (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.c | 33 |
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 | |||
198 | nouveau_gpuobj_late_takedown(struct drm_device *dev) | 198 | nouveau_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 | ||
217 | static int | 205 | static void |
218 | nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj) | 206 | nouveau_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 | ||
248 | void | 237 | void |
249 | nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr) | 238 | nouveau_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); |