Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright 2017 Thomas Gleixner <tglx@linutronix.de>
  3
  4#include <linux/irqdomain.h>
  5#include <linux/irq.h>
  6#include <linux/uaccess.h>
  7
  8#include "internals.h"
  9
 10static struct dentry *irq_dir;
 11
 12struct irq_bit_descr {
 13	unsigned int	mask;
 14	char		*name;
 15};
 16#define BIT_MASK_DESCR(m)	{ .mask = m, .name = #m }
 17
 18static void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int state,
 19				const struct irq_bit_descr *sd, int size)
 20{
 21	int i;
 22
 23	for (i = 0; i < size; i++, sd++) {
 24		if (state & sd->mask)
 25			seq_printf(m, "%*s%s\n", ind + 12, "", sd->name);
 26	}
 27}
 28
 29#ifdef CONFIG_SMP
 30static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc)
 31{
 32	struct irq_data *data = irq_desc_get_irq_data(desc);
 33	const struct cpumask *msk;
 34
 35	msk = irq_data_get_affinity_mask(data);
 36	seq_printf(m, "affinity: %*pbl\n", cpumask_pr_args(msk));
 37#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
 38	msk = irq_data_get_effective_affinity_mask(data);
 39	seq_printf(m, "effectiv: %*pbl\n", cpumask_pr_args(msk));
 40#endif
 41#ifdef CONFIG_GENERIC_PENDING_IRQ
 42	msk = desc->pending_mask;
 43	seq_printf(m, "pending:  %*pbl\n", cpumask_pr_args(msk));
 44#endif
 45}
 46#else
 47static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc) { }
 48#endif
 49
 50static const struct irq_bit_descr irqchip_flags[] = {
 51	BIT_MASK_DESCR(IRQCHIP_SET_TYPE_MASKED),
 52	BIT_MASK_DESCR(IRQCHIP_EOI_IF_HANDLED),
 53	BIT_MASK_DESCR(IRQCHIP_MASK_ON_SUSPEND),
 54	BIT_MASK_DESCR(IRQCHIP_ONOFFLINE_ENABLED),
 55	BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE),
 56	BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE),
 57	BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
 58	BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
 59	BIT_MASK_DESCR(IRQCHIP_SUPPORTS_NMI),
 60	BIT_MASK_DESCR(IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND),
 61	BIT_MASK_DESCR(IRQCHIP_IMMUTABLE),
 62};
 63
 64static void
 65irq_debug_show_chip(struct seq_file *m, struct irq_data *data, int ind)
 66{
 67	struct irq_chip *chip = data->chip;
 68
 69	if (!chip) {
 70		seq_printf(m, "chip: None\n");
 71		return;
 72	}
 73	seq_printf(m, "%*schip:    ", ind, "");
 74	if (chip->irq_print_chip)
 75		chip->irq_print_chip(data, m);
 76	else
 77		seq_printf(m, "%s", chip->name);
 78	seq_printf(m, "\n%*sflags:   0x%lx\n", ind + 1, "", chip->flags);
 79	irq_debug_show_bits(m, ind, chip->flags, irqchip_flags,
 80			    ARRAY_SIZE(irqchip_flags));
 81}
 82
 83static void
 84irq_debug_show_data(struct seq_file *m, struct irq_data *data, int ind)
 85{
 86	seq_printf(m, "%*sdomain:  %s\n", ind, "",
 87		   data->domain ? data->domain->name : "");
 88	seq_printf(m, "%*shwirq:   0x%lx\n", ind + 1, "", data->hwirq);
 89	irq_debug_show_chip(m, data, ind + 1);
 90	if (data->domain && data->domain->ops && data->domain->ops->debug_show)
 91		data->domain->ops->debug_show(m, NULL, data, ind + 1);
 92#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
 93	if (!data->parent_data)
 94		return;
 95	seq_printf(m, "%*sparent:\n", ind + 1, "");
 96	irq_debug_show_data(m, data->parent_data, ind + 4);
 97#endif
 98}
 99
