diff options
-rw-r--r-- | arch/x86/include/asm/k8.h | 13 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/k8.c | 52 | ||||
-rw-r--r-- | arch/x86/kernel/pci-gart_64.c | 27 | ||||
-rw-r--r-- | drivers/char/agp/amd64-agp.c | 33 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.c | 2 |
6 files changed, 82 insertions, 49 deletions
diff --git a/arch/x86/include/asm/k8.h b/arch/x86/include/asm/k8.h index af00bd1d2089..9cee145dcace 100644 --- a/arch/x86/include/asm/k8.h +++ b/arch/x86/include/asm/k8.h | |||
@@ -7,24 +7,27 @@ extern struct pci_device_id k8_nb_ids[]; | |||
7 | struct bootnode; | 7 | struct bootnode; |
8 | 8 | ||
9 | extern int early_is_k8_nb(u32 value); | 9 | extern int early_is_k8_nb(u32 value); |
10 | extern struct pci_dev **k8_northbridges; | ||
11 | extern int num_k8_northbridges; | ||
12 | extern int cache_k8_northbridges(void); | 10 | extern int cache_k8_northbridges(void); |
13 | extern void k8_flush_garts(void); | 11 | extern void k8_flush_garts(void); |
14 | extern int k8_get_nodes(struct bootnode *nodes); | 12 | extern int k8_get_nodes(struct bootnode *nodes); |
15 | extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn); | 13 | extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn); |
16 | extern int k8_scan_nodes(void); | 14 | extern int k8_scan_nodes(void); |
17 | 15 | ||
16 | struct k8_northbridge_info { | ||
17 | u16 num; | ||
18 | u8 gart_supported; | ||
19 | struct pci_dev **nb_misc; | ||
20 | }; | ||
21 | extern struct k8_northbridge_info k8_northbridges; | ||
22 | |||
18 | #ifdef CONFIG_K8_NB | 23 | #ifdef CONFIG_K8_NB |
19 | extern int num_k8_northbridges; | ||
20 | 24 | ||
21 | static inline struct pci_dev *node_to_k8_nb_misc(int node) | 25 | static inline struct pci_dev *node_to_k8_nb_misc(int node) |
22 | { | 26 | { |
23 | return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL; | 27 | return (node < k8_northbridges.num) ? k8_northbridges.nb_misc[node] : NULL; |
24 | } | 28 | } |
25 | 29 | ||
26 | #else | 30 | #else |
27 | #define num_k8_northbridges 0 | ||
28 | 31 | ||
29 | static inline struct pci_dev *node_to_k8_nb_misc(int node) | 32 | static inline struct pci_dev *node_to_k8_nb_misc(int node) |
30 | { | 33 | { |
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 2521cdcb877e..6fdfb0b20f8c 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -369,7 +369,7 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, | |||
369 | return; | 369 | return; |
370 | 370 | ||
371 | /* not in virtualized environments */ | 371 | /* not in virtualized environments */ |
372 | if (num_k8_northbridges == 0) | 372 | if (k8_northbridges.num == 0) |
373 | return; | 373 | return; |
374 | 374 | ||
375 | /* | 375 | /* |
@@ -377,7 +377,7 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, | |||
377 | * never freed but this is done only on shutdown so it doesn't matter. | 377 | * never freed but this is done only on shutdown so it doesn't matter. |
378 | */ | 378 | */ |
379 | if (!l3_caches) { | 379 | if (!l3_caches) { |
380 | int size = num_k8_northbridges * sizeof(struct amd_l3_cache *); | 380 | int size = k8_northbridges.num * sizeof(struct amd_l3_cache *); |
381 | 381 | ||
382 | l3_caches = kzalloc(size, GFP_ATOMIC); | 382 | l3_caches = kzalloc(size, GFP_ATOMIC); |
383 | if (!l3_caches) | 383 | if (!l3_caches) |
diff --git a/arch/x86/kernel/k8.c b/arch/x86/kernel/k8.c index 0f7bc20cfcde..5de1b6b39639 100644 --- a/arch/x86/kernel/k8.c +++ b/arch/x86/kernel/k8.c | |||
@@ -10,9 +10,6 @@ | |||
10 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
11 | #include <asm/k8.h> | 11 | #include <asm/k8.h> |
12 | 12 | ||
13 | int num_k8_northbridges; | ||
14 | EXPORT_SYMBOL(num_k8_northbridges); | ||
15 | |||
16 | static u32 *flush_words; | 13 | static u32 *flush_words; |
17 | 14 | ||
18 | struct pci_device_id k8_nb_ids[] = { | 15 | struct pci_device_id k8_nb_ids[] = { |
@@ -22,7 +19,7 @@ struct pci_device_id k8_nb_ids[] = { | |||
22 | }; | 19 | }; |
23 | EXPORT_SYMBOL(k8_nb_ids); | 20 | EXPORT_SYMBOL(k8_nb_ids); |
24 | 21 | ||
25 | struct pci_dev **k8_northbridges; | 22 | struct k8_northbridge_info k8_northbridges; |
26 | EXPORT_SYMBOL(k8_northbridges); | 23 | EXPORT_SYMBOL(k8_northbridges); |
27 | 24 | ||
28 | static struct pci_dev *next_k8_northbridge(struct pci_dev *dev) | 25 | static struct pci_dev *next_k8_northbridge(struct pci_dev *dev) |
@@ -40,36 +37,44 @@ int cache_k8_northbridges(void) | |||
40 | int i; | 37 | int i; |
41 | struct pci_dev *dev; | 38 | struct pci_dev *dev; |
42 | 39 | ||
43 | if (num_k8_northbridges) | 40 | if (k8_northbridges.num) |
44 | return 0; | 41 | return 0; |
45 | 42 | ||
46 | dev = NULL; | 43 | dev = NULL; |
47 | while ((dev = next_k8_northbridge(dev)) != NULL) | 44 | while ((dev = next_k8_northbridge(dev)) != NULL) |
48 | num_k8_northbridges++; | 45 | k8_northbridges.num++; |
46 | |||
47 | /* some CPU families (e.g. family 0x11) do not support GART */ | ||
48 | if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10) | ||
49 | k8_northbridges.gart_supported = 1; | ||
49 | 50 | ||
50 | k8_northbridges = kmalloc((num_k8_northbridges + 1) * sizeof(void *), | 51 | k8_northbridges.nb_misc = kmalloc((k8_northbridges.num + 1) * |
51 | GFP_KERNEL); | 52 | sizeof(void *), GFP_KERNEL); |
52 | if (!k8_northbridges) | 53 | if (!k8_northbridges.nb_misc) |
53 | return -ENOMEM; | 54 | return -ENOMEM; |
54 | 55 | ||
55 | if (!num_k8_northbridges) { | 56 | if (!k8_northbridges.num) { |
56 | k8_northbridges[0] = NULL; | 57 | k8_northbridges.nb_misc[0] = NULL; |
57 | return 0; | 58 | return 0; |
58 | } | 59 | } |
59 | 60 | ||
60 | flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL); | 61 | if (k8_northbridges.gart_supported) { |
61 | if (!flush_words) { | 62 | flush_words = kmalloc(k8_northbridges.num * sizeof(u32), |
62 | kfree(k8_northbridges); | 63 | GFP_KERNEL); |
63 | return -ENOMEM; | 64 | if (!flush_words) { |
65 | kfree(k8_northbridges.nb_misc); | ||
66 | return -ENOMEM; | ||
67 | } | ||
64 | } | 68 | } |
65 | 69 | ||
66 | dev = NULL; | 70 | dev = NULL; |
67 | i = 0; | 71 | i = 0; |
68 | while ((dev = next_k8_northbridge(dev)) != NULL) { | 72 | while ((dev = next_k8_northbridge(dev)) != NULL) { |
69 | k8_northbridges[i] = dev; | 73 | k8_northbridges.nb_misc[i] = dev; |
70 | pci_read_config_dword(dev, 0x9c, &flush_words[i++]); | 74 | if (k8_northbridges.gart_supported) |
75 | pci_read_config_dword(dev, 0x9c, &flush_words[i++]); | ||
71 | } | 76 | } |
72 | k8_northbridges[i] = NULL; | 77 | k8_northbridges.nb_misc[i] = NULL; |
73 | return 0; | 78 | return 0; |
74 | } | 79 | } |
75 | EXPORT_SYMBOL_GPL(cache_k8_northbridges); | 80 | EXPORT_SYMBOL_GPL(cache_k8_northbridges); |
@@ -93,22 +98,25 @@ void k8_flush_garts(void) | |||
93 | unsigned long flags; | 98 | unsigned long flags; |
94 | static DEFINE_SPINLOCK(gart_lock); | 99 | static DEFINE_SPINLOCK(gart_lock); |
95 | 100 | ||
101 | if (!k8_northbridges.gart_supported) | ||
102 | return; | ||
103 | |||
96 | /* Avoid races between AGP and IOMMU. In theory it's not needed | 104 | /* Avoid races between AGP and IOMMU. In theory it's not needed |
97 | but I'm not sure if the hardware won't lose flush requests | 105 | but I'm not sure if the hardware won't lose flush requests |
98 | when another is pending. This whole thing is so expensive anyways | 106 | when another is pending. This whole thing is so expensive anyways |
99 | that it doesn't matter to serialize more. -AK */ | 107 | that it doesn't matter to serialize more. -AK */ |
100 | spin_lock_irqsave(&gart_lock, flags); | 108 | spin_lock_irqsave(&gart_lock, flags); |
101 | flushed = 0; | 109 | flushed = 0; |
102 | for (i = 0; i < num_k8_northbridges; i++) { | 110 | for (i = 0; i < k8_northbridges.num; i++) { |
103 | pci_write_config_dword(k8_northbridges[i], 0x9c, | 111 | pci_write_config_dword(k8_northbridges.nb_misc[i], 0x9c, |
104 | flush_words[i]|1); | 112 | flush_words[i]|1); |
105 | flushed++; | 113 | flushed++; |
106 | } | 114 | } |
107 | for (i = 0; i < num_k8_northbridges; i++) { | 115 | for (i = 0; i < k8_northbridges.num; i++) { |
108 | u32 w; | 116 | u32 w; |
109 | /* Make sure the hardware actually executed the flush*/ | 117 | /* Make sure the hardware actually executed the flush*/ |
110 | for (;;) { | 118 | for (;;) { |
111 | pci_read_config_dword(k8_northbridges[i], | 119 | pci_read_config_dword(k8_northbridges.nb_misc[i], |
112 | 0x9c, &w); | 120 | 0x9c, &w); |
113 | if (!(w & 1)) | 121 | if (!(w & 1)) |
114 | break; | 122 | break; |
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 0f7f130caa67..8f214a2643fa 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c | |||
@@ -560,8 +560,11 @@ static void enable_gart_translations(void) | |||
560 | { | 560 | { |
561 | int i; | 561 | int i; |
562 | 562 | ||
563 | for (i = 0; i < num_k8_northbridges; i++) { | 563 | if (!k8_northbridges.gart_supported) |
564 | struct pci_dev *dev = k8_northbridges[i]; | 564 | return; |
565 | |||
566 | for (i = 0; i < k8_northbridges.num; i++) { | ||
567 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; | ||
565 | 568 | ||
566 | enable_gart_translation(dev, __pa(agp_gatt_table)); | 569 | enable_gart_translation(dev, __pa(agp_gatt_table)); |
567 | } | 570 | } |
@@ -592,10 +595,13 @@ static void gart_fixup_northbridges(struct sys_device *dev) | |||
592 | if (!fix_up_north_bridges) | 595 | if (!fix_up_north_bridges) |
593 | return; | 596 | return; |
594 | 597 | ||
598 | if (!k8_northbridges.gart_supported) | ||
599 | return; | ||
600 | |||
595 | pr_info("PCI-DMA: Restoring GART aperture settings\n"); | 601 | pr_info("PCI-DMA: Restoring GART aperture settings\n"); |
596 | 602 | ||
597 | for (i = 0; i < num_k8_northbridges; i++) { | 603 | for (i = 0; i < k8_northbridges.num; i++) { |
598 | struct pci_dev *dev = k8_northbridges[i]; | 604 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; |
599 | 605 | ||
600 | /* | 606 | /* |
601 | * Don't enable translations just yet. That is the next | 607 | * Don't enable translations just yet. That is the next |
@@ -649,8 +655,8 @@ static __init int init_k8_gatt(struct agp_kern_info *info) | |||
649 | 655 | ||
650 | aper_size = aper_base = info->aper_size = 0; | 656 | aper_size = aper_base = info->aper_size = 0; |
651 | dev = NULL; | 657 | dev = NULL; |
652 | for (i = 0; i < num_k8_northbridges; i++) { | 658 | for (i = 0; i < k8_northbridges.num; i++) { |
653 | dev = k8_northbridges[i]; | 659 | dev = k8_northbridges.nb_misc[i]; |
654 | new_aper_base = read_aperture(dev, &new_aper_size); | 660 | new_aper_base = read_aperture(dev, &new_aper_size); |
655 | if (!new_aper_base) | 661 | if (!new_aper_base) |
656 | goto nommu; | 662 | goto nommu; |
@@ -718,10 +724,13 @@ static void gart_iommu_shutdown(void) | |||
718 | if (!no_agp) | 724 | if (!no_agp) |
719 | return; | 725 | return; |
720 | 726 | ||
721 | for (i = 0; i < num_k8_northbridges; i++) { | 727 | if (!k8_northbridges.gart_supported) |
728 | return; | ||
729 | |||
730 | for (i = 0; i < k8_northbridges.num; i++) { | ||
722 | u32 ctl; | 731 | u32 ctl; |
723 | 732 | ||
724 | dev = k8_northbridges[i]; | 733 | dev = k8_northbridges.nb_misc[i]; |
725 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl); | 734 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl); |
726 | 735 | ||
727 | ctl &= ~GARTEN; | 736 | ctl &= ~GARTEN; |
@@ -739,7 +748,7 @@ int __init gart_iommu_init(void) | |||
739 | unsigned long scratch; | 748 | unsigned long scratch; |
740 | long i; | 749 | long i; |
741 | 750 | ||
742 | if (num_k8_northbridges == 0) | 751 | if (!k8_northbridges.gart_supported) |
743 | return 0; | 752 | return 0; |
744 | 753 | ||
745 | #ifndef CONFIG_AGP_AMD64 | 754 | #ifndef CONFIG_AGP_AMD64 |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 70312da4c968..bdf00d583d79 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -124,7 +124,7 @@ static int amd64_fetch_size(void) | |||
124 | u32 temp; | 124 | u32 temp; |
125 | struct aper_size_info_32 *values; | 125 | struct aper_size_info_32 *values; |
126 | 126 | ||
127 | dev = k8_northbridges[0]; | 127 | dev = k8_northbridges.nb_misc[0]; |
128 | if (dev==NULL) | 128 | if (dev==NULL) |
129 | return 0; | 129 | return 0; |
130 | 130 | ||
@@ -181,10 +181,14 @@ static int amd_8151_configure(void) | |||
181 | unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); | 181 | unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); |
182 | int i; | 182 | int i; |
183 | 183 | ||
184 | if (!k8_northbridges.gart_supported) | ||
185 | return 0; | ||
186 | |||
184 | /* Configure AGP regs in each x86-64 host bridge. */ | 187 | /* Configure AGP regs in each x86-64 host bridge. */ |
185 | for (i = 0; i < num_k8_northbridges; i++) { | 188 | for (i = 0; i < k8_northbridges.num; i++) { |
186 | agp_bridge->gart_bus_addr = | 189 | agp_bridge->gart_bus_addr = |
187 | amd64_configure(k8_northbridges[i], gatt_bus); | 190 | amd64_configure(k8_northbridges.nb_misc[i], |
191 | gatt_bus); | ||
188 | } | 192 | } |
189 | k8_flush_garts(); | 193 | k8_flush_garts(); |
190 | return 0; | 194 | return 0; |
@@ -195,8 +199,12 @@ static void amd64_cleanup(void) | |||
195 | { | 199 | { |
196 | u32 tmp; | 200 | u32 tmp; |
197 | int i; | 201 | int i; |
198 | for (i = 0; i < num_k8_northbridges; i++) { | 202 | |
199 | struct pci_dev *dev = k8_northbridges[i]; | 203 | if (!k8_northbridges.gart_supported) |
204 | return; | ||
205 | |||
206 | for (i = 0; i < k8_northbridges.num; i++) { | ||
207 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; | ||
200 | /* disable gart translation */ | 208 | /* disable gart translation */ |
201 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp); | 209 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp); |
202 | tmp &= ~AMD64_GARTEN; | 210 | tmp &= ~AMD64_GARTEN; |
@@ -319,16 +327,19 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, | |||
319 | return 0; | 327 | return 0; |
320 | } | 328 | } |
321 | 329 | ||
322 | static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) | 330 | static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) |
323 | { | 331 | { |
324 | int i; | 332 | int i; |
325 | 333 | ||
326 | if (cache_k8_northbridges() < 0) | 334 | if (cache_k8_northbridges() < 0) |
327 | return -ENODEV; | 335 | return -ENODEV; |
328 | 336 | ||
337 | if (!k8_northbridges.gart_supported) | ||
338 | return -ENODEV; | ||
339 | |||
329 | i = 0; | 340 | i = 0; |
330 | for (i = 0; i < num_k8_northbridges; i++) { | 341 | for (i = 0; i < k8_northbridges.num; i++) { |
331 | struct pci_dev *dev = k8_northbridges[i]; | 342 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; |
332 | if (fix_northbridge(dev, pdev, cap_ptr) < 0) { | 343 | if (fix_northbridge(dev, pdev, cap_ptr) < 0) { |
333 | dev_err(&dev->dev, "no usable aperture found\n"); | 344 | dev_err(&dev->dev, "no usable aperture found\n"); |
334 | #ifdef __x86_64__ | 345 | #ifdef __x86_64__ |
@@ -405,7 +416,8 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
405 | } | 416 | } |
406 | 417 | ||
407 | /* shadow x86-64 registers into ULi registers */ | 418 | /* shadow x86-64 registers into ULi registers */ |
408 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea); | 419 | pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE, |
420 | &httfea); | ||
409 | 421 | ||
410 | /* if x86-64 aperture base is beyond 4G, exit here */ | 422 | /* if x86-64 aperture base is beyond 4G, exit here */ |
411 | if ((httfea & 0x7fff) >> (32 - 25)) { | 423 | if ((httfea & 0x7fff) >> (32 - 25)) { |
@@ -472,7 +484,8 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
472 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); | 484 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); |
473 | 485 | ||
474 | /* shadow x86-64 registers into NVIDIA registers */ | 486 | /* shadow x86-64 registers into NVIDIA registers */ |
475 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase); | 487 | pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE, |
488 | &apbase); | ||
476 | 489 | ||
477 | /* if x86-64 aperture base is beyond 4G, exit here */ | 490 | /* if x86-64 aperture base is beyond 4G, exit here */ |
478 | if ( (apbase & 0x7fff) >> (32 - 25) ) { | 491 | if ( (apbase & 0x7fff) >> (32 - 25) ) { |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index e7d5d6b5dcf6..5babf6f48058 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -2927,7 +2927,7 @@ static int __init amd64_edac_init(void) | |||
2927 | * to finish initialization of the MC instances. | 2927 | * to finish initialization of the MC instances. |
2928 | */ | 2928 | */ |
2929 | err = -ENODEV; | 2929 | err = -ENODEV; |
2930 | for (nb = 0; nb < num_k8_northbridges; nb++) { | 2930 | for (nb = 0; nb < k8_northbridges.num; nb++) { |
2931 | if (!pvt_lookup[nb]) | 2931 | if (!pvt_lookup[nb]) |
2932 | continue; | 2932 | continue; |
2933 | 2933 | ||