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