diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 00:55:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 00:55:47 -0400 |
commit | e86908614f2c7fec401827e5cefd7a6ea9407f85 (patch) | |
tree | fcb5d9e52422b37bdaf0e647126ebdfc1680f162 /arch/powerpc/kernel/irq.c | |
parent | 547307420931344a868275bd7ea7a30f117a15a9 (diff) | |
parent | 9b4b8feb962f4b3e74768b7205f1f8f6cce87238 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (408 commits)
[POWERPC] Add memchr() to the bootwrapper
[POWERPC] Implement logging of unhandled signals
[POWERPC] Add legacy serial support for OPB with flattened device tree
[POWERPC] Use 1TB segments
[POWERPC] XilinxFB: Allow fixed framebuffer base address
[POWERPC] XilinxFB: Add support for custom screen resolution
[POWERPC] XilinxFB: Use pdata to pass around framebuffer parameters
[POWERPC] PCI: Add 64-bit physical address support to setup_indirect_pci
[POWERPC] 4xx: Kilauea defconfig file
[POWERPC] 4xx: Kilauea DTS
[POWERPC] 4xx: Add AMCC Kilauea eval board support to platforms/40x
[POWERPC] 4xx: Add AMCC 405EX support to cputable.c
[POWERPC] Adjust TASK_SIZE on ppc32 systems to 3GB that are capable
[POWERPC] Use PAGE_OFFSET to tell if an address is user/kernel in SW TLB handlers
[POWERPC] 85xx: Enable FP emulation in MPC8560 ADS defconfig
[POWERPC] 85xx: Killed <asm/mpc85xx.h>
[POWERPC] 85xx: Add cpm nodes for 8541/8555 CDS
[POWERPC] 85xx: Convert mpc8560ads to the new CPM binding.
[POWERPC] mpc8272ads: Remove muram from the CPM reg property.
[POWERPC] Make clockevents work on PPC601 processors
...
Fixed up conflict in Documentation/powerpc/booting-without-of.txt manually.
Diffstat (limited to 'arch/powerpc/kernel/irq.c')
-rw-r--r-- | arch/powerpc/kernel/irq.c | 97 |
1 files changed, 82 insertions, 15 deletions
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 9bf63d5256db..2250f9e6c5ca 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 |
@@ -417,10 +418,16 @@ irq_hw_number_t virq_to_hw(unsigned int virq) | |||
417 | } | 418 | } |
418 | EXPORT_SYMBOL_GPL(virq_to_hw); | 419 | EXPORT_SYMBOL_GPL(virq_to_hw); |
419 | 420 | ||
420 | __init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type, | 421 | static int default_irq_host_match(struct irq_host *h, struct device_node *np) |
421 | unsigned int revmap_arg, | 422 | { |
422 | struct irq_host_ops *ops, | 423 | return h->of_node != NULL && h->of_node == np; |
423 | irq_hw_number_t inval_irq) | 424 | } |
425 | |||
426 | struct irq_host *irq_alloc_host(struct device_node *of_node, | ||
427 | unsigned int revmap_type, | ||
428 | unsigned int revmap_arg, | ||
429 | struct irq_host_ops *ops, | ||
430 | irq_hw_number_t inval_irq) | ||
424 | { | 431 | { |
425 | struct irq_host *host; | 432 | struct irq_host *host; |
426 | unsigned int size = sizeof(struct irq_host); | 433 | unsigned int size = sizeof(struct irq_host); |
@@ -431,13 +438,7 @@ __init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type, | |||
431 | /* Allocate structure and revmap table if using linear mapping */ | 438 | /* Allocate structure and revmap table if using linear mapping */ |
432 | if (revmap_type == IRQ_HOST_MAP_LINEAR) | 439 | if (revmap_type == IRQ_HOST_MAP_LINEAR) |
433 | size += revmap_arg * sizeof(unsigned int); | 440 | size += revmap_arg * sizeof(unsigned int); |
434 | if (mem_init_done) | 441 | host = zalloc_maybe_bootmem(size, GFP_KERNEL); |
435 | host = kzalloc(size, GFP_KERNEL); | ||
436 | else { | ||
437 | host = alloc_bootmem(size); | ||
438 | if (host) | ||
439 | memset(host, 0, size); | ||
440 | } | ||
441 | if (host == NULL) | 442 | if (host == NULL) |
442 | return NULL; | 443 | return NULL; |
443 | 444 | ||
@@ -445,6 +446,10 @@ __init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type, | |||
445 | host->revmap_type = revmap_type; | 446 | host->revmap_type = revmap_type; |
446 | host->inval_irq = inval_irq; | 447 | host->inval_irq = inval_irq; |
447 | host->ops = ops; | 448 | host->ops = ops; |
449 | host->of_node = of_node; | ||
450 | |||
451 | if (host->ops->match == NULL) | ||
452 | host->ops->match = default_irq_host_match; | ||
448 | 453 | ||
449 | spin_lock_irqsave(&irq_big_lock, flags); | 454 | spin_lock_irqsave(&irq_big_lock, flags); |
450 | 455 | ||
@@ -476,7 +481,7 @@ __init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type, | |||
476 | host->inval_irq = 0; | 481 | host->inval_irq = 0; |
477 | /* setup us as the host for all legacy interrupts */ | 482 | /* setup us as the host for all legacy interrupts */ |
478 | for (i = 1; i < NUM_ISA_INTERRUPTS; i++) { | 483 | for (i = 1; i < NUM_ISA_INTERRUPTS; i++) { |
479 | irq_map[i].hwirq = 0; | 484 | irq_map[i].hwirq = i; |
480 | smp_wmb(); | 485 | smp_wmb(); |
481 | irq_map[i].host = host; | 486 | irq_map[i].host = host; |
482 | smp_wmb(); | 487 | smp_wmb(); |
@@ -520,7 +525,7 @@ struct irq_host *irq_find_host(struct device_node *node) | |||
520 | */ | 525 | */ |
521 | spin_lock_irqsave(&irq_big_lock, flags); | 526 | spin_lock_irqsave(&irq_big_lock, flags); |
522 | list_for_each_entry(h, &irq_hosts, link) | 527 | list_for_each_entry(h, &irq_hosts, link) |
523 | if (h->ops->match == NULL || h->ops->match(h, node)) { | 528 | if (h->ops->match(h, node)) { |
524 | found = h; | 529 | found = h; |
525 | break; | 530 | break; |
526 | } | 531 | } |
@@ -995,6 +1000,68 @@ static int irq_late_init(void) | |||
995 | } | 1000 | } |
996 | arch_initcall(irq_late_init); | 1001 | arch_initcall(irq_late_init); |
997 | 1002 | ||
1003 | #ifdef CONFIG_VIRQ_DEBUG | ||
1004 | static int virq_debug_show(struct seq_file *m, void *private) | ||
1005 | { | ||
1006 | unsigned long flags; | ||
1007 | irq_desc_t *desc; | ||
1008 | const char *p; | ||
1009 | char none[] = "none"; | ||
1010 | int i; | ||
1011 | |||
1012 | seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", | ||
1013 | "chip name", "host name"); | ||
1014 | |||
1015 | for (i = 1; i < NR_IRQS; i++) { | ||
1016 | desc = get_irq_desc(i); | ||
1017 | spin_lock_irqsave(&desc->lock, flags); | ||
1018 | |||
1019 | if (desc->action && desc->action->handler) { | ||
1020 | seq_printf(m, "%5d ", i); | ||
1021 | seq_printf(m, "0x%05lx ", virq_to_hw(i)); | ||
1022 | |||
1023 | if (desc->chip && desc->chip->typename) | ||
1024 | p = desc->chip->typename; | ||
1025 | else | ||
1026 | p = none; | ||
1027 | seq_printf(m, "%-15s ", p); | ||
1028 | |||
1029 | if (irq_map[i].host && irq_map[i].host->of_node) | ||
1030 | p = irq_map[i].host->of_node->full_name; | ||
1031 | else | ||
1032 | p = none; | ||
1033 | seq_printf(m, "%s\n", p); | ||
1034 | } | ||
1035 | |||
1036 | spin_unlock_irqrestore(&desc->lock, flags); | ||
1037 | } | ||
1038 | |||
1039 | return 0; | ||
1040 | } | ||
1041 | |||
1042 | static int virq_debug_open(struct inode *inode, struct file *file) | ||
1043 | { | ||
1044 | return single_open(file, virq_debug_show, inode->i_private); | ||
1045 | } | ||
1046 | |||
1047 | static const struct file_operations virq_debug_fops = { | ||
1048 | .open = virq_debug_open, | ||
1049 | .read = seq_read, | ||
1050 | .llseek = seq_lseek, | ||
1051 | .release = single_release, | ||
1052 | }; | ||
1053 | |||
1054 | static int __init irq_debugfs_init(void) | ||
1055 | { | ||
1056 | if (debugfs_create_file("virq_mapping", S_IRUGO, powerpc_debugfs_root, | ||
1057 | NULL, &virq_debug_fops)) | ||
1058 | return -ENOMEM; | ||
1059 | |||
1060 | return 0; | ||
1061 | } | ||
1062 | __initcall(irq_debugfs_init); | ||
1063 | #endif /* CONFIG_VIRQ_DEBUG */ | ||
1064 | |||
998 | #endif /* CONFIG_PPC_MERGE */ | 1065 | #endif /* CONFIG_PPC_MERGE */ |
999 | 1066 | ||
1000 | #ifdef CONFIG_PPC64 | 1067 | #ifdef CONFIG_PPC64 |