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..44bdd90893bc 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, @@ -2294,6 +2302,8 @@ err: return ret; } + a6xx_gmu_irq_disable(adreno_dev); + clks_gdsc_off: clk_bulk_disable_unprepare(gmu->num_clks, gmu->clks); @@ -2371,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 185d53386f2c..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); @@ -511,6 +517,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 +527,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 +549,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 +573,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 +984,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 +1023,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_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; } 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;