|
@@ -59,6 +59,7 @@
|
|
|
#include <asm/epapr_hcalls.h>
|
|
|
#include <asm/firmware.h>
|
|
|
#include <asm/dt_cpu_ftrs.h>
|
|
|
+#include <asm/drmem.h>
|
|
|
|
|
|
#include <mm/mmu_decl.h>
|
|
|
|
|
@@ -455,92 +456,74 @@ static int __init early_init_dt_scan_chosen_ppc(unsigned long node,
|
|
|
|
|
|
#ifdef CONFIG_PPC_PSERIES
|
|
|
/*
|
|
|
- * Interpret the ibm,dynamic-memory property in the
|
|
|
- * /ibm,dynamic-reconfiguration-memory node.
|
|
|
+ * Interpret the ibm dynamic reconfiguration memory LMBs.
|
|
|
* This contains a list of memory blocks along with NUMA affinity
|
|
|
* information.
|
|
|
*/
|
|
|
-static int __init early_init_dt_scan_drconf_memory(unsigned long node)
|
|
|
+static void __init early_init_drmem_lmb(struct drmem_lmb *lmb,
|
|
|
+ const __be32 **usm)
|
|
|
{
|
|
|
- const __be32 *dm, *ls, *usm;
|
|
|
- int l;
|
|
|
- unsigned long n, flags;
|
|
|
- u64 base, size, memblock_size;
|
|
|
- unsigned int is_kexec_kdump = 0, rngs;
|
|
|
-
|
|
|
- ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
|
|
|
- if (ls == NULL || l < dt_root_size_cells * sizeof(__be32))
|
|
|
- return 0;
|
|
|
- memblock_size = dt_mem_next_cell(dt_root_size_cells, &ls);
|
|
|
+ u64 base, size;
|
|
|
+ int is_kexec_kdump = 0, rngs;
|
|
|
|
|
|
- dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
|
|
|
- if (dm == NULL || l < sizeof(__be32))
|
|
|
- return 0;
|
|
|
+ base = lmb->base_addr;
|
|
|
+ size = drmem_lmb_size();
|
|
|
+ rngs = 1;
|
|
|
|
|
|
- n = of_read_number(dm++, 1); /* number of entries */
|
|
|
- if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(__be32))
|
|
|
- return 0;
|
|
|
+ /*
|
|
|
+ * Skip this block if the reserved bit is set in flags
|
|
|
+ * or if the block is not assigned to this partition.
|
|
|
+ */
|
|
|
+ if ((lmb->flags & DRCONF_MEM_RESERVED) ||
|
|
|
+ !(lmb->flags & DRCONF_MEM_ASSIGNED))
|
|
|
+ return;
|
|
|
|
|
|
- /* check if this is a kexec/kdump kernel. */
|
|
|
- usm = of_get_flat_dt_prop(node, "linux,drconf-usable-memory",
|
|
|
- &l);
|
|
|
- if (usm != NULL)
|
|
|
+ if (*usm)
|
|
|
is_kexec_kdump = 1;
|
|
|
|
|
|
- for (; n != 0; --n) {
|
|
|
- base = dt_mem_next_cell(dt_root_addr_cells, &dm);
|
|
|
- flags = of_read_number(&dm[3], 1);
|
|
|
- /* skip DRC index, pad, assoc. list index, flags */
|
|
|
- dm += 4;
|
|
|
- /* skip this block if the reserved bit is set in flags
|
|
|
- or if the block is not assigned to this partition */
|
|
|
- if ((flags & DRCONF_MEM_RESERVED) ||
|
|
|
- !(flags & DRCONF_MEM_ASSIGNED))
|
|
|
- continue;
|
|
|
- size = memblock_size;
|
|
|
- rngs = 1;
|
|
|
+ if (is_kexec_kdump) {
|
|
|
+ /*
|
|
|
+ * For each memblock in ibm,dynamic-memory, a
|
|
|
+ * corresponding entry in linux,drconf-usable-memory
|
|
|
+ * property contains a counter 'p' followed by 'p'
|
|
|
+ * (base, size) duple. Now read the counter from
|
|
|
+ * linux,drconf-usable-memory property
|
|
|
+ */
|
|
|
+ rngs = dt_mem_next_cell(dt_root_size_cells, usm);
|
|
|
+ if (!rngs) /* there are no (base, size) duple */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ do {
|
|
|
if (is_kexec_kdump) {
|
|
|
- /*
|
|
|
- * For each memblock in ibm,dynamic-memory, a corresponding
|
|
|
- * entry in linux,drconf-usable-memory property contains
|
|
|
- * a counter 'p' followed by 'p' (base, size) duple.
|
|
|
- * Now read the counter from
|
|
|
- * linux,drconf-usable-memory property
|
|
|
- */
|
|
|
- rngs = dt_mem_next_cell(dt_root_size_cells, &usm);
|
|
|
- if (!rngs) /* there are no (base, size) duple */
|
|
|
+ base = dt_mem_next_cell(dt_root_addr_cells, usm);
|
|
|
+ size = dt_mem_next_cell(dt_root_size_cells, usm);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (iommu_is_off) {
|
|
|
+ if (base >= 0x80000000ul)
|
|
|
continue;
|
|
|
+ if ((base + size) > 0x80000000ul)
|
|
|
+ size = 0x80000000ul - base;
|
|
|
}
|
|
|
- do {
|
|
|
- if (is_kexec_kdump) {
|
|
|
- base = dt_mem_next_cell(dt_root_addr_cells,
|
|
|
- &usm);
|
|
|
- size = dt_mem_next_cell(dt_root_size_cells,
|
|
|
- &usm);
|
|
|
- }
|
|
|
- if (iommu_is_off) {
|
|
|
- if (base >= 0x80000000ul)
|
|
|
- continue;
|
|
|
- if ((base + size) > 0x80000000ul)
|
|
|
- size = 0x80000000ul - base;
|
|
|
- }
|
|
|
- memblock_add(base, size);
|
|
|
- } while (--rngs);
|
|
|
- }
|
|
|
- memblock_dump_all();
|
|
|
- return 0;
|
|
|
+
|
|
|
+ DBG("Adding: %llx -> %llx\n", base, size);
|
|
|
+ memblock_add(base, size);
|
|
|
+ } while (--rngs);
|
|
|
}
|
|
|
-#else
|
|
|
-#define early_init_dt_scan_drconf_memory(node) 0
|
|
|
#endif /* CONFIG_PPC_PSERIES */
|
|
|
|
|
|
static int __init early_init_dt_scan_memory_ppc(unsigned long node,
|
|
|
const char *uname,
|
|
|
int depth, void *data)
|
|
|
{
|
|
|
+#ifdef CONFIG_PPC_PSERIES
|
|
|
if (depth == 1 &&
|
|
|
- strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0)
|
|
|
- return early_init_dt_scan_drconf_memory(node);
|
|
|
+ strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) {
|
|
|
+ walk_drmem_lmbs_early(node, early_init_drmem_lmb);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+#endif
|
|
|
|
|
|
return early_init_dt_scan_memory(node, uname, depth, data);
|
|
|
}
|