gpu: nvgpu: gsp: gsp isr and debug trace support

- Created GSP NVRISCV interrupt handle and
  respective functions and register reads.
- Created Debug trace support for GSP firmware.

NVGPU-7084

Signed-off-by: Ramesh Mylavarapu <rmylavarapu@nvidia.com>
Change-Id: I2728150c4db00403aa6e3c043bc19c51677dd9cf
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2589430
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Ramesh Mylavarapu
2021-09-05 00:19:00 +05:30
committed by mobile promotions
parent 2afd601a40
commit ffd0d3962f
14 changed files with 378 additions and 10 deletions

View File

@@ -159,7 +159,7 @@ extern void ga10b_falcon_sw_init(struct nvgpu_falcon *flcn)
flcn->flcn_base = g->ops.gsp.falcon_base_addr();
flcn->flcn2_base = g->ops.gsp.falcon2_base_addr();
flcn->is_falcon_supported = true;
flcn->is_interrupt_enabled = false;
flcn->is_interrupt_enabled = true;
check_and_enable_falcon2(flcn, &flcn->fuse_settings);
break;

View File

@@ -96,13 +96,6 @@ static int gsp_ucode_load_and_bootstrap(struct gk20a *g,
nvgpu_log_fn(g, " ");
/* core reset */
err = nvgpu_falcon_reset(flcn);
if (err != 0) {
nvgpu_err(g, "gsp core reset failed err=%d", err);
goto exit;
}
g->ops.falcon.set_bcr(flcn);
err = nvgpu_falcon_get_mem_size(flcn, MEM_DMEM, &dmem_size);
if (err != 0) {
@@ -225,6 +218,16 @@ int gsp_bootstrap_ns(struct gk20a *g, struct nvgpu_gsp *gsp)
goto exit;
}
/* core reset */
err = nvgpu_falcon_reset(gsp->gsp_flcn);
if (err != 0) {
nvgpu_err(g, "gsp core reset failed err=%d", err);
goto exit;
}
/* Enable required interrupts support and isr */
nvgpu_gsp_isr_support(g, true);
err = gsp_ucode_load_and_bootstrap(g, gsp->gsp_flcn, gsp_ucode);
if (err != 0) {
nvgpu_err(g, "gsp load and bootstrap failed");

View File

@@ -29,9 +29,27 @@
#include "gsp_priv.h"
#include "gsp_bootstrap.h"
void nvgpu_gsp_isr_support(struct gk20a *g, bool enable)
{
nvgpu_log_fn(g, " ");
/* Enable irq*/
nvgpu_mutex_acquire(&g->gsp->isr_mutex);
g->ops.gsp.enable_irq(g, enable);
g->gsp->isr_enabled = enable;
nvgpu_mutex_release(&g->gsp->isr_mutex);
}
void nvgpu_gsp_sw_deinit(struct gk20a *g)
{
if (g->gsp != NULL) {
nvgpu_gsp_isr_support(g, false);
nvgpu_mutex_destroy(&g->gsp->isr_mutex);
#ifdef CONFIG_NVGPU_FALCON_DEBUG
nvgpu_falcon_dbg_buf_destroy(g->gsp->gsp_flcn);
#endif
nvgpu_kfree(g, g->gsp);
g->gsp = NULL;
}
@@ -40,6 +58,7 @@ void nvgpu_gsp_sw_deinit(struct gk20a *g)
int nvgpu_gsp_sw_init(struct gk20a *g)
{
int err = 0;
struct nvgpu_gsp *gsp;
nvgpu_log_fn(g, " ");
@@ -59,8 +78,29 @@ int nvgpu_gsp_sw_init(struct gk20a *g)
goto exit;
}
gsp = g->gsp;
gsp->g = g;
/* gsp falcon software state */
g->gsp->gsp_flcn = &g->gsp_flcn;
gsp->gsp_flcn = &g->gsp_flcn;
/* enable debug buffer support */
#ifdef CONFIG_NVGPU_FALCON_DEBUG
if ((g->ops.gsp.gsp_get_queue_head != NULL) &&
(g->ops.gsp.gsp_get_queue_tail != NULL)) {
err = nvgpu_falcon_dbg_buf_init(
gsp->gsp_flcn, GSP_DMESG_BUFFER_SIZE,
g->ops.gsp.gsp_get_queue_head(GSP_DEBUG_BUFFER_QUEUE),
g->ops.gsp.gsp_get_queue_tail(GSP_DEBUG_BUFFER_QUEUE));
if (err != 0) {
nvgpu_err(g, "GSP debug init failed");
goto exit;
}
}
#endif
/* Init isr mutex */
nvgpu_mutex_init(&gsp->isr_mutex);
exit:
return err;
@@ -83,3 +123,31 @@ de_init:
nvgpu_gsp_sw_deinit(g);
return err;
}
void nvgpu_gsp_isr_mutex_aquire(struct gk20a *g)
{
struct nvgpu_gsp *gsp = g->gsp;
nvgpu_mutex_acquire(&gsp->isr_mutex);
}
void nvgpu_gsp_isr_mutex_release(struct gk20a *g)
{
struct nvgpu_gsp *gsp = g->gsp;
nvgpu_mutex_release(&gsp->isr_mutex);
}
bool nvgpu_gsp_is_isr_enable(struct gk20a *g)
{
struct nvgpu_gsp *gsp = g->gsp;
return gsp->isr_enabled;
}
struct nvgpu_falcon *nvgpu_gsp_falcon_instance(struct gk20a *g)
{
struct nvgpu_gsp *gsp = g->gsp;
return gsp->gsp_flcn;
}

View File

@@ -23,6 +23,11 @@
#ifndef NVGPU_GSP_PRIV
#define NVGPU_GSP_PRIV
#include <nvgpu/lock.h>
#define GSP_DEBUG_BUFFER_QUEUE 3U
#define GSP_DMESG_BUFFER_SIZE 0x1000U
struct gsp_fw {
/* gsp ucode */
struct nvgpu_firmware *code;
@@ -32,7 +37,12 @@ struct gsp_fw {
/* GSP descriptor's */
struct nvgpu_gsp {
struct gk20a *g;
struct gsp_fw gsp_ucode;
struct nvgpu_falcon *gsp_flcn;
bool isr_enabled;
struct nvgpu_mutex isr_mutex;
};
#endif /* NVGPU_GSP_PRIV */

View File

@@ -40,7 +40,9 @@
#include <nvgpu/fb.h>
#include <nvgpu/device.h>
#include <nvgpu/gr/gr.h>
#ifdef CONFIG_NVGPU_GSP_SCHEDULER
#include <nvgpu/gsp.h>
#endif
#include <nvgpu/pm_reservation.h>
#include <nvgpu/netlist.h>
#include <nvgpu/hal_init.h>

View File

@@ -26,6 +26,9 @@
#include <nvgpu/timers.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/bug.h>
#ifdef CONFIG_NVGPU_GSP_SCHEDULER
#include <nvgpu/gsp.h>
#endif
#include "gsp_ga10b.h"
@@ -51,3 +54,181 @@ int ga10b_gsp_engine_reset(struct gk20a *g)
return 0;
}
#ifdef CONFIG_NVGPU_GSP_SCHEDULER
u32 ga10b_gsp_queue_head_r(u32 i)
{
return pgsp_queue_head_r(i);
}
u32 ga10b_gsp_queue_head__size_1_v(void)
{
return pgsp_queue_head__size_1_v();
}
u32 ga10b_gsp_queue_tail_r(u32 i)
{
return pgsp_queue_tail_r(i);
}
u32 ga10b_gsp_queue_tail__size_1_v(void)
{
return pgsp_queue_tail__size_1_v();
}
static u32 ga10b_gsp_get_irqmask(struct gk20a *g)
{
return (gk20a_readl(g, pgsp_riscv_irqmask_r()) &
gk20a_readl(g, pgsp_riscv_irqdest_r()));
}
static bool ga10b_gsp_is_interrupted(struct gk20a *g, u32 *intr)
{
u32 supported_gsp_int = 0U;
u32 intr_stat = gk20a_readl(g, pgsp_falcon_irqstat_r());
supported_gsp_int = pgsp_falcon_irqstat_halt_true_f() |
pgsp_falcon_irqstat_swgen1_true_f();
if ((intr_stat & supported_gsp_int) != 0U) {
*intr = intr_stat;
return true;
}
return false;
}
static void ga10b_gsp_handle_swgen1_irq(struct gk20a *g)
{
int err = 0;
struct nvgpu_falcon *flcn = NULL;
nvgpu_log_fn(g, " ");
flcn = nvgpu_gsp_falcon_instance(g);
if (flcn == NULL) {
nvgpu_err(g, "GSP falcon instance not found");
return;
}
#ifdef CONFIG_NVGPU_FALCON_DEBUG
err = nvgpu_falcon_dbg_buf_display(flcn);
if (err != 0) {
nvgpu_err(g, "nvgpu_falcon_debug_buffer_display failed err=%d",
err);
}
#endif
}
static void ga10b_gsp_clr_intr(struct gk20a *g, u32 intr)
{
gk20a_writel(g, pgsp_riscv_irqmclr_r(), intr);
}
void ga10b_gsp_handle_interrupts(struct gk20a *g, u32 intr)
{
nvgpu_log_fn(g, " ");
/* swgen1 interrupt handle */
if ((intr & pgsp_falcon_irqstat_swgen1_true_f()) != 0U) {
ga10b_gsp_handle_swgen1_irq(g);
}
/* halt interrupt handle */
if ((intr & pgsp_falcon_irqstat_halt_true_f()) != 0U) {
nvgpu_err(g, "gsp halt intr not implemented");
}
}
void ga10b_gsp_isr(struct gk20a *g)
{
u32 intr = 0U;
u32 mask = 0U;
nvgpu_log_fn(g, " ");
if (!ga10b_gsp_is_interrupted(g, &intr)) {
nvgpu_err(g, "GSP interrupt not supported stat:0x%08x", intr);
return;
}
nvgpu_gsp_isr_mutex_aquire(g);
if (!nvgpu_gsp_is_isr_enable(g)) {
goto exit;
}
mask = ga10b_gsp_get_irqmask(g);
nvgpu_log_info(g, "received gsp interrupt: stat:0x%08x mask:0x%08x",
intr, mask);
if ((intr & mask) == 0U) {
nvgpu_log_info(g,
"clearing unhandled interrupt: stat:0x%08x mask:0x%08x",
intr, mask);
nvgpu_writel(g, pgsp_riscv_irqmclr_r(), intr);
goto exit;
}
intr = intr & mask;
ga10b_gsp_clr_intr(g, intr);
ga10b_gsp_handle_interrupts(g, intr);
exit:
nvgpu_gsp_isr_mutex_release(g);
}
static void ga10b_riscv_set_irq(struct gk20a *g, bool set_irq,
u32 intr_mask, u32 intr_dest)
{
if (set_irq) {
gk20a_writel(g, pgsp_riscv_irqmset_r(), intr_mask);
gk20a_writel(g, pgsp_riscv_irqdest_r(), intr_dest);
} else {
gk20a_writel(g, pgsp_riscv_irqmclr_r(), 0xffffffffU);
}
}
void ga10b_gsp_enable_irq(struct gk20a *g, bool enable)
{
u32 intr_mask;
u32 intr_dest;
nvgpu_log_fn(g, " ");
/* clear before setting required irq */
ga10b_riscv_set_irq(g, false, 0x0, 0x0);
nvgpu_cic_mon_intr_stall_unit_config(g,
NVGPU_CIC_INTR_UNIT_GSP, NVGPU_CIC_INTR_DISABLE);
if (enable) {
/* dest 0=falcon, 1=host; level 0=irq0, 1=irq1 */
intr_dest = pgsp_riscv_irqdest_gptmr_f(0) |
pgsp_riscv_irqdest_wdtmr_f(1) |
pgsp_riscv_irqdest_mthd_f(0) |
pgsp_riscv_irqdest_ctxsw_f(0) |
pgsp_riscv_irqdest_halt_f(1) |
pgsp_riscv_irqdest_exterr_f(0) |
pgsp_riscv_irqdest_swgen0_f(1) |
pgsp_riscv_irqdest_swgen1_f(1) |
pgsp_riscv_irqdest_ext_f(0xff);
/* 0=disable, 1=enable */
intr_mask = pgsp_riscv_irqmset_gptmr_f(1) |
pgsp_riscv_irqmset_wdtmr_f(1) |
pgsp_riscv_irqmset_mthd_f(0) |
pgsp_riscv_irqmset_ctxsw_f(0) |
pgsp_riscv_irqmset_halt_f(1) |
pgsp_riscv_irqmset_exterr_f(1) |
pgsp_riscv_irqmset_swgen0_f(1) |
pgsp_riscv_irqmset_swgen1_f(1);
/* set required irq */
ga10b_riscv_set_irq(g, true, intr_mask, intr_dest);
nvgpu_cic_mon_intr_stall_unit_config(g,
NVGPU_CIC_INTR_UNIT_GSP, NVGPU_CIC_INTR_ENABLE);
}
}
#endif /* CONFIG_NVGPU_GSP_SCHEDULER */

View File

@@ -26,5 +26,15 @@
u32 ga10b_gsp_falcon_base_addr(void);
u32 ga10b_gsp_falcon2_base_addr(void);
int ga10b_gsp_engine_reset(struct gk20a *g);
#ifdef CONFIG_NVGPU_GSP_SCHEDULER
/* queue */
u32 ga10b_gsp_queue_head_r(u32 i);
u32 ga10b_gsp_queue_head__size_1_v(void);
u32 ga10b_gsp_queue_tail_r(u32 i);
u32 ga10b_gsp_queue_tail__size_1_v(void);
/* interrupt */
void ga10b_gsp_enable_irq(struct gk20a *g, bool enable);
void ga10b_gsp_isr(struct gk20a *g);
#endif /* CONFIG_NVGPU_GSP_SCHEDULER */
#endif /* GSP_GA10B_H */

View File

@@ -1251,6 +1251,17 @@ static const struct gops_gsp ga10b_ops_gsp = {
.falcon_base_addr = ga10b_gsp_falcon_base_addr,
.falcon2_base_addr = ga10b_gsp_falcon2_base_addr,
.gsp_reset = ga10b_gsp_engine_reset,
#ifdef CONFIG_NVGPU_GSP_SCHEDULER
/* interrupt */
.enable_irq = ga10b_gsp_enable_irq,
.gsp_isr = ga10b_gsp_isr,
/* queue */
.gsp_get_queue_head = ga10b_gsp_queue_head_r,
.gsp_get_queue_head_size = ga10b_gsp_queue_head__size_1_v,
.gsp_get_queue_tail = ga10b_gsp_queue_tail_r,
.gsp_get_queue_tail_size = ga10b_gsp_queue_tail__size_1_v,
#endif /* CONFIG_NVGPU_GSP_SCHEDULER */
};
static const struct gops_pmu ga10b_ops_pmu = {

View File

@@ -440,6 +440,15 @@ bool ga10b_mc_intr_get_unit_info(struct gk20a *g, u32 unit)
case NVGPU_CIC_INTR_UNIT_RUNLIST_TREE_1:
nvgpu_log(g, gpu_dbg_intr, "RUNLIST interrupts");
break;
#ifdef CONFIG_NVGPU_GSP_SCHEDULER
case NVGPU_CIC_INTR_UNIT_GSP:
intr_unit_info->vectorid[0] =
func_priv_cpu_intr_gsp_vector_v();
intr_unit_info->vectorid_size = NVGPU_CIC_INTR_VECTORID_SIZE_ONE;
break;
#endif /* CONFIG_NVGPU_GSP_SCHEDULER */
default:
nvgpu_err(g, "non supported intr unit");
return false;
@@ -687,6 +696,15 @@ static void ga10b_intr_isr_stall_host2soc_2(struct gk20a *g)
g->ops.pmu.pmu_isr(g);
}
#ifdef CONFIG_NVGPU_GSP_SCHEDULER
if (ga10b_intr_is_unit_pending(g, NVGPU_CIC_INTR_UNIT_GSP, intr_leaf0, intr_leaf1,
&unit_subtree_mask) == true) {
handled_subtree_mask |= unit_subtree_mask;
ga10b_intr_subtree_clear(g, subtree, unit_subtree_mask);
g->ops.gsp.gsp_isr(g);
}
#endif /* CONFIG_NVGPU_GSP_SCHEDULER */
ga10b_intr_subtree_clear_unhandled(g, subtree, intr_leaf0, intr_leaf1,
handled_subtree_mask);
}

View File

@@ -76,7 +76,8 @@
#define NVGPU_CIC_INTR_UNIT_RUNLIST_TREE_1 17U
#define NVGPU_CIC_INTR_UNIT_GR_STALL 18U
#define NVGPU_CIC_INTR_UNIT_CE_STALL 19U
#define NVGPU_CIC_INTR_UNIT_MAX 20U
#define NVGPU_CIC_INTR_UNIT_GSP 20U
#define NVGPU_CIC_INTR_UNIT_MAX 21U
#define NVGPU_CIC_INTR_VECTORID_SIZE_MAX 32U
#define NVGPU_CIC_INTR_VECTORID_SIZE_ONE 1U

View File

@@ -25,12 +25,23 @@
#include <nvgpu/types.h>
struct gk20a;
struct nvgpu_gsp;
struct gops_gsp {
u32 (*falcon_base_addr)(void);
u32 (*falcon2_base_addr)(void);
void (*falcon_setup_boot_config)(struct gk20a *g);
int (*gsp_reset)(struct gk20a *g);
#ifdef CONFIG_NVGPU_GSP_SCHEDULER
/* queue */
u32 (*gsp_get_queue_head)(u32 i);
u32 (*gsp_get_queue_head_size)(void);
u32 (*gsp_get_queue_tail_size)(void);
u32 (*gsp_get_queue_tail)(u32 i);
void (*enable_irq)(struct gk20a *g, bool enable);
void (*gsp_isr)(struct gk20a *g);
#endif /* CONFIG_NVGPU_GSP_SCHEDULER */
};
#endif /* NVGPU_GOPS_GSP_H */

View File

@@ -23,8 +23,14 @@
#ifndef NVGPU_GSP
#define NVGPU_GSP
struct gk20a;
struct nvgpu_gsp;
int nvgpu_gsp_sw_init(struct gk20a *g);
int nvgpu_gsp_bootstrap(struct gk20a *g);
void nvgpu_gsp_sw_deinit(struct gk20a *g);
void nvgpu_gsp_isr_support(struct gk20a *g, bool enable);
void nvgpu_gsp_isr_mutex_aquire(struct gk20a *g);
void nvgpu_gsp_isr_mutex_release(struct gk20a *g);
bool nvgpu_gsp_is_isr_enable(struct gk20a *g);
struct nvgpu_falcon *nvgpu_gsp_falcon_instance(struct gk20a *g);
#endif /* NVGPU_GSP */

View File

@@ -82,6 +82,7 @@
#define func_priv_cpu_intr_pfb_vector_v() (0x0000008dU)
#define func_priv_cpu_intr_pmu_vector_v() (0x00000098U)
#define func_priv_cpu_intr_ltc_all_vector_v() (0x00000099U)
#define func_priv_cpu_intr_gsp_vector_v() (0x0000009bU)
#define func_priv_cpu_intr_pbus_vector_v() (0x0000009cU)
#define func_priv_cpu_intr_priv_ring_vector_v() (0x0000009eU)
#endif

View File

@@ -64,4 +64,50 @@
#define pgsp_falcon_engine_r() (0x001103c0U)
#define pgsp_falcon_engine_reset_true_f() (0x1U)
#define pgsp_falcon_engine_reset_false_f() (0x0U)
#define pgsp_falcon_irqstat_r() (0x00110008U)
#define pgsp_falcon_irqstat_halt_true_f() (0x10U)
#define pgsp_falcon_irqstat_exterr_true_f() (0x20U)
#define pgsp_falcon_irqstat_swgen0_true_f() (0x40U)
#define pgsp_falcon_irqstat_swgen1_true_f() (0x80U)
#define pgsp_falcon_irqmode_r() (0x0011000cU)
#define pgsp_riscv_irqmset_r() (0x00111520U)
#define pgsp_riscv_irqmset_gptmr_f(v) ((U32(v) & 0x1U) << 0U)
#define pgsp_riscv_irqmset_wdtmr_f(v) ((U32(v) & 0x1U) << 1U)
#define pgsp_riscv_irqmset_mthd_f(v) ((U32(v) & 0x1U) << 2U)
#define pgsp_riscv_irqmset_ctxsw_f(v) ((U32(v) & 0x1U) << 3U)
#define pgsp_riscv_irqmset_halt_f(v) ((U32(v) & 0x1U) << 4U)
#define pgsp_riscv_irqmset_exterr_f(v) ((U32(v) & 0x1U) << 5U)
#define pgsp_riscv_irqmset_swgen0_f(v) ((U32(v) & 0x1U) << 6U)
#define pgsp_riscv_irqmset_swgen1_f(v) ((U32(v) & 0x1U) << 7U)
#define pgsp_riscv_irqmclr_r() (0x00111524U)
#define pgsp_riscv_irqmclr_gptmr_f(v) ((U32(v) & 0x1U) << 0U)
#define pgsp_riscv_irqmclr_wdtmr_f(v) ((U32(v) & 0x1U) << 1U)
#define pgsp_riscv_irqmclr_mthd_f(v) ((U32(v) & 0x1U) << 2U)
#define pgsp_riscv_irqmclr_ctxsw_f(v) ((U32(v) & 0x1U) << 3U)
#define pgsp_riscv_irqmclr_halt_f(v) ((U32(v) & 0x1U) << 4U)
#define pgsp_riscv_irqmclr_exterr_f(v) ((U32(v) & 0x1U) << 5U)
#define pgsp_riscv_irqmclr_swgen0_f(v) ((U32(v) & 0x1U) << 6U)
#define pgsp_riscv_irqmclr_swgen1_f(v) ((U32(v) & 0x1U) << 7U)
#define pgsp_riscv_irqmclr_ext_f(v) ((U32(v) & 0xffU) << 8U)
#define pgsp_riscv_irqmask_r() (0x00111528U)
#define pgsp_riscv_irqdest_r() (0x0011152cU)
#define pgsp_riscv_irqdest_gptmr_f(v) ((U32(v) & 0x1U) << 0U)
#define pgsp_riscv_irqdest_wdtmr_f(v) ((U32(v) & 0x1U) << 1U)
#define pgsp_riscv_irqdest_mthd_f(v) ((U32(v) & 0x1U) << 2U)
#define pgsp_riscv_irqdest_ctxsw_f(v) ((U32(v) & 0x1U) << 3U)
#define pgsp_riscv_irqdest_halt_f(v) ((U32(v) & 0x1U) << 4U)
#define pgsp_riscv_irqdest_exterr_f(v) ((U32(v) & 0x1U) << 5U)
#define pgsp_riscv_irqdest_swgen0_f(v) ((U32(v) & 0x1U) << 6U)
#define pgsp_riscv_irqdest_swgen1_f(v) ((U32(v) & 0x1U) << 7U)
#define pgsp_riscv_irqdest_ext_f(v) ((U32(v) & 0xffU) << 8U)
#define pgsp_queue_head_r(i)\
(nvgpu_safe_add_u32(0x00110c00U, nvgpu_safe_mult_u32((i), 8U)))
#define pgsp_queue_head__size_1_v() (0x00000008U)
#define pgsp_queue_head_address_f(v) ((U32(v) & 0xffffffffU) << 0U)
#define pgsp_queue_head_address_v(r) (((r) >> 0U) & 0xffffffffU)
#define pgsp_queue_tail_r(i)\
(nvgpu_safe_add_u32(0x00110c04U, nvgpu_safe_mult_u32((i), 8U)))
#define pgsp_queue_tail__size_1_v() (0x00000008U)
#define pgsp_queue_tail_address_f(v) ((U32(v) & 0xffffffffU) << 0U)
#define pgsp_queue_tail_address_v(r) (((r) >> 0U) & 0xffffffffU)
#endif