diff --git a/msm/Makefile b/msm/Makefile index aff0d93920..241f5e757b 100644 --- a/msm/Makefile +++ b/msm/Makefile @@ -1,5 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only +CONFIG_DEBUGFS_SYNX = false + obj-m += synx/ipclite.o obj-m += synx-driver.o synx-driver-objs := synx/synx.o synx/synx_util.o synx/synx_debugfs.o synx/synx_global.o +synx-driver-$(CONFIG_DEBUGFS_SYNX) += synx/synx_debugfs_util.o diff --git a/msm/synx/synx_debugfs.c b/msm/synx/synx_debugfs.c index 711fa31424..afc7a97c2f 100644 --- a/msm/synx/synx_debugfs.c +++ b/msm/synx/synx_debugfs.c @@ -9,17 +9,24 @@ #include #include #include +#include #include "synx_api.h" #include "synx_debugfs.h" #include "synx_util.h" +#include "synx_global.h" +#include "synx_debugfs_util.h" -#define MAX_DBG_BUF_SIZE (36 * SYNX_MAX_OBJS) +#define MAX_DBG_BUF_SIZE (64 * SYNX_MAX_OBJS) +#ifdef ENABLE_DEBUGFS +#define MAX_HELP_BUF_SIZE (4096) +#define BUF_SIZE 16 +#endif struct dentry *my_direc; - -int synx_columns = NAME_COLUMN | ID_COLUMN | - STATE_COLUMN | GLOBAL_COLUMN; +u32 lower_handle_id = GLOBAL_HANDLE_STARTING_ID, upper_handle_id = GLOBAL_HANDLE_STARTING_ID; +long synx_columns = STATUS_COLUMN | ID_COLUMN | REF_CNT_COLUMN | + NUM_CHILD_COLUMN | SUBSCRIBERS_COLUMN | WAITERS_COLUMN | PARENTS_COLUMN | GLOBAL_SHARED_MEM; EXPORT_SYMBOL(synx_columns); int synx_debug = SYNX_ERR | SYNX_WARN | @@ -32,10 +39,10 @@ void populate_bound_rows( int j; for (j = 0; j < row->num_bound_synxs; j++) - cur += scnprintf(cur, end - cur, - "\n\tID: %d", - row->bound_synxs[j].external_desc.id); + SYNX_CONSOLE_LOG(cur, end, "\n\tID: %d", + row->bound_synxs[j].external_desc.id); } + static ssize_t synx_table_read(struct file *file, char *buf, size_t count, @@ -44,98 +51,149 @@ static ssize_t synx_table_read(struct file *file, struct synx_device *dev = file->private_data; struct error_node *err_node, *err_node_tmp; char *dbuf, *cur, *end; - int rc = SYNX_SUCCESS; ssize_t len = 0; dbuf = kzalloc(MAX_DBG_BUF_SIZE, GFP_KERNEL); if (!dbuf) return -ENOMEM; - /* dump client details */ cur = dbuf; end = cur + MAX_DBG_BUF_SIZE; - if (synx_columns & NAME_COLUMN) - cur += scnprintf(cur, end - cur, "| Name |"); - if (synx_columns & ID_COLUMN) - cur += scnprintf(cur, end - cur, "| ID |"); - if (synx_columns & STATE_COLUMN) - cur += scnprintf(cur, end - cur, "| Status |"); - if (synx_columns & FENCE_COLUMN) - cur += scnprintf(cur, end - cur, "| Fence |"); - if (synx_columns & COREDATA_COLUMN) - cur += scnprintf(cur, end - cur, "| Coredata |"); - if (synx_columns & GLOBAL_COLUMN) - cur += scnprintf(cur, end - cur, "| Coredata |"); - if (synx_columns & BOUND_COLUMN) - cur += scnprintf(cur, end - cur, "| Bound |"); - cur += scnprintf(cur, end - cur, "\n"); +#ifdef ENABLE_DEBUGFS + SYNX_CONSOLE_LOG(cur, end, "\n\tHandle ID start value : %d", lower_handle_id); + SYNX_CONSOLE_LOG(cur, end, "\n\tHandle ID end value : %d\n", upper_handle_id); - rc = synx_global_dump_shared_memory(); - if (rc) { - cur += scnprintf(cur, end - cur, - "Err %d: Failed to dump global shared mem\n", rc); - } - - if (synx_columns & ERROR_CODES && !list_empty( - &dev->error_list)) { - cur += scnprintf( - cur, end - cur, "\nError(s): "); + if (synx_columns & GLOBAL_HASHTABLE) + synx_debugfs_util_print_hash_table(&cur, &end, true); + if (synx_columns & LOCAL_HASHTABLE) + synx_debugfs_util_print_hash_table(&cur, &end, false); + if (synx_columns & CLIENT_HASHTABLE) + synx_debugfs_util_print_client_table(&cur, &end); + if (synx_columns & GLOBAL_SHARED_MEM) + synx_debugfs_util_print_global_shared_memory(&cur, &end); + if (synx_columns & DMA_FENCE_MAP) + synx_debugfs_util_print_dma_fence(&cur, &end); +#endif + if (synx_columns & ERROR_CODES && !list_empty(&dev->error_list)) { + SYNX_CONSOLE_LOG(cur, end, "\nError(s): "); mutex_lock(&dev->error_lock); list_for_each_entry_safe( err_node, err_node_tmp, &dev->error_list, node) { - cur += scnprintf(cur, end - cur, - "\n\tTime: %s - ID: %d - Code: %d", - err_node->timestamp, - err_node->h_synx, - err_node->error_code); + SYNX_CONSOLE_LOG(cur, end, "\n\tTime: %s - ", err_node->timestamp); + SYNX_CONSOLE_LOG(cur, end, "ID: %d - ", err_node->h_synx); + SYNX_CONSOLE_LOG(cur, end, "Code: %d", err_node->error_code); list_del(&err_node->node); kfree(err_node); } mutex_unlock(&dev->error_lock); } - len = simple_read_from_buffer(buf, count, ppos, dbuf, cur - dbuf); kfree(dbuf); return len; } +#ifdef ENABLE_DEBUGFS static ssize_t synx_table_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - return 0; + u32 stat = -1; + u32 i = 0, base = 10, num = 0; + bool invalid_val = false; + char *kbuffer = kzalloc(BUF_SIZE, GFP_KERNEL); + + if (!kbuffer) + return -ENOMEM; + stat = copy_from_user(kbuffer, buf, BUF_SIZE); + if (stat != 0) { + kfree(kbuffer); + return -EFAULT; + } + if (kbuffer[i] == '0' && (kbuffer[i+1] == 'x' || kbuffer[i+1] == 'X')) { + base = 16; + i += 2; + } + for ( ; (i < BUF_SIZE / 2 && kbuffer[i] != '-' && kbuffer[i] != '\n'); i++) + SYNX_READ_CHAR(kbuffer, num, base, i); + if (!invalid_val) + lower_handle_id = num; + + if (kbuffer[i] == '-') { + num = 0; + i++; + for ( ; i < BUF_SIZE && kbuffer[i] != '\n'; i++) + SYNX_READ_CHAR(kbuffer, num, base, i); + if (!invalid_val) + upper_handle_id = num; + } else if (kbuffer[i] == '\n') + upper_handle_id = lower_handle_id; + kfree(kbuffer); + + return count; } +#endif static const struct file_operations synx_table_fops = { .owner = THIS_MODULE, .read = synx_table_read, +#ifdef ENABLE_DEBUGFS .write = synx_table_write, +#endif .open = simple_open, }; +#ifdef ENABLE_DEBUGFS +static ssize_t synx_help_read(struct file *file, + char *buf, + size_t count, + loff_t *ppos) +{ + char *dbuf, *cur, *end; + ssize_t len = 0; + + dbuf = kzalloc(MAX_HELP_BUF_SIZE, GFP_KERNEL); + if (!dbuf) + return -ENOMEM; + + cur = dbuf; + end = cur + MAX_HELP_BUF_SIZE; + synx_debugfs_util_load_help_content(&cur, &end); + len = simple_read_from_buffer(buf, count, ppos, dbuf, cur - dbuf); + kfree(dbuf); + return len; +} +static const struct file_operations synx_help_fops = { + .owner = THIS_MODULE, + .read = synx_help_read, +}; +#endif struct dentry *synx_init_debugfs_dir(struct synx_device *dev) { struct dentry *dir = NULL; - dir = debugfs_create_dir("synx_debug", NULL); if (!dir) { dprintk(SYNX_ERR, "Failed to create debugfs for synx\n"); return NULL; } - debugfs_create_u32("debug_level", 0644, dir, &synx_debug); - debugfs_create_u32("column_level", 0644, dir, &synx_columns); + debugfs_create_ulong("column_level", 0644, dir, &synx_columns); if (!debugfs_create_file("synx_table", 0644, dir, dev, &synx_table_fops)) { dprintk(SYNX_ERR, "Failed to create debugfs file for synx\n"); return NULL; } - +#ifdef ENABLE_DEBUGFS + if (!debugfs_create_file("help", + 0444, dir, dev, &synx_help_fops)) { + dprintk(SYNX_ERR, "Failed to create debugfs help file for synx\n"); + return NULL; + } +#endif return dir; } diff --git a/msm/synx/synx_debugfs.h b/msm/synx/synx_debugfs.h index 0692a89281..d11aa02c7e 100644 --- a/msm/synx/synx_debugfs.h +++ b/msm/synx/synx_debugfs.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __SYNX_DEBUGFS_H__ @@ -11,6 +11,8 @@ #include #include "synx_private.h" +//#define ENABLE_DEBUGFS +#define STATE_NAME_SPACE (4) enum synx_debug_level { SYNX_ERR = 0x0001, @@ -26,14 +28,30 @@ enum synx_debug_level { }; enum synx_columns_level { - NAME_COLUMN = 0x0001, - ID_COLUMN = 0x0002, - BOUND_COLUMN = 0x0004, - STATE_COLUMN = 0x0008, - FENCE_COLUMN = 0x0010, - COREDATA_COLUMN = 0x0020, - GLOBAL_COLUMN = 0x0040, - ERROR_CODES = 0x8000, + NAME_COLUMN = 0x00000001, + ID_COLUMN = 0x00000002, + BOUND_COLUMN = 0x00000004, + STATUS_COLUMN = 0x00000008, + FENCE_COLUMN = 0x00000010, + COREDATA_COLUMN = 0x00000020, + GLOBAL_IDX_COLUMN = 0x00000040, + REL_CNT_COLUMN = 0x00000080, + MAP_CNT_COLUMN = 0x00000100, + REF_CNT_COLUMN = 0x00000200, + NUM_CHILD_COLUMN = 0x00000400, + SUBSCRIBERS_COLUMN = 0x00000800, + WAITERS_COLUMN = 0x00001000, + PARENTS_COLUMN = 0x00002000, + CLIENT_ID_COLUMN = 0x00004000, + + LOCAL_HASHTABLE = 0x00010000, + GLOBAL_HASHTABLE = 0x00020000, + CLIENT_HASHTABLE = 0x00040000, + GLOBAL_SHARED_MEM = 0x00080000, + DMA_FENCE_MAP = 0x00100000, + CSL_FENCE_MAP = 0x00200000, + + ERROR_CODES = 0x00008000, }; #ifndef SYNX_DBG_LABEL @@ -43,6 +61,8 @@ enum synx_columns_level { #define SYNX_DBG_TAG SYNX_DBG_LABEL ": %4s: " extern int synx_debug; +extern u32 lower_handle_id, upper_handle_id; +extern long synx_columns; static inline char *synx_debug_str(int level) { @@ -77,6 +97,36 @@ static inline char *synx_debug_str(int level) } \ } while (0) +#define SYNX_CONSOLE_LOG(__cur, __end, \ + __fmt_string, arg...) \ + do { \ + if ((__end - __cur) * (sizeof(char *)) \ + - strlen(__fmt_string) <= STATE_NAME_SPACE) \ + dprintk(SYNX_DBG, __fmt_string, ## arg); \ + else \ + __cur += scnprintf(__cur, __end - __cur, \ + __fmt_string, ## arg); \ + } while (0) + +#define SYNX_READ_CHAR(__buf, __num, \ + __base, __pos) \ + do { \ + if (__buf[__pos] >= '0' && \ + __buf[__pos] <= '9') \ + __num = __num * __base + \ + (__buf[__pos] - '0'); \ + else if (__buf[__pos] >= 'a' && \ + __buf[__pos] <= 'f') \ + __num = __num * __base + \ + (__buf[__pos] - 'a' + 10); \ + else if (__buf[__pos] >= 'A' && \ + __buf[__pos] <= 'F') \ + __num = __num * __base + \ + (__buf[__pos] - 'A' + 10); \ + else \ + invalid_val = true; \ + } while (0) + /** * synx_init_debugfs_dir - Initializes debugfs * diff --git a/msm/synx/synx_debugfs_util.c b/msm/synx/synx_debugfs_util.c new file mode 100644 index 0000000000..9b21d29fc4 --- /dev/null +++ b/msm/synx/synx_debugfs_util.c @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include + +#include "synx_debugfs.h" +#include "synx_debugfs_util.h" +#include "synx_util.h" +#include "synx_private.h" +#include "synx_global.h" + +#define MAX_CUSTOM_STATUS ((1UL << 32) - 1) + +char *synx_debugfs_util_get_state_name(u32 status) +{ + char *state; + + if (status == 0) + state = "INV"; + else if (status == 1) + state = "ACT"; + else if (status == 2) + state = "SUC"; + else if (status == 3) + state = "ERR"; + else if (status == 4) + state = "CAN"; + else if (status == 5) + state = "EXT"; + else if (status == 6) + state = "SSR"; + else if (status > 64 && status <= MAX_CUSTOM_STATUS) + state = "CUS"; + else + state = "???"; + + return state; +} + +static int synx_debugfs_util_get_client_data(struct synx_client *client) +{ + if (IS_ERR_OR_NULL(client)) + return -SYNX_NOENT; + kref_get(&client->refcount); + return SYNX_SUCCESS; +} + +static void synx_debugfs_util_put_client_data(struct synx_client *client) +{ + if (!IS_ERR_OR_NULL(client)) + kref_put(&client->refcount, synx_client_destroy); +} + +static int synx_debugfs_util_get_handle(struct synx_handle_coredata *handle_coredata) +{ + if (IS_ERR_OR_NULL(handle_coredata)) + return -SYNX_NOENT; + kref_get(&handle_coredata->refcount); + return SYNX_SUCCESS; +} + +static void synx_debugfs_util_put_handle(struct synx_handle_coredata *handle_coredata) +{ + if (!IS_ERR_OR_NULL(handle_coredata)) + kref_put(&handle_coredata->refcount, synx_util_destroy_handle); +} + +static int synx_debugfs_util_get_CSL_fence_entry(struct synx_entry_64 *entry) +{ + if (IS_ERR_OR_NULL(entry)) + return -SYNX_NOENT; + kref_get(&entry->refcount); + return SYNX_SUCCESS; +} + +static void synx_debugfs_util_put_CSL_fence_entry(struct synx_entry_64 *entry) +{ + if (!IS_ERR_OR_NULL(entry)) + kref_put(&entry->refcount, synx_util_destroy_data); +} + +bool synx_debugfs_util_is_valid_global_shared_memory_entry(struct synx_global_coredata *entry, + u32 idx) +{ + int i; + + if (!entry || entry->handle != idx) + return false; + if (entry->status || entry->handle || entry->refcount || + entry->num_child || entry->subscribers || entry->waiters) + return true; + + for (i = 0; i < SYNX_GLOBAL_MAX_PARENTS; i++) { + if (entry->parents[i]) + return true; + } + return false; +} + +static bool synx_debugfs_util_is_valid_dma_handle_range(struct synx_fence_entry *fence_entry) +{ + if ((fence_entry->g_handle >= lower_handle_id && + fence_entry->g_handle <= upper_handle_id) || + (fence_entry->l_handle >= lower_handle_id && + fence_entry->l_handle <= upper_handle_id)) + return true; + return false; +} + +static void synx_debugfs_util_print_map_column_values(char **cur, + char **end, + struct synx_map_entry *entry) +{ + if (synx_columns & STATUS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%s", synx_debugfs_util_get_state_name + (synx_util_get_object_status(entry->synx_obj))); + if (synx_columns & ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t %x", entry->key); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t %d", kref_read(&entry->refcount)); + if (synx_columns & BOUND_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t %d", entry->synx_obj->num_bound_synxs); + if (synx_columns & GLOBAL_IDX_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t %d", entry->synx_obj->global_idx); + if (synx_columns & MAP_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t %d", entry->synx_obj->map_count); + SYNX_CONSOLE_LOG(*cur, *end, "\n\t-------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, "-----------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, "-----------\n"); +} + +void synx_debugfs_util_print_hash_table(char **cur, + char **end, + bool is_global) +{ + struct synx_map_entry *map_entry = NULL; + struct synx_coredata *synx_obj = NULL; + u32 key; + + if (is_global) + SYNX_CONSOLE_LOG(*cur, *end, + "\n\t-------------GLOBAL MAP TABLE------------\n"); + else + SYNX_CONSOLE_LOG(*cur, *end, + "\n\t-------------LOCAL MAP TABLE------------\n"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\t\t"); + + if (synx_columns & STATUS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| STATUS |"); + if (synx_columns & ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| HANDLE |"); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| REF CNT |"); + if (synx_columns & BOUND_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| NUM BOUND |"); + if (synx_columns & GLOBAL_IDX_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| GLOBAL INDEX |"); + if (synx_columns & MAP_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| MAP CNT |"); + SYNX_CONSOLE_LOG(*cur, *end, "\n"); + + for (key = lower_handle_id; key <= upper_handle_id; key++) { + map_entry = synx_util_get_map_entry(key); + if (IS_ERR_OR_NULL(map_entry) || IS_ERR_OR_NULL(map_entry->synx_obj) || + (is_global ^ synx_util_is_global_handle(key))) { + synx_util_release_map_entry(map_entry); + continue; + } + synx_obj = map_entry->synx_obj; + synx_util_get_object(synx_obj); + mutex_lock(&synx_obj->obj_lock); + synx_debugfs_util_print_map_column_values(cur, end, map_entry); + mutex_unlock(&synx_obj->obj_lock); + synx_util_put_object(synx_obj); + synx_util_release_map_entry(map_entry); + } +} + +void synx_debugfs_util_print_dma_fence(char **cur, + char **end) +{ + struct synx_fence_entry *curr = NULL; + struct hlist_node *tmp; + struct dma_fence *fence_entry = NULL; + u32 map_itr; + + SYNX_CONSOLE_LOG(*cur, *end, "\n\t-------------DMA FENCE MAP TABLE------------\n"); + + if (synx_columns & FENCE_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| DMA FENCE |"); + if (synx_columns & STATUS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| STATUS |"); + if (synx_columns & ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| HANDLE |"); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| REF CNT |"); + SYNX_CONSOLE_LOG(*cur, *end, "\n"); + + spin_lock_bh(&synx_dev->native->fence_map_lock); + hash_for_each_safe(synx_dev->native->fence_map, map_itr, tmp, curr, node) { + if (IS_ERR_OR_NULL(curr)) + continue; + fence_entry = (struct dma_fence *)curr->key; + dma_fence_get(fence_entry); + if (synx_debugfs_util_is_valid_dma_handle_range(curr)) { + if (synx_columns & FENCE_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t%p", fence_entry); + if (synx_columns & STATUS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%s", + synx_debugfs_util_get_state_name + (__fence_state(fence_entry, false))); + if (synx_columns & ID_COLUMN) { + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%d", curr->g_handle); + SYNX_CONSOLE_LOG(*cur, *end, "\t%d", curr->l_handle); + } + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%d", + kref_read(&(fence_entry)->refcount)); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\t-------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, + "-----------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, "-----------\n"); + } + dma_fence_put(fence_entry); + } + spin_unlock_bh(&synx_dev->native->fence_map_lock); +} + +void synx_debugfs_util_print_csl_fence(char **cur, + char **end) +{ + u32 itr, rc = SYNX_SUCCESS; + struct synx_entry_64 *curr = NULL; + struct hlist_node *tmp; + struct synx_map_entry *map_entry = NULL; + + SYNX_CONSOLE_LOG(*cur, *end, "\n\t------------- CSL FENCE MAP TABLE------------\n"); + + if (synx_columns & FENCE_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| CSL FENCE |"); + if (synx_columns & STATUS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| STATUS |"); + if (synx_columns & ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| HANDLE |"); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| REF CNT |"); + SYNX_CONSOLE_LOG(*cur, *end, "\n"); + + spin_lock_bh(&synx_dev->native->csl_map_lock); + hash_for_each_safe(synx_dev->native->csl_fence_map, itr, tmp, curr, node) { + rc = synx_debugfs_util_get_CSL_fence_entry(curr); + if (rc) { + spin_unlock_bh(&synx_dev->native->csl_map_lock); + return; + } + if (curr->data[0] >= lower_handle_id && curr->data[0] <= upper_handle_id) { + if (synx_columns & FENCE_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "%p", curr->key); + if (synx_columns & STATUS_COLUMN) { + map_entry = synx_util_get_map_entry(curr->data[0]); + if (!IS_ERR_OR_NULL(map_entry) && + !IS_ERR_OR_NULL(map_entry->synx_obj)) { + SYNX_CONSOLE_LOG(*cur, *end, "\t%s", + synx_debugfs_util_get_state_name + (synx_util_get_object_status(map_entry->synx_obj))); + synx_util_release_map_entry(map_entry); + } + } //TODO : Update status field of CSL Fence with updated structure + if (synx_columns & ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%d", curr->data[0]); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t%d", kref_read(&curr->refcount)); + SYNX_CONSOLE_LOG(*cur, *end, "\n\t-------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, "-----------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, "-----------\n"); + } + synx_debugfs_util_put_CSL_fence_entry(curr); + } + spin_unlock_bh(&synx_dev->native->csl_map_lock); +} + +void synx_debugfs_util_print_global_shared_memory(char **cur, + char **end) +{ + struct synx_global_coredata synx_global_entry; + u32 i, idx; + + /* Column heading set up*/ + SYNX_CONSOLE_LOG(*cur, *end, + "\n\t ------------- GLOBAL SHARED MEMORY ------------\n\t"); + + if (synx_columns & STATUS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| STATUS |"); + if (synx_columns & ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| HANDLE |"); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| REF CNT |"); + if (synx_columns & NUM_CHILD_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| NUM CHILD |"); + if (synx_columns & SUBSCRIBERS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| SUBSCRIBERS |"); + if (synx_columns & WAITERS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| WAITERS |"); + if (synx_columns & PARENTS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| PARENTS |"); + SYNX_CONSOLE_LOG(*cur, *end, "\n"); + + for (idx = lower_handle_id ; idx <= upper_handle_id ; idx++) { + if (!synx_fetch_global_shared_memory_handle_details(idx, &synx_global_entry) || + !synx_debugfs_util_is_valid_global_shared_memory_entry(&synx_global_entry, idx)) + continue; + if (synx_columns & STATUS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t %s", + synx_debugfs_util_get_state_name(synx_global_entry.status)); + if (synx_columns & ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%x", synx_global_entry.handle); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%d", synx_global_entry.refcount); + if (synx_columns & NUM_CHILD_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%d", synx_global_entry.num_child); + if (synx_columns & SUBSCRIBERS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t%d", synx_global_entry.subscribers); + if (synx_columns & WAITERS_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%d", synx_global_entry.waiters); + if (synx_columns & PARENTS_COLUMN) { + for (i = 0; i < SYNX_GLOBAL_MAX_PARENTS; i++) { + if (synx_global_entry.parents[i]) + SYNX_CONSOLE_LOG(*cur, *end, " %2u", + synx_global_entry.parents[i]); + } + } + SYNX_CONSOLE_LOG(*cur, *end, "\n\t-------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, "-----------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, "-----------\n"); + } +} + +void synx_debugfs_util_print_client_table(char **cur, + char **end) +{ + u32 rc = SYNX_SUCCESS; + struct synx_client *curr; + struct hlist_node *tmp; + struct hlist_node *tmp2; + struct synx_handle_coredata *curr2 = NULL; + u32 client_map_itr, handle_map_itr; + + SYNX_CONSOLE_LOG(*cur, *end, "\n\t ------------- CLIENT MAP TABLE------------\n"); + if (synx_columns & CLIENT_ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| CLIENT ID |"); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "|CLIENT REF COUNT|"); + if (synx_columns & ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "| HANDLE ID |"); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "|REF COUNT|"); + if (synx_columns & REL_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "|REL COUNT|"); + SYNX_CONSOLE_LOG(*cur, *end, "\n"); + spin_lock_bh(&synx_dev->native->metadata_map_lock); + hash_for_each_safe(synx_dev->native->client_metadata_map, + client_map_itr, tmp, curr, node) { + rc = synx_debugfs_util_get_client_data(curr); + if (rc) + goto bail; + spin_lock_bh(&curr->handle_map_lock); + hash_for_each_safe(curr->handle_map, + handle_map_itr, tmp2, curr2, node) { + rc = synx_debugfs_util_get_handle(curr2); + if (rc) { + spin_unlock_bh(&curr->handle_map_lock); + synx_debugfs_util_put_client_data(curr); + goto bail; + } + if (curr2->key >= lower_handle_id && curr2->key <= upper_handle_id) { + if (synx_columns & CLIENT_ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t%u", curr->id); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%d", + kref_read(&curr->refcount)); + if (synx_columns & ID_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t%d", curr2->key); + if (synx_columns & REF_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%d", + kref_read(&curr2->refcount)); + if (synx_columns & REL_CNT_COLUMN) + SYNX_CONSOLE_LOG(*cur, *end, "\t\t%d", curr2->rel_count); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\t-------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, + "-----------------------------------------"); + SYNX_CONSOLE_LOG(*cur, *end, "-----------\n"); + } + synx_debugfs_util_put_handle(curr2); + } + spin_unlock_bh(&curr->handle_map_lock); + synx_debugfs_util_put_client_data(curr); + } +bail: + spin_unlock_bh(&synx_dev->native->metadata_map_lock); +} + +void synx_debugfs_util_load_help_content(char **cur, + char **end) +{ + SYNX_CONSOLE_LOG(*cur, *end, + "\n\n\tSynx tables Supported for debugfs with the column names:"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\n\tGLOBAL/LOCAL MAP COLUMNS : STATUS, ID, REF_CNT, BOUND,"); + SYNX_CONSOLE_LOG(*cur, *end, "\tGLOBAL INDEX, MAP CNT\n"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\tGLOBAL SHARED MEMORY COLUMNS : STATUS, ID,"); + SYNX_CONSOLE_LOG(*cur, *end, + "REF_CNT, NUM_CHILD, \tSUBSCRIBERS, WAITERS, PARENTS"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\n\tCLIENT MAP COLUMNS : CLIENT_ID, REF_CNT, REL_CNT, ID"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\n\tDMA FENCE COLUMNS: STATUS, ID, REF_CNT, DMA FENCE"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\n\tINSTRUCTIONS TO BE FOLLOWED:"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\n\tTO PRINT CHOOSE THE COLUMNS ACCORDINGLY AND ADD UP THE"); + SYNX_CONSOLE_LOG(*cur, *end, + "\tHEXADECIMAL VALUES & PASS THE ADDED UP VALUES FOR COLUMN ALONG"); + SYNX_CONSOLE_LOG(*cur, *end, "WITH TABLE SELECTION VALUE AS SHOWN BELOW:"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\tSet Below Values for Column selection\n"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\n\tNAME_COLUMN = 0x0001"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tID_COLUMN = 0x0002"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tBOUND_COLUMN = 0x0004"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tSTATUS_COLUMN = 0x0008"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tFENCE_COLUMN = 0x0010"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tCOREDATA_COLUMN = 0x0020"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tGLOBAL_IDX_COLUMN = 0x0040"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tREL_CNT_COLUMN = 0x0080"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tMAP_CNT_COLUMN = 0x0100"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tREF_CNT_COLUMN = 0x0200"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tNUM_CHILD_COLUMN = 0x0400"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tSUBSCRIBERS_COLUMN= 0x0800"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tWAITERS_COLUMN = 0x1000"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tPARENTS_COLUMN = 0x2000"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tCLIENT_ID_COLUMN = 0x4000"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\n\tSet Below Values for Table selection\n"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tLOCAL_HASHTABLE = 0x00010000"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tGLOBAL_HASHTABLE = 0x00020000"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tCLIENT_HASHTABLE = 0x00040000"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tGLOBAL_SHARED_MEM = 0x00080000"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tDMA_FENCE_MAP = 0x00100000\n"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\tExample : To select Global map & all its columns :"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\t echo 0x2034E>column_level"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\t Last four digits in hexadecimal flag"); + SYNX_CONSOLE_LOG(*cur, *end, " is dedicated for setting columns,"); + SYNX_CONSOLE_LOG(*cur, *end, + "\tuser can even set \"FFFF\" to set all columns"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\t Instead of passing 0x2034E, \tuser can even pass"); + SYNX_CONSOLE_LOG(*cur, *end, " 0x2FFFF to fetch the same"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\n\tUser can set Handle Range with echo command as shown below\n"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\techo 1048577-1048580>synx_table"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\tFor single handle : echo \"1048577\">synx_table"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\tHandle range can be set in hexadecimal values as shown below:"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\techo 0x100001-10000f>synx_table"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\tSingle handle : echo 0x100001>synx_table"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\n\tTo print info on console : cat synx_table"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\n\tHandle states :"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tACT : SYNX_STATE_ACTIVE"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tINV : SYNX_STATE_INVALID"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tERR : SYNX_STATE_SIGNALED_ERROR"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tSUC : SYNX_STATE_SIGNALED_SUCCESS"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tCAN : SYNX_STATE_SIGNALED_CANCELLED"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tEXT : SYNX_STATE_SIGNALED_EXTERNAL"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tSSR : SYNX_STATE_SIGNALED_SSR\n"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tCUS : CUSTOM SIGNAL"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\t??? : UNKNOWN / UNDEFINED"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\n\tAdditional information:"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\tNo need to set handle ID range and column or table selection"); + SYNX_CONSOLE_LOG(*cur, *end, "\tvalues again if once it is already set"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\tSimply using cat synx_table command user can print the data"); + SYNX_CONSOLE_LOG(*cur, *end, "\tfor same table with same set of columns"); + SYNX_CONSOLE_LOG(*cur, *end, "\n\tTo print all tables and all"); + SYNX_CONSOLE_LOG(*cur, *end, "columns set column level value to 0x1fffff"); + SYNX_CONSOLE_LOG(*cur, *end, + "\n\tCurrently we do not support CSL fence\n\n"); +} diff --git a/msm/synx/synx_debugfs_util.h b/msm/synx/synx_debugfs_util.h new file mode 100644 index 0000000000..4e47504a47 --- /dev/null +++ b/msm/synx/synx_debugfs_util.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __SYNX_DEBUGFS_UTIL_H__ +#define __SYNX_DEBUGFS_UTIL_H__ + +#include "synx_api.h" +#include "synx_private.h" + +#define GLOBAL_HANDLE_STARTING_ID (1048577) + +/* DMA FENCE print function */ +void synx_debugfs_util_print_dma_fence(char **cur, char **end); + +/* CSL FENCE print function */ +void synx_debugfs_util_print_csl_fence(char **cur, char **end); + +/* GLOBAL & LOCAL MAP print function */ +void synx_debugfs_util_print_hash_table(char **cur, char **end, bool flag); + +/* GLOBAL SHARED MEMORY print function */ +void synx_debugfs_util_print_global_shared_memory(char **cur, char **end); + +/* CLIENT MAP print function */ +void synx_debugfs_util_print_client_table(char **cur, char **end); + +/* Function to get SYNX State Name */ +char *synx_debugfs_util_get_state_name(u32 status); + +/* Function for loading content of the help option for debugfs v2 */ +void synx_debugfs_util_load_help_content(char **cur, char **end); + +/* Function to check entry of the global shared memory is valid or not */ +bool synx_debugfs_util_is_valid_global_shared_memory_entry(struct synx_global_coredata *entry, +u32 idx); + +#endif /* __SYNX_DEBUGFS_UTIL_H__ */ diff --git a/msm/synx/synx_global.c b/msm/synx/synx_global.c index 7a10a3d653..4ead16965b 100644 --- a/msm/synx/synx_global.c +++ b/msm/synx/synx_global.c @@ -5,7 +5,6 @@ #include #include - #include "synx_debugfs.h" #include "synx_global.h" @@ -78,6 +77,33 @@ static void synx_global_print_data( func, i, synx_g_obj->parents[i]); } +bool synx_fetch_global_shared_memory_handle_details(u32 synx_handle, + struct synx_global_coredata *synx_global_entry) +{ + int rc = SYNX_SUCCESS; + u32 idx; + unsigned long flags; + struct synx_global_coredata *entry; + + if (!synx_gmem.table) { + dprintk(SYNX_VERB, "synx_gmem is NULL\n"); + return false; + } + idx = synx_handle & SYNX_HANDLE_INDEX_MASK; + if (!synx_is_valid_idx(idx)) + return false; + rc = synx_gmem_lock(idx, &flags); + if (rc) { + dprintk(SYNX_VERB, "Failed to lock entry %d\n", idx); + return false; + } + entry = &synx_gmem.table[idx]; + memcpy(synx_global_entry, entry, sizeof(struct synx_global_coredata)); + synx_gmem_unlock(idx, &flags); + + return true; +} + int synx_global_dump_shared_memory(void) { int rc = SYNX_SUCCESS, idx; @@ -805,14 +831,13 @@ int synx_global_recover(enum synx_core_id core_id) const u32 size = SYNX_GLOBAL_MAX_OBJS; unsigned long flags; struct synx_global_coredata *synx_g_obj; - bool update; int *clear_idx = NULL; + if (!synx_gmem.table) return -SYNX_NOMEM; clear_idx = kzalloc(sizeof(int)*SYNX_GLOBAL_MAX_OBJS, GFP_KERNEL); - if (!clear_idx) return -SYNX_NOMEM; diff --git a/msm/synx/synx_global.h b/msm/synx/synx_global.h index 4f1b7edc2a..dcf5d10e9e 100644 --- a/msm/synx/synx_global.h +++ b/msm/synx/synx_global.h @@ -10,7 +10,6 @@ #include "ipclite_client.h" #include - /** * enum synx_core_id - Synx core IDs * @@ -299,4 +298,8 @@ int synx_global_dump_shared_memory(void); */ int synx_global_fetch_handle_details(u32 idx, u32 *h_synx); +/* Function to fetch global shared memory entry */ +bool synx_fetch_global_shared_memory_handle_details(u32 synx_handle, + struct synx_global_coredata *synx_global_entry); + #endif /* __SYNX_SHARED_MEM_H__ */ diff --git a/msm/synx/synx_util.c b/msm/synx/synx_util.c index 86d3e593da..65bea3a83c 100644 --- a/msm/synx/synx_util.c +++ b/msm/synx/synx_util.c @@ -10,9 +10,9 @@ #include "synx_debugfs.h" #include "synx_util.h" +#include "synx_private.h" extern void synx_external_callback(s32 sync_obj, int status, void *data); -static u32 __fence_state(struct dma_fence *fence, bool locked); int synx_util_init_coredata(struct synx_coredata *synx_obj, struct synx_create_params *params, @@ -224,7 +224,7 @@ int synx_util_init_group_coredata(struct synx_coredata *synx_obj, return rc; } -static void synx_util_destroy_coredata(struct kref *kref) +void synx_util_destroy_coredata(struct kref *kref) { int rc; struct synx_coredata *synx_obj = @@ -697,7 +697,7 @@ error: return -SYNX_INVALID; } -static u32 __fence_state(struct dma_fence *fence, bool locked) +u32 __fence_state(struct dma_fence *fence, bool locked) { s32 status; u32 state = SYNX_STATE_INVALID; @@ -1003,7 +1003,7 @@ static void synx_util_destroy_map_entry_worker( kfree(map_entry); } -static void synx_util_destroy_map_entry(struct kref *kref) +void synx_util_destroy_map_entry(struct kref *kref) { struct synx_map_entry *map_entry = container_of(kref, struct synx_map_entry, refcount); @@ -1046,7 +1046,7 @@ static void synx_util_destroy_handle_worker( kfree(synx_data); } -static void synx_util_destroy_handle(struct kref *kref) +void synx_util_destroy_handle(struct kref *kref) { struct synx_handle_coredata *synx_data = container_of(kref, struct synx_handle_coredata, @@ -1442,7 +1442,7 @@ static void synx_client_cleanup(struct work_struct *dispatch) vfree(client); } -static void synx_client_destroy(struct kref *kref) +void synx_client_destroy(struct kref *kref) { struct synx_client *client = container_of(kref, struct synx_client, refcount); @@ -1571,7 +1571,7 @@ struct synx_entry_64 *synx_util_retrieve_data(void *fence, return entry; } -static void synx_util_destroy_data(struct kref *kref) +void synx_util_destroy_data(struct kref *kref) { struct synx_entry_64 *entry = container_of(kref, struct synx_entry_64, refcount); diff --git a/msm/synx/synx_util.h b/msm/synx/synx_util.h index 95f54c4bb2..60d20dae13 100644 --- a/msm/synx/synx_util.h +++ b/msm/synx/synx_util.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __SYNX_UTIL_H__ @@ -11,7 +11,8 @@ #include "synx_private.h" extern struct synx_device *synx_dev; - +u32 __fence_state(struct dma_fence *fence, bool locked); +void synx_util_destroy_coredata(struct kref *kref); extern void synx_fence_callback(struct dma_fence *fence, struct dma_fence_cb *cb); extern int synx_native_signal_fence(struct synx_coredata *synx_obj, @@ -99,7 +100,7 @@ struct synx_map_entry *synx_util_insert_to_map(struct synx_coredata *synx_obj, u32 h_synx, u32 flags); struct synx_map_entry *synx_util_get_map_entry(u32 h_synx); void synx_util_release_map_entry(struct synx_map_entry *map_entry); - +void synx_util_destroy_map_entry(struct kref *kref); /* fence map functions */ int synx_util_insert_fence_entry(struct synx_fence_entry *entry, u32 *h_synx, u32 global); @@ -157,6 +158,8 @@ struct synx_handle_coredata *synx_util_acquire_handle(struct synx_client *client void synx_util_release_handle(struct synx_handle_coredata *synx_data); int synx_util_update_handle(struct synx_client *client, u32 h_synx, u32 sync_id, u32 type, struct synx_handle_coredata **handle); +void synx_client_destroy(struct kref *kref); +void synx_util_destroy_handle(struct kref *kref); /* client memory handler functions */ struct synx_client *synx_get_client(struct synx_session *session); @@ -172,6 +175,7 @@ struct synx_entry_64 *synx_util_retrieve_data(void *fence, u32 type); void synx_util_remove_data(void *fence, u32 type); /* misc */ +void synx_util_destroy_data(struct kref *kref); void synx_util_map_import_params_to_create( struct synx_import_indv_params *params, struct synx_create_params *c_params); diff --git a/synx_modules.bzl b/synx_modules.bzl index d6ae761a25..cf945d1afe 100644 --- a/synx_modules.bzl +++ b/synx_modules.bzl @@ -13,6 +13,7 @@ register_synx_module( "synx/synx_global.c", "synx/synx_util.c", "synx/synx_debugfs.c", + "synx/synx_debugfs_util.c", ], )