From d0de98fa16169562bd74913c6c9b3857f9065c79 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 31 May 2005 19:50:49 +0100 Subject: [PATCH 1/4] [PATCH] i945G patch for agpgart Attached is a small patch for i945G support against 2.6.11.11. From: Alan Hourihane Signed-off-by: Dave Jones --- drivers/char/agp/intel-agp.c | 15 +++++++++++++-- include/linux/pci_ids.h | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 8c7d727432bb..6a5047e0d333 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -418,7 +418,8 @@ static void intel_i830_init_gtt_entries(void) case I915_GMCH_GMS_STOLEN_48M: /* Check it's really I915G */ if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB) gtt_entries = MB(48) - KB(size); else gtt_entries = 0; @@ -426,7 +427,8 @@ static void intel_i830_init_gtt_entries(void) case I915_GMCH_GMS_STOLEN_64M: /* Check it's really I915G */ if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB) gtt_entries = MB(64) - KB(size); else gtt_entries = 0; @@ -1662,6 +1664,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, } name = "915GM"; break; + case PCI_DEVICE_ID_INTEL_82945G_HB: + if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) { + bridge->driver = &intel_915_driver; + } else { + bridge->driver = &intel_845_driver; + } + name = "945G"; + break; case PCI_DEVICE_ID_INTEL_7505_0: bridge->driver = &intel_7505_driver; name = "E7505"; @@ -1801,6 +1811,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_7205_0), ID(PCI_DEVICE_ID_INTEL_82915G_HB), ID(PCI_DEVICE_ID_INTEL_82915GM_HB), + ID(PCI_DEVICE_ID_INTEL_82945G_HB), { } }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index b0d6134e1ee6..18f734ec9181 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2382,6 +2382,8 @@ #define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582 #define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590 #define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592 +#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770 +#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772 #define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640 #define PCI_DEVICE_ID_INTEL_ICH6_1 0x2641 #define PCI_DEVICE_ID_INTEL_ICH6_2 0x2642 From e29b545cb153f230fbd8ff4c19bc98ab950f9f5c Mon Sep 17 00:00:00 2001 From: Michael Werner Date: Sun, 27 Mar 2005 22:08:42 -0800 Subject: [PATCH 2/4] [PATCH] sgi-agp: fixes a problem with accessing GART memory in sgi_tioca_insert_memory and sgi_tioca_remove_memory This patch fixes a problem with accessing GART memory in sgi_tioca_insert_memory and sgi_tioca_remove_memory. sgi-agp.c | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) Signed-off-by: Mike Werner Signed-off-by: Dave Jones --- drivers/char/agp/sgi-agp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index 4b3eda267976..d3aa159c9dec 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c @@ -133,11 +133,14 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start, off_t j; void *temp; struct agp_bridge_data *bridge; + u64 *table; bridge = mem->bridge; if (!bridge) return -EINVAL; + table = (u64 *)bridge->gatt_table; + temp = bridge->current_size; switch (bridge->driver->size_type) { @@ -175,7 +178,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start, j = pg_start; while (j < (pg_start + mem->page_count)) { - if (*(bridge->gatt_table + j)) + if (table[j]) return -EBUSY; j++; } @@ -186,7 +189,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start, } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - *(bridge->gatt_table + j) = + table[j] = bridge->driver->mask_memory(bridge, mem->memory[i], mem->type); } @@ -200,6 +203,7 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start, { size_t i; struct agp_bridge_data *bridge; + u64 *table; bridge = mem->bridge; if (!bridge) @@ -209,8 +213,10 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start, return -EINVAL; } + table = (u64 *)bridge->gatt_table; + for (i = pg_start; i < (mem->page_count + pg_start); i++) { - *(bridge->gatt_table + i) = 0; + table[i] = 0; } bridge->driver->tlb_flush(mem); From 07eee78ea8ba2d0b7b20551c35a3e7dd158d50bb Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 30 Mar 2005 13:17:04 -0800 Subject: [PATCH 3/4] [PATCH] AGP fix for Xen VMM When Linux is running on the Xen virtual machine monitor, physical addresses are virtualised and cannot be directly referenced by the AGP GART. This patch fixes the GART driver for Xen by adding a layer of abstraction between physical addresses and 'GART addresses'. Architecture-specific functions are also defined for allocating and freeing the GATT. Xen requires this to ensure that table really is contiguous from the point of view of the GART. These extra interface functions are defined as 'no-ops' for all existing architectures that use the GART driver. Signed-off-by: Keir Fraser Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- drivers/char/agp/agp.h | 2 ++ drivers/char/agp/ali-agp.c | 4 ++-- drivers/char/agp/amd-k7-agp.c | 6 +++--- drivers/char/agp/amd64-agp.c | 4 ++-- drivers/char/agp/ati-agp.c | 6 +++--- drivers/char/agp/backend.c | 6 +++--- drivers/char/agp/efficeon-agp.c | 2 +- drivers/char/agp/generic.c | 17 ++++++++--------- drivers/char/agp/hp-agp.c | 4 ++-- drivers/char/agp/i460-agp.c | 4 ++-- drivers/char/agp/intel-agp.c | 6 +++--- drivers/char/agp/sworks-agp.c | 8 ++++---- drivers/char/agp/uninorth-agp.c | 2 +- include/asm-alpha/agp.h | 10 ++++++++++ include/asm-i386/agp.h | 10 ++++++++++ include/asm-ia64/agp.h | 10 ++++++++++ include/asm-ppc/agp.h | 10 ++++++++++ include/asm-ppc64/agp.h | 10 ++++++++++ include/asm-sparc64/agp.h | 10 ++++++++++ include/asm-x86_64/agp.h | 10 ++++++++++ 20 files changed, 106 insertions(+), 35 deletions(-) diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index ad9c11391d81..c1fe013c64f3 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -278,6 +278,8 @@ void agp3_generic_cleanup(void); #define AGP_GENERIC_SIZES_ENTRIES 11 extern struct aper_size_info_16 agp3_generic_sizes[]; +#define virt_to_gart(x) (phys_to_gart(virt_to_phys(x))) +#define gart_to_virt(x) (phys_to_virt(gart_to_phys(x))) extern int agp_off; extern int agp_try_unsupported_boot; diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 0212febda654..9c9c9c2247ce 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -150,7 +150,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge) pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN )); + virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN )); return addr; } @@ -174,7 +174,7 @@ static void m1541_destroy_page(void * addr) pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN)); + virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN)); agp_generic_destroy_page(addr); } diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index e62a3c2c44a9..3a41672e4d66 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -43,7 +43,7 @@ static int amd_create_page_map(struct amd_page_map *page_map) SetPageReserved(virt_to_page(page_map->real)); global_cache_flush(); - page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), + page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { ClearPageReserved(virt_to_page(page_map->real)); @@ -154,7 +154,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge) agp_bridge->gatt_table_real = (u32 *)page_dir.real; agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped; - agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real); + agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); /* Get the address for the gart region. * This is a bus address even on the alpha, b/c its @@ -167,7 +167,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge) /* Calculate the agp offset */ for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { - writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1, + writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1, page_dir.remapped+GET_PAGE_DIR_OFF(addr)); readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ } diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 399c042f68f0..1407945a5892 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -219,7 +219,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] = static int amd_8151_configure(void) { - unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); + unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); /* Configure AGP regs in each x86-64 host bridge. */ for_each_nb() { @@ -591,7 +591,7 @@ static void __devexit agp_amd64_remove(struct pci_dev *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_gart(bridge->gatt_table_real), amd64_aperture_sizes[bridge->aperture_size_idx].size); agp_remove_bridge(bridge); agp_put_bridge(bridge); diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index a65f8827c283..e572ced9100a 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -61,7 +61,7 @@ static int ati_create_page_map(ati_page_map *page_map) SetPageReserved(virt_to_page(page_map->real)); err = map_page_into_agp(virt_to_page(page_map->real)); - page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), + page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL || err) { ClearPageReserved(virt_to_page(page_map->real)); @@ -343,7 +343,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) agp_bridge->gatt_table_real = (u32 *)page_dir.real; agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped; - agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real); + agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); /* Write out the size register */ current_size = A_SIZE_LVL2(agp_bridge->current_size); @@ -373,7 +373,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) /* Calculate the agp offset */ for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { - writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1, + writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1, page_dir.remapped+GET_PAGE_DIR_OFF(addr)); readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ } diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 2f3dfb63bdc6..4d4e602fdc7e 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -148,7 +148,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) return -ENOMEM; } - bridge->scratch_page_real = virt_to_phys(addr); + bridge->scratch_page_real = virt_to_gart(addr); bridge->scratch_page = bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0); } @@ -189,7 +189,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) err_out: if (bridge->driver->needs_scratch_page) bridge->driver->agp_destroy_page( - phys_to_virt(bridge->scratch_page_real)); + gart_to_virt(bridge->scratch_page_real)); if (got_gatt) bridge->driver->free_gatt_table(bridge); if (got_keylist) { @@ -214,7 +214,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) if (bridge->driver->agp_destroy_page && bridge->driver->needs_scratch_page) bridge->driver->agp_destroy_page( - phys_to_virt(bridge->scratch_page_real)); + gart_to_virt(bridge->scratch_page_real)); } /* When we remove the global variable agp_bridge from all drivers diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index 1383c3165ea1..ac19fdcd21c1 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c @@ -219,7 +219,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge) efficeon_private.l1_table[index] = page; - value = __pa(page) | pati | present | index; + value = virt_to_gart(page) | pati | present | index; pci_write_config_dword(agp_bridge->dev, EFFICEON_ATTPAGE, value); diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index c321a924e38a..d62505b5d25a 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -153,7 +153,7 @@ void agp_free_memory(struct agp_memory *curr) } if (curr->page_count != 0) { for (i = 0; i < curr->page_count; i++) { - curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i])); + curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i])); } } agp_free_key(curr->key); @@ -209,7 +209,7 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, agp_free_memory(new); return NULL; } - new->memory[i] = virt_to_phys(addr); + new->memory[i] = virt_to_gart(addr); new->page_count++; } new->bridge = bridge; @@ -806,8 +806,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) break; } - table = (char *) __get_free_pages(GFP_KERNEL, - page_order); + table = alloc_gatt_pages(page_order); if (table == NULL) { i++; @@ -838,7 +837,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) size = ((struct aper_size_info_fixed *) temp)->size; page_order = ((struct aper_size_info_fixed *) temp)->page_order; num_entries = ((struct aper_size_info_fixed *) temp)->num_entries; - table = (char *) __get_free_pages(GFP_KERNEL, page_order); + table = alloc_gatt_pages(page_order); } if (table == NULL) @@ -853,7 +852,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) agp_gatt_table = (void *)table; bridge->driver->cache_flush(); - bridge->gatt_table = ioremap_nocache(virt_to_phys(table), + bridge->gatt_table = ioremap_nocache(virt_to_gart(table), (PAGE_SIZE * (1 << page_order))); bridge->driver->cache_flush(); @@ -861,11 +860,11 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) ClearPageReserved(page); - free_pages((unsigned long) table, page_order); + free_gatt_pages(table, page_order); return -ENOMEM; } - bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real); + bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real); /* AK: bogus, should encode addresses > 4GB */ for (i = 0; i < num_entries; i++) { @@ -919,7 +918,7 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge) for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) ClearPageReserved(page); - free_pages((unsigned long) bridge->gatt_table_real, page_order); + free_gatt_pages(bridge->gatt_table_real, page_order); agp_gatt_table = NULL; bridge->gatt_table = NULL; diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 6052bfa04c72..99762b6c19ae 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -110,7 +110,7 @@ static int __init hp_zx1_ioc_shared(void) hp->gart_size = HP_ZX1_GART_SIZE; hp->gatt_entries = hp->gart_size / hp->io_page_size; - hp->io_pdir = phys_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE)); + hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE)); hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { @@ -248,7 +248,7 @@ hp_zx1_configure (void) agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS); if (hp->io_pdir_owner) { - writel(virt_to_phys(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE); + writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE); readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); readl(hp->ioc_regs+HP_ZX1_TCNFG); diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index adbea896c0d2..94943298c03e 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -372,7 +372,7 @@ static int i460_alloc_large_page (struct lp_desc *lp) } memset(lp->alloced_map, 0, map_size); - lp->paddr = virt_to_phys(lpage); + lp->paddr = virt_to_gart(lpage); lp->refcount = 0; atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); return 0; @@ -383,7 +383,7 @@ static void i460_free_large_page (struct lp_desc *lp) kfree(lp->alloced_map); lp->alloced_map = NULL; - free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT); + free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT); atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 6a5047e0d333..51266d6b4d78 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -286,7 +286,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) if (new == NULL) return NULL; - new->memory[0] = virt_to_phys(addr); + new->memory[0] = virt_to_gart(addr); if (pg_count == 4) { /* kludge to get 4 physical pages for ARGB cursor */ new->memory[1] = new->memory[0] + PAGE_SIZE; @@ -329,10 +329,10 @@ static void intel_i810_free_by_type(struct agp_memory *curr) agp_free_key(curr->key); if(curr->type == AGP_PHYS_MEMORY) { if (curr->page_count == 4) - i8xx_destroy_pages(phys_to_virt(curr->memory[0])); + i8xx_destroy_pages(gart_to_virt(curr->memory[0])); else agp_bridge->driver->agp_destroy_page( - phys_to_virt(curr->memory[0])); + gart_to_virt(curr->memory[0])); vfree(curr->memory); } kfree(curr); diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 10c23302dd84..a9fb12c20eb7 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -51,7 +51,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map) } SetPageReserved(virt_to_page(page_map->real)); global_cache_flush(); - page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), + page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { ClearPageReserved(virt_to_page(page_map->real)); @@ -162,7 +162,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) /* Create a fake scratch directory */ for(i = 0; i < 1024; i++) { writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i); - writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i); + writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i); } retval = serverworks_create_gatt_pages(value->num_entries / 1024); @@ -174,7 +174,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) agp_bridge->gatt_table_real = (u32 *)page_dir.real; agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped; - agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real); + agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); /* Get the address for the gart region. * This is a bus address even on the alpha, b/c its @@ -187,7 +187,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) /* Calculate the agp offset */ for(i = 0; i < value->num_entries / 1024; i++) - writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i); + writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i); return 0; } diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index a673971f2a90..c8255312b8c1 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -407,7 +407,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge) bridge->gatt_table_real = (u32 *) table; bridge->gatt_table = (u32 *)table; - bridge->gatt_bus_addr = virt_to_phys(table); + bridge->gatt_bus_addr = virt_to_gart(table); for (i = 0; i < num_entries; i++) bridge->gatt_table[i] = 0; diff --git a/include/asm-alpha/agp.h b/include/asm-alpha/agp.h index c99dbbb5bcb5..ef855a3bc0f5 100644 --- a/include/asm-alpha/agp.h +++ b/include/asm-alpha/agp.h @@ -10,4 +10,14 @@ #define flush_agp_mappings() #define flush_agp_cache() mb() +/* Convert a physical address to an address suitable for the GART. */ +#define phys_to_gart(x) (x) +#define gart_to_phys(x) (x) + +/* GATT allocation. Returns/accepts GATT kernel virtual address. */ +#define alloc_gatt_pages(order) \ + ((char *)__get_free_pages(GFP_KERNEL, (order))) +#define free_gatt_pages(table, order) \ + free_pages((unsigned long)(table), (order)) + #endif diff --git a/include/asm-i386/agp.h b/include/asm-i386/agp.h index a917ff50354f..b82f5f3ab887 100644 --- a/include/asm-i386/agp.h +++ b/include/asm-i386/agp.h @@ -21,4 +21,14 @@ int unmap_page_from_agp(struct page *page); worth it. Would need a page for it. */ #define flush_agp_cache() asm volatile("wbinvd":::"memory") +/* Convert a physical address to an address suitable for the GART. */ +#define phys_to_gart(x) (x) +#define gart_to_phys(x) (x) + +/* GATT allocation. Returns/accepts GATT kernel virtual address. */ +#define alloc_gatt_pages(order) \ + ((char *)__get_free_pages(GFP_KERNEL, (order))) +#define free_gatt_pages(table, order) \ + free_pages((unsigned long)(table), (order)) + #endif diff --git a/include/asm-ia64/agp.h b/include/asm-ia64/agp.h index d1316f1e6ee1..4e517f0e6afa 100644 --- a/include/asm-ia64/agp.h +++ b/include/asm-ia64/agp.h @@ -18,4 +18,14 @@ #define flush_agp_mappings() /* nothing */ #define flush_agp_cache() mb() +/* Convert a physical address to an address suitable for the GART. */ +#define phys_to_gart(x) (x) +#define gart_to_phys(x) (x) + +/* GATT allocation. Returns/accepts GATT kernel virtual address. */ +#define alloc_gatt_pages(order) \ + ((char *)__get_free_pages(GFP_KERNEL, (order))) +#define free_gatt_pages(table, order) \ + free_pages((unsigned long)(table), (order)) + #endif /* _ASM_IA64_AGP_H */ diff --git a/include/asm-ppc/agp.h b/include/asm-ppc/agp.h index be27cfa8c5b0..ca9e423307f4 100644 --- a/include/asm-ppc/agp.h +++ b/include/asm-ppc/agp.h @@ -10,4 +10,14 @@ #define flush_agp_mappings() #define flush_agp_cache() mb() +/* Convert a physical address to an address suitable for the GART. */ +#define phys_to_gart(x) (x) +#define gart_to_phys(x) (x) + +/* GATT allocation. Returns/accepts GATT kernel virtual address. */ +#define alloc_gatt_pages(order) \ + ((char *)__get_free_pages(GFP_KERNEL, (order))) +#define free_gatt_pages(table, order) \ + free_pages((unsigned long)(table), (order)) + #endif diff --git a/include/asm-ppc64/agp.h b/include/asm-ppc64/agp.h index be27cfa8c5b0..ca9e423307f4 100644 --- a/include/asm-ppc64/agp.h +++ b/include/asm-ppc64/agp.h @@ -10,4 +10,14 @@ #define flush_agp_mappings() #define flush_agp_cache() mb() +/* Convert a physical address to an address suitable for the GART. */ +#define phys_to_gart(x) (x) +#define gart_to_phys(x) (x) + +/* GATT allocation. Returns/accepts GATT kernel virtual address. */ +#define alloc_gatt_pages(order) \ + ((char *)__get_free_pages(GFP_KERNEL, (order))) +#define free_gatt_pages(table, order) \ + free_pages((unsigned long)(table), (order)) + #endif diff --git a/include/asm-sparc64/agp.h b/include/asm-sparc64/agp.h index ba05bdf9a211..58f8cb6ae767 100644 --- a/include/asm-sparc64/agp.h +++ b/include/asm-sparc64/agp.h @@ -8,4 +8,14 @@ #define flush_agp_mappings() #define flush_agp_cache() mb() +/* Convert a physical address to an address suitable for the GART. */ +#define phys_to_gart(x) (x) +#define gart_to_phys(x) (x) + +/* GATT allocation. Returns/accepts GATT kernel virtual address. */ +#define alloc_gatt_pages(order) \ + ((char *)__get_free_pages(GFP_KERNEL, (order))) +#define free_gatt_pages(table, order) \ + free_pages((unsigned long)(table), (order)) + #endif diff --git a/include/asm-x86_64/agp.h b/include/asm-x86_64/agp.h index 0bb9019d58aa..06c52ee9c06b 100644 --- a/include/asm-x86_64/agp.h +++ b/include/asm-x86_64/agp.h @@ -19,4 +19,14 @@ int unmap_page_from_agp(struct page *page); worth it. Would need a page for it. */ #define flush_agp_cache() asm volatile("wbinvd":::"memory") +/* Convert a physical address to an address suitable for the GART. */ +#define phys_to_gart(x) (x) +#define gart_to_phys(x) (x) + +/* GATT allocation. Returns/accepts GATT kernel virtual address. */ +#define alloc_gatt_pages(order) \ + ((char *)__get_free_pages(GFP_KERNEL, (order))) +#define free_gatt_pages(table, order) \ + free_pages((unsigned long)(table), (order)) + #endif From 66bb8bf8b235ba4d37fda14375827864977c6a3e Mon Sep 17 00:00:00 2001 From: David Mosberger Date: Mon, 4 Apr 2005 13:29:43 -0700 Subject: [PATCH 4/4] [PATCH] Replace check_bridge_mode() with (bridge->mode & AGSTAT_MODE_3_0). [AGPGART] Replace check_bridge_mode() with (bridge->mode & AGSTAT_MODE_3_0). As mentioned earlier, the current check_bridge_mode() code assumes that AGP bridges are PCI devices. This isn't always true. Definitely not for HP zx1 chipset and the same seems to be the case for SGI's AGP bridge. The patch below fixes the problem by picking up the AGP_MODE_3_0 bit from bridge->mode. I feel like I may be missing something, since I can't see any reason why check_bridge_mode() wasn't doing that in the first place. According to the AGP 3.0 specs, the AGP_MODE_3_0 bit is determined during the hardware reset and cannot be changed, so it seems to me it should be safe to pick it up from bridge->mode. With the patch applied, I can definitely use AGP acceleration both with AGP 2.0 and AGP 3.0 (one with an Nvidia card, the other with an ATI FireGL card). Unless someone spots a problem, please apply this patch so 3d acceleration can work on zx1 boxes again. This makes AGP work again on machines with an AGP bridge that isn't a PCI device. Signed-off-by: David Mosberger-Tang Signed-off-by: Dave Jones --- drivers/char/agp/generic.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index d62505b5d25a..f0079e991bdc 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -295,19 +295,6 @@ int agp_num_entries(void) EXPORT_SYMBOL_GPL(agp_num_entries); -static int check_bridge_mode(struct pci_dev *dev) -{ - u32 agp3; - u8 cap_ptr; - - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3); - if (agp3 & AGPSTAT_MODE_3_0) - return 1; - return 0; -} - - /** * agp_copy_info - copy bridge state information * @@ -328,7 +315,7 @@ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info) info->version.minor = bridge->version->minor; info->chipset = SUPPORTED; info->device = bridge->dev; - if (check_bridge_mode(bridge->dev)) + if (bridge->mode & AGPSTAT_MODE_3_0) info->mode = bridge->mode & ~AGP3_RESERVED_MASK; else info->mode = bridge->mode & ~AGP2_RESERVED_MASK; @@ -661,7 +648,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode bridge_agpstat &= ~AGPSTAT_FW; /* Check to see if we are operating in 3.0 mode */ - if (check_bridge_mode(agp_bridge->dev)) + if (agp_bridge->mode & AGPSTAT_MODE_3_0) agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); else agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); @@ -732,7 +719,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode) /* Do AGP version specific frobbing. */ if (bridge->major_version >= 3) { - if (check_bridge_mode(bridge->dev)) { + if (bridge->mode & AGPSTAT_MODE_3_0) { /* If we have 3.5, we can do the isoch stuff. */ if (bridge->minor_version >= 5) agp_3_5_enable(bridge);