All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT Pull] timer fixes for 3.14
@ 2014-02-15 19:21 Thomas Gleixner
  2014-02-18  2:59 ` Preeti Murthy
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Gleixner @ 2014-02-15 19:21 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: LKML, Andrew Morton, Ingo Molnar, H. Peter Anvin

Linus,

please pull the latest timers-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers-urgent-for-linus

The following trilogy of patches brings you:

 * Fix for a long standing math overflow issue with HZ < 60

 * An onliner fix for a corner case in the dreaded tick broadcast
   mechanism affecting a certain range of AMD machines which are
   infested with the infamous automagic C1E power control misfeature

 * A fix for one of the ARM platforms which allows the kernel to
   proceed and boot instead of stupidly panicing for no good
   reason. The patch is slightly larger than necessary, but it's less
   ugly than the alternative 5 liner.


Thanks,

	tglx

------------------>
Mikulas Patocka (1):
      time: Fix overflow when HZ is smaller than 60

Thomas Gleixner (1):
      tick: Clear broadcast pending bit when switching to oneshot

Tim Kryger (1):
      clocksource: Kona: Print warning rather than panic


 drivers/clocksource/bcm_kona_timer.c |   54 ++++++++++++++++++----------------
 kernel/time/jiffies.c                |    6 ++++
 kernel/time/tick-broadcast.c         |    1 +
 3 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c
index 974b2db..0595dc6 100644
--- a/drivers/clocksource/bcm_kona_timer.c
+++ b/drivers/clocksource/bcm_kona_timer.c
@@ -99,31 +99,6 @@ kona_timer_get_counter(void *timer_base, uint32_t *msw, uint32_t *lsw)
 	return;
 }
 
-static void __init kona_timers_init(struct device_node *node)
-{
-	u32 freq;
-	struct clk *external_clk;
-
-	external_clk = of_clk_get_by_name(node, NULL);
-
-	if (!IS_ERR(external_clk)) {
-		arch_timer_rate = clk_get_rate(external_clk);
-		clk_prepare_enable(external_clk);
-	} else if (!of_property_read_u32(node, "clock-frequency", &freq)) {
-		arch_timer_rate = freq;
-	} else {
-		panic("unable to determine clock-frequency");
-	}
-
-	/* Setup IRQ numbers */
-	timers.tmr_irq = irq_of_parse_and_map(node, 0);
-
-	/* Setup IO addresses */
-	timers.tmr_regs = of_iomap(node, 0);
-
-	kona_timer_disable_and_clear(timers.tmr_regs);
-}
-
 static int kona_timer_set_next_event(unsigned long clc,
 				  struct clock_event_device *unused)
 {
@@ -198,7 +173,34 @@ static struct irqaction kona_timer_irq = {
 
 static void __init kona_timer_init(struct device_node *node)
 {
-	kona_timers_init(node);
+	u32 freq;
+	struct clk *external_clk;
+
+	if (!of_device_is_available(node)) {
+		pr_info("Kona Timer v1 marked as disabled in device tree\n");
+		return;
+	}
+
+	external_clk = of_clk_get_by_name(node, NULL);
+
+	if (!IS_ERR(external_clk)) {
+		arch_timer_rate = clk_get_rate(external_clk);
+		clk_prepare_enable(external_clk);
+	} else if (!of_property_read_u32(node, "clock-frequency", &freq)) {
+		arch_timer_rate = freq;
+	} else {
+		pr_err("Kona Timer v1 unable to determine clock-frequency");
+		return;
+	}
+
+	/* Setup IRQ numbers */
+	timers.tmr_irq = irq_of_parse_and_map(node, 0);
+
+	/* Setup IO addresses */
+	timers.tmr_regs = of_iomap(node, 0);
+
+	kona_timer_disable_and_clear(timers.tmr_regs);
+
 	kona_timer_clockevents_init();
 	setup_irq(timers.tmr_irq, &kona_timer_irq);
 	kona_timer_set_next_event((arch_timer_rate / HZ), NULL);
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
index 7a925ba..a6a5bf5 100644
--- a/kernel/time/jiffies.c
+++ b/kernel/time/jiffies.c
@@ -51,7 +51,13 @@
  * HZ shrinks, so values greater than 8 overflow 32bits when
  * HZ=100.
  */
+#if HZ < 34
+#define JIFFIES_SHIFT	6
+#elif HZ < 67
+#define JIFFIES_SHIFT	7
+#else
 #define JIFFIES_SHIFT	8
+#endif
 
 static cycle_t jiffies_read(struct clocksource *cs)
 {
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 43780ab..98977a5 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -756,6 +756,7 @@ out:
 static void tick_broadcast_clear_oneshot(int cpu)
 {
 	cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
+	cpumask_clear_cpu(cpu, tick_broadcast_pending_mask);
 }
 
 static void tick_broadcast_init_next_event(struct cpumask *mask,

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [GIT Pull] timer fixes for 3.14
  2014-02-15 19:21 [GIT Pull] timer fixes for 3.14 Thomas Gleixner
@ 2014-02-18  2:59 ` Preeti Murthy
  2014-02-18 18:40   ` Thomas Gleixner
  0 siblings, 1 reply; 5+ messages in thread
From: Preeti Murthy @ 2014-02-18  2:59 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Linus Torvalds, LKML, Andrew Morton, Ingo Molnar, H. Peter Anvin,
	Preeti U Murthy

Hi Thomas,

With regard to the patch: "tick: Clear broadcast pending bit when
switching to oneshot"
isn't BROADCAST_EXIT called atleast after initializing the high
resolution timers while
handling the broadcast IPI and before re-entering idle? This should
clear the cpu bit
in the pending mask right?

idle()
|__BROADCAST_ENTER
    |__halt()
      |__broadcast_ipi
          |__init_highres()->clear oneshot mask
              |__return from interrupt->BROADCAST_EXIT (clear pending mask)
                   |__re-enter idle

When the cpu re-enters idle and does a BROADCAST_ENTER again, the
pending mask is cleared
and hence should not trigger a WARN_ON().

Thanks

Regards
Preeti U Murthy

On Sun, Feb 16, 2014 at 12:51 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> Linus,
>
> please pull the latest timers-urgent-for-linus git tree from:
>
>    git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers-urgent-for-linus
>
> The following trilogy of patches brings you:
>
>  * Fix for a long standing math overflow issue with HZ < 60
>
>  * An onliner fix for a corner case in the dreaded tick broadcast
>    mechanism affecting a certain range of AMD machines which are
>    infested with the infamous automagic C1E power control misfeature
>
>  * A fix for one of the ARM platforms which allows the kernel to
>    proceed and boot instead of stupidly panicing for no good
>    reason. The patch is slightly larger than necessary, but it's less
>    ugly than the alternative 5 liner.
>
>
> Thanks,
>
>         tglx
>
> ------------------>
> Mikulas Patocka (1):
>       time: Fix overflow when HZ is smaller than 60
>
> Thomas Gleixner (1):
>       tick: Clear broadcast pending bit when switching to oneshot
>
> Tim Kryger (1):
>       clocksource: Kona: Print warning rather than panic
>
>
>  drivers/clocksource/bcm_kona_timer.c |   54 ++++++++++++++++++----------------
>  kernel/time/jiffies.c                |    6 ++++
>  kernel/time/tick-broadcast.c         |    1 +
>  3 files changed, 35 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c
> index 974b2db..0595dc6 100644
> --- a/drivers/clocksource/bcm_kona_timer.c
> +++ b/drivers/clocksource/bcm_kona_timer.c
> @@ -99,31 +99,6 @@ kona_timer_get_counter(void *timer_base, uint32_t *msw, uint32_t *lsw)
>         return;
>  }
>
> -static void __init kona_timers_init(struct device_node *node)
> -{
> -       u32 freq;
> -       struct clk *external_clk;
> -
> -       external_clk = of_clk_get_by_name(node, NULL);
> -
> -       if (!IS_ERR(external_clk)) {
> -               arch_timer_rate = clk_get_rate(external_clk);
> -               clk_prepare_enable(external_clk);
> -       } else if (!of_property_read_u32(node, "clock-frequency", &freq)) {
> -               arch_timer_rate = freq;
> -       } else {
> -               panic("unable to determine clock-frequency");
> -       }
> -
> -       /* Setup IRQ numbers */
> -       timers.tmr_irq = irq_of_parse_and_map(node, 0);
> -
> -       /* Setup IO addresses */
> -       timers.tmr_regs = of_iomap(node, 0);
> -
> -       kona_timer_disable_and_clear(timers.tmr_regs);
> -}
> -
>  static int kona_timer_set_next_event(unsigned long clc,
>                                   struct clock_event_device *unused)
>  {
> @@ -198,7 +173,34 @@ static struct irqaction kona_timer_irq = {
>
>  static void __init kona_timer_init(struct device_node *node)
>  {
> -       kona_timers_init(node);
> +       u32 freq;
> +       struct clk *external_clk;
> +
> +       if (!of_device_is_available(node)) {
> +               pr_info("Kona Timer v1 marked as disabled in device tree\n");
> +               return;
> +       }
> +
> +       external_clk = of_clk_get_by_name(node, NULL);
> +
> +       if (!IS_ERR(external_clk)) {
> +               arch_timer_rate = clk_get_rate(external_clk);
> +               clk_prepare_enable(external_clk);
> +       } else if (!of_property_read_u32(node, "clock-frequency", &freq)) {
> +               arch_timer_rate = freq;
> +       } else {
> +               pr_err("Kona Timer v1 unable to determine clock-frequency");
> +               return;
> +       }
> +
> +       /* Setup IRQ numbers */
> +       timers.tmr_irq = irq_of_parse_and_map(node, 0);
> +
> +       /* Setup IO addresses */
> +       timers.tmr_regs = of_iomap(node, 0);
> +
> +       kona_timer_disable_and_clear(timers.tmr_regs);
> +
>         kona_timer_clockevents_init();
>         setup_irq(timers.tmr_irq, &kona_timer_irq);
>         kona_timer_set_next_event((arch_timer_rate / HZ), NULL);
> diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
> index 7a925ba..a6a5bf5 100644
> --- a/kernel/time/jiffies.c
> +++ b/kernel/time/jiffies.c
> @@ -51,7 +51,13 @@
>   * HZ shrinks, so values greater than 8 overflow 32bits when
>   * HZ=100.
>   */
> +#if HZ < 34
> +#define JIFFIES_SHIFT  6
> +#elif HZ < 67
> +#define JIFFIES_SHIFT  7
> +#else
>  #define JIFFIES_SHIFT  8
> +#endif
>
>  static cycle_t jiffies_read(struct clocksource *cs)
>  {
> diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
> index 43780ab..98977a5 100644
> --- a/kernel/time/tick-broadcast.c
> +++ b/kernel/time/tick-broadcast.c
> @@ -756,6 +756,7 @@ out:
>  static void tick_broadcast_clear_oneshot(int cpu)
>  {
>         cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
> +       cpumask_clear_cpu(cpu, tick_broadcast_pending_mask);
>  }
>
>  static void tick_broadcast_init_next_event(struct cpumask *mask,
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [GIT Pull] timer fixes for 3.14
  2014-02-18  2:59 ` Preeti Murthy
