summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShridhar Rasal <srasal@nvidia.com>2014-06-29 09:17:52 +0530
committerWinnie Hsu <whsu@nvidia.com>2014-10-17 10:56:12 -0700
commit83296fee29da1a2e6973157aa9f9d913071657bc (patch)
tree2f8a0bddb311b3f4be131b6e9d4fdd35dad423e5
parent8ea724b67e4366615059a83dfe28d3f49c48d25f (diff)
video: tegra: host: revise channel refcnt API's
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>
-rw-r--r--drivers/video/tegra/host/bus_client.c7
-rw-r--r--drivers/video/tegra/host/host1x/host1x_channel.c6
-rw-r--r--drivers/video/tegra/host/nvhost_channel.c20
-rw-r--r--drivers/video/tegra/host/nvhost_channel.h3
-rw-r--r--drivers/video/tegra/host/nvhost_intr.c2
5 files changed, 18 insertions, 20 deletions
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index 819f0cee59c8..634384329992 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -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;
diff --git a/drivers/video/tegra/host/host1x/host1x_channel.c b/drivers/video/tegra/host/host1x/host1x_channel.c
index 46f319ea83f6..5b2b4998af92 100644
--- a/drivers/video/tegra/host/host1x/host1x_channel.c
+++ b/drivers/video/tegra/host/host1x/host1x_channel.c
@@ -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;
}
diff --git a/drivers/video/tegra/host/nvhost_channel.c b/drivers/video/tegra/host/nvhost_channel.c
index 3e7455509f96..9f0ca9e1268e 100644
--- a/drivers/video/tegra/host/nvhost_channel.c
+++ b/drivers/video/tegra/host/nvhost_channel.c
@@ -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)
diff --git a/drivers/video/tegra/host/nvhost_channel.h b/drivers/video/tegra/host/nvhost_channel.h
index 9f165a380f4a..84643a28aca8 100644
--- a/drivers/video/tegra/host/nvhost_channel.h
+++ b/drivers/video/tegra/host/nvhost_channel.h
@@ -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,
diff --git a/drivers/video/tegra/host/nvhost_intr.c b/drivers/video/tegra/host/nvhost_intr.c
index 18b714c7e482..b856f26cb5f8 100644
--- a/drivers/video/tegra/host/nvhost_intr.c
+++ b/drivers/video/tegra/host/nvhost_intr.c
@@ -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);
}