From c744ab5d9c7b3505198ac1f713ac6bc0d7f3299b Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:12 -0600 Subject: [PATCH 1/5] msm: kgsl: Clean up the reset and soft reset paths a6xx added a new function hook and path for doing a GPU reset that fell back to the default reset path for a610 but a610 purposely skipped soft reset and the hard reset path is very similar to that used by GMU/RGMU enabled devices except for one little bit. Furthermore, if a610 skipped soft reset then there are no a6xx targets that do soft reset so there is no reason to have an a6xx specific soft reset path. And further to that, there isn't any reason to have any a6xx specific functions (like oob) in the generic soft reset path. Make the a6xx reset support all a6xx targets, remove unused infrastructure from the rest of the generic code and cleanup the generic functions to be a little bit easier to understand. Change-Id: Ic0dedbadd3570fe148a464ff0dc647d91099ae09 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno.c | 82 ++++++++++++++----------------- drivers/gpu/msm/adreno.h | 4 -- drivers/gpu/msm/adreno_a5xx.c | 4 -- drivers/gpu/msm/adreno_a6xx.c | 44 +++-------------- drivers/gpu/msm/adreno_dispatch.c | 5 +- 5 files changed, 45 insertions(+), 94 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index d0c81c13324a..3e5d2226b17e 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -31,6 +31,7 @@ #include "adreno-gpulist.h" static void adreno_input_work(struct work_struct *work); +static int adreno_soft_reset(struct kgsl_device *device); static unsigned int counter_delta(struct kgsl_device *device, unsigned int reg, unsigned int *counter); @@ -500,7 +501,7 @@ static struct input_handler adreno_input_handler = { * all the HW logic, restores GPU registers to default state and * flushes out pending VBIF transactions. */ -static int _soft_reset(struct adreno_device *adreno_dev) +static void _soft_reset(struct adreno_device *adreno_dev) { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); unsigned int reg; @@ -517,8 +518,6 @@ static int _soft_reset(struct adreno_device *adreno_dev) if (gpudev->regulator_enable) gpudev->regulator_enable(adreno_dev); - - return 0; } /** @@ -2315,28 +2314,21 @@ no_gx_power: int adreno_reset(struct kgsl_device *device, int fault) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); int ret = -EINVAL; - int i = 0; + int i; + + if (gpudev->reset) + return gpudev->reset(device, fault); /* * Try soft reset first Do not do soft reset for a IOMMU fault (because - * the IOMMU hardware needs a reset too) or for the A304 because it - * can't do SMMU programming of any kind after a soft reset + * the IOMMU hardware needs a reset too) */ - if (!(fault & ADRENO_IOMMU_PAGE_FAULT) && !adreno_is_a304(adreno_dev) - && !adreno_is_a612(adreno_dev) && !adreno_is_a610(adreno_dev)) { - /* Make sure VBIF is cleared before resetting */ - ret = adreno_clear_pending_transactions(device); + if (!(fault & ADRENO_IOMMU_PAGE_FAULT)) + ret = adreno_soft_reset(device); - if (ret == 0) { - ret = adreno_soft_reset(device); - if (ret) - dev_err(device->dev, - "Device soft reset failed: ret=%d\n", - ret); - } - } if (ret) { /* If soft reset failed/skipped, then pull the power */ kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT); @@ -2346,22 +2338,18 @@ int adreno_reset(struct kgsl_device *device, int fault) /* Try to reset the device */ ret = adreno_start(device, 0); - /* On some GPUS, keep trying until it works */ - if (ret && ADRENO_GPUREV(adreno_dev) < 600) { - for (i = 0; i < NUM_TIMES_RESET_RETRY; i++) { - msleep(20); - ret = adreno_start(device, 0); - if (!ret) - break; - } + for (i = 0; ret && i < NUM_TIMES_RESET_RETRY; i++) { + msleep(20); + ret = adreno_start(device, 0); } - } - if (ret) - return ret; - if (i != 0) - dev_warn(device->dev, + if (ret) + return ret; + + if (i != 0) + dev_warn(device->dev, "Device hard reset tried %d tries\n", i); + } /* * If active_cnt is non-zero then the system was active before @@ -2811,23 +2799,32 @@ bool adreno_hw_isidle(struct adreno_device *adreno_dev) return true; } -/** - * adreno_soft_reset() - Do a soft reset of the GPU hardware +/* + * adreno_soft_reset - Do a soft reset of the GPU hardware * @device: KGSL device to soft reset * * "soft reset" the GPU hardware - this is a fast path GPU reset * The GPU hardware is reset but we never pull power so we can skip * a lot of the standard adreno_stop/adreno_start sequence */ -int adreno_soft_reset(struct kgsl_device *device) +static int adreno_soft_reset(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); int ret; - ret = gmu_core_dev_oob_set(device, oob_gpu); - if (ret) + /* + * Don't allow a soft reset for a304 because the SMMU needs to be hard + * reset + */ + if (adreno_is_a304(adreno_dev)) + return -ENODEV; + + ret = adreno_clear_pending_transactions(device); + if (ret) { + dev_err(device->dev, "Timed out while clearing the VBIF\n"); return ret; + } kgsl_pwrctrl_change_state(device, KGSL_STATE_AWARE); adreno_set_active_ctxs_null(adreno_dev); @@ -2841,15 +2838,7 @@ int adreno_soft_reset(struct kgsl_device *device) /* save physical performance counter values before GPU soft reset */ adreno_perfcounter_save(adreno_dev); - /* Reset the GPU */ - if (gpudev->soft_reset) - ret = gpudev->soft_reset(adreno_dev); - else - ret = _soft_reset(adreno_dev); - if (ret) { - gmu_core_dev_oob_clear(device, oob_gpu); - return ret; - } + _soft_reset(adreno_dev); /* Clear the busy_data stats - we're starting over from scratch */ adreno_dev->busy_data.gpu_busy = 0; @@ -2889,7 +2878,8 @@ int adreno_soft_reset(struct kgsl_device *device) /* Restore physical performance counter values after soft reset */ adreno_perfcounter_restore(adreno_dev); - gmu_core_dev_oob_clear(device, oob_gpu); + if (ret) + dev_err(device->dev, "Device soft reset failed: %d\n", ret); return ret; } diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 3384128e3937..e81d9087b987 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -643,8 +643,6 @@ enum adreno_regs { ADRENO_REG_RBBM_INT_0_STATUS, ADRENO_REG_RBBM_PM_OVERRIDE2, ADRENO_REG_RBBM_SW_RESET_CMD, - ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD, - ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD2, ADRENO_REG_RBBM_CLOCK_CTL, ADRENO_REG_PA_SC_AA_CONFIG, ADRENO_REG_SQ_GPR_MANAGEMENT, @@ -789,7 +787,6 @@ struct adreno_gpudev { const char *(*iommu_fault_block)(struct kgsl_device *device, unsigned int fsynr1); int (*reset)(struct kgsl_device *device, int fault); - int (*soft_reset)(struct adreno_device *adreno_dev); bool (*sptprac_is_on)(struct adreno_device *adreno_dev); unsigned int (*ccu_invalidate)(struct adreno_device *adreno_dev, unsigned int *cmds); @@ -871,7 +868,6 @@ extern int adreno_wake_nice; extern unsigned int adreno_wake_timeout; int adreno_start(struct kgsl_device *device, int priority); -int adreno_soft_reset(struct kgsl_device *device); long adreno_ioctl(struct kgsl_device_private *dev_priv, unsigned int cmd, unsigned long arg); diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 661c3445ba6c..4a8d6efed37c 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -2378,10 +2378,6 @@ static unsigned int a5xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A5XX_RBBM_INT_0_STATUS), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_CLOCK_CTL, A5XX_RBBM_CLOCK_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_SW_RESET_CMD, A5XX_RBBM_SW_RESET_CMD), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD, - A5XX_RBBM_BLOCK_SW_RESET_CMD), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD2, - A5XX_RBBM_BLOCK_SW_RESET_CMD2), ADRENO_REG_DEFINE(ADRENO_REG_UCHE_INVALIDATE0, A5XX_UCHE_INVALIDATE0), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_RBBM_0_LO, A5XX_RBBM_PERFCTR_RBBM_0_LO), diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 55545558b6c0..0e639aaa7a85 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -1011,30 +1011,6 @@ static int a6xx_microcode_read(struct adreno_device *adreno_dev) return adreno_get_firmware(adreno_dev, a6xx_core->sqefw_name, sqe_fw); } -static int a6xx_soft_reset(struct adreno_device *adreno_dev) -{ - struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - unsigned int reg; - - if (gmu_core_isenabled(device)) - return 0; - - adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SW_RESET_CMD, 1); - /* - * Do a dummy read to get a brief read cycle delay for the - * reset to take effect - */ - adreno_readreg(adreno_dev, ADRENO_REG_RBBM_SW_RESET_CMD, ®); - adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SW_RESET_CMD, 0); - - /* Clear GBIF client halt and CX arbiter halt */ - adreno_deassert_gbif_halt(adreno_dev); - - a6xx_sptprac_enable(adreno_dev); - - return 0; -} - static int64_t a6xx_read_throttling_counters(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -1098,12 +1074,14 @@ static int a6xx_reset(struct kgsl_device *device, int fault) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int ret; - /* Use the regular reset sequence for No GMU */ - if (!gmu_core_isenabled(device)) - return adreno_reset(device, fault); - - /* Transition from ACTIVE to RESET state */ - kgsl_pwrctrl_change_state(device, KGSL_STATE_RESET); + /* + * GMU devices transition to KGSL_STATE_RESET, non GMU devices go + * directly to KGSL_STATE_INIT + */ + if (gmu_core_isenabled(device)) + kgsl_pwrctrl_change_state(device, KGSL_STATE_RESET); + else + kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT); /* since device is officially off now clear start bit */ clear_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv); @@ -2407,11 +2385,6 @@ static unsigned int a6xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A6XX_RBBM_INT_0_STATUS), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_CLOCK_CTL, A6XX_RBBM_CLOCK_CNTL), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_SW_RESET_CMD, A6XX_RBBM_SW_RESET_CMD), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD, - A6XX_RBBM_BLOCK_SW_RESET_CMD), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD2, - A6XX_RBBM_BLOCK_SW_RESET_CMD2), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO, A6XX_RBBM_PERFCTR_LOAD_VALUE_LO), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI, @@ -2615,7 +2588,6 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .hw_isidle = a6xx_hw_isidle, /* Replaced by NULL if GMU is disabled */ .iommu_fault_block = a6xx_iommu_fault_block, .reset = a6xx_reset, - .soft_reset = a6xx_soft_reset, .preemption_pre_ibsubmit = a6xx_preemption_pre_ibsubmit, .preemption_post_ibsubmit = a6xx_preemption_post_ibsubmit, .preemption_init = a6xx_preemption_init, diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index a8f3e0592cf1..55f2a54355c7 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -2197,10 +2197,7 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev) kgsl_process_event_group(device, &hung_rb->events); } - if (gpudev->reset) - ret = gpudev->reset(device, fault); - else - ret = adreno_reset(device, fault); + ret = adreno_reset(device, fault); mutex_unlock(&device->mutex); /* if any other fault got in until reset then ignore */ From 05fb67866218fcafca2f8f751eb524c8f7c06306 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:12 -0600 Subject: [PATCH 2/5] msm: kgsl: Move hw_isidle to target specific code Currently, there is a custom hw_isidle function defined for a6xx but the function pointer is removed in a6xx_start for non GMU/RGMU a6xx targets which has the effect of falling back to the generic adreno_hw_isidle function which confused at least two of us before we figured out what was happening. Instead of having a generic adreno_hw_isidle function except for a6xx, add a hw_isidle function hook for all targets and do the GMU check in the a6xx specific function. This also has the advantage of moving a a540 specific hack into the a5xx code and removes one of two usages of the gpucore specific busy mask and the other is in soft fault detect. Arguably we should get rid that too but for now we can just hardcode the mask in there and remove the busy mask from the gpucore struct. And finally it looks like adreno_isidle isn't used as a function hook, so remove it from the device function tables and mark it static. Change-Id: Ic0dedbad47fa5dee0e5d903a8f9dd9bf7230b759 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno-gpulist.h | 23 ----------- drivers/gpu/msm/adreno.c | 69 +++++-------------------------- drivers/gpu/msm/adreno.h | 12 +++--- drivers/gpu/msm/adreno_a3xx.c | 14 +++++++ drivers/gpu/msm/adreno_a5xx.c | 21 ++++++++++ drivers/gpu/msm/adreno_a6xx.c | 27 ++++++------ drivers/gpu/msm/adreno_dispatch.c | 9 +++- drivers/gpu/msm/kgsl_device.h | 1 - 8 files changed, 75 insertions(+), 101 deletions(-) diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index 606837dd690a..544f80d98f8f 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -28,7 +28,6 @@ static const struct adreno_a3xx_core adreno_gpu_core_a306 = { .gpudev = &adreno_a3xx_gpudev, .gmem_base = 0, .gmem_size = SZ_128K, - .busy_mask = 0x7ffffffe, .bus_width = 0, .snapshot_size = 600 * SZ_1K, }, @@ -51,7 +50,6 @@ static const struct adreno_a3xx_core adreno_gpu_core_a306a = { .gpudev = &adreno_a3xx_gpudev, .gmem_base = 0, .gmem_size = SZ_128K, - .busy_mask = 0x7ffffffe, .bus_width = 16, .snapshot_size = 600 * SZ_1K, }, @@ -72,7 +70,6 @@ static const struct adreno_a3xx_core adreno_gpu_core_a304 = { .gpudev = &adreno_a3xx_gpudev, .gmem_base = 0, .gmem_size = (SZ_64K + SZ_32K), - .busy_mask = 0x7ffffffe, .bus_width = 0, .snapshot_size = 600 * SZ_1K, }, @@ -197,7 +194,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a530v2 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -224,7 +220,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a530v3 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -291,7 +286,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a505 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_8K), - .busy_mask = 0xfffffffe, .bus_width = 16, .snapshot_size = SZ_1M, }, @@ -311,7 +305,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a506 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_8K), - .busy_mask = 0xfffffffe, .bus_width = 16, .snapshot_size = SZ_1M, }, @@ -390,7 +383,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a510 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_256K, - .busy_mask = 0xfffffffe, .bus_width = 16, .snapshot_size = SZ_1M, }, @@ -516,7 +508,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a540v2 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -600,7 +591,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a512 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_256K + SZ_16K), - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -620,7 +610,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a508 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_8K), - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -796,7 +785,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a630v2 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -897,7 +885,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a615 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 600 * SZ_1K, }, @@ -926,7 +913,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a618 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -1056,7 +1042,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a620 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0, .gmem_size = SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 2 * SZ_1M, }, @@ -1148,7 +1133,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a640 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, //Verified 1MB - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 2 * SZ_1M, }, @@ -1230,7 +1214,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a650 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0, .gmem_size = SZ_1M + SZ_128K, /* verified 1152kB */ - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 2 * SZ_1M, }, @@ -1261,7 +1244,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a650v2 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0, .gmem_size = SZ_1M + SZ_128K, /* verified 1152kB */ - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 2 * SZ_1M, }, @@ -1289,7 +1271,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a680 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_2M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -1368,7 +1349,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a612 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_4K), - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -1395,7 +1375,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a616 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -1423,7 +1402,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a610 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_4K), - .busy_mask = 0xfffffffe, .bus_width = 32, }, .prim_fifo_threshold = 0x00080000, @@ -1537,7 +1515,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a660 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0, .gmem_size = SZ_1M + SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 3e5d2226b17e..06c9b3b65fcd 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2740,7 +2740,7 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv, * * Returns true if interrupts are pending from device else 0. */ -inline unsigned int adreno_irq_pending(struct adreno_device *adreno_dev) +bool adreno_irq_pending(struct adreno_device *adreno_dev) { unsigned int status; @@ -2755,48 +2755,9 @@ inline unsigned int adreno_irq_pending(struct adreno_device *adreno_dev) */ if ((status & adreno_dev->irq_mask) || atomic_read(&adreno_dev->pending_irq_refcnt)) - return 1; - else - return 0; -} + return true; - -/** - * adreno_hw_isidle() - Check if the GPU core is idle - * @adreno_dev: Pointer to the Adreno device structure for the GPU - * - * Return true if the RBBM status register for the GPU type indicates that the - * hardware is idle - */ -bool adreno_hw_isidle(struct adreno_device *adreno_dev) -{ - const struct adreno_gpu_core *gpucore = adreno_dev->gpucore; - unsigned int reg_rbbm_status; - struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); - - /* if hw driver implements idle check - use it */ - if (gpudev->hw_isidle) - return gpudev->hw_isidle(adreno_dev); - - if (adreno_is_a540(adreno_dev)) - /** - * Due to CRC idle throttling GPU - * idle hysteresys can take up to - * 3usec for expire - account for it - */ - udelay(5); - - adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, - ®_rbbm_status); - - if (reg_rbbm_status & gpucore->busy_mask) - return false; - - /* Don't consider ourselves idle if there is an IRQ pending */ - if (adreno_irq_pending(adreno_dev)) - return false; - - return true; + return false; } /* @@ -2884,20 +2845,13 @@ static int adreno_soft_reset(struct kgsl_device *device) return ret; } -/* - * adreno_isidle() - return true if the GPU hardware is idle - * @device: Pointer to the KGSL device structure for the GPU - * - * Return true if the GPU hardware is idle and there are no commands pending in - * the ringbuffer - */ -bool adreno_isidle(struct kgsl_device *device) +static bool adreno_isidle(struct adreno_device *adreno_dev) { - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct adreno_ringbuffer *rb; int i; - if (!kgsl_state_is_awake(device)) + if (!kgsl_state_is_awake(KGSL_DEVICE(adreno_dev))) return true; /* @@ -2916,7 +2870,7 @@ bool adreno_isidle(struct kgsl_device *device) return false; } - return adreno_hw_isidle(adreno_dev); + return gpudev->hw_isidle(adreno_dev); } /* Print some key registers if a spin-for-idle times out */ @@ -2977,7 +2931,7 @@ int adreno_spin_idle(struct adreno_device *adreno_dev, unsigned int timeout) if (adreno_gpu_fault(adreno_dev) != 0) return -EDEADLK; - if (adreno_isidle(KGSL_DEVICE(adreno_dev))) + if (adreno_isidle(adreno_dev)) return 0; } while (time_before(jiffies, wait)); @@ -2990,7 +2944,7 @@ int adreno_spin_idle(struct adreno_device *adreno_dev, unsigned int timeout) if (adreno_gpu_fault(adreno_dev) != 0) return -EDEADLK; - if (adreno_isidle(KGSL_DEVICE(adreno_dev))) + if (adreno_isidle(adreno_dev)) return 0; return -ETIMEDOUT; @@ -3018,7 +2972,7 @@ int adreno_idle(struct kgsl_device *device) return -EDEADLK; /* Check if we are already idle before idling dispatcher */ - if (adreno_isidle(device)) + if (adreno_isidle(adreno_dev)) return 0; /* * Wait for dispatcher to finish completing commands @@ -3715,7 +3669,7 @@ static bool adreno_is_hw_collapsible(struct kgsl_device *device) device->pwrctrl.ctrl_flags) return false; - return adreno_isidle(device) && (gpudev->is_sptp_idle ? + return adreno_isidle(adreno_dev) && (gpudev->is_sptp_idle ? gpudev->is_sptp_idle(adreno_dev) : true); } @@ -3801,7 +3755,6 @@ static const struct kgsl_functable adreno_functable = { .regread = adreno_regread, .regwrite = adreno_regwrite, .idle = adreno_idle, - .isidle = adreno_isidle, .suspend_context = adreno_suspend_context, .first_open = adreno_first_open, .start = adreno_start, diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index e81d9087b987..9f442a513376 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -340,7 +340,6 @@ struct adreno_reglist { * @gpudev: Pointer to the GPU family specific functions for this core * @gmem_base: Base address of binning memory (GMEM/OCMEM) * @gmem_size: Amount of binning memory (GMEM/OCMEM) to reserve for the core - * @busy_mask: mask to check if GPU is busy in RBBM_STATUS * @bus_width: Bytes transferred in 1 cycle */ struct adreno_gpu_core { @@ -350,7 +349,6 @@ struct adreno_gpu_core { struct adreno_gpudev *gpudev; unsigned long gmem_base; size_t gmem_size; - unsigned int busy_mask; u32 bus_width; /** @snapshot_size: Size of the static snapshot region in bytes */ u32 snapshot_size; @@ -889,7 +887,6 @@ int adreno_switch_to_unsecure_mode(struct adreno_device *adreno_dev, void adreno_spin_idle_debug(struct adreno_device *adreno_dev, const char *str); int adreno_spin_idle(struct adreno_device *device, unsigned int timeout); int adreno_idle(struct kgsl_device *device); -bool adreno_isidle(struct kgsl_device *device); int adreno_set_constraint(struct kgsl_device *device, struct kgsl_context *context, @@ -905,8 +902,6 @@ void adreno_fault_skipcmd_detached(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj); -bool adreno_hw_isidle(struct adreno_device *adreno_dev); - void adreno_fault_detect_start(struct adreno_device *adreno_dev); void adreno_fault_detect_stop(struct adreno_device *adreno_dev); @@ -946,6 +941,13 @@ void adreno_rscc_regread(struct adreno_device *adreno_dev, void adreno_isense_regread(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int *value); +/** + * adreno_irq_pending - Return true if an interrupt is pending + * @adreno_dev: An Adreno GPU device handle + * + * Returns: true if interrupts are pending on the device + */ +bool adreno_irq_pending(struct adreno_device *adreno_dev); #define ADRENO_TARGET(_name, _id) \ static inline int adreno_is_##_name(struct adreno_device *adreno_dev) \ diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 150af9a93ff5..a36d2b74e598 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -1381,6 +1381,19 @@ static irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev) return ret; } +static bool a3xx_hw_isidle(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + u32 status; + + kgsl_regread(device, A3XX_RBBM_STATUS, &status); + + if (status & 0x7ffffffe) + return false; + + return adreno_irq_pending(adreno_dev) ? false : true; +} + struct adreno_gpudev adreno_a3xx_gpudev = { .reg_offsets = a3xx_register_offsets, .ft_perf_counters = a3xx_ft_perf_counters, @@ -1399,4 +1412,5 @@ struct adreno_gpudev adreno_a3xx_gpudev = { #endif .clk_set_options = a3xx_clk_set_options, .read_alwayson = a3xx_read_alwayson, + .hw_isidle = a3xx_hw_isidle, }; diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 4a8d6efed37c..c2d7a68f77a9 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -2752,6 +2752,26 @@ static irqreturn_t a5xx_irq_handler(struct adreno_device *adreno_dev) return ret; } +static bool a5xx_hw_isidle(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + u32 status; + + /* + * Due to CRC idle throttling the GPU idle hysteresis on a540 can take + * up to 5uS to expire + */ + if (adreno_is_a540(adreno_dev)) + udelay(5); + + kgsl_regread(device, A5XX_RBBM_STATUS, &status); + + if (status & 0xfffffffe) + return false; + + return adreno_irq_pending(adreno_dev) ? false : true; +} + #ifdef CONFIG_QCOM_KGSL_CORESIGHT static struct adreno_coresight_register a5xx_coresight_registers[] = { { A5XX_RBBM_CFG_DBGBUS_SEL_A }, @@ -2978,4 +2998,5 @@ struct adreno_gpudev adreno_a5xx_gpudev = { .preemption_schedule = a5xx_preemption_schedule, .clk_set_options = a5xx_clk_set_options, .read_alwayson = a5xx_read_alwayson, + .hw_isidle = a5xx_hw_isidle, }; diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 0e639aaa7a85..9135f78ba679 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -405,10 +405,6 @@ static void a6xx_start(struct adreno_device *adreno_dev) adreno_dev->irq_mask = A6XX_INT_MASK; - /* runtime adjust callbacks based on feature sets */ - if (!gmu_core_isenabled(device)) - /* Legacy idle management if gmu is disabled */ - ADRENO_GPU_DEVICE(adreno_dev)->hw_isidle = NULL; /* enable hardware clockgating */ a6xx_hwcg_set(adreno_dev, true); @@ -986,17 +982,24 @@ static void a6xx_gpu_keepalive(struct adreno_device *adreno_dev, ADRENO_REG_GMU_PWR_COL_KEEPALIVE, state); } -/* Bitmask for GPU idle status check */ -#define GPUBUSYIGNAHB BIT(23) static bool a6xx_hw_isidle(struct adreno_device *adreno_dev) { + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); unsigned int reg; - gmu_core_regread(KGSL_DEVICE(adreno_dev), - A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, ®); - if (reg & GPUBUSYIGNAHB) - return false; - return true; + /* Non GMU devices monitor the RBBM status */ + if (!gmu_core_isenabled(device)) { + kgsl_regread(device, A6XX_RBBM_STATUS, ®); + if (reg & 0xfffffffe) + return false; + + return adreno_irq_pending(adreno_dev) ? false : true; + } + + gmu_core_regread(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, ®); + + /* Bit 23 is GPUBUSYIGNAHB */ + return (reg & BIT(23)) ? false : true; } /* @@ -2585,7 +2588,7 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .read_throttling_counters = a6xx_read_throttling_counters, .microcode_read = a6xx_microcode_read, .gpu_keepalive = a6xx_gpu_keepalive, - .hw_isidle = a6xx_hw_isidle, /* Replaced by NULL if GMU is disabled */ + .hw_isidle = a6xx_hw_isidle, .iommu_fault_block = a6xx_iommu_fault_block, .reset = a6xx_reset, .preemption_pre_ibsubmit = a6xx_preemption_pre_ibsubmit, diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 55f2a54355c7..cf5176404627 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -175,8 +175,8 @@ static void fault_detect_read(struct adreno_device *adreno_dev) */ static inline bool _isidle(struct adreno_device *adreno_dev) { - const struct adreno_gpu_core *gpucore = adreno_dev->gpucore; unsigned int reg_rbbm_status; + u32 mask; if (!kgsl_state_is_awake(KGSL_DEVICE(adreno_dev))) goto ret; @@ -187,7 +187,12 @@ static inline bool _isidle(struct adreno_device *adreno_dev) /* only check rbbm status to determine if GPU is idle */ adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, ®_rbbm_status); - if (reg_rbbm_status & gpucore->busy_mask) + if (adreno_is_a3xx(adreno_dev)) + mask = 0x7ffffffe; + else + mask = 0xfffffffe; + + if (reg_rbbm_status & mask) return false; ret: diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 5d6c25383fb1..9e45d8455f58 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -97,7 +97,6 @@ struct kgsl_functable { void (*regwrite)(struct kgsl_device *device, unsigned int offsetwords, unsigned int value); int (*idle)(struct kgsl_device *device); - bool (*isidle)(struct kgsl_device *device); int (*suspend_context)(struct kgsl_device *device); int (*first_open)(struct kgsl_device *device); int (*last_close)(struct kgsl_device *device); From 76f54bf67ff03df0410cd2398faf69c2c60a4664 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Tue, 5 Nov 2019 16:39:15 -0700 Subject: [PATCH 3/5] msm: kgsl: Fixup the RGMU probe Fix the RGMU probe to use standard helper functions and do proper reference counting. Change-Id: Ic0dedbadf5af14338de83cd9041674cc6f1ea304 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl_rgmu.c | 149 +++++++++++++----------------------- drivers/gpu/msm/kgsl_rgmu.h | 11 +-- 2 files changed, 57 insertions(+), 103 deletions(-) diff --git a/drivers/gpu/msm/kgsl_rgmu.c b/drivers/gpu/msm/kgsl_rgmu.c index 008589ddae3f..dcd4f679769c 100644 --- a/drivers/gpu/msm/kgsl_rgmu.c +++ b/drivers/gpu/msm/kgsl_rgmu.c @@ -23,88 +23,65 @@ static int rgmu_irq_probe(struct kgsl_device *device) struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device); int ret; - rgmu->oob_interrupt_num = platform_get_irq_byname(rgmu->pdev, - "kgsl_oob"); - - ret = devm_request_irq(&rgmu->pdev->dev, - rgmu->oob_interrupt_num, - oob_irq_handler, IRQF_TRIGGER_HIGH, - "kgsl-oob", device); - if (ret) { - dev_err(&rgmu->pdev->dev, - "Request kgsl-oob interrupt failed:%d\n", ret); + ret = kgsl_request_irq(rgmu->pdev, "kgsl_oob", oob_irq_handler, device); + if (ret < 0) return ret; - } - rgmu->rgmu_interrupt_num = platform_get_irq_byname(rgmu->pdev, - "kgsl_rgmu"); + rgmu->oob_interrupt_num = ret; - ret = devm_request_irq(&rgmu->pdev->dev, - rgmu->rgmu_interrupt_num, - rgmu_irq_handler, IRQF_TRIGGER_HIGH, - "kgsl-rgmu", device); - if (ret) - dev_err(&rgmu->pdev->dev, - "Request kgsl-rgmu interrupt failed:%d\n", ret); + ret = kgsl_request_irq(rgmu->pdev, + "kgsl_rgmu", rgmu_irq_handler, device); + if (ret < 0) + return ret; - return ret; + rgmu->rgmu_interrupt_num = ret; + return 0; } -static int rgmu_regulators_probe(struct rgmu_device *rgmu, - struct device_node *node) +static int rgmu_regulators_probe(struct rgmu_device *rgmu) { - int ret; + int ret = 0; rgmu->cx_gdsc = devm_regulator_get(&rgmu->pdev->dev, "vddcx"); - if (IS_ERR_OR_NULL(rgmu->cx_gdsc)) { + if (IS_ERR(rgmu->cx_gdsc)) { ret = PTR_ERR(rgmu->cx_gdsc); - dev_err(&rgmu->pdev->dev, + if (ret != -EPROBE_DEFER) + dev_err(&rgmu->pdev->dev, "Couldn't get CX gdsc error:%d\n", ret); - rgmu->cx_gdsc = NULL; return ret; } rgmu->gx_gdsc = devm_regulator_get(&rgmu->pdev->dev, "vdd"); - if (IS_ERR_OR_NULL(rgmu->gx_gdsc)) { + if (IS_ERR(rgmu->gx_gdsc)) { ret = PTR_ERR(rgmu->gx_gdsc); - dev_err(&rgmu->pdev->dev, + if (ret != -EPROBE_DEFER) + dev_err(&rgmu->pdev->dev, "Couldn't get GX gdsc error:%d\n", ret); - rgmu->gx_gdsc = NULL; - return ret; } - return 0; + return ret; } static int rgmu_clocks_probe(struct rgmu_device *rgmu, struct device_node *node) { - const char *cname; - struct property *prop; - struct clk *c; - int i = 0; + int ret; - of_property_for_each_string(node, "clock-names", prop, cname) { + ret = devm_clk_bulk_get_all(&rgmu->pdev->dev, &rgmu->clks); + if (ret < 0) + return ret; - if (i >= ARRAY_SIZE(rgmu->clks)) { - dev_err(&rgmu->pdev->dev, - "dt: too many RGMU clocks defined\n"); - return -EINVAL; - } + rgmu->num_clks = ret; - c = devm_clk_get(&rgmu->pdev->dev, cname); - if (IS_ERR_OR_NULL(c)) { - dev_err(&rgmu->pdev->dev, - "dt: Couldn't get clock: %s\n", cname); - return PTR_ERR(c); - } + rgmu->gpu_clk = kgsl_of_clk_by_name(rgmu->clks, ret, "core"); + if (!rgmu->gpu_clk) { + dev_err(&rgmu->pdev->dev, "The GPU clock isn't defined\n"); + return -ENODEV; + } - /* Remember the key clocks that we need to control later */ - if (!strcmp(cname, "core")) - rgmu->gpu_clk = c; - else if (!strcmp(cname, "gmu")) - rgmu->rgmu_clk = c; - - rgmu->clks[i++] = c; + rgmu->rgmu_clk = kgsl_of_clk_by_name(rgmu->clks, ret, "gmu"); + if (!rgmu->rgmu_clk) { + dev_err(&rgmu->pdev->dev, "The RGMU clock isn't defined\n"); + return -ENODEV; } return 0; @@ -114,7 +91,7 @@ static void rgmu_disable_clks(struct kgsl_device *device) { struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device); struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); - int j = 0, ret; + int ret; /* Check GX GDSC is status */ if (gmu_dev_ops->gx_is_on(device)) { @@ -141,22 +118,17 @@ static void rgmu_disable_clks(struct kgsl_device *device) dev_err(&rgmu->pdev->dev, "gx is stuck on\n"); } - for (j = 0; j < ARRAY_SIZE(rgmu->clks); j++) - clk_disable_unprepare(rgmu->clks[j]); + clk_bulk_disable_unprepare(rgmu->num_clks, rgmu->clks); clear_bit(GMU_CLK_ON, &device->gmu_core.flags); } static int rgmu_enable_clks(struct kgsl_device *device) { - int ret, j = 0; + int ret; struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device); struct kgsl_pwrctrl *pwr = &device->pwrctrl; - if (IS_ERR_OR_NULL(rgmu->rgmu_clk) || - IS_ERR_OR_NULL(rgmu->gpu_clk)) - return -EINVAL; - ret = clk_set_rate(rgmu->rgmu_clk, RGMU_CLK_FREQ); if (ret) { dev_err(&rgmu->pdev->dev, "Couldn't set the RGMU clock\n"); @@ -170,14 +142,10 @@ static int rgmu_enable_clks(struct kgsl_device *device) return ret; } - for (j = 0; j < ARRAY_SIZE(rgmu->clks); j++) { - ret = clk_prepare_enable(rgmu->clks[j]); - if (ret) { - dev_err(&rgmu->pdev->dev, - "Fail(%d) to enable gpucc clk idx %d\n", - ret, j); - return ret; - } + ret = clk_bulk_prepare_enable(rgmu->num_clks, rgmu->clks); + if (ret) { + dev_err(&rgmu->pdev->dev, "Failed to enable RGMU clocks\n"); + return ret; } set_bit(GMU_CLK_ON, &device->gmu_core.flags); @@ -289,42 +257,31 @@ static int rgmu_probe(struct kgsl_device *device, struct platform_device *pdev) rgmu->pdev = pdev; /* Set up RGMU regulators */ - ret = rgmu_regulators_probe(rgmu, pdev->dev.of_node); + ret = rgmu_regulators_probe(rgmu); if (ret) return ret; + /* Set up RGMU clocks */ ret = rgmu_clocks_probe(rgmu, pdev->dev.of_node); if (ret) return ret; /* Map and reserve RGMU CSRs registers */ - res = platform_get_resource_byname(rgmu->pdev, - IORESOURCE_MEM, "kgsl_rgmu"); - if (res == NULL) { - dev_err(&rgmu->pdev->dev, - "platform_get_resource failed\n"); - return -EINVAL; - } - - if (res->start == 0 || resource_size(res) == 0) { - dev_err(&rgmu->pdev->dev, - "Register region is invalid\n"); - return -EINVAL; - } - - rgmu->reg_phys = res->start; - rgmu->reg_len = resource_size(res); - device->gmu_core.reg_virt = devm_ioremap(&rgmu->pdev->dev, res->start, - resource_size(res)); - - if (device->gmu_core.reg_virt == NULL) { - dev_err(&rgmu->pdev->dev, "Unable to remap rgmu registers\n"); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "kgsl_rgmu"); + if (!res) { + dev_err(&pdev->dev, "The RGMU register region isn't defined\n"); return -ENODEV; } - device->gmu_core.gmu2gpu_offset = - (rgmu->reg_phys - device->reg_phys) >> 2; - device->gmu_core.reg_len = rgmu->reg_len; + device->gmu_core.gmu2gpu_offset = (res->start - device->reg_phys) >> 2; + device->gmu_core.reg_len = resource_size(res); + device->gmu_core.reg_virt = devm_ioremap_resource(&pdev->dev, res); + + if (IS_ERR(device->gmu_core.reg_virt)) { + dev_err(&pdev->dev, "Unable to map the RGMU registers\n"); + return PTR_ERR(device->gmu_core.reg_virt); + } + device->gmu_core.ptr = (void *)rgmu; /* Initialize OOB and RGMU interrupts */ diff --git a/drivers/gpu/msm/kgsl_rgmu.h b/drivers/gpu/msm/kgsl_rgmu.h index 4b8f7f45955e..112f6e52c6ef 100644 --- a/drivers/gpu/msm/kgsl_rgmu.h +++ b/drivers/gpu/msm/kgsl_rgmu.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef __KGSL_RGMU_H #define __KGSL_RGMU_H @@ -18,9 +18,6 @@ /** * struct rgmu_device - rGMU device structure * @ver: RGMU firmware version - * @reg_phys: RGMU CSR physical address - * @reg_virt: RGMU CSR virtual address - * @reg_len: RGMU CSR range * @rgmu_interrupt_num: RGMU interrupt number * @oob_interrupt_num: number of RGMU asserted OOB interrupt * @fw_hostptr: Buffer which holds the RGMU firmware @@ -37,15 +34,15 @@ struct rgmu_device { u32 ver; struct platform_device *pdev; - unsigned long reg_phys; - unsigned int reg_len; unsigned int rgmu_interrupt_num; unsigned int oob_interrupt_num; unsigned int *fw_hostptr; uint32_t fw_size; struct regulator *cx_gdsc; struct regulator *gx_gdsc; - struct clk *clks[MAX_RGMU_CLKS]; + struct clk_bulk_data *clks; + /** @num_clks: Number of clocks in @clks */ + int num_clks; struct clk *gpu_clk; struct clk *rgmu_clk; unsigned int idle_level; From 8152ccc95e3679915564923f75cd413a1310d756 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 7 Nov 2019 10:08:38 -0700 Subject: [PATCH 4/5] msm: kgsl: Fixup the GMU probe Clean up the GMU probe to use standard functions and proper reference to make it more defer tolerant. Change-Id: Ic0dedbad7c561e24c07053ea3b19ef62e34621cb Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl_gmu.c | 206 +++++++++++++++---------------------- drivers/gpu/msm/kgsl_gmu.h | 4 - 2 files changed, 82 insertions(+), 128 deletions(-) diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index f7b28d9a70a3..848f49682276 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -25,7 +25,7 @@ struct gmu_iommu_context { const char *name; - struct device *dev; + struct platform_device *pdev; struct iommu_domain *domain; }; @@ -277,48 +277,57 @@ static struct gmu_memdesc *allocate_gmu_kmem(struct gmu_device *gmu, } static int gmu_iommu_cb_probe(struct gmu_device *gmu, - struct gmu_iommu_context *ctx, - struct device_node *node) + const char *name, struct gmu_iommu_context *ctx, + struct device_node *parent, iommu_fault_handler_t handler) { - struct platform_device *pdev = of_find_device_by_node(node); - struct device *dev; + struct device_node *node = of_get_child_by_name(parent, name); + struct platform_device *pdev; int ret; - dev = &pdev->dev; - of_dma_configure(dev, node, true); + if (!node) + return -ENODEV; - ctx->dev = dev; + pdev = of_find_device_by_node(node); + of_dma_configure(&pdev->dev, node, true); + + of_node_put(node); + + ctx->pdev = pdev; ctx->domain = iommu_domain_alloc(&platform_bus_type); if (ctx->domain == NULL) { dev_err(&gmu->pdev->dev, "gmu iommu fail to alloc %s domain\n", ctx->name); + platform_device_put(pdev); return -ENODEV; } - ret = iommu_attach_device(ctx->domain, dev); - if (ret) { - dev_err(&gmu->pdev->dev, "gmu iommu fail to attach %s device\n", - ctx->name); - iommu_domain_free(ctx->domain); + ret = iommu_attach_device(ctx->domain, &pdev->dev); + if (!ret) { + iommu_set_fault_handler(ctx->domain, handler, ctx); + return 0; } + dev_err(&gmu->pdev->dev, + "gmu iommu fail to attach %s device\n", ctx->name); + iommu_domain_free(ctx->domain); + ctx->domain = NULL; + platform_device_put(pdev); + return ret; } -static struct { - const char *compatible; - int index; - iommu_fault_handler_t hdlr; -} cbs[] = { - { "qcom,smmu-gmu-user-cb", - GMU_CONTEXT_USER, - gmu_user_fault_handler, - }, - { "qcom,smmu-gmu-kernel-cb", - GMU_CONTEXT_KERNEL, - gmu_kernel_fault_handler, - }, -}; + +static void gmu_iommu_cb_close(struct gmu_iommu_context *ctx) +{ + if (!ctx->domain) + return; + + iommu_detach_device(ctx->domain, &ctx->pdev->dev); + iommu_domain_free(ctx->domain); + + platform_device_put(ctx->pdev); + memset(ctx, 0, sizeof(*ctx)); +} /* * gmu_iommu_init() - probe IOMMU context banks used by GMU @@ -328,34 +337,17 @@ static struct { */ static int gmu_iommu_init(struct gmu_device *gmu, struct device_node *node) { - struct device_node *child; - struct gmu_iommu_context *ctx = NULL; - int ret, i; + int ret; - of_platform_populate(node, NULL, NULL, &gmu->pdev->dev); + devm_of_platform_populate(&gmu->pdev->dev); - for (i = 0; i < ARRAY_SIZE(cbs); i++) { - child = of_find_compatible_node(node, NULL, cbs[i].compatible); - if (child) { - ctx = &gmu_ctx[cbs[i].index]; - ret = gmu_iommu_cb_probe(gmu, ctx, child); - if (ret) - return ret; - iommu_set_fault_handler(ctx->domain, - cbs[i].hdlr, ctx); - } - } + ret = gmu_iommu_cb_probe(gmu, "gmu_user", + &gmu_ctx[GMU_CONTEXT_USER], node, gmu_user_fault_handler); + if (ret) + return ret; - for (i = 0; i < ARRAY_SIZE(gmu_ctx); i++) { - if (gmu_ctx[i].domain == NULL) { - dev_err(&gmu->pdev->dev, - "Missing GMU %s context bank node\n", - gmu_ctx[i].name); - return -EINVAL; - } - } - - return 0; + return gmu_iommu_cb_probe(gmu, "gmu_kernel", + &gmu_ctx[GMU_CONTEXT_KERNEL], node, gmu_kernel_fault_handler); } /* @@ -394,14 +386,8 @@ static void gmu_memory_close(struct gmu_device *gmu) clear_bit(i, &gmu->kmem_bitmap); } - for (i = 0; i < ARRAY_SIZE(gmu_ctx); i++) { - ctx = &gmu_ctx[i]; - - if (ctx->domain) { - iommu_detach_device(ctx->domain, ctx->dev); - iommu_domain_free(ctx->domain); - } - } + gmu_iommu_cb_close(&gmu_ctx[GMU_CONTEXT_USER]); + gmu_iommu_cb_close(&gmu_ctx[GMU_CONTEXT_KERNEL]); } static enum gmu_mem_type gmu_get_blk_memtype(struct gmu_device *gmu, @@ -1061,60 +1047,44 @@ static int gmu_reg_probe(struct kgsl_device *device) res = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_reg"); - if (res == NULL) { - dev_err(&gmu->pdev->dev, - "platform_get_resource kgsl_gmu_reg failed\n"); - return -EINVAL; - } - - if (res->start == 0 || resource_size(res) == 0) { - dev_err(&gmu->pdev->dev, - "dev %d kgsl_gmu_reg invalid register region\n", - gmu->pdev->dev.id); - return -EINVAL; - } - - gmu->reg_phys = res->start; - gmu->reg_len = resource_size(res); - device->gmu_core.reg_virt = devm_ioremap(&gmu->pdev->dev, - res->start, resource_size(res)); - if (device->gmu_core.reg_virt == NULL) { - dev_err(&gmu->pdev->dev, "kgsl_gmu_reg ioremap failed\n"); + if (!res) { + dev_err(&gmu->pdev->dev, "The GMU register region isn't defined\n"); return -ENODEV; } + device->gmu_core.gmu2gpu_offset = (res->start - device->reg_phys) >> 2; + device->gmu_core.reg_len = resource_size(res); + + /* + * We can't use devm_ioremap_resource here because we purposely double + * map the gpu_cc registers for debugging purposes + */ + device->gmu_core.reg_virt = devm_ioremap(&gmu->pdev->dev, res->start, + resource_size(res)); + + if (!device->gmu_core.reg_virt) { + dev_err(&gmu->pdev->dev, "Unable to map the GMU registers\n"); + return -ENOMEM; + } + return 0; } static int gmu_regulators_probe(struct gmu_device *gmu, - struct device_node *node) + struct platform_device *pdev) { - const char *name; - struct property *prop; - struct device *dev = &gmu->pdev->dev; - int ret = 0; + gmu->cx_gdsc = devm_regulator_get(&pdev->dev, "vddcx"); + if (IS_ERR(gmu->cx_gdsc)) { + if (PTR_ERR(gmu->cx_gdsc) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Couldn't get the vddcx gdsc\n"); + return PTR_ERR(gmu->cx_gdsc); + } - of_property_for_each_string(node, "regulator-names", prop, name) { - if (!strcmp(name, "vddcx")) { - gmu->cx_gdsc = devm_regulator_get(dev, name); - if (IS_ERR(gmu->cx_gdsc)) { - ret = PTR_ERR(gmu->cx_gdsc); - dev_err(dev, "dt: GMU couldn't get CX gdsc\n"); - gmu->cx_gdsc = NULL; - return ret; - } - } else if (!strcmp(name, "vdd")) { - gmu->gx_gdsc = devm_regulator_get(dev, name); - if (IS_ERR(gmu->gx_gdsc)) { - ret = PTR_ERR(gmu->gx_gdsc); - dev_err(dev, "dt: GMU couldn't get GX gdsc\n"); - gmu->gx_gdsc = NULL; - return ret; - } - } else { - dev_err(dev, "dt: Unknown GMU regulator: %s\n", name); - return -ENODEV; - } + gmu->gx_gdsc = devm_regulator_get(&pdev->dev, "vdd"); + if (IS_ERR(gmu->gx_gdsc)) { + if (PTR_ERR(gmu->gx_gdsc) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Couldn't get the vdd gdsc\n"); + return PTR_ERR(gmu->gx_gdsc); } return 0; @@ -1321,7 +1291,7 @@ static int gmu_probe(struct kgsl_device *device, struct platform_device *pdev) gmu->pdev = pdev; - device->gmu_core.ptr = (void *)gmu; + device->gmu_core.ptr = gmu; hfi = &gmu->hfi; gmu->load_mode = TCM_BOOT; @@ -1330,11 +1300,11 @@ static int gmu_probe(struct kgsl_device *device, struct platform_device *pdev) set_dma_ops(&gmu->pdev->dev, NULL); /* Set up GMU regulators */ - ret = gmu_regulators_probe(gmu, pdev->dev.of_node); + ret = gmu_regulators_probe(gmu, pdev); if (ret) return ret; - ret = devm_clk_bulk_get_all(&gmu->pdev->dev, &gmu->clks); + ret = devm_clk_bulk_get_all(&pdev->dev, &gmu->clks); if (ret < 0) return ret; @@ -1343,8 +1313,9 @@ static int gmu_probe(struct kgsl_device *device, struct platform_device *pdev) /* Get a pointer to the GMU clock */ gmu->gmu_clk = kgsl_of_clk_by_name(gmu->clks, gmu->num_clks, "gmu_clk"); if (!gmu->gmu_clk) { - dev_err(&gmu->pdev->dev, "Couldn't get gmu_clk\n"); - return -ENODEV; + dev_err(&pdev->dev, "Couldn't get gmu_clk\n"); + ret = -ENODEV; + goto error; } /* Set up GMU IOMMU and shared memory with GMU */ @@ -1366,10 +1337,6 @@ static int gmu_probe(struct kgsl_device *device, struct platform_device *pdev) if (ret) goto error; - device->gmu_core.gmu2gpu_offset = - (gmu->reg_phys - device->reg_phys) >> 2; - device->gmu_core.reg_len = gmu->reg_len; - /* Initialize HFI and GMU interrupts */ hfi->hfi_interrupt_num = kgsl_request_irq(gmu->pdev, "kgsl_hfi_irq", hfi_irq_handler, device); @@ -1474,9 +1441,6 @@ static int gmu_enable_gdsc(struct gmu_device *gmu) { int ret; - if (IS_ERR_OR_NULL(gmu->cx_gdsc)) - return 0; - ret = regulator_enable(gmu->cx_gdsc); if (ret) dev_err(&gmu->pdev->dev, @@ -1738,14 +1702,8 @@ static void gmu_remove(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - struct kgsl_hfi *hfi; - if (gmu == NULL || gmu->pdev == NULL) - return; - - hfi = &gmu->hfi; - - tasklet_kill(&hfi->tasklet); + tasklet_kill(&gmu->hfi.tasklet); gmu_stop(device); diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h index 7c6ca7e03b5c..b6a815d90965 100644 --- a/drivers/gpu/msm/kgsl_gmu.h +++ b/drivers/gpu/msm/kgsl_gmu.h @@ -141,8 +141,6 @@ struct icc_path; /** * struct gmu_device - GMU device structure * @ver: GMU Version information - * @reg_phys: GMU CSR physical address - * @reg_len: GMU CSR range * @gmu_interrupt_num: GMU interrupt number * @fw_image: GMU FW image * @hfi_mem: pointer to HFI shared memory @@ -174,8 +172,6 @@ struct gmu_device { u32 hfi; } ver; struct platform_device *pdev; - unsigned long reg_phys; - unsigned int reg_len; int gmu_interrupt_num; const struct firmware *fw_image; struct gmu_memdesc *hfi_mem; From ed253b59c0b23dfe169e6b48f194c9ba3c7c52c1 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:10 -0600 Subject: [PATCH 5/5] msm: kgsl: Use booleans for power control features Currently we use a bitmask for the power control features (SPTP, ACD, LM, etc). Move to individual booleans for each feature instead. Booleans are less unweidly to use and require less if () statements. Additionally if we properly use the Adreno feature flags when setting and/or modifying the booleans we can get rid of the feature flag checks in the rest of the code and use the control booleans as they are intended. And finally, move some of the target specific control features to the target specific code. This ensures that the target specific code can control the feature and the other targets don't accidentally specify the wrong state through sysfs. For example, if SPTP power collapse is only available for a5xx then the sysfs file should only ever return false for the other targets. Change-Id: Ic0dedbad1828ae9163a1a1357828156cb3281914 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno.c | 11 ++---- drivers/gpu/msm/adreno.h | 19 +++++----- drivers/gpu/msm/adreno_a5xx.c | 58 ++++++++++++------------------- drivers/gpu/msm/adreno_a5xx.h | 8 +---- drivers/gpu/msm/adreno_a6xx.c | 7 ++-- drivers/gpu/msm/adreno_a6xx_gmu.c | 6 ++-- drivers/gpu/msm/adreno_debugfs.c | 4 +-- drivers/gpu/msm/adreno_sysfs.c | 44 ++++++++++++----------- drivers/gpu/msm/kgsl_gmu.c | 20 ++++------- drivers/gpu/msm/kgsl_gmu_core.c | 2 +- drivers/gpu/msm/kgsl_gmu_core.h | 4 +-- drivers/gpu/msm/kgsl_hfi.c | 4 +-- 12 files changed, 80 insertions(+), 107 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 06c9b3b65fcd..6b6a5803b5b3 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -985,7 +985,7 @@ static void adreno_of_get_limits(struct adreno_device *adreno_dev, pwrctrl->throttle_mask = GENMASK(pwrctrl->num_pwrlevels - 1, pwrctrl->num_pwrlevels - 1 - throttle_level); - set_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); + adreno_dev->lm_enabled = true; } static int adreno_of_get_legacy_pwrlevels(struct adreno_device *adreno_dev, @@ -1363,13 +1363,6 @@ static void adreno_setup_device(struct adreno_device *adreno_dev) INIT_WORK(&adreno_dev->input_work, adreno_input_work); - /* - * Enable SPTP power collapse, throttling and hardware clock gating by - * default where applicable - */ - adreno_dev->pwrctrl_flag = BIT(ADRENO_SPTP_PC_CTRL) | - BIT(ADRENO_THROTTLING_CTRL) | BIT(ADRENO_HWCG_CTRL); - INIT_LIST_HEAD(&adreno_dev->active_list); spin_lock_init(&adreno_dev->active_list_lock); @@ -3733,7 +3726,7 @@ static bool adreno_is_hwcg_on(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - return test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->hwcg_enabled; } static int adreno_queue_cmds(struct kgsl_device_private *dev_priv, diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 9f442a513376..aeef52bd585a 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -206,12 +206,6 @@ enum adreno_gpurev { #define ADRENO_CTX_DETATCH_TIMEOUT_FAULT BIT(6) #define ADRENO_GMU_FAULT_SKIP_SNAPSHOT BIT(7) -#define ADRENO_SPTP_PC_CTRL 0 -#define ADRENO_LM_CTRL 1 -#define ADRENO_HWCG_CTRL 2 -#define ADRENO_THROTTLING_CTRL 3 -#define ADRENO_ACD_CTRL 4 - /* VBIF, GBIF halt request and ack mask */ #define GBIF_HALT_REQUEST 0x1E0 #define VBIF_RESET_ACK_MASK 0x00f0 @@ -411,7 +405,6 @@ struct adreno_gpu_core { * @halt: Atomic variable to check whether the GPU is currently halted * @pending_irq_refcnt: Atomic variable to keep track of running IRQ handlers * @ctx_d_debugfs: Context debugfs node - * @pwrctrl_flag: Flag to hold adreno specific power attributes * @profile_buffer: Memdesc holding the drawobj profiling buffer * @profile_index: Index to store the start/stop ticks in the profiling * buffer @@ -483,8 +476,16 @@ struct adreno_device { atomic_t halt; atomic_t pending_irq_refcnt; struct dentry *ctx_d_debugfs; - unsigned long pwrctrl_flag; - + /** @lm_enabled: True if limits management is enabled for this target */ + bool lm_enabled; + /** @acd_enabled: True if acd is enabled for this target */ + bool acd_enabled; + /** @hwcg_enabled: True if hardware clock gating is enabled */ + bool hwcg_enabled; + /** @throttling_enabled: True if LM throttling is enabled on a5xx */ + bool throttling_enabled; + /** @sptp_pc_enabled: True if SPTP power collapse is enabled on a5xx */ + bool sptp_pc_enabled; struct kgsl_memdesc *profile_buffer; unsigned int profile_index; struct kgsl_memdesc *pwrup_reglist; diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index c2d7a68f77a9..d7948be3b37c 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -89,7 +89,15 @@ static void a530_efuse_leakage(struct adreno_device *adreno_dev) static void a5xx_platform_setup(struct adreno_device *adreno_dev) { - set_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); + adreno_dev->sptp_pc_enabled = + ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC); + + if (adreno_is_a540(adreno_dev)) + adreno_dev->throttling_enabled = true; + + adreno_dev->hwcg_enabled = true; + adreno_dev->lm_enabled = + ADRENO_FEATURE(adreno_dev, ADRENO_LM); /* Set the GPU busy counter to use for frequency scaling */ adreno_dev->perfctr_pwr_lo = A5XX_RBBM_PERFCTR_RBBM_0_LO; @@ -261,8 +269,7 @@ static bool a5xx_is_sptp_idle(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); /* If feature is not supported or enabled, no worry */ - if (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC) || - !test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->sptp_pc_enabled) return true; kgsl_regread(device, A5XX_GPMU_SP_PWR_CLK_STATUS, ®); if (reg & BIT(20)) @@ -404,8 +411,7 @@ static void a5xx_regulator_disable(struct adreno_device *adreno_dev) return; /* If feature is not supported or not enabled */ - if (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC) || - !test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag)) { + if (!adreno_dev->sptp_pc_enabled) { /* Set the default register values; set SW_COLLAPSE to 1 */ kgsl_regwrite(device, A5XX_GPMU_SP_POWER_CNTL, 0x778001); /* @@ -456,8 +462,7 @@ static void a5xx_enable_pc(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - if (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC) || - !test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->sptp_pc_enabled) return; kgsl_regwrite(device, A5XX_GPMU_PWR_COL_INTER_FRAME_CTRL, 0x0000007F); @@ -701,7 +706,7 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on) const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev); int i; - if (!test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->hwcg_enabled) return; for (i = 0; i < a5xx_core->hwcg_count; i++) @@ -934,8 +939,7 @@ static void a530_lm_init(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev); - if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) || - !test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return; /* If something was wrong with the sequence file, return */ @@ -985,8 +989,7 @@ static void a530_lm_enable(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) || - !test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return; /* If no sequence properly initialized, return */ @@ -1015,10 +1018,10 @@ static void a540_lm_init(struct adreno_device *adreno_dev) << AGC_GPU_VERSION_SHIFT); unsigned int r; - if (!test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->throttling_enabled) agc_lm_config |= AGC_THROTTLE_DISABLE; - if (lm_on(adreno_dev)) { + if (adreno_dev->lm_enabled) { agc_lm_config |= AGC_LM_CONFIG_ENABLE_GPMU_ADAPTIVE | AGC_LM_CONFIG_ISENSE_ENABLE; @@ -1096,20 +1099,11 @@ static void a5xx_pwrlevel_change_settings(struct adreno_device *adreno_dev, unsigned int prelevel, unsigned int postlevel, bool post) { - int on = 0; - - /* On pre A540 HW only call through if LMx is supported and enabled */ - if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) && - test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) - on = ADRENO_LM; - - /* On 540+ HW call through unconditionally as long as GPMU is enabled */ - if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { - if (adreno_is_a540(adreno_dev)) - on = ADRENO_GPMU; - } - - if (!on) + /* + * On pre A540 HW only call through if LMx is supported and enabled, and + * always call through for a540 + */ + if (!adreno_is_a540(adreno_dev) && !adreno_dev->lm_enabled) return; if (!post) { @@ -1158,13 +1152,7 @@ static int64_t a5xx_read_throttling_counters(struct adreno_device *adreno_dev) uint32_t th[ADRENO_GPMU_THROTTLE_COUNTERS]; struct adreno_busy_data *busy = &adreno_dev->busy_data; - if (!adreno_is_a540(adreno_dev)) - return 0; - - if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) - return 0; - - if (!test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->throttling_enabled) return 0; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { diff --git a/drivers/gpu/msm/adreno_a5xx.h b/drivers/gpu/msm/adreno_a5xx.h index 41060a2bd166..90baffa9fc52 100644 --- a/drivers/gpu/msm/adreno_a5xx.h +++ b/drivers/gpu/msm/adreno_a5xx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2017,2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017,2019-2020 The Linux Foundation. All rights reserved. */ #ifndef _ADRENO_A5XX_H_ @@ -205,12 +205,6 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on); #define LM_DEFAULT_LIMIT 6000 #define A530_DEFAULT_LEAKAGE 0x004E001A -static inline bool lm_on(struct adreno_device *adreno_dev) -{ - return ADRENO_FEATURE(adreno_dev, ADRENO_LM) && - test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); -} - /** * to_a5xx_core - return the a5xx specific GPU core struct * @adreno_dev: An Adreno GPU device handle diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 9135f78ba679..73f95b44b036 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -238,7 +238,7 @@ static void a6xx_hwcg_set(struct adreno_device *adreno_dev, bool on) unsigned int value; int i; - if (!test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->hwcg_enabled) on = false; if (gmu_core_isenabled(device)) { @@ -1021,8 +1021,7 @@ static int64_t a6xx_read_throttling_counters(struct adreno_device *adreno_dev) u32 a, b, c; struct adreno_busy_data *busy = &adreno_dev->busy_data; - if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) || - !test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return 0; /* The counters are selected in a6xx_gmu_enable_lm() */ @@ -2281,6 +2280,8 @@ static void a6xx_platform_setup(struct adreno_device *adreno_dev) { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); + adreno_dev->hwcg_enabled = true; + adreno_dev->preempt.preempt_level = 1; adreno_dev->preempt.skipsaverestore = true; adreno_dev->preempt.usesgmem = true; diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 5dae8152f4c3..8d2d4e703339 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -487,8 +487,7 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) gmu_core_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0); - if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) && - test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (adreno_dev->lm_enabled) gmu_core_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 0); set_bit(GMU_RSCC_SLEEP_SEQ_DONE, &device->gmu_core.flags); @@ -1409,8 +1408,7 @@ static void a6xx_gmu_enable_lm(struct kgsl_device *device) memset(adreno_dev->busy_data.throttle_cycles, 0, sizeof(adreno_dev->busy_data.throttle_cycles)); - if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) || - !test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return; /* diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c index 03a59ce24408..2d2a6473089d 100644 --- a/drivers/gpu/msm/adreno_debugfs.c +++ b/drivers/gpu/msm/adreno_debugfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2002,2008-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2008-2020, The Linux Foundation. All rights reserved. */ #include @@ -59,7 +59,7 @@ static int _lm_limit_set(void *data, u64 val) adreno_dev->lm_limit = val; - if (test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) { + if (adreno_dev->lm_enabled) { mutex_lock(&device->mutex); kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); diff --git a/drivers/gpu/msm/adreno_sysfs.c b/drivers/gpu/msm/adreno_sysfs.c index 5256c25be624..f5fb8641fd5c 100644 --- a/drivers/gpu/msm/adreno_sysfs.c +++ b/drivers/gpu/msm/adreno_sysfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #include @@ -139,19 +139,19 @@ static bool _ft_hang_intr_status_show(struct adreno_device *adreno_dev) return true; } -static int _pwrctrl_store(struct adreno_device *adreno_dev, - unsigned int val, unsigned int flag) +static int pwrflag_store(struct adreno_device *adreno_dev, + unsigned int val, bool *flag) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - if (val == test_bit(flag, &adreno_dev->pwrctrl_flag)) + if (*flag == val) return 0; mutex_lock(&device->mutex); /* Power down the GPU before changing the state */ kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); - change_bit(flag, &adreno_dev->pwrctrl_flag); + *flag = val; kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); mutex_unlock(&device->mutex); @@ -201,42 +201,51 @@ static bool _preemption_show(struct adreno_device *adreno_dev) static int _hwcg_store(struct adreno_device *adreno_dev, bool val) { - return _pwrctrl_store(adreno_dev, val, ADRENO_HWCG_CTRL); + return pwrflag_store(adreno_dev, val, &adreno_dev->hwcg_enabled); } static bool _hwcg_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->hwcg_enabled; } static int _throttling_store(struct adreno_device *adreno_dev, bool val) { - return _pwrctrl_store(adreno_dev, val, ADRENO_THROTTLING_CTRL); + if (!adreno_is_a540(adreno_dev)) + return 0; + + return pwrflag_store(adreno_dev, val, &adreno_dev->throttling_enabled); } static bool _throttling_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->throttling_enabled; } static int _sptp_pc_store(struct adreno_device *adreno_dev, bool val) { - return _pwrctrl_store(adreno_dev, val, ADRENO_SPTP_PC_CTRL); + if (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC)) + return 0; + + return pwrflag_store(adreno_dev, val, &adreno_dev->sptp_pc_enabled); } static bool _sptp_pc_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->sptp_pc_enabled; } static int _lm_store(struct adreno_device *adreno_dev, bool val) { - return _pwrctrl_store(adreno_dev, val, ADRENO_LM_CTRL); + if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM)) + return 0; + + return pwrflag_store(adreno_dev, val, &adreno_dev->lm_enabled); } static bool _lm_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->lm_enabled; } static int _ifpc_store(struct adreno_device *adreno_dev, bool val) @@ -263,17 +272,12 @@ static unsigned int _preempt_count_show(struct adreno_device *adreno_dev) static bool _acd_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->acd_enabled; } static int _acd_store(struct adreno_device *adreno_dev, bool val) { - struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - - if (test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag) == val) - return 0; - - return gmu_core_acd_set(device, val); + return gmu_core_acd_set(KGSL_DEVICE(adreno_dev), val); } static ssize_t _sysfs_store_u32(struct device *dev, diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index 848f49682276..d39f2c0fa8ab 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -1130,11 +1130,11 @@ static int gmu_aop_mailbox_init(struct kgsl_device *device, if (IS_ERR(mailbox->channel)) return PTR_ERR(mailbox->channel); - set_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); + adreno_dev->acd_enabled = true; return 0; } -static int gmu_acd_set(struct kgsl_device *device, unsigned int val) +static int gmu_acd_set(struct kgsl_device *device, bool val) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); @@ -1143,7 +1143,7 @@ static int gmu_acd_set(struct kgsl_device *device, unsigned int val) return -EINVAL; /* Don't do any unneeded work if ACD is already in the correct state */ - if (val == test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag)) + if (adreno_dev->acd_enabled == val) return 0; mutex_lock(&device->mutex); @@ -1151,13 +1151,8 @@ static int gmu_acd_set(struct kgsl_device *device, unsigned int val) /* Power down the GPU before enabling or disabling ACD */ kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); - if (val) { - set_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); - gmu_aop_send_acd_state(device, true); - } else { - clear_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); - gmu_aop_send_acd_state(device, false); - } + adreno_dev->acd_enabled = val; + gmu_aop_send_acd_state(device, val); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); @@ -1562,8 +1557,7 @@ static int gmu_start(struct kgsl_device *device) switch (device->state) { case KGSL_STATE_INIT: - gmu_aop_send_acd_state(device, test_bit(ADRENO_ACD_CTRL, - &adreno_dev->pwrctrl_flag)); + gmu_aop_send_acd_state(device, adreno_dev->acd_enabled); /* Fall-thru */ case KGSL_STATE_SUSPEND: WARN_ON(test_bit(GMU_CLK_ON, &device->gmu_core.flags)); @@ -1710,7 +1704,7 @@ static void gmu_remove(struct kgsl_device *device) if (!IS_ERR_OR_NULL(gmu->mailbox.channel)) mbox_free_channel(gmu->mailbox.channel); - clear_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); + adreno_dev->acd_enabled = false; if (gmu->fw_image) release_firmware(gmu->fw_image); diff --git a/drivers/gpu/msm/kgsl_gmu_core.c b/drivers/gpu/msm/kgsl_gmu_core.c index 81414d8ae594..6072e9c8b7d5 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.c +++ b/drivers/gpu/msm/kgsl_gmu_core.c @@ -142,7 +142,7 @@ int gmu_core_dcvs_set(struct kgsl_device *device, int gpu_pwrlevel, return -EINVAL; } -int gmu_core_acd_set(struct kgsl_device *device, unsigned int val) +int gmu_core_acd_set(struct kgsl_device *device, bool val) { struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index 45280614dc9f..655693a68205 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -109,7 +109,7 @@ struct gmu_core_ops { void (*snapshot)(struct kgsl_device *device); bool (*regulator_isenabled)(struct kgsl_device *device); int (*suspend)(struct kgsl_device *device); - int (*acd_set)(struct kgsl_device *device, unsigned int val); + int (*acd_set)(struct kgsl_device *device, bool val); }; struct gmu_dev_ops { @@ -179,7 +179,7 @@ bool gmu_core_scales_bandwidth(struct kgsl_device *device); bool gmu_core_isenabled(struct kgsl_device *device); int gmu_core_dcvs_set(struct kgsl_device *device, int gpu_pwrlevel, int bus_level); -int gmu_core_acd_set(struct kgsl_device *device, unsigned int val); +int gmu_core_acd_set(struct kgsl_device *device, bool val); bool gmu_core_regulator_isenabled(struct kgsl_device *device); bool gmu_core_is_register_offset(struct kgsl_device *device, unsigned int offsetwords); diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c index cdd0a07309c7..d4affcda1b7d 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -653,7 +653,7 @@ static int hfi_send_lm_feature_ctrl(struct gmu_device *gmu, u32 slope = 0; int ret; - if (!test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return 0; memset(&req, 0, sizeof(req)); @@ -678,7 +678,7 @@ static int hfi_send_acd_feature_ctrl(struct gmu_device *gmu, { int ret = 0; - if (test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag)) { + if (adreno_dev->acd_enabled) { ret = hfi_send_acd_tbl(gmu); if (!ret) ret = hfi_send_feature_ctrl(gmu, HFI_FEATURE_ACD, 1, 0);