diff options
Diffstat (limited to 'drivers/char/agp')
-rw-r--r-- | drivers/char/agp/Kconfig | 4 | ||||
-rw-r--r-- | drivers/char/agp/agp.h | 4 | ||||
-rw-r--r-- | drivers/char/agp/amd-k7-agp.c | 5 | ||||
-rw-r--r-- | drivers/char/agp/amd64-agp.c | 9 | ||||
-rw-r--r-- | drivers/char/agp/ati-agp.c | 36 | ||||
-rw-r--r-- | drivers/char/agp/generic.c | 36 | ||||
-rw-r--r-- | drivers/char/agp/intel-agp.c | 181 | ||||
-rw-r--r-- | drivers/char/agp/sgi-agp.c | 9 | ||||
-rw-r--r-- | drivers/char/agp/via-agp.c | 21 |
9 files changed, 204 insertions, 101 deletions
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index c603bf291580..a9f9c48c2424 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig | |||
@@ -86,7 +86,7 @@ config AGP_NVIDIA | |||
86 | 86 | ||
87 | config AGP_SIS | 87 | config AGP_SIS |
88 | tristate "SiS chipset support" | 88 | tristate "SiS chipset support" |
89 | depends on AGP | 89 | depends on AGP && X86 |
90 | help | 90 | help |
91 | This option gives you AGP support for the GLX component of | 91 | This option gives you AGP support for the GLX component of |
92 | X on Silicon Integrated Systems [SiS] chipsets. | 92 | X on Silicon Integrated Systems [SiS] chipsets. |
@@ -103,7 +103,7 @@ config AGP_SWORKS | |||
103 | 103 | ||
104 | config AGP_VIA | 104 | config AGP_VIA |
105 | tristate "VIA chipset support" | 105 | tristate "VIA chipset support" |
106 | depends on AGP | 106 | depends on AGP && X86 |
107 | help | 107 | help |
108 | This option gives you AGP support for the GLX component of | 108 | This option gives you AGP support for the GLX component of |
109 | X on VIA MVP3/Apollo Pro chipsets. | 109 | X on VIA MVP3/Apollo Pro chipsets. |
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 8b3317fd46c9..1d59e2a5b9aa 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h | |||
@@ -225,6 +225,10 @@ struct agp_bridge_data { | |||
225 | #define I810_GMS_DISABLE 0x00000000 | 225 | #define I810_GMS_DISABLE 0x00000000 |
226 | #define I810_PGETBL_CTL 0x2020 | 226 | #define I810_PGETBL_CTL 0x2020 |
227 | #define I810_PGETBL_ENABLED 0x00000001 | 227 | #define I810_PGETBL_ENABLED 0x00000001 |
228 | #define I965_PGETBL_SIZE_MASK 0x0000000e | ||
229 | #define I965_PGETBL_SIZE_512KB (0 << 1) | ||
230 | #define I965_PGETBL_SIZE_256KB (1 << 1) | ||
231 | #define I965_PGETBL_SIZE_128KB (2 << 1) | ||
228 | #define I810_DRAM_CTL 0x3000 | 232 | #define I810_DRAM_CTL 0x3000 |
229 | #define I810_DRAM_ROW_0 0x00000001 | 233 | #define I810_DRAM_ROW_0 0x00000001 |
230 | #define I810_DRAM_ROW_0_SDRAM 0x00000001 | 234 | #define I810_DRAM_ROW_0_SDRAM 0x00000001 |
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 51d0d562d01e..c85c8cadb6df 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c | |||
@@ -101,6 +101,11 @@ static int amd_create_gatt_pages(int nr_tables) | |||
101 | for (i = 0; i < nr_tables; i++) { | 101 | for (i = 0; i < nr_tables; i++) { |
102 | entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL); | 102 | entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL); |
103 | if (entry == NULL) { | 103 | if (entry == NULL) { |
104 | while (i > 0) { | ||
105 | kfree(tables[i-1]); | ||
106 | i--; | ||
107 | } | ||
108 | kfree(tables); | ||
104 | retval = -ENOMEM; | 109 | retval = -ENOMEM; |
105 | break; | 110 | break; |
106 | } | 111 | } |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 2f2c4efff8a3..93d2209fee4c 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -650,6 +650,15 @@ static struct pci_device_id agp_amd64_pci_table[] = { | |||
650 | .subvendor = PCI_ANY_ID, | 650 | .subvendor = PCI_ANY_ID, |
651 | .subdevice = PCI_ANY_ID, | 651 | .subdevice = PCI_ANY_ID, |
652 | }, | 652 | }, |
653 | /* VIA K8M890 / K8N890 */ | ||
654 | { | ||
655 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
656 | .class_mask = ~0, | ||
657 | .vendor = PCI_VENDOR_ID_VIA, | ||
658 | .device = PCI_DEVICE_ID_VIA_VT3336, | ||
659 | .subvendor = PCI_ANY_ID, | ||
660 | .subdevice = PCI_ANY_ID, | ||
661 | }, | ||
653 | /* VIA K8T890 */ | 662 | /* VIA K8T890 */ |
654 | { | 663 | { |
655 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | 664 | .class = (PCI_CLASS_BRIDGE_HOST << 8), |
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index f244c6682738..9987dc2e0c3f 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
@@ -41,18 +41,18 @@ static struct gatt_mask ati_generic_masks[] = | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | 43 | ||
44 | typedef struct _ati_page_map { | 44 | struct ati_page_map { |
45 | unsigned long *real; | 45 | unsigned long *real; |
46 | unsigned long __iomem *remapped; | 46 | unsigned long __iomem *remapped; |
47 | } ati_page_map; | 47 | }; |
48 | 48 | ||
49 | static struct _ati_generic_private { | 49 | static struct _ati_generic_private { |
50 | volatile u8 __iomem *registers; | 50 | volatile u8 __iomem *registers; |
51 | ati_page_map **gatt_pages; | 51 | struct ati_page_map **gatt_pages; |
52 | int num_tables; | 52 | int num_tables; |
53 | } ati_generic_private; | 53 | } ati_generic_private; |
54 | 54 | ||
55 | static int ati_create_page_map(ati_page_map *page_map) | 55 | static int ati_create_page_map(struct ati_page_map *page_map) |
56 | { | 56 | { |
57 | int i, err = 0; | 57 | int i, err = 0; |
58 | 58 | ||
@@ -82,7 +82,7 @@ static int ati_create_page_map(ati_page_map *page_map) | |||
82 | } | 82 | } |
83 | 83 | ||
84 | 84 | ||
85 | static void ati_free_page_map(ati_page_map *page_map) | 85 | static void ati_free_page_map(struct ati_page_map *page_map) |
86 | { | 86 | { |
87 | unmap_page_from_agp(virt_to_page(page_map->real)); | 87 | unmap_page_from_agp(virt_to_page(page_map->real)); |
88 | iounmap(page_map->remapped); | 88 | iounmap(page_map->remapped); |
@@ -94,8 +94,8 @@ static void ati_free_page_map(ati_page_map *page_map) | |||
94 | static void ati_free_gatt_pages(void) | 94 | static void ati_free_gatt_pages(void) |
95 | { | 95 | { |
96 | int i; | 96 | int i; |
97 | ati_page_map **tables; | 97 | struct ati_page_map **tables; |
98 | ati_page_map *entry; | 98 | struct ati_page_map *entry; |
99 | 99 | ||
100 | tables = ati_generic_private.gatt_pages; | 100 | tables = ati_generic_private.gatt_pages; |
101 | for (i = 0; i < ati_generic_private.num_tables; i++) { | 101 | for (i = 0; i < ati_generic_private.num_tables; i++) { |
@@ -112,30 +112,30 @@ static void ati_free_gatt_pages(void) | |||
112 | 112 | ||
113 | static int ati_create_gatt_pages(int nr_tables) | 113 | static int ati_create_gatt_pages(int nr_tables) |
114 | { | 114 | { |
115 | ati_page_map **tables; | 115 | struct ati_page_map **tables; |
116 | ati_page_map *entry; | 116 | struct ati_page_map *entry; |
117 | int retval = 0; | 117 | int retval = 0; |
118 | int i; | 118 | int i; |
119 | 119 | ||
120 | tables = kzalloc((nr_tables + 1) * sizeof(ati_page_map *),GFP_KERNEL); | 120 | tables = kzalloc((nr_tables + 1) * sizeof(struct ati_page_map *),GFP_KERNEL); |
121 | if (tables == NULL) | 121 | if (tables == NULL) |
122 | return -ENOMEM; | 122 | return -ENOMEM; |
123 | 123 | ||
124 | for (i = 0; i < nr_tables; i++) { | 124 | for (i = 0; i < nr_tables; i++) { |
125 | entry = kzalloc(sizeof(ati_page_map), GFP_KERNEL); | 125 | entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL); |
126 | if (entry == NULL) { | 126 | if (entry == NULL) { |
127 | while (i>0) { | 127 | while (i > 0) { |
128 | kfree (tables[i-1]); | 128 | kfree(tables[i-1]); |
129 | i--; | 129 | i--; |
130 | } | 130 | } |
131 | kfree (tables); | 131 | kfree(tables); |
132 | tables = NULL; | ||
133 | retval = -ENOMEM; | 132 | retval = -ENOMEM; |
134 | break; | 133 | break; |
135 | } | 134 | } |
136 | tables[i] = entry; | 135 | tables[i] = entry; |
137 | retval = ati_create_page_map(entry); | 136 | retval = ati_create_page_map(entry); |
138 | if (retval != 0) break; | 137 | if (retval != 0) |
138 | break; | ||
139 | } | 139 | } |
140 | ati_generic_private.num_tables = nr_tables; | 140 | ati_generic_private.num_tables = nr_tables; |
141 | ati_generic_private.gatt_pages = tables; | 141 | ati_generic_private.gatt_pages = tables; |
@@ -340,7 +340,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start, | |||
340 | static int ati_create_gatt_table(struct agp_bridge_data *bridge) | 340 | static int ati_create_gatt_table(struct agp_bridge_data *bridge) |
341 | { | 341 | { |
342 | struct aper_size_info_lvl2 *value; | 342 | struct aper_size_info_lvl2 *value; |
343 | ati_page_map page_dir; | 343 | struct ati_page_map page_dir; |
344 | unsigned long addr; | 344 | unsigned long addr; |
345 | int retval; | 345 | int retval; |
346 | u32 temp; | 346 | u32 temp; |
@@ -400,7 +400,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) | |||
400 | 400 | ||
401 | static int ati_free_gatt_table(struct agp_bridge_data *bridge) | 401 | static int ati_free_gatt_table(struct agp_bridge_data *bridge) |
402 | { | 402 | { |
403 | ati_page_map page_dir; | 403 | struct ati_page_map page_dir; |
404 | 404 | ||
405 | page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; | 405 | page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; |
406 | page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; | 406 | page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 5ff457b41efb..3491d6f84bc6 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -419,6 +419,31 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ | |||
419 | *requested_mode &= ~AGP2_RESERVED_MASK; | 419 | *requested_mode &= ~AGP2_RESERVED_MASK; |
420 | } | 420 | } |
421 | 421 | ||
422 | /* | ||
423 | * Some dumb bridges are programmed to disobey the AGP2 spec. | ||
424 | * This is likely a BIOS misprogramming rather than poweron default, or | ||
425 | * it would be a lot more common. | ||
426 | * https://bugs.freedesktop.org/show_bug.cgi?id=8816 | ||
427 | * AGPv2 spec 6.1.9 states: | ||
428 | * The RATE field indicates the data transfer rates supported by this | ||
429 | * device. A.G.P. devices must report all that apply. | ||
430 | * Fix them up as best we can. | ||
431 | */ | ||
432 | switch (*bridge_agpstat & 7) { | ||
433 | case 4: | ||
434 | *bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X); | ||
435 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate" | ||
436 | "Fixing up support for x2 & x1\n"); | ||
437 | break; | ||
438 | case 2: | ||
439 | *bridge_agpstat |= AGPSTAT2_1X; | ||
440 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate" | ||
441 | "Fixing up support for x1\n"); | ||
442 | break; | ||
443 | default: | ||
444 | break; | ||
445 | } | ||
446 | |||
422 | /* Check the speed bits make sense. Only one should be set. */ | 447 | /* Check the speed bits make sense. Only one should be set. */ |
423 | tmp = *requested_mode & 7; | 448 | tmp = *requested_mode & 7; |
424 | switch (tmp) { | 449 | switch (tmp) { |
@@ -940,6 +965,9 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) | |||
940 | if (!bridge) | 965 | if (!bridge) |
941 | return -EINVAL; | 966 | return -EINVAL; |
942 | 967 | ||
968 | if (mem->page_count == 0) | ||
969 | return 0; | ||
970 | |||
943 | temp = bridge->current_size; | 971 | temp = bridge->current_size; |
944 | 972 | ||
945 | switch (bridge->driver->size_type) { | 973 | switch (bridge->driver->size_type) { |
@@ -991,8 +1019,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) | |||
991 | 1019 | ||
992 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 1020 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
993 | writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j); | 1021 | writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j); |
994 | readl(bridge->gatt_table+j); /* PCI Posting. */ | ||
995 | } | 1022 | } |
1023 | readl(bridge->gatt_table+j-1); /* PCI Posting. */ | ||
996 | 1024 | ||
997 | bridge->driver->tlb_flush(mem); | 1025 | bridge->driver->tlb_flush(mem); |
998 | return 0; | 1026 | return 0; |
@@ -1009,6 +1037,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) | |||
1009 | if (!bridge) | 1037 | if (!bridge) |
1010 | return -EINVAL; | 1038 | return -EINVAL; |
1011 | 1039 | ||
1040 | if (mem->page_count == 0) | ||
1041 | return 0; | ||
1042 | |||
1012 | if (type != 0 || mem->type != 0) { | 1043 | if (type != 0 || mem->type != 0) { |
1013 | /* The generic routines know nothing of memory types */ | 1044 | /* The generic routines know nothing of memory types */ |
1014 | return -EINVAL; | 1045 | return -EINVAL; |
@@ -1017,10 +1048,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) | |||
1017 | /* AK: bogus, should encode addresses > 4GB */ | 1048 | /* AK: bogus, should encode addresses > 4GB */ |
1018 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 1049 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
1019 | writel(bridge->scratch_page, bridge->gatt_table+i); | 1050 | writel(bridge->scratch_page, bridge->gatt_table+i); |
1020 | readl(bridge->gatt_table+i); /* PCI Posting. */ | ||
1021 | } | 1051 | } |
1052 | readl(bridge->gatt_table+i-1); /* PCI Posting. */ | ||
1022 | 1053 | ||
1023 | global_cache_flush(); | ||
1024 | bridge->driver->tlb_flush(mem); | 1054 | bridge->driver->tlb_flush(mem); |
1025 | return 0; | 1055 | return 0; |
1026 | } | 1056 | } |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 555b3a8ab49c..a3011de51f7c 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -207,6 +207,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, | |||
207 | int i, j, num_entries; | 207 | int i, j, num_entries; |
208 | void *temp; | 208 | void *temp; |
209 | 209 | ||
210 | if (mem->page_count == 0) | ||
211 | return 0; | ||
212 | |||
210 | temp = agp_bridge->current_size; | 213 | temp = agp_bridge->current_size; |
211 | num_entries = A_SIZE_FIX(temp)->num_entries; | 214 | num_entries = A_SIZE_FIX(temp)->num_entries; |
212 | 215 | ||
@@ -221,12 +224,16 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, | |||
221 | if (type != 0 || mem->type != 0) { | 224 | if (type != 0 || mem->type != 0) { |
222 | if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { | 225 | if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { |
223 | /* special insert */ | 226 | /* special insert */ |
224 | global_cache_flush(); | 227 | if (!mem->is_flushed) { |
228 | global_cache_flush(); | ||
229 | mem->is_flushed = TRUE; | ||
230 | } | ||
231 | |||
225 | for (i = pg_start; i < (pg_start + mem->page_count); i++) { | 232 | for (i = pg_start; i < (pg_start + mem->page_count); i++) { |
226 | writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4)); | 233 | writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4)); |
227 | readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
228 | } | 234 | } |
229 | global_cache_flush(); | 235 | readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */ |
236 | |||
230 | agp_bridge->driver->tlb_flush(mem); | 237 | agp_bridge->driver->tlb_flush(mem); |
231 | return 0; | 238 | return 0; |
232 | } | 239 | } |
@@ -236,14 +243,17 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, | |||
236 | } | 243 | } |
237 | 244 | ||
238 | insert: | 245 | insert: |
239 | global_cache_flush(); | 246 | if (!mem->is_flushed) { |
247 | global_cache_flush(); | ||
248 | mem->is_flushed = TRUE; | ||
249 | } | ||
250 | |||
240 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 251 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
241 | writel(agp_bridge->driver->mask_memory(agp_bridge, | 252 | writel(agp_bridge->driver->mask_memory(agp_bridge, |
242 | mem->memory[i], mem->type), | 253 | mem->memory[i], mem->type), |
243 | intel_i810_private.registers+I810_PTE_BASE+(j*4)); | 254 | intel_i810_private.registers+I810_PTE_BASE+(j*4)); |
244 | readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ | ||
245 | } | 255 | } |
246 | global_cache_flush(); | 256 | readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); /* PCI Posting. */ |
247 | 257 | ||
248 | agp_bridge->driver->tlb_flush(mem); | 258 | agp_bridge->driver->tlb_flush(mem); |
249 | return 0; | 259 | return 0; |
@@ -254,12 +264,14 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, | |||
254 | { | 264 | { |
255 | int i; | 265 | int i; |
256 | 266 | ||
267 | if (mem->page_count == 0) | ||
268 | return 0; | ||
269 | |||
257 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 270 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
258 | writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); | 271 | writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); |
259 | readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
260 | } | 272 | } |
273 | readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); | ||
261 | 274 | ||
262 | global_cache_flush(); | ||
263 | agp_bridge->driver->tlb_flush(mem); | 275 | agp_bridge->driver->tlb_flush(mem); |
264 | return 0; | 276 | return 0; |
265 | } | 277 | } |
@@ -370,6 +382,11 @@ static struct _intel_i830_private { | |||
370 | struct pci_dev *i830_dev; /* device one */ | 382 | struct pci_dev *i830_dev; /* device one */ |
371 | volatile u8 __iomem *registers; | 383 | volatile u8 __iomem *registers; |
372 | volatile u32 __iomem *gtt; /* I915G */ | 384 | volatile u32 __iomem *gtt; /* I915G */ |
385 | /* gtt_entries is the number of gtt entries that are already mapped | ||
386 | * to stolen memory. Stolen memory is larger than the memory mapped | ||
387 | * through gtt_entries, as it includes some reserved space for the BIOS | ||
388 | * popup and for the GTT. | ||
389 | */ | ||
373 | int gtt_entries; | 390 | int gtt_entries; |
374 | } intel_i830_private; | 391 | } intel_i830_private; |
375 | 392 | ||
@@ -380,14 +397,41 @@ static void intel_i830_init_gtt_entries(void) | |||
380 | u8 rdct; | 397 | u8 rdct; |
381 | int local = 0; | 398 | int local = 0; |
382 | static const int ddt[4] = { 0, 16, 32, 64 }; | 399 | static const int ddt[4] = { 0, 16, 32, 64 }; |
383 | int size; | 400 | int size; /* reserved space (in kb) at the top of stolen memory */ |
384 | 401 | ||
385 | pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl); | 402 | pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl); |
386 | 403 | ||
387 | /* We obtain the size of the GTT, which is also stored (for some | 404 | if (IS_I965) { |
388 | * reason) at the top of stolen memory. Then we add 4KB to that | 405 | u32 pgetbl_ctl; |
389 | * for the video BIOS popup, which is also stored in there. */ | 406 | |
390 | size = agp_bridge->driver->fetch_size() + 4; | 407 | pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL, |
408 | &pgetbl_ctl); | ||
409 | /* The 965 has a field telling us the size of the GTT, | ||
410 | * which may be larger than what is necessary to map the | ||
411 | * aperture. | ||
412 | */ | ||
413 | switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { | ||
414 | case I965_PGETBL_SIZE_128KB: | ||
415 | size = 128; | ||
416 | break; | ||
417 | case I965_PGETBL_SIZE_256KB: | ||
418 | size = 256; | ||
419 | break; | ||
420 | case I965_PGETBL_SIZE_512KB: | ||
421 | size = 512; | ||
422 | break; | ||
423 | default: | ||
424 | printk(KERN_INFO PFX "Unknown page table size, " | ||
425 | "assuming 512KB\n"); | ||
426 | size = 512; | ||
427 | } | ||
428 | size += 4; /* add in BIOS popup space */ | ||
429 | } else { | ||
430 | /* On previous hardware, the GTT size was just what was | ||
431 | * required to map the aperture. | ||
432 | */ | ||
433 | size = agp_bridge->driver->fetch_size() + 4; | ||
434 | } | ||
391 | 435 | ||
392 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || | 436 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || |
393 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { | 437 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { |
@@ -576,6 +620,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int | |||
576 | int i,j,num_entries; | 620 | int i,j,num_entries; |
577 | void *temp; | 621 | void *temp; |
578 | 622 | ||
623 | if (mem->page_count == 0) | ||
624 | return 0; | ||
625 | |||
579 | temp = agp_bridge->current_size; | 626 | temp = agp_bridge->current_size; |
580 | num_entries = A_SIZE_FIX(temp)->num_entries; | 627 | num_entries = A_SIZE_FIX(temp)->num_entries; |
581 | 628 | ||
@@ -598,16 +645,18 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int | |||
598 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) | 645 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) |
599 | return -EINVAL; | 646 | return -EINVAL; |
600 | 647 | ||
601 | global_cache_flush(); /* FIXME: Necessary ?*/ | 648 | if (!mem->is_flushed) { |
649 | global_cache_flush(); | ||
650 | mem->is_flushed = TRUE; | ||
651 | } | ||
602 | 652 | ||
603 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 653 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
604 | writel(agp_bridge->driver->mask_memory(agp_bridge, | 654 | writel(agp_bridge->driver->mask_memory(agp_bridge, |
605 | mem->memory[i], mem->type), | 655 | mem->memory[i], mem->type), |
606 | intel_i830_private.registers+I810_PTE_BASE+(j*4)); | 656 | intel_i830_private.registers+I810_PTE_BASE+(j*4)); |
607 | readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ | ||
608 | } | 657 | } |
658 | readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4)); | ||
609 | 659 | ||
610 | global_cache_flush(); | ||
611 | agp_bridge->driver->tlb_flush(mem); | 660 | agp_bridge->driver->tlb_flush(mem); |
612 | return 0; | 661 | return 0; |
613 | } | 662 | } |
@@ -617,7 +666,8 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start, | |||
617 | { | 666 | { |
618 | int i; | 667 | int i; |
619 | 668 | ||
620 | global_cache_flush(); | 669 | if (mem->page_count == 0) |
670 | return 0; | ||
621 | 671 | ||
622 | if (pg_start < intel_i830_private.gtt_entries) { | 672 | if (pg_start < intel_i830_private.gtt_entries) { |
623 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); | 673 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); |
@@ -626,10 +676,9 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start, | |||
626 | 676 | ||
627 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 677 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
628 | writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); | 678 | writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); |
629 | readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
630 | } | 679 | } |
680 | readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4)); | ||
631 | 681 | ||
632 | global_cache_flush(); | ||
633 | agp_bridge->driver->tlb_flush(mem); | 682 | agp_bridge->driver->tlb_flush(mem); |
634 | return 0; | 683 | return 0; |
635 | } | 684 | } |
@@ -686,6 +735,9 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, | |||
686 | int i,j,num_entries; | 735 | int i,j,num_entries; |
687 | void *temp; | 736 | void *temp; |
688 | 737 | ||
738 | if (mem->page_count == 0) | ||
739 | return 0; | ||
740 | |||
689 | temp = agp_bridge->current_size; | 741 | temp = agp_bridge->current_size; |
690 | num_entries = A_SIZE_FIX(temp)->num_entries; | 742 | num_entries = A_SIZE_FIX(temp)->num_entries; |
691 | 743 | ||
@@ -708,15 +760,17 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, | |||
708 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) | 760 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) |
709 | return -EINVAL; | 761 | return -EINVAL; |
710 | 762 | ||
711 | global_cache_flush(); | 763 | if (!mem->is_flushed) { |
764 | global_cache_flush(); | ||
765 | mem->is_flushed = TRUE; | ||
766 | } | ||
712 | 767 | ||
713 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 768 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
714 | writel(agp_bridge->driver->mask_memory(agp_bridge, | 769 | writel(agp_bridge->driver->mask_memory(agp_bridge, |
715 | mem->memory[i], mem->type), intel_i830_private.gtt+j); | 770 | mem->memory[i], mem->type), intel_i830_private.gtt+j); |
716 | readl(intel_i830_private.gtt+j); /* PCI Posting. */ | ||
717 | } | 771 | } |
772 | readl(intel_i830_private.gtt+j-1); | ||
718 | 773 | ||
719 | global_cache_flush(); | ||
720 | agp_bridge->driver->tlb_flush(mem); | 774 | agp_bridge->driver->tlb_flush(mem); |
721 | return 0; | 775 | return 0; |
722 | } | 776 | } |
@@ -726,7 +780,8 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start, | |||
726 | { | 780 | { |
727 | int i; | 781 | int i; |
728 | 782 | ||
729 | global_cache_flush(); | 783 | if (mem->page_count == 0) |
784 | return 0; | ||
730 | 785 | ||
731 | if (pg_start < intel_i830_private.gtt_entries) { | 786 | if (pg_start < intel_i830_private.gtt_entries) { |
732 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); | 787 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); |
@@ -735,30 +790,34 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start, | |||
735 | 790 | ||
736 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 791 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
737 | writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); | 792 | writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); |
738 | readl(intel_i830_private.gtt+i); | ||
739 | } | 793 | } |
794 | readl(intel_i830_private.gtt+i-1); | ||
740 | 795 | ||
741 | global_cache_flush(); | ||
742 | agp_bridge->driver->tlb_flush(mem); | 796 | agp_bridge->driver->tlb_flush(mem); |
743 | return 0; | 797 | return 0; |
744 | } | 798 | } |
745 | 799 | ||
746 | static int intel_i915_fetch_size(void) | 800 | /* Return the aperture size by just checking the resource length. The effect |
801 | * described in the spec of the MSAC registers is just changing of the | ||
802 | * resource size. | ||
803 | */ | ||
804 | static int intel_i9xx_fetch_size(void) | ||
747 | { | 805 | { |
748 | struct aper_size_info_fixed *values; | 806 | int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes); |
749 | u32 temp, offset; | 807 | int aper_size; /* size in megabytes */ |
808 | int i; | ||
750 | 809 | ||
751 | #define I915_256MB_ADDRESS_MASK (1<<27) | 810 | aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1); |
752 | 811 | ||
753 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | 812 | for (i = 0; i < num_sizes; i++) { |
813 | if (aper_size == intel_i830_sizes[i].size) { | ||
814 | agp_bridge->current_size = intel_i830_sizes + i; | ||
815 | agp_bridge->previous_size = agp_bridge->current_size; | ||
816 | return aper_size; | ||
817 | } | ||
818 | } | ||
754 | 819 | ||
755 | pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp); | 820 | return 0; |
756 | if (temp & I915_256MB_ADDRESS_MASK) | ||
757 | offset = 0; /* 128MB aperture */ | ||
758 | else | ||
759 | offset = 2; /* 256MB aperture */ | ||
760 | agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset); | ||
761 | return values[offset].size; | ||
762 | } | 821 | } |
763 | 822 | ||
764 | /* The intel i915 automatically initializes the agp aperture during POST. | 823 | /* The intel i915 automatically initializes the agp aperture during POST. |
@@ -821,40 +880,9 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, | |||
821 | return addr | bridge->driver->masks[type].mask; | 880 | return addr | bridge->driver->masks[type].mask; |
822 | } | 881 | } |
823 | 882 | ||
824 | static int intel_i965_fetch_size(void) | ||
825 | { | ||
826 | struct aper_size_info_fixed *values; | ||
827 | u32 offset = 0; | ||
828 | u8 temp; | ||
829 | |||
830 | #define I965_512MB_ADDRESS_MASK (3<<1) | ||
831 | |||
832 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | ||
833 | |||
834 | pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp); | ||
835 | temp &= I965_512MB_ADDRESS_MASK; | ||
836 | switch (temp) { | ||
837 | case 0x00: | ||
838 | offset = 0; /* 128MB */ | ||
839 | break; | ||
840 | case 0x06: | ||
841 | offset = 3; /* 512MB */ | ||
842 | break; | ||
843 | default: | ||
844 | case 0x02: | ||
845 | offset = 2; /* 256MB */ | ||
846 | break; | ||
847 | } | ||
848 | |||
849 | agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset); | ||
850 | |||
851 | /* The i965 GTT is always sized as if it had a 512kB aperture size */ | ||
852 | return 512; | ||
853 | } | ||
854 | |||
855 | /* The intel i965 automatically initializes the agp aperture during POST. | 883 | /* The intel i965 automatically initializes the agp aperture during POST. |
856 | + * Use the memory already set aside for in the GTT. | 884 | * Use the memory already set aside for in the GTT. |
857 | + */ | 885 | */ |
858 | static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) | 886 | static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) |
859 | { | 887 | { |
860 | int page_order; | 888 | int page_order; |
@@ -1574,7 +1602,7 @@ static struct agp_bridge_driver intel_915_driver = { | |||
1574 | .num_aperture_sizes = 4, | 1602 | .num_aperture_sizes = 4, |
1575 | .needs_scratch_page = TRUE, | 1603 | .needs_scratch_page = TRUE, |
1576 | .configure = intel_i915_configure, | 1604 | .configure = intel_i915_configure, |
1577 | .fetch_size = intel_i915_fetch_size, | 1605 | .fetch_size = intel_i9xx_fetch_size, |
1578 | .cleanup = intel_i915_cleanup, | 1606 | .cleanup = intel_i915_cleanup, |
1579 | .tlb_flush = intel_i810_tlbflush, | 1607 | .tlb_flush = intel_i810_tlbflush, |
1580 | .mask_memory = intel_i810_mask_memory, | 1608 | .mask_memory = intel_i810_mask_memory, |
@@ -1598,7 +1626,7 @@ static struct agp_bridge_driver intel_i965_driver = { | |||
1598 | .num_aperture_sizes = 4, | 1626 | .num_aperture_sizes = 4, |
1599 | .needs_scratch_page = TRUE, | 1627 | .needs_scratch_page = TRUE, |
1600 | .configure = intel_i915_configure, | 1628 | .configure = intel_i915_configure, |
1601 | .fetch_size = intel_i965_fetch_size, | 1629 | .fetch_size = intel_i9xx_fetch_size, |
1602 | .cleanup = intel_i915_cleanup, | 1630 | .cleanup = intel_i915_cleanup, |
1603 | .tlb_flush = intel_i810_tlbflush, | 1631 | .tlb_flush = intel_i810_tlbflush, |
1604 | .mask_memory = intel_i965_mask_memory, | 1632 | .mask_memory = intel_i965_mask_memory, |
@@ -1927,6 +1955,15 @@ static int agp_intel_resume(struct pci_dev *pdev) | |||
1927 | 1955 | ||
1928 | pci_restore_state(pdev); | 1956 | pci_restore_state(pdev); |
1929 | 1957 | ||
1958 | /* We should restore our graphics device's config space, | ||
1959 | * as host bridge (00:00) resumes before graphics device (02:00), | ||
1960 | * then our access to its pci space can work right. | ||
1961 | */ | ||
1962 | if (intel_i810_private.i810_dev) | ||
1963 | pci_restore_state(intel_i810_private.i810_dev); | ||
1964 | if (intel_i830_private.i830_dev) | ||
1965 | pci_restore_state(intel_i830_private.i830_dev); | ||
1966 | |||
1930 | if (bridge->driver == &intel_generic_driver) | 1967 | if (bridge->driver == &intel_generic_driver) |
1931 | intel_configure(); | 1968 | intel_configure(); |
1932 | else if (bridge->driver == &intel_850_driver) | 1969 | else if (bridge->driver == &intel_850_driver) |
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index d73be4c2db8a..902648db7efa 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c | |||
@@ -281,10 +281,11 @@ static int __devinit agp_sgi_init(void) | |||
281 | else | 281 | else |
282 | return 0; | 282 | return 0; |
283 | 283 | ||
284 | sgi_tioca_agp_bridges = | 284 | sgi_tioca_agp_bridges = kmalloc(tioca_gart_found * |
285 | (struct agp_bridge_data **)kmalloc(tioca_gart_found * | 285 | sizeof(struct agp_bridge_data *), |
286 | sizeof(struct agp_bridge_data *), | 286 | GFP_KERNEL); |
287 | GFP_KERNEL); | 287 | if (!sgi_tioca_agp_bridges) |
288 | return -ENOMEM; | ||
288 | 289 | ||
289 | j = 0; | 290 | j = 0; |
290 | list_for_each_entry(info, &tioca_list, ca_list) { | 291 | list_for_each_entry(info, &tioca_list, ca_list) { |
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index c149ac9ce9a7..2ded7a280d7f 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c | |||
@@ -380,9 +380,23 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata = | |||
380 | /* P4M800CE */ | 380 | /* P4M800CE */ |
381 | { | 381 | { |
382 | .device_id = PCI_DEVICE_ID_VIA_P4M800CE, | 382 | .device_id = PCI_DEVICE_ID_VIA_P4M800CE, |
383 | .chipset_name = "P4M800CE", | 383 | .chipset_name = "VT3314", |
384 | }, | ||
385 | /* CX700 */ | ||
386 | { | ||
387 | .device_id = PCI_DEVICE_ID_VIA_CX700, | ||
388 | .chipset_name = "CX700", | ||
389 | }, | ||
390 | /* VT3336 */ | ||
391 | { | ||
392 | .device_id = PCI_DEVICE_ID_VIA_VT3336, | ||
393 | .chipset_name = "VT3336", | ||
394 | }, | ||
395 | /* P4M890 */ | ||
396 | { | ||
397 | .device_id = PCI_DEVICE_ID_VIA_P4M890, | ||
398 | .chipset_name = "P4M890", | ||
384 | }, | 399 | }, |
385 | |||
386 | { }, /* dummy final entry, always present */ | 400 | { }, /* dummy final entry, always present */ |
387 | }; | 401 | }; |
388 | 402 | ||
@@ -524,6 +538,9 @@ static const struct pci_device_id agp_via_pci_table[] = { | |||
524 | ID(PCI_DEVICE_ID_VIA_83_87XX_1), | 538 | ID(PCI_DEVICE_ID_VIA_83_87XX_1), |
525 | ID(PCI_DEVICE_ID_VIA_3296_0), | 539 | ID(PCI_DEVICE_ID_VIA_3296_0), |
526 | ID(PCI_DEVICE_ID_VIA_P4M800CE), | 540 | ID(PCI_DEVICE_ID_VIA_P4M800CE), |
541 | ID(PCI_DEVICE_ID_VIA_CX700), | ||
542 | ID(PCI_DEVICE_ID_VIA_VT3336), | ||
543 | ID(PCI_DEVICE_ID_VIA_P4M890), | ||
527 | { } | 544 | { } |
528 | }; | 545 | }; |
529 | 546 | ||