Merge commit 'v3.0' into x86/vdso
H. Peter Anvin [Thu, 4 Aug 2011 23:13:20 +0000 (16:13 -0700)]
1  2 
arch/x86/Kconfig
drivers/char/hpet.c
include/linux/clocksource.h

diff --combined arch/x86/Kconfig
@@@ -93,10 -93,6 +93,10 @@@ config CLOCKSOURCE_WATCHDO
  config GENERIC_CLOCKEVENTS
        def_bool y
  
 +config ARCH_CLOCKSOURCE_DATA
 +      def_bool y
 +      depends on X86_64
 +
  config GENERIC_CLOCKEVENTS_BROADCAST
        def_bool y
        depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
@@@ -1174,7 -1170,7 +1174,7 @@@ comment "NUMA (Summit) requires SMP, 64
  config AMD_NUMA
        def_bool y
        prompt "Old style AMD Opteron NUMA detection"
-       depends on NUMA && PCI
+       depends on X86_64 && NUMA && PCI
        ---help---
          Enable AMD NUMA node topology detection.  You should say Y here if
          you have a multi processor AMD system. This uses an old method to
diff --combined drivers/char/hpet.c
@@@ -163,11 -163,32 +163,32 @@@ static irqreturn_t hpet_interrupt(int i
         * This has the effect of treating non-periodic like periodic.
         */
        if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) {
-               unsigned long m, t;
+               unsigned long m, t, mc, base, k;
+               struct hpet __iomem *hpet = devp->hd_hpet;
+               struct hpets *hpetp = devp->hd_hpets;
  
                t = devp->hd_ireqfreq;
                m = read_counter(&devp->hd_timer->hpet_compare);
-               write_counter(t + m, &devp->hd_timer->hpet_compare);
+               mc = read_counter(&hpet->hpet_mc);
+               /* The time for the next interrupt would logically be t + m,
+                * however, if we are very unlucky and the interrupt is delayed
+                * for longer than t then we will completely miss the next
+                * interrupt if we set t + m and an application will hang.
+                * Therefore we need to make a more complex computation assuming
+                * that there exists a k for which the following is true:
+                * k * t + base < mc + delta
+                * (k + 1) * t + base > mc + delta
+                * where t is the interval in hpet ticks for the given freq,
+                * base is the theoretical start value 0 < base < t,
+                * mc is the main counter value at the time of the interrupt,
+                * delta is the time it takes to write the a value to the
+                * comparator.
+                * k may then be computed as (mc - base + delta) / t .
+                */
+               base = mc % t;
+               k = (mc - base + hpetp->hp_delta) / t;
+               write_counter(t * (k + 1) + base,
+                             &devp->hd_timer->hpet_compare);
        }
  
        if (devp->hd_flags & HPET_SHARED_IRQ)
@@@ -931,7 -952,7 +952,7 @@@ int hpet_alloc(struct hpet_data *hdp
  #ifdef CONFIG_IA64
        if (!hpet_clocksource) {
                hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
 -              CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr);
 +              clocksource_hpet.archdata.fsys_mmio = hpet_mctr;
                clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq);
                hpetp->hp_clocksource = &clocksource_hpet;
                hpet_clocksource = &clocksource_hpet;
  typedef u64 cycle_t;
  struct clocksource;
  
 +#ifdef CONFIG_ARCH_CLOCKSOURCE_DATA
 +#include <asm/clocksource.h>
 +#endif
 +
  /**
   * struct cyclecounter - hardware abstraction for a free running counter
   *    Provides completely state-free accessors to the underlying hardware.
@@@ -157,7 -153,7 +157,7 @@@ extern u64 timecounter_cyc2time(struct 
   * @shift:            cycle to nanosecond divisor (power of two)
   * @max_idle_ns:      max idle time permitted by the clocksource (nsecs)
   * @flags:            flags describing special properties
 - * @vread:            vsyscall based read
 + * @archdata:         arch-specific data
   * @suspend:          suspend function for the clocksource, if necessary
   * @resume:           resume function for the clocksource, if necessary
   */
@@@ -173,13 -169,16 +173,13 @@@ struct clocksource 
        u32 shift;
        u64 max_idle_ns;
  
 -#ifdef CONFIG_IA64
 -      void *fsys_mmio;        /* used by fsyscall asm code */
 -#define CLKSRC_FSYS_MMIO_SET(mmio, addr)      ((mmio) = (addr))
 -#else
 -#define CLKSRC_FSYS_MMIO_SET(mmio, addr)      do { } while (0)
 +#ifdef CONFIG_ARCH_CLOCKSOURCE_DATA
 +      struct arch_clocksource_data archdata;
  #endif
 +
        const char *name;
        struct list_head list;
        int rating;
 -      cycle_t (*vread)(void);
        int (*enable)(struct clocksource *cs);
        void (*disable)(struct clocksource *cs);
        unsigned long flags;
  #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
        /* Watchdog related data, used by the framework */
        struct list_head wd_list;
+       cycle_t cs_last;
        cycle_t wd_last;
  #endif
  } ____cacheline_aligned;