Merge branch 'timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
Linus Torvalds [Mon, 1 Mar 2010 16:48:25 +0000 (08:48 -0800)]
* 'timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  posix-timers.c: Don't export local functions
  clocksource: start CMT at clocksource resume
  clocksource: add suspend callback
  clocksource: add argument to resume callback
  ntp: Cleanup xtime references in ntp.c
  ntp: Make time_esterror and time_maxerror static

1  2 
arch/x86/kernel/tsc.c
drivers/clocksource/sh_cmt.c
kernel/time/clocksource.c
kernel/time/timekeeping.c

diff --combined arch/x86/kernel/tsc.c
@@@ -740,7 -740,7 +740,7 @@@ static cycle_t __vsyscall_fn vread_tsc(
  }
  #endif
  
- static void resume_tsc(void)
+ static void resume_tsc(struct clocksource *cs)
  {
        clocksource_tsc.cycle_last = 0;
  }
@@@ -806,7 -806,7 +806,7 @@@ static void __init check_system_tsc_rel
        unsigned long res_low, res_high;
  
        rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high);
 -      /* Geode_LX - the OLPC CPU has a possibly a very reliable TSC */
 +      /* Geode_LX - the OLPC CPU has a very reliable TSC */
        if (res_low & RTSC_SUSP)
                tsc_clocksource_reliable = 1;
  #endif
@@@ -40,7 -40,6 +40,6 @@@ struct sh_cmt_priv 
        struct platform_device *pdev;
  
        unsigned long flags;
-       unsigned long flags_suspend;
        unsigned long match_value;
        unsigned long next_match_value;
        unsigned long max_match_value;
@@@ -432,6 -431,11 +431,11 @@@ static void sh_cmt_clocksource_disable(
        sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
  }
  
+ static void sh_cmt_clocksource_resume(struct clocksource *cs)
+ {
+       sh_cmt_start(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
+ }
  static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
                                       char *name, unsigned long rating)
  {
        cs->read = sh_cmt_clocksource_read;
        cs->enable = sh_cmt_clocksource_enable;
        cs->disable = sh_cmt_clocksource_disable;
+       cs->suspend = sh_cmt_clocksource_disable;
+       cs->resume = sh_cmt_clocksource_resume;
        cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
        cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
        pr_info("sh_cmt: %s used as clock source\n", cs->name);
@@@ -603,13 -609,18 +609,13 @@@ static int sh_cmt_setup(struct sh_cmt_p
        p->irqaction.handler = sh_cmt_interrupt;
        p->irqaction.dev_id = p;
        p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
 -      ret = setup_irq(irq, &p->irqaction);
 -      if (ret) {
 -              pr_err("sh_cmt: failed to request irq %d\n", irq);
 -              goto err1;
 -      }
  
        /* get hold of clock */
        p->clk = clk_get(&p->pdev->dev, cfg->clk);
        if (IS_ERR(p->clk)) {
                pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk);
                ret = PTR_ERR(p->clk);
 -              goto err2;
 +              goto err1;
        }
  
        if (resource_size(res) == 6) {
                p->clear_bits = ~0xc000;
        }
  
 -      return sh_cmt_register(p, cfg->name,
 -                             cfg->clockevent_rating,
 -                             cfg->clocksource_rating);
 - err2:
 -      remove_irq(irq, &p->irqaction);
 - err1:
 +      ret = sh_cmt_register(p, cfg->name,
 +                            cfg->clockevent_rating,
 +                            cfg->clocksource_rating);
 +      if (ret) {
 +              pr_err("sh_cmt: registration failed\n");
 +              goto err1;
 +      }
 +
 +      ret = setup_irq(irq, &p->irqaction);
 +      if (ret) {
 +              pr_err("sh_cmt: failed to request irq %d\n", irq);
 +              goto err1;
 +      }
 +
 +      return 0;
 +
 +err1:
        iounmap(p->mapbase);
 - err0:
 +err0:
        return ret;
  }
  
