]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - arch/s390/kernel/topology.c
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
[linux-2.6.git] / arch / s390 / kernel / topology.c
index 632b13e100538704758cea2eebd75c6cfdc15bf7..90e9ba11eba1940db367d3b23a95187b4b371c70 100644 (file)
@@ -3,6 +3,9 @@
  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
+#define KMSG_COMPONENT "cpu"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/init.h>
@@ -12,6 +15,7 @@
 #include <linux/workqueue.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
+#include <linux/cpuset.h>
 #include <asm/delay.h>
 #include <asm/s390_ext.h>
 #include <asm/sysinfo.h>
@@ -57,26 +61,29 @@ struct core_info {
        cpumask_t mask;
 };
 
+static int topology_enabled;
 static void topology_work_fn(struct work_struct *work);
 static struct tl_info *tl_info;
 static struct core_info core_info;
 static int machine_has_topology;
-static int machine_has_topology_irq;
 static struct timer_list topology_timer;
 static void set_topology_timer(void);
 static DECLARE_WORK(topology_work, topology_work_fn);
+/* topology_lock protects the core linked list */
+static DEFINE_SPINLOCK(topology_lock);
 
 cpumask_t cpu_core_map[NR_CPUS];
 
 cpumask_t cpu_coregroup_map(unsigned int cpu)
 {
        struct core_info *core = &core_info;
+       unsigned long flags;
        cpumask_t mask;
 
        cpus_clear(mask);
-       if (!machine_has_topology)
-               return cpu_present_map;
-       mutex_lock(&smp_cpu_state_mutex);
+       if (!topology_enabled || !machine_has_topology)
+               return cpu_possible_map;
+       spin_lock_irqsave(&topology_lock, flags);
        while (core) {
                if (cpu_isset(cpu, core->mask)) {
                        mask = core->mask;
@@ -84,7 +91,7 @@ cpumask_t cpu_coregroup_map(unsigned int cpu)
                }
                core = core->next;
        }
-       mutex_unlock(&smp_cpu_state_mutex);
+       spin_unlock_irqrestore(&topology_lock, flags);
        if (cpus_empty(mask))
                mask = cpumask_of_cpu(cpu);
        return mask;
@@ -133,7 +140,7 @@ static void tl_to_cores(struct tl_info *info)
        union tl_entry *tle, *end;
        struct core_info *core = &core_info;
 
-       mutex_lock(&smp_cpu_state_mutex);
+       spin_lock_irq(&topology_lock);
        clear_cores();
        tle = info->tle;
        end = (union tl_entry *)((unsigned long)info + info->length);
@@ -157,7 +164,7 @@ static void tl_to_cores(struct tl_info *info)
                }
                tle = next_tle(tle);
        }
-       mutex_unlock(&smp_cpu_state_mutex);
+       spin_unlock_irq(&topology_lock);
 }
 
 static void topology_update_polarization_simple(void)
@@ -165,7 +172,7 @@ static void topology_update_polarization_simple(void)
        int cpu;
 
        mutex_lock(&smp_cpu_state_mutex);
-       for_each_present_cpu(cpu)
+       for_each_possible_cpu(cpu)
                smp_cpu_polarization[cpu] = POLARIZATION_HRZ;
        mutex_unlock(&smp_cpu_state_mutex);
 }
@@ -196,7 +203,7 @@ int topology_set_cpu_management(int fc)
                rc = ptf(PTF_HORIZONTAL);
        if (rc)
                return -EBUSY;
-       for_each_present_cpu(cpu)
+       for_each_possible_cpu(cpu)
                smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
        return rc;
 }
@@ -205,11 +212,11 @@ static void update_cpu_core_map(void)
 {
        int cpu;
 
-       for_each_present_cpu(cpu)
+       for_each_possible_cpu(cpu)
                cpu_core_map[cpu] = cpu_coregroup_map(cpu);
 }
 
-void arch_update_cpu_topology(void)
+int arch_update_cpu_topology(void)
 {
        struct tl_info *info = tl_info;
        struct sys_device *sysdev;
@@ -218,7 +225,7 @@ void arch_update_cpu_topology(void)
        if (!machine_has_topology) {
                update_cpu_core_map();
                topology_update_polarization_simple();
-               return;
+               return 0;
        }
        stsi(info, 15, 1, 2);
        tl_to_cores(info);
@@ -227,11 +234,12 @@ void arch_update_cpu_topology(void)
                sysdev = get_cpu_sysdev(cpu);
                kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
        }
+       return 1;
 }
 
 static void topology_work_fn(struct work_struct *work)
 {
-       arch_reinit_sched_domains();
+       rebuild_sched_domains();
 }
 
 void topology_schedule_update(void)
@@ -254,10 +262,14 @@ static void set_topology_timer(void)
        add_timer(&topology_timer);
 }
 
-static void topology_interrupt(__u16 code)
+static int __init early_parse_topology(char *p)
 {
-       schedule_work(&topology_work);
+       if (strncmp(p, "on", 2))
+               return 0;
+       topology_enabled = 1;
+       return 0;
 }
+early_param("topology", early_parse_topology);
 
 static int __init init_topology_update(void)
 {
@@ -269,14 +281,7 @@ static int __init init_topology_update(void)
                goto out;
        }
        init_timer_deferrable(&topology_timer);
-       if (machine_has_topology_irq) {
-               rc = register_external_interrupt(0x2005, topology_interrupt);
-               if (rc)
-                       goto out;
-               ctl_set_bit(0, 8);
-       }
-       else
-               set_topology_timer();
+       set_topology_timer();
 out:
        update_cpu_core_map();
        return rc;
@@ -297,9 +302,6 @@ void __init s390_init_cpu_topology(void)
                return;
        machine_has_topology = 1;
 
-       if (facility_bits & (1ULL << 51))
-               machine_has_topology_irq = 1;
-
        tl_info = alloc_bootmem_pages(PAGE_SIZE);
        info = tl_info;
        stsi(info, 15, 1, 2);
@@ -308,7 +310,7 @@ void __init s390_init_cpu_topology(void)
        for (i = 0; i < info->mnest - 2; i++)
                nr_cores *= info->mag[NR_MAG - 3 - i];
 
-       printk(KERN_INFO "CPU topology:");
+       pr_info("The CPU configuration topology of the machine is:");
        for (i = 0; i < NR_MAG; i++)
                printk(" %d", info->mag[i]);
        printk(" / %d\n", info->mnest);
@@ -323,5 +325,4 @@ void __init s390_init_cpu_topology(void)
        return;
 error:
        machine_has_topology = 0;
-       machine_has_topology_irq = 0;
 }