From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
This series contain a number of cleanups and fixes to our CPU hotplug
code, including fixing crashes on G5 machines, properly re-initializing
idle threads etc...
Tested on PowerMac G5 and pSeries machines.
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:39
This is used by some "soft" hotplug implementations. I needs to
call idle_task_exit() when the CPU is going away, and we remove
the now no-longer needed set_cpu_online() and local_irq_enable()
which are handled by the return to start_secondary
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/smp.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:39
Use the generic code, just add the MPIC priority setting,
I don't see any use in mucking around with the decrementer,
as 32-bit will have EE off all along, and 64-bit will be able
to deal with it.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/platforms/powermac/smp.c | 17 +++++------------
1 files changed, 5 insertions(+), 12 deletions(-)
@@ -322,28 +322,6 @@ int generic_cpu_disable(void)return0;}-intgeneric_cpu_enable(unsignedintcpu)-{-/* Do the normal bootup if we haven't-*alreadybootstrapped.*/-if(system_state!=SYSTEM_RUNNING)-return-ENOSYS;--/* get the target out of it's holding state */-per_cpu(cpu_state,cpu)=CPU_UP_PREPARE;-smp_wmb();--while(!cpu_online(cpu))-cpu_relax();--#ifdef CONFIG_PPC64-fixup_irqs(cpu_online_mask);-/* counter the irq disable in fixup_irqs */-local_irq_enable();-#endif-return0;-}-voidgeneric_cpu_die(unsignedintcpu){inti;
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
With some implementations, it is possible that a timer interrupt
occurs every few seconds on an offline CPU. In this case, just
re-arm the decrementer and return immediately
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/time.c | 15 +++++++++++----
1 files changed, 11 insertions(+), 4 deletions(-)
@@ -577,14 +577,21 @@ void timer_interrupt(struct pt_regs * regs)structclock_event_device*evt=&decrementer->event;u64now;+/* Ensure a positive value is written to the decrementer, or else+*someCPUswillcontinuuetotakedecrementerexceptions+*/+set_dec(DECREMENTER_MAX);++/* Some implementations of hotplug will get timer interrupts while+*offline,justignorethese+*/+if(!cpu_online(smp_processor_id()))+return;+trace_timer_interrupt_entry(regs);__get_cpu_var(irq_stat).timer_irqs++;-/* Ensure a positive value is written to the decrementer, or else-*someCPUswillcontinuuetotakedecrementerexceptions*/-set_dec(DECREMENTER_MAX);-#if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)if(atomic_read(&ppc_n_lost_interrupts)!=0)do_IRQ(regs);
@@ -650,51 +650,6 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)returnPCI_PROBE_NORMAL;returnPCI_PROBE_DEVTREE;}--#ifdef CONFIG_HOTPLUG_CPU-/* access per cpu vars from generic smp.c */-DECLARE_PER_CPU(int,cpu_state);--staticvoidpmac64_cpu_die(void)-{-/*-*turnoffasmuchaspossible,we'llbe-*kickedoutasthiswillonlybeinvoked-*oncore99platformsfornow...-*/--printk(KERN_INFO"CPU#%d offline\n",smp_processor_id());-__get_cpu_var(cpu_state)=CPU_DEAD;-smp_wmb();--/*-*duringthepaththatleadsherepreemptionisdisabled,-*reenableitnowsothatwhencominguppreemptcountis-*zerocorrectly-*/-preempt_enable();--/*-*hard-disableinterruptsforthenon-NAPcase,theNAPcode-*needstore-enableinterrupts(butsoft-disablesthem)-*/-hard_irq_disable();--while(1){-/* let's not take timer interrupts too often ... */-set_dec(0x7fffffff);--/* should always be true at this point */-if(cpu_has_feature(CPU_FTR_CAN_NAP))-power4_cpu_offline_powersave();-else{-HMT_low();-HMT_very_low();-}-}-}-#endif /* CONFIG_HOTPLUG_CPU */-#endif /* CONFIG_PPC64 */define_machine(powermac){
@@ -878,7 +878,9 @@ static int smp_core99_cpu_disable(void)return0;}-voidpmac32_cpu_die(void)+#ifdef CONFIG_PPC32++staticvoidpmac_cpu_die(void){local_irq_disable();idle_task_exit();
@@ -889,7 +891,52 @@ void pmac32_cpu_die(void)low_cpu_die();}-#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */+#else /* CONFIG_PPC32 */++staticvoidpmac_cpu_die(void)+{+local_irq_disable();+idle_task_exit();++/*+*turnoffasmuchaspossible,we'llbe+*kickedoutasthiswillonlybeinvoked+*oncore99platformsfornow...+*/++printk(KERN_INFO"CPU#%d offline\n",smp_processor_id());+__get_cpu_var(cpu_state)=CPU_DEAD;+smp_wmb();++/*+*duringthepaththatleadsherepreemptionisdisabled,+*reenableitnowsothatwhencominguppreemptcountis+*zerocorrectly+*/+preempt_enable();++/*+*hard-disableinterruptsforthenon-NAPcase,theNAPcode+*needstore-enableinterrupts(butsoft-disablesthem)+*/+hard_irq_disable();++while(1){+/* let's not take timer interrupts too often ... */+set_dec(0x7fffffff);++/* should always be true at this point */+if(cpu_has_feature(CPU_FTR_CAN_NAP))+power4_cpu_offline_powersave();+else{+HMT_low();+HMT_very_low();+}+}+}++#endif /* else CONFIG_PPC32 */+#endif /* CONFIG_HOTPLUG_CPU *//* Core99 Macs (dual G4s and G5s) */structsmp_ops_tcore99_smp_ops={
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
Use generic cpu_state, call idle_task_exit() properly, and
remove smp_core99_cpu_die() which isn't useful, the generic
function does the job just fine.
---
arch/powerpc/include/asm/smp.h | 1 +
arch/powerpc/platforms/powermac/smp.c | 25 +++++--------------------
2 files changed, 6 insertions(+), 20 deletions(-)
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
Various thing are torn down when a CPU is hot-unplugged. That CPU
is expected to go back to start_secondary when re-plugged to re
initialize everything, such as clock sources, maps, ...
Some implementations just return from cpu_die() callback
in the idle loop when the CPU is "re-plugged". This is not enough.
We fix it using a little asm trampoline which resets the stack
and calls back into start_secondary as if we were all fresh from
boot. The trampoline already existed on ppc64, but we add it for
ppc32
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/smp.h | 1 +
arch/powerpc/kernel/head_32.S | 9 +++++++++
arch/powerpc/kernel/smp.c | 9 +++++++--
arch/powerpc/platforms/pseries/offline_states.h | 2 --
4 files changed, 17 insertions(+), 4 deletions(-)
@@ -558,7 +558,8 @@ int __devinit start_secondary(void *unused)local_irq_enable();cpu_idle();-return0;++BUG();}intsetup_profiling_timer(unsignedintmultiplier)
@@ -660,5 +661,9 @@ void cpu_die(void){if(ppc_md.cpu_die)ppc_md.cpu_die();++/* If we return, we re-enter start_secondary */+start_secondary_resume();}+#endif
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
Instead, keep it static, expose an accessor and use that from
the PowerMac code. Avoids easy namespace collisions and will
make it easier to consolidate with other implementations.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/smp.h | 2 +-
arch/powerpc/kernel/smp.c | 7 ++++++-
arch/powerpc/platforms/powermac/smp.c | 12 ++++++++----
3 files changed, 15 insertions(+), 6 deletions(-)
@@ -305,7 +305,7 @@ void __devinit smp_prepare_boot_cpu(void)#ifdef CONFIG_HOTPLUG_CPU/* State of each CPU during hotplug phases */-DEFINE_PER_CPU(int,cpu_state)={0};+staticDEFINE_PER_CPU(int,cpu_state)={0};intgeneric_cpu_disable(void){
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
This allows us to stop abusing smp_ops->setup_cpu() for cleanup
tasks that have to take place after the initial boot time CPU
bringup.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/machdep.h | 1 +
arch/powerpc/kernel/smp.c | 4 ++++
2 files changed, 5 insertions(+), 0 deletions(-)
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
Those instructions do nothing on non-threaded processors such
as 970's used on those machines.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/platforms/powermac/smp.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
@@ -928,10 +928,6 @@ static void pmac_cpu_die(void)/* should always be true at this point */if(cpu_has_feature(CPU_FTR_CAN_NAP))power4_cpu_offline_powersave();-else{-HMT_low();-HMT_very_low();-}}}
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
The generic code properly re-initializes the preempt count in the
idle thread now
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/platforms/powermac/smp.c | 7 -------
1 files changed, 0 insertions(+), 7 deletions(-)
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
Instead of creating idle threads at boot for all possible CPUs, we
create them on demand, like x86 or ARM, and we properly call init_idle
to re-initialize an idle thread when a CPU was unplugged and is now
re-plugged.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/smp.c | 100 +++++++++++++++++++++++++++++++++++----------
1 files changed, 78 insertions(+), 22 deletions(-)
@@ -57,6 +57,25 @@#define DBG(fmt...)#endif++/* Store all idle threads, this can be reused instead of creating+*anewthread.Alsoavoidscomplicatedthreaddestroyfunctionality+*foridlethreads.+*/+#ifdef CONFIG_HOTPLUG_CPU+/*+*NeededonlyforCONFIG_HOTPLUG_CPUbecause__cpuinitdatais+*removedafterinitfor!CONFIG_HOTPLUG_CPU.+*/+staticDEFINE_PER_CPU(structtask_struct*,idle_thread_array);+#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x))+#define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p))+#else+staticstructtask_struct*idle_thread_array[NR_CPUS]__cpuinitdata;+#define get_idle_for_cpu(x) (idle_thread_array[(x)])+#define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p))+#endif+structthread_info*secondary_ti;DEFINE_PER_CPU(cpumask_var_t,cpu_sibling_map);
@@ -238,23 +257,6 @@ static void __devinit smp_store_cpu_info(int id)per_cpu(cpu_pvr,id)=mfspr(SPRN_PVR);}-staticvoid__initsmp_create_idle(unsignedintcpu)-{-structtask_struct*p;--/* create a process for the processor */-p=fork_idle(cpu);-if(IS_ERR(p))-panic("failed fork for CPU %u: %li",cpu,PTR_ERR(p));-#ifdef CONFIG_PPC64-paca[cpu].__current=p;-paca[cpu].kstack=(unsignedlong)task_thread_info(p)-+THREAD_SIZE-STACK_FRAME_OVERHEAD;-#endif-current_set[cpu]=task_thread_info(p);-task_thread_info(p)->cpu=cpu;-}-void__initsmp_prepare_cpus(unsignedintmax_cpus){unsignedintcpu;
@@ -288,10 +290,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)max_cpus=NR_CPUS;elsemax_cpus=1;--for_each_possible_cpu(cpu)-if(cpu!=boot_cpuid)-smp_create_idle(cpu);}void__devinitsmp_prepare_boot_cpu(void)
@@ -355,9 +353,62 @@ void generic_set_cpu_dead(unsigned int cpu)}#endif+structcreate_idle{+structwork_structwork;+structtask_struct*idle;+structcompletiondone;+intcpu;+};++staticvoid__cpuinitdo_fork_idle(structwork_struct*work)+{+structcreate_idle*c_idle=+container_of(work,structcreate_idle,work);++c_idle->idle=fork_idle(c_idle->cpu);+complete(&c_idle->done);+}++staticint__cpuinitcreate_idle(unsignedintcpu)+{+structthread_info*ti;+structcreate_idlec_idle={+.cpu=cpu,+.done=COMPLETION_INITIALIZER_ONSTACK(c_idle.done),+};+INIT_WORK_ONSTACK(&c_idle.work,do_fork_idle);++c_idle.idle=get_idle_for_cpu(cpu);++/* We can't use kernel_thread since we must avoid to+*reschedulethechild.Weuseaworkqueuebecause+*wewanttoforkfromakernelthread,notwhatever+*userspaceprocesshappenstobetryingtoonlineus.+*/+if(!c_idle.idle){+schedule_work(&c_idle.work);+wait_for_completion(&c_idle.done);+}else+init_idle(c_idle.idle,cpu);+if(IS_ERR(c_idle.idle)){+pr_err("Failed fork for CPU %u: %li",cpu,PTR_ERR(c_idle.idle));+returnPTR_ERR(c_idle.idle);+}+ti=task_thread_info(c_idle.idle);++#ifdef CONFIG_PPC64+paca[cpu].__current=c_idle.idle;+paca[cpu].kstack=(unsignedlong)ti+THREAD_SIZE-STACK_FRAME_OVERHEAD;+#endif+ti->cpu=cpu;+current_set[cpu]=ti;++return0;+}+int__cpuinit__cpu_up(unsignedintcpu){-intc;+intrc,c;secondary_ti=current_set[cpu];
@@ -365,6 +416,11 @@ int __cpuinit __cpu_up(unsigned int cpu)(smp_ops->cpu_bootable&&!smp_ops->cpu_bootable(cpu)))return-EINVAL;+/* Make sure we have an idle thread */+rc=create_idle(cpu);+if(rc)+returnrc;+/* Make sure callin-map entry is 0 (can be leftover a CPU*hotplug*/
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
This collides with the cpu_state in our SMP code, use processor_state
instead.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/macintosh/therm_pm72.c | 60 ++++++++++++++++++++--------------------
1 files changed, 30 insertions(+), 30 deletions(-)
@@ -1833,14 +1833,14 @@ static int main_control_loop(void *x)if(cpu_pid_type==CPU_PID_TYPE_COMBINED)do_monitor_cpu_combined();elseif(cpu_pid_type==CPU_PID_TYPE_RACKMAC){-do_monitor_cpu_rack(&cpu_state[0]);-if(cpu_state[1].monitor!=NULL)-do_monitor_cpu_rack(&cpu_state[1]);+do_monitor_cpu_rack(&processor_state[0]);+if(processor_state[1].monitor!=NULL)+do_monitor_cpu_rack(&processor_state[1]);// better deal with UP}else{-do_monitor_cpu_split(&cpu_state[0]);-if(cpu_state[1].monitor!=NULL)-do_monitor_cpu_split(&cpu_state[1]);+do_monitor_cpu_split(&processor_state[0]);+if(processor_state[1].monitor!=NULL)+do_monitor_cpu_split(&processor_state[1]);// better deal with UP}/* Then, the rest */
@@ -1885,8 +1885,8 @@ static int main_control_loop(void *x)*/staticvoiddispose_control_loops(void){-dispose_cpu_state(&cpu_state[0]);-dispose_cpu_state(&cpu_state[1]);+dispose_processor_state(&processor_state[0]);+dispose_processor_state(&processor_state[1]);dispose_backside_state(&backside_state);dispose_drives_state(&drives_state);dispose_slots_state(&slots_state);
@@ -1928,12 +1928,12 @@ static int create_control_loops(void)/* Create control loops for everything. If any fail, everything*fails*/-if(init_cpu_state(&cpu_state[0],0))+if(init_processor_state(&processor_state[0],0))gotofail;if(cpu_pid_type==CPU_PID_TYPE_COMBINED)fetch_cpu_pumps_minmax();-if(cpu_count>1&&init_cpu_state(&cpu_state[1],1))+if(cpu_count>1&&init_processor_state(&processor_state[1],1))gotofail;if(init_backside_state(&backside_state))gotofail;
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:40
On some machines that use i2c to synchronize the timebases (such
as PowerMac7,2/7,3 G5 machines), hotplug CPU would crash when
putting back a new CPU online due to the underlying i2c bus being
closed.
This uses the newly added bringup_done() callback to move the close
along with other housekeeping calls, and adds a CPU notifier to
re-open the i2c bus around subsequent hotplug operations
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/platforms/powermac/smp.c | 71 +++++++++++++++++++++++++-------
1 files changed, 55 insertions(+), 16 deletions(-)
@@ -840,30 +840,68 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)/* Setup openpic */mpic_setup_this_cpu();+}-if(cpu_nr==0){-#ifdef CONFIG_PPC64-externvoidg5_phy_disable_cpu1(void);+#ifdef CONFIG_HOTPLUG_CPU+staticintsmp_core99_cpu_notify(structnotifier_block*self,+unsignedlongaction,void*hcpu)+{+intrc;-/* Close i2c bus if it was used for tb sync */+switch(action){+caseCPU_UP_PREPARE:+caseCPU_UP_PREPARE_FROZEN:+/* Open i2c bus if it was used for tb sync */if(pmac_tb_clock_chip_host){-pmac_i2c_close(pmac_tb_clock_chip_host);-pmac_tb_clock_chip_host=NULL;+rc=pmac_i2c_open(pmac_tb_clock_chip_host,1);+if(rc){+pr_err("Failed to open i2c bus for time sync\n");+returnnotifier_from_errno(rc);+}}+break;+caseCPU_ONLINE:+caseCPU_UP_CANCELED:+/* Close i2c bus if it was used for tb sync */+if(pmac_tb_clock_chip_host)+pmac_i2c_close(pmac_tb_clock_chip_host);+break;+default:+break;+}+returnNOTIFY_OK;+}-/* If we didn't start the second CPU, we must take-*itoffthebus-*/-if(of_machine_is_compatible("MacRISC4")&&-num_online_cpus()<2)-g5_phy_disable_cpu1();-#endif /* CONFIG_PPC64 */+staticstructnotifier_block__cpuinitdatasmp_core99_cpu_nb={+.notifier_call=smp_core99_cpu_notify,+};+#endif /* CONFIG_HOTPLUG_CPU */-if(ppc_md.progress)-ppc_md.progress("core99_setup_cpu 0 done",0x349);+staticvoid__initsmp_core99_bringup_done(void)+{+#ifdef CONFIG_PPC64+externvoidg5_phy_disable_cpu1(void);++/* Close i2c bus if it was used for tb sync */+if(pmac_tb_clock_chip_host)+pmac_i2c_close(pmac_tb_clock_chip_host);++/* If we didn't start the second CPU, we must take+*itoffthebus.+*/+if(of_machine_is_compatible("MacRISC4")&&+num_online_cpus()<2){+set_cpu_present(1,false);+g5_phy_disable_cpu1();}-}+#endif /* CONFIG_PPC64 */+#ifdef CONFIG_HOTPLUG_CPU+register_cpu_notifier(&smp_core99_cpu_nb);+#endif+if(ppc_md.progress)+ppc_md.progress("smp_core99_bringup_done",0x349);+}#ifdef CONFIG_HOTPLUG_CPU
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-08 06:37:42
The current code soft-disables, and then goes to NAP mode which
turns interrupts on. That means that if an interrupt occurs, we
will hit the masked interrupt code path which isn't what we want,
as it will return with EE off, which will either get us out of
NAP mode, or fail to enter it (according to spec).
Instead, let's just rely on the fact that it is safe to take
decrementer interrupts on an offline CPU and leave interrupts
enabled. We can also get rid of the special case in asm for
power4_cpu_offline_powersave() and just use power4_idle().
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/machdep.h | 1 -
arch/powerpc/kernel/head_64.S | 7 +++++++
arch/powerpc/kernel/idle_power4.S | 21 ---------------------
arch/powerpc/platforms/powermac/smp.c | 14 ++++++++------
4 files changed, 15 insertions(+), 28 deletions(-)
@@ -916,18 +916,20 @@ static void pmac_cpu_die(void)preempt_enable();/*-*hard-disableinterruptsforthenon-NAPcase,theNAPcode-*needstore-enableinterrupts(butsoft-disablesthem)+*Re-enableinterrupts.TheNAPcodeneedstoenablethem+*anyways,doitnowsowedealwiththecasewhereonealready+*happenedwhilesoft-disabled.+*Weshouldn'tgetanyexternalinterrupts,onlydecrementer,andthe+*decrementerhandlerissafeforuseonofflineCPUs*/-hard_irq_disable();+local_irq_enable();while(1){/* let's not take timer interrupts too often ... */set_dec(0x7fffffff);-/* should always be true at this point */-if(cpu_has_feature(CPU_FTR_CAN_NAP))-power4_cpu_offline_powersave();+/* Enter NAP mode */+power4_idle();}}
So the SYSTEM_RUNNING check is to avoid clashing with the logic in
smp_setup_cpu_maps() I presume:
arch/powerpc/kernel/setup-common.c: vdso_data->processorCount = num_present_cpus();
But why not remove that, and let the increment in start_secondary() do
all the work?
With the current code if a cpu is present but fails to come up the count
will be wrong I think.
cheers
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-03-10 03:46:10
On Thu, 2011-03-10 at 14:41 +1100, Michael Ellerman wrote:
So the SYSTEM_RUNNING check is to avoid clashing with the logic in
smp_setup_cpu_maps() I presume:
arch/powerpc/kernel/setup-common.c: vdso_data->processorCount = num_present_cpus();
But why not remove that, and let the increment in start_secondary() do
all the work?
With the current code if a cpu is present but fails to come up the count
will be wrong I think.
I agree, on the other hand I'm worried about the way that things it
used in lparcfg.c (which looks bogus regardless) and it's not clear
to me what userspace uses it for (I bet some "licencing" stuff :-)
The lparcfg bit looks like something that should turn into counting
possible processors I suppose but it's hard to tell.
Cheers,
Ben.
From: Michael Ellerman <hidden> Date: 2011-03-10 08:01:08
On Tue, 2011-03-08 at 17:37 +1100, Benjamin Herrenschmidt wrote:
quoted hunk
With some implementations, it is possible that a timer interrupt
occurs every few seconds on an offline CPU. In this case, just
re-arm the decrementer and return immediately
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/time.c | 15 +++++++++++----
1 files changed, 11 insertions(+), 4 deletions(-)
@@ -577,14 +577,21 @@ void timer_interrupt(struct pt_regs * regs)structclock_event_device*evt=&decrementer->event;u64now;+/* Ensure a positive value is written to the decrementer, or else+*someCPUswillcontinuuetotakedecrementerexceptions
^
Seeing as you're moving it anyway, and maybe a full-stop.
cheers
From: Michael Ellerman <hidden> Date: 2011-03-29 05:37:20
On Tue, 2011-03-08 at 17:37 +1100, Benjamin Herrenschmidt wrote:
quoted hunk
Instead, keep it static, expose an accessor and use that from
the PowerMac code. Avoids easy namespace collisions and will
make it easier to consolidate with other implementations.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/smp.h | 2 +-
arch/powerpc/kernel/smp.c | 7 ++++++-
arch/powerpc/platforms/powermac/smp.c | 12 ++++++++----
3 files changed, 15 insertions(+), 6 deletions(-)