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