summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2014-06-27 06:45:02 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:10:20 -0400
commite2638d73fd56f9a93c44839ebd61d6ba58c40dd8 (patch)
tree00dae636bb2d2db72066f9af4b741670095f4e35
parent2c15c3265bbcd88baf119f33f16c5a54d3d3f5a7 (diff)
gpu: nvgpu: Wait for idle via FIFO registers
Wait for engine idle via FIFO's engine status instead of submitting WFI to channel. Submitting WFI and waiting is not robust, and wait might invoke debug dump which cannot be done while powering down. Bug 1499214 Change-Id: I4d52e8558e1a862ad4292036594d81ebfbd5f36b Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/432151 Reviewed-by: Sachin Nikam <snikam@nvidia.com> Tested-by: Sachin Nikam <snikam@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c23
-rw-r--r--drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c2
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.c35
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.h1
4 files changed, 42 insertions, 19 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index 33681c2a..b4d9c785 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -1948,29 +1948,14 @@ int gk20a_channel_suspend(struct gk20a *g)
1948 struct fifo_gk20a *f = &g->fifo; 1948 struct fifo_gk20a *f = &g->fifo;
1949 u32 chid; 1949 u32 chid;
1950 bool channels_in_use = false; 1950 bool channels_in_use = false;
1951 struct device *d = dev_from_gk20a(g);
1952 int err; 1951 int err;
1953 1952
1954 gk20a_dbg_fn(""); 1953 gk20a_dbg_fn("");
1955 1954
1956 /* idle the engine by submitting WFI on non-KEPLER_C channel */ 1955 /* wait for engine idle */
1957 for (chid = 0; chid < f->num_channels; chid++) { 1956 err = gk20a_fifo_wait_engine_idle(g);
1958 struct channel_gk20a *c = &f->channel[chid]; 1957 if (err)
1959 if (c->in_use && c->obj_class != KEPLER_C && !c->has_timedout) { 1958 return err;
1960 err = gk20a_channel_submit_wfi(c);
1961 if (err) {
1962 gk20a_err(d, "cannot idle channel %d\n",
1963 chid);
1964 return err;
1965 }
1966
1967 if (c->sync)
1968 c->sync->wait_cpu(c->sync,
1969 &c->last_submit.post_fence,
1970 500000);
1971 break;
1972 }
1973 }
1974 1959
1975 for (chid = 0; chid < f->num_channels; chid++) { 1960 for (chid = 0; chid < f->num_channels; chid++) {
1976 if (f->channel[chid].in_use) { 1961 if (f->channel[chid].in_use) {
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
index 8cb1d0a5..fb15b3da 100644
--- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
@@ -633,6 +633,8 @@ static int dbg_set_powergate(struct dbg_session_gk20a *dbg_s,
633 break; 633 break;
634 } 634 }
635 635
636 gk20a_dbg(gpu_dbg_fn|gpu_dbg_gpu_dbg, "%s powergate mode = %d done",
637 dev_name(dbg_s->dev), powermode);
636 return err; 638 return err;
637} 639}
638 640
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
index 52c0627d..daf40d9c 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
@@ -1955,6 +1955,41 @@ bool gk20a_fifo_mmu_fault_pending(struct gk20a *g)
1955 return false; 1955 return false;
1956} 1956}
1957 1957
1958int gk20a_fifo_wait_engine_idle(struct gk20a *g)
1959{
1960 unsigned long end_jiffies = jiffies +
1961 msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
1962 unsigned long delay = GR_IDLE_CHECK_DEFAULT;
1963 int ret = -ETIMEDOUT;
1964 u32 i;
1965 struct device *d = dev_from_gk20a(g);
1966
1967 gk20a_dbg_fn("");
1968
1969 for (i = 0; i < fifo_engine_status__size_1_v(); i++) {
1970 do {
1971 u32 status = gk20a_readl(g, fifo_engine_status_r(i));
1972 if (!fifo_engine_status_engine_v(status)) {
1973 ret = 0;
1974 break;
1975 }
1976
1977 usleep_range(delay, delay * 2);
1978 delay = min_t(unsigned long,
1979 delay << 1, GR_IDLE_CHECK_MAX);
1980 } while (time_before(jiffies, end_jiffies) ||
1981 !tegra_platform_is_silicon());
1982 if (ret) {
1983 gk20a_err(d, "cannot idle engine %u\n", i);
1984 break;
1985 }
1986 }
1987
1988 gk20a_dbg_fn("done");
1989
1990 return ret;
1991}
1992
1958void gk20a_init_fifo(struct gpu_ops *gops) 1993void gk20a_init_fifo(struct gpu_ops *gops)
1959{ 1994{
1960 gk20a_init_channel(gops); 1995 gk20a_init_channel(gops);
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
index 6e6907c1..e738b152 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
@@ -169,4 +169,5 @@ void gk20a_init_fifo(struct gpu_ops *gops);
169 169
170void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g, 170void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g,
171 unsigned long fault_id); 171 unsigned long fault_id);
172int gk20a_fifo_wait_engine_idle(struct gk20a *g);
172#endif /*__GR_GK20A_H__*/ 173#endif /*__GR_GK20A_H__*/