mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
msm: kgsl: Add APIs to provide GPU stats
Add APIs which provide per GPU freq active and total time, number of GPU frequency corners and number of frames processed by GPU. Change-Id: If42e76a435a4766a3de0b9b028d48b6c1759e466 Signed-off-by: Deepak Kumar <dkumar@codeaurora.org>
This commit is contained in:
parent
dc1e3e8117
commit
e646feb198
12 changed files with 144 additions and 4 deletions
|
|
@ -2948,6 +2948,8 @@ static int a6xx_boot(struct adreno_device *adreno_dev)
|
|||
kgsl_pwrscale_wake(device);
|
||||
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -3016,6 +3018,7 @@ static int a6xx_first_boot(struct adreno_device *adreno_dev)
|
|||
set_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags);
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -3277,6 +3280,8 @@ static void a6xx_gmu_touch_wakeup(struct adreno_device *adreno_dev)
|
|||
kgsl_pwrscale_wake(device);
|
||||
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
|
@ -500,6 +500,7 @@ static void a6xx_hwsched_touch_wakeup(struct adreno_device *adreno_dev)
|
|||
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -541,6 +542,8 @@ static int a6xx_hwsched_boot(struct adreno_device *adreno_dev)
|
|||
kgsl_pwrscale_wake(device);
|
||||
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -589,6 +592,7 @@ static int a6xx_hwsched_first_boot(struct adreno_device *adreno_dev)
|
|||
set_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags);
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
|
|||
|
|
@ -896,6 +896,7 @@ static int a6xx_boot(struct adreno_device *adreno_dev)
|
|||
|
||||
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -934,6 +935,7 @@ static void a6xx_rgmu_touch_wakeup(struct adreno_device *adreno_dev)
|
|||
|
||||
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -1002,6 +1004,7 @@ static int a6xx_first_boot(struct adreno_device *adreno_dev)
|
|||
set_bit(RGMU_PRIV_FIRST_BOOT_DONE, &rgmu->flags);
|
||||
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
|
|||
|
|
@ -304,6 +304,9 @@ static void _retire_timestamp(struct kgsl_drawobj *drawobj)
|
|||
context->id, drawobj->timestamp,
|
||||
!!(drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME));
|
||||
|
||||
if (drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME)
|
||||
atomic64_inc(&context->proc_priv->frame_count);
|
||||
|
||||
/*
|
||||
* For A3xx we still get the rptr from the CP_RB_RPTR instead of
|
||||
* rptr scratch out address. At this point GPU clocks turned off.
|
||||
|
|
@ -2355,6 +2358,9 @@ static void retire_cmdobj(struct adreno_device *adreno_dev,
|
|||
context->id, drawobj->timestamp,
|
||||
!!(drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME));
|
||||
|
||||
if (drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME)
|
||||
atomic64_inc(&context->proc_priv->frame_count);
|
||||
|
||||
/*
|
||||
* For A3xx we still get the rptr from the CP_RB_RPTR instead of
|
||||
* rptr scratch out address. At this point GPU clocks turned off.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/ion.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/msm_kgsl.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
|
@ -1043,6 +1044,24 @@ done:
|
|||
return private;
|
||||
}
|
||||
|
||||
int kgsl_gpu_frame_count(pid_t pid, u64 *frame_count)
|
||||
{
|
||||
struct kgsl_process_private *p;
|
||||
|
||||
if (!frame_count)
|
||||
return -EINVAL;
|
||||
|
||||
p = kgsl_process_private_find(pid);
|
||||
if (!p)
|
||||
return -ENOENT;
|
||||
|
||||
*frame_count = atomic64_read(&p->frame_count);
|
||||
kgsl_process_private_put(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_gpu_frame_count);
|
||||
|
||||
static int kgsl_close_device(struct kgsl_device *device)
|
||||
{
|
||||
int result = 0;
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
#ifndef __KGSL_H
|
||||
#define __KGSL_H
|
||||
|
||||
#include <uapi/linux/msm_kgsl.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/msm_kgsl.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "kgsl_gmu_core.h"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2013-2017,2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2017,2019,2021 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef __KGSL_COMPAT_H
|
||||
#define __KGSL_COMPAT_H
|
||||
|
||||
#include <uapi/linux/msm_kgsl.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/msm_kgsl.h>
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
|
|
|
|||
|
|
@ -437,6 +437,7 @@ struct kgsl_context {
|
|||
* @fd_count: Counter for the number of FDs for this process
|
||||
* @ctxt_count: Count for the number of contexts for this process
|
||||
* @ctxt_count_lock: Spinlock to protect ctxt_count
|
||||
* @frame_count: Count for the number of frames processed
|
||||
*/
|
||||
struct kgsl_process_private {
|
||||
unsigned long priv;
|
||||
|
|
@ -460,6 +461,7 @@ struct kgsl_process_private {
|
|||
int fd_count;
|
||||
atomic_t ctxt_count;
|
||||
spinlock_t ctxt_count_lock;
|
||||
atomic64_t frame_count;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/msm_kgsl.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
|
@ -1878,6 +1879,7 @@ static int _wake(struct kgsl_device *device)
|
|||
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE);
|
||||
|
||||
device->ftbl->deassert_gbif_halt(device);
|
||||
pwr->last_stat_updated = ktime_get();
|
||||
/*
|
||||
* No need to turn on/off irq here as it no longer affects
|
||||
* power collapse
|
||||
|
|
@ -2258,3 +2260,42 @@ int kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device)
|
|||
/* Request adjusted DCVS level */
|
||||
return device->ftbl->gpu_clock_set(device, pwr->active_pwrlevel);
|
||||
}
|
||||
|
||||
int kgsl_gpu_num_freqs(void)
|
||||
{
|
||||
struct kgsl_device *device = kgsl_get_device(0);
|
||||
|
||||
if (!device)
|
||||
return -ENODEV;
|
||||
|
||||
return device->pwrctrl.num_pwrlevels;
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_gpu_num_freqs);
|
||||
|
||||
int kgsl_gpu_stat(struct kgsl_gpu_freq_stat *stats, u32 numfreq)
|
||||
{
|
||||
struct kgsl_device *device = kgsl_get_device(0);
|
||||
struct kgsl_pwrctrl *pwr;
|
||||
int i;
|
||||
|
||||
if (!device)
|
||||
return -ENODEV;
|
||||
|
||||
pwr = &device->pwrctrl;
|
||||
|
||||
if (!stats || (numfreq < pwr->num_pwrlevels))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&device->mutex);
|
||||
kgsl_pwrscale_update_stats(device);
|
||||
|
||||
for (i = 0; i < pwr->num_pwrlevels; i++) {
|
||||
stats[i].freq = pwr->pwrlevels[i].gpu_freq;
|
||||
stats[i].active_time = pwr->clock_times[i];
|
||||
stats[i].idle_time = pwr->time_in_pwrlevel[i] - pwr->clock_times[i];
|
||||
}
|
||||
mutex_unlock(&device->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_gpu_stat);
|
||||
|
|
|
|||
|
|
@ -175,6 +175,10 @@ struct kgsl_pwrctrl {
|
|||
u32 minbw_timeout;
|
||||
/** @ddr_qos_devfreq: Devfreq device for setting DDR qos policy */
|
||||
struct devfreq *ddr_qos_devfreq;
|
||||
/** @time_in_pwrlevel: Each pwrlevel active duration in usec */
|
||||
u64 time_in_pwrlevel[KGSL_MAX_PWRLEVELS];
|
||||
/** @last_stat_updated: The last time stats were updated */
|
||||
ktime_t last_stat_updated;
|
||||
};
|
||||
|
||||
int kgsl_pwrctrl_init(struct kgsl_device *device);
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device)
|
|||
|
||||
if (device->state == KGSL_STATE_ACTIVE) {
|
||||
struct kgsl_power_stats stats;
|
||||
ktime_t cur_time = ktime_get();
|
||||
|
||||
device->ftbl->power_stats(device, &stats);
|
||||
device->pwrscale.accum_stats.busy_time += stats.busy_time;
|
||||
|
|
@ -129,6 +130,9 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device)
|
|||
device->pwrscale.accum_stats.ram_wait += stats.ram_wait;
|
||||
pwrctrl->clock_times[pwrctrl->active_pwrlevel] +=
|
||||
stats.busy_time;
|
||||
pwrctrl->time_in_pwrlevel[pwrctrl->active_pwrlevel] +=
|
||||
ktime_us_delta(cur_time, pwrctrl->last_stat_updated);
|
||||
pwrctrl->last_stat_updated = cur_time;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
52
include/linux/msm_kgsl.h
Normal file
52
include/linux/msm_kgsl.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef _MSM_KGSL_H
|
||||
#define _MSM_KGSL_H
|
||||
|
||||
/**
|
||||
* struct kgsl_gpu_freq_stat - Per GPU freq stat struct
|
||||
* @freq: GPU frequency in Hz
|
||||
* @active_time: GPU busy time in usecs
|
||||
* @idle_time: GPU idle time in usec
|
||||
*/
|
||||
struct kgsl_gpu_freq_stat {
|
||||
u32 freq;
|
||||
u64 active_time;
|
||||
u64 idle_time;
|
||||
};
|
||||
|
||||
/**
|
||||
* kgsl_gpu_num_freqs - Get number of available GPU frequencies
|
||||
*
|
||||
* Return: number of available frequencies on success or negative error
|
||||
* on failure
|
||||
*/
|
||||
int kgsl_gpu_num_freqs(void);
|
||||
|
||||
/**
|
||||
* kgsl_gpu_stat - Get per GPU freq stats
|
||||
* @stats: Array of struct kgsl_gpu_freq_stat to hold stats
|
||||
* @numfreq: Number of entries in @stats
|
||||
*
|
||||
* This function will populate @stats with per freq stats.
|
||||
* Number of entries in @stats array must be greater or
|
||||
* equal to value returned by function kgsl_gpu_num_freqs
|
||||
*
|
||||
* Return: 0 on success or negative error on failure
|
||||
*/
|
||||
int kgsl_gpu_stat(struct kgsl_gpu_freq_stat *stats, u32 numfreq);
|
||||
|
||||
/**
|
||||
* kgsl_gpu_frame_count - Get number of frames already processed by GPU
|
||||
* @pid: pid of the process for which frame count is required
|
||||
* @frame_count: pointer to a u64 to store frame count
|
||||
*
|
||||
* Return: zero on success and number of frames processed corresponding
|
||||
* to @pid in @frame_count or negative error on failure
|
||||
*/
|
||||
int kgsl_gpu_frame_count(pid_t pid, u64 *frame_count);
|
||||
|
||||
#endif /* _MSM_KGSL_H */
|
||||
|
||||
Loading…
Reference in a new issue