Skip to content

Commit 88b3aac

Browse files
committed
parisc: Implement __cpu_die() and __cpu_disable() for CPU hotplugging
Add relevant code to __cpu_die() and __cpu_disable() to finally enable the CPU hotplugging features. Reset the irq count values in smp_callin() to zero before bringing up the CPU. It seems that the firmware may need up to 8 seconds to fully stop a CPU in which no other PDC calls are allowed to be made. Use a timeout __cpu_die() to accommodate for this. Use "chcpu -d 1" to bring CPU1 down, and "chcpu -e 1" to bring it up. Signed-off-by: Helge Deller <deller@gmx.de>
1 parent db2b0d7 commit 88b3aac

File tree

3 files changed

+90
-22
lines changed

3 files changed

+90
-22
lines changed

arch/parisc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ config PARISC
5656
select HAVE_ARCH_TRACEHOOK
5757
select HAVE_REGS_AND_STACK_ACCESS_API
5858
select GENERIC_SCHED_CLOCK
59+
select GENERIC_IRQ_MIGRATION if SMP
5960
select HAVE_UNSTABLE_SCHED_CLOCK if SMP
6061
select LEGACY_TIMER_TICK
6162
select CPU_NO_EFFICIENT_FFS

arch/parisc/include/asm/smp.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,7 @@ static inline void smp_send_all_nop(void) { return; }
4444

4545
#define NO_PROC_ID 0xFF /* No processor magic marker */
4646
#define ANY_PROC_ID 0xFF /* Any processor magic marker */
47-
static inline int __cpu_disable (void) {
48-
return 0;
49-
}
50-
static inline void __cpu_die (unsigned int cpu) {
51-
while(1)
52-
;
53-
}
47+
int __cpu_disable(void);
48+
void __cpu_die(unsigned int cpu);
5449

5550
#endif /* __ASM_SMP_H */

arch/parisc/kernel/smp.c

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/ftrace.h>
3131
#include <linux/cpu.h>
3232
#include <linux/kgdb.h>
33+
#include <linux/sched/hotplug.h>
3334

3435
#include <linux/atomic.h>
3536
#include <asm/current.h>
@@ -60,8 +61,6 @@ volatile struct task_struct *smp_init_current_idle_task;
6061
/* track which CPU is booting */
6162
static volatile int cpu_now_booting;
6263

63-
static int parisc_max_cpus = 1;
64-
6564
static DEFINE_PER_CPU(spinlock_t, ipi_lock);
6665

