]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: host: add lock for ch open
authorShridhar Rasal <srasal@nvidia.com>
Thu, 8 May 2014 04:47:23 +0000 (10:17 +0530)
committerMandar Padmawar <mpadmawar@nvidia.com>
Fri, 23 May 2014 08:57:35 +0000 (01:57 -0700)
There is race in channel open/release call,
to avoid that add channel lock in channel ops callbacks.

Bug 1503232

Change-Id: I7c27d43f55af7cf88cd8c9027897d57790481bcd
(cherry picked from commit ea59410b46e0553196201091857ed33d93049e2d)

Signed-off-by: Shridhar Rasal <srasal@nvidia.com>
Change-Id: I52a6109270efb87449bde5f4b5e5d38c5f8e5c31
Reviewed-on: http://git-master/r/412526
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
drivers/video/tegra/host/bus_client.c

index d3f2f7e6ea4a8eb4cf30010bdfef765466ac9aab..819f0cee59c8f202c1cbe7d26c6cc0c74b5465d4 100644 (file)
@@ -54,6 +54,8 @@
 #include "nvhost_hwctx.h"
 #include "nvhost_sync.h"
 
+DEFINE_MUTEX(channel_lock);
+
 static int validate_reg(struct platform_device *ndev, u32 offset, int count)
 {
        int err = 0;
@@ -173,6 +175,11 @@ static int nvhost_channelrelease(struct inode *inode, struct file *filp)
 {
        struct nvhost_channel_userctx *priv = filp->private_data;
 
+       mutex_lock(&channel_lock);
+       if (!priv->ch || !priv->ch->dev) {
+               mutex_unlock(&channel_lock);
+               return 0;
+       }
        trace_nvhost_channel_release(dev_name(&priv->ch->dev->dev));
 
        filp->private_data = NULL;
@@ -194,6 +201,7 @@ static int nvhost_channelrelease(struct inode *inode, struct file *filp)
        if (priv->job)
                nvhost_job_put(priv->job);
 
+       mutex_unlock(&channel_lock);
        nvhost_putchannel(priv->ch);
        kfree(priv);
        return 0;
@@ -227,6 +235,11 @@ static int __nvhost_channelopen(struct inode *inode,
                        return -EBUSY;
        }
 
+       mutex_lock(&channel_lock);
+       if (!ch || !ch->dev) {
+               mutex_unlock(&channel_lock);
+               return -EINVAL;
+       }
        trace_nvhost_channel_open(dev_name(&ch->dev->dev));
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -261,12 +274,14 @@ static int __nvhost_channelopen(struct inode *inode,
        priv->timeout_debug_dump = true;
        if (!tegra_platform_is_silicon())
                priv->timeout = 0;
+       mutex_unlock(&channel_lock);
        return 0;
 fail_priv:
        nvhost_module_remove_client(ch->dev, priv);
 fail_add_client:
        kfree(priv);
 fail:
+       mutex_unlock(&channel_lock);
        nvhost_channelrelease(inode, filp);
        return -ENOMEM;
 }