mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-23 18:16:01 +03:00
Mostly just including necessary includes to make sure that
global function declarations actually match their implementations.
Also work around pointer munging warning:
/build/ddpx/linux/kernel/nvgpu/drivers/gpu/nvgpu/common/pmu/pmu.c: In function 'nvgpu_pmu_process_init_msg':
/build/ddpx/linux/kernel/nvgpu/drivers/gpu/nvgpu/common/pmu/pmu.c:348:4: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
(*(u32 *)gid_data.signature == PMU_SHA1_GID_SIGNATURE);
Work around this warning by simply moving the type punning.
This code is certainly dangerous - it assumes the endianness
of the header data is the same as the machine this code is
running on. Apparently it works, though, so this ignores
the warning.
JIRA NVGPU-525
Change-Id: Id704bae7805440bebfad51c8c8365e6d2b7a39eb
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1692454
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
200 lines
6.1 KiB
C
200 lines
6.1 KiB
C
/*
|
|
* GP10B priv ring
|
|
*
|
|
* Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "gk20a/gk20a.h"
|
|
|
|
#include <nvgpu/log.h>
|
|
#include <nvgpu/timers.h>
|
|
#include <nvgpu/enabled.h>
|
|
|
|
#include <nvgpu/hw/gp10b/hw_mc_gp10b.h>
|
|
#include <nvgpu/hw/gp10b/hw_pri_ringmaster_gp10b.h>
|
|
#include <nvgpu/hw/gp10b/hw_pri_ringstation_sys_gp10b.h>
|
|
#include <nvgpu/hw/gp10b/hw_pri_ringstation_gpc_gp10b.h>
|
|
|
|
#include "priv_ring_gp10b.h"
|
|
|
|
static const char * const invalid_str = "invalid";
|
|
|
|
static const char *const error_type_badf1xyy[] = {
|
|
"client timeout",
|
|
"decode error",
|
|
"client in reset",
|
|
"client floorswept",
|
|
"client stuck ack",
|
|
"client expected ack",
|
|
"fence error",
|
|
"subid error",
|
|
"byte access unsupported",
|
|
};
|
|
|
|
static const char *const error_type_badf2xyy[] = {
|
|
"orphan gpc/fbp"
|
|
};
|
|
|
|
static const char *const error_type_badf3xyy[] = {
|
|
"priv ring dead"
|
|
};
|
|
|
|
static const char *const error_type_badf5xyy[] = {
|
|
"client error",
|
|
"priv level violation",
|
|
"indirect priv level violation",
|
|
"local local ring error",
|
|
"falcon mem access priv level violation",
|
|
"pri route error"
|
|
};
|
|
|
|
void gp10b_priv_ring_decode_error_code(struct gk20a *g,
|
|
u32 error_code)
|
|
{
|
|
u32 error_type_index;
|
|
|
|
error_type_index = (error_code & 0x00000f00) >> 16;
|
|
error_code = error_code & 0xBADFf000;
|
|
|
|
if (error_code == 0xBADF1000) {
|
|
if (error_type_index <
|
|
ARRAY_SIZE(error_type_badf1xyy))
|
|
nvgpu_err(g, "%s",
|
|
error_type_badf1xyy[error_type_index]);
|
|
} else if (error_code == 0xBADF2000) {
|
|
if (error_type_index <
|
|
ARRAY_SIZE(error_type_badf2xyy))
|
|
nvgpu_err(g, "%s",
|
|
error_type_badf2xyy[error_type_index]);
|
|
} else if (error_code == 0xBADF3000) {
|
|
if (error_type_index <
|
|
ARRAY_SIZE(error_type_badf3xyy))
|
|
nvgpu_err(g, "%s",
|
|
error_type_badf3xyy[error_type_index]);
|
|
} else if (error_code == 0xBADF5000) {
|
|
if (error_type_index <
|
|
ARRAY_SIZE(error_type_badf5xyy))
|
|
nvgpu_err(g, "%s",
|
|
error_type_badf5xyy[error_type_index]);
|
|
}
|
|
}
|
|
|
|
void gp10b_priv_ring_isr(struct gk20a *g)
|
|
{
|
|
u32 status0, status1;
|
|
u32 cmd;
|
|
s32 retry = 100;
|
|
u32 gpc;
|
|
u32 gpc_stride, offset;
|
|
u32 error_info;
|
|
u32 error_code;
|
|
|
|
if (nvgpu_is_enabled(g, NVGPU_IS_FMODEL)) {
|
|
nvgpu_info(g, "unhandled priv ring intr");
|
|
return;
|
|
}
|
|
|
|
status0 = gk20a_readl(g, pri_ringmaster_intr_status0_r());
|
|
status1 = gk20a_readl(g, pri_ringmaster_intr_status1_r());
|
|
|
|
nvgpu_err(g, "ringmaster intr status0: 0x%08x,"
|
|
"status1: 0x%08x", status0, status1);
|
|
|
|
if (pri_ringmaster_intr_status0_ring_start_conn_fault_v(status0) != 0)
|
|
nvgpu_err(g,
|
|
"BUG: connectivity problem on the startup sequence");
|
|
|
|
if (pri_ringmaster_intr_status0_disconnect_fault_v(status0) != 0)
|
|
nvgpu_err(g, "ring disconnected");
|
|
|
|
if (pri_ringmaster_intr_status0_overflow_fault_v(status0) != 0)
|
|
nvgpu_err(g, "ring overflowed");
|
|
|
|
if (pri_ringmaster_intr_status0_gbl_write_error_sys_v(status0) != 0) {
|
|
error_info =
|
|
gk20a_readl(g, pri_ringstation_sys_priv_error_info_r());
|
|
error_code =
|
|
gk20a_readl(g, pri_ringstation_sys_priv_error_code_r());
|
|
nvgpu_err(g, "SYS write error. ADR 0x%08x WRDAT 0x%08x "
|
|
"INFO 0x%08x (subid 0x%08x priv level %d), "
|
|
"CODE 0x%08x",
|
|
gk20a_readl(g, pri_ringstation_sys_priv_error_adr_r()),
|
|
gk20a_readl(g, pri_ringstation_sys_priv_error_wrdat_r()),
|
|
error_info,
|
|
pri_ringstation_sys_priv_error_info_subid_v(error_info),
|
|
pri_ringstation_sys_priv_error_info_priv_level_v(error_info),
|
|
error_code);
|
|
if (g->ops.priv_ring.decode_error_code)
|
|
g->ops.priv_ring.decode_error_code(g, error_code);
|
|
}
|
|
|
|
if (status1) {
|
|
gpc_stride = nvgpu_get_litter_value(g, GPU_LIT_GPC_PRIV_STRIDE);
|
|
for (gpc = 0; gpc < g->gr.gpc_count; gpc++) {
|
|
offset = gpc * gpc_stride;
|
|
if (status1 & BIT(gpc)) {
|
|
error_info = gk20a_readl(g,
|
|
pri_ringstation_gpc_gpc0_priv_error_info_r() + offset);
|
|
error_code = gk20a_readl(g,
|
|
pri_ringstation_gpc_gpc0_priv_error_code_r() + offset);
|
|
nvgpu_err(g, "GPC%u write error. ADR 0x%08x "
|
|
"WRDAT 0x%08x "
|
|
"INFO 0x%08x (subid 0x%08x priv level %d), "
|
|
"CODE 0x%08x", gpc,
|
|
gk20a_readl(g,
|
|
pri_ringstation_gpc_gpc0_priv_error_adr_r() + offset),
|
|
gk20a_readl(g,
|
|
pri_ringstation_gpc_gpc0_priv_error_wrdat_r() + offset),
|
|
error_info,
|
|
pri_ringstation_gpc_gpc0_priv_error_info_subid_v(error_info),
|
|
pri_ringstation_gpc_gpc0_priv_error_info_priv_level_v(error_info),
|
|
error_code);
|
|
|
|
if (g->ops.priv_ring.decode_error_code)
|
|
g->ops.priv_ring.decode_error_code(g,
|
|
error_code);
|
|
|
|
status1 = status1 & (~(BIT(gpc)));
|
|
if (!status1)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/* clear interrupt */
|
|
cmd = gk20a_readl(g, pri_ringmaster_command_r());
|
|
cmd = set_field(cmd, pri_ringmaster_command_cmd_m(),
|
|
pri_ringmaster_command_cmd_ack_interrupt_f());
|
|
gk20a_writel(g, pri_ringmaster_command_r(), cmd);
|
|
|
|
/* poll for clear interrupt done */
|
|
cmd = pri_ringmaster_command_cmd_v(
|
|
gk20a_readl(g, pri_ringmaster_command_r()));
|
|
while (cmd != pri_ringmaster_command_cmd_no_cmd_v() && retry) {
|
|
nvgpu_udelay(20);
|
|
cmd = pri_ringmaster_command_cmd_v(
|
|
gk20a_readl(g, pri_ringmaster_command_r()));
|
|
retry--;
|
|
}
|
|
|
|
if (retry == 0)
|
|
nvgpu_err(g, "priv ringmaster intr ack failed");
|
|
}
|