diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 008b0129f..89074c49d 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -215,7 +215,8 @@ nvgpu-$(CONFIG_DEBUG_FS) += \ os/linux/debug_ltc.o \ os/linux/debug_xve.o \ os/linux/debug_clk_gv100.o \ - os/linux/debug_volt.o + os/linux/debug_volt.o \ + os/linux/debug_s_param.o ifeq ($(CONFIG_NVGPU_TRACK_MEM_USAGE),y) nvgpu-$(CONFIG_DEBUG_FS) += \ diff --git a/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.c b/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.c index daeae9ffd..1e3fe731c 100644 --- a/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.c +++ b/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.c @@ -102,6 +102,85 @@ static int vfe_vars_pmustatus_instget(struct gk20a *g, void *pboardobjgrppmu, return 0; } +static int vfe_var_get_s_param_value(struct gk20a *g, + struct vfe_var_single_sensed_fuse *fuse_value, + struct nv_pmu_boardobj *ppmudata) +{ + struct nv_pmu_perf_vfe_var_single_sensed_fuse_get_status *pstatus; + pstatus = (struct nv_pmu_perf_vfe_var_single_sensed_fuse_get_status *) + (void *)ppmudata; + + nvgpu_log_info(g, " "); + + if (pstatus->super.board_obj.type != + fuse_value->super.super.super.super.type) { + nvgpu_err(g,"pmu data and boardobj type not matching"); + return -EINVAL; + } + + if(pstatus->fuse_value_integer.b_signed) { + fuse_value->b_fuse_value_signed = + pstatus->fuse_value_integer.b_signed; + fuse_value->fuse_value_integer = + (u32)pstatus->fuse_value_integer.data.signed_value; + fuse_value->fuse_value_hw_integer = + (u32)pstatus->fuse_value_hw_integer.data.signed_value; + } else { + fuse_value->b_fuse_value_signed = + pstatus->fuse_value_integer.b_signed; + fuse_value->fuse_value_integer = + pstatus->fuse_value_integer.data.unsigned_value; + fuse_value->fuse_value_hw_integer = + pstatus->fuse_value_hw_integer.data.unsigned_value; + } + return 0; +} + +int nvgpu_vfe_var_boardobj_grp_get_status(struct gk20a *g) { + struct boardobjgrp *pboardobjgrp; + struct boardobjgrpmask *pboardobjgrpmask; + struct nv_pmu_boardobjgrp_super *pboardobjgrppmu; + struct boardobj *pboardobj = NULL; + struct nv_pmu_boardobj_query *pboardobjpmustatus = NULL; + struct vfe_var_single_sensed_fuse *single_sensed_fuse = NULL; + int status; + u8 index; + + nvgpu_log_info(g, " "); + pboardobjgrp = &g->perf_pmu->vfe_varobjs.super.super; + pboardobjgrpmask = &g->perf_pmu->vfe_varobjs.super.mask.super; + status = pboardobjgrp->pmugetstatus(g, pboardobjgrp, pboardobjgrpmask); + if (status != 0) { + nvgpu_err(g, "err getting boardobjs from pmu"); + return status; + } + pboardobjgrppmu = pboardobjgrp->pmu.getstatus.buf; + + BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) { + single_sensed_fuse = (struct vfe_var_single_sensed_fuse *) + (void *)pboardobj; + status = pboardobjgrp->pmustatusinstget(g, + (struct nv_pmu_boardobjgrp *)(void *)pboardobjgrppmu, + &pboardobjpmustatus, index); + if (status != 0) { + nvgpu_err(g, "could not get status object instance"); + return status; + } + /* At present we are updating only s_param, + * in future we can add other fields if required */ + if (single_sensed_fuse->vfield_info.v_field_id == + VFIELD_ID_S_PARAM) { + status = vfe_var_get_s_param_value(g, single_sensed_fuse, + (struct nv_pmu_boardobj *)(void *)pboardobjpmustatus); + if (status != 0) { + nvgpu_err(g, "could not get single sensed fuse value"); + return status; + } + break; + } + } + return 0; +} int vfe_var_sw_setup(struct gk20a *g) { diff --git a/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.h b/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.h index b7d9fb413..2ca228194 100644 --- a/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.h +++ b/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.h @@ -106,4 +106,6 @@ struct vfe_var_single_sensed_temp { int temp_default; }; +int nvgpu_vfe_var_boardobj_grp_get_status(struct gk20a *g); + #endif /* NVGPU_PERF_VFE_VAR_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/bios.h b/drivers/gpu/nvgpu/include/nvgpu/bios.h index cbb2d4ca6..781416106 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/bios.h +++ b/drivers/gpu/nvgpu/include/nvgpu/bios.h @@ -536,6 +536,7 @@ struct vbios_vfe_3x_equ_entry_struct { #define VFIELD_CODE(pvregentry) ((pvregentry->strap_reg_desc & 0xE0U) >> 5U) +#define VFIELD_ID_S_PARAM 0x07U #define VFIELD_ID_STRAP_IDDQ 0x09U #define VFIELD_ID_STRAP_IDDQ_1 0x0BU diff --git a/drivers/gpu/nvgpu/os/linux/debug_s_param.c b/drivers/gpu/nvgpu/os/linux/debug_s_param.c new file mode 100644 index 000000000..2cbbf9b81 --- /dev/null +++ b/drivers/gpu/nvgpu/os/linux/debug_s_param.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "os_linux.h" +#include "include/nvgpu/bios.h" + +#include +#include + +static int get_s_param_info(void *data, u64 *val) +{ + struct gk20a *g = (struct gk20a *)data; + struct boardobjgrp *pboardobjgrp; + struct boardobj *pboardobj = NULL; + struct vfe_var_single_sensed_fuse *single_sensed_fuse = NULL; + int status; + u8 index; + + status = nvgpu_vfe_var_boardobj_grp_get_status(g); + if(status != 0) { + nvgpu_err(g, "Vfe_var get status failed"); + return status; + } + + pboardobjgrp = &g->perf_pmu->vfe_varobjs.super.super; + + BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) { + single_sensed_fuse = (struct vfe_var_single_sensed_fuse *) + (void *)pboardobj; + if(single_sensed_fuse->vfield_info.v_field_id == + VFIELD_ID_S_PARAM) { + *val = single_sensed_fuse->fuse_value_hw_integer; + } + } + return status; +} +DEFINE_SIMPLE_ATTRIBUTE(s_param_fops, get_s_param_info , NULL, "%llu\n"); + +int nvgpu_s_param_init_debugfs(struct gk20a *g) +{ + struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); + struct dentry *dbgentry; + + dbgentry = debugfs_create_file( + "s_param", S_IRUGO, l->debugfs, g, &s_param_fops); + if (!dbgentry) { + pr_err("%s: Failed to make debugfs node\n", __func__); + return -ENOMEM; + } + + return 0; +} diff --git a/drivers/gpu/nvgpu/os/linux/debug_s_param.h b/drivers/gpu/nvgpu/os/linux/debug_s_param.h new file mode 100644 index 000000000..f5250494e --- /dev/null +++ b/drivers/gpu/nvgpu/os/linux/debug_s_param.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __DEBUG_S_PARAM_TU104_H +#define __DEBUG_S_PARAM_TU104_H + +#include + +#ifdef CONFIG_DEBUG_FS +int nvgpu_s_param_init_debugfs(struct gk20a *g); +#else +static inline int nvgpu_s_param_init_debugfs(struct gk20a *g) +{ + return 0; +} +#endif + +#endif diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index 494c51766..f6a20b0ce 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -241,6 +241,14 @@ int nvgpu_finalize_poweron_linux(struct nvgpu_os_linux *l) } } + if (l->ops.s_param.init_debugfs) { + err = l->ops.s_param.init_debugfs(g); + if (err) { + nvgpu_err(g, "failed to init linux s_param trace debugfs"); + return err; + } + } + err = nvgpu_pmgr_init_debugfs_linux(l); if (err) { nvgpu_err(g, "failed to init linux pmgr debugfs"); diff --git a/drivers/gpu/nvgpu/os/linux/os_linux.h b/drivers/gpu/nvgpu/os/linux/os_linux.h index 71e0c65d2..6c8b974aa 100644 --- a/drivers/gpu/nvgpu/os/linux/os_linux.h +++ b/drivers/gpu/nvgpu/os/linux/os_linux.h @@ -56,6 +56,10 @@ struct nvgpu_os_linux_ops { struct { int (*init_debugfs)(struct gk20a *g); } volt; + + struct { + int (*init_debugfs)(struct gk20a *g); + } s_param; }; struct nvgpu_os_linux { diff --git a/drivers/gpu/nvgpu/os/linux/os_ops_tu104.c b/drivers/gpu/nvgpu/os/linux/os_ops_tu104.c index 94f279787..6b70b738a 100644 --- a/drivers/gpu/nvgpu/os/linux/os_ops_tu104.c +++ b/drivers/gpu/nvgpu/os/linux/os_ops_tu104.c @@ -19,6 +19,7 @@ #include "os/linux/debug_therm_gp106.h" #include "os/linux/debug_clk_gv100.h" #include "os/linux/debug_volt.h" +#include "os/linux/debug_s_param.h" static struct nvgpu_os_linux_ops tu104_os_linux_ops = { .therm = { @@ -30,6 +31,9 @@ static struct nvgpu_os_linux_ops tu104_os_linux_ops = { .volt = { .init_debugfs = nvgpu_volt_init_debugfs, }, + .s_param = { + .init_debugfs = nvgpu_s_param_init_debugfs, + }, }; void nvgpu_tu104_init_os_ops(struct nvgpu_os_linux *l) @@ -37,4 +41,5 @@ void nvgpu_tu104_init_os_ops(struct nvgpu_os_linux *l) l->ops.therm = tu104_os_linux_ops.therm; l->ops.clk = tu104_os_linux_ops.clk; l->ops.volt = tu104_os_linux_ops.volt; + l->ops.s_param = tu104_os_linux_ops.s_param; }