aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/proc.c')
-rw-r--r--kernel/irq/proc.c169
1 files changed, 157 insertions, 12 deletions
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 09a2ee540bd2..4bd4faa6323a 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -11,6 +11,7 @@
11#include <linux/proc_fs.h> 11#include <linux/proc_fs.h>
12#include <linux/seq_file.h> 12#include <linux/seq_file.h>
13#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/kernel_stat.h>
14 15
15#include "internals.h" 16#include "internals.h"
16 17
@@ -18,16 +19,19 @@ static struct proc_dir_entry *root_irq_dir;
18 19
19#ifdef CONFIG_SMP 20#ifdef CONFIG_SMP
20 21
21static int irq_affinity_proc_show(struct seq_file *m, void *v) 22static int show_irq_affinity(int type, struct seq_file *m, void *v)
22{ 23{
23 struct irq_desc *desc = irq_to_desc((long)m->private); 24 struct irq_desc *desc = irq_to_desc((long)m->private);
24 const struct cpumask *mask = desc->affinity; 25 const struct cpumask *mask = desc->irq_data.affinity;
25 26
26#ifdef CONFIG_GENERIC_PENDING_IRQ 27#ifdef CONFIG_GENERIC_PENDING_IRQ
27 if (desc->status & IRQ_MOVE_PENDING) 28 if (irqd_is_setaffinity_pending(&desc->irq_data))
28 mask = desc->pending_mask; 29 mask = desc->pending_mask;
29#endif 30#endif
30 seq_cpumask(m, mask); 31 if (type)
32 seq_cpumask_list(m, mask);
33 else
34 seq_cpumask(m, mask);
31 seq_putc(m, '\n'); 35 seq_putc(m, '\n');
32 return 0; 36 return 0;
33} 37}
@@ -58,21 +62,34 @@ static int irq_affinity_hint_proc_show(struct seq_file *m, void *v)
58#endif 62#endif
59 63
60int no_irq_affinity; 64int no_irq_affinity;
61static ssize_t irq_affinity_proc_write(struct file *file, 65static int irq_affinity_proc_show(struct seq_file *m, void *v)
66{
67 return show_irq_affinity(0, m, v);
68}
69
70static int irq_affinity_list_proc_show(struct seq_file *m, void *v)
71{
72 return show_irq_affinity(1, m, v);
73}
74
75
76static ssize_t write_irq_affinity(int type, struct file *file,
62 const char __user *buffer, size_t count, loff_t *pos) 77 const char __user *buffer, size_t count, loff_t *pos)
63{ 78{
64 unsigned int irq = (int)(long)PDE(file->f_path.dentry->d_inode)->data; 79 unsigned int irq = (int)(long)PDE(file->f_path.dentry->d_inode)->data;
65 cpumask_var_t new_value; 80 cpumask_var_t new_value;
66 int err; 81 int err;
67 82
68 if (!irq_to_desc(irq)->chip->set_affinity || no_irq_affinity || 83 if (!irq_can_set_affinity(irq) || no_irq_affinity)
69 irq_balancing_disabled(irq))
70 return -EIO; 84 return -EIO;
71 85
72 if (!alloc_cpumask_var(&new_value, GFP_KERNEL)) 86 if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
73 return -ENOMEM; 87 return -ENOMEM;
74 88
75 err = cpumask_parse_user(buffer, count, new_value); 89 if (type)
90 err = cpumask_parselist_user(buffer, count, new_value);
91 else
92 err = cpumask_parse_user(buffer, count, new_value);
76 if (err) 93 if (err)
77 goto free_cpumask; 94 goto free_cpumask;
78 95
@@ -89,7 +106,7 @@ static ssize_t irq_affinity_proc_write(struct file *file,
89 if (!cpumask_intersects(new_value, cpu_online_mask)) { 106 if (!cpumask_intersects(new_value, cpu_online_mask)) {
90 /* Special case for empty set - allow the architecture 107 /* Special case for empty set - allow the architecture
91 code to set default SMP affinity. */ 108 code to set default SMP affinity. */
92 err = irq_select_affinity_usr(irq) ? -EINVAL : count; 109 err = irq_select_affinity_usr(irq, new_value) ? -EINVAL : count;
93 } else { 110 } else {
94 irq_set_affinity(irq, new_value); 111 irq_set_affinity(irq, new_value);
95 err = count; 112 err = count;
@@ -100,11 +117,28 @@ free_cpumask:
100 return err; 117 return err;
101} 118}
102 119
120static ssize_t irq_affinity_proc_write(struct file *file,
121 const char __user *buffer, size_t count, loff_t *pos)
122{
123 return write_irq_affinity(0, file, buffer, count, pos);
124}
125
126static ssize_t irq_affinity_list_proc_write(struct file *file,
127 const char __user *buffer, size_t count, loff_t *pos)
128{
129 return write_irq_affinity(1, file, buffer, count, pos);
130}
131
103static int irq_affinity_proc_open(struct inode *inode, struct file *file) 132static int irq_affinity_proc_open(struct inode *inode, struct file *file)
104{ 133{
105 return single_open(file, irq_affinity_proc_show, PDE(inode)->data); 134 return single_open(file, irq_affinity_proc_show, PDE(inode)->data);
106} 135}
107 136
137static int irq_affinity_list_proc_open(struct inode *inode, struct file *file)
138{
139 return single_open(file, irq_affinity_list_proc_show, PDE(inode)->data);
140}
141
108static int irq_affinity_hint_proc_open(struct inode *inode, struct file *file) 142static int irq_affinity_hint_proc_open(struct inode *inode, struct file *file)
109{ 143{
110 return single_open(file, irq_affinity_hint_proc_show, PDE(inode)->data); 144 return single_open(file, irq_affinity_hint_proc_show, PDE(inode)->data);
@@ -125,6 +159,14 @@ static const struct file_operations irq_affinity_hint_proc_fops = {
125 .release = single_release, 159 .release = single_release,
126}; 160};
127 161
162static const struct file_operations irq_affinity_list_proc_fops = {
163 .open = irq_affinity_list_proc_open,
164 .read = seq_read,
165 .llseek = seq_lseek,
166 .release = single_release,
167 .write = irq_affinity_list_proc_write,
168};
169
128static int default_affinity_show(struct seq_file *m, void *v) 170static int default_affinity_show(struct seq_file *m, void *v)
129{ 171{
130 seq_cpumask(m, irq_default_affinity); 172 seq_cpumask(m, irq_default_affinity);
@@ -185,7 +227,7 @@ static int irq_node_proc_show(struct seq_file *m, void *v)
185{ 227{
186 struct irq_desc *desc = irq_to_desc((long) m->private); 228 struct irq_desc *desc = irq_to_desc((long) m->private);
187 229
188 seq_printf(m, "%d\n", desc->node); 230 seq_printf(m, "%d\n", desc->irq_data.node);
189 return 0; 231 return 0;
190} 232}
191 233
@@ -214,7 +256,7 @@ static int irq_spurious_proc_show(struct seq_file *m, void *v)
214 256
215static int irq_spurious_proc_open(struct inode *inode, struct file *file) 257static int irq_spurious_proc_open(struct inode *inode, struct file *file)
216{ 258{
217 return single_open(file, irq_spurious_proc_show, NULL); 259 return single_open(file, irq_spurious_proc_show, PDE(inode)->data);
218} 260}
219 261
220static const struct file_operations irq_spurious_proc_fops = { 262static const struct file_operations irq_spurious_proc_fops = {
@@ -269,7 +311,7 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
269{ 311{
270 char name [MAX_NAMELEN]; 312 char name [MAX_NAMELEN];
271 313
272 if (!root_irq_dir || (desc->chip == &no_irq_chip) || desc->dir) 314 if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir)
273 return; 315 return;
274 316
275 memset(name, 0, MAX_NAMELEN); 317 memset(name, 0, MAX_NAMELEN);
@@ -289,6 +331,10 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
289 proc_create_data("affinity_hint", 0400, desc->dir, 331 proc_create_data("affinity_hint", 0400, desc->dir,
290 &irq_affinity_hint_proc_fops, (void *)(long)irq); 332 &irq_affinity_hint_proc_fops, (void *)(long)irq);
291 333
334 /* create /proc/irq/<irq>/smp_affinity_list */
335 proc_create_data("smp_affinity_list", 0600, desc->dir,
336 &irq_affinity_list_proc_fops, (void *)(long)irq);
337
292 proc_create_data("node", 0444, desc->dir, 338 proc_create_data("node", 0444, desc->dir,
293 &irq_node_proc_fops, (void *)(long)irq); 339 &irq_node_proc_fops, (void *)(long)irq);
294#endif 340#endif
@@ -297,6 +343,25 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
297 &irq_spurious_proc_fops, (void *)(long)irq); 343 &irq_spurious_proc_fops, (void *)(long)irq);
298} 344}
299 345
346void unregister_irq_proc(unsigned int irq, struct irq_desc *desc)
347{
348 char name [MAX_NAMELEN];
349
350 if (!root_irq_dir || !desc->dir)
351 return;
352#ifdef CONFIG_SMP
353 remove_proc_entry("smp_affinity", desc->dir);
354 remove_proc_entry("affinity_hint", desc->dir);
355 remove_proc_entry("smp_affinity_list", desc->dir);
356 remove_proc_entry("node", desc->dir);
357#endif
358 remove_proc_entry("spurious", desc->dir);
359
360 memset(name, 0, MAX_NAMELEN);
361 sprintf(name, "%u", irq);
362 remove_proc_entry(name, root_irq_dir);
363}
364
300#undef MAX_NAMELEN 365#undef MAX_NAMELEN
301 366
302void unregister_handler_proc(unsigned int irq, struct irqaction *action) 367void unregister_handler_proc(unsigned int irq, struct irqaction *action)
@@ -339,3 +404,83 @@ void init_irq_proc(void)
339 } 404 }
340} 405}
341 406
407#ifdef CONFIG_GENERIC_IRQ_SHOW
408
409int __weak arch_show_interrupts(struct seq_file *p, int prec)
410{
411 return 0;
412}
413
414#ifndef ACTUAL_NR_IRQS
415# define ACTUAL_NR_IRQS nr_irqs
416#endif
417
418int show_interrupts(struct seq_file *p, void *v)
419{
420 static int prec;
421
422 unsigned long flags, any_count = 0;
423 int i = *(loff_t *) v, j;
424 struct irqaction *action;
425 struct irq_desc *desc;
426
427 if (i > ACTUAL_NR_IRQS)
428 return 0;
429
430 if (i == ACTUAL_NR_IRQS)
431 return arch_show_interrupts(p, prec);
432
433 /* print header and calculate the width of the first column */
434 if (i == 0) {
435 for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
436 j *= 10;
437
438 seq_printf(p, "%*s", prec + 8, "");
439 for_each_online_cpu(j)
440 seq_printf(p, "CPU%-8d", j);
441 seq_putc(p, '\n');
442 }
443
444 desc = irq_to_desc(i);
445 if (!desc)
446 return 0;
447
448 raw_spin_lock_irqsave(&desc->lock, flags);
449 for_each_online_cpu(j)
450 any_count |= kstat_irqs_cpu(i, j);
451 action = desc->action;
452 if (!action && !any_count)
453 goto out;
454
455 seq_printf(p, "%*d: ", prec, i);
456 for_each_online_cpu(j)
457 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
458
459 if (desc->irq_data.chip) {
460 if (desc->irq_data.chip->irq_print_chip)
461 desc->irq_data.chip->irq_print_chip(&desc->irq_data, p);
462 else if (desc->irq_data.chip->name)
463 seq_printf(p, " %8s", desc->irq_data.chip->name);
464 else
465 seq_printf(p, " %8s", "-");
466 } else {
467 seq_printf(p, " %8s", "None");
468 }
469#ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL
470 seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge");
471#endif
472 if (desc->name)
473 seq_printf(p, "-%-8s", desc->name);
474
475 if (action) {
476 seq_printf(p, " %s", action->name);
477 while ((action = action->next) != NULL)
478 seq_printf(p, ", %s", action->name);
479 }
480
481 seq_putc(p, '\n');
482out:
483 raw_spin_unlock_irqrestore(&desc->lock, flags);
484 return 0;
485}
486#endif