summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c777
1 files changed, 777 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c
new file mode 100644
index 00000000..b944844e
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c
@@ -0,0 +1,777 @@
1/*
2 * GP10B Tegra Platform Interface
3 *
4 * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15
16#include <linux/of_platform.h>
17#include <linux/debugfs.h>
18#include <linux/dma-buf.h>
19#include <linux/nvmap.h>
20#include <linux/reset.h>
21#include <linux/platform/tegra/emc_bwmgr.h>
22
23#include <uapi/linux/nvgpu.h>
24
25#include <soc/tegra/tegra_bpmp.h>
26#include <soc/tegra/tegra_powergate.h>
27
28#include <nvgpu/kmem.h>
29#include <nvgpu/bug.h>
30#include <nvgpu/enabled.h>
31#include <nvgpu/hashtable.h>
32#include <nvgpu/nvhost.h>
33
34#include "os_linux.h"
35
36#include "clk.h"
37
38#include "gk20a/gk20a.h"
39
40#include "platform_gk20a.h"
41#include "platform_gk20a_tegra.h"
42#include "gp10b/platform_gp10b.h"
43#include "platform_gp10b_tegra.h"
44#include "scale.h"
45
46/* Select every GP10B_FREQ_SELECT_STEP'th frequency from h/w table */
47#define GP10B_FREQ_SELECT_STEP 8
48/* Max number of freq supported in h/w */
49#define GP10B_MAX_SUPPORTED_FREQS 120
50static unsigned long
51gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS / GP10B_FREQ_SELECT_STEP];
52
53#define TEGRA_GP10B_BW_PER_FREQ 64
54#define TEGRA_DDR4_BW_PER_FREQ 16
55
56#define EMC_BW_RATIO (TEGRA_GP10B_BW_PER_FREQ / TEGRA_DDR4_BW_PER_FREQ)
57
58static struct {
59 char *name;
60 unsigned long default_rate;
61} tegra_gp10b_clocks[] = {
62 {"gpu", 1000000000},
63 {"gpu_sys", 204000000} };
64
65static void gr_gp10b_remove_sysfs(struct device *dev);
66
67/*
68 * gp10b_tegra_get_clocks()
69 *
70 * This function finds clocks in tegra platform and populates
71 * the clock information to gp10b platform data.
72 */
73
74int gp10b_tegra_get_clocks(struct device *dev)
75{
76 struct gk20a_platform *platform = dev_get_drvdata(dev);
77 unsigned int i;
78
79 platform->num_clks = 0;
80 for (i = 0; i < ARRAY_SIZE(tegra_gp10b_clocks); i++) {
81 long rate = tegra_gp10b_clocks[i].default_rate;
82 struct clk *c;
83
84 c = clk_get(dev, tegra_gp10b_clocks[i].name);
85 if (IS_ERR(c)) {
86 nvgpu_err(platform->g, "cannot get clock %s",
87 tegra_gp10b_clocks[i].name);
88 } else {
89 clk_set_rate(c, rate);
90 platform->clk[i] = c;
91 }
92 }
93 platform->num_clks = i;
94
95 return 0;
96}
97
98static void gp10b_tegra_scale_init(struct device *dev)
99{
100 struct gk20a_platform *platform = gk20a_get_platform(dev);
101 struct gk20a_scale_profile *profile = platform->g->scale_profile;
102 struct tegra_bwmgr_client *bwmgr_handle;
103
104 if (!profile)
105 return;
106
107 bwmgr_handle = tegra_bwmgr_register(TEGRA_BWMGR_CLIENT_GPU);
108 if (!bwmgr_handle)
109 return;
110
111 profile->private_data = (void *)bwmgr_handle;
112}
113
114static void gp10b_tegra_scale_exit(struct device *dev)
115{
116 struct gk20a_platform *platform = gk20a_get_platform(dev);
117 struct gk20a_scale_profile *profile = platform->g->scale_profile;
118
119 if (profile)
120 tegra_bwmgr_unregister(
121 (struct tegra_bwmgr_client *)profile->private_data);
122}
123
124static int gp10b_tegra_probe(struct device *dev)
125{
126 struct gk20a_platform *platform = dev_get_drvdata(dev);
127#ifdef CONFIG_TEGRA_GK20A_NVHOST
128 int ret;
129
130 ret = nvgpu_get_nvhost_dev(platform->g);
131 if (ret)
132 return ret;
133#endif
134
135 platform->bypass_smmu = !device_is_iommuable(dev);
136 platform->disable_bigpage = platform->bypass_smmu;
137
138 platform->g->gr.t18x.ctx_vars.dump_ctxsw_stats_on_channel_close
139 = false;
140 platform->g->gr.t18x.ctx_vars.dump_ctxsw_stats_on_channel_close
141 = false;
142
143 platform->g->gr.t18x.ctx_vars.force_preemption_gfxp = false;
144 platform->g->gr.t18x.ctx_vars.force_preemption_cilp = false;
145
146 gp10b_tegra_get_clocks(dev);
147 nvgpu_linux_init_clk_support(platform->g);
148 gk20a_tegra_init_secure_alloc(platform->g);
149
150 return 0;
151}
152
153static int gp10b_tegra_late_probe(struct device *dev)
154{
155 /* Cause early VPR resize */
156 gk20a_tegra_secure_page_alloc(dev);
157
158 /* Initialise tegra specific scaling quirks */
159 gp10b_tegra_scale_init(dev);
160 return 0;
161}
162
163int gp10b_tegra_remove(struct device *dev)
164{
165 gr_gp10b_remove_sysfs(dev);
166
167 /* deinitialise tegra specific scaling quirks */
168 gp10b_tegra_scale_exit(dev);
169
170#ifdef CONFIG_TEGRA_GK20A_NVHOST
171 nvgpu_free_nvhost_dev(get_gk20a(dev));
172#endif
173
174 return 0;
175}
176
177static bool gp10b_tegra_is_railgated(struct device *dev)
178{
179 bool ret = false;
180
181 if (tegra_bpmp_running())
182 ret = !tegra_powergate_is_powered(TEGRA186_POWER_DOMAIN_GPU);
183
184 return ret;
185}
186
187static int gp10b_tegra_railgate(struct device *dev)
188{
189 struct gk20a_platform *platform = gk20a_get_platform(dev);
190 struct gk20a_scale_profile *profile = platform->g->scale_profile;
191
192 /* remove emc frequency floor */
193 if (profile)
194 tegra_bwmgr_set_emc(
195 (struct tegra_bwmgr_client *)profile->private_data,
196 0, TEGRA_BWMGR_SET_EMC_FLOOR);
197
198 if (tegra_bpmp_running() &&
199 tegra_powergate_is_powered(TEGRA186_POWER_DOMAIN_GPU)) {
200 int i;
201 for (i = 0; i < platform->num_clks; i++) {
202 if (platform->clk[i])
203 clk_disable_unprepare(platform->clk[i]);
204 }
205 tegra_powergate_partition(TEGRA186_POWER_DOMAIN_GPU);
206 }
207 return 0;
208}
209
210static int gp10b_tegra_unrailgate(struct device *dev)
211{
212 int ret = 0;
213 struct gk20a_platform *platform = gk20a_get_platform(dev);
214 struct gk20a_scale_profile *profile = platform->g->scale_profile;
215
216 if (tegra_bpmp_running()) {
217 int i;
218 ret = tegra_unpowergate_partition(TEGRA186_POWER_DOMAIN_GPU);
219 for (i = 0; i < platform->num_clks; i++) {
220 if (platform->clk[i])
221 clk_prepare_enable(platform->clk[i]);
222 }
223 }
224
225 /* to start with set emc frequency floor to max rate*/
226 if (profile)
227 tegra_bwmgr_set_emc(
228 (struct tegra_bwmgr_client *)profile->private_data,
229 tegra_bwmgr_get_max_emc_rate(),
230 TEGRA_BWMGR_SET_EMC_FLOOR);
231 return ret;
232}
233
234static int gp10b_tegra_suspend(struct device *dev)
235{
236 return 0;
237}
238
239int gp10b_tegra_reset_assert(struct device *dev)
240{
241 struct gk20a_platform *platform = gk20a_get_platform(dev);
242 int ret = 0;
243
244 if (!platform->reset_control)
245 return -EINVAL;
246
247 ret = reset_control_assert(platform->reset_control);
248
249 return ret;
250}
251
252int gp10b_tegra_reset_deassert(struct device *dev)
253{
254 struct gk20a_platform *platform = gk20a_get_platform(dev);
255 int ret = 0;
256
257 if (!platform->reset_control)
258 return -EINVAL;
259
260 ret = reset_control_deassert(platform->reset_control);
261
262 return ret;
263}
264
265static void gp10b_tegra_prescale(struct device *dev)
266{
267 struct gk20a *g = get_gk20a(dev);
268 u32 avg = 0;
269
270 gk20a_dbg_fn("");
271
272 nvgpu_pmu_load_norm(g, &avg);
273
274 gk20a_dbg_fn("done");
275}
276
277static void gp10b_tegra_postscale(struct device *pdev,
278 unsigned long freq)
279{
280 struct gk20a_platform *platform = gk20a_get_platform(pdev);
281 struct gk20a_scale_profile *profile = platform->g->scale_profile;
282 struct gk20a *g = get_gk20a(pdev);
283 unsigned long emc_rate;
284
285 gk20a_dbg_fn("");
286 if (profile && !gp10b_tegra_is_railgated(pdev)) {
287 unsigned long emc_scale;
288
289 if (freq <= gp10b_freq_table[0])
290 emc_scale = 0;
291 else
292 emc_scale = g->emc3d_ratio;
293
294 emc_rate = (freq * EMC_BW_RATIO * emc_scale) / 1000;
295
296 if (emc_rate > tegra_bwmgr_get_max_emc_rate())
297 emc_rate = tegra_bwmgr_get_max_emc_rate();
298
299 tegra_bwmgr_set_emc(
300 (struct tegra_bwmgr_client *)profile->private_data,
301 emc_rate, TEGRA_BWMGR_SET_EMC_FLOOR);
302 }
303 gk20a_dbg_fn("done");
304}
305
306static long gp10b_round_clk_rate(struct device *dev, unsigned long rate)
307{
308 struct gk20a *g = get_gk20a(dev);
309 struct gk20a_scale_profile *profile = g->scale_profile;
310 unsigned long *freq_table = profile->devfreq_profile.freq_table;
311 int max_states = profile->devfreq_profile.max_state;
312 int i;
313
314 for (i = 0; i < max_states; ++i)
315 if (freq_table[i] >= rate)
316 return freq_table[i];
317
318 return freq_table[max_states - 1];
319}
320
321static int gp10b_clk_get_freqs(struct device *dev,
322 unsigned long **freqs, int *num_freqs)
323{
324 struct gk20a_platform *platform = gk20a_get_platform(dev);
325 unsigned long max_rate;
326 unsigned long new_rate = 0, prev_rate = 0;
327 int i = 0, freq_counter = 0;
328
329 max_rate = clk_round_rate(platform->clk[0], (UINT_MAX - 1));
330
331 /*
332 * Walk the h/w frequency table and only select
333 * GP10B_FREQ_SELECT_STEP'th frequencies and
334 * add MAX freq to last
335 */
336 for (; i < GP10B_MAX_SUPPORTED_FREQS; ++i) {
337 prev_rate = new_rate;
338 new_rate = clk_round_rate(platform->clk[0], prev_rate + 1);
339
340 if (i % GP10B_FREQ_SELECT_STEP == 0 ||
341 new_rate == max_rate) {
342 gp10b_freq_table[freq_counter++] = new_rate;
343
344 if (new_rate == max_rate)
345 break;
346 }
347 }
348
349 WARN_ON(i == GP10B_MAX_SUPPORTED_FREQS);
350
351 /* Fill freq table */
352 *freqs = gp10b_freq_table;
353 *num_freqs = freq_counter;
354
355 gk20a_dbg_info("min rate: %ld max rate: %ld num_of_freq %d\n",
356 gp10b_freq_table[0], max_rate, *num_freqs);
357
358 return 0;
359}
360
361struct gk20a_platform gp10b_tegra_platform = {
362 .has_syncpoints = true,
363
364 /* power management configuration */
365 .railgate_delay_init = 500,
366
367 /* power management configuration */
368 .can_railgate_init = true,
369 .enable_elpg = true,
370 .can_elpg_init = true,
371 .enable_blcg = true,
372 .enable_slcg = true,
373 .enable_elcg = true,
374 .can_slcg = true,
375 .can_blcg = true,
376 .can_elcg = true,
377 .enable_aelpg = true,
378 .enable_perfmon = true,
379
380 /* ptimer src frequency in hz*/
381 .ptimer_src_freq = 31250000,
382
383 .ch_wdt_timeout_ms = 5000,
384
385 .probe = gp10b_tegra_probe,
386 .late_probe = gp10b_tegra_late_probe,
387 .remove = gp10b_tegra_remove,
388
389 /* power management callbacks */
390 .suspend = gp10b_tegra_suspend,
391 .railgate = gp10b_tegra_railgate,
392 .unrailgate = gp10b_tegra_unrailgate,
393 .is_railgated = gp10b_tegra_is_railgated,
394
395 .busy = gk20a_tegra_busy,
396 .idle = gk20a_tegra_idle,
397
398 .dump_platform_dependencies = gk20a_tegra_debug_dump,
399
400 .has_cde = true,
401
402 .clk_round_rate = gp10b_round_clk_rate,
403 .get_clk_freqs = gp10b_clk_get_freqs,
404
405 /* frequency scaling configuration */
406 .prescale = gp10b_tegra_prescale,
407 .postscale = gp10b_tegra_postscale,
408 .devfreq_governor = "nvhost_podgov",
409
410 .qos_notify = gk20a_scale_qos_notify,
411
412 .reset_assert = gp10b_tegra_reset_assert,
413 .reset_deassert = gp10b_tegra_reset_deassert,
414
415 .force_reset_in_do_idle = false,
416
417 .soc_name = "tegra18x",
418
419 .unified_memory = true,
420};
421
422
423#define ECC_STAT_NAME_MAX_SIZE 100
424
425
426static DEFINE_HASHTABLE(ecc_hash_table, 5);
427
428static struct device_attribute *dev_attr_sm_lrf_ecc_single_err_count_array;
429static struct device_attribute *dev_attr_sm_lrf_ecc_double_err_count_array;
430
431static struct device_attribute *dev_attr_sm_shm_ecc_sec_count_array;
432static struct device_attribute *dev_attr_sm_shm_ecc_sed_count_array;
433static struct device_attribute *dev_attr_sm_shm_ecc_ded_count_array;
434
435static struct device_attribute *dev_attr_tex_ecc_total_sec_pipe0_count_array;
436static struct device_attribute *dev_attr_tex_ecc_total_ded_pipe0_count_array;
437static struct device_attribute *dev_attr_tex_ecc_unique_sec_pipe0_count_array;
438static struct device_attribute *dev_attr_tex_ecc_unique_ded_pipe0_count_array;
439static struct device_attribute *dev_attr_tex_ecc_total_sec_pipe1_count_array;
440static struct device_attribute *dev_attr_tex_ecc_total_ded_pipe1_count_array;
441static struct device_attribute *dev_attr_tex_ecc_unique_sec_pipe1_count_array;
442static struct device_attribute *dev_attr_tex_ecc_unique_ded_pipe1_count_array;
443
444static struct device_attribute *dev_attr_l2_ecc_sec_count_array;
445static struct device_attribute *dev_attr_l2_ecc_ded_count_array;
446
447
448static u32 gen_ecc_hash_key(char *str)
449{
450 int i = 0;
451 u32 hash_key = 0;
452
453 while (str[i]) {
454 hash_key += (u32)(str[i]);
455 i++;
456 };
457
458 return hash_key;
459}
460
461static ssize_t ecc_stat_show(struct device *dev,
462 struct device_attribute *attr,
463 char *buf)
464{
465 const char *ecc_stat_full_name = attr->attr.name;
466 const char *ecc_stat_base_name;
467 unsigned int hw_unit;
468 struct gk20a_ecc_stat *ecc_stat;
469 u32 hash_key;
470
471 if (sscanf(ecc_stat_full_name, "ltc%u", &hw_unit) == 1) {
472 ecc_stat_base_name = &(ecc_stat_full_name[strlen("ltc0_")]);
473 } else if (sscanf(ecc_stat_full_name, "gpc0_tpc%u", &hw_unit) == 1) {
474 ecc_stat_base_name = &(ecc_stat_full_name[strlen("gpc0_tpc0_")]);
475 } else if (sscanf(ecc_stat_full_name, "gpc%u", &hw_unit) == 1) {
476 ecc_stat_base_name = &(ecc_stat_full_name[strlen("gpc0_")]);
477 } else if (sscanf(ecc_stat_full_name, "eng%u", &hw_unit) == 1) {
478 ecc_stat_base_name = &(ecc_stat_full_name[strlen("eng0_")]);
479 } else {
480 return snprintf(buf,
481 PAGE_SIZE,
482 "Error: Invalid ECC stat name!\n");
483 }
484
485 hash_key = gen_ecc_hash_key((char *)ecc_stat_base_name);
486 hash_for_each_possible(ecc_hash_table,
487 ecc_stat,
488 hash_node,
489 hash_key) {
490 if (!strcmp(ecc_stat_full_name, ecc_stat->names[hw_unit]))
491 return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stat->counters[hw_unit]);
492 }
493
494 return snprintf(buf, PAGE_SIZE, "Error: No ECC stat found!\n");
495}
496
497int gr_gp10b_ecc_stat_create(struct device *dev,
498 int is_l2,
499 char *ecc_stat_name,
500 struct gk20a_ecc_stat *ecc_stat,
501 struct device_attribute **dev_attr_array)
502{
503 struct gk20a *g = get_gk20a(dev);
504 char *ltc_unit_name = "ltc";
505 char *gr_unit_name = "gpc0_tpc";
506 int num_hw_units = 0;
507
508 if (is_l2)
509 num_hw_units = g->ltc_count;
510 else
511 num_hw_units = g->gr.tpc_count;
512
513
514 return gp10b_ecc_stat_create(dev, num_hw_units,
515 is_l2 ? ltc_unit_name : gr_unit_name,
516 ecc_stat_name,
517 ecc_stat,
518 dev_attr_array);
519}
520
521int gp10b_ecc_stat_create(struct device *dev,
522 int num_hw_units,
523 char *ecc_unit_name,
524 char *ecc_stat_name,
525 struct gk20a_ecc_stat *ecc_stat,
526 struct device_attribute **__dev_attr_array)
527{
528 int error = 0;
529 struct gk20a *g = get_gk20a(dev);
530 int hw_unit = 0;
531 u32 hash_key = 0;
532 struct device_attribute *dev_attr_array;
533
534 /* Allocate arrays */
535 dev_attr_array = nvgpu_kzalloc(g, sizeof(struct device_attribute) *
536 num_hw_units);
537 ecc_stat->counters = nvgpu_kzalloc(g, sizeof(u32) * num_hw_units);
538 ecc_stat->names = nvgpu_kzalloc(g, sizeof(char *) * num_hw_units);
539 for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
540 ecc_stat->names[hw_unit] = nvgpu_kzalloc(g, sizeof(char) *
541 ECC_STAT_NAME_MAX_SIZE);
542 }
543
544 for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
545 /* Fill in struct device_attribute members */
546 snprintf(ecc_stat->names[hw_unit],
547 ECC_STAT_NAME_MAX_SIZE,
548 "%s%d_%s",
549 ecc_unit_name,
550 hw_unit,
551 ecc_stat_name);
552
553 sysfs_attr_init(&dev_attr_array[hw_unit].attr);
554 dev_attr_array[hw_unit].attr.name = ecc_stat->names[hw_unit];
555 dev_attr_array[hw_unit].attr.mode = VERIFY_OCTAL_PERMISSIONS(S_IRUGO);
556 dev_attr_array[hw_unit].show = ecc_stat_show;
557 dev_attr_array[hw_unit].store = NULL;
558
559 /* Create sysfs file */
560 error |= device_create_file(dev, &dev_attr_array[hw_unit]);
561 }
562
563 /* Add hash table entry */
564 hash_key = gen_ecc_hash_key(ecc_stat_name);
565 hash_add(ecc_hash_table,
566 &ecc_stat->hash_node,
567 hash_key);
568
569 *__dev_attr_array = dev_attr_array;
570
571 return error;
572}
573
574void gr_gp10b_ecc_stat_remove(struct device *dev,
575 int is_l2,
576 struct gk20a_ecc_stat *ecc_stat,
577 struct device_attribute *dev_attr_array)
578{
579 struct gk20a *g = get_gk20a(dev);
580 int num_hw_units = 0;
581
582 if (is_l2)
583 num_hw_units = g->ltc_count;
584 else
585 num_hw_units = g->gr.tpc_count;
586
587 gp10b_ecc_stat_remove(dev, num_hw_units, ecc_stat, dev_attr_array);
588}
589
590void gp10b_ecc_stat_remove(struct device *dev,
591 int num_hw_units,
592 struct gk20a_ecc_stat *ecc_stat,
593 struct device_attribute *dev_attr_array)
594{
595 struct gk20a *g = get_gk20a(dev);
596 int hw_unit = 0;
597
598 /* Remove sysfs files */
599 for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
600 device_remove_file(dev, &dev_attr_array[hw_unit]);
601 }
602
603 /* Remove hash table entry */
604 hash_del(&ecc_stat->hash_node);
605
606 /* Free arrays */
607 nvgpu_kfree(g, ecc_stat->counters);
608 for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
609 nvgpu_kfree(g, ecc_stat->names[hw_unit]);
610 }
611 nvgpu_kfree(g, ecc_stat->names);
612 nvgpu_kfree(g, dev_attr_array);
613}
614
615void gr_gp10b_create_sysfs(struct gk20a *g)
616{
617 int error = 0;
618 struct device *dev = dev_from_gk20a(g);
619
620 /* This stat creation function is called on GR init. GR can get
621 initialized multiple times but we only need to create the ECC
622 stats once. Therefore, add the following check to avoid
623 creating duplicate stat sysfs nodes. */
624 if (g->ecc.gr.t18x.sm_lrf_single_err_count.counters != NULL)
625 return;
626
627 error |= gr_gp10b_ecc_stat_create(dev,
628 0,
629 "sm_lrf_ecc_single_err_count",
630 &g->ecc.gr.t18x.sm_lrf_single_err_count,
631 &dev_attr_sm_lrf_ecc_single_err_count_array);
632 error |= gr_gp10b_ecc_stat_create(dev,
633 0,
634 "sm_lrf_ecc_double_err_count",
635 &g->ecc.gr.t18x.sm_lrf_double_err_count,
636 &dev_attr_sm_lrf_ecc_double_err_count_array);
637
638 error |= gr_gp10b_ecc_stat_create(dev,
639 0,
640 "sm_shm_ecc_sec_count",
641 &g->ecc.gr.t18x.sm_shm_sec_count,
642 &dev_attr_sm_shm_ecc_sec_count_array);
643 error |= gr_gp10b_ecc_stat_create(dev,
644 0,
645 "sm_shm_ecc_sed_count",
646 &g->ecc.gr.t18x.sm_shm_sed_count,
647 &dev_attr_sm_shm_ecc_sed_count_array);
648 error |= gr_gp10b_ecc_stat_create(dev,
649 0,
650 "sm_shm_ecc_ded_count",
651 &g->ecc.gr.t18x.sm_shm_ded_count,
652 &dev_attr_sm_shm_ecc_ded_count_array);
653
654 error |= gr_gp10b_ecc_stat_create(dev,
655 0,
656 "tex_ecc_total_sec_pipe0_count",
657 &g->ecc.gr.t18x.tex_total_sec_pipe0_count,
658 &dev_attr_tex_ecc_total_sec_pipe0_count_array);
659 error |= gr_gp10b_ecc_stat_create(dev,
660 0,
661 "tex_ecc_total_ded_pipe0_count",
662 &g->ecc.gr.t18x.tex_total_ded_pipe0_count,
663 &dev_attr_tex_ecc_total_ded_pipe0_count_array);
664 error |= gr_gp10b_ecc_stat_create(dev,
665 0,
666 "tex_ecc_unique_sec_pipe0_count",
667 &g->ecc.gr.t18x.tex_unique_sec_pipe0_count,
668 &dev_attr_tex_ecc_unique_sec_pipe0_count_array);
669 error |= gr_gp10b_ecc_stat_create(dev,
670 0,
671 "tex_ecc_unique_ded_pipe0_count",
672 &g->ecc.gr.t18x.tex_unique_ded_pipe0_count,
673 &dev_attr_tex_ecc_unique_ded_pipe0_count_array);
674 error |= gr_gp10b_ecc_stat_create(dev,
675 0,
676 "tex_ecc_total_sec_pipe1_count",
677 &g->ecc.gr.t18x.tex_total_sec_pipe1_count,
678 &dev_attr_tex_ecc_total_sec_pipe1_count_array);
679 error |= gr_gp10b_ecc_stat_create(dev,
680 0,
681 "tex_ecc_total_ded_pipe1_count",
682 &g->ecc.gr.t18x.tex_total_ded_pipe1_count,
683 &dev_attr_tex_ecc_total_ded_pipe1_count_array);
684 error |= gr_gp10b_ecc_stat_create(dev,
685 0,
686 "tex_ecc_unique_sec_pipe1_count",
687 &g->ecc.gr.t18x.tex_unique_sec_pipe1_count,
688 &dev_attr_tex_ecc_unique_sec_pipe1_count_array);
689 error |= gr_gp10b_ecc_stat_create(dev,
690 0,
691 "tex_ecc_unique_ded_pipe1_count",
692 &g->ecc.gr.t18x.tex_unique_ded_pipe1_count,
693 &dev_attr_tex_ecc_unique_ded_pipe1_count_array);
694
695 error |= gr_gp10b_ecc_stat_create(dev,
696 1,
697 "lts0_ecc_sec_count",
698 &g->ecc.gr.t18x.l2_sec_count,
699 &dev_attr_l2_ecc_sec_count_array);
700 error |= gr_gp10b_ecc_stat_create(dev,
701 1,
702 "lts0_ecc_ded_count",
703 &g->ecc.gr.t18x.l2_ded_count,
704 &dev_attr_l2_ecc_ded_count_array);
705
706 if (error)
707 dev_err(dev, "Failed to create sysfs attributes!\n");
708}
709
710static void gr_gp10b_remove_sysfs(struct device *dev)
711{
712 struct gk20a *g = get_gk20a(dev);
713
714 gr_gp10b_ecc_stat_remove(dev,
715 0,
716 &g->ecc.gr.t18x.sm_lrf_single_err_count,
717 dev_attr_sm_lrf_ecc_single_err_count_array);
718 gr_gp10b_ecc_stat_remove(dev,
719 0,
720 &g->ecc.gr.t18x.sm_lrf_double_err_count,
721 dev_attr_sm_lrf_ecc_double_err_count_array);
722
723 gr_gp10b_ecc_stat_remove(dev,
724 0,
725 &g->ecc.gr.t18x.sm_shm_sec_count,
726 dev_attr_sm_shm_ecc_sec_count_array);
727 gr_gp10b_ecc_stat_remove(dev,
728 0,
729 &g->ecc.gr.t18x.sm_shm_sed_count,
730 dev_attr_sm_shm_ecc_sed_count_array);
731 gr_gp10b_ecc_stat_remove(dev,
732 0,
733 &g->ecc.gr.t18x.sm_shm_ded_count,
734 dev_attr_sm_shm_ecc_ded_count_array);
735
736 gr_gp10b_ecc_stat_remove(dev,
737 0,
738 &g->ecc.gr.t18x.tex_total_sec_pipe0_count,
739 dev_attr_tex_ecc_total_sec_pipe0_count_array);
740 gr_gp10b_ecc_stat_remove(dev,
741 0,
742 &g->ecc.gr.t18x.tex_total_ded_pipe0_count,
743 dev_attr_tex_ecc_total_ded_pipe0_count_array);
744 gr_gp10b_ecc_stat_remove(dev,
745 0,
746 &g->ecc.gr.t18x.tex_unique_sec_pipe0_count,
747 dev_attr_tex_ecc_unique_sec_pipe0_count_array);
748 gr_gp10b_ecc_stat_remove(dev,
749 0,
750 &g->ecc.gr.t18x.tex_unique_ded_pipe0_count,
751 dev_attr_tex_ecc_unique_ded_pipe0_count_array);
752 gr_gp10b_ecc_stat_remove(dev,
753 0,
754 &g->ecc.gr.t18x.tex_total_sec_pipe1_count,
755 dev_attr_tex_ecc_total_sec_pipe1_count_array);
756 gr_gp10b_ecc_stat_remove(dev,
757 0,
758 &g->ecc.gr.t18x.tex_total_ded_pipe1_count,
759 dev_attr_tex_ecc_total_ded_pipe1_count_array);
760 gr_gp10b_ecc_stat_remove(dev,
761 0,
762 &g->ecc.gr.t18x.tex_unique_sec_pipe1_count,
763 dev_attr_tex_ecc_unique_sec_pipe1_count_array);
764 gr_gp10b_ecc_stat_remove(dev,
765 0,
766 &g->ecc.gr.t18x.tex_unique_ded_pipe1_count,
767 dev_attr_tex_ecc_unique_ded_pipe1_count_array);
768
769 gr_gp10b_ecc_stat_remove(dev,
770 1,
771 &g->ecc.gr.t18x.l2_sec_count,
772 dev_attr_l2_ecc_sec_count_array);
773 gr_gp10b_ecc_stat_remove(dev,
774 1,
775 &g->ecc.gr.t18x.l2_ded_count,
776 dev_attr_l2_ecc_ded_count_array);
777}