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

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

drm/nouveau: fix gpuobj refcount to use atomics

parent dac79008
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ enum nouveau_flags {
#define NVOBJ_FLAG_ZERO_FREE		(1 << 2)
struct nouveau_gpuobj {
	struct drm_device *dev;
	struct kref refcount;
	struct list_head list;

	struct drm_mm_node *im_pramin;
@@ -145,7 +146,6 @@ struct nouveau_gpuobj {
	int im_bound;

	uint32_t flags;
	int refcount;

	u32 size;
	u32 pinst;
+11 −22
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
	NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
	gpuobj->dev = dev;
	gpuobj->flags = flags;
	gpuobj->refcount = 1;
	kref_init(&gpuobj->refcount);
	gpuobj->size = size;

	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
@@ -198,25 +198,15 @@ void
nouveau_gpuobj_late_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpuobj *gpuobj = NULL;
	struct list_head *entry, *tmp;

	NV_DEBUG(dev, "\n");

	list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) {
		gpuobj = list_entry(entry, struct nouveau_gpuobj, list);

		NV_ERROR(dev, "gpuobj %p still exists at takedown, refs=%d\n",
			 gpuobj, gpuobj->refcount);

		gpuobj->refcount = 1;
		nouveau_gpuobj_ref(NULL, &gpuobj);
	}
	BUG_ON(!list_empty(&dev_priv->gpuobj_list));
}

static int
nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj)
static void
nouveau_gpuobj_del(struct kref *ref)
{
	struct nouveau_gpuobj *gpuobj =
		container_of(ref, struct nouveau_gpuobj, refcount);
	struct drm_device *dev = gpuobj->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_engine *engine = &dev_priv->engine;
@@ -242,17 +232,16 @@ nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj)
	list_del(&gpuobj->list);

	kfree(gpuobj);
	return 0;
}

void
nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr)
{
	if (ref)
		ref->refcount++;
		kref_get(&ref->refcount);

	if (*ptr && --(*ptr)->refcount == 0)
		nouveau_gpuobj_del(*ptr);
	if (*ptr)
		kref_put(&(*ptr)->refcount, nouveau_gpuobj_del);

	*ptr = ref;
}
@@ -275,7 +264,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
	NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
	gpuobj->dev = dev;
	gpuobj->flags = flags;
	gpuobj->refcount = 1;
	kref_init(&gpuobj->refcount);
	gpuobj->size  = size;
	gpuobj->pinst = pinst;
	gpuobj->cinst = 0xdeadbeef;
@@ -561,7 +550,7 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
	gpuobj->dev = chan->dev;
	gpuobj->engine = NVOBJ_ENGINE_SW;
	gpuobj->class = class;
	gpuobj->refcount = 1;
	kref_init(&gpuobj->refcount);
	gpuobj->cinst = 0x40;

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