@@@ -674,38 -674,11 +680,11 @@@ static int __devexit sh_cmt_remove(stru
        return -EBUSY; /* cannot unregister clockevent and clocksource */
  }
  
- static int sh_cmt_suspend(struct device *dev)
- {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct sh_cmt_priv *p = platform_get_drvdata(pdev);
-       /* save flag state and stop CMT channel */
-       p->flags_suspend = p->flags;
-       sh_cmt_stop(p, p->flags);
-       return 0;
- }
- static int sh_cmt_resume(struct device *dev)
- {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct sh_cmt_priv *p = platform_get_drvdata(pdev);
-       /* start CMT channel from saved state */
-       sh_cmt_start(p, p->flags_suspend);
-       return 0;
- }
- static struct dev_pm_ops sh_cmt_dev_pm_ops = {
-       .suspend = sh_cmt_suspend,
-       .resume = sh_cmt_resume,
- };
  static struct platform_driver sh_cmt_device_driver = {
        .probe          = sh_cmt_probe,
        .remove         = __devexit_p(sh_cmt_remove),
        .driver         = {
                .name   = "sh_cmt",
-               .pm     = &sh_cmt_dev_pm_ops,
        }
  };
  
@@@ -343,19 -343,7 +343,19 @@@ static void clocksource_resume_watchdog
  {
        unsigned long flags;
  
 -      spin_lock_irqsave(&watchdog_lock, flags);
 +      /*
 +       * We use trylock here to avoid a potential dead lock when
 +       * kgdb calls this code after the kernel has been stopped with
 +       * watchdog_lock held. When watchdog_lock is held we just
 +       * return and accept, that the watchdog might trigger and mark
 +       * the monitored clock source (usually TSC) unstable.
 +       *
 +       * This does not affect the other caller clocksource_resume()
 +       * because at this point the kernel is UP, interrupts are
 +       * disabled and nothing can hold watchdog_lock.
 +       */
 +      if (!spin_trylock_irqsave(&watchdog_lock, flags))
 +              return;
        clocksource_reset_watchdog();
        spin_unlock_irqrestore(&watchdog_lock, flags);
  }
@@@ -453,6 -441,18 +453,18 @@@ static inline int clocksource_watchdog_
  #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */
  
  /**
+  * clocksource_suspend - suspend the clocksource(s)
+  */
+ void clocksource_suspend(void)
+ {
+       struct clocksource *cs;
+       list_for_each_entry_reverse(cs, &clocksource_list, list)
+               if (cs->suspend)
+                       cs->suspend(cs);
+ }
+ /**
   * clocksource_resume - resume the clocksource(s)
   */
  void clocksource_resume(void)
  
        list_for_each_entry(cs, &clocksource_list, list)
                if (cs->resume)
-                       cs->resume();
+                       cs->resume(cs);
  
        clocksource_resume_watchdog();
  }
   * clocksource_touch_watchdog - Update watchdog
   *
   * Update the watchdog after exception contexts such as kgdb so as not
 - * to incorrectly trip the watchdog.
 - *
 + * to incorrectly trip the watchdog. This might fail when the kernel
 + * was stopped in code which holds watchdog_lock.
   */
  void clocksource_touch_watchdog(void)
  {
@@@ -622,6 -622,7 +622,7 @@@ static int timekeeping_suspend(struct s
        write_sequnlock_irqrestore(&xtime_lock, flags);
  
        clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
+       clocksource_suspend();
  
        return 0;
  }
@@@ -880,7 -881,6 +881,7 @@@ void getboottime(struct timespec *ts
  
        set_normalized_timespec(ts, -boottime.tv_sec, -boottime.tv_nsec);
  }
 +EXPORT_SYMBOL_GPL(getboottime);
  
  /**
   * monotonic_to_bootbased - Convert the monotonic time to boot based.
@@@ -890,7 -890,6 +891,7 @@@ void monotonic_to_bootbased(struct time
  {
        *ts = timespec_add_safe(*ts, total_sleep_time);
  }
 +EXPORT_SYMBOL_GPL(monotonic_to_bootbased);
  
  unsigned long get_seconds(void)
  {