summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2014-04-09 06:33:31 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:09:06 -0400
commit3df84a13d142b20f63970b9523143dd0e46c2ff9 (patch)
tree262f8b11454349ea46a28ca808a43d673f934743 /drivers
parent542f729aa9ea9c5eb845c35d855e3925f45ab24f (diff)
gpu: nvgpu: Make trigger mmu fault GPU specific
Add abstraction for triggering fake MMU fault, and a gk20a implementation. Also adds recovery to FE hardware warning exception to make testing easier. Bug 1495967 Change-Id: I6703cff37900a4c4592023423f9c0b31a8928db2 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c2
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.h2
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.c76
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.h1
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h2
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_gk20a.c1
6 files changed, 51 insertions, 33 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index 6056f558..4cce7260 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -1953,7 +1953,7 @@ clean_up:
1953 return ret; 1953 return ret;
1954} 1954}
1955 1955
1956void gk20a_init_fifo(struct gpu_ops *gops) 1956void gk20a_init_channel(struct gpu_ops *gops)
1957{ 1957{
1958 gops->fifo.bind_channel = channel_gk20a_bind; 1958 gops->fifo.bind_channel = channel_gk20a_bind;
1959} 1959}
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
index 429db85d..47fc714c 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
@@ -167,6 +167,6 @@ int gk20a_channel_release(struct inode *inode, struct file *filp);
167struct channel_gk20a *gk20a_get_channel_from_file(int fd); 167struct channel_gk20a *gk20a_get_channel_from_file(int fd);
168void gk20a_channel_update(struct channel_gk20a *c, int nr_completed); 168void gk20a_channel_update(struct channel_gk20a *c, int nr_completed);
169 169
170void gk20a_init_fifo(struct gpu_ops *gops); 170void gk20a_init_channel(struct gpu_ops *gops);
171 171
172#endif /*__CHANNEL_GK20A_H__*/ 172#endif /*__CHANNEL_GK20A_H__*/
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
index 5575b995..f1987ed5 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
@@ -1092,43 +1092,15 @@ static void gk20a_fifo_get_faulty_channel(struct gk20a *g, int engine_id,
1092 fifo_engine_status_id_v(status); 1092 fifo_engine_status_id_v(status);
1093} 1093}
1094 1094
1095void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids, 1095static void gk20a_fifo_trigger_mmu_fault(struct gk20a *g,
1096 bool verbose) 1096 unsigned long engine_ids)
1097{ 1097{
1098 unsigned long end_jiffies = jiffies + 1098 unsigned long end_jiffies = jiffies +
1099 msecs_to_jiffies(gk20a_get_gr_idle_timeout(g)); 1099 msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
1100 unsigned long delay = GR_IDLE_CHECK_DEFAULT; 1100 unsigned long delay = GR_IDLE_CHECK_DEFAULT;
1101 unsigned long engine_id, i; 1101 unsigned long engine_id;
1102 unsigned long _engine_ids = __engine_ids;
1103 unsigned long engine_ids = 0;
1104 int ret; 1102 int ret;
1105 1103
1106 if (verbose)
1107 gk20a_debug_dump(g->dev);
1108
1109 /* store faulted engines in advance */
1110 g->fifo.mmu_fault_engines = 0;
1111 for_each_set_bit(engine_id, &_engine_ids, 32) {
1112 bool ref_type_ch;
1113 int ref_chid;
1114 gk20a_fifo_get_faulty_channel(g, engine_id, &ref_chid,
1115 &ref_type_ch);
1116
1117 /* Reset *all* engines that use the
1118 * same channel as faulty engine */
1119 for (i = 0; i < g->fifo.max_engines; i++) {
1120 bool type_ch;
1121 u32 chid;
1122 gk20a_fifo_get_faulty_channel(g, i, &chid, &type_ch);
1123 if (ref_type_ch == type_ch && ref_chid == chid) {
1124 engine_ids |= BIT(i);
1125 g->fifo.mmu_fault_engines |=
1126 BIT(gk20a_engine_id_to_mmu_id(i));
1127 }
1128 }
1129
1130 }
1131
1132 /* trigger faults for all bad engines */ 1104 /* trigger faults for all bad engines */
1133 for_each_set_bit(engine_id, &engine_ids, 32) { 1105 for_each_set_bit(engine_id, &engine_ids, 32) {
1134 if (engine_id > g->fifo.max_engines) { 1106 if (engine_id > g->fifo.max_engines) {
@@ -1164,6 +1136,42 @@ void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids,
1164 gk20a_writel(g, fifo_trigger_mmu_fault_r(engine_id), 0); 1136 gk20a_writel(g, fifo_trigger_mmu_fault_r(engine_id), 0);
1165} 1137}
1166 1138
1139void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids,
1140 bool verbose)
1141{
1142 unsigned long engine_id, i;
1143 unsigned long _engine_ids = __engine_ids;
1144 unsigned long engine_ids = 0;
1145
1146 if (verbose)
1147 gk20a_debug_dump(g->dev);
1148
1149 /* store faulted engines in advance */
1150 g->fifo.mmu_fault_engines = 0;
1151 for_each_set_bit(engine_id, &_engine_ids, 32) {
1152 bool ref_type_ch;
1153 int ref_chid;
1154 gk20a_fifo_get_faulty_channel(g, engine_id, &ref_chid,
1155 &ref_type_ch);
1156
1157 /* Reset *all* engines that use the
1158 * same channel as faulty engine */
1159 for (i = 0; i < g->fifo.max_engines; i++) {
1160 bool type_ch;
1161 u32 chid;
1162 gk20a_fifo_get_faulty_channel(g, i, &chid, &type_ch);
1163 if (ref_type_ch == type_ch && ref_chid == chid) {
1164 engine_ids |= BIT(i);
1165 g->fifo.mmu_fault_engines |=
1166 BIT(gk20a_engine_id_to_mmu_id(i));
1167 }
1168 }
1169
1170 }
1171
1172 g->ops.fifo.trigger_mmu_fault(g, engine_ids);
1173}
1174
1167 1175
1168static bool gk20a_fifo_handle_sched_error(struct gk20a *g) 1176static bool gk20a_fifo_handle_sched_error(struct gk20a *g)
1169{ 1177{
@@ -1834,3 +1842,9 @@ bool gk20a_fifo_mmu_fault_pending(struct gk20a *g)
1834 else 1842 else
1835 return false; 1843 return false;
1836} 1844}
1845
1846void gk20a_init_fifo(struct gpu_ops *gops)
1847{
1848 gk20a_init_channel(gops);
1849 gops->fifo.trigger_mmu_fault = gk20a_fifo_trigger_mmu_fault;
1850}
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
index 051acda2..078ae8f0 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
@@ -158,6 +158,7 @@ int gk20a_fifo_suspend(struct gk20a *g);
158bool gk20a_fifo_mmu_fault_pending(struct gk20a *g); 158bool gk20a_fifo_mmu_fault_pending(struct gk20a *g);
159void gk20a_fifo_recover(struct gk20a *g, u32 engine_ids, bool verbose); 159void gk20a_fifo_recover(struct gk20a *g, u32 engine_ids, bool verbose);
160int gk20a_init_fifo_reset_enable_hw(struct gk20a *g); 160int gk20a_init_fifo_reset_enable_hw(struct gk20a *g);
161void gk20a_init_fifo(struct gpu_ops *gops);
161 162
162void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g, 163void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g,
163 unsigned long fault_id); 164 unsigned long fault_id);
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index 7aca186e..7aa10692 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -137,6 +137,8 @@ struct gpu_ops {
137 } clock_gating; 137 } clock_gating;
138 struct { 138 struct {
139 void (*bind_channel)(struct channel_gk20a *ch_gk20a); 139 void (*bind_channel)(struct channel_gk20a *ch_gk20a);
140 void (*trigger_mmu_fault)(struct gk20a *g,
141 unsigned long engine_ids);
140 } fifo; 142 } fifo;
141 struct pmu_v { 143 struct pmu_v {
142 /*used for change of enum zbc update cmd id from ver 0 to ver1*/ 144 /*used for change of enum zbc update cmd id from ver 0 to ver1*/
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
index ced1f62f..b2a92f81 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
@@ -5333,6 +5333,7 @@ int gk20a_gr_isr(struct gk20a *g)
5333 u32 fe = gk20a_readl(g, gr_fe_hww_esr_r()); 5333 u32 fe = gk20a_readl(g, gr_fe_hww_esr_r());
5334 gk20a_dbg(gpu_dbg_intr, "fe warning %08x\n", fe); 5334 gk20a_dbg(gpu_dbg_intr, "fe warning %08x\n", fe);
5335 gk20a_writel(g, gr_fe_hww_esr_r(), fe); 5335 gk20a_writel(g, gr_fe_hww_esr_r(), fe);
5336 need_reset |= -EFAULT;
5336 } 5337 }
5337 5338
5338 /* check if a gpc exception has occurred */ 5339 /* check if a gpc exception has occurred */