Commit 4bbdec7a authored by Yasuaki Ishimatsu's avatar Yasuaki Ishimatsu Committed by Tony Luck

[IA64] Fix invalid irq vector assumption for iosapic

Many of IOSAPIC codes depends on the flollowing assumptions, but these
would become invalid when multiple vector domain will be supported in
the future.

  - 1:1 mapping between IRQ and vector
  - IRQ == vector

To fix those invalid assumptions, this patch changes iosapic_intr_info[]
to be indexed by irq number instead of vector.
Signed-off-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarYasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent eb21ab24
...@@ -147,7 +147,7 @@ static struct iosapic_intr_info { ...@@ -147,7 +147,7 @@ static struct iosapic_intr_info {
unsigned char polarity: 1; /* interrupt polarity unsigned char polarity: 1; /* interrupt polarity
* (see iosapic.h) */ * (see iosapic.h) */
unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ unsigned char trigger : 1; /* trigger mode (see iosapic.h) */
} iosapic_intr_info[IA64_NUM_VECTORS]; } iosapic_intr_info[NR_IRQS];
static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */
...@@ -181,17 +181,18 @@ find_iosapic (unsigned int gsi) ...@@ -181,17 +181,18 @@ find_iosapic (unsigned int gsi)
return -1; return -1;
} }
static inline int static inline int __gsi_to_irq(unsigned int gsi)
_gsi_to_vector (unsigned int gsi)
{ {
int irq;
struct iosapic_intr_info *info; struct iosapic_intr_info *info;
struct iosapic_rte_info *rte; struct iosapic_rte_info *rte;
for (info = iosapic_intr_info; info < for (irq = 0; irq < NR_IRQS; irq++) {
iosapic_intr_info + IA64_NUM_VECTORS; ++info) info = &iosapic_intr_info[irq];
list_for_each_entry(rte, &info->rtes, rte_list) list_for_each_entry(rte, &info->rtes, rte_list)
if (rte->iosapic->gsi_base + rte->rte_index == gsi) if (rte->iosapic->gsi_base + rte->rte_index == gsi)
return info - iosapic_intr_info; return irq;
}
return -1; return -1;
} }
...@@ -202,7 +203,10 @@ _gsi_to_vector (unsigned int gsi) ...@@ -202,7 +203,10 @@ _gsi_to_vector (unsigned int gsi)
inline int inline int
gsi_to_vector (unsigned int gsi) gsi_to_vector (unsigned int gsi)
{ {
return _gsi_to_vector(gsi); int irq = __gsi_to_irq(gsi);
if (irq < 0)
return -1;
return irq_to_vector(irq);
} }
int int
...@@ -210,62 +214,48 @@ gsi_to_irq (unsigned int gsi) ...@@ -210,62 +214,48 @@ gsi_to_irq (unsigned int gsi)
{ {
unsigned long flags; unsigned long flags;
int irq; int irq;
/*
* XXX fix me: this assumes an identity mapping between IA-64 vector
* and Linux irq numbers...
*/
spin_lock_irqsave(&iosapic_lock, flags); spin_lock_irqsave(&iosapic_lock, flags);
irq = _gsi_to_vector(gsi); irq = __gsi_to_irq(gsi);
spin_unlock_irqrestore(&iosapic_lock, flags); spin_unlock_irqrestore(&iosapic_lock, flags);
return irq; return irq;
} }
static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, static struct iosapic_rte_info *find_rte(unsigned int irq, unsigned int gsi)
unsigned int vec)
{ {
struct iosapic_rte_info *rte; struct iosapic_rte_info *rte;
list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
if (rte->iosapic->gsi_base + rte->rte_index == gsi) if (rte->iosapic->gsi_base + rte->rte_index == gsi)
return rte; return rte;
return NULL; return NULL;
} }
static void static void
set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) set_rte (unsigned int gsi, unsigned int irq, unsigned int dest, int mask)
{ {
unsigned long pol, trigger, dmode; unsigned long pol, trigger, dmode;
u32 low32, high32; u32 low32, high32;
int rte_index; int rte_index;
char redir; char redir;
struct iosapic_rte_info *rte; struct iosapic_rte_info *rte;
ia64_vector vector = irq_to_vector(irq);
DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest); DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
rte = gsi_vector_to_rte(gsi, vector); rte = find_rte(irq, gsi);
if (!rte) if (!rte)
return; /* not an IOSAPIC interrupt */ return; /* not an IOSAPIC interrupt */
rte_index = rte->rte_index; rte_index = rte->rte_index;
pol = iosapic_intr_info[vector].polarity; pol = iosapic_intr_info[irq].polarity;
trigger = iosapic_intr_info[vector].trigger; trigger = iosapic_intr_info[irq].trigger;
dmode = iosapic_intr_info[vector].dmode; dmode = iosapic_intr_info[irq].dmode;
redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0; redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
{ set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
unsigned int irq;
for (irq = 0; irq < NR_IRQS; ++irq)
if (irq_to_vector(irq) == vector) {
set_irq_affinity_info(irq,
(int)(dest & 0xffff),
redir);
break;
}
}
#endif #endif
low32 = ((pol << IOSAPIC_POLARITY_SHIFT) | low32 = ((pol << IOSAPIC_POLARITY_SHIFT) |
...@@ -279,8 +269,8 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) ...@@ -279,8 +269,8 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask)
iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
iosapic_intr_info[vector].low32 = low32; iosapic_intr_info[irq].low32 = low32;
iosapic_intr_info[vector].dest = dest; iosapic_intr_info[irq].dest = dest;
} }
static void static void
...@@ -296,9 +286,12 @@ kexec_disable_iosapic(void) ...@@ -296,9 +286,12 @@ kexec_disable_iosapic(void)
{ {
struct iosapic_intr_info *info; struct iosapic_intr_info *info;
struct iosapic_rte_info *rte; struct iosapic_rte_info *rte;
u8 vec = 0; ia64_vector vec;
for (info = iosapic_intr_info; info < int irq;
iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) {
for (irq = 0; irq < NR_IRQS; irq++) {
info = &iosapic_intr_info[irq];
vec = irq_to_vector(irq);
list_for_each_entry(rte, &info->rtes, list_for_each_entry(rte, &info->rtes,
rte_list) { rte_list) {
iosapic_write(rte->iosapic, iosapic_write(rte->iosapic,
...@@ -315,15 +308,14 @@ mask_irq (unsigned int irq) ...@@ -315,15 +308,14 @@ mask_irq (unsigned int irq)
{ {
u32 low32; u32 low32;
int rte_index; int rte_index;
ia64_vector vec = irq_to_vector(irq);
struct iosapic_rte_info *rte; struct iosapic_rte_info *rte;
if (list_empty(&iosapic_intr_info[vec].rtes)) if (list_empty(&iosapic_intr_info[irq].rtes))
return; /* not an IOSAPIC interrupt! */ return; /* not an IOSAPIC interrupt! */
/* set only the mask bit */ /* set only the mask bit */
low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; low32 = iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
rte_index = rte->rte_index; rte_index = rte->rte_index;
iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
} }
...@@ -334,14 +326,13 @@ unmask_irq (unsigned int irq) ...@@ -334,14 +326,13 @@ unmask_irq (unsigned int irq)
{ {
u32 low32; u32 low32;
int rte_index; int rte_index;
ia64_vector vec = irq_to_vector(irq);
struct iosapic_rte_info *rte; struct iosapic_rte_info *rte;
if (list_empty(&iosapic_intr_info[vec].rtes)) if (list_empty(&iosapic_intr_info[irq].rtes))
return; /* not an IOSAPIC interrupt! */ return; /* not an IOSAPIC interrupt! */
low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; low32 = iosapic_intr_info[irq].low32 &= ~IOSAPIC_MASK;
list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
rte_index = rte->rte_index; rte_index = rte->rte_index;
iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
} }
...@@ -355,19 +346,17 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) ...@@ -355,19 +346,17 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
u32 high32, low32; u32 high32, low32;
int dest, rte_index; int dest, rte_index;
int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
ia64_vector vec;
struct iosapic_rte_info *rte; struct iosapic_rte_info *rte;
struct iosapic *iosapic; struct iosapic *iosapic;
irq &= (~IA64_IRQ_REDIRECTED); irq &= (~IA64_IRQ_REDIRECTED);
vec = irq_to_vector(irq);
if (cpus_empty(mask)) if (cpus_empty(mask))
return; return;
dest = cpu_physical_id(first_cpu(mask)); dest = cpu_physical_id(first_cpu(mask));
if (list_empty(&iosapic_intr_info[vec].rtes)) if (list_empty(&iosapic_intr_info[irq].rtes))
return; /* not an IOSAPIC interrupt */ return; /* not an IOSAPIC interrupt */
set_irq_affinity_info(irq, dest, redir); set_irq_affinity_info(irq, dest, redir);
...@@ -375,7 +364,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) ...@@ -375,7 +364,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
/* dest contains both id and eid */ /* dest contains both id and eid */
high32 = dest << IOSAPIC_DEST_SHIFT; high32 = dest << IOSAPIC_DEST_SHIFT;
low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); low32 = iosapic_intr_info[irq].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
if (redir) if (redir)
/* change delivery mode to lowest priority */ /* change delivery mode to lowest priority */
low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
...@@ -383,9 +372,9 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) ...@@ -383,9 +372,9 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
/* change delivery mode to fixed */ /* change delivery mode to fixed */
low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
iosapic_intr_info[vec].low32 = low32; iosapic_intr_info[irq].low32 = low32;
iosapic_intr_info[vec].dest = dest; iosapic_intr_info[irq].dest = dest;
list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
iosapic = rte->iosapic; iosapic = rte->iosapic;
rte_index = rte->rte_index; rte_index = rte->rte_index;
iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
...@@ -412,7 +401,7 @@ iosapic_end_level_irq (unsigned int irq) ...@@ -412,7 +401,7 @@ iosapic_end_level_irq (unsigned int irq)
struct iosapic_rte_info *rte; struct iosapic_rte_info *rte;
move_native_irq(irq); move_native_irq(irq);
list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
iosapic_eoi(rte->iosapic->addr, vec); iosapic_eoi(rte->iosapic->addr, vec);
} }
...@@ -498,10 +487,9 @@ iosapic_version (char __iomem *addr) ...@@ -498,10 +487,9 @@ iosapic_version (char __iomem *addr)
return __iosapic_read(addr, IOSAPIC_VERSION); return __iosapic_read(addr, IOSAPIC_VERSION);
} }
static int iosapic_find_sharable_vector (unsigned long trigger, static int iosapic_find_sharable_irq(unsigned long trigger, unsigned long pol)
unsigned long pol)
{ {
int i, vector = -ENOSPC, min_count = -1; int i, irq = -ENOSPC, min_count = -1;
struct iosapic_intr_info *info; struct iosapic_intr_info *info;
/* /*
...@@ -511,19 +499,18 @@ static int iosapic_find_sharable_vector (unsigned long trigger, ...@@ -511,19 +499,18 @@ static int iosapic_find_sharable_vector (unsigned long trigger,
if (trigger == IOSAPIC_EDGE) if (trigger == IOSAPIC_EDGE)
return -EINVAL; return -EINVAL;
for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { for (i = 0; i <= NR_IRQS; i++) {
info = &iosapic_intr_info[i]; info = &iosapic_intr_info[i];
if (info->trigger == trigger && info->polarity == pol && if (info->trigger == trigger && info->polarity == pol &&
(info->dmode == IOSAPIC_FIXED || info->dmode == (info->dmode == IOSAPIC_FIXED || info->dmode ==
IOSAPIC_LOWEST_PRIORITY)) { IOSAPIC_LOWEST_PRIORITY)) {
if (min_count == -1 || info->count < min_count) { if (min_count == -1 || info->count < min_count) {
vector = i; irq = i;
min_count = info->count; min_count = info->count;
} }
} }
} }
return irq;
return vector;
} }
/* /*
...@@ -531,26 +518,25 @@ static int iosapic_find_sharable_vector (unsigned long trigger, ...@@ -531,26 +518,25 @@ static int iosapic_find_sharable_vector (unsigned long trigger,
* assign a new vector for the other and make the vector available * assign a new vector for the other and make the vector available
*/ */
static void __init static void __init
iosapic_reassign_vector (int vector) iosapic_reassign_vector (int irq)
{ {
int irq, new_vector; int new_irq;
if (!list_empty(&iosapic_intr_info[vector].rtes)) { if (!list_empty(&iosapic_intr_info[irq].rtes)) {
irq = create_irq(); new_irq = create_irq();
if (irq < 0) if (new_irq < 0)
panic("%s: out of interrupt vectors!\n", __FUNCTION__); panic("%s: out of interrupt vectors!\n", __FUNCTION__);
new_vector = irq_to_vector(irq);
printk(KERN_INFO "Reassigning vector %d to %d\n", printk(KERN_INFO "Reassigning vector %d to %d\n",
vector, new_vector); irq_to_vector(irq), irq_to_vector(new_irq));
memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], memcpy(&iosapic_intr_info[new_irq], &iosapic_intr_info[irq],
sizeof(struct iosapic_intr_info)); sizeof(struct iosapic_intr_info));
INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes); INIT_LIST_HEAD(&iosapic_intr_info[new_irq].rtes);
list_move(iosapic_intr_info[vector].rtes.next, list_move(iosapic_intr_info[irq].rtes.next,
&iosapic_intr_info[new_vector].rtes); &iosapic_intr_info[new_irq].rtes);
memset(&iosapic_intr_info[vector], 0, memset(&iosapic_intr_info[irq], 0,
sizeof(struct iosapic_intr_info)); sizeof(struct iosapic_intr_info));
iosapic_intr_info[vector].low32 = IOSAPIC_MASK; iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
} }
} }
...@@ -595,13 +581,13 @@ static void iosapic_free_rte (struct iosapic_rte_info *rte) ...@@ -595,13 +581,13 @@ static void iosapic_free_rte (struct iosapic_rte_info *rte)
kfree(rte); kfree(rte);
} }
static inline int vector_is_shared (int vector) static inline int irq_is_shared (int irq)
{ {
return (iosapic_intr_info[vector].count > 1); return (iosapic_intr_info[irq].count > 1);
} }
static int static int
register_intr (unsigned int gsi, int vector, unsigned char delivery, register_intr (unsigned int gsi, int irq, unsigned char delivery,
unsigned long polarity, unsigned long trigger) unsigned long polarity, unsigned long trigger)
{ {
irq_desc_t *idesc; irq_desc_t *idesc;
...@@ -616,7 +602,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, ...@@ -616,7 +602,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
return -ENODEV; return -ENODEV;
} }
rte = gsi_vector_to_rte(gsi, vector); rte = find_rte(irq, gsi);
if (!rte) { if (!rte) {
rte = iosapic_alloc_rte(); rte = iosapic_alloc_rte();
if (!rte) { if (!rte) {
...@@ -628,12 +614,12 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, ...@@ -628,12 +614,12 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
rte->iosapic = &iosapic_lists[index]; rte->iosapic = &iosapic_lists[index];
rte->rte_index = gsi - rte->iosapic->gsi_base; rte->rte_index = gsi - rte->iosapic->gsi_base;
rte->refcnt++; rte->refcnt++;
list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes); list_add_tail(&rte->rte_list, &iosapic_intr_info[irq].rtes);
iosapic_intr_info[vector].count++; iosapic_intr_info[irq].count++;
iosapic_lists[index].rtes_inuse++; iosapic_lists[index].rtes_inuse++;
} }
else if (vector_is_shared(vector)) { else if (irq_is_shared(irq)) {
struct iosapic_intr_info *info = &iosapic_intr_info[vector]; struct iosapic_intr_info *info = &iosapic_intr_info[irq];
if (info->trigger != trigger || info->polarity != polarity) { if (info->trigger != trigger || info->polarity != polarity) {
printk (KERN_WARNING printk (KERN_WARNING
"%s: cannot override the interrupt\n", "%s: cannot override the interrupt\n",
...@@ -642,21 +628,21 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, ...@@ -642,21 +628,21 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
} }
} }
iosapic_intr_info[vector].polarity = polarity; iosapic_intr_info[irq].polarity = polarity;
iosapic_intr_info[vector].dmode = delivery; iosapic_intr_info[irq].dmode = delivery;
iosapic_intr_info[vector].trigger = trigger; iosapic_intr_info[irq].trigger = trigger;
if (trigger == IOSAPIC_EDGE) if (trigger == IOSAPIC_EDGE)
irq_type = &irq_type_iosapic_edge; irq_type = &irq_type_iosapic_edge;
else else
irq_type = &irq_type_iosapic_level; irq_type = &irq_type_iosapic_level;
idesc = irq_desc + vector; idesc = irq_desc + irq;
if (idesc->chip != irq_type) { if (idesc->chip != irq_type) {
if (idesc->chip != &no_irq_type) if (idesc->chip != &no_irq_type)
printk(KERN_WARNING printk(KERN_WARNING
"%s: changing vector %d from %s to %s\n", "%s: changing vector %d from %s to %s\n",
__FUNCTION__, vector, __FUNCTION__, irq_to_vector(irq),
idesc->chip->name, irq_type->name); idesc->chip->name, irq_type->name);
idesc->chip = irq_type; idesc->chip = irq_type;
} }
...@@ -664,7 +650,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, ...@@ -664,7 +650,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
} }
static unsigned int static unsigned int
get_target_cpu (unsigned int gsi, int vector) get_target_cpu (unsigned int gsi, int irq)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static int cpu = -1; static int cpu = -1;
...@@ -674,8 +660,8 @@ get_target_cpu (unsigned int gsi, int vector) ...@@ -674,8 +660,8 @@ get_target_cpu (unsigned int gsi, int vector)
* In case of vector shared by multiple RTEs, all RTEs that * In case of vector shared by multiple RTEs, all RTEs that
* share the vector need to use the same destination CPU. * share the vector need to use the same destination CPU.
*/ */
if (!list_empty(&iosapic_intr_info[vector].rtes)) if (!list_empty(&iosapic_intr_info[irq].rtes))
return iosapic_intr_info[vector].dest; return iosapic_intr_info[irq].dest;
/* /*
* If the platform supports redirection via XTP, let it * If the platform supports redirection via XTP, let it
...@@ -692,7 +678,7 @@ get_target_cpu (unsigned int gsi, int vector) ...@@ -692,7 +678,7 @@ get_target_cpu (unsigned int gsi, int vector)
return cpu_physical_id(smp_processor_id()); return cpu_physical_id(smp_processor_id());
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
if (cpe_vector > 0 && vector == IA64_CPEP_VECTOR) if (cpe_vector > 0 && irq_to_vector(irq) == IA64_CPEP_VECTOR)
return get_cpei_target_cpu(); return get_cpei_target_cpu();
#endif #endif
...@@ -718,8 +704,8 @@ get_target_cpu (unsigned int gsi, int vector) ...@@ -718,8 +704,8 @@ get_target_cpu (unsigned int gsi, int vector)
if (!num_cpus) if (!num_cpus)
goto skip_numa_setup; goto skip_numa_setup;
/* Use vector assignment to distribute across cpus in node */ /* Use irq assignment to distribute across cpus in node */
cpu_index = vector % num_cpus; cpu_index = irq % num_cpus;
for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++)
numa_cpu = next_cpu(numa_cpu, cpu_mask); numa_cpu = next_cpu(numa_cpu, cpu_mask);
...@@ -754,7 +740,7 @@ int ...@@ -754,7 +740,7 @@ int
iosapic_register_intr (unsigned int gsi, iosapic_register_intr (unsigned int gsi,
unsigned long polarity, unsigned long trigger) unsigned long polarity, unsigned long trigger)
{ {
int irq, vector, mask = 1, err; int irq, mask = 1, err;
unsigned int dest; unsigned int dest;
unsigned long flags; unsigned long flags;
struct iosapic_rte_info *rte; struct iosapic_rte_info *rte;
...@@ -766,9 +752,9 @@ iosapic_register_intr (unsigned int gsi, ...@@ -766,9 +752,9 @@ iosapic_register_intr (unsigned int gsi,
* don't touch the RTE. * don't touch the RTE.
*/ */
spin_lock_irqsave(&iosapic_lock, flags); spin_lock_irqsave(&iosapic_lock, flags);
vector = gsi_to_vector(gsi); irq = __gsi_to_irq(gsi);
if (vector > 0) { if (irq > 0) {
rte = gsi_vector_to_rte(gsi, vector); rte = find_rte(irq, gsi);
rte->refcnt++; rte->refcnt++;
goto unlock_iosapic_lock; goto unlock_iosapic_lock;
} }
...@@ -776,18 +762,17 @@ iosapic_register_intr (unsigned int gsi, ...@@ -776,18 +762,17 @@ iosapic_register_intr (unsigned int gsi,
/* If vector is running out, we try to find a sharable vector */ /* If vector is running out, we try to find a sharable vector */
irq = create_irq(); irq = create_irq();
if (irq < 0) { if (irq < 0) {
vector = iosapic_find_sharable_vector(trigger, polarity); irq = iosapic_find_sharable_irq(trigger, polarity);
if (vector < 0) if (irq < 0)
goto unlock_iosapic_lock; goto unlock_iosapic_lock;
} else }
vector = irq_to_vector(irq);
spin_lock(&irq_desc[vector].lock); spin_lock(&irq_desc[irq].lock);
dest = get_target_cpu(gsi, vector); dest = get_target_cpu(gsi, irq);
err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, err = register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY,
polarity, trigger); polarity, trigger);
if (err < 0) { if (err < 0) {
vector = err; irq = err;
goto unlock_all; goto unlock_all;
} }
...@@ -795,27 +780,27 @@ iosapic_register_intr (unsigned int gsi, ...@@ -795,27 +780,27 @@ iosapic_register_intr (unsigned int gsi,
* If the vector is shared and already unmasked for other * If the vector is shared and already unmasked for other
* interrupt sources, don't mask it. * interrupt sources, don't mask it.
*/ */
low32 = iosapic_intr_info[vector].low32; low32 = iosapic_intr_info[irq].low32;
if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK)) if (irq_is_shared(irq) && !(low32 & IOSAPIC_MASK))
mask = 0; mask = 0;
set_rte(gsi, vector, dest, mask); set_rte(gsi, irq, dest, mask);
printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
(polarity == IOSAPIC_POL_HIGH ? "high" : "low"), (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
cpu_logical_id(dest), dest, vector); cpu_logical_id(dest), dest, irq_to_vector(irq));
unlock_all: unlock_all:
spin_unlock(&irq_desc[vector].lock); spin_unlock(&irq_desc[irq].lock);
unlock_iosapic_lock: unlock_iosapic_lock:
spin_unlock_irqrestore(&iosapic_lock, flags); spin_unlock_irqrestore(&iosapic_lock, flags);
return vector; return irq;
} }
void void
iosapic_unregister_intr (unsigned int gsi) iosapic_unregister_intr (unsigned int gsi)
{ {
unsigned long flags; unsigned long flags;
int irq, vector, index; int irq, index;
irq_desc_t *idesc; irq_desc_t *idesc;
u32 low32; u32 low32;
unsigned long trigger, polarity; unsigned long trigger, polarity;
...@@ -834,10 +819,9 @@ iosapic_unregister_intr (unsigned int gsi) ...@@ -834,10 +819,9 @@ iosapic_unregister_intr (unsigned int gsi)
WARN_ON(1); WARN_ON(1);
return; return;
} }
vector = irq_to_vector(irq);
spin_lock_irqsave(&iosapic_lock, flags); spin_lock_irqsave(&iosapic_lock, flags);
if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { if ((rte = find_rte(irq, gsi)) == NULL) {
printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
gsi); gsi);
WARN_ON(1); WARN_ON(1);
...@@ -854,36 +838,36 @@ iosapic_unregister_intr (unsigned int gsi) ...@@ -854,36 +838,36 @@ iosapic_unregister_intr (unsigned int gsi)
spin_unlock(&idesc->lock); spin_unlock(&idesc->lock);
/* Mask the interrupt */ /* Mask the interrupt */
low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK;
iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32); iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32);
iosapic_intr_info[vector].count--; iosapic_intr_info[irq].count--;
iosapic_free_rte(rte); iosapic_free_rte(rte);
index = find_iosapic(gsi); index = find_iosapic(gsi);
iosapic_lists[index].rtes_inuse--; iosapic_lists[index].rtes_inuse--;
WARN_ON(iosapic_lists[index].rtes_inuse < 0); WARN_ON(iosapic_lists[index].rtes_inuse < 0);
trigger = iosapic_intr_info[vector].trigger; trigger = iosapic_intr_info[irq].trigger;
polarity = iosapic_intr_info[vector].polarity; polarity = iosapic_intr_info[irq].polarity;
dest = iosapic_intr_info[vector].dest; dest = iosapic_intr_info[irq].dest;
printk(KERN_INFO printk(KERN_INFO
"GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n", "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",
gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
(polarity == IOSAPIC_POL_HIGH ? "high" : "low"), (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
cpu_logical_id(dest), dest, vector); cpu_logical_id(dest), dest, irq_to_vector(irq));
if (list_empty(&iosapic_intr_info[vector].rtes)) { if (list_empty(&iosapic_intr_info[irq].rtes)) {
/* Sanity check */ /* Sanity check */
BUG_ON(iosapic_intr_info[vector].count); BUG_ON(iosapic_intr_info[irq].count);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Clear affinity */ /* Clear affinity */
cpus_setall(idesc->affinity); cpus_setall(idesc->affinity);
#endif #endif
/* Clear the interrupt information */ /* Clear the interrupt information */
memset(&iosapic_intr_info[vector], 0, memset(&iosapic_intr_info[irq], 0,
sizeof(struct iosapic_intr_info)); sizeof(struct iosapic_intr_info));
iosapic_intr_info[vector].low32 |= IOSAPIC_MASK; iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
/* Destroy IRQ */ /* Destroy IRQ */
destroy_irq(irq); destroy_irq(irq);
...@@ -908,11 +892,12 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, ...@@ -908,11 +892,12 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
switch (int_type) { switch (int_type) {
case ACPI_INTERRUPT_PMI: case ACPI_INTERRUPT_PMI:
vector = iosapic_vector; vector = iosapic_vector;
irq = vector; /* FIXME */
/* /*
* since PMI vector is alloc'd by FW(ACPI) not by kernel, * since PMI vector is alloc'd by FW(ACPI) not by kernel,
* we need to make sure the vector is available * we need to make sure the vector is available
*/ */
iosapic_reassign_vector(vector); iosapic_reassign_vector(irq);
delivery = IOSAPIC_PMI; delivery = IOSAPIC_PMI;
break; break;
case ACPI_INTERRUPT_INIT: case ACPI_INTERRUPT_INIT:
...@@ -924,6 +909,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, ...@@ -924,6 +909,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
break; break;
case ACPI_INTERRUPT_CPEI: case ACPI_INTERRUPT_CPEI:
vector = IA64_CPE_VECTOR; vector = IA64_CPE_VECTOR;
irq = vector; /* FIXME */
delivery = IOSAPIC_LOWEST_PRIORITY; delivery = IOSAPIC_LOWEST_PRIORITY;
mask = 1; mask = 1;
break; break;
...@@ -933,7 +919,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, ...@@ -933,7 +919,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
return -1; return -1;
} }
register_intr(gsi, vector, delivery, polarity, trigger); register_intr(gsi, irq, delivery, polarity, trigger);
printk(KERN_INFO printk(KERN_INFO
"PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)" "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)"
...@@ -943,7 +929,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, ...@@ -943,7 +929,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
(polarity == IOSAPIC_POL_HIGH ? "high" : "low"), (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
cpu_logical_id(dest), dest, vector); cpu_logical_id(dest), dest, vector);
set_rte(gsi, vector, dest, mask); set_rte(gsi, irq, dest, mask);
return vector; return vector;
} }
...@@ -955,30 +941,30 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, ...@@ -955,30 +941,30 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
unsigned long polarity, unsigned long polarity,
unsigned long trigger) unsigned long trigger)
{ {
int vector; int vector, irq;
unsigned int dest = cpu_physical_id(smp_processor_id()); unsigned int dest = cpu_physical_id(smp_processor_id());
vector = isa_irq_to_vector(isa_irq); vector = isa_irq_to_vector(isa_irq);
irq = vector; /* FIXME */
register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n", DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level", isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level",
polarity == IOSAPIC_POL_HIGH ? "high" : "low", polarity == IOSAPIC_POL_HIGH ? "high" : "low",
cpu_logical_id(dest), dest, vector); cpu_logical_id(dest), dest, vector);
set_rte(gsi, vector, dest, 1); set_rte(gsi, irq, dest, 1);
} }
void __init void __init
iosapic_system_init (int system_pcat_compat) iosapic_system_init (int system_pcat_compat)
{ {
int vector; int irq;
for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) { for (irq = 0; irq < NR_IRQS; ++irq) {
iosapic_intr_info[vector].low32 = IOSAPIC_MASK; iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
/* mark as unused */ /* mark as unused */
INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
} }
pcat_compat = system_pcat_compat; pcat_compat = system_pcat_compat;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment