> On 12/27/2011 05:25 AM, Zhao Chenhui wrote:
> >  * The driver doesn't support MPC8536 Rev 1.0 due to a JOG erratum.
> >    Subsequent revisions of MPC8536 have corrected the erratum.
> 
> Where do you check for this?

Nowhere. I just notify this patch don't support MPC8536 Rev 1.0.

> 
> > +#define POWMGTCSR_LOSSLESS_MASK    0x00400000
> > +#define POWMGTCSR_JOG_MASK 0x00200000
> 
> Are these really masks, or just values to use?

They are masks.

> 
> > +#define POWMGTCSR_CORE0_IRQ_MSK    0x80000000
> > +#define POWMGTCSR_CORE0_CI_MSK     0x40000000
> > +#define POWMGTCSR_CORE0_DOZING     0x00000008
> > +#define POWMGTCSR_CORE0_NAPPING    0x00000004
> > +
> > +#define POWMGTCSR_CORE_INT_MSK     0x00000800
> > +#define POWMGTCSR_CORE_CINT_MSK    0x00000400
> > +#define POWMGTCSR_CORE_UDE_MSK     0x00000200
> > +#define POWMGTCSR_CORE_MCP_MSK     0x00000100
> > +#define P1022_POWMGTCSR_MSK        (POWMGTCSR_CORE_INT_MSK | \
> > +                            POWMGTCSR_CORE_CINT_MSK | \
> > +                            POWMGTCSR_CORE_UDE_MSK | \
> > +                            POWMGTCSR_CORE_MCP_MSK)
> > +
> > +static void keep_waking_up(void *dummy)
> > +{
> > +   unsigned long flags;
> > +
> > +   local_irq_save(flags);
> > +   mb();
> > +
> > +   in_jog_process = 1;
> > +   mb();
> > +
> > +   while (in_jog_process != 0)
> > +           mb();
> > +
> > +   local_irq_restore(flags);
> > +}
> 
> Please document this.  Compare in_jog_process == 1, not != 0 -- it's
> unlikely, but what if the other cpu sees that in_jog_process has been
> set to 1, exits and sets in_jog_process to 0, then re-enters set_pll and
> sets in_jog_process to -1 again before this function does another load
> of in_jog_process?

Thanks. I'll fix it.

> 
> Do you really need all these mb()s?  I think this would suffice:
> 
>       local_irq_save(flags);
> 
>       in_jog_process = 1;
> 
>       while (in_jog_process == 1)
>               barrier();
> 
>       local_irq_restore();
> 
> It's not really a performance issue, just simplicity.
> 
> > +static int p1022_set_pll(unsigned int cpu, unsigned int pll)
> > +{
> > +   int index, hw_cpu = get_hard_smp_processor_id(cpu);
> > +   int shift;
> > +   u32 corefreq, val, mask = 0;
> > +   unsigned int cur_pll = get_pll(hw_cpu);
> > +   unsigned long flags;
> > +   int ret = 0;
> > +
> > +   if (pll == cur_pll)
> > +           return 0;
> > +
> > +   shift = hw_cpu * CORE_RATIO_BITS + CORE0_RATIO_SHIFT;
> > +   val = (pll & CORE_RATIO_MASK) << shift;
> > +
> > +   corefreq = sysfreq * pll / 2;
> > +   /*
> > +    * Set the COREx_SPD bit if the requested core frequency
> > +    * is larger than the threshold frequency.
> > +    */
> > +   if (corefreq > FREQ_533MHz)
> > +           val |= PMJCR_CORE0_SPD_MASK << hw_cpu;
> 
> P1022 manual says the threshold is 500 MHz (but doesn't say how to set
> the bit if the frequency is exactly 500 MHz).  Where did 533340000 come
> from?

Please refer to Chapter 25 "25.4.1.11 Power Management Jog Control Register 
(PMJCR)".

> 
> > +
> > +   mask = (CORE_RATIO_MASK << shift) | (PMJCR_CORE0_SPD_MASK <<
> hw_cpu);
> > +   clrsetbits_be32(guts + PMJCR, mask, val);
> > +
> > +   /* readback to sync write */
> > +   val = in_be32(guts + PMJCR);
> 
> You don't use val after this -- just ignore the return value from
> in_be32().

OK.

> 
> > +   /*
> > +    * A Jog request can not be asserted when any core is in a low
> > +    * power state on P1022. Before executing a jog request, any
> > +    * core which is in a low power state must be waked by a
> > +    * interrupt, and keep waking up until the sequence is
> > +    * finished.
> > +    */
> > +   for_each_present_cpu(index) {
> > +           if (!cpu_online(index))
> > +                   return -EFAULT;
> > +   }
> 
> EFAULT is not the appropriate error code -- it is for when userspace
> passes a bad virtual address.
> 
> Better, don't fail here -- bring the other core out of the low power
> state in order to do the jog.  cpufreq shouldn't stop working just
> because we took a core offline.
> 
> What prevents a core from going offline just after you check here?
> 
> > +   in_jog_process = -1;
> > +   mb();
> > +   smp_call_function(keep_waking_up, NULL, 0);
> 
> What does "keep waking up" mean?  Something like spin_while_jogging
> might be clearer.
> 
> > +   local_irq_save(flags);
> > +   mb();
> > +   /* Wait for the other core to wake. */
> > +   while (in_jog_process != 1)
> > +           mb();
> 
> Timeout?  And more unnecessary mb()s.
> 
> Might be nice to support more than two cores, even if this code isn't
> currently expected to be used on such hardware (it's just a generic
> "hold other cpus" loop; might as well make it reusable).  You could do
> this by using an atomic count for other cores to check in and out of the
> spin loop.

This is just for P1022, a dual-core chip. A separate patch will
support multi-core chips, such as P4080, etc.

> 
> > +   out_be32(guts + POWMGTCSR, POWMGTCSR_JOG_MASK |
> P1022_POWMGTCSR_MSK);
> > +
> > +   if (!spin_event_timeout(((in_be32(guts + POWMGTCSR) &
> > +       POWMGTCSR_JOG_MASK) == 0), 10000, 10)) {
> > +           pr_err("%s: Fail to switch the core frequency.\n", __func__);
> > +           ret = -EFAULT;
> > +   }
> > +
> > +   clrbits32(guts + POWMGTCSR, P1022_POWMGTCSR_MSK);
> > +   in_jog_process = 0;
> > +   mb();
> 
> This mb() (or better, a readback of POWMGTCSR) should be before you
> clear in_jog_process.  For clarity of its purpose, the clearing of
> POWMGTCSR should go in the failure branch of spin_event_timeout().

According to the manual, P1022_POWMGTCSR_MSK should be reset
by software regardless of failure or success.

-chenhui
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to