gpu: nvgpu: rework ecc structure and sysfs

- create common file common/ecc.c which include common functions for add
  ecc counters and remove counters.
- common code will create a list of all counter which make it easier to
  iterate all counters.
- Add chip specific file for adding ecc counters.
- add linux specific file os/linux/ecc_sysfs.c to export counters to
  sysfs.
- remove obsolete code
- MISRA violation for using snprintf is not solved, tracking with
  jira NVGPU-859

Jira NVGPUT-115

Change-Id: I1905c43c5c9b2b131199807533dee8e63ddc12f4
Signed-off-by: Richard Zhao <rizhao@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1763536
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Richard Zhao
2018-06-26 17:37:40 -07:00
committed by mobile promotions
parent 5ff1b3fe5a
commit 7f14aafc2c
32 changed files with 1044 additions and 1006 deletions

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <nvgpu/ecc.h>
#include "gk20a/gk20a.h"
#include "os_linux.h"
int nvgpu_ecc_sysfs_init(struct gk20a *g)
{
struct device *dev = dev_from_gk20a(g);
struct nvgpu_ecc *ecc = &g->ecc;
struct dev_ext_attribute *attr;
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
struct nvgpu_ecc_stat *stat;
int i = 0, err;
attr = nvgpu_kzalloc(g, sizeof(*attr) * ecc->stats_count);
if (!attr)
return -ENOMEM;
nvgpu_list_for_each_entry(stat,
&ecc->stats_list, nvgpu_ecc_stat, node) {
if (i >= ecc->stats_count) {
err = -EINVAL;
nvgpu_err(g, "stats_list longer than stats_count %d",
ecc->stats_count);
break;
}
sysfs_attr_init(&attr[i].attr);
attr[i].attr.attr.name = stat->name;
attr[i].attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(S_IRUGO);
attr[i].var = &stat->counter;
attr[i].attr.show = device_show_int;
err = device_create_file(dev, &attr[i].attr);
if (err) {
nvgpu_err(g, "sysfs node create failed for %s\n",
stat->name);
break;
}
i++;
}
if (err) {
while (i-- > 0)
device_remove_file(dev, &attr[i].attr);
nvgpu_kfree(g, attr);
return err;
}
l->ecc_attrs = attr;
return 0;
}
void nvgpu_ecc_sysfs_remove(struct gk20a *g)
{
struct device *dev = dev_from_gk20a(g);
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
struct nvgpu_ecc *ecc = &g->ecc;
int i;
for (i = 0; i < ecc->stats_count; i++)
device_remove_file(dev, &l->ecc_attrs[i].attr);
nvgpu_kfree(g, l->ecc_attrs);
l->ecc_attrs = NULL;
}

View File

