linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] PPC32 mem_pieces interface cleanup
@ 2005-06-27 16:28 Jon Loeliger
  2005-06-28  6:30 ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 2+ messages in thread
From: Jon Loeliger @ 2005-06-27 16:28 UTC (permalink / raw)
  To: linuxppc-embedded@ozlabs.org

[-- Attachment #1: Type: text/plain, Size: 396 bytes --]

Guys,

As an initial step towards getting the OF Flat Dev tree
handled in the PPC32 tree, this patch cleans up some of
the interface parts of the very early mem_pieces manager
and adds some PPC64-LMB-like routines as well.

It has been built and booted on 85xx and pmac boards.

Thanks,
jdl


Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>



[-- Attachment #2: mem_pieces_cleanup.patch --]
[-- Type: text/x-patch, Size: 9638 bytes --]

Index: arch/ppc/mm/init.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/init.c  (mode:100644)
+++ uncommitted/arch/ppc/mm/init.c  (mode:100644)
@@ -316,7 +316,7 @@
 	if (init_bootmem_done) {
 		p = alloc_bootmem_pages(PAGE_SIZE);
 	} else {
-		p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE);
+		p = mem_pieces_find(&phys_avail, PAGE_SIZE, PAGE_SIZE);
 	}
 	return p;
 }
@@ -495,10 +495,8 @@
 	 * Initially, available physical memory is equivalent to all
 	 * physical memory.
 	 */
-
-	phys_avail.regions[0].address = PPC_MEMSTART;
-	phys_avail.regions[0].size = total_memory;
-	phys_avail.n_regions = 1;
+	mem_pieces_reset(&phys_avail);
+	mem_pieces_add(&phys_avail, PPC_MEMSTART, total_memory);
 
 	/*
 	 * Map out the kernel text/data/bss from the available physical
Index: arch/ppc/mm/mem_pieces.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/mem_pieces.c  (mode:100644)
+++ uncommitted/arch/ppc/mm/mem_pieces.c  (mode:100644)
@@ -22,19 +22,105 @@
 
 #include "mem_pieces.h"
 
-extern struct mem_pieces phys_avail;
 
-static void mem_pieces_print(struct mem_pieces *);
+static unsigned int __init mem_pieces_addrs_adjacent(unsigned int base1,
+						    unsigned int size1,
+						    unsigned int base2,
+						     unsigned int size2);
+static int __init mem_pieces_regions_adjacent(struct mem_pieces *mp,
+					      unsigned int r1,
+					      unsigned int r2);
+static void __init mem_pieces_coalesce_regions(struct mem_pieces *mp,
+					       unsigned int r1,
+					       unsigned int r2);
+
+
+void __init
+mem_pieces_reset(struct mem_pieces *mp)
+{
+	/*
+	 * Create a dummy zero size block which will get coalesced
+	 * away later.  This simplifies the mem_pieces_add() code below.
+	 */
+	mp->regions[0].address = 0;
+	mp->regions[0].size = 0;
+	mp->n_regions = 1;
+}
+
+
+/*
+ * mem_pieces_add() -- Add a memory block to a sorted region table,
+ *	merging adjacent blocks if possible.
+ *	Returns 0 on straight add, >0 on coallsced, -1 on failure.
+ */
+
+int __init
+mem_pieces_add(struct mem_pieces *mp, unsigned int base, unsigned int size)
+{
+	unsigned int i;
+	unsigned int coalesced;
+
+	/*
+	 * First try and coalesce this mem_piece with another.
+	 */
+	coalesced = 0;
+	for (i = 0; i < mp->n_regions; i++) {
+		unsigned int rgnbase = mp->regions[i].address;
+		unsigned int rgnsize = mp->regions[i].size;
+		int adjacent = mem_pieces_addrs_adjacent(base, size,
+							 rgnbase, rgnsize);
+		if (adjacent > 0) {
+			mp->regions[i].address -= size;
+			mp->regions[i].size += size;
+			coalesced++;
+			break;
+		} else if (adjacent < 0) {
+			mp->regions[i].size += size;
+			coalesced++;
+			break;
+		}
+	}
+
+	if ((i < mp->n_regions-1) && mem_pieces_regions_adjacent(mp, i, i+1)) {
+		mem_pieces_coalesce_regions(mp, i, i+1);
+		coalesced++;
+	}
+
+	if (coalesced) {
+		return coalesced;
+	} else if (mp->n_regions >= MEM_PIECES_MAX ) {
+		return -1;
+	}
+
+	/*
+	 * Couldn't coalesce the new mem_piece, so add it to the sorted table.
+	 */
+	for (i = mp->n_regions-1; i >= 0; i--) {
+		if (base < mp->regions[i].address) {
+			/* Shift up a slot. */
+			mp->regions[i+1].address = mp->regions[i].address;
+			mp->regions[i+1].size = mp->regions[i].size;
+		}  else {
+			/* Insert in newly opened slot. */
+			mp->regions[i+1].address = base;
+			mp->regions[i+1].size = size;
+			break;
+		}
+	}
+	++mp->n_regions;
+
+	return 0;
+}
+
 
 /*
  * Scan a region for a piece of a given size with the required alignment.
  */
 void __init *
