powerpc: Use one common impl. of RTAS timebase sync and use raw spinlock
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 16 Jun 2009 16:42:50 +0000 (16:42 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 26 Jun 2009 06:55:25 +0000 (16:55 +1000)
Several platforms use their own copy of what is essentially the same code,
using RTAS to synchronize the timebases when bringing up new CPUs. This
moves it all into a single common implementation and additionally
turns the spinlock into a raw spinlock since the former can rely on
the timebase not being frozen when spinlock debugging is enabled, and finally
masks interrupts while the timebase is disabled.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/rtas.h
arch/powerpc/kernel/rtas.c
arch/powerpc/platforms/cell/smp.c
arch/powerpc/platforms/chrp/smp.c
arch/powerpc/platforms/pseries/smp.c

index 0af42d20b692a7cffb094afc731dc1c90d5a98b3..168fce726201d3799fc3878e3a7620e1575a6dfd 100644 (file)
@@ -245,5 +245,8 @@ static inline u32 rtas_config_addr(int busno, int devfn, int reg)
                        (devfn << 8) | (reg & 0xff);
 }
 
+extern void __cpuinit rtas_give_timebase(void);
+extern void __cpuinit rtas_take_timebase(void);
+
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_RTAS_H */
index d9a9974c69389539aea8898acf5bf58310bdccc6..c434823b8c83a02b9ccd161e2e22bea1c52a1c65 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/syscalls.h>
 #include <asm/smp.h>
 #include <asm/atomic.h>
+#include <asm/time.h>
 
 struct rtas_t rtas = {
        .lock = __RAW_SPIN_LOCK_UNLOCKED
@@ -971,3 +972,33 @@ int __init early_init_dt_scan_rtas(unsigned long node,
        /* break now */
        return 1;
 }
+
+static raw_spinlock_t timebase_lock;
+static u64 timebase = 0;
+
+void __cpuinit rtas_give_timebase(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       hard_irq_disable();
+       __raw_spin_lock(&timebase_lock);
+       rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
+       timebase = get_tb();
+       __raw_spin_unlock(&timebase_lock);
+
+       while (timebase)
+               barrier();
+       rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
+       local_irq_restore(flags);
+}
+
+void __cpuinit rtas_take_timebase(void)
+{
+       while (!timebase)
+               barrier();
+       __raw_spin_lock(&timebase_lock);
+       set_tb(timebase >> 32, timebase & 0xffffffff);
+       timebase = 0;
+       __raw_spin_unlock(&timebase_lock);
+}
index 9046803c827670a273c5b43d13cee1367ffa16fe..bc97fada48c664662ee59808c9f6424820d42f6a 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/prom.h>
 #include <asm/smp.h>
 #include <asm/paca.h>
-#include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
@@ -140,31 +139,6 @@ static void __devinit smp_cell_setup_cpu(int cpu)
        mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
 }
 
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned long timebase = 0;
-
-static void __devinit cell_give_timebase(void)
-{
-       spin_lock(&timebase_lock);
-       rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-       timebase = get_tb();
-       spin_unlock(&timebase_lock);
-
-       while (timebase)
-               barrier();
-       rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
-}
-
-static void __devinit cell_take_timebase(void)
-{
-       while (!timebase)
-               barrier();
-       spin_lock(&timebase_lock);
-       set_tb(timebase >> 32, timebase & 0xffffffff);
-       timebase = 0;
-       spin_unlock(&timebase_lock);
-}
-
 static void __devinit smp_cell_kick_cpu(int nr)
 {
        BUG_ON(nr < 0 || nr >= NR_CPUS);
@@ -224,8 +198,8 @@ void __init smp_init_cell(void)
 
        /* Non-lpar has additional take/give timebase */
        if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
-               smp_ops->give_timebase = cell_give_timebase;
-               smp_ops->take_timebase = cell_take_timebase;
+               smp_ops->give_timebase = rtas_give_timebase;
+               smp_ops->take_timebase = rtas_take_timebase;
        }
 
        DBG(" <- smp_init_cell()\n");
index 10a4a4d063b6411b04db150f4bd00980aa67a6ee..02cafecc90e32b9562adf267dd689d742605abc3 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
-#include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/mpic.h>
 #include <asm/rtas.h>
@@ -42,40 +41,12 @@ static void __devinit smp_chrp_setup_cpu(int cpu_nr)
        mpic_setup_this_cpu();
 }
 
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned int timebase_upper = 0, timebase_lower = 0;
-
-void __devinit smp_chrp_give_timebase(void)
-{
-       spin_lock(&timebase_lock);
-       rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-       timebase_upper = get_tbu();
-       timebase_lower = get_tbl();
-       spin_unlock(&timebase_lock);
-
-       while (timebase_upper || timebase_lower)
-               barrier();
-       rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
-}
-
-void __devinit smp_chrp_take_timebase(void)
-{
-       while (!(timebase_upper || timebase_lower))
-               barrier();
-       spin_lock(&timebase_lock);
-       set_tb(timebase_upper, timebase_lower);
-       timebase_upper = 0;
-       timebase_lower = 0;
-       spin_unlock(&timebase_lock);
-       printk("CPU %i taken timebase\n", smp_processor_id());
-}
-
 /* CHRP with openpic */
 struct smp_ops_t chrp_smp_ops = {
        .message_pass = smp_mpic_message_pass,
        .probe = smp_mpic_probe,
        .kick_cpu = smp_chrp_kick_cpu,
        .setup_cpu = smp_chrp_setup_cpu,
-       .give_timebase = smp_chrp_give_timebase,
-       .take_timebase = smp_chrp_take_timebase,
+       .give_timebase = rtas_give_timebase,
+       .take_timebase = rtas_take_timebase,
 };
index 1a231c389ba0122ce7f55419962af8a1bbdab25f..1f8f6cfb94f7f504b4f44f025fc02b600b392000 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/prom.h>
 #include <asm/smp.h>
 #include <asm/paca.h>
-#include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
@@ -118,31 +117,6 @@ static void __devinit smp_xics_setup_cpu(int cpu)
 }
 #endif /* CONFIG_XICS */
 
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned long timebase = 0;
-
-static void __devinit pSeries_give_timebase(void)
-{
-       spin_lock(&timebase_lock);
-       rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-       timebase = get_tb();
-       spin_unlock(&timebase_lock);
-
-       while (timebase)
-               barrier();
-       rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
-}
-
-static void __devinit pSeries_take_timebase(void)
-{
-       while (!timebase)
-               barrier();
-       spin_lock(&timebase_lock);
-       set_tb(timebase >> 32, timebase & 0xffffffff);
-       timebase = 0;
-       spin_unlock(&timebase_lock);
-}
-
 static void __devinit smp_pSeries_kick_cpu(int nr)
 {
        BUG_ON(nr < 0 || nr >= NR_CPUS);
@@ -209,8 +183,8 @@ static void __init smp_init_pseries(void)
 
        /* Non-lpar has additional take/give timebase */
        if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
-               smp_ops->give_timebase = pSeries_give_timebase;
-               smp_ops->take_timebase = pSeries_take_timebase;
+               smp_ops->give_timebase = rtas_give_timebase;
+               smp_ops->take_timebase = rtas_take_timebase;
        }
 
        pr_debug(" <- smp_init_pSeries()\n");