gpu: nvgpu: ECC override

-sysfs functions to call into LS PMU and modify
 ECC overide register

Bug 1699676

Change-Id: Iaf6cc3a86160b806e52ab168577caad42b2c5d22
Signed-off-by: Supriya <ssharatkumar@nvidia.com>
Reviewed-on: http://git-master/r/921252
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Supriya
2015-12-10 12:54:38 +05:30
committed by Deepak Nibade
parent 02ee4d4188
commit 640d0e2c3b
7 changed files with 187 additions and 5 deletions

View File

@@ -25,6 +25,7 @@ obj-$(CONFIG_GK20A) += \
gp10b_gating_reglist.o \
regops_gp10b.o \
cde_gp10b.o \
therm_gp10b.o
therm_gp10b.o \
gp10b_sysfs.o
obj-$(CONFIG_TEGRA_GK20A) += platform_gp10b_tegra.o

View File

@@ -0,0 +1,66 @@
/*
* GP10B specific sysfs files
*
* Copyright (c) 2016, 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 <linux/platform_device.h>
#include "gk20a/gk20a.h"
#include "gp10b_sysfs.h"
#define ROOTRW (S_IRWXU|S_IRGRP|S_IROTH)
static ssize_t ecc_enable_store(struct device *device,
struct device_attribute *attr, const char *buf, size_t count)
{
struct platform_device *ndev = to_platform_device(device);
struct gk20a *g = get_gk20a(ndev);
u32 ecc_mask;
u32 err = 0;
err = sscanf(buf, "%d", &ecc_mask);
if (err == 1) {
err = g->ops.pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd
(g, ecc_mask);
if (err)
dev_err(device, "ECC override did not happen\n");
} else
return -EINVAL;
return count;
}
static ssize_t ecc_enable_read(struct device *device,
struct device_attribute *attr, char *buf)
{
struct platform_device *ndev = to_platform_device(device);
struct gk20a *g = get_gk20a(ndev);
return sprintf(buf, "ecc override =0x%x\n",
g->ops.gr.get_lrf_tex_ltc_dram_override(g));
}
static DEVICE_ATTR(ecc_enable, ROOTRW, ecc_enable_read, ecc_enable_store);
void gp10b_create_sysfs(struct platform_device *dev)
{
int error = 0;
error |= device_create_file(&dev->dev, &dev_attr_ecc_enable);
if (error)
dev_err(&dev->dev, "Failed to create sysfs attributes!\n");
}
void gp10b_remove_sysfs(struct device *dev)
{
device_remove_file(dev, &dev_attr_ecc_enable);
}

View File

@@ -0,0 +1,25 @@
/*
* GP10B specific sysfs files
*
* Copyright (c) 2016, 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.
*/
#ifndef _GP10B_SYSFS_H_
#define _GP10B_SYSFS_H_
/*ECC Fuse*/
#define FUSE_OPT_ECC_EN 0x358
void gp10b_create_sysfs(struct platform_device *dev);
void gp10b_remove_sysfs(struct device *dev);
#endif /*_GP10B_SYSFS_H_*/

View File

@@ -28,6 +28,7 @@
#include "hw_proj_gp10b.h"
#include "hw_ctxsw_prog_gp10b.h"
#include "hw_mc_gp10b.h"
#include "gp10b_sysfs.h"
#include <linux/vmalloc.h>
static bool gr_gp10b_is_valid_class(struct gk20a *g, u32 class_num)
@@ -1702,6 +1703,14 @@ static u32 gp10b_mask_hww_warp_esr(u32 hww_warp_esr)
return hww_warp_esr;
}
static u32 get_ecc_override_val(struct gk20a *g)
{
if (tegra_fuse_readl(FUSE_OPT_ECC_EN))
return gk20a_readl(g, gr_fecs_feature_override_ecc_r());
else
return 0;
}
void gp10b_init_gr(struct gpu_ops *gops)
{
gm20b_init_gr(gops);
@@ -1739,4 +1748,5 @@ void gp10b_init_gr(struct gpu_ops *gops)
gr_gp10b_pre_process_sm_exception;
gops->gr.handle_fecs_error = gr_gp10b_handle_fecs_error;
gops->gr.create_gr_sysfs = gr_gp10b_create_sysfs;
gops->gr.get_lrf_tex_ltc_dram_override = get_ecc_override_val;
}

View File

@@ -1478,6 +1478,10 @@ static inline u32 gr_fecs_ctxsw_idlestate_r(void)
{
return 0x00409420;
}
static inline u32 gr_fecs_feature_override_ecc_r(void)
{
return 0x00409658;
}
static inline u32 gr_gpc0_gpccs_ctxsw_idlestate_r(void)
{
return 0x00502420;

View File

@@ -34,6 +34,7 @@
#include "ltc_gp10b.h"
#include "hw_gr_gp10b.h"
#include "hw_ltc_gp10b.h"
#include "gp10b_sysfs.h"
#define GP10B_MAX_SUPPORTED_FREQS 11
static unsigned long gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS];
@@ -142,7 +143,8 @@ static int gp10b_tegra_late_probe(struct platform_device *pdev)
{
/* Make gk20a power domain a subdomain of host1x */
nvhost_register_client_domain(dev_to_genpd(&pdev->dev));
/*Create GP10B specific sysfs*/
gp10b_create_sysfs(pdev);
return 0;
}
@@ -150,9 +152,9 @@ static int gp10b_tegra_remove(struct platform_device *pdev)
{
/* remove gk20a power subdomain from host1x */
nvhost_unregister_client_domain(dev_to_genpd(&pdev->dev));
gr_gp10b_remove_sysfs(&pdev->dev);
/*Remove GP10B specific sysfs*/
gp10b_remove_sysfs(&pdev->dev);
return 0;
}

