summaryrefslogtreecommitdiff
path: root/lwis_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'lwis_debug.c')
-rw-r--r--lwis_debug.c196
1 files changed, 182 insertions, 14 deletions
diff --git a/lwis_debug.c b/lwis_debug.c
index 882f9f7..8e5927e 100644
--- a/lwis_debug.c
+++ b/lwis_debug.c
@@ -99,10 +99,17 @@ static void list_transactions(struct lwis_client *client, char *k_buf, size_t k_
trans_hist->info.emit_success_event_id,
trans_hist->info.emit_error_event_id);
strlcat(k_buf, tmp_buf, k_buf_size);
- scnprintf(tmp_buf, sizeof(tmp_buf),
- " Num Entries: %zu Processed @ %lld for %lldns\n",
- trans_hist->info.num_io_entries, trans_hist->process_timestamp,
- trans_hist->process_duration_ns);
+ /* Process timestamp not recorded */
+ if (trans_hist->process_timestamp == -1) {
+ scnprintf(tmp_buf, sizeof(tmp_buf), " Num Entries: %zu\n",
+ trans_hist->info.num_io_entries);
+ } else {
+ scnprintf(tmp_buf, sizeof(tmp_buf),
+ " Num Entries: %zu Processed @ %lld for %lldns\n",
+ trans_hist->info.num_io_entries,
+ trans_hist->process_timestamp,
+ trans_hist->process_duration_ns);
+ }
strlcat(k_buf, tmp_buf, k_buf_size);
}
hist_idx++;
@@ -177,7 +184,7 @@ static int generate_device_info(struct lwis_device *lwis_dev, char *buffer, size
}
static int generate_event_states_info(struct lwis_device *lwis_dev, char *buffer,
- size_t buffer_size)
+ size_t buffer_size, int lwis_event_dump_cnt)
{
/* Temporary buffer to be concatenated to the main buffer. */
char tmp_buf[96] = {};
@@ -186,13 +193,27 @@ static int generate_event_states_info(struct lwis_device *lwis_dev, char *buffer
unsigned long flags;
struct lwis_device_event_state *state;
bool enabled_event_present = false;
+ int traverse_last_events_size;
if (lwis_dev == NULL) {
pr_err("Unknown LWIS device pointer\n");
return -EINVAL;
}
- scnprintf(buffer, buffer_size, "=== LWIS EVENT STATES INFO: %s ===\n", lwis_dev->name);
+ if (lwis_event_dump_cnt >= 0 && lwis_event_dump_cnt <= EVENT_DEBUG_HISTORY_SIZE) {
+ scnprintf(tmp_buf, sizeof(tmp_buf), "=== LWIS DUMP LAST %d Received Events ===\n",
+ lwis_event_dump_cnt);
+ strlcat(buffer, tmp_buf, buffer_size);
+ traverse_last_events_size = lwis_event_dump_cnt;
+ } else if (lwis_event_dump_cnt > EVENT_DEBUG_HISTORY_SIZE) {
+ pr_err("lwis_event_dump_cnt (%d) exceed EVENT_DEBUG_HISTORY_SIZE (%d) \n",
+ lwis_event_dump_cnt, EVENT_DEBUG_HISTORY_SIZE);
+ return -EINVAL;
+ } else {
+ scnprintf(buffer, buffer_size, "=== LWIS EVENT STATES INFO: %s ===\n",
+ lwis_dev->name);
+ traverse_last_events_size = EVENT_DEBUG_HISTORY_SIZE;
+ }
spin_lock_irqsave(&lwis_dev->lock, flags);
if (hash_empty(lwis_dev->event_states)) {
@@ -211,9 +232,18 @@ static int generate_event_states_info(struct lwis_device *lwis_dev, char *buffer
if (!enabled_event_present) {
strlcat(buffer, "No enabled events\n", buffer_size);
}
- strlcat(buffer, "Last Events:\n", buffer_size);
+ if (lwis_event_dump_cnt < 0) {
+ strlcat(buffer, "Last Events:\n", buffer_size);
+ }
+
idx = lwis_dev->debug_info.cur_event_hist_idx;
- for (i = 0; i < EVENT_DEBUG_HISTORY_SIZE; ++i) {
+ for (i = 0; i < traverse_last_events_size; ++i) {
+ if (lwis_event_dump_cnt >= 0) {
+ if (idx == 0) {
+ idx = EVENT_DEBUG_HISTORY_SIZE;
+ }
+ idx--;
+ }
state = &lwis_dev->debug_info.event_hist[idx].state;
/* Skip uninitialized entries */
if (state->event_id != 0) {
@@ -223,9 +253,11 @@ static int generate_event_states_info(struct lwis_device *lwis_dev, char *buffer
lwis_dev->debug_info.event_hist[idx].timestamp);
strlcat(buffer, tmp_buf, buffer_size);
}
- idx++;
- if (idx >= EVENT_DEBUG_HISTORY_SIZE) {
- idx = 0;
+ if (lwis_event_dump_cnt < 0) {
+ idx++;
+ if (idx >= EVENT_DEBUG_HISTORY_SIZE) {
+ idx = 0;
+ }
}
}
@@ -295,6 +327,101 @@ static int generate_buffer_info(struct lwis_device *lwis_dev, char *buffer, size
return 0;
}
+static int generate_register_io_history(struct lwis_device *lwis_dev, char *buffer,
+ size_t buffer_size)
+{
+ /* Temporary buffer to be concatenated to the main buffer. */
+ char tmp_buf[128] = {};
+ struct lwis_register_io_info *reg_io;
+ int i, hist_idx;
+
+ if (lwis_dev == NULL) {
+ pr_err("Unknown LWIS device pointer\n");
+ return -EINVAL;
+ }
+
+ scnprintf(buffer, buffer_size, "=== LWIS REGISTER IO INFO: %s ===\n", lwis_dev->name);
+ strlcat(buffer, "Last register read/writes:\n", buffer_size);
+ hist_idx = lwis_dev->debug_info.cur_io_entry_hist_idx;
+ for (i = 0; i < IO_ENTRY_DEBUG_HISTORY_SIZE; ++i) {
+ reg_io = &lwis_dev->debug_info.io_entry_hist[hist_idx];
+ /* Skip uninitialized entries */
+ if (reg_io->start_timestamp != 0) {
+ if (reg_io->io_entry.type == LWIS_IO_ENTRY_READ) {
+ scnprintf(
+ tmp_buf, sizeof(tmp_buf),
+ "READ: bid %d, offset %llu, val %llu, access_size %lu, start_timestamp %llu\n",
+ reg_io->io_entry.rw.bid, reg_io->io_entry.rw.offset,
+ reg_io->io_entry.rw.val, reg_io->access_size,
+ reg_io->start_timestamp);
+ strlcat(buffer, tmp_buf, buffer_size);
+ } else if (reg_io->io_entry.type == LWIS_IO_ENTRY_READ_BATCH) {
+ scnprintf(
+ tmp_buf, sizeof(tmp_buf),
+ "READ_BATCH: bid %d, offset %llu, size_in_bytes %lu, access_size %lu, start_timestamp %llu\n",
+ reg_io->io_entry.rw_batch.bid,
+ reg_io->io_entry.rw_batch.offset,
+ reg_io->io_entry.rw_batch.size_in_bytes,
+ reg_io->access_size, reg_io->start_timestamp);
+ strlcat(buffer, tmp_buf, buffer_size);
+ } else if (reg_io->io_entry.type == LWIS_IO_ENTRY_WRITE) {
+ scnprintf(
+ tmp_buf, sizeof(tmp_buf),
+ "WRITE: bid %d, offset %llu, val %llu, access_size %lu, start_timestamp %llu\n",
+ reg_io->io_entry.rw.bid, reg_io->io_entry.rw.offset,
+ reg_io->io_entry.rw.val, reg_io->access_size,
+ reg_io->start_timestamp);
+ strlcat(buffer, tmp_buf, buffer_size);
+ } else if (reg_io->io_entry.type == LWIS_IO_ENTRY_WRITE_BATCH) {
+ scnprintf(
+ tmp_buf, sizeof(tmp_buf),
+ "WRITE_BATCH: bid %d, offset %llu, size_in_bytes %lu, access_size %lu, start_timestamp %llu\n",
+ reg_io->io_entry.rw_batch.bid,
+ reg_io->io_entry.rw_batch.offset,
+ reg_io->io_entry.rw_batch.size_in_bytes,
+ reg_io->access_size, reg_io->start_timestamp);
+ strlcat(buffer, tmp_buf, buffer_size);
+ } else if (reg_io->io_entry.type == LWIS_IO_ENTRY_MODIFY) {
+ scnprintf(
+ tmp_buf, sizeof(tmp_buf),
+ "MODIFY: bid %d, offset %llu, access_size %lu, start_timestamp %llu\n",
+ reg_io->io_entry.mod.bid, reg_io->io_entry.mod.offset,
+ reg_io->access_size, reg_io->start_timestamp);
+ strlcat(buffer, tmp_buf, buffer_size);
+ }
+ }
+ hist_idx++;
+ if (hist_idx >= IO_ENTRY_DEBUG_HISTORY_SIZE) {
+ hist_idx = 0;
+ }
+ }
+
+ return 0;
+}
+
+int lwis_debug_print_register_io_history(struct lwis_device *lwis_dev)
+{
+ int ret = 0;
+ /* Buffer to store information */
+ const size_t buffer_size = 10240;
+ char *buffer = kzalloc(buffer_size, GFP_KERNEL);
+ if (!buffer) {
+ dev_err(lwis_dev->dev, "Failed to allocate register io history log buffer\n");
+ return -ENOMEM;
+ }
+
+ ret = generate_register_io_history(lwis_dev, buffer, buffer_size);
+ if (ret) {
+ dev_err(lwis_dev->dev, "Failed to generate register io history");
+ goto exit;
+ }
+ print_to_log(buffer);
+
+exit:
+ kfree(buffer);
+ return 0;
+}
+
int lwis_debug_print_device_info(struct lwis_device *lwis_dev)
{
int ret = 0;
@@ -311,7 +438,7 @@ int lwis_debug_print_device_info(struct lwis_device *lwis_dev)
return 0;
}
-int lwis_debug_print_event_states_info(struct lwis_device *lwis_dev)
+int lwis_debug_print_event_states_info(struct lwis_device *lwis_dev, int lwis_event_dump_cnt)
{
int ret = 0;
/* Buffer to store information */
@@ -322,7 +449,7 @@ int lwis_debug_print_event_states_info(struct lwis_device *lwis_dev)
return -ENOMEM;
}
- ret = generate_event_states_info(lwis_dev, buffer, buffer_size);
+ ret = generate_event_states_info(lwis_dev, buffer, buffer_size, lwis_event_dump_cnt);
if (ret) {
dev_err(lwis_dev->dev, "Failed to generate event states info");
goto exit;
@@ -410,7 +537,7 @@ static ssize_t event_states_read(struct file *fp, char __user *user_buf, size_t
return -ENOMEM;
}
- ret = generate_event_states_info(lwis_dev, buffer, buffer_size);
+ ret = generate_event_states_info(lwis_dev, buffer, buffer_size, /*lwis_event_dump_cnt=*/-1);
if (ret) {
dev_err(lwis_dev->dev, "Failed to generate event states info");
goto exit;
@@ -471,6 +598,31 @@ exit:
return ret;
}
+static ssize_t register_io_history_read(struct file *fp, char __user *user_buf, size_t count,
+ loff_t *position)
+{
+ int ret = 0;
+ /* Buffer to store information */
+ const size_t buffer_size = 10240;
+ struct lwis_device *lwis_dev = fp->f_inode->i_private;
+ char *buffer = kzalloc(buffer_size, GFP_KERNEL);
+ if (!buffer) {
+ dev_err(lwis_dev->dev, "Failed to allocate register io history log buffer\n");
+ return -ENOMEM;
+ }
+
+ ret = generate_register_io_history(lwis_dev, buffer, buffer_size);
+ if (ret) {
+ dev_err(lwis_dev->dev, "Failed to generate register io history");
+ goto exit;
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, position, buffer, strlen(buffer));
+exit:
+ kfree(buffer);
+ return ret;
+}
+
static struct file_operations dev_info_fops = {
.owner = THIS_MODULE,
.read = dev_info_read,
@@ -491,6 +643,11 @@ static struct file_operations buffer_info_fops = {
.read = buffer_info_read,
};
+static struct file_operations register_io_history_fops = {
+ .owner = THIS_MODULE,
+ .read = register_io_history_read,
+};
+
int lwis_device_debugfs_setup(struct lwis_device *lwis_dev, struct dentry *dbg_root)
{
struct dentry *dbg_dir;
@@ -498,6 +655,7 @@ int lwis_device_debugfs_setup(struct lwis_device *lwis_dev, struct dentry *dbg_r
struct dentry *dbg_event_file;
struct dentry *dbg_transaction_file;
struct dentry *dbg_buffer_file;
+ struct dentry *dbg_reg_io_file;
/* DebugFS not present, just return */
if (dbg_root == NULL) {
@@ -543,11 +701,20 @@ int lwis_device_debugfs_setup(struct lwis_device *lwis_dev, struct dentry *dbg_r
dbg_buffer_file = NULL;
}
+ dbg_reg_io_file = debugfs_create_file("io_history", 0444, dbg_dir, lwis_dev,
+ &register_io_history_fops);
+ if (IS_ERR_OR_NULL(dbg_reg_io_file)) {
+ dev_warn(lwis_dev->dev, "Failed to create DebugFS io_history - %ld",
+ PTR_ERR(dbg_reg_io_file));
+ dbg_reg_io_file = NULL;
+ }
+
lwis_dev->dbg_dir = dbg_dir;
lwis_dev->dbg_dev_info_file = dbg_dev_info_file;
lwis_dev->dbg_event_file = dbg_event_file;
lwis_dev->dbg_transaction_file = dbg_transaction_file;
lwis_dev->dbg_buffer_file = dbg_buffer_file;
+ lwis_dev->dbg_reg_io_file = dbg_reg_io_file;
return 0;
}
@@ -564,6 +731,7 @@ int lwis_device_debugfs_cleanup(struct lwis_device *lwis_dev)
lwis_dev->dbg_event_file = NULL;
lwis_dev->dbg_transaction_file = NULL;
lwis_dev->dbg_buffer_file = NULL;
+ lwis_dev->dbg_reg_io_file = NULL;
return 0;
}