Message ID | 20150917063300.26016.23728.sendpatchset@little-apple (mailing list archive) |
---|---|
State | RFC |
Delegated to: | Simon Horman |
Headers | show |
Hi Magnus, On Thu, Sep 17, 2015 at 8:33 AM, Magnus Damm <magnus.damm@gmail.com> wrote: > --- 0001/arch/arm/mach-shmobile/platsmp-apmu.c > +++ work/arch/arm/mach-shmobile/platsmp-apmu.c 2015-09-16 20:46:23.400513000 +0900 > @@ -24,6 +24,7 @@ > #include <asm/suspend.h> > #include "common.h" > #include "platsmp-apmu.h" > +#include "rcar-gen2.h" > > static struct { > void __iomem *iomem; > @@ -117,15 +118,67 @@ static void apmu_parse_cfg(void (*fn)(st > } > } > > -void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus, > - struct rcar_apmu_config *apmu_config, > - int num) > +static const struct of_device_id apmu_ids[] = { > + { .compatible = "renesas,apmu" }, > + { /*sentinel*/ } > +}; > + > +static void apmu_parse_dt(void (*fn)(struct resource *res, int cpu, int bit)) > +{ > + struct device_node *np_apmu, *np_cpu; > + struct resource res; > + u32 id; > + int bit, index; > + > + for_each_matching_node(np_apmu, apmu_ids) { > + /* only enable the cluster that includes the boot CPU */ > + bool is_allowed = false; > + for (bit = 0; bit < CONFIG_NR_CPUS; bit++) { > + np_cpu = of_parse_phandle(np_apmu, "cpus", bit); > + if (np_cpu) { > + if (!of_property_read_u32(np_cpu, "reg", &id)) { > + if (id == cpu_logical_map(0)) { > + is_allowed = true; > + of_node_put(np_cpu); > + break; > + } > + Trailing whitespace (thanks, checkpatch.pl!) > + } > + of_node_put(np_cpu); > + } > + } > + if (!is_allowed) > + continue; > + > + for (bit = 0; bit < CONFIG_NR_CPUS; bit++) { > + np_cpu = of_parse_phandle(np_apmu, "cpus", bit); > + if (np_cpu) { > + if (!of_property_read_u32(np_cpu, "reg", &id)) { > + index = get_logical_index(id); > + if ((index >= 0) && > + !of_address_to_resource(np_apmu, > + 0, &res)) > + fn(&res, index, bit); > + } > + of_node_put(np_cpu); > + } > + } > + of_node_put(np_apmu); ERROR: Bad of_node_put() on /apmu@e6152000 CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.3.0-rc3-koelsch-02290-gca074b0726212a2f #1797 Hardware name: Generic R8A7791 (Flattened Device Tree) [<c0017e9c>] (unwind_backtrace) from [<c00139f8>] (show_stack+0x10/0x14) [<c00139f8>] (show_stack) from [<c01efd24>] (dump_stack+0x70/0x8c) [<c01efd24>] (dump_stack) from [<c01f1eec>] (kobject_release+0x12c/0x19c) [<c01f1eec>] (kobject_release) from [<c032a89c>] (of_find_matching_node_and_match+0x78/0x90) [<c032a89c>] (of_find_matching_node_and_match) from [<c062e424>] (shmobile_smp_apmu_prepare_cpus_dt+0x150/0x178) [<c062e424>] (shmobile_smp_apmu_prepare_cpus_dt) from [<c0626c98>] (kernel_init_freeable+0x60/0x1e4) for_each_matching_node() takes care of calling of_node_put() on each element iterated over, cfr. of_find_matching_node_and_match(). > + } Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Magnus, On Thu, Sep 17, 2015 at 8:33 AM, Magnus Damm <magnus.damm@gmail.com> wrote: > --- 0001/arch/arm/mach-shmobile/platsmp-apmu.c > +++ work/arch/arm/mach-shmobile/platsmp-apmu.c 2015-09-16 20:46:23.400513000 +0900 > +static void __init shmobile_smp_apmu_prepare_cpus_dt(unsigned int max_cpus) > +{ > + shmobile_smp_apmu_setup_boot(); > + apmu_parse_dt(apmu_init_cpu); > + rcar_gen2_pm_init(); > +} The non-DT code in arch/arm/mach-shmobile/smp-r8a7790.c has two calls to rcar_sysc_power_up() here, cfr.: static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus) { /* let APMU code install data related to shmobile_boot_vector */ shmobile_smp_apmu_prepare_cpus(max_cpus, r8a7790_apmu_config, ARRAY_SIZE(r8a7790_apmu_config)); /* turn on power to SCU */ rcar_gen2_pm_init(); ===> rcar_sysc_power_up(&r8a7790_ca15_scu); ===> rcar_sysc_power_up(&r8a7790_ca7_scu); } The non-DT code in arch/arm/mach-shmobile/smp-r8a7791.c does not have such a call for its CA15 cluster. Does that mean they're not needed on Gen2 in general, and that they can be removed? I'd be happy to hear a confirming answer, as it's one less dependency on SYSC PM Domains in early SMP code ;-) Ah, this is because r8a7790 can boot from either CA15 or CA7, and only the SCU for the boot CPU is powered up (r8a7791 has only one cluster/SCU, so it's always the one with the boot CPU)? Note that on r8a7779 we're also stuck with this dependency, as r8a7779 uses SYSC instead of APMU for secondary core control. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
--- 0001/arch/arm/mach-shmobile/platsmp-apmu.c +++ work/arch/arm/mach-shmobile/platsmp-apmu.c 2015-09-16 20:46:23.400513000 +0900 @@ -24,6 +24,7 @@ #include <asm/suspend.h> #include "common.h" #include "platsmp-apmu.h" +#include "rcar-gen2.h" static struct { void __iomem *iomem; @@ -117,15 +118,67 @@ static void apmu_parse_cfg(void (*fn)(st } } -void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus, - struct rcar_apmu_config *apmu_config, - int num) +static const struct of_device_id apmu_ids[] = { + { .compatible = "renesas,apmu" }, + { /*sentinel*/ } +}; + +static void apmu_parse_dt(void (*fn)(struct resource *res, int cpu, int bit)) +{ + struct device_node *np_apmu, *np_cpu; + struct resource res; + u32 id; + int bit, index; + + for_each_matching_node(np_apmu, apmu_ids) { + /* only enable the cluster that includes the boot CPU */ + bool is_allowed = false; + for (bit = 0; bit < CONFIG_NR_CPUS; bit++) { + np_cpu = of_parse_phandle(np_apmu, "cpus", bit); + if (np_cpu) { + if (!of_property_read_u32(np_cpu, "reg", &id)) { + if (id == cpu_logical_map(0)) { + is_allowed = true; + of_node_put(np_cpu); + break; + } + + } + of_node_put(np_cpu); + } + } + if (!is_allowed) + continue; + + for (bit = 0; bit < CONFIG_NR_CPUS; bit++) { + np_cpu = of_parse_phandle(np_apmu, "cpus", bit); + if (np_cpu) { + if (!of_property_read_u32(np_cpu, "reg", &id)) { + index = get_logical_index(id); + if ((index >= 0) && + !of_address_to_resource(np_apmu, + 0, &res)) + fn(&res, index, bit); + } + of_node_put(np_cpu); + } + } + of_node_put(np_apmu); + } +} + +static void __init shmobile_smp_apmu_setup_boot(void) { /* install boot code shared by all CPUs */ shmobile_boot_fn = virt_to_phys(shmobile_smp_boot); shmobile_boot_arg = MPIDR_HWID_BITMASK; +} - /* perform per-cpu setup */ +void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus, + struct rcar_apmu_config *apmu_config, + int num) +{ + shmobile_smp_apmu_setup_boot(); apmu_parse_cfg(apmu_init_cpu, apmu_config, num); } @@ -236,3 +289,34 @@ void __init shmobile_smp_apmu_suspend_in shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend; } #endif + +static void __init shmobile_smp_apmu_prepare_cpus_dt(unsigned int max_cpus) +{ + shmobile_smp_apmu_setup_boot(); + apmu_parse_dt(apmu_init_cpu); + rcar_gen2_pm_init(); +} + +static int shmobile_smp_apmu_boot_secondary_md21(unsigned int cpu, + struct task_struct *idle) +{ + /* Error out when hardware debug mode is enabled */ + if (rcar_gen2_read_mode_pins() & BIT(21)) { + pr_warn("Unable to boot CPU%u when MD21 is set\n", cpu); + return -ENOTSUPP; + } + + return shmobile_smp_apmu_boot_secondary(cpu, idle); +} + +static struct smp_operations apmu_smp_ops __initdata = { + .smp_prepare_cpus = shmobile_smp_apmu_prepare_cpus_dt, + .smp_boot_secondary = shmobile_smp_apmu_boot_secondary_md21, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_can_disable = shmobile_smp_cpu_can_disable, + .cpu_die = shmobile_smp_apmu_cpu_die, + .cpu_kill = shmobile_smp_apmu_cpu_kill, +#endif +}; + +CPU_METHOD_OF_DECLARE(shmobile_smp_apmu, "renesas,apmu", &apmu_smp_ops);