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> 21*2050d45dSPavel 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; 300440d4c0SJoerg Roedel int gart_iommu_aperture_disabled __initdata = 0; 310440d4c0SJoerg Roedel int gart_iommu_aperture_allowed __initdata = 0; 32250c2277SThomas Gleixner 33250c2277SThomas Gleixner int fallback_aper_order __initdata = 1; /* 64MB */ 34250c2277SThomas Gleixner int fallback_aper_force __initdata = 0; 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); 80*2050d45dSPavel Machek register_nosave_region((u32)__pa(p) >> PAGE_SHIFT, 81*2050d45dSPavel Machek (u32)__pa(p+aper_size) >> PAGE_SHIFT); 82c140df97SIngo Molnar 83250c2277SThomas Gleixner return (u32)__pa(p); 84250c2277SThomas Gleixner } 85250c2277SThomas Gleixner 86250c2277SThomas Gleixner static int __init aperture_valid(u64 aper_base, u32 aper_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 } 99261a5ec3SYinghai Lu if (aper_size < 64*1024*1024) { 100261a5ec3SYinghai Lu printk(KERN_ERR "Aperture too small (%d MB)\n", aper_size>>20); 101261a5ec3SYinghai Lu return 0; 102261a5ec3SYinghai Lu } 10331183ba8SIngo Molnar 104250c2277SThomas Gleixner return 1; 105250c2277SThomas Gleixner } 106250c2277SThomas Gleixner 107250c2277SThomas Gleixner /* Find a PCI capability */ 108250c2277SThomas Gleixner static __u32 __init find_cap(int num, int slot, int func, int cap) 109250c2277SThomas Gleixner { 110250c2277SThomas Gleixner int bytes; 111c140df97SIngo Molnar u8 pos; 112c140df97SIngo Molnar 113c140df97SIngo Molnar if (!(read_pci_config_16(num, slot, func, PCI_STATUS) & 114c140df97SIngo Molnar PCI_STATUS_CAP_LIST)) 115250c2277SThomas Gleixner return 0; 116c140df97SIngo Molnar 117250c2277SThomas Gleixner pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST); 118250c2277SThomas Gleixner for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { 119250c2277SThomas Gleixner u8 id; 120c140df97SIngo Molnar 121250c2277SThomas Gleixner pos &= ~3; 122250c2277SThomas Gleixner id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID); 123250c2277SThomas Gleixner if (id == 0xff) 124250c2277SThomas Gleixner break; 125250c2277SThomas Gleixner if (id == cap) 126250c2277SThomas Gleixner return pos; 127c140df97SIngo Molnar pos = read_pci_config_byte(num, slot, func, 128c140df97SIngo Molnar pos+PCI_CAP_LIST_NEXT); 129250c2277SThomas Gleixner } 130250c2277SThomas Gleixner return 0; 131250c2277SThomas Gleixner } 132250c2277SThomas Gleixner 133250c2277SThomas Gleixner /* Read a standard AGPv3 bridge header */ 134250c2277SThomas Gleixner static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) 135250c2277SThomas Gleixner { 136250c2277SThomas Gleixner u32 apsize; 137250c2277SThomas Gleixner u32 apsizereg; 138250c2277SThomas Gleixner int nbits; 139250c2277SThomas Gleixner u32 aper_low, aper_hi; 140250c2277SThomas Gleixner u64 aper; 141250c2277SThomas Gleixner 14231183ba8SIngo Molnar printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", num, slot, func); 143250c2277SThomas Gleixner apsizereg = read_pci_config_16(num, slot, func, cap + 0x14); 144250c2277SThomas Gleixner if (apsizereg == 0xffffffff) { 14531183ba8SIngo Molnar printk(KERN_ERR "APSIZE in AGP bridge unreadable\n"); 146250c2277SThomas Gleixner return 0; 147250c2277SThomas Gleixner } 148250c2277SThomas Gleixner 149250c2277SThomas Gleixner apsize = apsizereg & 0xfff; 150250c2277SThomas Gleixner /* Some BIOS use weird encodings not in the AGPv3 table. */ 151250c2277SThomas Gleixner if (apsize & 0xff) 152250c2277SThomas Gleixner apsize |= 0xf00; 153250c2277SThomas Gleixner nbits = hweight16(apsize); 154250c2277SThomas Gleixner *order = 7 - nbits; 155250c2277SThomas Gleixner if ((int)*order < 0) /* < 32MB */ 156250c2277SThomas Gleixner *order = 0; 157250c2277SThomas Gleixner 158250c2277SThomas Gleixner aper_low = read_pci_config(num, slot, func, 0x10); 159250c2277SThomas Gleixner aper_hi = read_pci_config(num, slot, func, 0x14); 160250c2277SThomas Gleixner aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); 161250c2277SThomas Gleixner 16231183ba8SIngo Molnar printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", 163250c2277SThomas Gleixner aper, 32 << *order, apsizereg); 164250c2277SThomas Gleixner 165250c2277SThomas Gleixner if (!aperture_valid(aper, (32*1024*1024) << *order)) 166250c2277SThomas Gleixner return 0; 167250c2277SThomas Gleixner return (u32)aper; 168250c2277SThomas Gleixner } 169250c2277SThomas Gleixner 170c140df97SIngo Molnar /* 171c140df97SIngo Molnar * Look for an AGP bridge. Windows only expects the aperture in the 172c140df97SIngo Molnar * AGP bridge and some BIOS forget to initialize the Northbridge too. 173c140df97SIngo Molnar * Work around this here. 174c140df97SIngo Molnar * 175c140df97SIngo Molnar * Do an PCI bus scan by hand because we're running before the PCI 176c140df97SIngo Molnar * subsystem. 177c140df97SIngo Molnar * 178c140df97SIngo Molnar * All K8 AGP bridges are AGPv3 compliant, so we can do this scan 179c140df97SIngo Molnar * generically. It's probably overkill to always scan all slots because 180c140df97SIngo Molnar * the AGP bridges should be always an own bus on the HT hierarchy, 181c140df97SIngo Molnar * but do it here for future safety. 182c140df97SIngo Molnar */ 183250c2277SThomas Gleixner static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) 184250c2277SThomas Gleixner { 185250c2277SThomas Gleixner int num, slot, func; 186250c2277SThomas Gleixner 187250c2277SThomas Gleixner /* Poor man's PCI discovery */ 188250c2277SThomas Gleixner for (num = 0; num < 256; num++) { 189250c2277SThomas Gleixner for (slot = 0; slot < 32; slot++) { 190250c2277SThomas Gleixner for (func = 0; func < 8; func++) { 191250c2277SThomas Gleixner u32 class, cap; 192250c2277SThomas Gleixner u8 type; 193250c2277SThomas Gleixner class = read_pci_config(num, slot, func, 194250c2277SThomas Gleixner PCI_CLASS_REVISION); 195250c2277SThomas Gleixner if (class == 0xffffffff) 196250c2277SThomas Gleixner break; 197250c2277SThomas Gleixner 198250c2277SThomas Gleixner switch (class >> 16) { 199250c2277SThomas Gleixner case PCI_CLASS_BRIDGE_HOST: 200250c2277SThomas Gleixner case PCI_CLASS_BRIDGE_OTHER: /* needed? */ 201250c2277SThomas Gleixner /* AGP bridge? */ 202c140df97SIngo Molnar cap = find_cap(num, slot, func, 203c140df97SIngo Molnar PCI_CAP_ID_AGP); 204250c2277SThomas Gleixner if (!cap) 205250c2277SThomas Gleixner break; 206250c2277SThomas Gleixner *valid_agp = 1; 207c140df97SIngo Molnar return read_agp(num, slot, func, cap, 208c140df97SIngo Molnar order); 209250c2277SThomas Gleixner } 210250c2277SThomas Gleixner 211250c2277SThomas Gleixner /* No multi-function device? */ 212250c2277SThomas Gleixner type = read_pci_config_byte(num, slot, func, 213250c2277SThomas Gleixner PCI_HEADER_TYPE); 214250c2277SThomas Gleixner if (!(type & 0x80)) 215250c2277SThomas Gleixner break; 216250c2277SThomas Gleixner } 217250c2277SThomas Gleixner } 218250c2277SThomas Gleixner } 21931183ba8SIngo Molnar printk(KERN_INFO "No AGP bridge found\n"); 220c140df97SIngo Molnar 221250c2277SThomas Gleixner return 0; 222250c2277SThomas Gleixner } 223250c2277SThomas Gleixner 224aaf23042SYinghai Lu static int gart_fix_e820 __initdata = 1; 225aaf23042SYinghai Lu 226aaf23042SYinghai Lu static int __init parse_gart_mem(char *p) 227aaf23042SYinghai Lu { 228aaf23042SYinghai Lu if (!p) 229aaf23042SYinghai Lu return -EINVAL; 230aaf23042SYinghai Lu 231aaf23042SYinghai Lu if (!strncmp(p, "off", 3)) 232aaf23042SYinghai Lu gart_fix_e820 = 0; 233aaf23042SYinghai Lu else if (!strncmp(p, "on", 2)) 234aaf23042SYinghai Lu gart_fix_e820 = 1; 235aaf23042SYinghai Lu 236aaf23042SYinghai Lu return 0; 237aaf23042SYinghai Lu } 238aaf23042SYinghai Lu early_param("gart_fix_e820", parse_gart_mem); 239aaf23042SYinghai Lu 240aaf23042SYinghai Lu void __init early_gart_iommu_check(void) 241aaf23042SYinghai Lu { 242aaf23042SYinghai Lu /* 243aaf23042SYinghai Lu * in case it is enabled before, esp for kexec/kdump, 244aaf23042SYinghai Lu * previous kernel already enable that. memset called 245aaf23042SYinghai Lu * by allocate_aperture/__alloc_bootmem_nopanic cause restart. 246aaf23042SYinghai Lu * or second kernel have different position for GART hole. and new 247aaf23042SYinghai Lu * kernel could use hole as RAM that is still used by GART set by 248aaf23042SYinghai Lu * first kernel 249aaf23042SYinghai Lu * or BIOS forget to put that in reserved. 250aaf23042SYinghai Lu * try to update e820 to make that region as reserved. 251aaf23042SYinghai Lu */ 252aaf23042SYinghai Lu int fix, num; 253aaf23042SYinghai Lu u32 ctl; 254aaf23042SYinghai Lu u32 aper_size = 0, aper_order = 0, last_aper_order = 0; 255aaf23042SYinghai Lu u64 aper_base = 0, last_aper_base = 0; 256aaf23042SYinghai Lu int aper_enabled = 0, last_aper_enabled = 0; 257aaf23042SYinghai Lu 258aaf23042SYinghai Lu if (!early_pci_allowed()) 259aaf23042SYinghai Lu return; 260aaf23042SYinghai Lu 261aaf23042SYinghai Lu fix = 0; 262aaf23042SYinghai Lu for (num = 24; num < 32; num++) { 263aaf23042SYinghai Lu if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) 264aaf23042SYinghai Lu continue; 265aaf23042SYinghai Lu 266aaf23042SYinghai Lu ctl = read_pci_config(0, num, 3, 0x90); 267aaf23042SYinghai Lu aper_enabled = ctl & 1; 268aaf23042SYinghai Lu aper_order = (ctl >> 1) & 7; 269aaf23042SYinghai Lu aper_size = (32 * 1024 * 1024) << aper_order; 270aaf23042SYinghai Lu aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; 271aaf23042SYinghai Lu aper_base <<= 25; 272aaf23042SYinghai Lu 273aaf23042SYinghai Lu if ((last_aper_order && aper_order != last_aper_order) || 274aaf23042SYinghai Lu (last_aper_base && aper_base != last_aper_base) || 275aaf23042SYinghai Lu (last_aper_enabled && aper_enabled != last_aper_enabled)) { 276aaf23042SYinghai Lu fix = 1; 277aaf23042SYinghai Lu break; 278aaf23042SYinghai Lu } 279aaf23042SYinghai Lu last_aper_order = aper_order; 280aaf23042SYinghai Lu last_aper_base = aper_base; 281aaf23042SYinghai Lu last_aper_enabled = aper_enabled; 282aaf23042SYinghai Lu } 283aaf23042SYinghai Lu 284aaf23042SYinghai Lu if (!fix && !aper_enabled) 285aaf23042SYinghai Lu return; 286aaf23042SYinghai Lu 287aaf23042SYinghai Lu if (!aper_base || !aper_size || aper_base + aper_size > 0x100000000UL) 288aaf23042SYinghai Lu fix = 1; 289aaf23042SYinghai Lu 290aaf23042SYinghai Lu if (gart_fix_e820 && !fix && aper_enabled) { 291aaf23042SYinghai Lu if (e820_any_mapped(aper_base, aper_base + aper_size, 292aaf23042SYinghai Lu E820_RAM)) { 293aaf23042SYinghai Lu /* reserved it, so we can resuse it in second kernel */ 294aaf23042SYinghai Lu printk(KERN_INFO "update e820 for GART\n"); 295aaf23042SYinghai Lu add_memory_region(aper_base, aper_size, E820_RESERVED); 296aaf23042SYinghai Lu update_e820(); 297aaf23042SYinghai Lu } 298aaf23042SYinghai Lu return; 299aaf23042SYinghai Lu } 300aaf23042SYinghai Lu 301aaf23042SYinghai Lu /* different nodes have different setting, disable them all at first*/ 302aaf23042SYinghai Lu for (num = 24; num < 32; num++) { 303aaf23042SYinghai Lu if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) 304aaf23042SYinghai Lu continue; 305aaf23042SYinghai Lu 306aaf23042SYinghai Lu ctl = read_pci_config(0, num, 3, 0x90); 307aaf23042SYinghai Lu ctl &= ~1; 308aaf23042SYinghai Lu write_pci_config(0, num, 3, 0x90, ctl); 309aaf23042SYinghai Lu } 310aaf23042SYinghai Lu 311aaf23042SYinghai Lu } 312aaf23042SYinghai Lu 3130440d4c0SJoerg Roedel void __init gart_iommu_hole_init(void) 314250c2277SThomas Gleixner { 315250c2277SThomas Gleixner u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; 316250c2277SThomas Gleixner u64 aper_base, last_aper_base = 0; 317c140df97SIngo Molnar int fix, num, valid_agp = 0; 31847db4c3eSYinghai Lu int node; 319250c2277SThomas Gleixner 3200440d4c0SJoerg Roedel if (gart_iommu_aperture_disabled || !fix_aperture || 3210440d4c0SJoerg Roedel !early_pci_allowed()) 322250c2277SThomas Gleixner return; 323250c2277SThomas Gleixner 324250c2277SThomas Gleixner printk(KERN_INFO "Checking aperture...\n"); 325250c2277SThomas Gleixner 326250c2277SThomas Gleixner fix = 0; 32747db4c3eSYinghai Lu node = 0; 328250c2277SThomas Gleixner for (num = 24; num < 32; num++) { 329250c2277SThomas Gleixner if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) 330250c2277SThomas Gleixner continue; 331250c2277SThomas Gleixner 332250c2277SThomas Gleixner iommu_detected = 1; 3330440d4c0SJoerg Roedel gart_iommu_aperture = 1; 334250c2277SThomas Gleixner 335250c2277SThomas Gleixner aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; 336250c2277SThomas Gleixner aper_size = (32 * 1024 * 1024) << aper_order; 337250c2277SThomas Gleixner aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; 338250c2277SThomas Gleixner aper_base <<= 25; 339250c2277SThomas Gleixner 34047db4c3eSYinghai Lu printk(KERN_INFO "Node %d: aperture @ %Lx size %u MB\n", 34147db4c3eSYinghai Lu node, aper_base, aper_size >> 20); 34247db4c3eSYinghai Lu node++; 343250c2277SThomas Gleixner 344250c2277SThomas Gleixner if (!aperture_valid(aper_base, aper_size)) { 345250c2277SThomas Gleixner fix = 1; 346250c2277SThomas Gleixner break; 347250c2277SThomas Gleixner } 348250c2277SThomas Gleixner 349250c2277SThomas Gleixner if ((last_aper_order && aper_order != last_aper_order) || 350250c2277SThomas Gleixner (last_aper_base && aper_base != last_aper_base)) { 351250c2277SThomas Gleixner fix = 1; 352250c2277SThomas Gleixner break; 353250c2277SThomas Gleixner } 354250c2277SThomas Gleixner last_aper_order = aper_order; 355250c2277SThomas Gleixner last_aper_base = aper_base; 356250c2277SThomas Gleixner } 357250c2277SThomas Gleixner 358250c2277SThomas Gleixner if (!fix && !fallback_aper_force) { 359250c2277SThomas Gleixner if (last_aper_base) { 360250c2277SThomas Gleixner unsigned long n = (32 * 1024 * 1024) << last_aper_order; 361c140df97SIngo Molnar 362250c2277SThomas Gleixner insert_aperture_resource((u32)last_aper_base, n); 363250c2277SThomas Gleixner } 364250c2277SThomas Gleixner return; 365250c2277SThomas Gleixner } 366250c2277SThomas Gleixner 367250c2277SThomas Gleixner if (!fallback_aper_force) 368250c2277SThomas Gleixner aper_alloc = search_agp_bridge(&aper_order, &valid_agp); 369250c2277SThomas Gleixner 370250c2277SThomas Gleixner if (aper_alloc) { 371250c2277SThomas Gleixner /* Got the aperture from the AGP bridge */ 372250c2277SThomas Gleixner } else if (swiotlb && !valid_agp) { 373250c2277SThomas Gleixner /* Do nothing */ 374250c2277SThomas Gleixner } else if ((!no_iommu && end_pfn > MAX_DMA32_PFN) || 375250c2277SThomas Gleixner force_iommu || 376250c2277SThomas Gleixner valid_agp || 377250c2277SThomas Gleixner fallback_aper_force) { 37831183ba8SIngo Molnar printk(KERN_ERR 37931183ba8SIngo Molnar "Your BIOS doesn't leave a aperture memory hole\n"); 38031183ba8SIngo Molnar printk(KERN_ERR 38131183ba8SIngo Molnar "Please enable the IOMMU option in the BIOS setup\n"); 38231183ba8SIngo Molnar printk(KERN_ERR 38331183ba8SIngo Molnar "This costs you %d MB of RAM\n", 384250c2277SThomas Gleixner 32 << fallback_aper_order); 385250c2277SThomas Gleixner 386250c2277SThomas Gleixner aper_order = fallback_aper_order; 387250c2277SThomas Gleixner aper_alloc = allocate_aperture(); 388250c2277SThomas Gleixner if (!aper_alloc) { 389c140df97SIngo Molnar /* 390c140df97SIngo Molnar * Could disable AGP and IOMMU here, but it's 391c140df97SIngo Molnar * probably not worth it. But the later users 392c140df97SIngo Molnar * cannot deal with bad apertures and turning 393c140df97SIngo Molnar * on the aperture over memory causes very 394c140df97SIngo Molnar * strange problems, so it's better to panic 395c140df97SIngo Molnar * early. 396c140df97SIngo Molnar */ 397250c2277SThomas Gleixner panic("Not enough memory for aperture"); 398250c2277SThomas Gleixner } 399250c2277SThomas Gleixner } else { 400250c2277SThomas Gleixner return; 401250c2277SThomas Gleixner } 402250c2277SThomas Gleixner 403250c2277SThomas Gleixner /* Fix up the north bridges */ 404250c2277SThomas Gleixner for (num = 24; num < 32; num++) { 405250c2277SThomas Gleixner if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) 406250c2277SThomas Gleixner continue; 407250c2277SThomas Gleixner 408c140df97SIngo Molnar /* 409c140df97SIngo Molnar * Don't enable translation yet. That is done later. 410c140df97SIngo Molnar * Assume this BIOS didn't initialise the GART so 411c140df97SIngo Molnar * just overwrite all previous bits 412c140df97SIngo Molnar */ 413250c2277SThomas Gleixner write_pci_config(0, num, 3, 0x90, aper_order<<1); 414250c2277SThomas Gleixner write_pci_config(0, num, 3, 0x94, aper_alloc>>25); 415250c2277SThomas Gleixner } 416250c2277SThomas Gleixner } 417