diff options
author | Kerwin Wan <kerwinw@nvidia.com> | 2014-04-11 11:24:10 +0800 |
---|---|---|
committer | Mandar Padmawar <mpadmawar@nvidia.com> | 2014-04-22 05:05:40 -0700 |
commit | 6b61fc032d590f91fc34023f9db65389d82a7ba7 (patch) | |
tree | 7e406bce02801dfaffb461b256a4907a19ead925 /drivers/gpu | |
parent | e367a606177c846eaaaad39242a82ba382a1f5e5 (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.c | 80 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | 6 |
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); |