mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
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>
This commit is contained in:
committed by
Dan Willemsen
parent
2c15c3265b
commit
e2638d73fd
@@ -1948,29 +1948,14 @@ int gk20a_channel_suspend(struct gk20a *g)
|
|||||||
struct fifo_gk20a *f = &g->fifo;
|
struct fifo_gk20a *f = &g->fifo;
|
||||||
u32 chid;
|
u32 chid;
|
||||||
bool channels_in_use = false;
|
bool channels_in_use = false;
|
||||||
struct device *d = dev_from_gk20a(g);
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
gk20a_dbg_fn("");
|
gk20a_dbg_fn("");
|
||||||
|
|
||||||
/* idle the engine by submitting WFI on non-KEPLER_C channel */
|
/* wait for engine idle */
|
||||||
for (chid = 0; chid < f->num_channels; chid++) {
|
err = gk20a_fifo_wait_engine_idle(g);
|
||||||
struct channel_gk20a *c = &f->channel[chid];
|
if (err)
|
||||||
if (c->in_use && c->obj_class != KEPLER_C && !c->has_timedout) {
|
|
||||||
err = gk20a_channel_submit_wfi(c);
|
|
||||||
if (err) {
|
|
||||||
gk20a_err(d, "cannot idle channel %d\n",
|
|
||||||
chid);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
if (c->sync)
|
|
||||||
c->sync->wait_cpu(c->sync,
|
|
||||||
&c->last_submit.post_fence,
|
|
||||||
500000);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (chid = 0; chid < f->num_channels; chid++) {
|
for (chid = 0; chid < f->num_channels; chid++) {
|
||||||
if (f->channel[chid].in_use) {
|
if (f->channel[chid].in_use) {
|
||||||
|
|||||||
@@ -633,6 +633,8 @@ static int dbg_set_powergate(struct dbg_session_gk20a *dbg_s,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gk20a_dbg(gpu_dbg_fn|gpu_dbg_gpu_dbg, "%s powergate mode = %d done",
|
||||||
|
dev_name(dbg_s->dev), powermode);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1955,6 +1955,41 @@ bool gk20a_fifo_mmu_fault_pending(struct gk20a *g)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gk20a_fifo_wait_engine_idle(struct gk20a *g)
|
||||||
|
{
|
||||||
|
unsigned long end_jiffies = jiffies +
|
||||||
|
msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
|
||||||
|
unsigned long delay = GR_IDLE_CHECK_DEFAULT;
|
||||||
|
int ret = -ETIMEDOUT;
|
||||||
|
u32 i;
|
||||||
|
struct device *d = dev_from_gk20a(g);
|
||||||
|
|
||||||
|
gk20a_dbg_fn("");
|
||||||
|
|
||||||
|
for (i = 0; i < fifo_engine_status__size_1_v(); i++) {
|
||||||
|
do {
|
||||||
|
u32 status = gk20a_readl(g, fifo_engine_status_r(i));
|
||||||
|
if (!fifo_engine_status_engine_v(status)) {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep_range(delay, delay * 2);
|
||||||
|
delay = min_t(unsigned long,
|
||||||
|
delay << 1, GR_IDLE_CHECK_MAX);
|
||||||
|
} while (time_before(jiffies, end_jiffies) ||
|
||||||
|
!tegra_platform_is_silicon());
|
||||||
|
if (ret) {
|
||||||
|
gk20a_err(d, "cannot idle engine %u\n", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gk20a_dbg_fn("done");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void gk20a_init_fifo(struct gpu_ops *gops)
|
void gk20a_init_fifo(struct gpu_ops *gops)
|
||||||
{
|
{
|
||||||
gk20a_init_channel(gops);
|
gk20a_init_channel(gops);
|
||||||
|
|||||||
@@ -169,4 +169,5 @@ void gk20a_init_fifo(struct gpu_ops *gops);
|
|||||||
|
|
||||||
void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g,
|
void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g,
|
||||||
unsigned long fault_id);
|
unsigned long fault_id);
|
||||||
|
int gk20a_fifo_wait_engine_idle(struct gk20a *g);
|
||||||
#endif /*__GR_GK20A_H__*/
|
#endif /*__GR_GK20A_H__*/
|
||||||
|
|||||||
Reference in New Issue
Block a user