summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/pmu
diff options
context:
space:
mode:
authorPeng Liu <pengliu@nvidia.com>2018-10-30 16:45:43 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2019-04-01 18:27:17 -0400
commit3a11883f7f4399ae8dffbea00c1842e3c2095937 (patch)
tree82d36197046e73c13432250ec4ebce0da21791d5 /drivers/gpu/nvgpu/common/pmu
parentf1be222687a853b0218a5700a213f3d34d8ccc4f (diff)
gpu: nvgpu: using pmu counters for load estimate
PMU counters #0 and #4 are used to count total cycles and busy cycles. These counts are used by podgov to estimate GPU load. PMU idle intr status register is used to monitor overflow. Overflow rarely occurs because frequency governor reads and resets the counters at a high cadence. When overflow occurs, 100% work load is reported to frequency governor. Bug 1963732 Change-Id: I046480ebde162e6eda24577932b96cfd91b77c69 Signed-off-by: Peng Liu <pengliu@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1939547 (cherry picked from commit 34df0035194e0203f68f679acdd84e5533a48149) Reviewed-on: https://git-master.nvidia.com/r/1979495 Reviewed-by: Aaron Tian <atian@nvidia.com> Tested-by: Aaron Tian <atian@nvidia.com> Reviewed-by: Rajkumar Kasirajan <rkasirajan@nvidia.com> Tested-by: Rajkumar Kasirajan <rkasirajan@nvidia.com> Reviewed-by: Bibek Basu <bbasu@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common/pmu')
-rw-r--r--drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c b/drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c
index 57a4ea40..bf07bd79 100644
--- a/drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c
+++ b/drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c
@@ -236,6 +236,48 @@ int nvgpu_pmu_load_update(struct gk20a *g)
236 return 0; 236 return 0;
237} 237}
238 238
239int nvgpu_pmu_busy_cycles_norm(struct gk20a *g, u32 *norm)
240{
241 u64 busy_cycles, total_cycles;
242 u32 intr_status;
243
244 gk20a_busy_noresume(g);
245 if (!g->power_on) {
246 *norm = 0;
247 goto exit;
248 }
249
250 if (g->ops.pmu.pmu_read_idle_counter == NULL ||
251 g->ops.pmu.pmu_reset_idle_counter == NULL ||
252 g->ops.pmu.pmu_read_idle_intr_status == NULL ||
253 g->ops.pmu.pmu_clear_idle_intr_status == NULL) {
254 *norm = PMU_BUSY_CYCLES_NORM_MAX;
255 goto exit;
256 }
257
258 busy_cycles = g->ops.pmu.pmu_read_idle_counter(g, 4);
259 total_cycles = g->ops.pmu.pmu_read_idle_counter(g, 0);
260 intr_status = g->ops.pmu.pmu_read_idle_intr_status(g);
261
262 g->ops.pmu.pmu_reset_idle_counter(g, 4);
263 g->ops.pmu.pmu_reset_idle_counter(g, 0);
264
265 if (intr_status != 0UL) {
266 *norm = PMU_BUSY_CYCLES_NORM_MAX;
267 g->ops.pmu.pmu_clear_idle_intr_status(g);
268 } else if (total_cycles == 0ULL || busy_cycles > total_cycles) {
269 *norm = PMU_BUSY_CYCLES_NORM_MAX;
270 } else {
271 *norm = (u32)(busy_cycles * PMU_BUSY_CYCLES_NORM_MAX
272 / total_cycles);
273 }
274
275exit:
276 gk20a_idle_nosuspend(g);
277
278 return 0;
279}
280
239void nvgpu_pmu_get_load_counters(struct gk20a *g, u32 *busy_cycles, 281void nvgpu_pmu_get_load_counters(struct gk20a *g, u32 *busy_cycles,
240 u32 *total_cycles) 282 u32 *total_cycles)
241{ 283{