1 /* 2 * Copyright 2017 Thomas Gleixner <tglx@linutronix.de> 3 * 4 * This file is licensed under the GPL V2. 5 */ 6 #include <linux/irqdomain.h> 7 #include <linux/irq.h> 8 9 #include "internals.h" 10 11 static struct dentry *irq_dir; 12 13 struct irq_bit_descr { 14 unsigned int mask; 15 char *name; 16 }; 17 #define BIT_MASK_DESCR(m) { .mask = m, .name = #m } 18 19 static void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int state, 20 const struct irq_bit_descr *sd, int size) 21 { 22 int i; 23 24 for (i = 0; i < size; i++, sd++) { 25 if (state & sd->mask) 26 seq_printf(m, "%*s%s\n", ind + 12, "", sd->name); 27 } 28 } 29 30 #ifdef CONFIG_SMP 31 static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc) 32 { 33 struct irq_data *data = irq_desc_get_irq_data(desc); 34 struct cpumask *msk; 35 36 msk = irq_data_get_affinity_mask(data); 37 seq_printf(m, "affinity: %*pbl\n", cpumask_pr_args(msk)); 38 #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK 39 msk = irq_data_get_effective_affinity_mask(data); 40 seq_printf(m, "effectiv: %*pbl\n", cpumask_pr_args(msk)); 41 #endif 42 #ifdef CONFIG_GENERIC_PENDING_IRQ 43 msk = desc->pending_mask; 44 seq_printf(m, "pending: %*pbl\n", cpumask_pr_args(msk)); 45 #endif 46 } 47 #else 48 static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc) { } 49 #endif 50 51 static const struct irq_bit_descr irqchip_flags[] = { 52 BIT_MASK_DESCR(IRQCHIP_SET_TYPE_MASKED), 53 BIT_MASK_DESCR(IRQCHIP_EOI_IF_HANDLED), 54 BIT_MASK_DESCR(IRQCHIP_MASK_ON_SUSPEND), 55 BIT_MASK_DESCR(IRQCHIP_ONOFFLINE_ENABLED), 56 BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE), 57 BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE), 58 BIT_MASK_DESCR(IRQCHIP_EOI_THREADED), 59 }; 60 61 static void 62 irq_debug_show_chip(struct seq_file *m, struct irq_data *data, int ind) 63 { 64 struct irq_chip *chip = data->chip; 65 66 if (!chip) { 67 seq_printf(m, "chip: None\n"); 68 return; 69 } 70 seq_printf(m, "%*schip: %s\n", ind, "", chip->name); 71 seq_printf(m, "%*sflags: 0x%lx\n", ind + 1, "", chip->flags); 72 irq_debug_show_bits(m, ind, chip->flags, irqchip_flags, 73 ARRAY_SIZE(irqchip_flags)); 74 } 75 76 static void 77 irq_debug_show_data(struct seq_file *m, struct irq_data *data, int ind) 78 { 79 seq_printf(m, "%*sdomain: %s\n", ind, "", 80 data->domain ? data->domain->name : ""); 81 seq_printf(m, "%*shwirq: 0x%lx\n", ind + 1, "", data->hwirq); 82 irq_debug_show_chip(m, data, ind + 1); 83 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 84 if (!data->parent_data) 85 return; 86 seq_printf(m, "%*sparent:\n", ind + 1, ""); 87 irq_debug_show_data(m, data->parent_data, ind + 4); 88 #endif 89 } 90 91 static const struct irq_bit_descr irqdata_states[] = { 92 BIT_MASK_DESCR(IRQ_TYPE_EDGE_RISING), 93 BIT_MASK_DESCR(IRQ_TYPE_EDGE_FALLING), 94 BIT_MASK_DESCR(IRQ_TYPE_LEVEL_HIGH), 95 BIT_MASK_DESCR(IRQ_TYPE_LEVEL_LOW), 96 BIT_MASK_DESCR(IRQD_LEVEL), 97 98 BIT_MASK_DESCR(IRQD_ACTIVATED), 99 BIT_MASK_DESCR(IRQD_IRQ_STARTED), 100 BIT_MASK_DESCR(IRQD_IRQ_DISABLED), 101 BIT_MASK_DESCR(IRQD_IRQ_MASKED), 102 BIT_MASK_DESCR(IRQD_IRQ_INPROGRESS), 103 104 BIT_MASK_DESCR(IRQD_PER_CPU), 105 BIT_MASK_DESCR(IRQD_NO_BALANCING), 106 107 BIT_MASK_DESCR(IRQD_SINGLE_TARGET), 108 BIT_MASK_DESCR(IRQD_MOVE_PCNTXT), 109 BIT_MASK_DESCR(IRQD_AFFINITY_SET), 110 BIT_MASK_DESCR(IRQD_SETAFFINITY_PENDING), 111 BIT_MASK_DESCR(IRQD_AFFINITY_MANAGED), 112 BIT_MASK_DESCR(IRQD_MANAGED_SHUTDOWN), 113 114 BIT_MASK_DESCR(IRQD_FORWARDED_TO_VCPU), 115 116 BIT_MASK_DESCR(IRQD_WAKEUP_STATE), 117 BIT_MASK_DESCR(IRQD_WAKEUP_ARMED), 118 }; 119 120 static const struct irq_bit_descr irqdesc_states[] = { 121 BIT_MASK_DESCR(_IRQ_NOPROBE), 122 BIT_MASK_DESCR(_IRQ_NOREQUEST), 123 BIT_MASK_DESCR(_IRQ_NOTHREAD), 124 BIT_MASK_DESCR(_IRQ_NOAUTOEN), 125 BIT_MASK_DESCR(_IRQ_NESTED_THREAD), 126 BIT_MASK_DESCR(_IRQ_PER_CPU_DEVID), 127 BIT_MASK_DESCR(_IRQ_IS_POLLED), 128 BIT_MASK_DESCR(_IRQ_DISABLE_UNLAZY), 129 }; 130 131 static const struct irq_bit_descr irqdesc_istates[] = { 132 BIT_MASK_DESCR(IRQS_AUTODETECT), 133 BIT_MASK_DESCR(IRQS_SPURIOUS_DISABLED), 134 BIT_MASK_DESCR(IRQS_POLL_INPROGRESS), 135 BIT_MASK_DESCR(IRQS_ONESHOT), 136 BIT_MASK_DESCR(IRQS_REPLAY), 137 BIT_MASK_DESCR(IRQS_WAITING), 138 BIT_MASK_DESCR(IRQS_PENDING), 139 BIT_MASK_DESCR(IRQS_SUSPENDED), 140 }; 141 142 143 static int irq_debug_show(struct seq_file *m, void *p) 144 { 145 struct irq_desc *desc = m->private; 146 struct irq_data *data; 147 148 raw_spin_lock_irq(&desc->lock); 149 data = irq_desc_get_irq_data(desc); 150 seq_printf(m, "handler: %pf\n", desc->handle_irq); 151 seq_printf(m, "status: 0x%08x\n", desc->status_use_accessors); 152 irq_debug_show_bits(m, 0, desc->status_use_accessors, irqdesc_states, 153 ARRAY_SIZE(irqdesc_states)); 154 seq_printf(m, "istate: 0x%08x\n", desc->istate); 155 irq_debug_show_bits(m, 0, desc->istate, irqdesc_istates, 156 ARRAY_SIZE(irqdesc_istates)); 157 seq_printf(m, "ddepth: %u\n", desc->depth); 158 seq_printf(m, "wdepth: %u\n", desc->wake_depth); 159 seq_printf(m, "dstate: 0x%08x\n", irqd_get(data)); 160 irq_debug_show_bits(m, 0, irqd_get(data), irqdata_states, 161 ARRAY_SIZE(irqdata_states)); 162 seq_printf(m, "node: %d\n", irq_data_get_node(data)); 163 irq_debug_show_masks(m, desc); 164 irq_debug_show_data(m, data, 0); 165 raw_spin_unlock_irq(&desc->lock); 166 return 0; 167 } 168 169 static int irq_debug_open(struct inode *inode, struct file *file) 170 { 171 return single_open(file, irq_debug_show, inode->i_private); 172 } 173 174 static const struct file_operations dfs_irq_ops = { 175 .open = irq_debug_open, 176 .read = seq_read, 177 .llseek = seq_lseek, 178 .release = single_release, 179 }; 180 181 void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc) 182 { 183 char name [10]; 184 185 if (!irq_dir || !desc || desc->debugfs_file) 186 return; 187 188 sprintf(name, "%d", irq); 189 desc->debugfs_file = debugfs_create_file(name, 0444, irq_dir, desc, 190 &dfs_irq_ops); 191 } 192 193 static int __init irq_debugfs_init(void) 194 { 195 struct dentry *root_dir; 196 int irq; 197 198 root_dir = debugfs_create_dir("irq", NULL); 199 if (!root_dir) 200 return -ENOMEM; 201 202 irq_domain_debugfs_init(root_dir); 203 204 irq_dir = debugfs_create_dir("irqs", root_dir); 205 206 irq_lock_sparse(); 207 for_each_active_irq(irq) 208 irq_add_debugfs_entry(irq, irq_to_desc(irq)); 209 irq_unlock_sparse(); 210 211 return 0; 212 } 213 __initcall(irq_debugfs_init); 214