OMAP: McBSP: Rename thres sysfs symbols
[safe/jmp/linux-2.6] / arch / s390 / kernel / smp.c
index b167f74..2270730 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  arch/s390/kernel/smp.c
  *
- *    Copyright IBM Corp. 1999,2007
+ *    Copyright IBM Corp. 1999, 2009
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *              Martin Schwidefsky (schwidefsky@de.ibm.com)
  *              Heiko Carstens (heiko.carstens@de.ibm.com)
@@ -47,7 +47,7 @@
 #include <asm/timer.h>
 #include <asm/lowcore.h>
 #include <asm/sclp.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
 #include <asm/vdso.h>
 #include "entry.h"
 
@@ -226,7 +226,7 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
  */
 #define CPU_INIT_NO    1
 
-#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
+#ifdef CONFIG_ZFCPDUMP
 
 /*
  * zfcpdump_prefix_array holds prefix registers for the following scenario:
@@ -267,7 +267,7 @@ EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
 
 static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
 
-#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */
+#endif /* CONFIG_ZFCPDUMP */
 
 static int cpu_stopped(int cpu)
 {
@@ -297,8 +297,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
 {
        int cpu_id, logical_cpu;
 
-       logical_cpu = first_cpu(avail);
-       if (logical_cpu == NR_CPUS)
+       logical_cpu = cpumask_first(&avail);
+       if (logical_cpu >= nr_cpu_ids)
                return 0;
        for (cpu_id = 0; cpu_id <= 65535; cpu_id++) {
                if (cpu_known(cpu_id))
@@ -309,8 +309,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
                        continue;
                cpu_set(logical_cpu, cpu_present_map);
                smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED;
-               logical_cpu = next_cpu(logical_cpu, avail);
-               if (logical_cpu == NR_CPUS)
+               logical_cpu = cpumask_next(logical_cpu, &avail);
+               if (logical_cpu >= nr_cpu_ids)
                        break;
        }
        return 0;
@@ -322,8 +322,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
        int cpu_id, logical_cpu, cpu;
        int rc;
 
-       logical_cpu = first_cpu(avail);
-       if (logical_cpu == NR_CPUS)
+       logical_cpu = cpumask_first(&avail);
+       if (logical_cpu >= nr_cpu_ids)
                return 0;
        info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
@@ -344,8 +344,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
                        smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY;
                else
                        smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED;
-               logical_cpu = next_cpu(logical_cpu, avail);
-               if (logical_cpu == NR_CPUS)
+               logical_cpu = cpumask_next(logical_cpu, &avail);
+               if (logical_cpu >= nr_cpu_ids)
                        break;
        }
 out:
@@ -508,7 +508,6 @@ out:
        return -ENOMEM;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static void smp_free_lowcore(int cpu)
 {
        struct _lowcore *lowcore;
@@ -527,7 +526,6 @@ static void smp_free_lowcore(int cpu)
        free_pages((unsigned long) lowcore, lc_order);
        lowcore_ptr[cpu] = NULL;
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 /* Upping and downing of CPUs */
 int __cpuinit __cpu_up(unsigned int cpu)
@@ -536,16 +534,23 @@ int __cpuinit __cpu_up(unsigned int cpu)
        struct _lowcore *cpu_lowcore;
        struct stack_frame *sf;
        sigp_ccode ccode;
+       u32 lowcore;
 
        if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED)
                return -EIO;
        if (smp_alloc_lowcore(cpu))
                return -ENOMEM;
-
-       ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]),
-                                  cpu, sigp_set_prefix);
-       if (ccode)
-               return -EIO;
+       do {
+               ccode = signal_processor(cpu, sigp_initial_cpu_reset);
+               if (ccode == sigp_busy)
+                       udelay(10);
+               if (ccode == sigp_not_operational)
+                       goto err_out;
+       } while (ccode == sigp_busy);
+
+       lowcore = (u32)(unsigned long)lowcore_ptr[cpu];
+       while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
+               udelay(10);
 
        idle = current_set[cpu];
        cpu_lowcore = lowcore_ptr[cpu];
@@ -566,7 +571,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
        cpu_lowcore->current_task = (unsigned long) idle;
        cpu_lowcore->cpu_nr = cpu;
        cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
-       cpu_lowcore->ipl_device = S390_lowcore.ipl_device;
+       cpu_lowcore->machine_flags = S390_lowcore.machine_flags;
+       cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func;
        eieio();
 
        while (signal_processor(cpu, sigp_restart) == sigp_busy)
@@ -575,6 +581,10 @@ int __cpuinit __cpu_up(unsigned int cpu)
        while (!cpu_online(cpu))
                cpu_relax();
        return 0;
