[PATCH v3 07/13] ARM: hisi: add hip04 SoC support

Haojian Zhuang haojian.zhuang at linaro.org
Thu Apr 24 20:00:02 PDT 2014


On 22 April 2014 12:08, Nicolas Pitre <nicolas.pitre at linaro.org> wrote:
> On Fri, 18 Apr 2014, Haojian Zhuang wrote:
>
>> +
>> +     data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
>> +            CORE_DEBUG_RESET_BIT(cpu);
>> +     writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
>
> It might be a good idea to reset and initialize things only if
> hip04_cpu_table[cluster][cpu] was zero initially.  Please see the
> comment in mcpm_cpu_power_down() discussing concurrent up/down
> operations, and the way races are handled using dcscb_use_count in
> dcscb_power_up() / dcscb_power_down() for example.
>

I'll use it as reference.

>> +     spin_unlock(&boot_lock);
>> +     msleep(POLL_MSEC);
>
> You don't have to wait here.  The MCPM up method should set things for
> the CPU to come up eventually and that CPU to signal itself when it is
> finally online.
>

I have to wait. Otherwise, I'll meet hang when make the CPU offline &
online continuously.

>> +     return 0;
>> +}
>> +
>> +static void hip04_mcpm_power_down(void)
>> +{
>> +     unsigned int mpidr, cpu, cluster;
>> +     unsigned int v;
>> +
>> +     mpidr = read_cpuid_mpidr();
>> +     cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
>> +     cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
>> +
>> +     spin_lock(&boot_lock);
>> +     BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
>> +     __mcpm_cpu_going_down(cpu, cluster);
>> +
>> +     hip04_cpu_table[cluster][cpu]--;
>> +     if (hip04_cpu_table[cluster][cpu]) {
>> +             pr_err("Cluster %d CPU%d is still running\n", cluster, cpu);
>> +             goto out;
>> +     }
>
> This is wrong.  Please see dcscb_power_down() or tc2_pm_down() for
> examples of how to deal with this situation.
>
>> +     __mcpm_cpu_down(cpu, cluster);
>
> That call should happen last i.e. after coherency has been disabled and
> the CPU is about to call WFI.  Again, see the TC2 implementation for
> example.  You may also read
> Documentation/arm/cluster-pm-race-avoidance.txt for more details about
> those calls and the algorithm behind them.
>
>> +     spin_unlock(&boot_lock);
>> +
>> +     asm volatile(
>> +     "       mrc     p15, 0, %0, c1, c0, 0\n"
>> +     "       bic     %0, %0, %1\n"
>> +     "       mcr     p15, 0, %0, c1, c0, 0\n"
>> +       : "=&r" (v)
>> +       : "Ir" (CR_C)
>> +       :);
>> +
>> +     flush_cache_louis();
>> +
>> +     asm volatile(
>> +     /* Turn off coherency, disable SMP bit in ACTLR */
>> +     "       mrc     p15, 0, %0, c1, c0, 1\n"
>> +     "       bic     %0, %0, %1\n"
>> +     "       mcr     p15, 0, %0, c1, c0, 1\n"
>> +     : "=&r" (v)
>> +     : "Ir" (0x40)
>> +     :);
>
> The above code is not safe.
>
> You should use v7_exit_coherency_flush() instead.
>

OK.

>> +     isb();
>> +     dsb();
>> +
>> +     while (true)
>> +             wfi();
>
> This is wrong.  By the time execution gets here, it is well possible
> that another CPU decided that this CPU should not be down anymore, in
> which case wfi() will return.  See what's expected in this case by
> looking at mcpm_cpu_power_down() and what other backend implementations
> do.
>
>> +     return;
>> +out:
>> +     spin_unlock(&boot_lock);
>> +}
>> +
>> +static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
>> +{
>> +     unsigned int data, tries;
>> +
>> +     BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
>> +            cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
>> +
>> +     for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; tries++) {
>> +             data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
>> +             if (!(data & CORE_WFI_STATUS(cpu))) {
>> +                     msleep(POLL_MSEC);
>> +                     continue;
>> +             }
>> +             data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
>> +                    CORE_DEBUG_RESET_BIT(cpu);
>> +             writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
>
> Why are you resetting those here?
>

Do you mean that I should move this reset code into hip04_mcpm_power_down()?

Regards
Haojian



More information about the linux-arm-kernel mailing list