From ab403ac96fc7e95548107d361c8ae17ed2179c75 Mon Sep 17 00:00:00 2001
From: Ben Skeggs <bskeggs@redhat.com>
Date: Mon, 9 Sep 2013 15:26:07 +1000
Subject: [PATCH] drm/nv31/mpeg: remove need for separate refcnt on engine use

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
---
 .../gpu/drm/nouveau/core/engine/mpeg/nv31.c   | 39 ++++++++++---------
 .../gpu/drm/nouveau/core/engine/mpeg/nv31.h   |  1 -
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
index 77b630867010..7eb6d94c84e2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
@@ -137,18 +137,23 @@ nv31_mpeg_context_ctor(struct nouveau_object *parent,
 {
 	struct nv31_mpeg_priv *priv = (void *)engine;
 	struct nv31_mpeg_chan *chan;
+	unsigned long flags;
 	int ret;
 
-	if (!atomic_add_unless(&priv->refcount, 1, 1))
-		return -EBUSY;
-
 	ret = nouveau_object_create(parent, engine, oclass, 0, &chan);
 	*pobject = nv_object(chan);
 	if (ret)
 		return ret;
 
+	spin_lock_irqsave(&nv_engine(priv)->lock, flags);
+	if (priv->chan) {
+		spin_unlock_irqrestore(&nv_engine(priv)->lock, flags);
+		nouveau_object_destroy(&chan->base);
+		*pobject = NULL;
+		return -EBUSY;
+	}
 	priv->chan = chan;
-
+	spin_unlock_irqrestore(&nv_engine(priv)->lock, flags);
 	return 0;
 }
 
@@ -157,11 +162,12 @@ nv31_mpeg_context_dtor(struct nouveau_object *object)
 {
 	struct nv31_mpeg_priv *priv = (void *)object->engine;
 	struct nv31_mpeg_chan *chan = (void *)object;
+	unsigned long flags;
 
-	WARN_ON(priv->chan != chan);
+	spin_lock_irqsave(&nv_engine(priv)->lock, flags);
 	priv->chan = NULL;
+	spin_unlock_irqrestore(&nv_engine(priv)->lock, flags);
 	nouveau_object_destroy(&chan->base);
-	atomic_dec(&priv->refcount);
 }
 
 struct nouveau_oclass
@@ -193,20 +199,19 @@ nv31_mpeg_tile_prog(struct nouveau_engine *engine, int i)
 void
 nv31_mpeg_intr(struct nouveau_subdev *subdev)
 {
+	struct nv31_mpeg_priv *priv = (void *)subdev;
 	struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
 	struct nouveau_handle *handle;
-	struct nv31_mpeg_priv *priv = (void *)subdev;
-	struct nouveau_object *engctx = &priv->chan->base;
+	struct nouveau_object *engctx;
 	u32 stat = nv_rd32(priv, 0x00b100);
 	u32 type = nv_rd32(priv, 0x00b230);
 	u32 mthd = nv_rd32(priv, 0x00b234);
 	u32 data = nv_rd32(priv, 0x00b238);
 	u32 show = stat;
-	int chid = pfifo->chid(pfifo, engctx);
+	unsigned long flags;
 
-	if (engctx)
-		if (nouveau_object_inc(engctx))
-			engctx = NULL;
+	spin_lock_irqsave(&nv_engine(priv)->lock, flags);
+	engctx = nv_object(priv->chan);
 
 	if (stat & 0x01000000) {
 		/* happens on initial binding of the object */
@@ -227,14 +232,12 @@ nv31_mpeg_intr(struct nouveau_subdev *subdev)
 	nv_wr32(priv, 0x00b230, 0x00000001);
 
 	if (show) {
-		nv_error(priv,
-			 "ch %d [%s] 0x%08x 0x%08x 0x%08x 0x%08x\n",
-			 chid, nouveau_client_name(engctx), stat,
-			 type, mthd, data);
+		nv_error(priv, "ch %d [%s] 0x%08x 0x%08x 0x%08x 0x%08x\n",
+			 pfifo->chid(pfifo, engctx),
+			 nouveau_client_name(engctx), stat, type, mthd, data);
 	}
 
-	if (engctx)
-		WARN_ON(nouveau_object_dec(engctx, false));
+	spin_unlock_irqrestore(&nv_engine(priv)->lock, flags);
 }
 
 static int
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h
index 62d04e475315..d08629d0b6ad 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h
@@ -9,7 +9,6 @@ struct nv31_mpeg_chan {
 
 struct nv31_mpeg_priv {
 	struct nouveau_mpeg base;
-	atomic_t refcount;
 	struct nv31_mpeg_chan *chan;
 };
 
-- 
2.20.1