[PATCH v18 2/8] ARM: hisi: enable MCPM implementation

Haojian Zhuang haojian.zhuang at linaro.org
Tue Aug 12 18:28:13 PDT 2014


On 12 August 2014 23:52, Nicolas Pitre <nicolas.pitre at linaro.org> wrote:
> On Tue, 12 Aug 2014, Haojian Zhuang wrote:
>
>> +static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
>> +{
>> +     unsigned long data, mask;
>> +     void __iomem *sys_dreq, *sys_status;
>> +
>> +     if (!sysctrl)
>> +             return -ENODEV;
>> +     if (cluster >= HIP04_MAX_CLUSTERS || cpu >= HIP04_MAX_CPUS_PER_CLUSTER)
>> +             return -EINVAL;
>> +
>> +     spin_lock_irq(&boot_lock);
>> +
>> +     if (hip04_cpu_table[cluster][cpu])
>> +             goto out;
>> +
>> +     sys_dreq = sysctrl + SC_CPU_RESET_DREQ(cluster);
>> +     sys_status = sysctrl + SC_CPU_RESET_STATUS(cluster);
>> +     if (hip04_cluster_is_down(cluster)) {
>> +             data = CLUSTER_DEBUG_RESET_BIT;
>> +             writel_relaxed(data, sys_dreq);
>> +             do {
>> +                     cpu_relax();
>> +                     mask = CLUSTER_DEBUG_RESET_STATUS;
>> +                     data = readl_relaxed(sys_status);
>> +             } while (data & mask);
>> +     }
>> +
>> +     data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
>> +            CORE_DEBUG_RESET_BIT(cpu);
>> +     writel_relaxed(data, sys_dreq);
>> +     do {
>> +             cpu_relax();
>> +     } while (data == readl_relaxed(sys_status));
>> +     udelay(20);
>
> You really need this even if the snoops aren't disabled in
> hip04_mcpm_power_down() ?
>

I really need this. Otherwise, I failed to power up core again. And I
can't get any clue from document. It's based on tests.

>> +out:
>> +     hip04_cpu_table[cluster][cpu]++;
>> +     spin_unlock_irq(&boot_lock);
>> +
>> +     return 0;
>> +}
>> +
>> +static void hip04_mcpm_power_down(void)
>> +{
>> +     unsigned int mpidr, cpu, cluster;
>> +     bool skip_wfi = false, last_man = false;
>> +
>> +     mpidr = read_cpuid_mpidr();
>> +     cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
>> +     cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
>> +
>> +     __mcpm_cpu_going_down(cpu, cluster);
>> +
>> +     spin_lock_irq(&boot_lock);
>> +     BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
>> +     hip04_cpu_table[cluster][cpu]--;
>> +     if (hip04_cpu_table[cluster][cpu] == 1) {
>> +             /* A power_up request went ahead of us. */
>> +             skip_wfi = true;
>> +     } else if (hip04_cpu_table[cluster][cpu] > 1) {
>> +             pr_err("Cluster %d CPU%d boots multiple times\n", cluster, cpu);
>> +             BUG();
>> +     }
>> +
>> +     last_man = hip04_cluster_is_down(cluster);
>> +     if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
>> +             spin_unlock(&boot_lock);
>> +             v7_exit_coherency_flush(all);
>> +             __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
>> +     } else {
>> +             spin_unlock(&boot_lock);
>> +             v7_exit_coherency_flush(louis);
>> +     }
>> +
>> +     __mcpm_cpu_down(cpu, cluster);
>> +
>> +     if (!skip_wfi)
>> +             wfi();
>> +}
>> +
>> +static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
>> +{
>> +     unsigned int data, tries, count;
>> +
>> +     BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
>> +            cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
>> +
>> +     count = TIMEOUT_MSEC / POLL_MSEC;
>
> This count value doesn't make much sense anymore, does it?  Nothing
> relates to POLL_MSEC afterwards.
>
Yes, you're right. I'll fix.

>> +     spin_lock_irq(&boot_lock);
>> +     /*
>> +      * Target core should enter WFI first.
>> +      * Then cluster could be disabled in snoop filter.
>> +      * At last, target core could be reset.
>> +      */
>
> You should verify that the CPU usage count is still 0 here as I
> suggested.
>
I'll move the checking at here. And report error if the count is still 0.

>> +     for (tries = 0; tries < count; tries++) {
>> +             cpu_relax();
>
> There is probably no point calling cpu_relax() if it is followed by
> udelay().
>
This delay is required for power down the cluster. I should check if
all cores in cluster should be down.

If I removed the delay, I found that kernel panic reports. I guess
that L2 is still in the process of clean.

With this delay, everything works well. I failed to find a command to
clean L2 in coretex a15. It seems that I have to disable MMU & C bit
in target cpu. It worth trying but I need more time. So as a
workaround, I use udelay(50) at here.

>> +             udelay(50);
>> +             data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
>> +             if (!hip04_cpu_table[cluster][cpu] || \
>> +                 (data & CORE_WFI_STATUS(cpu))) {
>> +                     break;
>> +             }
>> +     }
>> +     if (tries >= count)
>> +             goto err;
>> +     if (hip04_cluster_is_down(cluster))
>> +             hip04_set_snoop_filter(cluster, 0);
>> +     data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
>> +            CORE_DEBUG_RESET_BIT(cpu);
>> +     writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
>> +     for (tries = 0; tries < count; tries++) {
>> +             cpu_relax();
>> +             udelay(50);
>> +             data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
>> +             if (!hip04_cpu_table[cluster][cpu] || \
>> +                 (data & CORE_RESET_STATUS(cpu))) {
>> +                     break;
>> +             }
>> +     }
>> +     if (tries >= count)
>> +             goto err;
>> +     spin_unlock_irq(&boot_lock);
>> +     return 0;
>> +err:
>> +     spin_unlock_irq(&boot_lock);
>> +     return -EBUSY;
>> +}
>
> I don't really like the way things are done in general.  And we're
> apparently going in circle over this. This is almost like if MCPM was of
> no benefit to you given all the things which look "wrong".  But given
> that no usable documentation is available, preventing me and others from
> suggesting better ways, then this platform is going to be limited to
> suboptimal CPU hotplug support.  So if you fix the minor issues I've
> noted above then I'll provide my reluctant ACK for this patch if nothing
> else can be helped.
>
OK. I'll fix them. But I can't delete these delay. Otherwise, I may
meet failure on hotplug.

Best Regards
Haojian



More information about the linux-arm-kernel mailing list