public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
* Updated CPU Hotplug patches for IA64 [Patch 1/7]
@ 2004-04-28  1:00 Ashok Raj
  2004-04-28  1:01 ` Updated CPU hotplug patches for IA64 [Patch 2/7] Ashok Raj
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Ashok Raj @ 2004-04-28  1:00 UTC (permalink / raw)
  To: linux-ia64

Hi Andrew

Here are the updated patches for CPU hotplug support for IA64. I reworked
some of the patches, and merged/split them based on feedback from 
David Mosberger-Tang, and couple others from the list.

Summary of changes.
- Removed kdb patch that got in by mistake :-(
- split migrate_irq.patch to separate the bug fix v.s. feature required for
  cpu hotplug support. (Thanks to Kanashige-san (fujitsu) for giving me that
  extra work :-)).
- Removed one per-cpu global that was also initialized to 0, which was not
  necessary.
- Removed some hunks that were white space in hotcpu_ia64.patch
- Sorted the newly added headers as per David Moshberger's requirements.
- Merged the rest of migrate_irq.patch with hotcpu_ia64.patch as it was
  integral part of the cpu hotplug patches.
- arch/ia64/dig/topology.c is added only for non-numa, numa adds it in 
  arch/ia64/mm/numa.c (Probably better to move to a common file in future)

Mostly the same, except some minor restructuring and cleanup...

Oh.. this time, i have learned to keep the lines together...:-) and not 
introducing line breaks... (Hopefully)

Cheers,
Ashok Raj
- Linux Core Software Group



Name: core_kernel_init.patch
Author: Ashok Raj (Intel Corporation)
D: This patch changes __init to __devinit to init_idle so that when a new cpu
D: arrives, it can call these functions at a later time.


---

 linux-2.6.5-lhcs-root/init/main.c    |    2 +-
 linux-2.6.5-lhcs-root/kernel/sched.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff -puN kernel/sched.c~core_kernel_init kernel/sched.c
--- linux-2.6.5-lhcs/kernel/sched.c~core_kernel_init	2004-04-26 22:14:54.113320301 -0700
+++ linux-2.6.5-lhcs-root/kernel/sched.c	2004-04-26 22:14:54.117226553 -0700
@@ -2657,7 +2657,7 @@ void show_state(void)
 	read_unlock(&tasklist_lock);
 }
 
-void __init init_idle(task_t *idle, int cpu)
+void __devinit init_idle(task_t *idle, int cpu)
 {
 	runqueue_t *idle_rq = cpu_rq(cpu), *rq = cpu_rq(task_cpu(idle));
 	unsigned long flags;
diff -puN init/main.c~core_kernel_init init/main.c
--- linux-2.6.5-lhcs/init/main.c~core_kernel_init	2004-04-26 22:14:54.114296864 -0700
+++ linux-2.6.5-lhcs-root/init/main.c	2004-04-26 22:14:54.124062494 -0700
@@ -181,7 +181,7 @@ EXPORT_SYMBOL(loops_per_jiffy);
    better than 1% */
 #define LPS_PREC 8
 
-void __init calibrate_delay(void)
+void __devinit calibrate_delay(void)
 {
 	unsigned long ticks, loopbit;
 	int lps_precision = LPS_PREC;

_

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

* Updated CPU hotplug patches for IA64 [Patch 2/7]
  2004-04-28  1:00 Updated CPU Hotplug patches for IA64 [Patch 1/7] Ashok Raj
@ 2004-04-28  1:01 ` Ashok Raj
  2004-04-28  1:02 ` Updated CPU hotplug patches for IA64 [Patch 3/7] Ashok Raj
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Ashok Raj @ 2004-04-28  1:01 UTC (permalink / raw)
  To: linux-ia64



Name: ia64_init_removal.patch
Author: Ashok Raj (Intel Corporation)
Status: Experimental

D: Contains changes from __init to __devinit to support cpu hotplug
D: Changes only arch/ia64 portions of the kernel tree.


---

 linux-2.6.5-lhcs-root/arch/ia64/kernel/setup.c   |    2 +-
 linux-2.6.5-lhcs-root/arch/ia64/kernel/smpboot.c |   12 ++++++------
 linux-2.6.5-lhcs-root/arch/ia64/kernel/time.c    |    2 +-
 linux-2.6.5-lhcs-root/arch/ia64/mm/init.c        |    4 ++--
 linux-2.6.5-lhcs-root/arch/ia64/mm/tlb.c         |    2 +-
 linux-2.6.5-lhcs-root/include/asm-ia64/smp.h     |    3 ++-
 6 files changed, 13 insertions(+), 12 deletions(-)

diff -puN arch/ia64/kernel/setup.c~init_removal_ia64 arch/ia64/kernel/setup.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/setup.c~init_removal_ia64	2004-04-26 22:15:29.923885511 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/setup.c	2004-04-26 22:15:29.932674578 -0700
@@ -575,7 +575,7 @@ get_max_cacheline_size (void)
 void
 cpu_init (void)
 {
-	extern void __init ia64_mmu_init (void *);
+	extern void __devinit ia64_mmu_init (void *);
 	unsigned long num_phys_stacked;
 	pal_vm_info_2_u_t vmi;
 	unsigned int max_ctx;
diff -puN arch/ia64/kernel/smpboot.c~init_removal_ia64 arch/ia64/kernel/smpboot.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/smpboot.c~init_removal_ia64	2004-04-26 22:15:29.925838637 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/smpboot.c	2004-04-26 22:15:29.933651141 -0700
@@ -69,7 +69,7 @@ static volatile unsigned long go[SLAVE +
 
 #define DEBUG_ITC_SYNC	0
 
-extern void __init calibrate_delay (void);
+extern void __devinit calibrate_delay (void);
 extern void start_ap (void);
 extern unsigned long ia64_iobase;
 
@@ -262,12 +262,12 @@ ia64_sync_itc (unsigned int master)
 /*
  * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
  */
-static inline void __init
+static inline void __devinit
 smp_setup_percpu_timer (void)
 {
 }
 
-static void __init
+static void __devinit
 smp_callin (void)
 {
 	int cpuid, phys_id;
@@ -333,7 +333,7 @@ smp_callin (void)
 /*
  * Activate a secondary processor.  head.S calls this.
  */
-int __init
+int __devinit
 start_secondary (void *unused)
 {
 	extern int cpu_idle (void);
@@ -346,7 +346,7 @@ start_secondary (void *unused)
 	return cpu_idle();
 }
 
-static struct task_struct * __init
+static struct task_struct * __devinit
 fork_by_hand (void)
 {
 	/*
@@ -356,7 +356,7 @@ fork_by_hand (void)
 	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL, NULL);
 }
 
-static int __init
+static int __devinit
 do_boot_cpu (int sapicid, int cpu)
 {
 	struct task_struct *idle;
diff -puN arch/ia64/kernel/time.c~init_removal_ia64 arch/ia64/kernel/time.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/time.c~init_removal_ia64	2004-04-26 22:15:29.926815200 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/time.c	2004-04-26 22:15:29.933651141 -0700
@@ -326,7 +326,7 @@ ia64_cpu_local_tick (void)
 	ia64_set_itm(local_cpu_data->itm_next);
 }
 
-void __init
+void __devinit
 ia64_init_itm (void)
 {
 	unsigned long platform_base_freq, itc_freq;
diff -puN arch/ia64/mm/init.c~init_removal_ia64 arch/ia64/mm/init.c
--- linux-2.6.5-lhcs/arch/ia64/mm/init.c~init_removal_ia64	2004-04-26 22:15:29.928768326 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/mm/init.c	2004-04-26 22:15:29.933651141 -0700
@@ -274,11 +274,11 @@ setup_gate (void)
 	ia64_patch_gate();
 }
 
-void __init
+void __devinit
 ia64_mmu_init (void *my_cpu_data)
 {
 	unsigned long psr, pta, impl_va_bits;
-	extern void __init tlb_init (void);
+	extern void __devinit tlb_init (void);
 	int cpu;
 
 #ifdef CONFIG_DISABLE_VHPT
diff -puN arch/ia64/mm/tlb.c~init_removal_ia64 arch/ia64/mm/tlb.c
--- linux-2.6.5-lhcs/arch/ia64/mm/tlb.c~init_removal_ia64	2004-04-26 22:15:29.929744889 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/mm/tlb.c	2004-04-26 22:15:29.934627704 -0700
@@ -166,7 +166,7 @@ flush_tlb_range (struct vm_area_struct *
 }
 EXPORT_SYMBOL(flush_tlb_range);
 
-void __init
+void __devinit
 ia64_tlb_init (void)
 {
 	ia64_ptce_info_t ptce_info;
diff -puN include/asm-ia64/smp.h~init_removal_ia64 include/asm-ia64/smp.h
--- linux-2.6.5-lhcs/include/asm-ia64/smp.h~init_removal_ia64	2004-04-26 22:15:29.930721452 -0700
+++ linux-2.6.5-lhcs-root/include/asm-ia64/smp.h	2004-04-26 22:15:29.934627704 -0700
@@ -36,7 +36,7 @@ extern struct smp_boot_data {
 	int cpu_phys_id[NR_CPUS];
 } smp_boot_data __initdata;
 
-extern char no_int_routing __initdata;
+extern char no_int_routing __devinitdata;
 
 extern cpumask_t phys_cpu_present_map;
 extern cpumask_t cpu_online_map;
@@ -113,6 +113,7 @@ hard_smp_processor_id (void)
 /* Upping and downing of CPUs */
 extern int __cpu_disable (void);
 extern void __cpu_die (unsigned int cpu);
+extern void cpu_die (void) __attribute__ ((noreturn));
 extern int __cpu_up (unsigned int cpu);
 extern void __init smp_build_cpu_map(void);
 

_

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

* Updated CPU hotplug patches for IA64 [Patch 3/7]
  2004-04-28  1:00 Updated CPU Hotplug patches for IA64 [Patch 1/7] Ashok Raj
  2004-04-28  1:01 ` Updated CPU hotplug patches for IA64 [Patch 2/7] Ashok Raj
