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 | |
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')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_object.c | 28 |
2 files changed, 27 insertions, 9 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 8ee854a4b3f5..0844f27651c0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -514,11 +514,13 @@ struct drm_nouveau_private { | |||
514 | 514 | ||
515 | void __iomem *mmio; | 515 | void __iomem *mmio; |
516 | 516 | ||
517 | spinlock_t ramin_lock; | ||
517 | void __iomem *ramin; | 518 | void __iomem *ramin; |
518 | u32 ramin_size; | 519 | u32 ramin_size; |
519 | u32 ramin_base; | 520 | u32 ramin_base; |
520 | bool ramin_available; | 521 | bool ramin_available; |
521 | spinlock_t ramin_lock; | 522 | struct drm_mm ramin_heap; |
523 | struct list_head gpuobj_list; | ||
522 | 524 | ||
523 | struct nouveau_bo *vga_ram; | 525 | struct nouveau_bo *vga_ram; |
524 | 526 | ||
@@ -592,10 +594,6 @@ struct drm_nouveau_private { | |||
592 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; | 594 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; |
593 | int vm_vram_pt_nr; | 595 | int vm_vram_pt_nr; |
594 | 596 | ||
595 | struct drm_mm ramin_heap; | ||
596 | |||
597 | struct list_head gpuobj_list; | ||
598 | |||
599 | struct nvbios vbios; | 597 | struct nvbios vbios; |
600 | 598 | ||
601 | struct nv04_mode_state mode_reg; | 599 | struct nv04_mode_state mode_reg; |
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 | } |