kernel_samsung_a53x/drivers/gpu/arm/exynos/common/gpex_debug.c
2024-06-15 16:02:09 -03:00

164 lines
3.8 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0
/*
* (C) COPYRIGHT 2021 Samsung Electronics Inc. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU licence.
*
* 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 the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*/
/* Implements */
#include <gpex_debug.h>
/* Uses */
#include <gpex_utils.h>
#include <mali_kbase.h>
#include <linux/ktime.h>
struct record {
int prev_data;
int new_data;
struct timespec64 ts;
int code;
};
#define CLK_HIST_SIZE 8
#define LLC_HIST_SIZE 8
#define BTS_HIST_SIZE 8
#define RTPM_HIST_SIZE 8
#define SUSPEND_HIST_SIZE 8
static const char* hist_name[HIST_TYPE_SIZE] = {"clk", "llc", "bts", "rtpm", "suspend"};
static const int hist_size[HIST_TYPE_SIZE] = {
CLK_HIST_SIZE, LLC_HIST_SIZE, BTS_HIST_SIZE, RTPM_HIST_SIZE, SUSPEND_HIST_SIZE };
static struct record * hist_arr[HIST_TYPE_SIZE];
static struct _debug_info {
int hist_idx[HIST_TYPE_SIZE];
int hist_errors[HIST_TYPE_SIZE];
struct record clk_hist[CLK_HIST_SIZE];
struct record llc_hist[LLC_HIST_SIZE];
struct record bts_hist[BTS_HIST_SIZE];
struct record rtpm_hist[RTPM_HIST_SIZE];
struct record suspend_hist[SUSPEND_HIST_SIZE];
struct device *dev;
} debug_info;
int gpex_debug_init(struct device **dev)
{
int idx;
debug_info.dev = *dev;
hist_arr[0] = debug_info.clk_hist;
hist_arr[1] = debug_info.llc_hist;
hist_arr[2] = debug_info.bts_hist;
hist_arr[3] = debug_info.rtpm_hist;
hist_arr[4] = debug_info.suspend_hist;
for (idx = 0; idx < HIST_TYPE_SIZE; idx++) {
memset(hist_arr[idx], -1, sizeof(*hist_arr[idx]) * hist_size[idx]);
}
gpex_utils_get_exynos_context()->debug_info = &debug_info;
return 0;
}
void gpex_debug_dump_hist(enum hist_type ht)
{
int idx = debug_info.hist_idx[ht];
int len = hist_size[ht];
if (debug_info.dev == NULL)
return;
while (len-- > 0) {
struct record rec = hist_arr[ht][idx];
dev_warn(debug_info.dev, "%s,%d.%.6d,%d,%d,%d",
hist_name[ht],
(int)rec.ts.tv_sec,
(int)(rec.ts.tv_nsec / 1000),
rec.prev_data,
rec.new_data,
rec.code);
idx--;
if (idx < 0)
idx = hist_size[ht] - 1;
}
}
static inline struct record *get_record(enum hist_type ht)
{
return &hist_arr[ht][debug_info.hist_idx[ht]];
}
void gpex_debug_new_record(enum hist_type ht)
{
debug_info.hist_idx[ht]++;
if (debug_info.hist_idx[ht] >= hist_size[ht])
debug_info.hist_idx[ht] = 0;
memset(get_record(ht), 0xAA, sizeof(struct record));
}
void gpex_debug_record_time(enum hist_type ht)
{
ktime_get_ts64(&get_record(ht)->ts);
}
void gpex_debug_record_prev_data(enum hist_type ht, int prev_data)
{
get_record(ht)->prev_data = prev_data;
}
void gpex_debug_record_new_data(enum hist_type ht, int new_data)
{
get_record(ht)->new_data = new_data;
}
void gpex_debug_record_code(enum hist_type ht, int code)
{
get_record(ht)->code = code;
}
void gpex_debug_record(enum hist_type ht, int prev_data, int new_data, int code)
{
struct record *rec = get_record(ht);
ktime_get_ts64(&rec->ts);
rec->prev_data = prev_data;
rec->new_data = new_data;
rec->code = code;
}
void gpex_debug_incr_error_cnt(enum hist_type ht)
{
debug_info.hist_errors[ht]++;
}
void gpex_debug_dump_error_cnt(void)
{
int idx = 0;
if (debug_info.dev == NULL)
return;
for (idx = 0; idx < HIST_TYPE_SIZE; idx++) {
dev_warn(debug_info.dev, "%s errors: %d", hist_name[idx], debug_info.hist_errors[idx]);
}
}