@ 2004-04-28  1:02 ` Ashok Raj
  2004-04-28  1:04 ` Updated CPU hotplug patches for IA64 [Patch 4/7] Ashok Raj
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Ashok Raj @ 2004-04-28  1:02 UTC (permalink / raw)
  To: linux-ia64



Name: sysfs_ia64.patch
Author: Ashok Raj (Intel Corporation)
D: Creation of sysfs via topology_init() creates sysfs entries. The creation of
D: the online control file is created separately when the cpu_up is invoked
D: in arch independent code.
---



---

 linux-2.6.5-lhcs-root/arch/ia64/dig/Makefile   |    5 ++
 linux-2.6.5-lhcs-root/arch/ia64/dig/topology.c |   43 +++++++++++++++++++++++++
 linux-2.6.5-lhcs-root/include/asm-ia64/cpu.h   |   17 +++++++++
 3 files changed, 65 insertions(+)

diff -puN arch/ia64/dig/Makefile~sysfs_ia64 arch/ia64/dig/Makefile
--- linux-2.6.5-lhcs/arch/ia64/dig/Makefile~sysfs_ia64	2004-04-26 23:03:37.000000000 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/dig/Makefile	2004-04-27 17:43:09.534588587 -0700
@@ -6,4 +6,9 @@
 #
 
 obj-y := setup.o
+
+ifndef CONFIG_NUMA
+obj-$(CONFIG_IA64_DIG) += topology.o
+endif
+
 obj-$(CONFIG_IA64_GENERIC) += machvec.o
diff -puN /dev/null arch/ia64/dig/topology.c
--- /dev/null	2003-09-15 06:02:17.000000000 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/dig/topology.c	2004-04-26 23:03:37.000000000 -0700
@@ -0,0 +1,43 @@
+/*
+ * arch/ia64/dig/topology.c
+ *	Popuate driverfs with topology information.
+ *	Derived entirely from i386/mach-default.c
+ *  Intel Corporation - Ashok Raj
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/cpumask.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <asm/cpu.h>
+
+static DEFINE_PER_CPU(struct ia64_cpu, cpu_devices);
+
+/*
+ * First Pass: simply borrowed code for now. Later should hook into
+ * hotplug notification for node/cpu/memory as applicable
+ */
+
+static int arch_register_cpu(int num)
+{
+	struct node *parent = NULL;
+
+#ifdef CONFIG_NUMA
+	//parent = &node_devices[cpu_to_node(num)].node;
+#endif
+
+	return register_cpu(&per_cpu(cpu_devices,num).cpu, num, parent);
+}
+
+static int __init topology_init(void)
+{
+    int i;
+
+    for_each_cpu(i) {
+        arch_register_cpu(i);
+	}
+    return 0;
+}
+
+subsys_initcall(topology_init);
diff -puN /dev/null include/asm-ia64/cpu.h
--- /dev/null	2003-09-15 06:02:17.000000000 -0700
+++ linux-2.6.5-lhcs-root/include/asm-ia64/cpu.h	2004-04-26 23:03:28.000000000 -0700
@@ -0,0 +1,17 @@
+#ifndef _ASM_IA64_CPU_H_
+#define _ASM_IA64_CPU_H_
+
+#include <linux/device.h>
+#include <linux/cpu.h>
+#include <linux/topology.h>
+#include <linux/percpu.h>
+
+struct ia64_cpu {
+	struct cpu cpu;
+};
+
+DECLARE_PER_CPU(struct ia64_cpu, cpu_devices);
+
+DECLARE_PER_CPU(int, cpu_state);
+
+#endif /* _ASM_IA64_CPU_H_ */

