summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gp10b/gr_gp10b.c145
-rw-r--r--drivers/gpu/nvgpu/gp10b/gr_gp10b.h28
-rw-r--r--drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h92
-rw-r--r--drivers/gpu/nvgpu/gp10b/hw_ltc_gp10b.h22
-rw-r--r--drivers/gpu/nvgpu/gp10b/ltc_gp10b.c33
-rw-r--r--drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c328
6 files changed, 644 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c
index c66dea92..90d0ce8d 100644
--- a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c
+++ b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c
@@ -80,6 +80,13 @@ static int gr_gp10b_handle_sm_exception(struct gk20a *g, u32 gpc, u32 tpc,
80 80
81 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr, 81 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr,
82 "Single bit error detected in SM LRF!"); 82 "Single bit error detected in SM LRF!");
83
84 g->gr.t18x.ecc_stats.sm_lrf_single_err_count.counters[tpc] +=
85 gk20a_readl(g,
86 gr_pri_gpc0_tpc0_sm_lrf_ecc_single_err_count_r() + offset);
87 gk20a_writel(g,
88 gr_pri_gpc0_tpc0_sm_lrf_ecc_single_err_count_r() + offset,
89 0);
83 } 90 }
84 if ( (lrf_ecc_status & 91 if ( (lrf_ecc_status &
85 gr_pri_gpc0_tpc0_sm_lrf_ecc_status_double_err_detected_qrfdp0_pending_f()) || 92 gr_pri_gpc0_tpc0_sm_lrf_ecc_status_double_err_detected_qrfdp0_pending_f()) ||
@@ -92,6 +99,13 @@ static int gr_gp10b_handle_sm_exception(struct gk20a *g, u32 gpc, u32 tpc,
92 99
93 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr, 100 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr,
94 "Double bit error detected in SM LRF!"); 101 "Double bit error detected in SM LRF!");
102
103 g->gr.t18x.ecc_stats.sm_lrf_double_err_count.counters[tpc] +=
104 gk20a_readl(g,
105 gr_pri_gpc0_tpc0_sm_lrf_ecc_double_err_count_r() + offset);
106 gk20a_writel(g,
107 gr_pri_gpc0_tpc0_sm_lrf_ecc_double_err_count_r() + offset,
108 0);
95 } 109 }
96 gk20a_writel(g, gr_pri_gpc0_tpc0_sm_lrf_ecc_status_r() + offset, 110 gk20a_writel(g, gr_pri_gpc0_tpc0_sm_lrf_ecc_status_r() + offset,
97 lrf_ecc_status); 111 lrf_ecc_status);
@@ -107,17 +121,42 @@ static int gr_gp10b_handle_sm_exception(struct gk20a *g, u32 gpc, u32 tpc,
107 gr_pri_gpc0_tpc0_sm_shm_ecc_status_single_err_detected_shm0_pending_f()) || 121 gr_pri_gpc0_tpc0_sm_shm_ecc_status_single_err_detected_shm0_pending_f()) ||
108 (shm_ecc_status & 122 (shm_ecc_status &
109 gr_pri_gpc0_tpc0_sm_shm_ecc_status_single_err_detected_shm1_pending_f()) ) { 123 gr_pri_gpc0_tpc0_sm_shm_ecc_status_single_err_detected_shm1_pending_f()) ) {
124 u32 ecc_stats_reg_val;
110 125
111 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr, 126 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr,
112 "Single bit error detected in SM SHM!"); 127 "Single bit error detected in SM SHM!");
128
129 ecc_stats_reg_val =
130 gk20a_readl(g,
131 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_r() + offset);
132 g->gr.t18x.ecc_stats.sm_shm_sec_count.counters[tpc] +=
133 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_corrected_v(ecc_stats_reg_val);
134 g->gr.t18x.ecc_stats.sm_shm_sed_count.counters[tpc] +=
135 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_detected_v(ecc_stats_reg_val);
136 ecc_stats_reg_val &= ~(gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_corrected_m() |
137 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_detected_m());
138 gk20a_writel(g,
139 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_r() + offset,
140 ecc_stats_reg_val);
113 } 141 }
114 if ( (shm_ecc_status & 142 if ( (shm_ecc_status &
115 gr_pri_gpc0_tpc0_sm_shm_ecc_status_double_err_detected_shm0_pending_f()) || 143 gr_pri_gpc0_tpc0_sm_shm_ecc_status_double_err_detected_shm0_pending_f()) ||
116 (shm_ecc_status & 144 (shm_ecc_status &
117 gr_pri_gpc0_tpc0_sm_shm_ecc_status_double_err_detected_shm1_pending_f()) ) { 145 gr_pri_gpc0_tpc0_sm_shm_ecc_status_double_err_detected_shm1_pending_f()) ) {
146 u32 ecc_stats_reg_val;
118 147
119 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr, 148 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr,
120 "Double bit error detected in SM SHM!"); 149 "Double bit error detected in SM SHM!");
150
151 ecc_stats_reg_val =
152 gk20a_readl(g,
153 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_r() + offset);
154 g->gr.t18x.ecc_stats.sm_shm_ded_count.counters[tpc] +=
155 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_double_detected_v(ecc_stats_reg_val);
156 ecc_stats_reg_val &= ~(gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_double_detected_m());
157 gk20a_writel(g,
158 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_r() + offset,
159 ecc_stats_reg_val);
121 } 160 }
122 gk20a_writel(g, gr_pri_gpc0_tpc0_sm_shm_ecc_status_r() + offset, 161 gk20a_writel(g, gr_pri_gpc0_tpc0_sm_shm_ecc_status_r() + offset,
123 shm_ecc_status); 162 shm_ecc_status);
@@ -133,6 +172,7 @@ static int gr_gp10b_handle_tex_exception(struct gk20a *g, u32 gpc, u32 tpc,
133 u32 offset = proj_gpc_stride_v() * gpc + 172 u32 offset = proj_gpc_stride_v() * gpc +
134 proj_tpc_in_gpc_stride_v() * tpc; 173 proj_tpc_in_gpc_stride_v() * tpc;
135 u32 esr; 174 u32 esr;
175 u32 ecc_stats_reg_val;
136 176
137 gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, ""); 177 gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, "");
138 178
@@ -143,10 +183,114 @@ static int gr_gp10b_handle_tex_exception(struct gk20a *g, u32 gpc, u32 tpc,
143 if (esr & gr_gpc0_tpc0_tex_m_hww_esr_ecc_sec_pending_f()) { 183 if (esr & gr_gpc0_tpc0_tex_m_hww_esr_ecc_sec_pending_f()) {
144 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr, 184 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr,
145 "Single bit error detected in TEX!"); 185 "Single bit error detected in TEX!");
186
187 /* Pipe 0 counters */
188 gk20a_writel(g,
189 gr_pri_gpc0_tpc0_tex_m_routing_r() + offset,
190 gr_pri_gpc0_tpc0_tex_m_routing_sel_pipe0_f());
191
192 ecc_stats_reg_val = gk20a_readl(g,
193 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r() + offset);
194 g->gr.t18x.ecc_stats.tex_total_sec_pipe0_count.counters[tpc] +=
195 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_sec_v(ecc_stats_reg_val);
196 ecc_stats_reg_val &= ~gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_sec_m();
197 gk20a_writel(g,
198 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r() + offset,
199 ecc_stats_reg_val);
200
201 ecc_stats_reg_val = gk20a_readl(g,
202 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r() + offset);
203 g->gr.t18x.ecc_stats.tex_unique_sec_pipe0_count.counters[tpc] +=
204 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_sec_v(ecc_stats_reg_val);
205 ecc_stats_reg_val &= ~gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_sec_m();
206 gk20a_writel(g,
207 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r() + offset,
208 ecc_stats_reg_val);
209
210
211 /* Pipe 1 counters */
212 gk20a_writel(g,
213 gr_pri_gpc0_tpc0_tex_m_routing_r() + offset,
214 gr_pri_gpc0_tpc0_tex_m_routing_sel_pipe1_f());
215
216 ecc_stats_reg_val = gk20a_readl(g,
217 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r() + offset);
218 g->gr.t18x.ecc_stats.tex_total_sec_pipe1_count.counters[tpc] +=
219 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_sec_v(ecc_stats_reg_val);
220 ecc_stats_reg_val &= ~gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_sec_m();
221 gk20a_writel(g,
222 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r() + offset,
223 ecc_stats_reg_val);
224
225 ecc_stats_reg_val = gk20a_readl(g,
226 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r() + offset);
227 g->gr.t18x.ecc_stats.tex_unique_sec_pipe1_count.counters[tpc] +=
228 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_sec_v(ecc_stats_reg_val);
229 ecc_stats_reg_val &= ~gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_sec_m();
230 gk20a_writel(g,
231 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r() + offset,
232 ecc_stats_reg_val);
233
234
235 gk20a_writel(g,
236 gr_pri_gpc0_tpc0_tex_m_routing_r() + offset,
237 gr_pri_gpc0_tpc0_tex_m_routing_sel_default_f());
146 } 238 }
147 if (esr & gr_gpc0_tpc0_tex_m_hww_esr_ecc_ded_pending_f()) { 239 if (esr & gr_gpc0_tpc0_tex_m_hww_esr_ecc_ded_pending_f()) {
148 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr, 240 gk20a_dbg(gpu_dbg_fn | gpu_dbg_intr,
149 "Double bit error detected in TEX!"); 241 "Double bit error detected in TEX!");
242
243 /* Pipe 0 counters */
244 gk20a_writel(g,
245 gr_pri_gpc0_tpc0_tex_m_routing_r() + offset,
246 gr_pri_gpc0_tpc0_tex_m_routing_sel_pipe0_f());
247
248 ecc_stats_reg_val = gk20a_readl(g,
249 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r() + offset);
250 g->gr.t18x.ecc_stats.tex_total_ded_pipe0_count.counters[tpc] +=
251 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_ded_v(ecc_stats_reg_val);
252 ecc_stats_reg_val &= ~gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_ded_m();
253 gk20a_writel(g,
254 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r() + offset,
255 ecc_stats_reg_val);
256
257 ecc_stats_reg_val = gk20a_readl(g,
258 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r() + offset);
259 g->gr.t18x.ecc_stats.tex_unique_ded_pipe0_count.counters[tpc] +=
260 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_ded_v(ecc_stats_reg_val);
261 ecc_stats_reg_val &= ~gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_ded_m();
262 gk20a_writel(g,
263 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r() + offset,
264 ecc_stats_reg_val);
265
266
267 /* Pipe 1 counters */
268 gk20a_writel(g,
269 gr_pri_gpc0_tpc0_tex_m_routing_r() + offset,
270 gr_pri_gpc0_tpc0_tex_m_routing_sel_pipe1_f());
271
272 ecc_stats_reg_val = gk20a_readl(g,
273 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r() + offset);
274 g->gr.t18x.ecc_stats.tex_total_ded_pipe1_count.counters[tpc] +=
275 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_ded_v(ecc_stats_reg_val);
276 ecc_stats_reg_val &= ~gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_ded_m();
277 gk20a_writel(g,
278 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r() + offset,
279 ecc_stats_reg_val);
280
281 ecc_stats_reg_val = gk20a_readl(g,
282 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r() + offset);
283 g->gr.t18x.ecc_stats.tex_unique_ded_pipe1_count.counters[tpc] +=
284 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_ded_v(ecc_stats_reg_val);
285 ecc_stats_reg_val &= ~gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_ded_m();
286 gk20a_writel(g,
287 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r() + offset,
288 ecc_stats_reg_val);
289
290
291 gk20a_writel(g,
292 gr_pri_gpc0_tpc0_tex_m_routing_r() + offset,
293 gr_pri_gpc0_tpc0_tex_m_routing_sel_default_f());
150 } 294 }
151 295
152 gk20a_writel(g, 296 gk20a_writel(g,
@@ -1594,4 +1738,5 @@ void gp10b_init_gr(struct gpu_ops *gops)
1594 gops->gr.pre_process_sm_exception = 1738 gops->gr.pre_process_sm_exception =
1595 gr_gp10b_pre_process_sm_exception; 1739 gr_gp10b_pre_process_sm_exception;
1596 gops->gr.handle_fecs_error = gr_gp10b_handle_fecs_error; 1740 gops->gr.handle_fecs_error = gr_gp10b_handle_fecs_error;
1741 gops->gr.create_gr_sysfs = gr_gp10b_create_sysfs;
1597} 1742}
diff --git a/drivers/gpu/nvgpu/gp10b/gr_gp10b.h b/drivers/gpu/nvgpu/gp10b/gr_gp10b.h
index c35fb384..bd4b5879 100644
--- a/drivers/gpu/nvgpu/gp10b/gr_gp10b.h
+++ b/drivers/gpu/nvgpu/gp10b/gr_gp10b.h
@@ -35,6 +35,13 @@ enum {
35void gp10b_init_gr(struct gpu_ops *ops); 35void gp10b_init_gr(struct gpu_ops *ops);
36int gr_gp10b_alloc_buffer(struct vm_gk20a *vm, size_t size, 36int gr_gp10b_alloc_buffer(struct vm_gk20a *vm, size_t size,
37 struct mem_desc *mem); 37 struct mem_desc *mem);
38void gr_gp10b_create_sysfs(struct platform_device *dev);
39
40struct ecc_stat {
41 char **names;
42 u32 *counters;
43 struct hlist_node hash_node;
44};
38 45
39struct gr_t18x { 46struct gr_t18x {
40 struct { 47 struct {
@@ -47,6 +54,27 @@ struct gr_t18x {
47 struct dentry *debugfs_dump_ctxsw_stats; 54 struct dentry *debugfs_dump_ctxsw_stats;
48 } ctx_vars; 55 } ctx_vars;
49 56
57 struct {
58 struct ecc_stat sm_lrf_single_err_count;
59 struct ecc_stat sm_lrf_double_err_count;
60
61 struct ecc_stat sm_shm_sec_count;
62 struct ecc_stat sm_shm_sed_count;
63 struct ecc_stat sm_shm_ded_count;
64
65 struct ecc_stat tex_total_sec_pipe0_count;
66 struct ecc_stat tex_total_ded_pipe0_count;
67 struct ecc_stat tex_unique_sec_pipe0_count;
68 struct ecc_stat tex_unique_ded_pipe0_count;
69 struct ecc_stat tex_total_sec_pipe1_count;
70 struct ecc_stat tex_total_ded_pipe1_count;
71 struct ecc_stat tex_unique_sec_pipe1_count;
72 struct ecc_stat tex_unique_ded_pipe1_count;
73
74 struct ecc_stat l2_sec_count;
75 struct ecc_stat l2_ded_count;
76 } ecc_stats;
77
50 int cilp_preempt_pending_chid; 78 int cilp_preempt_pending_chid;
51}; 79};
52 80
diff --git a/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h b/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h
index b494482a..0480527c 100644
--- a/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h
+++ b/drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h
@@ -530,6 +530,98 @@ static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_status_double_err_detected_shm1_pe
530{ 530{
531 return 0x200; 531 return 0x200;
532} 532}
533static inline u32 gr_pri_gpc0_tpc0_sm_lrf_ecc_single_err_count_r(void)
534{
535 return 0x005046bc;
536}
537static inline u32 gr_pri_gpc0_tpc0_sm_lrf_ecc_double_err_count_r(void)
538{
539 return 0x005046c0;
540}
541static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_r(void)
542{
543 return 0x005044a4;
544}
545static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_corrected_m(void)
546{
547 return 0xff << 0;
548}
549static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_corrected_v(u32 r)
550{
551 return (r >> 0) & 0xff;
552}
553static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_detected_m(void)
554{
555 return 0xff << 8;
556}
557static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_detected_v(u32 r)
558{
559 return (r >> 8) & 0xff;
560}
561static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_double_detected_m(void)
562{
563 return 0xff << 16;
564}
565static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_double_detected_v(u32 r)
566{
567 return (r >> 16) & 0xff;
568}
569static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_r(void)
570{
571 return 0x005042c4;
572}
573static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_sel_default_f(void)
574{
575 return 0x0;
576}
577static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_sel_pipe0_f(void)
578{
579 return 0x1;
580}
581static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_sel_pipe1_f(void)
582{
583 return 0x2;
584}
585static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r(void)
586{
587 return 0x00504218;
588}
589static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_sec_m(void)
590{
591 return 0xffff << 0;
592}
593static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_sec_v(u32 r)
594{
595 return (r >> 0) & 0xffff;
596}
597static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_ded_m(void)
598{
599 return 0xffff << 16;
600}
601static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_ded_v(u32 r)
602{
603 return (r >> 16) & 0xffff;
604}
605static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r(void)
606{
607 return 0x005042ec;
608}
609static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_sec_m(void)
610{
611 return 0xffff << 0;
612}
613static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_sec_v(u32 r)
614{
615 return (r >> 0) & 0xffff;
616}
617static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_ded_m(void)
618{
619 return 0xffff << 16;
620}
621static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_ded_v(u32 r)
622{
623 return (r >> 16) & 0xffff;
624}
533static inline u32 gr_pri_be0_crop_status1_r(void) 625static inline u32 gr_pri_be0_crop_status1_r(void)
534{ 626{
535 return 0x00410134; 627 return 0x00410134;
diff --git a/drivers/gpu/nvgpu/gp10b/hw_ltc_gp10b.h b/drivers/gpu/nvgpu/gp10b/hw_ltc_gp10b.h
index 302c2243..5916f695 100644
--- a/drivers/gpu/nvgpu/gp10b/hw_ltc_gp10b.h
+++ b/drivers/gpu/nvgpu/gp10b/hw_ltc_gp10b.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. 2 * Copyright (c) 2014-2016, 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,
@@ -314,6 +314,26 @@ static inline u32 ltc_ltc0_lts0_intr_r(void)
314{ 314{
315 return 0x0014040c; 315 return 0x0014040c;
316} 316}
317static inline u32 ltc_ltc0_lts0_dstg_ecc_report_r(void)
318{
319 return 0x0014051c;
320}
321static inline u32 ltc_ltc0_lts0_dstg_ecc_report_sec_count_m(void)
322{
323 return 0xff << 0;
324}
325static inline u32 ltc_ltc0_lts0_dstg_ecc_report_sec_count_v(u32 r)
326{
327 return (r >> 0) & 0xff;
328}
329static inline u32 ltc_ltc0_lts0_dstg_ecc_report_ded_count_m(void)
330{
331 return 0xff << 16;
332}
333static inline u32 ltc_ltc0_lts0_dstg_ecc_report_ded_count_v(u32 r)
334{
335 return (r >> 16) & 0xff;
336}
317static inline u32 ltc_ltcs_ltss_tstg_cmgmt0_r(void) 337static inline u32 ltc_ltcs_ltss_tstg_cmgmt0_r(void)
318{ 338{
319 return 0x0017e2a0; 339 return 0x0017e2a0;
diff --git a/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c b/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c
index d0be86a4..e68e762d 100644
--- a/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c
+++ b/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c
@@ -133,21 +133,48 @@ static void gp10b_ltc_isr(struct gk20a *g)
133 if ((mc_intr & 1 << ltc) == 0) 133 if ((mc_intr & 1 << ltc) == 0)
134 continue; 134 continue;
135 for (slice = 0; slice < g->gr.slices_per_ltc; slice++) { 135 for (slice = 0; slice < g->gr.slices_per_ltc; slice++) {
136 ltc_intr = gk20a_readl(g, ltc_ltc0_lts0_intr_r() + 136 u32 offset = proj_ltc_stride_v() * ltc +
137 proj_ltc_stride_v() * ltc + 137 proj_lts_stride_v() * slice;
138 proj_lts_stride_v() * slice); 138 ltc_intr = gk20a_readl(g, ltc_ltc0_lts0_intr_r() + offset);
139 139
140 /* Detect and handle ECC errors */ 140 /* Detect and handle ECC errors */
141 if (ltc_intr & 141 if (ltc_intr &
142 ltc_ltcs_ltss_intr_ecc_sec_error_pending_f()) { 142 ltc_ltcs_ltss_intr_ecc_sec_error_pending_f()) {
143 u32 ecc_stats_reg_val;
144
143 gk20a_err(dev_from_gk20a(g), 145 gk20a_err(dev_from_gk20a(g),
144 "Single bit error detected in GPU L2!"); 146 "Single bit error detected in GPU L2!");
147
148 ecc_stats_reg_val =
149 gk20a_readl(g,
150 ltc_ltc0_lts0_dstg_ecc_report_r() + offset);
151 g->gr.t18x.ecc_stats.l2_sec_count.counters[ltc] +=
152 ltc_ltc0_lts0_dstg_ecc_report_sec_count_v(ecc_stats_reg_val);
153 ecc_stats_reg_val &=
154 ~(ltc_ltc0_lts0_dstg_ecc_report_sec_count_m());
155 gk20a_writel(g,
156 ltc_ltc0_lts0_dstg_ecc_report_r() + offset,
157 ecc_stats_reg_val);
158
145 g->ops.mm.l2_flush(g, true); 159 g->ops.mm.l2_flush(g, true);
146 } 160 }
147 if (ltc_intr & 161 if (ltc_intr &
148 ltc_ltcs_ltss_intr_ecc_ded_error_pending_f()) { 162 ltc_ltcs_ltss_intr_ecc_ded_error_pending_f()) {
163 u32 ecc_stats_reg_val;
164
149 gk20a_err(dev_from_gk20a(g), 165 gk20a_err(dev_from_gk20a(g),
150 "Double bit error detected in GPU L2!"); 166 "Double bit error detected in GPU L2!");
167
168 ecc_stats_reg_val =
169 gk20a_readl(g,
170 ltc_ltc0_lts0_dstg_ecc_report_r() + offset);
171 g->gr.t18x.ecc_stats.l2_ded_count.counters[ltc] +=
172 ltc_ltc0_lts0_dstg_ecc_report_ded_count_v(ecc_stats_reg_val);
173 ecc_stats_reg_val &=
174 ~(ltc_ltc0_lts0_dstg_ecc_report_ded_count_m());
175 gk20a_writel(g,
176 ltc_ltc0_lts0_dstg_ecc_report_r() + offset,
177 ecc_stats_reg_val);
151 } 178 }
152 179
153 gk20a_err(dev_from_gk20a(g), "ltc%d, slice %d: %08x", 180 gk20a_err(dev_from_gk20a(g), "ltc%d, slice %d: %08x",
diff --git a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c
index 8bddff3d..0cfb1d91 100644
--- a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c
+++ b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c
@@ -26,9 +26,14 @@
26#include <linux/tegra_pm_domains.h> 26#include <linux/tegra_pm_domains.h>
27#include <linux/reset.h> 27#include <linux/reset.h>
28#include <soc/tegra/tegra_bpmp.h> 28#include <soc/tegra/tegra_bpmp.h>
29#include <linux/hashtable.h>
29#include "gk20a/platform_gk20a.h" 30#include "gk20a/platform_gk20a.h"
30#include "gk20a/gk20a.h" 31#include "gk20a/gk20a.h"
31#include "platform_tegra.h" 32#include "platform_tegra.h"
33#include "gr_gp10b.h"
34#include "ltc_gp10b.h"
35#include "hw_gr_gp10b.h"
36#include "hw_ltc_gp10b.h"
32 37
33#define GP10B_MAX_SUPPORTED_FREQS 11 38#define GP10B_MAX_SUPPORTED_FREQS 11
34static unsigned long gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS]; 39static unsigned long gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS];
@@ -40,6 +45,8 @@ static struct {
40 {"gpu", 1000000000}, 45 {"gpu", 1000000000},
41 {"gpu_sys", 204000000} }; 46 {"gpu_sys", 204000000} };
42 47
48static void gr_gp10b_remove_sysfs(struct device *dev);
49
43/* 50/*
44 * gp10b_tegra_get_clocks() 51 * gp10b_tegra_get_clocks()
45 * 52 *
@@ -144,6 +151,8 @@ static int gp10b_tegra_remove(struct platform_device *pdev)
144 /* remove gk20a power subdomain from host1x */ 151 /* remove gk20a power subdomain from host1x */
145 nvhost_unregister_client_domain(dev_to_genpd(&pdev->dev)); 152 nvhost_unregister_client_domain(dev_to_genpd(&pdev->dev));
146 153
154 gr_gp10b_remove_sysfs(&pdev->dev);
155
147 return 0; 156 return 0;
148 157
149} 158}
@@ -345,3 +354,322 @@ struct gk20a_platform t18x_gpu_tegra_platform = {
345 354
346 .force_reset_in_do_idle = true, 355 .force_reset_in_do_idle = true,
347}; 356};
357
358
359#define ECC_STAT_NAME_MAX_SIZE 100
360
361
362DEFINE_HASHTABLE(ecc_hash_table, 5);
363
364static struct device_attribute *dev_attr_sm_lrf_ecc_single_err_count_array;
365static struct device_attribute *dev_attr_sm_lrf_ecc_double_err_count_array;
366
367static struct device_attribute *dev_attr_sm_shm_ecc_sec_count_array;
368static struct device_attribute *dev_attr_sm_shm_ecc_sed_count_array;
369static struct device_attribute *dev_attr_sm_shm_ecc_ded_count_array;
370
371static struct device_attribute *dev_attr_tex_ecc_total_sec_pipe0_count_array;
372static struct device_attribute *dev_attr_tex_ecc_total_ded_pipe0_count_array;
373static struct device_attribute *dev_attr_tex_ecc_unique_sec_pipe0_count_array;
374static struct device_attribute *dev_attr_tex_ecc_unique_ded_pipe0_count_array;
375static struct device_attribute *dev_attr_tex_ecc_total_sec_pipe1_count_array;
376static struct device_attribute *dev_attr_tex_ecc_total_ded_pipe1_count_array;
377static struct device_attribute *dev_attr_tex_ecc_unique_sec_pipe1_count_array;
378static struct device_attribute *dev_attr_tex_ecc_unique_ded_pipe1_count_array;
379
380static struct device_attribute *dev_attr_l2_ecc_sec_count_array;
381static struct device_attribute *dev_attr_l2_ecc_ded_count_array;
382
383
384static u32 gen_ecc_hash_key(char *str)
385{
386 int i = 0;
387 u32 hash_key = 0;
388
389 while (str[i]) {
390 hash_key += (u32)(str[i]);
391 i++;
392 };
393
394 return hash_key;
395}
396
397static ssize_t ecc_stat_show(struct device *dev,
398 struct device_attribute *attr,
399 char *buf)
400{
401 const char *ecc_stat_full_name = attr->attr.name;
402 const char *ecc_stat_base_name;
403 unsigned int hw_unit;
404 struct ecc_stat *ecc_stat;
405 u32 hash_key;
406
407 if (sscanf(ecc_stat_full_name, "ltc%u", &hw_unit) == 1) {
408 ecc_stat_base_name = &(ecc_stat_full_name[strlen("ltc0_")]);
409 } else if (sscanf(ecc_stat_full_name, "gpc0_tpc%u", &hw_unit) == 1) {
410 ecc_stat_base_name = &(ecc_stat_full_name[strlen("gpc0_tpc0_")]);
411 } else {
412 return snprintf(buf,
413 PAGE_SIZE,
414 "Error: Invalid ECC stat name!\n");
415 }
416
417 hash_key = gen_ecc_hash_key((char *)ecc_stat_base_name);
418 hash_for_each_possible(ecc_hash_table,
419 ecc_stat,
420 hash_node,
421 hash_key) {
422 if (!strcmp(ecc_stat_full_name, ecc_stat->names[hw_unit]))
423 return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stat->counters[hw_unit]);
424 }
425
426 return snprintf(buf, PAGE_SIZE, "Error: No ECC stat found!\n");
427}
428
429static int ecc_stat_create(struct platform_device *dev,
430 int is_l2,
431 char *ecc_stat_name,
432 struct ecc_stat *ecc_stat,
433 struct device_attribute *dev_attr_array)
434{
435 int error = 0;
436 struct gk20a *g = get_gk20a(dev);
437 int num_hw_units = 0;
438 int hw_unit = 0;
439 u32 hash_key = 0;
440
441 if (is_l2)
442 num_hw_units = g->ltc_count;
443 else
444 num_hw_units = g->gr.tpc_count;
445
446 /* Allocate arrays */
447 dev_attr_array = kzalloc(sizeof(struct device_attribute) * num_hw_units, GFP_KERNEL);
448 ecc_stat->counters = kzalloc(sizeof(u32) * num_hw_units, GFP_KERNEL);
449 ecc_stat->names = kzalloc(sizeof(char *) * num_hw_units, GFP_KERNEL);
450 for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
451 ecc_stat->names[hw_unit] = kzalloc(sizeof(char) * ECC_STAT_NAME_MAX_SIZE, GFP_KERNEL);
452 }
453
454 for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
455 /* Fill in struct device_attribute members */
456 if (is_l2)
457 snprintf(ecc_stat->names[hw_unit],
458 ECC_STAT_NAME_MAX_SIZE,
459 "ltc%d_%s",
460 hw_unit,
461 ecc_stat_name);
462 else
463 snprintf(ecc_stat->names[hw_unit],
464 ECC_STAT_NAME_MAX_SIZE,
465 "gpc0_tpc%d_%s",
466 hw_unit,
467 ecc_stat_name);
468 dev_attr_array[hw_unit].attr.name = ecc_stat->names[hw_unit];
469 dev_attr_array[hw_unit].attr.mode = VERIFY_OCTAL_PERMISSIONS(S_IRUGO);
470 dev_attr_array[hw_unit].show = ecc_stat_show;
471 dev_attr_array[hw_unit].store = NULL;
472
473 /* Create sysfs file */
474 error |= device_create_file(&dev->dev,
475 &dev_attr_array[hw_unit]);
476 }
477
478 /* Add hash table entry */
479 hash_key = gen_ecc_hash_key(ecc_stat_name);
480 hash_add(ecc_hash_table,
481 &ecc_stat->hash_node,
482 hash_key);
483
484 return error;
485}
486
487static void ecc_stat_remove(struct device *dev,
488 int is_l2,
489 struct ecc_stat *ecc_stat,
490 struct device_attribute *dev_attr_array)
491{
492 struct platform_device *ndev = to_platform_device(dev);
493 struct gk20a *g = get_gk20a(ndev);
494 int num_hw_units = 0;
495 int hw_unit = 0;
496
497 if (is_l2)
498 num_hw_units = g->ltc_count;
499 else
500 num_hw_units = g->gr.tpc_count;
501
502 /* Remove sysfs files */
503 for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
504 device_remove_file(dev, &dev_attr_array[hw_unit]);
505 }
506
507 /* Remove hash table entry */
508 hash_del(&ecc_stat->hash_node);
509
510 /* Free arrays */
511 kfree(ecc_stat->counters);
512 for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
513 kfree(ecc_stat->names[hw_unit]);
514 }
515 kfree(ecc_stat->names);
516 kfree(dev_attr_array);
517}
518
519void gr_gp10b_create_sysfs(struct platform_device *dev)
520{
521 int error = 0;
522 struct gk20a *g = get_gk20a(dev);
523
524 error |= ecc_stat_create(dev,
525 0,
526 "sm_lrf_ecc_single_err_count",
527 &g->gr.t18x.ecc_stats.sm_lrf_single_err_count,
528 dev_attr_sm_lrf_ecc_single_err_count_array);
529 error |= ecc_stat_create(dev,
530 0,
531 "sm_lrf_ecc_double_err_count",
532 &g->gr.t18x.ecc_stats.sm_lrf_double_err_count,
533 dev_attr_sm_lrf_ecc_double_err_count_array);
534
535 error |= ecc_stat_create(dev,
536 0,
537 "sm_shm_ecc_sec_count",
538 &g->gr.t18x.ecc_stats.sm_shm_sec_count,
539 dev_attr_sm_shm_ecc_sec_count_array);
540 error |= ecc_stat_create(dev,
541 0,
542 "sm_shm_ecc_sed_count",
543 &g->gr.t18x.ecc_stats.sm_shm_sed_count,
544 dev_attr_sm_shm_ecc_sed_count_array);
545 error |= ecc_stat_create(dev,
546 0,
547 "sm_shm_ecc_ded_count",
548 &g->gr.t18x.ecc_stats.sm_shm_ded_count,
549 dev_attr_sm_shm_ecc_ded_count_array);
550
551 error |= ecc_stat_create(dev,
552 0,
553 "tex_ecc_total_sec_pipe0_count",
554 &g->gr.t18x.ecc_stats.tex_total_sec_pipe0_count,
555 dev_attr_tex_ecc_total_sec_pipe0_count_array);
556 error |= ecc_stat_create(dev,
557 0,
558 "tex_ecc_total_ded_pipe0_count",
559 &g->gr.t18x.ecc_stats.tex_total_ded_pipe0_count,
560 dev_attr_tex_ecc_total_ded_pipe0_count_array);
561 error |= ecc_stat_create(dev,
562 0,
563 "tex_ecc_unique_sec_pipe0_count",
564 &g->gr.t18x.ecc_stats.tex_unique_sec_pipe0_count,
565 dev_attr_tex_ecc_unique_sec_pipe0_count_array);
566 error |= ecc_stat_create(dev,
567 0,
568 "tex_ecc_unique_ded_pipe0_count",
569 &g->gr.t18x.ecc_stats.tex_unique_ded_pipe0_count,
570 dev_attr_tex_ecc_unique_ded_pipe0_count_array);
571 error |= ecc_stat_create(dev,
572 0,
573 "tex_ecc_total_sec_pipe1_count",
574 &g->gr.t18x.ecc_stats.tex_total_sec_pipe1_count,
575 dev_attr_tex_ecc_total_sec_pipe1_count_array);
576 error |= ecc_stat_create(dev,
577 0,
578 "tex_ecc_total_ded_pipe1_count",
579 &g->gr.t18x.ecc_stats.tex_total_ded_pipe1_count,
580 dev_attr_tex_ecc_total_ded_pipe1_count_array);
581 error |= ecc_stat_create(dev,
582 0,
583 "tex_ecc_unique_sec_pipe1_count",
584 &g->gr.t18x.ecc_stats.tex_unique_sec_pipe1_count,
585 dev_attr_tex_ecc_unique_sec_pipe1_count_array);
586 error |= ecc_stat_create(dev,
587 0,
588 "tex_ecc_unique_ded_pipe1_count",
589 &g->gr.t18x.ecc_stats.tex_unique_ded_pipe1_count,
590 dev_attr_tex_ecc_unique_ded_pipe1_count_array);
591
592 error |= ecc_stat_create(dev,
593 1,
594 "lts0_ecc_sec_count",
595 &g->gr.t18x.ecc_stats.l2_sec_count,
596 dev_attr_l2_ecc_sec_count_array);
597 error |= ecc_stat_create(dev,
598 1,
599 "lts0_ecc_ded_count",
600 &g->gr.t18x.ecc_stats.l2_ded_count,
601 dev_attr_l2_ecc_ded_count_array);
602
603 if (error)
604 dev_err(&dev->dev, "Failed to create sysfs attributes!\n");
605}
606
607static void gr_gp10b_remove_sysfs(struct device *dev)
608{
609 struct platform_device *ndev = to_platform_device(dev);
610 struct gk20a *g = get_gk20a(ndev);
611
612 ecc_stat_remove(dev,
613 0,
614 &g->gr.t18x.ecc_stats.sm_lrf_single_err_count,
615 dev_attr_sm_lrf_ecc_single_err_count_array);
616 ecc_stat_remove(dev,
617 0,
618 &g->gr.t18x.ecc_stats.sm_lrf_double_err_count,
619 dev_attr_sm_lrf_ecc_double_err_count_array);
620
621 ecc_stat_remove(dev,
622 0,
623 &g->gr.t18x.ecc_stats.sm_shm_sec_count,
624 dev_attr_sm_shm_ecc_sec_count_array);
625 ecc_stat_remove(dev,
626 0,
627 &g->gr.t18x.ecc_stats.sm_shm_sed_count,
628 dev_attr_sm_shm_ecc_sed_count_array);
629 ecc_stat_remove(dev,
630 0,
631 &g->gr.t18x.ecc_stats.sm_shm_ded_count,
632 dev_attr_sm_shm_ecc_ded_count_array);
633
634 ecc_stat_remove(dev,
635 0,
636 &g->gr.t18x.ecc_stats.tex_total_sec_pipe0_count,
637 dev_attr_tex_ecc_total_sec_pipe0_count_array);
638 ecc_stat_remove(dev,
639 0,
640 &g->gr.t18x.ecc_stats.tex_total_ded_pipe0_count,
641 dev_attr_tex_ecc_total_ded_pipe0_count_array);
642 ecc_stat_remove(dev,
643 0,
644 &g->gr.t18x.ecc_stats.tex_unique_sec_pipe0_count,
645 dev_attr_tex_ecc_unique_sec_pipe0_count_array);
646 ecc_stat_remove(dev,
647 0,
648 &g->gr.t18x.ecc_stats.tex_unique_ded_pipe0_count,
649 dev_attr_tex_ecc_unique_ded_pipe0_count_array);
650 ecc_stat_remove(dev,
651 0,
652 &g->gr.t18x.ecc_stats.tex_total_sec_pipe1_count,
653 dev_attr_tex_ecc_total_sec_pipe1_count_array);
654 ecc_stat_remove(dev,
655 0,
656 &g->gr.t18x.ecc_stats.tex_total_ded_pipe1_count,
657 dev_attr_tex_ecc_total_ded_pipe1_count_array);
658 ecc_stat_remove(dev,
659 0,
660 &g->gr.t18x.ecc_stats.tex_unique_sec_pipe1_count,
661 dev_attr_tex_ecc_unique_sec_pipe1_count_array);
662 ecc_stat_remove(dev,
663 0,
664 &g->gr.t18x.ecc_stats.tex_unique_ded_pipe1_count,
665 dev_attr_tex_ecc_unique_ded_pipe1_count_array);
666
667 ecc_stat_remove(dev,
668 1,
669 &g->gr.t18x.ecc_stats.l2_sec_count,
670 dev_attr_l2_ecc_sec_count_array);
671 ecc_stat_remove(dev,
672 1,
673 &g->gr.t18x.ecc_stats.l2_ded_count,
674 dev_attr_l2_ecc_ded_count_array);
675}