From 48e19c6c2857047a1d0f56d98bbe48dcd4726fcd Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Wed, 3 Sep 2014 18:40:28 +0530 Subject: gpu: nvgpu: add API to preempt TSG Add API gk20a_fifo_preempt_tsg() which takes ID of tsg and preempts it Bug 1514064 Bug 1470692 Change-Id: I1d52c1dd7a9aecc1314b0f223fe4eedecc033629 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/495583 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 93 +++++++++++++++++++++++++-------- drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | 1 + drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h | 8 +++ 3 files changed, 79 insertions(+), 23 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a') diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 230e1722..56ff4c87 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c @@ -1512,29 +1512,22 @@ void gk20a_fifo_nonstall_isr(struct gk20a *g) return; } -int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid) +static int __locked_fifo_preempt(struct gk20a *g, u32 id, bool is_tsg) { - struct fifo_gk20a *f = &g->fifo; + u32 delay = GR_IDLE_CHECK_DEFAULT; unsigned long end_jiffies = jiffies + msecs_to_jiffies(gk20a_get_gr_idle_timeout(g)); - u32 delay = GR_IDLE_CHECK_DEFAULT; u32 ret = 0; - u32 token = PMU_INVALID_MUTEX_OWNER_ID; - u32 mutex_ret = 0; - u32 i; - - gk20a_dbg_fn("%d", hw_chid); - - /* we have no idea which runlist we are using. lock all */ - for (i = 0; i < g->fifo.max_runlists; i++) - mutex_lock(&f->runlist_info[i].mutex); - - mutex_ret = pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); /* issue preempt */ - gk20a_writel(g, fifo_preempt_r(), - fifo_preempt_chid_f(hw_chid) | - fifo_preempt_type_channel_f()); + if (is_tsg) + gk20a_writel(g, fifo_preempt_r(), + fifo_preempt_id_f(id) | + fifo_preempt_type_tsg_f()); + else + gk20a_writel(g, fifo_preempt_r(), + fifo_preempt_chid_f(id) | + fifo_preempt_type_channel_f()); /* wait for preempt */ ret = -EBUSY; @@ -1551,16 +1544,70 @@ int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid) !tegra_platform_is_silicon()); if (ret) { - struct channel_gk20a *ch = &g->fifo.channel[hw_chid]; + if (is_tsg) { + /* TODO: recovery for TSG */ + gk20a_err(dev_from_gk20a(g), + "preempt TSG %d timeout\n", id); + } else { + struct channel_gk20a *ch = &g->fifo.channel[id]; - gk20a_err(dev_from_gk20a(g), "preempt channel %d timeout\n", - hw_chid); + gk20a_err(dev_from_gk20a(g), + "preempt channel %d timeout\n", id); - gk20a_set_error_notifier(ch, - NVHOST_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT); - gk20a_fifo_recover_ch(g, hw_chid, true); + gk20a_set_error_notifier(ch, + NVHOST_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT); + gk20a_fifo_recover_ch(g, id, true); + } } + return ret; +} + +int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid) +{ + struct fifo_gk20a *f = &g->fifo; + u32 ret = 0; + u32 token = PMU_INVALID_MUTEX_OWNER_ID; + u32 mutex_ret = 0; + u32 i; + + gk20a_dbg_fn("%d", hw_chid); + + /* we have no idea which runlist we are using. lock all */ + for (i = 0; i < g->fifo.max_runlists; i++) + mutex_lock(&f->runlist_info[i].mutex); + + mutex_ret = pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); + + ret = __locked_fifo_preempt(g, hw_chid, false); + + if (!mutex_ret) + pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); + + for (i = 0; i < g->fifo.max_runlists; i++) + mutex_unlock(&f->runlist_info[i].mutex); + + return ret; +} + +int gk20a_fifo_preempt_tsg(struct gk20a *g, u32 tsgid) +{ + struct fifo_gk20a *f = &g->fifo; + u32 ret = 0; + u32 token = PMU_INVALID_MUTEX_OWNER_ID; + u32 mutex_ret = 0; + u32 i; + + gk20a_dbg_fn("%d", tsgid); + + /* we have no idea which runlist we are using. lock all */ + for (i = 0; i < g->fifo.max_runlists; i++) + mutex_lock(&f->runlist_info[i].mutex); + + mutex_ret = pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); + + ret = __locked_fifo_preempt(g, tsgid, true); + if (!mutex_ret) pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h index bed8a361..04d22abb 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h @@ -146,6 +146,7 @@ void gk20a_fifo_isr(struct gk20a *g); void gk20a_fifo_nonstall_isr(struct gk20a *g); int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid); +int gk20a_fifo_preempt_tsg(struct gk20a *g, u32 tsgid); int gk20a_fifo_enable_engine_activity(struct gk20a *g, struct fifo_engine_info_gk20a *eng_info); diff --git a/drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h index 83e7d776..aa77d026 100644 --- a/drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h @@ -398,10 +398,18 @@ static inline u32 fifo_preempt_type_channel_f(void) { return 0x0; } +static inline u32 fifo_preempt_type_tsg_f(void) +{ + return 0x1000000; +} static inline u32 fifo_preempt_chid_f(u32 v) { return (v & 0xfff) << 0; } +static inline u32 fifo_preempt_id_f(u32 v) +{ + return (v & 0xfff) << 0; +} static inline u32 fifo_trigger_mmu_fault_r(u32 i) { return 0x00002a30 + i*4; -- cgit v1.2.2