diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-10-09 16:13:30 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-10-09 16:13:30 -0400 |
commit | 670aee3fc7ac37ae947f8b582d87b51d5fa36524 (patch) | |
tree | 9885998483d4506208e5aef9c13c8a86adea20bb /arch/mips/mm/init.c | |
parent | d61e87ac53292a3138b4354b687558973686b6ca (diff) | |
parent | 55582bccdc1e89ecc973c260d46e247df675d4df (diff) |
Merge branches 'pm-devfreq' and 'pm-cpufreq'
* pm-devfreq:
PM / devfreq: fix double kfree
PM / devfreq: Fix governor_store()
* pm-cpufreq:
cpufreq: prevent lockup on reading scaling_available_frequencies
cpufreq: acpi_cpufreq: prevent crash on reading freqdomain_cpus
Diffstat (limited to 'arch/mips/mm/init.c')
-rw-r--r-- | arch/mips/mm/init.c | 177 |
1 files changed, 114 insertions, 63 deletions
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 66d0f49c5bec..8770e619185e 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <asm/pgalloc.h> | 44 | #include <asm/pgalloc.h> |
45 | #include <asm/tlb.h> | 45 | #include <asm/tlb.h> |
46 | #include <asm/fixmap.h> | 46 | #include <asm/fixmap.h> |
47 | #include <asm/maar.h> | ||
47 | 48 | ||
48 | /* | 49 | /* |
49 | * We have up to 8 empty zeroed pages so we can map one of the right colour | 50 | * We have up to 8 empty zeroed pages so we can map one of the right colour |
@@ -252,6 +253,119 @@ void __init fixrange_init(unsigned long start, unsigned long end, | |||
252 | #endif | 253 | #endif |
253 | } | 254 | } |
254 | 255 | ||
256 | unsigned __weak platform_maar_init(unsigned num_pairs) | ||
257 | { | ||
258 | struct maar_config cfg[BOOT_MEM_MAP_MAX]; | ||
259 | unsigned i, num_configured, num_cfg = 0; | ||
260 | phys_addr_t skip; | ||
261 | |||
262 | for (i = 0; i < boot_mem_map.nr_map; i++) { | ||
263 | switch (boot_mem_map.map[i].type) { | ||
264 | case BOOT_MEM_RAM: | ||
265 | case BOOT_MEM_INIT_RAM: | ||
266 | break; | ||
267 | default: | ||
268 | continue; | ||
269 | } | ||
270 | |||
271 | skip = 0x10000 - (boot_mem_map.map[i].addr & 0xffff); | ||
272 | |||
273 | cfg[num_cfg].lower = boot_mem_map.map[i].addr; | ||
274 | cfg[num_cfg].lower += skip; | ||
275 | |||
276 | cfg[num_cfg].upper = cfg[num_cfg].lower; | ||
277 | cfg[num_cfg].upper += boot_mem_map.map[i].size - 1; | ||
278 | cfg[num_cfg].upper -= skip; | ||
279 | |||
280 | cfg[num_cfg].attrs = MIPS_MAAR_S; | ||
281 | num_cfg++; | ||
282 | } | ||
283 | |||
284 | num_configured = maar_config(cfg, num_cfg, num_pairs); | ||
285 | if (num_configured < num_cfg) | ||
286 | pr_warn("Not enough MAAR pairs (%u) for all bootmem regions (%u)\n", | ||
287 | num_pairs, num_cfg); | ||
288 | |||
289 | return num_configured; | ||
290 | } | ||
291 | |||
292 | void maar_init(void) | ||
293 | { | ||
294 | unsigned num_maars, used, i; | ||
295 | phys_addr_t lower, upper, attr; | ||
296 | static struct { | ||
297 | struct maar_config cfgs[3]; | ||
298 | unsigned used; | ||
299 | } recorded = { { { 0 } }, 0 }; | ||
300 | |||
301 | if (!cpu_has_maar) | ||
302 | return; | ||
303 | |||
304 | /* Detect the number of MAARs */ | ||
305 | write_c0_maari(~0); | ||
306 | back_to_back_c0_hazard(); | ||
307 | num_maars = read_c0_maari() + 1; | ||
308 | |||
309 | /* MAARs should be in pairs */ | ||
310 | WARN_ON(num_maars % 2); | ||
311 | |||
312 | /* Set MAARs using values we recorded already */ | ||
313 | if (recorded.used) { | ||
314 | used = maar_config(recorded.cfgs, recorded.used, num_maars / 2); | ||
315 | BUG_ON(used != recorded.used); | ||
316 | } else { | ||
317 | /* Configure the required MAARs */ | ||
318 | used = platform_maar_init(num_maars / 2); | ||
319 | } | ||
320 | |||
321 | /* Disable any further MAARs */ | ||
322 | for (i = (used * 2); i < num_maars; i++) { | ||
323 | write_c0_maari(i); | ||
324 | back_to_back_c0_hazard(); | ||
325 | write_c0_maar(0); | ||
326 | back_to_back_c0_hazard(); | ||
327 | } | ||
328 | |||
329 | if (recorded.used) | ||
330 | return; | ||
331 | |||
332 | pr_info("MAAR configuration:\n"); | ||
333 | for (i = 0; i < num_maars; i += 2) { | ||
334 | write_c0_maari(i); | ||
335 | back_to_back_c0_hazard(); | ||
336 | upper = read_c0_maar(); | ||
337 | |||
338 | write_c0_maari(i + 1); | ||
339 | back_to_back_c0_hazard(); | ||
340 | lower = read_c0_maar(); | ||
341 | |||
342 | attr = lower & upper; | ||
343 | lower = (lower & MIPS_MAAR_ADDR) << 4; | ||
344 | upper = ((upper & MIPS_MAAR_ADDR) << 4) | 0xffff; | ||
345 | |||
346 | pr_info(" [%d]: ", i / 2); | ||
347 | if (!(attr & MIPS_MAAR_V)) { | ||
348 | pr_cont("disabled\n"); | ||
349 | continue; | ||
350 | } | ||
351 | |||
352 | pr_cont("%pa-%pa", &lower, &upper); | ||
353 | |||
354 | if (attr & MIPS_MAAR_S) | ||
355 | pr_cont(" speculate"); | ||
356 | |||
357 | pr_cont("\n"); | ||
358 | |||
359 | /* Record the setup for use on secondary CPUs */ | ||
360 | if (used <= ARRAY_SIZE(recorded.cfgs)) { | ||
361 | recorded.cfgs[recorded.used].lower = lower; | ||
362 | recorded.cfgs[recorded.used].upper = upper; | ||
363 | recorded.cfgs[recorded.used].attrs = attr; | ||
364 | recorded.used++; | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | |||
255 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 369 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
256 | int page_is_ram(unsigned long pagenr) | 370 | int page_is_ram(unsigned long pagenr) |
257 | { | 371 | { |
@@ -334,69 +448,6 @@ static inline void mem_init_free_highmem(void) | |||
334 | #endif | 448 | #endif |
335 | } | 449 | } |
336 | 450 | ||
337 | unsigned __weak platform_maar_init(unsigned num_pairs) | ||
338 | { | ||
339 | struct maar_config cfg[BOOT_MEM_MAP_MAX]; | ||
340 | unsigned i, num_configured, num_cfg = 0; | ||
341 | phys_addr_t skip; | ||
342 | |||
343 | for (i = 0; i < boot_mem_map.nr_map; i++) { | ||
344 | switch (boot_mem_map.map[i].type) { | ||
345 | case BOOT_MEM_RAM: | ||
346 | case BOOT_MEM_INIT_RAM: | ||
347 | break; | ||
348 | default: | ||
349 | continue; | ||
350 | } | ||
351 | |||
352 | skip = 0x10000 - (boot_mem_map.map[i].addr & 0xffff); | ||
353 | |||
354 | cfg[num_cfg].lower = boot_mem_map.map[i].addr; | ||
355 | cfg[num_cfg].lower += skip; | ||
356 | |||
357 | cfg[num_cfg].upper = cfg[num_cfg].lower; | ||
358 | cfg[num_cfg].upper += boot_mem_map.map[i].size - 1; | ||
359 | cfg[num_cfg].upper -= skip; | ||
360 | |||
361 | cfg[num_cfg].attrs = MIPS_MAAR_S; | ||
362 | num_cfg++; | ||
363 | } | ||
364 | |||
365 | num_configured = maar_config(cfg, num_cfg, num_pairs); | ||
366 | if (num_configured < num_cfg) | ||
367 | pr_warn("Not enough MAAR pairs (%u) for all bootmem regions (%u)\n", | ||
368 | num_pairs, num_cfg); | ||
369 | |||
370 | return num_configured; | ||
371 | } | ||
372 | |||
373 | static void maar_init(void) | ||
374 | { | ||
375 | unsigned num_maars, used, i; | ||
376 | |||
377 | if (!cpu_has_maar) | ||
378 | return; | ||
379 | |||
380 | /* Detect the number of MAARs */ | ||
381 | write_c0_maari(~0); | ||
382 | back_to_back_c0_hazard(); | ||
383 | num_maars = read_c0_maari() + 1; | ||
384 | |||
385 | /* MAARs should be in pairs */ | ||
386 | WARN_ON(num_maars % 2); | ||
387 | |||
388 | /* Configure the required MAARs */ | ||
389 | used = platform_maar_init(num_maars / 2); | ||
390 | |||
391 | /* Disable any further MAARs */ | ||
392 | for (i = (used * 2); i < num_maars; i++) { | ||
393 | write_c0_maari(i); | ||
394 | back_to_back_c0_hazard(); | ||
395 | write_c0_maar(0); | ||
396 | back_to_back_c0_hazard(); | ||
397 | } | ||
398 | } | ||
399 | |||
400 | void __init mem_init(void) | 451 | void __init mem_init(void) |
401 | { | 452 | { |
402 | #ifdef CONFIG_HIGHMEM | 453 | #ifdef CONFIG_HIGHMEM |