aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/irq.c')
-rw-r--r--arch/powerpc/kernel/irq.c97
1 files changed, 82 insertions, 15 deletions
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 24bea97c736c..151b13119208 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -52,6 +52,7 @@
52#include <linux/mutex.h> 52#include <linux/mutex.h>
53#include <linux/bootmem.h> 53#include <linux/bootmem.h>
54#include <linux/pci.h> 54#include <linux/pci.h>
55#include <linux/debugfs.h>
55 56
56#include <asm/uaccess.h> 57#include <asm/uaccess.h>
57#include <asm/system.h> 58#include <asm/system.h>
@@ -272,7 +273,7 @@ void do_IRQ(struct pt_regs *regs)
272 struct thread_info *curtp, *irqtp; 273 struct thread_info *curtp, *irqtp;
273#endif 274#endif
274 275
275 irq_enter(); 276 irq_enter();
276 277
277#ifdef CONFIG_DEBUG_STACKOVERFLOW 278#ifdef CONFIG_DEBUG_STACKOVERFLOW
278 /* Debugging check for stack overflow: is there less than 2KB free? */ 279 /* Debugging check for stack overflow: is there less than 2KB free? */
@@ -321,7 +322,7 @@ void do_IRQ(struct pt_regs *regs)
321 /* That's not SMP safe ... but who cares ? */ 322 /* That's not SMP safe ... but who cares ? */
322 ppc_spurious_interrupts++; 323 ppc_spurious_interrupts++;
323 324
324 irq_exit(); 325 irq_exit();
325 set_irq_regs(old_regs); 326 set_irq_regs(old_regs);
326 327
327#ifdef CONFIG_PPC_ISERIES 328#ifdef CONFIG_PPC_ISERIES
@@ -418,10 +419,16 @@ irq_hw_number_t virq_to_hw(unsigned int virq)
418} 419}
419EXPORT_SYMBOL_GPL(virq_to_hw); 420EXPORT_SYMBOL_GPL(virq_to_hw);
420 421
421__init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type, 422static int default_irq_host_match(struct irq_host *h, struct device_node *np)
422 unsigned int revmap_arg, 423{
423 struct irq_host_ops *ops, 424 return h->of_node != NULL && h->of_node == np;
424 irq_hw_number_t inval_irq) 425}
426
427struct irq_host *irq_alloc_host(struct device_node *of_node,
428 unsigned int revmap_type,
429 unsigned int revmap_arg,
430 struct irq_host_ops *ops,
431 irq_hw_number_t inval_irq)
425{ 432{
426 struct irq_host *host; 433 struct irq_host *host;
427 unsigned int size = sizeof(struct irq_host); 434 unsigned int size = sizeof(struct irq_host);
@@ -432,13 +439,7 @@ __init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type,
432 /* Allocate structure and revmap table if using linear mapping */ 439 /* Allocate structure and revmap table if using linear mapping */
433 if (revmap_type == IRQ_HOST_MAP_LINEAR) 440 if (revmap_type == IRQ_HOST_MAP_LINEAR)
434 size += revmap_arg * sizeof(unsigned int); 441 size += revmap_arg * sizeof(unsigned int);
435 if (mem_init_done) 442 host = zalloc_maybe_bootmem(size, GFP_KERNEL);
436 host = kzalloc(size, GFP_KERNEL);
437 else {
438 host = alloc_bootmem(size);
439 if (host)
440 memset(host, 0, size);
441 }
442 if (host == NULL) 443 if (host == NULL)
443 return NULL; 444 return NULL;
444 445
@@ -446,6 +447,10 @@ __init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type,
446 host->revmap_type = revmap_type; 447 host->revmap_type = revmap_type;
447 host->inval_irq = inval_irq; 448 host->inval_irq = inval_irq;
448 host->ops = ops; 449 host->ops = ops;
450 host->of_node = of_node;
451
452 if (host->ops->match == NULL)
453 host->ops->match = default_irq_host_match;
449 454
450 spin_lock_irqsave(&irq_big_lock, flags); 455 spin_lock_irqsave(&irq_big_lock, flags);
451 456
@@ -477,7 +482,7 @@ __init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type,
477 host->inval_irq = 0; 482 host->inval_irq = 0;
478 /* setup us as the host for all legacy interrupts */ 483 /* setup us as the host for all legacy interrupts */
479 for (i = 1; i < NUM_ISA_INTERRUPTS; i++) { 484 for (i = 1; i < NUM_ISA_INTERRUPTS; i++) {
480 irq_map[i].hwirq = 0; 485 irq_map[i].hwirq = i;
481 smp_wmb(); 486 smp_wmb();
482 irq_map[i].host = host; 487 irq_map[i].host = host;
483 smp_wmb(); 488 smp_wmb();
@@ -521,7 +526,7 @@ struct irq_host *irq_find_host(struct device_node *node)
521 */ 526 */
522 spin_lock_irqsave(&irq_big_lock, flags); 527 spin_lock_irqsave(&irq_big_lock, flags);
523 list_for_each_entry(h, &irq_hosts, link) 528 list_for_each_entry(h, &irq_hosts, link)
524 if (h->ops->match == NULL || h->ops->match(h, node)) { 529 if (h->ops->match(h, node)) {
525 found = h; 530 found = h;
526 break; 531 break;
527 } 532 }
@@ -996,6 +1001,68 @@ static int irq_late_init(void)
996} 1001}
997arch_initcall(irq_late_init); 1002arch_initcall(irq_late_init);
998 1003
1004#ifdef CONFIG_VIRQ_DEBUG
1005static int virq_debug_show(struct seq_file *m, void *private)
1006{
1007 unsigned long flags;
1008 irq_desc_t *desc;
1009 const char *p;
1010 char none[] = "none";
1011 int i;
1012
1013 seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq",
1014 "chip name", "host name");
1015
1016 for (i = 1; i < NR_IRQS; i++) {
1017 desc = get_irq_desc(i);
1018 spin_lock_irqsave(&desc->lock, flags);
1019
1020 if (desc->action && desc->action->handler) {
1021 seq_printf(m, "%5d ", i);
1022 seq_printf(m, "0x%05lx ", virq_to_hw(i));
1023
1024 if (desc->chip && desc->chip->typename)
1025 p = desc->chip->typename;
1026 else
1027 p = none;
1028 seq_printf(m, "%-15s ", p);
1029
1030 if (irq_map[i].host && irq_map[i].host->of_node)
1031 p = irq_map[i].host->of_node->full_name;
1032 else
1033 p = none;
1034 seq_printf(m, "%s\n", p);
1035 }
1036
1037 spin_unlock_irqrestore(&desc->lock, flags);
1038 }
1039
1040 return 0;
1041}
1042
1043static int virq_debug_open(struct inode *inode, struct file *file)
1044{
1045 return single_open(file, virq_debug_show, inode->i_private);
1046}
1047
1048static const struct file_operations virq_debug_fops = {
1049 .open = virq_debug_open,
1050 .read = seq_read,
1051 .llseek = seq_lseek,
1052 .release = single_release,
1053};
1054
1055static int __init irq_debugfs_init(void)
1056{
1057 if (debugfs_create_file("virq_mapping", S_IRUGO, powerpc_debugfs_root,
1058 NULL, &virq_debug_fops))
1059 return -ENOMEM;
1060
1061 return 0;
1062}
1063__initcall(irq_debugfs_init);
1064#endif /* CONFIG_VIRQ_DEBUG */
1065
999#endif /* CONFIG_PPC_MERGE */ 1066#endif /* CONFIG_PPC_MERGE */
1000 1067
1001#ifdef CONFIG_PPC64 1068#ifdef CONFIG_PPC64