100static const struct irq_bit_descr irqdata_states[] = {
101	BIT_MASK_DESCR(IRQ_TYPE_EDGE_RISING),
102	BIT_MASK_DESCR(IRQ_TYPE_EDGE_FALLING),
103	BIT_MASK_DESCR(IRQ_TYPE_LEVEL_HIGH),
104	BIT_MASK_DESCR(IRQ_TYPE_LEVEL_LOW),
105	BIT_MASK_DESCR(IRQD_LEVEL),
106
107	BIT_MASK_DESCR(IRQD_ACTIVATED),
108	BIT_MASK_DESCR(IRQD_IRQ_STARTED),
109	BIT_MASK_DESCR(IRQD_IRQ_DISABLED),
110	BIT_MASK_DESCR(IRQD_IRQ_MASKED),
111	BIT_MASK_DESCR(IRQD_IRQ_INPROGRESS),
112
113	BIT_MASK_DESCR(IRQD_PER_CPU),
114	BIT_MASK_DESCR(IRQD_NO_BALANCING),
115
116	BIT_MASK_DESCR(IRQD_SINGLE_TARGET),
117	BIT_MASK_DESCR(IRQD_MOVE_PCNTXT),
118	BIT_MASK_DESCR(IRQD_AFFINITY_SET),
119	BIT_MASK_DESCR(IRQD_SETAFFINITY_PENDING),
120	BIT_MASK_DESCR(IRQD_AFFINITY_MANAGED),
121	BIT_MASK_DESCR(IRQD_AFFINITY_ON_ACTIVATE),
122	BIT_MASK_DESCR(IRQD_MANAGED_SHUTDOWN),
123	BIT_MASK_DESCR(IRQD_CAN_RESERVE),
124	BIT_MASK_DESCR(IRQD_MSI_NOMASK_QUIRK),
125
126	BIT_MASK_DESCR(IRQD_FORWARDED_TO_VCPU),
127
128	BIT_MASK_DESCR(IRQD_WAKEUP_STATE),
129	BIT_MASK_DESCR(IRQD_WAKEUP_ARMED),
130
131	BIT_MASK_DESCR(IRQD_DEFAULT_TRIGGER_SET),
132
133	BIT_MASK_DESCR(IRQD_HANDLE_ENFORCE_IRQCTX),
134
135	BIT_MASK_DESCR(IRQD_IRQ_ENABLED_ON_SUSPEND),
136};
137
138static const struct irq_bit_descr irqdesc_states[] = {
139	BIT_MASK_DESCR(_IRQ_NOPROBE),
140	BIT_MASK_DESCR(_IRQ_NOREQUEST),
141	BIT_MASK_DESCR(_IRQ_NOTHREAD),
142	BIT_MASK_DESCR(_IRQ_NOAUTOEN),
143	BIT_MASK_DESCR(_IRQ_NESTED_THREAD),
144	BIT_MASK_DESCR(_IRQ_PER_CPU_DEVID),
145	BIT_MASK_DESCR(_IRQ_IS_POLLED),
146	BIT_MASK_DESCR(_IRQ_DISABLE_UNLAZY),
147	BIT_MASK_DESCR(_IRQ_HIDDEN),
148};
149
150static const struct irq_bit_descr irqdesc_istates[] = {
151	BIT_MASK_DESCR(IRQS_AUTODETECT),
152	BIT_MASK_DESCR(IRQS_SPURIOUS_DISABLED),
153	BIT_MASK_DESCR(IRQS_POLL_INPROGRESS),
154	BIT_MASK_DESCR(IRQS_ONESHOT),
155	BIT_MASK_DESCR(IRQS_REPLAY),
156	BIT_MASK_DESCR(IRQS_WAITING),
157	BIT_MASK_DESCR(IRQS_PENDING),
158	BIT_MASK_DESCR(IRQS_SUSPENDED),
159	BIT_MASK_DESCR(IRQS_NMI),
160};
161
162
163static int irq_debug_show(struct seq_file *m, void *p)
164{
165	struct irq_desc *desc = m->private;
166	struct irq_data *data;
167
168	raw_spin_lock_irq(&desc->lock);
169	data = irq_desc_get_irq_data(desc);
170	seq_printf(m, "handler:  %ps\n", desc->handle_irq);
171	seq_printf(m, "device:   %s\n", desc->dev_name);
172	seq_printf(m, "status:   0x%08x\n", desc->status_use_accessors);
173	irq_debug_show_bits(m, 0, desc->status_use_accessors, irqdesc_states,
174			    ARRAY_SIZE(irqdesc_states));
175	seq_printf(m, "istate:   0x%08x\n", desc->istate);
176	irq_debug_show_bits(m, 0, desc->istate, irqdesc_istates,
177			    ARRAY_SIZE(irqdesc_istates));
178	seq_printf(m, "ddepth:   %u\n", desc->depth);
179	seq_printf(m, "wdepth:   %u\n", desc->wake_depth);
180	seq_printf(m, "dstate:   0x%08x\n", irqd_get(data));
181	irq_debug_show_bits(m, 0, irqd_get(data), irqdata_states,
182			    ARRAY_SIZE(irqdata_states));
183	seq_printf(m, "node:     %d\n", irq_data_get_node(data));
184	irq_debug_show_masks(m, desc);
185	irq_debug_show_data(m, data, 0);
186	raw_spin_unlock_irq(&desc->lock);
187	return 0;
188}
189
190static int irq_debug_open(struct inode *inode, struct file *file)
191{
192	return single_open(file, irq_debug_show, inode->i_private);
193}
194
195static ssize_t irq_debug_write(struct file *file, const char __user *user_buf,
196			       size_t count, loff_t *ppos)
197{
198	struct irq_desc *desc = file_inode(file)->i_private;
199	char buf[8] = { 0, };
200	size_t size;
201
202	size = min(sizeof(buf) - 1, count);
203	if (copy_from_user(buf, user_buf, size))
204		return -EFAULT;
205
206	if (!strncmp(buf, "trigger", size)) {
207		int err = irq_inject_interrupt(irq_desc_get_irq(desc));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
209		return err ? err : count;
210	}
211
212	return count;
213}
214
215static const struct file_operations dfs_irq_ops = {
216	.open		= irq_debug_open,
217	.write		= irq_debug_write,
218	.read		= seq_read,
219	.llseek		= seq_lseek,
220	.release	= single_release,
221};
222
223void irq_debugfs_copy_devname(int irq, struct device *dev)
224{
225	struct irq_desc *desc = irq_to_desc(irq);
226	const char *name = dev_name(dev);
227
228	if (name)
229		desc->dev_name = kstrdup(name, GFP_KERNEL);
230}
231
232void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc)
233{
234	char name [10];
235
236	if (!irq_dir || !desc || desc->debugfs_file)
237		return;
238
239	sprintf(name, "%d", irq);
240	desc->debugfs_file = debugfs_create_file(name, 0644, irq_dir, desc,
241						 &dfs_irq_ops);
242}
243
244static int __init irq_debugfs_init(void)
245{
246	struct dentry *root_dir;
247	int irq;
248
249	root_dir = debugfs_create_dir("irq", NULL);
 
 
250
251	irq_domain_debugfs_init(root_dir);
252
253	irq_dir = debugfs_create_dir("irqs", root_dir);
254
255	irq_lock_sparse();
256	for_each_active_irq(irq)
257		irq_add_debugfs_entry(irq, irq_to_desc(irq));
258	irq_unlock_sparse();
259
260	return 0;
261}
262__initcall(irq_debugfs_init);
v4.17
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright 2017 Thomas Gleixner <tglx@linutronix.de>
  3
  4#include <linux/irqdomain.h>
  5#include <linux/irq.h>
  6#include <linux/uaccess.h>
  7
  8#include "internals.h"
  9
 10static struct dentry *irq_dir;
 11
 12struct irq_bit_descr {
 13	unsigned int	mask;
 14	char		*name;
 15};
 16#define BIT_MASK_DESCR(m)	{ .mask = m, .name = #m }
 17
 18static void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int state,
 19				const struct irq_bit_descr *sd, int size)
 20{
 21	int i;
 22
 23	for (i = 0; i < size; i++, sd++) {
 24		if (state & sd->mask)
 25			seq_printf(m, "%*s%s\n", ind + 12, "", sd->name);
 26	}
 27}
 28
 29#ifdef CONFIG_SMP
 30static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc)
 31{
 32	struct irq_data *data = irq_desc_get_irq_data(desc);
 33	struct cpumask *msk;
 34
 35	msk = irq_data_get_affinity_mask(data);
 36	seq_printf(m, "affinity: %*pbl\n", cpumask_pr_args(msk));
 37#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
 38	msk = irq_data_get_effective_affinity_mask(data);
 39	seq_printf(m, "effectiv: %*pbl\n", cpumask_pr_args(msk));
 40#endif
 41#ifdef CONFIG_GENERIC_PENDING_IRQ
 42	msk = desc->pending_mask;
 43	seq_printf(m, "pending:  %*pbl\n", cpumask_pr_args(msk));
 44#endif
 45}
 46#else
 47static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc) { }
 48#endif
 49
 50static const struct irq_bit_descr irqchip_flags[] = {
 51	BIT_MASK_DESCR(IRQCHIP_SET_TYPE_MASKED),
 52	BIT_MASK_DESCR(IRQCHIP_EOI_IF_HANDLED),
 53	BIT_MASK_DESCR(IRQCHIP_MASK_ON_SUSPEND),
 54	BIT_MASK_DESCR(IRQCHIP_ONOFFLINE_ENABLED),
 55	BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE),
 56	BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE),
 57	BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
 
 
 
 
 58};
 59
 60static void
 61irq_debug_show_chip(struct seq_file *m, struct irq_data *data, int ind)
 62{
 63	struct irq_chip *chip = data->chip;
 64
 65	if (!chip) {
 66		seq_printf(m, "chip: None\n");
 67		return;
 68	}
 69	seq_printf(m, "%*schip:    %s\n", ind, "", chip->name);
 70	seq_printf(m, "%*sflags:   0x%lx\n", ind + 1, "", chip->flags);
 
 
 
 
 71	irq_debug_show_bits(m, ind, chip->flags, irqchip_flags,
 72			    ARRAY_SIZE(irqchip_flags));
 73}
 74
 75static void
 76irq_debug_show_data(struct seq_file *m, struct irq_data *data, int ind)
 77{
 78	seq_printf(m, "%*sdomain:  %s\n", ind, "",
 79		   data->domain ? data->domain->name : "");
 80	seq_printf(m, "%*shwirq:   0x%lx\n", ind + 1, "", data->hwirq);
 81	irq_debug_show_chip(m, data, ind + 1);
 82	if (data->domain && data->domain->ops && data->domain->ops->debug_show)
 83		data->domain->ops->debug_show(m, NULL, data, ind + 1);
 84#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
 85	if (!data->parent_data)
 86		return;
 87	seq_printf(m, "%*sparent:\n", ind + 1, "");
 88	irq_debug_show_data(m, data->parent_data, ind + 4);
 89#endif
 90}
 91
 92static const struct irq_bit_descr irqdata_states[] = {
 93	BIT_MASK_DESCR(IRQ_TYPE_EDGE_RISING),
 94	BIT_MASK_DESCR(IRQ_TYPE_EDGE_FALLING),
 95	BIT_MASK_DESCR(IRQ_TYPE_LEVEL_HIGH),
 96	BIT_MASK_DESCR(IRQ_TYPE_LEVEL_LOW),
 97	BIT_MASK_DESCR(IRQD_LEVEL),
 98
 99	BIT_MASK_DESCR(IRQD_ACTIVATED),
100	BIT_MASK_DESCR(IRQD_IRQ_STARTED),
101	BIT_MASK_DESCR(IRQD_IRQ_DISABLED),
102	BIT_MASK_DESCR(IRQD_IRQ_MASKED),
103	BIT_MASK_DESCR(IRQD_IRQ_INPROGRESS),
104
105	BIT_MASK_DESCR(IRQD_PER_CPU),
106	BIT_MASK_DESCR(IRQD_NO_BALANCING),
107
108	BIT_MASK_DESCR(IRQD_SINGLE_TARGET),
109	BIT_MASK_DESCR(IRQD_MOVE_PCNTXT),
110	BIT_MASK_DESCR(IRQD_AFFINITY_SET),
111	BIT_MASK_DESCR(IRQD_SETAFFINITY_PENDING),
112	BIT_MASK_DESCR(IRQD_AFFINITY_MANAGED),
 
113	BIT_MASK_DESCR(IRQD_MANAGED_SHUTDOWN),
114	BIT_MASK_DESCR(IRQD_CAN_RESERVE),
 
115
116	BIT_MASK_DESCR(IRQD_FORWARDED_TO_VCPU),
117
118	BIT_MASK_DESCR(IRQD_WAKEUP_STATE),
119	BIT_MASK_DESCR(IRQD_WAKEUP_ARMED),
 
 
 
 
 
 
120};
121
122static const struct irq_bit_descr irqdesc_states[] = {
123	BIT_MASK_DESCR(_IRQ_NOPROBE),
124	BIT_MASK_DESCR(_IRQ_NOREQUEST),
125	BIT_MASK_DESCR(_IRQ_NOTHREAD),
126	BIT_MASK_DESCR(_IRQ_NOAUTOEN),
127	BIT_MASK_DESCR(_IRQ_NESTED_THREAD),
128	BIT_MASK_DESCR(_IRQ_PER_CPU_DEVID),
129	BIT_MASK_DESCR(_IRQ_IS_POLLED),
130	BIT_MASK_DESCR(_IRQ_DISABLE_UNLAZY),
 
131};
132
133static const struct irq_bit_descr irqdesc_istates[] = {
134	BIT_MASK_DESCR(IRQS_AUTODETECT),
135	BIT_MASK_DESCR(IRQS_SPURIOUS_DISABLED),
136	BIT_MASK_DESCR(IRQS_POLL_INPROGRESS),
137	BIT_MASK_DESCR(IRQS_ONESHOT),
138	BIT_MASK_DESCR(IRQS_REPLAY),
139	BIT_MASK_DESCR(IRQS_WAITING),
140	BIT_MASK_DESCR(IRQS_PENDING),
141	BIT_MASK_DESCR(IRQS_SUSPENDED),
 
142};
143
144
145static int irq_debug_show(struct seq_file *m, void *p)
146{
147	struct irq_desc *desc = m->private;
148	struct irq_data *data;
149
150	raw_spin_lock_irq(&desc->lock);
151	data = irq_desc_get_irq_data(desc);
152	seq_printf(m, "handler:  %pf\n", desc->handle_irq);
153	seq_printf(m, "device:   %s\n", desc->dev_name);
154	seq_printf(m, "status:   0x%08x\n", desc->status_use_accessors);
155	irq_debug_show_bits(m, 0, desc->status_use_accessors, irqdesc_states,
156			    ARRAY_SIZE(irqdesc_states));
157	seq_printf(m, "istate:   0x%08x\n", desc->istate);
158	irq_debug_show_bits(m, 0, desc->istate, irqdesc_istates,
159			    ARRAY_SIZE(irqdesc_istates));
160	seq_printf(m, "ddepth:   %u\n", desc->depth);
161	seq_printf(m, "wdepth:   %u\n", desc->wake_depth);
162	seq_printf(m, "dstate:   0x%08x\n", irqd_get(data));
163	irq_debug_show_bits(m, 0, irqd_get(data), irqdata_states,
164			    ARRAY_SIZE(irqdata_states));
165	seq_printf(m, "node:     %d\n", irq_data_get_node(data));
166	irq_debug_show_masks(m, desc);
167	irq_debug_show_data(m, data, 0);
168	raw_spin_unlock_irq(&desc->lock);
169	return 0;
170}
171
172static int irq_debug_open(struct inode *inode, struct file *file)
173{
174	return single_open(file, irq_debug_show, inode->i_private);
175}
176
177static ssize_t irq_debug_write(struct file *file, const char __user *user_buf,
178			       size_t count, loff_t *ppos)
179{
180	struct irq_desc *desc = file_inode(file)->i_private;
181	char buf[8] = { 0, };
182	size_t size;
183
184	size = min(sizeof(buf) - 1, count);
185	if (copy_from_user(buf, user_buf, size))
186		return -EFAULT;
187
188	if (!strncmp(buf, "trigger", size)) {
189		unsigned long flags;
190		int err;
191
192		/* Try the HW interface first */
193		err = irq_set_irqchip_state(irq_desc_get_irq(desc),
194					    IRQCHIP_STATE_PENDING, true);
195		if (!err)
196			return count;
197
198		/*
199		 * Otherwise, try to inject via the resend interface,
200		 * which may or may not succeed.
201		 */
202		chip_bus_lock(desc);
203		raw_spin_lock_irqsave(&desc->lock, flags);
204
205		if (irq_settings_is_level(desc)) {
206			/* Can't do level, sorry */
207			err = -EINVAL;
208		} else {
209			desc->istate |= IRQS_PENDING;
210			check_irq_resend(desc);
211			err = 0;
212		}
213
214		raw_spin_unlock_irqrestore(&desc->lock, flags);
215		chip_bus_sync_unlock(desc);
216
217		return err ? err : count;
218	}
219
220	return count;
221}
222
223static const struct file_operations dfs_irq_ops = {
224	.open		= irq_debug_open,
225	.write		= irq_debug_write,
226	.read		= seq_read,
227	.llseek		= seq_lseek,
228	.release	= single_release,
229};
230
231void irq_debugfs_copy_devname(int irq, struct device *dev)
232{
233	struct irq_desc *desc = irq_to_desc(irq);
234	const char *name = dev_name(dev);
235
236	if (name)
237		desc->dev_name = kstrdup(name, GFP_KERNEL);
238}
239
240void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc)
241{
242	char name [10];
243
244	if (!irq_dir || !desc || desc->debugfs_file)
245		return;
246
247	sprintf(name, "%d", irq);
248	desc->debugfs_file = debugfs_create_file(name, 0644, irq_dir, desc,
249						 &dfs_irq_ops);
250}
251
252static int __init irq_debugfs_init(void)
253{
254	struct dentry *root_dir;
255	int irq;
256
257	root_dir = debugfs_create_dir("irq", NULL);
258	if (!root_dir)
259		return -ENOMEM;
260
261	irq_domain_debugfs_init(root_dir);
262
263	irq_dir = debugfs_create_dir("irqs", root_dir);
264
265	irq_lock_sparse();
266	for_each_active_irq(irq)
267		irq_add_debugfs_entry(irq, irq_to_desc(irq));
268	irq_unlock_sparse();
269
270	return 0;
271}
272__initcall(irq_debugfs_init);