summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/mips64/sgi-ip27/ip27-memory.c192
-rw-r--r--arch/mips64/sgi-ip27/ip27-setup.c2
2 files changed, 158 insertions, 36 deletions
diff --git a/arch/mips64/sgi-ip27/ip27-memory.c b/arch/mips64/sgi-ip27/ip27-memory.c
index 286c510b7..368a0d209 100644
--- a/arch/mips64/sgi-ip27/ip27-memory.c
+++ b/arch/mips64/sgi-ip27/ip27-memory.c
@@ -18,54 +18,178 @@
#include <asm/page.h>
#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
#include <asm/sn/klconfig.h>
+#include <asm/sn/arch.h>
+
+typedef unsigned long pfn_t; /* into <asm/sn/types.h> */
+#define KDM_TO_PHYS(x) ((x) & TO_PHYS_MASK) /* into asm/addrspace.h */
+
+#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT) /* into asm/sn/arch.h */
+#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT)
+#define mkpfn(nasid, off) (((pfn_t)(nasid) << PFN_NASIDSHFT) | (off))
+#define slot_getbasepfn(node,slot) \
+ (mkpfn(COMPACT_TO_NASID_NODEID(node), slot<<SLOT_PFNSHIFT))
+extern nasid_t compact_to_nasid_node[];
extern char _end;
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-void __init
-prom_meminit(void)
+short slot_lastfilled_cache[MAX_COMPACT_NODES];
+unsigned short slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS];
+
+/*
+ * Return pfn of first free page of memory on a node. PROM may allocate
+ * data structures on the first couple of pages of the first slot of each
+ * node. If this is the case, getfirstfree(node) > getslotstart(node, 0).
+ */
+pfn_t node_getfirstfree(cnodeid_t cnode)
+{
+#ifdef LATER
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ if (cnode == 0)
+ return KDM_TO_PHYS((unsigned long)(&_end));
+ return KDM_TO_PHYS(SYMMON_STK_ADDR(nasid, 0));
+#endif
+ if (cnode == 0)
+ return (KDM_TO_PHYS(PFN_ALIGN(&_end) - (CKSEG0 - K0BASE))
+ >> PAGE_SHIFT);
+ return slot_getbasepfn(cnode, 0);
+}
+
+/*
+ * Return the number of pages of memory provided by the given slot
+ * on the specified node.
+ */
+pfn_t slot_getsize(cnodeid_t node, int slot)
+{
+ return (pfn_t) slot_psize_cache[node][slot];
+}
+
+/*
+ * Return the pfn of the last free page of memory on a node.
+ */
+pfn_t node_getmaxclick(cnodeid_t node)
+{
+ pfn_t slot_psize;
+ int slot;
+
+ /*
+ * Start at the top slot. When we find a slot with memory in it,
+ * that's the winner.
+ */
+ for (slot = (node_getnumslots(node) - 1); slot >= 0; slot--) {
+ if ((slot_psize = slot_getsize(node, slot))) {
+ /* Return the basepfn + the slot size, minus 1. */
+ return slot_getbasepfn(node, slot) + slot_psize - 1;
+ }
+ }
+
+ /*
+ * If there's no memory on the node, return 0. This is likely
+ * to cause problems.
+ */
+ return (pfn_t)0;
+}
+
+static pfn_t slot_psize_compute(cnodeid_t node, int slot)
{
- unsigned long free_start, free_end, start_pfn, mb, bootmap_size;
- int bank, size;
- lboard_t *board;
- klmembnk_t *mem;
-
- board = find_lboard(KLTYPE_IP27);
- if (!board)
- panic("Can't find memory info for myself.");
-
- mem = (klmembnk_t *) KLCF_COMP(board, IP27_MEM_INDEX);
- if (!mem)
- panic("I'm running but don't exist?");
-
- mb = 0;
- for (bank = 0; bank < MD_MEM_BANKS; bank++) {
- size = KLCONFIG_MEMBNK_SIZE(mem, bank);
- mb += size;
- if (size != 512) {
- break;
+ nasid_t nasid;
+ lboard_t *brd;
+ klmembnk_t *banks;
+ unsigned long size;
+
+ nasid = COMPACT_TO_NASID_NODEID(node);
+ /* Find the node board */
+ brd = find_lboard_real((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
+ if (!brd)
+ return 0;
+
+ /* Get the memory bank structure */
+ banks = (klmembnk_t *)find_first_component(brd, KLSTRUCT_MEMBNK);
+ if (!banks)
+ return 0;
+
+ /* Size in _Megabytes_ */
+ size = (unsigned long)banks->membnk_bnksz[slot/4];
+
+ /* hack for 128 dimm banks */
+ if (size <= 128) {
+ if (slot%4 == 0) {
+ size <<= 20; /* size in bytes */
+ return(size >> PAGE_SHIFT);
+ } else {
+ return 0;
}
+ } else {
+ size /= 4;
+ size <<= 20;
+ return(size >> PAGE_SHIFT);
}
+}
- free_start = PFN_ALIGN(&_end) - (CKSEG0 - K0BASE);
- free_end = K0BASE + (mb << 20);
- start_pfn = PFN_UP((unsigned long)&_end - CKSEG0);
+pfn_t szmem(pfn_t fpage, pfn_t maxpmem)
+{
+ int node, slot;
+ int numslots;
+ pfn_t num_pages = 0;
+ pfn_t slot_psize;
- if (bank != MD_MEM_BANKS && size != 0)
- printk("Warning: noncontiguous memory configuration, "
- "not using entire available memory.");
+ for (node = 0; node < numnodes; node++) {
+ numslots = node_getnumslots(node);
+ for (slot = 0; slot < numslots; slot++) {
+ slot_psize = slot_psize_compute(node, slot);
+ num_pages += slot_psize;
+ slot_psize_cache[node][slot] =
+ (unsigned short) slot_psize;
+ if (slot_psize)
+ slot_lastfilled_cache[node] = slot;
+ }
+ }
+ if (maxpmem)
+ return((maxpmem > num_pages) ? num_pages : maxpmem);
+ else
+ return num_pages;
+}
- /* Register all the contiguous memory with the bootmem allocator
- and free it. Be careful about the bootmem freemap. */
- bootmap_size = init_bootmem(start_pfn, mb << (20 - PAGE_SHIFT));
- free_bootmem(__pa(free_start), (mb << 20) - __pa(free_start));
- reserve_bootmem(__pa(free_start), bootmap_size);
- free_bootmem(0x19000, 0x1c000 - 0x19000);
+/*
+ * Currently, the intranode memory hole support assumes that each slot
+ * contains at least 32 MBytes of memory. We assume all bootmem data
+ * fits on the first slot.
+ */
+void __init prom_meminit(void)
+{
+ extern void mlreset(void);
+ cnodeid_t node;
+ pfn_t slot_firstpfn, slot_lastpfn, slot_freepfn, numpages;
+ unsigned long bootmap_size;
- printk("Found %ldmb of memory.\n", mb);
+ mlreset();
+ numpages = szmem(0, 0);
+ for (node = 0; node < numnodes; node++) {
+ slot_firstpfn = slot_getbasepfn(node, 0);
+ slot_lastpfn = slot_firstpfn + slot_getsize(node, 0);
+ slot_freepfn = node_getfirstfree(node);
+ printk("Node %d slot 0: 0x%lx 0x%lx 0x%lx\n", node,
+ slot_firstpfn<<PAGE_SHIFT, slot_lastpfn<<PAGE_SHIFT,
+ slot_freepfn<<PAGE_SHIFT);
+ /* delete next 2 lines when we have numa support */
+ if (node == 0) {
+ max_low_pfn = (slot_lastpfn - slot_firstpfn);
+ bootmap_size = init_bootmem_node(node, slot_freepfn,
+ slot_firstpfn, slot_lastpfn);
+ free_bootmem_node(node, slot_firstpfn << PAGE_SHIFT,
+ (slot_lastpfn - slot_firstpfn) << PAGE_SHIFT);
+ reserve_bootmem_node(node, slot_firstpfn << PAGE_SHIFT,
+ ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size);
+ }
+ }
+ printk("Total memory probed : 0x%lx pages\n", numpages);
}
int __init page_is_ram(unsigned long pagenr)
diff --git a/arch/mips64/sgi-ip27/ip27-setup.c b/arch/mips64/sgi-ip27/ip27-setup.c
index e34058a30..c97eeb8b6 100644
--- a/arch/mips64/sgi-ip27/ip27-setup.c
+++ b/arch/mips64/sgi-ip27/ip27-setup.c
@@ -89,7 +89,6 @@ void __init ip27_setup(void)
{
nasid_t nid;
hubreg_t p, e;
- extern void mlreset(void);
set_cp0_status(ST0_IM, 0);
nid = get_nasid();
@@ -110,5 +109,4 @@ void __init ip27_setup(void)
verify_mode();
ioc3_sio_init();
ioc3_eth_init();
- mlreset();
}