diff --git a/drivers/gpu/nvgpu/common/mc/mc.c b/drivers/gpu/nvgpu/common/mc/mc.c index 5ab6814ca..002ed49bb 100644 --- a/drivers/gpu/nvgpu/common/mc/mc.c +++ b/drivers/gpu/nvgpu/common/mc/mc.c @@ -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); } diff --git a/drivers/gpu/nvgpu/hal/mc/mc_gm20b_fusa.c b/drivers/gpu/nvgpu/hal/mc/mc_gm20b_fusa.c index dcda4a504..457e2a927 100644 --- a/drivers/gpu/nvgpu/hal/mc/mc_gm20b_fusa.c +++ b/drivers/gpu/nvgpu/hal/mc/mc_gm20b_fusa.c @@ -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); } diff --git a/drivers/gpu/nvgpu/hal/mc/mc_gp10b.c b/drivers/gpu/nvgpu/hal/mc/mc_gp10b.c index 0a50aac82..e31114359 100644 --- a/drivers/gpu/nvgpu/hal/mc/mc_gp10b.c +++ b/drivers/gpu/nvgpu/hal/mc/mc_gp10b.c @@ -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()); } diff --git a/drivers/gpu/nvgpu/hal/mc/mc_gp10b_fusa.c b/drivers/gpu/nvgpu/hal/mc/mc_gp10b_fusa.c index 1bf4d43a0..28ec7a533 100644 --- a/drivers/gpu/nvgpu/hal/mc/mc_gp10b_fusa.c +++ b/drivers/gpu/nvgpu/hal/mc/mc_gp10b_fusa.c @@ -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, diff --git a/drivers/gpu/nvgpu/hal/mc/mc_gv100.c b/drivers/gpu/nvgpu/hal/mc/mc_gv100.c index 9fca5820f..b00d3da66 100644 --- a/drivers/gpu/nvgpu/hal/mc/mc_gv100.c +++ b/drivers/gpu/nvgpu/hal/mc/mc_gv100.c @@ -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; } diff --git a/drivers/gpu/nvgpu/hal/mc/mc_gv11b_fusa.c b/drivers/gpu/nvgpu/hal/mc/mc_gv11b_fusa.c index abbc5cf76..3820e64f5 100644 --- a/drivers/gpu/nvgpu/hal/mc/mc_gv11b_fusa.c +++ b/drivers/gpu/nvgpu/hal/mc/mc_gv11b_fusa.c @@ -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; } diff --git a/drivers/gpu/nvgpu/hal/mc/mc_tu104.c b/drivers/gpu/nvgpu/hal/mc/mc_tu104.c index cc7fc5ec2..710351d7e 100644 --- a/drivers/gpu/nvgpu/hal/mc/mc_tu104.c +++ b/drivers/gpu/nvgpu/hal/mc/mc_tu104.c @@ -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) diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index 0e5ca615c..09c09ae54 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -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) diff --git a/drivers/gpu/nvgpu/include/nvgpu/gops_mc.h b/drivers/gpu/nvgpu/include/nvgpu/gops_mc.h index 78328bc21..caa3040b4 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gops_mc.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gops_mc.h @@ -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); diff --git a/drivers/gpu/nvgpu/include/nvgpu/mc.h b/drivers/gpu/nvgpu/include/nvgpu/mc.h index f0dbd567b..ddd586038 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/mc.h +++ b/drivers/gpu/nvgpu/include/nvgpu/mc.h @@ -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 +#include +#include +#include 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 diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.c b/drivers/gpu/nvgpu/os/linux/driver_common.c index 1574b4946..91654c909 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.c +++ b/drivers/gpu/nvgpu/os/linux/driver_common.c @@ -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); diff --git a/drivers/gpu/nvgpu/os/linux/intr.c b/drivers/gpu/nvgpu/os/linux/intr.c index 09ecac3b3..7f3f7f072 100644 --- a/drivers/gpu/nvgpu/os/linux/intr.c +++ b/drivers/gpu/nvgpu/os/linux/intr.c @@ -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; } diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index b62eece4e..2f612016a 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -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) diff --git a/drivers/gpu/nvgpu/os/linux/pci.c b/drivers/gpu/nvgpu/os/linux/pci.c index 21c3bc0f8..c382fddfb 100644 --- a/drivers/gpu/nvgpu/os/linux/pci.c +++ b/drivers/gpu/nvgpu/os/linux/pci.c @@ -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); diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c index 245d48904..5fb91e55b 100644 --- a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c +++ b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c @@ -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;