Skip to content

Commit 6213f70

Browse files
author
Russell King
committed
ARM: smp: remove arch-provided "pen_release"
Consolidating the "pen_release" stuff amongst the various SoC implementations gives credence to having a CPU holding pen for secondary CPUs. However, this is far from the truth. Many SoC implementations cargo-cult copied various bits of the pen release implementation from the initial Realview/Versatile Express implementation without understanding what it was or why it existed. The reason it existed is because these are _development_ platforms, and some board firmware is unable to individually control the startup of secondary CPUs. Moreover, they do not have a way to power down or reset secondary CPUs for hot-unplug. Hence, the pen_release implementation was designed for ARM Ltd's development platforms to provide a working implementation, even though it is very far from what is required. It was decided a while back to reduce the duplication by consolidating the "pen_release" variable, but this only made the situation worse - we have ended up with several implementations that read this variable but do not write it - again, showing the cargo-cult mentality at work, lack of proper review of new code, and in some cases a lack of testing. While it would be preferable to remove pen_release entirely from the kernel, this is not possible without help from the SoC maintainers, which seems to be lacking. However, I want to remove pen_release from arch code to remove the credence that having it gives. This patch removes pen_release from the arch code entirely, adding private per-SoC definitions for it instead, and explicitly stating that write_pen_release() is cargo-cult copied and should not be copied any further. Rename write_pen_release() in a similar fashion as well. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
1 parent 7067855 commit 6213f70

File tree

12 files changed

+56
-43
lines changed

12 files changed

+56
-43
lines changed

arch/arm/include/asm/smp.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ struct secondary_data {
6767
void *stack;
6868
};
6969
extern struct secondary_data secondary_data;
70-
extern volatile int pen_release;
7170
extern void secondary_startup(void);
7271
extern void secondary_startup_arm(void);
7372

arch/arm/kernel/smp.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,6 @@
6262
*/
6363
struct secondary_data secondary_data;
6464

