Re: [PATCH v4 2/5] ARC: clocksource: DT based probe

2016-04-14 Thread Vineet Gupta
On Wednesday 13 April 2016 09:52 PM, Marc Zyngier wrote:
>> -int arc_counter_setup(void)
>> > +static void __init arc_cs_setup_rtc(struct device_node *node)
>> >  {
>> > -  write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX);
>> > -  write_aux_reg(ARC_REG_TIMER1_CNT, 0);
>> > -  write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
>> > +  int exists = cpuinfo_arc700[smp_processor_id()].extn.rtc;
>> > +
>> > +  if (WARN(!exists, "Local-64-bit-Ctr clocksource not detected"))
>> > +  return;
>> > +
>> > +  /* Local to CPU hence not usable in SMP */
>> > +  if (WARN(IS_ENABLED(CONFIG_SMP), "Local-64-bit-Ctr not usable in SMP"))
>> > +  return;
> Sorry if this outlines my lack of understanding of the ARC architecture,
> but what makes per-cpu timer unsuitable for SMP? I'd have thought that
> it was actually what you wanted...

This is clocksource, not clockevent. cs needs to synchronized across all cores 
so
that concurrent gtod call from threads on different cores gives you similar
values. This obviously is not true for the local RTC hardware timer.

___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


Re: [PATCH v4 2/5] ARC: clocksource: DT based probe

2016-04-14 Thread Marc Zyngier
On 14/04/16 10:26, Vineet Gupta wrote:
> On Wednesday 13 April 2016 09:52 PM, Marc Zyngier wrote:
>>> -int arc_counter_setup(void)
 +static void __init arc_cs_setup_rtc(struct device_node *node)
  {
 -  write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX);
 -  write_aux_reg(ARC_REG_TIMER1_CNT, 0);
 -  write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
 +  int exists = cpuinfo_arc700[smp_processor_id()].extn.rtc;
 +
 +  if (WARN(!exists, "Local-64-bit-Ctr clocksource not detected"))
 +  return;
 +
 +  /* Local to CPU hence not usable in SMP */
 +  if (WARN(IS_ENABLED(CONFIG_SMP), "Local-64-bit-Ctr not usable in SMP"))
 +  return;
>> Sorry if this outlines my lack of understanding of the ARC architecture,
>> but what makes per-cpu timer unsuitable for SMP? I'd have thought that
>> it was actually what you wanted...
> 
> This is clocksource, not clockevent. cs needs to synchronized across all 
> cores so
> that concurrent gtod call from threads on different cores gives you similar
> values. This obviously is not true for the local RTC hardware timer.

Unsynchronized counters on SMP HW, who would have thought! ;-) I guess
each and every architecture has to repeat the same mistakes.

Thanks for shedding some light on it.

M.
-- 
Jazz is not dead. It just smells funny...

___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


Re: [PATCH v4 1/5] ARC: clockevent: DT based probe

