aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel.send@gmail.com>2008-04-13 04:11:41 -0400
committerIngo Molnar <mingo@elte.hu>2008-05-12 15:28:10 -0400
commit1edc1ab3f68168ec6815e6d630f38948a6da005a (patch)
treef8ea99c5a917fcf2e8cf043755b665de4ebd49cf
parentaa134f1b09df6beaa4d031a50d5fda1f3cebce6c (diff)
x86: agp_gart size checking for buggy device
while looking at Rafael J. Wysocki's system boot log, I found a funny printout: Node 0: aperture @ de000000 size 32 MB Aperture too small (32 MB) AGP bridge at 00:04:00 Aperture from AGP @ de000000 size 4096 MB (APSIZE 0) Aperture too small (0 MB) Your BIOS doesn't leave a aperture memory hole Please enable the IOMMU option in the BIOS setup This costs you 64 MB of RAM Mapping aperture over 65536 KB of RAM @ 4000000 ... agpgart: Detected AGP bridge 20 agpgart: Aperture pointing to RAM agpgart: Aperture from AGP @ de000000 size 4096 MB agpgart: Aperture too small (0 MB) agpgart: No usable aperture found. agpgart: Consider rebooting with iommu=memaper=2 to get a good aperture. it means BIOS allocated the correct gart on the NB and AGP bridge, but because a bug in the silicon (the agp bridge reports the wrong order, it wants 4G instead) the kernel will reject that allocation. Also, because the size is only 32MB, and we try to get another 64M for gart, late fix_northbridge can not revert that change because it still reads the wrong size from agp bridge. So try to double check the order value from the agp bridge, before calling aperture_valid(). [ mingo@elte.hu: 32-bit fix. ] 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.c14
-rw-r--r--drivers/char/agp/amd64-agp.c11
2 files changed, 25 insertions, 0 deletions
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index 479926d9e004..2e93b3132dff 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -138,6 +138,7 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
138 int nbits; 138 int nbits;
139 u32 aper_low, aper_hi; 139 u32 aper_low, aper_hi;
140 u64 aper; 140 u64 aper;
141 u32 old_order;
141 142
142 printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", num, slot, func); 143 printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", num, slot, func);
143 apsizereg = read_pci_config_16(num, slot, func, cap + 0x14); 144 apsizereg = read_pci_config_16(num, slot, func, cap + 0x14);
@@ -146,6 +147,9 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
146 return 0; 147 return 0;
147 } 148 }
148 149
150 /* old_order could be the value from NB gart setting */
151 old_order = *order;
152
149 apsize = apsizereg & 0xfff; 153 apsize = apsizereg & 0xfff;
150 /* Some BIOS use weird encodings not in the AGPv3 table. */ 154 /* Some BIOS use weird encodings not in the AGPv3 table. */
151 if (apsize & 0xff) 155 if (apsize & 0xff)
@@ -159,6 +163,16 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
159 aper_hi = read_pci_config(num, slot, func, 0x14); 163 aper_hi = read_pci_config(num, slot, func, 0x14);
160 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); 164 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
161 165
166 /*
167 * 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 */
170 if (aper + (32UL<<(20 + *order)) > 0x100000000UL) {
171 printk(KERN_INFO "Aperture size %u MB (APSIZE %x) is not right, using settings from NB\n",
172 32 << *order, apsizereg);
173 *order = old_order;
174 }
175
162 printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", 176 printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
163 aper, 32 << *order, apsizereg); 177 aper, 32 << *order, apsizereg);
164 178
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 25d64224cdbb..9e3939db76e8 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -312,6 +312,17 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
312 pci_read_config_dword(agp, 0x10, &aper_low); 312 pci_read_config_dword(agp, 0x10, &aper_low);
313 pci_read_config_dword(agp, 0x14, &aper_hi); 313 pci_read_config_dword(agp, 0x14, &aper_hi);
314 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); 314 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
315
316 /*
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
319 */
320 if (aper + (32ULL<<(20 + order)) > 0x100000000ULL) {
321 printk(KERN_INFO "Aperture size %u MB is not right, using settings from NB\n",
322 32 << order);
323 order = nb_order;
324 }
325
315 printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order); 326 printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order);
316 if (order < 0 || !aperture_valid(aper, (32*1024*1024)<<order)) 327 if (order < 0 || !aperture_valid(aper, (32*1024*1024)<<order))
317 return -1; 328 return -1;