65-
/*
66-
* control for which core is the next to come out of the secondary
67-
* boot "holding pen"
68-
*/
69-
volatile int pen_release = -1;
70-
7165
enum ipi_msg_type {
7266
IPI_WAKEUP,
7367
IPI_TIMER,

arch/arm/mach-exynos/headsmp.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@ ENDPROC(exynos4_secondary_startup)
3636

3737
.align 2
3838
1: .long .
39-
.long pen_release
39+
.long exynos_pen_release

arch/arm/mach-exynos/platsmp.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828

2929
extern void exynos4_secondary_startup(void);
3030

31+
/* XXX exynos_pen_release is cargo culted code - DO NOT COPY XXX */
32+
volatile int exynos_pen_release = -1;
33+
3134
#ifdef CONFIG_HOTPLUG_CPU
3235
static inline void cpu_leave_lowpower(u32 core_id)
3336
{
@@ -57,7 +60,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
5760

5861
wfi();
5962

60-
if (pen_release == core_id) {
63+
if (exynos_pen_release == core_id) {
6164
/*
6265
* OK, proper wakeup, we're done
6366
*/
@@ -228,15 +231,17 @@ void exynos_core_restart(u32 core_id)
228231
}
229232

230233
/*
231-
* Write pen_release in a way that is guaranteed to be visible to all
232-
* observers, irrespective of whether they're taking part in coherency
234+
* XXX CARGO CULTED CODE - DO NOT COPY XXX
235+
*
236+
* Write exynos_pen_release in a way that is guaranteed to be visible to
237+
* all observers, irrespective of whether they're taking part in coherency
233238
* or not. This is necessary for the hotplug code to work reliably.
234239
*/
235-
static void write_pen_release(int val)
240+
static void exynos_write_pen_release(int val)
236241
{
237-
pen_release = val;
242+
exynos_pen_release = val;
238243
smp_wmb();
239-
sync_cache_w(&pen_release);
244+
sync_cache_w(&exynos_pen_release);
240245
}
241246

242247
static DEFINE_SPINLOCK(boot_lock);
@@ -247,7 +252,7 @@ static void exynos_secondary_init(unsigned int cpu)
247252
* let the primary processor know we're out of the
248253
* pen, then head off into the C entry point
249254
*/
250-
write_pen_release(-1);
255+
exynos_write_pen_release(-1);
251256

252257
/*
253258
* Synchronise with the boot thread.
@@ -322,12 +327,12 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
322327
/*
323328
* The secondary processor is waiting to be released from
324329
* the holding pen - release it, then wait for it to flag
325-
* that it has been released by resetting pen_release.
330+
* that it has been released by resetting exynos_pen_release.
326331
*
327-
* Note that "pen_release" is the hardware CPU core ID, whereas
332+
* Note that "exynos_pen_release" is the hardware CPU core ID, whereas
328333
* "cpu" is Linux's internal ID.
329334
*/
330-
write_pen_release(core_id);
335+
exynos_write_pen_release(core_id);
331336

332337
if (!exynos_cpu_power_state(core_id)) {
333338
exynos_cpu_power_up(core_id);
@@ -376,13 +381,13 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
376381
else
377382
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
378383

379-
if (pen_release == -1)
384+
if (exynos_pen_release == -1)
380385
break;
381386

382387
udelay(10);
383388
}
384389

385-
if (pen_release != -1)
390+
if (exynos_pen_release != -1)
386391
ret = -ETIMEDOUT;
387392

388393
/*
@@ -392,7 +397,7 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
392397
fail:
393398
spin_unlock(&boot_lock);
394399

395-
return pen_release != -1 ? ret : 0;
400+
return exynos_pen_release != -1 ? ret : 0;
396401
}
397402

398403
static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)

arch/arm/mach-prima2/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <asm/mach/time.h>
1616
#include <asm/exception.h>
1717

18+
extern volatile int prima2_pen_release;
19+
1820
extern const struct smp_operations sirfsoc_smp_ops;
1921
extern void sirfsoc_secondary_startup(void);
2022
extern void sirfsoc_cpu_die(unsigned int cpu);

arch/arm/mach-prima2/headsmp.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ ENDPROC(sirfsoc_secondary_startup)
3434

3535
.align
3636
1: .long .
37-
.long pen_release
37+
.long prima2_pen_release

arch/arm/mach-prima2/hotplug.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
#include <linux/smp.h>
1212

1313
#include <asm/smp_plat.h>
14+
#include "common.h"
1415

1516
static inline void platform_do_lowpower(unsigned int cpu)
1617
{
1718
/* we put the platform to just WFI */
1819
for (;;) {
1920
__asm__ __volatile__("dsb\n\t" "wfi\n\t"
2021
: : : "memory");
21-
if (pen_release == cpu_logical_map(cpu)) {
22+
if (prima2_pen_release == cpu_logical_map(cpu)) {
2223
/*
2324
* OK, proper wakeup, we're done
2425
*/

arch/arm/mach-prima2/platsmp.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ static void __iomem *clk_base;
2424

2525
static DEFINE_SPINLOCK(boot_lock);
2626

27+
/* XXX prima2_pen_release is cargo culted code - DO NOT COPY XXX */
28+
volatile int prima2_pen_release = -1;
29+
2730
static void sirfsoc_secondary_init(unsigned int cpu)
2831
{
2932
/*
3033
* let the primary processor know we're out of the
3134
* pen, then head off into the C entry point
3235
*/
33-
pen_release = -1;
36+
prima2_pen_release = -1;
3437
smp_wmb();
3538

3639
/*
@@ -80,13 +83,13 @@ static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
8083
/*
8184
* The secondary processor is waiting to be released from
8285
* the holding pen - release it, then wait for it to flag
83-
* that it has been released by resetting pen_release.
86+
* that it has been released by resetting prima2_pen_release.
8487
*
85-
* Note that "pen_release" is the hardware CPU ID, whereas
88+
* Note that "prima2_pen_release" is the hardware CPU ID, whereas
8689
* "cpu" is Linux's internal ID.
8790
*/
88-
pen_release = cpu_logical_map(cpu);
89-
sync_cache_w(&pen_release);
91+
prima2_pen_release = cpu_logical_map(cpu);
92+
sync_cache_w(&prima2_pen_release);
9093

9194
/*
9295
* Send the secondary CPU SEV, thereby causing the boot monitor to read
@@ -97,7 +100,7 @@ static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
97100
timeout = jiffies + (1 * HZ);
98101
while (time_before(jiffies, timeout)) {
99102
smp_rmb();
100-
if (pen_release == -1)
103+
if (prima2_pen_release == -1)
101104
break;
102105

103106
udelay(10);
@@ -109,7 +112,7 @@ static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
109112
*/
110113
spin_unlock(&boot_lock);
111114

112-
return pen_release != -1 ? -ENOSYS : 0;
115+
return prima2_pen_release != -1 ? -ENOSYS : 0;
113116
}
114117

115118
const struct smp_operations sirfsoc_smp_ops __initconst = {

arch/arm/mach-spear/generic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include <asm/mach/time.h>
2222

23+
extern volatile int spear_pen_release;
24+
2325
extern void spear13xx_timer_init(void);
2426
extern void spear3xx_timer_init(void);
2527
extern struct pl022_ssp_controller pl022_plat_data;

arch/arm/mach-spear/headsmp.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,5 @@ pen: ldr r7, [r6]
4343

4444
.align
4545
1: .long .
46-
.long pen_release
46+
.long spear_pen_release
4747
ENDPROC(spear13xx_secondary_startup)

arch/arm/mach-spear/hotplug.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <asm/cp15.h>
1717
#include <asm/smp_plat.h>
1818

19+
#include "generic.h"
20+
1921
static inline void cpu_enter_lowpower(void)
2022
{
2123
unsigned int v;
@@ -57,7 +59,7 @@ static inline void spear13xx_do_lowpower(unsigned int cpu, int *spurious)
5759
for (;;) {
5860
wfi();
5961

60-
if (pen_release == cpu) {
62+
if (spear_pen_release == cpu) {
6163
/*
6264
* OK, proper wakeup, we're done
6365
*/

arch/arm/mach-spear/platsmp.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,21 @@
2020
#include <mach/spear.h>
2121
#include "generic.h"
2222

23+
/* XXX spear_pen_release is cargo culted code - DO NOT COPY XXX */
24+
volatile int spear_pen_release = -1;
25+
2326
/*
24-
* Write pen_release in a way that is guaranteed to be visible to all
25-
* observers, irrespective of whether they're taking part in coherency
27+
* XXX CARGO CULTED CODE - DO NOT COPY XXX
28+
*
29+
* Write spear_pen_release in a way that is guaranteed to be visible to
30+
* all observers, irrespective of whether they're taking part in coherency
2631
* or not. This is necessary for the hotplug code to work reliably.
2732
*/
28-
static void write_pen_release(int val)
33+
static void spear_write_pen_release(int val)
2934
{
30-
pen_release = val;
35+
spear_pen_release = val;
3136
smp_wmb();
32-
sync_cache_w(&pen_release);
37+
sync_cache_w(&spear_pen_release);
3338
}
3439

3540
static DEFINE_SPINLOCK(boot_lock);
@@ -42,7 +47,7 @@ static void spear13xx_secondary_init(unsigned int cpu)
4247
* let the primary processor know we're out of the
4348
* pen, then head off into the C entry point
4449
*/
45-
write_pen_release(-1);
50+
spear_write_pen_release(-1);
4651

4752
/*
4853
* Synchronise with the boot thread.
@@ -64,17 +69,17 @@ static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)
6469
/*
6570
* The secondary processor is waiting to be released from
6671
* the holding pen - release it, then wait for it to flag
67-
* that it has been released by resetting pen_release.
72+
* that it has been released by resetting spear_pen_release.
6873
*
69-
* Note that "pen_release" is the hardware CPU ID, whereas
74+
* Note that "spear_pen_release" is the hardware CPU ID, whereas
7075
* "cpu" is Linux's internal ID.
7176
*/
72-
write_pen_release(cpu);
77+
spear_write_pen_release(cpu);
7378

7479
timeout = jiffies + (1 * HZ);
7580
while (time_before(jiffies, timeout)) {
7681
smp_rmb();
77-
if (pen_release == -1)
82+
if (spear_pen_release == -1)
7883
break;
7984

8085
udelay(10);
@@ -86,7 +91,7 @@ static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)
8691
*/
8792
spin_unlock(&boot_lock);
8893

89-
return pen_release != -1 ? -ENOSYS : 0;
94+
return spear_pen_release != -1 ? -ENOSYS : 0;
9095
}
9196

9297
/*

0 commit comments

Comments
 (0)