From c9178c3d01f6f38a33f9624c620d290cb9036964 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 4 Mar 2007 18:13:34 +1100 Subject: ati: make pcigart code able to handle variable size PCI GART aperture This code doesn't enable a variable aperture it just modifies the codebase to allow me fix it up later --- linux-core/ati_pcigart.c | 69 ++++++++++++++++++++++++------------------------ linux-core/drmP.h | 1 + shared-core/r128_cce.c | 1 + shared-core/r128_drv.h | 2 ++ shared-core/radeon_cp.c | 3 ++- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c index bbdb841c..bb30dd74 100644 --- a/linux-core/ati_pcigart.c +++ b/linux-core/ati_pcigart.c @@ -33,41 +33,25 @@ #include "drmP.h" -#if PAGE_SIZE == 65536 -# define ATI_PCIGART_TABLE_ORDER 0 -# define ATI_PCIGART_TABLE_PAGES (1 << 0) -#elif PAGE_SIZE == 16384 -# define ATI_PCIGART_TABLE_ORDER 1 -# define ATI_PCIGART_TABLE_PAGES (1 << 1) -#elif PAGE_SIZE == 8192 -# define ATI_PCIGART_TABLE_ORDER 2 -# define ATI_PCIGART_TABLE_PAGES (1 << 2) -#elif PAGE_SIZE == 4096 -# define ATI_PCIGART_TABLE_ORDER 3 -# define ATI_PCIGART_TABLE_PAGES (1 << 3) -#else -# error - PAGE_SIZE not 64K, 16K, 8K or 4K -#endif - -# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */ # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ -static void *drm_ati_alloc_pcigart_table(void) +static void *drm_ati_alloc_pcigart_table(int order) { unsigned long address; struct page *page; int i; - DRM_DEBUG("%s\n", __FUNCTION__); + + DRM_DEBUG("%s: alloc %d order\n", __FUNCTION__, order); address = __get_free_pages(GFP_KERNEL | __GFP_COMP, - ATI_PCIGART_TABLE_ORDER); + order); if (address == 0UL) { return NULL; } page = virt_to_page(address); - for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) { + for (i = 0; i < order; i++, page++) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) get_page(page); #endif @@ -78,22 +62,23 @@ static void *drm_ati_alloc_pcigart_table(void) return (void *)address; } -static void drm_ati_free_pcigart_table(void *address) +static void drm_ati_free_pcigart_table(void *address, int order) { struct page *page; int i; + int num_pages = 1 << order; DRM_DEBUG("%s\n", __FUNCTION__); page = virt_to_page((unsigned long)address); - for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) { + for (i = 0; i < num_pages; i++, page++) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) __put_page(page); #endif ClearPageReserved(page); } - free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER); + free_pages((unsigned long)address, order); } int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) @@ -101,6 +86,8 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) drm_sg_mem_t *entry = dev->sg; unsigned long pages; int i; + int order; + int num_pages, max_pages; /* we need to support large memory configurations */ if (!entry) { @@ -108,15 +95,19 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) return 0; } + order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE); + num_pages = 1 << order; + if (gart_info->bus_addr) { if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { pci_unmap_single(dev->pdev, gart_info->bus_addr, - ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, + num_pages * PAGE_SIZE, PCI_DMA_TODEVICE); } - pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) - ? entry->pages : ATI_MAX_PCIGART_PAGES; + max_pages = (gart_info->table_size / sizeof(u32)); + pages = (entry->pages <= max_pages) + ? entry->pages : max_pages; for (i = 0; i < pages; i++) { if (!entry->busaddr[i]) @@ -132,7 +123,8 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) if (gart_info->gart_table_location == DRM_ATI_GART_MAIN && gart_info->addr) { - drm_ati_free_pcigart_table(gart_info->addr); + + drm_ati_free_pcigart_table(gart_info->addr, order); gart_info->addr = NULL; } @@ -147,6 +139,9 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) unsigned long pages; u32 *pci_gart, page_base, bus_address = 0; int i, j, ret = 0; + int order; + int max_pages; + int num_pages; if (!entry) { DRM_ERROR("no scatter/gather memory!\n"); @@ -156,7 +151,9 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); - address = drm_ati_alloc_pcigart_table(); + order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE); + num_pages = 1 << order; + address = drm_ati_alloc_pcigart_table(order); if (!address) { DRM_ERROR("cannot allocate PCI GART page!\n"); goto done; @@ -168,11 +165,12 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) } bus_address = pci_map_single(dev->pdev, address, - ATI_PCIGART_TABLE_PAGES * - PAGE_SIZE, PCI_DMA_TODEVICE); + num_pages * PAGE_SIZE, + PCI_DMA_TODEVICE); if (bus_address == 0) { DRM_ERROR("unable to map PCIGART pages!\n"); - drm_ati_free_pcigart_table(address); + order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE); + drm_ati_free_pcigart_table(address, order); address = NULL; goto done; } @@ -185,10 +183,11 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) pci_gart = (u32 *) address; - pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) - ? entry->pages : ATI_MAX_PCIGART_PAGES; + max_pages = (gart_info->table_size / sizeof(u32)); + pages = (entry->pages <= max_pages) + ? entry->pages : max_pages; - memset(pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32)); + memset(pci_gart, 0, max_pages * sizeof(u32)); for (i = 0; i < pages; i++) { /* we need to support large memory configurations */ diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 2285bc02..d1dbdc2d 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -593,6 +593,7 @@ typedef struct ati_pcigart_info { void *addr; dma_addr_t bus_addr; drm_local_map_t mapping; + int table_size; } drm_ati_pcigart_info; diff --git a/shared-core/r128_cce.c b/shared-core/r128_cce.c index f9a9eb32..62859d5a 100644 --- a/shared-core/r128_cce.c +++ b/shared-core/r128_cce.c @@ -560,6 +560,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init) if (dev_priv->is_pci) { #endif dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; + dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; dev_priv->gart_info.addr = NULL; dev_priv->gart_info.bus_addr = 0; dev_priv->gart_info.is_pcie = 0; diff --git a/shared-core/r128_drv.h b/shared-core/r128_drv.h index f1efb49d..90868356 100644 --- a/shared-core/r128_drv.h +++ b/shared-core/r128_drv.h @@ -383,6 +383,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, #define R128_PERFORMANCE_BOXES 0 +#define R128_PCIGART_TABLE_SIZE 32768 + #define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) #define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) #define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 0fa6535d..976b9fbd 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1622,6 +1622,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) } else #endif { + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; /* if we have an offset set from userspace */ if (dev_priv->pcigart_offset) { dev_priv->gart_info.bus_addr = @@ -1629,7 +1630,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->gart_info.mapping.offset = dev_priv->gart_info.bus_addr; dev_priv->gart_info.mapping.size = - RADEON_PCIGART_TABLE_SIZE; + dev_priv->gart_info.table_size; drm_core_ioremap(&dev_priv->gart_info.mapping, dev); dev_priv->gart_info.addr = -- cgit v1.2.3 From 188a93c9dfde31de4d86733fa46b50487d3a4ac0 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 4 Mar 2007 19:10:46 +1100 Subject: radeon: make PCI GART aperture size variable, but making table size variable This is precursor to getting a TTM backend for this stuff, and also allows the PCI table to be allocated at fb 0 --- shared-core/radeon_cp.c | 5 +++-- shared-core/radeon_drm.h | 1 + shared-core/radeon_drv.h | 4 +++- shared-core/radeon_state.c | 6 ++++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 976b9fbd..e02796e7 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1622,9 +1622,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) } else #endif { - dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; /* if we have an offset set from userspace */ - if (dev_priv->pcigart_offset) { + if (dev_priv->pcigart_offset_set) { dev_priv->gart_info.bus_addr = dev_priv->pcigart_offset + dev_priv->fb_location; dev_priv->gart_info.mapping.offset = @@ -2231,6 +2230,8 @@ int radeon_driver_firstopen(struct drm_device *dev) drm_local_map_t *map; drm_radeon_private_t *dev_priv = dev->dev_private; + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; + ret = drm_addmap(dev, drm_get_resource_start(dev, 2), drm_get_resource_len(dev, 2), _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio); diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index f5edbc19..e96e7851 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -708,6 +708,7 @@ typedef struct drm_radeon_setparam { #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ +#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ /* 1.14: Clients can allocate/free a surface */ diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 5c426fe0..3e56af30 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -95,10 +95,11 @@ * 1.24- Add general-purpose packet for manipulating scratch registers (r300) * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, * new packet type) + * 1.26- Add support for variable size PCI(E) gart aperture */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 25 +#define DRIVER_MINOR 26 #define DRIVER_PATCHLEVEL 0 /* @@ -282,6 +283,7 @@ typedef struct drm_radeon_private { struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES]; unsigned long pcigart_offset; + unsigned int pcigart_offset_set; drm_ati_pcigart_info gart_info; u32 scratch_ages[5]; diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 40b7d6ce..b95549d8 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3196,10 +3196,16 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) break; case RADEON_SETPARAM_PCIGART_LOCATION: dev_priv->pcigart_offset = sp.value; + dev_priv->pcigart_offset_set = 1; break; case RADEON_SETPARAM_NEW_MEMMAP: dev_priv->new_memmap = sp.value; break; + case RADEON_SETPARAM_PCIGART_TABLE_SIZE: + dev_priv->gart_info.table_size = sp.value; + if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; + break; default: DRM_DEBUG("Invalid parameter %d\n", sp.param); return DRM_ERR(EINVAL); -- cgit v1.2.3