xref: /linux/kernel/irq/proc.c (revision c0c9209ddd96bc4f1d70a8b9958710671e076080)
1 /*
2  * linux/kernel/irq/proc.c
3  *
4  * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
5  *
6  * This file contains the /proc/irq/ handling code.
7  */
8 
9 #include <linux/irq.h>
10 #include <linux/proc_fs.h>
11 #include <linux/seq_file.h>
12 #include <linux/interrupt.h>
13 
14 #include "internals.h"
15 
16 static struct proc_dir_entry *root_irq_dir;
17 
18 #ifdef CONFIG_SMP
19 
20 static int irq_affinity_proc_show(struct seq_file *m, void *v)
21 {
22 	struct irq_desc *desc = irq_desc + (long)m->private;
23 	cpumask_t *mask = &desc->affinity;
24 
25 #ifdef CONFIG_GENERIC_PENDING_IRQ
26 	if (desc->status & IRQ_MOVE_PENDING)
27 		mask = &desc->pending_mask;
28 #endif
29 	seq_cpumask(m, mask);
30 	seq_putc(m, '\n');
31 	return 0;
32 }
33 
34 #ifndef is_affinity_mask_valid
35 #define is_affinity_mask_valid(val) 1
36 #endif
37 
38 int no_irq_affinity;
39 static ssize_t irq_affinity_proc_write(struct file *file,
40 		const char __user *buffer, size_t count, loff_t *pos)
41 {
42 	unsigned int irq = (int)(long)PDE(file->f_path.dentry->d_inode)->data;
43 	cpumask_t new_value;
44 	int err;
45 
46 	if (!irq_desc[irq].chip->set_affinity || no_irq_affinity ||
47 	    irq_balancing_disabled(irq))
48 		return -EIO;
49 
50 	err = cpumask_parse_user(buffer, count, new_value);
51 	if (err)
52 		return err;
53 
54 	if (!is_affinity_mask_valid(new_value))
55 		return -EINVAL;
56 
57 	/*
58 	 * Do not allow disabling IRQs completely - it's a too easy
59 	 * way to make the system unusable accidentally :-) At least
60 	 * one online CPU still has to be targeted.
61 	 */
62 	if (!cpus_intersects(new_value, cpu_online_map))
63 		/* Special case for empty set - allow the architecture
64 		   code to set default SMP affinity. */
65 		return irq_select_affinity(irq) ? -EINVAL : count;
66 
67 	irq_set_affinity(irq, new_value);
68 
69 	return count;
70 }
71 
72 static int irq_affinity_proc_open(struct inode *inode, struct file *file)
73 {
74 	return single_open(file, irq_affinity_proc_show, PDE(inode)->data);
75 }
76 
77 static const struct file_operations irq_affinity_proc_fops = {
78 	.open		= irq_affinity_proc_open,
79 	.read		= seq_read,
80 	.llseek		= seq_lseek,
81 	.release	= single_release,
82 	.write		= irq_affinity_proc_write,
83 };
84 
85 static int default_affinity_show(struct seq_file *m, void *v)
86 {
87 	seq_cpumask(m, &irq_default_affinity);
88 	seq_putc(m, '\n');
89 	return 0;
90 }
91 
92 static ssize_t default_affinity_write(struct file *file,
93 		const char __user *buffer, size_t count, loff_t *ppos)
94 {
95 	cpumask_t new_value;
96 	int err;
97 
98 	err = cpumask_parse_user(buffer, count, new_value);
99 	if (err)
100 		return err;
101 
102 	if (!is_affinity_mask_valid(new_value))
103 		return -EINVAL;
104 
105 	/*
106 	 * Do not allow disabling IRQs completely - it's a too easy
107 	 * way to make the system unusable accidentally :-) At least
108 	 * one online CPU still has to be targeted.
109 	 */
110 	if (!cpus_intersects(new_value, cpu_online_map))
111 		return -EINVAL;
112 
113 	irq_default_affinity = new_value;
114 
115 	return count;
116 }
117 
118 static int default_affinity_open(struct inode *inode, struct file *file)
119 {
120 	return single_open(file, default_affinity_show, NULL);
121 }
122 
123 static const struct file_operations default_affinity_proc_fops = {
124 	.open		= default_affinity_open,
125 	.read		= seq_read,
126 	.llseek		= seq_lseek,
127 	.release	= single_release,
128 	.write		= default_affinity_write,
129 };
130 #endif
131 
132 static int irq_spurious_read(char *page, char **start, off_t off,
133 				  int count, int *eof, void *data)
134 {
135 	struct irq_desc *d = &irq_desc[(long) data];
136 	return sprintf(page, "count %u\n"
137 			     "unhandled %u\n"
138 			     "last_unhandled %u ms\n",
139 			d->irq_count,
140 			d->irqs_unhandled,
141 			jiffies_to_msecs(d->last_unhandled));
142 }
143 
144 #define MAX_NAMELEN 128
145 
146 static int name_unique(unsigned int irq, struct irqaction *new_action)
147 {
148 	struct irq_desc *desc = irq_desc + irq;
149 	struct irqaction *action;
150 	unsigned long flags;
151 	int ret = 1;
152 
153 	spin_lock_irqsave(&desc->lock, flags);
154 	for (action = desc->action ; action; action = action->next) {
155 		if ((action != new_action) && action->name &&
156 				!strcmp(new_action->name, action->name)) {
157 			ret = 0;
158 			break;
159 		}
160 	}
161 	spin_unlock_irqrestore(&desc->lock, flags);
162 	return ret;
163 }
164 
165 void register_handler_proc(unsigned int irq, struct irqaction *action)
166 {
167 	char name [MAX_NAMELEN];
168 
169 	if (!irq_desc[irq].dir || action->dir || !action->name ||
170 					!name_unique(irq, action))
171 		return;
172 
173 	memset(name, 0, MAX_NAMELEN);
174 	snprintf(name, MAX_NAMELEN, "%s", action->name);
175 
176 	/* create /proc/irq/1234/handler/ */
177 	action->dir = proc_mkdir(name, irq_desc[irq].dir);
178 }
179 
180 #undef MAX_NAMELEN
181 
182 #define MAX_NAMELEN 10
183 
184 void register_irq_proc(unsigned int irq)
185 {
186 	char name [MAX_NAMELEN];
187 	struct proc_dir_entry *entry;
188 
189 	if (!root_irq_dir ||
190 		(irq_desc[irq].chip == &no_irq_chip) ||
191 			irq_desc[irq].dir)
192 		return;
193 
194 	memset(name, 0, MAX_NAMELEN);
195 	sprintf(name, "%d", irq);
196 
197 	/* create /proc/irq/1234 */
198 	irq_desc[irq].dir = proc_mkdir(name, root_irq_dir);
199 
200 #ifdef CONFIG_SMP
201 	/* create /proc/irq/<irq>/smp_affinity */
202 	proc_create_data("smp_affinity", 0600, irq_desc[irq].dir,
203 			 &irq_affinity_proc_fops, (void *)(long)irq);
204 #endif
205 
206 	entry = create_proc_entry("spurious", 0444, irq_desc[irq].dir);
207 	if (entry) {
208 		entry->data = (void *)(long)irq;
209 		entry->read_proc = irq_spurious_read;
210 	}
211 }
212 
213 #undef MAX_NAMELEN
214 
215 void unregister_handler_proc(unsigned int irq, struct irqaction *action)
216 {
217 	if (action->dir)
218 		remove_proc_entry(action->dir->name, irq_desc[irq].dir);
219 }
220 
221 void register_default_affinity_proc(void)
222 {
223 #ifdef CONFIG_SMP
224 	proc_create("irq/default_smp_affinity", 0600, NULL,
225 		    &default_affinity_proc_fops);
226 #endif
227 }
228 
229 void init_irq_proc(void)
230 {
231 	int i;
232 
233 	/* create /proc/irq */
234 	root_irq_dir = proc_mkdir("irq", NULL);
235 	if (!root_irq_dir)
236 		return;
237 
238 	register_default_affinity_proc();
239 
240 	/*
241 	 * Create entries for all existing IRQs.
242 	 */
243 	for (i = 0; i < NR_IRQS; i++)
244 		register_irq_proc(i);
245 }
246 
247