Loading drivers/gpu/msm/adreno.c +10 −2 Original line number Diff line number Diff line Loading @@ -586,6 +586,9 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device) unsigned int status = 0, fence = 0, fence_retries = 0, tmp, int_bit; unsigned int shadow_status = 0; int i; u64 ts, ts1, ts2; ts = gmu_core_dev_read_ao_counter(device); atomic_inc(&adreno_dev->pending_irq_refcnt); /* Ensure this increment is done before the IRQ status is updated */ Loading @@ -612,6 +615,8 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device) &fence); while (fence != 0) { ts1 = gmu_core_dev_read_ao_counter(device); /* Wait for small time before trying again */ udelay(1); adreno_readreg(adreno_dev, Loading @@ -619,14 +624,17 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device) &fence); if (fence_retries == FENCE_RETRY_MAX && fence != 0) { ts2 = gmu_core_dev_read_ao_counter(device); adreno_readreg(adreno_dev, ADRENO_REG_GMU_RBBM_INT_UNMASKED_STATUS, &shadow_status); dev_crit_ratelimited(device->dev, "Status=0x%x Unmasked status=0x%x Mask=0x%x\n", "Status=0x%x Unmasked status=0x%x Timestamps:%llx %llx %llx\n", shadow_status & irq_params->mask, shadow_status, irq_params->mask); shadow_status, ts, ts1, ts2); adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT); adreno_dispatcher_schedule(KGSL_DEVICE Loading drivers/gpu/msm/adreno_a6xx.h +1 −25 Original line number Diff line number Diff line Loading @@ -244,31 +244,6 @@ static inline int timed_poll_check_rscc(struct kgsl_device *device, return -ETIMEDOUT; } /* * read_AO_counter() - Returns the 64bit always on counter value * * @device: Pointer to KGSL device */ static inline uint64_t read_AO_counter(struct kgsl_device *device) { unsigned int l, h, h1; gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); /* * If there's no change in COUNTER_H we have no overflow so return, * otherwise read COUNTER_L again */ if (h == h1) return (uint64_t) l | ((uint64_t) h << 32); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); return (uint64_t) l | ((uint64_t) h1 << 32); } /* Preemption functions */ void a6xx_preemption_trigger(struct adreno_device *adreno_dev); void a6xx_preemption_schedule(struct adreno_device *adreno_dev); Loading Loading @@ -297,4 +272,5 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev); int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev); void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev); bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev); u64 a6xx_gmu_read_ao_counter(struct kgsl_device *device); #endif drivers/gpu/msm/adreno_a6xx_gmu.c +31 −5 Original line number Diff line number Diff line Loading @@ -886,7 +886,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct kgsl_device *device) unsigned long t; uint64_t ts1, ts2, ts3; ts1 = read_AO_counter(device); ts1 = a6xx_gmu_read_ao_counter(device); t = jiffies + msecs_to_jiffies(GMU_IDLE_TIMEOUT); do { Loading @@ -901,7 +901,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct kgsl_device *device) usleep_range(10, 100); } while (!time_after(jiffies, t)); ts2 = read_AO_counter(device); ts2 = a6xx_gmu_read_ao_counter(device); /* Check one last time */ gmu_core_regread(device, A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, ®); Loading @@ -910,7 +910,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct kgsl_device *device) if (idle_trandition_complete(gmu->idle_level, reg, reg1)) return 0; ts3 = read_AO_counter(device); ts3 = a6xx_gmu_read_ao_counter(device); /* Collect abort data to help with debugging */ gmu_core_regread(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, ®2); Loading Loading @@ -954,14 +954,14 @@ static int a6xx_gmu_wait_for_idle(struct kgsl_device *device) unsigned int status2; uint64_t ts1; ts1 = read_AO_counter(device); ts1 = a6xx_gmu_read_ao_counter(device); if (timed_poll_check(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, 0, GMU_START_TIMEOUT, CXGXCPUBUSYIGNAHB)) { gmu_core_regread(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2, &status2); dev_err(&gmu->pdev->dev, "GMU not idling: status2=0x%x %llx %llx\n", status2, ts1, read_AO_counter(device)); status2, ts1, a6xx_gmu_read_ao_counter(device)); return -ETIMEDOUT; } Loading Loading @@ -1722,6 +1722,31 @@ static int a6xx_gmu_wait_for_active_transition( return -ETIMEDOUT; } /* * a6xx_gmu_read_ao_counter() - Returns the 64bit always on counter value * * @device: Pointer to KGSL device */ u64 a6xx_gmu_read_ao_counter(struct kgsl_device *device) { unsigned int l, h, h1; gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); /* * If there's no change in COUNTER_H we have no overflow so return, * otherwise read COUNTER_L again */ if (h == h1) return (uint64_t) l | ((uint64_t) h << 32); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); return (uint64_t) l | ((uint64_t) h1 << 32); } struct gmu_dev_ops adreno_a6xx_gmudev = { .load_firmware = a6xx_gmu_load_firmware, .oob_set = a6xx_gmu_oob_set, Loading @@ -1739,6 +1764,7 @@ struct gmu_dev_ops adreno_a6xx_gmudev = { .snapshot = a6xx_gmu_snapshot, .cooperative_reset = a6xx_gmu_cooperative_reset, .wait_for_active_transition = a6xx_gmu_wait_for_active_transition, .read_ao_counter = a6xx_gmu_read_ao_counter, .gmu2host_intr_mask = HFI_IRQ_MASK, .gmu_ao_intr_mask = GMU_AO_INT_MASK, }; drivers/gpu/msm/adreno_a6xx_rgmu.c +4 −3 Original line number Diff line number Diff line Loading @@ -259,7 +259,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct kgsl_device *device) if (rgmu->idle_level != GPU_HW_IFPC) return 0; ts1 = read_AO_counter(device); ts1 = a6xx_gmu_read_ao_counter(device); t = jiffies + msecs_to_jiffies(RGMU_IDLE_TIMEOUT); do { Loading @@ -273,7 +273,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct kgsl_device *device) usleep_range(10, 100); } while (!time_after(jiffies, t)); ts2 = read_AO_counter(device); ts2 = a6xx_gmu_read_ao_counter(device); /* Do one last read incase it succeeds */ gmu_core_regread(device, Loading @@ -282,7 +282,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct kgsl_device *device) if (reg[0] & GX_GDSC_POWER_OFF) return 0; ts3 = read_AO_counter(device); ts3 = a6xx_gmu_read_ao_counter(device); /* Collect abort data to help with debugging */ gmu_core_regread(device, A6XX_RGMU_CX_PCC_DEBUG, ®[1]); Loading Loading @@ -573,6 +573,7 @@ struct gmu_dev_ops adreno_a6xx_rgmudev = { .ifpc_show = a6xx_rgmu_ifpc_show, .snapshot = a6xx_rgmu_snapshot, .halt_execution = a6xx_rgmu_halt_execution, .read_ao_counter = a6xx_gmu_read_ao_counter, .gmu2host_intr_mask = RGMU_OOB_IRQ_MASK, .gmu_ao_intr_mask = RGMU_AO_IRQ_MASK, }; drivers/gpu/msm/kgsl_gmu_core.c +10 −0 Original line number Diff line number Diff line Loading @@ -380,3 +380,13 @@ int gmu_core_dev_wait_for_active_transition(struct kgsl_device *device) return 0; } u64 gmu_core_dev_read_ao_counter(struct kgsl_device *device) { struct gmu_dev_ops *ops = GMU_DEVICE_OPS(device); if (ops && ops->read_ao_counter) return ops->read_ao_counter(device); return 0; } Loading
drivers/gpu/msm/adreno.c +10 −2 Original line number Diff line number Diff line Loading @@ -586,6 +586,9 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device) unsigned int status = 0, fence = 0, fence_retries = 0, tmp, int_bit; unsigned int shadow_status = 0; int i; u64 ts, ts1, ts2; ts = gmu_core_dev_read_ao_counter(device); atomic_inc(&adreno_dev->pending_irq_refcnt); /* Ensure this increment is done before the IRQ status is updated */ Loading @@ -612,6 +615,8 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device) &fence); while (fence != 0) { ts1 = gmu_core_dev_read_ao_counter(device); /* Wait for small time before trying again */ udelay(1); adreno_readreg(adreno_dev, Loading @@ -619,14 +624,17 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device) &fence); if (fence_retries == FENCE_RETRY_MAX && fence != 0) { ts2 = gmu_core_dev_read_ao_counter(device); adreno_readreg(adreno_dev, ADRENO_REG_GMU_RBBM_INT_UNMASKED_STATUS, &shadow_status); dev_crit_ratelimited(device->dev, "Status=0x%x Unmasked status=0x%x Mask=0x%x\n", "Status=0x%x Unmasked status=0x%x Timestamps:%llx %llx %llx\n", shadow_status & irq_params->mask, shadow_status, irq_params->mask); shadow_status, ts, ts1, ts2); adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT); adreno_dispatcher_schedule(KGSL_DEVICE Loading
drivers/gpu/msm/adreno_a6xx.h +1 −25 Original line number Diff line number Diff line Loading @@ -244,31 +244,6 @@ static inline int timed_poll_check_rscc(struct kgsl_device *device, return -ETIMEDOUT; } /* * read_AO_counter() - Returns the 64bit always on counter value * * @device: Pointer to KGSL device */ static inline uint64_t read_AO_counter(struct kgsl_device *device) { unsigned int l, h, h1; gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); /* * If there's no change in COUNTER_H we have no overflow so return, * otherwise read COUNTER_L again */ if (h == h1) return (uint64_t) l | ((uint64_t) h << 32); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); return (uint64_t) l | ((uint64_t) h1 << 32); } /* Preemption functions */ void a6xx_preemption_trigger(struct adreno_device *adreno_dev); void a6xx_preemption_schedule(struct adreno_device *adreno_dev); Loading Loading @@ -297,4 +272,5 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev); int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev); void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev); bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev); u64 a6xx_gmu_read_ao_counter(struct kgsl_device *device); #endif
drivers/gpu/msm/adreno_a6xx_gmu.c +31 −5 Original line number Diff line number Diff line Loading @@ -886,7 +886,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct kgsl_device *device) unsigned long t; uint64_t ts1, ts2, ts3; ts1 = read_AO_counter(device); ts1 = a6xx_gmu_read_ao_counter(device); t = jiffies + msecs_to_jiffies(GMU_IDLE_TIMEOUT); do { Loading @@ -901,7 +901,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct kgsl_device *device) usleep_range(10, 100); } while (!time_after(jiffies, t)); ts2 = read_AO_counter(device); ts2 = a6xx_gmu_read_ao_counter(device); /* Check one last time */ gmu_core_regread(device, A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, ®); Loading @@ -910,7 +910,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct kgsl_device *device) if (idle_trandition_complete(gmu->idle_level, reg, reg1)) return 0; ts3 = read_AO_counter(device); ts3 = a6xx_gmu_read_ao_counter(device); /* Collect abort data to help with debugging */ gmu_core_regread(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, ®2); Loading Loading @@ -954,14 +954,14 @@ static int a6xx_gmu_wait_for_idle(struct kgsl_device *device) unsigned int status2; uint64_t ts1; ts1 = read_AO_counter(device); ts1 = a6xx_gmu_read_ao_counter(device); if (timed_poll_check(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, 0, GMU_START_TIMEOUT, CXGXCPUBUSYIGNAHB)) { gmu_core_regread(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2, &status2); dev_err(&gmu->pdev->dev, "GMU not idling: status2=0x%x %llx %llx\n", status2, ts1, read_AO_counter(device)); status2, ts1, a6xx_gmu_read_ao_counter(device)); return -ETIMEDOUT; } Loading Loading @@ -1722,6 +1722,31 @@ static int a6xx_gmu_wait_for_active_transition( return -ETIMEDOUT; } /* * a6xx_gmu_read_ao_counter() - Returns the 64bit always on counter value * * @device: Pointer to KGSL device */ u64 a6xx_gmu_read_ao_counter(struct kgsl_device *device) { unsigned int l, h, h1; gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); /* * If there's no change in COUNTER_H we have no overflow so return, * otherwise read COUNTER_L again */ if (h == h1) return (uint64_t) l | ((uint64_t) h << 32); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); return (uint64_t) l | ((uint64_t) h1 << 32); } struct gmu_dev_ops adreno_a6xx_gmudev = { .load_firmware = a6xx_gmu_load_firmware, .oob_set = a6xx_gmu_oob_set, Loading @@ -1739,6 +1764,7 @@ struct gmu_dev_ops adreno_a6xx_gmudev = { .snapshot = a6xx_gmu_snapshot, .cooperative_reset = a6xx_gmu_cooperative_reset, .wait_for_active_transition = a6xx_gmu_wait_for_active_transition, .read_ao_counter = a6xx_gmu_read_ao_counter, .gmu2host_intr_mask = HFI_IRQ_MASK, .gmu_ao_intr_mask = GMU_AO_INT_MASK, };
drivers/gpu/msm/adreno_a6xx_rgmu.c +4 −3 Original line number Diff line number Diff line Loading @@ -259,7 +259,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct kgsl_device *device) if (rgmu->idle_level != GPU_HW_IFPC) return 0; ts1 = read_AO_counter(device); ts1 = a6xx_gmu_read_ao_counter(device); t = jiffies + msecs_to_jiffies(RGMU_IDLE_TIMEOUT); do { Loading @@ -273,7 +273,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct kgsl_device *device) usleep_range(10, 100); } while (!time_after(jiffies, t)); ts2 = read_AO_counter(device); ts2 = a6xx_gmu_read_ao_counter(device); /* Do one last read incase it succeeds */ gmu_core_regread(device, Loading @@ -282,7 +282,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct kgsl_device *device) if (reg[0] & GX_GDSC_POWER_OFF) return 0; ts3 = read_AO_counter(device); ts3 = a6xx_gmu_read_ao_counter(device); /* Collect abort data to help with debugging */ gmu_core_regread(device, A6XX_RGMU_CX_PCC_DEBUG, ®[1]); Loading Loading @@ -573,6 +573,7 @@ struct gmu_dev_ops adreno_a6xx_rgmudev = { .ifpc_show = a6xx_rgmu_ifpc_show, .snapshot = a6xx_rgmu_snapshot, .halt_execution = a6xx_rgmu_halt_execution, .read_ao_counter = a6xx_gmu_read_ao_counter, .gmu2host_intr_mask = RGMU_OOB_IRQ_MASK, .gmu_ao_intr_mask = RGMU_AO_IRQ_MASK, };
drivers/gpu/msm/kgsl_gmu_core.c +10 −0 Original line number Diff line number Diff line Loading @@ -380,3 +380,13 @@ int gmu_core_dev_wait_for_active_transition(struct kgsl_device *device) return 0; } u64 gmu_core_dev_read_ao_counter(struct kgsl_device *device) { struct gmu_dev_ops *ops = GMU_DEVICE_OPS(device); if (ops && ops->read_ao_counter) return ops->read_ao_counter(device); return 0; }