diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu index c2d985597..109d1e4d7 100644 --- a/drivers/gpu/nvgpu/Makefile.nvgpu +++ b/drivers/gpu/nvgpu/Makefile.nvgpu @@ -41,6 +41,7 @@ nvgpu-y := \ common/linux/firmware.o \ common/linux/thread.o \ common/linux/vm.o \ + common/linux/intr.o \ common/mm/nvgpu_allocator.o \ common/mm/bitmap_allocator.o \ common/mm/buddy_allocator.o \ diff --git a/drivers/gpu/nvgpu/common/linux/intr.c b/drivers/gpu/nvgpu/common/linux/intr.c new file mode 100644 index 000000000..77e44dd97 --- /dev/null +++ b/drivers/gpu/nvgpu/common/linux/intr.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014-2017, 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. + */ + +#include + +#include "gk20a/gk20a.h" + +#include + +irqreturn_t nvgpu_intr_stall(struct gk20a *g) +{ + u32 mc_intr_0; + + trace_mc_gk20a_intr_stall(g->name); + + if (!g->power_on) + return IRQ_NONE; + + /* not from gpu when sharing irq with others */ + mc_intr_0 = g->ops.mc.intr_stall(g); + if (unlikely(!mc_intr_0)) + return IRQ_NONE; + + g->ops.mc.intr_stall_pause(g); + + atomic_inc(&g->hw_irq_stall_count); + + trace_mc_gk20a_intr_stall_done(g->name); + + return IRQ_WAKE_THREAD; +} + +irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g) +{ + gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); + + trace_mc_gk20a_intr_thread_stall(g->name); + + g->ops.mc.isr_stall(g); + g->ops.mc.intr_stall_resume(g); + + wake_up_all(&g->sw_irq_stall_last_handled_wq); + + trace_mc_gk20a_intr_thread_stall_done(g->name); + + return IRQ_HANDLED; +} + diff --git a/drivers/gpu/nvgpu/common/linux/intr.h b/drivers/gpu/nvgpu/common/linux/intr.h new file mode 100644 index 000000000..243d8f51a --- /dev/null +++ b/drivers/gpu/nvgpu/common/linux/intr.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2014-2017, 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. + */ + +#ifndef __NVGPU_LINUX_INTR_H__ +#define __NVGPU_LINUX_INTR_H__ +struct gk20a; + +irqreturn_t nvgpu_intr_stall(struct gk20a *g); +irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g); +#endif diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c index ab99bef0d..5e8af0653 100644 --- a/drivers/gpu/nvgpu/common/linux/module.c +++ b/drivers/gpu/nvgpu/common/linux/module.c @@ -36,6 +36,7 @@ #include "gk20a/ctxsw_trace_gk20a.h" #include "pci.h" #include "module.h" +#include "intr.h" #ifdef CONFIG_TEGRA_19x_GPU #include "nvgpu_gpuid_t19x.h" #endif @@ -482,7 +483,7 @@ static irqreturn_t gk20a_intr_isr_stall(int irq, void *dev_id) { struct gk20a *g = dev_id; - return g->ops.mc.isr_stall(g); + return nvgpu_intr_stall(g); } static irqreturn_t gk20a_intr_isr_nonstall(int irq, void *dev_id) @@ -496,7 +497,7 @@ static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id) { struct gk20a *g = dev_id; - return g->ops.mc.isr_thread_stall(g); + return nvgpu_intr_thread_stall(g); } void gk20a_remove_support(struct gk20a *g) diff --git a/drivers/gpu/nvgpu/common/linux/pci.c b/drivers/gpu/nvgpu/common/linux/pci.c index d729d273c..767e9d473 100644 --- a/drivers/gpu/nvgpu/common/linux/pci.c +++ b/drivers/gpu/nvgpu/common/linux/pci.c @@ -25,6 +25,7 @@ #include "gk20a/platform_gk20a.h" #include "clk/clk.h" #include "module.h" +#include "intr.h" #include "pci.h" @@ -232,7 +233,7 @@ static irqreturn_t nvgpu_pci_isr(int irq, void *dev_id) irqreturn_t ret_stall; irqreturn_t ret_nonstall; - ret_stall = g->ops.mc.isr_stall(g); + ret_stall = nvgpu_intr_stall(g); ret_nonstall = g->ops.mc.isr_nonstall(g); #if defined(CONFIG_PCI_MSI) @@ -248,9 +249,7 @@ static irqreturn_t nvgpu_pci_intr_thread(int irq, void *dev_id) { struct gk20a *g = dev_id; - g->ops.mc.isr_thread_stall(g); - - return IRQ_HANDLED; + return nvgpu_intr_thread_stall(g); } static int nvgpu_pci_init_support(struct pci_dev *pdev) diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index ceadbae2b..29ac4763e 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -812,13 +812,15 @@ struct gpu_ops { void (*intr_enable)(struct gk20a *g); void (*intr_unit_config)(struct gk20a *g, bool enable, bool is_stalling, u32 unit); - irqreturn_t (*isr_stall)(struct gk20a *g); + void (*isr_stall)(struct gk20a *g); irqreturn_t (*isr_nonstall)(struct gk20a *g); - irqreturn_t (*isr_thread_stall)(struct gk20a *g); void (*isr_thread_nonstall)(struct gk20a *g, u32 intr); void (*isr_nonstall_cb)(struct work_struct *work); bool (*is_intr_hub_pending)(struct gk20a *g, u32 mc_intr); u32 intr_mask_restore[4]; + u32 (*intr_stall)(struct gk20a *g); + void (*intr_stall_pause)(struct gk20a *g); + void (*intr_stall_resume)(struct gk20a *g); void (*enable)(struct gk20a *g, u32 units); void (*disable)(struct gk20a *g, u32 units); void (*reset)(struct gk20a *g, u32 units); diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c index ca7189ccc..bc11b14d5 100644 --- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c @@ -1,7 +1,7 @@ /* * GK20A Master Control * - * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2017, 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, @@ -41,33 +41,6 @@ void mc_gk20a_nonstall_cb(struct work_struct *work) } while (atomic_read(&g->nonstall_ops) != 0); } -irqreturn_t mc_gk20a_isr_stall(struct gk20a *g) -{ - u32 mc_intr_0; - - trace_mc_gk20a_intr_stall(g->name); - - if (!g->power_on) - return IRQ_NONE; - - /* not from gpu when sharing irq with others */ - mc_intr_0 = gk20a_readl(g, mc_intr_0_r()); - if (unlikely(!mc_intr_0)) - return IRQ_NONE; - - gk20a_writel(g, mc_intr_en_0_r(), - mc_intr_en_0_inta_disabled_f()); - - /* flush previous write */ - gk20a_readl(g, mc_intr_en_0_r()); - - atomic_inc(&g->hw_irq_stall_count); - - trace_mc_gk20a_intr_stall_done(g->name); - - return IRQ_WAKE_THREAD; -} - irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g) { u32 mc_intr_1; @@ -106,7 +79,7 @@ irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g) return IRQ_HANDLED; } -irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) +void mc_gk20a_isr_stall(struct gk20a *g) { u32 mc_intr_0; int hw_irq_count; @@ -114,11 +87,7 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) u32 active_engine_id = 0; u32 engine_enum = ENGINE_INVAL_GK20A; - gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); - - trace_mc_gk20a_intr_thread_stall(g->name); - - mc_intr_0 = gk20a_readl(g, mc_intr_0_r()); + mc_intr_0 = g->ops.mc.intr_stall(g); hw_irq_count = atomic_read(&g->hw_irq_stall_count); gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0); @@ -156,18 +125,6 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) /* sync handled irq counter before re-enabling interrupts */ atomic_set(&g->sw_irq_stall_last_handled, hw_irq_count); - - gk20a_writel(g, mc_intr_en_0_r(), - mc_intr_en_0_inta_hardware_f()); - - /* flush previous write */ - gk20a_readl(g, mc_intr_en_0_r()); - - wake_up_all(&g->sw_irq_stall_last_handled_wq); - - trace_mc_gk20a_intr_thread_stall_done(g->name); - - return IRQ_HANDLED; } void mc_gk20a_intr_thread_nonstall(struct gk20a *g, u32 mc_intr_1) @@ -250,6 +207,29 @@ void mc_gk20a_intr_unit_config(struct gk20a *g, bool enable, } } +void mc_gk20a_intr_stall_pause(struct gk20a *g) +{ + gk20a_writel(g, mc_intr_en_0_r(), + mc_intr_en_0_inta_disabled_f()); + + /* flush previous write */ + gk20a_readl(g, mc_intr_en_0_r()); +} + +void mc_gk20a_intr_stall_resume(struct gk20a *g) +{ + gk20a_writel(g, mc_intr_en_0_r(), + mc_intr_en_0_inta_hardware_f()); + + /* flush previous write */ + gk20a_readl(g, mc_intr_en_0_r()); +} + +u32 mc_gk20a_intr_stall(struct gk20a *g) +{ + return gk20a_readl(g, mc_intr_0_r()); +} + void gk20a_mc_disable(struct gk20a *g, u32 units) { u32 pmc; @@ -312,8 +292,10 @@ void gk20a_init_mc(struct gpu_ops *gops) gops->mc.intr_enable = mc_gk20a_intr_enable; gops->mc.intr_unit_config = mc_gk20a_intr_unit_config; gops->mc.isr_stall = mc_gk20a_isr_stall; + gops->mc.intr_stall = mc_gk20a_intr_stall; + gops->mc.intr_stall_pause = mc_gk20a_intr_stall_pause; + gops->mc.intr_stall_resume = mc_gk20a_intr_stall_resume; gops->mc.isr_nonstall = mc_gk20a_isr_nonstall; - gops->mc.isr_thread_stall = mc_gk20a_intr_thread_stall; gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb; gops->mc.enable = gk20a_mc_enable; diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.h b/drivers/gpu/nvgpu/gk20a/mc_gk20a.h index 9c70eba11..2b4a183e8 100644 --- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.h @@ -19,7 +19,10 @@ void gk20a_init_mc(struct gpu_ops *gops); void mc_gk20a_intr_enable(struct gk20a *g); void mc_gk20a_intr_unit_config(struct gk20a *g, bool enable, bool is_stalling, u32 mask); -irqreturn_t mc_gk20a_isr_stall(struct gk20a *g); +void mc_gk20a_isr_stall(struct gk20a *g); +u32 mc_gk20a_intr_stall(struct gk20a *g); +void mc_gk20a_intr_stall_pause(struct gk20a *g); +void mc_gk20a_intr_stall_resume(struct gk20a *g); irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g); irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g); void mc_gk20a_intr_thread_nonstall(struct gk20a *g, u32 intr); diff --git a/drivers/gpu/nvgpu/gm20b/mc_gm20b.c b/drivers/gpu/nvgpu/gm20b/mc_gm20b.c index 05504e823..ebb9780d4 100644 --- a/drivers/gpu/nvgpu/gm20b/mc_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/mc_gm20b.c @@ -22,8 +22,10 @@ void gm20b_init_mc(struct gpu_ops *gops) gops->mc.intr_enable = mc_gk20a_intr_enable; gops->mc.intr_unit_config = mc_gk20a_intr_unit_config; gops->mc.isr_stall = mc_gk20a_isr_stall; + gops->mc.intr_stall = mc_gk20a_intr_stall; + gops->mc.intr_stall_pause = mc_gk20a_intr_stall_pause; + gops->mc.intr_stall_resume = mc_gk20a_intr_stall_resume; gops->mc.isr_nonstall = mc_gk20a_isr_nonstall; - gops->mc.isr_thread_stall = mc_gk20a_intr_thread_stall; gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb; gops->mc.enable = gk20a_mc_enable; diff --git a/drivers/gpu/nvgpu/gp10b/mc_gp10b.c b/drivers/gpu/nvgpu/gp10b/mc_gp10b.c index 4a48d7fa6..bfc7a3d4a 100644 --- a/drivers/gpu/nvgpu/gp10b/mc_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/mc_gp10b.c @@ -1,7 +1,7 @@ /* - * GP20B master + * GP10B master * - * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2017, 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, @@ -67,25 +67,6 @@ void mc_gp10b_intr_unit_config(struct gk20a *g, bool enable, gk20a_writel(g, reg, mask); } -irqreturn_t mc_gp10b_isr_stall(struct gk20a *g) -{ - u32 mc_intr_0; - - if (!g->power_on) - return IRQ_NONE; - - /* not from gpu when sharing irq with others */ - mc_intr_0 = gk20a_readl(g, mc_intr_r(0)); - if (unlikely(!mc_intr_0)) - return IRQ_NONE; - - gk20a_writel(g, mc_intr_en_clear_r(0), 0xffffffff); - - atomic_inc(&g->hw_irq_stall_count); - - return IRQ_WAKE_THREAD; -} - irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g) { u32 mc_intr_1; @@ -117,7 +98,7 @@ irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g) return IRQ_HANDLED; } -irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g) +void mc_gp10b_isr_stall(struct gk20a *g) { u32 mc_intr_0; int hw_irq_count; @@ -126,8 +107,6 @@ irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g) u32 active_engine_id = 0; u32 engine_enum = ENGINE_INVAL_GK20A; - gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); - mc_intr_0 = gk20a_readl(g, mc_intr_r(0)); hw_irq_count = atomic_read(&g->hw_irq_stall_count); @@ -172,12 +151,22 @@ irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g) gk20a_dbg(gpu_dbg_intr, "stall intr done 0x%08x\n", mc_intr_0); +} + +u32 mc_gp10b_intr_stall(struct gk20a *g) +{ + return gk20a_readl(g, mc_intr_r(NVGPU_MC_INTR_STALLING)); +} + +void mc_gp10b_intr_stall_pause(struct gk20a *g) +{ + gk20a_writel(g, mc_intr_en_clear_r(NVGPU_MC_INTR_STALLING), 0xffffffff); +} + +void mc_gp10b_intr_stall_resume(struct gk20a *g) +{ gk20a_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING), g->ops.mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]); - - wake_up_all(&g->sw_irq_stall_last_handled_wq); - - return IRQ_HANDLED; } void gp10b_init_mc(struct gpu_ops *gops) @@ -185,8 +174,10 @@ void gp10b_init_mc(struct gpu_ops *gops) gops->mc.intr_enable = mc_gp10b_intr_enable; gops->mc.intr_unit_config = mc_gp10b_intr_unit_config; gops->mc.isr_stall = mc_gp10b_isr_stall; + gops->mc.intr_stall = mc_gp10b_intr_stall; + gops->mc.intr_stall_pause = mc_gp10b_intr_stall_pause; + gops->mc.intr_stall_resume = mc_gp10b_intr_stall_resume; gops->mc.isr_nonstall = mc_gp10b_isr_nonstall; - gops->mc.isr_thread_stall = mc_gp10b_intr_thread_stall; gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb; gops->mc.enable = gk20a_mc_enable; diff --git a/drivers/gpu/nvgpu/gp10b/mc_gp10b.h b/drivers/gpu/nvgpu/gp10b/mc_gp10b.h index b2ec4be4c..31867a888 100644 --- a/drivers/gpu/nvgpu/gp10b/mc_gp10b.h +++ b/drivers/gpu/nvgpu/gp10b/mc_gp10b.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2017, 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, @@ -24,8 +24,7 @@ void gp10b_init_mc(struct gpu_ops *gops); void mc_gp10b_intr_enable(struct gk20a *g); void mc_gp10b_intr_unit_config(struct gk20a *g, bool enable, bool is_stalling, u32 mask); -irqreturn_t mc_gp10b_isr_stall(struct gk20a *g); +void mc_gp10b_isr_stall(struct gk20a *g); irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g); -irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g); irqreturn_t mc_gp10b_intr_thread_nonstall(struct gk20a *g); #endif