diff options
author | Adeel Raza <araza@nvidia.com> | 2015-12-11 19:16:21 -0500 |
---|---|---|
committer | Deepak Nibade <dnibade@nvidia.com> | 2016-12-27 04:52:10 -0500 |
commit | e9b03e903c10e1fce9daf5fa7e51b8c4a0b65c95 (patch) | |
tree | 7d55abac9face13a5753fc26a9817743606e8870 | |
parent | f7d327985fca67266ea409e24c0ef6505d98f338 (diff) |
gpu: nvgpu: gp10b: add ECC stats sysfs nodes
Add sysfs nodes for querying ECC single/double bit error counts.
Bug 1699676
Change-Id: I6d5219facadaa17207ac759b88fe19077207d8f1
Signed-off-by: Adeel Raza <araza@nvidia.com>
Reviewed-on: http://git-master/r/935363
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/gr_gp10b.c | 145 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/gr_gp10b.h | 28 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/hw_gr_gp10b.h | 92 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/hw_ltc_gp10b.h | 22 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/ltc_gp10b.c | 33 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c | 328 |
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 { | |||
35 | void gp10b_init_gr(struct gpu_ops *ops); | 35 | void gp10b_init_gr(struct gpu_ops *ops); |
36 | int gr_gp10b_alloc_buffer(struct vm_gk20a *vm, size_t size, | 36 | int gr_gp10b_alloc_buffer(struct vm_gk20a *vm, size_t size, |
37 | struct mem_desc *mem); | 37 | struct mem_desc *mem); |
38 | void gr_gp10b_create_sysfs(struct platform_device *dev); | ||
39 | |||
40 | struct ecc_stat { | ||
41 | char **names; | ||
42 | u32 *counters; | ||
43 | struct hlist_node hash_node; | ||
44 | }; | ||
38 | 45 | ||
39 | struct gr_t18x { | 46 | struct 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 | } |
533 | static inline u32 gr_pri_gpc0_tpc0_sm_lrf_ecc_single_err_count_r(void) | ||
534 | { | ||
535 | return 0x005046bc; | ||
536 | } | ||
537 | static inline u32 gr_pri_gpc0_tpc0_sm_lrf_ecc_double_err_count_r(void) | ||
538 | { | ||
539 | return 0x005046c0; | ||
540 | } | ||
541 | static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_r(void) | ||
542 | { | ||
543 | return 0x005044a4; | ||
544 | } | ||
545 | static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_corrected_m(void) | ||
546 | { | ||
547 | return 0xff << 0; | ||
548 | } | ||
549 | static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_corrected_v(u32 r) | ||
550 | { | ||
551 | return (r >> 0) & 0xff; | ||
552 | } | ||
553 | static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_detected_m(void) | ||
554 | { | ||
555 | return 0xff << 8; | ||
556 | } | ||
557 | static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_single_detected_v(u32 r) | ||
558 | { | ||
559 | return (r >> 8) & 0xff; | ||
560 | } | ||
561 | static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_double_detected_m(void) | ||
562 | { | ||
563 | return 0xff << 16; | ||
564 | } | ||
565 | static inline u32 gr_pri_gpc0_tpc0_sm_shm_ecc_err_count_double_detected_v(u32 r) | ||
566 | { | ||
567 | return (r >> 16) & 0xff; | ||
568 | } | ||
569 | static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_r(void) | ||
570 | { | ||
571 | return 0x005042c4; | ||
572 | } | ||
573 | static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_sel_default_f(void) | ||
574 | { | ||
575 | return 0x0; | ||
576 | } | ||
577 | static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_sel_pipe0_f(void) | ||
578 | { | ||
579 | return 0x1; | ||
580 | } | ||
581 | static inline u32 gr_pri_gpc0_tpc0_tex_m_routing_sel_pipe1_f(void) | ||
582 | { | ||
583 | return 0x2; | ||
584 | } | ||
585 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_r(void) | ||
586 | { | ||
587 | return 0x00504218; | ||
588 | } | ||
589 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_sec_m(void) | ||
590 | { | ||
591 | return 0xffff << 0; | ||
592 | } | ||
593 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_sec_v(u32 r) | ||
594 | { | ||
595 | return (r >> 0) & 0xffff; | ||
596 | } | ||
597 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_ded_m(void) | ||
598 | { | ||
599 | return 0xffff << 16; | ||
600 | } | ||
601 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_total_ded_v(u32 r) | ||
602 | { | ||
603 | return (r >> 16) & 0xffff; | ||
604 | } | ||
605 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_r(void) | ||
606 | { | ||
607 | return 0x005042ec; | ||
608 | } | ||
609 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_sec_m(void) | ||
610 | { | ||
611 | return 0xffff << 0; | ||
612 | } | ||
613 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_sec_v(u32 r) | ||
614 | { | ||
615 | return (r >> 0) & 0xffff; | ||
616 | } | ||
617 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_ded_m(void) | ||
618 | { | ||
619 | return 0xffff << 16; | ||
620 | } | ||
621 | static inline u32 gr_pri_gpc0_tpc0_tex_m_ecc_cnt_unique_ded_v(u32 r) | ||
622 | { | ||
623 | return (r >> 16) & 0xffff; | ||
624 | } | ||
533 | static inline u32 gr_pri_be0_crop_status1_r(void) | 625 | static 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 | } |
317 | static inline u32 ltc_ltc0_lts0_dstg_ecc_report_r(void) | ||
318 | { | ||
319 | return 0x0014051c; | ||
320 | } | ||
321 | static inline u32 ltc_ltc0_lts0_dstg_ecc_report_sec_count_m(void) | ||
322 | { | ||
323 | return 0xff << 0; | ||
324 | } | ||
325 | static inline u32 ltc_ltc0_lts0_dstg_ecc_report_sec_count_v(u32 r) | ||
326 | { | ||
327 | return (r >> 0) & 0xff; | ||
328 | } | ||
329 | static inline u32 ltc_ltc0_lts0_dstg_ecc_report_ded_count_m(void) | ||
330 | { | ||
331 | return 0xff << 16; | ||
332 | } | ||
333 | static inline u32 ltc_ltc0_lts0_dstg_ecc_report_ded_count_v(u32 r) | ||
334 | { | ||
335 | return (r >> 16) & 0xff; | ||
336 | } | ||
317 | static inline u32 ltc_ltcs_ltss_tstg_cmgmt0_r(void) | 337 | static 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 |
34 | static unsigned long gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS]; | 39 | static 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 | ||
48 | static 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 | |||
362 | DEFINE_HASHTABLE(ecc_hash_table, 5); | ||
363 | |||
364 | static struct device_attribute *dev_attr_sm_lrf_ecc_single_err_count_array; | ||
365 | static struct device_attribute *dev_attr_sm_lrf_ecc_double_err_count_array; | ||
366 | |||
367 | static struct device_attribute *dev_attr_sm_shm_ecc_sec_count_array; | ||
368 | static struct device_attribute *dev_attr_sm_shm_ecc_sed_count_array; | ||
369 | static struct device_attribute *dev_attr_sm_shm_ecc_ded_count_array; | ||
370 | |||
371 | static struct device_attribute *dev_attr_tex_ecc_total_sec_pipe0_count_array; | ||
372 | static struct device_attribute *dev_attr_tex_ecc_total_ded_pipe0_count_array; | ||
373 | static struct device_attribute *dev_attr_tex_ecc_unique_sec_pipe0_count_array; | ||
374 | static struct device_attribute *dev_attr_tex_ecc_unique_ded_pipe0_count_array; | ||
375 | static struct device_attribute *dev_attr_tex_ecc_total_sec_pipe1_count_array; | ||
376 | static struct device_attribute *dev_attr_tex_ecc_total_ded_pipe1_count_array; | ||
377 | static struct device_attribute *dev_attr_tex_ecc_unique_sec_pipe1_count_array; | ||
378 | static struct device_attribute *dev_attr_tex_ecc_unique_ded_pipe1_count_array; | ||
379 | |||
380 | static struct device_attribute *dev_attr_l2_ecc_sec_count_array; | ||
381 | static struct device_attribute *dev_attr_l2_ecc_ded_count_array; | ||
382 | |||
383 | |||
384 | static 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 | |||
397 | static 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 | |||
429 | static 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 | |||
487 | static 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 | |||
519 | void 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 | |||
607 | static 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 | } | ||