提交 1edc1ab3 编写于 作者: Y Yinghai Lu 提交者: Ingo Molnar

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: NYinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: NIngo Molnar <mingo@elte.hu>
Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
上级 aa134f1b
...@@ -138,6 +138,7 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) ...@@ -138,6 +138,7 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
int nbits; int nbits;
u32 aper_low, aper_hi; u32 aper_low, aper_hi;
u64 aper; u64 aper;
u32 old_order;
printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", num, slot, func); printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", num, slot, func);
apsizereg = read_pci_config_16(num, slot, func, cap + 0x14); 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,6 +147,9 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
return 0; return 0;
} }
/* old_order could be the value from NB gart setting */
old_order = *order;
apsize = apsizereg & 0xfff; apsize = apsizereg & 0xfff;
/* Some BIOS use weird encodings not in the AGPv3 table. */ /* Some BIOS use weird encodings not in the AGPv3 table. */
if (apsize & 0xff) if (apsize & 0xff)
...@@ -159,6 +163,16 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) ...@@ -159,6 +163,16 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
aper_hi = read_pci_config(num, slot, func, 0x14); aper_hi = read_pci_config(num, slot, func, 0x14);
aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
/*
* On some sick chips, APSIZE is 0. It means it wants 4G
* so let double check that order, and lets trust AMD NB settings:
*/
if (aper + (32UL<<(20 + *order)) > 0x100000000UL) {
printk(KERN_INFO "Aperture size %u MB (APSIZE %x) is not right, using settings from NB\n",
32 << *order, apsizereg);
*order = old_order;
}
printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
aper, 32 << *order, apsizereg); aper, 32 << *order, apsizereg);
......
...@@ -312,6 +312,17 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, ...@@ -312,6 +312,17 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
pci_read_config_dword(agp, 0x10, &aper_low); pci_read_config_dword(agp, 0x10, &aper_low);
pci_read_config_dword(agp, 0x14, &aper_hi); pci_read_config_dword(agp, 0x14, &aper_hi);
aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
/*
* On some sick chips APSIZE is 0. This means it wants 4G
* so let double check that order, and lets trust the AMD NB settings
*/
if (aper + (32ULL<<(20 + order)) > 0x100000000ULL) {
printk(KERN_INFO "Aperture size %u MB is not right, using settings from NB\n",
32 << order);
order = nb_order;
}
printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order); printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order);
if (order < 0 || !aperture_valid(aper, (32*1024*1024)<<order)) if (order < 0 || !aperture_valid(aper, (32*1024*1024)<<order))
return -1; return -1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册