Commit a5797c1f authored by Dave Jones's avatar Dave Jones

Merge bk://linux-dj.bkbits.net/agpgart

into delerium.codemonkey.org.uk:/mnt/data/src/bk/agpgart
parents 20e743bb 6cf5f82c
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#define AMD_TLBFLUSH 0x0c /* In mmio region (32-bit register) */ #define AMD_TLBFLUSH 0x0c /* In mmio region (32-bit register) */
#define AMD_CACHEENTRY 0x10 /* In mmio region (32-bit register) */ #define AMD_CACHEENTRY 0x10 /* In mmio region (32-bit register) */
static struct pci_device_id agp_amdk7_pci_table[];
struct amd_page_map { struct amd_page_map {
unsigned long *real; unsigned long *real;
unsigned long *remapped; unsigned long *remapped;
...@@ -41,7 +43,7 @@ static int amd_create_page_map(struct amd_page_map *page_map) ...@@ -41,7 +43,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
SetPageReserved(virt_to_page(page_map->real)); SetPageReserved(virt_to_page(page_map->real));
global_cache_flush(); global_cache_flush();
page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
PAGE_SIZE); PAGE_SIZE);
if (page_map->remapped == NULL) { if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real)); ClearPageReserved(virt_to_page(page_map->real));
...@@ -90,7 +92,7 @@ static int amd_create_gatt_pages(int nr_tables) ...@@ -90,7 +92,7 @@ static int amd_create_gatt_pages(int nr_tables)
int retval = 0; int retval = 0;
int i; int i;
tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *), tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *),
GFP_KERNEL); GFP_KERNEL);
if (tables == NULL) if (tables == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -124,7 +126,7 @@ static int amd_create_gatt_pages(int nr_tables) ...@@ -124,7 +126,7 @@ static int amd_create_gatt_pages(int nr_tables)
#define GET_PAGE_DIR_OFF(addr) (addr >> 22) #define GET_PAGE_DIR_OFF(addr) (addr >> 22)
#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ #define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr)) GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr))
#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
#define GET_GATT(addr) (amd_irongate_private.gatt_pages[\ #define GET_GATT(addr) (amd_irongate_private.gatt_pages[\
GET_PAGE_DIR_IDX(addr)]->remapped) GET_PAGE_DIR_IDX(addr)]->remapped)
...@@ -174,7 +176,7 @@ static int amd_create_gatt_table(void) ...@@ -174,7 +176,7 @@ static int amd_create_gatt_table(void)
static int amd_free_gatt_table(void) static int amd_free_gatt_table(void)
{ {
struct amd_page_map page_dir; struct amd_page_map page_dir;
page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
page_dir.remapped = (unsigned long *)agp_bridge->gatt_table; page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
...@@ -224,9 +226,9 @@ static int amd_irongate_configure(void) ...@@ -224,9 +226,9 @@ static int amd_irongate_configure(void)
/* Write the Sync register */ /* Write the Sync register */
pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL, 0x80); pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL, 0x80);
/* Set indexing mode */ /* Set indexing mode */
pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL2, 0x00); pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL2, 0x00);
/* Write the enable register */ /* Write the enable register */
enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE); enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE);
...@@ -394,7 +396,6 @@ static struct agp_device_ids amd_agp_device_ids[] __devinitdata = ...@@ -394,7 +396,6 @@ static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
static int __devinit agp_amdk7_probe(struct pci_dev *pdev, static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct agp_device_ids *devs = amd_agp_device_ids;
struct agp_bridge_data *bridge; struct agp_bridge_data *bridge;
u8 cap_ptr; u8 cap_ptr;
int j; int j;
...@@ -403,19 +404,10 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, ...@@ -403,19 +404,10 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
if (!cap_ptr) if (!cap_ptr)
return -ENODEV; return -ENODEV;
for (j = 0; devs[j].chipset_name; j++) { j = ent - agp_amdk7_pci_table;
if (pdev->device == devs[j].device_id) { printk(KERN_INFO PFX "Detected AMD %s chipset\n",
printk (KERN_INFO PFX "Detected AMD %s chipset\n", amd_agp_device_ids[j].chipset_name);
devs[j].chipset_name);
goto found;
}
}
printk(KERN_ERR PFX "Unsupported AMD chipset (device id: %04x)\n",
pdev->device);
return -ENODEV;
found:
bridge = agp_alloc_bridge(); bridge = agp_alloc_bridge();
if (!bridge) if (!bridge)
return -ENOMEM; return -ENOMEM;
...@@ -442,12 +434,29 @@ static void __devexit agp_amdk7_remove(struct pci_dev *pdev) ...@@ -442,12 +434,29 @@ static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
agp_put_bridge(bridge); agp_put_bridge(bridge);
} }
/* must be the same order as name table above */
static struct pci_device_id agp_amdk7_pci_table[] = { static struct pci_device_id agp_amdk7_pci_table[] = {
{ {
.class = (PCI_CLASS_BRIDGE_HOST << 8), .class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0, .class_mask = ~0,
.vendor = PCI_VENDOR_ID_AMD, .vendor = PCI_VENDOR_ID_AMD,
.device = PCI_ANY_ID, .device = PCI_DEVICE_ID_AMD_FE_GATE_7006,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_AMD,
.device = PCI_DEVICE_ID_AMD_FE_GATE_700E,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_AMD,
.device = PCI_DEVICE_ID_AMD_FE_GATE_700C,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
}, },
......
/* /*
* Copyright 2001-2003 SuSE Labs. * Copyright 2001-2003 SuSE Labs.
* Distributed under the GNU public license, v2. * Distributed under the GNU public license, v2.
* *
* This is a GART driver for the AMD Opteron/Athlon64 on-CPU northbridge. * This is a GART driver for the AMD Opteron/Athlon64 on-CPU northbridge.
* It also includes support for the AMD 8151 AGP bridge, * It also includes support for the AMD 8151 AGP bridge,
* although it doesn't actually do much, as all the real * although it doesn't actually do much, as all the real
...@@ -194,7 +194,7 @@ static u64 amd64_configure (struct pci_dev *hammer, u64 gatt_table) ...@@ -194,7 +194,7 @@ static u64 amd64_configure (struct pci_dev *hammer, u64 gatt_table)
/* keep CPU's coherent. */ /* keep CPU's coherent. */
flush_amd64_tlb (hammer); flush_amd64_tlb (hammer);
return aper_base; return aper_base;
} }
...@@ -261,53 +261,53 @@ struct agp_bridge_driver amd_8151_driver = { ...@@ -261,53 +261,53 @@ struct agp_bridge_driver amd_8151_driver = {
/* Some basic sanity checks for the aperture. */ /* Some basic sanity checks for the aperture. */
static int __devinit aperture_valid(u64 aper, u32 size) static int __devinit aperture_valid(u64 aper, u32 size)
{ {
u32 pfn, c; u32 pfn, c;
if (aper == 0) { if (aper == 0) {
printk(KERN_ERR PFX "No aperture\n"); printk(KERN_ERR PFX "No aperture\n");
return 0; return 0;
} }
if (size < 32*1024*1024) { if (size < 32*1024*1024) {
printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20); printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20);
return 0; return 0;
} }
if (aper + size > 0xffffffff) { if (aper + size > 0xffffffff) {
printk(KERN_ERR PFX "Aperture out of bounds\n"); printk(KERN_ERR PFX "Aperture out of bounds\n");
return 0; return 0;
} }
pfn = aper >> PAGE_SHIFT; pfn = aper >> PAGE_SHIFT;
for (c = 0; c < size/PAGE_SIZE; c++) { for (c = 0; c < size/PAGE_SIZE; c++) {
if (!pfn_valid(pfn + c)) if (!pfn_valid(pfn + c))
break; break;
if (!PageReserved(pfn_to_page(pfn + c))) { if (!PageReserved(pfn_to_page(pfn + c))) {
printk(KERN_ERR PFX "Aperture pointing to RAM\n"); printk(KERN_ERR PFX "Aperture pointing to RAM\n");
return 0; return 0;
} }
} }
/* Request the Aperture. This catches cases when someone else /* Request the Aperture. This catches cases when someone else
already put a mapping in there - happens with some very broken BIOS already put a mapping in there - happens with some very broken BIOS
Maybe better to use pci_assign_resource/pci_enable_device instead trusting Maybe better to use pci_assign_resource/pci_enable_device instead
the bridges? */ trusting the bridges? */
if (!aperture_resource && if (!aperture_resource &&
!(aperture_resource = request_mem_region(aper, size, "aperture"))) { !(aperture_resource = request_mem_region(aper, size, "aperture"))) {
printk(KERN_ERR PFX "Aperture conflicts with PCI mapping.\n"); printk(KERN_ERR PFX "Aperture conflicts with PCI mapping.\n");
return 0; return 0;
} }
return 1; return 1;
} }
/* /*
* W*s centric BIOS sometimes only set up the aperture in the AGP * W*s centric BIOS sometimes only set up the aperture in the AGP
* bridge, not the northbridge. On AMD64 this is handled early * bridge, not the northbridge. On AMD64 this is handled early
* in aperture.c, but when GART_IOMMU is not enabled or we run * in aperture.c, but when GART_IOMMU is not enabled or we run
* on a 32bit kernel this needs to be redone. * on a 32bit kernel this needs to be redone.
* Unfortunately it is impossible to fix the aperture here because it's too late * Unfortunately it is impossible to fix the aperture here because it's too late
* to allocate that much memory. But at least error out cleanly instead of * to allocate that much memory. But at least error out cleanly instead of
* crashing. * crashing.
*/ */
static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
u16 cap) u16 cap)
{ {
u32 aper_low, aper_hi; u32 aper_low, aper_hi;
...@@ -316,38 +316,38 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, ...@@ -316,38 +316,38 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
u32 nb_order, nb_base; u32 nb_order, nb_base;
u16 apsize; u16 apsize;
pci_read_config_dword(nb, 0x90, &nb_order); pci_read_config_dword(nb, 0x90, &nb_order);
nb_order = (nb_order >> 1) & 7; nb_order = (nb_order >> 1) & 7;
pci_read_config_dword(nb, 0x94, &nb_base); pci_read_config_dword(nb, 0x94, &nb_base);
nb_aper = nb_base << 25; nb_aper = nb_base << 25;
if (aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) { if (aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) {
return 0; return 0;
} }
/* Northbridge seems to contain crap. Try the AGP bridge. */ /* Northbridge seems to contain crap. Try the AGP bridge. */
pci_read_config_word(agp, cap+0x14, &apsize); pci_read_config_word(agp, cap+0x14, &apsize);
if (apsize == 0xffff) if (apsize == 0xffff)
return -1; return -1;
apsize &= 0xfff; apsize &= 0xfff;
/* Some BIOS use weird encodings not in the AGPv3 table. */ /* Some BIOS use weird encodings not in the AGPv3 table. */
if (apsize & 0xff) if (apsize & 0xff)
apsize |= 0xf00; apsize |= 0xf00;
order = 7 - hweight16(apsize); order = 7 - hweight16(apsize);
pci_read_config_dword(agp, 0x10, &aper_low); pci_read_config_dword(agp, 0x10, &aper_low);
pci_read_config_dword(agp, 0x14, &aper_hi); pci_read_config_dword(agp, 0x14, &aper_hi);
aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order); printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order);
if (order < 0 || !aperture_valid(aper, (32*1024*1024)<<order)) if (order < 0 || !aperture_valid(aper, (32*1024*1024)<<order))
return -1; return -1;
pci_write_config_dword(nb, 0x90, order << 1); pci_write_config_dword(nb, 0x90, order << 1);
pci_write_config_dword(nb, 0x94, aper >> 25); pci_write_config_dword(nb, 0x94, aper >> 25);
return 0; return 0;
} }
static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
{ {
...@@ -355,19 +355,19 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) ...@@ -355,19 +355,19 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
int i = 0; int i = 0;
/* cache pci_devs of northbridges. */ /* cache pci_devs of northbridges. */
while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev))
!= NULL) { != NULL) {
if (i == MAX_HAMMER_GARTS) { if (i == MAX_HAMMER_GARTS) {
printk(KERN_ERR PFX "Too many northbridges for AGP\n"); printk(KERN_ERR PFX "Too many northbridges for AGP\n");
return -1; return -1;
} }
if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) {
printk(KERN_ERR PFX "No usable aperture found.\n"); printk(KERN_ERR PFX "No usable aperture found.\n");
#ifdef __x86_64__ #ifdef __x86_64__
/* should port this to i386 */ /* should port this to i386 */
printk(KERN_ERR PFX "Consider rebooting with iommu=memaper=2 to get a good aperture.\n"); printk(KERN_ERR PFX "Consider rebooting with iommu=memaper=2 to get a good aperture.\n");
#endif #endif
return -1; return -1;
} }
hammers[i++] = loop_dev; hammers[i++] = loop_dev;
} }
...@@ -377,8 +377,7 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) ...@@ -377,8 +377,7 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
/* Handle AMD 8151 quirks */ /* Handle AMD 8151 quirks */
static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge) static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
{
{
char *revstring; char *revstring;
u8 rev_id; u8 rev_id;
...@@ -417,12 +416,12 @@ static struct aper_size_info_32 nforce3_sizes[5] = ...@@ -417,12 +416,12 @@ static struct aper_size_info_32 nforce3_sizes[5] =
/* Handle shadow device of the Nvidia NForce3 */ /* Handle shadow device of the Nvidia NForce3 */
/* CHECK-ME original 2.4 version set up some IORRs. Check if that is needed. */ /* CHECK-ME original 2.4 version set up some IORRs. Check if that is needed. */
static int __devinit nforce3_agp_init(struct pci_dev *pdev) static int __devinit nforce3_agp_init(struct pci_dev *pdev)
{ {
u32 tmp, apbase, apbar, aplimit; u32 tmp, apbase, apbar, aplimit;
struct pci_dev *dev1; struct pci_dev *dev1;
int i; int i;
unsigned size = amd64_fetch_size(); unsigned size = amd64_fetch_size();
printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n"); printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n");
...@@ -432,17 +431,17 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev) ...@@ -432,17 +431,17 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
"nForce3 chipset, but could not find " "nForce3 chipset, but could not find "
"the secondary device.\n"); "the secondary device.\n");
return -ENODEV; return -ENODEV;
} }
for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++) for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++)
if (nforce3_sizes[i].size == size) if (nforce3_sizes[i].size == size)
break; break;
if (i == ARRAY_SIZE(nforce3_sizes)) { if (i == ARRAY_SIZE(nforce3_sizes)) {
printk(KERN_INFO PFX "No NForce3 size found for %d\n", size); printk(KERN_INFO PFX "No NForce3 size found for %d\n", size);
return -ENODEV; return -ENODEV;
} }
pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp); pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp);
tmp &= ~(0xf); tmp &= ~(0xf);
tmp |= nforce3_sizes[i].size_value; tmp |= nforce3_sizes[i].size_value;
...@@ -491,8 +490,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, ...@@ -491,8 +490,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
pdev->device == PCI_DEVICE_ID_AMD_8151_0) { pdev->device == PCI_DEVICE_ID_AMD_8151_0) {
amd8151_init(pdev, bridge); amd8151_init(pdev, bridge);
} else { } else {
printk(KERN_INFO PFX "Detected AGP bridge %x\n", printk(KERN_INFO PFX "Detected AGP bridge %x\n", pdev->devfn);
pdev->devfn);
} }
bridge->driver = &amd_8151_driver; bridge->driver = &amd_8151_driver;
...@@ -507,10 +505,10 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, ...@@ -507,10 +505,10 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
return -ENODEV; return -ENODEV;
} }
if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
int ret = nforce3_agp_init(pdev); int ret = nforce3_agp_init(pdev);
if (ret) { if (ret) {
agp_put_bridge(bridge); agp_put_bridge(bridge);
return ret; return ret;
} }
} }
...@@ -523,8 +521,8 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev) ...@@ -523,8 +521,8 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev)
{ {
struct agp_bridge_data *bridge = pci_get_drvdata(pdev); struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
release_mem_region(virt_to_phys(bridge->gatt_table_real), release_mem_region(virt_to_phys(bridge->gatt_table_real),
amd64_aperture_sizes[bridge->aperture_size_idx].size); amd64_aperture_sizes[bridge->aperture_size_idx].size);
agp_remove_bridge(bridge); agp_remove_bridge(bridge);
agp_put_bridge(bridge); agp_put_bridge(bridge);
} }
...@@ -581,6 +579,15 @@ static struct pci_device_id agp_amd64_pci_table[] = { ...@@ -581,6 +579,15 @@ static struct pci_device_id agp_amd64_pci_table[] = {
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
}, },
/* SIS 755 */
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_SI,
.device = PCI_DEVICE_ID_SI_755,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{ } { }
}; };
...@@ -600,15 +607,15 @@ int __init agp_amd64_init(void) ...@@ -600,15 +607,15 @@ int __init agp_amd64_init(void)
int err = 0; int err = 0;
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
if (pci_module_init(&agp_amd64_pci_driver) > 0) { if (pci_module_init(&agp_amd64_pci_driver) > 0) {
struct pci_dev *dev; struct pci_dev *dev;
if (!agp_try_unsupported && !agp_try_unsupported_boot) { if (!agp_try_unsupported && !agp_try_unsupported_boot) {
printk(KERN_INFO PFX "No supported AGP bridge found.\n"); printk(KERN_INFO PFX "No supported AGP bridge found.\n");
#ifdef MODULE #ifdef MODULE
printk(KERN_INFO PFX "You can try agp_try_unsupported=1\n"); printk(KERN_INFO PFX "You can try agp_try_unsupported=1\n");
#else #else
printk(KERN_INFO PFX "You can boot with agp=try_unsupported\n"); printk(KERN_INFO PFX "You can boot with agp=try_unsupported\n");
#endif #endif
return -ENODEV; return -ENODEV;
} }
...@@ -622,12 +629,12 @@ int __init agp_amd64_init(void) ...@@ -622,12 +629,12 @@ int __init agp_amd64_init(void)
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev))) { while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev))) {
if (!pci_find_capability(dev, PCI_CAP_ID_AGP)) if (!pci_find_capability(dev, PCI_CAP_ID_AGP))
continue; continue;
/* Only one bridge supported right now */ /* Only one bridge supported right now */
if (agp_amd64_probe(dev, NULL) == 0) { if (agp_amd64_probe(dev, NULL) == 0) {
err = 0; err = 0;
break; break;
} }
} }
} }
return err; return err;
} }
......
...@@ -131,6 +131,7 @@ static int ati_create_gatt_pages(int nr_tables) ...@@ -131,6 +131,7 @@ static int ati_create_gatt_pages(int nr_tables)
i--; i--;
} }
kfree (tables); kfree (tables);
tables = NULL;
retval = -ENOMEM; retval = -ENOMEM;
break; break;
} }
......
...@@ -238,11 +238,14 @@ void agp_put_bridge(struct agp_bridge_data *bridge) ...@@ -238,11 +238,14 @@ void agp_put_bridge(struct agp_bridge_data *bridge)
} }
EXPORT_SYMBOL(agp_put_bridge); EXPORT_SYMBOL(agp_put_bridge);
int agp_add_bridge(struct agp_bridge_data *bridge) int agp_add_bridge(struct agp_bridge_data *bridge)
{ {
int error; int error;
if (agp_off)
return -ENODEV;
if (!bridge->dev) { if (!bridge->dev) {
printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n"); printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
return -EINVAL; return -EINVAL;
...@@ -308,9 +311,9 @@ EXPORT_SYMBOL(agp_try_unsupported_boot); ...@@ -308,9 +311,9 @@ EXPORT_SYMBOL(agp_try_unsupported_boot);
static int __init agp_init(void) static int __init agp_init(void)
{ {
if (!agp_off) if (!agp_off)
printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n", printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n",
AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
return 0; return 0;
} }
...@@ -325,7 +328,7 @@ static __init int agp_setup(char *s) ...@@ -325,7 +328,7 @@ static __init int agp_setup(char *s)
agp_off = 1; agp_off = 1;
if (!strcmp(s,"try_unsupported")) if (!strcmp(s,"try_unsupported"))
agp_try_unsupported_boot = 1; agp_try_unsupported_boot = 1;
return 1; return 1;
} }
__setup("agp=", agp_setup); __setup("agp=", agp_setup);
#endif #endif
......
...@@ -1233,7 +1233,7 @@ static int find_i810(u16 device, const char *name) ...@@ -1233,7 +1233,7 @@ static int find_i810(u16 device, const char *name)
name); name);
return 0; return 0;
} }
intel_i810_private.i810_dev = i810_dev; intel_i810_private.i810_dev = i810_dev;
return 1; return 1;
} }
...@@ -1382,8 +1382,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, ...@@ -1382,8 +1382,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
name = "E7205"; name = "E7205";
break; break;
default: default:
printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)\n", if (cap_ptr)
printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n",
pdev->device); pdev->device);
agp_put_bridge(bridge);
return -ENODEV; return -ENODEV;
}; };
...@@ -1406,7 +1408,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, ...@@ -1406,7 +1408,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
if (!r->start && r->end) { if (!r->start && r->end) {
if(pci_assign_resource(pdev, 0)) { if(pci_assign_resource(pdev, 0)) {
printk(KERN_ERR PFX "could not assign resource 0\n"); printk(KERN_ERR PFX "could not assign resource 0\n");
return (-ENODEV); agp_put_bridge(bridge);
return -ENODEV;
} }
} }
...@@ -1417,7 +1420,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, ...@@ -1417,7 +1420,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
*/ */
if (pci_enable_device(pdev)) { if (pci_enable_device(pdev)) {
printk(KERN_ERR PFX "Unable to Enable PCI device\n"); printk(KERN_ERR PFX "Unable to Enable PCI device\n");
return (-ENODEV); agp_put_bridge(bridge);
return -ENODEV;
} }
/* Fill in the mode register */ /* Fill in the mode register */
...@@ -1442,14 +1446,11 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) ...@@ -1442,14 +1446,11 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
agp_put_bridge(bridge); agp_put_bridge(bridge);
} }
static int agp_intel_suspend(struct pci_dev *dev, u32 state)
{
return 0;
}
static int agp_intel_resume(struct pci_dev *pdev) static int agp_intel_resume(struct pci_dev *pdev)
{ {
struct agp_bridge_data *bridge = pci_get_drvdata(pdev); struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
pci_restore_state(pdev, pdev->saved_config_space);
if (bridge->driver == &intel_generic_driver) if (bridge->driver == &intel_generic_driver)
intel_configure(); intel_configure();
...@@ -1462,14 +1463,36 @@ static int agp_intel_resume(struct pci_dev *pdev) ...@@ -1462,14 +1463,36 @@ static int agp_intel_resume(struct pci_dev *pdev)
} }
static struct pci_device_id agp_intel_pci_table[] = { static struct pci_device_id agp_intel_pci_table[] = {
{ #define ID(x) \
.class = (PCI_CLASS_BRIDGE_HOST << 8), { \
.class_mask = ~0, .class = (PCI_CLASS_BRIDGE_HOST << 8), \
.vendor = PCI_VENDOR_ID_INTEL, .class_mask = ~0, \
.device = PCI_ANY_ID, .vendor = PCI_VENDOR_ID_INTEL, \
.subvendor = PCI_ANY_ID, .device = x, \
.subdevice = PCI_ANY_ID, .subvendor = PCI_ANY_ID, \
}, .subdevice = PCI_ANY_ID, \
}
ID(PCI_DEVICE_ID_INTEL_82443LX_0),
ID(PCI_DEVICE_ID_INTEL_82443BX_0),
ID(PCI_DEVICE_ID_INTEL_82443GX_0),
ID(PCI_DEVICE_ID_INTEL_82810_MC1),
ID(PCI_DEVICE_ID_INTEL_82810_MC3),
ID(PCI_DEVICE_ID_INTEL_82810E_MC),
ID(PCI_DEVICE_ID_INTEL_82815_MC),
ID(PCI_DEVICE_ID_INTEL_82820_HB),
ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
ID(PCI_DEVICE_ID_INTEL_82830_HB),
ID(PCI_DEVICE_ID_INTEL_82840_HB),
ID(PCI_DEVICE_ID_INTEL_82845_HB),
ID(PCI_DEVICE_ID_INTEL_82845G_HB),
ID(PCI_DEVICE_ID_INTEL_82850_HB),
ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
ID(PCI_DEVICE_ID_INTEL_82860_HB),
ID(PCI_DEVICE_ID_INTEL_82865_HB),
ID(PCI_DEVICE_ID_INTEL_82875_HB),
ID(PCI_DEVICE_ID_INTEL_7505_0),
ID(PCI_DEVICE_ID_INTEL_7205_0),
{ } { }
}; };
...@@ -1480,7 +1503,6 @@ static struct pci_driver agp_intel_pci_driver = { ...@@ -1480,7 +1503,6 @@ static struct pci_driver agp_intel_pci_driver = {
.id_table = agp_intel_pci_table, .id_table = agp_intel_pci_table,
.probe = agp_intel_probe, .probe = agp_intel_probe,
.remove = agp_intel_remove, .remove = agp_intel_remove,
.suspend = agp_intel_suspend,
.resume = agp_intel_resume, .resume = agp_intel_resume,
}; };
......
...@@ -491,10 +491,9 @@ static int __devinit agp_intelmch_probe(struct pci_dev *pdev, ...@@ -491,10 +491,9 @@ static int __devinit agp_intelmch_probe(struct pci_dev *pdev,
char *name = "(unknown)"; char *name = "(unknown)";
u8 cap_ptr = 0; u8 cap_ptr = 0;
if (!boot_cpu_has(X86_FEATURE_LM))
return -ENODEV;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
if (!cap_ptr)
return -ENODEV;
bridge = agp_alloc_bridge(); bridge = agp_alloc_bridge();
if (!bridge) if (!bridge)
...@@ -570,14 +569,11 @@ static void __devexit agp_intelmch_remove(struct pci_dev *pdev) ...@@ -570,14 +569,11 @@ static void __devexit agp_intelmch_remove(struct pci_dev *pdev)
agp_put_bridge(bridge); agp_put_bridge(bridge);
} }
static int agp_intelmch_suspend(struct pci_dev *dev, u32 state)
{
return 0;
}
static int agp_intelmch_resume(struct pci_dev *pdev) static int agp_intelmch_resume(struct pci_dev *pdev)
{ {
struct agp_bridge_data *bridge = pci_get_drvdata(pdev); struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
pci_restore_state(pdev, pdev->saved_config_space);
if (bridge->driver == &intel_845_driver) if (bridge->driver == &intel_845_driver)
intel_845_configure(); intel_845_configure();
...@@ -590,7 +586,15 @@ static struct pci_device_id agp_intelmch_pci_table[] = { ...@@ -590,7 +586,15 @@ static struct pci_device_id agp_intelmch_pci_table[] = {
.class = (PCI_CLASS_BRIDGE_HOST << 8), .class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0, .class_mask = ~0,
.vendor = PCI_VENDOR_ID_INTEL, .vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_ANY_ID, .device = PCI_DEVICE_ID_INTEL_82865_HB,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_82875_HB,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
}, },
...@@ -604,7 +608,6 @@ static struct pci_driver agp_intelmch_pci_driver = { ...@@ -604,7 +608,6 @@ static struct pci_driver agp_intelmch_pci_driver = {
.id_table = agp_intelmch_pci_table, .id_table = agp_intelmch_pci_table,
.probe = agp_intelmch_probe, .probe = agp_intelmch_probe,
.remove = agp_intelmch_remove, .remove = agp_intelmch_remove,
.suspend = agp_intelmch_suspend,
.resume = agp_intelmch_resume, .resume = agp_intelmch_resume,
}; };
......
...@@ -380,7 +380,15 @@ static struct pci_device_id agp_nvidia_pci_table[] = { ...@@ -380,7 +380,15 @@ static struct pci_device_id agp_nvidia_pci_table[] = {
.class = (PCI_CLASS_BRIDGE_HOST << 8), .class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0, .class_mask = ~0,
.vendor = PCI_VENDOR_ID_NVIDIA, .vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_ANY_ID, .device = PCI_DEVICE_ID_NVIDIA_NFORCE,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NFORCE2,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
}, },
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#define SIS_TLBCNTRL 0x97 #define SIS_TLBCNTRL 0x97
#define SIS_TLBFLUSH 0x98 #define SIS_TLBFLUSH 0x98
static int __devinitdata agp_sis_force_delay = 0;
static int __devinitdata agp_sis_agp_spec = -1;
static int sis_fetch_size(void) static int sis_fetch_size(void)
{ {
...@@ -67,7 +69,7 @@ static void sis_cleanup(void) ...@@ -67,7 +69,7 @@ static void sis_cleanup(void)
(previous_size->size_value & ~(0x03))); (previous_size->size_value & ~(0x03)));
} }
static void sis_648_enable(u32 mode) static void sis_delayed_enable(u32 mode)
{ {
struct pci_dev *device = NULL; struct pci_dev *device = NULL;
u32 command; u32 command;
...@@ -94,13 +96,12 @@ static void sis_648_enable(u32 mode) ...@@ -94,13 +96,12 @@ static void sis_648_enable(u32 mode)
pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
/* /*
* Weird: on 648(fx) and 746(fx) chipsets any rate change in the target * Weird: on some sis chipsets any rate change in the target
* command register triggers a 5ms screwup during which the master * command register triggers a 5ms screwup during which the master
* cannot be configured * cannot be configured
*/ */
if (device->device == PCI_DEVICE_ID_SI_648 || if (device->device == agp_bridge->dev->device) {
device->device == PCI_DEVICE_ID_SI_746) { printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n");
printk(KERN_INFO PFX "SiS chipset with AGP problems detected. Giving bridge time to recover.\n");
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout (1+(HZ*10)/1000); schedule_timeout (1+(HZ*10)/1000);
} }
...@@ -223,28 +224,35 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata = ...@@ -223,28 +224,35 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
}; };
// chipsets that require the 'delay hack'
static int sis_broken_chipsets[] __devinitdata = {
PCI_DEVICE_ID_SI_648,
PCI_DEVICE_ID_SI_746,
0 // terminator
};
static void __devinit sis_get_driver(struct agp_bridge_data *bridge) static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
{ {
if (bridge->dev->device == PCI_DEVICE_ID_SI_648) { int i;
sis_driver.agp_enable=sis_648_enable;
if (agp_bridge->major_version == 3) {
sis_driver.aperture_sizes = agp3_generic_sizes;
sis_driver.size_type = U16_APER_SIZE;
sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES;
sis_driver.configure = agp3_generic_configure;
sis_driver.fetch_size = agp3_generic_fetch_size;
sis_driver.cleanup = agp3_generic_cleanup;
sis_driver.tlb_flush = agp3_generic_tlbflush;
}
}
if (bridge->dev->device == PCI_DEVICE_ID_SI_746) { for(i=0; sis_broken_chipsets[i]!=0; ++i)
/* if(bridge->dev->device==sis_broken_chipsets[i])
* We don't know enough about the 746 to enable it properly. break;
* Though we do know that it needs the 'delay' hack to settle
* after changing modes. if(sis_broken_chipsets[i] || agp_sis_force_delay)
*/ sis_driver.agp_enable=sis_delayed_enable;
sis_driver.agp_enable=sis_648_enable;
// sis chipsets that indicate less than agp3.5
// are not actually fully agp3 compliant
if ((agp_bridge->major_version == 3 && agp_bridge->minor_version >= 5
&& agp_sis_agp_spec!=0) || agp_sis_agp_spec==1) {
sis_driver.aperture_sizes = agp3_generic_sizes;
sis_driver.size_type = U16_APER_SIZE;
sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES;
sis_driver.configure = agp3_generic_configure;
sis_driver.fetch_size = agp3_generic_fetch_size;
sis_driver.cleanup = agp3_generic_cleanup;
sis_driver.tlb_flush = agp3_generic_tlbflush;
} }
} }
...@@ -335,4 +343,8 @@ static void __exit agp_sis_cleanup(void) ...@@ -335,4 +343,8 @@ static void __exit agp_sis_cleanup(void)
module_init(agp_sis_init); module_init(agp_sis_init);
module_exit(agp_sis_cleanup); module_exit(agp_sis_cleanup);
MODULE_PARM(agp_sis_force_delay,"i");
MODULE_PARM_DESC(agp_sis_force_delay,"forces sis delay hack");
MODULE_PARM(agp_sis_agp_spec,"i");
MODULE_PARM_DESC(agp_sis_agp_spec,"0=force sis init, 1=force generic agp3 init, default: autodetect");
MODULE_LICENSE("GPL and additional rights"); MODULE_LICENSE("GPL and additional rights");
...@@ -248,26 +248,13 @@ static int serverworks_fetch_size(void) ...@@ -248,26 +248,13 @@ static int serverworks_fetch_size(void)
*/ */
static void serverworks_tlbflush(struct agp_memory *temp) static void serverworks_tlbflush(struct agp_memory *temp)
{ {
unsigned long end; OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 1);
while(INREG8(serverworks_private.registers, SVWRKS_POSTFLUSH) == 1)
OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01); cpu_relax();
end = jiffies + 3*HZ;
while(INREG8(serverworks_private.registers, OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 1);
SVWRKS_POSTFLUSH) == 0x01) { while(INREG32(serverworks_private.registers, SVWRKS_DIRFLUSH) == 1)
if((signed)(end - jiffies) <= 0) { cpu_relax();
printk(KERN_ERR PFX "Posted write buffer flush took more"
"then 3 seconds\n");
}
}
OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001);
end = jiffies + 3*HZ;
while(INREG32(serverworks_private.registers,
SVWRKS_DIRFLUSH) == 0x00000001) {
if((signed)(end - jiffies) <= 0) {
printk(KERN_ERR PFX "TLB flush took more"
"then 3 seconds\n");
}
}
} }
static int serverworks_configure(void) static int serverworks_configure(void)
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <linux/agp_backend.h> #include <linux/agp_backend.h>
#include "agp.h" #include "agp.h"
static struct pci_device_id agp_via_pci_table[];
#define VIA_GARTCTRL 0x80 #define VIA_GARTCTRL 0x80
#define VIA_APSIZE 0x84 #define VIA_APSIZE 0x84
#define VIA_ATTBASE 0x88 #define VIA_ATTBASE 0x88
...@@ -378,20 +380,9 @@ static int __devinit agp_via_probe(struct pci_dev *pdev, ...@@ -378,20 +380,9 @@ static int __devinit agp_via_probe(struct pci_dev *pdev,
if (!cap_ptr) if (!cap_ptr)
return -ENODEV; return -ENODEV;
/* probe for known chipsets */ j = ent - agp_via_pci_table;
for (j = 0; devs[j].chipset_name; j++) { printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name);
if (pdev->device == devs[j].device_id) {
printk (KERN_INFO PFX "Detected VIA %s chipset\n",
devs[j].chipset_name);
goto found;
}
}
printk(KERN_ERR PFX "Unsupported VIA chipset (device id: %04x)\n",
pdev->device);
return -ENODEV;
found:
bridge = agp_alloc_bridge(); bridge = agp_alloc_bridge();
if (!bridge) if (!bridge)
return -ENOMEM; return -ENOMEM;
...@@ -432,15 +423,40 @@ static void __devexit agp_via_remove(struct pci_dev *pdev) ...@@ -432,15 +423,40 @@ static void __devexit agp_via_remove(struct pci_dev *pdev)
agp_put_bridge(bridge); agp_put_bridge(bridge);
} }
/* must be the same order as name table above */
static struct pci_device_id agp_via_pci_table[] = { static struct pci_device_id agp_via_pci_table[] = {
{ #define ID(x) \
.class = (PCI_CLASS_BRIDGE_HOST << 8), { \
.class_mask = ~0, .class = (PCI_CLASS_BRIDGE_HOST << 8), \
.vendor = PCI_VENDOR_ID_VIA, .class_mask = ~0, \
.device = PCI_ANY_ID, .vendor = PCI_VENDOR_ID_VIA, \
.subvendor = PCI_ANY_ID, .device = x, \
.subdevice = PCI_ANY_ID, .subvendor = PCI_ANY_ID, \
}, .subdevice = PCI_ANY_ID, \
}
ID(PCI_DEVICE_ID_VIA_82C598_0),
ID(PCI_DEVICE_ID_VIA_8501_0),
ID(PCI_DEVICE_ID_VIA_8601_0),
ID(PCI_DEVICE_ID_VIA_82C691_0),
ID(PCI_DEVICE_ID_VIA_8371_0),
ID(PCI_DEVICE_ID_VIA_8633_0),
ID(PCI_DEVICE_ID_VIA_XN266),
ID(PCI_DEVICE_ID_VIA_8361),
ID(PCI_DEVICE_ID_VIA_8363_0),
ID(PCI_DEVICE_ID_VIA_8753_0),
ID(PCI_DEVICE_ID_VIA_8367_0),
ID(PCI_DEVICE_ID_VIA_8653_0),
ID(PCI_DEVICE_ID_VIA_XM266),
ID(PCI_DEVICE_ID_VIA_862X_0),
ID(PCI_DEVICE_ID_VIA_8377_0),
ID(PCI_DEVICE_ID_VIA_8605_0),
ID(PCI_DEVICE_ID_VIA_8703_51_0),
ID(PCI_DEVICE_ID_VIA_8754C_0),
ID(PCI_DEVICE_ID_VIA_8763_0),
ID(PCI_DEVICE_ID_VIA_8378_0),
ID(PCI_DEVICE_ID_VIA_PT880),
ID(PCI_DEVICE_ID_VIA_8783_0),
ID(PCI_DEVICE_ID_VIA_PX8X0_0),
{ } { }
}; };
......
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