+
+err_out:
+       smp_free_lowcore(cpu);
+       return -EIO;
 }
 
 static int __init setup_possible_cpus(char *s)
@@ -582,9 +592,9 @@ static int __init setup_possible_cpus(char *s)
        int pcpus, cpu;
 
        pcpus = simple_strtoul(s, NULL, 0);
-       cpu_possible_map = cpumask_of_cpu(0);
-       for (cpu = 1; cpu < pcpus && cpu < NR_CPUS; cpu++)
-               cpu_set(cpu, cpu_possible_map);
+       init_cpu_possible(cpumask_of(0));
+       for (cpu = 1; cpu < pcpus && cpu < nr_cpu_ids; cpu++)
+               set_cpu_possible(cpu, true);
        return 0;
 }
 early_param("possible_cpus", setup_possible_cpus);
@@ -846,13 +856,20 @@ static ssize_t show_idle_count(struct sys_device *dev,
 {
        struct s390_idle_data *idle;
        unsigned long long idle_count;
+       unsigned int sequence;
 
        idle = &per_cpu(s390_idle, dev->id);
-       spin_lock(&idle->lock);
+repeat:
+       sequence = idle->sequence;
+       smp_rmb();
+       if (sequence & 1)
+               goto repeat;
        idle_count = idle->idle_count;
        if (idle->idle_enter)
                idle_count++;
-       spin_unlock(&idle->lock);
+       smp_rmb();
+       if (idle->sequence != sequence)
+               goto repeat;
        return sprintf(buf, "%llu\n", idle_count);
 }
 static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -862,15 +879,22 @@ static ssize_t show_idle_time(struct sys_device *dev,
 {
        struct s390_idle_data *idle;
        unsigned long long now, idle_time, idle_enter;
+       unsigned int sequence;
 
        idle = &per_cpu(s390_idle, dev->id);
-       spin_lock(&idle->lock);
        now = get_clock();
+repeat:
+       sequence = idle->sequence;
+       smp_rmb();
+       if (sequence & 1)
+               goto repeat;
        idle_time = idle->idle_time;
        idle_enter = idle->idle_enter;
        if (idle_enter != 0ULL && idle_enter < now)
                idle_time += now - idle_enter;
-       spin_unlock(&idle->lock);
+       smp_rmb();
+       if (idle->sequence != sequence)
+               goto repeat;
        return sprintf(buf, "%llu\n", idle_time >> 12);
 }
 static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL);
@@ -898,11 +922,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
                idle = &per_cpu(s390_idle, cpu);
-               spin_lock_irq(&idle->lock);
-               idle->idle_enter = 0;
-               idle->idle_time = 0;
-               idle->idle_count = 0;
-               spin_unlock_irq(&idle->lock);
+               memset(idle, 0, sizeof(struct s390_idle_data));
                if (sysfs_create_group(&s->kobj, &cpu_online_attr_group))
                        return NOTIFY_BAD;
                break;
@@ -1021,6 +1041,42 @@ out:
 static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show,
                         dispatching_store);
 
+/*
+ * If the resume kernel runs on another cpu than the suspended kernel,
+ * we have to switch the cpu IDs in the logical map.
+ */
+void smp_switch_boot_cpu_in_resume(u32 resume_phys_cpu_id,
+                                  struct _lowcore *suspend_lowcore)
+{
+       int cpu, suspend_cpu_id, resume_cpu_id;
+       u32 suspend_phys_cpu_id;
+
+       suspend_phys_cpu_id = __cpu_logical_map[suspend_lowcore->cpu_nr];
+       suspend_cpu_id = suspend_lowcore->cpu_nr;
+
+       for_each_present_cpu(cpu) {
+               if (__cpu_logical_map[cpu] == resume_phys_cpu_id) {
+                       resume_cpu_id = cpu;
+                       goto found;
+               }
+       }
+       panic("Could not find resume cpu in logical map.\n");
+
+found:
+       printk("Resume  cpu ID: %i/%i\n", resume_phys_cpu_id, resume_cpu_id);
+       printk("Suspend cpu ID: %i/%i\n", suspend_phys_cpu_id, suspend_cpu_id);
+
+       __cpu_logical_map[resume_cpu_id] = suspend_phys_cpu_id;
+       __cpu_logical_map[suspend_cpu_id] = resume_phys_cpu_id;
+
+       lowcore_ptr[suspend_cpu_id]->cpu_addr = resume_phys_cpu_id;
+}
+
+u32 smp_get_phys_cpu_id(void)
+{
+       return __cpu_logical_map[smp_processor_id()];
+}
+
 static int __init topology_init(void)
 {
        int cpu;