diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2014-04-23 05:31:25 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:09:43 -0400 |
commit | b1538c34167c01cefb6308d7209978fa1e39b28e (patch) | |
tree | d7b4315176b556966151219a821f9ee9cb7ca6ad | |
parent | eea79aaa60087174adf7e6876ac089cb4734ebaf (diff) |
gpu: nvgpu: gk20a: add syncpt null checks
On channel_finish() path, we first check if last submit was
WFI and in that case we do not submit new WFI but just wait
on old syncpt fence.
But it is possible that sync resource is already freed from
another path (channel_suspend())
Hence add a NULL check there to prevent Null pointer
exception.
Also, in channel_free() path, move syncpt free API after
channel_unbind() since we logically free the syncpt after
unbinding the channel.
Bug 1305024
Change-Id: Icc2fc83f004310560fc459527e1d37730428ec2d
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/400233
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Shridhar Rasal <srasal@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index d52e3f7e..344223ae 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -659,11 +659,6 @@ void gk20a_free_channel(struct channel_gk20a *ch, bool finish) | |||
659 | 659 | ||
660 | channel_gk20a_free_priv_cmdbuf(ch); | 660 | channel_gk20a_free_priv_cmdbuf(ch); |
661 | 661 | ||
662 | if (ch->sync) { | ||
663 | ch->sync->destroy(ch->sync); | ||
664 | ch->sync = NULL; | ||
665 | } | ||
666 | |||
667 | /* release channel binding to the as_share */ | 662 | /* release channel binding to the as_share */ |
668 | gk20a_as_release_share(ch_vm->as_share); | 663 | gk20a_as_release_share(ch_vm->as_share); |
669 | 664 | ||
@@ -673,6 +668,11 @@ unbind: | |||
673 | 668 | ||
674 | ch->vpr = false; | 669 | ch->vpr = false; |
675 | ch->vm = NULL; | 670 | ch->vm = NULL; |
671 | |||
672 | if (ch->sync) { | ||
673 | ch->sync->destroy(ch->sync); | ||
674 | ch->sync = NULL; | ||
675 | } | ||
676 | WARN_ON(ch->sync); | 676 | WARN_ON(ch->sync); |
677 | 677 | ||
678 | /* unlink all debug sessions */ | 678 | /* unlink all debug sessions */ |
@@ -1697,12 +1697,15 @@ int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout) | |||
1697 | gk20a_dbg_fn("waiting for channel to finish thresh:%d", | 1697 | gk20a_dbg_fn("waiting for channel to finish thresh:%d", |
1698 | ch->last_submit_fence.thresh); | 1698 | ch->last_submit_fence.thresh); |
1699 | 1699 | ||
1700 | err = ch->sync->wait_cpu(ch->sync, &ch->last_submit_fence, timeout); | 1700 | if (ch->sync) { |
1701 | if (WARN_ON(err)) | 1701 | err = ch->sync->wait_cpu(ch->sync, &ch->last_submit_fence, |
1702 | dev_warn(dev_from_gk20a(ch->g), | 1702 | timeout); |
1703 | "timed out waiting for gk20a channel to finish"); | 1703 | if (WARN_ON(err)) |
1704 | else | 1704 | dev_warn(dev_from_gk20a(ch->g), |
1705 | ch->cmds_pending = false; | 1705 | "timed out waiting for gk20a channel to finish"); |
1706 | else | ||
1707 | ch->cmds_pending = false; | ||
1708 | } | ||
1706 | 1709 | ||
1707 | return err; | 1710 | return err; |
1708 | } | 1711 | } |
@@ -1903,8 +1906,9 @@ int gk20a_channel_suspend(struct gk20a *g) | |||
1903 | return err; | 1906 | return err; |
1904 | } | 1907 | } |
1905 | 1908 | ||
1906 | c->sync->wait_cpu(c->sync, &c->last_submit_fence, | 1909 | if (c->sync) |
1907 | 500000); | 1910 | c->sync->wait_cpu(c->sync, |
1911 | &c->last_submit_fence, 500000); | ||
1908 | break; | 1912 | break; |
1909 | } | 1913 | } |
1910 | } | 1914 | } |