summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2017-05-11 16:12:03 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-05-26 06:34:08 -0400
commit726900b8433294fd89a6d730d2fec9de8e33afda (patch)
tree6d6aa5b6e07a792441e43b74ea273f85933eebe0 /drivers
parent0bb47c3675d2030545d40353931e2b8120541de4 (diff)
gpu: nvgpu: Split stalling interrupt handling
Split handling of stalling interrupt to Linux specific chip agnostic and OS independent chip specific parts. Linux specific chip independent part contains handler for ISR and passing the control to a bottom half. It uses the new MC HALs intr_stall (query interrupt status), intr_pause (pause interrupts) and intr_resume (resume interrupts). MC HAL isr_stall now returns void and gets called in thread context and thus remove isr_thread_stall and replace the implementation with isr_stall. JIRA NVGPU-26 Change-Id: I206f330f6fc4a1f4def47c5f986585ac4080216d Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/1480243 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/Makefile.nvgpu1
-rw-r--r--drivers/gpu/nvgpu/common/linux/intr.c58
-rw-r--r--drivers/gpu/nvgpu/common/linux/intr.h20
-rw-r--r--drivers/gpu/nvgpu/common/linux/module.c5
-rw-r--r--drivers/gpu/nvgpu/common/linux/pci.c7
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h6
-rw-r--r--drivers/gpu/nvgpu/gk20a/mc_gk20a.c76
-rw-r--r--drivers/gpu/nvgpu/gk20a/mc_gk20a.h5
-rw-r--r--drivers/gpu/nvgpu/gm20b/mc_gm20b.c4
-rw-r--r--drivers/gpu/nvgpu/gp10b/mc_gp10b.c49
-rw-r--r--drivers/gpu/nvgpu/gp10b/mc_gp10b.h5
11 files changed, 147 insertions, 89 deletions
diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu
index c2d98559..109d1e4d 100644
--- a/drivers/gpu/nvgpu/Makefile.nvgpu
+++ b/drivers/gpu/nvgpu/Makefile.nvgpu
@@ -41,6 +41,7 @@ nvgpu-y := \
41 common/linux/firmware.o \ 41 common/linux/firmware.o \
42 common/linux/thread.o \ 42 common/linux/thread.o \
43 common/linux/vm.o \ 43 common/linux/vm.o \
44 common/linux/intr.o \
44 common/mm/nvgpu_allocator.o \ 45 common/mm/nvgpu_allocator.o \
45 common/mm/bitmap_allocator.o \ 46 common/mm/bitmap_allocator.o \
46 common/mm/buddy_allocator.o \ 47 common/mm/buddy_allocator.o \
diff --git a/drivers/gpu/nvgpu/common/linux/intr.c b/drivers/gpu/nvgpu/common/linux/intr.c
new file mode 100644
index 00000000..77e44dd9
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/intr.c
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#include <trace/events/gk20a.h>
15
16#include "gk20a/gk20a.h"
17
18#include <nvgpu/atomic.h>
19
20irqreturn_t nvgpu_intr_stall(struct gk20a *g)
21{
22 u32 mc_intr_0;
23
24 trace_mc_gk20a_intr_stall(g->name);
25
26 if (!g->power_on)
27 return IRQ_NONE;
28
29 /* not from gpu when sharing irq with others */
30 mc_intr_0 = g->ops.mc.intr_stall(g);
31 if (unlikely(!mc_intr_0))
32 return IRQ_NONE;
33
34 g->ops.mc.intr_stall_pause(g);
35
36 atomic_inc(&g->hw_irq_stall_count);
37
38 trace_mc_gk20a_intr_stall_done(g->name);
39
40 return IRQ_WAKE_THREAD;
41}
42
43irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g)
44{
45 gk20a_dbg(gpu_dbg_intr, "interrupt thread launched");
46
47 trace_mc_gk20a_intr_thread_stall(g->name);
48
49 g->ops.mc.isr_stall(g);
50 g->ops.mc.intr_stall_resume(g);
51
52 wake_up_all(&g->sw_irq_stall_last_handled_wq);
53
54 trace_mc_gk20a_intr_thread_stall_done(g->name);
55
56 return IRQ_HANDLED;
57}
58
diff --git a/drivers/gpu/nvgpu/common/linux/intr.h b/drivers/gpu/nvgpu/common/linux/intr.h
new file mode 100644
index 00000000..243d8f51
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/intr.h
@@ -0,0 +1,20 @@
1/*
2 * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#ifndef __NVGPU_LINUX_INTR_H__
15#define __NVGPU_LINUX_INTR_H__
16struct gk20a;
17
18irqreturn_t nvgpu_intr_stall(struct gk20a *g);
19irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g);
20#endif
diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c
index ab99bef0..5e8af065 100644
--- a/drivers/gpu/nvgpu/common/linux/module.c
+++ b/drivers/gpu/nvgpu/common/linux/module.c
@@ -36,6 +36,7 @@
36#include "gk20a/ctxsw_trace_gk20a.h" 36#include "gk20a/ctxsw_trace_gk20a.h"
37#include "pci.h" 37#include "pci.h"
38#include "module.h" 38#include "module.h"
39#include "intr.h"
39#ifdef CONFIG_TEGRA_19x_GPU 40#ifdef CONFIG_TEGRA_19x_GPU
40#include "nvgpu_gpuid_t19x.h" 41#include "nvgpu_gpuid_t19x.h"
41#endif 42#endif
@@ -482,7 +483,7 @@ static irqreturn_t gk20a_intr_isr_stall(int irq, void *dev_id)
482{ 483{
483 struct gk20a *g = dev_id; 484 struct gk20a *g = dev_id;
484 485
485 return g->ops.mc.isr_stall(g); 486 return nvgpu_intr_stall(g);
486} 487}
487 488
488static irqreturn_t gk20a_intr_isr_nonstall(int irq, void *dev_id) 489static irqreturn_t gk20a_intr_isr_nonstall(int irq, void *dev_id)
@@ -496,7 +497,7 @@ static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id)
496{ 497{
497 struct gk20a *g = dev_id; 498 struct gk20a *g = dev_id;
498 499
499 return g->ops.mc.isr_thread_stall(g); 500 return nvgpu_intr_thread_stall(g);
500} 501}
501 502
502void gk20a_remove_support(struct gk20a *g) 503void gk20a_remove_support(struct gk20a *g)
diff --git a/drivers/gpu/nvgpu/common/linux/pci.c b/drivers/gpu/nvgpu/common/linux/pci.c
index d729d273..767e9d47 100644
--- a/drivers/gpu/nvgpu/common/linux/pci.c
+++ b/drivers/gpu/nvgpu/common/linux/pci.c
@@ -25,6 +25,7 @@
25#include "gk20a/platform_gk20a.h" 25#include "gk20a/platform_gk20a.h"
26#include "clk/clk.h" 26#include "clk/clk.h"
27#include "module.h" 27#include "module.h"
28#include "intr.h"
28 29
29#include "pci.h" 30#include "pci.h"
30 31
@@ -232,7 +233,7 @@ static irqreturn_t nvgpu_pci_isr(int irq, void *dev_id)
232 irqreturn_t ret_stall; 233 irqreturn_t ret_stall;
233 irqreturn_t ret_nonstall; 234 irqreturn_t ret_nonstall;
234 235
235 ret_stall = g->ops.mc.isr_stall(g); 236 ret_stall = nvgpu_intr_stall(g);
236 ret_nonstall = g->ops.mc.isr_nonstall(g); 237 ret_nonstall = g->ops.mc.isr_nonstall(g);
237 238
238#if defined(CONFIG_PCI_MSI) 239#if defined(CONFIG_PCI_MSI)
@@ -248,9 +249,7 @@ static irqreturn_t nvgpu_pci_intr_thread(int irq, void *dev_id)
248{ 249{
249 struct gk20a *g = dev_id; 250 struct gk20a *g = dev_id;
250 251
251 g->ops.mc.isr_thread_stall(g); 252 return nvgpu_intr_thread_stall(g);
252
253 return IRQ_HANDLED;
254} 253}
255 254
256static int nvgpu_pci_init_support(struct pci_dev *pdev) 255static int nvgpu_pci_init_support(struct pci_dev *pdev)
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index ceadbae2..29ac4763 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -812,13 +812,15 @@ struct gpu_ops {
812 void (*intr_enable)(struct gk20a *g); 812 void (*intr_enable)(struct gk20a *g);
813 void (*intr_unit_config)(struct gk20a *g, 813 void (*intr_unit_config)(struct gk20a *g,
814 bool enable, bool is_stalling, u32 unit); 814 bool enable, bool is_stalling, u32 unit);
815 irqreturn_t (*isr_stall)(struct gk20a *g); 815 void (*isr_stall)(struct gk20a *g);
816 irqreturn_t (*isr_nonstall)(struct gk20a *g); 816 irqreturn_t (*isr_nonstall)(struct gk20a *g);
817 irqreturn_t (*isr_thread_stall)(struct gk20a *g);
818 void (*isr_thread_nonstall)(struct gk20a *g, u32 intr); 817 void (*isr_thread_nonstall)(struct gk20a *g, u32 intr);
819 void (*isr_nonstall_cb)(struct work_struct *work); 818 void (*isr_nonstall_cb)(struct work_struct *work);
820 bool (*is_intr_hub_pending)(struct gk20a *g, u32 mc_intr); 819 bool (*is_intr_hub_pending)(struct gk20a *g, u32 mc_intr);
821 u32 intr_mask_restore[4]; 820 u32 intr_mask_restore[4];
821 u32 (*intr_stall)(struct gk20a *g);
822 void (*intr_stall_pause)(struct gk20a *g);
823 void (*intr_stall_resume)(struct gk20a *g);
822 void (*enable)(struct gk20a *g, u32 units); 824 void (*enable)(struct gk20a *g, u32 units);
823 void (*disable)(struct gk20a *g, u32 units); 825 void (*disable)(struct gk20a *g, u32 units);
824 void (*reset)(struct gk20a *g, u32 units); 826 void (*reset)(struct gk20a *g, u32 units);
diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c
index ca7189cc..bc11b14d 100644
--- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * GK20A Master Control 2 * GK20A Master Control
3 * 3 *
4 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -41,33 +41,6 @@ void mc_gk20a_nonstall_cb(struct work_struct *work)
41 } while (atomic_read(&g->nonstall_ops) != 0); 41 } while (atomic_read(&g->nonstall_ops) != 0);
42} 42}
43 43
44irqreturn_t mc_gk20a_isr_stall(struct gk20a *g)
45{
46 u32 mc_intr_0;
47
48 trace_mc_gk20a_intr_stall(g->name);
49
50 if (!g->power_on)
51 return IRQ_NONE;
52
53 /* not from gpu when sharing irq with others */
54 mc_intr_0 = gk20a_readl(g, mc_intr_0_r());
55 if (unlikely(!mc_intr_0))
56 return IRQ_NONE;
57
58 gk20a_writel(g, mc_intr_en_0_r(),
59 mc_intr_en_0_inta_disabled_f());
60
61 /* flush previous write */
62 gk20a_readl(g, mc_intr_en_0_r());
63
64 atomic_inc(&g->hw_irq_stall_count);
65
66 trace_mc_gk20a_intr_stall_done(g->name);
67
68 return IRQ_WAKE_THREAD;
69}
70
71irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g) 44irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g)
72{ 45{
73 u32 mc_intr_1; 46 u32 mc_intr_1;
@@ -106,7 +79,7 @@ irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g)
106 return IRQ_HANDLED; 79 return IRQ_HANDLED;
107} 80}
108 81
109irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) 82void mc_gk20a_isr_stall(struct gk20a *g)
110{ 83{
111 u32 mc_intr_0; 84 u32 mc_intr_0;
112 int hw_irq_count; 85 int hw_irq_count;
@@ -114,11 +87,7 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g)
114 u32 active_engine_id = 0; 87 u32 active_engine_id = 0;
115 u32 engine_enum = ENGINE_INVAL_GK20A; 88 u32 engine_enum = ENGINE_INVAL_GK20A;
116 89
117 gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); 90 mc_intr_0 = g->ops.mc.intr_stall(g);
118
119 trace_mc_gk20a_intr_thread_stall(g->name);
120
121 mc_intr_0 = gk20a_readl(g, mc_intr_0_r());
122 hw_irq_count = atomic_read(&g->hw_irq_stall_count); 91 hw_irq_count = atomic_read(&g->hw_irq_stall_count);
123 92
124 gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0); 93 gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0);
@@ -156,18 +125,6 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g)
156 125
157 /* sync handled irq counter before re-enabling interrupts */ 126 /* sync handled irq counter before re-enabling interrupts */
158 atomic_set(&g->sw_irq_stall_last_handled, hw_irq_count); 127 atomic_set(&g->sw_irq_stall_last_handled, hw_irq_count);
159
160 gk20a_writel(g, mc_intr_en_0_r(),
161 mc_intr_en_0_inta_hardware_f());
162
163 /* flush previous write */
164 gk20a_readl(g, mc_intr_en_0_r());
165
166 wake_up_all(&g->sw_irq_stall_last_handled_wq);
167
168 trace_mc_gk20a_intr_thread_stall_done(g->name);
169
170 return IRQ_HANDLED;
171} 128}
172 129
173void mc_gk20a_intr_thread_nonstall(struct gk20a *g, u32 mc_intr_1) 130void mc_gk20a_intr_thread_nonstall(struct gk20a *g, u32 mc_intr_1)
@@ -250,6 +207,29 @@ void mc_gk20a_intr_unit_config(struct gk20a *g, bool enable,
250 } 207 }
251} 208}
252 209
210void mc_gk20a_intr_stall_pause(struct gk20a *g)
211{
212 gk20a_writel(g, mc_intr_en_0_r(),
213 mc_intr_en_0_inta_disabled_f());
214
215 /* flush previous write */
216 gk20a_readl(g, mc_intr_en_0_r());
217}
218
219void mc_gk20a_intr_stall_resume(struct gk20a *g)
220{
221 gk20a_writel(g, mc_intr_en_0_r(),
222 mc_intr_en_0_inta_hardware_f());
223
224 /* flush previous write */
225 gk20a_readl(g, mc_intr_en_0_r());
226}
227
228u32 mc_gk20a_intr_stall(struct gk20a *g)
229{
230 return gk20a_readl(g, mc_intr_0_r());
231}
232
253void gk20a_mc_disable(struct gk20a *g, u32 units) 233void gk20a_mc_disable(struct gk20a *g, u32 units)
254{ 234{
255 u32 pmc; 235 u32 pmc;
@@ -312,8 +292,10 @@ void gk20a_init_mc(struct gpu_ops *gops)
312 gops->mc.intr_enable = mc_gk20a_intr_enable; 292 gops->mc.intr_enable = mc_gk20a_intr_enable;
313 gops->mc.intr_unit_config = mc_gk20a_intr_unit_config; 293 gops->mc.intr_unit_config = mc_gk20a_intr_unit_config;
314 gops->mc.isr_stall = mc_gk20a_isr_stall; 294 gops->mc.isr_stall = mc_gk20a_isr_stall;
295 gops->mc.intr_stall = mc_gk20a_intr_stall;
296 gops->mc.intr_stall_pause = mc_gk20a_intr_stall_pause;
297 gops->mc.intr_stall_resume = mc_gk20a_intr_stall_resume;
315 gops->mc.isr_nonstall = mc_gk20a_isr_nonstall; 298 gops->mc.isr_nonstall = mc_gk20a_isr_nonstall;
316 gops->mc.isr_thread_stall = mc_gk20a_intr_thread_stall;
317 gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; 299 gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall;
318 gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb; 300 gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb;
319 gops->mc.enable = gk20a_mc_enable; 301 gops->mc.enable = gk20a_mc_enable;
diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.h b/drivers/gpu/nvgpu/gk20a/mc_gk20a.h
index 9c70eba1..2b4a183e 100644
--- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.h
@@ -19,7 +19,10 @@ void gk20a_init_mc(struct gpu_ops *gops);
19void mc_gk20a_intr_enable(struct gk20a *g); 19void mc_gk20a_intr_enable(struct gk20a *g);
20void mc_gk20a_intr_unit_config(struct gk20a *g, bool enable, 20void mc_gk20a_intr_unit_config(struct gk20a *g, bool enable,
21 bool is_stalling, u32 mask); 21 bool is_stalling, u32 mask);
22irqreturn_t mc_gk20a_isr_stall(struct gk20a *g); 22void mc_gk20a_isr_stall(struct gk20a *g);
23u32 mc_gk20a_intr_stall(struct gk20a *g);
24void mc_gk20a_intr_stall_pause(struct gk20a *g);
25void mc_gk20a_intr_stall_resume(struct gk20a *g);
23irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g); 26irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g);
24irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g); 27irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g);
25void mc_gk20a_intr_thread_nonstall(struct gk20a *g, u32 intr); 28void mc_gk20a_intr_thread_nonstall(struct gk20a *g, u32 intr);
diff --git a/drivers/gpu/nvgpu/gm20b/mc_gm20b.c b/drivers/gpu/nvgpu/gm20b/mc_gm20b.c
index 05504e82..ebb9780d 100644
--- a/drivers/gpu/nvgpu/gm20b/mc_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/mc_gm20b.c
@@ -22,8 +22,10 @@ void gm20b_init_mc(struct gpu_ops *gops)
22 gops->mc.intr_enable = mc_gk20a_intr_enable; 22 gops->mc.intr_enable = mc_gk20a_intr_enable;
23 gops->mc.intr_unit_config = mc_gk20a_intr_unit_config; 23 gops->mc.intr_unit_config = mc_gk20a_intr_unit_config;
24 gops->mc.isr_stall = mc_gk20a_isr_stall; 24 gops->mc.isr_stall = mc_gk20a_isr_stall;
25 gops->mc.intr_stall = mc_gk20a_intr_stall;
26 gops->mc.intr_stall_pause = mc_gk20a_intr_stall_pause;
27 gops->mc.intr_stall_resume = mc_gk20a_intr_stall_resume;
25 gops->mc.isr_nonstall = mc_gk20a_isr_nonstall; 28 gops->mc.isr_nonstall = mc_gk20a_isr_nonstall;
26 gops->mc.isr_thread_stall = mc_gk20a_intr_thread_stall;
27 gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; 29 gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall;
28 gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb; 30 gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb;
29 gops->mc.enable = gk20a_mc_enable; 31 gops->mc.enable = gk20a_mc_enable;
diff --git a/drivers/gpu/nvgpu/gp10b/mc_gp10b.c b/drivers/gpu/nvgpu/gp10b/mc_gp10b.c
index 4a48d7fa..bfc7a3d4 100644
--- a/drivers/gpu/nvgpu/gp10b/mc_gp10b.c
+++ b/drivers/gpu/nvgpu/gp10b/mc_gp10b.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * GP20B master 2 * GP10B master
3 * 3 *
4 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -67,25 +67,6 @@ void mc_gp10b_intr_unit_config(struct gk20a *g, bool enable,
67 gk20a_writel(g, reg, mask); 67 gk20a_writel(g, reg, mask);
68} 68}
69 69
70irqreturn_t mc_gp10b_isr_stall(struct gk20a *g)
71{
72 u32 mc_intr_0;
73
74 if (!g->power_on)
75 return IRQ_NONE;
76
77 /* not from gpu when sharing irq with others */
78 mc_intr_0 = gk20a_readl(g, mc_intr_r(0));
79 if (unlikely(!mc_intr_0))
80 return IRQ_NONE;
81
82 gk20a_writel(g, mc_intr_en_clear_r(0), 0xffffffff);
83
84 atomic_inc(&g->hw_irq_stall_count);
85
86 return IRQ_WAKE_THREAD;
87}
88
89irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g) 70irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g)
90{ 71{
91 u32 mc_intr_1; 72 u32 mc_intr_1;
@@ -117,7 +98,7 @@ irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g)
117 return IRQ_HANDLED; 98 return IRQ_HANDLED;
118} 99}
119 100
120irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g) 101void mc_gp10b_isr_stall(struct gk20a *g)
121{ 102{
122 u32 mc_intr_0; 103 u32 mc_intr_0;
123 int hw_irq_count; 104 int hw_irq_count;
@@ -126,8 +107,6 @@ irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g)
126 u32 active_engine_id = 0; 107 u32 active_engine_id = 0;
127 u32 engine_enum = ENGINE_INVAL_GK20A; 108 u32 engine_enum = ENGINE_INVAL_GK20A;
128 109
129 gk20a_dbg(gpu_dbg_intr, "interrupt thread launched");
130
131 mc_intr_0 = gk20a_readl(g, mc_intr_r(0)); 110 mc_intr_0 = gk20a_readl(g, mc_intr_r(0));
132 hw_irq_count = atomic_read(&g->hw_irq_stall_count); 111 hw_irq_count = atomic_read(&g->hw_irq_stall_count);
133 112
@@ -172,12 +151,22 @@ irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g)
172 151
173 gk20a_dbg(gpu_dbg_intr, "stall intr done 0x%08x\n", mc_intr_0); 152 gk20a_dbg(gpu_dbg_intr, "stall intr done 0x%08x\n", mc_intr_0);
174 153
175 gk20a_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING), 154}
176 g->ops.mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]);
177 155
178 wake_up_all(&g->sw_irq_stall_last_handled_wq); 156u32 mc_gp10b_intr_stall(struct gk20a *g)
157{
158 return gk20a_readl(g, mc_intr_r(NVGPU_MC_INTR_STALLING));
159}
179 160
180 return IRQ_HANDLED; 161void mc_gp10b_intr_stall_pause(struct gk20a *g)
162{
163 gk20a_writel(g, mc_intr_en_clear_r(NVGPU_MC_INTR_STALLING), 0xffffffff);
164}
165
166void mc_gp10b_intr_stall_resume(struct gk20a *g)
167{
168 gk20a_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING),
169 g->ops.mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]);
181} 170}
182 171
183void gp10b_init_mc(struct gpu_ops *gops) 172void gp10b_init_mc(struct gpu_ops *gops)
@@ -185,8 +174,10 @@ void gp10b_init_mc(struct gpu_ops *gops)
185 gops->mc.intr_enable = mc_gp10b_intr_enable; 174 gops->mc.intr_enable = mc_gp10b_intr_enable;
186 gops->mc.intr_unit_config = mc_gp10b_intr_unit_config; 175 gops->mc.intr_unit_config = mc_gp10b_intr_unit_config;
187 gops->mc.isr_stall = mc_gp10b_isr_stall; 176 gops->mc.isr_stall = mc_gp10b_isr_stall;
177 gops->mc.intr_stall = mc_gp10b_intr_stall;
178 gops->mc.intr_stall_pause = mc_gp10b_intr_stall_pause;
179 gops->mc.intr_stall_resume = mc_gp10b_intr_stall_resume;
188 gops->mc.isr_nonstall = mc_gp10b_isr_nonstall; 180 gops->mc.isr_nonstall = mc_gp10b_isr_nonstall;
189 gops->mc.isr_thread_stall = mc_gp10b_intr_thread_stall;
190 gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; 181 gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall;
191 gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb; 182 gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb;
192 gops->mc.enable = gk20a_mc_enable; 183 gops->mc.enable = gk20a_mc_enable;
diff --git a/drivers/gpu/nvgpu/gp10b/mc_gp10b.h b/drivers/gpu/nvgpu/gp10b/mc_gp10b.h
index b2ec4be4..31867a88 100644
--- a/drivers/gpu/nvgpu/gp10b/mc_gp10b.h
+++ b/drivers/gpu/nvgpu/gp10b/mc_gp10b.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 2 * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
@@ -24,8 +24,7 @@ void gp10b_init_mc(struct gpu_ops *gops);
24void mc_gp10b_intr_enable(struct gk20a *g); 24void mc_gp10b_intr_enable(struct gk20a *g);
25void mc_gp10b_intr_unit_config(struct gk20a *g, bool enable, 25void mc_gp10b_intr_unit_config(struct gk20a *g, bool enable,
26 bool is_stalling, u32 mask); 26 bool is_stalling, u32 mask);
27irqreturn_t mc_gp10b_isr_stall(struct gk20a *g); 27void mc_gp10b_isr_stall(struct gk20a *g);
28irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g); 28irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g);
29irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g);
30irqreturn_t mc_gp10b_intr_thread_nonstall(struct gk20a *g); 29irqreturn_t mc_gp10b_intr_thread_nonstall(struct gk20a *g);
31#endif 30#endif