86 #include <linux/kernel.h>
87 #include <linux/list.h>
88 #include <linux/pci.h>
89 #include <linux/slab.h>
91 #include <linux/string.h>
94 #include <asm/delay.h>
95 #include <asm/hw_irq.h>
98 #include <asm/machvec.h>
99 #include <asm/processor.h>
100 #include <asm/ptrace.h>
102 #undef DEBUG_INTERRUPT_ROUTING
104 #ifdef DEBUG_INTERRUPT_ROUTING
105 #define DBG(fmt...) printk(fmt)
119 static struct iosapic {
121 unsigned int gsi_base;
122 unsigned short num_rte;
128 } iosapic_lists[NR_IOSAPICS];
137 static struct iosapic_intr_info {
144 unsigned char dmode : 3;
153 iosapic_write(
struct iosapic *iosapic,
unsigned int reg,
u32 val)
158 __iosapic_write(iosapic->addr, reg, val);
159 spin_unlock_irqrestore(&iosapic->lock, flags);
166 find_iosapic (
unsigned int gsi)
170 for (i = 0; i < NR_IOSAPICS; i++) {
171 if ((
unsigned) (gsi - iosapic_lists[i].gsi_base) <
172 iosapic_lists[i].num_rte)
179 static inline int __gsi_to_irq(
unsigned int gsi)
182 struct iosapic_intr_info *
info;
185 for (irq = 0; irq <
NR_IRQS; irq++) {
186 info = &iosapic_intr_info[irq];
201 irq = __gsi_to_irq(gsi);
202 spin_unlock_irqrestore(&iosapic_lock, flags);
206 static struct iosapic_rte_info *find_rte(
unsigned int irq,
unsigned int gsi)
217 set_rte (
unsigned int gsi,
unsigned int irq,
unsigned int dest,
int mask)
226 DBG(
KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
228 rte = find_rte(irq, gsi);
233 pol = iosapic_intr_info[irq].polarity;
234 trigger = iosapic_intr_info[irq].trigger;
235 dmode = iosapic_intr_info[irq].dmode;
254 iosapic_intr_info[irq].low32 = low32;
255 iosapic_intr_info[irq].dest =
dest;
269 struct iosapic_intr_info *
info;
274 for (irq = 0; irq <
NR_IRQS; irq++) {
275 info = &iosapic_intr_info[irq];
276 vec = irq_to_vector(irq);
282 iosapic_eoi(rte->
iosapic->addr, vec);
291 unsigned int irq = data->
irq;
296 if (!iosapic_intr_info[irq].
count)
310 unsigned int irq = data->
irq;
315 if (!iosapic_intr_info[irq].count)
327 iosapic_set_affinity(
struct irq_data *data,
const struct cpumask *mask,
331 unsigned int irq = data->
irq;
336 struct iosapic *iosapic;
341 if (cpu >= nr_cpu_ids)
344 if (irq_prepare_move(irq, cpu))
349 if (!iosapic_intr_info[irq].count)
365 low32 |= irq_to_vector(irq);
367 iosapic_intr_info[irq].low32 = low32;
368 iosapic_intr_info[irq].dest =
dest;
385 iosapic_startup_level_irq (
struct irq_data *data)
392 iosapic_unmask_level_irq (
struct irq_data *data)
394 unsigned int irq = data->
irq;
397 int do_unmask_irq = 0;
399 irq_complete_move(irq);
400 if (
unlikely(irqd_is_setaffinity_pending(data))) {
407 iosapic_eoi(rte->iosapic->
addr, vec);
415 #define iosapic_shutdown_level_irq mask_irq
416 #define iosapic_enable_level_irq unmask_irq
417 #define iosapic_disable_level_irq mask_irq
418 #define iosapic_ack_level_irq nop
420 static struct irq_chip irq_type_iosapic_level = {
421 .name =
"IO-SAPIC-level",
422 .irq_startup = iosapic_startup_level_irq,
427 .irq_mask = mask_irq,
428 .irq_unmask = iosapic_unmask_level_irq,
429 .irq_set_affinity = iosapic_set_affinity
437 iosapic_startup_edge_irq (
struct irq_data *data)
449 iosapic_ack_edge_irq (
struct irq_data *data)
451 irq_complete_move(data->
irq);
455 #define iosapic_enable_edge_irq unmask_irq
456 #define iosapic_disable_edge_irq nop
458 static struct irq_chip irq_type_iosapic_edge = {
459 .name =
"IO-SAPIC-edge",
460 .irq_startup = iosapic_startup_edge_irq,
464 .irq_ack = iosapic_ack_edge_irq,
465 .irq_mask = mask_irq,
466 .irq_unmask = unmask_irq,
467 .irq_set_affinity = iosapic_set_affinity
485 static int iosapic_find_sharable_irq(
unsigned long trigger,
unsigned long pol)
487 int i, irq = -
ENOSPC, min_count = -1;
488 struct iosapic_intr_info *
info;
497 for (i = 0; i <
NR_IRQS; i++) {
498 info = &iosapic_intr_info[
i];
499 if (info->trigger == trigger && info->polarity == pol &&
503 if (min_count == -1 || info->count < min_count) {
505 min_count = info->count;
517 iosapic_reassign_vector (
int irq)
521 if (iosapic_intr_info[irq].count) {
524 panic(
"%s: out of interrupt vectors!\n", __func__);
526 irq_to_vector(irq), irq_to_vector(new_irq));
527 memcpy(&iosapic_intr_info[new_irq], &iosapic_intr_info[irq],
528 sizeof(
struct iosapic_intr_info));
529 INIT_LIST_HEAD(&iosapic_intr_info[new_irq].rtes);
530 list_move(iosapic_intr_info[irq].rtes.next,
531 &iosapic_intr_info[new_irq].rtes);
532 memset(&iosapic_intr_info[irq], 0,
533 sizeof(
struct iosapic_intr_info));
535 INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
539 static inline int irq_is_shared (
int irq)
541 return (iosapic_intr_info[irq].count > 1);
548 return &irq_type_iosapic_edge;
550 return &irq_type_iosapic_level;
554 register_intr (
unsigned int gsi,
int irq,
unsigned char delivery,
555 unsigned long polarity,
unsigned long trigger)
561 index = find_iosapic(gsi);
568 rte = find_rte(irq, gsi);
581 iosapic_intr_info[irq].count++;
582 iosapic_lists[
index].rtes_inuse++;
585 struct iosapic_intr_info *info = &iosapic_intr_info[irq];
586 if (info->count > 0 &&
587 (info->trigger != trigger || info->polarity != polarity)){
589 "%s: cannot override the interrupt\n",
594 iosapic_intr_info[irq].count++;
595 iosapic_lists[
index].rtes_inuse++;
598 iosapic_intr_info[irq].polarity =
polarity;
599 iosapic_intr_info[irq].dmode = delivery;
600 iosapic_intr_info[irq].trigger =
trigger;
602 irq_type = iosapic_get_irq_chip(trigger);
604 chip = irq_get_chip(irq);
605 if (irq_type != NULL && chip != irq_type) {
608 "%s: changing vector %d from %s to %s\n",
609 __func__, irq_to_vector(irq),
613 __irq_set_chip_handler_name_locked(irq, chip, trigger ==
IOSAPIC_EDGE ?
620 get_target_cpu (
unsigned int gsi,
int irq)
631 if (iosapic_intr_info[irq].count)
632 return iosapic_intr_info[irq].dest;
655 int num_cpus,
cpu_index, iosapic_index, numa_cpu, i = 0;
658 iosapic_index = find_iosapic(gsi);
659 if (iosapic_index < 0 ||
661 goto skip_numa_setup;
671 goto skip_numa_setup;
674 cpu_index = irq % num_cpus;
680 if (numa_cpu < nr_cpu_ids)
691 if (++cpu >= nr_cpu_ids)
701 static inline unsigned char choose_dmode(
void)
717 unsigned long polarity,
unsigned long trigger)
719 int irq, mask = 1,
err;
733 irq = __gsi_to_irq(gsi);
735 rte = find_rte(irq, gsi);
736 if(iosapic_intr_info[irq].count == 0) {
738 dynamic_irq_init(irq);
741 goto unlock_iosapic_lock;
748 irq = iosapic_find_sharable_irq(trigger, polarity);
750 goto unlock_iosapic_lock;
755 dest = get_target_cpu(gsi, irq);
756 dmode = choose_dmode();
757 err = register_intr(gsi, irq, dmode, polarity, trigger);
761 goto unlock_iosapic_lock;
768 low32 = iosapic_intr_info[irq].low32;
771 set_rte(gsi, irq, dest, mask);
780 spin_unlock_irqrestore(&iosapic_lock, flags);
808 if ((rte = find_rte(irq, gsi)) == NULL) {
824 iosapic_intr_info[irq].count--;
825 index = find_iosapic(gsi);
826 iosapic_lists[
index].rtes_inuse--;
827 WARN_ON(iosapic_lists[index].rtes_inuse < 0);
829 trigger = iosapic_intr_info[irq].trigger;
830 polarity = iosapic_intr_info[irq].polarity;
831 dest = iosapic_intr_info[irq].dest;
833 "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",
838 if (iosapic_intr_info[irq].count == 0) {
844 iosapic_intr_info[irq].dest = 0;
845 iosapic_intr_info[irq].dmode = 0;
846 iosapic_intr_info[irq].polarity = 0;
847 iosapic_intr_info[irq].trigger = 0;
854 spin_unlock_irqrestore(&iosapic_lock, flags);
862 int iosapic_vector,
u16 eid,
u16 id,
863 unsigned long polarity,
unsigned long trigger)
865 static const char *
const name[] = {
"unknown",
"PMI",
"INIT",
"CPEI"};
866 unsigned char delivery;
867 int irq,
vector, mask = 0;
868 unsigned int dest = ((
id << 8) | eid) & 0xffff;
871 case ACPI_INTERRUPT_PMI:
872 irq = vector = iosapic_vector;
878 iosapic_reassign_vector(irq);
881 case ACPI_INTERRUPT_INIT:
884 panic(
"%s: out of interrupt vectors!\n", __func__);
885 vector = irq_to_vector(irq);
888 case ACPI_INTERRUPT_CPEI:
900 register_intr(gsi, irq, delivery, polarity, trigger);
903 "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)"
905 int_type <
ARRAY_SIZE(name) ? name[int_type] :
"unknown",
906 int_type, gsi, (trigger ==
IOSAPIC_EDGE ?
"edge" :
"level"),
910 set_rte(gsi, irq, dest, mask);
919 unsigned long polarity,
920 unsigned long trigger)
928 dmode = choose_dmode();
929 register_intr(gsi, irq, dmode, polarity, trigger);
931 DBG(
"ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
932 isa_irq, gsi, trigger ==
IOSAPIC_EDGE ?
"edge" :
"level",
936 set_rte(gsi, irq, dest, 1);
948 "%s: Disabling PC-AT compatible 8259 interrupts\n",
960 for (irq = 0; irq <
NR_IRQS; ++irq) {
963 INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
965 iosapic_intr_info[irq].count = 0;
968 pcat_compat = system_pcat_compat;
970 iosapic_pcat_compat_init();
978 for (index = 0; index < NR_IOSAPICS; index++)
979 if (!iosapic_lists[index].
addr)
987 iosapic_free (
int index)
989 memset(&iosapic_lists[index], 0,
sizeof(iosapic_lists[0]));
993 iosapic_check_gsi_range (
unsigned int gsi_base,
unsigned int ver)
996 unsigned int gsi_end,
base,
end;
999 gsi_end = gsi_base + ((ver >> 16) & 0xff);
1000 for (index = 0; index < NR_IOSAPICS; index++) {
1001 if (!iosapic_lists[index].
addr)
1007 if (gsi_end < base ||
end < gsi_base)
1019 unsigned int isa_irq,
ver;
1021 unsigned long flags;
1024 index = find_iosapic(gsi_base);
1026 spin_unlock_irqrestore(&iosapic_lock, flags);
1032 spin_unlock_irqrestore(&iosapic_lock, flags);
1035 ver = iosapic_version(addr);
1036 if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
1038 spin_unlock_irqrestore(&iosapic_lock, flags);
1047 num_rte = ((ver >> 16) & 0xff) + 1;
1049 index = iosapic_alloc();
1051 iosapic_lists[
index].gsi_base = gsi_base;
1052 iosapic_lists[
index].num_rte = num_rte;
1057 spin_unlock_irqrestore(&iosapic_lock, flags);
1059 if ((gsi_base == 0) && pcat_compat) {
1065 for (isa_irq = 0; isa_irq < 16; ++isa_irq)
1073 #ifdef CONFIG_HOTPLUG
1078 unsigned long flags;
1081 index = find_iosapic(gsi_base);
1084 __func__, gsi_base);
1088 if (iosapic_lists[index].rtes_inuse) {
1091 __func__, gsi_base);
1096 iosapic_free(index);
1098 spin_unlock_irqrestore(&iosapic_lock, flags);
1105 map_iosapic_to_node(
unsigned int gsi_base,
int node)
1109 index = find_iosapic(gsi_base);
1112 __func__, gsi_base);