aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel@gmail.com>2008-04-13 21:42:31 -0400
committerIngo Molnar <mingo@elte.hu>2008-05-12 15:28:10 -0400
commit8c9fd91a0dc503f085169d44f4360be025f75224 (patch)
tree9c182a2683d427ea10aa8f846bac1d0bb51f09ac
parent1edc1ab3f68168ec6815e6d630f38948a6da005a (diff)
x86: checking aperture size order
some systems are using 32M for gart and agp when memory is less than 4G. Kernel will reject and try to allcate another 64M that is not needed, and we will waste 64M of perfectly good RAM. this patch adds a workaround by checking aper_base/order between NB and agp bridge. If they are the same, and memory size is less than 4G, it will allow it. Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/kernel/aperture_64.c47
-rw-r--r--drivers/char/agp/amd64-agp.c12
2 files changed, 41 insertions, 18 deletions
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index 2e93b3132dff..8c325b7f2d9b 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -83,7 +83,7 @@ static u32 __init allocate_aperture(void)
83 return (u32)__pa(p); 83 return (u32)__pa(p);
84} 84}
85 85
86static int __init aperture_valid(u64 aper_base, u32 aper_size) 86static int __init aperture_valid(u64 aper_base, u32 aper_size, u32 min_size)
87{ 87{
88 if (!aper_base) 88 if (!aper_base)
89 return 0; 89 return 0;
@@ -96,8 +96,9 @@ static int __init aperture_valid(u64 aper_base, u32 aper_size)
96 printk(KERN_ERR "Aperture pointing to e820 RAM. Ignoring.\n"); 96 printk(KERN_ERR "Aperture pointing to e820 RAM. Ignoring.\n");
97 return 0; 97 return 0;
98 } 98 }
99 if (aper_size < 64*1024*1024) { 99 if (aper_size < min_size) {
100 printk(KERN_ERR "Aperture too small (%d MB)\n", aper_size>>20); 100 printk(KERN_ERR "Aperture too small (%d MB) than (%d MB)\n",
101 aper_size>>20, min_size>>20);
101 return 0; 102 return 0;
102 } 103 }
103 104
@@ -167,7 +168,9 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
167 * On some sick chips, APSIZE is 0. It means it wants 4G 168 * On some sick chips, APSIZE is 0. It means it wants 4G
168 * so let double check that order, and lets trust AMD NB settings: 169 * so let double check that order, and lets trust AMD NB settings:
169 */ 170 */
170 if (aper + (32UL<<(20 + *order)) > 0x100000000UL) { 171 printk(KERN_INFO "Aperture from AGP @ %Lx old size %u MB\n",
172 aper, 32 << old_order);
173 if (aper + (32ULL<<(20 + *order)) > 0x100000000ULL) {
171 printk(KERN_INFO "Aperture size %u MB (APSIZE %x) is not right, using settings from NB\n", 174 printk(KERN_INFO "Aperture size %u MB (APSIZE %x) is not right, using settings from NB\n",
172 32 << *order, apsizereg); 175 32 << *order, apsizereg);
173 *order = old_order; 176 *order = old_order;
@@ -176,7 +179,7 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
176 printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", 179 printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
177 aper, 32 << *order, apsizereg); 180 aper, 32 << *order, apsizereg);
178 181
179 if (!aperture_valid(aper, (32*1024*1024) << *order)) 182 if (!aperture_valid(aper, (32*1024*1024) << *order, 32<<20))
180 return 0; 183 return 0;
181 return (u32)aper; 184 return (u32)aper;
182} 185}
@@ -302,8 +305,8 @@ void __init early_gart_iommu_check(void)
302 fix = 1; 305 fix = 1;
303 306
304 if (gart_fix_e820 && !fix && aper_enabled) { 307 if (gart_fix_e820 && !fix && aper_enabled) {
305 if (e820_any_mapped(aper_base, aper_base + aper_size, 308 if (!e820_all_mapped(aper_base, aper_base + aper_size,
306 E820_RAM)) { 309 E820_RESERVED)) {
307 /* reserved it, so we can resuse it in second kernel */ 310 /* reserved it, so we can resuse it in second kernel */
308 printk(KERN_INFO "update e820 for GART\n"); 311 printk(KERN_INFO "update e820 for GART\n");
309 add_memory_region(aper_base, aper_size, E820_RESERVED); 312 add_memory_region(aper_base, aper_size, E820_RESERVED);
@@ -324,8 +327,11 @@ void __init early_gart_iommu_check(void)
324 327
325} 328}
326 329
330static int __initdata printed_gart_size_msg;
331
327void __init gart_iommu_hole_init(void) 332void __init gart_iommu_hole_init(void)
328{ 333{
334 u32 agp_aper_base = 0, agp_aper_order = 0;
329 u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; 335 u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
330 u64 aper_base, last_aper_base = 0; 336 u64 aper_base, last_aper_base = 0;
331 int fix, num, valid_agp = 0; 337 int fix, num, valid_agp = 0;
@@ -337,6 +343,9 @@ void __init gart_iommu_hole_init(void)
337 343
338 printk(KERN_INFO "Checking aperture...\n"); 344 printk(KERN_INFO "Checking aperture...\n");
339 345
346 if (!fallback_aper_force)
347 agp_aper_base = search_agp_bridge(&agp_aper_order, &valid_agp);
348
340 fix = 0; 349 fix = 0;
341 node = 0; 350 node = 0;
342 for (num = 24; num < 32; num++) { 351 for (num = 24; num < 32; num++) {
@@ -355,9 +364,21 @@ void __init gart_iommu_hole_init(void)
355 node, aper_base, aper_size >> 20); 364 node, aper_base, aper_size >> 20);
356 node++; 365 node++;
357 366
358 if (!aperture_valid(aper_base, aper_size)) { 367 if (!aperture_valid(aper_base, aper_size, 64<<20)) {
359 fix = 1; 368 if (valid_agp && agp_aper_base &&
360 break; 369 agp_aper_base == aper_base &&
370 agp_aper_order == aper_order) {
371 /* the same between two setting from NB and agp */
372 if (!no_iommu && end_pfn > MAX_DMA32_PFN && !printed_gart_size_msg) {
373 printk(KERN_ERR "you are using iommu with agp, but GART size is less than 64M\n");
374 printk(KERN_ERR "please increase GART size in your BIOS setup\n");
375 printk(KERN_ERR "if BIOS doesn't have that option, contact your HW vendor!\n");
376 printed_gart_size_msg = 1;
377 }
378 } else {
379 fix = 1;
380 break;
381 }
361 } 382 }
362 383
363 if ((last_aper_order && aper_order != last_aper_order) || 384 if ((last_aper_order && aper_order != last_aper_order) ||
@@ -378,8 +399,10 @@ void __init gart_iommu_hole_init(void)
378 return; 399 return;
379 } 400 }
380 401
381 if (!fallback_aper_force) 402 if (!fallback_aper_force) {
382 aper_alloc = search_agp_bridge(&aper_order, &valid_agp); 403 aper_alloc = agp_aper_base;
404 aper_order = agp_aper_order;
405 }
383 406
384 if (aper_alloc) { 407 if (aper_alloc) {
385 /* Got the aperture from the AGP bridge */ 408 /* Got the aperture from the AGP bridge */
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 9e3939db76e8..9c24470a8252 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -245,11 +245,7 @@ static int __devinit aperture_valid(u64 aper, u32 size)
245 printk(KERN_ERR PFX "No aperture\n"); 245 printk(KERN_ERR PFX "No aperture\n");
246 return 0; 246 return 0;
247 } 247 }
248 if (size < 32*1024*1024) { 248 if ((u64)aper + size > 0x100000000ULL) {
249 printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20);
250 return 0;
251 }
252 if ((u64)aper + size > 0x100000000ULL) {
253 printk(KERN_ERR PFX "Aperture out of bounds\n"); 249 printk(KERN_ERR PFX "Aperture out of bounds\n");
254 return 0; 250 return 0;
255 } 251 }
@@ -257,6 +253,10 @@ static int __devinit aperture_valid(u64 aper, u32 size)
257 printk(KERN_ERR PFX "Aperture pointing to RAM\n"); 253 printk(KERN_ERR PFX "Aperture pointing to RAM\n");
258 return 0; 254 return 0;
259 } 255 }
256 if (size < 32*1024*1024) {
257 printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20);
258 return 0;
259 }
260 260
261 /* Request the Aperture. This catches cases when someone else 261 /* Request the Aperture. This catches cases when someone else
262 already put a mapping in there - happens with some very broken BIOS 262 already put a mapping in there - happens with some very broken BIOS
@@ -317,7 +317,7 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
317 * On some sick chips APSIZE is 0. This means it wants 4G 317 * On some sick chips APSIZE is 0. This means it wants 4G
318 * so let double check that order, and lets trust the AMD NB settings 318 * so let double check that order, and lets trust the AMD NB settings
319 */ 319 */
320 if (aper + (32ULL<<(20 + order)) > 0x100000000ULL) { 320 if (order >=0 && aper + (32ULL<<(20 + order)) > 0x100000000ULL) {
321 printk(KERN_INFO "Aperture size %u MB is not right, using settings from NB\n", 321 printk(KERN_INFO "Aperture size %u MB is not right, using settings from NB\n",
322 32 << order); 322 32 << order);
323 order = nb_order; 323 order = nb_order;