summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2014-06-02 05:02:26 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:10:03 -0400
commit28c35a1b99cdfc8ef950241471a213a211bd1836 (patch)
tree97fab22efd375244cc2e5f011f85e9b881a62fa7 /drivers/gpu/nvgpu
parentbcf8c6411cebde9435b97cb6b575b947205688fa (diff)
gpu: nvgpu: Fault engines on PBDMA error
On PBDMA error even though the engine might not be wedged, we need to kick the channel out of engine. Add that logic. Also when channel is not in engine, we need to remove it from runlist. Bug 1498688 Change-Id: I5939feb41d0a90635ba313b265c7e3b5d3f48622 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/417682 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-by: Kevin Huang (Eng-SW) <kevinh@nvidia.com> Reviewed-by: Seshendra Gadagottu <sgadagottu@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.c100
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.h2
-rw-r--r--drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h4
3 files changed, 58 insertions, 48 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
index db1ccd72..f36a3eb6 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
@@ -1145,6 +1145,51 @@ static void gk20a_fifo_trigger_mmu_fault(struct gk20a *g,
1145 gk20a_writel(g, fifo_intr_en_0_r(), 0x7FFFFFFF); 1145 gk20a_writel(g, fifo_intr_en_0_r(), 0x7FFFFFFF);
1146} 1146}
1147 1147
1148u32 gk20a_fifo_engines_on_ch(struct gk20a *g, u32 hw_chid)
1149{
1150 int i;
1151 u32 engines = 0;
1152
1153 for (i = 0; i < g->fifo.max_engines; i++) {
1154 u32 status = gk20a_readl(g, fifo_engine_status_r(i));
1155 u32 ctx_status =
1156 fifo_engine_status_ctx_status_v(status);
1157 bool type_ch = fifo_pbdma_status_id_type_v(status) ==
1158 fifo_pbdma_status_id_type_chid_v();
1159 bool busy = fifo_engine_status_engine_v(status) ==
1160 fifo_engine_status_engine_busy_v();
1161 u32 id = (ctx_status ==
1162 fifo_engine_status_ctx_status_ctxsw_load_v()) ?
1163 fifo_engine_status_next_id_v(status) :
1164 fifo_engine_status_id_v(status);
1165
1166 if (type_ch && busy && id == hw_chid)
1167 engines |= BIT(i);
1168 }
1169
1170 return engines;
1171}
1172
1173void gk20a_fifo_recover_ch(struct gk20a *g, u32 hw_chid, bool verbose)
1174{
1175 u32 engines = gk20a_fifo_engines_on_ch(g, hw_chid);
1176 if (engines)
1177 gk20a_fifo_recover(g, engines, verbose);
1178 else {
1179 int i;
1180 struct channel_gk20a *ch =
1181 g->fifo.channel + hw_chid;
1182
1183 gk20a_disable_channel_no_update(ch);
1184 for (i = 0; i < g->fifo.max_runlists; i++)
1185 gk20a_fifo_update_runlist(g, i,
1186 hw_chid, false, false);
1187
1188 if (gk20a_fifo_set_ctx_mmu_error(g, ch))
1189 gk20a_debug_dump(g->dev);
1190 }
1191}
1192
1148void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids, 1193void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids,
1149 bool verbose) 1194 bool verbose)
1150{ 1195{
@@ -1326,7 +1371,6 @@ static u32 fifo_error_isr(struct gk20a *g, u32 fifo_intr)
1326 return handled; 1371 return handled;
1327} 1372}
1328 1373
1329
1330static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, 1374static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev,
1331 struct gk20a *g, 1375 struct gk20a *g,
1332 struct fifo_gk20a *f, 1376 struct fifo_gk20a *f,
@@ -1345,9 +1389,11 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev,
1345 if ((f->intr.pbdma.device_fatal_0 | 1389 if ((f->intr.pbdma.device_fatal_0 |
1346 f->intr.pbdma.channel_fatal_0 | 1390 f->intr.pbdma.channel_fatal_0 |
1347 f->intr.pbdma.restartable_0) & pbdma_intr_0) { 1391 f->intr.pbdma.restartable_0) & pbdma_intr_0) {
1348 dev_err(dev, "pbdma_intr_0(%d):0x%08x PBH: %08x M0: %08x", 1392 gk20a_err(dev_from_gk20a(g),
1393 "pbdma_intr_0(%d):0x%08x PBH: %08x SHADOW: %08x M0: %08x",
1349 pbdma_id, pbdma_intr_0, 1394 pbdma_id, pbdma_intr_0,
1350 gk20a_readl(g, pbdma_pb_header_r(pbdma_id)), 1395 gk20a_readl(g, pbdma_pb_header_r(pbdma_id)),
1396 gk20a_readl(g, pbdma_hdr_shadow_r(pbdma_id)),
1351 gk20a_readl(g, pbdma_method0_r(pbdma_id))); 1397 gk20a_readl(g, pbdma_method0_r(pbdma_id)));
1352 reset = true; 1398 reset = true;
1353 handled |= ((f->intr.pbdma.device_fatal_0 | 1399 handled |= ((f->intr.pbdma.device_fatal_0 |
@@ -1371,32 +1417,10 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev,
1371 if (reset) { 1417 if (reset) {
1372 /* Remove the channel from runlist */ 1418 /* Remove the channel from runlist */
1373 u32 status = gk20a_readl(g, fifo_pbdma_status_r(pbdma_id)); 1419 u32 status = gk20a_readl(g, fifo_pbdma_status_r(pbdma_id));
1420 u32 hw_chid = fifo_pbdma_status_id_v(status);
1374 if (fifo_pbdma_status_id_type_v(status) 1421 if (fifo_pbdma_status_id_type_v(status)
1375 == fifo_pbdma_status_id_type_chid_v()) { 1422 == fifo_pbdma_status_id_type_chid_v()) {
1376 struct channel_gk20a *ch = g->fifo.channel + 1423 gk20a_fifo_recover_ch(g, hw_chid, true);
1377 fifo_pbdma_status_id_v(status);
1378 struct fifo_runlist_info_gk20a *runlist =
1379 g->fifo.runlist_info;
1380 int i;
1381 bool verbose;
1382
1383 /* disable the channel from hw and increment
1384 * syncpoints */
1385 gk20a_disable_channel_no_update(ch);
1386
1387 /* remove the channel from runlist */
1388 clear_bit(ch->hw_chid,
1389 runlist->active_channels);
1390 ch->has_timedout = true;
1391
1392 /* Recreate the runlist */
1393 for (i = 0; i < g->fifo.max_runlists; i++)
1394 gk20a_fifo_update_runlist(g,
1395 0, ~0, false, false);
1396
1397 verbose = gk20a_fifo_set_ctx_mmu_error(g, ch);
1398 if (verbose)
1399 gk20a_debug_dump(g->dev);
1400 } 1424 }
1401 } 1425 }
1402 1426
@@ -1523,34 +1547,14 @@ int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid)
1523 !tegra_platform_is_silicon()); 1547 !tegra_platform_is_silicon());
1524 1548
1525 if (ret) { 1549 if (ret) {
1526 int i; 1550 struct channel_gk20a *ch = &g->fifo.channel[hw_chid];
1527 u32 engines = 0;
1528 struct fifo_gk20a *f = &g->fifo;
1529 struct channel_gk20a *ch = &f->channel[hw_chid];
1530 1551
1531 gk20a_err(dev_from_gk20a(g), "preempt channel %d timeout\n", 1552 gk20a_err(dev_from_gk20a(g), "preempt channel %d timeout\n",
1532 hw_chid); 1553 hw_chid);
1533 1554
1534 /* forcefully reset all busy engines using this channel */
1535 for (i = 0; i < g->fifo.max_engines; i++) {
1536 u32 status = gk20a_readl(g, fifo_engine_status_r(i));
1537 u32 ctx_status =
1538 fifo_engine_status_ctx_status_v(status);
1539 bool type_ch = fifo_pbdma_status_id_type_v(status) ==
1540 fifo_pbdma_status_id_type_chid_v();
1541 bool busy = fifo_engine_status_engine_v(status) ==
1542 fifo_engine_status_engine_busy_v();
1543 u32 id = (ctx_status ==
1544 fifo_engine_status_ctx_status_ctxsw_load_v()) ?
1545 fifo_engine_status_next_id_v(status) :
1546 fifo_engine_status_id_v(status);
1547
1548 if (type_ch && busy && id == hw_chid)
1549 engines |= BIT(i);
1550 }
1551 gk20a_set_error_notifier(ch, 1555 gk20a_set_error_notifier(ch,
1552 NVHOST_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT); 1556 NVHOST_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT);
1553 gk20a_fifo_recover(g, engines, true); 1557 gk20a_fifo_recover_ch(g, hw_chid, true);
1554 } 1558 }
1555 1559
1556 /* re-enable elpg or release pmu mutex */ 1560 /* re-enable elpg or release pmu mutex */
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
index 078ae8f0..8a4e0a8f 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
@@ -149,6 +149,7 @@ int gk20a_fifo_enable_engine_activity(struct gk20a *g,
149int gk20a_fifo_disable_engine_activity(struct gk20a *g, 149int gk20a_fifo_disable_engine_activity(struct gk20a *g,
150 struct fifo_engine_info_gk20a *eng_info, 150 struct fifo_engine_info_gk20a *eng_info,
151 bool wait_for_idle); 151 bool wait_for_idle);
152u32 gk20a_fifo_engines_on_ch(struct gk20a *g, u32 hw_chid);
152 153
153int gk20a_fifo_update_runlist(struct gk20a *g, u32 engine_id, u32 hw_chid, 154int gk20a_fifo_update_runlist(struct gk20a *g, u32 engine_id, u32 hw_chid,
154 bool add, bool wait_for_finish); 155 bool add, bool wait_for_finish);
@@ -157,6 +158,7 @@ int gk20a_fifo_suspend(struct gk20a *g);
157 158
158bool gk20a_fifo_mmu_fault_pending(struct gk20a *g); 159bool gk20a_fifo_mmu_fault_pending(struct gk20a *g);
159void gk20a_fifo_recover(struct gk20a *g, u32 engine_ids, bool verbose); 160void gk20a_fifo_recover(struct gk20a *g, u32 engine_ids, bool verbose);
161void gk20a_fifo_recover_ch(struct gk20a *g, u32 hw_chid, bool verbose);
160int gk20a_init_fifo_reset_enable_hw(struct gk20a *g); 162int gk20a_init_fifo_reset_enable_hw(struct gk20a *g);
161void gk20a_init_fifo(struct gpu_ops *gops); 163void gk20a_init_fifo(struct gpu_ops *gops);
162 164
diff --git a/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h b/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h
index 60e83122..0d749c20 100644
--- a/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h
@@ -174,6 +174,10 @@ static inline u32 pbdma_pb_header_type_inc_f(void)
174{ 174{
175 return 0x20000000; 175 return 0x20000000;
176} 176}
177static inline u32 pbdma_hdr_shadow_r(u32 i)
178{
179 return 0x00040118 + i*8192;
180}
177static inline u32 pbdma_subdevice_r(u32 i) 181static inline u32 pbdma_subdevice_r(u32 i)
178{ 182{
179 return 0x00040094 + i*8192; 183 return 0x00040094 + i*8192;