@ 2014-02-18 18:40   ` Thomas Gleixner
  2014-02-19  3:23     ` Preeti U Murthy
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Gleixner @ 2014-02-18 18:40 UTC (permalink / raw)
  To: Preeti Murthy
  Cc: Linus Torvalds, LKML, Andrew Morton, Ingo Molnar, H. Peter Anvin,
	Preeti U Murthy

On Tue, 18 Feb 2014, Preeti Murthy wrote:

> Hi Thomas,
> 
> With regard to the patch: "tick: Clear broadcast pending bit when
> switching to oneshot"
> isn't BROADCAST_EXIT called atleast after initializing the high
> resolution timers while
> handling the broadcast IPI and before re-entering idle? This should
> clear the cpu bit
> in the pending mask right?
> 
> idle()
> |__BROADCAST_ENTER
>     |__halt()
>       |__broadcast_ipi
>           |__init_highres()->clear oneshot mask
>               |__return from interrupt->BROADCAST_EXIT (clear pending mask)

Unfortunately not:

     if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_oneshot_mask)) {
     	  clear pending mask;
     }

>                    |__re-enter idle

Go figure :)
 
Thanks,

	tglx

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [GIT Pull] timer fixes for 3.14
  2014-02-18 18:40   ` Thomas Gleixner
@ 2014-02-19  3:23     ` Preeti U Murthy
  0 siblings, 0 replies; 5+ messages in thread
