video: tegra: host: revise channel refcnt API's
Shridhar Rasal [Sun, 29 Jun 2014 03:47:52 +0000 (08:47 +0530)]
Use only one API to subtract channel refcnts.
To check unbanalaced channel refcnt add WARN_ON when count
goes below zero.
Print error number when channel unmap fails.

Bug 1526504

Change-Id: If88f028a44c9b796d8eaae4affcd0026758cfbe8
(cherry picked from commit f98ce1fc2066e2309af2ef7a52801abadbd40f00)
Signed-off-by: Shridhar Rasal <srasal@nvidia.com>
Reviewed-on: http://git-master/r/496479
Reviewed-on: http://git-master/r/538723
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Shreshtha Sahu <ssahu@nvidia.com>
Tested-by: Shreshtha Sahu <ssahu@nvidia.com>
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>

drivers/video/tegra/host/bus_client.c
drivers/video/tegra/host/host1x/host1x_channel.c
drivers/video/tegra/host/nvhost_channel.c
drivers/video/tegra/host/nvhost_channel.h
drivers/video/tegra/host/nvhost_intr.c

index 819f0ce..6343843 100644 (file)
@@ -202,7 +202,7 @@ static int nvhost_channelrelease(struct inode *inode, struct file *filp)
                nvhost_job_put(priv->job);
 
        mutex_unlock(&channel_lock);
-       nvhost_putchannel(priv->ch);
+       nvhost_putchannel(priv->ch, 1);
        kfree(priv);
        return 0;
 }
@@ -220,7 +220,8 @@ static int __nvhost_channelopen(struct inode *inode,
                                struct nvhost_device_data, cdev);
                ret = nvhost_channel_map(pdata, &ch);
                if (ret) {
-                       pr_err("%s: failed to map channel\n", __func__);
+                       pr_err("%s: failed to map channel, error: %d\n",
+                                       __func__, ret);
                        return ret;
                }
        } else {
@@ -244,7 +245,7 @@ static int __nvhost_channelopen(struct inode *inode,
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv) {
-               nvhost_putchannel(ch);
+               nvhost_putchannel(ch, 1);
                goto fail;
        }
        filp->private_data = priv;
index 46f319e..5b2b499 100644 (file)
@@ -318,7 +318,7 @@ static int host1x_channel_submit(struct nvhost_job *job)
        err = mutex_lock_interruptible(&ch->submitlock);
        if (err) {
                nvhost_module_idle_mult(ch->dev, job->num_syncpts);
-               nvhost_putchannel_mult(ch, job->num_syncpts);
+               nvhost_putchannel(ch, job->num_syncpts);
                goto error;
        }
 
@@ -326,7 +326,7 @@ static int host1x_channel_submit(struct nvhost_job *job)
                completed_waiters[i] = nvhost_intr_alloc_waiter();
                if (!completed_waiters[i]) {
                        nvhost_module_idle_mult(ch->dev, job->num_syncpts);
-                       nvhost_putchannel_mult(ch, job->num_syncpts);
+                       nvhost_putchannel(ch, job->num_syncpts);
                        mutex_unlock(&ch->submitlock);
                        err = -ENOMEM;
                        goto error;
@@ -342,7 +342,7 @@ static int host1x_channel_submit(struct nvhost_job *job)
        err = nvhost_cdma_begin(&ch->cdma, job);
        if (err) {
                nvhost_module_idle_mult(ch->dev, job->num_syncpts);
-               nvhost_putchannel_mult(ch, job->num_syncpts);
+               nvhost_putchannel(ch, job->num_syncpts);
                mutex_unlock(&ch->submitlock);
                goto error;
        }
index 3e74555..9f0ca9e 100644 (file)
@@ -125,7 +125,7 @@ int nvhost_channel_release(struct nvhost_device_data *pdata)
        for (i = 0; i < pdata->num_channels; i++) {
                ch = pdata->channels[i];
                if (ch && ch->dev)
-                       nvhost_putchannel(ch);
+                       nvhost_putchannel(ch, 1);
        }
        return 0;
 }
@@ -377,19 +377,17 @@ void nvhost_getchannel(struct nvhost_channel *ch)
        atomic_inc(&ch->refcount);
 }
 
-void nvhost_putchannel(struct nvhost_channel *ch)
+void nvhost_putchannel(struct nvhost_channel *ch, int cnt)
 {
-       if (!atomic_dec_if_positive(&ch->refcount))
-               nvhost_channel_unmap(ch);
-}
-
+       int ref;
 
-void nvhost_putchannel_mult(struct nvhost_channel *ch, int cnt)
-{
-       int i;
+       ref = atomic_sub_return(cnt, &ch->refcount);
 
-       for (i = 0; i < cnt; i++)
-               nvhost_putchannel(ch);
+       /* WARN on negative reference, with zero reference unmap channel*/
+       if (!ref)
+               nvhost_channel_unmap(ch);
+       else if (ref < 0)
+               WARN_ON(1);
 }
 
 int nvhost_channel_suspend(struct nvhost_channel *ch)
index 9f165a3..84643a2 100644 (file)
@@ -85,8 +85,7 @@ void nvhost_set_notifier(struct nvhost_channel *ch, __u32 error);
 void nvhost_free_error_notifiers(struct nvhost_channel *ch);
 
 void nvhost_getchannel(struct nvhost_channel *ch);
-void nvhost_putchannel(struct nvhost_channel *ch);
-void nvhost_putchannel_mult(struct nvhost_channel *ch, int cnt);
+void nvhost_putchannel(struct nvhost_channel *ch, int cnt);
 int nvhost_channel_suspend(struct nvhost_channel *ch);
 
 int nvhost_channel_read_reg(struct nvhost_channel *channel,
index 18b714c..b856f26 100644 (file)
@@ -175,7 +175,7 @@ static void action_submit_complete(struct nvhost_waitlist *waiter)
                        channel->cdma.med_prio_count,
                        channel->cdma.low_prio_count);
 
-       nvhost_putchannel_mult(channel, nr_completed);
+       nvhost_putchannel(channel, nr_completed);
 
 }