diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-09-01 01:24:38 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-09-24 02:23:41 -0400 |
commit | e05d7eaeba57921abad0ef564b0875e225171de8 (patch) | |
tree | d352380a0e22e0da802068562716fb50246c7c9a /drivers/gpu/drm/nouveau/nouveau_object.c | |
parent | eb9bcbdc45369105bc004a82c7bed60655aae926 (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.c | 28 |
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 | } |