2013-10-31 16:10:30

by Soren Brinkmann

[permalink] [raw]
Subject: [PATCH 0/6] arm: zynq: BSP update

These are a few updates and fixes for the Zynq BSP coming
cherry-picked/ported from the Xilinx vendor tree.

Sören

Michal Simek (1):
arm: zynq: Add support for zynq_cpu_kill function

Peter Crosthwaite (1):
arm: zynq: platsmp: Fix CPU presence check

Soren Brinkmann (4):
arm: zynq: Invalidate L1 in secondary boot
arm: zynq: Use of_platform_populate instead of bus_probe
arm: zynq: Set proper GIC flags
arm: zynq: headsmp: Move .glbl out of actual code

arch/arm/mach-zynq/common.c | 16 ++++++++++------
arch/arm/mach-zynq/common.h | 2 ++
arch/arm/mach-zynq/headsmp.S | 11 ++++++++---
arch/arm/mach-zynq/platsmp.c | 13 +++++++++++--
4 files changed, 31 insertions(+), 11 deletions(-)

--
1.8.4.1


2013-10-31 16:10:34

by Soren Brinkmann

[permalink] [raw]
Subject: [PATCH 1/6] arm: zynq: platsmp: Fix CPU presence check

From: Peter Crosthwaite <[email protected]>

Fix an off-by-one error in the logic that checks if a CPU is present.
The ncores variable is a count of cores while the cpu variable is a
0 based index. So if ncores == cpu, cpu is out of range. Fix this
comparison so non-existent CPUs are not probed.

Signed-off-by: Peter Crosthwaite <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/arm/mach-zynq/platsmp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index 689fbbc3d9c8..2512624e657d 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -39,7 +39,7 @@ int zynq_cpun_start(u32 address, int cpu)
u32 trampoline_code_size = &zynq_secondary_trampoline_end -
&zynq_secondary_trampoline;

- if (cpu > ncores) {
+ if (cpu >= ncores) {
pr_warn("CPU No. is not available in the system\n");
return -1;
}
--
1.8.4.1

2013-10-31 16:10:39

by Soren Brinkmann

[permalink] [raw]
Subject: [PATCH 2/6] arm: zynq: Invalidate L1 in secondary boot

During boot, Linux initiates a clean-invalidate operation only, resulting
in faulty data to be written to the memory system during resume.
Therefore invalidate the L1 in the secondary boot path to avoid these
issues.

Signed-off-by: Soren Brinkmann <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/arm/mach-zynq/common.h | 2 ++
arch/arm/mach-zynq/headsmp.S | 6 +++++-
arch/arm/mach-zynq/platsmp.c | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index 3040d219570f..c22c92cea8cb 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -17,6 +17,8 @@
#ifndef __MACH_ZYNQ_COMMON_H__
#define __MACH_ZYNQ_COMMON_H__

+void zynq_secondary_startup(void);
+
extern int zynq_slcr_init(void);
extern void zynq_slcr_system_reset(void);
extern void zynq_slcr_cpu_stop(int cpu);
diff --git a/arch/arm/mach-zynq/headsmp.S b/arch/arm/mach-zynq/headsmp.S
index d4cd5f34fe5c..57a32869f0aa 100644
--- a/arch/arm/mach-zynq/headsmp.S
+++ b/arch/arm/mach-zynq/headsmp.S
@@ -18,5 +18,9 @@ zynq_secondary_trampoline_jump:
.word /* cpu 1 */
.globl zynq_secondary_trampoline_end
zynq_secondary_trampoline_end:
-
ENDPROC(zynq_secondary_trampoline)
+
+ENTRY(zynq_secondary_startup)
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(zynq_secondary_startup)
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index 2512624e657d..daed70682c54 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -95,7 +95,7 @@ EXPORT_SYMBOL(zynq_cpun_start);
static int zynq_boot_secondary(unsigned int cpu,
struct task_struct *idle)
{
- return zynq_cpun_start(virt_to_phys(secondary_startup), cpu);
+ return zynq_cpun_start(virt_to_phys(zynq_secondary_startup), cpu);
}

/*
--
1.8.4.1

2013-10-31 16:10:51

by Soren Brinkmann

[permalink] [raw]
Subject: [PATCH 3/6] arm: zynq: Add support for zynq_cpu_kill function

From: Michal Simek <[email protected]>

Use simple hook to slcr to stop cpu.

Signed-off-by: Michal Simek <[email protected]>
---
arch/arm/mach-zynq/platsmp.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index daed70682c54..4f592a7efc10 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -126,11 +126,20 @@ static void __init zynq_smp_prepare_cpus(unsigned int max_cpus)
scu_enable(zynq_scu_base);
}

+#ifdef CONFIG_HOTPLUG_CPU
+static int zynq_cpu_kill(unsigned cpu)
+{
+ zynq_slcr_cpu_stop(cpu);
+ return 1;
+}
+#endif
+
struct smp_operations zynq_smp_ops __initdata = {
.smp_init_cpus = zynq_smp_init_cpus,
.smp_prepare_cpus = zynq_smp_prepare_cpus,
.smp_boot_secondary = zynq_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = zynq_platform_cpu_die,
+ .cpu_kill = zynq_cpu_kill,
#endif
};
--
1.8.4.1

2013-10-31 16:11:15

by Soren Brinkmann

[permalink] [raw]
Subject: [PATCH 4/6] arm: zynq: Use of_platform_populate instead of bus_probe

All new boards should be using this function instead of
of_platform_bus_probe.

Two side effects:
1. Possible to probe node which are not in the bus
2. Remove bus_id table from platform code

Signed-off-by: Soren Brinkmann <[email protected]>
---
arch/arm/mach-zynq/common.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 5f252569c689..5690925519bf 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -39,11 +39,6 @@

void __iomem *zynq_scu_base;

-static struct of_device_id zynq_of_bus_ids[] __initdata = {
- { .compatible = "simple-bus", },
- {}
-};
-
/**
* zynq_init_machine - System specific initialization, intended to be
* called from board specific initialization.
@@ -55,7 +50,7 @@ static void __init zynq_init_machine(void)
*/
l2x0_of_init(0x02060000, 0xF0F0FFFF);

- of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}