_

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

* Updated CPU hotplug patches for IA64 [Patch 4/7]
  2004-04-28  1:00 Updated CPU Hotplug patches for IA64 [Patch 1/7] Ashok Raj
  2004-04-28  1:01 ` Updated CPU hotplug patches for IA64 [Patch 2/7] Ashok Raj
  2004-04-28  1:02 ` Updated CPU hotplug patches for IA64 [Patch 3/7] Ashok Raj
@ 2004-04-28  1:04 ` Ashok Raj
  2004-04-28  1:05 ` Updated CPU hotplug patches for IA64 [Patch 5/7] Ashok Raj
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Ashok Raj @ 2004-04-28  1:04 UTC (permalink / raw)
  To: linux-ia64



Name: ia64_irq_affinity_fix.patch
Author: Ashok Raj (Intel Corporation)
Status: Tested with Hotplug CPU Code

D: irq affinity setting via /proc was forcing iosapic rte programming
D: by force. The correct way to do this is to perform this when a interrupt
D: is pending.


---

 linux-2.6.5-lhcs-root/arch/ia64/kernel/iosapic.c |   19 +++++++++++++++++++
 linux-2.6.5-lhcs-root/arch/ia64/kernel/irq.c     |   12 +++++++++---
 2 files changed, 28 insertions(+), 3 deletions(-)

diff -puN arch/ia64/kernel/irq.c~ia64_irq_affinity_fix arch/ia64/kernel/irq.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/irq.c~ia64_irq_affinity_fix	2004-04-27 17:43:36.398860154 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/irq.c	2004-04-27 17:43:36.402766406 -0700
@@ -46,7 +46,7 @@
 #include <asm/delay.h>
 #include <asm/irq.h>
 
-
+extern cpumask_t    __cacheline_aligned pending_irq_cpumask[NR_IRQS];
 
 /*
  * Linux has a controller-independent x86 interrupt architecture.
@@ -938,7 +938,9 @@ 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]);
+	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");
@@ -956,6 +958,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;
@@ -994,7 +997,10 @@ 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;
 }
 
diff -puN arch/ia64/kernel/iosapic.c~ia64_irq_affinity_fix arch/ia64/kernel/iosapic.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/iosapic.c~ia64_irq_affinity_fix	2004-04-27 17:43:36.400813280 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/iosapic.c	2004-04-27 17:43:36.402766406 -0700
@@ -98,6 +98,7 @@
 #endif
 
 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. */
 
@@ -327,6 +328,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 +359,7 @@ 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 +399,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

_

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

* Updated CPU hotplug patches for IA64 [Patch 5/7]
  2004-04-28  1:00 Updated CPU Hotplug patches for IA64 [Patch 1/7] Ashok Raj
                   ` (2 preceding siblings ...)
  2004-04-28  1:04 ` Updated CPU hotplug patches for IA64 [Patch 4/7] Ashok Raj
