diff options
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/gr_gv11b.c | 87 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/gr_gv11b.h | 8 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c | 59 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/hw/gv11b/hw_gr_gv11b.h | 72 |
4 files changed, 225 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/gr_gv11b.c b/drivers/gpu/nvgpu/gv11b/gr_gv11b.c index 179c7d33..ad34233c 100644 --- a/drivers/gpu/nvgpu/gv11b/gr_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/gr_gv11b.c | |||
@@ -108,6 +108,89 @@ static bool gr_gv11b_is_valid_compute_class(struct gk20a *g, u32 class_num) | |||
108 | return valid; | 108 | return valid; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int gr_gv11b_handle_l1_tag_exception(struct gk20a *g, u32 gpc, u32 tpc, | ||
112 | bool *post_event, struct channel_gk20a *fault_ch, | ||
113 | u32 *hww_global_esr) | ||
114 | { | ||
115 | u32 gpc_stride = nvgpu_get_litter_value(g, GPU_LIT_GPC_STRIDE); | ||
116 | u32 tpc_in_gpc_stride = nvgpu_get_litter_value(g, GPU_LIT_TPC_IN_GPC_STRIDE); | ||
117 | u32 offset = gpc_stride * gpc + tpc_in_gpc_stride * tpc; | ||
118 | u32 l1_tag_ecc_status, l1_tag_ecc_corrected_err_status = 0; | ||
119 | u32 l1_tag_ecc_uncorrected_err_status = 0; | ||
120 | u32 l1_tag_corrected_err_count_delta = 0; | ||
121 | u32 l1_tag_uncorrected_err_count_delta = 0; | ||
122 | bool is_l1_tag_ecc_corrected_total_err_overflow = 0; | ||
123 | bool is_l1_tag_ecc_uncorrected_total_err_overflow = 0; | ||
124 | |||
125 | /* Check for L1 tag ECC errors. */ | ||
126 | l1_tag_ecc_status = gk20a_readl(g, | ||
127 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_r() + offset); | ||
128 | l1_tag_ecc_corrected_err_status = l1_tag_ecc_status & | ||
129 | (gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_el1_0_m() | | ||
130 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_el1_1_m() | | ||
131 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_pixrpf_m() | | ||
132 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_miss_fifo_m()); | ||
133 | l1_tag_ecc_uncorrected_err_status = l1_tag_ecc_status & | ||
134 | (gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_el1_0_m() | | ||
135 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_el1_1_m() | | ||
136 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_pixrpf_m() | | ||
137 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_miss_fifo_m()); | ||
138 | |||
139 | if ((l1_tag_ecc_corrected_err_status == 0) && (l1_tag_ecc_uncorrected_err_status == 0)) | ||
140 | return 0; | ||
141 | |||
142 | l1_tag_corrected_err_count_delta = | ||
143 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_corrected_err_count_total_v( | ||
144 | gk20a_readl(g, | ||
145 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_corrected_err_count_r() + | ||
146 | offset)); | ||
147 | l1_tag_uncorrected_err_count_delta = | ||
148 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_uncorrected_err_count_total_v( | ||
149 | gk20a_readl(g, | ||
150 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_uncorrected_err_count_r() + | ||
151 | offset)); | ||
152 | is_l1_tag_ecc_corrected_total_err_overflow = | ||
153 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_total_counter_overflow_v(l1_tag_ecc_status); | ||
154 | is_l1_tag_ecc_uncorrected_total_err_overflow = | ||
155 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_total_counter_overflow_v(l1_tag_ecc_status); | ||
156 | |||
157 | if ((l1_tag_corrected_err_count_delta > 0) || is_l1_tag_ecc_corrected_total_err_overflow) { | ||
158 | gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr, | ||
159 | "corrected error (SBE) detected in SM L1 tag! err_mask [%08x] is_overf [%d]", | ||
160 | l1_tag_ecc_corrected_err_status, is_l1_tag_ecc_corrected_total_err_overflow); | ||
161 | |||
162 | /* HW uses 16-bits counter */ | ||
163 | l1_tag_corrected_err_count_delta += | ||
164 | (is_l1_tag_ecc_corrected_total_err_overflow << | ||
165 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_corrected_err_count_total_s()); | ||
166 | g->gr.t19x.ecc_stats.sm_l1_tag_corrected_err_count.counters[tpc] += | ||
167 | l1_tag_corrected_err_count_delta; | ||
168 | gk20a_writel(g, | ||
169 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_corrected_err_count_r() + offset, | ||
170 | 0); | ||
171 | } | ||
172 | if ((l1_tag_uncorrected_err_count_delta > 0) || is_l1_tag_ecc_uncorrected_total_err_overflow) { | ||
173 | gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr, | ||
174 | "Uncorrected error (DBE) detected in SM L1 tag! err_mask [%08x] is_overf [%d]", | ||
175 | l1_tag_ecc_uncorrected_err_status, is_l1_tag_ecc_uncorrected_total_err_overflow); | ||
176 | |||
177 | /* HW uses 16-bits counter */ | ||
178 | l1_tag_uncorrected_err_count_delta += | ||
179 | (is_l1_tag_ecc_uncorrected_total_err_overflow << | ||
180 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_uncorrected_err_count_total_s()); | ||
181 | g->gr.t19x.ecc_stats.sm_l1_tag_uncorrected_err_count.counters[tpc] += | ||
182 | l1_tag_uncorrected_err_count_delta; | ||
183 | gk20a_writel(g, | ||
184 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_uncorrected_err_count_r() + offset, | ||
185 | 0); | ||
186 | } | ||
187 | |||
188 | gk20a_writel(g, gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_r() + offset, | ||
189 | gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_reset_task_f()); | ||
190 | |||
191 | return 0; | ||
192 | |||
193 | } | ||
111 | 194 | ||
112 | static int gr_gv11b_handle_sm_exception(struct gk20a *g, u32 gpc, u32 tpc, | 195 | static int gr_gv11b_handle_sm_exception(struct gk20a *g, u32 gpc, u32 tpc, |
113 | bool *post_event, struct channel_gk20a *fault_ch, | 196 | bool *post_event, struct channel_gk20a *fault_ch, |
@@ -118,7 +201,8 @@ static int gr_gv11b_handle_sm_exception(struct gk20a *g, u32 gpc, u32 tpc, | |||
118 | proj_tpc_in_gpc_stride_v() * tpc; | 201 | proj_tpc_in_gpc_stride_v() * tpc; |
119 | u32 lrf_ecc_status; | 202 | u32 lrf_ecc_status; |
120 | 203 | ||
121 | gr_gk20a_handle_sm_exception(g, gpc, tpc, post_event, fault_ch, hww_global_esr); | 204 | /* Check for L1 tag ECC errors. */ |
205 | gr_gv11b_handle_l1_tag_exception(g, gpc, tpc, post_event, fault_ch, hww_global_esr); | ||
122 | 206 | ||
123 | /* Check for LRF ECC errors. */ | 207 | /* Check for LRF ECC errors. */ |
124 | lrf_ecc_status = gk20a_readl(g, | 208 | lrf_ecc_status = gk20a_readl(g, |
@@ -1692,6 +1776,7 @@ void gv11b_init_gr(struct gpu_ops *gops) | |||
1692 | gops->gr.pre_process_sm_exception = | 1776 | gops->gr.pre_process_sm_exception = |
1693 | gr_gv11b_pre_process_sm_exception; | 1777 | gr_gv11b_pre_process_sm_exception; |
1694 | gops->gr.handle_fecs_error = gr_gv11b_handle_fecs_error; | 1778 | gops->gr.handle_fecs_error = gr_gv11b_handle_fecs_error; |
1779 | gops->gr.create_gr_sysfs = gr_gv11b_create_sysfs; | ||
1695 | gops->gr.setup_rop_mapping = gr_gv11b_setup_rop_mapping; | 1780 | gops->gr.setup_rop_mapping = gr_gv11b_setup_rop_mapping; |
1696 | gops->gr.init_sw_veid_bundle = gr_gv11b_init_sw_veid_bundle; | 1781 | gops->gr.init_sw_veid_bundle = gr_gv11b_init_sw_veid_bundle; |
1697 | gops->gr.program_zcull_mapping = gr_gv11b_program_zcull_mapping; | 1782 | gops->gr.program_zcull_mapping = gr_gv11b_program_zcull_mapping; |
diff --git a/drivers/gpu/nvgpu/gv11b/gr_gv11b.h b/drivers/gpu/nvgpu/gv11b/gr_gv11b.h index 9d9f969d..2d6e3d1f 100644 --- a/drivers/gpu/nvgpu/gv11b/gr_gv11b.h +++ b/drivers/gpu/nvgpu/gv11b/gr_gv11b.h | |||
@@ -35,6 +35,13 @@ enum { | |||
35 | VOLTA_DMA_COPY_A = 0xC3B5, | 35 | VOLTA_DMA_COPY_A = 0xC3B5, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | struct gr_t19x { | ||
39 | struct { | ||
40 | struct gr_gp10b_ecc_stat sm_l1_tag_corrected_err_count; | ||
41 | struct gr_gp10b_ecc_stat sm_l1_tag_uncorrected_err_count; | ||
42 | } ecc_stats; | ||
43 | }; | ||
44 | |||
38 | #define NVC397_SET_SHADER_EXCEPTIONS 0x1528 | 45 | #define NVC397_SET_SHADER_EXCEPTIONS 0x1528 |
39 | #define NVC397_SET_CIRCULAR_BUFFER_SIZE 0x1280 | 46 | #define NVC397_SET_CIRCULAR_BUFFER_SIZE 0x1280 |
40 | #define NVC397_SET_ALPHA_CIRCULAR_BUFFER_SIZE 0x02dc | 47 | #define NVC397_SET_ALPHA_CIRCULAR_BUFFER_SIZE 0x02dc |
@@ -48,4 +55,5 @@ int gr_gv11b_alloc_buffer(struct vm_gk20a *vm, size_t size, | |||
48 | /*zcull*/ | 55 | /*zcull*/ |
49 | void gr_gv11b_program_zcull_mapping(struct gk20a *g, u32 zcull_num_entries, | 56 | void gr_gv11b_program_zcull_mapping(struct gk20a *g, u32 zcull_num_entries, |
50 | u32 *zcull_map_tiles); | 57 | u32 *zcull_map_tiles); |
58 | void gr_gv11b_create_sysfs(struct device *dev); | ||
51 | #endif | 59 | #endif |
diff --git a/drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c b/drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c index 97845035..8ca9dd30 100644 --- a/drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c +++ b/drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c | |||
@@ -27,11 +27,13 @@ | |||
27 | #include "tegra/linux/clk.h" | 27 | #include "tegra/linux/clk.h" |
28 | 28 | ||
29 | #include "gp10b/platform_gp10b.h" | 29 | #include "gp10b/platform_gp10b.h" |
30 | #include "tegra/linux/platform_gp10b_tegra.h" | ||
30 | 31 | ||
31 | #include "tegra/linux/platform_gk20a_tegra.h" | 32 | #include "tegra/linux/platform_gk20a_tegra.h" |
32 | #include "gr_gv11b.h" | 33 | #include "gr_gv11b.h" |
33 | #include "nvgpu_gpuid_t19x.h" | 34 | #include "nvgpu_gpuid_t19x.h" |
34 | 35 | ||
36 | static void gr_gv11b_remove_sysfs(struct device *dev); | ||
35 | 37 | ||
36 | static int gv11b_tegra_probe(struct device *dev) | 38 | static int gv11b_tegra_probe(struct device *dev) |
37 | { | 39 | { |
@@ -57,6 +59,15 @@ static int gv11b_tegra_probe(struct device *dev) | |||
57 | return 0; | 59 | return 0; |
58 | } | 60 | } |
59 | 61 | ||
62 | static int gv11b_tegra_remove(struct device *dev) | ||
63 | { | ||
64 | gp10b_tegra_remove(dev); | ||
65 | |||
66 | gr_gv11b_remove_sysfs(dev); | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
60 | static bool gv11b_tegra_is_railgated(struct device *dev) | 71 | static bool gv11b_tegra_is_railgated(struct device *dev) |
61 | { | 72 | { |
62 | bool ret = false; | 73 | bool ret = false; |
@@ -89,6 +100,7 @@ struct gk20a_platform t19x_gpu_tegra_platform = { | |||
89 | .ptimer_src_freq = 31250000, | 100 | .ptimer_src_freq = 31250000, |
90 | 101 | ||
91 | .probe = gv11b_tegra_probe, | 102 | .probe = gv11b_tegra_probe, |
103 | .remove = gv11b_tegra_remove, | ||
92 | 104 | ||
93 | /* power management callbacks */ | 105 | /* power management callbacks */ |
94 | .suspend = gv11b_tegra_suspend, | 106 | .suspend = gv11b_tegra_suspend, |
@@ -110,3 +122,50 @@ struct gk20a_platform t19x_gpu_tegra_platform = { | |||
110 | .reset_assert = gp10b_tegra_reset_assert, | 122 | .reset_assert = gp10b_tegra_reset_assert, |
111 | .reset_deassert = gp10b_tegra_reset_deassert, | 123 | .reset_deassert = gp10b_tegra_reset_deassert, |
112 | }; | 124 | }; |
125 | |||
126 | static struct device_attribute *dev_attr_sm_l1_tag_ecc_corrected_err_count_array; | ||
127 | static struct device_attribute *dev_attr_sm_l1_tag_ecc_uncorrected_err_count_array; | ||
128 | |||
129 | void gr_gv11b_create_sysfs(struct device *dev) | ||
130 | { | ||
131 | struct gk20a *g = get_gk20a(dev); | ||
132 | int error = 0; | ||
133 | /* This stat creation function is called on GR init. GR can get | ||
134 | initialized multiple times but we only need to create the ECC | ||
135 | stats once. Therefore, add the following check to avoid | ||
136 | creating duplicate stat sysfs nodes. */ | ||
137 | if (g->gr.t19x.ecc_stats.sm_l1_tag_corrected_err_count.counters != NULL) | ||
138 | return; | ||
139 | |||
140 | gr_gp10b_create_sysfs(dev); | ||
141 | |||
142 | error |= gr_gp10b_ecc_stat_create(dev, | ||
143 | 0, | ||
144 | "sm_l1_tag_ecc_corrected_err_count", | ||
145 | &g->gr.t19x.ecc_stats.sm_l1_tag_corrected_err_count, | ||
146 | dev_attr_sm_l1_tag_ecc_corrected_err_count_array); | ||
147 | |||
148 | error |= gr_gp10b_ecc_stat_create(dev, | ||
149 | 0, | ||
150 | "sm_l1_tag_ecc_uncorrected_err_count", | ||
151 | &g->gr.t19x.ecc_stats.sm_l1_tag_uncorrected_err_count, | ||
152 | dev_attr_sm_l1_tag_ecc_uncorrected_err_count_array); | ||
153 | |||
154 | if (error) | ||
155 | dev_err(dev, "Failed to create gv11b sysfs attributes!\n"); | ||
156 | } | ||
157 | |||
158 | static void gr_gv11b_remove_sysfs(struct device *dev) | ||
159 | { | ||
160 | struct gk20a *g = get_gk20a(dev); | ||
161 | |||
162 | gr_gp10b_ecc_stat_remove(dev, | ||
163 | 0, | ||
164 | &g->gr.t19x.ecc_stats.sm_l1_tag_corrected_err_count, | ||
165 | dev_attr_sm_l1_tag_ecc_corrected_err_count_array); | ||
166 | |||
167 | gr_gp10b_ecc_stat_remove(dev, | ||
168 | 0, | ||
169 | &g->gr.t19x.ecc_stats.sm_l1_tag_uncorrected_err_count, | ||
170 | dev_attr_sm_l1_tag_ecc_uncorrected_err_count_array); | ||
171 | } | ||
diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/gv11b/hw_gr_gv11b.h b/drivers/gpu/nvgpu/include/nvgpu/hw/gv11b/hw_gr_gv11b.h index 592a7899..d45385a8 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/hw/gv11b/hw_gr_gv11b.h +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/gv11b/hw_gr_gv11b.h | |||
@@ -482,6 +482,78 @@ static inline u32 gr_pri_gpc0_tpc0_sm_lrf_ecc_status_r(void) | |||
482 | { | 482 | { |
483 | return 0x00504358; | 483 | return 0x00504358; |
484 | } | 484 | } |
485 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_r(void) | ||
486 | { | ||
487 | return 0x00504624; | ||
488 | } | ||
489 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_el1_0_m(void) | ||
490 | { | ||
491 | return 0x1 << 0; | ||
492 | } | ||
493 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_el1_1_m(void) | ||
494 | { | ||
495 | return 0x1 << 1; | ||
496 | } | ||
497 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_el1_0_m(void) | ||
498 | { | ||
499 | return 0x1 << 2; | ||
500 | } | ||
501 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_el1_1_m(void) | ||
502 | { | ||
503 | return 0x1 << 3; | ||
504 | } | ||
505 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_pixrpf_m(void) | ||
506 | { | ||
507 | return 0x1 << 4; | ||
508 | } | ||
509 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_miss_fifo_m(void) | ||
510 | { | ||
511 | return 0x1 << 5; | ||
512 | } | ||
513 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_pixrpf_m(void) | ||
514 | { | ||
515 | return 0x1 << 6; | ||
516 | } | ||
517 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_miss_fifo_m(void) | ||
518 | { | ||
519 | return 0x1 << 7; | ||
520 | } | ||
521 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_corrected_err_total_counter_overflow_v(u32 r) | ||
522 | { | ||
523 | return (r >> 8) & 0x1; | ||
524 | } | ||
525 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_uncorrected_err_total_counter_overflow_v(u32 r) | ||
526 | { | ||
527 | return (r >> 10) & 0x1; | ||
528 | } | ||
529 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_status_reset_task_f(void) | ||
530 | { | ||
531 | return 0x40000000; | ||
532 | } | ||
533 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_corrected_err_count_r(void) | ||
534 | { | ||
535 | return 0x00504628; | ||
536 | } | ||
537 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_corrected_err_count_total_s(void) | ||
538 | { | ||
539 | return 16; | ||
540 | } | ||
541 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_corrected_err_count_total_v(u32 r) | ||
542 | { | ||
543 | return (r >> 0) & 0xffff; | ||
544 | } | ||
545 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_uncorrected_err_count_r(void) | ||
546 | { | ||
547 | return 0x0050462c; | ||
548 | } | ||
549 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_uncorrected_err_count_total_s(void) | ||
550 | { | ||
551 | return 16; | ||
552 | } | ||
553 | static inline u32 gr_pri_gpc0_tpc0_sm_l1_tag_ecc_uncorrected_err_count_total_v(u32 r) | ||
554 | { | ||
555 | return (r >> 0) & 0xffff; | ||
556 | } | ||
485 | static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_r(void) | 557 | static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_r(void) |
486 | { | 558 | { |
487 | return 0x005042c4; | 559 | return 0x005042c4; |