topology.c revision caa04f69df9a5d4c10867b475006cf6f2f1e8500
1dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens/* 2dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens * Copyright IBM Corp. 2007 3dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> 4dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens */ 5dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 6395d31d40cc38270dd7c024691404e2eddf0678dMartin Schwidefsky#define KMSG_COMPONENT "cpu" 7395d31d40cc38270dd7c024691404e2eddf0678dMartin Schwidefsky#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 8395d31d40cc38270dd7c024691404e2eddf0678dMartin Schwidefsky 9dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/kernel.h> 10dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/mm.h> 11dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/init.h> 12dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/device.h> 13dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/bootmem.h> 14dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/sched.h> 15dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/workqueue.h> 16dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/cpu.h> 17dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/smp.h> 18f414f5f15376764d68a31dc568d9e814d3fcb58aHeiko Carstens#include <linux/cpuset.h> 19dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <asm/delay.h> 20dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 21c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens#define PTF_HORIZONTAL (0UL) 22c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens#define PTF_VERTICAL (1UL) 23c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens#define PTF_CHECK (2UL) 24dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 254cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstruct mask_info { 264cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens struct mask_info *next; 2710d3858950557cd3cc05f647ede597114c610177Heiko Carstens unsigned char id; 28dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens cpumask_t mask; 29dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}; 30dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 31c9af3fa9e1e3e5154649991a14b74f3a2dee19eeHeiko Carstensstatic int topology_enabled = 1; 32dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void topology_work_fn(struct work_struct *work); 33c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstensstatic struct sysinfo_15_1_x *tl_info; 34dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic struct timer_list topology_timer; 35dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void set_topology_timer(void); 36dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic DECLARE_WORK(topology_work, topology_work_fn); 3774af283102b358b0da545460d0d176f473e110f6Heiko Carstens/* topology_lock protects the core linked list */ 3874af283102b358b0da545460d0d176f473e110f6Heiko Carstensstatic DEFINE_SPINLOCK(topology_lock); 39dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 404cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic struct mask_info core_info; 41d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstenscpumask_t cpu_core_map[NR_CPUS]; 4210d3858950557cd3cc05f647ede597114c610177Heiko Carstensunsigned char cpu_core_id[NR_CPUS]; 43d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens 444cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#ifdef CONFIG_SCHED_BOOK 454cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic struct mask_info book_info; 464cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstenscpumask_t cpu_book_map[NR_CPUS]; 474cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensunsigned char cpu_book_id[NR_CPUS]; 484cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#endif 494cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 504cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) 51dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 52dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens cpumask_t mask; 53dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 540f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_clear(&mask); 550b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens if (!topology_enabled || !MACHINE_HAS_TOPOLOGY) { 560b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens cpumask_copy(&mask, cpumask_of(cpu)); 570b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens return mask; 580b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens } 594cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens while (info) { 600f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro if (cpumask_test_cpu(cpu, &info->mask)) { 614cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens mask = info->mask; 62dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens break; 63dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 644cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = info->next; 65dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 660f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro if (cpumask_empty(&mask)) 670f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_copy(&mask, cpumask_of(cpu)); 68dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens return mask; 69dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 70dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 71c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstensstatic void add_cpus_to_mask(struct topology_cpu *tl_cpu, 72c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens struct mask_info *book, struct mask_info *core) 73dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 74dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens unsigned int cpu; 75dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 76c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS); 77c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens cpu < TOPOLOGY_CPU_BITS; 78c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1)) 79dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens { 80dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens unsigned int rcpu, lcpu; 81dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 82c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin; 83dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens for_each_present_cpu(lcpu) { 844cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens if (cpu_logical_map(lcpu) != rcpu) 854cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens continue; 864cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#ifdef CONFIG_SCHED_BOOK 870f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_set_cpu(lcpu, &book->mask); 884cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens cpu_book_id[lcpu] = book->id; 894cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#endif 900f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_set_cpu(lcpu, &core->mask); 914cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens cpu_core_id[lcpu] = core->id; 924cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens smp_cpu_polarization[lcpu] = tl_cpu->pp; 93dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 94dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 95dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 96dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 974cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic void clear_masks(void) 98dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 994cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens struct mask_info *info; 100dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 1014cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = &core_info; 1024cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens while (info) { 1030f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_clear(&info->mask); 1044cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = info->next; 1054cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens } 1064cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#ifdef CONFIG_SCHED_BOOK 1074cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = &book_info; 1084cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens while (info) { 1090f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_clear(&info->mask); 1104cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = info->next; 111dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 1124cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#endif 113dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 114dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 115c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstensstatic union topology_entry *next_tle(union topology_entry *tle) 116dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 117c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens if (!tle->nl) 118c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens return (union topology_entry *)((struct topology_cpu *)tle + 1); 119c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens return (union topology_entry *)((struct topology_container *)tle + 1); 120dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 121dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 122c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstensstatic void tl_to_cores(struct sysinfo_15_1_x *info) 123dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 1244cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#ifdef CONFIG_SCHED_BOOK 1254cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens struct mask_info *book = &book_info; 1264cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#else 1274cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens struct mask_info *book = NULL; 1284cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#endif 1294cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens struct mask_info *core = &core_info; 130c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens union topology_entry *tle, *end; 1314cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 132dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 13374af283102b358b0da545460d0d176f473e110f6Heiko Carstens spin_lock_irq(&topology_lock); 1344cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens clear_masks(); 135c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens tle = info->tle; 136c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens end = (union topology_entry *)((unsigned long)info + info->length); 137dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens while (tle < end) { 138dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens switch (tle->nl) { 1394cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#ifdef CONFIG_SCHED_BOOK 140dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens case 2: 1414cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens book = book->next; 1424cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens book->id = tle->container.id; 143dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens break; 1444cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#endif 145dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens case 1: 146dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens core = core->next; 14710d3858950557cd3cc05f647ede597114c610177Heiko Carstens core->id = tle->container.id; 148dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens break; 149dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens case 0: 1504cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens add_cpus_to_mask(&tle->cpu, book, core); 151dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens break; 152dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens default: 1534cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens clear_masks(); 154d7015c120e0ac55d86cabbe7a14997b99f39e282Julia Lawall goto out; 155dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 156dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens tle = next_tle(tle); 157dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 158d7015c120e0ac55d86cabbe7a14997b99f39e282Julia Lawallout: 15974af283102b358b0da545460d0d176f473e110f6Heiko Carstens spin_unlock_irq(&topology_lock); 160dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 161dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 162c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensstatic void topology_update_polarization_simple(void) 163c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{ 164c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens int cpu; 165c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 166c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens mutex_lock(&smp_cpu_state_mutex); 1675439050f9f1aa92381ab9beccbea6ddf0c687c2bHeiko Carstens for_each_possible_cpu(cpu) 168c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens smp_cpu_polarization[cpu] = POLARIZATION_HRZ; 169c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens mutex_unlock(&smp_cpu_state_mutex); 170c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens} 171c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 172c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensstatic int ptf(unsigned long fc) 173dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 174dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens int rc; 175dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 176dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens asm volatile( 177dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens " .insn rre,0xb9a20000,%1,%1\n" 178dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens " ipm %0\n" 179dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens " srl %0,28\n" 180dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens : "=d" (rc) 181c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens : "d" (fc) : "cc"); 182c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens return rc; 183c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens} 184c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 185c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensint topology_set_cpu_management(int fc) 186c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{ 187c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens int cpu; 188c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens int rc; 189c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 1909186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens if (!MACHINE_HAS_TOPOLOGY) 191c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens return -EOPNOTSUPP; 192c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens if (fc) 193c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens rc = ptf(PTF_VERTICAL); 194c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens else 195c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens rc = ptf(PTF_HORIZONTAL); 196c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens if (rc) 197c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens return -EBUSY; 1985439050f9f1aa92381ab9beccbea6ddf0c687c2bHeiko Carstens for_each_possible_cpu(cpu) 199c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN; 200dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens return rc; 201dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 202dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 203d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstensstatic void update_cpu_core_map(void) 204d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens{ 2054cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens unsigned long flags; 206d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens int cpu; 207d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens 2084cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens spin_lock_irqsave(&topology_lock, flags); 2094cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens for_each_possible_cpu(cpu) { 2104cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens cpu_core_map[cpu] = cpu_group_map(&core_info, cpu); 2114cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#ifdef CONFIG_SCHED_BOOK 2124cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens cpu_book_map[cpu] = cpu_group_map(&book_info, cpu); 2134cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#endif 2144cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens } 2154cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens spin_unlock_irqrestore(&topology_lock, flags); 2164cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens} 2174cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 21896f4a70d8eb4d746b19d5b5510407c8ff0d00340Heiko Carstensvoid store_topology(struct sysinfo_15_1_x *info) 2194cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens{ 2204cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#ifdef CONFIG_SCHED_BOOK 2214cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens int rc; 2224cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 2234cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens rc = stsi(info, 15, 1, 3); 2244cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens if (rc != -ENOSYS) 2254cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens return; 2264cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#endif 2274cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens stsi(info, 15, 1, 2); 228d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens} 229d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens 230ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstensint arch_update_cpu_topology(void) 231dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 232c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens struct sysinfo_15_1_x *info = tl_info; 233dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens struct sys_device *sysdev; 234dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens int cpu; 235dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 2369186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens if (!MACHINE_HAS_TOPOLOGY) { 237d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens update_cpu_core_map(); 238c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens topology_update_polarization_simple(); 239ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstens return 0; 240c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens } 2414cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens store_topology(info); 242dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens tl_to_cores(info); 243d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens update_cpu_core_map(); 244dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens for_each_online_cpu(cpu) { 245dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens sysdev = get_cpu_sysdev(cpu); 246dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens kobject_uevent(&sysdev->kobj, KOBJ_CHANGE); 247dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 248ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstens return 1; 249dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 250dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 251fd781fa25c9e9c6fd1599df060b05e7c4ad724e5Heiko Carstensstatic void topology_work_fn(struct work_struct *work) 252fd781fa25c9e9c6fd1599df060b05e7c4ad724e5Heiko Carstens{ 253f414f5f15376764d68a31dc568d9e814d3fcb58aHeiko Carstens rebuild_sched_domains(); 254dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 255dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 256c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensvoid topology_schedule_update(void) 257c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{ 258c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens schedule_work(&topology_work); 259c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens} 260c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 261dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void topology_timer_fn(unsigned long ignored) 262dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 263c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens if (ptf(PTF_CHECK)) 264c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens topology_schedule_update(); 265dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens set_topology_timer(); 266dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 267dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 268dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void set_topology_timer(void) 269dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 270dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens topology_timer.function = topology_timer_fn; 271dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens topology_timer.data = 0; 272dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens topology_timer.expires = jiffies + 60 * HZ; 273dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens add_timer(&topology_timer); 274dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 275dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 2762b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstensstatic int __init early_parse_topology(char *p) 277dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 278c9af3fa9e1e3e5154649991a14b74f3a2dee19eeHeiko Carstens if (strncmp(p, "off", 3)) 2792b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstens return 0; 280c9af3fa9e1e3e5154649991a14b74f3a2dee19eeHeiko Carstens topology_enabled = 0; 2812b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstens return 0; 282dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 2832b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstensearly_param("topology", early_parse_topology); 284dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 285dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic int __init init_topology_update(void) 286dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 287dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens int rc; 288dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 289d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens rc = 0; 2909186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens if (!MACHINE_HAS_TOPOLOGY) { 291c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens topology_update_polarization_simple(); 292d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens goto out; 293c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens } 294c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens init_timer_deferrable(&topology_timer); 295349f1b671a4b2612c1355612bedadc81f86d26f1Heiko Carstens set_topology_timer(); 296d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstensout: 297d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens update_cpu_core_map(); 298d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens return rc; 299dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 300dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens__initcall(init_topology_update); 301dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 302caa04f69df9a5d4c10867b475006cf6f2f1e8500Sebastian Ottstatic void __init alloc_masks(struct sysinfo_15_1_x *info, 303caa04f69df9a5d4c10867b475006cf6f2f1e8500Sebastian Ott struct mask_info *mask, int offset) 3044cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens{ 3054cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens int i, nr_masks; 3064cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 307c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens nr_masks = info->mag[TOPOLOGY_NR_MAG - offset]; 3084cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens for (i = 0; i < info->mnest - offset; i++) 309c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i]; 3104cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens nr_masks = max(nr_masks, 1); 3114cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens for (i = 0; i < nr_masks; i++) { 3124cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens mask->next = alloc_bootmem(sizeof(struct mask_info)); 3134cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens mask = mask->next; 3144cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens } 3154cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens} 3164cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 317dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensvoid __init s390_init_cpu_topology(void) 318dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 319c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens struct sysinfo_15_1_x *info; 320dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens int i; 321dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 3229186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens if (!MACHINE_HAS_TOPOLOGY) 323dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens return; 324dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens tl_info = alloc_bootmem_pages(PAGE_SIZE); 325dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens info = tl_info; 3264cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens store_topology(info); 327395d31d40cc38270dd7c024691404e2eddf0678dMartin Schwidefsky pr_info("The CPU configuration topology of the machine is:"); 328c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens for (i = 0; i < TOPOLOGY_NR_MAG; i++) 329dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens printk(" %d", info->mag[i]); 330dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens printk(" / %d\n", info->mnest); 3314cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens alloc_masks(info, &core_info, 2); 3324cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#ifdef CONFIG_SCHED_BOOK 3334cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens alloc_masks(info, &book_info, 3); 3344cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens#endif 335dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 336