@ 2004-04-28  1:05 ` Ashok Raj
  2004-04-28  1:07 ` Updated CPU hotplug patches for IA64 [Patch 6/7] Ashok Raj
  2004-04-28  1:08 ` Updated CPU hotplug patches for IA64 [Patch 7/7] Ashok Raj
  5 siblings, 0 replies; 7+ messages in thread
From: Ashok Raj @ 2004-04-28  1:05 UTC (permalink / raw)
  To: linux-ia64



Name: hotcpu_ia64.patch
Author: Ashok Raj (Intel Corporation)
D: Supports basic ability to enable hotplug functions for IA64.
D: Code is just evolving, and there are several loose ends to tie up.
D:
D: What this code drop does
D: - Support logical online and offline
D: - Handles interrupt migration without loss of interrupts.
D: - Handles stress fine > 24+ hrs with make -j/ftp/rcp workloads
D: - Handles irq migration from a dying cpu without loss of interrupts.
D: What needs to be done
D: - Boot CPU removal support, with platform level authentication
D: - Putting cpu being removed in BOOT_RENDEZ mode.


---

 linux-2.6.5-lhcs-root/arch/ia64/Kconfig           |    9 +
 linux-2.6.5-lhcs-root/arch/ia64/kernel/iosapic.c  |    7 -
 linux-2.6.5-lhcs-root/arch/ia64/kernel/irq.c      |  103 +++++++++++++++++
 linux-2.6.5-lhcs-root/arch/ia64/kernel/irq_ia64.c |   60 +++++++++-
 linux-2.6.5-lhcs-root/arch/ia64/kernel/process.c  |   43 +++++++
 linux-2.6.5-lhcs-root/arch/ia64/kernel/sal.c      |   13 ++
 linux-2.6.5-lhcs-root/arch/ia64/kernel/smp.c      |   26 ++++
 linux-2.6.5-lhcs-root/arch/ia64/kernel/smpboot.c  |  130 ++++++++++++++++++++--
 linux-2.6.5-lhcs-root/arch/ia64/kernel/time.c     |    5 
 linux-2.6.5-lhcs-root/include/asm-ia64/smp.h      |    2 
 10 files changed, 381 insertions(+), 17 deletions(-)

diff -puN arch/ia64/Kconfig~hotcpu_ia64 arch/ia64/Kconfig
--- linux-2.6.5-lhcs/arch/ia64/Kconfig~hotcpu_ia64	2004-04-27 17:43:38.003353163 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/Kconfig	2004-04-27 17:43:38.018001608 -0700
@@ -367,6 +367,15 @@ config PCI_DOMAINS
 
 source "drivers/pci/Kconfig"
 
+config HOTPLUG_CPU
+    bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+    depends on SMP && HOTPLUG && EXPERIMENTAL
+	default n
+    ---help---
+      Say Y here to experiment with turning CPUs off and on.  CPUs
+      can be controlled through /sys/devices/system/cpu/cpu#
+      Say N.
+
 source "drivers/pci/hotplug/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
diff -puN arch/ia64/kernel/irq.c~hotcpu_ia64 arch/ia64/kernel/irq.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/irq.c~hotcpu_ia64	2004-04-27 17:43:38.005306289 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/irq.c	2004-04-27 17:43:38.018978171 -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.
  */
 
 /*
@@ -27,6 +33,7 @@
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
+#include <linux/cpu.h>
 #include <linux/ctype.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
@@ -35,14 +42,17 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
+#include <linux/notifier.h>
 
 #include <asm/atomic.h>
+#include <asm/cpu.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 
@@ -1006,6 +1016,99 @@ static int irq_affinity_write_proc (stru
 
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_HOTPLUG_CPU
+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;
+	irq_desc_t *desc;
+	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;
+
+		cpus_and(mask, irq_affinity[irq], cpu_online_map);
+		if (any_online_cpu(mask) = NR_CPUS) {
+			/*
+			 * 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)));
+			}
+		}
+	}
+}
+
+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);
+		}
+	}
+
+	/*
+	 * 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();
+}
+#endif
+
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
diff -puN arch/ia64/kernel/process.c~hotcpu_ia64 arch/ia64/kernel/process.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/process.c~hotcpu_ia64	2004-04-27 17:43:38.006282852 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/process.c	2004-04-27 17:43:38.019954734 -0700
@@ -7,6 +7,7 @@
 #define __KERNEL_SYSCALLS__	/* see <asm/unistd.h> */
 #include <linux/config.h>
 
+#include <linux/cpu.h>
 #include <linux/pm.h>
 #include <linux/elf.h>
 #include <linux/errno.h>
@@ -14,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/notifier.h>
 #include <linux/personality.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -22,13 +24,17 @@
 #include <linux/thread_info.h>
 #include <linux/unistd.h>
 #include <linux/efi.h>
+#include <linux/interrupt.h>
 
+#include <asm/cpu.h>
 #include <asm/delay.h>
 #include <asm/elf.h>
 #include <asm/ia32.h>
+#include <asm/irq.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/sal.h>
+#include <asm/tlbflush.h>
 #include <asm/uaccess.h>
 #include <asm/unwind.h>
 #include <asm/user.h>
@@ -180,6 +186,40 @@ default_idle (void)
 			safe_halt();
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/* We don't actually take CPU down, just spin without interrupts. */
+static inline void play_dead(void)
+{
+	extern void ia64_cpu_local_tick (void);
+	/* Ack it */
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+
+	/* We shouldn't have to disable interrupts while dead, but
+	 * some interrupts just don't seem to go away, and this makes
+	 * it "work" for testing purposes. */
+	max_xtp();
+	local_irq_disable();
+	/* Death loop */
+	while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
+		cpu_relax();
+
+	/*
+	 * Enable timer interrupts from now on
+	 * Not required if we put processor in SAL_BOOT_RENDEZ mode.
+	 */
+	local_flush_tlb_all();
+	cpu_set(smp_processor_id(), cpu_online_map);
+	wmb();
+	ia64_cpu_local_tick ();
+	local_irq_enable();
+}
+#else
+static inline void play_dead(void)
+{
+	BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 void __attribute__((noreturn))
 cpu_idle (void *unused)
 {
@@ -195,7 +235,6 @@ cpu_idle (void *unused)
 		if (!need_resched())
 			min_xtp();
 #endif
-
 		while (!need_resched()) {
 			if (mark_idle)
 				(*mark_idle)(1);
@@ -210,6 +249,8 @@ cpu_idle (void *unused)
 #endif
 		schedule();
 		check_pgt_cache();
+		if (cpu_is_offline(smp_processor_id()))
+			play_dead();
 	}
 }
 
diff -puN arch/ia64/kernel/smpboot.c~hotcpu_ia64 arch/ia64/kernel/smpboot.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/smpboot.c~hotcpu_ia64	2004-04-27 17:43:38.008235978 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/smpboot.c	2004-04-27 17:43:38.020931297 -0700
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/acpi.h>
 #include <linux/bootmem.h>
+#include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -22,10 +23,12 @@
 #include <linux/kernel.h>
 #include <linux/kernel_stat.h>
 #include <linux/mm.h>
+#include <linux/notifier.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/efi.h>
+#include <linux/percpu.h>
 
 #include <asm/atomic.h>
 #include <asm/bitops.h>
@@ -44,6 +47,7 @@
 #include <asm/ptrace.h>
 #include <asm/sal.h>
 #include <asm/system.h>
+#include <asm/tlbflush.h>
 #include <asm/unistd.h>
 
 #define SMP_DEBUG 0
@@ -75,6 +79,11 @@ extern unsigned long ia64_iobase;
 
 task_t *task_for_booting_cpu;
 
+/*
+ * State for each CPU
+ */
+DEFINE_PER_CPU(int, cpu_state);
+
 /* Bitmask of currently online CPUs */
 cpumask_t cpu_online_map;
 EXPORT_SYMBOL(cpu_online_map);
@@ -280,12 +289,16 @@ smp_callin (void)
 	cpuid = smp_processor_id();
 	phys_id = hard_smp_processor_id();
 
-	if (cpu_test_and_set(cpuid, cpu_online_map)) {
+	if (cpu_online(cpuid)) {
 		printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n",
 		       phys_id, cpuid);
 		BUG();
 	}
 
+	lock_ipi_calllock();
+	cpu_set(cpuid, cpu_online_map);
+	unlock_ipi_calllock();
+
 	smp_setup_percpu_timer();
 
 	/*
@@ -356,29 +369,51 @@ fork_by_hand (void)
 	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL, NULL);
 }
 
+struct create_idle {
+	struct task_struct *idle;
+	struct completion done;
+};
+
+void
+do_fork_idle(void *_c_idle)
+{
+	struct create_idle *c_idle = _c_idle;
+
+	c_idle->idle = fork_by_hand();
+	complete(&c_idle->done);
+}
+
 static int __devinit
 do_boot_cpu (int sapicid, int cpu)
 {
-	struct task_struct *idle;
 	int timeout;
+	struct create_idle c_idle;
+	DECLARE_WORK(work, do_fork_idle, &c_idle);
 
+	init_completion(&c_idle.done);
 	/*
 	 * We can't use kernel_thread since we must avoid to reschedule the child.
 	 */
-	idle = fork_by_hand();
-	if (IS_ERR(idle))
+	if (!keventd_up() || current_is_keventd())
+		work.func(work.data);
+	else {
+		schedule_work(&work);
+		wait_for_completion(&c_idle.done);
+	}
+
+	if (IS_ERR(c_idle.idle))
 		panic("failed fork for CPU %d", cpu);
-	wake_up_forked_process(idle);
+	wake_up_forked_process(c_idle.idle);
 
 	/*
 	 * We remove it from the pidhash and the runqueue
 	 * once we got the process:
 	 */
-	init_idle(idle, cpu);
+	init_idle(c_idle.idle, cpu);
 
-	unhash_process(idle);
+	unhash_process(c_idle.idle);
 
-	task_for_booting_cpu = idle;
+	task_for_booting_cpu = c_idle.idle;
 
 	Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
 
@@ -542,6 +577,74 @@ void __devinit smp_prepare_boot_cpu(void
 	cpu_set(smp_processor_id(), cpu_callin_map);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+extern void fixup_irqs(void);
+/* must be called with cpucontrol mutex held */
+static int __devinit cpu_enable(unsigned int cpu)
+{
+	per_cpu(cpu_state,cpu) = CPU_UP_PREPARE;
+	wmb();
+
+	while (!cpu_online(cpu))
+		cpu_relax();
+	return 0;
+}
+
+int __cpu_disable(void)
+{
+	int cpu = smp_processor_id();
+
+	/*
+	 * dont permit boot processor for now
+	 */
+	if (cpu = 0)
+		return -EBUSY;
+
+	fixup_irqs();
+	local_flush_tlb_all();
+	printk ("Disabled cpu %u\n", smp_processor_id());
+	return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	unsigned int i;
+
+	for (i = 0; i < 100; i++) {
+		/* They ack this in play_dead by setting CPU_DEAD */
+		if (per_cpu(cpu_state, cpu) = CPU_DEAD)
+		{
+			/*
+			 * TBD: Enable this when physical removal
+			 * or when we put the processor is put in
+			 * SAL_BOOT_RENDEZ mode
+			 * cpu_clear(cpu, cpu_callin_map);
+			 */
+			return;
+		}
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ/10);
+	}
+ 	printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+}
+#else /* !CONFIG_HOTPLUG_CPU */
+static int __devinit cpu_enable(unsigned int cpu)
+{
+	return 0;
+}
+
+int __cpu_disable(void)
+{
+	return -ENOSYS;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	/* We said "no" in __cpu_disable */
+	BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 void
 smp_cpus_done (unsigned int dummy)
 {
@@ -570,6 +673,17 @@ __cpu_up (unsigned int cpu)
 	if (sapicid = -1)
 		return -EINVAL;
 
+	/*
+	 * Already booted.. just enable and get outa idle lool
+	 */
+	if (cpu_isset(cpu, cpu_callin_map))
+	{
+		cpu_enable(cpu);
+		local_irq_enable();
+		while (!cpu_isset(cpu, cpu_online_map))
+			mb();
+		return 0;
+	}
 	/* Processor goes to start_secondary(), sets online flag */
 	ret = do_boot_cpu(sapicid, cpu);
 	if (ret < 0)
diff -puN arch/ia64/kernel/smp.c~hotcpu_ia64 arch/ia64/kernel/smp.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/smp.c~hotcpu_ia64	2004-04-27 17:43:38.010189104 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/smp.c	2004-04-27 17:43:38.020931297 -0700
@@ -71,10 +71,23 @@ static volatile struct call_data_struct 
 /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
 static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned;
 
+extern void cpu_halt (void);
+
+void
+lock_ipi_calllock(void)
+{
+	spin_lock_irq(&call_lock);
+}
+
+void
+unlock_ipi_calllock(void)
+{
+	spin_unlock_irq(&call_lock);
+}
+
 static void
 stop_this_cpu (void)
 {
-	extern void cpu_halt (void);
 	/*
 	 * Remove this CPU:
 	 */
@@ -84,6 +97,17 @@ stop_this_cpu (void)
 	cpu_halt();
 }
 
+void
+cpu_die(void)
+{
+	max_xtp();
+	local_irq_disable();
+	cpu_halt();
+	/* Should never be here */
+	BUG();
+	for (;;);
+}
+
 irqreturn_t
 handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
 {
diff -puN arch/ia64/kernel/time.c~hotcpu_ia64 arch/ia64/kernel/time.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/time.c~hotcpu_ia64	2004-04-27 17:43:38.011165667 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/time.c	2004-04-27 17:43:38.021907860 -0700
@@ -10,6 +10,7 @@
  */
 #include <linux/config.h>
 
+#include <linux/cpu.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -244,6 +245,10 @@ timer_interrupt (int irq, void *dev_id, 
 {
 	unsigned long new_itm;
 
+	if (unlikely(cpu_is_offline(smp_processor_id()))) {
+		return IRQ_HANDLED;
+	}
+
 	platform_timer_interrupt(irq, dev_id, regs);
 
 	new_itm = local_cpu_data->itm_next;
diff -puN include/asm-ia64/smp.h~hotcpu_ia64 include/asm-ia64/smp.h
--- linux-2.6.5-lhcs/include/asm-ia64/smp.h~hotcpu_ia64	2004-04-27 17:43:38.012142230 -0700
+++ linux-2.6.5-lhcs-root/include/asm-ia64/smp.h	2004-04-27 17:43:38.021907860 -0700
@@ -123,6 +123,8 @@ extern void smp_do_timer (struct pt_regs
 extern int smp_call_function_single (int cpuid, void (*func) (void *info), void *info,
 				     int retry, int wait);
 extern void smp_send_reschedule (int cpu);
+extern void lock_ipi_calllock(void);
+extern void unlock_ipi_calllock(void);
 
 #endif /* CONFIG_SMP */
 #endif /* _ASM_IA64_SMP_H */
diff -puN arch/ia64/kernel/iosapic.c~hotcpu_ia64 arch/ia64/kernel/iosapic.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/iosapic.c~hotcpu_ia64	2004-04-27 17:43:38.014095356 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/iosapic.c	2004-04-27 17:43:38.022884423 -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:
@@ -189,8 +191,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;
@@ -308,9 +312,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);
diff -puN arch/ia64/kernel/irq_ia64.c~hotcpu_ia64 arch/ia64/kernel/irq_ia64.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/irq_ia64.c~hotcpu_ia64	2004-04-27 17:43:38.015071919 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/irq_ia64.c	2004-04-27 17:43:38.022884423 -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/sal.c~hotcpu_ia64 arch/ia64/kernel/sal.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/sal.c~hotcpu_ia64	2004-04-27 17:43:38.017025045 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/sal.c	2004-04-27 17:43:38.022884423 -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] 7+ messages in thread

* Updated CPU hotplug patches for IA64 [Patch 6/7]
  2004-04-28  1:00 Updated CPU Hotplug patches for IA64 [Patch 1/7] Ashok Raj
                   ` (3 preceding siblings ...)
  2004-04-28  1:05 ` Updated CPU hotplug patches for IA64 [Patch 5/7] Ashok Raj
@ 2004-04-28  1:07 ` Ashok Raj
  2004-04-28  1:08 ` Updated CPU hotplug patches for IA64 [Patch 7/7] Ashok Raj
  5 siblings, 0 replies; 7+ messages in thread
From: Ashok Raj @ 2004-04-28  1:07 UTC (permalink / raw)
  To: linux-ia64



Name: ia64_palinfo.patch
Author: Ashok Raj (Intel Corporation)
Status: Tested with Hotplug CPU Code

D: Changes proc entries for cpu hotplug to be created via the cpu 
D: hotplug notifier callbacks. Also fixed a bug in the removal code
D: that did not remove proc entries as expected.


---

 linux-2.6.5-lhcs-root/arch/ia64/kernel/palinfo.c |  134 +++++++++++++++++------
 1 files changed, 104 insertions(+), 30 deletions(-)

diff -puN arch/ia64/kernel/palinfo.c~ia64_palinfo arch/ia64/kernel/palinfo.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/palinfo.c~ia64_palinfo	2004-04-27 17:43:40.668393590 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/palinfo.c	2004-04-27 17:43:40.671323279 -0700
@@ -8,11 +8,14 @@
  *
  * Copyright (C) 2000-2001, 2003 Hewlett-Packard Co
  *	Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 2004 Intel Corporation
+ *  Ashok Raj <ashok.raj@intel.com>
  *
  * 05/26/2000	S.Eranian	initial release
  * 08/21/2000	S.Eranian	updated to July 2000 PAL specs
  * 02/05/2001   S.Eranian	fixed module support
  * 10/23/2001	S.Eranian	updated pal_perf_mon_info bug fixes
+ * 03/24/2004	Ashok Raj	updated to work with CPU Hotplug
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -22,6 +25,9 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/efi.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
 
 #include <asm/pal.h>
 #include <asm/sal.h>
@@ -768,13 +774,12 @@ static palinfo_entry_t palinfo_entries[]
  * does not do recursion of deletion
  *
  * Notes:
- *	- first +1 accounts for the cpuN entry
- *	- second +1 account for toplevel palinfo
- *
+ *	- +1 accounts for the cpuN directory entry in /proc/pal
  */
-#define NR_PALINFO_PROC_ENTRIES	(NR_CPUS*(NR_PALINFO_ENTRIES+1)+1)
+#define NR_PALINFO_PROC_ENTRIES	(NR_CPUS*(NR_PALINFO_ENTRIES+1))
 
 static struct proc_dir_entry *palinfo_proc_entries[NR_PALINFO_PROC_ENTRIES];
+static struct proc_dir_entry *palinfo_dir;
 
 /*
  * This data structure is used to pass which cpu,function is being requested
@@ -888,47 +893,107 @@ palinfo_read_entry(char *page, char **st
 	return len;
 }
 
-static int __init
-palinfo_init(void)
+static void
+create_palinfo_proc_entries(unsigned int cpu)
 {
 #	define CPUSTR	"cpu%d"
 
 	pal_func_cpu_u_t f;
-	struct proc_dir_entry **pdir = palinfo_proc_entries;
-	struct proc_dir_entry *palinfo_dir, *cpu_dir;
-	int i, j;
+	struct proc_dir_entry **pdir;
+	struct proc_dir_entry *cpu_dir;
+	int j;
 	char cpustr[sizeof(CPUSTR)];
 
-	printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
-
-	palinfo_dir = proc_mkdir("pal", NULL);
 
 	/*
 	 * we keep track of created entries in a depth-first order for
 	 * cleanup purposes. Each entry is stored into palinfo_proc_entries
 	 */
-	for (i=0; i < NR_CPUS; i++) {
+	sprintf(cpustr,CPUSTR, cpu);
 
-		if (!cpu_online(i)) continue;
+	cpu_dir = proc_mkdir(cpustr, palinfo_dir);
 
-		sprintf(cpustr,CPUSTR, i);
+	f.req_cpu = cpu;
 
-		cpu_dir = proc_mkdir(cpustr, palinfo_dir);
+	/*
+	 * Compute the location to store per cpu entries
+	 * We dont store the top level entry in this list, but
+	 * remove it finally after removing all cpu entries.
+	 */
+	pdir = &palinfo_proc_entries[cpu*(NR_PALINFO_ENTRIES+1)];
+	*pdir++ = cpu_dir;
+	for (j=0; j < NR_PALINFO_ENTRIES; j++) {
+		f.func_id = j;
+		*pdir = create_proc_read_entry(
+				palinfo_entries[j].name, 0, cpu_dir,
+				palinfo_read_entry, (void *)f.value);
+		if (*pdir)
+			(*pdir)->owner = THIS_MODULE;
+		pdir++;
+	}
+}
 
-		f.req_cpu = i;
+static void
+remove_palinfo_proc_entries(unsigned int hcpu)
+{
+	int j;
+	struct proc_dir_entry *cpu_dir, **pdir;
 
-		for (j=0; j < NR_PALINFO_ENTRIES; j++) {
-			f.func_id = j;
-			*pdir = create_proc_read_entry(
-					palinfo_entries[j].name, 0, cpu_dir,
-					palinfo_read_entry, (void *)f.value);
-			if (*pdir)
-				(*pdir)->owner = THIS_MODULE;
-			pdir++;
+	pdir = &palinfo_proc_entries[hcpu*(NR_PALINFO_ENTRIES+1)];
+	cpu_dir = *pdir;
+	*pdir++=NULL;
+	for (j=0; j < (NR_PALINFO_ENTRIES); j++) {
+		if ((*pdir)) {
+			remove_proc_entry ((*pdir)->name, cpu_dir);
+			*pdir ++= NULL;
 		}
-		*pdir++ = cpu_dir;
 	}
-	*pdir = palinfo_dir;
+
+	if (cpu_dir) {
+		remove_proc_entry(cpu_dir->name, palinfo_dir);
+	}
+}
+
+static int __devinit palinfo_cpu_callback(struct notifier_block *nfb,
+								unsigned long action,
+								void *hcpu)
+{
+	unsigned int hotcpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+		create_palinfo_proc_entries(hotcpu);
+		break;
+#ifdef CONFIG_HOTPLUG_CPU
+	case CPU_DEAD:
+		remove_palinfo_proc_entries(hotcpu);
+		break;
+#endif
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block palinfo_cpu_notifier +{
+	.notifier_call = palinfo_cpu_callback,
+	.priority = 0,
+};
+
+static int __init
+palinfo_init(void)
+{
+	int i = 0;
+
+	printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
+	palinfo_dir = proc_mkdir("pal", NULL);
+
+	/* Create palinfo dirs in /proc for all online cpus */
+	for_each_online_cpu(i) {
+		create_palinfo_proc_entries(i);
+	}
+
+	/* Register for future delivery via notify registration */
+	register_cpu_notifier(&palinfo_cpu_notifier);
 
 	return 0;
 }
@@ -939,10 +1004,19 @@ palinfo_exit(void)
 	int i = 0;
 
 	/* remove all nodes: depth first pass. Could optimize this  */
-	for (i=0; i< NR_PALINFO_PROC_ENTRIES ; i++) {
-		if (palinfo_proc_entries[i])
-			remove_proc_entry (palinfo_proc_entries[i]->name, NULL);
+	for_each_online_cpu(i) {
+		remove_palinfo_proc_entries(i);
 	}
+
+	/*
+	 * Remove the top level entry finally
+	 */
+	remove_proc_entry(palinfo_dir->name, NULL);
+
+	/*
+	 * Unregister from cpu notifier callbacks
+	 */
+	unregister_cpu_notifier(&palinfo_cpu_notifier);
 }
 
 module_init(palinfo_init);

_

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

* Updated CPU hotplug patches for IA64 [Patch 7/7]
  2004-04-28  1:00 Updated CPU Hotplug patches for IA64 [Patch 1/7] Ashok Raj
                   ` (4 preceding siblings ...)
  2004-04-28  1:07 ` Updated CPU hotplug patches for IA64 [Patch 6/7] Ashok Raj
@ 2004-04-28  1:08 ` Ashok Raj
  5 siblings, 0 replies; 7+ messages in thread
