This patch adds inter domain interrupt migration for IOSAPIC. This is
needed when all CPUs in the domain is hot-removed.
Signed-off-by: Kenji Kaneshige <[EMAIL PROTECTED]>
---
linux-2.6.13-rc1-kanesige/arch/ia64/kernel/iosapic.c | 68 ++++++++++++------
linux-2.6.13-rc1-kanesige/arch/ia64/kernel/irq_ia64.c | 36 ++++++++-
linux-2.6.13-rc1-kanesige/include/asm-ia64/hw_irq.h | 1
3 files changed, 83 insertions(+), 22 deletions(-)
diff -puN arch/ia64/kernel/iosapic.c~vector-domain-ia64-migrate-irq-domain
arch/ia64/kernel/iosapic.c
---
linux-2.6.13-rc1/arch/ia64/kernel/iosapic.c~vector-domain-ia64-migrate-irq-domain
2005-07-13 16:12:53.000000000 +0900
+++ linux-2.6.13-rc1-kanesige/arch/ia64/kernel/iosapic.c 2005-07-13
16:12:53.000000000 +0900
@@ -311,6 +311,25 @@ unmask_irq (unsigned int irq)
static void
+iosapic_move_gsv (unsigned int src, unsigned int dst)
+{
+ struct iosapic_intr_info *info_src = &iosapic_intr_info[src];
+ struct iosapic_intr_info *info_dst = &iosapic_intr_info[dst];
+ struct iosapic_rte_info *rte, *next;
+
+ memcpy(info_dst, info_src, sizeof(*info_dst));
+ info_dst->low32 &= ~0xff;
+ info_dst->low32 |= (ia64_vector)gsv_to_vector(dst);
+ INIT_LIST_HEAD(&info_dst->rtes);
+ list_for_each_entry_safe(rte, next, &info_src->rtes, rte_list)
+ list_move_tail(&rte->rte_list, &info_dst->rtes);
+ memset(info_src, 0, sizeof(*info_src));
+ info_src->low32 = IOSAPIC_MASK;
+ INIT_LIST_HEAD(&info_src->rtes);
+}
+
+
+static void
iosapic_set_affinity (unsigned int irq, cpumask_t mask)
{
#ifdef CONFIG_SMP
@@ -331,15 +350,24 @@ iosapic_set_affinity (unsigned int irq,
cpu = first_cpu(mask);
dest = cpu_physical_id(cpu);
- /*
- * XXX - IRQ migration between different domains is not supported yet.
- */
- if (!cpu_isset(cpu, ia64_domain_to_cpumask(gsv_to_domain(gsv))))
- return;
-
if (list_empty(&iosapic_intr_info[gsv].rtes))
return; /* not an IOSAPIC interrupt */
+ /*
+ * IRQ migration between different domains
+ */
+ if (!cpu_isset(cpu, ia64_domain_to_cpumask(gsv_to_domain(gsv)))) {
+ int src = gsv;
+ spin_lock_irqsave(&iosapic_lock, flags);
+ gsv = reassign_irq_gsv(irq, ia64_cpu_to_domain(cpu));
+ if (gsv < 0) {
+ spin_unlock_irqrestore(&iosapic_lock, flags);
+ return;
+ }
+ iosapic_move_gsv(src, gsv);
+ spin_unlock_irqrestore(&iosapic_lock, flags);
+ }
+
set_irq_affinity_info(irq, dest, redir);
/* dest contains both id and eid */
@@ -384,10 +412,17 @@ static void
iosapic_end_level_irq (unsigned int irq)
{
unsigned int gsv = irq_to_gsv(irq);
- ia64_vector vec = gsv_to_vector(gsv);
+ ia64_vector vec;
struct iosapic_rte_info *rte;
move_irq(irq);
+ /*
+ * In the case of irq migration to other domain, irq might be
+ * associated to another gsv.
+ */
+ gsv = irq_to_gsv(irq);
+ vec = gsv_to_vector(gsv);
+
list_for_each_entry(rte, &iosapic_intr_info[gsv].rtes, rte_list)
iosapic_eoi(rte->addr, vec);
}
@@ -525,18 +560,13 @@ iosapic_reassign_gsv (unsigned int gsv)
{
int new_gsv;
- if (!list_empty(&iosapic_intr_info[gsv].rtes)) {
- new_gsv = assign_irq_gsv(AUTO_ASSIGN, gsv_to_domain(gsv));
- printk(KERN_INFO "Reassigning vector %d to %d\n",
- gsv_to_vector(gsv), gsv_to_vector(new_gsv));
- memcpy(&iosapic_intr_info[new_gsv], &iosapic_intr_info[gsv],
- sizeof(struct iosapic_intr_info));
- INIT_LIST_HEAD(&iosapic_intr_info[new_gsv].rtes);
- list_move(iosapic_intr_info[gsv].rtes.next,
&iosapic_intr_info[new_gsv].rtes);
- memset(&iosapic_intr_info[gsv], 0, sizeof(struct
iosapic_intr_info));
- iosapic_intr_info[gsv].low32 = IOSAPIC_MASK;
- INIT_LIST_HEAD(&iosapic_intr_info[gsv].rtes);
- }
+ if (list_empty(&iosapic_intr_info[gsv].rtes))
+ return;
+
+ new_gsv = assign_irq_gsv(AUTO_ASSIGN, gsv_to_domain(gsv));
+ printk(KERN_INFO "Reassigning vector %d to %d\n",
+ gsv_to_vector(gsv), gsv_to_vector(new_gsv));
+ iosapic_move_gsv(gsv, new_gsv);
}
static struct iosapic_rte_info *iosapic_alloc_rte (void)
diff -puN arch/ia64/kernel/irq_ia64.c~vector-domain-ia64-migrate-irq-domain
arch/ia64/kernel/irq_ia64.c
---
linux-2.6.13-rc1/arch/ia64/kernel/irq_ia64.c~vector-domain-ia64-migrate-irq-domain
2005-07-13 16:12:53.000000000 +0900
+++ linux-2.6.13-rc1-kanesige/arch/ia64/kernel/irq_ia64.c 2005-07-13
16:12:53.000000000 +0900
@@ -97,14 +97,21 @@ ia64_free_vector (unsigned int domain, u
static unsigned long ia64_irq_mask[BITS_TO_LONGS(NR_IRQS)];
static int
-ia64_alloc_irq (void)
+ia64_alloc_irq (int irq)
{
- int irq;
+ if (irq != AUTO_ASSIGN) {
+ if (!test_and_set_bit(irq, ia64_irq_mask))
+ return irq;
+ else
+ return -1;
+ }
+
do {
irq = find_first_zero_bit(ia64_irq_mask, NR_IRQS);
if (irq > NR_IRQS)
return -1;
} while (test_and_set_bit(irq, ia64_irq_mask));
+
return irq;
}
@@ -126,7 +133,7 @@ assign_irq_gsv_domain (int irq, int doma
if ((vector = ia64_alloc_vector(domain)) < 0)
return -ENOSPC;
- if ((irq = ia64_alloc_irq()) < 0) {
+ if ((irq = ia64_alloc_irq(irq)) < 0) {
ia64_free_vector(domain, vector);
return -ENOSPC;
}
@@ -178,6 +185,29 @@ free_irq_gsv (int gsv)
}
int
+reassign_irq_gsv (int irq, int domain)
+{
+ int new_vector, new_gsv, old_gsv, old_vector, old_domain;
+
+ new_vector = ia64_alloc_vector(domain);
+ if (new_vector < 0)
+ return -ENOSPC;
+
+ old_gsv = irq_to_gsv(irq);
+ new_gsv = domain_vector_to_gsv(domain, new_vector);
+
+ ia64_irq_to_gsv_map[irq] = new_gsv;
+ ia64_gsv_to_irq_map[new_gsv] = irq;
+ ia64_gsv_to_irq_map[old_gsv] = -1;
+
+ old_domain = gsv_to_domain(old_gsv);
+ old_vector = gsv_to_vector(old_gsv);
+ ia64_free_vector(old_domain, old_vector);
+
+ return new_gsv;
+}
+
+int
assign_irq_vector (int irq)
{
return gsv_to_vector(assign_irq_gsv(irq, 0));
diff -puN include/asm-ia64/hw_irq.h~vector-domain-ia64-migrate-irq-domain
include/asm-ia64/hw_irq.h
---
linux-2.6.13-rc1/include/asm-ia64/hw_irq.h~vector-domain-ia64-migrate-irq-domain
2005-07-13 16:12:53.000000000 +0900
+++ linux-2.6.13-rc1-kanesige/include/asm-ia64/hw_irq.h 2005-07-14
13:13:49.000000000 +0900
@@ -96,6 +96,7 @@ extern struct hw_interrupt_type irq_type
extern int assign_irq_vector (int irq); /* allocate a free vector */
extern int assign_irq_gsv (int irq, int domain);
extern void free_irq_gsv (int gsv);
+extern int reassign_irq_gsv (int irq, int domain);
extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int
redirect);
extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
extern void __init ia64_vector_domain_init(void);
_
-
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html