mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 10:34:43 +03:00
gpu: nvgpu: Update read_pending_interrupts hal
Modify read_pending_interrupts hal to report the pending gr interrupt bit back to isr to process. semaphore_timeout interrupt bit is removed after gk20a chip. Remove that bit checking from the isr function. Remove some static functions for handling interrupt, which only calls gk20a_gr_set_error_notifier. Call that function directly from isr JIRA NVGPU-3016 Change-Id: Ic7084f038114fbce6d6b5c10a806dee6280e5c0a Signed-off-by: Vinod G <vinodg@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2092876 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
9f486ba21e
commit
1095f0eea3
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user