From 4492c62ffe9398bd4457f6f1c2773e40afe909fb Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Fri, 17 Mar 2017 11:09:44 -0700 Subject: gpu: nvgpu: Add bus HAL Add bus HAL and move all bus related hardware sequencing to that file: BAR1 binding, timer access, and interrupt handling. Change-Id: Ibc5f5797dc338de10749b446a7bdbcae600fecb4 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/1323353 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile.nvgpu | 2 + drivers/gpu/nvgpu/clk/clk_arb.c | 4 +- drivers/gpu/nvgpu/clk/clk_mclk.c | 4 +- drivers/gpu/nvgpu/gk20a/bus_gk20a.c | 156 ++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/bus_gk20a.h | 29 ++++++ drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c | 2 +- drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c | 4 +- drivers/gpu/nvgpu/gk20a/gk20a.c | 104 +------------------ drivers/gpu/nvgpu/gk20a/gk20a.h | 12 ++- drivers/gpu/nvgpu/gk20a/hal_gk20a.c | 3 +- drivers/gpu/nvgpu/gk20a/mc_gk20a.c | 2 +- drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 25 +---- drivers/gpu/nvgpu/gm20b/bus_gm20b.c | 64 ++++++++++++ drivers/gpu/nvgpu/gm20b/bus_gm20b.h | 23 ++++ drivers/gpu/nvgpu/gm20b/hal_gm20b.c | 3 +- drivers/gpu/nvgpu/gm20b/mm_gm20b.c | 34 ------ drivers/gpu/nvgpu/gp106/hal_gp106.c | 3 +- drivers/gpu/nvgpu/gp10b/hal_gp10b.c | 3 +- drivers/gpu/nvgpu/gp10b/mc_gp10b.c | 2 +- drivers/gpu/nvgpu/gp10b/mm_gp10b.c | 2 +- drivers/gpu/nvgpu/vgpu/vgpu.c | 2 +- 21 files changed, 306 insertions(+), 177 deletions(-) create mode 100644 drivers/gpu/nvgpu/gk20a/bus_gk20a.c create mode 100644 drivers/gpu/nvgpu/gk20a/bus_gk20a.h create mode 100644 drivers/gpu/nvgpu/gm20b/bus_gm20b.c create mode 100644 drivers/gpu/nvgpu/gm20b/bus_gm20b.h diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu index 3852e728..9cf5195b 100644 --- a/drivers/gpu/nvgpu/Makefile.nvgpu +++ b/drivers/gpu/nvgpu/Makefile.nvgpu @@ -34,6 +34,7 @@ nvgpu-y := \ common/semaphore.o \ common/vbios/bios.o \ gk20a/gk20a.o \ + gk20a/bus_gk20a.o \ gk20a/sched_gk20a.o \ gk20a/as_gk20a.o \ gk20a/ctrl_gk20a.o \ @@ -67,6 +68,7 @@ nvgpu-y := \ gk20a/mc_gk20a.o \ gk20a/sim_gk20a.o \ gm20b/hal_gm20b.o \ + gm20b/bus_gm20b.o \ gm20b/ltc_gm20b.o \ gm20b/ce2_gm20b.o \ gm20b/gr_gm20b.o \ diff --git a/drivers/gpu/nvgpu/clk/clk_arb.c b/drivers/gpu/nvgpu/clk/clk_arb.c index 30447d3e..fc821235 100644 --- a/drivers/gpu/nvgpu/clk/clk_arb.c +++ b/drivers/gpu/nvgpu/clk/clk_arb.c @@ -1062,7 +1062,7 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) goto exit_arb; #ifdef CONFIG_DEBUG_FS - g->ops.read_ptimer(g, &t0); + g->ops.bus.read_ptimer(g, &t0); #endif /* Only one arbiter should be running */ @@ -1248,7 +1248,7 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) wake_up_interruptible(&arb->request_wq); #ifdef CONFIG_DEBUG_FS - g->ops.read_ptimer(g, &t1); + g->ops.bus.read_ptimer(g, &t1); debug = arb->debug == &arb->debug_pool[0] ? &arb->debug_pool[1] : &arb->debug_pool[0]; diff --git a/drivers/gpu/nvgpu/clk/clk_mclk.c b/drivers/gpu/nvgpu/clk/clk_mclk.c index c2e9b35c..e5452051 100644 --- a/drivers/gpu/nvgpu/clk/clk_mclk.c +++ b/drivers/gpu/nvgpu/clk/clk_mclk.c @@ -2311,7 +2311,7 @@ int clk_mclkseq_change_mclk_gddr5(struct gk20a *g, u16 val) pseq_cmd->cmd_type = NV_PMU_SEQ_CMD_ID_RUN_SCRIPT; #ifdef CONFIG_DEBUG_FS - g->ops.read_ptimer(g, &t0); + g->ops.bus.read_ptimer(g, &t0); #endif if (speed == gk20a_mclk_high_speed) { @@ -2362,7 +2362,7 @@ int clk_mclkseq_change_mclk_gddr5(struct gk20a *g, u16 val) mclk->speed = speed; #ifdef CONFIG_DEBUG_FS - g->ops.read_ptimer(g, &t1); + g->ops.bus.read_ptimer(g, &t1); nvgpu_mutex_acquire(&mclk->data_lock); mclk->switch_num++; diff --git a/drivers/gpu/nvgpu/gk20a/bus_gk20a.c b/drivers/gpu/nvgpu/gk20a/bus_gk20a.c new file mode 100644 index 00000000..fda1f80e --- /dev/null +++ b/drivers/gpu/nvgpu/gk20a/bus_gk20a.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include + +#include "gk20a.h" + +#include +#include +#include +#include + +void gk20a_bus_init_hw(struct gk20a *g) +{ + struct gk20a_platform *platform = gk20a_get_platform(g->dev); + + /* enable pri timeout only on silicon */ + if (tegra_platform_is_silicon()) { + gk20a_writel(g, + timer_pri_timeout_r(), + timer_pri_timeout_period_f( + platform->default_pri_timeout ? + platform->default_pri_timeout : + 0x186A0) | + timer_pri_timeout_en_en_enabled_f()); + } else { + gk20a_writel(g, + timer_pri_timeout_r(), + timer_pri_timeout_period_f(0x186A0) | + timer_pri_timeout_en_en_disabled_f()); + } + + if (!tegra_platform_is_silicon()) + gk20a_writel(g, bus_intr_en_0_r(), 0x0); + else + gk20a_writel(g, bus_intr_en_0_r(), + bus_intr_en_0_pri_squash_m() | + bus_intr_en_0_pri_fecserr_m() | + bus_intr_en_0_pri_timeout_m()); +} + +void gk20a_bus_isr(struct gk20a *g) +{ + u32 val, err_code; + val = gk20a_readl(g, bus_intr_0_r()); + if (val & (bus_intr_0_pri_squash_m() | + bus_intr_0_pri_fecserr_m() | + bus_intr_0_pri_timeout_m())) { + gk20a_dbg(gpu_dbg_intr, "pmc_enable : 0x%x", + gk20a_readl(g, mc_enable_r())); + gk20a_dbg(gpu_dbg_intr, "NV_PBUS_INTR_0 : 0x%x", val); + gk20a_dbg(gpu_dbg_intr, + "NV_PTIMER_PRI_TIMEOUT_SAVE_0: 0x%x\n", + gk20a_readl(g, timer_pri_timeout_save_0_r())); + gk20a_dbg(gpu_dbg_intr, + "NV_PTIMER_PRI_TIMEOUT_SAVE_1: 0x%x\n", + gk20a_readl(g, timer_pri_timeout_save_1_r())); + err_code = gk20a_readl(g, timer_pri_timeout_fecs_errcode_r()); + gk20a_dbg(gpu_dbg_intr, + "NV_PTIMER_PRI_TIMEOUT_FECS_ERRCODE: 0x%x\n", + err_code); + if (err_code == 0xbadf13) + gk20a_dbg(gpu_dbg_intr, + "NV_PGRAPH_PRI_GPC0_GPCCS_FS_GPC: 0x%x\n", + gk20a_readl(g, gr_gpc0_fs_gpc_r())); + + gk20a_writel(g, timer_pri_timeout_save_0_r(), 0); + gk20a_writel(g, timer_pri_timeout_save_1_r(), 0); + } + + if (val) + gk20a_dbg(gpu_dbg_intr, + "Unhandled pending pbus interrupt\n"); + + gk20a_writel(g, bus_intr_0_r(), val); +} + +int gk20a_read_ptimer(struct gk20a *g, u64 *value) +{ + const unsigned int max_iterations = 3; + unsigned int i = 0; + u32 gpu_timestamp_hi_prev = 0; + + if (!value) + return -EINVAL; + + /* Note. The GPU nanosecond timer consists of two 32-bit + * registers (high & low). To detect a possible low register + * wrap-around between the reads, we need to read the high + * register before and after low. The wraparound happens + * approximately once per 4 secs. */ + + /* get initial gpu_timestamp_hi value */ + gpu_timestamp_hi_prev = gk20a_readl(g, timer_time_1_r()); + + for (i = 0; i < max_iterations; ++i) { + u32 gpu_timestamp_hi = 0; + u32 gpu_timestamp_lo = 0; + + gpu_timestamp_lo = gk20a_readl(g, timer_time_0_r()); + gpu_timestamp_hi = gk20a_readl(g, timer_time_1_r()); + + if (gpu_timestamp_hi == gpu_timestamp_hi_prev) { + *value = (((u64)gpu_timestamp_hi) << 32) | + gpu_timestamp_lo; + return 0; + } + + /* wrap-around detected, retry */ + gpu_timestamp_hi_prev = gpu_timestamp_hi; + } + + /* too many iterations, bail out */ + gk20a_err(dev_from_gk20a(g), "failed to read ptimer"); + return -EBUSY; +} + +static int gk20a_bus_bar1_bind(struct gk20a *g, struct mem_desc *bar1_inst) +{ + u64 iova = gk20a_mm_inst_block_addr(g, bar1_inst); + u32 ptr_v = (u32)(iova >> bar1_instance_block_shift_gk20a()); + + gk20a_dbg_info("bar1 inst block ptr: 0x%08x", ptr_v); + + gk20a_writel(g, bus_bar1_block_r(), + gk20a_aperture_mask(g, bar1_inst, + bus_bar1_block_target_sys_mem_ncoh_f(), + bus_bar1_block_target_vid_mem_f()) | + bus_bar1_block_mode_virtual_f() | + bus_bar1_block_ptr_f(ptr_v)); + + return 0; +} + +void gk20a_init_bus(struct gpu_ops *gops) +{ + gops->bus.init_hw = gk20a_bus_init_hw; + gops->bus.isr = gk20a_bus_isr; + gops->bus.read_ptimer = gk20a_read_ptimer; + gops->bus.bar1_bind = gk20a_bus_bar1_bind; +} diff --git a/drivers/gpu/nvgpu/gk20a/bus_gk20a.h b/drivers/gpu/nvgpu/gk20a/bus_gk20a.h new file mode 100644 index 00000000..01526f06 --- /dev/null +++ b/drivers/gpu/nvgpu/gk20a/bus_gk20a.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef BUS_GK20A_H +#define BUS_GK20A_H + +struct gk20a; +struct gpu_ops; +struct mem_desc; + +void gk20a_init_bus(struct gpu_ops *gops); + +void gk20a_bus_isr(struct gk20a *g); +int gk20a_read_ptimer(struct gk20a *g, u64 *value); +void gk20a_bus_init_hw(struct gk20a *g); + +#endif /* GK20A_H */ diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c index e6626c4a..67971369 100644 --- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c @@ -725,7 +725,7 @@ static int nvgpu_gpu_get_gpu_time( if (err) return err; - err = g->ops.read_ptimer(g, &time); + err = g->ops.bus.read_ptimer(g, &time); if (!err) args->gpu_timestamp = time; diff --git a/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c index 4ad2abd6..0736a03b 100644 --- a/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c @@ -686,7 +686,7 @@ void gk20a_ctxsw_trace_channel_reset(struct gk20a *g, struct channel_gk20a *ch) if (!g->ctxsw_trace) return; - g->ops.read_ptimer(g, &entry.timestamp); + g->ops.bus.read_ptimer(g, &entry.timestamp); gk20a_ctxsw_trace_write(g, &entry); gk20a_ctxsw_trace_wake_up(g, 0); #endif @@ -706,7 +706,7 @@ void gk20a_ctxsw_trace_tsg_reset(struct gk20a *g, struct tsg_gk20a *tsg) if (!g->ctxsw_trace) return; - g->ops.read_ptimer(g, &entry.timestamp); + g->ops.bus.read_ptimer(g, &entry.timestamp); gk20a_ctxsw_trace_write(g, &entry); gk20a_ctxsw_trace_wake_up(g, 0); #endif diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 76484dd5..72528758 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -57,6 +57,7 @@ #include "hal.h" #include "vgpu/vgpu.h" #include "pci.h" +#include "bus_gk20a.h" #ifdef CONFIG_ARCH_TEGRA_18x_SOC #include "pstate/pstate.h" #endif @@ -70,11 +71,8 @@ #endif #include -#include -#include #include #include -#include #include @@ -330,42 +328,6 @@ static irqreturn_t gk20a_intr_isr_nonstall(int irq, void *dev_id) return g->ops.mc.isr_nonstall(g); } -void gk20a_pbus_isr(struct gk20a *g) -{ - u32 val, err_code; - val = gk20a_readl(g, bus_intr_0_r()); - if (val & (bus_intr_0_pri_squash_m() | - bus_intr_0_pri_fecserr_m() | - bus_intr_0_pri_timeout_m())) { - gk20a_dbg(gpu_dbg_intr, "pmc_enable : 0x%x", - gk20a_readl(g, mc_enable_r())); - gk20a_dbg(gpu_dbg_intr, "NV_PBUS_INTR_0 : 0x%x", val); - gk20a_dbg(gpu_dbg_intr, - "NV_PTIMER_PRI_TIMEOUT_SAVE_0: 0x%x\n", - gk20a_readl(g, timer_pri_timeout_save_0_r())); - gk20a_dbg(gpu_dbg_intr, - "NV_PTIMER_PRI_TIMEOUT_SAVE_1: 0x%x\n", - gk20a_readl(g, timer_pri_timeout_save_1_r())); - err_code = gk20a_readl(g, timer_pri_timeout_fecs_errcode_r()); - gk20a_dbg(gpu_dbg_intr, - "NV_PTIMER_PRI_TIMEOUT_FECS_ERRCODE: 0x%x\n", - err_code); - if (err_code == 0xbadf13) - gk20a_dbg(gpu_dbg_intr, - "NV_PGRAPH_PRI_GPC0_GPCCS_FS_GPC: 0x%x\n", - gk20a_readl(g, gr_gpc0_fs_gpc_r())); - - gk20a_writel(g, timer_pri_timeout_save_0_r(), 0); - gk20a_writel(g, timer_pri_timeout_save_1_r(), 0); - } - - if (val) - gk20a_dbg(gpu_dbg_intr, - "Unhandled pending pbus interrupt\n"); - - gk20a_writel(g, bus_intr_0_r(), val); -} - static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id) { struct gk20a *g = dev_id; @@ -596,13 +558,7 @@ int gk20a_pm_finalize_poweron(struct device *dev) if (err) goto done; - if (!tegra_platform_is_silicon()) - gk20a_writel(g, bus_intr_en_0_r(), 0x0); - else - gk20a_writel(g, bus_intr_en_0_r(), - bus_intr_en_0_pri_squash_m() | - bus_intr_en_0_pri_fecserr_m() | - bus_intr_en_0_pri_timeout_m()); + g->ops.bus.init_hw(g); if (g->ops.clk.disable_slowboot) g->ops.clk.disable_slowboot(g); @@ -630,22 +586,6 @@ int gk20a_pm_finalize_poweron(struct device *dev) } } - /* enable pri timeout only on silicon */ - if (tegra_platform_is_silicon()) { - gk20a_writel(g, - timer_pri_timeout_r(), - timer_pri_timeout_period_f( - platform->default_pri_timeout ? - platform->default_pri_timeout : - 0x186A0) | - timer_pri_timeout_en_en_enabled_f()); - } else { - gk20a_writel(g, - timer_pri_timeout_r(), - timer_pri_timeout_period_f(0x186A0) | - timer_pri_timeout_en_en_disabled_f()); - } - err = gk20a_init_fifo_reset_enable_hw(g); if (err) { gk20a_err(dev, "failed to reset gk20a fifo"); @@ -1910,46 +1850,6 @@ int gk20a_init_gpu_characteristics(struct gk20a *g) return 0; } -int gk20a_read_ptimer(struct gk20a *g, u64 *value) -{ - const unsigned int max_iterations = 3; - unsigned int i = 0; - u32 gpu_timestamp_hi_prev = 0; - - if (!value) - return -EINVAL; - - /* Note. The GPU nanosecond timer consists of two 32-bit - * registers (high & low). To detect a possible low register - * wrap-around between the reads, we need to read the high - * register before and after low. The wraparound happens - * approximately once per 4 secs. */ - - /* get initial gpu_timestamp_hi value */ - gpu_timestamp_hi_prev = gk20a_readl(g, timer_time_1_r()); - - for (i = 0; i < max_iterations; ++i) { - u32 gpu_timestamp_hi = 0; - u32 gpu_timestamp_lo = 0; - - gpu_timestamp_lo = gk20a_readl(g, timer_time_0_r()); - gpu_timestamp_hi = gk20a_readl(g, timer_time_1_r()); - - if (gpu_timestamp_hi == gpu_timestamp_hi_prev) { - *value = (((u64)gpu_timestamp_hi) << 32) | - gpu_timestamp_lo; - return 0; - } - - /* wrap-around detected, retry */ - gpu_timestamp_hi_prev = gpu_timestamp_hi; - } - - /* too many iterations, bail out */ - gk20a_err(dev_from_gk20a(g), "failed to read ptimer"); - return -EBUSY; -} - /* * Free the gk20a struct. */ diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 7c836b3c..8d03cc9a 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -629,7 +629,6 @@ struct gpu_ops { struct vm_gk20a *vm); u64 (*get_iova_addr)(struct gk20a *g, struct scatterlist *sgl, u32 flags); - int (*bar1_bind)(struct gk20a *g, struct mem_desc *bar1_inst); size_t (*get_vidmem_size)(struct gk20a *g); void (*init_inst_block)(struct mem_desc *inst_block, struct vm_gk20a *vm, u32 big_page_size); @@ -773,7 +772,13 @@ struct gpu_ops { int (*get_litter_value)(struct gk20a *g, int value); int (*chip_init_gpu_characteristics)(struct gk20a *g); - int (*read_ptimer)(struct gk20a *g, u64 *value); + + struct { + void (*init_hw)(struct gk20a *g); + void (*isr)(struct gk20a *g); + int (*read_ptimer)(struct gk20a *g, u64 *value); + int (*bar1_bind)(struct gk20a *g, struct mem_desc *bar1_inst); + } bus; int (*bios_init)(struct gk20a *g); @@ -1417,8 +1422,6 @@ int gk20a_wait_for_idle(struct device *dev); int gk20a_init_gpu_characteristics(struct gk20a *g); -void gk20a_pbus_isr(struct gk20a *g); - int gk20a_user_init(struct device *dev, const char *interface_name, struct class *class); void gk20a_user_deinit(struct device *dev, struct class *class); @@ -1435,7 +1438,6 @@ static inline u32 scale_ptimer(u32 timeout , u32 scale10x) return (timeout * 10) / scale10x; } -int gk20a_read_ptimer(struct gk20a *g, u64 *value); extern struct class nvgpu_class; #define INTERFACE_NAME "nvhost%s-gpu" diff --git a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c index 23725b8b..1e4fffdc 100644 --- a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c @@ -16,6 +16,7 @@ */ #include "hal_gk20a.h" +#include "bus_gk20a.h" #include "ltc_gk20a.h" #include "fb_gk20a.h" #include "gk20a.h" @@ -147,6 +148,7 @@ int gk20a_init_hal(struct gk20a *g) gops->privsecurity = 0; gops->securegpccs = 0; gops->pmupstate = false; + gk20a_init_bus(gops); gk20a_init_mc(gops); gk20a_init_ltc(gops); gk20a_init_gr_ops(gops); @@ -169,7 +171,6 @@ int gk20a_init_hal(struct gk20a *g) gops->name = "gk20a"; gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics; gops->get_litter_value = gk20a_get_litter_value; - gops->read_ptimer = gk20a_read_ptimer; c->twod_class = FERMI_TWOD_A; c->threed_class = KEPLER_C; diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c index a1861b0d..e51c4a29 100644 --- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c @@ -150,7 +150,7 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) if (mc_intr_0 & mc_intr_0_ltc_pending_f()) g->ops.ltc.isr(g); if (mc_intr_0 & mc_intr_0_pbus_pending_f()) - gk20a_pbus_isr(g); + g->ops.bus.isr(g); /* sync handled irq counter before re-enabling interrupts */ atomic_set(&g->sw_irq_stall_last_handled, hw_irq_count); diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index eaf8f74a..b9217c2c 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c @@ -42,12 +42,13 @@ #include "mm_gk20a.h" #include "fence_gk20a.h" #include "kind_gk20a.h" +#include "bus_gk20a.h" #include -#include #include #include #include +#include #include #include @@ -1087,8 +1088,8 @@ int gk20a_init_mm_setup_hw(struct gk20a *g) g->ops.fb.init_hw(g); - if (g->ops.mm.bar1_bind) - g->ops.mm.bar1_bind(g, &mm->bar1.inst_block); + if (g->ops.bus.bar1_bind) + g->ops.bus.bar1_bind(g, &mm->bar1.inst_block); if (g->ops.mm.init_bar2_mm_hw_setup) { err = g->ops.mm.init_bar2_mm_hw_setup(g); @@ -1103,23 +1104,6 @@ int gk20a_init_mm_setup_hw(struct gk20a *g) return 0; } -static int gk20a_mm_bar1_bind(struct gk20a *g, struct mem_desc *bar1_inst) -{ - u64 iova = gk20a_mm_inst_block_addr(g, bar1_inst); - u32 ptr_v = (u32)(iova >> bar1_instance_block_shift_gk20a()); - - gk20a_dbg_info("bar1 inst block ptr: 0x%08x", ptr_v); - - gk20a_writel(g, bus_bar1_block_r(), - gk20a_aperture_mask(g, bar1_inst, - bus_bar1_block_target_sys_mem_ncoh_f(), - bus_bar1_block_target_vid_mem_f()) | - bus_bar1_block_mode_virtual_f() | - bus_bar1_block_ptr_f(ptr_v)); - - return 0; -} - int gk20a_init_mm_support(struct gk20a *g) { u32 err; @@ -5447,7 +5431,6 @@ void gk20a_init_mm(struct gpu_ops *gops) gops->mm.get_mmu_levels = gk20a_mm_get_mmu_levels; gops->mm.init_pdb = gk20a_mm_init_pdb; gops->mm.init_mm_setup_hw = gk20a_init_mm_setup_hw; - gops->mm.bar1_bind = gk20a_mm_bar1_bind; gops->mm.init_inst_block = gk20a_init_inst_block; gops->mm.is_bar1_supported = gk20a_mm_is_bar1_supported; gops->mm.mmu_fault_pending = gk20a_fifo_mmu_fault_pending; diff --git a/drivers/gpu/nvgpu/gm20b/bus_gm20b.c b/drivers/gpu/nvgpu/gm20b/bus_gm20b.c new file mode 100644 index 00000000..68a4b15f --- /dev/null +++ b/drivers/gpu/nvgpu/gm20b/bus_gm20b.c @@ -0,0 +1,64 @@ +/* + * GM20B MMU + * + * 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 + +#include "bus_gm20b.h" +#include "gk20a/gk20a.h" +#include "gk20a/bus_gk20a.h" + +#include + +static int gm20b_bus_bar1_bind(struct gk20a *g, struct mem_desc *bar1_inst) +{ + struct nvgpu_timeout timeout; + int err = 0; + u64 iova = gk20a_mm_inst_block_addr(g, bar1_inst); + u32 ptr_v = (u32)(iova >> bar1_instance_block_shift_gk20a()); + + gk20a_dbg_info("bar1 inst block ptr: 0x%08x", ptr_v); + + gk20a_writel(g, bus_bar1_block_r(), + gk20a_aperture_mask(g, bar1_inst, + bus_bar1_block_target_sys_mem_ncoh_f(), + bus_bar1_block_target_vid_mem_f()) | + bus_bar1_block_mode_virtual_f() | + bus_bar1_block_ptr_f(ptr_v)); + nvgpu_timeout_init(g, &timeout, 1000, NVGPU_TIMER_RETRY_TIMER); + do { + u32 val = gk20a_readl(g, bus_bind_status_r()); + u32 pending = bus_bind_status_bar1_pending_v(val); + u32 outstanding = bus_bind_status_bar1_outstanding_v(val); + if (!pending && !outstanding) + break; + + udelay(5); + } while (!nvgpu_timeout_expired(&timeout)); + + if (nvgpu_timeout_peek_expired(&timeout)) + err = -EINVAL; + + return err; +} + +void gm20b_init_bus(struct gpu_ops *gops) +{ + gops->bus.init_hw = gk20a_bus_init_hw; + gops->bus.isr = gk20a_bus_isr; + gops->bus.read_ptimer = gk20a_read_ptimer; + gops->bus.bar1_bind = gm20b_bus_bar1_bind; +} diff --git a/drivers/gpu/nvgpu/gm20b/bus_gm20b.h b/drivers/gpu/nvgpu/gm20b/bus_gm20b.h new file mode 100644 index 00000000..853e50a6 --- /dev/null +++ b/drivers/gpu/nvgpu/gm20b/bus_gm20b.h @@ -0,0 +1,23 @@ +/* + * GM20B BUS + * + * Copyright (c) 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_GM20B_BUS +#define _NVGPU_GM20B_BUS + +struct gpu_ops; + +void gm20b_init_bus(struct gpu_ops *gops); + +#endif diff --git a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c index ad041f67..684f5731 100644 --- a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c @@ -18,6 +18,7 @@ #include "gk20a/gk20a.h" #include "gk20a/dbg_gpu_gk20a.h" #include "gk20a/css_gr_gk20a.h" +#include "gk20a/bus_gk20a.h" #include "ltc_gm20b.h" #include "ce2_gm20b.h" @@ -215,6 +216,7 @@ int gm20b_init_hal(struct gk20a *g) } } #endif + gk20a_init_bus(gops); gm20b_init_mc(gops); gm20b_init_ltc(gops); gm20b_init_gr(gops); @@ -238,7 +240,6 @@ int gm20b_init_hal(struct gk20a *g) gops->name = "gm20b"; gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics; gops->get_litter_value = gm20b_get_litter_value; - gops->read_ptimer = gk20a_read_ptimer; c->twod_class = FERMI_TWOD_A; c->threed_class = MAXWELL_B; diff --git a/drivers/gpu/nvgpu/gm20b/mm_gm20b.c b/drivers/gpu/nvgpu/gm20b/mm_gm20b.c index 18f9eec1..949a5c5d 100644 --- a/drivers/gpu/nvgpu/gm20b/mm_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/mm_gm20b.c @@ -13,17 +13,12 @@ * more details. */ -#include - #include "gk20a/gk20a.h" #include "mm_gm20b.h" -#include - #include #include -#include static void gm20b_mm_set_big_page_size(struct gk20a *g, struct mem_desc *mem, int size) @@ -55,34 +50,6 @@ static bool gm20b_mm_support_sparse(struct gk20a *g) return true; } -static int gm20b_mm_bar1_bind(struct gk20a *g, struct mem_desc *bar1_inst) -{ - int retry = 1000; - u64 iova = gk20a_mm_inst_block_addr(g, bar1_inst); - u32 ptr_v = (u32)(iova >> bar1_instance_block_shift_gk20a()); - - gk20a_dbg_info("bar1 inst block ptr: 0x%08x", ptr_v); - - gk20a_writel(g, bus_bar1_block_r(), - gk20a_aperture_mask(g, bar1_inst, - bus_bar1_block_target_sys_mem_ncoh_f(), - bus_bar1_block_target_vid_mem_f()) | - bus_bar1_block_mode_virtual_f() | - bus_bar1_block_ptr_f(ptr_v)); - do { - u32 val = gk20a_readl(g, bus_bind_status_r()); - u32 pending = bus_bind_status_bar1_pending_v(val); - u32 outstanding = bus_bind_status_bar1_outstanding_v(val); - if (!pending && !outstanding) - break; - - udelay(5); - retry--; - } while (retry >= 0 || !tegra_platform_is_silicon()); - - return retry ? -EINVAL : 0; -} - static bool gm20b_mm_is_bar1_supported(struct gk20a *g) { return true; @@ -107,7 +74,6 @@ void gm20b_init_mm(struct gpu_ops *gops) gops->mm.get_mmu_levels = gk20a_mm_get_mmu_levels; gops->mm.init_pdb = gk20a_mm_init_pdb; gops->mm.init_mm_setup_hw = gk20a_init_mm_setup_hw; - gops->mm.bar1_bind = gm20b_mm_bar1_bind; gops->mm.is_bar1_supported = gm20b_mm_is_bar1_supported; gops->mm.init_inst_block = gk20a_init_inst_block; gops->mm.mmu_fault_pending = gk20a_fifo_mmu_fault_pending; diff --git a/drivers/gpu/nvgpu/gp106/hal_gp106.c b/drivers/gpu/nvgpu/gp106/hal_gp106.c index a05b71ab..36f72b12 100644 --- a/drivers/gpu/nvgpu/gp106/hal_gp106.c +++ b/drivers/gpu/nvgpu/gp106/hal_gp106.c @@ -21,6 +21,7 @@ #include "gk20a/gk20a.h" #include "gk20a/dbg_gpu_gk20a.h" #include "gk20a/css_gr_gk20a.h" +#include "gk20a/bus_gk20a.h" #include "gp10b/gr_gp10b.h" #include "gp10b/fecs_trace_gp10b.h" @@ -223,6 +224,7 @@ int gp106_init_hal(struct gk20a *g) gops->privsecurity = 1; gops->securegpccs = 1; gops->pmupstate = true; + gk20a_init_bus(gops); gp10b_init_mc(gops); gp106_init_gr(gops); gp10b_init_fecs_trace_ops(gops); @@ -251,7 +253,6 @@ int gp106_init_hal(struct gk20a *g) gops->get_litter_value = gp106_get_litter_value; gops->chip_init_gpu_characteristics = gp106_init_gpu_characteristics; gops->gr_ctx.use_dma_for_fw_bootstrap = true; - gops->read_ptimer = gk20a_read_ptimer; c->twod_class = FERMI_TWOD_A; c->threed_class = PASCAL_B; diff --git a/drivers/gpu/nvgpu/gp10b/hal_gp10b.c b/drivers/gpu/nvgpu/gp10b/hal_gp10b.c index 62a19abd..245d2d26 100644 --- a/drivers/gpu/nvgpu/gp10b/hal_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/hal_gp10b.c @@ -21,6 +21,7 @@ #include "gk20a/gk20a.h" #include "gk20a/dbg_gpu_gk20a.h" #include "gk20a/css_gr_gk20a.h" +#include "gk20a/bus_gk20a.h" #include "gp10b/gr_gp10b.h" #include "gp10b/fecs_trace_gp10b.h" @@ -232,6 +233,7 @@ int gp10b_init_hal(struct gk20a *g) } #endif + gk20a_init_bus(gops); gp10b_init_mc(gops); gp10b_init_gr(gops); gp10b_init_fecs_trace_ops(gops); @@ -254,7 +256,6 @@ int gp10b_init_hal(struct gk20a *g) gops->name = "gp10b"; gops->chip_init_gpu_characteristics = gp10b_init_gpu_characteristics; gops->get_litter_value = gp10b_get_litter_value; - gops->read_ptimer = gk20a_read_ptimer; c->twod_class = FERMI_TWOD_A; c->threed_class = PASCAL_A; diff --git a/drivers/gpu/nvgpu/gp10b/mc_gp10b.c b/drivers/gpu/nvgpu/gp10b/mc_gp10b.c index fc0e6553..547169ed 100644 --- a/drivers/gpu/nvgpu/gp10b/mc_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/mc_gp10b.c @@ -162,7 +162,7 @@ irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g) if (mc_intr_0 & mc_intr_ltc_pending_f()) g->ops.ltc.isr(g); if (mc_intr_0 & mc_intr_pbus_pending_f()) - gk20a_pbus_isr(g); + g->ops.bus.isr(g); /* sync handled irq counter before re-enabling interrupts */ atomic_set(&g->sw_irq_stall_last_handled, hw_irq_count); diff --git a/drivers/gpu/nvgpu/gp10b/mm_gp10b.c b/drivers/gpu/nvgpu/gp10b/mm_gp10b.c index 26facbe3..a5322bad 100644 --- a/drivers/gpu/nvgpu/gp10b/mm_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/mm_gp10b.c @@ -45,7 +45,7 @@ static int gp10b_init_mm_setup_hw(struct gk20a *g) (g->ops.mm.get_iova_addr(g, g->mm.sysmem_flush.sgt->sgl, 0) >> 8ULL)); - g->ops.mm.bar1_bind(g, inst_block); + g->ops.bus.bar1_bind(g, inst_block); if (g->ops.mm.init_bar2_mm_hw_setup) { err = g->ops.mm.init_bar2_mm_hw_setup(g); diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c index 2d7417f0..72606952 100644 --- a/drivers/gpu/nvgpu/vgpu/vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/vgpu.c @@ -362,7 +362,7 @@ void vgpu_init_hal_common(struct gk20a *g) vgpu_init_css_ops(gops); #endif gops->chip_init_gpu_characteristics = vgpu_init_gpu_characteristics; - gops->read_ptimer = vgpu_read_ptimer; + gops->bus.read_ptimer = vgpu_read_ptimer; } static int vgpu_init_hal(struct gk20a *g) -- cgit v1.2.2