@@ -141,6 +141,7 @@ struct nvgpu_os_linux {
struct dentry *debugfs_dump_ctxsw_stats;
#endif
DECLARE_HASHTABLE(ecc_sysfs_stats_htable, 5);
struct dev_ext_attribute *ecc_attrs;
struct gk20a_cde_app cde_app;

View File

@@ -52,11 +52,6 @@ static int nvgpu_pci_tegra_probe(struct device *dev)
static int nvgpu_pci_tegra_remove(struct device *dev)
{
struct gk20a *g = get_gk20a(dev);
if (g->ops.gr.remove_gr_sysfs)
g->ops.gr.remove_gr_sysfs(g);
return 0;
}

View File

@@ -1,269 +0,0 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/hashtable.h>
#include <nvgpu/kmem.h>
#include <nvgpu/bug.h>
#include <nvgpu/hashtable.h>
#include "os_linux.h"
#include "gk20a/gk20a.h"
#include "platform_gk20a.h"
#include "platform_gk20a_tegra.h"
#include "platform_gp10b.h"
#include "platform_gp10b_tegra.h"
#include "platform_ecc_sysfs.h"
static u32 gen_ecc_hash_key(char *str)
{
int i = 0;
u32 hash_key = 0x811c9dc5;
while (str[i]) {
hash_key *= 0x1000193;
hash_key ^= (u32)(str[i]);
i++;
};
return hash_key;
}
static ssize_t ecc_stat_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
const char *ecc_stat_full_name = attr->attr.name;
const char *ecc_stat_base_name;
unsigned int hw_unit;
unsigned int subunit;
struct gk20a_ecc_stat *ecc_stat;
u32 hash_key;
struct gk20a *g = get_gk20a(dev);
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
if (sscanf(ecc_stat_full_name, "ltc%u_lts%u", &hw_unit,
&subunit) == 2) {
ecc_stat_base_name = &(ecc_stat_full_name[strlen("ltc0_lts0_")]);
hw_unit = g->gr.slices_per_ltc * hw_unit + subunit;
} else if (sscanf(ecc_stat_full_name, "ltc%u", &hw_unit) == 1) {
ecc_stat_base_name = &(ecc_stat_full_name[strlen("ltc0_")]);
} else if (sscanf(ecc_stat_full_name, "gpc0_tpc%u", &hw_unit) == 1) {
ecc_stat_base_name = &(ecc_stat_full_name[strlen("gpc0_tpc0_")]);
} else if (sscanf(ecc_stat_full_name, "gpc%u", &hw_unit) == 1) {
ecc_stat_base_name = &(ecc_stat_full_name[strlen("gpc0_")]);
} else if (sscanf(ecc_stat_full_name, "eng%u", &hw_unit) == 1) {
ecc_stat_base_name = &(ecc_stat_full_name[strlen("eng0_")]);
} else {
return snprintf(buf,
PAGE_SIZE,
"Error: Invalid ECC stat name!\n");
}
hash_key = gen_ecc_hash_key((char *)ecc_stat_base_name);
hash_for_each_possible(l->ecc_sysfs_stats_htable,
ecc_stat,
hash_node,
hash_key) {
if (hw_unit >= ecc_stat->count)
continue;
if (!strcmp(ecc_stat_full_name, ecc_stat->names[hw_unit]))
return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stat->counters[hw_unit]);
}
return snprintf(buf, PAGE_SIZE, "Error: No ECC stat found!\n");
}
int nvgpu_gr_ecc_stat_create(struct device *dev,
int is_l2, char *ecc_stat_name,
struct gk20a_ecc_stat *ecc_stat)
{
struct gk20a *g = get_gk20a(dev);
char *ltc_unit_name = "ltc";
char *gr_unit_name = "gpc0_tpc";
char *lts_unit_name = "lts";
int num_hw_units = 0;
int num_subunits = 0;
if (is_l2 == 1)
num_hw_units = g->ltc_count;
else if (is_l2 == 2) {
num_hw_units = g->ltc_count;
num_subunits = g->gr.slices_per_ltc;
} else
num_hw_units = g->gr.tpc_count;
return nvgpu_ecc_stat_create(dev, num_hw_units, num_subunits,
is_l2 ? ltc_unit_name : gr_unit_name,
num_subunits ? lts_unit_name: NULL,
ecc_stat_name,
ecc_stat);
}
int nvgpu_ecc_stat_create(struct device *dev,
int num_hw_units, int num_subunits,
char *ecc_unit_name, char *ecc_subunit_name,
char *ecc_stat_name,
struct gk20a_ecc_stat *ecc_stat)
{
int error = 0;
struct gk20a *g = get_gk20a(dev);
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
int hw_unit = 0;
int subunit = 0;
int element = 0;
u32 hash_key = 0;
struct device_attribute *dev_attr_array;
int num_elements = num_subunits ? num_subunits * num_hw_units :
num_hw_units;
/* Allocate arrays */
dev_attr_array = nvgpu_kzalloc(g, sizeof(struct device_attribute) *
num_elements);
ecc_stat->counters = nvgpu_kzalloc(g, sizeof(u32) * num_elements);
ecc_stat->names = nvgpu_kzalloc(g, sizeof(char *) * num_elements);
for (hw_unit = 0; hw_unit < num_elements; hw_unit++) {
ecc_stat->names[hw_unit] = nvgpu_kzalloc(g, sizeof(char) *
ECC_STAT_NAME_MAX_SIZE);
}
ecc_stat->count = num_elements;
if (num_subunits) {
for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
for (subunit = 0; subunit < num_subunits; subunit++) {
element = hw_unit*num_subunits + subunit;
snprintf(ecc_stat->names[element],
ECC_STAT_NAME_MAX_SIZE,
"%s%d_%s%d_%s",
ecc_unit_name,
hw_unit,
ecc_subunit_name,
subunit,
ecc_stat_name);
sysfs_attr_init(&dev_attr_array[element].attr);
dev_attr_array[element].attr.name =
ecc_stat->names[element];
dev_attr_array[element].attr.mode =
VERIFY_OCTAL_PERMISSIONS(S_IRUGO);
dev_attr_array[element].show = ecc_stat_show;
dev_attr_array[element].store = NULL;
/* Create sysfs file */
error |= device_create_file(dev,
&dev_attr_array[element]);
}
}
} else {
for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
/* Fill in struct device_attribute members */
snprintf(ecc_stat->names[hw_unit],
ECC_STAT_NAME_MAX_SIZE,
"%s%d_%s",
ecc_unit_name,
hw_unit,
ecc_stat_name);
sysfs_attr_init(&dev_attr_array[hw_unit].attr);
dev_attr_array[hw_unit].attr.name =
ecc_stat->names[hw_unit];
dev_attr_array[hw_unit].attr.mode =
VERIFY_OCTAL_PERMISSIONS(S_IRUGO);
dev_attr_array[hw_unit].show = ecc_stat_show;
dev_attr_array[hw_unit].store = NULL;
/* Create sysfs file */
error |= device_create_file(dev,
&dev_attr_array[hw_unit]);
}
}
/* Add hash table entry */
hash_key = gen_ecc_hash_key(ecc_stat_name);
hash_add(l->ecc_sysfs_stats_htable,
&ecc_stat->hash_node,
hash_key);
ecc_stat->attr_array = dev_attr_array;
return error;
}
void nvgpu_gr_ecc_stat_remove(struct device *dev,
int is_l2, struct gk20a_ecc_stat *ecc_stat)
{
struct gk20a *g = get_gk20a(dev);
int num_hw_units = 0;
int num_subunits = 0;
if (is_l2 == 1)
num_hw_units = g->ltc_count;
else if (is_l2 == 2) {
num_hw_units = g->ltc_count;
num_subunits = g->gr.slices_per_ltc;
} else
num_hw_units = g->gr.tpc_count;
nvgpu_ecc_stat_remove(dev, num_hw_units, num_subunits, ecc_stat);
}
void nvgpu_ecc_stat_remove(struct device *dev,
int num_hw_units, int num_subunits,
struct gk20a_ecc_stat *ecc_stat)
{
struct gk20a *g = get_gk20a(dev);
struct device_attribute *dev_attr_array = ecc_stat->attr_array;
int hw_unit = 0;
int subunit = 0;
int element = 0;
int num_elements = num_subunits ? num_subunits * num_hw_units :
num_hw_units;
/* Remove sysfs files */
if (num_subunits) {
for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) {
for (subunit = 0; subunit < num_subunits; subunit++) {
element = hw_unit * num_subunits + subunit;
device_remove_file(dev,
&dev_attr_array[element]);
}
}
} else {
for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++)
device_remove_file(dev, &dev_attr_array[hw_unit]);
}
/* Remove hash table entry */
hash_del(&ecc_stat->hash_node);
/* Free arrays */
nvgpu_kfree(g, ecc_stat->counters);
for (hw_unit = 0; hw_unit < num_elements; hw_unit++)
nvgpu_kfree(g, ecc_stat->names[hw_unit]);
nvgpu_kfree(g, ecc_stat->names);
nvgpu_kfree(g, dev_attr_array);
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NVGPU_PLATFORM_SYSFS_H_
#define _NVGPU_PLATFORM_SYSFS_H_
#include "gp10b/gr_gp10b.h"
#define ECC_STAT_NAME_MAX_SIZE 100
int nvgpu_gr_ecc_stat_create(struct device *dev,
int is_l2, char *ecc_stat_name,
struct gk20a_ecc_stat *ecc_stat);
int nvgpu_ecc_stat_create(struct device *dev,
int num_hw_units, int num_subunits,
char *ecc_unit_name, char *ecc_subunit_name,
char *ecc_stat_name,
struct gk20a_ecc_stat *ecc_stat);
void nvgpu_gr_ecc_stat_remove(struct device *dev,
int is_l2, struct gk20a_ecc_stat *ecc_stat);
void nvgpu_ecc_stat_remove(struct device *dev,
int num_hw_units, int num_subunits,
struct gk20a_ecc_stat *ecc_stat);
#endif

