^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright IBM Corp. 2008, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Jan Glauber (jang@linux.vnet.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "qdio_debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "qdio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) debug_info_t *qdio_dbf_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) debug_info_t *qdio_dbf_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static struct dentry *debugfs_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define QDIO_DEBUGFS_NAME_LEN 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define QDIO_DBF_NAME_LEN 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct qdio_dbf_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) char dbf_name[QDIO_DBF_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) debug_info_t *dbf_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct list_head dbf_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static LIST_HEAD(qdio_dbf_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static DEFINE_MUTEX(qdio_dbf_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static debug_info_t *qdio_get_dbf_entry(char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct qdio_dbf_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) debug_info_t *rc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) mutex_lock(&qdio_dbf_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) list_for_each_entry(entry, &qdio_dbf_list, dbf_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (strcmp(entry->dbf_name, name) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) rc = entry->dbf_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) mutex_unlock(&qdio_dbf_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static void qdio_clear_dbf_list(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct qdio_dbf_entry *entry, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) mutex_lock(&qdio_dbf_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) list_for_each_entry_safe(entry, tmp, &qdio_dbf_list, dbf_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) list_del(&entry->dbf_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) debug_unregister(entry->dbf_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) mutex_unlock(&qdio_dbf_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int qdio_allocate_dbf(struct qdio_irq *irq_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) char text[QDIO_DBF_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct qdio_dbf_entry *new_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* allocate trace view for the interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) snprintf(text, QDIO_DBF_NAME_LEN, "qdio_%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) dev_name(&irq_ptr->cdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) irq_ptr->debug_area = qdio_get_dbf_entry(text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (irq_ptr->debug_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf reused");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) irq_ptr->debug_area = debug_register(text, 2, 1, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (!irq_ptr->debug_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (debug_register_view(irq_ptr->debug_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) &debug_hex_ascii_view)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) debug_unregister(irq_ptr->debug_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) debug_set_level(irq_ptr->debug_area, DBF_WARN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) new_entry = kzalloc(sizeof(struct qdio_dbf_entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!new_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) debug_unregister(irq_ptr->debug_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) strlcpy(new_entry->dbf_name, text, QDIO_DBF_NAME_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) new_entry->dbf_info = irq_ptr->debug_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) mutex_lock(&qdio_dbf_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) list_add(&new_entry->dbf_list, &qdio_dbf_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) mutex_unlock(&qdio_dbf_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int qstat_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned char state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct qdio_q *q = m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) seq_printf(m, "Timestamp: %Lx Last AI: %Lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) q->timestamp, last_ai_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) seq_printf(m, "nr_used: %d ftc: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) atomic_read(&q->nr_buf_used), q->first_to_check);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (q->is_input_q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) seq_printf(m, "batch start: %u batch count: %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) q->u.in.batch_start, q->u.in.batch_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) seq_printf(m, "DSCI: %x IRQs disabled: %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *(u8 *)q->irq_ptr->dsci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) test_bit(QDIO_IRQ_DISABLED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) &q->irq_ptr->poll_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) seq_printf(m, "SBAL states:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) debug_get_buf_state(q, i, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case SLSB_P_INPUT_NOT_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case SLSB_P_OUTPUT_NOT_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) seq_printf(m, "N");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) case SLSB_P_OUTPUT_PENDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) seq_printf(m, "P");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case SLSB_P_INPUT_PRIMED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) case SLSB_CU_OUTPUT_PRIMED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) seq_printf(m, "+");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case SLSB_P_INPUT_ACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) seq_printf(m, "A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case SLSB_P_INPUT_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) case SLSB_P_OUTPUT_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) seq_printf(m, "x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case SLSB_CU_INPUT_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) case SLSB_P_OUTPUT_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) seq_printf(m, "-");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) case SLSB_P_INPUT_HALTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) case SLSB_P_OUTPUT_HALTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) seq_printf(m, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) seq_printf(m, "?");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (i == 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) seq_printf(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) seq_printf(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) seq_printf(m, "\nSBAL statistics:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (!q->irq_ptr->perf_stat_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) seq_printf(m, " disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) seq_printf(m, "\n1 2.. 4.. 8.. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) "16.. 32.. 64.. 128\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) seq_printf(m, "\nError NOP Total\n%-10u %-10u %-10u\n\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) q->q_stats.nr_sbal_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) DEFINE_SHOW_ATTRIBUTE(qstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int ssqd_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct ccw_device *cdev = m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct qdio_ssqd_desc ssqd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) rc = qdio_get_ssqd_desc(cdev, &ssqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) seq_hex_dump(m, "", DUMP_PREFIX_NONE, 16, 4, &ssqd, sizeof(ssqd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) DEFINE_SHOW_ATTRIBUTE(ssqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static char *qperf_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) "Assumed adapter interrupts",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) "QDIO interrupts",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) "Requested PCIs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) "Inbound tasklet runs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) "Inbound tasklet resched",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) "Inbound tasklet resched2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) "Outbound tasklet runs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) "SIGA read",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) "SIGA write",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) "SIGA sync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) "Inbound calls",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) "Inbound handler",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) "Inbound stop_polling",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) "Inbound queue full",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) "Outbound calls",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) "Outbound handler",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) "Outbound queue full",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) "Outbound fast_requeue",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) "Outbound target_full",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) "QEBSM eqbs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) "QEBSM eqbs partial",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) "QEBSM sqbs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) "QEBSM sqbs partial",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) "Discarded interrupts"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static int qperf_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct qdio_irq *irq_ptr = m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) unsigned int *stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (!irq_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (!irq_ptr->perf_stat_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) seq_printf(m, "disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) stat = (unsigned int *)&irq_ptr->perf_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) seq_printf(m, "%26s:\t%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) qperf_names[i], *(stat + i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) size_t count, loff_t *off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct seq_file *seq = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct qdio_irq *irq_ptr = seq->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct qdio_q *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (!irq_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ret = kstrtoul_from_user(ubuf, count, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) irq_ptr->perf_stat_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) for_each_input_queue(irq_ptr, q, i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) memset(&q->q_stats, 0, sizeof(q->q_stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) for_each_output_queue(irq_ptr, q, i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) memset(&q->q_stats, 0, sizeof(q->q_stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) irq_ptr->perf_stat_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int qperf_seq_open(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return single_open(filp, qperf_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) file_inode(filp)->i_private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static const struct file_operations debugfs_perf_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .open = qperf_seq_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .write = qperf_seq_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static void setup_debugfs_entry(struct dentry *parent, struct qdio_q *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) char name[QDIO_DEBUGFS_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) q->is_input_q ? "input" : "output",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) q->nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) debugfs_create_file(name, 0444, parent, q, &qstat_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) void qdio_setup_debug_entries(struct qdio_irq *irq_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct qdio_q *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&irq_ptr->cdev->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) debugfs_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) debugfs_create_file("statistics", S_IFREG | S_IRUGO | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) irq_ptr->debugfs_dev, irq_ptr, &debugfs_perf_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) debugfs_create_file("ssqd", 0444, irq_ptr->debugfs_dev, irq_ptr->cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) &ssqd_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) for_each_input_queue(irq_ptr, q, i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) setup_debugfs_entry(irq_ptr->debugfs_dev, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) for_each_output_queue(irq_ptr, q, i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) setup_debugfs_entry(irq_ptr->debugfs_dev, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) debugfs_remove_recursive(irq_ptr->debugfs_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int __init qdio_debug_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) debugfs_root = debugfs_create_dir("qdio", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) debug_set_level(qdio_dbf_setup, DBF_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) DBF_EVENT("dbf created\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) debug_set_level(qdio_dbf_error, DBF_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) DBF_ERROR("dbf created\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) void qdio_debug_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) qdio_clear_dbf_list();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) debugfs_remove_recursive(debugfs_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) debug_unregister(qdio_dbf_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) debug_unregister(qdio_dbf_error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }