topology.c revision 4baeb964d96d38dff461af5b9d578f0a9ba67617
1dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens/* 24baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens * Copyright IBM Corp. 2007,2011 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 983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/workqueue.h> 10dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/bootmem.h> 1183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/cpuset.h> 1283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/device.h> 1383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/kernel.h> 14dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/sched.h> 1583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/init.h> 1683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/delay.h> 17dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/cpu.h> 18dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/smp.h> 1983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/mm.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 Carstensstatic struct mask_info book_info; 454cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstenscpumask_t cpu_book_map[NR_CPUS]; 464cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensunsigned char cpu_book_id[NR_CPUS]; 4783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 4883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens/* smp_cpu_state_mutex must be held when accessing this array */ 4983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensint cpu_polarization[NR_CPUS]; 504cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 514cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) 52dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 53dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens cpumask_t mask; 54dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 550f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_clear(&mask); 560b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens if (!topology_enabled || !MACHINE_HAS_TOPOLOGY) { 570b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens cpumask_copy(&mask, cpumask_of(cpu)); 580b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens return mask; 590b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens } 604cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens while (info) { 610f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro if (cpumask_test_cpu(cpu, &info->mask)) { 624cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens mask = info->mask; 63dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens break; 64dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 654cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = info->next; 66dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 670f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro if (cpumask_empty(&mask)) 680f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_copy(&mask, cpumask_of(cpu)); 69dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens return mask; 70dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 71dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 72f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstensstatic struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu, 73f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens struct mask_info *book, 74f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens struct mask_info *core, 754baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens int one_core_per_cpu) 76dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 77dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens unsigned int cpu; 78dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 79c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS); 80c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens cpu < TOPOLOGY_CPU_BITS; 81c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1)) 82dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens { 83dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens unsigned int rcpu, lcpu; 84dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 85c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin; 86dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens for_each_present_cpu(lcpu) { 874cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens if (cpu_logical_map(lcpu) != rcpu) 884cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens continue; 890f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_set_cpu(lcpu, &book->mask); 904cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens cpu_book_id[lcpu] = book->id; 910f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_set_cpu(lcpu, &core->mask); 924baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens if (one_core_per_cpu) { 93f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens cpu_core_id[lcpu] = rcpu; 94f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens core = core->next; 95f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens } else { 96f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens cpu_core_id[lcpu] = core->id; 97f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens } 9883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens cpu_set_polarization(lcpu, tl_cpu->pp); 99dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 100dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 101f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens return core; 102dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 103dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 1044cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic void clear_masks(void) 105dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 1064cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens struct mask_info *info; 107dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 1084cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = &core_info; 1094cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens while (info) { 1100f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_clear(&info->mask); 1114cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = info->next; 1124cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens } 1134cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = &book_info; 1144cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens while (info) { 1150f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro cpumask_clear(&info->mask); 1164cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens info = info->next; 117dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 118dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 119dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 120c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstensstatic union topology_entry *next_tle(union topology_entry *tle) 121dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 122c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens if (!tle->nl) 123c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens return (union topology_entry *)((struct topology_cpu *)tle + 1); 124c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens return (union topology_entry *)((struct topology_container *)tle + 1); 125dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 126dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 1274baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstensstatic void __tl_to_cores_generic(struct sysinfo_15_1_x *info) 128dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 1294cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens struct mask_info *core = &core_info; 13083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens struct mask_info *book = &book_info; 131c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens union topology_entry *tle, *end; 1324cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 133c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens tle = info->tle; 134c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens end = (union topology_entry *)((unsigned long)info + info->length); 135dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens while (tle < end) { 136dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens switch (tle->nl) { 137dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens case 2: 1384cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens book = book->next; 1394cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens book->id = tle->container.id; 140dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens break; 141dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens case 1: 142dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens core = core->next; 14310d3858950557cd3cc05f647ede597114c610177Heiko Carstens core->id = tle->container.id; 144dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens break; 145dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens case 0: 1464baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens add_cpus_to_mask(&tle->cpu, book, core, 0); 147dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens break; 148dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens default: 1494cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens clear_masks(); 1504baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens return; 151dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 152dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens tle = next_tle(tle); 153dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 1544baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens} 1554baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens 1564baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstensstatic void __tl_to_cores_z10(struct sysinfo_15_1_x *info) 1574baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens{ 1584baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens struct mask_info *core = &core_info; 1594baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens struct mask_info *book = &book_info; 1604baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens union topology_entry *tle, *end; 1614baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens 1624baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens tle = info->tle; 1634baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens end = (union topology_entry *)((unsigned long)info + info->length); 1644baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens while (tle < end) { 1654baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens switch (tle->nl) { 1664baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens case 1: 1674baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens book = book->next; 1684baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens book->id = tle->container.id; 1694baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens break; 1704baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens case 0: 1714baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens core = add_cpus_to_mask(&tle->cpu, book, core, 1); 1724baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens break; 1734baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens default: 1744baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens clear_masks(); 1754baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens return; 1764baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens } 1774baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens tle = next_tle(tle); 1784baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens } 1794baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens} 1804baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens 1814baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstensstatic void tl_to_cores(struct sysinfo_15_1_x *info) 1824baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens{ 1834baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens struct cpuid cpu_id; 1844baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens 1854baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens get_cpu_id(&cpu_id); 1864baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens spin_lock_irq(&topology_lock); 1874baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens clear_masks(); 1884baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens switch (cpu_id.machine) { 1894baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens case 0x2097: 1904baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens case 0x2098: 1914baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens __tl_to_cores_z10(info); 1924baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens break; 1934baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens default: 1944baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens __tl_to_cores_generic(info); 1954baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens } 19674af283102b358b0da545460d0d176f473e110f6Heiko Carstens spin_unlock_irq(&topology_lock); 197dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 198dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 199c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensstatic void topology_update_polarization_simple(void) 200c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{ 201c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens int cpu; 202c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 203c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens mutex_lock(&smp_cpu_state_mutex); 2045439050f9f1aa92381ab9beccbea6ddf0c687c2bHeiko Carstens for_each_possible_cpu(cpu) 20583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens cpu_set_polarization(cpu, POLARIZATION_HRZ); 206c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens mutex_unlock(&smp_cpu_state_mutex); 207c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens} 208c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 209c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensstatic int ptf(unsigned long fc) 210dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 211dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens int rc; 212dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 213dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens asm volatile( 214dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens " .insn rre,0xb9a20000,%1,%1\n" 215dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens " ipm %0\n" 216dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens " srl %0,28\n" 217dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens : "=d" (rc) 218c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens : "d" (fc) : "cc"); 219c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens return rc; 220c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens} 221c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 222c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensint topology_set_cpu_management(int fc) 223c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{ 22483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens int cpu, rc; 225c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 2269186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens if (!MACHINE_HAS_TOPOLOGY) 227c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens return -EOPNOTSUPP; 228c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens if (fc) 229c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens rc = ptf(PTF_VERTICAL); 230c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens else 231c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens rc = ptf(PTF_HORIZONTAL); 232c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens if (rc) 233c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens return -EBUSY; 2345439050f9f1aa92381ab9beccbea6ddf0c687c2bHeiko Carstens for_each_possible_cpu(cpu) 23583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); 236dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens return rc; 237dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 238dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 239d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstensstatic void update_cpu_core_map(void) 240d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens{ 2414cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens unsigned long flags; 242d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens int cpu; 243d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens 2444cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens spin_lock_irqsave(&topology_lock, flags); 2454cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens for_each_possible_cpu(cpu) { 2464cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens cpu_core_map[cpu] = cpu_group_map(&core_info, cpu); 2474cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens cpu_book_map[cpu] = cpu_group_map(&book_info, cpu); 2484cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens } 2494cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens spin_unlock_irqrestore(&topology_lock, flags); 2504cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens} 2514cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 25296f4a70d8eb4d746b19d5b5510407c8ff0d00340Heiko Carstensvoid store_topology(struct sysinfo_15_1_x *info) 2534cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens{ 2544cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens int rc; 2554cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 2564cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens rc = stsi(info, 15, 1, 3); 2574cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens if (rc != -ENOSYS) 2584cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens return; 2594cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens stsi(info, 15, 1, 2); 260d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens} 261d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens 262ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstensint arch_update_cpu_topology(void) 263dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 264c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens struct sysinfo_15_1_x *info = tl_info; 265dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens struct sys_device *sysdev; 266dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens int cpu; 267dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 2689186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens if (!MACHINE_HAS_TOPOLOGY) { 269d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens update_cpu_core_map(); 270c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens topology_update_polarization_simple(); 271ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstens return 0; 272c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens } 2734cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens store_topology(info); 274dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens tl_to_cores(info); 275d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens update_cpu_core_map(); 276dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens for_each_online_cpu(cpu) { 277dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens sysdev = get_cpu_sysdev(cpu); 278dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens kobject_uevent(&sysdev->kobj, KOBJ_CHANGE); 279dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens } 280ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstens return 1; 281dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 282dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 283fd781fa25c9e9c6fd1599df060b05e7c4ad724e5Heiko Carstensstatic void topology_work_fn(struct work_struct *work) 284fd781fa25c9e9c6fd1599df060b05e7c4ad724e5Heiko Carstens{ 285f414f5f15376764d68a31dc568d9e814d3fcb58aHeiko Carstens rebuild_sched_domains(); 286dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 287dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 288c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensvoid topology_schedule_update(void) 289c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{ 290c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens schedule_work(&topology_work); 291c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens} 292c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens 293dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void topology_timer_fn(unsigned long ignored) 294dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 295c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens if (ptf(PTF_CHECK)) 296c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens topology_schedule_update(); 297dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens set_topology_timer(); 298dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 299dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 300dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void set_topology_timer(void) 301dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 302dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens topology_timer.function = topology_timer_fn; 303dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens topology_timer.data = 0; 304dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens topology_timer.expires = jiffies + 60 * HZ; 305dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens add_timer(&topology_timer); 306dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 307dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 3082b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstensstatic int __init early_parse_topology(char *p) 309dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 310c9af3fa9e1e3e5154649991a14b74f3a2dee19eeHeiko Carstens if (strncmp(p, "off", 3)) 3112b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstens return 0; 312c9af3fa9e1e3e5154649991a14b74f3a2dee19eeHeiko Carstens topology_enabled = 0; 3132b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstens return 0; 314dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 3152b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstensearly_param("topology", early_parse_topology); 316dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 317caa04f69df9a5d4c10867b475006cf6f2f1e8500Sebastian Ottstatic void __init alloc_masks(struct sysinfo_15_1_x *info, 318caa04f69df9a5d4c10867b475006cf6f2f1e8500Sebastian Ott struct mask_info *mask, int offset) 3194cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens{ 3204cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens int i, nr_masks; 3214cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 322c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens nr_masks = info->mag[TOPOLOGY_NR_MAG - offset]; 3234cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens for (i = 0; i < info->mnest - offset; i++) 324c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i]; 3254cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens nr_masks = max(nr_masks, 1); 3264cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens for (i = 0; i < nr_masks; i++) { 3274cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens mask->next = alloc_bootmem(sizeof(struct mask_info)); 3284cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens mask = mask->next; 3294cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens } 3304cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens} 3314cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens 332dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensvoid __init s390_init_cpu_topology(void) 333dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{ 334c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens struct sysinfo_15_1_x *info; 335dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens int i; 336dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens 3379186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens if (!MACHINE_HAS_TOPOLOGY) 338dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens return; 339dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens tl_info = alloc_bootmem_pages(PAGE_SIZE); 340dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens info = tl_info; 3414cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens store_topology(info); 342395d31d40cc38270dd7c024691404e2eddf0678dMartin Schwidefsky pr_info("The CPU configuration topology of the machine is:"); 343c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens for (i = 0; i < TOPOLOGY_NR_MAG; i++) 34483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens printk(KERN_CONT " %d", info->mag[i]); 34583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens printk(KERN_CONT " / %d\n", info->mnest); 346f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens alloc_masks(info, &core_info, 1); 347f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens alloc_masks(info, &book_info, 2); 348dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens} 34983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 35083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic int cpu_management; 35183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 35283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic ssize_t dispatching_show(struct sysdev_class *class, 35383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens struct sysdev_class_attribute *attr, 35483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens char *buf) 35583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{ 35683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens ssize_t count; 35783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 35883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens mutex_lock(&smp_cpu_state_mutex); 35983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens count = sprintf(buf, "%d\n", cpu_management); 36083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens mutex_unlock(&smp_cpu_state_mutex); 36183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens return count; 36283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens} 36383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 36483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic ssize_t dispatching_store(struct sysdev_class *dev, 36583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens struct sysdev_class_attribute *attr, 36683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens const char *buf, 36783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens size_t count) 36883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{ 36983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens int val, rc; 37083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens char delim; 37183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 37283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens if (sscanf(buf, "%d %c", &val, &delim) != 1) 37383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens return -EINVAL; 37483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens if (val != 0 && val != 1) 37583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens return -EINVAL; 37683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens rc = 0; 37783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens get_online_cpus(); 37883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens mutex_lock(&smp_cpu_state_mutex); 37983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens if (cpu_management == val) 38083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens goto out; 38183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens rc = topology_set_cpu_management(val); 38283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens if (!rc) 38383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens cpu_management = val; 38483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensout: 38583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens mutex_unlock(&smp_cpu_state_mutex); 38683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens put_online_cpus(); 38783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens return rc ? rc : count; 38883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens} 38983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, 39083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens dispatching_store); 39183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 39283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic ssize_t cpu_polarization_show(struct sys_device *dev, 39383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens struct sysdev_attribute *attr, char *buf) 39483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{ 39583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens int cpu = dev->id; 39683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens ssize_t count; 39783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 39883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens mutex_lock(&smp_cpu_state_mutex); 39983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens switch (cpu_read_polarization(cpu)) { 40083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens case POLARIZATION_HRZ: 40183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens count = sprintf(buf, "horizontal\n"); 40283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens break; 40383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens case POLARIZATION_VL: 40483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens count = sprintf(buf, "vertical:low\n"); 40583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens break; 40683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens case POLARIZATION_VM: 40783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens count = sprintf(buf, "vertical:medium\n"); 40883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens break; 40983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens case POLARIZATION_VH: 41083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens count = sprintf(buf, "vertical:high\n"); 41183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens break; 41283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens default: 41383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens count = sprintf(buf, "unknown\n"); 41483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens break; 41583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens } 41683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens mutex_unlock(&smp_cpu_state_mutex); 41783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens return count; 41883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens} 41983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL); 42083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 42183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic struct attribute *topology_cpu_attrs[] = { 42283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens &attr_polarization.attr, 42383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens NULL, 42483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}; 42583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 42683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic struct attribute_group topology_cpu_attr_group = { 42783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens .attrs = topology_cpu_attrs, 42883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}; 42983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 43083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensint topology_cpu_init(struct cpu *cpu) 43183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{ 43283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens return sysfs_create_group(&cpu->sysdev.kobj, &topology_cpu_attr_group); 43383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens} 43483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens 43583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic int __init topology_init(void) 43683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{ 43783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens if (!MACHINE_HAS_TOPOLOGY) { 43883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens topology_update_polarization_simple(); 43983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens goto out; 44083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens } 44183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens init_timer_deferrable(&topology_timer); 44283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens set_topology_timer(); 44383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensout: 44483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens update_cpu_core_map(); 44583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens return sysdev_class_create_file(&cpu_sysdev_class, &attr_dispatching); 44683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens} 44783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensdevice_initcall(topology_init); 448