Skip to content

Commit

Permalink
[IA64] Add mapping table between irq and vector
Browse files Browse the repository at this point in the history
Add mapping tables between irqs and vectors, and its management code.
This is necessary for supporting multiple vector domain because 1:1
mapping between irq and vector will be changed to n:1.

The irq == vector relationship between irqs and vectors is explicitly
remained for percpu interrupts, platform interrupts, isa IRQs and
vectors assigned using assign_irq_vector() because some programs might
depend on it.

And I should consider the following problem.

When pci drivers enabled/disabled devices dynamically, its irq number
is changed to the different one. Therefore, suspend/resume code may
happen problem.

To fix this problem, I bound gsi to irq.

Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
  • Loading branch information
Yasuaki Ishimatsu authored and Tony Luck committed Jul 17, 2007
1 parent f8c087f commit e1b30a3
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 64 deletions.
61 changes: 35 additions & 26 deletions arch/ia64/kernel/iosapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ static DEFINE_SPINLOCK(iosapic_lock);
* These tables map IA-64 vectors to the IOSAPIC pin that generates this
* vector.
*/

#define NO_REF_RTE 0

static struct iosapic {
char __iomem *addr; /* base address of IOSAPIC */
unsigned int gsi_base; /* GSI base */
Expand Down Expand Up @@ -204,7 +207,7 @@ inline int
gsi_to_vector (unsigned int gsi)
{
int irq = __gsi_to_irq(gsi);
if (irq < 0)
if (check_irq_used(irq) < 0)
return -1;
return irq_to_vector(irq);
}
Expand Down Expand Up @@ -619,14 +622,18 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
iosapic_intr_info[irq].count++;
iosapic_lists[index].rtes_inuse++;
}
else if (irq_is_shared(irq)) {
else if (rte->refcnt == NO_REF_RTE) {
struct iosapic_intr_info *info = &iosapic_intr_info[irq];
if (info->trigger != trigger || info->polarity != polarity) {
if (info->count > 0 &&
(info->trigger != trigger || info->polarity != polarity)){
printk (KERN_WARNING
"%s: cannot override the interrupt\n",
__FUNCTION__);
return -EINVAL;
}
rte->refcnt++;
iosapic_intr_info[irq].count++;
iosapic_lists[index].rtes_inuse++;
}

iosapic_intr_info[irq].polarity = polarity;
Expand Down Expand Up @@ -756,12 +763,17 @@ iosapic_register_intr (unsigned int gsi,
irq = __gsi_to_irq(gsi);
if (irq > 0) {
rte = find_rte(irq, gsi);
rte->refcnt++;
goto unlock_iosapic_lock;
}
if(iosapic_intr_info[irq].count == 0) {
assign_irq_vector(irq);
dynamic_irq_init(irq);
} else if (rte->refcnt != NO_REF_RTE) {
rte->refcnt++;
goto unlock_iosapic_lock;
}
} else
irq = create_irq();

/* If vector is running out, we try to find a sharable vector */
irq = create_irq();
if (irq < 0) {
irq = iosapic_find_sharable_irq(trigger, polarity);
if (irq < 0)
Expand Down Expand Up @@ -832,18 +844,14 @@ iosapic_unregister_intr (unsigned int gsi)
if (--rte->refcnt > 0)
goto out;

/* Remove the rte entry from the list */
idesc = irq_desc + irq;
spin_lock(&idesc->lock);
list_del(&rte->rte_list);
spin_unlock(&idesc->lock);
rte->refcnt = NO_REF_RTE;

/* Mask the interrupt */
low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK;
iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32);

iosapic_intr_info[irq].count--;
iosapic_free_rte(rte);
index = find_iosapic(gsi);
iosapic_lists[index].rtes_inuse--;
WARN_ON(iosapic_lists[index].rtes_inuse < 0);
Expand All @@ -857,21 +865,20 @@ iosapic_unregister_intr (unsigned int gsi)
(polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
cpu_logical_id(dest), dest, irq_to_vector(irq));

if (list_empty(&iosapic_intr_info[irq].rtes)) {
/* Sanity check */
BUG_ON(iosapic_intr_info[irq].count);
if (iosapic_intr_info[irq].count == 0) {
#ifdef CONFIG_SMP
/* Clear affinity */
cpus_setall(idesc->affinity);
#endif
/* Clear the interrupt information */
memset(&iosapic_intr_info[irq], 0,
sizeof(struct iosapic_intr_info));
iosapic_intr_info[irq].dest = 0;
iosapic_intr_info[irq].dmode = 0;
iosapic_intr_info[irq].polarity = 0;
iosapic_intr_info[irq].trigger = 0;
iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);

/* Destroy IRQ */
destroy_irq(irq);
/* Destroy and reserve IRQ */
destroy_and_reserve_irq(irq);
}
out:
spin_unlock_irqrestore(&iosapic_lock, flags);
Expand All @@ -892,8 +899,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,

switch (int_type) {
case ACPI_INTERRUPT_PMI:
vector = iosapic_vector;
irq = vector; /* FIXME */
irq = vector = iosapic_vector;
bind_irq_vector(irq, vector);
/*
* since PMI vector is alloc'd by FW(ACPI) not by kernel,
* we need to make sure the vector is available
Expand All @@ -909,8 +916,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
delivery = IOSAPIC_INIT;
break;
case ACPI_INTERRUPT_CPEI:
vector = IA64_CPE_VECTOR;
irq = vector; /* FIXME */
irq = vector = IA64_CPE_VECTOR;
BUG_ON(bind_irq_vector(irq, vector));
delivery = IOSAPIC_LOWEST_PRIORITY;
mask = 1;
break;
Expand Down Expand Up @@ -945,8 +952,8 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
int vector, irq;
unsigned int dest = cpu_physical_id(smp_processor_id());

vector = isa_irq_to_vector(isa_irq);
irq = vector; /* FIXME */
irq = vector = isa_irq_to_vector(isa_irq);
BUG_ON(bind_irq_vector(irq, vector));
register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);

DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
Expand All @@ -966,6 +973,8 @@ iosapic_system_init (int system_pcat_compat)
iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
/* mark as unused */
INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);

iosapic_intr_info[irq].count = 0;
}

pcat_compat = system_pcat_compat;
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void ack_bad_irq(unsigned int irq)
#ifdef CONFIG_IA64_GENERIC
unsigned int __ia64_local_vector_to_irq (ia64_vector vec)
{
return (unsigned int) vec;
return __get_cpu_var(vector_irq)[vec];
}
#endif

Expand Down
Loading

0 comments on commit e1b30a3

Please sign in to comment.