diff --git a/drivers/misc/mods/Makefile b/drivers/misc/mods/Makefile index 95ea2916..dda15bae 100644 --- a/drivers/misc/mods/Makefile +++ b/drivers/misc/mods/Makefile @@ -4,6 +4,7 @@ mods-y += mods_mem.o mods-y += mods_irq.o mods-y += mods_clock.o mods-$(CONFIG_ARCH_TEGRA) += mods_tegraprod.o +mods-$(CONFIG_ARCH_TEGRA_19x_SOC) += mods_ras.o mods-$(CONFIG_PCI) += mods_pci.o mods-$(CONFIG_ACPI) += mods_acpi.o mods-$(CONFIG_ARCH_TEGRA) += mods_dmabuf.o diff --git a/drivers/misc/mods/mods_debugfs.c b/drivers/misc/mods/mods_debugfs.c index 3f85765c..076deffa 100644 --- a/drivers/misc/mods/mods_debugfs.c +++ b/drivers/misc/mods/mods_debugfs.c @@ -29,6 +29,10 @@ static struct dentry *mods_debugfs_dir; +#ifdef CONFIG_ARCH_TEGRA_19x_SOC +#include "mods_ras.h" +#endif + #if defined(MODS_TEGRA) && defined(MODS_HAS_KFUSE) #include #endif @@ -474,6 +478,39 @@ static int mods_mi_set(void *data, u64 val) mods_set_multi_instance((int)val); return 0; } + +#ifdef CONFIG_ARCH_TEGRA_19x_SOC +static int mods_set_err_sel(void *data, u64 val) +{ + set_err_sel(val); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(mods_err_sel_fops, 0, mods_set_err_sel, "%llu\n"); + +static int mods_set_err_ctrl(void *data, u64 val) +{ + set_err_ctrl(val); + return 0; +} + +static int mods_get_err_ctrl(void *data, u64 *val) +{ + *val = get_err_ctrl(); + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(mods_err_ctrl_fops, mods_get_err_ctrl, + mods_set_err_ctrl, "%llu\n"); + +static int mods_enable_cpu_core_reporting(void *data, u64 val) +{ + enable_cpu_core_reporting(val); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(mods_enable_cpu_fops, 0, mods_enable_cpu_core_reporting, + "%llu\n"); +#endif + DEFINE_SIMPLE_ATTRIBUTE(mods_mi_fops, mods_mi_get, mods_mi_set, "%llu\n"); void mods_remove_debugfs(void) @@ -484,6 +521,10 @@ void mods_remove_debugfs(void) int mods_create_debugfs(struct miscdevice *modsdev) { +#ifdef MODS_HAS_DEBUGFS +#ifdef CONFIG_ARCH_TEGRA_19x_SOC + struct dentry *ras_debugfs_entry; +#endif struct dentry *retval; int err = 0; #ifdef CONFIG_TEGRA_DC @@ -533,6 +574,36 @@ int mods_create_debugfs(struct miscdevice *modsdev) goto remove_out; } +#ifdef CONFIG_ARCH_TEGRA_19x_SOC + if (of_find_node_by_name(NULL, "carmel_ras")) { + ras_debugfs_entry = debugfs_create_dir("ras", mods_debugfs_dir); + if (IS_ERR(ras_debugfs_entry)) { + err = -EIO; + goto remove_out; + } + + retval = debugfs_create_file("err_sel", 0644, + ras_debugfs_entry, 0, &mods_err_sel_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + + retval = debugfs_create_file("err_ctrl", 0644, + ras_debugfs_entry, 0, &mods_err_ctrl_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + retval = debugfs_create_file("ccplex_config", 0644, + ras_debugfs_entry, 0, &mods_enable_cpu_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + } +#endif + retval = debugfs_create_file("debug", 0644, mods_debugfs_dir, 0, &mods_debug_fops); if (IS_ERR(retval)) { @@ -693,5 +764,8 @@ remove_out: dev_err(modsdev->this_device, "could not create debugfs\n"); mods_remove_debugfs(); return err; +#else + return 0; +#endif } diff --git a/drivers/misc/mods/mods_ras.c b/drivers/misc/mods/mods_ras.c new file mode 100644 index 00000000..e0eadbfa --- /dev/null +++ b/drivers/misc/mods/mods_ras.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017-2019, 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. + */ + +#include "mods_ras.h" + +#include +#include +#include + +/* Encodes requested core/cluster to report + * ras for. If 0, refers to ccplex + */ +static u64 ras_ccplex_config; + +void enable_cpu_core_reporting(u64 config) +{ + ras_ccplex_config = config; +} + +void set_err_sel(u64 sel_val) +{ + u8 core, cluster, ccplex; + u64 errx; + + ccplex = 0; + core = ras_ccplex_config >> 1; + cluster = ras_ccplex_config & 1; + if (!ras_ccplex_config) + ccplex = 1; + + if (ccplex) { + errx = sel_val; + } else { + if (!cluster) { + errx = (tegra18_logical_to_cluster(core) << 5) + + (tegra18_logical_to_cpu(core) << 4) + + sel_val; + } else { + errx = 512 + (tegra18_logical_to_cluster(core) << 4) + + sel_val; + } + } + + mods_debug_printk(DEBUG_FUNC, "ERR_SEL is %llu, Core is %u\n", + errx, core); + + ras_write_errselr(errx); +} + +void set_err_ctrl(u64 ctrl_val) +{ + u64 updated_val; + + ras_write_error_control(ctrl_val); + updated_val = ras_read_error_control(); + mods_debug_printk(DEBUG_ALL, "ERR_CTRL updated value is %llu", + updated_val); +} + +u64 get_err_ctrl(void) +{ + return ras_read_error_control(); +} diff --git a/drivers/misc/mods/mods_ras.h b/drivers/misc/mods/mods_ras.h new file mode 100644 index 00000000..b1286d70 --- /dev/null +++ b/drivers/misc/mods/mods_ras.h @@ -0,0 +1,38 @@ +/* + * mods_ras.h - This file is part of NVIDIA MODS kernel driver. + * + * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA MODS kernel driver is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * NVIDIA MODS kernel driver is distributed in the hope that 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 NVIDIA MODS kernel driver. + * If not, see . + */ + +#include "mods_internal.h" + +void enable_cpu_core_reporting(u64 config); + +/*Set the ERR_SEL register to choose the + *node for which to enable/disable errors for + */ +void set_err_sel(u64 sel_val); + +/*Set the ERR_CTRL register selected + *by ERR_SEL + */ +void set_err_ctrl(u64 ctrl_val); + +/*Get the ERR_CTRL register selected + *by ERR_SEL + */ +u64 get_err_ctrl(void); +