1250c2277SThomas Gleixner /* 2250c2277SThomas Gleixner * Firmware replacement code. 3250c2277SThomas Gleixner * 4250c2277SThomas Gleixner * Work around broken BIOSes that don't set an aperture or only set the 5250c2277SThomas Gleixner * aperture in the AGP bridge. 6250c2277SThomas Gleixner * If all fails map the aperture over some low memory. This is cheaper than 7250c2277SThomas Gleixner * doing bounce buffering. The memory is lost. This is done at early boot 8250c2277SThomas Gleixner * because only the bootmem allocator can allocate 32+MB. 9250c2277SThomas Gleixner * 10250c2277SThomas Gleixner * Copyright 2002 Andi Kleen, SuSE Labs. 11250c2277SThomas Gleixner */ 12250c2277SThomas Gleixner #include <linux/kernel.h> 13250c2277SThomas Gleixner #include <linux/types.h> 14250c2277SThomas Gleixner #include <linux/init.h> 15250c2277SThomas Gleixner #include <linux/bootmem.h> 16250c2277SThomas Gleixner #include <linux/mmzone.h> 17250c2277SThomas Gleixner #include <linux/pci_ids.h> 18250c2277SThomas Gleixner #include <linux/pci.h> 19250c2277SThomas Gleixner #include <linux/bitops.h> 20250c2277SThomas Gleixner #include <linux/ioport.h> 212050d45dSPavel Machek #include <linux/suspend.h> 22250c2277SThomas Gleixner #include <asm/e820.h> 23250c2277SThomas Gleixner #include <asm/io.h> 24395624fcSJoerg Roedel #include <asm/gart.h> 25250c2277SThomas Gleixner #include <asm/pci-direct.h> 26250c2277SThomas Gleixner #include <asm/dma.h> 27250c2277SThomas Gleixner #include <asm/k8.h> 28250c2277SThomas Gleixner 290440d4c0SJoerg Roedel int gart_iommu_aperture; 307de6a4cdSPavel Machek int gart_iommu_aperture_disabled __initdata; 317de6a4cdSPavel Machek int gart_iommu_aperture_allowed __initdata; 32250c2277SThomas Gleixner 33250c2277SThomas Gleixner int fallback_aper_order __initdata = 1; /* 64MB */ 347de6a4cdSPavel Machek int fallback_aper_force __initdata; 35250c2277SThomas Gleixner 36250c2277SThomas Gleixner int fix_aperture __initdata = 1; 37250c2277SThomas Gleixner 38250c2277SThomas Gleixner static struct resource gart_resource = { 39250c2277SThomas Gleixner .name = "GART", 40250c2277SThomas Gleixner .flags = IORESOURCE_MEM, 41250c2277SThomas Gleixner }; 42250c2277SThomas Gleixner 43250c2277SThomas Gleixner static void __init insert_aperture_resource(u32 aper_base, u32 aper_size) 44250c2277SThomas Gleixner { 45250c2277SThomas Gleixner gart_resource.start = aper_base; 46250c2277SThomas Gleixner gart_resource.end = aper_base + aper_size - 1; 47250c2277SThomas Gleixner insert_resource(&iomem_resource, &gart_resource); 48250c2277SThomas Gleixner } 49250c2277SThomas Gleixner 50250c2277SThomas Gleixner /* This code runs before the PCI subsystem is initialized, so just 51250c2277SThomas Gleixner access the northbridge directly. */ 52250c2277SThomas Gleixner 53250c2277SThomas Gleixner static u32 __init allocate_aperture(void) 54250c2277SThomas Gleixner { 55250c2277SThomas Gleixner u32 aper_size; 56250c2277SThomas Gleixner void *p; 57250c2277SThomas Gleixner 58250c2277SThomas Gleixner if (fallback_aper_order > 7) 59250c2277SThomas Gleixner fallback_aper_order = 7; 60250c2277SThomas Gleixner aper_size = (32 * 1024 * 1024) << fallback_aper_order; 61250c2277SThomas Gleixner 62250c2277SThomas Gleixner /* 63c140df97SIngo Molnar * Aperture has to be naturally aligned. This means a 2GB aperture 64c140df97SIngo Molnar * won't have much chance of finding a place in the lower 4GB of 65c140df97SIngo Molnar * memory. Unfortunately we cannot move it up because that would 66c140df97SIngo Molnar * make the IOMMU useless. 67250c2277SThomas Gleixner */ 68250c2277SThomas Gleixner p = __alloc_bootmem_nopanic(aper_size, aper_size, 0); 69250c2277SThomas Gleixner if (!p || __pa(p)+aper_size > 0xffffffff) { 7031183ba8SIngo Molnar printk(KERN_ERR 7131183ba8SIngo Molnar "Cannot allocate aperture memory hole (%p,%uK)\n", 72250c2277SThomas Gleixner p, aper_size>>10); 73250c2277SThomas Gleixner if (p) 74250c2277SThomas Gleixner free_bootmem(__pa(p), aper_size); 75250c2277SThomas Gleixner return 0; 76250c2277SThomas Gleixner } 7731183ba8SIngo Molnar printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n", 78250c2277SThomas Gleixner aper_size >> 10, __pa(p)); 79250c2277SThomas Gleixner insert_aperture_resource((u32)__pa(p), aper_size); 802050d45dSPavel Machek register_nosave_region((u32)__pa(p) >> PAGE_SHIFT, 812050d45dSPavel Machek (u32)__pa(p+aper_size) >> PAGE_SHIFT); 82c140df97SIngo Molnar 83250c2277SThomas Gleixner return (u32)__pa(p); 84250c2277SThomas Gleixner } 85250c2277SThomas Gleixner 86*8c9fd91aSYinghai Lu static int __init aperture_valid(u64 aper_base, u32 aper_size, u32 min_size) 87250c2277SThomas Gleixner { 88250c2277SThomas Gleixner if (!aper_base) 89250c2277SThomas Gleixner return 0; 9031183ba8SIngo Molnar 91250c2277SThomas Gleixner if (aper_base + aper_size > 0x100000000UL) { 9231183ba8SIngo Molnar printk(KERN_ERR "Aperture beyond 4GB. Ignoring.\n"); 93250c2277SThomas Gleixner return 0; 94250c2277SThomas Gleixner } 95250c2277SThomas Gleixner if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) { 9631183ba8SIngo Molnar printk(KERN_ERR "Aperture pointing to e820 RAM. Ignoring.\n"); 97250c2277SThomas Gleixner return 0; 98250c2277SThomas Gleixner } 99*8c9fd91aSYinghai Lu if (aper_size < min_size) { 100*8c9fd91aSYinghai Lu printk(KERN_ERR "Aperture too small (%d MB) than (%d MB)\n", 101*8c9fd91aSYinghai Lu aper_size>>20, min_size>>20); 102261a5ec3SYinghai Lu return 0; 103261a5ec3SYinghai Lu } 10431183ba8SIngo Molnar 105250c2277SThomas Gleixner return 1; 106250c2277SThomas Gleixner } 107250c2277SThomas Gleixner 108250c2277SThomas Gleixner /* Find a PCI capability */ 109250c2277SThomas Gleixner static __u32 __init find_cap(int num, int slot, int func, int cap) 110250c2277SThomas Gleixner { 111250c2277SThomas Gleixner int bytes; 112c140df97SIngo Molnar u8 pos; 113c140df97SIngo Molnar 114c140df97SIngo Molnar if (!(read_pci_config_16(num, slot, func, PCI_STATUS) & 115c140df97SIngo Molnar PCI_STATUS_CAP_LIST)) 116250c2277SThomas Gleixner return 0; 117c140df97SIngo Molnar 118250c2277SThomas Gleixner pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST); 119250c2277SThomas Gleixner for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { 120250c2277SThomas Gleixner u8 id; 121c140df97SIngo Molnar 122250c2277SThomas Gleixner pos &= ~3; 123250c2277SThomas Gleixner id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID); 124250c2277SThomas Gleixner if (id == 0xff) 125250c2277SThomas Gleixner break; 126250c2277SThomas Gleixner if (id == cap) 127250c2277SThomas Gleixner return pos; 128c140df97SIngo Molnar pos = read_pci_config_byte(num, slot, func, 129c140df97SIngo Molnar pos+PCI_CAP_LIST_NEXT); 130250c2277SThomas Gleixner } 131250c2277SThomas Gleixner return 0; 132250c2277SThomas Gleixner } 133250c2277SThomas Gleixner 134250c2277SThomas Gleixner /* Read a standard AGPv3 bridge header */ 135250c2277SThomas Gleixner static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) 136250c2277SThomas Gleixner { 137250c2277SThomas Gleixner u32 apsize; 138250c2277SThomas Gleixner u32 apsizereg; 139250c2277SThomas Gleixner int nbits; 140250c2277SThomas Gleixner u32 aper_low, aper_hi; 141250c2277SThomas Gleixner u64 aper; 1421edc1ab3SYinghai Lu u32 old_order; 143250c2277SThomas Gleixner 14431183ba8SIngo Molnar printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", num, slot, func); 145250c2277SThomas Gleixner apsizereg = read_pci_config_16(num, slot, func, cap + 0x14); 146250c2277SThomas Gleixner if (apsizereg == 0xffffffff) { 14731183ba8SIngo Molnar printk(KERN_ERR "APSIZE in AGP bridge unreadable\n"); 148250c2277SThomas Gleixner return 0; 149250c2277SThomas Gleixner } 150250c2277SThomas Gleixner 1511edc1ab3SYinghai Lu /* old_order could be the value from NB gart setting */ 1521edc1ab3SYinghai Lu old_order = *order; 1531edc1ab3SYinghai Lu 154250c2277SThomas Gleixner apsize = apsizereg & 0xfff; 155250c2277SThomas Gleixner /* Some BIOS use weird encodings not in the AGPv3 table. */ 156250c2277SThomas Gleixner if (apsize & 0xff) 157250c2277SThomas Gleixner apsize |= 0xf00; 158250c2277SThomas Gleixner nbits = hweight16(apsize); 159250c2277SThomas Gleixner *order = 7 - nbits; 160250c2277SThomas Gleixner if ((int)*order < 0) /* < 32MB */ 161250c2277SThomas Gleixner *order = 0; 162250c2277SThomas Gleixner 163250c2277SThomas Gleixner aper_low = read_pci_config(num, slot, func, 0x10); 164250c2277SThomas Gleixner aper_hi = read_pci_config(num, slot, func, 0x14); 165250c2277SThomas Gleixner aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); 166250c2277SThomas Gleixner 1671edc1ab3SYinghai Lu /* 1681edc1ab3SYinghai Lu * On some sick chips, APSIZE is 0. It means it wants 4G 1691edc1ab3SYinghai Lu * so let double check that order, and lets trust AMD NB settings: 1701edc1ab3SYinghai Lu */ 171*8c9fd91aSYinghai Lu printk(KERN_INFO "Aperture from AGP @ %Lx old size %u MB\n", 172*8c9fd91aSYinghai Lu aper, 32 << old_order); 173*8c9fd91aSYinghai Lu if (aper + (32ULL<<(20 + *order)) > 0x100000000ULL) { 1741edc1ab3SYinghai Lu printk(KERN_INFO "Aperture size %u MB (APSIZE %x) is not right, using settings from NB\n", 1751edc1ab3SYinghai Lu 32 << *order, apsizereg); 1761edc1ab3SYinghai Lu *order = old_order; 1771edc1ab3SYinghai Lu } 1781edc1ab3SYinghai Lu 17931183ba8SIngo Molnar printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", 180250c2277SThomas Gleixner aper, 32 << *order, apsizereg); 181250c2277SThomas Gleixner 182*8c9fd91aSYinghai Lu if (!aperture_valid(aper, (32*1024*1024) << *order, 32<<20)) 183250c2277SThomas Gleixner return 0; 184250c2277SThomas Gleixner return (u32)aper; 185250c2277SThomas Gleixner } 186250c2277SThomas Gleixner 187c140df97SIngo Molnar /* 188c140df97SIngo Molnar * Look for an AGP bridge. Windows only expects the aperture in the 189c140df97SIngo Molnar * AGP bridge and some BIOS forget to initialize the Northbridge too. 190c140df97SIngo Molnar * Work around this here. 191c140df97SIngo Molnar * 192c140df97SIngo Molnar * Do an PCI bus scan by hand because we're running before the PCI 193c140df97SIngo Molnar * subsystem. 194c140df97SIngo Molnar * 195c140df97SIngo Molnar * All K8 AGP bridges are AGPv3 compliant, so we can do this scan 196c140df97SIngo Molnar * generically. It's probably overkill to always scan all slots because 197c140df97SIngo Molnar * the AGP bridges should be always an own bus on the HT hierarchy, 198c140df97SIngo Molnar * but do it here for future safety. 199c140df97SIngo Molnar */ 200250c2277SThomas Gleixner static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) 201250c2277SThomas Gleixner { 202250c2277SThomas Gleixner int num, slot, func; 203250c2277SThomas Gleixner 204250c2277SThomas Gleixner /* Poor man's PCI discovery */ 205250c2277SThomas Gleixner for (num = 0; num < 256; num++) { 206250c2277SThomas Gleixner for (slot = 0; slot < 32; slot++) { 207250c2277SThomas Gleixner for (func = 0; func < 8; func++) { 208250c2277SThomas Gleixner u32 class, cap; 209250c2277SThomas Gleixner u8 type; 210250c2277SThomas Gleixner class = read_pci_config(num, slot, func, 211250c2277SThomas Gleixner PCI_CLASS_REVISION); 212250c2277SThomas Gleixner if (class == 0xffffffff) 213250c2277SThomas Gleixner break; 214250c2277SThomas Gleixner 215250c2277SThomas Gleixner switch (class >> 16) { 216250c2277SThomas Gleixner case PCI_CLASS_BRIDGE_HOST: 217250c2277SThomas Gleixner case PCI_CLASS_BRIDGE_OTHER: /* needed? */ 218250c2277SThomas Gleixner /* AGP bridge? */ 219c140df97SIngo Molnar cap = find_cap(num, slot, func, 220c140df97SIngo Molnar PCI_CAP_ID_AGP); 221250c2277SThomas Gleixner if (!cap) 222250c2277SThomas Gleixner break; 223250c2277SThomas Gleixner *valid_agp = 1; 224c140df97SIngo Molnar return read_agp(num, slot, func, cap, 225c140df97SIngo Molnar order); 226250c2277SThomas Gleixner } 227250c2277SThomas Gleixner 228250c2277SThomas Gleixner /* No multi-function device? */ 229250c2277SThomas Gleixner type = read_pci_config_byte(num, slot, func, 230250c2277SThomas Gleixner PCI_HEADER_TYPE); 231250c2277SThomas Gleixner if (!(type & 0x80)) 232250c2277SThomas Gleixner break; 233250c2277SThomas Gleixner } 234250c2277SThomas Gleixner } 235250c2277SThomas Gleixner } 23631183ba8SIngo Molnar printk(KERN_INFO "No AGP bridge found\n"); 237c140df97SIngo Molnar 238250c2277SThomas Gleixner return 0; 239250c2277SThomas Gleixner } 240250c2277SThomas Gleixner 241aaf23042SYinghai Lu static int gart_fix_e820 __initdata = 1; 242aaf23042SYinghai Lu 243aaf23042SYinghai Lu static int __init parse_gart_mem(char *p) 244aaf23042SYinghai Lu { 245aaf23042SYinghai Lu if (!p) 246aaf23042SYinghai Lu return -EINVAL; 247aaf23042SYinghai Lu 248aaf23042SYinghai Lu if (!strncmp(p, "off", 3)) 249aaf23042SYinghai Lu gart_fix_e820 = 0; 250aaf23042SYinghai Lu else if (!strncmp(p, "on", 2)) 251aaf23042SYinghai Lu gart_fix_e820 = 1; 252aaf23042SYinghai Lu 253aaf23042SYinghai Lu return 0; 254aaf23042SYinghai Lu } 255aaf23042SYinghai Lu early_param("gart_fix_e820", parse_gart_mem); 256aaf23042SYinghai Lu 257aaf23042SYinghai Lu void __init early_gart_iommu_check(void) 258aaf23042SYinghai Lu { 259aaf23042SYinghai Lu /* 260aaf23042SYinghai Lu * in case it is enabled before, esp for kexec/kdump, 261aaf23042SYinghai Lu * previous kernel already enable that. memset called 262aaf23042SYinghai Lu * by allocate_aperture/__alloc_bootmem_nopanic cause restart. 263aaf23042SYinghai Lu * or second kernel have different position for GART hole. and new 264aaf23042SYinghai Lu * kernel could use hole as RAM that is still used by GART set by 265aaf23042SYinghai Lu * first kernel 266aaf23042SYinghai Lu * or BIOS forget to put that in reserved. 267aaf23042SYinghai Lu * try to update e820 to make that region as reserved. 268aaf23042SYinghai Lu */ 269aaf23042SYinghai Lu int fix, num; 270aaf23042SYinghai Lu u32 ctl; 271aaf23042SYinghai Lu u32 aper_size = 0, aper_order = 0, last_aper_order = 0; 272aaf23042SYinghai Lu u64 aper_base = 0, last_aper_base = 0; 273aaf23042SYinghai Lu int aper_enabled = 0, last_aper_enabled = 0; 274aaf23042SYinghai Lu 275aaf23042SYinghai Lu if (!early_pci_allowed()) 276aaf23042SYinghai Lu return; 277aaf23042SYinghai Lu 278aaf23042SYinghai Lu fix = 0; 279aaf23042SYinghai Lu for (num = 24; num < 32; num++) { 280aaf23042SYinghai Lu if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) 281aaf23042SYinghai Lu continue; 282aaf23042SYinghai Lu 283aaf23042SYinghai Lu ctl = read_pci_config(0, num, 3, 0x90); 284aaf23042SYinghai Lu aper_enabled = ctl & 1; 285aaf23042SYinghai Lu aper_order = (ctl >> 1) & 7; 286aaf23042SYinghai Lu aper_size = (32 * 1024 * 1024) << aper_order; 287aaf23042SYinghai Lu aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; 288aaf23042SYinghai Lu aper_base <<= 25; 289aaf23042SYinghai Lu 290aaf23042SYinghai Lu if ((last_aper_order && aper_order != last_aper_order) || 291aaf23042SYinghai Lu (last_aper_base && aper_base != last_aper_base) || 292aaf23042SYinghai Lu (last_aper_enabled && aper_enabled != last_aper_enabled)) { 293aaf23042SYinghai Lu fix = 1; 294aaf23042SYinghai Lu break; 295aaf23042SYinghai Lu } 296aaf23042SYinghai Lu last_aper_order = aper_order; 297aaf23042SYinghai Lu last_aper_base = aper_base; 298aaf23042SYinghai Lu last_aper_enabled = aper_enabled; 299aaf23042SYinghai Lu } 300aaf23042SYinghai Lu 301aaf23042SYinghai Lu if (!fix && !aper_enabled) 302aaf23042SYinghai Lu return; 303aaf23042SYinghai Lu 304aaf23042SYinghai Lu if (!aper_base || !aper_size || aper_base + aper_size > 0x100000000UL) 305aaf23042SYinghai Lu fix = 1; 306aaf23042SYinghai Lu 307aaf23042SYinghai Lu if (gart_fix_e820 && !fix && aper_enabled) { 308*8c9fd91aSYinghai Lu if (!e820_all_mapped(aper_base, aper_base + aper_size, 309*8c9fd91aSYinghai Lu E820_RESERVED)) { 310aaf23042SYinghai Lu /* reserved it, so we can resuse it in second kernel */ 311aaf23042SYinghai Lu printk(KERN_INFO "update e820 for GART\n"); 312aaf23042SYinghai Lu add_memory_region(aper_base, aper_size, E820_RESERVED); 313aaf23042SYinghai Lu update_e820(); 314aaf23042SYinghai Lu } 315aaf23042SYinghai Lu return; 316aaf23042SYinghai Lu } 317aaf23042SYinghai Lu 318aaf23042SYinghai Lu /* different nodes have different setting, disable them all at first*/ 319aaf23042SYinghai Lu for (num = 24; num < 32; num++) { 320aaf23042SYinghai Lu if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) 321aaf23042SYinghai Lu continue; 322aaf23042SYinghai Lu 323aaf23042SYinghai Lu ctl = read_pci_config(0, num, 3, 0x90); 324aaf23042SYinghai Lu ctl &= ~1; 325aaf23042SYinghai Lu write_pci_config(0, num, 3, 0x90, ctl); 326aaf23042SYinghai Lu } 327aaf23042SYinghai Lu 328aaf23042SYinghai Lu } 329aaf23042SYinghai Lu 330*8c9fd91aSYinghai Lu static int __initdata printed_gart_size_msg; 331*8c9fd91aSYinghai Lu 3320440d4c0SJoerg Roedel void __init gart_iommu_hole_init(void) 333250c2277SThomas Gleixner { 334*8c9fd91aSYinghai Lu u32 agp_aper_base = 0, agp_aper_order = 0; 335250c2277SThomas Gleixner u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; 336250c2277SThomas Gleixner u64 aper_base, last_aper_base = 0; 337c140df97SIngo Molnar int fix, num, valid_agp = 0; 33847db4c3eSYinghai Lu int node; 339250c2277SThomas Gleixner 3400440d4c0SJoerg Roedel if (gart_iommu_aperture_disabled || !fix_aperture || 3410440d4c0SJoerg Roedel !early_pci_allowed()) 342250c2277SThomas Gleixner return; 343250c2277SThomas Gleixner 344250c2277SThomas Gleixner printk(KERN_INFO "Checking aperture...\n"); 345250c2277SThomas Gleixner 346*8c9fd91aSYinghai Lu if (!fallback_aper_force) 347*8c9fd91aSYinghai Lu agp_aper_base = search_agp_bridge(&agp_aper_order, &valid_agp); 348*8c9fd91aSYinghai Lu 349250c2277SThomas Gleixner fix = 0; 35047db4c3eSYinghai Lu node = 0; 351250c2277SThomas Gleixner for (num = 24; num < 32; num++) { 352250c2277SThomas Gleixner if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) 353250c2277SThomas Gleixner continue; 354250c2277SThomas Gleixner 355250c2277SThomas Gleixner iommu_detected = 1; 3560440d4c0SJoerg Roedel gart_iommu_aperture = 1; 357250c2277SThomas Gleixner 358250c2277SThomas Gleixner aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; 359250c2277SThomas Gleixner aper_size = (32 * 1024 * 1024) << aper_order; 360250c2277SThomas Gleixner aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; 361250c2277SThomas Gleixner aper_base <<= 25; 362250c2277SThomas Gleixner 36347db4c3eSYinghai Lu printk(KERN_INFO "Node %d: aperture @ %Lx size %u MB\n", 36447db4c3eSYinghai Lu node, aper_base, aper_size >> 20); 36547db4c3eSYinghai Lu node++; 366250c2277SThomas Gleixner 367*8c9fd91aSYinghai Lu if (!aperture_valid(aper_base, aper_size, 64<<20)) { 368*8c9fd91aSYinghai Lu if (valid_agp && agp_aper_base && 369*8c9fd91aSYinghai Lu agp_aper_base == aper_base && 370*8c9fd91aSYinghai Lu agp_aper_order == aper_order) { 371*8c9fd91aSYinghai Lu /* the same between two setting from NB and agp */ 372*8c9fd91aSYinghai Lu if (!no_iommu && end_pfn > MAX_DMA32_PFN && !printed_gart_size_msg) { 373*8c9fd91aSYinghai Lu printk(KERN_ERR "you are using iommu with agp, but GART size is less than 64M\n"); 374*8c9fd91aSYinghai Lu printk(KERN_ERR "please increase GART size in your BIOS setup\n"); 375*8c9fd91aSYinghai Lu printk(KERN_ERR "if BIOS doesn't have that option, contact your HW vendor!\n"); 376*8c9fd91aSYinghai Lu printed_gart_size_msg = 1; 377*8c9fd91aSYinghai Lu } 378*8c9fd91aSYinghai Lu } else { 379250c2277SThomas Gleixner fix = 1; 380250c2277SThomas Gleixner break; 381250c2277SThomas Gleixner } 382*8c9fd91aSYinghai Lu } 383250c2277SThomas Gleixner 384250c2277SThomas Gleixner if ((last_aper_order && aper_order != last_aper_order) || 385250c2277SThomas Gleixner (last_aper_base && aper_base != last_aper_base)) { 386250c2277SThomas Gleixner fix = 1; 387250c2277SThomas Gleixner break; 388250c2277SThomas Gleixner } 389250c2277SThomas Gleixner last_aper_order = aper_order; 390250c2277SThomas Gleixner last_aper_base = aper_base; 391250c2277SThomas Gleixner } 392250c2277SThomas Gleixner 393250c2277SThomas Gleixner if (!fix && !fallback_aper_force) { 394250c2277SThomas Gleixner if (last_aper_base) { 395250c2277SThomas Gleixner unsigned long n = (32 * 1024 * 1024) << last_aper_order; 396c140df97SIngo Molnar 397250c2277SThomas Gleixner insert_aperture_resource((u32)last_aper_base, n); 398250c2277SThomas Gleixner } 399250c2277SThomas Gleixner return; 400250c2277SThomas Gleixner } 401250c2277SThomas Gleixner 402*8c9fd91aSYinghai Lu if (!fallback_aper_force) { 403*8c9fd91aSYinghai Lu aper_alloc = agp_aper_base; 404*8c9fd91aSYinghai Lu aper_order = agp_aper_order; 405*8c9fd91aSYinghai Lu } 406250c2277SThomas Gleixner 407250c2277SThomas Gleixner if (aper_alloc) { 408250c2277SThomas Gleixner /* Got the aperture from the AGP bridge */ 409250c2277SThomas Gleixner } else if (swiotlb && !valid_agp) { 410250c2277SThomas Gleixner /* Do nothing */ 411250c2277SThomas Gleixner } else if ((!no_iommu && end_pfn > MAX_DMA32_PFN) || 412250c2277SThomas Gleixner force_iommu || 413250c2277SThomas Gleixner valid_agp || 414250c2277SThomas Gleixner fallback_aper_force) { 41531183ba8SIngo Molnar printk(KERN_ERR 41631183ba8SIngo Molnar "Your BIOS doesn't leave a aperture memory hole\n"); 41731183ba8SIngo Molnar printk(KERN_ERR 41831183ba8SIngo Molnar "Please enable the IOMMU option in the BIOS setup\n"); 41931183ba8SIngo Molnar printk(KERN_ERR 42031183ba8SIngo Molnar "This costs you %d MB of RAM\n", 421250c2277SThomas Gleixner 32 << fallback_aper_order); 422250c2277SThomas Gleixner 423250c2277SThomas Gleixner aper_order = fallback_aper_order; 424250c2277SThomas Gleixner aper_alloc = allocate_aperture(); 425250c2277SThomas Gleixner if (!aper_alloc) { 426c140df97SIngo Molnar /* 427c140df97SIngo Molnar * Could disable AGP and IOMMU here, but it's 428c140df97SIngo Molnar * probably not worth it. But the later users 429c140df97SIngo Molnar * cannot deal with bad apertures and turning 430c140df97SIngo Molnar * on the aperture over memory causes very 431c140df97SIngo Molnar * strange problems, so it's better to panic 432c140df97SIngo Molnar * early. 433c140df97SIngo Molnar */ 434250c2277SThomas Gleixner panic("Not enough memory for aperture"); 435250c2277SThomas Gleixner } 436250c2277SThomas Gleixner } else { 437250c2277SThomas Gleixner return; 438250c2277SThomas Gleixner } 439250c2277SThomas Gleixner 440250c2277SThomas Gleixner /* Fix up the north bridges */ 441250c2277SThomas Gleixner for (num = 24; num < 32; num++) { 442250c2277SThomas Gleixner if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) 443250c2277SThomas Gleixner continue; 444250c2277SThomas Gleixner 445c140df97SIngo Molnar /* 446c140df97SIngo Molnar * Don't enable translation yet. That is done later. 447c140df97SIngo Molnar * Assume this BIOS didn't initialise the GART so 448c140df97SIngo Molnar * just overwrite all previous bits 449c140df97SIngo Molnar */ 450250c2277SThomas Gleixner write_pci_config(0, num, 3, 0x90, aper_order<<1); 451250c2277SThomas Gleixner write_pci_config(0, num, 3, 0x94, aper_alloc>>25); 452250c2277SThomas Gleixner } 453250c2277SThomas Gleixner } 454