View File

@@ -41,7 +41,6 @@
#include "gk20a/gk20a.h"
#include "platform_gk20a.h"
#include "platform_ecc_sysfs.h"
#include "platform_gk20a_tegra.h"
#include "platform_gp10b.h"
#include "platform_gp10b_tegra.h"
@@ -177,11 +176,6 @@ static int gp10b_tegra_late_probe(struct device *dev)
static int gp10b_tegra_remove(struct device *dev)
{
struct gk20a *g = get_gk20a(dev);
if (g->ops.gr.remove_gr_sysfs)
g->ops.gr.remove_gr_sysfs(g);
/* deinitialise tegra specific scaling quirks */
gp10b_tegra_scale_exit(dev);
@@ -476,162 +470,3 @@ struct gk20a_platform gp10b_tegra_platform = {
.secure_buffer_size = 401408,
};
void gr_gp10b_create_sysfs(struct gk20a *g)
{
int error = 0;
struct device *dev = dev_from_gk20a(g);
/* This stat creation function is called on GR init. GR can get
initialized multiple times but we only need to create the ECC
stats once. Therefore, add the following check to avoid
creating duplicate stat sysfs nodes. */
if (g->ecc.gr.sm_lrf_single_err_count.counters != NULL)
return;
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_lrf_ecc_single_err_count",
&g->ecc.gr.sm_lrf_single_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_lrf_ecc_double_err_count",
&g->ecc.gr.sm_lrf_double_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_shm_ecc_sec_count",
&g->ecc.gr.sm_shm_sec_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_shm_ecc_sed_count",
&g->ecc.gr.sm_shm_sed_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_shm_ecc_ded_count",
&g->ecc.gr.sm_shm_ded_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"tex_ecc_total_sec_pipe0_count",
&g->ecc.gr.tex_total_sec_pipe0_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"tex_ecc_total_ded_pipe0_count",
&g->ecc.gr.tex_total_ded_pipe0_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"tex_ecc_unique_sec_pipe0_count",
&g->ecc.gr.tex_unique_sec_pipe0_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"tex_ecc_unique_ded_pipe0_count",
&g->ecc.gr.tex_unique_ded_pipe0_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"tex_ecc_total_sec_pipe1_count",
&g->ecc.gr.tex_total_sec_pipe1_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"tex_ecc_total_ded_pipe1_count",
&g->ecc.gr.tex_total_ded_pipe1_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"tex_ecc_unique_sec_pipe1_count",
&g->ecc.gr.tex_unique_sec_pipe1_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"tex_ecc_unique_ded_pipe1_count",
&g->ecc.gr.tex_unique_ded_pipe1_count);
error |= nvgpu_gr_ecc_stat_create(dev,
2,
"ecc_sec_count",
&g->ecc.ltc.l2_sec_count);
error |= nvgpu_gr_ecc_stat_create(dev,
2,
"ecc_ded_count",
&g->ecc.ltc.l2_ded_count);
if (error)
dev_err(dev, "Failed to create sysfs attributes!\n");
}
void gr_gp10b_remove_sysfs(struct gk20a *g)
{
struct device *dev = dev_from_gk20a(g);
if (!g->ecc.gr.sm_lrf_single_err_count.counters)
return;
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_lrf_single_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_lrf_double_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_shm_sec_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_shm_sed_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_shm_ded_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.tex_total_sec_pipe0_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.tex_total_ded_pipe0_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.tex_unique_sec_pipe0_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.tex_unique_ded_pipe0_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.tex_total_sec_pipe1_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.tex_total_ded_pipe1_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.tex_unique_sec_pipe1_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.tex_unique_ded_pipe1_count);
nvgpu_gr_ecc_stat_remove(dev,
2,
&g->ecc.ltc.l2_sec_count);
nvgpu_gr_ecc_stat_remove(dev,
2,
&g->ecc.ltc.l2_ded_count);
}