From: Preeti U Murthy @ 2014-02-19  3:23 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Preeti Murthy, Linus Torvalds, LKML, Andrew Morton, Ingo Molnar,
	H. Peter Anvin

On 02/19/2014 12:10 AM, Thomas Gleixner wrote:
> On Tue, 18 Feb 2014, Preeti Murthy wrote:
> 
>> Hi Thomas,
>>
>> With regard to the patch: "tick: Clear broadcast pending bit when
>> switching to oneshot"
>> isn't BROADCAST_EXIT called atleast after initializing the high
>> resolution timers while
>> handling the broadcast IPI and before re-entering idle? This should
>> clear the cpu bit
>> in the pending mask right?
>>
>> idle()
>> |__BROADCAST_ENTER
>>     |__halt()
>>       |__broadcast_ipi
>>           |__init_highres()->clear oneshot mask
>>               |__return from interrupt->BROADCAST_EXIT (clear pending mask)
> 
> Unfortunately not:
> 
>      if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_oneshot_mask)) {
>      	  clear pending mask;
>      }
> 
>>                    |__re-enter idle
> 
> Go figure :)

Ah right! Thanks :)

Regards
Preeti U Murthy
> 
> Thanks,
> 
> 	tglx
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [GIT Pull] timer fixes for 3.14
@ 2014-02-23  0:02 Thomas Gleixner
  0 siblings, 0 replies; 5+ messages in thread
