]> git.karo-electronics.de Git - karo-tx-linux.git/blob - kernel/irq/proc.c
afe4e68031483bc9e7fcc91ccf9f486273ef1965
[karo-tx-linux.git] / kernel / irq / proc.c
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/gfp.h>
11 #include <linux/proc_fs.h>
12 #include <linux/seq_file.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel_stat.h>
15
16 #include "internals.h"
17
18 static struct proc_dir_entry *root_irq_dir;
19
20 #ifdef CONFIG_SMP
21
22 static int irq_affinity_proc_show(struct seq_file *m, void *v)
23 {
24         struct irq_desc *desc = irq_to_desc((long)m->private);
25         const struct cpumask *mask = desc->irq_data.affinity;
26
27 #ifdef CONFIG_GENERIC_PENDING_IRQ
28         if (irqd_is_setaffinity_pending(&desc->irq_data))
29                 mask = desc->pending_mask;
30 #endif
31         seq_cpumask(m, mask);
32         seq_putc(m, '\n');
33         return 0;
34 }
35
36 static int irq_affinity_hint_proc_show(struct seq_file *m, void *v)
37 {
38         struct irq_desc *desc = irq_to_desc((long)m->private);
39         unsigned long flags;
40         cpumask_var_t mask;
41
42         if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
43                 return -ENOMEM;
44
45         raw_spin_lock_irqsave(&desc->lock, flags);
46         if (desc->affinity_hint)
47                 cpumask_copy(mask, desc->affinity_hint);
48         raw_spin_unlock_irqrestore(&desc->lock, flags);
49
50         seq_cpumask(m, mask);
51         seq_putc(m, '\n');
52         free_cpumask_var(mask);
53
54         return 0;
55 }
56
57 #ifndef is_affinity_mask_valid
58 #define is_affinity_mask_valid(val) 1
59 #endif
60
61 int no_irq_affinity;
62 static ssize_t irq_affinity_proc_write(struct file *file,
63                 const char __user *buffer, size_t count, loff_t *pos)
64 {
65         unsigned int irq = (int)(long)PDE(file->f_path.dentry->d_inode)->data;
66         cpumask_var_t new_value;
67         int err;
68
69         if (!irq_to_desc(irq)->irq_data.chip->irq_set_affinity || no_irq_affinity ||
70             irq_balancing_disabled(irq))
71                 return -EIO;
72
73         if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
74                 return -ENOMEM;
75
76         err = cpumask_parse_user(buffer, count, new_value);
77         if (err)
78                 goto free_cpumask;
79
80         if (!is_affinity_mask_valid(new_value)) {
81                 err = -EINVAL;
82                 goto free_cpumask;
83         }
84
85         /*
86          * Do not allow disabling IRQs completely - it's a too easy
87          * way to make the system unusable accidentally :-) At least
88          * one online CPU still has to be targeted.
89          */
90         if (!cpumask_intersects(new_value, cpu_online_mask)) {
91                 /* Special case for empty set - allow the architecture
92                    code to set default SMP affinity. */
93                 err = irq_select_affinity_usr(irq, new_value) ? -EINVAL : count;
94         } else {
95                 irq_set_affinity(irq, new_value);
96                 err = count;
97         }
98
99 free_cpumask:
100         free_cpumask_var(new_value);
101         return err;
102 }
103
104 static int irq_affinity_proc_open(struct inode *inode, struct file *file)
105 {
106         return single_open(file, irq_affinity_proc_show, PDE(inode)->data);
107 }
108
109 static int irq_affinity_hint_proc_open(struct inode *inode, struct file *file)
110 {
111         return single_open(file, irq_affinity_hint_proc_show, PDE(inode)->data);
112 }
113
114 static const struct file_operations irq_affinity_proc_fops = {
115         .open           = irq_affinity_proc_open,
116         .read           = seq_read,
117         .llseek         = seq_lseek,
118         .release        = single_release,
119         .write          = irq_affinity_proc_write,
120 };
121
122 static const struct file_operations irq_affinity_hint_proc_fops = {
123         .open           = irq_affinity_hint_proc_open,
124         .read           = seq_read,
125         .llseek         = seq_lseek,
126         .release        = single_release,
127 };
128
129 static int default_affinity_show(struct seq_file *m, void *v)
130 {
131         seq_cpumask(m, irq_default_affinity);
132         seq_putc(m, '\n');
133         return 0;
134 }
135
136 static ssize_t default_affinity_write(struct file *file,
137                 const char __user *buffer, size_t count, loff_t *ppos)
138 {
139         cpumask_var_t new_value;
140         int err;
141
142         if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
143                 return -ENOMEM;
144
145         err = cpumask_parse_user(buffer, count, new_value);
146         if (err)
147                 goto out;
148
149         if (!is_affinity_mask_valid(new_value)) {
150                 err = -EINVAL;
151                 goto out;
152         }
153
154         /*
155          * Do not allow disabling IRQs completely - it's a too easy
156          * way to make the system unusable accidentally :-) At least
157          * one online CPU still has to be targeted.
158          */
159         if (!cpumask_intersects(new_value, cpu_online_mask)) {
160                 err = -EINVAL;
161                 goto out;
162         }
163
164         cpumask_copy(irq_default_affinity, new_value);
165         err = count;
166
167 out:
168         free_cpumask_var(new_value);
169         return err;
170 }
171
172 static int default_affinity_open(struct inode *inode, struct file *file)
173 {
174         return single_open(file, default_affinity_show, PDE(inode)->data);
175 }
176
177 static const struct file_operations default_affinity_proc_fops = {
178         .open           = default_affinity_open,
179         .read           = seq_read,
180         .llseek         = seq_lseek,
181         .release        = single_release,
182         .write          = default_affinity_write,
183 };
184
185 static int irq_node_proc_show(struct seq_file *m, void *v)
186 {
187         struct irq_desc *desc = irq_to_desc((long) m->private);
188
189         seq_printf(m, "%d\n", desc->irq_data.node);
190         return 0;
191 }
192
193 static int irq_node_proc_open(struct inode *inode, struct file *file)
194 {
195         return single_open(file, irq_node_proc_show, PDE(inode)->data);
196 }
197
198 static const struct file_operations irq_node_proc_fops = {
199         .open           = irq_node_proc_open,
200         .read           = seq_read,
201         .llseek         = seq_lseek,
202         .release        = single_release,
203 };
204 #endif
205
206 static int irq_spurious_proc_show(struct seq_file *m, void *v)
207 {
208         struct irq_desc *desc = irq_to_desc((long) m->private);
209
210         seq_printf(m, "count %u\n" "unhandled %u\n" "last_unhandled %u ms\n",
211                    desc->irq_count, desc->irqs_unhandled,
212                    jiffies_to_msecs(desc->last_unhandled));
213         return 0;
214 }
215
216 static int irq_spurious_proc_open(struct inode *inode, struct file *file)
217 {
218         return single_open(file, irq_spurious_proc_show, PDE(inode)->data);
219 }
220
221 static const struct file_operations irq_spurious_proc_fops = {
222         .open           = irq_spurious_proc_open,
223         .read           = seq_read,
224         .llseek         = seq_lseek,
225         .release        = single_release,
226 };
227
228 #define MAX_NAMELEN 128
229
230 static int name_unique(unsigned int irq, struct irqaction *new_action)
231 {
232         struct irq_desc *desc = irq_to_desc(irq);
233         struct irqaction *action;
234         unsigned long flags;
235         int ret = 1;
236
237         raw_spin_lock_irqsave(&desc->lock, flags);
238         for (action = desc->action ; action; action = action->next) {
239                 if ((action != new_action) && action->name &&
240                                 !strcmp(new_action->name, action->name)) {
241                         ret = 0;
242                         break;
243                 }
244         }
245         raw_spin_unlock_irqrestore(&desc->lock, flags);
246         return ret;
247 }
248
249 void register_handler_proc(unsigned int irq, struct irqaction *action)
250 {
251         char name [MAX_NAMELEN];
252         struct irq_desc *desc = irq_to_desc(irq);
253
254         if (!desc->dir || action->dir || !action->name ||
255                                         !name_unique(irq, action))
256                 return;
257
258         memset(name, 0, MAX_NAMELEN);
259         snprintf(name, MAX_NAMELEN, "%s", action->name);
260
261         /* create /proc/irq/1234/handler/ */
262         action->dir = proc_mkdir(name, desc->dir);
263 }
264
265 #undef MAX_NAMELEN
266
267 #define MAX_NAMELEN 10
268
269 void register_irq_proc(unsigned int irq, struct irq_desc *desc)
270 {
271         char name [MAX_NAMELEN];
272
273         if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir)
274                 return;
275
276         memset(name, 0, MAX_NAMELEN);
277         sprintf(name, "%d", irq);
278
279         /* create /proc/irq/1234 */
280         desc->dir = proc_mkdir(name, root_irq_dir);
281         if (!desc->dir)
282                 return;
283
284 #ifdef CONFIG_SMP
285         /* create /proc/irq/<irq>/smp_affinity */
286         proc_create_data("smp_affinity", 0600, desc->dir,
287                          &irq_affinity_proc_fops, (void *)(long)irq);
288
289         /* create /proc/irq/<irq>/affinity_hint */
290         proc_create_data("affinity_hint", 0400, desc->dir,
291                          &irq_affinity_hint_proc_fops, (void *)(long)irq);
292
293         proc_create_data("node", 0444, desc->dir,
294                          &irq_node_proc_fops, (void *)(long)irq);
295 #endif
296
297         proc_create_data("spurious", 0444, desc->dir,
298                          &irq_spurious_proc_fops, (void *)(long)irq);
299 }
300
301 void unregister_irq_proc(unsigned int irq, struct irq_desc *desc)
302 {
303         char name [MAX_NAMELEN];
304
305         if (!root_irq_dir || !desc->dir)
306                 return;
307 #ifdef CONFIG_SMP
308         remove_proc_entry("smp_affinity", desc->dir);
309         remove_proc_entry("affinity_hint", desc->dir);
310         remove_proc_entry("node", desc->dir);
311 #endif
312         remove_proc_entry("spurious", desc->dir);
313
314         memset(name, 0, MAX_NAMELEN);
315         sprintf(name, "%u", irq);
316         remove_proc_entry(name, root_irq_dir);
317 }
318
319 #undef MAX_NAMELEN
320
321 void unregister_handler_proc(unsigned int irq, struct irqaction *action)
322 {
323         if (action->dir) {
324                 struct irq_desc *desc = irq_to_desc(irq);
325
326                 remove_proc_entry(action->dir->name, desc->dir);
327         }
328 }
329
330 static void register_default_affinity_proc(void)
331 {
332 #ifdef CONFIG_SMP
333         proc_create("irq/default_smp_affinity", 0600, NULL,
334                     &default_affinity_proc_fops);
335 #endif
336 }
337
338 void init_irq_proc(void)
339 {
340         unsigned int irq;
341         struct irq_desc *desc;
342
343         /* create /proc/irq */
344         root_irq_dir = proc_mkdir("irq", NULL);
345         if (!root_irq_dir)
346                 return;
347
348         register_default_affinity_proc();
349
350         /*
351          * Create entries for all existing IRQs.
352          */
353         for_each_irq_desc(irq, desc) {
354                 if (!desc)
355                         continue;
356
357                 register_irq_proc(irq, desc);
358         }
359 }
360
361 #ifdef CONFIG_GENERIC_IRQ_SHOW
362
363 int __weak arch_show_interrupts(struct seq_file *p, int prec)
364 {
365         return 0;
366 }
367
368 int show_interrupts(struct seq_file *p, void *v)
369 {
370         static int prec;
371
372         unsigned long flags, any_count = 0;
373         int i = *(loff_t *) v, j;
374         struct irqaction *action;
375         struct irq_desc *desc;
376
377         if (i > nr_irqs)
378                 return 0;
379
380         if (i == nr_irqs)
381                 return arch_show_interrupts(p, prec);
382
383         /* print header and calculate the width of the first column */
384         if (i == 0) {
385                 for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
386                         j *= 10;
387
388                 seq_printf(p, "%*s", prec + 8, "");
389                 for_each_online_cpu(j)
390                         seq_printf(p, "CPU%-8d", j);
391                 seq_putc(p, '\n');
392         }
393
394         desc = irq_to_desc(i);
395         if (!desc)
396                 return 0;
397
398         raw_spin_lock_irqsave(&desc->lock, flags);
399         for_each_online_cpu(j)
400                 any_count |= kstat_irqs_cpu(i, j);
401         action = desc->action;
402         if (!action && !any_count)
403                 goto out;
404
405         seq_printf(p, "%*d: ", prec, i);
406         for_each_online_cpu(j)
407                 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
408         seq_printf(p, " %8s", desc->irq_data.chip->name);
409         seq_printf(p, "-%-8s", desc->name);
410
411         if (action) {
412                 seq_printf(p, "  %s", action->name);
413                 while ((action = action->next) != NULL)
414                         seq_printf(p, ", %s", action->name);
415         }
416
417         seq_putc(p, '\n');
418 out:
419         raw_spin_unlock_irqrestore(&desc->lock, flags);
420         return 0;
421 }
422 #endif