From c381d24aab5e6b2678283aa3f7458747f6788ad0 Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Fri, 25 Sep 2020 09:43:56 -0600 Subject: [PATCH 1/3] msm: kgsl: Trigger recovery upon GMU assert in hwscheduling A GMU assert puts GMU in NMI so it will no longer be responsive and hence triggering recovery is important. Also, trigger recovery on WDOG or CM3 fault interrupt from GMU. Make sure snapshot and reset is only triggered if device was active. Also, clear the CM3 fault every SLUMBER exit. Change-Id: I9d6a063470bcd082a9cbecc5b8dcf0a412713bb1 Signed-off-by: Harshdeep Dhatt --- drivers/gpu/msm/adreno.c | 4 +--- drivers/gpu/msm/adreno_a6xx_gmu.c | 8 ++++++++ drivers/gpu/msm/adreno_a6xx_hwsched.c | 14 ++++++++------ drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c | 14 +++++++++++++- drivers/gpu/msm/adreno_hwsched.c | 3 +++ 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 8aeabbcb5966..99e527988c93 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1523,9 +1523,7 @@ static void adreno_unbind(struct device *dev) kgsl_pwrscale_close(device); - if (test_bit(GMU_DISPATCH, &device->gmu_core.flags)) - adreno_hwsched_dispatcher_close(adreno_dev); - else { + if (!test_bit(GMU_DISPATCH, &device->gmu_core.flags)) { adreno_dispatcher_close(adreno_dev); adreno_ringbuffer_close(adreno_dev); diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index ba3556f8d1ea..1d821e57cdb6 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -1314,6 +1314,9 @@ void a6xx_gmu_register_config(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); u32 gmu_log_info, chipid = 0; + /* Clear any previously set cm3 fault */ + atomic_set(&gmu->cm3_fault, 0); + /* Vote veto for FAL10 feature if supported*/ if (a6xx_core->veto_fal10) { gmu_core_regwrite(device, A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF, 0x1); @@ -2063,6 +2066,11 @@ static irqreturn_t a6xx_gmu_irq_handler(int irq, void *data) dev_err_ratelimited(&gmu->pdev->dev, "GMU watchdog expired interrupt received\n"); + + if (test_bit(GMU_DISPATCH, &device->gmu_core.flags)) { + adreno_get_gpu_halt(adreno_dev); + adreno_hwsched_set_fault(adreno_dev); + } } if (status & GMU_INT_HOST_AHB_BUS_ERR) dev_err_ratelimited(&gmu->pdev->dev, diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched.c b/drivers/gpu/msm/adreno_a6xx_hwsched.c index 185d53386f2c..50d79cc41c1b 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched.c +++ b/drivers/gpu/msm/adreno_a6xx_hwsched.c @@ -511,6 +511,8 @@ static int a6xx_hwsched_boot(struct adreno_device *adreno_dev) trace_kgsl_pwr_request_state(device, KGSL_STATE_ACTIVE); + adreno_hwsched_start(adreno_dev); + ret = a6xx_hwsched_gmu_boot(adreno_dev); if (ret) return ret; @@ -519,8 +521,6 @@ static int a6xx_hwsched_boot(struct adreno_device *adreno_dev) if (ret) return ret; - adreno_hwsched_start(adreno_dev); - mod_timer(&device->idle_timer, jiffies + device->pwrctrl.interval_timeout); @@ -543,6 +543,8 @@ static int a6xx_hwsched_first_boot(struct adreno_device *adreno_dev) if (test_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags)) return a6xx_hwsched_boot(adreno_dev); + adreno_hwsched_start(adreno_dev); + ret = a6xx_microcode_read(adreno_dev); if (ret) return ret; @@ -565,10 +567,6 @@ static int a6xx_hwsched_first_boot(struct adreno_device *adreno_dev) if (ret) return ret; - adreno_hwsched_init(adreno_dev); - - adreno_hwsched_start(adreno_dev); - adreno_get_bus_counters(adreno_dev); adreno_dev->cooperative_reset = ADRENO_FEATURE(adreno_dev, @@ -980,6 +978,8 @@ int a6xx_hwsched_probe(struct platform_device *pdev, adreno_dev->irq_mask = A6XX_HWSCHED_INT_MASK; + adreno_hwsched_init(adreno_dev); + return 0; } @@ -1017,6 +1017,8 @@ static void a6xx_hwsched_unbind(struct device *dev, struct device *master, struct kgsl_device *device = dev_get_drvdata(master); a6xx_gmu_remove(device); + + adreno_hwsched_dispatcher_close(ADRENO_DEVICE(device)); } static const struct component_ops a6xx_hwsched_component_ops = { diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c index 2c5dfc0d95ad..10914ffe7e5b 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c +++ b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c @@ -247,11 +247,14 @@ static void process_dbgq_irq(struct adreno_device *adreno_dev) { struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); u32 rcvd[MAX_RCVD_SIZE]; + bool recovery = false; while (a6xx_hfi_queue_read(gmu, HFI_DBG_ID, rcvd, sizeof(rcvd)) > 0) { - if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_ERR) + if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_ERR) { adreno_a6xx_receive_err_req(gmu, rcvd); + recovery = true; + } if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_DEBUG) adreno_a6xx_receive_debug_req(gmu, rcvd); @@ -259,6 +262,12 @@ static void process_dbgq_irq(struct adreno_device *adreno_dev) if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_LOG_BLOCK) adreno_a6xx_add_log_block(adreno_dev, rcvd); } + + if (!recovery) + return; + + adreno_get_gpu_halt(adreno_dev); + adreno_hwsched_set_fault(adreno_dev); } /* HFI interrupt handler */ @@ -293,6 +302,9 @@ static irqreturn_t a6xx_hwsched_hfi_handler(int irq, void *data) dev_err_ratelimited(&gmu->pdev->dev, "GMU CM3 fault interrupt received\n"); + + adreno_get_gpu_halt(adreno_dev); + adreno_hwsched_set_fault(adreno_dev); } /* Ignore OOB bits */ diff --git a/drivers/gpu/msm/adreno_hwsched.c b/drivers/gpu/msm/adreno_hwsched.c index 643acbdf0da3..7accee6ef2bc 100644 --- a/drivers/gpu/msm/adreno_hwsched.c +++ b/drivers/gpu/msm/adreno_hwsched.c @@ -1221,6 +1221,9 @@ static void reset_and_snapshot(struct adreno_device *adreno_dev) struct cmd_list_obj *obj = get_fault_cmdobj(adreno_dev); struct adreno_hwsched *hwsched = to_hwsched(adreno_dev); + if (device->state != KGSL_STATE_ACTIVE) + return; + if (!obj) { kgsl_device_snapshot(device, NULL, false); goto done; From 817655d509ea7935ce47430cd66bd42004cb883e Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Mon, 28 Sep 2020 11:03:35 -0600 Subject: [PATCH 2/3] msm: kgsl: Fix error handling during gmu boot Need to turn off interrupts if we encounter an error other than a gmu fault or timeout. Change-Id: If4261f5a2c8ce63bceede3a460faca0353817a39 Signed-off-by: Harshdeep Dhatt --- drivers/gpu/msm/adreno_a6xx_gmu.c | 4 ++++ drivers/gpu/msm/adreno_a6xx_hwsched.c | 14 ++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 1d821e57cdb6..44bdd90893bc 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -2302,6 +2302,8 @@ err: return ret; } + a6xx_gmu_irq_disable(adreno_dev); + clks_gdsc_off: clk_bulk_disable_unprepare(gmu->num_clks, gmu->clks); @@ -2379,6 +2381,8 @@ err: return ret; } + a6xx_gmu_irq_disable(adreno_dev); + clks_gdsc_off: clk_bulk_disable_unprepare(gmu->num_clks, gmu->clks); diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched.c b/drivers/gpu/msm/adreno_a6xx_hwsched.c index 50d79cc41c1b..322cb5c376fc 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched.c +++ b/drivers/gpu/msm/adreno_a6xx_hwsched.c @@ -204,10 +204,13 @@ static int a6xx_hwsched_gmu_first_boot(struct adreno_device *adreno_dev) return 0; err: - if (device->gmu_fault) + if (device->gmu_fault) { a6xx_gmu_suspend(adreno_dev); - return ret; + return ret; + } + + a6xx_gmu_irq_disable(adreno_dev); clks_gdsc_off: clk_bulk_disable_unprepare(gmu->num_clks, gmu->clks); @@ -262,10 +265,13 @@ static int a6xx_hwsched_gmu_boot(struct adreno_device *adreno_dev) return 0; err: - if (device->gmu_fault) + if (device->gmu_fault) { a6xx_gmu_suspend(adreno_dev); - return ret; + return ret; + } + + a6xx_gmu_irq_disable(adreno_dev); clks_gdsc_off: clk_bulk_disable_unprepare(gmu->num_clks, gmu->clks); From c79cda3408cafa7ec96a4abb910f5a48bc7ca174 Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Wed, 7 Oct 2020 08:28:08 -0600 Subject: [PATCH 3/3] msm: kgsl: Initialize drawctxt active node earlier gpudev->preemption_context_init() can fail and invoke adreno_drawctxt_detach(). This causes a crash because drawctxt->active_node is not initialized. Change-Id: I201759316cfa5dc831e1987d209c73efb97bb9ee Signed-off-by: Harshdeep Dhatt --- drivers/gpu/msm/adreno_drawctxt.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c index 165912dda049..417b853fe30f 100644 --- a/drivers/gpu/msm/adreno_drawctxt.c +++ b/drivers/gpu/msm/adreno_drawctxt.c @@ -401,6 +401,13 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv, adreno_context_debugfs_init(ADRENO_DEVICE(device), drawctxt); + if (!test_bit(GMU_DISPATCH, &device->gmu_core.flags)) { + /* set the context ringbuffer */ + drawctxt->rb = adreno_ctx_get_rb(adreno_dev, drawctxt); + + INIT_LIST_HEAD(&drawctxt->active_node); + } + if (gpudev->preemption_context_init) { ret = gpudev->preemption_context_init(&drawctxt->base); if (ret != 0) { @@ -412,13 +419,6 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv, /* copy back whatever flags we dediced were valid */ *flags = drawctxt->base.flags; - if (!test_bit(GMU_DISPATCH, &device->gmu_core.flags)) { - /* set the context ringbuffer */ - drawctxt->rb = adreno_ctx_get_rb(adreno_dev, drawctxt); - - INIT_LIST_HEAD(&drawctxt->active_node); - } - return &drawctxt->base; }