aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r--arch/powerpc/kernel/prom.c120
1 files changed, 107 insertions, 13 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index eac97f48b9b8..3bfe7837e820 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -31,10 +31,10 @@
31#include <linux/kexec.h> 31#include <linux/kexec.h>
32#include <linux/debugfs.h> 32#include <linux/debugfs.h>
33#include <linux/irq.h> 33#include <linux/irq.h>
34#include <linux/lmb.h>
34 35
35#include <asm/prom.h> 36#include <asm/prom.h>
36#include <asm/rtas.h> 37#include <asm/rtas.h>
37#include <asm/lmb.h>
38#include <asm/page.h> 38#include <asm/page.h>
39#include <asm/processor.h> 39#include <asm/processor.h>
40#include <asm/irq.h> 40#include <asm/irq.h>
@@ -51,6 +51,7 @@
51#include <asm/machdep.h> 51#include <asm/machdep.h>
52#include <asm/pSeries_reconfig.h> 52#include <asm/pSeries_reconfig.h>
53#include <asm/pci-bridge.h> 53#include <asm/pci-bridge.h>
54#include <asm/phyp_dump.h>
54#include <asm/kexec.h> 55#include <asm/kexec.h>
55 56
56#ifdef DEBUG 57#ifdef DEBUG
@@ -436,7 +437,7 @@ early_param("mem", early_parse_mem);
436 * The device tree may be allocated beyond our memory limit, or inside the 437 * The device tree may be allocated beyond our memory limit, or inside the
437 * crash kernel region for kdump. If so, move it out of the way. 438 * crash kernel region for kdump. If so, move it out of the way.
438 */ 439 */
439static void move_device_tree(void) 440static void __init move_device_tree(void)
440{ 441{
441 unsigned long start, size; 442 unsigned long start, size;
442 void *p; 443 void *p;
@@ -1040,6 +1041,87 @@ static void __init early_reserve_mem(void)
1040#endif 1041#endif
1041} 1042}
1042 1043
1044#ifdef CONFIG_PHYP_DUMP
1045/**
1046 * phyp_dump_calculate_reserve_size() - reserve variable boot area 5% or arg
1047 *
1048 * Function to find the largest size we need to reserve
1049 * during early boot process.
1050 *
1051 * It either looks for boot param and returns that OR
1052 * returns larger of 256 or 5% rounded down to multiples of 256MB.
1053 *
1054 */
1055static inline unsigned long phyp_dump_calculate_reserve_size(void)
1056{
1057 unsigned long tmp;
1058
1059 if (phyp_dump_info->reserve_bootvar)
1060 return phyp_dump_info->reserve_bootvar;
1061
1062 /* divide by 20 to get 5% of value */
1063 tmp = lmb_end_of_DRAM();
1064 do_div(tmp, 20);
1065
1066 /* round it down in multiples of 256 */
1067 tmp = tmp & ~0x0FFFFFFFUL;
1068
1069 return (tmp > PHYP_DUMP_RMR_END ? tmp : PHYP_DUMP_RMR_END);
1070}
1071
1072/**
1073 * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory
1074 *
1075 * This routine may reserve memory regions in the kernel only
1076 * if the system is supported and a dump was taken in last
1077 * boot instance or if the hardware is supported and the
1078 * scratch area needs to be setup. In other instances it returns
1079 * without reserving anything. The memory in case of dump being
1080 * active is freed when the dump is collected (by userland tools).
1081 */
1082static void __init phyp_dump_reserve_mem(void)
1083{
1084 unsigned long base, size;
1085 unsigned long variable_reserve_size;
1086
1087 if (!phyp_dump_info->phyp_dump_configured) {
1088 printk(KERN_ERR "Phyp-dump not supported on this hardware\n");
1089 return;
1090 }
1091
1092 if (!phyp_dump_info->phyp_dump_at_boot) {
1093 printk(KERN_INFO "Phyp-dump disabled at boot time\n");
1094 return;
1095 }
1096
1097 variable_reserve_size = phyp_dump_calculate_reserve_size();
1098
1099 if (phyp_dump_info->phyp_dump_is_active) {
1100 /* Reserve *everything* above RMR.Area freed by userland tools*/
1101 base = variable_reserve_size;
1102 size = lmb_end_of_DRAM() - base;
1103
1104 /* XXX crashed_ram_end is wrong, since it may be beyond
1105 * the memory_limit, it will need to be adjusted. */
1106 lmb_reserve(base, size);
1107
1108 phyp_dump_info->init_reserve_start = base;
1109 phyp_dump_info->init_reserve_size = size;
1110 } else {
1111 size = phyp_dump_info->cpu_state_size +
1112 phyp_dump_info->hpte_region_size +
1113 variable_reserve_size;
1114 base = lmb_end_of_DRAM() - size;
1115 lmb_reserve(base, size);
1116 phyp_dump_info->init_reserve_start = base;
1117 phyp_dump_info->init_reserve_size = size;
1118 }
1119}
1120#else
1121static inline void __init phyp_dump_reserve_mem(void) {}
1122#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */
1123
1124
1043void __init early_init_devtree(void *params) 1125void __init early_init_devtree(void *params)
1044{ 1126{
1045 DBG(" -> early_init_devtree(%p)\n", params); 1127 DBG(" -> early_init_devtree(%p)\n", params);
@@ -1052,6 +1134,11 @@ void __init early_init_devtree(void *params)
1052 of_scan_flat_dt(early_init_dt_scan_rtas, NULL); 1134 of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
1053#endif 1135#endif
1054 1136
1137#ifdef CONFIG_PHYP_DUMP
1138 /* scan tree to see if dump occured during last boot */
1139 of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
1140#endif
1141
1055 /* Retrieve various informations from the /chosen node of the 1142 /* Retrieve various informations from the /chosen node of the
1056 * device-tree, including the platform type, initrd location and 1143 * device-tree, including the platform type, initrd location and
1057 * size, TCE reserve, and more ... 1144 * size, TCE reserve, and more ...
@@ -1072,6 +1159,7 @@ void __init early_init_devtree(void *params)
1072 reserve_kdump_trampoline(); 1159 reserve_kdump_trampoline();
1073 reserve_crashkernel(); 1160 reserve_crashkernel();
1074 early_reserve_mem(); 1161 early_reserve_mem();
1162 phyp_dump_reserve_mem();
1075 1163
1076 lmb_enforce_memory_limit(memory_limit); 1164 lmb_enforce_memory_limit(memory_limit);
1077 lmb_analyze(); 1165 lmb_analyze();
@@ -1244,12 +1332,14 @@ EXPORT_SYMBOL(of_node_put);
1244 */ 1332 */
1245void of_attach_node(struct device_node *np) 1333void of_attach_node(struct device_node *np)
1246{ 1334{
1247 write_lock(&devtree_lock); 1335 unsigned long flags;
1336
1337 write_lock_irqsave(&devtree_lock, flags);
1248 np->sibling = np->parent->child; 1338 np->sibling = np->parent->child;
1249 np->allnext = allnodes; 1339 np->allnext = allnodes;
1250 np->parent->child = np; 1340 np->parent->child = np;
1251 allnodes = np; 1341 allnodes = np;
1252 write_unlock(&devtree_lock); 1342 write_unlock_irqrestore(&devtree_lock, flags);
1253} 1343}
1254 1344
1255/* 1345/*
@@ -1260,8 +1350,9 @@ void of_attach_node(struct device_node *np)
1260void of_detach_node(struct device_node *np) 1350void of_detach_node(struct device_node *np)
1261{ 1351{
1262 struct device_node *parent; 1352 struct device_node *parent;
1353 unsigned long flags;
1263 1354
1264 write_lock(&devtree_lock); 1355 write_lock_irqsave(&devtree_lock, flags);
1265 1356
1266 parent = np->parent; 1357 parent = np->parent;
1267 if (!parent) 1358 if (!parent)
@@ -1292,7 +1383,7 @@ void of_detach_node(struct device_node *np)
1292 of_node_set_flag(np, OF_DETACHED); 1383 of_node_set_flag(np, OF_DETACHED);
1293 1384
1294out_unlock: 1385out_unlock:
1295 write_unlock(&devtree_lock); 1386 write_unlock_irqrestore(&devtree_lock, flags);
1296} 1387}
1297 1388
1298#ifdef CONFIG_PPC_PSERIES 1389#ifdef CONFIG_PPC_PSERIES
@@ -1373,20 +1464,21 @@ __initcall(prom_reconfig_setup);
1373int prom_add_property(struct device_node* np, struct property* prop) 1464int prom_add_property(struct device_node* np, struct property* prop)
1374{ 1465{
1375 struct property **next; 1466 struct property **next;
1467 unsigned long flags;
1376 1468
1377 prop->next = NULL; 1469 prop->next = NULL;
1378 write_lock(&devtree_lock); 1470 write_lock_irqsave(&devtree_lock, flags);
1379 next = &np->properties; 1471 next = &np->properties;
1380 while (*next) { 1472 while (*next) {
1381 if (strcmp(prop->name, (*next)->name) == 0) { 1473 if (strcmp(prop->name, (*next)->name) == 0) {
1382 /* duplicate ! don't insert it */ 1474 /* duplicate ! don't insert it */
1383 write_unlock(&devtree_lock); 1475 write_unlock_irqrestore(&devtree_lock, flags);
1384 return -1; 1476 return -1;
1385 } 1477 }
1386 next = &(*next)->next; 1478 next = &(*next)->next;
1387 } 1479 }
1388 *next = prop; 1480 *next = prop;
1389 write_unlock(&devtree_lock); 1481 write_unlock_irqrestore(&devtree_lock, flags);
1390 1482
1391#ifdef CONFIG_PROC_DEVICETREE 1483#ifdef CONFIG_PROC_DEVICETREE
1392 /* try to add to proc as well if it was initialized */ 1484 /* try to add to proc as well if it was initialized */
@@ -1406,9 +1498,10 @@ int prom_add_property(struct device_node* np, struct property* prop)
1406int prom_remove_property(struct device_node *np, struct property *prop) 1498int prom_remove_property(struct device_node *np, struct property *prop)
1407{ 1499{
1408 struct property **next; 1500 struct property **next;
1501 unsigned long flags;
1409 int found = 0; 1502 int found = 0;
1410 1503
1411 write_lock(&devtree_lock); 1504 write_lock_irqsave(&devtree_lock, flags);
1412 next = &np->properties; 1505 next = &np->properties;
1413 while (*next) { 1506 while (*next) {
1414 if (*next == prop) { 1507 if (*next == prop) {
@@ -1421,7 +1514,7 @@ int prom_remove_property(struct device_node *np, struct property *prop)
1421 } 1514 }
1422 next = &(*next)->next; 1515 next = &(*next)->next;
1423 } 1516 }
1424 write_unlock(&devtree_lock); 1517 write_unlock_irqrestore(&devtree_lock, flags);
1425 1518
1426 if (!found) 1519 if (!found)
1427 return -ENODEV; 1520 return -ENODEV;
@@ -1447,9 +1540,10 @@ int prom_update_property(struct device_node *np,
1447 struct property *oldprop) 1540 struct property *oldprop)
1448{ 1541{
1449 struct property **next; 1542 struct property **next;
1543 unsigned long flags;
1450 int found = 0; 1544 int found = 0;
1451 1545
1452 write_lock(&devtree_lock); 1546 write_lock_irqsave(&devtree_lock, flags);
1453 next = &np->properties; 1547 next = &np->properties;
1454 while (*next) { 1548 while (*next) {
1455 if (*next == oldprop) { 1549 if (*next == oldprop) {
@@ -1463,7 +1557,7 @@ int prom_update_property(struct device_node *np,
1463 } 1557 }
1464 next = &(*next)->next; 1558 next = &(*next)->next;
1465 } 1559 }
1466 write_unlock(&devtree_lock); 1560 write_unlock_irqrestore(&devtree_lock, flags);
1467 1561
1468 if (!found) 1562 if (!found)
1469 return -ENODEV; 1563 return -ENODEV;