From f3cb140a71f179ce023bac48d5b92537893214a1 Mon Sep 17 00:00:00 2001 From: Lakshmanan M Date: Mon, 23 May 2016 12:20:14 +0530 Subject: gpu: nvgpu: Add device_info_data support Added device_info_data parsing support for maxwell GPU series. JIRA DNVGPU-26 Change-Id: I06dbec6056d4c26501e607c2c3d67ef468d206f4 Signed-off-by: Lakshmanan M Reviewed-on: http://git-master/r/1151602 Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 85 +++++++++++++++++++++++----------- drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | 6 ++- drivers/gpu/nvgpu/gk20a/gk20a.h | 6 ++- drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h | 4 ++ drivers/gpu/nvgpu/gm206/hw_top_gm206.h | 32 +++++++++++++ drivers/gpu/nvgpu/gm20b/fifo_gm20b.c | 46 +++++++++++++----- drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h | 32 +++++++++++++ 7 files changed, 171 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index cf97b33a..16ca16d8 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c @@ -44,39 +44,49 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, * Link engine IDs to MMU IDs and vice versa. */ -static inline u32 gk20a_engine_id_to_mmu_id(u32 engine_id) -{ - switch (engine_id) { - case ENGINE_GR_GK20A: - return 0x00; - case ENGINE_CE2_GK20A: - return 0x1b; - default: - return ~0; +static inline u32 gk20a_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id) +{ + u32 fault_id = ~0; + + if (engine_id < ENGINE_INVAL_GK20A) { + struct fifo_engine_info_gk20a *info = + &g->fifo.engine_info[engine_id]; + + fault_id = info->fault_id; } + return fault_id; } -static inline u32 gk20a_mmu_id_to_engine_id(u32 engine_id) +static inline u32 gk20a_mmu_id_to_engine_id(struct gk20a *g, u32 fault_id) { - switch (engine_id) { - case 0x00: - return ENGINE_GR_GK20A; - case 0x1b: - return ENGINE_CE2_GK20A; - default: - return ~0; + u32 engine_id; + u32 return_engine_id = ~0; + + for (engine_id = 0; engine_id < ENGINE_INVAL_GK20A; engine_id++) { + struct fifo_engine_info_gk20a *info = + &g->fifo.engine_info[engine_id]; + + if (info->fault_id == fault_id) { + return_engine_id = engine_id; + break; + } } + return return_engine_id; } -int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type) +int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type, + u32 *inst_id) { 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()) + else if (engine_type == top_device_info_type_enum_copy2_v()) { ret = ENGINE_CE2_GK20A; + if (inst_id) + *inst_id = 0x2; + } else gk20a_err(g->dev, "unknown engine %d", engine_type); @@ -95,6 +105,9 @@ static int init_engine_info(struct fifo_gk20a *f) u32 pbdma_id = ~0; u32 intr_id = ~0; u32 reset_id = ~0; + u32 inst_id = 0; + u32 pri_base = 0; + u32 fault_id = 0; gk20a_dbg_fn(""); @@ -152,7 +165,15 @@ static int init_engine_info(struct fifo_gk20a *f) u32 engine_type = top_device_info_type_enum_v(table_entry); engine_enum = - g->ops.fifo.engine_enum_from_type(g, engine_type); + g->ops.fifo.engine_enum_from_type(g, + engine_type, &inst_id); + } else if (entry == top_device_info_entry_data_v()) { + /* gk20a don't support device_info_data + packet parsing */ + if (g->ops.fifo.device_info_data_parse) + g->ops.fifo.device_info_data_parse(g, + table_entry, &inst_id, &pri_base, + &fault_id); } if (!top_device_info_chain_v(table_entry)) { @@ -164,6 +185,13 @@ static int init_engine_info(struct fifo_gk20a *f) info->reset_mask |= BIT(reset_id); info->runlist_id = runlist_id; info->pbdma_id = pbdma_id; + info->inst_id = inst_id; + info->pri_base = pri_base; + + if (!fault_id && + (engine_enum == ENGINE_CE2_GK20A)) + fault_id = 0x1b; + info->fault_id = fault_id; engine_enum = ENGINE_INVAL_GK20A; } @@ -948,7 +976,7 @@ static bool gk20a_fifo_handle_mmu_fault( { bool fake_fault; unsigned long fault_id; - unsigned long engine_mmu_id; + unsigned long engine_mmu_fault_id; bool verbose = true; u32 grfifo_ctl; @@ -988,10 +1016,11 @@ static bool gk20a_fifo_handle_mmu_fault( /* go through all faulted engines */ - for_each_set_bit(engine_mmu_id, &fault_id, 32) { + for_each_set_bit(engine_mmu_fault_id, &fault_id, 32) { /* bits in fifo_intr_mmu_fault_id_r do not correspond 1:1 to * engines. Convert engine_mmu_id to engine_id */ - u32 engine_id = gk20a_mmu_id_to_engine_id(engine_mmu_id); + u32 engine_id = gk20a_mmu_id_to_engine_id(g, + engine_mmu_fault_id); struct fifo_mmu_fault_info_gk20a f; struct channel_gk20a *ch = NULL; struct tsg_gk20a *tsg = NULL; @@ -1007,7 +1036,7 @@ static bool gk20a_fifo_handle_mmu_fault( || ctx_status == fifo_engine_status_ctx_status_ctxsw_load_v()); - get_exception_mmu_fault_info(g, engine_mmu_id, &f); + get_exception_mmu_fault_info(g, engine_mmu_fault_id, &f); trace_gk20a_mmu_fault(f.fault_hi_v, f.fault_lo_v, f.fault_info_v, @@ -1189,7 +1218,7 @@ static void gk20a_fifo_trigger_mmu_fault(struct gk20a *g, gk20a_writel(g, fifo_trigger_mmu_fault_r(engine_id), fifo_trigger_mmu_fault_id_f( - gk20a_engine_id_to_mmu_id(engine_id)) | + gk20a_engine_id_to_mmu_id(g, engine_id)) | fifo_trigger_mmu_fault_enable_f(1)); } @@ -1332,7 +1361,7 @@ void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids, engine_ids |= __engine_ids; for_each_set_bit(engine_id, &engine_ids, 32) { mmu_fault_engines |= - BIT(gk20a_engine_id_to_mmu_id(engine_id)); + BIT(gk20a_engine_id_to_mmu_id(g, engine_id)); } } else { /* store faulted engines in advance */ @@ -1353,7 +1382,7 @@ void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids, if (ref_type == type && ref_id == id) { engine_ids |= BIT(i); mmu_fault_engines |= - BIT(gk20a_engine_id_to_mmu_id(i)); + BIT(gk20a_engine_id_to_mmu_id(g, i)); } } } @@ -2728,4 +2757,6 @@ void gk20a_init_fifo(struct gpu_ops *gops) 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; + /* gk20a don't support device_info_data packet parsing */ + gops->fifo.device_info_data_parse = NULL; } diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h index e795eba0..986db4b1 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h @@ -82,6 +82,9 @@ struct fifo_engine_info_gk20a { u32 intr_mask; u32 reset_mask; u32 pbdma_id; + u32 inst_id; + u32 pri_base; + u32 fault_id; struct fifo_pbdma_exception_info_gk20a pbdma_exception_info; struct fifo_engine_exception_info_gk20a engine_exception_info; struct fifo_mmu_fault_info_gk20a mmu_fault_info; @@ -222,6 +225,7 @@ 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); +int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type, + u32 *inst_id); #endif /*__GR_GK20A_H__*/ diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 56f8fddb..0e13fba3 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -340,7 +340,11 @@ 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); + int (*engine_enum_from_type)(struct gk20a *g, u32 engine_type, + u32 *inst_id); + void (*device_info_data_parse)(struct gk20a *g, + u32 table_entry, u32 *inst_id, + u32 *pri_base, u32 *fault_id); } 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 6981cf71..517cffef 100644 --- a/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h @@ -158,6 +158,10 @@ static inline u32 top_device_info_entry_engine_type_v(void) { return 0x00000003; } +static inline u32 top_device_info_entry_data_v(void) +{ + return 0x00000001; +} static inline u32 top_fs_status_fbp_r(void) { return 0x00022548; diff --git a/drivers/gpu/nvgpu/gm206/hw_top_gm206.h b/drivers/gpu/nvgpu/gm206/hw_top_gm206.h index 289f4411..e6ec1d27 100644 --- a/drivers/gpu/nvgpu/gm206/hw_top_gm206.h +++ b/drivers/gpu/nvgpu/gm206/hw_top_gm206.h @@ -158,6 +158,38 @@ static inline u32 top_device_info_entry_enum_v(void) { return 0x00000002; } +static inline u32 top_device_info_entry_data_v(void) +{ + return 0x00000001; +} +static inline u32 top_device_info_data_type_v(u32 r) +{ + return (r >> 30) & 0x1; +} +static inline u32 top_device_info_data_type_enum2_v(void) +{ + return 0x00000000; +} +static inline u32 top_device_info_data_pri_base_v(u32 r) +{ + return (r >> 12) & 0x7ff; +} +static inline u32 top_device_info_data_pri_base_align_v(void) +{ + return 0x0000000c; +} +static inline u32 top_device_info_data_fault_id_enum_v(u32 r) +{ + return (r >> 3) & 0x1f; +} +static inline u32 top_device_info_data_fault_id_v(u32 r) +{ + return (r >> 2) & 0x1; +} +static inline u32 top_device_info_data_fault_id_valid_v(void) +{ + return 0x00000001; +} static inline u32 top_scratch1_r(void) { return 0x0002240c; diff --git a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c index a6d953a4..eaa22dc2 100644 --- a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c @@ -19,6 +19,7 @@ #include "hw_ccsr_gm20b.h" #include "hw_ram_gm20b.h" #include "hw_fifo_gm20b.h" +#include "hw_top_gm20b.h" static void channel_gm20b_bind(struct channel_gk20a *c) { @@ -45,16 +46,17 @@ static void channel_gm20b_bind(struct channel_gk20a *c) ccsr_channel_enable_set_true_f()); } -static inline u32 gm20b_engine_id_to_mmu_id(u32 engine_id) +static inline u32 gm20b_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id) { - switch (engine_id) { - case ENGINE_GR_GK20A: - return 0; - case ENGINE_CE2_GK20A: - return 1; - default: - return ~0; + u32 fault_id = ~0; + + if (engine_id < ENGINE_INVAL_GK20A) { + struct fifo_engine_info_gk20a *info = + &g->fifo.engine_info[engine_id]; + + fault_id = info->fault_id; } + return fault_id; } static void gm20b_fifo_trigger_mmu_fault(struct gk20a *g, @@ -68,14 +70,15 @@ static void gm20b_fifo_trigger_mmu_fault(struct gk20a *g, /* trigger faults for all bad engines */ for_each_set_bit(engine_id, &engine_ids, 32) { - u32 engine_mmu_id; + u32 engine_mmu_fault_id; if (engine_id > g->fifo.max_engines) { gk20a_err(dev_from_gk20a(g), "faulting unknown engine %ld", engine_id); } else { - engine_mmu_id = gm20b_engine_id_to_mmu_id(engine_id); - gk20a_writel(g, fifo_trigger_mmu_fault_r(engine_mmu_id), + engine_mmu_fault_id = gm20b_engine_id_to_mmu_id(g, + engine_id); + gk20a_writel(g, fifo_trigger_mmu_fault_r(engine_id), fifo_trigger_mmu_fault_enable_f(1)); } } @@ -106,6 +109,26 @@ static u32 gm20b_fifo_get_num_fifos(struct gk20a *g) return ccsr_channel__size_1_v(); } +void gm20b_device_info_data_parse(struct gk20a *g, + u32 table_entry, u32 *inst_id, + u32 *pri_base, u32 *fault_id) +{ + if (top_device_info_data_type_v(table_entry) == + top_device_info_data_type_enum2_v()) { + if (pri_base) { + *pri_base = + (top_device_info_data_pri_base_v(table_entry) + << top_device_info_data_pri_base_align_v()); + } + if (fault_id && (top_device_info_data_fault_id_v(table_entry) == + top_device_info_data_fault_id_valid_v())) { + *fault_id = + top_device_info_data_fault_id_enum_v(table_entry); + } + } else + gk20a_err(g->dev, "unknown device_info_data %d", + top_device_info_data_type_v(table_entry)); +} void gm20b_init_fifo(struct gpu_ops *gops) { gops->fifo.bind_channel = channel_gm20b_bind; @@ -127,4 +150,5 @@ void gm20b_init_fifo(struct gpu_ops *gops) 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; + gops->fifo.device_info_data_parse = gm20b_device_info_data_parse; } diff --git a/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h b/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h index b0cf6579..c70f388c 100644 --- a/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h @@ -178,4 +178,36 @@ static inline u32 top_device_info_entry_engine_type_v(void) { return 0x00000003; } +static inline u32 top_device_info_entry_data_v(void) +{ + return 0x00000001; +} +static inline u32 top_device_info_data_type_v(u32 r) +{ + return (r >> 30) & 0x1; +} +static inline u32 top_device_info_data_type_enum2_v(void) +{ + return 0x00000000; +} +static inline u32 top_device_info_data_pri_base_v(u32 r) +{ + return (r >> 12) & 0x7ff; +} +static inline u32 top_device_info_data_pri_base_align_v(void) +{ + return 0x0000000c; +} +static inline u32 top_device_info_data_fault_id_enum_v(u32 r) +{ + return (r >> 3) & 0x1f; +} +static inline u32 top_device_info_data_fault_id_v(u32 r) +{ + return (r >> 2) & 0x1; +} +static inline u32 top_device_info_data_fault_id_valid_v(void) +{ + return 0x00000001; +} #endif -- cgit v1.2.2