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:38 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-09-24 02:23:41 -0400
commite05d7eaeba57921abad0ef564b0875e225171de8 (patch)
treed352380a0e22e0da802068562716fb50246c7c9a /drivers/gpu/drm/nouveau/nouveau_object.c
parenteb9bcbdc45369105bc004a82c7bed60655aae926 (diff)
drm/nouveau: protect gpuobj list + global instmem heap with spinlock
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.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 02a0151b0738..37615a447a4a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -93,7 +93,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
93 kref_init(&gpuobj->refcount); 93 kref_init(&gpuobj->refcount);
94 gpuobj->size = size; 94 gpuobj->size = size;
95 95
96 spin_lock(&dev_priv->ramin_lock);
96 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); 97 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
98 spin_unlock(&dev_priv->ramin_lock);
97 99
98 if (chan) { 100 if (chan) {
99 NV_DEBUG(dev, "channel heap\n"); 101 NV_DEBUG(dev, "channel heap\n");
@@ -117,9 +119,22 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
117 } 119 }
118 120
119 /* try and get aperture space */ 121 /* try and get aperture space */
120 ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); 122 do {
121 if (ramin) 123 if (drm_mm_pre_get(&dev_priv->ramin_heap))
122 ramin = drm_mm_get_block(ramin, size, align); 124 return -ENOMEM;
125
126 spin_lock(&dev_priv->ramin_lock);
127 ramin = drm_mm_search_free(&dev_priv->ramin_heap, size,
128 align, 0);
129 if (ramin == NULL) {
130 spin_unlock(&dev_priv->ramin_lock);
131 nouveau_gpuobj_ref(NULL, &gpuobj);
132 return ret;
133 }
134
135 ramin = drm_mm_get_block_atomic(ramin, size, align);
136 spin_unlock(&dev_priv->ramin_lock);
137 } while (ramin == NULL);
123 138
124 /* on nv50 it's ok to fail, we have a fallback path */ 139 /* on nv50 it's ok to fail, we have a fallback path */
125 if (!ramin && dev_priv->card_type < NV_50) { 140 if (!ramin && dev_priv->card_type < NV_50) {
@@ -226,10 +241,11 @@ nouveau_gpuobj_del(struct kref *ref)
226 if (gpuobj->im_backing) 241 if (gpuobj->im_backing)
227 engine->instmem.clear(dev, gpuobj); 242 engine->instmem.clear(dev, gpuobj);
228 243
244 spin_lock(&dev_priv->ramin_lock);
229 if (gpuobj->im_pramin) 245 if (gpuobj->im_pramin)
230 drm_mm_put_block(gpuobj->im_pramin); 246 drm_mm_put_block(gpuobj->im_pramin);
231
232 list_del(&gpuobj->list); 247 list_del(&gpuobj->list);
248 spin_unlock(&dev_priv->ramin_lock);
233 249
234 kfree(gpuobj); 250 kfree(gpuobj);
235} 251}
@@ -276,7 +292,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
276 dev_priv->engine.instmem.flush(dev); 292 dev_priv->engine.instmem.flush(dev);
277 } 293 }
278 294
295 spin_lock(&dev_priv->ramin_lock);
279 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); 296 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
297 spin_unlock(&dev_priv->ramin_lock);
280 *pgpuobj = gpuobj; 298 *pgpuobj = gpuobj;
281 return 0; 299 return 0;
282} 300}
@@ -553,7 +571,9 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
553 kref_init(&gpuobj->refcount); 571 kref_init(&gpuobj->refcount);
554 gpuobj->cinst = 0x40; 572 gpuobj->cinst = 0x40;
555 573
574 spin_lock(&dev_priv->ramin_lock);
556 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); 575 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
576 spin_unlock(&dev_priv->ramin_lock);
557 *gpuobj_ret = gpuobj; 577 *gpuobj_ret = gpuobj;
558 return 0; 578 return 0;
559} 579}