summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2016-08-03 16:04:38 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2016-09-15 15:23:37 -0400
commiteee2744d497213a503de927cbbfe179753f5e370 (patch)
treefd4570dfa75578c7227e00e653113b8765789e72 /drivers
parent33665060728693c28ed5222a0d9004e261c63e82 (diff)
gpu: nvgpu: When powering down, abort if not idle
When trying to power down GPU the engine might be still busy. In this case delay power down by returning -EBUSY from gk20a_pm_runtime_suspend(). Bug 200224907 Change-Id: Ibad74c090add24a185bc1a7a02df367af9b95ced Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/1213042 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c6
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.c16
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.h1
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c10
4 files changed, 24 insertions, 9 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index b4c132ce..085caec5 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -2789,16 +2789,10 @@ int gk20a_channel_suspend(struct gk20a *g)
2789 struct fifo_gk20a *f = &g->fifo; 2789 struct fifo_gk20a *f = &g->fifo;
2790 u32 chid; 2790 u32 chid;
2791 bool channels_in_use = false; 2791 bool channels_in_use = false;
2792 int err;
2793 u32 active_runlist_ids = 0; 2792 u32 active_runlist_ids = 0;
2794 2793
2795 gk20a_dbg_fn(""); 2794 gk20a_dbg_fn("");
2796 2795
2797 /* wait for engine idle */
2798 err = g->ops.fifo.wait_engine_idle(g);
2799 if (err)
2800 return err;
2801
2802 for (chid = 0; chid < f->num_channels; chid++) { 2796 for (chid = 0; chid < f->num_channels; chid++) {
2803 struct channel_gk20a *ch = &f->channel[chid]; 2797 struct channel_gk20a *ch = &f->channel[chid];
2804 if (gk20a_channel_get(ch)) { 2798 if (gk20a_channel_get(ch)) {
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
index ff052400..2e38c4b6 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
@@ -3016,6 +3016,19 @@ bool gk20a_fifo_mmu_fault_pending(struct gk20a *g)
3016 return false; 3016 return false;
3017} 3017}
3018 3018
3019bool gk20a_fifo_is_engine_busy(struct gk20a *g)
3020{
3021 int i;
3022
3023 for (i = 0; i < fifo_engine_status__size_1_v(); i++) {
3024 u32 status = gk20a_readl(g, fifo_engine_status_r(i));
3025 if (fifo_engine_status_engine_v(status) ==
3026 fifo_engine_status_engine_busy_v())
3027 return true;
3028 }
3029 return false;
3030}
3031
3019int gk20a_fifo_wait_engine_idle(struct gk20a *g) 3032int gk20a_fifo_wait_engine_idle(struct gk20a *g)
3020{ 3033{
3021 unsigned long end_jiffies = jiffies + 3034 unsigned long end_jiffies = jiffies +
@@ -3023,7 +3036,6 @@ int gk20a_fifo_wait_engine_idle(struct gk20a *g)
3023 unsigned long delay = GR_IDLE_CHECK_DEFAULT; 3036 unsigned long delay = GR_IDLE_CHECK_DEFAULT;
3024 int ret = -ETIMEDOUT; 3037 int ret = -ETIMEDOUT;
3025 u32 i; 3038 u32 i;
3026 struct device *d = dev_from_gk20a(g);
3027 3039
3028 gk20a_dbg_fn(""); 3040 gk20a_dbg_fn("");
3029 3041
@@ -3041,7 +3053,7 @@ int gk20a_fifo_wait_engine_idle(struct gk20a *g)
3041 } while (time_before(jiffies, end_jiffies) || 3053 } while (time_before(jiffies, end_jiffies) ||
3042 !tegra_platform_is_silicon()); 3054 !tegra_platform_is_silicon());
3043 if (ret) { 3055 if (ret) {
3044 gk20a_err(d, "cannot idle engine %u\n", i); 3056 gk20a_dbg_info("cannot idle engine %u", i);
3045 break; 3057 break;
3046 } 3058 }
3047 } 3059 }
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
index 17c6dbf6..71a9d35d 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
@@ -206,6 +206,7 @@ void gk20a_init_fifo(struct gpu_ops *gops);
206void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g, 206void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g,
207 unsigned long fault_id); 207 unsigned long fault_id);
208int gk20a_fifo_wait_engine_idle(struct gk20a *g); 208int gk20a_fifo_wait_engine_idle(struct gk20a *g);
209bool gk20a_fifo_is_engine_busy(struct gk20a *g);
209u32 gk20a_fifo_engine_interrupt_mask(struct gk20a *g); 210u32 gk20a_fifo_engine_interrupt_mask(struct gk20a *g);
210u32 gk20a_fifo_get_pbdma_signature(struct gk20a *g); 211u32 gk20a_fifo_get_pbdma_signature(struct gk20a *g);
211u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g, 212u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g,
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index f6bb9445..10fa86a1 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -767,6 +767,10 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
767 if (!g->power_on) 767 if (!g->power_on)
768 goto done; 768 goto done;
769 769
770 if (gk20a_fifo_is_engine_busy(g)) {
771 mutex_unlock(&g->poweroff_lock);
772 return -EBUSY;
773 }
770 gk20a_scale_suspend(dev); 774 gk20a_scale_suspend(dev);
771 775
772 /* cancel any pending cde work */ 776 /* cancel any pending cde work */
@@ -1353,6 +1357,7 @@ static int gk20a_pm_runtime_suspend(struct device *dev)
1353fail_railgate: 1357fail_railgate:
1354 gk20a_pm_finalize_poweron(dev); 1358 gk20a_pm_finalize_poweron(dev);
1355fail: 1359fail:
1360 pm_runtime_mark_last_busy(dev);
1356 return err; 1361 return err;
1357} 1362}
1358 1363
@@ -1751,6 +1756,7 @@ int __gk20a_do_idle(struct device *dev, bool force_reset)
1751 msecs_to_jiffies(GK20A_WAIT_FOR_IDLE_MS); 1756 msecs_to_jiffies(GK20A_WAIT_FOR_IDLE_MS);
1752 int ref_cnt; 1757 int ref_cnt;
1753 bool is_railgated; 1758 bool is_railgated;
1759 int err = 0;
1754 1760
1755 /* acquire busy lock to block other busy() calls */ 1761 /* acquire busy lock to block other busy() calls */
1756 down_write(&g->busy_lock); 1762 down_write(&g->busy_lock);
@@ -1825,7 +1831,9 @@ int __gk20a_do_idle(struct device *dev, bool force_reset)
1825 */ 1831 */
1826 1832
1827 /* Save the GPU state */ 1833 /* Save the GPU state */
1828 gk20a_pm_prepare_poweroff(dev); 1834 err = gk20a_pm_prepare_poweroff(dev);
1835 if (err)
1836 goto fail_drop_usage_count;
1829 1837
1830 /* railgate GPU */ 1838 /* railgate GPU */
1831 platform->railgate(dev); 1839 platform->railgate(dev);