diff options
Diffstat (limited to 'arch/s390/kernel/topology.c')
-rw-r--r-- | arch/s390/kernel/topology.c | 105 |
1 files changed, 33 insertions, 72 deletions
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 13559c993847..94b06c31fc8a 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
@@ -18,55 +18,20 @@ | |||
18 | #include <linux/cpuset.h> | 18 | #include <linux/cpuset.h> |
19 | #include <asm/delay.h> | 19 | #include <asm/delay.h> |
20 | #include <asm/s390_ext.h> | 20 | #include <asm/s390_ext.h> |
21 | #include <asm/sysinfo.h> | ||
22 | |||
23 | #define CPU_BITS 64 | ||
24 | #define NR_MAG 6 | ||
25 | 21 | ||
26 | #define PTF_HORIZONTAL (0UL) | 22 | #define PTF_HORIZONTAL (0UL) |
27 | #define PTF_VERTICAL (1UL) | 23 | #define PTF_VERTICAL (1UL) |
28 | #define PTF_CHECK (2UL) | 24 | #define PTF_CHECK (2UL) |
29 | 25 | ||
30 | struct tl_cpu { | ||
31 | unsigned char reserved0[4]; | ||
32 | unsigned char :6; | ||
33 | unsigned char pp:2; | ||
34 | unsigned char reserved1; | ||
35 | unsigned short origin; | ||
36 | unsigned long mask[CPU_BITS / BITS_PER_LONG]; | ||
37 | }; | ||
38 | |||
39 | struct tl_container { | ||
40 | unsigned char reserved[7]; | ||
41 | unsigned char id; | ||
42 | }; | ||
43 | |||
44 | union tl_entry { | ||
45 | unsigned char nl; | ||
46 | struct tl_cpu cpu; | ||
47 | struct tl_container container; | ||
48 | }; | ||
49 | |||
50 | struct tl_info { | ||
51 | unsigned char reserved0[2]; | ||
52 | unsigned short length; | ||
53 | unsigned char mag[NR_MAG]; | ||
54 | unsigned char reserved1; | ||
55 | unsigned char mnest; | ||
56 | unsigned char reserved2[4]; | ||
57 | union tl_entry tle[0]; | ||
58 | }; | ||
59 | |||
60 | struct mask_info { | 26 | struct mask_info { |
61 | struct mask_info *next; | 27 | struct mask_info *next; |
62 | unsigned char id; | 28 | unsigned char id; |
63 | cpumask_t mask; | 29 | cpumask_t mask; |
64 | }; | 30 | }; |
65 | 31 | ||
66 | static int topology_enabled; | 32 | static int topology_enabled = 1; |
67 | static void topology_work_fn(struct work_struct *work); | 33 | static void topology_work_fn(struct work_struct *work); |
68 | static struct tl_info *tl_info; | 34 | static struct sysinfo_15_1_x *tl_info; |
69 | static int machine_has_topology; | ||
70 | static struct timer_list topology_timer; | 35 | static struct timer_list topology_timer; |
71 | static void set_topology_timer(void); | 36 | static void set_topology_timer(void); |
72 | static DECLARE_WORK(topology_work, topology_work_fn); | 37 | static DECLARE_WORK(topology_work, topology_work_fn); |
@@ -88,8 +53,10 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) | |||
88 | cpumask_t mask; | 53 | cpumask_t mask; |
89 | 54 | ||
90 | cpus_clear(mask); | 55 | cpus_clear(mask); |
91 | if (!topology_enabled || !machine_has_topology) | 56 | if (!topology_enabled || !MACHINE_HAS_TOPOLOGY) { |
92 | return cpu_possible_map; | 57 | cpumask_copy(&mask, cpumask_of(cpu)); |
58 | return mask; | ||
59 | } | ||
93 | while (info) { | 60 | while (info) { |
94 | if (cpu_isset(cpu, info->mask)) { | 61 | if (cpu_isset(cpu, info->mask)) { |
95 | mask = info->mask; | 62 | mask = info->mask; |
@@ -102,18 +69,18 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) | |||
102 | return mask; | 69 | return mask; |
103 | } | 70 | } |
104 | 71 | ||
105 | static void add_cpus_to_mask(struct tl_cpu *tl_cpu, struct mask_info *book, | 72 | static void add_cpus_to_mask(struct topology_cpu *tl_cpu, |
106 | struct mask_info *core) | 73 | struct mask_info *book, struct mask_info *core) |
107 | { | 74 | { |
108 | unsigned int cpu; | 75 | unsigned int cpu; |
109 | 76 | ||
110 | for (cpu = find_first_bit(&tl_cpu->mask[0], CPU_BITS); | 77 | for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS); |
111 | cpu < CPU_BITS; | 78 | cpu < TOPOLOGY_CPU_BITS; |
112 | cpu = find_next_bit(&tl_cpu->mask[0], CPU_BITS, cpu + 1)) | 79 | cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1)) |
113 | { | 80 | { |
114 | unsigned int rcpu, lcpu; | 81 | unsigned int rcpu, lcpu; |
115 | 82 | ||
116 | rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin; | 83 | rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin; |
117 | for_each_present_cpu(lcpu) { | 84 | for_each_present_cpu(lcpu) { |
118 | if (cpu_logical_map(lcpu) != rcpu) | 85 | if (cpu_logical_map(lcpu) != rcpu) |
119 | continue; | 86 | continue; |
@@ -146,15 +113,14 @@ static void clear_masks(void) | |||
146 | #endif | 113 | #endif |
147 | } | 114 | } |
148 | 115 | ||
149 | static union tl_entry *next_tle(union tl_entry *tle) | 116 | static union topology_entry *next_tle(union topology_entry *tle) |
150 | { | 117 | { |
151 | if (tle->nl) | 118 | if (!tle->nl) |
152 | return (union tl_entry *)((struct tl_container *)tle + 1); | 119 | return (union topology_entry *)((struct topology_cpu *)tle + 1); |
153 | else | 120 | return (union topology_entry *)((struct topology_container *)tle + 1); |
154 | return (union tl_entry *)((struct tl_cpu *)tle + 1); | ||
155 | } | 121 | } |
156 | 122 | ||
157 | static void tl_to_cores(struct tl_info *info) | 123 | static void tl_to_cores(struct sysinfo_15_1_x *info) |
158 | { | 124 | { |
159 | #ifdef CONFIG_SCHED_BOOK | 125 | #ifdef CONFIG_SCHED_BOOK |
160 | struct mask_info *book = &book_info; | 126 | struct mask_info *book = &book_info; |
@@ -162,13 +128,13 @@ static void tl_to_cores(struct tl_info *info) | |||
162 | struct mask_info *book = NULL; | 128 | struct mask_info *book = NULL; |
163 | #endif | 129 | #endif |
164 | struct mask_info *core = &core_info; | 130 | struct mask_info *core = &core_info; |
165 | union tl_entry *tle, *end; | 131 | union topology_entry *tle, *end; |
166 | 132 | ||
167 | 133 | ||
168 | spin_lock_irq(&topology_lock); | 134 | spin_lock_irq(&topology_lock); |
169 | clear_masks(); | 135 | clear_masks(); |
170 | tle = info->tle; | 136 | tle = info->tle; |
171 | end = (union tl_entry *)((unsigned long)info + info->length); | 137 | end = (union topology_entry *)((unsigned long)info + info->length); |
172 | while (tle < end) { | 138 | while (tle < end) { |
173 | switch (tle->nl) { | 139 | switch (tle->nl) { |
174 | #ifdef CONFIG_SCHED_BOOK | 140 | #ifdef CONFIG_SCHED_BOOK |
@@ -186,7 +152,6 @@ static void tl_to_cores(struct tl_info *info) | |||
186 | break; | 152 | break; |
187 | default: | 153 | default: |
188 | clear_masks(); | 154 | clear_masks(); |
189 | machine_has_topology = 0; | ||
190 | goto out; | 155 | goto out; |
191 | } | 156 | } |
192 | tle = next_tle(tle); | 157 | tle = next_tle(tle); |
@@ -223,7 +188,7 @@ int topology_set_cpu_management(int fc) | |||
223 | int cpu; | 188 | int cpu; |
224 | int rc; | 189 | int rc; |
225 | 190 | ||
226 | if (!machine_has_topology) | 191 | if (!MACHINE_HAS_TOPOLOGY) |
227 | return -EOPNOTSUPP; | 192 | return -EOPNOTSUPP; |
228 | if (fc) | 193 | if (fc) |
229 | rc = ptf(PTF_VERTICAL); | 194 | rc = ptf(PTF_VERTICAL); |
@@ -251,7 +216,7 @@ static void update_cpu_core_map(void) | |||
251 | spin_unlock_irqrestore(&topology_lock, flags); | 216 | spin_unlock_irqrestore(&topology_lock, flags); |
252 | } | 217 | } |
253 | 218 | ||
254 | static void store_topology(struct tl_info *info) | 219 | void store_topology(struct sysinfo_15_1_x *info) |
255 | { | 220 | { |
256 | #ifdef CONFIG_SCHED_BOOK | 221 | #ifdef CONFIG_SCHED_BOOK |
257 | int rc; | 222 | int rc; |
@@ -265,11 +230,11 @@ static void store_topology(struct tl_info *info) | |||
265 | 230 | ||
266 | int arch_update_cpu_topology(void) | 231 | int arch_update_cpu_topology(void) |
267 | { | 232 | { |
268 | struct tl_info *info = tl_info; | 233 | struct sysinfo_15_1_x *info = tl_info; |
269 | struct sys_device *sysdev; | 234 | struct sys_device *sysdev; |
270 | int cpu; | 235 | int cpu; |
271 | 236 | ||
272 | if (!machine_has_topology) { | 237 | if (!MACHINE_HAS_TOPOLOGY) { |
273 | update_cpu_core_map(); | 238 | update_cpu_core_map(); |
274 | topology_update_polarization_simple(); | 239 | topology_update_polarization_simple(); |
275 | return 0; | 240 | return 0; |
@@ -311,9 +276,9 @@ static void set_topology_timer(void) | |||
311 | 276 | ||
312 | static int __init early_parse_topology(char *p) | 277 | static int __init early_parse_topology(char *p) |
313 | { | 278 | { |
314 | if (strncmp(p, "on", 2)) | 279 | if (strncmp(p, "off", 3)) |
315 | return 0; | 280 | return 0; |
316 | topology_enabled = 1; | 281 | topology_enabled = 0; |
317 | return 0; | 282 | return 0; |
318 | } | 283 | } |
319 | early_param("topology", early_parse_topology); | 284 | early_param("topology", early_parse_topology); |
@@ -323,7 +288,7 @@ static int __init init_topology_update(void) | |||
323 | int rc; | 288 | int rc; |
324 | 289 | ||
325 | rc = 0; | 290 | rc = 0; |
326 | if (!machine_has_topology) { | 291 | if (!MACHINE_HAS_TOPOLOGY) { |
327 | topology_update_polarization_simple(); | 292 | topology_update_polarization_simple(); |
328 | goto out; | 293 | goto out; |
329 | } | 294 | } |
@@ -335,13 +300,14 @@ out: | |||
335 | } | 300 | } |
336 | __initcall(init_topology_update); | 301 | __initcall(init_topology_update); |
337 | 302 | ||
338 | static void alloc_masks(struct tl_info *info, struct mask_info *mask, int offset) | 303 | static void alloc_masks(struct sysinfo_15_1_x *info, struct mask_info *mask, |
304 | int offset) | ||
339 | { | 305 | { |
340 | int i, nr_masks; | 306 | int i, nr_masks; |
341 | 307 | ||
342 | nr_masks = info->mag[NR_MAG - offset]; | 308 | nr_masks = info->mag[TOPOLOGY_NR_MAG - offset]; |
343 | for (i = 0; i < info->mnest - offset; i++) | 309 | for (i = 0; i < info->mnest - offset; i++) |
344 | nr_masks *= info->mag[NR_MAG - offset - 1 - i]; | 310 | nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i]; |
345 | nr_masks = max(nr_masks, 1); | 311 | nr_masks = max(nr_masks, 1); |
346 | for (i = 0; i < nr_masks; i++) { | 312 | for (i = 0; i < nr_masks; i++) { |
347 | mask->next = alloc_bootmem(sizeof(struct mask_info)); | 313 | mask->next = alloc_bootmem(sizeof(struct mask_info)); |
@@ -351,21 +317,16 @@ static void alloc_masks(struct tl_info *info, struct mask_info *mask, int offset | |||
351 | 317 | ||
352 | void __init s390_init_cpu_topology(void) | 318 | void __init s390_init_cpu_topology(void) |
353 | { | 319 | { |
354 | unsigned long long facility_bits; | 320 | struct sysinfo_15_1_x *info; |
355 | struct tl_info *info; | ||
356 | int i; | 321 | int i; |
357 | 322 | ||
358 | if (stfle(&facility_bits, 1) <= 0) | 323 | if (!MACHINE_HAS_TOPOLOGY) |
359 | return; | ||
360 | if (!(facility_bits & (1ULL << 52)) || !(facility_bits & (1ULL << 61))) | ||
361 | return; | 324 | return; |
362 | machine_has_topology = 1; | ||
363 | |||
364 | tl_info = alloc_bootmem_pages(PAGE_SIZE); | 325 | tl_info = alloc_bootmem_pages(PAGE_SIZE); |
365 | info = tl_info; | 326 | info = tl_info; |
366 | store_topology(info); | 327 | store_topology(info); |
367 | pr_info("The CPU configuration topology of the machine is:"); | 328 | pr_info("The CPU configuration topology of the machine is:"); |
368 | for (i = 0; i < NR_MAG; i++) | 329 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) |
369 | printk(" %d", info->mag[i]); | 330 | printk(" %d", info->mag[i]); |
370 | printk(" / %d\n", info->mnest); | 331 | printk(" / %d\n", info->mnest); |
371 | alloc_masks(info, &core_info, 2); | 332 | alloc_masks(info, &core_info, 2); |