static void __init zynq_timer_init(void)
--
1.8.4.1

2013-10-31 16:11:20

by Soren Brinkmann

[permalink] [raw]
Subject: [PATCH 6/6] arm: zynq: headsmp: Move .glbl out of actual code

Move the .glbl lines exporting symbols to the top of the file and out of
the actual code, in order to make the code more readable.

Signed-off-by: Soren Brinkmann <[email protected]>
---
arch/arm/mach-zynq/headsmp.S | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-zynq/headsmp.S b/arch/arm/mach-zynq/headsmp.S
index 57a32869f0aa..12d1b40c7d78 100644
--- a/arch/arm/mach-zynq/headsmp.S
+++ b/arch/arm/mach-zynq/headsmp.S
@@ -9,14 +9,15 @@
#include <linux/linkage.h>
#include <linux/init.h>

+.globl zynq_secondary_trampoline_jump
+.globl zynq_secondary_trampoline_end
+
ENTRY(zynq_secondary_trampoline)
ldr r0, [pc]
bx r0
-.globl zynq_secondary_trampoline_jump
zynq_secondary_trampoline_jump:
/* Space for jumping address */
.word /* cpu 1 */
-.globl zynq_secondary_trampoline_end
zynq_secondary_trampoline_end:
ENDPROC(zynq_secondary_trampoline)

--
1.8.4.1

2013-10-31 16:11:43

by Soren Brinkmann

[permalink] [raw]
Subject: [PATCH 5/6] arm: zynq: Set proper GIC flags

Zynq is able to wake up on any IRQ, so flag it with
IRQCHIP_SKIP_SET_WAKE, and we want to mask off the IRQs when
going to suspend to avoid transient effects so also flag
this with IRQCHIP_MASK_ON_SUSPEND.

This is essentially, making the same changes as commit
'ARM: ux500: set proper GIC flags'
(sha1: 7e1f97ea8ffa66679252520dbbbd6ec413ecae68) for Zynq.

Signed-off-by: Soren Brinkmann <[email protected]>
---
arch/arm/mach-zynq/common.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 5690925519bf..eb59bae37c04 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -25,6 +25,8 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/of.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -86,6 +88,12 @@ static void __init zynq_map_io(void)
zynq_scu_map_io();
}

