1dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens/*
2a53c8fab3f87c995c30ac226a03af95361243144Heiko 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>
1380020fbd65c17d3d9e7d80cfd3fa4c57ae7ff765Heiko Carstens#include <linux/export.h>
1483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/kernel.h>
15dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/sched.h>
1683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/init.h>
1783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/delay.h>
18dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/cpu.h>
19dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens#include <linux/smp.h>
2083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens#include <linux/mm.h>
2178609132795b4e3d6d51c6b67d461bf1626afb2fHeiko Carstens#include <asm/sysinfo.h>
22dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
23c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens#define PTF_HORIZONTAL	(0UL)
24c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens#define PTF_VERTICAL	(1UL)
25c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens#define PTF_CHECK	(2UL)
26dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
274cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstruct mask_info {
284cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	struct mask_info *next;
2910d3858950557cd3cc05f647ede597114c610177Heiko Carstens	unsigned char id;
30dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	cpumask_t mask;
31dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens};
32dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
33d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstatic void set_topology_timer(void);
34dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void topology_work_fn(struct work_struct *work);
35c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstensstatic struct sysinfo_15_1_x *tl_info;
36dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
37d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstatic int topology_enabled = 1;
38d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstatic DECLARE_WORK(topology_work, topology_work_fn);
39d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens
40d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens/* topology_lock protects the socket and book linked lists */
41d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstatic DEFINE_SPINLOCK(topology_lock);
42d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstatic struct mask_info socket_info;
434cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic struct mask_info book_info;
44d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens
45d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstruct cpu_topology_s390 cpu_topology[NR_CPUS];
4680020fbd65c17d3d9e7d80cfd3fa4c57ae7ff765Heiko CarstensEXPORT_SYMBOL_GPL(cpu_topology);
4783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
484cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
49dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
50dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	cpumask_t mask;
51dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
52d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	cpumask_copy(&mask, cpumask_of(cpu));
53d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	if (!topology_enabled || !MACHINE_HAS_TOPOLOGY)
540b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens		return mask;
55d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	for (; info; info = info->next) {
56d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		if (cpumask_test_cpu(cpu, &info->mask))
57d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			return info->mask;
580b52783d4feb14d6ff990a63512a66d6131d41f9Heiko Carstens	}
59dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	return mask;
60dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
61dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
62f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstensstatic struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
63f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens					  struct mask_info *book,
64d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens					  struct mask_info *socket,
65d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens					  int one_socket_per_cpu)
66dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
67dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	unsigned int cpu;
68dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
690327dab0e88b2f4be6ad7dcd5af86d085d2c0603Wei Yongjun	for_each_set_bit(cpu, &tl_cpu->mask[0], TOPOLOGY_CPU_BITS) {
708b646bd759086f6090fe27acf414c0b5faa737f4Martin Schwidefsky		unsigned int rcpu;
718b646bd759086f6090fe27acf414c0b5faa737f4Martin Schwidefsky		int lcpu;
72dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
73c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens		rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin;
748b646bd759086f6090fe27acf414c0b5faa737f4Martin Schwidefsky		lcpu = smp_find_processor_id(rcpu);
75d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		if (lcpu < 0)
76d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			continue;
77d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		cpumask_set_cpu(lcpu, &book->mask);
78d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		cpu_topology[lcpu].book_id = book->id;
79d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		cpumask_set_cpu(lcpu, &socket->mask);
80d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		cpu_topology[lcpu].core_id = rcpu;
81d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		if (one_socket_per_cpu) {
82d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			cpu_topology[lcpu].socket_id = rcpu;
83d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			socket = socket->next;
84d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		} else {
85d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			cpu_topology[lcpu].socket_id = socket->id;
86dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		}
87d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		smp_cpu_set_polarization(lcpu, tl_cpu->pp);
88dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	}
89d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	return socket;
90dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
91dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
924cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic void clear_masks(void)
93dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
944cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	struct mask_info *info;
95dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
96d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	info = &socket_info;
974cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	while (info) {
980f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro		cpumask_clear(&info->mask);
994cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		info = info->next;
1004cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	}
1014cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	info = &book_info;
1024cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	while (info) {
1030f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro		cpumask_clear(&info->mask);
1044cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		info = info->next;
105dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	}
106dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
107dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
108c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstensstatic union topology_entry *next_tle(union topology_entry *tle)
109dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
110c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	if (!tle->nl)
111c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens		return (union topology_entry *)((struct topology_cpu *)tle + 1);
112c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	return (union topology_entry *)((struct topology_container *)tle + 1);
113dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
114dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
115d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstatic void __tl_to_masks_generic(struct sysinfo_15_1_x *info)
116dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
117d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	struct mask_info *socket = &socket_info;
11883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	struct mask_info *book = &book_info;
119c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	union topology_entry *tle, *end;
1204cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens
121c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	tle = info->tle;
122c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	end = (union topology_entry *)((unsigned long)info + info->length);
123dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	while (tle < end) {
124dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		switch (tle->nl) {
125dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		case 2:
1264cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens			book = book->next;
1274cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens			book->id = tle->container.id;
128dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens			break;
129dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		case 1:
130d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			socket = socket->next;
131d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			socket->id = tle->container.id;
132dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens			break;
133dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		case 0:
134d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			add_cpus_to_mask(&tle->cpu, book, socket, 0);
135dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens			break;
136dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		default:
1374cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens			clear_masks();
1384baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			return;
139dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		}
140dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		tle = next_tle(tle);
141dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	}
1424baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens}
1434baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens
144d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstatic void __tl_to_masks_z10(struct sysinfo_15_1_x *info)
1454baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens{
146d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	struct mask_info *socket = &socket_info;
1474baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	struct mask_info *book = &book_info;
1484baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	union topology_entry *tle, *end;
1494baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens
1504baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	tle = info->tle;
1514baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	end = (union topology_entry *)((unsigned long)info + info->length);
1524baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	while (tle < end) {
1534baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		switch (tle->nl) {
1544baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		case 1:
1554baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			book = book->next;
1564baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			book->id = tle->container.id;
1574baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			break;
1584baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		case 0:
159d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			socket = add_cpus_to_mask(&tle->cpu, book, socket, 1);
1604baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			break;
1614baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		default:
1624baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			clear_masks();
1634baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			return;
1644baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		}
1654baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		tle = next_tle(tle);
1664baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	}
1674baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens}
1684baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens
169d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstatic void tl_to_masks(struct sysinfo_15_1_x *info)
1704baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens{
1714baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	struct cpuid cpu_id;
1724baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens
1734baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	spin_lock_irq(&topology_lock);
174d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	get_cpu_id(&cpu_id);
1754baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	clear_masks();
1764baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	switch (cpu_id.machine) {
1774baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	case 0x2097:
1784baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	case 0x2098:
179d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		__tl_to_masks_z10(info);
1804baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		break;
1814baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	default:
182d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		__tl_to_masks_generic(info);
1834baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	}
18474af283102b358b0da545460d0d176f473e110f6Heiko Carstens	spin_unlock_irq(&topology_lock);
185dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
186dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
187c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensstatic void topology_update_polarization_simple(void)
188c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{
189c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	int cpu;
190c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
191c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	mutex_lock(&smp_cpu_state_mutex);
1925439050f9f1aa92381ab9beccbea6ddf0c687c2bHeiko Carstens	for_each_possible_cpu(cpu)
19350ab9a9a60fc83b8e8db36b54f365226e2b139acHeiko Carstens		smp_cpu_set_polarization(cpu, POLARIZATION_HRZ);
194c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	mutex_unlock(&smp_cpu_state_mutex);
195c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens}
196c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
197c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensstatic int ptf(unsigned long fc)
198dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
199dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	int rc;
200dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
201dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	asm volatile(
202dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		"	.insn	rre,0xb9a20000,%1,%1\n"
203dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		"	ipm	%0\n"
204dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		"	srl	%0,28\n"
205dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		: "=d" (rc)
206c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		: "d" (fc)  : "cc");
207c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	return rc;
208c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens}
209c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
210c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensint topology_set_cpu_management(int fc)
211c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{
21283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	int cpu, rc;
213c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
2149186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens	if (!MACHINE_HAS_TOPOLOGY)
215c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		return -EOPNOTSUPP;
216c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	if (fc)
217c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		rc = ptf(PTF_VERTICAL);
218c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	else
219c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		rc = ptf(PTF_HORIZONTAL);
220c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	if (rc)
221c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		return -EBUSY;
2225439050f9f1aa92381ab9beccbea6ddf0c687c2bHeiko Carstens	for_each_possible_cpu(cpu)
22350ab9a9a60fc83b8e8db36b54f365226e2b139acHeiko Carstens		smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
224dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	return rc;
225dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
226dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
227d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstensstatic void update_cpu_masks(void)
228d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens{
2294cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	unsigned long flags;
230d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens	int cpu;
231d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens
2324cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	spin_lock_irqsave(&topology_lock, flags);
2334cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	for_each_possible_cpu(cpu) {
234d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		cpu_topology[cpu].core_mask = cpu_group_map(&socket_info, cpu);
235d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		cpu_topology[cpu].book_mask = cpu_group_map(&book_info, cpu);
236d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		if (!MACHINE_HAS_TOPOLOGY) {
237d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			cpu_topology[cpu].core_id = cpu;
238d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			cpu_topology[cpu].socket_id = cpu;
239d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens			cpu_topology[cpu].book_id = cpu;
240d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		}
2414cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	}
2424cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	spin_unlock_irqrestore(&topology_lock, flags);
2434cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens}
2444cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens
24596f4a70d8eb4d746b19d5b5510407c8ff0d00340Heiko Carstensvoid store_topology(struct sysinfo_15_1_x *info)
2464cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens{
247fade4dc49101e3b68fb375fd2b00d0ef1f31a36fHeiko Carstens	if (topology_max_mnest >= 3)
248fade4dc49101e3b68fb375fd2b00d0ef1f31a36fHeiko Carstens		stsi(info, 15, 1, 3);
249fade4dc49101e3b68fb375fd2b00d0ef1f31a36fHeiko Carstens	else
250fade4dc49101e3b68fb375fd2b00d0ef1f31a36fHeiko Carstens		stsi(info, 15, 1, 2);
251d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens}
252d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens
253ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstensint arch_update_cpu_topology(void)
254dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
255c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	struct sysinfo_15_1_x *info = tl_info;
2568a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers	struct device *dev;
257dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	int cpu;
258dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
2599186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens	if (!MACHINE_HAS_TOPOLOGY) {
260d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens		update_cpu_masks();
261c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		topology_update_polarization_simple();
262ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstens		return 0;
263c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	}
2644cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	store_topology(info);
265d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	tl_to_masks(info);
266d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	update_cpu_masks();
267dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	for_each_online_cpu(cpu) {
2688a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers		dev = get_cpu_device(cpu);
2698a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers		kobject_uevent(&dev->kobj, KOBJ_CHANGE);
270dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	}
271ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstens	return 1;
272dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
273dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
274fd781fa25c9e9c6fd1599df060b05e7c4ad724e5Heiko Carstensstatic void topology_work_fn(struct work_struct *work)
275fd781fa25c9e9c6fd1599df060b05e7c4ad724e5Heiko Carstens{
276f414f5f15376764d68a31dc568d9e814d3fcb58aHeiko Carstens	rebuild_sched_domains();
277dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
278dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
279c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensvoid topology_schedule_update(void)
280c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{
281c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	schedule_work(&topology_work);
282c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens}
283c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
284dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void topology_timer_fn(unsigned long ignored)
285dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
286c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	if (ptf(PTF_CHECK))
287c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		topology_schedule_update();
288dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	set_topology_timer();
289dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
290dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
291d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstensstatic struct timer_list topology_timer =
292d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	TIMER_DEFERRED_INITIALIZER(topology_timer_fn, 0, 0);
293d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens
294d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstensstatic atomic_t topology_poll = ATOMIC_INIT(0);
295d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens
296dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void set_topology_timer(void)
297dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
298d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	if (atomic_add_unless(&topology_poll, -1, 0))
299d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		mod_timer(&topology_timer, jiffies + HZ / 10);
300d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	else
301d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		mod_timer(&topology_timer, jiffies + HZ * 60);
302d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens}
303d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens
304d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstensvoid topology_expect_change(void)
305d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens{
306d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	if (!MACHINE_HAS_TOPOLOGY)
307d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		return;
308d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	/* This is racy, but it doesn't matter since it is just a heuristic.
309d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	 * Worst case is that we poll in a higher frequency for a bit longer.
310d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	 */
311d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	if (atomic_read(&topology_poll) > 60)
312d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		return;
313d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	atomic_add(60, &topology_poll);
314d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	set_topology_timer();
315dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
316dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
3172b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstensstatic int __init early_parse_topology(char *p)
318dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
319c9af3fa9e1e3e5154649991a14b74f3a2dee19eeHeiko Carstens	if (strncmp(p, "off", 3))
3202b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstens		return 0;
321c9af3fa9e1e3e5154649991a14b74f3a2dee19eeHeiko Carstens	topology_enabled = 0;
3222b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstens	return 0;
323dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
3242b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstensearly_param("topology", early_parse_topology);
325dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
326caa04f69df9a5d4c10867b475006cf6f2f1e8500Sebastian Ottstatic void __init alloc_masks(struct sysinfo_15_1_x *info,
327caa04f69df9a5d4c10867b475006cf6f2f1e8500Sebastian Ott			       struct mask_info *mask, int offset)
3284cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens{
3294cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	int i, nr_masks;
3304cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens
331c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	nr_masks = info->mag[TOPOLOGY_NR_MAG - offset];
3324cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	for (i = 0; i < info->mnest - offset; i++)
333c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens		nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i];
3344cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	nr_masks = max(nr_masks, 1);
3354cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	for (i = 0; i < nr_masks; i++) {
33650be634507284eea38df78154d22615d21200b42Philipp Hachtmann		mask->next = alloc_bootmem_align(
33750be634507284eea38df78154d22615d21200b42Philipp Hachtmann			roundup_pow_of_two(sizeof(struct mask_info)),
33850be634507284eea38df78154d22615d21200b42Philipp Hachtmann			roundup_pow_of_two(sizeof(struct mask_info)));
3394cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		mask = mask->next;
3404cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	}
3414cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens}
3424cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens
343dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensvoid __init s390_init_cpu_topology(void)
344dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
345c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	struct sysinfo_15_1_x *info;
346dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	int i;
347dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
3489186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens	if (!MACHINE_HAS_TOPOLOGY)
349dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		return;
350dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	tl_info = alloc_bootmem_pages(PAGE_SIZE);
351dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	info = tl_info;
3524cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	store_topology(info);
353395d31d40cc38270dd7c024691404e2eddf0678dMartin Schwidefsky	pr_info("The CPU configuration topology of the machine is:");
354c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
35583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		printk(KERN_CONT " %d", info->mag[i]);
35683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	printk(KERN_CONT " / %d\n", info->mnest);
357d1e57508fbd63b340788afe6f2c74a608603e714Heiko Carstens	alloc_masks(info, &socket_info, 1);
358f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens	alloc_masks(info, &book_info, 2);
359dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
36083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
36183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic int cpu_management;
36283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
36372f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic ssize_t dispatching_show(struct device *dev,
36472f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds				struct device_attribute *attr,
36583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens				char *buf)
36683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
36783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	ssize_t count;
36883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
36983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_lock(&smp_cpu_state_mutex);
37083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	count = sprintf(buf, "%d\n", cpu_management);
37183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_unlock(&smp_cpu_state_mutex);
37283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	return count;
37383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
37483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
37572f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic ssize_t dispatching_store(struct device *dev,
37672f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds				 struct device_attribute *attr,
37783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens				 const char *buf,
37883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens				 size_t count)
37983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
38083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	int val, rc;
38183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	char delim;
38283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
38383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	if (sscanf(buf, "%d %c", &val, &delim) != 1)
38483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		return -EINVAL;
38583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	if (val != 0 && val != 1)
38683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		return -EINVAL;
38783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	rc = 0;
38883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	get_online_cpus();
38983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_lock(&smp_cpu_state_mutex);
39083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	if (cpu_management == val)
39183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		goto out;
39283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	rc = topology_set_cpu_management(val);
393d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	if (rc)
394d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		goto out;
395d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	cpu_management = val;
396d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	topology_expect_change();
39783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensout:
39883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_unlock(&smp_cpu_state_mutex);
39983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	put_online_cpus();
40083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	return rc ? rc : count;
40183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
40272f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic DEVICE_ATTR(dispatching, 0644, dispatching_show,
40383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens			 dispatching_store);
40483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
40572f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic ssize_t cpu_polarization_show(struct device *dev,
40672f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds				     struct device_attribute *attr, char *buf)
40783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
40883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	int cpu = dev->id;
40983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	ssize_t count;
41083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
41183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_lock(&smp_cpu_state_mutex);
41250ab9a9a60fc83b8e8db36b54f365226e2b139acHeiko Carstens	switch (smp_cpu_get_polarization(cpu)) {
41383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	case POLARIZATION_HRZ:
41483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "horizontal\n");
41583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
41683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	case POLARIZATION_VL:
41783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "vertical:low\n");
41883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
41983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	case POLARIZATION_VM:
42083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "vertical:medium\n");
42183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
42283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	case POLARIZATION_VH:
42383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "vertical:high\n");
42483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
42583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	default:
42683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "unknown\n");
42783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
42883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	}
42983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_unlock(&smp_cpu_state_mutex);
43083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	return count;
43183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
43272f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic DEVICE_ATTR(polarization, 0444, cpu_polarization_show, NULL);
43383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
43483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic struct attribute *topology_cpu_attrs[] = {
43572f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds	&dev_attr_polarization.attr,
43683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	NULL,
43783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens};
43883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
43983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic struct attribute_group topology_cpu_attr_group = {
44083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	.attrs = topology_cpu_attrs,
44183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens};
44283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
44383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensint topology_cpu_init(struct cpu *cpu)
44483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
44572f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds	return sysfs_create_group(&cpu->dev.kobj, &topology_cpu_attr_group);
44683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
44783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
4482dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittotconst struct cpumask *cpu_coregroup_mask(int cpu)
4492dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot{
4502dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot	return &cpu_topology[cpu].core_mask;
4512dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot}
4522dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot
4532dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittotstatic const struct cpumask *cpu_book_mask(int cpu)
4542dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot{
4552dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot	return &cpu_topology[cpu].book_mask;
4562dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot}
4572dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot
4582dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittotstatic struct sched_domain_topology_level s390_topology[] = {
4592dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot	{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
4602dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot	{ cpu_book_mask, SD_INIT_NAME(BOOK) },
4612dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot	{ cpu_cpu_mask, SD_INIT_NAME(DIE) },
4622dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot	{ NULL, },
4632dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot};
4642dfd747629e65f89d2dbceb92fffc763f66228b2Vincent Guittot
46583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic int __init topology_init(void)
46683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
46748e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefsky	if (MACHINE_HAS_TOPOLOGY)
46848e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefsky		set_topology_timer();
46948e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefsky	else
47083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		topology_update_polarization_simple();
47172f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds	return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
47283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
47383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensdevice_initcall(topology_init);
47448e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefsky
47548e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefskystatic int __init early_topology_init(void)
47648e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefsky{
47748e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefsky	set_sched_topology(s390_topology);
47848e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefsky	return 0;
47948e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefsky}
48048e9a6c1f54695609b709bf674aac133794ada00Martin Schwidefskyearly_initcall(early_topology_init);
481