Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e05d7eae authored by Ben Skeggs's avatar Ben Skeggs
Browse files

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

parent eb9bcbdc
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -514,11 +514,13 @@ struct drm_nouveau_private {

	void __iomem *mmio;

	spinlock_t ramin_lock;
	void __iomem *ramin;
	u32 ramin_size;
	u32 ramin_base;
	bool ramin_available;
	spinlock_t ramin_lock;
	struct drm_mm ramin_heap;
	struct list_head gpuobj_list;

	struct nouveau_bo *vga_ram;

@@ -592,10 +594,6 @@ struct drm_nouveau_private {
	struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
	int vm_vram_pt_nr;

	struct drm_mm ramin_heap;

	struct list_head gpuobj_list;

	struct nvbios vbios;

	struct nv04_mode_state mode_reg;
+24 −4
Original line number Diff line number Diff line
@@ -93,7 +93,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
	kref_init(&gpuobj->refcount);
	gpuobj->size = size;

	spin_lock(&dev_priv->ramin_lock);
	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
	spin_unlock(&dev_priv->ramin_lock);

	if (chan) {
		NV_DEBUG(dev, "channel heap\n");
@@ -117,9 +119,22 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
		}

		/* try and get aperture space */
		ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0);
		if (ramin)
			ramin = drm_mm_get_block(ramin, size, align);
		do {
			if (drm_mm_pre_get(&dev_priv->ramin_heap))
				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 */
		if (!ramin && dev_priv->card_type < NV_50) {
@@ -226,10 +241,11 @@ nouveau_gpuobj_del(struct kref *ref)
	if (gpuobj->im_backing)
		engine->instmem.clear(dev, gpuobj);

	spin_lock(&dev_priv->ramin_lock);
	if (gpuobj->im_pramin)
		drm_mm_put_block(gpuobj->im_pramin);

	list_del(&gpuobj->list);
	spin_unlock(&dev_priv->ramin_lock);

	kfree(gpuobj);
}
@@ -276,7 +292,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
		dev_priv->engine.instmem.flush(dev);
	}

	spin_lock(&dev_priv->ramin_lock);
	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
	spin_unlock(&dev_priv->ramin_lock);
	*pgpuobj = gpuobj;
	return 0;
}
@@ -553,7 +571,9 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
	kref_init(&gpuobj->refcount);
	gpuobj->cinst = 0x40;

	spin_lock(&dev_priv->ramin_lock);
	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
	spin_unlock(&dev_priv->ramin_lock);
	*gpuobj_ret = gpuobj;
	return 0;
}