From: Ashok Raj @ 2004-04-28  1:08 UTC (permalink / raw)
  To: linux-ia64



Name: cpu_present_map.patch
Author: Ashok Raj (Intel Corporation)
D: This patch adds cpu_present_map, cpu_present() and for_each_cpu_present()
D: to distinguish between possible cpu's in a system and cpu's physically
D: present in a system. Before cpu hotplug was introduced cpu_possible()
D: represented cpu's physically present in the system. With hotplug capable
D: Kernel, there is a requirement to distinguish a cpu as possible verses a 
D: CPU physically present in the system. This is required so thta when
D: smp_init() attempts to start all cpu's it should now only attempt
D: to start cpu's present in the system. When a hotplug cpu is
D: physically inserted cpu_present_map will have bits updated
D: dynamically.


---

 arch/ia64/kernel/smp.c                           |    0 
 linux-2.6.5-lhcs-root/arch/ia64/kernel/smpboot.c |   21 +++++++++++++++++++--
 linux-2.6.5-lhcs-root/fs/proc/proc_misc.c        |    4 ++--
 linux-2.6.5-lhcs-root/include/asm-ia64/cpumask.h |    1 +
 linux-2.6.5-lhcs-root/include/asm-ia64/smp.h     |    5 +++++
 linux-2.6.5-lhcs-root/include/linux/cpumask.h    |   16 ++++++++++++++++
 linux-2.6.5-lhcs-root/init/main.c                |    2 +-
 linux-2.6.5-lhcs-root/kernel/cpu.c               |    2 +-
 8 files changed, 45 insertions(+), 6 deletions(-)

