patch-2.3.48 linux/arch/mips/arc/memory.c

Next file: linux/arch/mips/arc/misc.c
Previous file: linux/arch/mips/arc/init.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.47/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c
@@ -4,25 +4,30 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: memory.c,v 1.5 1999/04/14 21:25:02 tsbogend Exp $
+ * $Id: memory.c,v 1.10 2000/01/27 23:21:57 ralf Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/bootmem.h>
 #include <linux/swap.h>
+#include <linux/config.h>
 
 #include <asm/sgialib.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/bootinfo.h>
 
-/* #define DEBUG */
+#undef DEBUG
 
-struct linux_mdesc * __init prom_getmdesc(struct linux_mdesc *curr)
+extern char _end;
+
+struct linux_mdesc * __init
+ArcGetMemoryDescriptor(struct linux_mdesc *Current)
 {
-	return romvec->get_mdesc(curr);
+	return romvec->get_mdesc(Current);
 }
 
 #ifdef DEBUG /* convenient for debugging */
@@ -50,159 +55,185 @@
 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
 #endif
 
-static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS];
-
-struct prom_pmemblock * __init prom_getpblock_array(void)
-{
-	return &prom_pblocks[0];
-}
+static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS];
 
 #define MEMTYPE_DONTUSE   0
 #define MEMTYPE_PROM      1
 #define MEMTYPE_FREE      2
 
-static int __init prom_memtype_classify (union linux_memtypes type)
+static inline int memtype_classify_arcs (union linux_memtypes type)
 {
-    if (prom_flags & PROM_FLAG_ARCS) {
 	switch (type.arcs) {
-	 case arcs_free:
-	 case arcs_fcontig:
-	    return MEMTYPE_FREE;
-	 case arcs_atmp:
-	 case arcs_aperm:
-	    return MEMTYPE_PROM;
-	 default:
-	    return MEMTYPE_DONTUSE;
+	case arcs_fcontig:
+	case arcs_free:
+		return MEMTYPE_FREE;
+	case arcs_atmp:
+		return MEMTYPE_PROM;
+	case arcs_eblock:
+	case arcs_rvpage:
+	case arcs_bmem:
+	case arcs_prog:
+	case arcs_aperm:
+		return MEMTYPE_DONTUSE;
+	default:
+		BUG();
 	}
-    } else {
+	while(1);				/* Nuke warning.  */
+}
+
+static inline int memtype_classify_arc (union linux_memtypes type)
+{
 	switch (type.arc) {
-	 case arc_free:
-	 case arc_fcontig:
-	    return MEMTYPE_FREE;
-	 case arc_rvpage:
-	 case arc_atmp:
-	 case arc_aperm:
-	    return MEMTYPE_PROM;
-	 default:
-	    return MEMTYPE_DONTUSE;
+	case arc_free:
+	case arc_fcontig:
+		return MEMTYPE_FREE;
+	case arc_atmp:
+		return MEMTYPE_PROM;
+	case arc_eblock:
+	case arc_rvpage:
+	case arc_bmem:
+	case arc_prog:
+	case arc_aperm:
+		return MEMTYPE_DONTUSE;
+	default:
+		BUG();
 	}
-    }
+	while(1);				/* Nuke warning.  */
 }
 
-static void __init prom_setup_memupper(void)
+static int __init prom_memtype_classify (union linux_memtypes type)
+{
+	if (prom_flags & PROM_FLAG_ARCS)	/* SGI is ``different'' ...  */
+		return memtype_classify_arcs(type);
+
+	return memtype_classify_arc(type);
+}
+
+static inline unsigned long find_max_low_pfn(void)
 {
 	struct prom_pmemblock *p, *highest;
+	unsigned long pfn;
 
-	for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) {
-		if(p->base == 0xdeadbeef)
-			prom_printf("WHEEE, bogus pmemblock\n");
-		if(!highest || p->base > highest->base)
+	p = pblocks;
+	highest = 0;
+	while (p->size != 0) {
+		if (!highest || p->base > highest->base)
 			highest = p;
+		p++;
 	}
-	mips_memory_upper = highest->base + highest->size;
+
+	pfn = (highest->base + highest->size) >> PAGE_SHIFT;
 #ifdef DEBUG
-	prom_printf("prom_setup_memupper: mips_memory_upper = %08lx\n",
-		    mips_memory_upper);
+	prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn);
 #endif
+	return pfn;
+}
+
+static inline struct prom_pmemblock *find_largest_memblock(void)
+{
+	struct prom_pmemblock *p, *largest;
+
+	p = pblocks;
+	largest = 0;
+	while (p->size != 0) {
+		if (!largest || p->size > largest->size)
+			largest = p;
+		p++;
+	}
+
+	return largest;
 }
 
 void __init prom_meminit(void)
 {
+	struct prom_pmemblock *largest;
+	unsigned long bootmap_size;
 	struct linux_mdesc *p;
 	int totram;
 	int i = 0;
 
-	p = prom_getmdesc(PROM_NULL_MDESC);
 #ifdef DEBUG
 	prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
+	p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
 	while(p) {
 		prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
 			    i, p, p->base, p->pages, mtypes(p->type));
-		p = prom_getmdesc(p);
+		p = ArcGetMemoryDescriptor(p);
 		i++;
 	}
 #endif