View File

@@ -2,7 +2,7 @@
* GP10B PMU
*
* Copyright (c) 2015-2016, 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.
@@ -14,6 +14,7 @@
*/
#include <linux/delay.h> /* for udelay */
#include <linux/tegra-fuse.h>
#include "gk20a/gk20a.h"
#include "gk20a/pmu_gk20a.h"
#include "gm20b/acr_gm20b.h"
@@ -21,6 +22,7 @@
#include "pmu_gp10b.h"
#include "hw_pwr_gp10b.h"
#include "gp10b_sysfs.h"
#define gp10b_dbg_pmu(fmt, arg...) \
gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
@@ -324,6 +326,76 @@ static int gp10b_init_pmu_setup_hw1(struct gk20a *g)
}
static void pmu_handle_ecc_en_dis_msg(struct gk20a *g, struct pmu_msg *msg,
void *param, u32 handle, u32 status)
{
struct pmu_gk20a *pmu = &g->pmu;
struct pmu_msg_lrf_tex_ltc_dram_en_dis *ecc =
&msg->msg.lrf_tex_ltc_dram.en_dis;
gk20a_dbg_fn("");
if (status != 0) {
gk20a_err(dev_from_gk20a(g), "ECC en dis cmd aborted");
return;
}
if (msg->msg.lrf_tex_ltc_dram.msg_type !=
PMU_LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS) {
gk20a_err(dev_from_gk20a(g),
"Invalid msg for LRF_TEX_LTC_DRAM_CMD_ID_EN_DIS cmd");
return;
} else if (ecc->pmu_status != 0) {
gk20a_err(dev_from_gk20a(g),
"LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS msg status = %x",
ecc->pmu_status);
gk20a_err(dev_from_gk20a(g),
"LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS msg en fail = %x",
ecc->en_fail_mask);
gk20a_err(dev_from_gk20a(g),
"LRF_TEX_LTC_DRAM_MSG_ID_EN_DIS msg dis fail = %x",
ecc->dis_fail_mask);
} else
pmu->override_done = 1;
gk20a_dbg_fn("done");
}
static int send_ecc_overide_en_dis_cmd(struct gk20a *g, u32 bitmask)
{
struct pmu_gk20a *pmu = &g->pmu;
struct pmu_cmd cmd;
u32 seq;
int status;
gk20a_dbg_fn("");
if (!tegra_fuse_readl(FUSE_OPT_ECC_EN)) {
gk20a_err(dev_from_gk20a(g), "Board not ECC capable");
return -1;
}
if (!(g->acr.capabilities &
ACR_LRF_TEX_LTC_DRAM_PRIV_MASK_ENABLE_LS_OVERRIDE)) {
gk20a_err(dev_from_gk20a(g), "check ACR capabilities");
return -1;
}
memset(&cmd, 0, sizeof(struct pmu_cmd));
cmd.hdr.unit_id = PMU_UNIT_FECS_MEM_OVERRIDE;
cmd.hdr.size = PMU_CMD_HDR_SIZE +
sizeof(struct pmu_cmd_lrf_tex_ltc_dram_en_dis);
cmd.cmd.lrf_tex_ltc_dram.en_dis.cmd_type =
PMU_LRF_TEX_LTC_DRAM_CMD_ID_EN_DIS;
cmd.cmd.lrf_tex_ltc_dram.en_dis.en_dis_mask = (u8)(bitmask & 0xff);
gp10b_dbg_pmu("cmd post PMU_ECC_CMD_ID_EN_DIS_ECC");
pmu->override_done = 0;
status = gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_LPQ,
pmu_handle_ecc_en_dis_msg, NULL, &seq, ~0);
if (status)
gk20a_err(dev_from_gk20a(g), "ECC override failed");
else
pmu_wait_message_cond(pmu, gk20a_get_gr_idle_timeout(g),
&pmu->override_done, 1);
gk20a_dbg_fn("done");
return status;
}
void gp10b_init_pmu_ops(struct gpu_ops *gops)
{
if (gops->privsecurity) {
@@ -342,4 +414,6 @@ void gp10b_init_pmu_ops(struct gpu_ops *gops)
gops->pmu.write_dmatrfbase = gp10b_write_dmatrfbase;
gops->pmu.pmu_elpg_statistics = gp10b_pmu_elpg_statistics;
gops->pmu.pmu_pg_grinit_param = gp10b_pg_gr_init;
gops->pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd =
send_ecc_overide_en_dis_cmd;
}