Merge "msm-perf: Kgsl events collection for perf"

This commit is contained in:
qctecmdr 2020-09-09 18:24:29 -07:00 committed by Gerrit - the friendly Code Review server
commit 5a6978730b
2 changed files with 175 additions and 0 deletions

View File

@ -18,6 +18,11 @@
#include <linux/input.h>
#include <linux/kthread.h>
#include <linux/sched/core_ctl.h>
#include <soc/qcom/msm_performance.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <linux/circ_buf.h>
#include <linux/ktime.h>
/*
* Sched will provide the data for every 20ms window,
@ -26,6 +31,7 @@
*/
#define POLL_INT 25
#define NODE_NAME_MAX_CHARS 16
#define QUEUE_POOL_SIZE 512 /*2^8 always keep in 2^x */
enum cpu_clusters {
MIN = 0,
@ -42,6 +48,25 @@ struct cpu_status {
static DEFINE_PER_CPU(struct cpu_status, msm_perf_cpu_stats);
static DEFINE_PER_CPU(struct freq_qos_request, qos_req_min);
static DEFINE_PER_CPU(struct freq_qos_request, qos_req_max);
static DECLARE_COMPLETION(gfx_evt_arrival);
struct gpu_data {
pid_t pid;
int ctx_id;
unsigned int timestamp;
ktime_t arrive_ts;
int evt_typ;
};
static struct gpu_data gpu_circ_buff[QUEUE_POOL_SIZE];
struct queue_indicies {
int head;
int tail;
};
static struct queue_indicies curr_pos;
static DEFINE_SPINLOCK(gfx_circ_buff_lock);
struct events {
spinlock_t cpu_hotplug_lock;
@ -59,6 +84,9 @@ static unsigned int curr_cap[CLUSTER_MAX];
static cpumask_var_t limit_mask_min;
static cpumask_var_t limit_mask_max;
static atomic_t game_status;
static atomic_t game_status_pid;
static bool ready_for_freq_updates;
static int freq_qos_request_init(void)
@ -314,6 +342,45 @@ static struct attribute_group events_attr_group = {
.attrs = events_attrs,
};
static ssize_t show_perf_gfx_evts(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
struct queue_indicies updated_pos;
unsigned long flags;
ssize_t retval = 0;
int idx = 0, size, act_idx, ret = -1;
ret = wait_for_completion_interruptible(&gfx_evt_arrival);
if (ret)
return 0;
spin_lock_irqsave(&gfx_circ_buff_lock, flags);
updated_pos.head = curr_pos.head;
updated_pos.tail = curr_pos.tail;
size = CIRC_CNT(updated_pos.head, updated_pos.tail, QUEUE_POOL_SIZE);
curr_pos.tail = (curr_pos.tail + size) % QUEUE_POOL_SIZE;
spin_unlock_irqrestore(&gfx_circ_buff_lock, flags);
for (idx = 0; idx < size; idx++) {
act_idx = (updated_pos.tail + idx) % QUEUE_POOL_SIZE;
retval += scnprintf(buf + retval, PAGE_SIZE - retval,
"%d %d %u %d %lu :",
gpu_circ_buff[act_idx].pid,
gpu_circ_buff[act_idx].ctx_id,
gpu_circ_buff[act_idx].timestamp,
gpu_circ_buff[act_idx].evt_typ,
ktime_to_us(gpu_circ_buff[act_idx].arrive_ts));
if (retval >= PAGE_SIZE) {
pr_err("msm_perf:data limit exceed\n");
break;
}
}
return retval;
}
static struct kobj_attribute gfx_event_info_attr =
__ATTR(gfx_evt, 0444, show_perf_gfx_evts, NULL);
static ssize_t show_big_nr(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
@ -364,6 +431,7 @@ static struct attribute *notify_attrs[] = {
&top_load_attr.attr,
&cluster_top_load_attr.attr,
&cluster_curr_cap_attr.attr,
&gfx_event_info_attr.attr,
NULL,
};
@ -554,6 +622,84 @@ static const struct kernel_param_ops param_ops_cc_register = {
module_param_cb(core_ctl_register, &param_ops_cc_register,
&core_ctl_register, 0644);
void msm_perf_events_update(enum evt_update_t update_typ,
enum gfx_evt_t evt_typ, pid_t pid,
uint32_t ctx_id, uint32_t timestamp)
{
unsigned long flags;
int idx = 0;
if (update_typ != MSM_PERF_GFX)
return;
if (!atomic_read(&game_status) ||
(pid != atomic_read(&game_status_pid)))
return;
spin_lock_irqsave(&gfx_circ_buff_lock, flags);
idx = curr_pos.head;
curr_pos.head = ((curr_pos.head + 1) % QUEUE_POOL_SIZE);
spin_unlock_irqrestore(&gfx_circ_buff_lock, flags);
gpu_circ_buff[idx].pid = pid;
gpu_circ_buff[idx].ctx_id = ctx_id;
gpu_circ_buff[idx].timestamp = timestamp;
gpu_circ_buff[idx].evt_typ = evt_typ;
gpu_circ_buff[idx].arrive_ts = ktime_get();
if (evt_typ == MSM_PERF_QUEUE || evt_typ == MSM_PERF_RETIRED)
complete(&gfx_evt_arrival);
}
static int set_game_start_event(const char *buf, const struct kernel_param *kp)
{
long usr_val = 0;
int ret = strlen(buf);
kstrtol(buf, 0, &usr_val);
atomic_set(&game_status, usr_val);
return ret;
}
static int get_game_start_event(char *buf, const struct kernel_param *kp)
{
long usr_val = atomic_read(&game_status);
return scnprintf(buf, PAGE_SIZE, "%ld\n", usr_val);
}
static const struct kernel_param_ops param_ops_game_start_evt = {
.set = set_game_start_event,
.get = get_game_start_event,
};
module_param_cb(evnt_gplaf_status, &param_ops_game_start_evt, NULL, 0644);
static int set_game_start_pid(const char *buf, const struct kernel_param *kp)
{
long usr_val = 0;
int ret = strlen(buf);
kstrtol(buf, 0, &usr_val);
atomic_set(&game_status_pid, usr_val);
return ret;
}
static int get_game_start_pid(char *buf, const struct kernel_param *kp)
{
long usr_val = atomic_read(&game_status_pid);
return scnprintf(buf, PAGE_SIZE, "%ld\n", usr_val);
}
static const struct kernel_param_ops param_ops_game_start_pid = {
.set = set_game_start_pid,
.get = get_game_start_pid,
};
module_param_cb(evnt_gplaf_pid, &param_ops_game_start_pid, NULL, 0644);
/*******************************GFX Call************************************/
static int __init msm_performance_init(void)
{
int ret;

View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef __MSM_PERFORMANCE_H
#define __MSM_PERFORMANCE_H
enum gfx_evt_t {
MSM_PERF_INVAL,
MSM_PERF_QUEUE,
MSM_PERF_SUBMIT,
MSM_PERF_RETIRED
};
enum evt_update_t {
MSM_PERF_GFX,
};
#ifdef CONFIG_MSM_PERFORMANCE
void msm_perf_events_update(enum evt_update_t update_typ,
enum gfx_evt_t evt_typ, pid_t pid,
uint32_t ctx_id, uint32_t timestamp);
#else
static inline void msm_perf_events_update(enum evt_update_t update_typ,
enum gfx_evt_t evt_typ, pid_t pid,
uint32_t ctx_id, uint32_t timestamp){}
#endif
#endif