diff -puN include/asm-ia64/smp.h~cpu_present include/asm-ia64/smp.h
--- linux-2.6.5-lhcs/include/asm-ia64/smp.h~cpu_present	2004-04-27 17:43:43.994567168 -0700
+++ linux-2.6.5-lhcs-root/include/asm-ia64/smp.h	2004-04-27 17:43:44.006285924 -0700
@@ -48,7 +48,12 @@ extern volatile int ia64_cpu_to_sapicid[
 
 extern unsigned long ap_wakeup_vector;
 
+#ifdef CONFIG_HOTPLUG_CPU
+extern cpumask_t cpu_possible_map;
+#define cpu_present_map phys_cpu_present_map
+#else
 #define cpu_possible_map phys_cpu_present_map
+#endif
 
 /*
  * Function to map hard smp processor id to logical id.  Slow, so don't use this in
diff -puN arch/ia64/kernel/smpboot.c~cpu_present arch/ia64/kernel/smpboot.c
--- linux-2.6.5-lhcs/arch/ia64/kernel/smpboot.c~cpu_present	2004-04-27 17:43:43.995543731 -0700
+++ linux-2.6.5-lhcs-root/arch/ia64/kernel/smpboot.c	2004-04-27 17:43:44.007262487 -0700
@@ -87,9 +87,15 @@ DEFINE_PER_CPU(int, cpu_state);
 /* Bitmask of currently online CPUs */
 cpumask_t cpu_online_map;
 EXPORT_SYMBOL(cpu_online_map);
+
 cpumask_t phys_cpu_present_map;
 EXPORT_SYMBOL(phys_cpu_present_map);
 
+#ifdef CONFIG_HOTPLUG_CPU
+cpumask_t cpu_possible_map;
+EXPORT_SYMBOL(cpu_possible_map);
+#endif
+
 /* which logical CPU number maps to which CPU (physical APIC ID) */
 volatile int ia64_cpu_to_sapicid[NR_CPUS];
 EXPORT_SYMBOL(ia64_cpu_to_sapicid);
@@ -108,6 +114,7 @@ static int __init
 nointroute (char *str)
 {
 	no_int_routing = 1;
+	printk ("no_int_routing on\n");
 	return 1;
 }
 
@@ -472,13 +479,23 @@ smp_build_cpu_map (void)
 	int sapicid, cpu, i;
 	int boot_cpu_id = hard_smp_processor_id();
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++)
+	/*
+	 * Since ACPI does not give us whats MAX cpu's
+	 * possible in the entire platform, we will just have to use
+	 * NR_CPUS set for possible map. cpu_present_map a.k.a
+	 * phys_cpu_present_map can grow based on a new cpu
+	 * becomming available to the system.
+	 */
+	cpus_clear(cpu_possible_map);
+	for (cpu=0; cpu < NR_CPUS; cpu++) {
 		ia64_cpu_to_sapicid[cpu] = -1;
+		cpu_set(cpu, cpu_possible_map);
+	}
 
 	ia64_cpu_to_sapicid[0] = boot_cpu_id;
