diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index cdbb4a6c2..6ee73ffe1 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c @@ -68,6 +68,20 @@ static inline u32 gk20a_mmu_id_to_engine_id(u32 engine_id) } } +int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type) +{ + int ret = ENGINE_INVAL_GK20A; + + gk20a_dbg_info("engine type %d", engine_type); + if (engine_type == top_device_info_type_enum_graphics_v()) + ret = ENGINE_GR_GK20A; + else if (engine_type == top_device_info_type_enum_copy2_v()) + ret = ENGINE_CE2_GK20A; + else + gk20a_err(g->dev, "unknown engine %d", engine_type); + + return ret; +} static int init_engine_info(struct fifo_gk20a *f) { @@ -75,6 +89,12 @@ static int init_engine_info(struct fifo_gk20a *f) struct device *d = dev_from_gk20a(g); u32 i; u32 max_info_entries = top_device_info__size_1_v(); + u32 engine_enum = ENGINE_INVAL_GK20A; + u32 engine_id = ~0; + u32 runlist_id = ~0; + u32 pbdma_id = ~0; + u32 intr_id = ~0; + u32 reset_id = ~0; gk20a_dbg_fn(""); @@ -83,57 +103,71 @@ static int init_engine_info(struct fifo_gk20a *f) f->num_engines = 2; for (i = 0; i < max_info_entries; i++) { - struct fifo_engine_info_gk20a *info = NULL; u32 table_entry = gk20a_readl(f->g, top_device_info_r(i)); u32 entry = top_device_info_entry_v(table_entry); - u32 engine_enum; - int pbdma_id; u32 runlist_bit; - if (entry != top_device_info_entry_enum_v()) - continue; + if (entry == top_device_info_entry_enum_v()) { + if (top_device_info_engine_v(table_entry)) { + engine_id = + top_device_info_engine_enum_v(table_entry); + gk20a_dbg_info("info: engine_id %d", + top_device_info_engine_enum_v(table_entry)); + } - /* we only care about GR engine here */ - engine_enum = top_device_info_engine_enum_v(table_entry); - if (engine_enum >= ENGINE_INVAL_GK20A) - continue; - gk20a_dbg_info("info: engine_id %d", - top_device_info_engine_enum_v(table_entry)); - info = &g->fifo.engine_info[engine_enum]; + if (top_device_info_runlist_v(table_entry)) { + runlist_id = + top_device_info_runlist_enum_v(table_entry); + gk20a_dbg_info("gr info: runlist_id %d", runlist_id); - info->runlist_id = - top_device_info_runlist_enum_v(table_entry); - gk20a_dbg_info("gr info: runlist_id %d", info->runlist_id); + runlist_bit = BIT(runlist_id); - info->engine_id = - top_device_info_engine_enum_v(table_entry); - gk20a_dbg_info("gr info: engine_id %d", info->engine_id); + for (pbdma_id = 0; pbdma_id < f->num_pbdma; pbdma_id++) { + gk20a_dbg_info("gr info: pbdma_map[%d]=%d", + pbdma_id, f->pbdma_map[pbdma_id]); + if (f->pbdma_map[pbdma_id] & runlist_bit) + break; + } - runlist_bit = 1 << info->runlist_id; + if (pbdma_id == f->num_pbdma) { + gk20a_err(d, "busted pbdma map"); + return -EINVAL; + } + } - for (pbdma_id = 0; pbdma_id < f->num_pbdma; pbdma_id++) { - gk20a_dbg_info("gr info: pbdma_map[%d]=%d", - pbdma_id, f->pbdma_map[pbdma_id]); - if (f->pbdma_map[pbdma_id] & runlist_bit) - break; + if (top_device_info_intr_v(table_entry)) { + intr_id = + top_device_info_intr_enum_v(table_entry); + gk20a_dbg_info("gr info: intr_id %d", intr_id); + } + + if (top_device_info_reset_v(table_entry)) { + reset_id = + top_device_info_reset_enum_v(table_entry); + gk20a_dbg_info("gr info: reset_id %d", + reset_id); + } + } else if (entry == top_device_info_entry_engine_type_v()) { + u32 engine_type = + top_device_info_type_enum_v(table_entry); + engine_enum = + g->ops.fifo.engine_enum_from_type(g, engine_type); } - if (pbdma_id == f->num_pbdma) { - gk20a_err(d, "busted pbmda map"); - return -EINVAL; + if (!top_device_info_chain_v(table_entry)) { + if (engine_enum < ENGINE_INVAL_GK20A) { + struct fifo_engine_info_gk20a *info = + &g->fifo.engine_info[engine_enum]; + + info->intr_mask |= BIT(intr_id); + info->reset_mask |= BIT(reset_id); + info->runlist_id = runlist_id; + info->pbdma_id = pbdma_id; + + engine_enum = ENGINE_INVAL_GK20A; + } } - info->pbdma_id = pbdma_id; - - info->intr_id = - top_device_info_intr_enum_v(table_entry); - gk20a_dbg_info("gr info: intr_id %d", info->intr_id); - - info->reset_id = - top_device_info_reset_enum_v(table_entry); - gk20a_dbg_info("gr info: reset_id %d", - info->reset_id); - } return 0; @@ -145,13 +179,12 @@ u32 gk20a_fifo_engine_interrupt_mask(struct gk20a *g) int i = 0; for (i = 0; i < g->fifo.max_engines; i++) { - u32 intr_id = g->fifo.engine_info[i].intr_id; + u32 intr_mask = g->fifo.engine_info[i].intr_mask; if (i == ENGINE_CE2_GK20A && (!g->ops.ce2.isr_stall || !g->ops.ce2.isr_nonstall)) continue; - if (intr_id) - eng_intr_mask |= BIT(intr_id); + eng_intr_mask |= intr_mask; } return eng_intr_mask; @@ -771,7 +804,7 @@ void gk20a_fifo_reset_engine(struct gk20a *g, u32 engine_id) { gk20a_dbg_fn(""); - if (engine_id == top_device_info_type_enum_graphics_v()) { + if (engine_id == ENGINE_GR_GK20A) { if (support_gk20a_pmu(g->dev) && g->elpg_enabled) gk20a_pmu_disable_elpg(g); /*HALT_PIPELINE method, halt GR engine*/ @@ -788,7 +821,7 @@ void gk20a_fifo_reset_engine(struct gk20a *g, u32 engine_id) if (support_gk20a_pmu(g->dev) && g->elpg_enabled) gk20a_pmu_enable_elpg(g); } - if (engine_id == top_device_info_type_enum_copy0_v()) + if (engine_id == ENGINE_CE2_GK20A) gk20a_reset(g, mc_enable_ce2_m()); } @@ -2694,4 +2727,5 @@ void gk20a_init_fifo(struct gpu_ops *gops) gops->fifo.get_pbdma_signature = gk20a_fifo_get_pbdma_signature; gops->fifo.set_runlist_interleave = gk20a_fifo_set_runlist_interleave; gops->fifo.force_reset_ch = gk20a_fifo_force_reset_ch; + gops->fifo.engine_enum_from_type = gk20a_fifo_engine_enum_from_type; } diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h index c95ba71c1..e795eba08 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h @@ -79,8 +79,8 @@ struct fifo_mmu_fault_info_gk20a { struct fifo_engine_info_gk20a { u32 engine_id; u32 runlist_id; - u32 intr_id; - u32 reset_id; + u32 intr_mask; + u32 reset_mask; u32 pbdma_id; struct fifo_pbdma_exception_info_gk20a pbdma_exception_info; struct fifo_engine_exception_info_gk20a engine_exception_info; @@ -222,5 +222,6 @@ void gk20a_fifo_debugfs_init(struct device *dev); const char *gk20a_fifo_interleave_level_name(u32 interleave_level); +int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type); #endif /*__GR_GK20A_H__*/ diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 5d06a441a..d5310b02e 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -330,6 +330,7 @@ struct gpu_ops { int (*channel_set_timeslice)(struct channel_gk20a *ch, u32 timeslice); int (*force_reset_ch)(struct channel_gk20a *ch, bool verbose); + int (*engine_enum_from_type)(struct gk20a *g, u32 engine_type); } fifo; struct pmu_v { /*used for change of enum zbc update cmd id from ver 0 to ver1*/ diff --git a/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h b/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h index 35d9d3474..6981cf71f 100644 --- a/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2016, 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, @@ -118,13 +118,29 @@ static inline u32 top_device_info_type_enum_graphics_f(void) { return 0x0; } -static inline u32 top_device_info_type_enum_copy0_v(void) +static inline u32 top_device_info_type_enum_copy2_v(void) { - return 0x00000001; + return 0x00000003; } -static inline u32 top_device_info_type_enum_copy0_f(void) +static inline u32 top_device_info_type_enum_copy2_f(void) { - return 0x4; + return 0xc; +} +static inline u32 top_device_info_engine_v(u32 r) +{ + return (r >> 5) & 0x1; +} +static inline u32 top_device_info_runlist_v(u32 r) +{ + return (r >> 4) & 0x1; +} +static inline u32 top_device_info_intr_v(u32 r) +{ + return (r >> 3) & 0x1; +} +static inline u32 top_device_info_reset_v(u32 r) +{ + return (r >> 2) & 0x1; } static inline u32 top_device_info_entry_v(u32 r) { @@ -138,6 +154,10 @@ static inline u32 top_device_info_entry_enum_v(void) { return 0x00000002; } +static inline u32 top_device_info_entry_engine_type_v(void) +{ + return 0x00000003; +} static inline u32 top_fs_status_fbp_r(void) { return 0x00022548; diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c index fe6448c96..70da7a02a 100644 --- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c @@ -84,9 +84,9 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0); - if (mc_intr_0 & BIT(g->fifo.engine_info[ENGINE_GR_GK20A].intr_id)) + if (mc_intr_0 & g->fifo.engine_info[ENGINE_GR_GK20A].intr_mask) gr_gk20a_elpg_protected_call(g, gk20a_gr_isr(g)); - if (mc_intr_0 & BIT(g->fifo.engine_info[ENGINE_CE2_GK20A].intr_id) + if (mc_intr_0 & g->fifo.engine_info[ENGINE_CE2_GK20A].intr_mask && g->ops.ce2.isr_stall) g->ops.ce2.isr_stall(g); if (mc_intr_0 & mc_intr_0_pfifo_pending_f()) @@ -132,9 +132,9 @@ irqreturn_t mc_gk20a_intr_thread_nonstall(struct gk20a *g) gk20a_fifo_nonstall_isr(g); if (mc_intr_1 & mc_intr_0_priv_ring_pending_f()) gk20a_priv_ring_isr(g); - if (mc_intr_1 & BIT(g->fifo.engine_info[ENGINE_GR_GK20A].intr_id)) + if (mc_intr_1 & g->fifo.engine_info[ENGINE_GR_GK20A].intr_mask) gk20a_gr_nonstall_isr(g); - if (mc_intr_1 & BIT(g->fifo.engine_info[ENGINE_CE2_GK20A].intr_id) + if (mc_intr_1 & g->fifo.engine_info[ENGINE_CE2_GK20A].intr_mask && g->ops.ce2.isr_nonstall) g->ops.ce2.isr_nonstall(g); diff --git a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c index e738b1d20..a6d953a45 100644 --- a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c @@ -126,4 +126,5 @@ void gm20b_init_fifo(struct gpu_ops *gops) gops->fifo.get_pbdma_signature = gk20a_fifo_get_pbdma_signature; gops->fifo.set_runlist_interleave = gk20a_fifo_set_runlist_interleave; gops->fifo.force_reset_ch = gk20a_fifo_force_reset_ch; + gops->fifo.engine_enum_from_type = gk20a_fifo_engine_enum_from_type; } diff --git a/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h b/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h index c0ad007d7..b0cf65798 100644 --- a/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2016, 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, @@ -138,13 +138,29 @@ static inline u32 top_device_info_type_enum_graphics_f(void) { return 0x0; } -static inline u32 top_device_info_type_enum_copy0_v(void) +static inline u32 top_device_info_type_enum_copy2_v(void) { - return 0x00000001; + return 0x00000003; } -static inline u32 top_device_info_type_enum_copy0_f(void) +static inline u32 top_device_info_type_enum_copy2_f(void) { - return 0x4; + return 0xc; +} +static inline u32 top_device_info_engine_v(u32 r) +{ + return (r >> 5) & 0x1; +} +static inline u32 top_device_info_runlist_v(u32 r) +{ + return (r >> 4) & 0x1; +} +static inline u32 top_device_info_intr_v(u32 r) +{ + return (r >> 3) & 0x1; +} +static inline u32 top_device_info_reset_v(u32 r) +{ + return (r >> 2) & 0x1; } static inline u32 top_device_info_entry_v(u32 r) { @@ -158,4 +174,8 @@ static inline u32 top_device_info_entry_enum_v(void) { return 0x00000002; } +static inline u32 top_device_info_entry_engine_type_v(void) +{ + return 0x00000003; +} #endif