From: Thomas Gleixner @ 2014-02-23  0:02 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, LKML, Ingo Molnar, H. Peter Anvin

Linus,

please pull the latest timers-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
timers-urgent-for-linus

Short summary:

      * Serialize the registration of a new sched_clock in the
        currently ARM only generic sched_clock facilty to avoid
        sched_clock havoc

Thanks,

        tglx

------------------>
Stephen Boyd (1):
      sched_clock: Prevent callers from seeing half-updated data


 kernel/time/sched_clock.c |   46 ++++++++++++++++++++++++++++-----------------
 1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index 0abb364..4d23dc4 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -116,20 +116,42 @@ static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
 void __init sched_clock_register(u64 (*read)(void), int bits,
 				 unsigned long rate)
 {
+	u64 res, wrap, new_mask, new_epoch, cyc, ns;
+	u32 new_mult, new_shift;
+	ktime_t new_wrap_kt;
 	unsigned long r;
-	u64 res, wrap;
 	char r_unit;
 
 	if (cd.rate > rate)
 		return;
 
 	WARN_ON(!irqs_disabled());
-	read_sched_clock = read;
-	sched_clock_mask = CLOCKSOURCE_MASK(bits);
-	cd.rate = rate;
 
 	/* calculate the mult/shift to convert counter ticks to ns. */
-	clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600);
+	clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600);
+
+	new_mask = CLOCKSOURCE_MASK(bits);
+
+	/* calculate how many ns until we wrap */
+	wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask);
+	new_wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
+
+	/* update epoch for new counter and update epoch_ns from old counter*/
+	new_epoch = read();
+	cyc = read_sched_clock();
+	ns = cd.epoch_ns + cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
+			  cd.mult, cd.shift);
+
+	raw_write_seqcount_begin(&cd.seq);
+	read_sched_clock = read;
+	sched_clock_mask = new_mask;
+	cd.rate = rate;
+	cd.wrap_kt = new_wrap_kt;
+	cd.mult = new_mult;
+	cd.shift = new_shift;
+	cd.epoch_cyc = new_epoch;
+	cd.epoch_ns = ns;
+	raw_write_seqcount_end(&cd.seq);
 
 	r = rate;
 	if (r >= 4000000) {
@@ -141,22 +163,12 @@ void __init sched_clock_register(u64 (*read)(void), int bits,
 	} else
 		r_unit = ' ';
 
-	/* calculate how many ns until we wrap */
-	wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
-	cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
-
 	/* calculate the ns resolution of this counter */
-	res = cyc_to_ns(1ULL, cd.mult, cd.shift);
+	res = cyc_to_ns(1ULL, new_mult, new_shift);
+
 	pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
 		bits, r, r_unit, res, wrap);
 
-	update_sched_clock();
-
-	/*
-	 * Ensure that sched_clock() starts off at 0ns
-	 */
-	cd.epoch_ns = 0;
-
 	/* Enable IRQ time accounting if we have a fast enough sched_clock */
 	if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
 		enable_sched_clock_irqtime();

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-02-23  0:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-15 19:21 [GIT Pull] timer fixes for 3.14 Thomas Gleixner
2014-02-18  2:59 ` Preeti Murthy
2014-02-18 18:40   ` Thomas Gleixner
2014-02-19  3:23     ` Preeti U Murthy
2014-02-23  0:02 Thomas Gleixner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.