Commit b45aba16 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] 2.5.54 AGP driver fixes for x86-64

This is just to make x86-64 boot with IOMMU and compiled in AGP driver
again.  Previously both AGP and the IOMMU code would set up an aperture,
with AGP being winner, messing up pci_map_*.

This is needed for the x86-64 update for 2.5.54 I sent earlier.

Actually using /dev/agpgart still corrupts memory unfortunately, haven't
tracked that down yet.

I also commented on some (usually 64bit, but at least one 32bit) bugs in
the driver too.

These changes should be all nops on i386.

 - Export amd k8 init function for x86-64.  It needs to be called early
   by the iommu code.  Add some comments to warn about about that (the
   upcoming VIA and SIS K8 chipsets will have the same problem)
 - Declare gatt table as u32 following the AGP spec.
 - Comment some bugs.
parent 717db2f9
...@@ -128,8 +128,8 @@ struct agp_bridge_data { ...@@ -128,8 +128,8 @@ struct agp_bridge_data {
void *dev_private_data; void *dev_private_data;
struct pci_dev *dev; struct pci_dev *dev;
struct gatt_mask *masks; struct gatt_mask *masks;
unsigned long *gatt_table; u32 *gatt_table;
unsigned long *gatt_table_real; u32 *gatt_table_real;
unsigned long scratch_page; unsigned long scratch_page;
unsigned long gart_bus_addr; unsigned long gart_bus_addr;
unsigned long gatt_bus_addr; unsigned long gatt_bus_addr;
......
...@@ -8,6 +8,12 @@ ...@@ -8,6 +8,12 @@
* removed now). * removed now).
*/ */
/*
* On x86-64 the AGP driver needs to be initialized early by the IOMMU
* code. When you use this driver as a template for a new K8 AGP bridge
* driver don't forget to change arch/x86_64/kernel/pci-gart.c too -AK.
*/
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -63,7 +69,8 @@ static int x86_64_insert_memory(agp_memory * mem, off_t pg_start, int type) ...@@ -63,7 +69,8 @@ static int x86_64_insert_memory(agp_memory * mem, off_t pg_start, int type)
return -EINVAL; return -EINVAL;
/* Make sure we can fit the range in the gatt table. */ /* Make sure we can fit the range in the gatt table. */
if ((pg_start + mem->page_count) > num_entries) /* FIXME: could wrap */
if (((unsigned long)pg_start + mem->page_count) > num_entries)
return -EINVAL; return -EINVAL;
j = pg_start; j = pg_start;
...@@ -512,7 +519,7 @@ static struct __initdata pci_driver agp_amdk8_pci_driver = { ...@@ -512,7 +519,7 @@ static struct __initdata pci_driver agp_amdk8_pci_driver = {
.probe = agp_amdk8_probe, .probe = agp_amdk8_probe,
}; };
static int __init agp_amdk8_init(void) int __init agp_amdk8_init(void)
{ {
int ret_val; int ret_val;
...@@ -531,8 +538,12 @@ static void __exit agp_amdk8_cleanup(void) ...@@ -531,8 +538,12 @@ static void __exit agp_amdk8_cleanup(void)
pci_unregister_driver(&agp_amdk8_pci_driver); pci_unregister_driver(&agp_amdk8_pci_driver);
} }
/* On x86-64 the PCI driver needs to initialize this driver early
for the IOMMU, so it has to be called via a backdoor. */
#ifndef CONFIG_GART_IOMMU
module_init(agp_amdk8_init); module_init(agp_amdk8_init);
module_exit(agp_amdk8_cleanup); module_exit(agp_amdk8_cleanup);
#endif
MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>"); MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
MODULE_LICENSE("GPL and additional rights"); MODULE_LICENSE("GPL and additional rights");
......
...@@ -469,7 +469,7 @@ int agp_generic_create_gatt_table(void) ...@@ -469,7 +469,7 @@ int agp_generic_create_gatt_table(void)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
SetPageReserved(page); SetPageReserved(page);
agp_bridge.gatt_table_real = (unsigned long *) table; agp_bridge.gatt_table_real = (u32 *) table;
agp_gatt_table = (void *)table; agp_gatt_table = (void *)table;
CACHE_FLUSH(); CACHE_FLUSH();
agp_bridge.gatt_table = ioremap_nocache(virt_to_phys(table), agp_bridge.gatt_table = ioremap_nocache(virt_to_phys(table),
...@@ -486,6 +486,7 @@ int agp_generic_create_gatt_table(void) ...@@ -486,6 +486,7 @@ int agp_generic_create_gatt_table(void)
} }
agp_bridge.gatt_bus_addr = virt_to_phys(agp_bridge.gatt_table_real); agp_bridge.gatt_bus_addr = virt_to_phys(agp_bridge.gatt_table_real);
/* AK: bogus, should encode addresses > 4GB */
for (i = 0; i < num_entries; i++) for (i = 0; i < num_entries; i++)
agp_bridge.gatt_table[i] = (unsigned long) agp_bridge.scratch_page; agp_bridge.gatt_table[i] = (unsigned long) agp_bridge.scratch_page;
...@@ -586,6 +587,7 @@ int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type) ...@@ -586,6 +587,7 @@ int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type)
return -EINVAL; return -EINVAL;
} }
/* AK: could wrap */
if ((pg_start + mem->page_count) > num_entries) if ((pg_start + mem->page_count) > num_entries)
return -EINVAL; return -EINVAL;
...@@ -618,6 +620,8 @@ int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, int type) ...@@ -618,6 +620,8 @@ int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, int type)
/* The generic routines know nothing of memory types */ /* The generic routines know nothing of memory types */
return -EINVAL; return -EINVAL;
} }
/* AK: bogus, should encode addresses > 4GB */
for (i = pg_start; i < (mem->page_count + pg_start); i++) { for (i = pg_start; i < (mem->page_count + pg_start); i++) {
agp_bridge.gatt_table[i] = agp_bridge.gatt_table[i] =
(unsigned long) agp_bridge.scratch_page; (unsigned long) agp_bridge.scratch_page;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment