public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch
@ 2004-04-25  6:47 Ashok Raj
  2004-04-26  3:28 ` Kenji Kaneshige
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Ashok Raj @ 2004-04-25  6:47 UTC (permalink / raw)
  To: linux-ia64

Patch 7/7

Cheers,
ashok raj
- Linux Core Software Group
   


Name: migrate_irq.patch
Author: Ashok Raj (Intel Corporation)
D: This patch adds interrupt migration necessary for supporting CPU removal
in IA64.
D: Devices dont stop generating interrupts, and some special handling is
required to 
D: ensure the kernel does not loose interrupt events in the process of
D: migrating interrupt destinations to different target cpu's. For proper
D: functioning, we need to disable platform level interrupt redirection.
D: Rest is in code for review. To test, i manually migrated network, disk
D: interrupts to cpu3 and removed it later, interrupts should now start
D: on first online cpu (i.e the boot cpu). At time of release worked fine
for
D: 24+ hrs without any panics and hangs.


---

 linux-2.6.5-lhcs-root/arch/ia64/kernel/iosapic.c  |   28 +++++
 linux-2.6.5-lhcs-root/arch/ia64/kernel/irq.c      |  114
++++++++++++++++++----
 linux-2.6.5-lhcs-root/arch/ia64/kernel/irq_ia64.c |   60 ++++++++++-
 linux-2.6.5-lhcs-root/arch/ia64/kernel/sal.c      |   13 ++
 4 files changed, 190 insertions(+), 25 deletions(-)

diff -puN arch/ia64/kernel/irq.c~migrate_irq arch/ia64/kernel/irq.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/irq.c~migrate_irq	2004-04-23
23:11:22.976199926 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/irq.c	2004-04-23
23:11:22.982059304 -0700
@@ -8,6 +8,12 @@
  * instead of just grabbing them. Thus setups with different IRQ numbers
  * shouldn't result in any weird surprises, and installing new handlers
  * should be easier.
+ *
+ * Copyright (C) Ashok Raj<ashok.raj@intel.com>, Intel Corporation 2004
+ *
+ * 4/14/2004: Added code to handle cpu migration and do safe irq
+ *			migration without lossing interrupts for iosapic
+ *			architecture.
  */
 
 /*
@@ -49,8 +55,9 @@
 #include <asm/irq.h>
 #include <asm/tlbflush.h>
 #include <asm/cpu.h>
+#include <asm/bug.h>
 
-
+extern cpumask_t	__cacheline_aligned pending_irq_cpumask[NR_IRQS];
 
 /*
  * Linux has a controller-independent x86 interrupt architecture.
@@ -943,10 +950,14 @@ void set_irq_affinity_info (unsigned int
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
+	extern void print_rte(unsigned int irq);
+	int len = sprintf(page, "%s", irq_redir[(long)data] ? "r " : "");
+
+	len += cpumask_scnprintf(page+len, count, irq_affinity[(long)data]);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
+
 	return len;
 }
 
@@ -961,6 +972,7 @@ static int irq_affinity_write_proc (stru
 	int rlen;
 	int prelen;
 	irq_desc_t *desc = irq_descp(irq);
+	unsigned long flags;
 
 	if (!desc->handler->set_affinity)
 		return -EIO;
@@ -999,40 +1011,106 @@ static int irq_affinity_write_proc (stru
 	if (cpus_empty(tmp))
 		return -EINVAL;
 
-	desc->handler->set_affinity(irq, new_value);
+	spin_lock_irqsave(&desc->lock, flags);
+	pending_irq_cpumask[irq] = new_value;
+	spin_unlock_irqrestore(&desc->lock, flags);
+
 	return full_count;
 }
 
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_HOTPLUG_CPU
-void fixup_irqs(void)
+unsigned int vectors_in_migration[NR_IRQS];
+
+/*
+ * Since cpu_online_map is already updated, we just need to check for
+ * affinity that has zeros
+ */
+static void migrate_irqs(void)
 {
 	cpumask_t	mask;
-	unsigned int irq, redir;
 	irq_desc_t *desc;
-	static int warned;
+	int 		irq, new_cpu;
+
+	for (irq=0; irq < NR_IRQS; irq++) {
+		desc = irq_descp(irq);
+
+		/*
+		 * No handling for now.
+		 * TBD: Implement a disable function so we can now
+		 * tell CPU not to respond to these local intr sources.
+		 * such as ITV,CPEI,MCA etc.
+		 */
+		if (desc->status = IRQ_PER_CPU)
+			continue;
 
-	for (irq = 0; irq < NR_IRQS; irq++) {
 		cpus_and(mask, irq_affinity[irq], cpu_online_map);
 		if (any_online_cpu(mask) = NR_CPUS) {
-			printk("Breaking affinity for irq %ui\n", irq);
-			mask = any_online_cpu(cpu_online_map);
+			/*
+			 * Save it for phase 2 processing
+			 */
+			vectors_in_migration[irq] = irq;
+
+			new_cpu = any_online_cpu(cpu_online_map);
+			mask = cpumask_of_cpu(new_cpu);
+
+			/*
+			 * Al three are essential, currently WARN_ON.. maybe
panic?
+			 */
+			if (desc->handler && desc->handler->disable &&
+				desc->handler->enable &&
desc->handler->set_affinity) {
+				desc->handler->disable(irq);
+				desc->handler->set_affinity(irq, mask);
+				desc->handler->enable(irq);
+			} else {
+				WARN_ON((!(desc->handler) ||
!(desc->handler->disable) ||
+						!(desc->handler->enable) ||
+
!(desc->handler->set_affinity)));
+			}
 		}
-		desc = irq_descp(irq);
-		if (desc->handler->set_affinity) {
-			redir = irq_redir[irq];
-			desc->handler->set_affinity(irq | (redir ?
IA64_IRQ_REDIRECTED : 0),
-
mask);
+	}
+}
+
+void fixup_irqs(void)
+{
+	unsigned int irq;
+	extern void ia64_process_pending_intr(void);
+
+	ia64_set_itv(1<<16);
+	/*
+	 * Phase 1: Locate irq's bound to this cpu and
+	 * relocate them for cpu removal.
+	 */
+	migrate_irqs();
+
+	/*
+	 * Phase 2: Perform interrupt processing for all entries reported in
+	 * local APIC.
+	 */
+	ia64_process_pending_intr();
+
+	/*
+	 * Phase 3: Now handle any interrupts not captured in local APIC.
+	 * This is to account for cases that device interrupted during the
time the
+	 * rte was being disabled and re-programmed.
+	 */
+	for (irq=0; irq < NR_IRQS; irq++) {
+		if (vectors_in_migration[irq]) {
+			vectors_in_migration[irq]=0;
+			do_IRQ(irq, NULL);
 		}
-		else if (desc->action && !(warned++))
-			printk("Cannot set affinity for irq %i\n", irq);
 	}
+
+	/*
+	 * Now let processor die. We do irq disable and max_xtp() to
+	 * ensure there is no more interrupts routed to this processor.
+	 * But the local timer interrupt can have 1 pending which we
+	 * take care in timer_interrupt().
+	 */
 	max_xtp();
 	local_irq_disable();
-	__get_cpu_var(cpu_state) = CPU_DEAD;
 }
-
 #endif
 
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
diff -puN arch/ia64/kernel/irq_ia64.c~migrate_irq
arch/ia64/kernel/irq_ia64.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/irq_ia64.c~migrate_irq	2004-04-23
23:11:22.977176489 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/irq_ia64.c	2004-04-23
23:11:22.983035867 -0700
@@ -10,6 +10,8 @@
  *
  * 09/15/00 Goutham Rao <goutham.rao@intel.com> Implemented
pci_irq_to_vector
  *                      PCI to vector allocation routine.
+ * 04/14/2004 Ashok Raj <ashok.raj@intel.com>
+ *						Added CPU Hotplug handling
for IPF.
  */
 
 #include <linux/config.h>
@@ -85,6 +87,11 @@ ia64_alloc_vector (void)
 
 extern unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs);
 
+#ifdef CONFIG_SMP
+#	define IS_RESCHEDULE(vec)	(vec = IA64_IPI_RESCHEDULE)
+#else
+#	define IS_RESCHEDULE(vec)	(0)
+#endif
 /*
  * That's where the IVT branches when we get an external
  * interrupt. This branches to the correct hardware IRQ handler via
@@ -94,11 +101,6 @@ void
 ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
 {
 	unsigned long saved_tpr;
-#ifdef CONFIG_SMP
-#	define IS_RESCHEDULE(vec)	(vec = IA64_IPI_RESCHEDULE)
-#else
-#	define IS_RESCHEDULE(vec)	(0)
-#endif
 
 #if IRQ_DEBUG
 	{
@@ -162,6 +164,54 @@ ia64_handle_irq (ia64_vector vector, str
 	irq_exit();
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * This function emulates a interrupt processing when a cpu is about to be
+ * brought down.
+ */
+void ia64_process_pending_intr(void)
+{
+	ia64_vector vector;
+	unsigned long saved_tpr;
+	extern unsigned int vectors_in_migration[NR_IRQS];
+
+	vector = ia64_get_ivr();
+
+	 irq_enter();
+	 saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
+	 ia64_srlz_d();
+
+	 /*
+	  * Perform normal interrupt style processing
+	  */
+	while (vector != IA64_SPURIOUS_INT_VECTOR) {
+		if (!IS_RESCHEDULE(vector)) {
+			ia64_setreg(_IA64_REG_CR_TPR, vector);
+			ia64_srlz_d();
+
+			/*
+			 * Now try calling normal ia64_handle_irq as it
would have got called
+			 * from a real intr handler. Try passing null for
pt_regs, hopefully
+			 * it will work. I hope it works!.
+			 * Probably could shared code.
+			 */
+			vectors_in_migration[local_vector_to_irq(vector)]=0;
+			do_IRQ(local_vector_to_irq(vector), NULL);
+
+			/*
+			 * Disable interrupts and send EOI
+			 */
+			local_irq_disable();
+			ia64_setreg(_IA64_REG_CR_TPR, saved_tpr);
+		}
+		ia64_eoi();
+		vector = ia64_get_ivr();
+	}
+	irq_exit();
+}
+#endif
+
+
 #ifdef CONFIG_SMP
 extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs
*regs);
 
diff -puN arch/ia64/kernel/iosapic.c~migrate_irq arch/ia64/kernel/iosapic.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/iosapic.c~migrate_irq	2004-04-23
23:11:22.979129615 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/iosapic.c	2004-04-23
23:11:22.983035867 -0700
@@ -32,6 +32,8 @@
  * 03/02/19	B. Helgaas	Make pcat_compat system-wide, not
per-IOSAPIC.
  *				Remove iosapic_address & gsi_base from
external interfaces.
  *				Rationalize __init/__devinit attributes.
+ * 04/12/04 Ashok Raj	<ashok.raj@intel.com> Intel Corporation 2004
+ *				Updated to work with irq migration necessary
for CPU Hotplug
  */
 /*
  * Here is what the interrupt logic between a PCI device and the kernel
looks like:
@@ -99,6 +101,8 @@
 
 static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
 
+cpumask_t	__cacheline_aligned pending_irq_cpumask[NR_IRQS];
+
 /* These tables map IA-64 vectors to the IOSAPIC pin that generates this
vector. */
 
 static struct iosapic_intr_info {
@@ -188,8 +192,10 @@ set_rte (unsigned int vector, unsigned i
 	pol     = iosapic_intr_info[vector].polarity;
 	trigger = iosapic_intr_info[vector].trigger;
 	dmode   = iosapic_intr_info[vector].dmode;
+	vector &= (~IA64_IRQ_REDIRECTED);
 
 	redir = (dmode = IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
+
 #ifdef CONFIG_SMP
 	{
 		unsigned int irq;
@@ -307,9 +313,8 @@ iosapic_set_affinity (unsigned int irq, 
 
 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
-		/* get current delivery mode by reading the low32 */
-		writel(IOSAPIC_RTE_LOW(rte_index), addr +
IOSAPIC_REG_SELECT);
 		low32 = iosapic_intr_info[vec].low32 & ~(7 <<
IOSAPIC_DELIVERY_SHIFT);
+
 		if (redir)
 		        /* change delivery mode to lowest priority */
 			low32 |= (IOSAPIC_LOWEST_PRIORITY <<
IOSAPIC_DELIVERY_SHIFT);
@@ -327,6 +332,21 @@ iosapic_set_affinity (unsigned int irq, 
 #endif
 }
 
+static inline void move_irq(int irq)
+{
+	/* note - we hold desc->lock */
+	cpumask_t tmp;
+	irq_desc_t *desc = irq_descp(irq);
+
+	if (!cpus_empty(pending_irq_cpumask[irq])) {
+		cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
+		if (unlikely(!cpus_empty(tmp))) {
+			desc->handler->set_affinity(irq,
pending_irq_cpumask[irq]);
+		}
+		cpus_clear(pending_irq_cpumask[irq]);
+	}
+}
+
 /*
  * Handlers for level-triggered interrupts.
  */
@@ -343,6 +363,8 @@ iosapic_end_level_irq (unsigned int irq)
 {
 	ia64_vector vec = irq_to_vector(irq);
 
+	move_irq(irq);
+
 	writel(vec, iosapic_intr_info[vec].addr + IOSAPIC_EOI);
 }
 
@@ -382,6 +404,8 @@ static void
 iosapic_ack_edge_irq (unsigned int irq)
 {
 	irq_desc_t *idesc = irq_descp(irq);
+
+	move_irq(irq);
 	/*
 	 * Once we have recorded IRQ_PENDING already, we can mask the
 	 * interrupt for real. This prevents IRQ storms from unhandled
diff -puN arch/ia64/kernel/sal.c~migrate_irq arch/ia64/kernel/sal.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/sal.c~migrate_irq	2004-04-23
23:11:22.980106178 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/sal.c	2004-04-23
23:11:22.984012430 -0700
@@ -122,10 +122,23 @@ sal_desc_entry_point (void *p)
 static void __init
 set_smp_redirect (int flag)
 {
+#ifndef CONFIG_HOTPLUG_CPU
 	if (no_int_routing)
 		smp_int_redirect &= ~flag;
 	else
 		smp_int_redirect |= flag;
+#else
+	/*
+	 * For CPU Hotplug we dont want to do any chipset supported
+	 * interrupt redirection. The reason is this would require that
+	 * All interrupts be stopped and hard bind the irq to a cpu.
+	 * Later when the interrupt is fired we need to set the redir hint
+	 * on again in the vector. This is combersome for something that the
+	 * user mode irq balancer will solve anyways.
+	 */
+	no_int_routing=1;
+	smp_int_redirect &= ~flag;
+#endif
 }
 #else
 #define set_smp_redirect(flag)	do { } while (0)

_


^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch
  2004-04-25  6:47 [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch Ashok Raj
@ 2004-04-26  3:28 ` Kenji Kaneshige
  2004-04-26  4:47 ` Ashok Raj
  2004-04-26 22:21 ` David Mosberger
  2 siblings, 0 replies; 4+ messages in thread
From: Kenji Kaneshige @ 2004-04-26  3:28 UTC (permalink / raw)
  To: linux-ia64

Hi Ashok,

I think some parts of your patch are required not only to support
CPU removal, but also to fix the following problem of IRQ affinity of
current ia64 linux :)

Current irq_affinity_write_proc() changes unmasked RTEs by force.
But I think it is dangerous because it might cause a race condition
if some interrupts are generated while changing the RTE. 

Your patch solves this problem by changing the RTE while the
interrupt is pending, doesn't it?

Thanks,
Kenji Kaneshige


> -----Original Message-----
> From: linux-ia64-owner@vger.kernel.org 
> [mailto:linux-ia64-owner@vger.kernel.org]On Behalf Of Ashok Raj
> Sent: Sunday, April 25, 2004 3:47 PM
> To: LHCS list
> Cc: linux-ia64@vger.kernel.org; davidm@hpl.hp.com; akpm@osdl.org; 
> Rusty Russell; Luck, Tony; Mallick, Asit K; Saxena, Sunil; Shah, Rajesh
> Subject: [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch
> 
> 
> Patch 7/7
> 
> Cheers,
> ashok raj
> - Linux Core Software Group
>    
> 
> 
> Name: migrate_irq.patch
> Author: Ashok Raj (Intel Corporation)
> D: This patch adds interrupt migration necessary for supporting 
> CPU removal
> in IA64.
> D: Devices dont stop generating interrupts, and some special handling is
> required to 
> D: ensure the kernel does not loose interrupt events in the process of
> D: migrating interrupt destinations to different target cpu's. For proper
> D: functioning, we need to disable platform level interrupt redirection.
> D: Rest is in code for review. To test, i manually migrated network, disk
> D: interrupts to cpu3 and removed it later, interrupts should now start
> D: on first online cpu (i.e the boot cpu). At time of release worked fine
> for
> D: 24+ hrs without any panics and hangs.
> 
> 
> ---
> 
>  linux-2.6.5-lhcs-root/arch/ia64/kernel/iosapic.c  |   28 +++++
>  linux-2.6.5-lhcs-root/arch/ia64/kernel/irq.c      |  114
> ++++++++++++++++++----
>  linux-2.6.5-lhcs-root/arch/ia64/kernel/irq_ia64.c |   60 ++++++++++-
>  linux-2.6.5-lhcs-root/arch/ia64/kernel/sal.c      |   13 ++
>  4 files changed, 190 insertions(+), 25 deletions(-)
> 
> diff -puN arch/ia64/kernel/irq.c~migrate_irq arch/ia64/kernel/irq.c
> --- linux-2.6.5-lhcs/arch/ia64/kernel/irq.c~migrate_irq	2004-04-23
> 23:11:22.976199926 -0700
> +++ linux-2.6.5-lhcs-root/arch/ia64/kernel/irq.c	2004-04-23
> 23:11:22.982059304 -0700
> @@ -8,6 +8,12 @@
>   * instead of just grabbing them. Thus setups with different IRQ numbers
>   * shouldn't result in any weird surprises, and installing new handlers
>   * should be easier.
> + *
> + * Copyright (C) Ashok Raj<ashok.raj@intel.com>, Intel Corporation 2004
> + *
> + * 4/14/2004: Added code to handle cpu migration and do safe irq
> + *			migration without lossing interrupts for iosapic
> + *			architecture.
>   */
>  
>  /*
> @@ -49,8 +55,9 @@
>  #include <asm/irq.h>
>  #include <asm/tlbflush.h>
>  #include <asm/cpu.h>
> +#include <asm/bug.h>
>  
> -
> +extern cpumask_t	__cacheline_aligned pending_irq_cpumask[NR_IRQS];
>  
>  /*
>   * Linux has a controller-independent x86 interrupt architecture.
> @@ -943,10 +950,14 @@ void set_irq_affinity_info (unsigned int
>  static int irq_affinity_read_proc (char *page, char **start, off_t off,
>  			int count, int *eof, void *data)
>  {
> -	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
> +	extern void print_rte(unsigned int irq);
> +	int len = sprintf(page, "%s", irq_redir[(long)data] ? "r " : "");
> +
> +	len += cpumask_scnprintf(page+len, count, irq_affinity[(long)data]);
>  	if (count - len < 2)
>  		return -EINVAL;
>  	len += sprintf(page + len, "\n");
> +
>  	return len;
>  }
>  
> @@ -961,6 +972,7 @@ static int irq_affinity_write_proc (stru
>  	int rlen;
>  	int prelen;
>  	irq_desc_t *desc = irq_descp(irq);
> +	unsigned long flags;
>  
>  	if (!desc->handler->set_affinity)
>  		return -EIO;
> @@ -999,40 +1011,106 @@ static int irq_affinity_write_proc (stru
>  	if (cpus_empty(tmp))
>  		return -EINVAL;
>  
> -	desc->handler->set_affinity(irq, new_value);
> +	spin_lock_irqsave(&desc->lock, flags);
> +	pending_irq_cpumask[irq] = new_value;
> +	spin_unlock_irqrestore(&desc->lock, flags);
> +
>  	return full_count;
>  }
>  
>  #endif /* CONFIG_SMP */
>  
>  #ifdef CONFIG_HOTPLUG_CPU
> -void fixup_irqs(void)
> +unsigned int vectors_in_migration[NR_IRQS];
> +
> +/*
> + * Since cpu_online_map is already updated, we just need to check for
> + * affinity that has zeros
> + */
> +static void migrate_irqs(void)
>  {
>  	cpumask_t	mask;
> -	unsigned int irq, redir;
>  	irq_desc_t *desc;
> -	static int warned;
> +	int 		irq, new_cpu;
> +
> +	for (irq=0; irq < NR_IRQS; irq++) {
> +		desc = irq_descp(irq);
> +
> +		/*
> +		 * No handling for now.
> +		 * TBD: Implement a disable function so we can now
> +		 * tell CPU not to respond to these local intr sources.
> +		 * such as ITV,CPEI,MCA etc.
> +		 */
> +		if (desc->status = IRQ_PER_CPU)
> +			continue;
>  
> -	for (irq = 0; irq < NR_IRQS; irq++) {
>  		cpus_and(mask, irq_affinity[irq], cpu_online_map);
>  		if (any_online_cpu(mask) = NR_CPUS) {
> -			printk("Breaking affinity for irq %ui\n", irq);
> -			mask = any_online_cpu(cpu_online_map);
> +			/*
> +			 * Save it for phase 2 processing
> +			 */
> +			vectors_in_migration[irq] = irq;
> +
> +			new_cpu = any_online_cpu(cpu_online_map);
> +			mask = cpumask_of_cpu(new_cpu);
> +
> +			/*
> +			 * Al three are essential, currently WARN_ON.. maybe
> panic?
> +			 */
> +			if (desc->handler && desc->handler->disable &&
> +				desc->handler->enable &&
> desc->handler->set_affinity) {
> +				desc->handler->disable(irq);
> +				desc->handler->set_affinity(irq, mask);
> +				desc->handler->enable(irq);
> +			} else {
> +				WARN_ON((!(desc->handler) ||
> !(desc->handler->disable) ||
> +						!(desc->handler->enable) ||
> +
> !(desc->handler->set_affinity)));
> +			}
>  		}
> -		desc = irq_descp(irq);
> -		if (desc->handler->set_affinity) {
> -			redir = irq_redir[irq];
> -			desc->handler->set_affinity(irq | (redir ?
> IA64_IRQ_REDIRECTED : 0),
> -
> mask);
> +	}
> +}
> +
> +void fixup_irqs(void)
> +{
> +	unsigned int irq;
> +	extern void ia64_process_pending_intr(void);
> +
> +	ia64_set_itv(1<<16);
> +	/*
> +	 * Phase 1: Locate irq's bound to this cpu and
> +	 * relocate them for cpu removal.
> +	 */
> +	migrate_irqs();
> +
> +	/*
> +	 * Phase 2: Perform interrupt processing for all entries reported in
> +	 * local APIC.
> +	 */
> +	ia64_process_pending_intr();
> +
> +	/*
> +	 * Phase 3: Now handle any interrupts not captured in local APIC.
> +	 * This is to account for cases that device interrupted during the
> time the
> +	 * rte was being disabled and re-programmed.
> +	 */
> +	for (irq=0; irq < NR_IRQS; irq++) {
> +		if (vectors_in_migration[irq]) {
> +			vectors_in_migration[irq]=0;
> +			do_IRQ(irq, NULL);
>  		}
> -		else if (desc->action && !(warned++))
> -			printk("Cannot set affinity for irq %i\n", irq);
>  	}
> +
> +	/*
> +	 * Now let processor die. We do irq disable and max_xtp() to
> +	 * ensure there is no more interrupts routed to this processor.
> +	 * But the local timer interrupt can have 1 pending which we
> +	 * take care in timer_interrupt().
> +	 */
>  	max_xtp();
>  	local_irq_disable();
> -	__get_cpu_var(cpu_state) = CPU_DEAD;
>  }
> -
>  #endif
>  
>  static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
> diff -puN arch/ia64/kernel/irq_ia64.c~migrate_irq
> arch/ia64/kernel/irq_ia64.c
> --- linux-2.6.5-lhcs/arch/ia64/kernel/irq_ia64.c~migrate_irq	2004-04-23
> 23:11:22.977176489 -0700
> +++ linux-2.6.5-lhcs-root/arch/ia64/kernel/irq_ia64.c	2004-04-23
> 23:11:22.983035867 -0700
> @@ -10,6 +10,8 @@
>   *
>   * 09/15/00 Goutham Rao <goutham.rao@intel.com> Implemented
> pci_irq_to_vector
>   *                      PCI to vector allocation routine.
> + * 04/14/2004 Ashok Raj <ashok.raj@intel.com>
> + *						Added CPU Hotplug handling
> for IPF.
>   */
>  
>  #include <linux/config.h>
> @@ -85,6 +87,11 @@ ia64_alloc_vector (void)
>  
>  extern unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs);
>  
> +#ifdef CONFIG_SMP
> +#	define IS_RESCHEDULE(vec)	(vec = IA64_IPI_RESCHEDULE)
> +#else
> +#	define IS_RESCHEDULE(vec)	(0)
> +#endif
>  /*
>   * That's where the IVT branches when we get an external
>   * interrupt. This branches to the correct hardware IRQ handler via
> @@ -94,11 +101,6 @@ void
>  ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
>  {
>  	unsigned long saved_tpr;
> -#ifdef CONFIG_SMP
> -#	define IS_RESCHEDULE(vec)	(vec = IA64_IPI_RESCHEDULE)
> -#else
> -#	define IS_RESCHEDULE(vec)	(0)
> -#endif
>  
>  #if IRQ_DEBUG
>  	{
> @@ -162,6 +164,54 @@ ia64_handle_irq (ia64_vector vector, str
>  	irq_exit();
>  }
>  
> +#ifdef CONFIG_HOTPLUG_CPU
> +/*
> + * This function emulates a interrupt processing when a cpu is 
> about to be
> + * brought down.
> + */
> +void ia64_process_pending_intr(void)
> +{
> +	ia64_vector vector;
> +	unsigned long saved_tpr;
> +	extern unsigned int vectors_in_migration[NR_IRQS];
> +
> +	vector = ia64_get_ivr();
> +
> +	 irq_enter();
> +	 saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
> +	 ia64_srlz_d();
> +
> +	 /*
> +	  * Perform normal interrupt style processing
> +	  */
> +	while (vector != IA64_SPURIOUS_INT_VECTOR) {
> +		if (!IS_RESCHEDULE(vector)) {
> +			ia64_setreg(_IA64_REG_CR_TPR, vector);
> +			ia64_srlz_d();
> +
> +			/*
> +			 * Now try calling normal ia64_handle_irq as it
> would have got called
> +			 * from a real intr handler. Try passing null for
> pt_regs, hopefully
> +			 * it will work. I hope it works!.
> +			 * Probably could shared code.
> +			 */
> +			vectors_in_migration[local_vector_to_irq(vector)]=0;
> +			do_IRQ(local_vector_to_irq(vector), NULL);
> +
> +			/*
> +			 * Disable interrupts and send EOI
> +			 */
> +			local_irq_disable();
> +			ia64_setreg(_IA64_REG_CR_TPR, saved_tpr);
> +		}
> +		ia64_eoi();
> +		vector = ia64_get_ivr();
> +	}
> +	irq_exit();
> +}
> +#endif
> +
> +
>  #ifdef CONFIG_SMP
>  extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs
> *regs);
>  
> diff -puN arch/ia64/kernel/iosapic.c~migrate_irq 
> arch/ia64/kernel/iosapic.c
> --- linux-2.6.5-lhcs/arch/ia64/kernel/iosapic.c~migrate_irq	2004-04-23
> 23:11:22.979129615 -0700
> +++ linux-2.6.5-lhcs-root/arch/ia64/kernel/iosapic.c	2004-04-23
> 23:11:22.983035867 -0700
> @@ -32,6 +32,8 @@
>   * 03/02/19	B. Helgaas	Make pcat_compat system-wide, not
> per-IOSAPIC.
>   *				Remove iosapic_address & gsi_base from
> external interfaces.
>   *				Rationalize __init/__devinit attributes.
> + * 04/12/04 Ashok Raj	<ashok.raj@intel.com> Intel Corporation 2004
> + *				Updated to work with irq migration necessary
> for CPU Hotplug
>   */
>  /*
>   * Here is what the interrupt logic between a PCI device and the kernel
> looks like:
> @@ -99,6 +101,8 @@
>  
>  static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
>  
> +cpumask_t	__cacheline_aligned pending_irq_cpumask[NR_IRQS];
> +
>  /* These tables map IA-64 vectors to the IOSAPIC pin that generates this
> vector. */
>  
>  static struct iosapic_intr_info {
> @@ -188,8 +192,10 @@ set_rte (unsigned int vector, unsigned i
>  	pol     = iosapic_intr_info[vector].polarity;
>  	trigger = iosapic_intr_info[vector].trigger;
>  	dmode   = iosapic_intr_info[vector].dmode;
> +	vector &= (~IA64_IRQ_REDIRECTED);
>  
>  	redir = (dmode = IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
> +
>  #ifdef CONFIG_SMP
>  	{
>  		unsigned int irq;
> @@ -307,9 +313,8 @@ iosapic_set_affinity (unsigned int irq, 
>  
>  	spin_lock_irqsave(&iosapic_lock, flags);
>  	{
> -		/* get current delivery mode by reading the low32 */
> -		writel(IOSAPIC_RTE_LOW(rte_index), addr +
> IOSAPIC_REG_SELECT);
>  		low32 = iosapic_intr_info[vec].low32 & ~(7 <<
> IOSAPIC_DELIVERY_SHIFT);
> +
>  		if (redir)
>  		        /* change delivery mode to lowest priority */
>  			low32 |= (IOSAPIC_LOWEST_PRIORITY <<
> IOSAPIC_DELIVERY_SHIFT);
> @@ -327,6 +332,21 @@ iosapic_set_affinity (unsigned int irq, 
>  #endif
>  }
>  
> +static inline void move_irq(int irq)
> +{
> +	/* note - we hold desc->lock */
> +	cpumask_t tmp;
> +	irq_desc_t *desc = irq_descp(irq);
> +
> +	if (!cpus_empty(pending_irq_cpumask[irq])) {
> +		cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
> +		if (unlikely(!cpus_empty(tmp))) {
> +			desc->handler->set_affinity(irq,
> pending_irq_cpumask[irq]);
> +		}
> +		cpus_clear(pending_irq_cpumask[irq]);
> +	}
> +}
> +
>  /*
>   * Handlers for level-triggered interrupts.
>   */
> @@ -343,6 +363,8 @@ iosapic_end_level_irq (unsigned int irq)
>  {
>  	ia64_vector vec = irq_to_vector(irq);
>  
> +	move_irq(irq);
> +
>  	writel(vec, iosapic_intr_info[vec].addr + IOSAPIC_EOI);
>  }
>  
> @@ -382,6 +404,8 @@ static void
>  iosapic_ack_edge_irq (unsigned int irq)
>  {
>  	irq_desc_t *idesc = irq_descp(irq);
> +
> +	move_irq(irq);
>  	/*
>  	 * Once we have recorded IRQ_PENDING already, we can mask the
>  	 * interrupt for real. This prevents IRQ storms from unhandled
> diff -puN arch/ia64/kernel/sal.c~migrate_irq arch/ia64/kernel/sal.c
> --- linux-2.6.5-lhcs/arch/ia64/kernel/sal.c~migrate_irq	2004-04-23
> 23:11:22.980106178 -0700
> +++ linux-2.6.5-lhcs-root/arch/ia64/kernel/sal.c	2004-04-23
> 23:11:22.984012430 -0700
> @@ -122,10 +122,23 @@ sal_desc_entry_point (void *p)
>  static void __init
>  set_smp_redirect (int flag)
>  {
> +#ifndef CONFIG_HOTPLUG_CPU
>  	if (no_int_routing)
>  		smp_int_redirect &= ~flag;
>  	else
>  		smp_int_redirect |= flag;
> +#else
> +	/*
> +	 * For CPU Hotplug we dont want to do any chipset supported
> +	 * interrupt redirection. The reason is this would require that
> +	 * All interrupts be stopped and hard bind the irq to a cpu.
> +	 * Later when the interrupt is fired we need to set the redir hint
> +	 * on again in the vector. This is combersome for something that the
> +	 * user mode irq balancer will solve anyways.
> +	 */
> +	no_int_routing=1;
> +	smp_int_redirect &= ~flag;
> +#endif
>  }
>  #else
>  #define set_smp_redirect(flag)	do { } while (0)
> 
> _
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch
  2004-04-25  6:47 [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch Ashok Raj
  2004-04-26  3:28 ` Kenji Kaneshige
@ 2004-04-26  4:47 ` Ashok Raj
  2004-04-26 22:21 ` David Mosberger
  2 siblings, 0 replies; 4+ messages in thread
From: Ashok Raj @ 2004-04-26  4:47 UTC (permalink / raw)
  To: linux-ia64


>-----Original Message-----
>From: Kenji Kaneshige [mailto:kaneshige.kenji@jp.fujitsu.com]
>Sent: Sunday, April 25, 2004 8:29 PM
>To: Raj, Ashok; LHCS list
>Cc: linux-ia64@vger.kernel.org; davidm@hpl.hp.com; akpm@osdl.org; Rusty
>Russell; Luck, Tony; Mallick, Asit K; Saxena, Sunil; Shah, Rajesh
>Subject: RE: [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch
>
>Hi Ashok,
>
>I think some parts of your patch are required not only to support
>CPU removal, but also to fix the following problem of IRQ affinity of
>current ia64 linux :)
>
>Current irq_affinity_write_proc() changes unmasked RTEs by force.
>But I think it is dangerous because it might cause a race condition
>if some interrupts are generated while changing the RTE.
>
>Your patch solves this problem by changing the RTE while the
>interrupt is pending, doesn't it?

Thanks for looking in to the patch Kaneshige san. 

You are correct. This patch also has a portion required by general affinity
handler code. I was planning to do this separately, but got a little lazy
and put both together.. :-) 

Cheers,
Ashok Raj
[Linux core software team]


^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch
  2004-04-25  6:47 [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch Ashok Raj
  2004-04-26  3:28 ` Kenji Kaneshige
  2004-04-26  4:47 ` Ashok Raj
@ 2004-04-26 22:21 ` David Mosberger
  2 siblings, 0 replies; 4+ messages in thread
From: David Mosberger @ 2004-04-26 22:21 UTC (permalink / raw)
  To: linux-ia64

>>>>> On Sun, 25 Apr 2004 21:47:25 -0700, "Ashok Raj" <ashok.raj@intel.com> said:

  Ashok> You are correct. This patch also has a portion required by
  Ashok> general affinity handler code. I was planning to do this
  Ashok> separately, but got a little lazy and put both together.. :-)

Please submit separate patches for separate fixes/enhancements.

	--david

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2004-04-26 22:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-25  6:47 [RFC IA64 Hotplug] [Patch 7/7] migrate_irq.patch Ashok Raj
2004-04-26  3:28 ` Kenji Kaneshige
2004-04-26  4:47 ` Ashok Raj
2004-04-26 22:21 ` David Mosberger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox