• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
show_irq_affinity(int type,struct seq_file * m,void * v)22  static int show_irq_affinity(int type, 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  	if (type)
32  		seq_cpumask_list(m, mask);
33  	else
34  		seq_cpumask(m, mask);
35  	seq_putc(m, '\n');
36  	return 0;
37  }
38  
irq_affinity_hint_proc_show(struct seq_file * m,void * v)39  static int irq_affinity_hint_proc_show(struct seq_file *m, void *v)
40  {
41  	struct irq_desc *desc = irq_to_desc((long)m->private);
42  	unsigned long flags;
43  	cpumask_var_t mask;
44  
45  	if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
46  		return -ENOMEM;
47  
48  	raw_spin_lock_irqsave(&desc->lock, flags);
49  	if (desc->affinity_hint)
50  		cpumask_copy(mask, desc->affinity_hint);
51  	raw_spin_unlock_irqrestore(&desc->lock, flags);
52  
53  	seq_cpumask(m, mask);
54  	seq_putc(m, '\n');
55  	free_cpumask_var(mask);
56  
57  	return 0;
58  }
59  
60  #ifndef is_affinity_mask_valid
61  #define is_affinity_mask_valid(val) 1
62  #endif
63  
64  int no_irq_affinity;
irq_affinity_proc_show(struct seq_file * m,void * v)65  static int irq_affinity_proc_show(struct seq_file *m, void *v)
66  {
67  	return show_irq_affinity(0, m, v);
68  }
69  
irq_affinity_list_proc_show(struct seq_file * m,void * v)70  static int irq_affinity_list_proc_show(struct seq_file *m, void *v)
71  {
72  	return show_irq_affinity(1, m, v);
73  }
74  
75  
write_irq_affinity(int type,struct file * file,const char __user * buffer,size_t count,loff_t * pos)76  static ssize_t write_irq_affinity(int type, struct file *file,
77  		const char __user *buffer, size_t count, loff_t *pos)
78  {
79  	unsigned int irq = (int)(long)PDE_DATA(file_inode(file));
80  	cpumask_var_t new_value;
81  	int err;
82  
83  	if (!irq_can_set_affinity(irq) || no_irq_affinity)
84  		return -EIO;
85  
86  	if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
87  		return -ENOMEM;
88  
89  	if (type)
90  		err = cpumask_parselist_user(buffer, count, new_value);
91  	else
92  		err = cpumask_parse_user(buffer, count, new_value);
93  	if (err)
94  		goto free_cpumask;
95  
96  	if (!is_affinity_mask_valid(new_value)) {
97  		err = -EINVAL;
98  		goto free_cpumask;
99  	}
100  
101  	/*
102  	 * Do not allow disabling IRQs completely - it's a too easy
103  	 * way to make the system unusable accidentally :-) At least
104  	 * one online CPU still has to be targeted.
105  	 */
106  	if (!cpumask_intersects(new_value, cpu_online_mask)) {
107  		/* Special case for empty set - allow the architecture
108  		   code to set default SMP affinity. */
109  		err = irq_select_affinity_usr(irq, new_value) ? -EINVAL : count;
110  	} else {
111  		irq_set_affinity(irq, new_value);
112  		err = count;
113  	}
114  
115  free_cpumask:
116  	free_cpumask_var(new_value);
117  	return err;
118  }
119  
irq_affinity_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * pos)120  static 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  
irq_affinity_list_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * pos)126  static 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  
irq_affinity_proc_open(struct inode * inode,struct file * file)132  static int irq_affinity_proc_open(struct inode *inode, struct file *file)
133  {
134  	return single_open(file, irq_affinity_proc_show, PDE_DATA(inode));
135  }
136  
irq_affinity_list_proc_open(struct inode * inode,struct file * file)137  static int irq_affinity_list_proc_open(struct inode *inode, struct file *file)
138  {
139  	return single_open(file, irq_affinity_list_proc_show, PDE_DATA(inode));
140  }
141  
irq_affinity_hint_proc_open(struct inode * inode,struct file * file)142  static int irq_affinity_hint_proc_open(struct inode *inode, struct file *file)
143  {
144  	return single_open(file, irq_affinity_hint_proc_show, PDE_DATA(inode));
145  }
146  
147  static const struct file_operations irq_affinity_proc_fops = {
148  	.open		= irq_affinity_proc_open,
149  	.read		= seq_read,
150  	.llseek		= seq_lseek,
151  	.release	= single_release,
152  	.write		= irq_affinity_proc_write,
153  };
154  
155  static const struct file_operations irq_affinity_hint_proc_fops = {
156  	.open		= irq_affinity_hint_proc_open,
157  	.read		= seq_read,
158  	.llseek		= seq_lseek,
159  	.release	= single_release,
160  };
161  
162  static 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  
default_affinity_show(struct seq_file * m,void * v)170  static int default_affinity_show(struct seq_file *m, void *v)
171  {
172  	seq_cpumask(m, irq_default_affinity);
173  	seq_putc(m, '\n');
174  	return 0;
175  }
176  
default_affinity_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)177  static ssize_t default_affinity_write(struct file *file,
178  		const char __user *buffer, size_t count, loff_t *ppos)
179  {
180  	cpumask_var_t new_value;
181  	int err;
182  
183  	if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
184  		return -ENOMEM;
185  
186  	err = cpumask_parse_user(buffer, count, new_value);
187  	if (err)
188  		goto out;
189  
190  	if (!is_affinity_mask_valid(new_value)) {
191  		err = -EINVAL;
192  		goto out;
193  	}
194  
195  	/*
196  	 * Do not allow disabling IRQs completely - it's a too easy
197  	 * way to make the system unusable accidentally :-) At least
198  	 * one online CPU still has to be targeted.
199  	 */
200  	if (!cpumask_intersects(new_value, cpu_online_mask)) {
201  		err = -EINVAL;
202  		goto out;
203  	}
204  
205  	cpumask_copy(irq_default_affinity, new_value);
206  	err = count;
207  
208  out:
209  	free_cpumask_var(new_value);
210  	return err;
211  }
212  
default_affinity_open(struct inode * inode,struct file * file)213  static int default_affinity_open(struct inode *inode, struct file *file)
214  {
215  	return single_open(file, default_affinity_show, PDE_DATA(inode));
216  }
217  
218  static const struct file_operations default_affinity_proc_fops = {
219  	.open		= default_affinity_open,
220  	.read		= seq_read,
221  	.llseek		= seq_lseek,
222  	.release	= single_release,
223  	.write		= default_affinity_write,
224  };
225  
irq_node_proc_show(struct seq_file * m,void * v)226  static int irq_node_proc_show(struct seq_file *m, void *v)
227  {
228  	struct irq_desc *desc = irq_to_desc((long) m->private);
229  
230  	seq_printf(m, "%d\n", desc->irq_data.node);
231  	return 0;
232  }
233  
irq_node_proc_open(struct inode * inode,struct file * file)234  static int irq_node_proc_open(struct inode *inode, struct file *file)
235  {
236  	return single_open(file, irq_node_proc_show, PDE_DATA(inode));
237  }
238  
239  static const struct file_operations irq_node_proc_fops = {
240  	.open		= irq_node_proc_open,
241  	.read		= seq_read,
242  	.llseek		= seq_lseek,
243  	.release	= single_release,
244  };
245  #endif
246  
irq_spurious_proc_show(struct seq_file * m,void * v)247  static int irq_spurious_proc_show(struct seq_file *m, void *v)
248  {
249  	struct irq_desc *desc = irq_to_desc((long) m->private);
250  
251  	seq_printf(m, "count %u\n" "unhandled %u\n" "last_unhandled %u ms\n",
252  		   desc->irq_count, desc->irqs_unhandled,
253  		   jiffies_to_msecs(desc->last_unhandled));
254  	return 0;
255  }
256  
irq_spurious_proc_open(struct inode * inode,struct file * file)257  static int irq_spurious_proc_open(struct inode *inode, struct file *file)
258  {
259  	return single_open(file, irq_spurious_proc_show, PDE_DATA(inode));
260  }
261  
262  static const struct file_operations irq_spurious_proc_fops = {
263  	.open		= irq_spurious_proc_open,
264  	.read		= seq_read,
265  	.llseek		= seq_lseek,
266  	.release	= single_release,
267  };
268  
269  #define MAX_NAMELEN 128
270  
name_unique(unsigned int irq,struct irqaction * new_action)271  static int name_unique(unsigned int irq, struct irqaction *new_action)
272  {
273  	struct irq_desc *desc = irq_to_desc(irq);
274  	struct irqaction *action;
275  	unsigned long flags;
276  	int ret = 1;
277  
278  	raw_spin_lock_irqsave(&desc->lock, flags);
279  	for (action = desc->action ; action; action = action->next) {
280  		if ((action != new_action) && action->name &&
281  				!strcmp(new_action->name, action->name)) {
282  			ret = 0;
283  			break;
284  		}
285  	}
286  	raw_spin_unlock_irqrestore(&desc->lock, flags);
287  	return ret;
288  }
289  
register_handler_proc(unsigned int irq,struct irqaction * action)290  void register_handler_proc(unsigned int irq, struct irqaction *action)
291  {
292  	char name [MAX_NAMELEN];
293  	struct irq_desc *desc = irq_to_desc(irq);
294  
295  	if (!desc->dir || action->dir || !action->name ||
296  					!name_unique(irq, action))
297  		return;
298  
299  	memset(name, 0, MAX_NAMELEN);
300  	snprintf(name, MAX_NAMELEN, "%s", action->name);
301  
302  	/* create /proc/irq/1234/handler/ */
303  	action->dir = proc_mkdir(name, desc->dir);
304  }
305  
306  #undef MAX_NAMELEN
307  
308  #define MAX_NAMELEN 10
309  
register_irq_proc(unsigned int irq,struct irq_desc * desc)310  void register_irq_proc(unsigned int irq, struct irq_desc *desc)
311  {
312  	char name [MAX_NAMELEN];
313  
314  	if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir)
315  		return;
316  
317  	memset(name, 0, MAX_NAMELEN);
318  	sprintf(name, "%d", irq);
319  
320  	/* create /proc/irq/1234 */
321  	desc->dir = proc_mkdir(name, root_irq_dir);
322  	if (!desc->dir)
323  		return;
324  
325  #ifdef CONFIG_SMP
326  	/* create /proc/irq/<irq>/smp_affinity */
327  	proc_create_data("smp_affinity", 0600, desc->dir,
328  			 &irq_affinity_proc_fops, (void *)(long)irq);
329  
330  	/* create /proc/irq/<irq>/affinity_hint */
331  	proc_create_data("affinity_hint", 0400, desc->dir,
332  			 &irq_affinity_hint_proc_fops, (void *)(long)irq);
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  
338  	proc_create_data("node", 0444, desc->dir,
339  			 &irq_node_proc_fops, (void *)(long)irq);
340  #endif
341  
342  	proc_create_data("spurious", 0444, desc->dir,
343  			 &irq_spurious_proc_fops, (void *)(long)irq);
344  }
345  
unregister_irq_proc(unsigned int irq,struct irq_desc * desc)346  void 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  
365  #undef MAX_NAMELEN
366  
unregister_handler_proc(unsigned int irq,struct irqaction * action)367  void unregister_handler_proc(unsigned int irq, struct irqaction *action)
368  {
369  	proc_remove(action->dir);
370  }
371  
register_default_affinity_proc(void)372  static void register_default_affinity_proc(void)
373  {
374  #ifdef CONFIG_SMP
375  	proc_create("irq/default_smp_affinity", 0600, NULL,
376  		    &default_affinity_proc_fops);
377  #endif
378  }
379  
init_irq_proc(void)380  void init_irq_proc(void)
381  {
382  	unsigned int irq;
383  	struct irq_desc *desc;
384  
385  	/* create /proc/irq */
386  	root_irq_dir = proc_mkdir("irq", NULL);
387  	if (!root_irq_dir)
388  		return;
389  
390  	register_default_affinity_proc();
391  
392  	/*
393  	 * Create entries for all existing IRQs.
394  	 */
395  	for_each_irq_desc(irq, desc) {
396  		if (!desc)
397  			continue;
398  
399  		register_irq_proc(irq, desc);
400  	}
401  }
402  
403  #ifdef CONFIG_GENERIC_IRQ_SHOW
404  
arch_show_interrupts(struct seq_file * p,int prec)405  int __weak arch_show_interrupts(struct seq_file *p, int prec)
406  {
407  	return 0;
408  }
409  
410  #ifndef ACTUAL_NR_IRQS
411  # define ACTUAL_NR_IRQS nr_irqs
412  #endif
413  
show_interrupts(struct seq_file * p,void * v)414  int show_interrupts(struct seq_file *p, void *v)
415  {
416  	static int prec;
417  
418  	unsigned long flags, any_count = 0;
419  	int i = *(loff_t *) v, j;
420  	struct irqaction *action;
421  	struct irq_desc *desc;
422  
423  	if (i > ACTUAL_NR_IRQS)
424  		return 0;
425  
426  	if (i == ACTUAL_NR_IRQS)
427  		return arch_show_interrupts(p, prec);
428  
429  	/* print header and calculate the width of the first column */
430  	if (i == 0) {
431  		for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
432  			j *= 10;
433  
434  		seq_printf(p, "%*s", prec + 8, "");
435  		for_each_online_cpu(j)
436  			seq_printf(p, "CPU%-8d", j);
437  		seq_putc(p, '\n');
438  	}
439  
440  	desc = irq_to_desc(i);
441  	if (!desc)
442  		return 0;
443  
444  	raw_spin_lock_irqsave(&desc->lock, flags);
445  	for_each_online_cpu(j)
446  		any_count |= kstat_irqs_cpu(i, j);
447  	action = desc->action;
448  	if (!action && !any_count)
449  		goto out;
450  
451  	seq_printf(p, "%*d: ", prec, i);
452  	for_each_online_cpu(j)
453  		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
454  
455  	if (desc->irq_data.chip) {
456  		if (desc->irq_data.chip->irq_print_chip)
457  			desc->irq_data.chip->irq_print_chip(&desc->irq_data, p);
458  		else if (desc->irq_data.chip->name)
459  			seq_printf(p, " %8s", desc->irq_data.chip->name);
460  		else
461  			seq_printf(p, " %8s", "-");
462  	} else {
463  		seq_printf(p, " %8s", "None");
464  	}
465  #ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL
466  	seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge");
467  #endif
468  	if (desc->name)
469  		seq_printf(p, "-%-8s", desc->name);
470  
471  	if (action) {
472  		seq_printf(p, "  %s", action->name);
473  		while ((action = action->next) != NULL)
474  			seq_printf(p, ", %s", action->name);
475  	}
476  
477  	seq_putc(p, '\n');
478  out:
479  	raw_spin_unlock_irqrestore(&desc->lock, flags);
480  	return 0;
481  }
482  #endif
483