summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c90
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h6
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_gk20a.c107
-rw-r--r--drivers/gpu/nvgpu/gm20b/gr_gm20b.c111
-rw-r--r--include/uapi/linux/nvgpu.h22
5 files changed, 335 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
index d9c96417..f717e207 100644
--- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
@@ -564,6 +564,86 @@ static int nvgpu_dbg_gpu_ioctl_read_single_sm_error_state(
564 return 0; 564 return 0;
565} 565}
566 566
567static int nvgpu_dbg_gpu_ioctl_clear_single_sm_error_state(
568 struct dbg_session_gk20a *dbg_s,
569 struct nvgpu_dbg_gpu_clear_single_sm_error_state_args *args)
570{
571 struct gk20a *g = get_gk20a(dbg_s->dev);
572 struct gr_gk20a *gr = &g->gr;
573 u32 sm_id;
574 struct channel_gk20a *ch = dbg_s->ch;
575 int err = 0;
576
577 sm_id = args->sm_id;
578
579 if (sm_id >= gr->no_of_sm)
580 return -EINVAL;
581
582 err = gk20a_busy(g->dev);
583 if (err)
584 return err;
585
586 err = gr_gk20a_elpg_protected_call(g,
587 g->ops.gr.clear_sm_error_state(g, ch, sm_id));
588
589 gk20a_idle(g->dev);
590
591 return err;
592}
593
594static int nvgpu_dbg_gpu_ioctl_write_single_sm_error_state(
595 struct dbg_session_gk20a *dbg_s,
596 struct nvgpu_dbg_gpu_write_single_sm_error_state_args *args)
597{
598 struct gk20a *g = get_gk20a(dbg_s->dev);
599 struct gr_gk20a *gr = &g->gr;
600 u32 sm_id;
601 struct channel_gk20a *ch = dbg_s->ch;
602 struct nvgpu_dbg_gpu_sm_error_state_record *sm_error_state;
603 int err = 0;
604
605 sm_id = args->sm_id;
606 if (sm_id >= gr->no_of_sm)
607 return -EINVAL;
608
609 sm_error_state = kzalloc(sizeof(*sm_error_state), GFP_KERNEL);
610 if (!sm_error_state)
611 return -ENOMEM;
612
613 if (args->sm_error_state_record_size > 0) {
614 size_t read_size = sizeof(*sm_error_state);
615
616 if (read_size > args->sm_error_state_record_size)
617 read_size = args->sm_error_state_record_size;
618
619 mutex_lock(&g->dbg_sessions_lock);
620 err = copy_from_user(sm_error_state,
621 (void __user *)(uintptr_t)
622 args->sm_error_state_record_mem,
623 read_size);
624 mutex_unlock(&g->dbg_sessions_lock);
625 if (err) {
626 err = -ENOMEM;
627 goto err_free;
628 }
629 }
630
631 err = gk20a_busy(g->dev);
632 if (err)
633 goto err_free;
634
635 err = gr_gk20a_elpg_protected_call(g,
636 g->ops.gr.update_sm_error_state(g, ch,
637 sm_id, sm_error_state));
638
639 gk20a_idle(g->dev);
640
641err_free:
642 kfree(sm_error_state);
643
644 return err;
645}
646
567long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd, 647long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd,
568 unsigned long arg) 648 unsigned long arg)
569{ 649{
@@ -666,6 +746,16 @@ long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd,
666 (struct nvgpu_dbg_gpu_read_single_sm_error_state_args *)buf); 746 (struct nvgpu_dbg_gpu_read_single_sm_error_state_args *)buf);
667 break; 747 break;
668 748
749 case NVGPU_DBG_GPU_IOCTL_CLEAR_SINGLE_SM_ERROR_STATE:
750 err = nvgpu_dbg_gpu_ioctl_clear_single_sm_error_state(dbg_s,
751 (struct nvgpu_dbg_gpu_clear_single_sm_error_state_args *)buf);
752 break;
753
754 case NVGPU_DBG_GPU_IOCTL_WRITE_SINGLE_SM_ERROR_STATE:
755 err = nvgpu_dbg_gpu_ioctl_write_single_sm_error_state(dbg_s,
756 (struct nvgpu_dbg_gpu_write_single_sm_error_state_args *)buf);
757 break;
758
669 default: 759 default:
670 gk20a_err(dev_from_gk20a(g), 760 gk20a_err(dev_from_gk20a(g),
671 "unrecognized dbg gpu ioctl cmd: 0x%x", 761 "unrecognized dbg gpu ioctl cmd: 0x%x",
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index c70217ea..d1ce6afb 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -242,6 +242,12 @@ struct gpu_ops {
242 u32 (*get_lrf_tex_ltc_dram_override)(struct gk20a *g); 242 u32 (*get_lrf_tex_ltc_dram_override)(struct gk20a *g);
243 int (*record_sm_error_state)(struct gk20a *g, 243 int (*record_sm_error_state)(struct gk20a *g,
244 u32 gpc, u32 tpc); 244 u32 gpc, u32 tpc);
245 int (*update_sm_error_state)(struct gk20a *g,
246 struct channel_gk20a *ch, u32 sm_id,
247 struct nvgpu_dbg_gpu_sm_error_state_record *
248 sm_error_state);
249 int (*clear_sm_error_state)(struct gk20a *g,
250 struct channel_gk20a *ch, u32 sm_id);
245 } gr; 251 } gr;
246 const char *name; 252 const char *name;
247 struct { 253 struct {
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
index c0a25e68..4c88751e 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
@@ -5535,6 +5535,111 @@ static int gk20a_gr_record_sm_error_state(struct gk20a *g, u32 gpc, u32 tpc)
5535 return 0; 5535 return 0;
5536} 5536}
5537 5537
5538static int gk20a_gr_update_sm_error_state(struct gk20a *g,
5539 struct channel_gk20a *ch, u32 sm_id,
5540 struct nvgpu_dbg_gpu_sm_error_state_record *sm_error_state)
5541{
5542 u32 gpc, tpc, offset;
5543 struct gr_gk20a *gr = &g->gr;
5544 struct channel_ctx_gk20a *ch_ctx = &ch->ch_ctx;
5545 int err = 0;
5546
5547 mutex_lock(&g->dbg_sessions_lock);
5548
5549 gr->sm_error_states[sm_id].hww_global_esr =
5550 sm_error_state->hww_global_esr;
5551 gr->sm_error_states[sm_id].hww_warp_esr =
5552 sm_error_state->hww_warp_esr;
5553 gr->sm_error_states[sm_id].hww_global_esr_report_mask =
5554 sm_error_state->hww_global_esr_report_mask;
5555 gr->sm_error_states[sm_id].hww_warp_esr_report_mask =
5556 sm_error_state->hww_warp_esr_report_mask;
5557
5558 err = gr_gk20a_disable_ctxsw(g);
5559 if (err) {
5560 gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw\n");
5561 goto fail;
5562 }
5563
5564 gpc = g->gr.sm_to_cluster[sm_id].gpc_index;
5565 tpc = g->gr.sm_to_cluster[sm_id].tpc_index;
5566
5567 offset = proj_gpc_stride_v() * gpc +
5568 proj_tpc_in_gpc_stride_v() * tpc;
5569
5570 if (gk20a_is_channel_ctx_resident(ch)) {
5571 gk20a_writel(g, gr_gpc0_tpc0_sm_hww_global_esr_r() + offset,
5572 gr->sm_error_states[sm_id].hww_global_esr);
5573 gk20a_writel(g, gr_gpc0_tpc0_sm_hww_warp_esr_r() + offset,
5574 gr->sm_error_states[sm_id].hww_warp_esr);
5575 gk20a_writel(g, gr_gpcs_tpcs_sm_hww_global_esr_report_mask_r() + offset,
5576 gr->sm_error_states[sm_id].hww_global_esr_report_mask);
5577 gk20a_writel(g, gr_gpcs_tpcs_sm_hww_warp_esr_report_mask_r() + offset,
5578 gr->sm_error_states[sm_id].hww_warp_esr_report_mask);
5579 } else {
5580 err = gr_gk20a_ctx_patch_write_begin(g, ch_ctx);
5581 if (err)
5582 goto enable_ctxsw;
5583
5584 gr_gk20a_ctx_patch_write(g, ch_ctx,
5585 gr_gpcs_tpcs_sm_hww_global_esr_report_mask_r() + offset,
5586 gr->sm_error_states[sm_id].hww_global_esr_report_mask,
5587 true);
5588 gr_gk20a_ctx_patch_write(g, ch_ctx,
5589 gr_gpcs_tpcs_sm_hww_warp_esr_report_mask_r() + offset,
5590 gr->sm_error_states[sm_id].hww_warp_esr_report_mask,
5591 true);
5592
5593 gr_gk20a_ctx_patch_write_end(g, ch_ctx);
5594 }
5595
5596enable_ctxsw:
5597 err = gr_gk20a_enable_ctxsw(g);
5598
5599fail:
5600 mutex_unlock(&g->dbg_sessions_lock);
5601 return err;
5602}
5603
5604static int gk20a_gr_clear_sm_error_state(struct gk20a *g,
5605 struct channel_gk20a *ch, u32 sm_id)
5606{
5607 u32 gpc, tpc, offset;
5608 u32 val;
5609 struct gr_gk20a *gr = &g->gr;
5610 int err = 0;
5611
5612 mutex_lock(&g->dbg_sessions_lock);
5613
5614 memset(&gr->sm_error_states[sm_id], 0, sizeof(*gr->sm_error_states));
5615
5616 err = gr_gk20a_disable_ctxsw(g);
5617 if (err) {
5618 gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw\n");
5619 goto fail;
5620 }
5621
5622 if (gk20a_is_channel_ctx_resident(ch)) {
5623 gpc = g->gr.sm_to_cluster[sm_id].gpc_index;
5624 tpc = g->gr.sm_to_cluster[sm_id].tpc_index;
5625
5626 offset = proj_gpc_stride_v() * gpc +
5627 proj_tpc_in_gpc_stride_v() * tpc;
5628
5629 val = gk20a_readl(g, gr_gpc0_tpc0_sm_hww_global_esr_r() + offset);
5630 gk20a_writel(g, gr_gpc0_tpc0_sm_hww_global_esr_r() + offset,
5631 val);
5632 gk20a_writel(g, gr_gpc0_tpc0_sm_hww_warp_esr_r() + offset,
5633 0);
5634 }
5635
5636 err = gr_gk20a_enable_ctxsw(g);
5637
5638fail:
5639 mutex_unlock(&g->dbg_sessions_lock);
5640 return err;
5641}
5642
5538int gr_gk20a_handle_sm_exception(struct gk20a *g, u32 gpc, u32 tpc, 5643int gr_gk20a_handle_sm_exception(struct gk20a *g, u32 gpc, u32 tpc,
5539 bool *post_event, struct channel_gk20a *fault_ch) 5644 bool *post_event, struct channel_gk20a *fault_ch)
5540{ 5645{
@@ -8415,4 +8520,6 @@ void gk20a_init_gr_ops(struct gpu_ops *gops)
8415 gops->gr.update_smpc_ctxsw_mode = gr_gk20a_update_smpc_ctxsw_mode; 8520 gops->gr.update_smpc_ctxsw_mode = gr_gk20a_update_smpc_ctxsw_mode;
8416 gops->gr.update_hwpm_ctxsw_mode = gr_gk20a_update_hwpm_ctxsw_mode; 8521 gops->gr.update_hwpm_ctxsw_mode = gr_gk20a_update_hwpm_ctxsw_mode;
8417 gops->gr.record_sm_error_state = gk20a_gr_record_sm_error_state; 8522 gops->gr.record_sm_error_state = gk20a_gr_record_sm_error_state;
8523 gops->gr.update_sm_error_state = gk20a_gr_update_sm_error_state;
8524 gops->gr.clear_sm_error_state = gk20a_gr_clear_sm_error_state;
8418} 8525}
diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c
index eeb70d76..204a90f3 100644
--- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c
@@ -1219,6 +1219,115 @@ static int gm20b_gr_record_sm_error_state(struct gk20a *g, u32 gpc, u32 tpc)
1219 return 0; 1219 return 0;
1220} 1220}
1221 1221
1222static int gm20b_gr_update_sm_error_state(struct gk20a *g,
1223 struct channel_gk20a *ch, u32 sm_id,
1224 struct nvgpu_dbg_gpu_sm_error_state_record *sm_error_state)
1225{
1226 u32 gpc, tpc, offset;
1227 struct gr_gk20a *gr = &g->gr;
1228 struct channel_ctx_gk20a *ch_ctx = &ch->ch_ctx;
1229 int err = 0;
1230
1231 mutex_lock(&g->dbg_sessions_lock);
1232
1233 gr->sm_error_states[sm_id].hww_global_esr =
1234 sm_error_state->hww_global_esr;
1235 gr->sm_error_states[sm_id].hww_warp_esr =
1236 sm_error_state->hww_warp_esr;
1237 gr->sm_error_states[sm_id].hww_warp_esr_pc =
1238 sm_error_state->hww_warp_esr_pc;
1239 gr->sm_error_states[sm_id].hww_global_esr_report_mask =
1240 sm_error_state->hww_global_esr_report_mask;
1241 gr->sm_error_states[sm_id].hww_warp_esr_report_mask =
1242 sm_error_state->hww_warp_esr_report_mask;
1243
1244 err = gr_gk20a_disable_ctxsw(g);
1245 if (err) {
1246 gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw\n");
1247 goto fail;
1248 }
1249
1250 gpc = g->gr.sm_to_cluster[sm_id].gpc_index;
1251 tpc = g->gr.sm_to_cluster[sm_id].tpc_index;
1252
1253 offset = proj_gpc_stride_v() * gpc +
1254 proj_tpc_in_gpc_stride_v() * tpc;
1255
1256 if (gk20a_is_channel_ctx_resident(ch)) {
1257 gk20a_writel(g, gr_gpc0_tpc0_sm_hww_global_esr_r() + offset,
1258 gr->sm_error_states[sm_id].hww_global_esr);
1259 gk20a_writel(g, gr_gpc0_tpc0_sm_hww_warp_esr_r() + offset,
1260 gr->sm_error_states[sm_id].hww_warp_esr);
1261 gk20a_writel(g, gr_gpc0_tpc0_sm_hww_warp_esr_pc_r() + offset,
1262 gr->sm_error_states[sm_id].hww_warp_esr_pc);
1263 gk20a_writel(g, gr_gpcs_tpcs_sm_hww_global_esr_report_mask_r() + offset,
1264 gr->sm_error_states[sm_id].hww_global_esr_report_mask);
1265 gk20a_writel(g, gr_gpcs_tpcs_sm_hww_warp_esr_report_mask_r() + offset,
1266 gr->sm_error_states[sm_id].hww_warp_esr_report_mask);
1267 } else {
1268 err = gr_gk20a_ctx_patch_write_begin(g, ch_ctx);
1269 if (err)
1270 goto enable_ctxsw;
1271
1272 gr_gk20a_ctx_patch_write(g, ch_ctx,
1273 gr_gpcs_tpcs_sm_hww_global_esr_report_mask_r() + offset,
1274 gr->sm_error_states[sm_id].hww_global_esr_report_mask,
1275 true);
1276 gr_gk20a_ctx_patch_write(g, ch_ctx,
1277 gr_gpcs_tpcs_sm_hww_warp_esr_report_mask_r() + offset,
1278 gr->sm_error_states[sm_id].hww_warp_esr_report_mask,
1279 true);
1280
1281 gr_gk20a_ctx_patch_write_end(g, ch_ctx);
1282 }
1283
1284enable_ctxsw:
1285 err = gr_gk20a_enable_ctxsw(g);
1286
1287fail:
1288 mutex_unlock(&g->dbg_sessions_lock);
1289 return err;
1290}
1291
1292static int gm20b_gr_clear_sm_error_state(struct gk20a *g,
1293 struct channel_gk20a *ch, u32 sm_id)
1294{
1295 u32 gpc, tpc, offset;
1296 u32 val;
1297 struct gr_gk20a *gr = &g->gr;
1298 int err = 0;
1299
1300 mutex_lock(&g->dbg_sessions_lock);
1301
1302 memset(&gr->sm_error_states[sm_id], 0, sizeof(*gr->sm_error_states));
1303
1304 err = gr_gk20a_disable_ctxsw(g);
1305 if (err) {
1306 gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw\n");
1307 goto fail;
1308 }
1309
1310 if (gk20a_is_channel_ctx_resident(ch)) {
1311 gpc = g->gr.sm_to_cluster[sm_id].gpc_index;
1312 tpc = g->gr.sm_to_cluster[sm_id].tpc_index;
1313
1314 offset = proj_gpc_stride_v() * gpc +
1315 proj_tpc_in_gpc_stride_v() * tpc;
1316
1317 val = gk20a_readl(g, gr_gpc0_tpc0_sm_hww_global_esr_r() + offset);
1318 gk20a_writel(g, gr_gpc0_tpc0_sm_hww_global_esr_r() + offset,
1319 val);
1320 gk20a_writel(g, gr_gpc0_tpc0_sm_hww_warp_esr_r() + offset,
1321 0);
1322 }
1323
1324 err = gr_gk20a_enable_ctxsw(g);
1325
1326fail:
1327 mutex_unlock(&g->dbg_sessions_lock);
1328 return err;
1329}
1330
1222void gm20b_init_gr(struct gpu_ops *gops) 1331void gm20b_init_gr(struct gpu_ops *gops)
1223{ 1332{
1224 gops->gr.init_gpc_mmu = gr_gm20b_init_gpc_mmu; 1333 gops->gr.init_gpc_mmu = gr_gm20b_init_gpc_mmu;
@@ -1286,4 +1395,6 @@ void gm20b_init_gr(struct gpu_ops *gops)
1286 gops->gr.update_smpc_ctxsw_mode = gr_gk20a_update_smpc_ctxsw_mode; 1395 gops->gr.update_smpc_ctxsw_mode = gr_gk20a_update_smpc_ctxsw_mode;
1287 gops->gr.update_hwpm_ctxsw_mode = gr_gk20a_update_hwpm_ctxsw_mode; 1396 gops->gr.update_hwpm_ctxsw_mode = gr_gk20a_update_hwpm_ctxsw_mode;
1288 gops->gr.record_sm_error_state = gm20b_gr_record_sm_error_state; 1397 gops->gr.record_sm_error_state = gm20b_gr_record_sm_error_state;
1398 gops->gr.update_sm_error_state = gm20b_gr_update_sm_error_state;
1399 gops->gr.clear_sm_error_state = gm20b_gr_clear_sm_error_state;
1289} 1400}
diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h
index 96619015..89871b53 100644
--- a/include/uapi/linux/nvgpu.h
+++ b/include/uapi/linux/nvgpu.h
@@ -703,8 +703,28 @@ struct nvgpu_dbg_gpu_read_single_sm_error_state_args {
703 _IOWR(NVGPU_DBG_GPU_IOCTL_MAGIC, 14, struct nvgpu_dbg_gpu_read_single_sm_error_state_args) 703 _IOWR(NVGPU_DBG_GPU_IOCTL_MAGIC, 14, struct nvgpu_dbg_gpu_read_single_sm_error_state_args)
704 704
705 705
706struct nvgpu_dbg_gpu_clear_single_sm_error_state_args {
707 __u32 sm_id;
708 __u32 padding;
709};
710
711#define NVGPU_DBG_GPU_IOCTL_CLEAR_SINGLE_SM_ERROR_STATE \
712 _IOW(NVGPU_DBG_GPU_IOCTL_MAGIC, 15, struct nvgpu_dbg_gpu_clear_single_sm_error_state_args)
713
714
715struct nvgpu_dbg_gpu_write_single_sm_error_state_args {
716 __u32 sm_id;
717 __u32 padding;
718 __u64 sm_error_state_record_mem;
719 __u64 sm_error_state_record_size;
720};
721
722#define NVGPU_DBG_GPU_IOCTL_WRITE_SINGLE_SM_ERROR_STATE \
723 _IOW(NVGPU_DBG_GPU_IOCTL_MAGIC, 16, struct nvgpu_dbg_gpu_write_single_sm_error_state_args)
724
725
706#define NVGPU_DBG_GPU_IOCTL_LAST \ 726#define NVGPU_DBG_GPU_IOCTL_LAST \
707 _IOC_NR(NVGPU_DBG_GPU_IOCTL_READ_SINGLE_SM_ERROR_STATE) 727 _IOC_NR(NVGPU_DBG_GPU_IOCTL_WRITE_SINGLE_SM_ERROR_STATE)
708 728
709#define NVGPU_DBG_GPU_IOCTL_MAX_ARG_SIZE \ 729#define NVGPU_DBG_GPU_IOCTL_MAX_ARG_SIZE \
710 sizeof(struct nvgpu_dbg_gpu_perfbuf_map_args) 730 sizeof(struct nvgpu_dbg_gpu_perfbuf_map_args)