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