+
 	cpus_clear(phys_cpu_present_map);
 	cpu_set(0, phys_cpu_present_map);
-
 	for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) {
 		sapicid = smp_boot_data.cpu_phys_id[i];
 		if (sapicid = boot_cpu_id)
diff -puN include/linux/cpumask.h~cpu_present include/linux/cpumask.h
--- linux-2.6.5-lhcs/include/linux/cpumask.h~cpu_present	2004-04-27 17:43:43.997496857 -0700
+++ linux-2.6.5-lhcs-root/include/linux/cpumask.h	2004-04-27 17:43:44.007262487 -0700
@@ -16,6 +16,16 @@ extern cpumask_t cpu_possible_map;
 #define cpu_online(cpu)			cpu_isset(cpu, cpu_online_map)
 #define cpu_possible(cpu)		cpu_isset(cpu, cpu_possible_map)
 
+#ifdef ARCH_HAS_CPU_PRESENT_MAP
+extern cpumask_t cpu_present_map;
+#define cpu_present(cpu)		cpu_isset(cpu, cpu_present_map)
+#define num_present_cpus()		cpus_weight(cpu_present_map)
+#else
+#define cpu_present_map			cpu_possible_map
+#define cpu_present(x)			cpu_possible(x)
+#define num_present_cpus()		num_possible_cpus()
+#endif
+
 #define for_each_cpu_mask(cpu, mask)					\
 	for (cpu = first_cpu_const(mk_cpumask_const(mask));		\
 		cpu < NR_CPUS;						\
@@ -23,13 +33,19 @@ extern cpumask_t cpu_possible_map;
 
 #define for_each_cpu(cpu) for_each_cpu_mask(cpu, cpu_possible_map)
 #define for_each_online_cpu(cpu) for_each_cpu_mask(cpu, cpu_online_map)
+#define for_each_present_cpu(cpu) for_each_cpu_mask(cpu, cpu_present_map)
 #else
 #define	cpu_online_map			cpumask_of_cpu(0)
 #define	cpu_possible_map		cpumask_of_cpu(0)
+#define cpu_present_map			cpumask_of_cpu(0)
+
 #define num_online_cpus()		1
 #define num_possible_cpus()		1
+#define num_present_cpus		1
+
 #define cpu_online(cpu)			({ BUG_ON((cpu) != 0); 1; })
 #define cpu_possible(cpu)		({ BUG_ON((cpu) != 0); 1; })
+#define cpu_present(cpu)		({ BUG_ON((cpu) != 0); 1; })
 
 #define for_each_cpu(cpu) for (cpu = 0; cpu < 1; cpu++)
 #define for_each_online_cpu(cpu) for (cpu = 0; cpu < 1; cpu++)
diff -puN init/main.c~cpu_present init/main.c
--- linux-2.6.5-lhcs/init/main.c~cpu_present	2004-04-27 17:43:43.999449983 -0700
+++ linux-2.6.5-lhcs-root/init/main.c	2004-04-27 17:43:44.007262487 -0700
@@ -360,7 +360,7 @@ static void __init smp_init(void)
 	for (i = 0; i < NR_CPUS; i++) {
 		if (num_online_cpus() >= max_cpus)
 			break;
-		if (cpu_possible(i) && !cpu_online(i)) {
+		if (cpu_possible(i) && !cpu_online(i) && cpu_present(i)) {
 			cpu_up(i);
 			j++;
 		}
diff -puN kernel/cpu.c~cpu_present kernel/cpu.c
--- linux-2.6.5-lhcs/kernel/cpu.c~cpu_present	2004-04-27 17:43:44.000426546 -0700
+++ linux-2.6.5-lhcs-root/kernel/cpu.c	2004-04-27 17:43:44.008239050 -0700
@@ -169,7 +169,7 @@ int __devinit cpu_up(unsigned int cpu)
 	if ((ret = down_interruptible(&cpucontrol)) != 0)
 		return ret;
 
-	if (cpu_online(cpu)) {
+	if (cpu_online(cpu) || !cpu_present(cpu)) {
 		ret = -EINVAL;
 		goto out;
 	}
diff -puN arch/ia64/kernel/smp.c~cpu_present arch/ia64/kernel/smp.c
diff -puN fs/proc/proc_misc.c~cpu_present fs/proc/proc_misc.c
--- linux-2.6.5-lhcs/fs/proc/proc_misc.c~cpu_present	2004-04-27 17:43:44.003356235 -0700
+++ linux-2.6.5-lhcs-root/fs/proc/proc_misc.c	2004-04-27 17:43:44.008239050 -0700
@@ -368,7 +368,7 @@ int show_stat(struct seq_file *p, void *
 	if (wall_to_monotonic.tv_nsec)
 		--jif;
 
-	for_each_cpu(i) {
+	for_each_online_cpu(i) {
 		int j;
 
 		user += kstat_cpu(i).cpustat.user;
@@ -390,7 +390,7 @@ int show_stat(struct seq_file *p, void *
 		(unsigned long long)jiffies_64_to_clock_t(iowait),
 		(unsigned long long)jiffies_64_to_clock_t(irq),
 		(unsigned long long)jiffies_64_to_clock_t(softirq));
-	for_each_cpu(i) {
+	for_each_online_cpu(i) {
 
 		/* Copy values here to work around gcc-2.95.3, gcc-2.96 */
 		user = kstat_cpu(i).cpustat.user;
diff -puN include/asm-ia64/cpumask.h~cpu_present include/asm-ia64/cpumask.h
--- linux-2.6.5-lhcs/include/asm-ia64/cpumask.h~cpu_present	2004-04-27 17:43:44.004332798 -0700
+++ linux-2.6.5-lhcs-root/include/asm-ia64/cpumask.h	2004-04-27 17:43:44.008239050 -0700
@@ -1,6 +1,7 @@
 #ifndef _ASM_IA64_CPUMASK_H
 #define _ASM_IA64_CPUMASK_H
 
+#define ARCH_HAS_CPU_PRESENT_MAP
 #include <asm-generic/cpumask.h>
 
 #endif /* _ASM_IA64_CPUMASK_H */

_

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

end of thread, other threads:[~2004-04-28  1:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-28  1:00 Updated CPU Hotplug patches for IA64 [Patch 1/7] Ashok Raj
2004-04-28  1:01 ` Updated CPU hotplug patches for IA64 [Patch 2/7] Ashok Raj
2004-04-28  1:02 ` Updated CPU hotplug patches for IA64 [Patch 3/7] Ashok Raj
2004-04-28  1:04 ` Updated CPU hotplug patches for IA64 [Patch 4/7] Ashok Raj
2004-04-28  1:05 ` Updated CPU hotplug patches for IA64 [Patch 5/7] Ashok Raj
2004-04-28  1:07 ` Updated CPU hotplug patches for IA64 [Patch 6/7] Ashok Raj
2004-04-28  1:08 ` Updated CPU hotplug patches for IA64 [Patch 7/7] Ashok Raj

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