diff options
author | Andi Kleen <ak@suse.de> | 2006-06-26 07:56:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 13:48:15 -0400 |
commit | a32073bffc656ca4bde6002b6cf7c1a8e0e22712 (patch) | |
tree | 5ddcd3107eca8807685a19490c2c849d728a51a6 /drivers | |
parent | 7c2d9cd218916276e52a5dae827b84a159fe5c96 (diff) |
[PATCH] x86_64: Clean and enhance up K8 northbridge access code
- Factor out the duplicated access/cache code into a single file
* Shared between i386/x86-64.
- Share flush code between AGP and IOMMU
* Fix a bug: AGP didn't wait for end of flush before
- Drop 8 northbridges limit and allocate dynamically
- Add lock to serialize AGP and IOMMU GART flushes
- Add PCI ID for next AMD northbridge
- Random related cleanups
The old K8 NUMA discovery code is unchanged. New systems
should all use SRAT for this.
Cc: "Navin Boppuri" <navin.boppuri@newisys.com>
Cc: Dave Jones <davej@redhat.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/agp/amd64-agp.c | 77 |
1 files changed, 25 insertions, 52 deletions
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index ac3c33a2e37d..229d015757f9 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -15,11 +15,9 @@ | |||
15 | #include <linux/agp_backend.h> | 15 | #include <linux/agp_backend.h> |
16 | #include <linux/mmzone.h> | 16 | #include <linux/mmzone.h> |
17 | #include <asm/page.h> /* PAGE_SIZE */ | 17 | #include <asm/page.h> /* PAGE_SIZE */ |
18 | #include <asm/k8.h> | ||
18 | #include "agp.h" | 19 | #include "agp.h" |
19 | 20 | ||
20 | /* Will need to be increased if AMD64 ever goes >8-way. */ | ||
21 | #define MAX_HAMMER_GARTS 8 | ||
22 | |||
23 | /* PTE bits. */ | 21 | /* PTE bits. */ |
24 | #define GPTE_VALID 1 | 22 | #define GPTE_VALID 1 |
25 | #define GPTE_COHERENT 2 | 23 | #define GPTE_COHERENT 2 |
@@ -53,28 +51,12 @@ | |||
53 | #define ULI_X86_64_HTT_FEA_REG 0x50 | 51 | #define ULI_X86_64_HTT_FEA_REG 0x50 |
54 | #define ULI_X86_64_ENU_SCR_REG 0x54 | 52 | #define ULI_X86_64_ENU_SCR_REG 0x54 |
55 | 53 | ||
56 | static int nr_garts; | ||
57 | static struct pci_dev * hammers[MAX_HAMMER_GARTS]; | ||
58 | |||
59 | static struct resource *aperture_resource; | 54 | static struct resource *aperture_resource; |
60 | static int __initdata agp_try_unsupported = 1; | 55 | static int __initdata agp_try_unsupported = 1; |
61 | 56 | ||
62 | #define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++) | ||
63 | |||
64 | static void flush_amd64_tlb(struct pci_dev *dev) | ||
65 | { | ||
66 | u32 tmp; | ||
67 | |||
68 | pci_read_config_dword (dev, AMD64_GARTCACHECTL, &tmp); | ||
69 | tmp |= INVGART; | ||
70 | pci_write_config_dword (dev, AMD64_GARTCACHECTL, tmp); | ||
71 | } | ||
72 | |||
73 | static void amd64_tlbflush(struct agp_memory *temp) | 57 | static void amd64_tlbflush(struct agp_memory *temp) |
74 | { | 58 | { |
75 | int gart_iterator; | 59 | k8_flush_garts(); |
76 | for_each_nb() | ||
77 | flush_amd64_tlb(hammers[gart_iterator]); | ||
78 | } | 60 | } |
79 | 61 | ||
80 | static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) | 62 | static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) |
@@ -153,7 +135,7 @@ static int amd64_fetch_size(void) | |||
153 | u32 temp; | 135 | u32 temp; |
154 | struct aper_size_info_32 *values; | 136 | struct aper_size_info_32 *values; |
155 | 137 | ||
156 | dev = hammers[0]; | 138 | dev = k8_northbridges[0]; |
157 | if (dev==NULL) | 139 | if (dev==NULL) |
158 | return 0; | 140 | return 0; |
159 | 141 | ||
@@ -201,9 +183,6 @@ static u64 amd64_configure (struct pci_dev *hammer, u64 gatt_table) | |||
201 | tmp &= ~(DISGARTCPU | DISGARTIO); | 183 | tmp &= ~(DISGARTCPU | DISGARTIO); |
202 | pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp); | 184 | pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp); |
203 | 185 | ||
204 | /* keep CPU's coherent. */ | ||
205 | flush_amd64_tlb (hammer); | ||
206 | |||
207 | return aper_base; | 186 | return aper_base; |
208 | } | 187 | } |
209 | 188 | ||
@@ -222,13 +201,14 @@ static struct aper_size_info_32 amd_8151_sizes[7] = | |||
222 | static int amd_8151_configure(void) | 201 | static int amd_8151_configure(void) |
223 | { | 202 | { |
224 | unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); | 203 | unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); |
225 | int gart_iterator; | 204 | int i; |
226 | 205 | ||
227 | /* Configure AGP regs in each x86-64 host bridge. */ | 206 | /* Configure AGP regs in each x86-64 host bridge. */ |
228 | for_each_nb() { | 207 | for (i = 0; i < num_k8_northbridges; i++) { |
229 | agp_bridge->gart_bus_addr = | 208 | agp_bridge->gart_bus_addr = |
230 | amd64_configure(hammers[gart_iterator],gatt_bus); | 209 | amd64_configure(k8_northbridges[i], gatt_bus); |
231 | } | 210 | } |
211 | k8_flush_garts(); | ||
232 | return 0; | 212 | return 0; |
233 | } | 213 | } |
234 | 214 | ||
@@ -236,12 +216,13 @@ static int amd_8151_configure(void) | |||
236 | static void amd64_cleanup(void) | 216 | static void amd64_cleanup(void) |
237 | { | 217 | { |
238 | u32 tmp; | 218 | u32 tmp; |
239 | int gart_iterator; | 219 | int i; |
240 | for_each_nb() { | 220 | for (i = 0; i < num_k8_northbridges; i++) { |
221 | struct pci_dev *dev = k8_northbridges[i]; | ||
241 | /* disable gart translation */ | 222 | /* disable gart translation */ |
242 | pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp); | 223 | pci_read_config_dword (dev, AMD64_GARTAPERTURECTL, &tmp); |
243 | tmp &= ~AMD64_GARTEN; | 224 | tmp &= ~AMD64_GARTEN; |
244 | pci_write_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, tmp); | 225 | pci_write_config_dword (dev, AMD64_GARTAPERTURECTL, tmp); |
245 | } | 226 | } |
246 | } | 227 | } |
247 | 228 | ||
@@ -361,17 +342,15 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, | |||
361 | 342 | ||
362 | static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) | 343 | static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) |
363 | { | 344 | { |
364 | struct pci_dev *loop_dev = NULL; | 345 | int i; |
365 | int i = 0; | 346 | |
366 | 347 | if (cache_k8_northbridges() < 0) | |
367 | /* cache pci_devs of northbridges. */ | 348 | return -ENODEV; |
368 | while ((loop_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) | 349 | |
369 | != NULL) { | 350 | i = 0; |
370 | if (i == MAX_HAMMER_GARTS) { | 351 | for (i = 0; i < num_k8_northbridges; i++) { |
371 | printk(KERN_ERR PFX "Too many northbridges for AGP\n"); | 352 | struct pci_dev *dev = k8_northbridges[i]; |
372 | return -1; | 353 | if (fix_northbridge(dev, pdev, cap_ptr) < 0) { |
373 | } | ||
374 | if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { | ||
375 | printk(KERN_ERR PFX "No usable aperture found.\n"); | 354 | printk(KERN_ERR PFX "No usable aperture found.\n"); |
376 | #ifdef __x86_64__ | 355 | #ifdef __x86_64__ |
377 | /* should port this to i386 */ | 356 | /* should port this to i386 */ |
@@ -379,10 +358,8 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) | |||
379 | #endif | 358 | #endif |
380 | return -1; | 359 | return -1; |
381 | } | 360 | } |
382 | hammers[i++] = loop_dev; | ||
383 | } | 361 | } |
384 | nr_garts = i; | 362 | return 0; |
385 | return i == 0 ? -1 : 0; | ||
386 | } | 363 | } |
387 | 364 | ||
388 | /* Handle AMD 8151 quirks */ | 365 | /* Handle AMD 8151 quirks */ |
@@ -450,7 +427,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
450 | } | 427 | } |
451 | 428 | ||
452 | /* shadow x86-64 registers into ULi registers */ | 429 | /* shadow x86-64 registers into ULi registers */ |
453 | pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &httfea); | 430 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea); |
454 | 431 | ||
455 | /* if x86-64 aperture base is beyond 4G, exit here */ | 432 | /* if x86-64 aperture base is beyond 4G, exit here */ |
456 | if ((httfea & 0x7fff) >> (32 - 25)) | 433 | if ((httfea & 0x7fff) >> (32 - 25)) |
@@ -513,7 +490,7 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev) | |||
513 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); | 490 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); |
514 | 491 | ||
515 | /* shadow x86-64 registers into NVIDIA registers */ | 492 | /* shadow x86-64 registers into NVIDIA registers */ |
516 | pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase); | 493 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase); |
517 | 494 | ||
518 | /* if x86-64 aperture base is beyond 4G, exit here */ | 495 | /* if x86-64 aperture base is beyond 4G, exit here */ |
519 | if ( (apbase & 0x7fff) >> (32 - 25) ) { | 496 | if ( (apbase & 0x7fff) >> (32 - 25) ) { |
@@ -754,10 +731,6 @@ static struct pci_driver agp_amd64_pci_driver = { | |||
754 | int __init agp_amd64_init(void) | 731 | int __init agp_amd64_init(void) |
755 | { | 732 | { |
756 | int err = 0; | 733 | int err = 0; |
757 | static struct pci_device_id amd64nb[] = { | ||
758 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, | ||
759 | { }, | ||
760 | }; | ||
761 | 734 | ||
762 | if (agp_off) | 735 | if (agp_off) |
763 | return -EINVAL; | 736 | return -EINVAL; |
@@ -774,7 +747,7 @@ int __init agp_amd64_init(void) | |||
774 | } | 747 | } |
775 | 748 | ||
776 | /* First check that we have at least one AMD64 NB */ | 749 | /* First check that we have at least one AMD64 NB */ |
777 | if (!pci_dev_present(amd64nb)) | 750 | if (!pci_dev_present(k8_nb_ids)) |
778 | return -ENODEV; | 751 | return -ENODEV; |
779 | 752 | ||
780 | /* Look for any AGP bridge */ | 753 | /* Look for any AGP bridge */ |