Loading drivers/gpu/msm/adreno.c +10 −120 Original line number Diff line number Diff line Loading @@ -1243,86 +1243,6 @@ static bool regulators_left_on(struct kgsl_device *device) return false; } static void _setup_throttling_counters(struct adreno_device *adreno_dev) { int i, ret; if (!adreno_is_a540(adreno_dev)) return; if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) return; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { /* reset throttled cycles ivalue */ adreno_dev->busy_data.throttle_cycles[i] = 0; if (adreno_dev->gpmu_throttle_counters[i] != 0) continue; ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_GPMU_PWR, ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i, &adreno_dev->gpmu_throttle_counters[i], NULL, PERFCOUNTER_FLAG_KERNEL); WARN_ONCE(ret, "Unable to get clock throttling counter %x\n", ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i); } } /* FW driven idle 10% throttle */ #define IDLE_10PCT 0 /* number of cycles when clock is throttled by 50% (CRC) */ #define CRC_50PCT 1 /* number of cycles when clock is throttled by more than 50% (CRC) */ #define CRC_MORE50PCT 2 /* number of cycles when clock is throttle by less than 50% (CRC) */ #define CRC_LESS50PCT 3 static uint64_t _read_throttling_counters(struct adreno_device *adreno_dev) { int i, adj; 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)) return 0; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { if (!adreno_dev->gpmu_throttle_counters[i]) return 0; th[i] = counter_delta(KGSL_DEVICE(adreno_dev), adreno_dev->gpmu_throttle_counters[i], &busy->throttle_cycles[i]); } adj = th[CRC_MORE50PCT] - th[IDLE_10PCT]; adj = th[CRC_50PCT] + th[CRC_LESS50PCT] / 3 + (adj < 0 ? 0 : adj) * 3; trace_kgsl_clock_throttling( th[IDLE_10PCT], th[CRC_50PCT], th[CRC_MORE50PCT], th[CRC_LESS50PCT], adj); return adj; } static void _update_threshold_count(struct adreno_device *adreno_dev, uint64_t adj) { if (adreno_is_a530(adreno_dev)) kgsl_regread(KGSL_DEVICE(adreno_dev), adreno_dev->lm_threshold_count, &adreno_dev->lm_threshold_cross); else if (adreno_is_a540(adreno_dev)) adreno_dev->lm_threshold_cross = adj; } static void _set_secvid(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); Loading Loading @@ -1419,8 +1339,8 @@ static int _adreno_start(struct adreno_device *adreno_dev) } } if (device->pwrctrl.bus_control) { if (device->pwrctrl.bus_control) { /* VBIF waiting for RAM */ if (adreno_dev->starved_ram_lo == 0) { ret = adreno_perfcounter_get(adreno_dev, Loading Loading @@ -1456,20 +1376,6 @@ static int _adreno_start(struct adreno_device *adreno_dev) adreno_dev->busy_data.vbif_ram_cycles = 0; adreno_dev->busy_data.vbif_starved_ram = 0; if (adreno_is_a530(adreno_dev) && ADRENO_FEATURE(adreno_dev, ADRENO_LM) && adreno_dev->lm_threshold_count == 0) { ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 27, &adreno_dev->lm_threshold_count, NULL, PERFCOUNTER_FLAG_KERNEL); /* Ignore noncritical ret - used for debugfs */ if (ret) adreno_dev->lm_threshold_count = 0; } _setup_throttling_counters(adreno_dev); /* Restore performance counter registers with saved values */ adreno_perfcounter_restore(adreno_dev); Loading Loading @@ -2576,27 +2482,6 @@ static inline s64 adreno_ticks_to_us(u32 ticks, u32 freq) return ticks / freq; } static unsigned int counter_delta(struct kgsl_device *device, unsigned int reg, unsigned int *counter) { unsigned int val; unsigned int ret = 0; /* Read the value */ kgsl_regread(device, reg, &val); /* Return 0 for the first read */ if (*counter != 0) { if (val < *counter) ret = (0xFFFFFFFF - *counter) + val; else ret = val - *counter; } *counter = val; return ret; } /** * adreno_power_stats() - Reads the counters needed for freq decisions * @device: Pointer to device whose counters are read Loading @@ -2608,6 +2493,7 @@ static void adreno_power_stats(struct kgsl_device *device, struct kgsl_power_stats *stats) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct adreno_busy_data *busy = &adreno_dev->busy_data; uint64_t adj = 0; Loading @@ -2621,8 +2507,11 @@ static void adreno_power_stats(struct kgsl_device *device, gpu_busy = counter_delta(device, adreno_dev->perfctr_pwr_lo, &busy->gpu_busy); adj = _read_throttling_counters(adreno_dev); if (gpudev->read_throttling_counters) { adj = gpudev->read_throttling_counters(adreno_dev); gpu_busy += adj; } stats->busy_time = adreno_ticks_to_us(gpu_busy, kgsl_pwrctrl_active_freq(pwr)); } Loading @@ -2643,8 +2532,9 @@ static void adreno_power_stats(struct kgsl_device *device, stats->ram_time = ram_cycles; stats->ram_wait = starved_ram; } if (adreno_dev->lm_threshold_count) _update_threshold_count(adreno_dev, adj); if (adreno_dev->lm_threshold_count && gpudev->count_throttles) gpudev->count_throttles(adreno_dev, adj); } static unsigned int adreno_gpuid(struct kgsl_device *device, Loading drivers/gpu/msm/adreno.h +24 −0 Original line number Diff line number Diff line Loading @@ -756,6 +756,10 @@ struct adreno_gpudev { void (*pwrlevel_change_settings)(struct adreno_device *, unsigned int prelevel, unsigned int postlevel, bool post); uint64_t (*read_throttling_counters)(struct adreno_device *); void (*count_throttles)(struct adreno_device *, uint64_t adj); int (*enable_pwr_counters)(struct adreno_device *, unsigned int counter); unsigned int (*preemption_pre_ibsubmit)(struct adreno_device *, struct adreno_ringbuffer *rb, unsigned int *, struct kgsl_context *); Loading Loading @@ -1466,4 +1470,24 @@ static inline void adreno_ringbuffer_set_pagetable(struct adreno_ringbuffer *rb, spin_unlock_irqrestore(&rb->preempt_lock, flags); } static inline unsigned int counter_delta(struct kgsl_device *device, unsigned int reg, unsigned int *counter) { unsigned int val; unsigned int ret = 0; /* Read the value */ kgsl_regread(device, reg, &val); /* Return 0 for the first read */ if (*counter != 0) { if (val < *counter) ret = (0xFFFFFFFF - *counter) + val; else ret = val - *counter; } *counter = val; return ret; } #endif /*__ADRENO_H */ drivers/gpu/msm/adreno_a5xx.c +122 −16 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include "kgsl_sharedmem.h" #include "kgsl_log.h" #include "kgsl.h" #include "kgsl_trace.h" #include "adreno_a5xx_packets.h" static int zap_ucode_loaded; Loading Loading @@ -1543,6 +1544,76 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev, } } static void a5xx_count_throttles(struct adreno_device *adreno_dev, uint64_t adj) { if (adreno_is_a530(adreno_dev)) kgsl_regread(KGSL_DEVICE(adreno_dev), adreno_dev->lm_threshold_count, &adreno_dev->lm_threshold_cross); else if (adreno_is_a540(adreno_dev)) adreno_dev->lm_threshold_cross = adj; } static int a5xx_enable_pwr_counters(struct adreno_device *adreno_dev, unsigned int counter) { /* * On 5XX we have to emulate the PWR counters which are physically * missing. Program countable 6 on RBBM_PERFCTR_RBBM_0 as a substitute * for PWR:1. Don't emulate PWR:0 as nobody uses it and we don't want * to take away too many of the generic RBBM counters. */ if (counter == 0) return -EINVAL; kgsl_regwrite(KGSL_DEVICE(adreno_dev), A5XX_RBBM_PERFCTR_RBBM_SEL_0, 6); return 0; } /* FW driven idle 10% throttle */ #define IDLE_10PCT 0 /* number of cycles when clock is throttled by 50% (CRC) */ #define CRC_50PCT 1 /* number of cycles when clock is throttled by more than 50% (CRC) */ #define CRC_MORE50PCT 2 /* number of cycles when clock is throttle by less than 50% (CRC) */ #define CRC_LESS50PCT 3 static uint64_t a5xx_read_throttling_counters(struct adreno_device *adreno_dev) { int i, adj; 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)) return 0; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { if (!adreno_dev->gpmu_throttle_counters[i]) return 0; th[i] = counter_delta(KGSL_DEVICE(adreno_dev), adreno_dev->gpmu_throttle_counters[i], &busy->throttle_cycles[i]); } adj = th[CRC_MORE50PCT] - th[IDLE_10PCT]; adj = th[CRC_50PCT] + th[CRC_LESS50PCT] / 3 + (adj < 0 ? 0 : adj) * 3; trace_kgsl_clock_throttling( th[IDLE_10PCT], th[CRC_50PCT], th[CRC_MORE50PCT], th[CRC_LESS50PCT], adj); return adj; } static void a5xx_enable_64bit(struct adreno_device *adreno_dev) { Loading Loading @@ -1599,12 +1670,44 @@ static void a5xx_gpmu_reset(struct work_struct *work) /* Soft reset of the GPMU block */ kgsl_regwrite(device, A5XX_RBBM_BLOCK_SW_RESET_CMD, BIT(16)); /* GPU comes up in secured mode, make it unsecured by default */ if (!ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)) kgsl_regwrite(device, A5XX_RBBM_SECVID_TRUST_CNTL, 0x0); a5xx_gpmu_init(adreno_dev); out: mutex_unlock(&device->mutex); } static void _setup_throttling_counters(struct adreno_device *adreno_dev) { int i, ret; if (!adreno_is_a540(adreno_dev)) return; if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) return; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { /* reset throttled cycles ivalue */ adreno_dev->busy_data.throttle_cycles[i] = 0; if (adreno_dev->gpmu_throttle_counters[i] != 0) continue; ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_GPMU_PWR, ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i, &adreno_dev->gpmu_throttle_counters[i], NULL, PERFCOUNTER_FLAG_KERNEL); WARN_ONCE(ret, "Unable to get clock throttling counter %x\n", ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i); } } /* * a5xx_start() - Device start * @adreno_dev: Pointer to adreno device Loading @@ -1616,6 +1719,21 @@ static void a5xx_start(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); unsigned int bit; int ret; if (adreno_is_a530(adreno_dev) && ADRENO_FEATURE(adreno_dev, ADRENO_LM) && adreno_dev->lm_threshold_count == 0) { ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 27, &adreno_dev->lm_threshold_count, NULL, PERFCOUNTER_FLAG_KERNEL); /* Ignore noncritical ret - used for debugfs */ if (ret) adreno_dev->lm_threshold_count = 0; } _setup_throttling_counters(adreno_dev); adreno_vbif_start(adreno_dev, a5xx_vbif_platforms, ARRAY_SIZE(a5xx_vbif_platforms)); Loading Loading @@ -1921,11 +2039,6 @@ static int a5xx_post_start(struct adreno_device *adreno_dev) static int a5xx_gpmu_init(struct adreno_device *adreno_dev) { int ret; struct kgsl_device *device = KGSL_DEVICE(adreno_dev); /* GPU comes up in secured mode, make it unsecured by default */ if (!ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)) kgsl_regwrite(device, A5XX_RBBM_SECVID_TRUST_CNTL, 0x0); /* Set up LM before initializing the GPMU */ a5xx_lm_init(adreno_dev); Loading Loading @@ -2246,20 +2359,10 @@ static int a5xx_rb_start(struct adreno_device *adreno_dev, if (ret) return ret; /* Set up LM before initializing the GPMU */ a5xx_lm_init(adreno_dev); /* Enable SPTP based power collapse before enabling GPMU */ a5xx_enable_pc(adreno_dev); /* Program the GPMU */ ret = a5xx_gpmu_start(adreno_dev); ret = a5xx_gpmu_init(adreno_dev); if (ret) return ret; /* Enable limits management */ a5xx_lm_enable(adreno_dev); a5xx_post_start(adreno_dev); return 0; Loading Loading @@ -3421,6 +3524,9 @@ struct adreno_gpudev adreno_a5xx_gpudev = { .regulator_enable = a5xx_regulator_enable, .regulator_disable = a5xx_regulator_disable, .pwrlevel_change_settings = a5xx_pwrlevel_change_settings, .read_throttling_counters = a5xx_read_throttling_counters, .count_throttles = a5xx_count_throttles, .enable_pwr_counters = a5xx_enable_pwr_counters, .preemption_pre_ibsubmit = a5xx_preemption_pre_ibsubmit, .preemption_yield_enable = a5xx_preemption_yield_enable, Loading drivers/gpu/msm/adreno_perfcounter.c +4 −23 Original line number Diff line number Diff line Loading @@ -598,28 +598,6 @@ int adreno_perfcounter_put(struct adreno_device *adreno_dev, return -EINVAL; } static int _perfcounter_enable_pwr(struct adreno_device *adreno_dev, unsigned int counter) { /* PWR counters enabled by default on A3XX/A4XX so nothing to do */ if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev)) return 0; /* * On 5XX we have to emulate the PWR counters which are physically * missing. Program countable 6 on RBBM_PERFCTR_RBBM_0 as a substitute * for PWR:1. Don't emulate PWR:0 as nobody uses it and we don't want * to take away too many of the generic RBBM counters. */ if (counter == 0) return -EINVAL; kgsl_regwrite(KGSL_DEVICE(adreno_dev), A5XX_RBBM_PERFCTR_RBBM_SEL_0, 6); return 0; } static void _perfcounter_enable_vbif(struct adreno_device *adreno_dev, struct adreno_perfcounters *counters, unsigned int counter, unsigned int countable) Loading Loading @@ -771,6 +749,7 @@ static int adreno_perfcounter_enable(struct adreno_device *adreno_dev, unsigned int group, unsigned int counter, unsigned int countable) { struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (counters == NULL) return -EINVAL; Loading @@ -786,7 +765,9 @@ static int adreno_perfcounter_enable(struct adreno_device *adreno_dev, /* alwayson counter is global, so init value is 0 */ break; case KGSL_PERFCOUNTER_GROUP_PWR: return _perfcounter_enable_pwr(adreno_dev, counter); if (gpudev->enable_pwr_counters) return gpudev->enable_pwr_counters(adreno_dev, counter); return 0; case KGSL_PERFCOUNTER_GROUP_VBIF: if (countable > VBIF2_PERF_CNT_SEL_MASK) return -EINVAL; Loading Loading
drivers/gpu/msm/adreno.c +10 −120 Original line number Diff line number Diff line Loading @@ -1243,86 +1243,6 @@ static bool regulators_left_on(struct kgsl_device *device) return false; } static void _setup_throttling_counters(struct adreno_device *adreno_dev) { int i, ret; if (!adreno_is_a540(adreno_dev)) return; if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) return; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { /* reset throttled cycles ivalue */ adreno_dev->busy_data.throttle_cycles[i] = 0; if (adreno_dev->gpmu_throttle_counters[i] != 0) continue; ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_GPMU_PWR, ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i, &adreno_dev->gpmu_throttle_counters[i], NULL, PERFCOUNTER_FLAG_KERNEL); WARN_ONCE(ret, "Unable to get clock throttling counter %x\n", ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i); } } /* FW driven idle 10% throttle */ #define IDLE_10PCT 0 /* number of cycles when clock is throttled by 50% (CRC) */ #define CRC_50PCT 1 /* number of cycles when clock is throttled by more than 50% (CRC) */ #define CRC_MORE50PCT 2 /* number of cycles when clock is throttle by less than 50% (CRC) */ #define CRC_LESS50PCT 3 static uint64_t _read_throttling_counters(struct adreno_device *adreno_dev) { int i, adj; 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)) return 0; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { if (!adreno_dev->gpmu_throttle_counters[i]) return 0; th[i] = counter_delta(KGSL_DEVICE(adreno_dev), adreno_dev->gpmu_throttle_counters[i], &busy->throttle_cycles[i]); } adj = th[CRC_MORE50PCT] - th[IDLE_10PCT]; adj = th[CRC_50PCT] + th[CRC_LESS50PCT] / 3 + (adj < 0 ? 0 : adj) * 3; trace_kgsl_clock_throttling( th[IDLE_10PCT], th[CRC_50PCT], th[CRC_MORE50PCT], th[CRC_LESS50PCT], adj); return adj; } static void _update_threshold_count(struct adreno_device *adreno_dev, uint64_t adj) { if (adreno_is_a530(adreno_dev)) kgsl_regread(KGSL_DEVICE(adreno_dev), adreno_dev->lm_threshold_count, &adreno_dev->lm_threshold_cross); else if (adreno_is_a540(adreno_dev)) adreno_dev->lm_threshold_cross = adj; } static void _set_secvid(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); Loading Loading @@ -1419,8 +1339,8 @@ static int _adreno_start(struct adreno_device *adreno_dev) } } if (device->pwrctrl.bus_control) { if (device->pwrctrl.bus_control) { /* VBIF waiting for RAM */ if (adreno_dev->starved_ram_lo == 0) { ret = adreno_perfcounter_get(adreno_dev, Loading Loading @@ -1456,20 +1376,6 @@ static int _adreno_start(struct adreno_device *adreno_dev) adreno_dev->busy_data.vbif_ram_cycles = 0; adreno_dev->busy_data.vbif_starved_ram = 0; if (adreno_is_a530(adreno_dev) && ADRENO_FEATURE(adreno_dev, ADRENO_LM) && adreno_dev->lm_threshold_count == 0) { ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 27, &adreno_dev->lm_threshold_count, NULL, PERFCOUNTER_FLAG_KERNEL); /* Ignore noncritical ret - used for debugfs */ if (ret) adreno_dev->lm_threshold_count = 0; } _setup_throttling_counters(adreno_dev); /* Restore performance counter registers with saved values */ adreno_perfcounter_restore(adreno_dev); Loading Loading @@ -2576,27 +2482,6 @@ static inline s64 adreno_ticks_to_us(u32 ticks, u32 freq) return ticks / freq; } static unsigned int counter_delta(struct kgsl_device *device, unsigned int reg, unsigned int *counter) { unsigned int val; unsigned int ret = 0; /* Read the value */ kgsl_regread(device, reg, &val); /* Return 0 for the first read */ if (*counter != 0) { if (val < *counter) ret = (0xFFFFFFFF - *counter) + val; else ret = val - *counter; } *counter = val; return ret; } /** * adreno_power_stats() - Reads the counters needed for freq decisions * @device: Pointer to device whose counters are read Loading @@ -2608,6 +2493,7 @@ static void adreno_power_stats(struct kgsl_device *device, struct kgsl_power_stats *stats) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct adreno_busy_data *busy = &adreno_dev->busy_data; uint64_t adj = 0; Loading @@ -2621,8 +2507,11 @@ static void adreno_power_stats(struct kgsl_device *device, gpu_busy = counter_delta(device, adreno_dev->perfctr_pwr_lo, &busy->gpu_busy); adj = _read_throttling_counters(adreno_dev); if (gpudev->read_throttling_counters) { adj = gpudev->read_throttling_counters(adreno_dev); gpu_busy += adj; } stats->busy_time = adreno_ticks_to_us(gpu_busy, kgsl_pwrctrl_active_freq(pwr)); } Loading @@ -2643,8 +2532,9 @@ static void adreno_power_stats(struct kgsl_device *device, stats->ram_time = ram_cycles; stats->ram_wait = starved_ram; } if (adreno_dev->lm_threshold_count) _update_threshold_count(adreno_dev, adj); if (adreno_dev->lm_threshold_count && gpudev->count_throttles) gpudev->count_throttles(adreno_dev, adj); } static unsigned int adreno_gpuid(struct kgsl_device *device, Loading
drivers/gpu/msm/adreno.h +24 −0 Original line number Diff line number Diff line Loading @@ -756,6 +756,10 @@ struct adreno_gpudev { void (*pwrlevel_change_settings)(struct adreno_device *, unsigned int prelevel, unsigned int postlevel, bool post); uint64_t (*read_throttling_counters)(struct adreno_device *); void (*count_throttles)(struct adreno_device *, uint64_t adj); int (*enable_pwr_counters)(struct adreno_device *, unsigned int counter); unsigned int (*preemption_pre_ibsubmit)(struct adreno_device *, struct adreno_ringbuffer *rb, unsigned int *, struct kgsl_context *); Loading Loading @@ -1466,4 +1470,24 @@ static inline void adreno_ringbuffer_set_pagetable(struct adreno_ringbuffer *rb, spin_unlock_irqrestore(&rb->preempt_lock, flags); } static inline unsigned int counter_delta(struct kgsl_device *device, unsigned int reg, unsigned int *counter) { unsigned int val; unsigned int ret = 0; /* Read the value */ kgsl_regread(device, reg, &val); /* Return 0 for the first read */ if (*counter != 0) { if (val < *counter) ret = (0xFFFFFFFF - *counter) + val; else ret = val - *counter; } *counter = val; return ret; } #endif /*__ADRENO_H */
drivers/gpu/msm/adreno_a5xx.c +122 −16 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include "kgsl_sharedmem.h" #include "kgsl_log.h" #include "kgsl.h" #include "kgsl_trace.h" #include "adreno_a5xx_packets.h" static int zap_ucode_loaded; Loading Loading @@ -1543,6 +1544,76 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev, } } static void a5xx_count_throttles(struct adreno_device *adreno_dev, uint64_t adj) { if (adreno_is_a530(adreno_dev)) kgsl_regread(KGSL_DEVICE(adreno_dev), adreno_dev->lm_threshold_count, &adreno_dev->lm_threshold_cross); else if (adreno_is_a540(adreno_dev)) adreno_dev->lm_threshold_cross = adj; } static int a5xx_enable_pwr_counters(struct adreno_device *adreno_dev, unsigned int counter) { /* * On 5XX we have to emulate the PWR counters which are physically * missing. Program countable 6 on RBBM_PERFCTR_RBBM_0 as a substitute * for PWR:1. Don't emulate PWR:0 as nobody uses it and we don't want * to take away too many of the generic RBBM counters. */ if (counter == 0) return -EINVAL; kgsl_regwrite(KGSL_DEVICE(adreno_dev), A5XX_RBBM_PERFCTR_RBBM_SEL_0, 6); return 0; } /* FW driven idle 10% throttle */ #define IDLE_10PCT 0 /* number of cycles when clock is throttled by 50% (CRC) */ #define CRC_50PCT 1 /* number of cycles when clock is throttled by more than 50% (CRC) */ #define CRC_MORE50PCT 2 /* number of cycles when clock is throttle by less than 50% (CRC) */ #define CRC_LESS50PCT 3 static uint64_t a5xx_read_throttling_counters(struct adreno_device *adreno_dev) { int i, adj; 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)) return 0; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { if (!adreno_dev->gpmu_throttle_counters[i]) return 0; th[i] = counter_delta(KGSL_DEVICE(adreno_dev), adreno_dev->gpmu_throttle_counters[i], &busy->throttle_cycles[i]); } adj = th[CRC_MORE50PCT] - th[IDLE_10PCT]; adj = th[CRC_50PCT] + th[CRC_LESS50PCT] / 3 + (adj < 0 ? 0 : adj) * 3; trace_kgsl_clock_throttling( th[IDLE_10PCT], th[CRC_50PCT], th[CRC_MORE50PCT], th[CRC_LESS50PCT], adj); return adj; } static void a5xx_enable_64bit(struct adreno_device *adreno_dev) { Loading Loading @@ -1599,12 +1670,44 @@ static void a5xx_gpmu_reset(struct work_struct *work) /* Soft reset of the GPMU block */ kgsl_regwrite(device, A5XX_RBBM_BLOCK_SW_RESET_CMD, BIT(16)); /* GPU comes up in secured mode, make it unsecured by default */ if (!ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)) kgsl_regwrite(device, A5XX_RBBM_SECVID_TRUST_CNTL, 0x0); a5xx_gpmu_init(adreno_dev); out: mutex_unlock(&device->mutex); } static void _setup_throttling_counters(struct adreno_device *adreno_dev) { int i, ret; if (!adreno_is_a540(adreno_dev)) return; if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) return; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { /* reset throttled cycles ivalue */ adreno_dev->busy_data.throttle_cycles[i] = 0; if (adreno_dev->gpmu_throttle_counters[i] != 0) continue; ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_GPMU_PWR, ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i, &adreno_dev->gpmu_throttle_counters[i], NULL, PERFCOUNTER_FLAG_KERNEL); WARN_ONCE(ret, "Unable to get clock throttling counter %x\n", ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i); } } /* * a5xx_start() - Device start * @adreno_dev: Pointer to adreno device Loading @@ -1616,6 +1719,21 @@ static void a5xx_start(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); unsigned int bit; int ret; if (adreno_is_a530(adreno_dev) && ADRENO_FEATURE(adreno_dev, ADRENO_LM) && adreno_dev->lm_threshold_count == 0) { ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 27, &adreno_dev->lm_threshold_count, NULL, PERFCOUNTER_FLAG_KERNEL); /* Ignore noncritical ret - used for debugfs */ if (ret) adreno_dev->lm_threshold_count = 0; } _setup_throttling_counters(adreno_dev); adreno_vbif_start(adreno_dev, a5xx_vbif_platforms, ARRAY_SIZE(a5xx_vbif_platforms)); Loading Loading @@ -1921,11 +2039,6 @@ static int a5xx_post_start(struct adreno_device *adreno_dev) static int a5xx_gpmu_init(struct adreno_device *adreno_dev) { int ret; struct kgsl_device *device = KGSL_DEVICE(adreno_dev); /* GPU comes up in secured mode, make it unsecured by default */ if (!ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)) kgsl_regwrite(device, A5XX_RBBM_SECVID_TRUST_CNTL, 0x0); /* Set up LM before initializing the GPMU */ a5xx_lm_init(adreno_dev); Loading Loading @@ -2246,20 +2359,10 @@ static int a5xx_rb_start(struct adreno_device *adreno_dev, if (ret) return ret; /* Set up LM before initializing the GPMU */ a5xx_lm_init(adreno_dev); /* Enable SPTP based power collapse before enabling GPMU */ a5xx_enable_pc(adreno_dev); /* Program the GPMU */ ret = a5xx_gpmu_start(adreno_dev); ret = a5xx_gpmu_init(adreno_dev); if (ret) return ret; /* Enable limits management */ a5xx_lm_enable(adreno_dev); a5xx_post_start(adreno_dev); return 0; Loading Loading @@ -3421,6 +3524,9 @@ struct adreno_gpudev adreno_a5xx_gpudev = { .regulator_enable = a5xx_regulator_enable, .regulator_disable = a5xx_regulator_disable, .pwrlevel_change_settings = a5xx_pwrlevel_change_settings, .read_throttling_counters = a5xx_read_throttling_counters, .count_throttles = a5xx_count_throttles, .enable_pwr_counters = a5xx_enable_pwr_counters, .preemption_pre_ibsubmit = a5xx_preemption_pre_ibsubmit, .preemption_yield_enable = a5xx_preemption_yield_enable, Loading
drivers/gpu/msm/adreno_perfcounter.c +4 −23 Original line number Diff line number Diff line Loading @@ -598,28 +598,6 @@ int adreno_perfcounter_put(struct adreno_device *adreno_dev, return -EINVAL; } static int _perfcounter_enable_pwr(struct adreno_device *adreno_dev, unsigned int counter) { /* PWR counters enabled by default on A3XX/A4XX so nothing to do */ if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev)) return 0; /* * On 5XX we have to emulate the PWR counters which are physically * missing. Program countable 6 on RBBM_PERFCTR_RBBM_0 as a substitute * for PWR:1. Don't emulate PWR:0 as nobody uses it and we don't want * to take away too many of the generic RBBM counters. */ if (counter == 0) return -EINVAL; kgsl_regwrite(KGSL_DEVICE(adreno_dev), A5XX_RBBM_PERFCTR_RBBM_SEL_0, 6); return 0; } static void _perfcounter_enable_vbif(struct adreno_device *adreno_dev, struct adreno_perfcounters *counters, unsigned int counter, unsigned int countable) Loading Loading @@ -771,6 +749,7 @@ static int adreno_perfcounter_enable(struct adreno_device *adreno_dev, unsigned int group, unsigned int counter, unsigned int countable) { struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (counters == NULL) return -EINVAL; Loading @@ -786,7 +765,9 @@ static int adreno_perfcounter_enable(struct adreno_device *adreno_dev, /* alwayson counter is global, so init value is 0 */ break; case KGSL_PERFCOUNTER_GROUP_PWR: return _perfcounter_enable_pwr(adreno_dev, counter); if (gpudev->enable_pwr_counters) return gpudev->enable_pwr_counters(adreno_dev, counter); return 0; case KGSL_PERFCOUNTER_GROUP_VBIF: if (countable > VBIF2_PERF_CNT_SEL_MASK) return -EINVAL; Loading