diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index 3b0dc3e9b..1b9c898dc 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c @@ -293,11 +293,6 @@ u32 gr_gk20a_get_patch_slots(struct gk20a *g) return PATCH_CTX_SLOTS_PER_PAGE; } -#define NVA297_SET_ALPHA_CIRCULAR_BUFFER_SIZE 0x02dcU -#define NVA297_SET_CIRCULAR_BUFFER_SIZE 0x1280U -#define NVA297_SET_SHADER_EXCEPTIONS 0x1528U -#define NVA0C0_SET_SHADER_EXCEPTIONS 0x1528U - #define NVA297_SET_SHADER_EXCEPTIONS_ENABLE_FALSE U32(0) void gk20a_gr_set_shader_exceptions(struct gk20a *g, u32 data) @@ -365,29 +360,6 @@ static void gk20a_gr_set_error_notifier(struct gk20a *g, } } -static int gk20a_gr_handle_semaphore_timeout_pending(struct gk20a *g, - struct nvgpu_gr_isr_data *isr_data) -{ - nvgpu_log_fn(g, " "); - gk20a_gr_set_error_notifier(g, isr_data, - NVGPU_ERR_NOTIFIER_GR_SEMAPHORE_TIMEOUT); - nvgpu_err(g, - "gr semaphore timeout"); - return -EINVAL; -} - -static int gk20a_gr_intr_illegal_notify_pending(struct gk20a *g, - struct nvgpu_gr_isr_data *isr_data) -{ - nvgpu_log_fn(g, " "); - gk20a_gr_set_error_notifier(g, isr_data, - NVGPU_ERR_NOTIFIER_GR_ILLEGAL_NOTIFY); - /* This is an unrecoverable error, reset is needed */ - nvgpu_err(g, - "gr semaphore timeout"); - return -EINVAL; -} - static int gk20a_gr_handle_illegal_method(struct gk20a *g, struct nvgpu_gr_isr_data *isr_data) { @@ -404,18 +376,6 @@ static int gk20a_gr_handle_illegal_method(struct gk20a *g, return ret; } -static int gk20a_gr_handle_illegal_class(struct gk20a *g, - struct nvgpu_gr_isr_data *isr_data) -{ - nvgpu_log_fn(g, " "); - gk20a_gr_set_error_notifier(g, isr_data, - NVGPU_ERR_NOTIFIER_GR_ERROR_SW_NOTIFY); - nvgpu_err(g, - "invalid class 0x%08x, offset 0x%08x", - isr_data->class_num, isr_data->offset); - return -EINVAL; -} - int gk20a_gr_handle_fecs_error(struct gk20a *g, struct channel_gk20a *ch, struct nvgpu_gr_isr_data *isr_data) { @@ -536,23 +496,6 @@ static int gk20a_gr_handle_class_error(struct gk20a *g, return -EINVAL; } -static int gk20a_gr_handle_firmware_method(struct gk20a *g, - struct nvgpu_gr_isr_data *isr_data) -{ - u32 chid = isr_data->ch != NULL ? - isr_data->ch->chid : FIFO_INVAL_CHANNEL_ID; - - nvgpu_log_fn(g, " "); - - gk20a_gr_set_error_notifier(g, isr_data, - NVGPU_ERR_NOTIFIER_GR_ERROR_SW_NOTIFY); - nvgpu_err(g, - "firmware method 0x%08x, offset 0x%08x for channel %u", - isr_data->class_num, isr_data->offset, - chid); - return -EINVAL; -} - /* Used by sw interrupt thread to translate current ctx to chid. * Also used by regops to translate current ctx to chid and tsgid. * For performance, we don't want to go through 128 channels every time. @@ -804,8 +747,8 @@ static int gk20a_gr_post_bpt_events(struct gk20a *g, struct tsg_gk20a *tsg, int gk20a_gr_isr(struct gk20a *g) { struct nvgpu_gr_isr_data isr_data; + struct nvgpu_gr_intr_info intr_info; bool need_reset = false; - u32 gr_intr = g->ops.gr.intr.read_pending_interrupts(g); struct channel_gk20a *ch = NULL; struct channel_gk20a *fault_ch = NULL; u32 tsgid = NVGPU_INVALID_TSG_ID; @@ -814,6 +757,7 @@ int gk20a_gr_isr(struct gk20a *g) u32 global_esr = 0; u32 chid; struct nvgpu_gr_config *gr_config = g->gr.config; + u32 gr_intr = g->ops.gr.intr.read_pending_interrupts(g, &intr_info); u32 clear_intr = gr_intr; nvgpu_log_fn(g, " "); @@ -857,72 +801,73 @@ int gk20a_gr_isr(struct gk20a *g) isr_data.curr_ctx, isr_data.offset, isr_data.sub_chan, isr_data.class_num); - if ((gr_intr & gr_intr_notify_pending_f()) != 0U) { + if (intr_info.notify != 0U) { g->ops.gr.intr.handle_notify_pending(g, &isr_data); - clear_intr &= ~gr_intr_notify_pending_f(); + clear_intr &= ~intr_info.notify; } - if ((gr_intr & gr_intr_semaphore_pending_f()) != 0U) { + if (intr_info.semaphore != 0U) { g->ops.gr.intr.handle_semaphore_pending(g, &isr_data); - clear_intr &= ~gr_intr_semaphore_pending_f(); + clear_intr &= ~intr_info.semaphore; } - if ((gr_intr & gr_intr_semaphore_timeout_pending_f()) != 0U) { - if (gk20a_gr_handle_semaphore_timeout_pending(g, - &isr_data) != 0) { - need_reset = true; - } - clear_intr &= ~gr_intr_semaphore_pending_f(); + if (intr_info.illegal_notify != 0U) { + nvgpu_err(g, "illegal notify pending"); + + gk20a_gr_set_error_notifier(g, &isr_data, + NVGPU_ERR_NOTIFIER_GR_ILLEGAL_NOTIFY); + need_reset = true; + clear_intr &= ~intr_info.illegal_notify; } - if ((gr_intr & gr_intr_illegal_notify_pending_f()) != 0U) { - if (gk20a_gr_intr_illegal_notify_pending(g, - &isr_data) != 0) { - need_reset = true; - } - clear_intr &= ~gr_intr_illegal_notify_pending_f(); - } - - if ((gr_intr & gr_intr_illegal_method_pending_f()) != 0U) { + if (intr_info.illegal_method != 0U) { if (gk20a_gr_handle_illegal_method(g, &isr_data) != 0) { need_reset = true; } - clear_intr &= ~gr_intr_illegal_method_pending_f(); + clear_intr &= ~intr_info.illegal_method; } - if ((gr_intr & gr_intr_illegal_class_pending_f()) != 0U) { - if (gk20a_gr_handle_illegal_class(g, &isr_data) != 0) { - need_reset = true; - } - clear_intr &= ~gr_intr_illegal_class_pending_f(); + if (intr_info.illegal_class != 0U) { + nvgpu_err(g, "invalid class 0x%08x, offset 0x%08x", + isr_data.class_num, isr_data.offset); + + gk20a_gr_set_error_notifier(g, &isr_data, + NVGPU_ERR_NOTIFIER_GR_ERROR_SW_NOTIFY); + need_reset = true; + clear_intr &= ~intr_info.illegal_class; } - if ((gr_intr & gr_intr_fecs_error_pending_f()) != 0U) { + if (intr_info.fecs_error != 0U) { if (g->ops.gr.handle_fecs_error(g, ch, &isr_data) != 0) { need_reset = true; } - clear_intr &= ~gr_intr_fecs_error_pending_f(); + clear_intr &= ~intr_info.fecs_error; } - if ((gr_intr & gr_intr_class_error_pending_f()) != 0U) { + if (intr_info.class_error != 0U) { if (gk20a_gr_handle_class_error(g, &isr_data) != 0) { need_reset = true; } - clear_intr &= ~gr_intr_class_error_pending_f(); + clear_intr &= ~intr_info.class_error; } /* this one happens if someone tries to hit a non-whitelisted * register using set_falcon[4] */ - if ((gr_intr & gr_intr_firmware_method_pending_f()) != 0U) { - if (gk20a_gr_handle_firmware_method(g, &isr_data) != 0) { - need_reset = true; - } - nvgpu_log(g, gpu_dbg_intr | gpu_dbg_gpu_dbg, - "firmware method intr pending\n"); - clear_intr &= ~gr_intr_firmware_method_pending_f(); + if (intr_info.fw_method != 0U) { + u32 ch_id = isr_data.ch != NULL ? + isr_data.ch->chid : FIFO_INVAL_CHANNEL_ID; + nvgpu_err(g, + "firmware method 0x%08x, offset 0x%08x for channel %u", + isr_data.class_num, isr_data.offset, + ch_id); + + gk20a_gr_set_error_notifier(g, &isr_data, + NVGPU_ERR_NOTIFIER_GR_ERROR_SW_NOTIFY); + need_reset = true; + clear_intr &= ~intr_info.fw_method; } - if ((gr_intr & gr_intr_exception_pending_f()) != 0U) { + if (intr_info.exception != 0U) { bool is_gpc_exception = false; need_reset = g->ops.gr.intr.handle_exceptions(g, @@ -954,7 +899,7 @@ int gk20a_gr_isr(struct gk20a *g) } #endif } - clear_intr &= ~gr_intr_exception_pending_f(); + clear_intr &= ~intr_info.exception; if (need_reset) { nvgpu_err(g, "set gr exception notifier"); diff --git a/drivers/gpu/nvgpu/hal/gr/intr/gr_intr_gm20b.c b/drivers/gpu/nvgpu/hal/gr/intr/gr_intr_gm20b.c index 63e9b461d..c52c31ecd 100644 --- a/drivers/gpu/nvgpu/hal/gr/intr/gr_intr_gm20b.c +++ b/drivers/gpu/nvgpu/hal/gr/intr/gr_intr_gm20b.c @@ -36,9 +36,52 @@ void gm20b_gr_intr_clear_pending_interrupts(struct gk20a *g, u32 gr_intr) nvgpu_writel(g, gr_intr_r(), gr_intr); } -u32 gm20b_gr_intr_read_pending_interrupts(struct gk20a *g) +u32 gm20b_gr_intr_read_pending_interrupts(struct gk20a *g, + struct nvgpu_gr_intr_info *intr_info) { - return nvgpu_readl(g, gr_intr_r()); + u32 gr_intr = nvgpu_readl(g, gr_intr_r()); + + (void) memset(intr_info, 0, sizeof(struct nvgpu_gr_intr_info)); + + if ((gr_intr & gr_intr_notify_pending_f()) != 0U) { + intr_info->notify = gr_intr_notify_pending_f(); + } + + if ((gr_intr & gr_intr_semaphore_pending_f()) != 0U) { + intr_info->semaphore = gr_intr_semaphore_pending_f(); + } + + if ((gr_intr & gr_intr_illegal_notify_pending_f()) != 0U) { + intr_info->illegal_notify = gr_intr_illegal_notify_pending_f(); + } + + if ((gr_intr & gr_intr_illegal_method_pending_f()) != 0U) { + intr_info->illegal_method = gr_intr_illegal_method_pending_f(); + } + + if ((gr_intr & gr_intr_illegal_class_pending_f()) != 0U) { + intr_info->illegal_class = gr_intr_illegal_class_pending_f(); + } + + if ((gr_intr & gr_intr_fecs_error_pending_f()) != 0U) { + intr_info->fecs_error = gr_intr_fecs_error_pending_f(); + } + + if ((gr_intr & gr_intr_class_error_pending_f()) != 0U) { + intr_info->class_error = gr_intr_class_error_pending_f(); + } + + /* this one happens if someone tries to hit a non-whitelisted + * register using set_falcon[4] */ + if ((gr_intr & gr_intr_firmware_method_pending_f()) != 0U) { + intr_info->fw_method = gr_intr_firmware_method_pending_f(); + } + + if ((gr_intr & gr_intr_exception_pending_f()) != 0U) { + intr_info->exception = gr_intr_exception_pending_f(); + } + + return gr_intr; } bool gm20b_gr_intr_handle_exceptions(struct gk20a *g, bool *is_gpc_exception) diff --git a/drivers/gpu/nvgpu/hal/gr/intr/gr_intr_gm20b.h b/drivers/gpu/nvgpu/hal/gr/intr/gr_intr_gm20b.h index 49f59b6b5..fd7956db4 100644 --- a/drivers/gpu/nvgpu/hal/gr/intr/gr_intr_gm20b.h +++ b/drivers/gpu/nvgpu/hal/gr/intr/gr_intr_gm20b.h @@ -29,9 +29,11 @@ struct gk20a; struct nvgpu_gr_config; struct nvgpu_gr_tpc_exception; struct nvgpu_gr_isr_data; +struct nvgpu_gr_intr_info; void gm20b_gr_intr_clear_pending_interrupts(struct gk20a *g, u32 gr_intr); -u32 gm20b_gr_intr_read_pending_interrupts(struct gk20a *g); +u32 gm20b_gr_intr_read_pending_interrupts(struct gk20a *g, + struct nvgpu_gr_intr_info *intr_info); bool gm20b_gr_intr_handle_exceptions(struct gk20a *g, bool *is_gpc_exception); u32 gm20b_gr_intr_read_gpc_tpc_exception(u32 gpc_exception); u32 gm20b_gr_intr_read_gpc_exception(struct gk20a *g, u32 gpc); diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index 00b299110..b5cc46ab9 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -66,6 +66,7 @@ struct nvgpu_gr_zbc_query_params; struct nvgpu_gr_zcull; struct nvgpu_gr_zcull_info; struct nvgpu_gr_tpc_exception; +struct nvgpu_gr_intr_info; struct nvgpu_channel_hw_state; struct nvgpu_engine_status_info; struct nvgpu_pbdma_status_info; @@ -784,7 +785,8 @@ struct gpu_ops { struct { void (*clear_pending_interrupts)(struct gk20a *g, u32 gr_intr); - u32 (*read_pending_interrupts)(struct gk20a *g); + u32 (*read_pending_interrupts)(struct gk20a *g, + struct nvgpu_gr_intr_info *intr_info); bool (*handle_exceptions)(struct gk20a *g, bool *is_gpc_exception); u32 (*read_gpc_tpc_exception)(u32 gpc_exception); diff --git a/drivers/gpu/nvgpu/include/nvgpu/gr/gr_intr.h b/drivers/gpu/nvgpu/include/nvgpu/gr/gr_intr.h index 6b02c02fc..2675dc491 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gr/gr_intr.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gr/gr_intr.h @@ -27,6 +27,18 @@ struct channel_gk20a; +struct nvgpu_gr_intr_info { + u32 notify; + u32 semaphore; + u32 illegal_notify; + u32 illegal_method; + u32 illegal_class; + u32 fecs_error; + u32 class_error; + u32 fw_method; + u32 exception; +}; + struct nvgpu_gr_tpc_exception { bool tex_exception; bool sm_exception;