View File

@@ -18,6 +18,5 @@
#define _PLATFORM_GP10B_TEGRA_H_
#include "gp10b/gr_gp10b.h"
#include "platform_ecc_sysfs.h"
#endif

View File

@@ -39,7 +39,6 @@
#include "platform_gp10b.h"
#include "platform_gp10b_tegra.h"
#include "platform_ecc_sysfs.h"
#include "os_linux.h"
#include "platform_gk20a_tegra.h"
@@ -94,11 +93,6 @@ static int gv11b_tegra_late_probe(struct device *dev)
static int gv11b_tegra_remove(struct device *dev)
{
struct gk20a *g = get_gk20a(dev);
if (g->ops.gr.remove_gr_sysfs)
g->ops.gr.remove_gr_sysfs(g);
gv11b_tegra_scale_exit(dev);
#ifdef CONFIG_TEGRA_GK20A_NVHOST
@@ -261,328 +255,3 @@ struct gk20a_platform gv11b_tegra_platform = {
.secure_buffer_size = 667648,
};
void gr_gv11b_create_sysfs(struct gk20a *g)
{
struct device *dev = dev_from_gk20a(g);
int error = 0;
/* This stat creation function is called on GR init. GR can get
initialized multiple times but we only need to create the ECC
stats once. Therefore, add the following check to avoid
creating duplicate stat sysfs nodes. */
if (g->ecc.gr.sm_l1_tag_corrected_err_count.counters != NULL)
return;
gr_gp10b_create_sysfs(g);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_l1_tag_ecc_corrected_err_count",
&g->ecc.gr.sm_l1_tag_corrected_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_l1_tag_ecc_uncorrected_err_count",
&g->ecc.gr.sm_l1_tag_uncorrected_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_cbu_ecc_corrected_err_count",
&g->ecc.gr.sm_cbu_corrected_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_cbu_ecc_uncorrected_err_count",
&g->ecc.gr.sm_cbu_uncorrected_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_l1_data_ecc_corrected_err_count",
&g->ecc.gr.sm_l1_data_corrected_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_l1_data_ecc_uncorrected_err_count",
&g->ecc.gr.sm_l1_data_uncorrected_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_icache_ecc_corrected_err_count",
&g->ecc.gr.sm_icache_corrected_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"sm_icache_ecc_uncorrected_err_count",
&g->ecc.gr.sm_icache_uncorrected_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"gcc_l15_ecc_corrected_err_count",
&g->ecc.gr.gcc_l15_corrected_err_count);
error |= nvgpu_gr_ecc_stat_create(dev,
0,
"gcc_l15_ecc_uncorrected_err_count",
&g->ecc.gr.gcc_l15_uncorrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
g->ltc_count,
0,
"ltc",
NULL,
"l2_cache_uncorrected_err_count",
&g->ecc.ltc.l2_cache_uncorrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
g->ltc_count,
0,
"ltc",
NULL,
"l2_cache_corrected_err_count",
&g->ecc.ltc.l2_cache_corrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"gpc",
NULL,
"fecs_ecc_uncorrected_err_count",
&g->ecc.gr.fecs_uncorrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"gpc",
NULL,
"fecs_ecc_corrected_err_count",
&g->ecc.gr.fecs_corrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
g->gr.gpc_count,
0,
"gpc",
NULL,
"gpccs_ecc_uncorrected_err_count",
&g->ecc.gr.gpccs_uncorrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
g->gr.gpc_count,
0,
"gpc",
NULL,
"gpccs_ecc_corrected_err_count",
&g->ecc.gr.gpccs_corrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
g->gr.gpc_count,
0,
"gpc",
NULL,
"mmu_l1tlb_ecc_uncorrected_err_count",
&g->ecc.gr.mmu_l1tlb_uncorrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
g->gr.gpc_count,
0,
"gpc",
NULL,
"mmu_l1tlb_ecc_corrected_err_count",
&g->ecc.gr.mmu_l1tlb_corrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"eng",
NULL,
"mmu_l2tlb_ecc_uncorrected_err_count",
&g->ecc.fb.mmu_l2tlb_uncorrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"eng",
NULL,
"mmu_l2tlb_ecc_corrected_err_count",
&g->ecc.fb.mmu_l2tlb_corrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"eng",
NULL,
"mmu_hubtlb_ecc_uncorrected_err_count",
&g->ecc.fb.mmu_hubtlb_uncorrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"eng",
NULL,
"mmu_hubtlb_ecc_corrected_err_count",
&g->ecc.fb.mmu_hubtlb_corrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"eng",
NULL,
"mmu_fillunit_ecc_uncorrected_err_count",
&g->ecc.fb.mmu_fillunit_uncorrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"eng",
NULL,
"mmu_fillunit_ecc_corrected_err_count",
&g->ecc.fb.mmu_fillunit_corrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"eng",
NULL,
"pmu_ecc_uncorrected_err_count",
&g->ecc.pmu.pmu_uncorrected_err_count);
error |= nvgpu_ecc_stat_create(dev,
1,
0,
"eng",
NULL,
"pmu_ecc_corrected_err_count",
&g->ecc.pmu.pmu_corrected_err_count);
if (error)
dev_err(dev, "Failed to create gv11b sysfs attributes!\n");
}
void gr_gv11b_remove_sysfs(struct gk20a *g)
{
struct device *dev = dev_from_gk20a(g);
if (!g->ecc.gr.sm_l1_tag_corrected_err_count.counters)
return;
gr_gp10b_remove_sysfs(g);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_l1_tag_corrected_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_l1_tag_uncorrected_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_cbu_corrected_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_cbu_uncorrected_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_l1_data_corrected_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_l1_data_uncorrected_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_icache_corrected_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.sm_icache_uncorrected_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.gcc_l15_corrected_err_count);
nvgpu_gr_ecc_stat_remove(dev,
0,
&g->ecc.gr.gcc_l15_uncorrected_err_count);
nvgpu_ecc_stat_remove(dev,
g->ltc_count,
0,
&g->ecc.ltc.l2_cache_uncorrected_err_count);
nvgpu_ecc_stat_remove(dev,
g->ltc_count,
0,
&g->ecc.ltc.l2_cache_corrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.gr.fecs_uncorrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.gr.fecs_corrected_err_count);
nvgpu_ecc_stat_remove(dev,
g->gr.gpc_count,
0,
&g->ecc.gr.gpccs_uncorrected_err_count);
nvgpu_ecc_stat_remove(dev,
g->gr.gpc_count,
0,
&g->ecc.gr.gpccs_corrected_err_count);
nvgpu_ecc_stat_remove(dev,
g->gr.gpc_count,
0,
&g->ecc.gr.mmu_l1tlb_uncorrected_err_count);
nvgpu_ecc_stat_remove(dev,
g->gr.gpc_count,
0,
&g->ecc.gr.mmu_l1tlb_corrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.fb.mmu_l2tlb_uncorrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.fb.mmu_l2tlb_corrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.fb.mmu_hubtlb_uncorrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.fb.mmu_hubtlb_corrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.fb.mmu_fillunit_uncorrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.fb.mmu_fillunit_corrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.pmu.pmu_uncorrected_err_count);
nvgpu_ecc_stat_remove(dev,
1,
0,
&g->ecc.pmu.pmu_corrected_err_count);
}