Squashed backup commit (no shallow-clone history issues) of xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2 branch, upstream commit 9eece662e) plus all fixes applied to get everpal_defconfig building clean against a modern (GCC 15.2.0) toolchain -- see the previous commit message on the lineage-23.2 branch (also in this repo history is not available here since this is a squashed snapshot; full incremental history lives in the local DL380 checkout and the upstream GitHub remote). Upstream: https://github.com/xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2)
634 lines
15 KiB
C
634 lines
15 KiB
C
/*
|
|
* Copyright (C) 2018 MediaTek Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
|
|
*/
|
|
|
|
#include <trace/events/sched.h>
|
|
#include <trace/events/mtk_events.h>
|
|
|
|
#ifdef CONFIG_MTK_DRAMC
|
|
#include <mtk_dramc.h>
|
|
#endif
|
|
|
|
#include <linux/mm.h>
|
|
#include <linux/swap.h>
|
|
#include <mt-plat/mtk_blocktag.h>
|
|
#include <helio-dvfsrc.h>
|
|
#include <linux/jiffies.h>
|
|
|
|
#include <linux/module.h>
|
|
#ifndef __CHECKER__
|
|
#define CREATE_TRACE_POINTS
|
|
#include "perf_tracker_trace.h"
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_QOS_FRAMEWORK
|
|
#include <mtk_qos_sram.h>
|
|
#endif
|
|
|
|
#ifdef QOS_SHARE_SUPPORT
|
|
#include <mtk_qos_share.h>
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_PERF_OBSERVER
|
|
#include <mt-plat/mtk_perfobserver.h>
|
|
#endif
|
|
|
|
#include <mt-plat/perf_tracker.h>
|
|
#include <linux/arch_topology.h>
|
|
#include "perf_tracker_internal.h"
|
|
|
|
#ifdef CONFIG_MTK_SKB_OWNER
|
|
#include <net/sock.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/ip.h>
|
|
#include <linux/tcp.h>
|
|
#include <linux/udp.h>
|
|
#include <net/tcp.h>
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_GAUGE_VERSION
|
|
#include <mt-plat/mtk_battery.h>
|
|
|
|
static void fuel_gauge_handler(struct work_struct *work);
|
|
|
|
static int fuel_gauge_enable;
|
|
static int fuel_gauge_delay; /* ms */
|
|
static DECLARE_DELAYED_WORK(fuel_gauge, fuel_gauge_handler);
|
|
#endif
|
|
|
|
static int perf_tracker_on, perf_tracker_init;
|
|
static DEFINE_MUTEX(perf_ctl_mutex);
|
|
static int cluster_nr = -1;
|
|
|
|
#ifdef CONFIG_MTK_GPU_SWPM_SUPPORT
|
|
unsigned int gpu_pmu_enable;
|
|
unsigned int is_gpu_pmu_worked;
|
|
unsigned int gpu_pmu_period = 8000000; //8ms
|
|
|
|
void (*MTKGPUPower_model_start_symbol)(unsigned int interval_ns);
|
|
void (*MTKGPUPower_model_stop_symbol)(void);
|
|
void (*MTKGPUPower_model_suspend_symbol)(void);
|
|
void (*MTKGPUPower_model_resume_symbol)(void);
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_SKB_OWNER
|
|
static int net_pkt_trace_enable;
|
|
#endif
|
|
|
|
#if !defined(CONFIG_MTK_BLOCK_TAG) || !defined(MTK_BTAG_FEATURE_MICTX_IOSTAT)
|
|
struct mtk_btag_mictx_iostat_struct {
|
|
__u64 duration; /* duration time for below performance data (ns) */
|
|
__u32 tp_req_r; /* throughput (per-request): read (KB/s) */
|
|
__u32 tp_req_w; /* throughput (per-request): write (KB/s) */
|
|
__u32 tp_all_r; /* throughput (overlapped) : read (KB/s) */
|
|
__u32 tp_all_w; /* throughput (overlapped) : write (KB/s) */
|
|
__u32 reqsize_r; /* request size : read (Bytes) */
|
|
__u32 reqsize_w; /* request size : write (Bytes) */
|
|
__u32 reqcnt_r; /* request count: read */
|
|
__u32 reqcnt_w; /* request count: write */
|
|
__u16 wl; /* storage device workload (%) */
|
|
__u16 top; /* ratio of request (size) by top-app */
|
|
__u16 q_depth; /* storage cmdq queue depth */
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_BLOCK_TAG
|
|
static struct mtk_btag_mictx_iostat_struct iostatptr;
|
|
|
|
void __attribute__((weak)) mtk_btag_mictx_enable(int enable) {}
|
|
|
|
int __attribute__((weak)) mtk_btag_mictx_get_data(
|
|
struct mtk_btag_mictx_iostat_struct *io)
|
|
{
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_GAUGE_VERSION
|
|
static void fuel_gauge_handler(struct work_struct *work)
|
|
{
|
|
int curr, volt;
|
|
|
|
if (!fuel_gauge_enable)
|
|
return;
|
|
|
|
/* read current(mA) and valtage(mV) from pmic */
|
|
curr = battery_get_bat_current();
|
|
volt = battery_get_bat_voltage();
|
|
|
|
trace_fuel_gauge(curr, volt);
|
|
|
|
queue_delayed_work(system_power_efficient_wq,
|
|
&fuel_gauge, msecs_to_jiffies(fuel_gauge_delay));
|
|
}
|
|
#endif
|
|
|
|
static void init_function_symbols(void)
|
|
{
|
|
#define _FUNC_SYMBOL_GET(_func_name_) \
|
|
do { \
|
|
_func_name_##_symbol = (void *)symbol_get(_func_name_); \
|
|
if (_func_name_##_symbol == NULL) { \
|
|
pr_debug("Symbol : %s is not found!\n", #_func_name_); \
|
|
} \
|
|
} while (0)
|
|
#ifdef CONFIG_MTK_GPU_SWPM_SUPPORT
|
|
_FUNC_SYMBOL_GET(MTKGPUPower_model_start);
|
|
_FUNC_SYMBOL_GET(MTKGPUPower_model_stop);
|
|
_FUNC_SYMBOL_GET(MTKGPUPower_model_suspend);
|
|
_FUNC_SYMBOL_GET(MTKGPUPower_model_resume);
|
|
#endif
|
|
}
|
|
|
|
int perf_tracker_enable(int val)
|
|
{
|
|
mutex_lock(&perf_ctl_mutex);
|
|
|
|
val = (val > 0) ? 1 : 0;
|
|
|
|
perf_tracker_on = val;
|
|
#ifdef CONFIG_MTK_BLOCK_TAG
|
|
mtk_btag_mictx_enable(val);
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_GPU_SWPM_SUPPORT
|
|
// GPU PMU Recording
|
|
if (val == 1 && gpu_pmu_enable && !is_gpu_pmu_worked) {
|
|
if (MTKGPUPower_model_start_symbol)
|
|
MTKGPUPower_model_start_symbol(gpu_pmu_period);
|
|
is_gpu_pmu_worked = 1;
|
|
} else if (val == 0 && is_gpu_pmu_worked) {
|
|
if (MTKGPUPower_model_stop_symbol)
|
|
MTKGPUPower_model_stop_symbol();
|
|
is_gpu_pmu_worked = 0;
|
|
}
|
|
#endif
|
|
|
|
mutex_unlock(&perf_ctl_mutex);
|
|
|
|
return (perf_tracker_on == val) ? 0 : -1;
|
|
}
|
|
|
|
unsigned int __attribute__((weak)) get_dram_data_rate(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
u32 __attribute__((weak)) qos_sram_read(u32 offset)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int __attribute__((weak)) get_cur_vcore_uv(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int __attribute__((weak)) get_cur_ddr_khz(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
unsigned int __attribute__((weak)) qos_rec_get_hist_bw(unsigned int idx, unsigned int type)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
unsigned int __attribute__((weak)) qos_rec_get_hist_data_bw(unsigned int idx, unsigned int type)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
unsigned int __attribute__((weak)) qos_rec_get_hist_idx(void)
|
|
{
|
|
return 0xFFFF;
|
|
}
|
|
|
|
|
|
static inline u32 cpu_stall_ratio(int cpu)
|
|
{
|
|
#ifdef CM_STALL_RATIO_OFFSET
|
|
return qos_sram_read(CM_STALL_RATIO_OFFSET + cpu * 4);
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
#define K(x) ((x) << (PAGE_SHIFT - 10))
|
|
#define max_cpus 8
|
|
#define bw_hist_nums 8
|
|
#define bw_record_nums 32
|
|
|
|
void __perf_tracker(u64 wallclock,
|
|
long mm_available,
|
|
long mm_free)
|
|
{
|
|
int dram_rate = 0;
|
|
#ifdef CONFIG_MTK_BLOCK_TAG
|
|
struct mtk_btag_mictx_iostat_struct *iostat = &iostatptr;
|
|
#endif
|
|
int bw_c = 0, bw_g = 0, bw_mm = 0, bw_total = 0, bw_idx = 0;
|
|
u32 bw_record = 0, bw_data[bw_record_nums] = {0};
|
|
int vcore_uv = 0;
|
|
int i;
|
|
int stall[max_cpus] = {0};
|
|
unsigned int sched_freq[3] = {0};
|
|
int cid;
|
|
|
|
#ifdef CONFIG_MTK_PERF_OBSERVER
|
|
pob_qos_tracker(wallclock);
|
|
#endif
|
|
|
|
if (!perf_tracker_on || !perf_tracker_init)
|
|
return;
|
|
|
|
/* dram freq */
|
|
dram_rate = get_cur_ddr_khz();
|
|
dram_rate = dram_rate / 1000;
|
|
|
|
if (dram_rate <= 0)
|
|
dram_rate = get_dram_data_rate();
|
|
|
|
/* vcore */
|
|
vcore_uv = get_cur_vcore_uv();
|
|
|
|
#ifdef CONFIG_MTK_QOS_FRAMEWORK
|
|
/* emi */
|
|
bw_c = qos_sram_read(QOS_DEBUG_1);
|
|
bw_g = qos_sram_read(QOS_DEBUG_2);
|
|
bw_mm = qos_sram_read(QOS_DEBUG_3);
|
|
bw_total = qos_sram_read(QOS_DEBUG_0);
|
|
#endif
|
|
/* emi history */
|
|
bw_idx = qos_rec_get_hist_idx();
|
|
if (bw_idx != 0xFFFF) {
|
|
for (bw_record = 0; bw_record < bw_record_nums; bw_record += 8) {
|
|
/* occupied bw history */
|
|
bw_data[bw_record] = qos_rec_get_hist_bw(bw_idx, 0);
|
|
bw_data[bw_record+1] = qos_rec_get_hist_bw(bw_idx, 1);
|
|
bw_data[bw_record+2] = qos_rec_get_hist_bw(bw_idx, 2);
|
|
bw_data[bw_record+3] = qos_rec_get_hist_bw(bw_idx, 3);
|
|
/* data bw history */
|
|
bw_data[bw_record+4] = qos_rec_get_hist_data_bw(bw_idx, 0);
|
|
bw_data[bw_record+5] = qos_rec_get_hist_data_bw(bw_idx, 1);
|
|
bw_data[bw_record+6] = qos_rec_get_hist_data_bw(bw_idx, 2);
|
|
bw_data[bw_record+7] = qos_rec_get_hist_data_bw(bw_idx, 3);
|
|
|
|
bw_idx -= 1;
|
|
if (bw_idx < 0)
|
|
bw_idx = bw_idx + bw_hist_nums;
|
|
}
|
|
/* trace for short bin */
|
|
trace_perf_index_sbin(bw_data, bw_record);
|
|
}
|
|
|
|
/* sched: cpu freq */
|
|
for (cid = 0; cid < cluster_nr; cid++)
|
|
sched_freq[cid] = mt_cpufreq_get_cur_freq(cid);
|
|
|
|
/* trace for short msg */
|
|
trace_perf_index_s(
|
|
sched_freq[0], sched_freq[1], sched_freq[2],
|
|
dram_rate, bw_c, bw_g, bw_mm, bw_total,
|
|
vcore_uv);
|
|
|
|
if (!hit_long_check())
|
|
return;
|
|
|
|
/* free mem */
|
|
if (mm_free == -1) {
|
|
mm_free = global_zone_page_state(NR_FREE_PAGES);
|
|
mm_available = si_mem_available();
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_BLOCK_TAG
|
|
/* IO stat */
|
|
if (mtk_btag_mictx_get_data(iostat))
|
|
memset(iostat, 0, sizeof(struct mtk_btag_mictx_iostat_struct));
|
|
#endif
|
|
|
|
/* cpu stall ratio */
|
|
for (i = 0; i < nr_cpu_ids || i < max_cpus; i++)
|
|
stall[i] = cpu_stall_ratio(i);
|
|
|
|
/* trace for long msg */
|
|
trace_perf_index_l(
|
|
K(mm_free),
|
|
K(mm_available),
|
|
#ifdef CONFIG_MTK_BLOCK_TAG
|
|
iostat->wl,
|
|
iostat->tp_req_r, iostat->tp_all_r,
|
|
iostat->reqsize_r, iostat->reqcnt_r,
|
|
iostat->tp_req_w, iostat->tp_all_w,
|
|
iostat->reqsize_w, iostat->reqcnt_w,
|
|
iostat->duration, iostat->q_depth,
|
|
iostat->top,
|
|
#else
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
#endif
|
|
stall);
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_GAUGE_VERSION
|
|
static ssize_t show_fuel_gauge_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
unsigned int len = 0, max_len = 4096;
|
|
|
|
len += snprintf(buf, max_len, "fuel_gauge_enable = %u\n",
|
|
fuel_gauge_enable);
|
|
return len;
|
|
}
|
|
|
|
static ssize_t store_fuel_gauge_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
int tmp;
|
|
|
|
mutex_lock(&perf_ctl_mutex);
|
|
|
|
if (kstrtouint(buf, 10, &tmp) == 0)
|
|
fuel_gauge_enable = (tmp > 0) ? 1 : 0;
|
|
|
|
if (fuel_gauge_enable) {
|
|
/* default delay 8ms */
|
|
fuel_gauge_delay = (fuel_gauge_delay > 0) ?
|
|
fuel_gauge_delay : 8;
|
|
|
|
/* start fuel gauge tracking */
|
|
queue_delayed_work(system_power_efficient_wq,
|
|
&fuel_gauge,
|
|
msecs_to_jiffies(fuel_gauge_delay));
|
|
}
|
|
|
|
mutex_unlock(&perf_ctl_mutex);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t show_fuel_gauge_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
unsigned int len = 0, max_len = 4096;
|
|
|
|
len += snprintf(buf, max_len, "fuel_gauge_period = %u(ms)\n",
|
|
fuel_gauge_delay);
|
|
return len;
|
|
}
|
|
|
|
static ssize_t store_fuel_gauge_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
int tmp;
|
|
|
|
mutex_lock(&perf_ctl_mutex);
|
|
|
|
if (kstrtouint(buf, 10, &tmp) == 0)
|
|
if (tmp > 0) /* ms */
|
|
fuel_gauge_delay = tmp;
|
|
|
|
mutex_unlock(&perf_ctl_mutex);
|
|
|
|
return count;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_GPU_SWPM_SUPPORT
|
|
void perf_update_gpu_counter(unsigned int gpu_data[], unsigned int len)
|
|
{
|
|
trace_perf_index_gpu(gpu_data, len);
|
|
}
|
|
EXPORT_SYMBOL(perf_update_gpu_counter);
|
|
|
|
static ssize_t show_gpu_pmu_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
unsigned int len = 0;
|
|
unsigned int max_len = 4096;
|
|
uint is_inited = 0;
|
|
|
|
if (MTKGPUPower_model_start_symbol)
|
|
is_inited = 1;
|
|
|
|
len += snprintf(buf, max_len, "gpu_pmu_enable = %u, is_inited = %u\n",
|
|
gpu_pmu_enable, is_inited);
|
|
return len;
|
|
}
|
|
|
|
static ssize_t store_gpu_pmu_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
mutex_lock(&perf_ctl_mutex);
|
|
|
|
if (kstrtouint(buf, 10, &gpu_pmu_enable) == 0)
|
|
gpu_pmu_enable = (gpu_pmu_enable > 0) ? 1 : 0;
|
|
|
|
mutex_unlock(&perf_ctl_mutex);
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
static ssize_t show_gpu_pmu_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
unsigned int len = 0;
|
|
unsigned int max_len = 4096;
|
|
|
|
len += snprintf(buf, max_len, "gpu_pmu_period = %u\n",
|
|
gpu_pmu_period);
|
|
return len;
|
|
}
|
|
|
|
static ssize_t store_gpu_pmu_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
mutex_lock(&perf_ctl_mutex);
|
|
|
|
if (kstrtouint(buf, 10, &gpu_pmu_period) == 0) {
|
|
if (gpu_pmu_period < 1000000) // 1ms
|
|
gpu_pmu_period = 1000000;
|
|
}
|
|
|
|
mutex_unlock(&perf_ctl_mutex);
|
|
|
|
return count;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_SKB_OWNER
|
|
void perf_update_tcp_rtt(struct sock *sk, long seq_rtt_us)
|
|
{
|
|
if (net_pkt_trace_enable && sk)
|
|
trace_tcp_rtt(sk->sk_uid.val, ntohs(sk->sk_dport),
|
|
sk->sk_num, sk->sk_family,
|
|
ntohl(sk->sk_daddr), seq_rtt_us);
|
|
}
|
|
|
|
void perf_net_pkt_trace(struct sock *sk, struct sk_buff *skb, int copied)
|
|
{
|
|
struct iphdr *iph = ip_hdr(skb);
|
|
struct tcphdr *tcph = NULL;
|
|
struct udphdr *udph = NULL;
|
|
int len, saddr, sport, dport;
|
|
int seq = 0;
|
|
|
|
if (net_pkt_trace_enable && iph->version == 4 && sk) {
|
|
if (iph->protocol == 6) { /* TCP */
|
|
tcph = (struct tcphdr *)((char *)iph+(iph->ihl*4));
|
|
sport = ntohs(tcph->source);
|
|
dport = ntohs(tcph->dest);
|
|
seq = TCP_SKB_CB(skb)->seq;
|
|
} else if (iph->protocol == 17) { /* UDP */
|
|
udph = (struct udphdr *)((char *)iph+(iph->ihl*4));
|
|
sport = ntohs(udph->source);
|
|
dport = ntohs(udph->dest);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
len = ntohs(iph->tot_len);
|
|
saddr = ntohl(iph->saddr);
|
|
/* tracing for packet */
|
|
trace_socket_packet(sk->sk_uid.val, iph->protocol,
|
|
dport, sport, saddr, len, copied, seq);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* make perf tracker on
|
|
* /sys/devices/system/cpu/perf/enable
|
|
* 1: on
|
|
* 0: off
|
|
*/
|
|
static ssize_t show_perf_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
unsigned int len = 0;
|
|
unsigned int max_len = 4096;
|
|
|
|
len += snprintf(buf, max_len, "enable = %d\n",
|
|
perf_tracker_on);
|
|
return len;
|
|
}
|
|
|
|
static ssize_t store_perf_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
int val = 0;
|
|
|
|
if (sscanf(buf, "%iu", &val) != 0)
|
|
perf_tracker_enable(val);
|
|
|
|
return count;
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_SKB_OWNER
|
|
static ssize_t show_perf_net_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
unsigned int len;
|
|
unsigned int max_len = 4096;
|
|
|
|
len = snprintf(buf, max_len, "enable = %d\n",
|
|
net_pkt_trace_enable);
|
|
return len;
|
|
}
|
|
|
|
static ssize_t store_perf_net_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
int val;
|
|
|
|
mutex_lock(&perf_ctl_mutex);
|
|
|
|
if (sscanf(buf, "%iu", &val) != 0) {
|
|
val = (val > 0) ? 1 : 0;
|
|
|
|
net_pkt_trace_enable = val;
|
|
}
|
|
|
|
mutex_unlock(&perf_ctl_mutex);
|
|
|
|
return count;
|
|
}
|
|
#endif
|
|
|
|
static struct kobj_attribute perf_enable_attr =
|
|
__ATTR(enable, 0600, show_perf_enable, store_perf_enable);
|
|
#ifdef CONFIG_MTK_GAUGE_VERSION
|
|
static struct kobj_attribute perf_fuel_gauge_enable_attr =
|
|
__ATTR(fuel_gauge_enable, 0600,
|
|
show_fuel_gauge_enable, store_fuel_gauge_enable);
|
|
static struct kobj_attribute perf_fuel_gauge_period_attr =
|
|
__ATTR(fuel_gauge_period, 0600,
|
|
show_fuel_gauge_period, store_fuel_gauge_period);
|
|
#endif
|
|
#ifdef CONFIG_MTK_GPU_SWPM_SUPPORT
|
|
static struct kobj_attribute perf_gpu_pmu_enable_attr =
|
|
__ATTR(gpu_pmu_enable, 0600, show_gpu_pmu_enable, store_gpu_pmu_enable);
|
|
static struct kobj_attribute perf_gpu_pmu_period_attr =
|
|
__ATTR(gpu_pmu_period, 0600, show_gpu_pmu_period, store_gpu_pmu_period);
|
|
#endif
|
|
#ifdef CONFIG_MTK_SKB_OWNER
|
|
static struct kobj_attribute perf_net_enable_attr =
|
|
__ATTR(net_pkt_enable, 0600, show_perf_net_enable, store_perf_net_enable);
|
|
#endif
|
|
|
|
static struct attribute *perf_attrs[] = {
|
|
&perf_enable_attr.attr,
|
|
#ifdef CONFIG_MTK_GAUGE_VERSION
|
|
&perf_fuel_gauge_enable_attr.attr,
|
|
&perf_fuel_gauge_period_attr.attr,
|
|
#endif
|
|
#ifdef CONFIG_MTK_GPU_SWPM_SUPPORT
|
|
&perf_gpu_pmu_enable_attr.attr,
|
|
&perf_gpu_pmu_period_attr.attr,
|
|
#endif
|
|
#ifdef CONFIG_MTK_SKB_OWNER
|
|
&perf_net_enable_attr.attr,
|
|
#endif
|
|
NULL,
|
|
};
|
|
|
|
static struct attribute_group perf_attr_group = {
|
|
.attrs = perf_attrs,
|
|
};
|
|
|
|
static int init_perf_tracker(void)
|
|
{
|
|
int ret = 0;
|
|
struct kobject *kobj = NULL;
|
|
|
|
perf_tracker_init = 1;
|
|
cluster_nr = arch_get_nr_clusters();
|
|
|
|
if (unlikely(cluster_nr <= 0 || cluster_nr > 3))
|
|
cluster_nr = 3;
|
|
|
|
kobj = kobject_create_and_add("perf", &cpu_subsys.dev_root->kobj);
|
|
|
|
if (kobj) {
|
|
ret = sysfs_create_group(kobj, &perf_attr_group);
|
|
if (ret)
|
|
kobject_put(kobj);
|
|
else
|
|
kobject_uevent(kobj, KOBJ_ADD);
|
|
}
|
|
|
|
init_function_symbols();
|
|
|
|
return 0;
|
|
}
|
|
late_initcall_sync(init_perf_tracker);
|