6766
enum ipi_message_type {
@@ -269,7 +268,7 @@ void arch_send_call_function_single_ipi(int cpu)
269268
/*
270269
* Called by secondaries to update state and initialize CPU registers.
271270
*/
272-
static void __init
271+
static void
273272
smp_cpu_init(int cpunum)
274273
{
275274
extern void init_IRQ(void); /* arch/parisc/kernel/irq.c */
@@ -309,7 +308,7 @@ smp_cpu_init(int cpunum)
309308
* Slaves start using C here. Indirectly called from smp_slave_stext.
310309
* Do what start_kernel() and main() do for boot strap processor (aka monarch)
311310
*/
312-
void __init smp_callin(unsigned long pdce_proc)
311+
void smp_callin(unsigned long pdce_proc)
313312
{
314313
int slave_id = cpu_now_booting;
315314

@@ -334,11 +333,28 @@ void __init smp_callin(unsigned long pdce_proc)
334333
/*
335334
* Bring one cpu online.
336335
*/
337-
int smp_boot_one_cpu(int cpuid, struct task_struct *idle)
336+
static int smp_boot_one_cpu(int cpuid, struct task_struct *idle)
338337
{
339338
const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid);
340339
long timeout;
341340

341+
#ifdef CONFIG_HOTPLUG_CPU
342+
int i;
343+
344+
/* reset irq statistics for this CPU */
345+
memset(&per_cpu(irq_stat, cpuid), 0, sizeof(irq_cpustat_t));
346+
for (i = 0; i < NR_IRQS; i++) {
347+
struct irq_desc *desc = irq_to_desc(i);
348+
349+
if (desc && desc->kstat_irqs)
350+
*per_cpu_ptr(desc->kstat_irqs, cpuid) = 0;
351+
}
352+
#endif
353+
354+
/* wait until last booting CPU has started. */
355+
while (cpu_now_booting)
356+
;
357+
342358
/* Let _start know what logical CPU we're booting
343359
** (offset into init_tasks[],cpu_data[])
344360
*/
@@ -374,7 +390,6 @@ int smp_boot_one_cpu(int cpuid, struct task_struct *idle)
374390
if(cpu_online(cpuid)) {
375391
/* Which implies Slave has started up */
376392
cpu_now_booting = 0;
377-
smp_init_current_idle_task = NULL;
378393
goto alive ;
379394
}
380395
udelay(100);
@@ -415,25 +430,82 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
415430
spin_lock_init(&per_cpu(ipi_lock, cpu));
416431

417432
init_cpu_present(cpumask_of(0));
418-
419-
parisc_max_cpus = max_cpus;
420-
if (!max_cpus)
421-
printk(KERN_INFO "SMP mode deactivated.\n");
422433
}
423434

424435

425-
void smp_cpus_done(unsigned int cpu_max)
436+
void __init smp_cpus_done(unsigned int cpu_max)
426437
{
427-
return;
428438
}
429439

430440

431441
int __cpu_up(unsigned int cpu, struct task_struct *tidle)
432442
{
433-
if (cpu != 0 && cpu < parisc_max_cpus && smp_boot_one_cpu(cpu, tidle))
434-
return -ENOSYS;
443+
if (cpu_online(cpu))
444+
return 0;
445+
446+
if (num_online_cpus() < setup_max_cpus && smp_boot_one_cpu(cpu, tidle))
447+
return -EIO;
448+
449+
return cpu_online(cpu) ? 0 : -EIO;
450+
}
451+
452+
/*
453+
* __cpu_disable runs on the processor to be shutdown.
454+
*/
455+
int __cpu_disable(void)
456+
{
457+
#ifdef CONFIG_HOTPLUG_CPU
458+
unsigned int cpu = smp_processor_id();
459+
460+
remove_cpu_topology(cpu);
461+
462+
/*
463+
* Take this CPU offline. Once we clear this, we can't return,
464+
* and we must not schedule until we're ready to give up the cpu.
465+
*/
466+
set_cpu_online(cpu, false);
467+
468+
disable_percpu_irq(IPI_IRQ);
469+
470+
irq_migrate_all_off_this_cpu();
471+
472+
flush_cache_all_local();
473+
flush_tlb_all_local(NULL);
474+
475+
/* disable all irqs, including timer irq */
476+
local_irq_disable();
477+
478+
/* wait for next timer irq ... */
479+
mdelay(1000/HZ+100);
480+
481+
/* ... and then clear all pending external irqs */
482+
set_eiem(0);
483+
mtctl(~0UL, CR_EIRR);
484+
mfctl(CR_EIRR);
485+
mtctl(0, CR_EIRR);
486+
#endif
487+
return 0;
488+
}
489+
490+
/*
491+
* called on the thread which is asking for a CPU to be shutdown -
492+
* waits until shutdown has completed, or it is timed out.
493+
*/
494+
void __cpu_die(unsigned int cpu)
495+
{
496+
pdc_cpu_rendezvous_lock();
497+
498+
if (!cpu_wait_death(cpu, 5)) {
499+
pr_crit("CPU%u: cpu didn't die\n", cpu);
500+
return;
501+
}
502+
pr_info("CPU%u: is shutting down\n", cpu);
503+
504+
/* set task's state to interruptible sleep */
505+
set_current_state(TASK_INTERRUPTIBLE);
506+
schedule_timeout((IS_ENABLED(CONFIG_64BIT) ? 8:2) * HZ);
435507

436-
return cpu_online(cpu) ? 0 : -ENOSYS;
508+
pdc_cpu_rendezvous_unlock();
437509
}
438510

439511
#ifdef CONFIG_PROC_FS

0 commit comments

Comments
 (0)