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