2016-04-14 Thread Vineet Gupta
On Wednesday 13 April 2016 06:29 PM, Daniel Lezcano wrote:
> On Wed, Apr 13, 2016 at 05:10:01PM +0530, Vineet Gupta wrote:
>>  - timer frequency is derived from DT (no longer rely on top level
>>DT "clock-frequency" probed early and exported by asm/clk.h)
>>
>>  - TIMER0_IRQ need not be exported across arch code, confined to intc as
>>it is property of same
>>
>> Cc: Daniel Lezcano 
>> Signed-off-by: Vineet Gupta 
>> ---
> 
> [ ... ]
> 
>> +static void noinline arc_get_timer_clk(struct device_node *node)
>> +{
>> +struct clk *clk;
>> +int ret;
>> +
>> +clk = of_clk_get(node, 0);
>> +if (IS_ERR(clk))
>> +panic("Can't get timer clock");
>> +
> 
> Don't panic here. Change the function to return an error and let the
> caller to handle it.
> 
>> +ret = clk_prepare_enable(clk);
>> +if (ret)
>> +pr_err("Couldn't enable parent clock\n");

I suppose we need to return here too ?

>> +
>> +arc_timer_freq = clk_get_rate(clk);
>> +}
>> +
> 
> [ ... ]
> 
>> +static void __init arc_clockevent_setup(struct device_node *node)
>>  {
>>  struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
>>  int ret;
>>  
>>  register_cpu_notifier(&arc_timer_cpu_nb);
>>  
>> +arc_timer_irq = irq_of_parse_and_map(node, 0);
>> +if (arc_timer_irq <= 0)
>> +panic("Can't parse IRQ");
>> +
>> +arc_get_timer_clk(node);
> 
> Connected to the comment above, check the return code.

Right and if there's error, bail from here too ? This will leave a system w/o a
working clockevent and our lpj setup loop will spin forever. Better to add a 
WARN
so that user knows to fix his DT.

> 
>> +
>> +evt->irq = arc_timer_irq;
>>  evt->cpumask = cpumask_of(smp_processor_id());
>> -clockevents_config_and_register(evt, arc_get_core_freq(),
>> +clockevents_config_and_register(evt, arc_timer_freq,
>>  0, ARC_TIMER_MAX);
>>  
>>  /* Needs apriori irq_set_percpu_devid() done in intc map function */
>> @@ -291,6 +312,7 @@ static void __init arc_clockevent_setup(void)
>>  
>>  enable_percpu_irq(arc_timer_irq, 0);
>>  }
>> +CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_clockevent_setup);
>>  
>>  /*
>>   * Called from start_kernel() - boot CPU only
>> @@ -299,7 +321,6 @@ static void __init arc_clockevent_setup(void)
>>   * -Also sets up any global state needed for timer subsystem:
>>   *- for "counting" timer, registers a clocksource, usable across CPUs
>>   *  (provided that underlying counter h/w is synchronized across cores)
>> - *- for "event" timer, sets up TIMER0 IRQ (as that is platform agnostic)
>>   */
>>  void __init time_init(void)
>>  {
>> @@ -315,7 +336,5 @@ void __init time_init(void)
>>   * CLK upto 4.29 GHz can be safely represented in 32 bits
>>   * because Max 32 bit number is 4,294,967,295
>>   */
>> -clocksource_register_hz(&arc_counter, arc_get_core_freq());
>> -
>> -arc_clockevent_setup();
>> +clocksource_register_hz(&arc_counter, arc_timer_freq);
>>  }
>> -- 
>> 2.5.0
>>
> 


___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


Re: [PATCH v4 2/5] ARC: clocksource: DT based probe

2016-04-14 Thread Vineet Gupta
On Thursday 14 April 2016 03:02 PM, Marc Zyngier wrote:
>> This is clocksource, not clockevent. cs needs to synchronized across all 
>> cores so
>> > that concurrent gtod call from threads on different cores gives you similar
>> > values. This obviously is not true for the local RTC hardware timer.
> Unsynchronized counters on SMP HW, who would have thought! ;-) I guess
> each and every architecture has to repeat the same mistakes.

Not really - hardware wise the SMP support is pretty recent and before that we
only had UP cores. So transition from 32 TIMER1 to 64 bit RTC was only a natural
progression in improvements and in theory SoC guys throw in this local timer 
into
the config. We just prevent SMP linux from using it.



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


Re: [PATCH v4 1/5] ARC: clockevent: DT based probe

