irq.c (f3d607c6b39bd9cb5000e03e2c0dc2afe1241374) | irq.c (40d50cf7ca956183f3a573bc21082e1c7d04fa7b) |
---|---|
1/* 2 * Derived from arch/i386/kernel/irq.c 3 * Copyright (C) 1992 Linus Torvalds 4 * Adapted from arch/i386 by Gary Thomas 5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 6 * Updated and modified by Cort Dougan <cort@fsmlabs.com> 7 * Copyright (C) 1996-2001 Cort Dougan 8 * Adapted for Power Macintosh by Paul Mackerras --- 56 unchanged lines hidden (view full) --- 65#include <asm/ptrace.h> 66#include <asm/machdep.h> 67#include <asm/udbg.h> 68#ifdef CONFIG_PPC64 69#include <asm/paca.h> 70#include <asm/firmware.h> 71#include <asm/lv1call.h> 72#endif | 1/* 2 * Derived from arch/i386/kernel/irq.c 3 * Copyright (C) 1992 Linus Torvalds 4 * Adapted from arch/i386 by Gary Thomas 5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 6 * Updated and modified by Cort Dougan <cort@fsmlabs.com> 7 * Copyright (C) 1996-2001 Cort Dougan 8 * Adapted for Power Macintosh by Paul Mackerras --- 56 unchanged lines hidden (view full) --- 65#include <asm/ptrace.h> 66#include <asm/machdep.h> 67#include <asm/udbg.h> 68#ifdef CONFIG_PPC64 69#include <asm/paca.h> 70#include <asm/firmware.h> 71#include <asm/lv1call.h> 72#endif |
73#define CREATE_TRACE_POINTS 74#include <asm/trace.h> | |
75 76int __irq_offset_value; 77static int ppc_spurious_interrupts; 78 79#ifdef CONFIG_PPC32 80EXPORT_SYMBOL(__irq_offset_value); 81atomic_t ppc_n_lost_interrupts; 82 83#ifdef CONFIG_TAU_INT 84extern int tau_initialized; 85extern int tau_interrupts(int); 86#endif 87#endif /* CONFIG_PPC32 */ 88 89#ifdef CONFIG_PPC64 | 73 74int __irq_offset_value; 75static int ppc_spurious_interrupts; 76 77#ifdef CONFIG_PPC32 78EXPORT_SYMBOL(__irq_offset_value); 79atomic_t ppc_n_lost_interrupts; 80 81#ifdef CONFIG_TAU_INT 82extern int tau_initialized; 83extern int tau_interrupts(int); 84#endif 85#endif /* CONFIG_PPC32 */ 86 87#ifdef CONFIG_PPC64 |
88 89#ifndef CONFIG_SPARSE_IRQ |
|
90EXPORT_SYMBOL(irq_desc); | 90EXPORT_SYMBOL(irq_desc); |
91#endif |
|
91 92int distribute_irqs = 1; 93 94static inline notrace unsigned long get_hard_enabled(void) 95{ 96 unsigned long enabled; 97 98 __asm__ __volatile__("lbz %0,%1(13)" --- 85 unchanged lines hidden (view full) --- 184 struct irq_desc *desc; 185 unsigned long flags; 186 187 if (i == 0) { 188 seq_puts(p, " "); 189 for_each_online_cpu(j) 190 seq_printf(p, "CPU%d ", j); 191 seq_putc(p, '\n'); | 92 93int distribute_irqs = 1; 94 95static inline notrace unsigned long get_hard_enabled(void) 96{ 97 unsigned long enabled; 98 99 __asm__ __volatile__("lbz %0,%1(13)" --- 85 unchanged lines hidden (view full) --- 185 struct irq_desc *desc; 186 unsigned long flags; 187 188 if (i == 0) { 189 seq_puts(p, " "); 190 for_each_online_cpu(j) 191 seq_printf(p, "CPU%d ", j); 192 seq_putc(p, '\n'); |
192 } 193 194 if (i < NR_IRQS) { 195 desc = get_irq_desc(i); 196 spin_lock_irqsave(&desc->lock, flags); 197 action = desc->action; 198 if (!action || !action->handler) 199 goto skip; 200 seq_printf(p, "%3d: ", i); 201#ifdef CONFIG_SMP 202 for_each_online_cpu(j) 203 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); 204#else 205 seq_printf(p, "%10u ", kstat_irqs(i)); 206#endif /* CONFIG_SMP */ 207 if (desc->chip) 208 seq_printf(p, " %s ", desc->chip->typename); 209 else 210 seq_puts(p, " None "); 211 seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); 212 seq_printf(p, " %s", action->name); 213 for (action = action->next; action; action = action->next) 214 seq_printf(p, ", %s", action->name); 215 seq_putc(p, '\n'); 216skip: 217 spin_unlock_irqrestore(&desc->lock, flags); 218 } else if (i == NR_IRQS) { | 193 } else if (i == nr_irqs) { |
219#if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT) 220 if (tau_initialized){ 221 seq_puts(p, "TAU: "); 222 for_each_online_cpu(j) 223 seq_printf(p, "%10u ", tau_interrupts(j)); 224 seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); 225 } 226#endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/ 227 seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); | 194#if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT) 195 if (tau_initialized){ 196 seq_puts(p, "TAU: "); 197 for_each_online_cpu(j) 198 seq_printf(p, "%10u ", tau_interrupts(j)); 199 seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); 200 } 201#endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/ 202 seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); |
203 204 return 0; |
|
228 } | 205 } |
206 207 desc = irq_to_desc(i); 208 if (!desc) 209 return 0; 210 211 spin_lock_irqsave(&desc->lock, flags); 212 213 action = desc->action; 214 if (!action || !action->handler) 215 goto skip; 216 217 seq_printf(p, "%3d: ", i); 218#ifdef CONFIG_SMP 219 for_each_online_cpu(j) 220 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); 221#else 222 seq_printf(p, "%10u ", kstat_irqs(i)); 223#endif /* CONFIG_SMP */ 224 225 if (desc->chip) 226 seq_printf(p, " %s ", desc->chip->name); 227 else 228 seq_puts(p, " None "); 229 230 seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); 231 seq_printf(p, " %s", action->name); 232 233 for (action = action->next; action; action = action->next) 234 seq_printf(p, ", %s", action->name); 235 seq_putc(p, '\n'); 236 237skip: 238 spin_unlock_irqrestore(&desc->lock, flags); 239 |
|
229 return 0; 230} 231 232#ifdef CONFIG_HOTPLUG_CPU 233void fixup_irqs(cpumask_t map) 234{ | 240 return 0; 241} 242 243#ifdef CONFIG_HOTPLUG_CPU 244void fixup_irqs(cpumask_t map) 245{ |
246 struct irq_desc *desc; |
|
235 unsigned int irq; 236 static int warned; 237 238 for_each_irq(irq) { 239 cpumask_t mask; 240 | 247 unsigned int irq; 248 static int warned; 249 250 for_each_irq(irq) { 251 cpumask_t mask; 252 |
241 if (irq_desc[irq].status & IRQ_PER_CPU) | 253 desc = irq_to_desc(irq); 254 if (desc && desc->status & IRQ_PER_CPU) |
242 continue; 243 | 255 continue; 256 |
244 cpumask_and(&mask, irq_desc[irq].affinity, &map); | 257 cpumask_and(&mask, desc->affinity, &map); |
245 if (any_online_cpu(mask) == NR_CPUS) { 246 printk("Breaking affinity for irq %i\n", irq); 247 mask = map; 248 } | 258 if (any_online_cpu(mask) == NR_CPUS) { 259 printk("Breaking affinity for irq %i\n", irq); 260 mask = map; 261 } |
249 if (irq_desc[irq].chip->set_affinity) 250 irq_desc[irq].chip->set_affinity(irq, &mask); 251 else if (irq_desc[irq].action && !(warned++)) | 262 if (desc->chip->set_affinity) 263 desc->chip->set_affinity(irq, &mask); 264 else if (desc->action && !(warned++)) |
252 printk("Cannot set affinity for irq %i\n", irq); 253 } 254 255 local_irq_enable(); 256 mdelay(1); 257 local_irq_disable(); 258} 259#endif --- 10 unchanged lines hidden (view full) --- 270 irqtp = hardirq_ctx[smp_processor_id()]; 271 272 if (curtp == irqtp) { 273 /* We're already on the irq stack, just handle it */ 274 generic_handle_irq(irq); 275 return; 276 } 277 | 265 printk("Cannot set affinity for irq %i\n", irq); 266 } 267 268 local_irq_enable(); 269 mdelay(1); 270 local_irq_disable(); 271} 272#endif --- 10 unchanged lines hidden (view full) --- 283 irqtp = hardirq_ctx[smp_processor_id()]; 284 285 if (curtp == irqtp) { 286 /* We're already on the irq stack, just handle it */ 287 generic_handle_irq(irq); 288 return; 289 } 290 |
278 desc = irq_desc + irq; | 291 desc = irq_to_desc(irq); |
279 saved_sp_limit = current->thread.ksp_limit; 280 281 irqtp->task = curtp->task; 282 irqtp->flags = 0; 283 284 /* Copy the softirq bits in preempt_count so that the 285 * softirq checks work in the hardirq context. */ 286 irqtp->preempt_count = (irqtp->preempt_count & ~SOFTIRQ_MASK) | --- 35 unchanged lines hidden (view full) --- 322#endif 323} 324 325void do_IRQ(struct pt_regs *regs) 326{ 327 struct pt_regs *old_regs = set_irq_regs(regs); 328 unsigned int irq; 329 | 292 saved_sp_limit = current->thread.ksp_limit; 293 294 irqtp->task = curtp->task; 295 irqtp->flags = 0; 296 297 /* Copy the softirq bits in preempt_count so that the 298 * softirq checks work in the hardirq context. */ 299 irqtp->preempt_count = (irqtp->preempt_count & ~SOFTIRQ_MASK) | --- 35 unchanged lines hidden (view full) --- 335#endif 336} 337 338void do_IRQ(struct pt_regs *regs) 339{ 340 struct pt_regs *old_regs = set_irq_regs(regs); 341 unsigned int irq; 342 |
330 trace_irq_entry(regs); 331 | |
332 irq_enter(); 333 334 check_stack_overflow(); 335 336 irq = ppc_md.get_irq(); 337 338 if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) 339 handle_one_irq(irq); --- 7 unchanged lines hidden (view full) --- 347#ifdef CONFIG_PPC_ISERIES 348 if (firmware_has_feature(FW_FEATURE_ISERIES) && 349 get_lppaca()->int_dword.fields.decr_int) { 350 get_lppaca()->int_dword.fields.decr_int = 0; 351 /* Signal a fake decrementer interrupt */ 352 timer_interrupt(regs); 353 } 354#endif | 343 irq_enter(); 344 345 check_stack_overflow(); 346 347 irq = ppc_md.get_irq(); 348 349 if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) 350 handle_one_irq(irq); --- 7 unchanged lines hidden (view full) --- 358#ifdef CONFIG_PPC_ISERIES 359 if (firmware_has_feature(FW_FEATURE_ISERIES) && 360 get_lppaca()->int_dword.fields.decr_int) { 361 get_lppaca()->int_dword.fields.decr_int = 0; 362 /* Signal a fake decrementer interrupt */ 363 timer_interrupt(regs); 364 } 365#endif |
355 356 trace_irq_exit(regs); | |
357} 358 359void __init init_IRQ(void) 360{ 361 if (ppc_md.init_IRQ) 362 ppc_md.init_IRQ(); 363 364 exc_lvl_ctx_init(); --- 171 unchanged lines hidden (view full) --- 536 /* setup us as the host for all legacy interrupts */ 537 for (i = 1; i < NUM_ISA_INTERRUPTS; i++) { 538 irq_map[i].hwirq = i; 539 smp_wmb(); 540 irq_map[i].host = host; 541 smp_wmb(); 542 543 /* Clear norequest flags */ | 366} 367 368void __init init_IRQ(void) 369{ 370 if (ppc_md.init_IRQ) 371 ppc_md.init_IRQ(); 372 373 exc_lvl_ctx_init(); --- 171 unchanged lines hidden (view full) --- 545 /* setup us as the host for all legacy interrupts */ 546 for (i = 1; i < NUM_ISA_INTERRUPTS; i++) { 547 irq_map[i].hwirq = i; 548 smp_wmb(); 549 irq_map[i].host = host; 550 smp_wmb(); 551 552 /* Clear norequest flags */ |
544 get_irq_desc(i)->status &= ~IRQ_NOREQUEST; | 553 irq_to_desc(i)->status &= ~IRQ_NOREQUEST; |
545 546 /* Legacy flags are left to default at this point, 547 * one can then use irq_create_mapping() to 548 * explicitly change them 549 */ 550 ops->map(host, i, i); 551 } 552 break; --- 49 unchanged lines hidden (view full) --- 602 BUG_ON(count < NUM_ISA_INTERRUPTS); 603 if (count < NR_IRQS) 604 irq_virq_count = count; 605} 606 607static int irq_setup_virq(struct irq_host *host, unsigned int virq, 608 irq_hw_number_t hwirq) 609{ | 554 555 /* Legacy flags are left to default at this point, 556 * one can then use irq_create_mapping() to 557 * explicitly change them 558 */ 559 ops->map(host, i, i); 560 } 561 break; --- 49 unchanged lines hidden (view full) --- 611 BUG_ON(count < NUM_ISA_INTERRUPTS); 612 if (count < NR_IRQS) 613 irq_virq_count = count; 614} 615 616static int irq_setup_virq(struct irq_host *host, unsigned int virq, 617 irq_hw_number_t hwirq) 618{ |
619 struct irq_desc *desc; 620 621 desc = irq_to_desc_alloc_node(virq, 0); 622 if (!desc) { 623 pr_debug("irq: -> allocating desc failed\n"); 624 goto error; 625 } 626 |
|
610 /* Clear IRQ_NOREQUEST flag */ | 627 /* Clear IRQ_NOREQUEST flag */ |
611 get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | 628 desc->status &= ~IRQ_NOREQUEST; |
612 613 /* map it */ 614 smp_wmb(); 615 irq_map[virq].hwirq = hwirq; 616 smp_mb(); 617 618 if (host->ops->map(host, virq, hwirq)) { 619 pr_debug("irq: -> mapping failed, freeing\n"); | 629 630 /* map it */ 631 smp_wmb(); 632 irq_map[virq].hwirq = hwirq; 633 smp_mb(); 634 635 if (host->ops->map(host, virq, hwirq)) { 636 pr_debug("irq: -> mapping failed, freeing\n"); |
620 irq_free_virt(virq, 1); 621 return -1; | 637 goto error; |
622 } 623 624 return 0; | 638 } 639 640 return 0; |
641 642error: 643 irq_free_virt(virq, 1); 644 return -1; |
|
625} 626 627unsigned int irq_create_direct_mapping(struct irq_host *host) 628{ 629 unsigned int virq; 630 631 if (host == NULL) 632 host = irq_default_host; --- 67 unchanged lines hidden (view full) --- 700 printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n", 701 hwirq, host->of_node ? host->of_node->full_name : "null", virq); 702 703 return virq; 704} 705EXPORT_SYMBOL_GPL(irq_create_mapping); 706 707unsigned int irq_create_of_mapping(struct device_node *controller, | 645} 646 647unsigned int irq_create_direct_mapping(struct irq_host *host) 648{ 649 unsigned int virq; 650 651 if (host == NULL) 652 host = irq_default_host; --- 67 unchanged lines hidden (view full) --- 720 printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n", 721 hwirq, host->of_node ? host->of_node->full_name : "null", virq); 722 723 return virq; 724} 725EXPORT_SYMBOL_GPL(irq_create_mapping); 726 727unsigned int irq_create_of_mapping(struct device_node *controller, |
708 u32 *intspec, unsigned int intsize) | 728 const u32 *intspec, unsigned int intsize) |
709{ 710 struct irq_host *host; 711 irq_hw_number_t hwirq; 712 unsigned int type = IRQ_TYPE_NONE; 713 unsigned int virq; 714 715 if (controller == NULL) 716 host = irq_default_host; --- 16 unchanged lines hidden (view full) --- 733 734 /* Create mapping */ 735 virq = irq_create_mapping(host, hwirq); 736 if (virq == NO_IRQ) 737 return virq; 738 739 /* Set type if specified and different than the current one */ 740 if (type != IRQ_TYPE_NONE && | 729{ 730 struct irq_host *host; 731 irq_hw_number_t hwirq; 732 unsigned int type = IRQ_TYPE_NONE; 733 unsigned int virq; 734 735 if (controller == NULL) 736 host = irq_default_host; --- 16 unchanged lines hidden (view full) --- 753 754 /* Create mapping */ 755 virq = irq_create_mapping(host, hwirq); 756 if (virq == NO_IRQ) 757 return virq; 758 759 /* Set type if specified and different than the current one */ 760 if (type != IRQ_TYPE_NONE && |
741 type != (get_irq_desc(virq)->status & IRQF_TRIGGER_MASK)) | 761 type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK)) |
742 set_irq_type(virq, type); 743 return virq; 744} 745EXPORT_SYMBOL_GPL(irq_create_of_mapping); 746 747unsigned int irq_of_parse_and_map(struct device_node *dev, int index) 748{ 749 struct of_irq oirq; --- 55 unchanged lines hidden (view full) --- 805 break; 806 } 807 808 /* Destroy map */ 809 smp_mb(); 810 irq_map[virq].hwirq = host->inval_irq; 811 812 /* Set some flags */ | 762 set_irq_type(virq, type); 763 return virq; 764} 765EXPORT_SYMBOL_GPL(irq_create_of_mapping); 766 767unsigned int irq_of_parse_and_map(struct device_node *dev, int index) 768{ 769 struct of_irq oirq; --- 55 unchanged lines hidden (view full) --- 825 break; 826 } 827 828 /* Destroy map */ 829 smp_mb(); 830 irq_map[virq].hwirq = host->inval_irq; 831 832 /* Set some flags */ |
813 get_irq_desc(virq)->status |= IRQ_NOREQUEST; | 833 irq_to_desc(virq)->status |= IRQ_NOREQUEST; |
814 815 /* Free it */ 816 irq_free_virt(virq, 1); 817} 818EXPORT_SYMBOL_GPL(irq_dispose_mapping); 819 820unsigned int irq_find_mapping(struct irq_host *host, 821 irq_hw_number_t hwirq) --- 175 unchanged lines hidden (view full) --- 997 host = irq_map[i].host; 998 irq_map[i].hwirq = host->inval_irq; 999 smp_wmb(); 1000 irq_map[i].host = NULL; 1001 } 1002 spin_unlock_irqrestore(&irq_big_lock, flags); 1003} 1004 | 834 835 /* Free it */ 836 irq_free_virt(virq, 1); 837} 838EXPORT_SYMBOL_GPL(irq_dispose_mapping); 839 840unsigned int irq_find_mapping(struct irq_host *host, 841 irq_hw_number_t hwirq) --- 175 unchanged lines hidden (view full) --- 1017 host = irq_map[i].host; 1018 irq_map[i].hwirq = host->inval_irq; 1019 smp_wmb(); 1020 irq_map[i].host = NULL; 1021 } 1022 spin_unlock_irqrestore(&irq_big_lock, flags); 1023} 1024 |
1005void irq_early_init(void) | 1025int arch_early_irq_init(void) |
1006{ | 1026{ |
1007 unsigned int i; | 1027 struct irq_desc *desc; 1028 int i; |
1008 | 1029 |
1009 for (i = 0; i < NR_IRQS; i++) 1010 get_irq_desc(i)->status |= IRQ_NOREQUEST; | 1030 for (i = 0; i < NR_IRQS; i++) { 1031 desc = irq_to_desc(i); 1032 if (desc) 1033 desc->status |= IRQ_NOREQUEST; 1034 } 1035 1036 return 0; |
1011} 1012 | 1037} 1038 |
1039int arch_init_chip_data(struct irq_desc *desc, int node) 1040{ 1041 desc->status |= IRQ_NOREQUEST; 1042 return 0; 1043} 1044 |
|
1013/* We need to create the radix trees late */ 1014static int irq_late_init(void) 1015{ 1016 struct irq_host *h; 1017 unsigned int i; 1018 1019 /* 1020 * No mutual exclusion with respect to accessors of the tree is needed --- 43 unchanged lines hidden (view full) --- 1064 struct irq_desc *desc; 1065 const char *p; 1066 char none[] = "none"; 1067 int i; 1068 1069 seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", 1070 "chip name", "host name"); 1071 | 1045/* We need to create the radix trees late */ 1046static int irq_late_init(void) 1047{ 1048 struct irq_host *h; 1049 unsigned int i; 1050 1051 /* 1052 * No mutual exclusion with respect to accessors of the tree is needed --- 43 unchanged lines hidden (view full) --- 1096 struct irq_desc *desc; 1097 const char *p; 1098 char none[] = "none"; 1099 int i; 1100 1101 seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", 1102 "chip name", "host name"); 1103 |
1072 for (i = 1; i < NR_IRQS; i++) { 1073 desc = get_irq_desc(i); | 1104 for (i = 1; i < nr_irqs; i++) { 1105 desc = irq_to_desc(i); 1106 if (!desc) 1107 continue; 1108 |
1074 spin_lock_irqsave(&desc->lock, flags); 1075 1076 if (desc->action && desc->action->handler) { 1077 seq_printf(m, "%5d ", i); 1078 seq_printf(m, "0x%05lx ", virq_to_hw(i)); 1079 | 1109 spin_lock_irqsave(&desc->lock, flags); 1110 1111 if (desc->action && desc->action->handler) { 1112 seq_printf(m, "%5d ", i); 1113 seq_printf(m, "0x%05lx ", virq_to_hw(i)); 1114 |
1080 if (desc->chip && desc->chip->typename) 1081 p = desc->chip->typename; | 1115 if (desc->chip && desc->chip->name) 1116 p = desc->chip->name; |
1082 else 1083 p = none; 1084 seq_printf(m, "%-15s ", p); 1085 1086 if (irq_map[i].host && irq_map[i].host->of_node) 1087 p = irq_map[i].host->of_node->full_name; 1088 else 1089 p = none; --- 41 unchanged lines hidden --- | 1117 else 1118 p = none; 1119 seq_printf(m, "%-15s ", p); 1120 1121 if (irq_map[i].host && irq_map[i].host->of_node) 1122 p = irq_map[i].host->of_node->full_name; 1123 else 1124 p = none; --- 41 unchanged lines hidden --- |