+static void __init zynq_irq_init(void)
+{
+ gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
+ irqchip_init();
+}
+
static void zynq_system_reset(enum reboot_mode mode, const char *cmd)
{
zynq_slcr_system_reset();
@@ -99,6 +107,7 @@ static const char * const zynq_dt_match[] = {
DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
.smp = smp_ops(zynq_smp_ops),
.map_io = zynq_map_io,
+ .init_irq = zynq_irq_init,
.init_machine = zynq_init_machine,
.init_time = zynq_timer_init,
.dt_compat = zynq_dt_match,
--
1.8.4.1

2013-10-31 16:17:52

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH 1/6] arm: zynq: platsmp: Fix CPU presence check

On Thu, Oct 31, 2013 at 09:10:14AM -0700, Soren Brinkmann wrote:
> From: Peter Crosthwaite <[email protected]>
>
> Fix an off-by-one error in the logic that checks if a CPU is present.
> The ncores variable is a count of cores while the cpu variable is a
> 0 based index. So if ncores == cpu, cpu is out of range. Fix this
> comparison so non-existent CPUs are not probed.
>
> Signed-off-by: Peter Crosthwaite <[email protected]>
> Signed-off-by: Michal Simek <[email protected]>

There's another two bugs here.

> ---
> arch/arm/mach-zynq/platsmp.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
> index 689fbbc3d9c8..2512624e657d 100644
> --- a/arch/arm/mach-zynq/platsmp.c
> +++ b/arch/arm/mach-zynq/platsmp.c
> @@ -39,7 +39,7 @@ int zynq_cpun_start(u32 address, int cpu)
> u32 trampoline_code_size = &zynq_secondary_trampoline_end -
> &zynq_secondary_trampoline;
>
> - if (cpu > ncores) {
> + if (cpu >= ncores) {
> pr_warn("CPU No. is not available in the system\n");

Much better: pr_warn("CPU%d is not available\n", cpu);

However, if you have set the cpu possible/present masks correctly,
you will never hit this because the generic code already checks that
the CPU being requested is legal. So actually I'd suggest getting
rid of this entire if() statement and block.

> return -1;

The second issue is one of laziness. -1 as a return code for something
that gets propagated back to userspace. Do we really mean to return to
userspace -EPERM because of this or other failures in this function?
All those idiotic and lazy (and that's exactly what they are - idiotic
and lazy) "return -1" statements need to be fixed.

Shame on the arm-soc maintainers for not having an automatic filter for
this kind of sloppy programming.

2013-10-31 16:42:43

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: Re: [PATCH 1/6] arm: zynq: platsmp: Fix CPU presence check

Hi Soren,

On 31/10/13 16:10, Soren Brinkmann wrote:
> From: Peter Crosthwaite <[email protected]>
>
> Fix an off-by-one error in the logic that checks if a CPU is present.
> The ncores variable is a count of cores while the cpu variable is a
> 0 based index. So if ncores == cpu, cpu is out of range. Fix this
> comparison so non-existent CPUs are not probed.
>

Not entirely related to this patch, I had found that zynq_smp_prepare_cpus is
setting cpu_present_mask which is redundant(CMIIW present == possible). I had
posted a patch[1] to remove that, consider including that in the series if you
think it make sense.

Regards,
Sudeep

[1] http://www.spinics.net/lists/arm-kernel/msg260734.html

> Signed-off-by: Peter Crosthwaite <[email protected]>
> Signed-off-by: Michal Simek <[email protected]>
> ---
> arch/arm/mach-zynq/platsmp.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
> index 689fbbc3d9c8..2512624e657d 100644
> --- a/arch/arm/mach-zynq/platsmp.c
> +++ b/arch/arm/mach-zynq/platsmp.c
> @@ -39,7 +39,7 @@ int zynq_cpun_start(u32 address, int cpu)
> u32 trampoline_code_size = &zynq_secondary_trampoline_end -
> &zynq_secondary_trampoline;
>
> - if (cpu > ncores) {
> + if (cpu >= ncores) {
> pr_warn("CPU No. is not available in the system\n");
> return -1;
> }
>

2013-10-31 17:37:37

by Soren Brinkmann

[permalink] [raw]
Subject: [PATCH] arm: zynq: platsmp: Remove CPU presence check

The generic code already checks that the CPU being requested is legal if
the cpu possible/present masks are set correctly.

Cc: Russell King <[email protected]>
Signed-off-by: Soren Brinkmann <[email protected]>
---
As per Russel's suggestion, consider this alternative for 1/6.

Sören

arch/arm/mach-zynq/platsmp.c | 5 -----
1 file changed, 5 deletions(-)

diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index bc730eb38f00..8021499e7b70 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -39,11 +39,6 @@ int zynq_cpun_start(u32 address, int cpu)
u32 trampoline_code_size = &zynq_secondary_trampoline_end -
&zynq_secondary_trampoline;

- if (cpu > ncores) {
- pr_warn("CPU No. is not available in the system\n");
- return -1;
- }
-
/* MS: Expectation that SLCR are directly map and accessible */
/* Not possible to jump to non aligned address */
if (!(address & 3) && (!address || (address >= trampoline_code_size))) {
--
1.8.4.1