mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 09:12:24 +03:00
gpu: nvgpu: add doxygen for common MC unit
Add doxygen details about Master Control (MC) common unit. Moved the interrupt handling related variables to new structure nvgpu_mc. JIRA NVGPU-2524 Change-Id: I61fb4ba325d9bd71e9505af01cd5a82e4e205833 Signed-off-by: Sagar Kamble <skamble@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2226019 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Alex Waterman
parent
b26acdeb87
commit
f2b49f1c40
@@ -48,18 +48,19 @@ static int cyclic_delta(int a, int b)
|
||||
*/
|
||||
void nvgpu_wait_for_deferred_interrupts(struct gk20a *g)
|
||||
{
|
||||
int stall_irq_threshold = nvgpu_atomic_read(&g->hw_irq_stall_count);
|
||||
int nonstall_irq_threshold = nvgpu_atomic_read(&g->hw_irq_nonstall_count);
|
||||
int stall_irq_threshold = nvgpu_atomic_read(&g->mc.hw_irq_stall_count);
|
||||
int nonstall_irq_threshold =
|
||||
nvgpu_atomic_read(&g->mc.hw_irq_nonstall_count);
|
||||
|
||||
/* wait until all stalling irqs are handled */
|
||||
NVGPU_COND_WAIT(&g->sw_irq_stall_last_handled_cond,
|
||||
NVGPU_COND_WAIT(&g->mc.sw_irq_stall_last_handled_cond,
|
||||
cyclic_delta(stall_irq_threshold,
|
||||
nvgpu_atomic_read(&g->sw_irq_stall_last_handled))
|
||||
nvgpu_atomic_read(&g->mc.sw_irq_stall_last_handled))
|
||||
<= 0, 0U);
|
||||
|
||||
/* wait until all non-stalling irqs are handled */
|
||||
NVGPU_COND_WAIT(&g->sw_irq_nonstall_last_handled_cond,
|
||||
NVGPU_COND_WAIT(&g->mc.sw_irq_nonstall_last_handled_cond,
|
||||
cyclic_delta(nonstall_irq_threshold,
|
||||
nvgpu_atomic_read(&g->sw_irq_nonstall_last_handled))
|
||||
nvgpu_atomic_read(&g->mc.sw_irq_nonstall_last_handled))
|
||||
<= 0, 0U);
|
||||
}
|
||||
|
||||
@@ -107,11 +107,11 @@ void gm20b_mc_disable(struct gk20a *g, u32 units)
|
||||
|
||||
nvgpu_log(g, gpu_dbg_info, "pmc disable: %08x", units);
|
||||
|
||||
nvgpu_spinlock_acquire(&g->mc_enable_lock);
|
||||
nvgpu_spinlock_acquire(&g->mc.enable_lock);
|
||||
pmc = nvgpu_readl(g, mc_enable_r());
|
||||
pmc &= ~units;
|
||||
nvgpu_writel(g, mc_enable_r(), pmc);
|
||||
nvgpu_spinlock_release(&g->mc_enable_lock);
|
||||
nvgpu_spinlock_release(&g->mc.enable_lock);
|
||||
}
|
||||
|
||||
void gm20b_mc_enable(struct gk20a *g, u32 units)
|
||||
@@ -120,12 +120,12 @@ void gm20b_mc_enable(struct gk20a *g, u32 units)
|
||||
|
||||
nvgpu_log(g, gpu_dbg_info, "pmc enable: %08x", units);
|
||||
|
||||
nvgpu_spinlock_acquire(&g->mc_enable_lock);
|
||||
nvgpu_spinlock_acquire(&g->mc.enable_lock);
|
||||
pmc = nvgpu_readl(g, mc_enable_r());
|
||||
pmc |= units;
|
||||
nvgpu_writel(g, mc_enable_r(), pmc);
|
||||
pmc = nvgpu_readl(g, mc_enable_r());
|
||||
nvgpu_spinlock_release(&g->mc_enable_lock);
|
||||
nvgpu_spinlock_release(&g->mc.enable_lock);
|
||||
|
||||
nvgpu_udelay(MC_ENABLE_DELAY_US);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ int mc_gp10b_intr_enable(struct gk20a *g)
|
||||
|
||||
nvgpu_writel(g, mc_intr_en_clear_r(NVGPU_MC_INTR_STALLING),
|
||||
U32_MAX);
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING] =
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING] =
|
||||
mc_intr_pfifo_pending_f() |
|
||||
mc_intr_priv_ring_pending_f() |
|
||||
mc_intr_pbus_pending_f() |
|
||||
@@ -49,15 +49,15 @@ int mc_gp10b_intr_enable(struct gk20a *g)
|
||||
mc_intr_replayable_fault_pending_f() |
|
||||
eng_intr_mask;
|
||||
nvgpu_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING),
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
|
||||
nvgpu_writel(g, mc_intr_en_clear_r(NVGPU_MC_INTR_NONSTALLING),
|
||||
U32_MAX);
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_NONSTALLING] =
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING] =
|
||||
mc_intr_pfifo_pending_f() |
|
||||
eng_intr_mask;
|
||||
nvgpu_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_NONSTALLING),
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]);
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -68,18 +68,18 @@ void mc_gp10b_intr_pmu_unit_config(struct gk20a *g, bool enable)
|
||||
|
||||
if (enable) {
|
||||
reg = mc_intr_en_set_r(NVGPU_MC_INTR_STALLING);
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING] |=
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING] |=
|
||||
mc_intr_pmu_pending_f();
|
||||
nvgpu_writel(g, reg, mc_intr_pmu_pending_f());
|
||||
|
||||
} else {
|
||||
reg = mc_intr_en_clear_r(NVGPU_MC_INTR_STALLING);
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING] &=
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING] &=
|
||||
~mc_intr_pmu_pending_f();
|
||||
nvgpu_writel(g, reg, mc_intr_pmu_pending_f());
|
||||
|
||||
reg = mc_intr_en_clear_r(NVGPU_MC_INTR_NONSTALLING);
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_NONSTALLING] &=
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING] &=
|
||||
~mc_intr_pmu_pending_f();
|
||||
nvgpu_writel(g, reg, mc_intr_pmu_pending_f());
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ void mc_gp10b_intr_stall_pause(struct gk20a *g)
|
||||
void mc_gp10b_intr_stall_resume(struct gk20a *g)
|
||||
{
|
||||
nvgpu_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING),
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
}
|
||||
|
||||
u32 mc_gp10b_intr_nonstall(struct gk20a *g)
|
||||
@@ -165,7 +165,7 @@ void mc_gp10b_intr_nonstall_pause(struct gk20a *g)
|
||||
void mc_gp10b_intr_nonstall_resume(struct gk20a *g)
|
||||
{
|
||||
nvgpu_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_NONSTALLING),
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]);
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]);
|
||||
}
|
||||
|
||||
bool mc_gp10b_is_intr1_pending(struct gk20a *g,
|
||||
|
||||
@@ -42,7 +42,7 @@ int mc_gv100_intr_enable(struct gk20a *g)
|
||||
U32_MAX);
|
||||
nvgpu_writel(g, mc_intr_en_clear_r(NVGPU_MC_INTR_NONSTALLING),
|
||||
U32_MAX);
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING] =
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING] =
|
||||
mc_intr_pfifo_pending_f() |
|
||||
mc_intr_hub_pending_f() |
|
||||
mc_intr_priv_ring_pending_f() |
|
||||
@@ -51,15 +51,15 @@ int mc_gv100_intr_enable(struct gk20a *g)
|
||||
mc_intr_nvlink_pending_f() |
|
||||
eng_intr_mask;
|
||||
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_NONSTALLING] =
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING] =
|
||||
mc_intr_pfifo_pending_f()
|
||||
| eng_intr_mask;
|
||||
|
||||
nvgpu_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING),
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
|
||||
nvgpu_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_NONSTALLING),
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]);
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ int mc_gv11b_intr_enable(struct gk20a *g)
|
||||
nvgpu_writel(g, mc_intr_en_clear_r(NVGPU_MC_INTR_NONSTALLING),
|
||||
U32_MAX);
|
||||
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING] =
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING] =
|
||||
mc_intr_pfifo_pending_f() |
|
||||
mc_intr_hub_pending_f() |
|
||||
mc_intr_priv_ring_pending_f() |
|
||||
@@ -50,15 +50,15 @@ int mc_gv11b_intr_enable(struct gk20a *g)
|
||||
mc_intr_ltc_pending_f() |
|
||||
eng_intr_mask;
|
||||
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_NONSTALLING] =
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING] =
|
||||
mc_intr_pfifo_pending_f()
|
||||
| eng_intr_mask;
|
||||
|
||||
nvgpu_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING),
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
|
||||
nvgpu_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_NONSTALLING),
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]);
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ static void intr_tu104_stall_enable(struct gk20a *g)
|
||||
|
||||
nvgpu_writel(g, mc_intr_en_clear_r(NVGPU_MC_INTR_STALLING), U32_MAX);
|
||||
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING] =
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING] =
|
||||
mc_intr_pfifo_pending_f() |
|
||||
mc_intr_priv_ring_pending_f() |
|
||||
mc_intr_pbus_pending_f() |
|
||||
@@ -152,7 +152,7 @@ static void intr_tu104_stall_enable(struct gk20a *g)
|
||||
eng_intr_mask;
|
||||
|
||||
nvgpu_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING),
|
||||
g->mc_intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
g->mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]);
|
||||
}
|
||||
|
||||
static void intr_tu104_nonstall_enable(struct gk20a *g)
|
||||
|
||||
@@ -942,8 +942,6 @@ struct gk20a {
|
||||
u64 pg_ungating_time_us;
|
||||
u32 pg_gating_cnt;
|
||||
|
||||
struct nvgpu_spinlock mc_enable_lock;
|
||||
|
||||
struct gk20a_as as;
|
||||
|
||||
struct nvgpu_mutex client_lock;
|
||||
@@ -952,23 +950,10 @@ struct gk20a {
|
||||
/** The HAL function pointers */
|
||||
struct gpu_ops ops;
|
||||
|
||||
u32 mc_intr_mask_restore[4];
|
||||
/*used for change of enum zbc update cmd id from ver 0 to ver1*/
|
||||
u8 pmu_ver_cmd_id_zbc_table_update;
|
||||
|
||||
/* Needed to keep track of deferred interrupts */
|
||||
nvgpu_atomic_t hw_irq_stall_count;
|
||||
nvgpu_atomic_t hw_irq_nonstall_count;
|
||||
|
||||
struct nvgpu_cond sw_irq_stall_last_handled_cond;
|
||||
nvgpu_atomic_t sw_irq_stall_last_handled;
|
||||
|
||||
struct nvgpu_cond sw_irq_nonstall_last_handled_cond;
|
||||
nvgpu_atomic_t sw_irq_nonstall_last_handled;
|
||||
|
||||
bool irqs_enabled;
|
||||
u32 irq_stall; /* can be same as irq_nonstall in case of PCI */
|
||||
u32 irq_nonstall;
|
||||
struct nvgpu_mc mc;
|
||||
|
||||
/*
|
||||
* The deductible memory size for max_comptag_mem (in MBytes)
|
||||
|
||||
@@ -106,11 +106,11 @@ struct gops_mc {
|
||||
* #intr_stall_pause, #intr_stall_resume,
|
||||
* #intr_nonstall_pause and #intr_nonstall_resume.
|
||||
* - Initialize the stalling interrupts bitmask
|
||||
* #mc_intr_mask_restore[#NVGPU_MC_INTR_STALLING] with various
|
||||
* #intr_mask_restore[#NVGPU_MC_INTR_STALLING] with various
|
||||
* units (FIFO, HUB, PRIV_RING, PBUS, LTC) OR'ing with engine
|
||||
* interrupts mask.
|
||||
* - Initialize the non-stalling interrupts bitmask
|
||||
* #mc_intr_mask_restore[#NVGPU_MC_INTR_NONSTALLING] with FIFO
|
||||
* #intr_mask_restore[#NVGPU_MC_INTR_NONSTALLING] with FIFO
|
||||
* unit OR'ing with engine interrupts mask.
|
||||
* - Write the bitmasks to the stalling and the non-stalling interrupts
|
||||
* enable registers respectively (mc_intr_en_set_r()).
|
||||
@@ -194,7 +194,7 @@ struct gops_mc {
|
||||
*
|
||||
* Steps:
|
||||
* - Enable the stalling interrupts as configured during #intr_enable.
|
||||
* Write #mc_intr_mask_restore[#NVGPU_MC_INTR_STALLING] to the
|
||||
* Write #intr_mask_restore[#NVGPU_MC_INTR_STALLING] to the
|
||||
* stalling interrupts enable set register
|
||||
* (mc_intr_en_set_r(#NVGPU_MC_INTR_STALLING)).
|
||||
*/
|
||||
@@ -267,7 +267,7 @@ struct gops_mc {
|
||||
* Steps:
|
||||
* - Enable the non-stalling interrupts as configured during
|
||||
* #intr_enable.
|
||||
* Write #mc_intr_mask_restore[#NVGPU_MC_INTR_NONSTALLING]
|
||||
* Write #intr_mask_restore[#NVGPU_MC_INTR_NONSTALLING]
|
||||
* to the non-stalling interrupts enable set register
|
||||
* (mc_intr_en_set_r(#NVGPU_MC_INTR_NONSTALLING)).
|
||||
*/
|
||||
@@ -322,19 +322,19 @@ struct gops_mc {
|
||||
*
|
||||
* Steps:
|
||||
* - Disable the HW unit/engine.
|
||||
* - Acquire g->mc_enable_lock spinlock.
|
||||
* - Acquire g->mc.enable_lock spinlock.
|
||||
* - Read mc_enable_r register and clear the bits in the read value
|
||||
* corresponding to HW unit to be disabled.
|
||||
* - Write mc_enable_r with the updated value.
|
||||
* - Release g->mc_enable_lock spinlock.
|
||||
* - Release g->mc.enable_lock spinlock.
|
||||
* - Sleep/wait for 500us if resetting CE engines else sleep for 20us.
|
||||
* - Enable the HW unit/engine.
|
||||
* - Acquire g->mc_enable_lock spinlock.
|
||||
* - Acquire g->mc.enable_lock spinlock.
|
||||
* - Read mc_enable_r register and set the bits in the read value
|
||||
* corresponding to HW unit to be disabled.
|
||||
* - Write mc_enable_r with the updated value.
|
||||
* - Read back mc_enable_r.
|
||||
* - Release g->mc_enable_lock spinlock.
|
||||
* - Release g->mc.enable_lock spinlock.
|
||||
* - Sleep/wait for 20us.
|
||||
*/
|
||||
void (*reset)(struct gk20a *g, u32 units);
|
||||
|
||||
@@ -23,20 +23,115 @@
|
||||
#ifndef NVGPU_MC_H
|
||||
#define NVGPU_MC_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @page unit-mc Unit Master Control (MC)
|
||||
*
|
||||
* Overview
|
||||
* ========
|
||||
*
|
||||
* The Master Control (MC) unit is responsible for configuring HW units/engines
|
||||
* in the GPU.
|
||||
*
|
||||
* It provides interfaces to nvgpu driver to access the GPU chip details and
|
||||
* program HW units/engines through following registers:
|
||||
*
|
||||
* + Boot registers: Setup by BIOS and read by nvgpu driver.
|
||||
* - Has the information about architecture, implementation and revision.
|
||||
*
|
||||
* + Interrupt registers: These allow to control the interrupts for the local
|
||||
* devices. Interrupts are set by an event and are cleared by software.
|
||||
*
|
||||
* Various interrupts sources are: Graphics, Copy*, NVENC*, NVDEC, SEC,
|
||||
* PFIFO, HUB, PFB, THERMAL, HDACODEC, PTIMER, PMGR, NVLINK, DFD, PMU,
|
||||
* LTC, PDISP, PBUS, XVE, PRIV_RING, SOFTWARE.
|
||||
*
|
||||
* + There are two interrupt status registers:
|
||||
* + mc_intr_r(0) is for stalling interrupts routed to CPU.
|
||||
* + mc_intr_r(1) is for non-stalling interrupts routed to CPU.
|
||||
* + There are two interrupt enable registers, which can be updated
|
||||
* through interrupt set/clear (mc_intr_set_r/mc_intr_clear_r)
|
||||
* registers.
|
||||
* + mc_intr_en_r(0) is for stalling interrupts routed to CPU.
|
||||
* + mc_intr_en_r(1) is for non-stalling interrupts routed to CPU.
|
||||
* + Register mc_intr_ltc_r indicates which of the FB partitions
|
||||
* are reporting an LTC interrupt.
|
||||
*
|
||||
* + Configuration registers: These are used to configure each of the HW
|
||||
* units/engines after reset.
|
||||
* - Master Control Enable Register (mc_enable_r()) is used to enable/
|
||||
* disable engines.
|
||||
*
|
||||
* Data Structures
|
||||
* ===============
|
||||
*
|
||||
* + struct nvgpu_mc
|
||||
* This struct holds the variables needed to manage the configuration and
|
||||
* interrupt handling of the units/engines.
|
||||
*
|
||||
*
|
||||
* Static Design
|
||||
* =============
|
||||
*
|
||||
* nvgpu initialization
|
||||
* --------------------
|
||||
* Before initializing nvgpu driver, the MC unit interface to get the chip
|
||||
* version details is invoked. Interrupts are enabled at MC level in
|
||||
* #nvgpu_finalize_poweron and the engines are reset.
|
||||
*
|
||||
* nvgpu teardown
|
||||
* --------------
|
||||
* During #nvgpu_prepare_poweroff, all interrupts are disabled at MC level
|
||||
* by calling the interface from the MC unit.
|
||||
*
|
||||
* External APIs
|
||||
* -------------
|
||||
* Most of the static interfaces are HAL functions. They are documented
|
||||
* here.
|
||||
* + include/nvgpu/gops_mc.h
|
||||
*
|
||||
* Dynamic Design
|
||||
* ==============
|
||||
*
|
||||
* At runtime, the stalling and non-stalling interrupts are inquired through
|
||||
* MC unit interface. Then corresponding handlers that are exported by the
|
||||
* MC unit are invoked. While in ISRs, interrupts are disabled and they
|
||||
* are re-enabled after ISRs through interfaces provided by the MC unit.
|
||||
*
|
||||
* For quiesce state handling, interrupts will have to be disabled that is
|
||||
* again supported through MC unit interface.
|
||||
*
|
||||
* External APIs
|
||||
* -------------
|
||||
* Some of the dynamic interfaces are HAL functions. They are documented
|
||||
* here.
|
||||
* + include/nvgpu/gops_mc.h
|
||||
*
|
||||
* Following interface is common function.
|
||||
* + nvgpu_wait_for_deferred_interrupts()
|
||||
*/
|
||||
|
||||
|
||||
#include <nvgpu/types.h>
|
||||
#include <nvgpu/cond.h>
|
||||
#include <nvgpu/atomic.h>
|
||||
#include <nvgpu/lock.h>
|
||||
|
||||
struct gk20a;
|
||||
|
||||
/**
|
||||
* Enumeration of all units intended to be used by any HAL that requires
|
||||
* unit as parameter.
|
||||
*
|
||||
* Units are added to the enumeration as needed, so it is not complete.
|
||||
* unit as parameter. Units are added to the enumeration as needed, so
|
||||
* it is not complete.
|
||||
*/
|
||||
enum nvgpu_unit {
|
||||
/** FIFO Engine */
|
||||
NVGPU_UNIT_FIFO,
|
||||
/** Performance Monitoring unit */
|
||||
NVGPU_UNIT_PERFMON,
|
||||
/** Graphics Engine */
|
||||
NVGPU_UNIT_GRAPH,
|
||||
/** BLPG and BLCG controllers within Graphics Engine */
|
||||
NVGPU_UNIT_BLG,
|
||||
#ifdef CONFIG_NVGPU_HAL_NON_FUSA
|
||||
NVGPU_UNIT_PWR,
|
||||
@@ -49,13 +144,106 @@ enum nvgpu_unit {
|
||||
/** Bit offset of the Architecture field in the HW version register */
|
||||
#define NVGPU_GPU_ARCHITECTURE_SHIFT 4U
|
||||
|
||||
/** Index for accessing registers corresponding to stalling interrupts */
|
||||
#define NVGPU_MC_INTR_STALLING 0U
|
||||
/** Index for accessing registers corresponding to non-stalling interrupts */
|
||||
#define NVGPU_MC_INTR_NONSTALLING 1U
|
||||
|
||||
/** Operations that will need to be executed on non stall workqueue. */
|
||||
#define NVGPU_NONSTALL_OPS_WAKEUP_SEMAPHORE BIT32(0)
|
||||
#define NVGPU_NONSTALL_OPS_POST_EVENTS BIT32(1)
|
||||
|
||||
/**
|
||||
* This struct holds the variables needed to manage the configuration and
|
||||
* interrupt handling of the units/engines.
|
||||
*/
|
||||
struct nvgpu_mc {
|
||||
/** Lock to access the mc_enable_r */
|
||||
struct nvgpu_spinlock enable_lock;
|
||||
|
||||
/**
|
||||
* Bitmask of the stalling/non-stalling interrupts enabled.
|
||||
* This is used to enable/disable the interrupts at runtime.
|
||||
* intr_mask_restore[2] & intr_mask_restore[3] are applicable
|
||||
* when GSP exists.
|
||||
*/
|
||||
u32 intr_mask_restore[4];
|
||||
|
||||
/**
|
||||
* Below are the counters & condition varibles needed to keep track of
|
||||
* the deferred interrupts.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stalling interrupt counter - incremented on receipt of the stalling
|
||||
* interrupt in #isr_stall and read in the function
|
||||
* #nvgpu_wait_for_deferred_interrupts.
|
||||
*/
|
||||
nvgpu_atomic_t hw_irq_stall_count;
|
||||
|
||||
/**
|
||||
* Non-stalling interrupt counter - incremented on receipt of the
|
||||
* non-stalling interrupt in #isr_nonstall and read in the function
|
||||
* #nvgpu_wait_for_deferred_interrupts.
|
||||
*/
|
||||
nvgpu_atomic_t hw_irq_nonstall_count;
|
||||
|
||||
/**
|
||||
* The condition variable that is signalled upon handling of the
|
||||
* stalling interrupt. It is wait upon by the function
|
||||
* #nvgpu_wait_for_deferred_interrupts.
|
||||
*/
|
||||
struct nvgpu_cond sw_irq_stall_last_handled_cond;
|
||||
|
||||
/**
|
||||
* Stalling interrupt status counter - updated on handling of the
|
||||
* stalling interrupt.
|
||||
*/
|
||||
nvgpu_atomic_t sw_irq_stall_last_handled;
|
||||
|
||||
/**
|
||||
* The condition variable that is signalled upon handling of the
|
||||
* non-stalling interrupt. It is wait upon by the function
|
||||
* #nvgpu_wait_for_deferred_interrupts.
|
||||
*/
|
||||
struct nvgpu_cond sw_irq_nonstall_last_handled_cond;
|
||||
|
||||
/**
|
||||
* Non-stalling interrupt status counter - updated on handling of the
|
||||
* non-stalling interrupt.
|
||||
*/
|
||||
nvgpu_atomic_t sw_irq_nonstall_last_handled;
|
||||
|
||||
/** nvgpu interrupts enabled status from host OS perspective */
|
||||
bool irqs_enabled;
|
||||
|
||||
/**
|
||||
* Interrupt line for stalling interrupts.
|
||||
* Can be same as irq_nonstall in case of PCI.
|
||||
*/
|
||||
u32 irq_stall;
|
||||
|
||||
/** Interrupt line for non-stalling interrupts. */
|
||||
u32 irq_nonstall;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Wait for the interrupts to complete.
|
||||
*
|
||||
* @param g [in] The GPU driver struct.
|
||||
*
|
||||
* While freeing the channel or entering SW quiesce state, nvgpu driver needs
|
||||
* to waits until all interrupt handlers that have been scheduled to run have
|
||||
* completed as those could access channel after freeing.
|
||||
* Steps:
|
||||
* - Get the stalling and non-stalling interrupts atomic count.
|
||||
* - Wait on the condition variable #sw_irq_stall_last_handled_cond until
|
||||
* #sw_irq_stall_last_handled becomes greater than or equal to previously
|
||||
* read stalling interrupt atomic count.
|
||||
* - Wait on the condition variable #sw_irq_nonstall_last_handled_cond until
|
||||
* #sw_irq_nonstall_last_handled becomes greater than or equal to previously
|
||||
* read non-stalling interrupt atomic count.
|
||||
*/
|
||||
void nvgpu_wait_for_deferred_interrupts(struct gk20a *g);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -52,13 +52,13 @@ static void nvgpu_init_vars(struct gk20a *g)
|
||||
struct device *dev = dev_from_gk20a(g);
|
||||
struct gk20a_platform *platform = dev_get_drvdata(dev);
|
||||
|
||||
nvgpu_cond_init(&g->sw_irq_stall_last_handled_cond);
|
||||
nvgpu_cond_init(&g->sw_irq_nonstall_last_handled_cond);
|
||||
nvgpu_cond_init(&g->mc.sw_irq_stall_last_handled_cond);
|
||||
nvgpu_cond_init(&g->mc.sw_irq_nonstall_last_handled_cond);
|
||||
|
||||
init_rwsem(&l->busy_lock);
|
||||
nvgpu_rwsem_init(&g->deterministic_busy);
|
||||
|
||||
nvgpu_spinlock_init(&g->mc_enable_lock);
|
||||
nvgpu_spinlock_init(&g->mc.enable_lock);
|
||||
|
||||
nvgpu_spinlock_init(&g->power_spinlock);
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ irqreturn_t nvgpu_intr_stall(struct gk20a *g)
|
||||
}
|
||||
#endif
|
||||
|
||||
nvgpu_atomic_inc(&g->hw_irq_stall_count);
|
||||
nvgpu_atomic_inc(&g->mc.hw_irq_stall_count);
|
||||
|
||||
#ifdef CONFIG_NVGPU_TRACE
|
||||
trace_mc_gk20a_intr_stall_done(g->name);
|
||||
@@ -66,13 +66,13 @@ irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g)
|
||||
trace_mc_gk20a_intr_thread_stall(g->name);
|
||||
#endif
|
||||
|
||||
hw_irq_count = nvgpu_atomic_read(&g->hw_irq_stall_count);
|
||||
hw_irq_count = nvgpu_atomic_read(&g->mc.hw_irq_stall_count);
|
||||
g->ops.mc.isr_stall(g);
|
||||
g->ops.mc.intr_stall_resume(g);
|
||||
/* sync handled irq counter before re-enabling interrupts */
|
||||
nvgpu_atomic_set(&g->sw_irq_stall_last_handled, hw_irq_count);
|
||||
nvgpu_atomic_set(&g->mc.sw_irq_stall_last_handled, hw_irq_count);
|
||||
|
||||
nvgpu_cond_broadcast(&g->sw_irq_stall_last_handled_cond);
|
||||
nvgpu_cond_broadcast(&g->mc.sw_irq_stall_last_handled_cond);
|
||||
|
||||
#ifdef CONFIG_NVGPU_TRACE
|
||||
trace_mc_gk20a_intr_thread_stall_done(g->name);
|
||||
@@ -114,14 +114,14 @@ irqreturn_t nvgpu_intr_nonstall(struct gk20a *g)
|
||||
queue_work(l->nonstall_work_queue, &l->nonstall_fn_work);
|
||||
}
|
||||
|
||||
hw_irq_count = nvgpu_atomic_inc_return(&g->hw_irq_nonstall_count);
|
||||
hw_irq_count = nvgpu_atomic_inc_return(&g->mc.hw_irq_nonstall_count);
|
||||
|
||||
/* sync handled irq counter before re-enabling interrupts */
|
||||
nvgpu_atomic_set(&g->sw_irq_nonstall_last_handled, hw_irq_count);
|
||||
nvgpu_atomic_set(&g->mc.sw_irq_nonstall_last_handled, hw_irq_count);
|
||||
|
||||
g->ops.mc.intr_nonstall_resume(g);
|
||||
|
||||
nvgpu_cond_broadcast(&g->sw_irq_nonstall_last_handled_cond);
|
||||
nvgpu_cond_broadcast(&g->mc.sw_irq_nonstall_last_handled_cond);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -543,11 +543,11 @@ static int gk20a_lockout_registers(struct gk20a *g)
|
||||
|
||||
int nvgpu_enable_irqs(struct gk20a *g)
|
||||
{
|
||||
if (!g->irqs_enabled) {
|
||||
enable_irq(g->irq_stall);
|
||||
if (g->irq_stall != g->irq_nonstall)
|
||||
enable_irq(g->irq_nonstall);
|
||||
g->irqs_enabled = true;
|
||||
if (!g->mc.irqs_enabled) {
|
||||
enable_irq(g->mc.irq_stall);
|
||||
if (g->mc.irq_stall != g->mc.irq_nonstall)
|
||||
enable_irq(g->mc.irq_nonstall);
|
||||
g->mc.irqs_enabled = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -555,11 +555,11 @@ int nvgpu_enable_irqs(struct gk20a *g)
|
||||
|
||||
void nvgpu_disable_irqs(struct gk20a *g)
|
||||
{
|
||||
if (g->irqs_enabled) {
|
||||
disable_irq(g->irq_stall);
|
||||
if (g->irq_stall != g->irq_nonstall)
|
||||
disable_irq(g->irq_nonstall);
|
||||
g->irqs_enabled = false;
|
||||
if (g->mc.irqs_enabled) {
|
||||
disable_irq(g->mc.irq_stall);
|
||||
if (g->mc.irq_stall != g->mc.irq_nonstall)
|
||||
disable_irq(g->mc.irq_nonstall);
|
||||
g->mc.irqs_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,7 +642,7 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
|
||||
goto done;
|
||||
|
||||
/* disable IRQs and wait for completion */
|
||||
irqs_enabled = g->irqs_enabled;
|
||||
irqs_enabled = g->mc.irqs_enabled;
|
||||
nvgpu_disable_irqs(g);
|
||||
|
||||
gk20a_scale_suspend(dev);
|
||||
@@ -1156,9 +1156,9 @@ void nvgpu_free_irq(struct gk20a *g)
|
||||
{
|
||||
struct device *dev = dev_from_gk20a(g);
|
||||
|
||||
devm_free_irq(dev, g->irq_stall, g);
|
||||
if (g->irq_stall != g->irq_nonstall)
|
||||
devm_free_irq(dev, g->irq_nonstall, g);
|
||||
devm_free_irq(dev, g->mc.irq_stall, g);
|
||||
if (g->mc.irq_stall != g->mc.irq_nonstall)
|
||||
devm_free_irq(dev, g->mc.irq_nonstall, g);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1572,37 +1572,37 @@ static int gk20a_probe(struct platform_device *dev)
|
||||
if (nvgpu_platform_is_simulation(gk20a))
|
||||
nvgpu_set_enabled(gk20a, NVGPU_IS_FMODEL, true);
|
||||
|
||||
gk20a->irq_stall = platform_get_irq(dev, 0);
|
||||
gk20a->irq_nonstall = platform_get_irq(dev, 1);
|
||||
if ((int)gk20a->irq_stall < 0 || (int)gk20a->irq_nonstall < 0) {
|
||||
gk20a->mc.irq_stall = platform_get_irq(dev, 0);
|
||||
gk20a->mc.irq_nonstall = platform_get_irq(dev, 1);
|
||||
if ((int)gk20a->mc.irq_stall < 0 || (int)gk20a->mc.irq_nonstall < 0) {
|
||||
err = -ENXIO;
|
||||
goto return_err;
|
||||
}
|
||||
|
||||
err = devm_request_threaded_irq(&dev->dev,
|
||||
gk20a->irq_stall,
|
||||
gk20a->mc.irq_stall,
|
||||
gk20a_intr_isr_stall,
|
||||
gk20a_intr_thread_stall,
|
||||
0, "gk20a_stall", gk20a);
|
||||
if (err) {
|
||||
dev_err(&dev->dev,
|
||||
"failed to request stall intr irq @ %d\n",
|
||||
gk20a->irq_stall);
|
||||
gk20a->mc.irq_stall);
|
||||
goto return_err;
|
||||
}
|
||||
err = devm_request_irq(&dev->dev,
|
||||
gk20a->irq_nonstall,
|
||||
gk20a->mc.irq_nonstall,
|
||||
gk20a_intr_isr_nonstall,
|
||||
0, "gk20a_nonstall", gk20a);
|
||||
if (err) {
|
||||
dev_err(&dev->dev,
|
||||
"failed to request non-stall intr irq @ %d\n",
|
||||
gk20a->irq_nonstall);
|
||||
gk20a->mc.irq_nonstall);
|
||||
goto return_err;
|
||||
}
|
||||
disable_irq(gk20a->irq_stall);
|
||||
if (gk20a->irq_stall != gk20a->irq_nonstall)
|
||||
disable_irq(gk20a->irq_nonstall);
|
||||
disable_irq(gk20a->mc.irq_stall);
|
||||
if (gk20a->mc.irq_stall != gk20a->mc.irq_nonstall)
|
||||
disable_irq(gk20a->mc.irq_nonstall);
|
||||
|
||||
err = gk20a_init_support(dev);
|
||||
if (err)
|
||||
|
||||
@@ -484,15 +484,15 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
|
||||
g->msi_enabled = true;
|
||||
#endif
|
||||
|
||||
g->irq_stall = pdev->irq;
|
||||
g->irq_nonstall = pdev->irq;
|
||||
if ((int)g->irq_stall < 0) {
|
||||
g->mc.irq_stall = pdev->irq;
|
||||
g->mc.irq_nonstall = pdev->irq;
|
||||
if ((int)g->mc.irq_stall < 0) {
|
||||
err = -ENXIO;
|
||||
goto err_disable_msi;
|
||||
}
|
||||
|
||||
err = devm_request_threaded_irq(&pdev->dev,
|
||||
g->irq_stall,
|
||||
g->mc.irq_stall,
|
||||
nvgpu_pci_isr,
|
||||
nvgpu_pci_intr_thread,
|
||||
#if defined(CONFIG_PCI_MSI)
|
||||
@@ -501,10 +501,10 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
|
||||
IRQF_SHARED, "nvgpu", g);
|
||||
if (err) {
|
||||
nvgpu_err(g,
|
||||
"failed to request irq @ %d", g->irq_stall);
|
||||
"failed to request irq @ %d", g->mc.irq_stall);
|
||||
goto err_disable_msi;
|
||||
}
|
||||
disable_irq(g->irq_stall);
|
||||
disable_irq(g->mc.irq_stall);
|
||||
|
||||
err = nvgpu_pci_init_support(pdev);
|
||||
if (err)
|
||||
@@ -629,7 +629,7 @@ static void nvgpu_pci_remove(struct pci_dev *pdev)
|
||||
/* IRQ does not need to be enabled in MSI as the line is not
|
||||
* shared
|
||||
*/
|
||||
enable_irq(g->irq_stall);
|
||||
enable_irq(g->mc.irq_stall);
|
||||
}
|
||||
#endif
|
||||
nvgpu_pci_pm_deinit(&pdev->dev);
|
||||
|
||||
@@ -385,7 +385,7 @@ int vgpu_probe(struct platform_device *pdev)
|
||||
|
||||
init_rwsem(&l->busy_lock);
|
||||
|
||||
nvgpu_spinlock_init(&gk20a->mc_enable_lock);
|
||||
nvgpu_spinlock_init(&gk20a->mc.enable_lock);
|
||||
|
||||
gk20a->ch_wdt_init_limit_ms = platform->ch_wdt_init_limit_ms;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user