Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ppc64: Use the merged lmb routines

The only real change here is that lmb_enforce_memory_limit now takes
the memory_limit as a parameter instead of as a global variable.

Signed-off-by: Paul Mackerras <paulus@samba.org>

+4 -383
+1 -1
arch/ppc64/kernel/Makefile
··· 12 12 align.o semaphore.o bitops.o pacaData.o \ 13 13 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ 14 14 ptrace32.o signal32.o rtc.o init_task.o \ 15 - lmb.o cputable.o cpu_setup_power4.o \ 15 + cputable.o cpu_setup_power4.o \ 16 16 iommu.o sysfs.o vdso.o pmc.o firmware.o prom.o 17 17 obj-y += vdso32/ vdso64/ 18 18
-299
arch/ppc64/kernel/lmb.c
··· 1 - /* 2 - * Procedures for interfacing to Open Firmware. 3 - * 4 - * Peter Bergner, IBM Corp. June 2001. 5 - * Copyright (C) 2001 Peter Bergner. 6 - * 7 - * This program is free software; you can redistribute it and/or 8 - * modify it under the terms of the GNU General Public License 9 - * as published by the Free Software Foundation; either version 10 - * 2 of the License, or (at your option) any later version. 11 - */ 12 - 13 - #include <linux/config.h> 14 - #include <linux/kernel.h> 15 - #include <linux/init.h> 16 - #include <linux/bitops.h> 17 - #include <asm/types.h> 18 - #include <asm/page.h> 19 - #include <asm/prom.h> 20 - #include <asm/lmb.h> 21 - #include <asm/abs_addr.h> 22 - 23 - struct lmb lmb; 24 - 25 - #undef DEBUG 26 - 27 - void lmb_dump_all(void) 28 - { 29 - #ifdef DEBUG 30 - unsigned long i; 31 - 32 - udbg_printf("lmb_dump_all:\n"); 33 - udbg_printf(" memory.cnt = 0x%lx\n", 34 - lmb.memory.cnt); 35 - udbg_printf(" memory.size = 0x%lx\n", 36 - lmb.memory.size); 37 - for (i=0; i < lmb.memory.cnt ;i++) { 38 - udbg_printf(" memory.region[0x%x].base = 0x%lx\n", 39 - i, lmb.memory.region[i].base); 40 - udbg_printf(" .size = 0x%lx\n", 41 - lmb.memory.region[i].size); 42 - } 43 - 44 - udbg_printf("\n reserved.cnt = 0x%lx\n", 45 - lmb.reserved.cnt); 46 - udbg_printf(" reserved.size = 0x%lx\n", 47 - lmb.reserved.size); 48 - for (i=0; i < lmb.reserved.cnt ;i++) { 49 - udbg_printf(" reserved.region[0x%x].base = 0x%lx\n", 50 - i, lmb.reserved.region[i].base); 51 - udbg_printf(" .size = 0x%lx\n", 52 - lmb.reserved.region[i].size); 53 - } 54 - #endif /* DEBUG */ 55 - } 56 - 57 - static unsigned long __init 58 - lmb_addrs_overlap(unsigned long base1, unsigned long size1, 59 - unsigned long base2, unsigned long size2) 60 - { 61 - return ((base1 < (base2+size2)) && (base2 < (base1+size1))); 62 - } 63 - 64 - static long __init 65 - lmb_addrs_adjacent(unsigned long base1, unsigned long size1, 66 - unsigned long base2, unsigned long size2) 67 - { 68 - if (base2 == base1 + size1) 69 - return 1; 70 - else if (base1 == base2 + size2) 71 - return -1; 72 - 73 - return 0; 74 - } 75 - 76 - static long __init 77 - lmb_regions_adjacent(struct lmb_region *rgn, unsigned long r1, unsigned long r2) 78 - { 79 - unsigned long base1 = rgn->region[r1].base; 80 - unsigned long size1 = rgn->region[r1].size; 81 - unsigned long base2 = rgn->region[r2].base; 82 - unsigned long size2 = rgn->region[r2].size; 83 - 84 - return lmb_addrs_adjacent(base1, size1, base2, size2); 85 - } 86 - 87 - /* Assumption: base addr of region 1 < base addr of region 2 */ 88 - static void __init 89 - lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2) 90 - { 91 - unsigned long i; 92 - 93 - rgn->region[r1].size += rgn->region[r2].size; 94 - for (i=r2; i < rgn->cnt-1; i++) { 95 - rgn->region[i].base = rgn->region[i+1].base; 96 - rgn->region[i].size = rgn->region[i+1].size; 97 - } 98 - rgn->cnt--; 99 - } 100 - 101 - /* This routine called with relocation disabled. */ 102 - void __init 103 - lmb_init(void) 104 - { 105 - /* Create a dummy zero size LMB which will get coalesced away later. 106 - * This simplifies the lmb_add() code below... 107 - */ 108 - lmb.memory.region[0].base = 0; 109 - lmb.memory.region[0].size = 0; 110 - lmb.memory.cnt = 1; 111 - 112 - /* Ditto. */ 113 - lmb.reserved.region[0].base = 0; 114 - lmb.reserved.region[0].size = 0; 115 - lmb.reserved.cnt = 1; 116 - } 117 - 118 - /* This routine called with relocation disabled. */ 119 - void __init 120 - lmb_analyze(void) 121 - { 122 - int i; 123 - 124 - lmb.memory.size = 0; 125 - 126 - for (i = 0; i < lmb.memory.cnt; i++) 127 - lmb.memory.size += lmb.memory.region[i].size; 128 - } 129 - 130 - /* This routine called with relocation disabled. */ 131 - static long __init 132 - lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size) 133 - { 134 - unsigned long i, coalesced = 0; 135 - long adjacent; 136 - 137 - /* First try and coalesce this LMB with another. */ 138 - for (i=0; i < rgn->cnt; i++) { 139 - unsigned long rgnbase = rgn->region[i].base; 140 - unsigned long rgnsize = rgn->region[i].size; 141 - 142 - adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); 143 - if ( adjacent > 0 ) { 144 - rgn->region[i].base -= size; 145 - rgn->region[i].size += size; 146 - coalesced++; 147 - break; 148 - } 149 - else if ( adjacent < 0 ) { 150 - rgn->region[i].size += size; 151 - coalesced++; 152 - break; 153 - } 154 - } 155 - 156 - if ((i < rgn->cnt-1) && lmb_regions_adjacent(rgn, i, i+1) ) { 157 - lmb_coalesce_regions(rgn, i, i+1); 158 - coalesced++; 159 - } 160 - 161 - if ( coalesced ) { 162 - return coalesced; 163 - } else if ( rgn->cnt >= MAX_LMB_REGIONS ) { 164 - return -1; 165 - } 166 - 167 - /* Couldn't coalesce the LMB, so add it to the sorted table. */ 168 - for (i=rgn->cnt-1; i >= 0; i--) { 169 - if (base < rgn->region[i].base) { 170 - rgn->region[i+1].base = rgn->region[i].base; 171 - rgn->region[i+1].size = rgn->region[i].size; 172 - } else { 173 - rgn->region[i+1].base = base; 174 - rgn->region[i+1].size = size; 175 - break; 176 - } 177 - } 178 - rgn->cnt++; 179 - 180 - return 0; 181 - } 182 - 183 - /* This routine called with relocation disabled. */ 184 - long __init 185 - lmb_add(unsigned long base, unsigned long size) 186 - { 187 - struct lmb_region *_rgn = &(lmb.memory); 188 - 189 - /* On pSeries LPAR systems, the first LMB is our RMO region. */ 190 - if ( base == 0 ) 191 - lmb.rmo_size = size; 192 - 193 - return lmb_add_region(_rgn, base, size); 194 - 195 - } 196 - 197 - long __init 198 - lmb_reserve(unsigned long base, unsigned long size) 199 - { 200 - struct lmb_region *_rgn = &(lmb.reserved); 201 - 202 - return lmb_add_region(_rgn, base, size); 203 - } 204 - 205 - long __init 206 - lmb_overlaps_region(struct lmb_region *rgn, unsigned long base, unsigned long size) 207 - { 208 - unsigned long i; 209 - 210 - for (i=0; i < rgn->cnt; i++) { 211 - unsigned long rgnbase = rgn->region[i].base; 212 - unsigned long rgnsize = rgn->region[i].size; 213 - if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) { 214 - break; 215 - } 216 - } 217 - 218 - return (i < rgn->cnt) ? i : -1; 219 - } 220 - 221 - unsigned long __init 222 - lmb_alloc(unsigned long size, unsigned long align) 223 - { 224 - return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE); 225 - } 226 - 227 - unsigned long __init 228 - lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) 229 - { 230 - long i, j; 231 - unsigned long base = 0; 232 - 233 - for (i=lmb.memory.cnt-1; i >= 0; i--) { 234 - unsigned long lmbbase = lmb.memory.region[i].base; 235 - unsigned long lmbsize = lmb.memory.region[i].size; 236 - 237 - if ( max_addr == LMB_ALLOC_ANYWHERE ) 238 - base = _ALIGN_DOWN(lmbbase+lmbsize-size, align); 239 - else if ( lmbbase < max_addr ) 240 - base = _ALIGN_DOWN(min(lmbbase+lmbsize,max_addr)-size, align); 241 - else 242 - continue; 243 - 244 - while ( (lmbbase <= base) && 245 - ((j = lmb_overlaps_region(&lmb.reserved,base,size)) >= 0) ) { 246 - base = _ALIGN_DOWN(lmb.reserved.region[j].base-size, align); 247 - } 248 - 249 - if ( (base != 0) && (lmbbase <= base) ) 250 - break; 251 - } 252 - 253 - if ( i < 0 ) 254 - return 0; 255 - 256 - lmb_add_region(&lmb.reserved, base, size); 257 - 258 - return base; 259 - } 260 - 261 - /* You must call lmb_analyze() before this. */ 262 - unsigned long __init 263 - lmb_phys_mem_size(void) 264 - { 265 - return lmb.memory.size; 266 - } 267 - 268 - unsigned long __init 269 - lmb_end_of_DRAM(void) 270 - { 271 - int idx = lmb.memory.cnt - 1; 272 - 273 - return (lmb.memory.region[idx].base + lmb.memory.region[idx].size); 274 - } 275 - 276 - /* 277 - * Truncate the lmb list to memory_limit if it's set 278 - * You must call lmb_analyze() after this. 279 - */ 280 - void __init lmb_enforce_memory_limit(void) 281 - { 282 - extern unsigned long memory_limit; 283 - unsigned long i, limit; 284 - 285 - if (! memory_limit) 286 - return; 287 - 288 - limit = memory_limit; 289 - for (i = 0; i < lmb.memory.cnt; i++) { 290 - if (limit > lmb.memory.region[i].size) { 291 - limit -= lmb.memory.region[i].size; 292 - continue; 293 - } 294 - 295 - lmb.memory.region[i].size = limit; 296 - lmb.memory.cnt = i + 1; 297 - break; 298 - } 299 - }
+3 -2
arch/ppc64/kernel/prom.c
··· 78 78 extern struct rtas_t rtas; 79 79 extern struct lmb lmb; 80 80 extern unsigned long klimit; 81 + extern unsigned long memory_limit; 81 82 82 83 static int __initdata dt_root_addr_cells; 83 84 static int __initdata dt_root_size_cells; ··· 1064 1063 { 1065 1064 u32 *prop; 1066 1065 u64 *prop64; 1067 - extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end; 1066 + extern unsigned long tce_alloc_start, tce_alloc_end; 1068 1067 1069 1068 DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); 1070 1069 ··· 1238 1237 lmb_init(); 1239 1238 scan_flat_dt(early_init_dt_scan_root, NULL); 1240 1239 scan_flat_dt(early_init_dt_scan_memory, NULL); 1241 - lmb_enforce_memory_limit(); 1240 + lmb_enforce_memory_limit(memory_limit); 1242 1241 lmb_analyze(); 1243 1242 systemcfg->physicalMemorySize = lmb_phys_mem_size(); 1244 1243 lmb_reserve(0, __pa(klimit));
-81
include/asm-ppc64/lmb.h
··· 1 - #ifndef _PPC64_LMB_H 2 - #define _PPC64_LMB_H 3 - 4 - /* 5 - * Definitions for talking to the Open Firmware PROM on 6 - * Power Macintosh computers. 7 - * 8 - * Copyright (C) 2001 Peter Bergner, IBM Corp. 9 - * 10 - * This program is free software; you can redistribute it and/or 11 - * modify it under the terms of the GNU General Public License 12 - * as published by the Free Software Foundation; either version 13 - * 2 of the License, or (at your option) any later version. 14 - */ 15 - 16 - #include <linux/init.h> 17 - #include <asm/prom.h> 18 - 19 - #define MAX_LMB_REGIONS 128 20 - 21 - #define LMB_ALLOC_ANYWHERE 0 22 - 23 - struct lmb_property { 24 - unsigned long base; 25 - unsigned long size; 26 - }; 27 - 28 - struct lmb_region { 29 - unsigned long cnt; 30 - unsigned long size; 31 - struct lmb_property region[MAX_LMB_REGIONS+1]; 32 - }; 33 - 34 - struct lmb { 35 - unsigned long debug; 36 - unsigned long rmo_size; 37 - struct lmb_region memory; 38 - struct lmb_region reserved; 39 - }; 40 - 41 - extern struct lmb lmb; 42 - 43 - extern void __init lmb_init(void); 44 - extern void __init lmb_analyze(void); 45 - extern long __init lmb_add(unsigned long, unsigned long); 46 - extern long __init lmb_reserve(unsigned long, unsigned long); 47 - extern unsigned long __init lmb_alloc(unsigned long, unsigned long); 48 - extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long, 49 - unsigned long); 50 - extern unsigned long __init lmb_phys_mem_size(void); 51 - extern unsigned long __init lmb_end_of_DRAM(void); 52 - extern unsigned long __init lmb_abs_to_phys(unsigned long); 53 - extern void __init lmb_enforce_memory_limit(void); 54 - 55 - extern void lmb_dump_all(void); 56 - 57 - extern unsigned long io_hole_start; 58 - 59 - static inline unsigned long 60 - lmb_size_bytes(struct lmb_region *type, unsigned long region_nr) 61 - { 62 - return type->region[region_nr].size; 63 - } 64 - static inline unsigned long 65 - lmb_size_pages(struct lmb_region *type, unsigned long region_nr) 66 - { 67 - return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT; 68 - } 69 - static inline unsigned long 70 - lmb_start_pfn(struct lmb_region *type, unsigned long region_nr) 71 - { 72 - return type->region[region_nr].base >> PAGE_SHIFT; 73 - } 74 - static inline unsigned long 75 - lmb_end_pfn(struct lmb_region *type, unsigned long region_nr) 76 - { 77 - return lmb_start_pfn(type, region_nr) + 78 - lmb_size_pages(type, region_nr); 79 - } 80 - 81 - #endif /* _PPC64_LMB_H */