topology.c revision 8b646bd759086f6090fe27acf414c0b5faa737f4
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 void set_topology_timer(void);
35dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic DECLARE_WORK(topology_work, topology_work_fn);
3674af283102b358b0da545460d0d176f473e110f6Heiko Carstens/* topology_lock protects the core linked list */
3774af283102b358b0da545460d0d176f473e110f6Heiko Carstensstatic DEFINE_SPINLOCK(topology_lock);
38dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
394cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic struct mask_info core_info;
40d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstenscpumask_t cpu_core_map[NR_CPUS];
4110d3858950557cd3cc05f647ede597114c610177Heiko Carstensunsigned char cpu_core_id[NR_CPUS];
42d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens
434cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic struct mask_info book_info;
444cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstenscpumask_t cpu_book_map[NR_CPUS];
454cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensunsigned char cpu_book_id[NR_CPUS];
4683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
4783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens/* smp_cpu_state_mutex must be held when accessing this array */
4883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensint cpu_polarization[NR_CPUS];
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
71f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstensstatic struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
72f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens					  struct mask_info *book,
73f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens					  struct mask_info *core,
744baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens					  int one_core_per_cpu)
75dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
76dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	unsigned int cpu;
77dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
78c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS);
79c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	     cpu < TOPOLOGY_CPU_BITS;
80c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	     cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1))
81dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	{
828b646bd759086f6090fe27acf414c0b5faa737f4Martin Schwidefsky		unsigned int rcpu;
838b646bd759086f6090fe27acf414c0b5faa737f4Martin Schwidefsky		int lcpu;
84dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
85c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens		rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin;
868b646bd759086f6090fe27acf414c0b5faa737f4Martin Schwidefsky		lcpu = smp_find_processor_id(rcpu);
878b646bd759086f6090fe27acf414c0b5faa737f4Martin Schwidefsky		if (lcpu >= 0) {
880f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro			cpumask_set_cpu(lcpu, &book->mask);
894cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens			cpu_book_id[lcpu] = book->id;
900f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro			cpumask_set_cpu(lcpu, &core->mask);
914baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			if (one_core_per_cpu) {
92f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens				cpu_core_id[lcpu] = rcpu;
93f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens				core = core->next;
94f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens			} else {
95f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens				cpu_core_id[lcpu] = core->id;
96f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens			}
9783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens			cpu_set_polarization(lcpu, tl_cpu->pp);
98dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		}
99dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	}
100f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens	return core;
101dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
102dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
1034cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstensstatic void clear_masks(void)
104dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
1054cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	struct mask_info *info;
106dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
1074cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	info = &core_info;
1084cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	while (info) {
1090f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro		cpumask_clear(&info->mask);
1104cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		info = info->next;
1114cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	}
1124cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	info = &book_info;
1134cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	while (info) {
1140f1959f50646612b247d624bdbf8b0c8816f2a93KOSAKI Motohiro		cpumask_clear(&info->mask);
1154cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		info = info->next;
116dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	}
117dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
118dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
119c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstensstatic union topology_entry *next_tle(union topology_entry *tle)
120dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
121c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	if (!tle->nl)
122c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens		return (union topology_entry *)((struct topology_cpu *)tle + 1);
123c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	return (union topology_entry *)((struct topology_container *)tle + 1);
124dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
125dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
1264baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstensstatic void __tl_to_cores_generic(struct sysinfo_15_1_x *info)
127dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
1284cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	struct mask_info *core = &core_info;
12983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	struct mask_info *book = &book_info;
130c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	union topology_entry *tle, *end;
1314cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens
132c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	tle = info->tle;
133c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	end = (union topology_entry *)((unsigned long)info + info->length);
134dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	while (tle < end) {
135dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		switch (tle->nl) {
136dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		case 2:
1374cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens			book = book->next;
1384cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens			book->id = tle->container.id;
139dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens			break;
140dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		case 1:
141dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens			core = core->next;
14210d3858950557cd3cc05f647ede597114c610177Heiko Carstens			core->id = tle->container.id;
143dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens			break;
144dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		case 0:
1454baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			add_cpus_to_mask(&tle->cpu, book, core, 0);
146dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens			break;
147dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		default:
1484cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens			clear_masks();
1494baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			return;
150dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		}
151dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		tle = next_tle(tle);
152dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	}
1534baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens}
1544baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens
1554baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstensstatic void __tl_to_cores_z10(struct sysinfo_15_1_x *info)
1564baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens{
1574baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	struct mask_info *core = &core_info;
1584baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	struct mask_info *book = &book_info;
1594baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	union topology_entry *tle, *end;
1604baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens
1614baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	tle = info->tle;
1624baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	end = (union topology_entry *)((unsigned long)info + info->length);
1634baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	while (tle < end) {
1644baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		switch (tle->nl) {
1654baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		case 1:
1664baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			book = book->next;
1674baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			book->id = tle->container.id;
1684baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			break;
1694baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		case 0:
1704baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			core = add_cpus_to_mask(&tle->cpu, book, core, 1);
1714baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			break;
1724baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		default:
1734baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			clear_masks();
1744baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens			return;
1754baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		}
1764baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		tle = next_tle(tle);
1774baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	}
1784baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens}
1794baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens
1804baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstensstatic void tl_to_cores(struct sysinfo_15_1_x *info)
1814baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens{
1824baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	struct cpuid cpu_id;
1834baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens
1844baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	get_cpu_id(&cpu_id);
1854baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	spin_lock_irq(&topology_lock);
1864baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	clear_masks();
1874baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	switch (cpu_id.machine) {
1884baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	case 0x2097:
1894baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	case 0x2098:
1904baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		__tl_to_cores_z10(info);
1914baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		break;
1924baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	default:
1934baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens		__tl_to_cores_generic(info);
1944baeb964d96d38dff461af5b9d578f0a9ba67617Heiko Carstens	}
19574af283102b358b0da545460d0d176f473e110f6Heiko Carstens	spin_unlock_irq(&topology_lock);
196dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
197dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
198c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensstatic void topology_update_polarization_simple(void)
199c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{
200c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	int cpu;
201c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
202c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	mutex_lock(&smp_cpu_state_mutex);
2035439050f9f1aa92381ab9beccbea6ddf0c687c2bHeiko Carstens	for_each_possible_cpu(cpu)
20483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		cpu_set_polarization(cpu, POLARIZATION_HRZ);
205c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	mutex_unlock(&smp_cpu_state_mutex);
206c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens}
207c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
208c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensstatic int ptf(unsigned long fc)
209dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
210dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	int rc;
211dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
212dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	asm volatile(
213dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		"	.insn	rre,0xb9a20000,%1,%1\n"
214dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		"	ipm	%0\n"
215dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		"	srl	%0,28\n"
216dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		: "=d" (rc)
217c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		: "d" (fc)  : "cc");
218c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	return rc;
219c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens}
220c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
221c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensint topology_set_cpu_management(int fc)
222c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{
22383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	int cpu, rc;
224c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
2259186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens	if (!MACHINE_HAS_TOPOLOGY)
226c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		return -EOPNOTSUPP;
227c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	if (fc)
228c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		rc = ptf(PTF_VERTICAL);
229c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	else
230c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		rc = ptf(PTF_HORIZONTAL);
231c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	if (rc)
232c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		return -EBUSY;
2335439050f9f1aa92381ab9beccbea6ddf0c687c2bHeiko Carstens	for_each_possible_cpu(cpu)
23483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
235dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	return rc;
236dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
237dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
238d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstensstatic void update_cpu_core_map(void)
239d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens{
2404cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	unsigned long flags;
241d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens	int cpu;
242d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens
2434cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	spin_lock_irqsave(&topology_lock, flags);
2444cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	for_each_possible_cpu(cpu) {
2454cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		cpu_core_map[cpu] = cpu_group_map(&core_info, cpu);
2464cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		cpu_book_map[cpu] = cpu_group_map(&book_info, cpu);
2474cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	}
2484cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	spin_unlock_irqrestore(&topology_lock, flags);
2494cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens}
2504cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens
25196f4a70d8eb4d746b19d5b5510407c8ff0d00340Heiko Carstensvoid store_topology(struct sysinfo_15_1_x *info)
2524cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens{
2534cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	int rc;
2544cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens
2554cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	rc = stsi(info, 15, 1, 3);
2564cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	if (rc != -ENOSYS)
2574cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		return;
2584cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	stsi(info, 15, 1, 2);
259d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens}
260d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens
261ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstensint arch_update_cpu_topology(void)
262dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
263c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	struct sysinfo_15_1_x *info = tl_info;
2648a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers	struct device *dev;
265dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	int cpu;
266dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
2679186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens	if (!MACHINE_HAS_TOPOLOGY) {
268d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens		update_cpu_core_map();
269c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		topology_update_polarization_simple();
270ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstens		return 0;
271c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	}
2724cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	store_topology(info);
273dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	tl_to_cores(info);
274d00aa4e7d0129983fc4389c85e15a066eb4e69a9Heiko Carstens	update_cpu_core_map();
275dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	for_each_online_cpu(cpu) {
2768a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers		dev = get_cpu_device(cpu);
2778a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers		kobject_uevent(&dev->kobj, KOBJ_CHANGE);
278dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	}
279ee79d1bdb6a10499e53f80b1e8d14110215178baHeiko Carstens	return 1;
280dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
281dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
282fd781fa25c9e9c6fd1599df060b05e7c4ad724e5Heiko Carstensstatic void topology_work_fn(struct work_struct *work)
283fd781fa25c9e9c6fd1599df060b05e7c4ad724e5Heiko Carstens{
284f414f5f15376764d68a31dc568d9e814d3fcb58aHeiko Carstens	rebuild_sched_domains();
285dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
286dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
287c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstensvoid topology_schedule_update(void)
288c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens{
289c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	schedule_work(&topology_work);
290c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens}
291c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens
292dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void topology_timer_fn(unsigned long ignored)
293dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
294c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens	if (ptf(PTF_CHECK))
295c10fde0d9e2112c25052a8742e893ec5965c0007Heiko Carstens		topology_schedule_update();
296dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	set_topology_timer();
297dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
298dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
299d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstensstatic struct timer_list topology_timer =
300d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	TIMER_DEFERRED_INITIALIZER(topology_timer_fn, 0, 0);
301d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens
302d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstensstatic atomic_t topology_poll = ATOMIC_INIT(0);
303d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens
304dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensstatic void set_topology_timer(void)
305dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
306d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	if (atomic_add_unless(&topology_poll, -1, 0))
307d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		mod_timer(&topology_timer, jiffies + HZ / 10);
308d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	else
309d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		mod_timer(&topology_timer, jiffies + HZ * 60);
310d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens}
311d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens
312d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstensvoid topology_expect_change(void)
313d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens{
314d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	if (!MACHINE_HAS_TOPOLOGY)
315d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		return;
316d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	/* This is racy, but it doesn't matter since it is just a heuristic.
317d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	 * Worst case is that we poll in a higher frequency for a bit longer.
318d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	 */
319d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	if (atomic_read(&topology_poll) > 60)
320d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		return;
321d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	atomic_add(60, &topology_poll);
322d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	set_topology_timer();
323dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
324dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
3252b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstensstatic int __init early_parse_topology(char *p)
326dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
327c9af3fa9e1e3e5154649991a14b74f3a2dee19eeHeiko Carstens	if (strncmp(p, "off", 3))
3282b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstens		return 0;
329c9af3fa9e1e3e5154649991a14b74f3a2dee19eeHeiko Carstens	topology_enabled = 0;
3302b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstens	return 0;
331dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
3322b1a61f0a8c714c96277bf16a823a84bafa1397dHeiko Carstensearly_param("topology", early_parse_topology);
333dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
334caa04f69df9a5d4c10867b475006cf6f2f1e8500Sebastian Ottstatic void __init alloc_masks(struct sysinfo_15_1_x *info,
335caa04f69df9a5d4c10867b475006cf6f2f1e8500Sebastian Ott			       struct mask_info *mask, int offset)
3364cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens{
3374cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	int i, nr_masks;
3384cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens
339c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	nr_masks = info->mag[TOPOLOGY_NR_MAG - offset];
3404cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	for (i = 0; i < info->mnest - offset; i++)
341c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens		nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i];
3424cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	nr_masks = max(nr_masks, 1);
3434cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	for (i = 0; i < nr_masks; i++) {
3444cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		mask->next = alloc_bootmem(sizeof(struct mask_info));
3454cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens		mask = mask->next;
3464cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	}
3474cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens}
3484cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens
349dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstensvoid __init s390_init_cpu_topology(void)
350dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens{
351c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	struct sysinfo_15_1_x *info;
352dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	int i;
353dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens
3549186d7a9cfd75e51ac4db4a40e0a558371988bd2Heiko Carstens	if (!MACHINE_HAS_TOPOLOGY)
355dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens		return;
356dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	tl_info = alloc_bootmem_pages(PAGE_SIZE);
357dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens	info = tl_info;
3584cb14bc8c54f8489251d5cba8328cb410ead0ceaHeiko Carstens	store_topology(info);
359395d31d40cc38270dd7c024691404e2eddf0678dMartin Schwidefsky	pr_info("The CPU configuration topology of the machine is:");
360c30f91b6a264aef9ffb05e13931514c2a988c495Heiko Carstens	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
36183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		printk(KERN_CONT " %d", info->mag[i]);
36283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	printk(KERN_CONT " / %d\n", info->mnest);
363f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens	alloc_masks(info, &core_info, 1);
364f6bf1a8acd2cb3a92a7b7c9ab03e56a32ac5ece5Heiko Carstens	alloc_masks(info, &book_info, 2);
365dbd70fb499952d0ba282f0159dafacfc31d50313Heiko Carstens}
36683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
36783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic int cpu_management;
36883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
36972f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic ssize_t dispatching_show(struct device *dev,
37072f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds				struct device_attribute *attr,
37183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens				char *buf)
37283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
37383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	ssize_t count;
37483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
37583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_lock(&smp_cpu_state_mutex);
37683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	count = sprintf(buf, "%d\n", cpu_management);
37783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_unlock(&smp_cpu_state_mutex);
37883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	return count;
37983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
38083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
38172f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic ssize_t dispatching_store(struct device *dev,
38272f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds				 struct device_attribute *attr,
38383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens				 const char *buf,
38483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens				 size_t count)
38583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
38683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	int val, rc;
38783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	char delim;
38883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
38983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	if (sscanf(buf, "%d %c", &val, &delim) != 1)
39083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		return -EINVAL;
39183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	if (val != 0 && val != 1)
39283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		return -EINVAL;
39383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	rc = 0;
39483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	get_online_cpus();
39583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_lock(&smp_cpu_state_mutex);
39683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	if (cpu_management == val)
39783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		goto out;
39883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	rc = topology_set_cpu_management(val);
399d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	if (rc)
400d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens		goto out;
401d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	cpu_management = val;
402d68bddb7329a4d47d950d6b0745a7e274d230ed4Heiko Carstens	topology_expect_change();
40383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensout:
40483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_unlock(&smp_cpu_state_mutex);
40583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	put_online_cpus();
40683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	return rc ? rc : count;
40783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
40872f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic DEVICE_ATTR(dispatching, 0644, dispatching_show,
40983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens			 dispatching_store);
41083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
41172f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic ssize_t cpu_polarization_show(struct device *dev,
41272f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds				     struct device_attribute *attr, char *buf)
41383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
41483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	int cpu = dev->id;
41583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	ssize_t count;
41683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
41783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_lock(&smp_cpu_state_mutex);
41883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	switch (cpu_read_polarization(cpu)) {
41983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	case POLARIZATION_HRZ:
42083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "horizontal\n");
42183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
42283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	case POLARIZATION_VL:
42383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "vertical:low\n");
42483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
42583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	case POLARIZATION_VM:
42683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "vertical:medium\n");
42783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
42883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	case POLARIZATION_VH:
42983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "vertical:high\n");
43083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
43183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	default:
43283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		count = sprintf(buf, "unknown\n");
43383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		break;
43483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	}
43583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	mutex_unlock(&smp_cpu_state_mutex);
43683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	return count;
43783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
43872f318897e50c29b91efd1ed24515a93c138a2baLinus Torvaldsstatic DEVICE_ATTR(polarization, 0444, cpu_polarization_show, NULL);
43983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
44083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic struct attribute *topology_cpu_attrs[] = {
44172f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds	&dev_attr_polarization.attr,
44283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	NULL,
44383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens};
44483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
44583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic struct attribute_group topology_cpu_attr_group = {
44683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	.attrs = topology_cpu_attrs,
44783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens};
44883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
44983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensint topology_cpu_init(struct cpu *cpu)
45083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
45172f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds	return sysfs_create_group(&cpu->dev.kobj, &topology_cpu_attr_group);
45283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
45383a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens
45483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensstatic int __init topology_init(void)
45583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens{
45683a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	if (!MACHINE_HAS_TOPOLOGY) {
45783a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		topology_update_polarization_simple();
45883a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens		goto out;
45983a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	}
46083a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	set_topology_timer();
46183a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensout:
46283a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens	update_cpu_core_map();
46372f318897e50c29b91efd1ed24515a93c138a2baLinus Torvalds	return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
46483a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstens}
46583a24e32908476c33ea9abc132c73020e2cd3620Heiko Carstensdevice_initcall(topology_init);
466