aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/irq.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-12 00:55:47 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-12 00:55:47 -0400
commite86908614f2c7fec401827e5cefd7a6ea9407f85 (patch)
treefcb5d9e52422b37bdaf0e647126ebdfc1680f162 /arch/powerpc/kernel/irq.c
parent547307420931344a868275bd7ea7a30f117a15a9 (diff)
parent9b4b8feb962f4b3e74768b7205f1f8f6cce87238 (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.c97
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}
418EXPORT_SYMBOL_GPL(virq_to_hw); 419EXPORT_SYMBOL_GPL(virq_to_hw);
419 420
420__init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type, 421static 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
426struct 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}
996arch_initcall(irq_late_init); 1001arch_initcall(irq_late_init);
997 1002
1003#ifdef CONFIG_VIRQ_DEBUG
1004static 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
1042static int virq_debug_open(struct inode *inode, struct file *file)
1043{
1044 return single_open(file, virq_debug_show, inode->i_private);
1045}
1046
1047static 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
1054static 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