Commit e05d7eae authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau: protect gpuobj list + global instmem heap with spinlock

Reviewed-by: default avatarFrancisco Jerez <currojerez@riseup.net>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent eb9bcbdc
...@@ -514,11 +514,13 @@ struct drm_nouveau_private { ...@@ -514,11 +514,13 @@ struct drm_nouveau_private {
void __iomem *mmio; void __iomem *mmio;
spinlock_t ramin_lock;
void __iomem *ramin; void __iomem *ramin;
u32 ramin_size; u32 ramin_size;
u32 ramin_base; u32 ramin_base;
bool ramin_available; bool ramin_available;
spinlock_t ramin_lock; struct drm_mm ramin_heap;
struct list_head gpuobj_list;
struct nouveau_bo *vga_ram; struct nouveau_bo *vga_ram;
...@@ -592,10 +594,6 @@ struct drm_nouveau_private { ...@@ -592,10 +594,6 @@ struct drm_nouveau_private {
struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
int vm_vram_pt_nr; int vm_vram_pt_nr;
struct drm_mm ramin_heap;
struct list_head gpuobj_list;
struct nvbios vbios; struct nvbios vbios;
struct nv04_mode_state mode_reg; struct nv04_mode_state mode_reg;
......
...@@ -93,7 +93,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, ...@@ -93,7 +93,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
kref_init(&gpuobj->refcount); kref_init(&gpuobj->refcount);
gpuobj->size = size; gpuobj->size = size;
spin_lock(&dev_priv->ramin_lock);
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
spin_unlock(&dev_priv->ramin_lock);
if (chan) { if (chan) {
NV_DEBUG(dev, "channel heap\n"); NV_DEBUG(dev, "channel heap\n");
...@@ -117,9 +119,22 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, ...@@ -117,9 +119,22 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
} }
/* try and get aperture space */ /* try and get aperture space */
ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); do {
if (ramin) if (drm_mm_pre_get(&dev_priv->ramin_heap))
ramin = drm_mm_get_block(ramin, size, align); return -ENOMEM;
spin_lock(&dev_priv->ramin_lock);
ramin = drm_mm_search_free(&dev_priv->ramin_heap, size,
align, 0);
if (ramin == NULL) {
spin_unlock(&dev_priv->ramin_lock);
nouveau_gpuobj_ref(NULL, &gpuobj);
return ret;
}
ramin = drm_mm_get_block_atomic(ramin, size, align);
spin_unlock(&dev_priv->ramin_lock);
} while (ramin == NULL);
/* on nv50 it's ok to fail, we have a fallback path */ /* on nv50 it's ok to fail, we have a fallback path */
if (!ramin && dev_priv->card_type < NV_50) { if (!ramin && dev_priv->card_type < NV_50) {
...@@ -226,10 +241,11 @@ nouveau_gpuobj_del(struct kref *ref) ...@@ -226,10 +241,11 @@ nouveau_gpuobj_del(struct kref *ref)
if (gpuobj->im_backing) if (gpuobj->im_backing)
engine->instmem.clear(dev, gpuobj); engine->instmem.clear(dev, gpuobj);
spin_lock(&dev_priv->ramin_lock);
if (gpuobj->im_pramin) if (gpuobj->im_pramin)
drm_mm_put_block(gpuobj->im_pramin); drm_mm_put_block(gpuobj->im_pramin);
list_del(&gpuobj->list); list_del(&gpuobj->list);
spin_unlock(&dev_priv->ramin_lock);
kfree(gpuobj); kfree(gpuobj);
} }
...@@ -276,7 +292,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst, ...@@ -276,7 +292,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
dev_priv->engine.instmem.flush(dev); dev_priv->engine.instmem.flush(dev);
} }
spin_lock(&dev_priv->ramin_lock);
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
spin_unlock(&dev_priv->ramin_lock);
*pgpuobj = gpuobj; *pgpuobj = gpuobj;
return 0; return 0;
} }
...@@ -553,7 +571,9 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, ...@@ -553,7 +571,9 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
kref_init(&gpuobj->refcount); kref_init(&gpuobj->refcount);
gpuobj->cinst = 0x40; gpuobj->cinst = 0x40;
spin_lock(&dev_priv->ramin_lock);
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
spin_unlock(&dev_priv->ramin_lock);
*gpuobj_ret = gpuobj; *gpuobj_ret = gpuobj;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment