[PATCH] Avoid console spam with ext3 aborted journal.
[linux-2.6/verdex.git] / arch / x86_64 / kernel / aperture.c
bloba491f72cc96663a79bf26a5e8f642cbab55dac26
1 /*
2 * Firmware replacement code.
3 *
4 * Work around broken BIOSes that don't set an aperture or only set the
5 * aperture in the AGP bridge.
6 * If all fails map the aperture over some low memory. This is cheaper than
7 * doing bounce buffering. The memory is lost. This is done at early boot
8 * because only the bootmem allocator can allocate 32+MB.
9 *
10 * Copyright 2002 Andi Kleen, SuSE Labs.
11 * $Id: aperture.c,v 1.7 2003/08/01 03:36:18 ak Exp $
13 #include <linux/config.h>
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <linux/init.h>
17 #include <linux/bootmem.h>
18 #include <linux/mmzone.h>
19 #include <linux/pci_ids.h>
20 #include <linux/pci.h>
21 #include <linux/bitops.h>
22 #include <asm/e820.h>
23 #include <asm/io.h>
24 #include <asm/proto.h>
25 #include <asm/pci-direct.h>
27 int iommu_aperture;
28 int iommu_aperture_disabled __initdata = 0;
29 int iommu_aperture_allowed __initdata = 0;
31 int fallback_aper_order __initdata = 1; /* 64MB */
32 int fallback_aper_force __initdata = 0;
34 int fix_aperture __initdata = 1;
36 #define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
38 static struct resource aper_res = {
39 .name = "Aperture",
40 .flags = IORESOURCE_MEM,
43 static u32 __init allocate_aperture(void)
45 #ifdef CONFIG_DISCONTIGMEM
46 pg_data_t *nd0 = NODE_DATA(0);
47 #else
48 pg_data_t *nd0 = &contig_page_data;
49 #endif
50 u32 aper_size;
51 void *p;
53 if (fallback_aper_order > 7)
54 fallback_aper_order = 7;
55 aper_size = (32 * 1024 * 1024) << fallback_aper_order;
57 /*
58 * Aperture has to be naturally aligned. This means an 2GB
59 * aperture won't have much chances to find a place in the
60 * lower 4GB of memory. Unfortunately we cannot move it up
61 * because that would make the IOMMU useless.
64 /* First try to find some free unused space */
65 if (!allocate_resource(&iomem_resource, &aper_res,
66 aper_size,
67 0, 0xffffffff,
68 aper_size,
69 NULL, NULL)) {
70 printk(KERN_INFO "Putting aperture at %lx-%lx\n",
71 aper_res.start, aper_res.end);
72 return aper_res.start;
75 /* No free space found. Go on to waste some memory... */
76 p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0);
77 if (!p || __pa(p)+aper_size > 0xffffffff) {
78 printk("Cannot allocate aperture memory hole (%p,%uK)\n",
79 p, aper_size>>10);
80 if (p)
81 free_bootmem_node(nd0, (unsigned long)p, aper_size);
82 return 0;
84 printk("Mapping aperture over %d KB of precious RAM @ %lx\n",
85 aper_size >> 10, __pa(p));
86 return (u32)__pa(p);
89 static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size)
91 if (!aper_base)
92 return 0;
93 if (aper_size < 64*1024*1024) {
94 printk("Aperture from %s too small (%d MB)\n", name, aper_size>>20);
95 return 0;
97 if (aper_base + aper_size >= 0xffffffff) {
98 printk("Aperture from %s beyond 4GB. Ignoring.\n",name);
99 return 0;
101 if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
102 printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
103 return 0;
105 /* Don't check the resource here because the aperture is usually
106 in an e820 reserved area, and we allocated these earlier. */
107 return 1;
111 * Find a PCI capability.
112 * This code runs before the PCI subsystem is initialized, so just
113 * access the northbridge directly.
115 static __u32 __init find_cap(int num, int slot, int func, int cap)
117 u8 pos;
118 int bytes;
119 if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
120 return 0;
121 pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
122 for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
123 u8 id;
124 pos &= ~3;
125 id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
126 if (id == 0xff)
127 break;
128 if (id == cap)
129 return pos;
130 pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
132 return 0;
135 /* Read a standard AGPv3 bridge header */
136 static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
138 u32 apsize;
139 u32 apsizereg;
140 int nbits;
141 u32 aper_low, aper_hi;
142 u64 aper;
144 printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func);
145 apsizereg = read_pci_config_16(num,slot,func, cap + 0x14);
146 if (apsizereg == 0xffffffff) {
147 printk("APSIZE in AGP bridge unreadable\n");
148 return 0;
151 apsize = apsizereg & 0xfff;
152 /* Some BIOS use weird encodings not in the AGPv3 table. */
153 if (apsize & 0xff)
154 apsize |= 0xf00;
155 nbits = hweight16(apsize);
156 *order = 7 - nbits;
157 if ((int)*order < 0) /* < 32MB */
158 *order = 0;
160 aper_low = read_pci_config(num,slot,func, 0x10);
161 aper_hi = read_pci_config(num,slot,func,0x14);
162 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
164 printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
165 aper, 32 << *order, apsizereg);
167 if (!aperture_valid("AGP bridge", aper, (32*1024*1024) << *order))
168 return 0;
169 return (u32)aper;
172 /* Look for an AGP bridge. Windows only expects the aperture in the
173 AGP bridge and some BIOS forget to initialize the Northbridge too.
174 Work around this here.
176 Do an PCI bus scan by hand because we're running before the PCI
177 subsystem.
179 All K8 AGP bridges are AGPv3 compliant, so we can do this scan
180 generically. It's probably overkill to always scan all slots because
181 the AGP bridges should be always an own bus on the HT hierarchy,
182 but do it here for future safety. */
183 static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
185 int num, slot, func;
187 /* Poor man's PCI discovery */
188 for (num = 0; num < 32; num++) {
189 for (slot = 0; slot < 32; slot++) {
190 for (func = 0; func < 8; func++) {
191 u32 class, cap;
192 u8 type;
193 class = read_pci_config(num,slot,func,
194 PCI_CLASS_REVISION);
195 if (class == 0xffffffff)
196 break;
198 switch (class >> 16) {
199 case PCI_CLASS_BRIDGE_HOST:
200 case PCI_CLASS_BRIDGE_OTHER: /* needed? */
201 /* AGP bridge? */
202 cap = find_cap(num,slot,func,PCI_CAP_ID_AGP);
203 if (!cap)
204 break;
205 *valid_agp = 1;
206 return read_agp(num,slot,func,cap,order);
209 /* No multi-function device? */
210 type = read_pci_config_byte(num,slot,func,
211 PCI_HEADER_TYPE);
212 if (!(type & 0x80))
213 break;
217 printk("No AGP bridge found\n");
218 return 0;
221 void __init iommu_hole_init(void)
223 int fix, num;
224 u32 aper_size, aper_alloc = 0, aper_order, last_aper_order = 0;
225 u64 aper_base, last_aper_base = 0;
226 int valid_agp = 0;
228 if (iommu_aperture_disabled || !fix_aperture)
229 return;
231 printk("Checking aperture...\n");
233 fix = 0;
234 for (num = 24; num < 32; num++) {
235 char name[30];
236 if (read_pci_config(0, num, 3, 0x00) != NB_ID_3)
237 continue;
239 iommu_aperture = 1;
241 aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7;
242 aper_size = (32 * 1024 * 1024) << aper_order;
243 aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
244 aper_base <<= 25;
246 printk("CPU %d: aperture @ %Lx size %u MB\n", num-24,
247 aper_base, aper_size>>20);
249 sprintf(name, "northbridge cpu %d", num-24);
251 if (!aperture_valid(name, aper_base, aper_size)) {
252 fix = 1;
253 break;
256 if ((last_aper_order && aper_order != last_aper_order) ||
257 (last_aper_base && aper_base != last_aper_base)) {
258 fix = 1;
259 break;
261 last_aper_order = aper_order;
262 last_aper_base = aper_base;
265 if (!fix && !fallback_aper_force)
266 return;
268 if (!fallback_aper_force)
269 aper_alloc = search_agp_bridge(&aper_order, &valid_agp);
271 if (aper_alloc) {
272 /* Got the aperture from the AGP bridge */
273 } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
274 force_iommu ||
275 valid_agp ||
276 fallback_aper_force) {
277 printk("Your BIOS doesn't leave a aperture memory hole\n");
278 printk("Please enable the IOMMU option in the BIOS setup\n");
280 aper_order = fallback_aper_order;
281 aper_alloc = allocate_aperture();
282 if (!aper_alloc) {
283 /* Could disable AGP and IOMMU here, but it's probably
284 not worth it. But the later users cannot deal with
285 bad apertures and turning on the aperture over memory
286 causes very strange problems, so it's better to
287 panic early. */
288 panic("Not enough memory for aperture");
290 } else {
291 return;
294 /* Fix up the north bridges */
295 for (num = 24; num < 32; num++) {
296 if (read_pci_config(0, num, 3, 0x00) != NB_ID_3)
297 continue;
299 /* Don't enable translation yet. That is done later.
300 Assume this BIOS didn't initialise the GART so
301 just overwrite all previous bits */
302 write_pci_config(0, num, 3, 0x90, aper_order<<1);
303 write_pci_config(0, num, 3, 0x94, aper_alloc>>25);