-mem_pieces_find(unsigned int size, unsigned int align)
+mem_pieces_find(struct mem_pieces *mp, unsigned int size, unsigned int align)
 {
 	int i;
 	unsigned a, e;
-	struct mem_pieces *mp = &phys_avail;
 
 	for (i = 0; i < mp->n_regions; ++i) {
 		a = mp->regions[i].address;
@@ -50,6 +136,7 @@
 	return NULL;
 }
 
+
 /*
  * Remove some memory from an array of pieces
  */
@@ -59,7 +146,7 @@
 {
 	int i, j;
 	unsigned int end, rs, re;
-	struct reg_property *rp;
+	struct mem_pieces_property *rp;
 
 	end = start + size;
 	for (i = 0, rp = mp->regions; i < mp->n_regions; ++i, ++rp) {
@@ -109,17 +196,20 @@
 	}
 }
 
-static void __init
+
+void __init
 mem_pieces_print(struct mem_pieces *mp)
 {
 	int i;
 
-	for (i = 0; i < mp->n_regions; ++i)
+	for (i = 0; i < mp->n_regions; ++i) {
 		printk(" [%x, %x)", mp->regions[i].address,
 		       mp->regions[i].address + mp->regions[i].size);
+	}
 	printk("\n");
 }
 
+
 void __init
 mem_pieces_sort(struct mem_pieces *mp)
 {
@@ -139,6 +229,7 @@
 	}
 }
 
+
 void __init
 mem_pieces_coalesce(struct mem_pieces *mp)
 {
@@ -161,3 +252,66 @@
 	}
 	mp->n_regions = d;
 }
+
+
+unsigned int __init
+mem_pieces_get_phys_mem_size(struct mem_pieces *mp)
+{
+	int i;
+	unsigned int total = 0;
+
+	for (i = 0; i < mp->n_regions; i++) {
+		total += mp->regions[i].size;
+	}
+	return total;
+}
+
+
+static unsigned int __init
+mem_pieces_addrs_adjacent(unsigned int base1, unsigned int size1,
+			 unsigned int base2, unsigned int size2)
+{
+	if (base2 == base1 + size1) {
+		return 1;
+	} else if (base1 == base2 + size2) {
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int __init
+mem_pieces_regions_adjacent(struct mem_pieces *mp,
+			    unsigned int r1,
+			    unsigned int r2)
+{
+	unsigned int base1 = mp->regions[r1].address;
+	unsigned int size1 = mp->regions[r1].size;
+	unsigned int base2 = mp->regions[r2].address;
+	unsigned int size2 = mp->regions[r2].size;
+
+	return mem_pieces_addrs_adjacent(base1, size1, base2, size2);
+}
+
+
+/*
+ * Coalesce block r2 into block r1.
+ * Assumes base addr of region 1 < base addr of region 2
+ */
+
+static void __init
+mem_pieces_coalesce_regions(struct mem_pieces *mp,
+			    unsigned int r1,
+			    unsigned int r2)
+{
+	unsigned int i;
+
+	mp->regions[r1].size += mp->regions[r2].size;
+	for (i = r2; i < mp->n_regions-1; i++) {
+		mp->regions[i].address = mp->regions[i+1].address;
+		mp->regions[i].size = mp->regions[i+1].size;
+	}
+	--mp->n_regions;
+
+}
Index: arch/ppc/mm/mem_pieces.h
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/mem_pieces.h  (mode:100644)
+++ uncommitted/arch/ppc/mm/mem_pieces.h  (mode:100644)
@@ -17,8 +17,6 @@
 #ifndef __MEM_PIECES_H__
 #define	__MEM_PIECES_H__
 
-#include <asm/prom.h>
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -26,20 +24,34 @@
 
 /* Type Definitions */
 
+struct mem_pieces_property {
+	unsigned int address;
+	unsigned int size;
+};
+
+
 #define	MEM_PIECES_MAX	32
 
 struct mem_pieces {
     int n_regions;
-    struct reg_property regions[MEM_PIECES_MAX];
+    struct mem_pieces_property regions[MEM_PIECES_MAX];
 };
 
 /* Function Prototypes */
 
-extern void	*mem_pieces_find(unsigned int size, unsigned int align);
-extern void	 mem_pieces_remove(struct mem_pieces *mp, unsigned int start,
+extern void	 mem_pieces_reset(struct mem_pieces *mp);
+extern int	 mem_pieces_add(struct mem_pieces *mp,
+				unsigned int base, unsigned int size);
+extern void	*mem_pieces_find(struct mem_pieces *mp,
+				 unsigned int size, unsigned int align);
+extern void	 mem_pieces_remove(struct mem_pieces *mp,
+				   unsigned int start,
 				   unsigned int size, int must_exist);
 extern void	 mem_pieces_coalesce(struct mem_pieces *mp);
 extern void	 mem_pieces_sort(struct mem_pieces *mp);
+extern unsigned int mem_pieces_get_phys_mem_size(struct mem_pieces *mp);
+extern void	 mem_pieces_print(struct mem_pieces *);
+
 
 #ifdef __cplusplus
 }
Index: arch/ppc/mm/ppc_mmu.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/ppc_mmu.c  (mode:100644)
+++ uncommitted/arch/ppc/mm/ppc_mmu.c  (mode:100644)
@@ -186,6 +186,7 @@
 	unsigned int hmask, mb, mb2;
 	unsigned int n_hpteg, lg_n_hpteg;
 
+	extern struct mem_pieces phys_avail;
 	extern unsigned int hash_page_patch_A[];
 	extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
 	extern unsigned int hash_page[];
@@ -245,7 +246,7 @@
 	 * Find some memory for the hash table.
 	 */
 	if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
-	Hash = mem_pieces_find(Hash_size, Hash_size);
+	Hash = mem_pieces_find(&phys_avail, Hash_size, Hash_size);
 	cacheable_memzero(Hash, Hash_size);
 	_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
 #endif /* CONFIG_POWER4 */
Index: arch/ppc/platforms/pmac_setup.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/platforms/pmac_setup.c  (mode:100644)
+++ uncommitted/arch/ppc/platforms/pmac_setup.c  (mode:100644)
@@ -575,7 +575,6 @@
 static int __init
 get_mem_prop(char *name, struct mem_pieces *mp)
 {
-	struct reg_property *rp;
 	int i, s;
 	unsigned int *ip;
 	int nac = prom_n_addr_cells(memory_node);
@@ -588,18 +587,16 @@
 		return 0;
 	}
 	s /= (nsc + nac) * 4;
-	rp = mp->regions;
 	for (i = 0; i < s; ++i, ip += nac+nsc) {
+		unsigned int size;
 		if (nac >= 2 && ip[nac-2] != 0)
 			continue;
-		rp->address = ip[nac-1];
 		if (nsc >= 2 && ip[nac+nsc-2] != 0)
-			rp->size = ~0U;
+			size = ~0U;
 		else
-			rp->size = ip[nac+nsc-1];
-		++rp;
+			size = ip[nac+nsc-1];
+		mem_pieces_add(mp, ip[nac-1], size);
 	}
-	mp->n_regions = rp - mp->regions;
 
 	/* Make sure the pieces are sorted. */
 	mem_pieces_sort(mp);
@@ -620,6 +617,8 @@
 	unsigned long a, total;
 	struct mem_pieces phys_mem;
 
+	mem_pieces_reset(&phys_mem);
+
 	/*
 	 * Find out where physical memory is, and check that it
 	 * starts at 0 and is contiguous.  It seems that RAM is

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] PPC32 mem_pieces interface cleanup
  2005-06-27 16:28 [PATCH] PPC32 mem_pieces interface cleanup Jon Loeliger
@ 2005-06-28  6:30 ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 2+ messages in thread
From: Benjamin Herrenschmidt @ 2005-06-28  6:30 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-embedded@ozlabs.org

On Mon, 2005-06-27 at 11:28 -0500, Jon Loeliger wrote:
> Guys,
> 
> As an initial step towards getting the OF Flat Dev tree
> handled in the PPC32 tree, this patch cleans up some of
> the interface parts of the very early mem_pieces manager
> and adds some PPC64-LMB-like routines as well.
> 
> It has been built and booted on 85xx and pmac boards.

Please make sure you CC linuxppc-dev on such patches or they'll be
missed by me and/or paulus most of the time :)

Ben.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2005-06-28  6:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-06-27 16:28 [PATCH] PPC32 mem_pieces interface cleanup Jon Loeliger
2005-06-28  6:30 ` Benjamin Herrenschmidt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).