This patch adds GLES mem profiler feature.
You could use it by "cat /sys/kernel/debug/mali/gles_mem/<PID>".
Without user-DDK's MALI_IOC_MEM_PROFILE_GLES_MEM, it only show layout.
With this ioctl, you could check current GLES relevant memory status
in opened session and also check memory leakage in trash subdirectory.
The mechanism of detecting memory leakage is checking information when
the session is closed. So the user misses to free (GLES)memory during
session, it(the PID) could be found in trash.
Caution! When app is killed and the session is forcely shut down, then
it(the PID) could be found in trash but we can not guarantee there is a
real memory leakage. That is because like this case, it is impossible
to call MALI_IOC_MEM_PROFILE_GLES_MEM to remove allocated memory.
Change-Id: I78a08f7b53594dc20f8cc6f4c892250fdc9e8208
Signed-off-by: YoungJun Cho <yj44.cho@samsung.com>
[jy0922.shim: applied to r5p2_rel0 from r5p0_rel0]
Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
MALI_FAKE_PLATFORM_DEVICE ?= 1
DFS_ONE_STEP_SCALE_DOWN ?= 1
MATCH_DFS_TO_LOWER_FREQ ?= 1
+GLES_MEM_PROFILE ?= 1
# The GPL product will only include the license/gpl directory
ccflags-y += -I$(src)/linux/license/gpl
ccflags-y += -DSPRD_GPU_BOOST
ccflags-y += -DSPRD_DFS_ONE_STEP_SCALE_DOWN=$(DFS_ONE_STEP_SCALE_DOWN)
ccflags-y += -DSPRD_MATCH_DFS_TO_LOWER_FREQ=$(MATCH_DFS_TO_LOWER_FREQ)
+ccflags-y += -DTIZEN_GLES_MEM_PROFILE=$(GLES_MEM_PROFILE)
ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP)
ccflags-y += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED)
#include "mali_osk_list.h"
#include "mali_session.h"
#include "mali_ukk.h"
+#if TIZEN_GLES_MEM_PROFILE
+#include "mali_kernel_sysfs.h"
+#endif
_MALI_OSK_LIST_HEAD(mali_sessions);
static u32 mali_session_count = 0;
}
}
+#if TIZEN_GLES_MEM_PROFILE
+static void mali_session_gles_mem_init(struct mali_session_data *session)
+{
+ struct mali_session_gles_mem_profile_info *info;
+ int i;
+
+ mali_sysfs_gles_mem_profile_add((void *)session);
+
+ for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) {
+ info = &(session->gles_mem_profile_info[i]);
+ info->type = i;
+ info->lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED,
+ _MALI_OSK_LOCK_ORDER_SESSIONS);
+ if (!info->lock)
+ MALI_PRINT_ERROR(("Mutex init failure"));
+ _MALI_OSK_INIT_LIST_HEAD(&(info->api_head));
+ }
+}
+
+static void mali_session_gles_mem_profile_apis_remove(
+ struct mali_session_gles_mem_profile_info *info)
+{
+ struct mali_session_gles_mem_profile_api_info *api, *tmp;
+
+ _mali_osk_mutex_wait(info->lock);
+
+ _MALI_OSK_LIST_FOREACHENTRY(api, tmp, &(info->api_head),
+ struct mali_session_gles_mem_profile_api_info, link) {
+ _mali_osk_list_delinit(&(api->link));
+ _mali_osk_free(api);
+ }
+
+ _mali_osk_mutex_signal(info->lock);
+}
+
+static void mali_session_gles_mem_deinit(struct mali_session_data *session)
+{
+ struct mali_session_gles_mem_profile_trash_info *trash_info = NULL;
+ struct mali_session_gles_mem_profile_info *info;
+ int i;
+
+ for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) {
+ info = &(session->gles_mem_profile_info[i]);
+ if (!info->lock)
+ continue;
+
+ if (info->size) {
+ trash_info =
+ (struct mali_session_gles_mem_profile_trash_info *)
+ mali_sysfs_gles_mem_profile_move_to_trash(
+ (void *)trash_info,
+ (void *)session, i);
+ } else
+ mali_session_gles_mem_profile_apis_remove(info);
+
+ _mali_osk_mutex_term(info->lock);
+ }
+
+ mali_sysfs_gles_mem_profile_remove((void *)session);
+}
+#endif /* TIZEN_GLES_MEM_PROFILE */
+
void mali_session_add(struct mali_session_data *session)
{
mali_session_lock();
_mali_osk_list_add(&session->link, &mali_sessions);
mali_session_count++;
mali_session_unlock();
+
+#if TIZEN_GLES_MEM_PROFILE
+ mali_session_gles_mem_init(session);
+#endif
}
void mali_session_remove(struct mali_session_data *session)
{
+#if TIZEN_GLES_MEM_PROFILE
+ mali_session_gles_mem_deinit(session);
+#endif
+
mali_session_lock();
_mali_osk_list_delinit(&session->link);
mali_session_count--;
total_mali_mem_size = _mali_ukk_report_total_memory_size();
_mali_osk_ctxprintf(print_ctx, "Mali mem usage: %u\nMali mem limit: %u\n", mali_mem_usage, total_mali_mem_size);
}
+
+#if TIZEN_GLES_MEM_PROFILE
+void mali_session_gles_mem_profile_api_add(
+ struct mali_session_gles_mem_profile_info *info,
+ struct mali_session_gles_mem_profile_api_info *api,
+ _mali_osk_list_t *head)
+{
+ if (!info->lock)
+ return;
+
+ _mali_osk_mutex_wait(info->lock);
+
+ _mali_osk_list_add(&(api->link), head);
+
+ _mali_osk_mutex_signal(info->lock);
+}
+
+static const char *mali_session_gles_mem_profile_to_str(
+ enum mali_session_gles_mem_profile_type type)
+{
+ switch (type) {
+ case MALI_GLES_MEM_UNTYPED:
+ return "mali_gles_mem Untyped";
+ case MALI_GLES_MEM_VB_IB:
+ return "mali_gles_mem Vertex & Index buffer";
+ case MALI_GLES_MEM_TEXTURE:
+ return "mali_gles_mem Texture";
+ case MALI_GLES_MEM_RSW:
+ return "mali_gles_mem RSW";
+ case MALI_GLES_MEM_PLBU_HEAP:
+ return "mali_gles_mem PLBU heap";
+ case MALI_GLES_MEM_UNTYPE_GP_CMD_LIST:
+ return "mali_gles_mem Uuntyped GP cmd list";
+ case MALI_GLES_MEM_SHADER:
+ return "mali_gles_mem Shader";
+ case MALI_GLES_MEM_TD:
+ return "mali_gles_mem TD";
+ case MALI_GLES_MEM_UNTYPE_FRAME_POOL:
+ return "mali_gles_mem Untyped frame pool";
+ case MALI_GLES_MEM_UNTYPE_SURFACE:
+ return "mali_gles_mem Untyped surface";
+ case MALI_GLES_MEM_RT:
+ return "mali_gles_mem Render target";
+ case MALI_GLES_MEM_VARYING:
+ return "mali_gles_mem Varying buffer";
+ case MALI_GLES_MEM_STREAMS:
+ return "mali_gles_mem Streams buffer";
+ case MALI_GLES_MEM_POINTER_ARRAY:
+ return "mali_gles_mem Pointer array buffer";
+ case MALI_GLES_MEM_SLAVE_TILE_LIST:
+ return "mali_gles_mem Slave tile list buffer";
+ case MALI_GLES_MEM_POLYGON_CMD_LIST:
+ return "mali_gles_mem Polygon cmd list";
+ case MALI_GLES_MEM_FRAGMENT_STACK:
+ return "mali_gles_mem Fragment stack";
+ case MALI_GLES_MEM_UNIFORM:
+ return "mali_gles_mem Uniforms";
+ case MALI_GLES_MEM_PBUFFER:
+ return "mali_gles_mem Pbuffer";
+ default:
+ return "mali_gles_mem Untyped";
+ }
+}
+
+static void mali_session_gles_mem_profile_api_tracking(
+ _mali_osk_print_ctx *print_ctx,
+ struct mali_session_gles_mem_profile_info *info)
+{
+ struct mali_session_gles_mem_profile_api_info *api, *tmp;
+
+ _MALI_OSK_LIST_FOREACHENTRY(api, tmp, &(info->api_head),
+ struct mali_session_gles_mem_profile_api_info, link) {
+ _mali_osk_ctxprintf(print_ctx, "\t| %-36s\t%-30d\n",
+ api->api, api->size);
+ }
+}
+
+s64 mali_session_gles_mem_profile_info_tracking(_mali_osk_print_ctx *print_ctx,
+ void *data, bool trash)
+{
+ struct mali_session_gles_mem_profile_trash_info *trash_info = NULL;
+ struct mali_session_gles_mem_profile_info *info;
+ struct mali_session_data *session = NULL;
+ s64 total_size = 0;
+ int i;
+
+ MALI_DEBUG_ASSERT_POINTER(print_ctx);
+ MALI_DEBUG_ASSERT_POINTER(data);
+
+ if (trash) {
+ trash_info =
+ (struct mali_session_gles_mem_profile_trash_info *)data;
+ } else
+ session = (struct mali_session_data *)data;
+
+ for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) {
+ if (trash)
+ info = &(trash_info->info[i]);
+ else
+ info = &(session->gles_mem_profile_info[i]);
+ if (!info->lock)
+ continue;
+
+ _mali_osk_mutex_wait(info->lock);
+
+ _mali_osk_ctxprintf(print_ctx, "%-36s\t%-30lld\n",
+ mali_session_gles_mem_profile_to_str(
+ i << MALI_GLES_MEM_SHIFT),
+ info->size);
+ mali_session_gles_mem_profile_api_tracking(print_ctx, info);
+ total_size += info->size;
+
+ _mali_osk_mutex_signal(info->lock);
+ }
+
+ return total_size;
+}
+#endif /* TIZEN_GLES_MEM_PROFILE */
/* Number of frame builder job lists per session. */
#define MALI_PP_JOB_FB_LOOKUP_LIST_SIZE 16
#define MALI_PP_JOB_FB_LOOKUP_LIST_MASK (MALI_PP_JOB_FB_LOOKUP_LIST_SIZE - 1)
+#if TIZEN_GLES_MEM_PROFILE
+#define MALI_GLES_MEM_SHIFT 8
+
+enum mali_session_gles_mem_profile_type {
+ MALI_GLES_MEM_PP_READ = (1 << 0),
+ MALI_GLES_MEM_PP_WRITE = (1 << 1),
+ MALI_GLES_MEM_GP_READ = (1 << 2),
+ MALI_GLES_MEM_GP_WRITE = (1 << 3),
+ MALI_GLES_MEM_CPU_READ = (1 << 4),
+ MALI_GLES_MEM_CPU_WRITE = (1 << 5),
+ MALI_GLES_MEM_GP_L2_ALLOC = (1 << 6),
+ MALI_GLES_MEM_FRAME_POOL_ALLOC = (1 << 7),
+ /* type of this mem block */
+ MALI_GLES_MEM_UNTYPED = (0 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_VB_IB = (1 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_TEXTURE = (2 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_VARYING = (3 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_RT = (4 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_PBUFFER = (5 << MALI_GLES_MEM_SHIFT),
+ /* memory types for gp command */
+ MALI_GLES_MEM_PLBU_HEAP = (6 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_POINTER_ARRAY = (7 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_SLAVE_TILE_LIST = (8 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_UNTYPE_GP_CMD_LIST = (9 << MALI_GLES_MEM_SHIFT),
+ /* memory type for polygon list command */
+ MALI_GLES_MEM_POLYGON_CMD_LIST = (10 << MALI_GLES_MEM_SHIFT),
+ /* memory types for pp command */
+ MALI_GLES_MEM_TD = (11 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_RSW = (12 << MALI_GLES_MEM_SHIFT),
+ /* other memory types */
+ MALI_GLES_MEM_SHADER = (13 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_STREAMS = (14 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_FRAGMENT_STACK = (15 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_UNIFORM = (16 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_UNTYPE_FRAME_POOL = (17 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_UNTYPE_SURFACE = (18 << MALI_GLES_MEM_SHIFT),
+ MALI_GLES_MEM_MAX = (19 << MALI_GLES_MEM_SHIFT),
+};
+
+#define MALI_MAX_GLES_MEM_TYPES (MALI_GLES_MEM_MAX >> MALI_GLES_MEM_SHIFT)
+
+struct mali_session_gles_mem_profile_api_info {
+ char api[64]; /**< API name */
+ u16 id; /**< API ID */
+ int size; /**< Total size for this API */
+ _MALI_OSK_LIST_HEAD(link); /**< Link for the list of all EGL/GL API */
+};
+
+struct mali_session_gles_mem_profile_info {
+ u32 type; /**< Memory type ID */
+ s64 size; /**< Total sizes for this type */
+ _mali_osk_mutex_t *lock; /**< Mutex lock */
+ _mali_osk_list_t api_head; /**< List of all EGL/GL APIs for this type */
+};
+
+struct mali_session_gles_mem_profile_trash_info {
+ u32 pid;
+ char *comm;
+ struct mali_session_gles_mem_profile_info info[MALI_MAX_GLES_MEM_TYPES];
+};
+#endif /* TIZEN_GLES_MEM_PROFILE */
struct mali_session_data {
_mali_osk_notification_queue_t *ioctl_queue;
#ifdef SPRD_GPU_BOOST
int level;
#endif
+
+#if TIZEN_GLES_MEM_PROFILE
+ struct dentry *gles_mem_profile_dentry;
+ struct mali_session_gles_mem_profile_info
+ gles_mem_profile_info[MALI_MAX_GLES_MEM_TYPES];
+#endif
};
_mali_osk_errcode_t mali_session_initialize(void);
void mali_session_memory_tracking(_mali_osk_print_ctx *print_ctx);
+#if TIZEN_GLES_MEM_PROFILE
+void mali_session_gles_mem_profile_api_add(
+ struct mali_session_gles_mem_profile_info *info,
+ struct mali_session_gles_mem_profile_api_info *api,
+ _mali_osk_list_t *head);
+s64 mali_session_gles_mem_profile_info_tracking(_mali_osk_print_ctx *print_ctx,
+ void *data, bool trash);
+#endif
+
#endif /* __MALI_SESSION_H__ */
#define MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, _mali_uk_query_mmu_page_table_dump_size_s)
#define MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_DUMP_MMU_PAGE_TABLE, _mali_uk_dump_mmu_page_table_s)
#define MALI_IOC_MEM_WRITE_SAFE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MEM_WRITE_SAFE, _mali_uk_mem_write_safe_s)
+#if TIZEN_GLES_MEM_PROFILE
+#define MALI_IOC_MEM_PROFILE_GLES_MEM _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GLES_MEM_PROFILER, _mali_uk_gles_mem_profiler_s)
+#endif
#define MALI_IOC_PP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_START_JOB, _mali_uk_pp_start_job_s)
#define MALI_IOC_PP_AND_GP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_AND_GP_START_JOB, _mali_uk_pp_and_gp_start_job_s)
_MALI_UK_DUMP_MMU_PAGE_TABLE, /**< _mali_ukk_mem_dump_mmu_page_table() */
_MALI_UK_DMA_BUF_GET_SIZE, /**< _mali_ukk_dma_buf_get_size() */
_MALI_UK_MEM_WRITE_SAFE, /**< _mali_uku_mem_write_safe() */
+#if TIZEN_GLES_MEM_PROFILE
+ _MALI_UK_GLES_MEM_PROFILER, /**< _mali_uku_gles_mem_profiler() */
+#endif
/** Common functions for each core */
u64 page_table_dump; /**< [out] pointer within buffer where MMU page table dump is stored */
} _mali_uk_dump_mmu_page_table_s;
+#if TIZEN_GLES_MEM_PROFILE
+/**
+ * @brief Arguments for _mali_uk[uk]_gles_mem_profiler()
+ */
+typedef struct {
+ u64 ctx; /**< [in,out] user-kernel context (trashed on output) */
+ char api[64]; /**< [in] OpenGLES or EGL API function name */
+ u32 entrypoint;/**< [in] OpenGLES or EGL API entrypoint */
+ u32 type; /**< [in] Type of memory */
+ int size; /**< [in] Number of bytes. +ve means allocated. -ve means freed */
+} _mali_uk_gles_mem_profiler_s;
+#endif
+
/** @} */ /* end group _mali_uk_memory */
#endif
break;
+#if TIZEN_GLES_MEM_PROFILE
+ case MALI_IOC_MEM_PROFILE_GLES_MEM:
+ BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_gles_mem_profiler_s),
+ sizeof(u64)));
+ err = mem_profile_gles_mem(session_data,
+ (_mali_uk_gles_mem_profiler_s __user *)arg);
+ break;
+#endif
+
case MALI_IOC_PP_START_JOB:
BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_pp_start_job_s), sizeof(u64)));
err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg);
#define POWER_BUFFER_SIZE 3
static struct dentry *mali_debugfs_dir = NULL;
+#if TIZEN_GLES_MEM_PROFILE
+struct dentry *mali_gles_mem_profile_dir;
+struct dentry *mali_gles_mem_profile_trash_dir;
+#endif
typedef enum {
_MALI_DEVICE_SUSPEND,
#endif
}
+#if TIZEN_GLES_MEM_PROFILE
+ mali_gles_mem_profile_dir = debugfs_create_dir(
+ "gles_mem",
+ mali_debugfs_dir);
+#endif
+
#if MALI_STATE_TRACKING
debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
#endif
return 0;
}
+#if TIZEN_GLES_MEM_PROFILE
+static void gles_mem_profile_show_common(struct seq_file *s, char *comm,
+ u32 pid)
+{
+ seq_printf(s,
+ "%s\n"
+ "%s (%s)\t\t%s(%d)\n"
+ "%s\n%s\t\t\t\t%s(%s)\n"
+ "\t| %s\t\t\t\t%s(%s)\n%s\n",
+ "===============================================================",
+ "Process name", comm, "Process ID", pid,
+ "---------------------------------------------------------------",
+ "Type Name", "Type Usage", "bytes", "API Name", "API Usage", "bytes",
+ "***************************************************************");
+}
+
+static int gles_mem_profile_show(struct seq_file *s, void *private_data)
+{
+ struct mali_session_data *session =
+ (struct mali_session_data *)(s->private);
+
+ gles_mem_profile_show_common(s, session->comm, session->pid);
+
+ seq_printf(s, "\n\nTotal Mali GLES mem usage: %lld (bytes)\n",
+ mali_session_gles_mem_profile_info_tracking(s,
+ (void *)session,
+ false));
+
+ return 0;
+}
+
+static int gles_mem_profile_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, gles_mem_profile_show, inode->i_private);
+}
+
+static const struct file_operations gles_mem_profile_fops = {
+ .owner = THIS_MODULE,
+ .open = gles_mem_profile_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release
+};
+
+int mali_sysfs_gles_mem_profile_add(void *data)
+{
+ struct mali_session_data *session = (struct mali_session_data *)data;
+ char name[11];
+
+ if (!mali_gles_mem_profile_dir)
+ return 0;
+
+ _mali_osk_snprintf(name, sizeof(name), "%u", session->pid);
+ session->gles_mem_profile_dentry =
+ debugfs_create_file(name, S_IRUSR,
+ mali_gles_mem_profile_dir,
+ (void *)session,
+ &gles_mem_profile_fops);
+
+ return 0;
+}
+
+void mali_sysfs_gles_mem_profile_remove(void *data)
+{
+ struct mali_session_data *session = (struct mali_session_data *)data;
+
+ debugfs_remove(session->gles_mem_profile_dentry);
+}
+
+static int gles_mem_profile_trash_show(struct seq_file *s, void *private_data)
+{
+ struct mali_session_gles_mem_profile_trash_info *trash_info =
+ (struct mali_session_gles_mem_profile_trash_info *)(s->private);
+
+ gles_mem_profile_show_common(s, trash_info->comm, trash_info->pid);
+
+ seq_printf(s, "\n\nTotal Mali GLES mem usage: %lld (bytes)\n",
+ mali_session_gles_mem_profile_info_tracking(s,
+ (void *)trash_info,
+ true));
+
+ return 0;
+}
+
+static int gles_mem_profile_trash_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, gles_mem_profile_trash_show, inode->i_private);
+}
+
+static const struct file_operations gles_mem_profile_trash_fops = {
+ .owner = THIS_MODULE,
+ .open = gles_mem_profile_trash_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release
+};
+
+void *mali_sysfs_gles_mem_profile_move_to_trash(void *data1, void *data2,
+ int idx)
+{
+ struct mali_session_gles_mem_profile_trash_info *trash_info =
+ (struct mali_session_gles_mem_profile_trash_info *)data1;
+ struct mali_session_data *session = (struct mali_session_data *)data2;
+ struct mali_session_gles_mem_profile_info *tinfo, *info;
+
+ if (!mali_gles_mem_profile_dir)
+ return NULL;
+
+ if (!trash_info) {
+ char name[11];
+ int i;
+
+ trash_info =
+ (struct mali_session_gles_mem_profile_trash_info *)
+ _mali_osk_calloc(1,
+ sizeof(struct mali_session_gles_mem_profile_trash_info)
+ );
+ if (!trash_info) {
+ MALI_PRINT_ERROR(("TrashInfo alloc failure"));
+ return NULL;
+ }
+
+ trash_info->pid = session->pid;
+ trash_info->comm = session->comm;
+
+ for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) {
+ tinfo = &(trash_info->info[i]);
+ tinfo->type = i;
+ tinfo->lock =
+ _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED,
+ _MALI_OSK_LOCK_ORDER_SESSIONS);
+ if (!tinfo->lock)
+ MALI_PRINT_ERROR(("Mutex init failure"));
+ _MALI_OSK_INIT_LIST_HEAD(&(tinfo->api_head));
+ }
+
+ if (!mali_gles_mem_profile_trash_dir) {
+ mali_gles_mem_profile_trash_dir =
+ debugfs_create_dir("trash",
+ mali_gles_mem_profile_dir);
+ }
+
+ _mali_osk_snprintf(name, sizeof(name), "%u", trash_info->pid);
+ debugfs_create_file(name, S_IRUSR,
+ mali_gles_mem_profile_trash_dir,
+ (void *)trash_info,
+ &gles_mem_profile_trash_fops);
+ }
+
+ tinfo = &(trash_info->info[idx]);
+ info = &(session->gles_mem_profile_info[idx]);
+
+ _mali_osk_mutex_wait(info->lock);
+
+ if (tinfo->lock) {
+ tinfo->type = info->type;
+ tinfo->size = info->size;
+ _mali_osk_list_move_list(&(info->api_head), &(tinfo->api_head));
+ }
+
+ _mali_osk_mutex_signal(info->lock);
+
+ return trash_info;
+}
+#endif /* TIZEN_GLES_MEM_PROFILE */
+
#else /* MALI_LICENSE_IS_GPL */
/* Dummy implementations for non-GPL */
return 0;
}
+#if TIZEN_GLES_MEM_PROFILE
+int mali_sysfs_gles_mem_profile_add(void *data)
+{
+ return 0;
+}
+
+void mali_sysfs_gles_mem_profile_remove(void *data)
+{
+ return;
+}
+
+void *mali_sysfs_gles_mem_profile_move_to_trash(void *data1, void *data2,
+ int idx)
+{
+ return NULL;
+}
+#endif /* TIZEN_GLES_MEM_PROFILE */
#endif /* MALI_LICENSE_IS_GPL */
int mali_sysfs_register(const char *mali_dev_name);
int mali_sysfs_unregister(void);
+#if TIZEN_GLES_MEM_PROFILE
+int mali_sysfs_gles_mem_profile_add(void *data);
+void mali_sysfs_gles_mem_profile_remove(void *data);
+void *mali_sysfs_gles_mem_profile_move_to_trash(void *data1, void *data2,
+ int idx);
+#endif
#ifdef __cplusplus
}
return 0;
}
+#if TIZEN_GLES_MEM_PROFILE
+int mem_profile_gles_mem(struct mali_session_data *session_data,
+ _mali_uk_gles_mem_profiler_s __user *uargs)
+{
+ _mali_uk_gles_mem_profiler_s kargs;
+ struct mali_session_gles_mem_profile_info *info;
+ struct mali_session_gles_mem_profile_api_info *api, *tmp;
+ mali_bool flag = MALI_FALSE;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+ MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+ if (copy_from_user(&kargs, uargs, sizeof(_mali_uk_gles_mem_profiler_s)))
+ return -EFAULT;
+
+ kargs.ctx = (uintptr_t)session_data;
+
+ info = &session_data->gles_mem_profile_info[kargs.type];
+ if (!info) {
+ MALI_PRINT_ERROR(("No info is available. Something wrong"));
+ return -EINVAL;
+ }
+
+ _MALI_OSK_LIST_FOREACHENTRY(api, tmp, &(info->api_head),
+ struct mali_session_gles_mem_profile_api_info, link) {
+ if (api->id == (u16)kargs.entrypoint) {
+ /* This API is recorded already. Update it. */
+ api->size += kargs.size;
+ info->size += kargs.size;
+ flag = MALI_TRUE;
+ break;
+ }
+ }
+
+ if (flag == MALI_FALSE) {
+ /*
+ * This is the first time the API is recorded for this info.
+ * So add it.
+ */
+ api = (struct mali_session_gles_mem_profile_api_info *)
+ _mali_osk_calloc(1,
+ sizeof(struct mali_session_gles_mem_profile_api_info));
+ if (!api) {
+ MALI_PRINT_ERROR(("Alloc failure"));
+ return -ENOMEM;
+ }
+ memcpy(&api->api, &kargs.api, sizeof(api->api));
+
+ api->id = (u16)kargs.entrypoint;
+ api->size += kargs.size;
+ info->size += kargs.size;
+
+ mali_session_gles_mem_profile_api_add(info, api,
+ &(info->api_head));
+ }
+
+ return 0;
+}
+#endif
int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user *uargs);
int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user *uargs);
int mem_usage_get_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_memory_usage_get_s __user *uargs);
+#if TIZEN_GLES_MEM_PROFILE
+int mem_profile_gles_mem(struct mali_session_data *session_data,
+ _mali_uk_gles_mem_profiler_s __user *uargs);
+#endif
int timeline_get_latest_point_wrapper(struct mali_session_data *session, _mali_uk_timeline_get_latest_point_s __user *uargs);
int timeline_wait_wrapper(struct mali_session_data *session, _mali_uk_timeline_wait_s __user *uargs);