-	p = prom_getmdesc(PROM_NULL_MDESC);
+
 	totram = 0;
 	i = 0;
-	while(p) {
-	    prom_pblocks[i].type = prom_memtype_classify (p->type);
-	    prom_pblocks[i].base = ((p->base<<PAGE_SHIFT) + 0x80000000);
-	    prom_pblocks[i].size = p->pages << PAGE_SHIFT;
-	    switch (prom_pblocks[i].type) {
-	     case MEMTYPE_FREE:
-		totram += prom_pblocks[i].size;
+	p = PROM_NULL_MDESC;
+	while ((p = ArcGetMemoryDescriptor(p))) {
+		pblocks[i].type = prom_memtype_classify(p->type);
+		pblocks[i].base = p->base << PAGE_SHIFT;
+		pblocks[i].size = p->pages << PAGE_SHIFT;
+
+		switch (pblocks[i].type) {
+		case MEMTYPE_FREE:
+			totram += pblocks[i].size;
 #ifdef DEBUG
-		prom_printf("free_chunk[%d]: base=%08lx size=%d\n",
-			    i, prom_pblocks[i].base,
-			    prom_pblocks[i].size);
+			prom_printf("free_chunk[%d]: base=%08lx size=%x\n",
+				    i, pblocks[i].base,
+				    pblocks[i].size);
 #endif
-		i++;
-		break;
-	     case MEMTYPE_PROM:
+			i++;
+			break;
+		case MEMTYPE_PROM:
 #ifdef DEBUG
-		prom_printf("prom_chunk[%d]: base=%08lx size=%d\n",
-			    i, prom_pblocks[i].base,
-			    prom_pblocks[i].size);
+			prom_printf("prom_chunk[%d]: base=%08lx size=%x\n",
+				    i, pblocks[i].base,
+				    pblocks[i].size);
 #endif
-		i++;
-		break;
-	     default:
-		break;
-	    }
-	    p = prom_getmdesc(p);
-	}
-	prom_pblocks[i].base = 0xdeadbeef;
-	prom_pblocks[i].size = 0; /* indicates last elem. of array */
-	printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n",
-		    totram, (totram/1024), (totram/1024/1024));
+			i++;
+			break;
+		default:
+			break;
+		}
+	}
+	pblocks[i].size = 0;
 
-	/* Setup upper physical memory bound. */
-	prom_setup_memupper();
-}
+	max_low_pfn = find_max_low_pfn();
+	largest = find_largest_memblock();
+	bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn);
 
-/* Called from mem_init() to fixup the mem_map page settings. */
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
-	struct prom_pmemblock *p;
-	int i, nents;
+	for (i = 0; pblocks[i].size; i++)
+		if (pblocks[i].type == MEMTYPE_FREE)
+			free_bootmem(pblocks[i].base, pblocks[i].size);
 
-	/* Determine number of pblockarray entries. */
-	p = prom_getpblock_array();
-	for(i = 0; p[i].size; i++)
-		;
-	nents = i;
-restart:
-	while(start < end) {
-		for(i = 0; i < nents; i++) {
-			if((p[i].type == MEMTYPE_FREE) &&
-			   (start >= (p[i].base)) &&
-			   (start < (p[i].base + p[i].size))) {
-				start = p[i].base + p[i].size;
-				start &= PAGE_MASK;
-				goto restart;
-			}
-		}
-		set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags);
-		start += PAGE_SIZE;
+	/* This test is simpleminded.  It will fail if the bootmem bitmap
+	   falls into multiple adjacent ARC memory areas.  */
+	if (bootmap_size > largest->size) {
+		prom_printf("CRITIAL: overwriting PROM data.\n");
+		BUG();
 	}
+	reserve_bootmem(largest->base, bootmap_size);
+
+	printk("PROMLIB: Total free ram %dK / %dMB.\n",
+	       totram >> 10, totram >> 20);
 }
 
-void prom_free_prom_memory (void)
+void __init
+prom_free_prom_memory (void)
 {
-    struct prom_pmemblock *p;
-    unsigned long addr;
-    unsigned long num_pages = 0;
+	struct prom_pmemblock *p;
+	unsigned long freed = 0;
+	unsigned long addr;
 
-    for(p = prom_getpblock_array(); p->size != 0; p++) {
-	if (p->type == MEMTYPE_PROM) {
-	    for (addr = p->base; addr < p->base + p->size; addr += PAGE_SIZE) {
-		mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
-		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
-		free_page(addr);
-		num_pages++;
-	    }
+	for (p = pblocks; p->size != 0; p++) {
+		if (p->type != MEMTYPE_PROM)
+			continue;
+
+		addr = PAGE_OFFSET + p->base;
+		while (addr < p->base + p->size) {
+			ClearPageReserved(mem_map + MAP_NR(addr));
+			set_page_count(mem_map + MAP_NR(addr), 1);
+			free_page(addr);
+			addr += PAGE_SIZE;
+			freed += PAGE_SIZE;
+		}
 	}
-    }
-    printk ("Freeing prom memory: %dk freed\n",num_pages << (PAGE_SHIFT - 10));
+	printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)