2016-04-14 Thread Daniel Lezcano
On Thu, Apr 14, 2016 at 03:02:38PM +0530, Vineet Gupta wrote:
> On Wednesday 13 April 2016 06:29 PM, Daniel Lezcano wrote:
> > On Wed, Apr 13, 2016 at 05:10:01PM +0530, Vineet Gupta wrote:
> >>  - timer frequency is derived from DT (no longer rely on top level
> >>DT "clock-frequency" probed early and exported by asm/clk.h)
> >>
> >>  - TIMER0_IRQ need not be exported across arch code, confined to intc as
> >>it is property of same
> >>
> >> Cc: Daniel Lezcano 
> >> Signed-off-by: Vineet Gupta 
> >> ---
> > 
> > [ ... ]
> > 
> >> +static void noinline arc_get_timer_clk(struct device_node *node)
> >> +{
> >> +  struct clk *clk;
> >> +  int ret;
> >> +
> >> +  clk = of_clk_get(node, 0);
> >> +  if (IS_ERR(clk))
> >> +  panic("Can't get timer clock");
> >> +
> > 
> > Don't panic here. Change the function to return an error and let the
> > caller to handle it.
> > 
> >> +  ret = clk_prepare_enable(clk);
> >> +  if (ret)
> >> +  pr_err("Couldn't enable parent clock\n");
> 
> I suppose we need to return here too ?
>
> >> +
> >> +  arc_timer_freq = clk_get_rate(clk);
> >> +}
> >> +
> > 
> > [ ... ]
> > 
> >> +static void __init arc_clockevent_setup(struct device_node *node)
> >>  {
> >>struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
> >>int ret;
> >>  
> >>register_cpu_notifier(&arc_timer_cpu_nb);
> >>  
> >> +  arc_timer_irq = irq_of_parse_and_map(node, 0);
> >> +  if (arc_timer_irq <= 0)
> >> +  panic("Can't parse IRQ");
> >> +
> >> +  arc_get_timer_clk(node);
> > 
> > Connected to the comment above, check the return code.
> 
> Right and if there's error, bail from here too ? This will leave a system w/o 
> a
> working clockevent and our lpj setup loop will spin forever. Better to add a 
> WARN
> so that user knows to fix his DT.

You can handle the error as you wish here. I just don't want panics spread in 
the
code.

In the patch 2/5, you mention:

"Remove some of the panic() calls if underlying timer is NOT detected as
 fallback clocksource might still be available"

but you add calls to arc_get_timer_clk() which can panic.

The main problem is the macro CLOCKSOURCE_OF_DECLARE() which expect an init 
function
returning void. I would like to change the code to have it returning an int, so
the panic could be raised in the generic clksrc code when all clocksource inits 
fail.

In the meantime, it is a good practice to concentrate all panics in a single 
place,
that is in the init function to facilitate the conversion above which will 
happen
in the future ...

  -- Daniel


 
> >> +
> >> +  evt->irq = arc_timer_irq;
> >>evt->cpumask = cpumask_of(smp_processor_id());
> >> -  clockevents_config_and_register(evt, arc_get_core_freq(),
> >> +  clockevents_config_and_register(evt, arc_timer_freq,
> >>0, ARC_TIMER_MAX);
> >>  
> >>/* Needs apriori irq_set_percpu_devid() done in intc map function */
> >> @@ -291,6 +312,7 @@ static void __init arc_clockevent_setup(void)
> >>  
> >>enable_percpu_irq(arc_timer_irq, 0);
> >>  }
> >> +CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", 
> >> arc_clockevent_setup);
> >>  
> >>  /*
> >>   * Called from start_kernel() - boot CPU only
> >> @@ -299,7 +321,6 @@ static void __init arc_clockevent_setup(void)
> >>   * -Also sets up any global state needed for timer subsystem:
> >>   *- for "counting" timer, registers a clocksource, usable across CPUs
> >>   *  (provided that underlying counter h/w is synchronized across 
> >> cores)
> >> - *- for "event" timer, sets up TIMER0 IRQ (as that is platform 
> >> agnostic)
> >>   */
> >>  void __init time_init(void)
> >>  {
> >> @@ -315,7 +336,5 @@ void __init time_init(void)
> >> * CLK upto 4.29 GHz can be safely represented in 32 bits
> >> * because Max 32 bit number is 4,294,967,295
> >> */
> >> -  clocksource_register_hz(&arc_counter, arc_get_core_freq());
> >> -
> >> -  arc_clockevent_setup();
> >> +  clocksource_register_hz(&arc_counter, arc_timer_freq);
> >>  }
> >> -- 
> >> 2.5.0
> >>
> > 
> 

___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc