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 15 #include "internals.h" 16 17 static struct proc_dir_entry *root_irq_dir; 18 19 #ifdef CONFIG_SMP 20 21 static int irq_affinity_proc_show(struct seq_file *m, void *v) 22 { 23 struct irq_desc *desc = irq_to_desc((long)m->private); 24 const struct cpumask *mask = desc->affinity; 25 26 #ifdef CONFIG_GENERIC_PENDING_IRQ 27 if (desc->status & IRQ_MOVE_PENDING) 28 mask = desc->pending_mask; 29 #endif 30 seq_cpumask(m, mask); 31 seq_putc(m, '\n'); 32 return 0; 33 } 34 35 #ifndef is_affinity_mask_valid 36 #define is_affinity_mask_valid(val) 1 37 #endif 38 39 int no_irq_affinity; 40 static ssize_t irq_affinity_proc_write(struct file *file, 41 const char __user *buffer, size_t count, loff_t *pos) 42 { 43 unsigned int irq = (int)(long)PDE(file->f_path.dentry->d_inode)->data; 44 cpumask_var_t new_value; 45 int err; 46 47 if (!irq_to_desc(irq)->chip->set_affinity || no_irq_affinity || 48 irq_balancing_disabled(irq)) 49 return -EIO; 50 51 if (!alloc_cpumask_var(&new_value, GFP_KERNEL)) 52 return -ENOMEM; 53 54 err = cpumask_parse_user(buffer, count, new_value); 55 if (err) 56 goto free_cpumask; 57 58 if (!is_affinity_mask_valid(new_value)) { 59 err = -EINVAL; 60 goto free_cpumask; 61 } 62 63 /* 64 * Do not allow disabling IRQs completely - it's a too easy 65 * way to make the system unusable accidentally :-) At least 66 * one online CPU still has to be targeted. 67 */ 68 if (!cpumask_intersects(new_value, cpu_online_mask)) { 69 /* Special case for empty set - allow the architecture 70 code to set default SMP affinity. */ 71 err = irq_select_affinity_usr(irq) ? -EINVAL : count; 72 } else { 73 irq_set_affinity(irq, new_value); 74 err = count; 75 } 76 77 free_cpumask: 78 free_cpumask_var(new_value); 79 return err; 80 } 81 82 static int irq_affinity_proc_open(struct inode *inode, struct file *file) 83 { 84 return single_open(file, irq_affinity_proc_show, PDE(inode)->data); 85 } 86 87 static const struct file_operations irq_affinity_proc_fops = { 88 .open = irq_affinity_proc_open, 89 .read = seq_read, 90 .llseek = seq_lseek, 91 .release = single_release, 92 .write = irq_affinity_proc_write, 93 }; 94 95 static int default_affinity_show(struct seq_file *m, void *v) 96 { 97 seq_cpumask(m, irq_default_affinity); 98 seq_putc(m, '\n'); 99 return 0; 100 } 101 102 static ssize_t default_affinity_write(struct file *file, 103 const char __user *buffer, size_t count, loff_t *ppos) 104 { 105 cpumask_var_t new_value; 106 int err; 107 108 if (!alloc_cpumask_var(&new_value, GFP_KERNEL)) 109 return -ENOMEM; 110 111 err = cpumask_parse_user(buffer, count, new_value); 112 if (err) 113 goto out; 114 115 if (!is_affinity_mask_valid(new_value)) { 116 err = -EINVAL; 117 goto out; 118 } 119 120 /* 121 * Do not allow disabling IRQs completely - it's a too easy 122 * way to make the system unusable accidentally :-) At least 123 * one online CPU still has to be targeted. 124 */ 125 if (!cpumask_intersects(new_value, cpu_online_mask)) { 126 err = -EINVAL; 127 goto out; 128 } 129 130 cpumask_copy(irq_default_affinity, new_value); 131 err = count; 132 133 out: 134 free_cpumask_var(new_value); 135 return err; 136 } 137 138 static int default_affinity_open(struct inode *inode, struct file *file) 139 { 140 return single_open(file, default_affinity_show, PDE(inode)->data); 141 } 142 143 static const struct file_operations default_affinity_proc_fops = { 144 .open = default_affinity_open, 145 .read = seq_read, 146 .llseek = seq_lseek, 147 .release = single_release, 148 .write = default_affinity_write, 149 }; 150 #endif 151 152 static int irq_spurious_proc_show(struct seq_file *m, void *v) 153 { 154 struct irq_desc *desc = irq_to_desc((long) m->private); 155 156 seq_printf(m, "count %u\n" "unhandled %u\n" "last_unhandled %u ms\n", 157 desc->irq_count, desc->irqs_unhandled, 158 jiffies_to_msecs(desc->last_unhandled)); 159 return 0; 160 } 161 162 static int irq_spurious_proc_open(struct inode *inode, struct file *file) 163 { 164 return single_open(file, irq_spurious_proc_show, NULL); 165 } 166 167 static const struct file_operations irq_spurious_proc_fops = { 168 .open = irq_spurious_proc_open, 169 .read = seq_read, 170 .llseek = seq_lseek, 171 .release = single_release, 172 }; 173 174 #define MAX_NAMELEN 128 175 176 static int name_unique(unsigned int irq, struct irqaction *new_action) 177 { 178 struct irq_desc *desc = irq_to_desc(irq); 179 struct irqaction *action; 180 unsigned long flags; 181 int ret = 1; 182 183 raw_spin_lock_irqsave(&desc->lock, flags); 184 for (action = desc->action ; action; action = action->next) { 185 if ((action != new_action) && action->name && 186 !strcmp(new_action->name, action->name)) { 187 ret = 0; 188 break; 189 } 190 } 191 raw_spin_unlock_irqrestore(&desc->lock, flags); 192 return ret; 193 } 194 195 void register_handler_proc(unsigned int irq, struct irqaction *action) 196 { 197 char name [MAX_NAMELEN]; 198 struct irq_desc *desc = irq_to_desc(irq); 199 200 if (!desc->dir || action->dir || !action->name || 201 !name_unique(irq, action)) 202 return; 203 204 memset(name, 0, MAX_NAMELEN); 205 snprintf(name, MAX_NAMELEN, "%s", action->name); 206 207 /* create /proc/irq/1234/handler/ */ 208 action->dir = proc_mkdir(name, desc->dir); 209 } 210 211 #undef MAX_NAMELEN 212 213 #define MAX_NAMELEN 10 214 215 void register_irq_proc(unsigned int irq, struct irq_desc *desc) 216 { 217 char name [MAX_NAMELEN]; 218 219 if (!root_irq_dir || (desc->chip == &no_irq_chip) || desc->dir) 220 return; 221 222 memset(name, 0, MAX_NAMELEN); 223 sprintf(name, "%d", irq); 224 225 /* create /proc/irq/1234 */ 226 desc->dir = proc_mkdir(name, root_irq_dir); 227 if (!desc->dir) 228 return; 229 230 #ifdef CONFIG_SMP 231 /* create /proc/irq/<irq>/smp_affinity */ 232 proc_create_data("smp_affinity", 0600, desc->dir, 233 &irq_affinity_proc_fops, (void *)(long)irq); 234 #endif 235 236 proc_create_data("spurious", 0444, desc->dir, 237 &irq_spurious_proc_fops, (void *)(long)irq); 238 } 239 240 #undef MAX_NAMELEN 241 242 void unregister_handler_proc(unsigned int irq, struct irqaction *action) 243 { 244 if (action->dir) { 245 struct irq_desc *desc = irq_to_desc(irq); 246 247 remove_proc_entry(action->dir->name, desc->dir); 248 } 249 } 250 251 static void register_default_affinity_proc(void) 252 { 253 #ifdef CONFIG_SMP 254 proc_create("irq/default_smp_affinity", 0600, NULL, 255 &default_affinity_proc_fops); 256 #endif 257 } 258 259 void init_irq_proc(void) 260 { 261 unsigned int irq; 262 struct irq_desc *desc; 263 264 /* create /proc/irq */ 265 root_irq_dir = proc_mkdir("irq", NULL); 266 if (!root_irq_dir) 267 return; 268 269 register_default_affinity_proc(); 270 271 /* 272 * Create entries for all existing IRQs. 273 */ 274 for_each_irq_desc(irq, desc) { 275 if (!desc) 276 continue; 277 278 register_irq_proc(irq, desc); 279 } 280 } 281 282