summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorKerwin Wan <kerwinw@nvidia.com>2014-04-11 11:24:10 +0800
committerMandar Padmawar <mpadmawar@nvidia.com>2014-04-22 05:05:40 -0700
commit6b61fc032d590f91fc34023f9db65389d82a7ba7 (patch)
tree7e406bce02801dfaffb461b256a4907a19ead925 /drivers/gpu
parente367a606177c846eaaaad39242a82ba382a1f5e5 (diff)
gpu: nvgpu: gk20a: check the return value of gk20a_channel_busy
gk20a_channel_busy is called to host gpu so that gk20a can be accessed. But it may return error like if gpu fails to be powered on. Always check the return value of gk20a_channel_busy to avoid illegal access to gk20a. Bug 1488409 Change-Id: Ie22da9e436ee5ea711003530419f546a73791b73 Signed-off-by: Kerwin Wan <kerwinw@nvidia.com> Reviewed-on: http://git-master/r/395180 (cherry picked from commit 95ef5ebb95cb7ea048f83dd2945b1c14a1d20261) Reviewed-on: http://git-master/r/398693 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c80
-rw-r--r--drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c4
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c6
3 files changed, 77 insertions, 13 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index 4cce72603481..8f850abac886 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -687,10 +687,16 @@ int gk20a_channel_release(struct inode *inode, struct file *filp)
{
struct channel_gk20a *ch = (struct channel_gk20a *)filp->private_data;
struct gk20a *g = ch->g;
+ int err;
trace_gk20a_channel_release(dev_name(&g->dev->dev));
- gk20a_channel_busy(ch->g->dev);
+ err = gk20a_channel_busy(ch->g->dev);
+ if (err) {
+ gk20a_err(dev_from_gk20a(g), "failed to release channel %d",
+ ch->hw_chid);
+ return err;
+ }
gk20a_free_channel(ch, true);
gk20a_channel_idle(ch->g->dev);
@@ -1412,7 +1418,7 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
{
struct gk20a *g = c->g;
struct device *d = dev_from_gk20a(g);
- u32 err = 0;
+ int err = 0;
int i;
struct priv_cmd_entry *wait_cmd = NULL;
struct priv_cmd_entry *incr_cmd = NULL;
@@ -1443,7 +1449,11 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
gk20a_dbg_info("channel %d", c->hw_chid);
/* gk20a_channel_update releases this ref. */
- gk20a_channel_busy(g->dev);
+ err = gk20a_channel_busy(g->dev);
+ if (err) {
+ gk20a_err(d, "failed to host gk20a to submit gpfifo");
+ return err;
+ }
trace_gk20a_channel_submit_gpfifo(c->g->dev->name,
c->hw_chid,
@@ -2019,19 +2029,37 @@ long gk20a_channel_ioctl(struct file *filp,
case NVHOST_IOCTL_CHANNEL_SET_NVMAP_FD:
break;
case NVHOST_IOCTL_CHANNEL_ALLOC_OBJ_CTX:
- gk20a_channel_busy(dev);
+ err = gk20a_channel_busy(dev);
+ if (err) {
+ dev_err(&dev->dev,
+ "%s: failed to host gk20a for ioctl cmd: 0x%x",
+ __func__, cmd);
+ return err;
+ }
err = gk20a_alloc_obj_ctx(ch,
(struct nvhost_alloc_obj_ctx_args *)buf);
gk20a_channel_idle(dev);
break;
case NVHOST_IOCTL_CHANNEL_FREE_OBJ_CTX:
- gk20a_channel_busy(dev);
+ err = gk20a_channel_busy(dev);
+ if (err) {
+ dev_err(&dev->dev,
+ "%s: failed to host gk20a for ioctl cmd: 0x%x",
+ __func__, cmd);
+ return err;
+ }
err = gk20a_free_obj_ctx(ch,
(struct nvhost_free_obj_ctx_args *)buf);
gk20a_channel_idle(dev);
break;
case NVHOST_IOCTL_CHANNEL_ALLOC_GPFIFO:
- gk20a_channel_busy(dev);
+ err = gk20a_channel_busy(dev);
+ if (err) {
+ dev_err(&dev->dev,
+ "%s: failed to host gk20a for ioctl cmd: 0x%x",
+ __func__, cmd);
+ return err;
+ }
err = gk20a_alloc_channel_gpfifo(ch,
(struct nvhost_alloc_gpfifo_args *)buf);
gk20a_channel_idle(dev);
@@ -2041,26 +2069,50 @@ long gk20a_channel_ioctl(struct file *filp,
(struct nvhost_submit_gpfifo_args *)buf);
break;
case NVHOST_IOCTL_CHANNEL_WAIT:
- gk20a_channel_busy(dev);
+ err = gk20a_channel_busy(dev);
+ if (err) {
+ dev_err(&dev->dev,
+ "%s: failed to host gk20a for ioctl cmd: 0x%x",
+ __func__, cmd);
+ return err;
+ }
err = gk20a_channel_wait(ch,
(struct nvhost_wait_args *)buf);
gk20a_channel_idle(dev);
break;
case NVHOST_IOCTL_CHANNEL_ZCULL_BIND:
- gk20a_channel_busy(dev);
+ err = gk20a_channel_busy(dev);
+ if (err) {
+ dev_err(&dev->dev,
+ "%s: failed to host gk20a for ioctl cmd: 0x%x",
+ __func__, cmd);
+ return err;
+ }
err = gk20a_channel_zcull_bind(ch,
(struct nvhost_zcull_bind_args *)buf);
gk20a_channel_idle(dev);
break;
case NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER:
- gk20a_channel_busy(dev);
+ err = gk20a_channel_busy(dev);
+ if (err) {
+ dev_err(&dev->dev,
+ "%s: failed to host gk20a for ioctl cmd: 0x%x",
+ __func__, cmd);
+ return err;
+ }
err = gk20a_init_error_notifier(ch,
(struct nvhost_set_error_notifier *)buf);
gk20a_channel_idle(dev);
break;
#ifdef CONFIG_GK20A_CYCLE_STATS
case NVHOST_IOCTL_CHANNEL_CYCLE_STATS:
- gk20a_channel_busy(dev);
+ err = gk20a_channel_busy(dev);
+ if (err) {
+ dev_err(&dev->dev,
+ "%s: failed to host gk20a for ioctl cmd: 0x%x",
+ __func__, cmd);
+ return err;
+ }
err = gk20a_channel_cycle_stats(ch,
(struct nvhost_cycle_stats_args *)buf);
gk20a_channel_idle(dev);
@@ -2093,7 +2145,13 @@ long gk20a_channel_ioctl(struct file *filp,
ch->has_timedout;
break;
case NVHOST_IOCTL_CHANNEL_SET_PRIORITY:
- gk20a_channel_busy(dev);
+ err = gk20a_channel_busy(dev);
+ if (err) {
+ dev_err(&dev->dev,
+ "%s: failed to host gk20a for ioctl cmd: 0x%x",
+ __func__, cmd);
+ return err;
+ }
gk20a_channel_set_priority(ch,
((struct nvhost_set_priority_args *)buf)->priority);
gk20a_channel_idle(dev);
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
index da7d733e3fd0..bc5dc4c1f048 100644
--- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
@@ -555,7 +555,9 @@ static int dbg_set_powergate(struct dbg_session_gk20a *dbg_s,
gk20a_dbg(gpu_dbg_gpu_dbg | gpu_dbg_fn, "module busy");
gk20a_busy(g->dev);
- gk20a_channel_busy(dbg_s->pdev);
+ err = gk20a_channel_busy(dbg_s->pdev);
+ if (err)
+ return -EPERM;
g->ops.clock_gating.slcg_gr_load_gating_prod(g,
false);
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c
index f6b43f506bd0..14629fbeecaf 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c
@@ -268,6 +268,7 @@ static ssize_t elpg_enable_store(struct device *device,
struct platform_device *ndev = to_platform_device(device);
struct gk20a *g = get_gk20a(ndev);
unsigned long val = 0;
+ int err;
if (kstrtoul(buf, 10, &val) < 0)
return -EINVAL;
@@ -276,7 +277,10 @@ static ssize_t elpg_enable_store(struct device *device,
* Since elpg is refcounted, we should not unnecessarily call
* enable/disable if it is already so.
*/
- gk20a_channel_busy(g->dev);
+ err = gk20a_channel_busy(g->dev);
+ if (err)
+ return -EAGAIN;
+
if (val && !g->elpg_enabled) {
g->elpg_enabled = true;
gk20a_pmu_enable_elpg(g);