[PATCH] x86_64: trivial gart clean-up
[deliverable/linux.git] / arch / x86_64 / kernel / aperture.c
CommitLineData
1da177e4
LT
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 $
12 */
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>
ca8642f6 26#include <asm/dma.h>
1da177e4
LT
27
28int iommu_aperture;
29int iommu_aperture_disabled __initdata = 0;
30int iommu_aperture_allowed __initdata = 0;
31
32int fallback_aper_order __initdata = 1; /* 64MB */
33int fallback_aper_force __initdata = 0;
34
35int fix_aperture __initdata = 1;
36
42442ed5
AM
37/* This code runs before the PCI subsystem is initialized, so just
38 access the northbridge directly. */
1da177e4 39
42442ed5 40#define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
ece90303 41
1da177e4
LT
42static u32 __init allocate_aperture(void)
43{
1da177e4 44 pg_data_t *nd0 = NODE_DATA(0);
1da177e4
LT
45 u32 aper_size;
46 void *p;
47
48 if (fallback_aper_order > 7)
49 fallback_aper_order = 7;
50 aper_size = (32 * 1024 * 1024) << fallback_aper_order;
51
52 /*
42442ed5
AM
53 * Aperture has to be naturally aligned. This means an 2GB aperture won't
54 * have much chances to find a place in the lower 4GB of memory.
55 * Unfortunately we cannot move it up because that would make the
56 * IOMMU useless.
1da177e4
LT
57 */
58 p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0);
59 if (!p || __pa(p)+aper_size > 0xffffffff) {
60 printk("Cannot allocate aperture memory hole (%p,%uK)\n",
61 p, aper_size>>10);
62 if (p)
c912c2db 63 free_bootmem_node(nd0, __pa(p), aper_size);
1da177e4
LT
64 return 0;
65 }
42442ed5 66 printk("Mapping aperture over %d KB of RAM @ %lx\n",
1da177e4
LT
67 aper_size >> 10, __pa(p));
68 return (u32)__pa(p);
69}
70
71static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size)
72{
73 if (!aper_base)
74 return 0;
75 if (aper_size < 64*1024*1024) {
76 printk("Aperture from %s too small (%d MB)\n", name, aper_size>>20);
77 return 0;
78 }
79 if (aper_base + aper_size >= 0xffffffff) {
80 printk("Aperture from %s beyond 4GB. Ignoring.\n",name);
81 return 0;
82 }
eee5a9fa 83 if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
1da177e4
LT
84 printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
85 return 0;
86 }
87 return 1;
88}
89
42442ed5 90/* Find a PCI capability */
1da177e4
LT
91static __u32 __init find_cap(int num, int slot, int func, int cap)
92{
93 u8 pos;
94 int bytes;
95 if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
96 return 0;
97 pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
98 for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
99 u8 id;
100 pos &= ~3;
101 id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
102 if (id == 0xff)
103 break;
104 if (id == cap)
105 return pos;
106 pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
107 }
108 return 0;
109}
110
111/* Read a standard AGPv3 bridge header */
112static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
113{
114 u32 apsize;
115 u32 apsizereg;
116 int nbits;
117 u32 aper_low, aper_hi;
118 u64 aper;
119
120 printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func);
121 apsizereg = read_pci_config_16(num,slot,func, cap + 0x14);
122 if (apsizereg == 0xffffffff) {
123 printk("APSIZE in AGP bridge unreadable\n");
124 return 0;
125 }
126
127 apsize = apsizereg & 0xfff;
128 /* Some BIOS use weird encodings not in the AGPv3 table. */
129 if (apsize & 0xff)
130 apsize |= 0xf00;
131 nbits = hweight16(apsize);
132 *order = 7 - nbits;
133 if ((int)*order < 0) /* < 32MB */
134 *order = 0;
135
136 aper_low = read_pci_config(num,slot,func, 0x10);
137 aper_hi = read_pci_config(num,slot,func,0x14);
138 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
139
140 printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
141 aper, 32 << *order, apsizereg);
142
143 if (!aperture_valid("AGP bridge", aper, (32*1024*1024) << *order))
144 return 0;
145 return (u32)aper;
146}
147
148/* Look for an AGP bridge. Windows only expects the aperture in the
149 AGP bridge and some BIOS forget to initialize the Northbridge too.
150 Work around this here.
151
152 Do an PCI bus scan by hand because we're running before the PCI
153 subsystem.
154
155 All K8 AGP bridges are AGPv3 compliant, so we can do this scan
156 generically. It's probably overkill to always scan all slots because
157 the AGP bridges should be always an own bus on the HT hierarchy,
158 but do it here for future safety. */
159static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
160{
161 int num, slot, func;
162
163 /* Poor man's PCI discovery */
9c01dda0 164 for (num = 0; num < 256; num++) {
1da177e4
LT
165 for (slot = 0; slot < 32; slot++) {
166 for (func = 0; func < 8; func++) {
167 u32 class, cap;
168 u8 type;
169 class = read_pci_config(num,slot,func,
170 PCI_CLASS_REVISION);
171 if (class == 0xffffffff)
172 break;
173
174 switch (class >> 16) {
175 case PCI_CLASS_BRIDGE_HOST:
176 case PCI_CLASS_BRIDGE_OTHER: /* needed? */
177 /* AGP bridge? */
178 cap = find_cap(num,slot,func,PCI_CAP_ID_AGP);
179 if (!cap)
180 break;
181 *valid_agp = 1;
182 return read_agp(num,slot,func,cap,order);
183 }
184
185 /* No multi-function device? */
186 type = read_pci_config_byte(num,slot,func,
187 PCI_HEADER_TYPE);
188 if (!(type & 0x80))
189 break;
190 }
191 }
192 }
193 printk("No AGP bridge found\n");
194 return 0;
195}
196
197void __init iommu_hole_init(void)
198{
199 int fix, num;
50895c5d 200 u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
1da177e4
LT
201 u64 aper_base, last_aper_base = 0;
202 int valid_agp = 0;
203
204 if (iommu_aperture_disabled || !fix_aperture)
205 return;
206
207 printk("Checking aperture...\n");
208
209 fix = 0;
210 for (num = 24; num < 32; num++) {
211 char name[30];
212 if (read_pci_config(0, num, 3, 0x00) != NB_ID_3)
213 continue;
214
215 iommu_aperture = 1;
216
217 aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7;
218 aper_size = (32 * 1024 * 1024) << aper_order;
219 aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
220 aper_base <<= 25;
221
222 printk("CPU %d: aperture @ %Lx size %u MB\n", num-24,
223 aper_base, aper_size>>20);
224
225 sprintf(name, "northbridge cpu %d", num-24);
226
227 if (!aperture_valid(name, aper_base, aper_size)) {
228 fix = 1;
229 break;
230 }
231
232 if ((last_aper_order && aper_order != last_aper_order) ||
233 (last_aper_base && aper_base != last_aper_base)) {
234 fix = 1;
235 break;
236 }
237 last_aper_order = aper_order;
238 last_aper_base = aper_base;
239 }
240
241 if (!fix && !fallback_aper_force)
242 return;
243
244 if (!fallback_aper_force)
245 aper_alloc = search_agp_bridge(&aper_order, &valid_agp);
246
247 if (aper_alloc) {
248 /* Got the aperture from the AGP bridge */
63f02fd7
AK
249 } else if (swiotlb && !valid_agp) {
250 /* Do nothing */
60b08c67 251 } else if ((!no_iommu && end_pfn > MAX_DMA32_PFN) ||
1da177e4
LT
252 force_iommu ||
253 valid_agp ||
254 fallback_aper_force) {
255 printk("Your BIOS doesn't leave a aperture memory hole\n");
256 printk("Please enable the IOMMU option in the BIOS setup\n");
42442ed5
AM
257 printk("This costs you %d MB of RAM\n",
258 32 << fallback_aper_order);
1da177e4
LT
259
260 aper_order = fallback_aper_order;
261 aper_alloc = allocate_aperture();
262 if (!aper_alloc) {
263 /* Could disable AGP and IOMMU here, but it's probably
264 not worth it. But the later users cannot deal with
265 bad apertures and turning on the aperture over memory
266 causes very strange problems, so it's better to
267 panic early. */
268 panic("Not enough memory for aperture");
269 }
270 } else {
271 return;
272 }
273
274 /* Fix up the north bridges */
275 for (num = 24; num < 32; num++) {
276 if (read_pci_config(0, num, 3, 0x00) != NB_ID_3)
277 continue;
278
279 /* Don't enable translation yet. That is done later.
280 Assume this BIOS didn't initialise the GART so
281 just overwrite all previous bits */
282 write_pci_config(0, num, 3, 0x90, aper_order<<1);
283 write_pci_config(0, num, 3, 0x94, aper_alloc>>25);
284 }
285}
This page took 0.134356 seconds and 5 git commands to generate.