From 7af9d670371de868f0642148fe2d594bc9a7dea3 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:05:29 -0700 Subject: Initial XP10 code drop from XGI. See attachment 10246 on https://bugs.freedesktop.org/show_bug.cgi?id=5921 --- linux-core/xgi_pcie.c | 1060 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1060 insertions(+) create mode 100644 linux-core/xgi_pcie.c (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c new file mode 100644 index 00000000..62e2323f --- /dev/null +++ b/linux-core/xgi_pcie.c @@ -0,0 +1,1060 @@ + +/**************************************************************************** + * Copyright (C) 2003-2006 by XGI Technology, Taiwan. + * * + * All Rights Reserved. * + * * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL XGI AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ***************************************************************************/ + +#include "xgi_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_regs.h" +#include "xgi_pcie.h" +#include "xgi_misc.h" + +static xgi_pcie_heap_t *xgi_pcie_heap = NULL; +static kmem_cache_t *xgi_pcie_cache_block = NULL; +static xgi_pcie_block_t *xgi_pcie_vertex_block = NULL; +static xgi_pcie_block_t *xgi_pcie_cmdlist_block = NULL; +static xgi_pcie_block_t *xgi_pcie_scratchpad_block = NULL; +extern struct list_head xgi_mempid_list; + +static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) +{ + struct page *page; + unsigned long page_addr = 0; + unsigned long page_count = 0; + int i; + + page_count = (1 << page_order); + page_addr = __get_free_pages(GFP_KERNEL, page_order); + + if (page_addr == 0UL) + { + XGI_ERROR("Can't get free pages: 0x%lx from system memory !\n", + page_count); + return 0; + } + + page = virt_to_page(page_addr); + + for (i = 0; i < page_count; i++, page++) + { + XGI_INC_PAGE_COUNT(page); + XGILockPage(page); + } + + XGI_INFO("page_count: 0x%lx page_order: 0x%lx page_addr: 0x%lx \n", + page_count, page_order, page_addr); + return page_addr; +} + +static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) +{ + struct page *page; + unsigned long page_count = 0; + int i; + + page_count = (1 << page_order); + page = virt_to_page(page_addr); + + for (i = 0; i < page_count; i++, page++) + { + XGI_DEC_PAGE_COUNT(page); + XGIUnlockPage(page); + } + + free_pages(page_addr, page_order); +} + +static int xgi_pcie_lut_init(xgi_info_t *info) +{ + unsigned char *page_addr = NULL; + unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; + unsigned long count = 0; + u8 temp = 0; + + /* Jong 06/06/2006 */ + unsigned long pcie_aperture_size; + + info->pcie.size = 128 * 1024 * 1024; + + /* Get current FB aperture size */ + temp = In3x5(0x27); + XGI_INFO("In3x5(0x27): 0x%x \n", temp); + + if (temp & 0x01) /* 256MB; Jong 06/05/2006; 0x10000000 */ + { + /* Jong 06/06/2006; allocate memory */ + pcie_aperture_size=256 * 1024 * 1024; + /* info->pcie.base = 256 * 1024 * 1024; */ /* pcie base is different from fb base */ + } + else /* 128MB; Jong 06/05/2006; 0x08000000 */ + { + /* Jong 06/06/2006; allocate memory */ + pcie_aperture_size=128 * 1024 * 1024; + /* info->pcie.base = 128 * 1024 * 1024; */ + } + + /* Jong 06/06/2006; allocate memory; it can be used for build-in kernel modules */ + /* info->pcie.base=(unsigned long)alloc_bootmem(pcie_mem_size); */ + /* total 496 MB; need 256 MB (0x10000000); start from 240 MB (0x0F000000) */ + /* info->pcie.base=ioremap(0x0F000000, 0x10000000); */ /* Cause system hang */ + info->pcie.base=pcie_aperture_size; /* works */ + /* info->pcie.base=info->fb.base + info->fb.size; */ /* System hang */ + /* info->pcie.base=128 * 1024 * 1024;*/ /* System hang */ + + XGI_INFO("Jong06062006-info->pcie.base: 0x%lx \n", info->pcie.base); + + + /* Get current lookup table page size */ + temp = bReadReg(0xB00C); + if (temp & 0x04) /* 8KB */ + { + info->lutPageSize = 8 * 1024; + } + else /* 4KB */ + { + info->lutPageSize = 4 * 1024; + } + + XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + +#if 0 + /* Get current lookup table location */ + temp = bReadReg(0xB00C); + if (temp & 0x02) /* LFB */ + { + info->isLUTInLFB = TRUE; + /* Current we only support lookup table in LFB */ + temp &= 0xFD; + bWriteReg(0xB00C, temp); + info->isLUTInLFB = FALSE; + } + else /* SFB */ + { + info->isLUTInLFB = FALSE; + } + + XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + + /* Get current SDFB page size */ + temp = bReadReg(0xB00C); + if (temp & 0x08) /* 8MB */ + { + info->sdfbPageSize = 8 * 1024 * 1024; + } + else /* 4MB */ + { + info->sdfbPageSize = 4 * 1024 * 1024; + } +#endif + pciePageCount = (info->pcie.size + PAGE_SIZE - 1) / PAGE_SIZE; + + /* + * Allocate memory for PCIE GART table; + */ + lutEntryNum = pciePageCount; + lutPageCount = (lutEntryNum * 4 + PAGE_SIZE - 1) / PAGE_SIZE; + + /* get page_order base on page_count */ + count = lutPageCount; + for (lutPageOrder = 0; count; count >>= 1, ++lutPageOrder); + + if ((lutPageCount << 1) == (1 << lutPageOrder)) + { + lutPageOrder -= 1; + } + + XGI_INFO("lutEntryNum: 0x%lx lutPageCount: 0x%lx lutPageOrder 0x%lx\n", + lutEntryNum, lutPageCount, lutPageOrder); + + info->lutPageOrder = lutPageOrder; + page_addr = (unsigned char *)xgi_pcie_lut_alloc(lutPageOrder); + + if (!page_addr) + { + XGI_ERROR("cannot allocate PCIE lut page!\n"); + goto fail; + } + info->lut_base = (unsigned long *)page_addr; + + XGI_INFO("page_addr: 0x%p virt_to_phys(page_virtual): 0x%lx \n", + page_addr, virt_to_phys(page_addr)); + + XGI_INFO("info->lut_base: 0x%p __pa(info->lut_base): 0x%lx info->lutPageOrder 0x%lx\n", + info->lut_base, __pa(info->lut_base), info->lutPageOrder); + + /* + * clean all PCIE GART Entry + */ + memset(page_addr, 0, PAGE_SIZE << lutPageOrder); + +#if defined(__i386__) || defined(__x86_64__) + asm volatile ( "wbinvd" ::: "memory" ); +#else + mb(); +#endif + + /* Set GART in SFB */ + bWriteReg(0xB00C, bReadReg(0xB00C) & ~0x02); + /* Set GART base address to HW */ + dwWriteReg(0xB034, __pa(info->lut_base)); + + return 1; +fail: + return 0; +} + +static void xgi_pcie_lut_cleanup(xgi_info_t *info) +{ + if (info->lut_base) + { + XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", + info->lut_base, info->lutPageOrder); + xgi_pcie_lut_free((unsigned long)info->lut_base, info->lutPageOrder); + info->lut_base = NULL; + } +} + +static xgi_pcie_block_t *xgi_pcie_new_node(void) +{ + xgi_pcie_block_t *block = (xgi_pcie_block_t *)kmem_cache_alloc(xgi_pcie_cache_block, GFP_KERNEL); + if (block == NULL) + { + return NULL; + } + + block->offset = 0; /* block's offset in pcie memory, begin from 0 */ + block->size = 0; /* The block size. */ + block->bus_addr = 0; /* CPU access address/bus address */ + block->hw_addr = 0; /* GE access address */ + block->page_count = 0; + block->page_order = 0; + block->page_block = NULL; + block->page_table = NULL; + block->owner = PCIE_INVALID; + + return block; +} + +static void xgi_pcie_block_stuff_free(xgi_pcie_block_t *block) +{ + struct page *page; + xgi_page_block_t *page_block = block->page_block; + xgi_page_block_t *free_block; + unsigned long page_count = 0; + int i; + + //XGI_INFO("block->page_block: 0x%p \n", block->page_block); + while (page_block) + { + page_count = page_block->page_count; + + page = virt_to_page(page_block->virt_addr); + for (i = 0; i < page_count; i++, page++) + { + XGI_DEC_PAGE_COUNT(page); + XGIUnlockPage(page); + } + free_pages(page_block->virt_addr, page_block->page_order); + + page_block->phys_addr = 0; + page_block->virt_addr = 0; + page_block->page_count = 0; + page_block->page_order = 0; + + free_block = page_block; + page_block = page_block->next; + //XGI_INFO("free free_block: 0x%p \n", free_block); + kfree(free_block); + free_block = NULL; + } + + if (block->page_table) + { + //XGI_INFO("free block->page_table: 0x%p \n", block->page_table); + kfree(block->page_table); + block->page_table = NULL; + } +} + +int xgi_pcie_heap_init(xgi_info_t *info) +{ + xgi_pcie_block_t *block; + + if (!xgi_pcie_lut_init(info)) + { + XGI_ERROR("xgi_pcie_lut_init failed\n"); + return 0; + } + + xgi_pcie_heap = (xgi_pcie_heap_t *)kmalloc(sizeof(xgi_pcie_heap_t), GFP_KERNEL); + if(!xgi_pcie_heap) + { + XGI_ERROR("xgi_pcie_heap alloc failed\n"); + goto fail1; + } + INIT_LIST_HEAD(&xgi_pcie_heap->free_list); + INIT_LIST_HEAD(&xgi_pcie_heap->used_list); + INIT_LIST_HEAD(&xgi_pcie_heap->sort_list); + + xgi_pcie_heap->max_freesize = info->pcie.size; + + xgi_pcie_cache_block = kmem_cache_create("xgi_pcie_block", sizeof(xgi_pcie_block_t), + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (NULL == xgi_pcie_cache_block) + { + XGI_ERROR("Fail to creat xgi_pcie_block\n"); + goto fail2; + } + + block = (xgi_pcie_block_t *)xgi_pcie_new_node(); + if (!block) + { + XGI_ERROR("xgi_pcie_new_node failed\n"); + goto fail3; + } + + block->offset = 0; /* block's offset in pcie memory, begin from 0 */ + block->size = info->pcie.size; + + list_add(&block->list, &xgi_pcie_heap->free_list); + + XGI_INFO("PCIE start address: 0x%lx, memory size : 0x%lx\n", block->offset, block->size); + return 1; +fail3: + if (xgi_pcie_cache_block) + { + kmem_cache_destroy(xgi_pcie_cache_block); + xgi_pcie_cache_block = NULL; + } + +fail2: + if(xgi_pcie_heap) + { + kfree(xgi_pcie_heap); + xgi_pcie_heap = NULL; + } +fail1: + xgi_pcie_lut_cleanup(info); + return 0; +} + +void xgi_pcie_heap_check(void) +{ + struct list_head *useList, *temp; + xgi_pcie_block_t *block; + unsigned int ownerIndex; + char *ownerStr[6] = {"2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE"}; + + if (xgi_pcie_heap) + { + useList = &xgi_pcie_heap->used_list; + temp = useList->next; + XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); + while (temp != useList) + { + block = list_entry(temp, struct xgi_pcie_block_s, list); + if (block->owner == PCIE_2D) + ownerIndex = 0; + else if (block->owner > PCIE_3D_TEXTURE || block->owner < PCIE_2D || block->owner < PCIE_3D) + ownerIndex = 5; + else + ownerIndex = block->owner - PCIE_3D + 1; + XGI_INFO("Allocated by %s, block->offset: 0x%lx block->size: 0x%lx \n", + ownerStr[ownerIndex], block->offset, block->size); + temp = temp->next; + } + + } +} + + +void xgi_pcie_heap_cleanup(xgi_info_t *info) +{ + struct list_head *free_list, *temp; + xgi_pcie_block_t *block; + int j; + + xgi_pcie_lut_cleanup(info); + XGI_INFO("xgi_pcie_lut_cleanup scceeded\n"); + + if (xgi_pcie_heap) + { + free_list = &xgi_pcie_heap->free_list; + for (j = 0; j < 3; j++, free_list++) + { + temp = free_list->next; + + while (temp != free_list) + { + block = list_entry(temp, struct xgi_pcie_block_s, list); + XGI_INFO("No. %d block->offset: 0x%lx block->size: 0x%lx \n", + j, block->offset, block->size); + xgi_pcie_block_stuff_free(block); + block->bus_addr = 0; + block->hw_addr = 0; + + temp = temp->next; + //XGI_INFO("No. %d free block: 0x%p \n", j, block); + kmem_cache_free(xgi_pcie_cache_block, block); + block = NULL; + } + } + + XGI_INFO("free xgi_pcie_heap: 0x%p \n", xgi_pcie_heap); + kfree(xgi_pcie_heap); + xgi_pcie_heap = NULL; + } + + if (xgi_pcie_cache_block) + { + kmem_cache_destroy(xgi_pcie_cache_block); + xgi_pcie_cache_block = NULL; + } +} + + +static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t *info, + unsigned long originalSize, + enum PcieOwner owner) +{ + struct list_head *free_list; + xgi_pcie_block_t *block, *used_block, *free_block; + xgi_page_block_t *page_block, *prev_page_block; + struct page *page; + unsigned long page_order = 0, count = 0, index =0; + unsigned long page_addr = 0; + unsigned long *lut_addr = NULL; + unsigned long lut_id = 0; + unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; + int i, j, page_count = 0; + int temp = 0; + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-Begin\n"); + XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", originalSize, size); + + if (owner == PCIE_3D) + { + if (xgi_pcie_vertex_block) + { + XGI_INFO("PCIE Vertex has been created, return directly.\n"); + return xgi_pcie_vertex_block; + } + } + + if (owner == PCIE_3D_CMDLIST) + { + if (xgi_pcie_cmdlist_block) + { + XGI_INFO("PCIE Cmdlist has been created, return directly.\n"); + return xgi_pcie_cmdlist_block; + } + } + + if (owner == PCIE_3D_SCRATCHPAD) + { + if (xgi_pcie_scratchpad_block) + { + XGI_INFO("PCIE Scratchpad has been created, return directly.\n"); + return xgi_pcie_scratchpad_block; + } + } + + if (size == 0) + { + XGI_ERROR("size == 0 \n"); + return (NULL); + } + + XGI_INFO("max_freesize: 0x%lx \n", xgi_pcie_heap->max_freesize); + if (size > xgi_pcie_heap->max_freesize) + { + XGI_ERROR("size: 0x%lx bigger than PCIE total free size: 0x%lx.\n", + size, xgi_pcie_heap->max_freesize); + return (NULL); + } + + /* Jong 05/30/2006; find next free list which has enough space*/ + free_list = xgi_pcie_heap->free_list.next; + while (free_list != &xgi_pcie_heap->free_list) + { + //XGI_INFO("free_list: 0x%px \n", free_list); + block = list_entry(free_list, struct xgi_pcie_block_s, list); + if (size <= block->size) + { + break; + } + free_list = free_list->next; + } + + if (free_list == &xgi_pcie_heap->free_list) + { + XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", size/1024); + return (NULL); + } + + free_block = block; + XGI_INFO("alloc size: 0x%lx from offset: 0x%lx size: 0x%lx \n", + size, free_block->offset, free_block->size); + + if (size == free_block->size) + { + used_block = free_block; + XGI_INFO("size==free_block->size: free_block = 0x%p\n", free_block); + list_del(&free_block->list); + } + else + { + used_block = xgi_pcie_new_node(); + if (used_block == NULL) + { + return NULL; + } + + if (used_block == free_block) + { + XGI_ERROR("used_block == free_block = 0x%p\n", used_block); + } + + used_block->offset = free_block->offset; + used_block->size = size; + + free_block->offset += size; + free_block->size -= size; + } + + xgi_pcie_heap->max_freesize -= size; + + used_block->bus_addr = info->pcie.base + used_block->offset; + used_block->hw_addr = info->pcie.base + used_block->offset; + used_block->page_count = page_count = size / PAGE_SIZE; + + /* get page_order base on page_count */ + for (used_block->page_order = 0; page_count; page_count >>= 1) + { + ++used_block->page_order; + } + + if ((used_block->page_count << 1) == (1 << used_block->page_order)) + { + used_block->page_order--; + } + XGI_INFO("used_block->offset: 0x%lx, used_block->size: 0x%lx, used_block->bus_addr: 0x%lx, used_block->hw_addr: 0x%lx, used_block->page_count: 0x%lx used_block->page_order: 0x%lx\n", + used_block->offset, used_block->size, used_block->bus_addr, used_block->hw_addr, used_block->page_count, used_block->page_order); + + used_block->page_block = NULL; + //used_block->page_block = (xgi_pages_block_t *)kmalloc(sizeof(xgi_pages_block_t), GFP_KERNEL); + //if (!used_block->page_block) return NULL; + //used_block->page_block->next = NULL; + + used_block->page_table = (xgi_pte_t *)kmalloc(sizeof(xgi_pte_t) * used_block->page_count, GFP_KERNEL); + if (used_block->page_table == NULL) + { + goto fail; + } + + lut_id = (used_block->offset >> PAGE_SHIFT); + lut_addr = info->lut_base; + lut_addr += lut_id; + XGI_INFO("lutAddr: 0x%p lutID: 0x%lx \n", lut_addr, lut_id); + + /* alloc free pages from system */ + page_count = used_block->page_count; + page_block = used_block->page_block; + prev_page_block = used_block->page_block; + for (i = 0; page_count > 0; i++) + { + /* if size is bigger than 2M bytes, it should be split */ + if (page_count > (1 << XGI_PCIE_ALLOC_MAX_ORDER)) + { + page_order = XGI_PCIE_ALLOC_MAX_ORDER; + } + else + { + count = page_count; + for (page_order = 0; count; count >>= 1, ++page_order); + + if ((page_count << 1) == (1 << page_order)) + { + page_order -= 1; + } + } + + count = (1 << page_order); + page_addr = __get_free_pages(GFP_KERNEL, page_order); + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_addr=0x%lx \n", page_addr); + + if (!page_addr) + { + XGI_ERROR("No: %d :Can't get free pages: 0x%lx from system memory !\n", + i, count); + goto fail; + } + + /* Jong 05/30/2006; test */ + memset((unsigned char *)page_addr, 0xFF, PAGE_SIZE << page_order); + /* memset((unsigned char *)page_addr, 0, PAGE_SIZE << page_order); */ + + if (page_block == NULL) + { + page_block = (xgi_page_block_t *)kmalloc(sizeof(xgi_page_block_t), GFP_KERNEL); + if (!page_block) + { + XGI_ERROR("Can't get memory for page_block! \n"); + goto fail; + } + } + + if (prev_page_block == NULL) + { + used_block->page_block = page_block; + prev_page_block = page_block; + } + else + { + prev_page_block->next = page_block; + prev_page_block = page_block; + } + + page_block->next = NULL; + page_block->phys_addr = __pa(page_addr); + page_block->virt_addr = page_addr; + page_block->page_count = count; + page_block->page_order = page_order; + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_block->phys_addr=0x%lx \n", page_block->phys_addr); + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_block->virt_addr=0x%lx \n", page_block->virt_addr); + + page = virt_to_page(page_addr); + + //XGI_INFO("No: %d page_order: 0x%lx page_count: 0x%x count: 0x%lx index: 0x%lx lut_addr: 0x%p" + // "page_block->phys_addr: 0x%lx page_block->virt_addr: 0x%lx \n", + // i, page_order, page_count, count, index, lut_addr, page_block->phys_addr, page_block->virt_addr); + + for (j = 0 ; j < count; j++, page++, lut_addr++) + { + used_block->page_table[index + j].phys_addr = __pa(page_address(page)); + used_block->page_table[index + j].virt_addr = (unsigned long)page_address(page); + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].phys_addr=0x%lx \n", used_block->page_table[index + j].phys_addr); + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].virt_addr=0x%lx \n", used_block->page_table[index + j].virt_addr); + + *lut_addr = __pa(page_address(page)); + XGI_INC_PAGE_COUNT(page); + XGILockPage(page); + + if (temp) + { + XGI_INFO("__pa(page_address(page)): 0x%lx lutAddr: 0x%p lutAddr No: 0x%x = 0x%lx \n", + __pa(page_address(page)), lut_addr, j, *lut_addr); + temp--; + } + } + + page_block = page_block->next; + page_count -= count; + index += count; + temp = 0; + } + + used_block->owner = owner; + list_add(&used_block->list, &xgi_pcie_heap->used_list); + +#if defined(__i386__) || defined(__x86_64__) + asm volatile ( "wbinvd" ::: "memory" ); +#else + mb(); +#endif + + /* Flush GART Table */ + bWriteReg(0xB03F, 0x40); + bWriteReg(0xB03F, 0x00); + + if (owner == PCIE_3D) + { + xgi_pcie_vertex_block = used_block; + } + + if (owner == PCIE_3D_CMDLIST) + { + xgi_pcie_cmdlist_block = used_block; + } + + if (owner == PCIE_3D_SCRATCHPAD) + { + xgi_pcie_scratchpad_block = used_block; + } + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-End \n"); + return (used_block); + +fail: + xgi_pcie_block_stuff_free(used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + return NULL; +} + +static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t *info, unsigned long offset) +{ + struct list_head *free_list, *used_list; + xgi_pcie_block_t *used_block, *block = NULL; + xgi_pcie_block_t *prev, *next; + unsigned long upper, lower; + + used_list = xgi_pcie_heap->used_list.next; + while (used_list != &xgi_pcie_heap->used_list) + { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + if (block->offset == offset) + { + break; + } + used_list = used_list->next; + } + + if (used_list == &xgi_pcie_heap->used_list) + { + XGI_ERROR("can't find block: 0x%lx to free!\n", offset); + return (NULL); + } + + used_block = block; + XGI_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx, bus_addr = 0x%lx, hw_addr = 0x%lx\n", + used_block, used_block->offset, used_block->size, used_block->bus_addr, used_block->hw_addr); + + xgi_pcie_block_stuff_free(used_block); + + /* update xgi_pcie_heap */ + xgi_pcie_heap->max_freesize += used_block->size; + + prev = next = NULL; + upper = used_block->offset + used_block->size; + lower = used_block->offset; + + free_list = xgi_pcie_heap->free_list.next; + + while (free_list != &xgi_pcie_heap->free_list) + { + block = list_entry(free_list, struct xgi_pcie_block_s, list); + if (block->offset == upper) + { + next = block; + } + else if ((block->offset + block->size) == lower) + { + prev = block; + } + free_list = free_list->next; + } + + XGI_INFO("next = 0x%p, prev = 0x%p\n", next, prev); + list_del(&used_block->list); + + if (prev && next) + { + prev->size += (used_block->size + next->size); + list_del(&next->list); + XGI_INFO("free node 0x%p\n", next); + kmem_cache_free(xgi_pcie_cache_block, next); + kmem_cache_free(xgi_pcie_cache_block, used_block); + next = NULL; + used_block = NULL; + return (prev); + } + + if (prev) + { + prev->size += used_block->size; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + used_block = NULL; + return (prev); + } + + if (next) + { + next->size += used_block->size; + next->offset = used_block->offset; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + used_block = NULL; + return (next); + } + + used_block->bus_addr = 0; + used_block->hw_addr = 0; + used_block->page_count = 0; + used_block->page_order = 0; + list_add(&used_block->list, &xgi_pcie_heap->free_list); + XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", + used_block, used_block->offset, used_block->size); + return (used_block); +} + +void xgi_pcie_alloc(xgi_info_t *info, unsigned long size, + enum PcieOwner owner, xgi_mem_alloc_t *alloc) +{ + xgi_pcie_block_t *block; + xgi_mem_pid_t *mempid_block; + + xgi_down(info->pcie_sem); + block = xgi_pcie_mem_alloc(info, size, owner); + xgi_up(info->pcie_sem); + + if (block == NULL) + { + alloc->location = INVALID; + alloc->size = 0; + alloc->bus_addr = 0; + alloc->hw_addr = 0; + XGI_ERROR("PCIE RAM allocation failed\n"); + } + else + { + XGI_INFO("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", + block->offset, block->bus_addr); + alloc->location = NON_LOCAL; + alloc->size = block->size; + alloc->bus_addr = block->bus_addr; + alloc->hw_addr = block->hw_addr; + + /* + manage mempid, handle PCIE_3D, PCIE_3D_TEXTURE. + PCIE_3D request means a opengl process created. + PCIE_3D_TEXTURE request means texture cannot alloc from fb. + */ + if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) + { + mempid_block = kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); + if (!mempid_block) + XGI_ERROR("mempid_block alloc failed\n"); + mempid_block->location = NON_LOCAL; + if (owner == PCIE_3D) + mempid_block->bus_addr = 0xFFFFFFFF;/*xgi_pcie_vertex_block has the address*/ + else + mempid_block->bus_addr = alloc->bus_addr; + mempid_block->pid = alloc->pid; + + XGI_INFO("Memory ProcessID add one pcie block pid:%ld successfully! \n", mempid_block->pid); + list_add(&mempid_block->list, &xgi_mempid_list); + } + } +} + +void xgi_pcie_free(xgi_info_t *info, unsigned long bus_addr) +{ + xgi_pcie_block_t *block; + unsigned long offset = bus_addr - info->pcie.base; + xgi_mem_pid_t *mempid_block; + xgi_mem_pid_t *mempid_freeblock = NULL; + struct list_head *mempid_list; + char isvertex = 0; + int processcnt; + + if (xgi_pcie_vertex_block && xgi_pcie_vertex_block->bus_addr == bus_addr) + isvertex = 1; + + if (isvertex) + { + /*check is there any other process using vertex*/ + processcnt = 0; + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) + { + mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) + { + ++processcnt; + } + mempid_list = mempid_list->next; + } + if (processcnt > 1) + { + return; + } + } + + xgi_down(info->pcie_sem); + block = xgi_pcie_mem_free(info, offset); + xgi_up(info->pcie_sem); + + if (block == NULL) + { + XGI_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); + } + + if (isvertex) + xgi_pcie_vertex_block = NULL; + + /* manage mempid */ + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) + { + mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) + { + mempid_freeblock = mempid_block; + break; + } + mempid_list = mempid_list->next; + } + if (mempid_freeblock) + { + list_del(&mempid_freeblock->list); + XGI_INFO("Memory ProcessID delete one pcie block pid:%ld successfully! \n", mempid_freeblock->pid); + kfree(mempid_freeblock); + } +} + +/* + * given a bus address, fid the pcie mem block + * uses the bus address as the key. + */ +void *xgi_find_pcie_block(xgi_info_t *info, unsigned long address) +{ + struct list_head *used_list; + xgi_pcie_block_t *block; + int i; + + used_list = xgi_pcie_heap->used_list.next; + + while (used_list != &xgi_pcie_heap->used_list) + { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + + if (block->bus_addr == address) + { + return block; + } + + if (block->page_table) + { + for (i = 0; i < block->page_count; i++) + { + unsigned long offset = block->bus_addr; + if ( (address >= offset) && (address < (offset + PAGE_SIZE))) + { + return block; + } + } + } + used_list = used_list->next; + } + + XGI_ERROR("could not find map for vm 0x%lx\n", address); + + return NULL; +} + +/* + address -- GE HW address + return -- CPU virtual address + + assume the CPU VAddr is continuous in not the same block +*/ +void *xgi_find_pcie_virt(xgi_info_t *info, unsigned long address) +{ + struct list_head *used_list; + xgi_pcie_block_t *block; + unsigned long offset_in_page; + unsigned long loc_in_pagetable; + void * ret; + + XGI_INFO("Jong_05292006-xgi_find_pcie_virt-Begin\n"); + + used_list = xgi_pcie_heap->used_list.next; + XGI_INFO("Jong_05292006-used_list=%ul\n", used_list); + + offset_in_page = address & (PAGE_SIZE-1); + XGI_INFO("Jong_05292006-address=0x%px, PAGE_SIZE-1=%ul, offset_in_page=%ul\n", address, PAGE_SIZE-1, offset_in_page); + + while (used_list != &xgi_pcie_heap->used_list) + { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + XGI_INFO("Jong_05292006-block=0x%px\n", block); + XGI_INFO("Jong_05292006-block->hw_addr=0x%px\n", block->hw_addr); + XGI_INFO("Jong_05292006- block->size=%ul\n", block->size); + + if ((address >= block->hw_addr) && (address < (block->hw_addr + block->size))) + { + loc_in_pagetable = (address - block->hw_addr) >> PAGE_SHIFT; + ret = (void*)(block->page_table[loc_in_pagetable].virt_addr + offset_in_page); + + XGI_INFO("Jong_05292006-PAGE_SHIFT=%d\n", PAGE_SHIFT); + XGI_INFO("Jong_05292006-loc_in_pagetable=0x%px\n", loc_in_pagetable); + XGI_INFO("Jong_05292006-block->page_table[loc_in_pagetable].virt_addr=0x%px\n", block->page_table[loc_in_pagetable].virt_addr); + XGI_INFO("Jong_05292006-offset_in_page=%d\n", offset_in_page); + XGI_INFO("Jong_05292006-return(virt_addr)=0x%px\n", ret); + + return ret ; + } + else + { + XGI_INFO("Jong_05292006-used_list = used_list->next;\n"); + used_list = used_list->next; + } + } + + XGI_ERROR("could not find map for vm 0x%lx\n", address); + return NULL; +} + + +void xgi_read_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req) +{ + +} + +void xgi_write_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req) +{ +} + +/* + address -- GE hw address +*/ +void xgi_test_rwinkernel(xgi_info_t *info, unsigned long address) +{ + unsigned long * virtaddr = 0; + if (address == 0) + { + XGI_INFO("[Jong-kd] input GE HW addr is 0x00000000\n"); + return; + } + + virtaddr = (unsigned long *) xgi_find_pcie_virt(info, address); + + XGI_INFO("[Jong-kd] input GE HW addr is 0x%lx\n", address); + XGI_INFO("[Jong-kd] convert to CPU virt addr 0x%px\n", virtaddr); + XGI_INFO("[Jong-kd] origin [virtaddr] = 0x%lx\n", *virtaddr); + if (virtaddr != NULL) + { + *virtaddr = 0x00f00fff; + } + + XGI_INFO("[Jong-kd] modified [virtaddr] = 0x%lx\n", *virtaddr); +} + -- cgit v1.2.3 From 434657a2582362367ba2a94f827511252001368f Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:10:30 -0700 Subject: dos2unix and Lindent --- linux-core/xgi_pcie.c | 2091 ++++++++++++++++++++++++------------------------- 1 file changed, 1031 insertions(+), 1060 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 62e2323f..9457770a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -1,1060 +1,1031 @@ - -/**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation on the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL XGI AND/OR - * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - ***************************************************************************/ - -#include "xgi_types.h" -#include "xgi_linux.h" -#include "xgi_drv.h" -#include "xgi_regs.h" -#include "xgi_pcie.h" -#include "xgi_misc.h" - -static xgi_pcie_heap_t *xgi_pcie_heap = NULL; -static kmem_cache_t *xgi_pcie_cache_block = NULL; -static xgi_pcie_block_t *xgi_pcie_vertex_block = NULL; -static xgi_pcie_block_t *xgi_pcie_cmdlist_block = NULL; -static xgi_pcie_block_t *xgi_pcie_scratchpad_block = NULL; -extern struct list_head xgi_mempid_list; - -static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) -{ - struct page *page; - unsigned long page_addr = 0; - unsigned long page_count = 0; - int i; - - page_count = (1 << page_order); - page_addr = __get_free_pages(GFP_KERNEL, page_order); - - if (page_addr == 0UL) - { - XGI_ERROR("Can't get free pages: 0x%lx from system memory !\n", - page_count); - return 0; - } - - page = virt_to_page(page_addr); - - for (i = 0; i < page_count; i++, page++) - { - XGI_INC_PAGE_COUNT(page); - XGILockPage(page); - } - - XGI_INFO("page_count: 0x%lx page_order: 0x%lx page_addr: 0x%lx \n", - page_count, page_order, page_addr); - return page_addr; -} - -static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) -{ - struct page *page; - unsigned long page_count = 0; - int i; - - page_count = (1 << page_order); - page = virt_to_page(page_addr); - - for (i = 0; i < page_count; i++, page++) - { - XGI_DEC_PAGE_COUNT(page); - XGIUnlockPage(page); - } - - free_pages(page_addr, page_order); -} - -static int xgi_pcie_lut_init(xgi_info_t *info) -{ - unsigned char *page_addr = NULL; - unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; - unsigned long count = 0; - u8 temp = 0; - - /* Jong 06/06/2006 */ - unsigned long pcie_aperture_size; - - info->pcie.size = 128 * 1024 * 1024; - - /* Get current FB aperture size */ - temp = In3x5(0x27); - XGI_INFO("In3x5(0x27): 0x%x \n", temp); - - if (temp & 0x01) /* 256MB; Jong 06/05/2006; 0x10000000 */ - { - /* Jong 06/06/2006; allocate memory */ - pcie_aperture_size=256 * 1024 * 1024; - /* info->pcie.base = 256 * 1024 * 1024; */ /* pcie base is different from fb base */ - } - else /* 128MB; Jong 06/05/2006; 0x08000000 */ - { - /* Jong 06/06/2006; allocate memory */ - pcie_aperture_size=128 * 1024 * 1024; - /* info->pcie.base = 128 * 1024 * 1024; */ - } - - /* Jong 06/06/2006; allocate memory; it can be used for build-in kernel modules */ - /* info->pcie.base=(unsigned long)alloc_bootmem(pcie_mem_size); */ - /* total 496 MB; need 256 MB (0x10000000); start from 240 MB (0x0F000000) */ - /* info->pcie.base=ioremap(0x0F000000, 0x10000000); */ /* Cause system hang */ - info->pcie.base=pcie_aperture_size; /* works */ - /* info->pcie.base=info->fb.base + info->fb.size; */ /* System hang */ - /* info->pcie.base=128 * 1024 * 1024;*/ /* System hang */ - - XGI_INFO("Jong06062006-info->pcie.base: 0x%lx \n", info->pcie.base); - - - /* Get current lookup table page size */ - temp = bReadReg(0xB00C); - if (temp & 0x04) /* 8KB */ - { - info->lutPageSize = 8 * 1024; - } - else /* 4KB */ - { - info->lutPageSize = 4 * 1024; - } - - XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); - -#if 0 - /* Get current lookup table location */ - temp = bReadReg(0xB00C); - if (temp & 0x02) /* LFB */ - { - info->isLUTInLFB = TRUE; - /* Current we only support lookup table in LFB */ - temp &= 0xFD; - bWriteReg(0xB00C, temp); - info->isLUTInLFB = FALSE; - } - else /* SFB */ - { - info->isLUTInLFB = FALSE; - } - - XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); - - /* Get current SDFB page size */ - temp = bReadReg(0xB00C); - if (temp & 0x08) /* 8MB */ - { - info->sdfbPageSize = 8 * 1024 * 1024; - } - else /* 4MB */ - { - info->sdfbPageSize = 4 * 1024 * 1024; - } -#endif - pciePageCount = (info->pcie.size + PAGE_SIZE - 1) / PAGE_SIZE; - - /* - * Allocate memory for PCIE GART table; - */ - lutEntryNum = pciePageCount; - lutPageCount = (lutEntryNum * 4 + PAGE_SIZE - 1) / PAGE_SIZE; - - /* get page_order base on page_count */ - count = lutPageCount; - for (lutPageOrder = 0; count; count >>= 1, ++lutPageOrder); - - if ((lutPageCount << 1) == (1 << lutPageOrder)) - { - lutPageOrder -= 1; - } - - XGI_INFO("lutEntryNum: 0x%lx lutPageCount: 0x%lx lutPageOrder 0x%lx\n", - lutEntryNum, lutPageCount, lutPageOrder); - - info->lutPageOrder = lutPageOrder; - page_addr = (unsigned char *)xgi_pcie_lut_alloc(lutPageOrder); - - if (!page_addr) - { - XGI_ERROR("cannot allocate PCIE lut page!\n"); - goto fail; - } - info->lut_base = (unsigned long *)page_addr; - - XGI_INFO("page_addr: 0x%p virt_to_phys(page_virtual): 0x%lx \n", - page_addr, virt_to_phys(page_addr)); - - XGI_INFO("info->lut_base: 0x%p __pa(info->lut_base): 0x%lx info->lutPageOrder 0x%lx\n", - info->lut_base, __pa(info->lut_base), info->lutPageOrder); - - /* - * clean all PCIE GART Entry - */ - memset(page_addr, 0, PAGE_SIZE << lutPageOrder); - -#if defined(__i386__) || defined(__x86_64__) - asm volatile ( "wbinvd" ::: "memory" ); -#else - mb(); -#endif - - /* Set GART in SFB */ - bWriteReg(0xB00C, bReadReg(0xB00C) & ~0x02); - /* Set GART base address to HW */ - dwWriteReg(0xB034, __pa(info->lut_base)); - - return 1; -fail: - return 0; -} - -static void xgi_pcie_lut_cleanup(xgi_info_t *info) -{ - if (info->lut_base) - { - XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", - info->lut_base, info->lutPageOrder); - xgi_pcie_lut_free((unsigned long)info->lut_base, info->lutPageOrder); - info->lut_base = NULL; - } -} - -static xgi_pcie_block_t *xgi_pcie_new_node(void) -{ - xgi_pcie_block_t *block = (xgi_pcie_block_t *)kmem_cache_alloc(xgi_pcie_cache_block, GFP_KERNEL); - if (block == NULL) - { - return NULL; - } - - block->offset = 0; /* block's offset in pcie memory, begin from 0 */ - block->size = 0; /* The block size. */ - block->bus_addr = 0; /* CPU access address/bus address */ - block->hw_addr = 0; /* GE access address */ - block->page_count = 0; - block->page_order = 0; - block->page_block = NULL; - block->page_table = NULL; - block->owner = PCIE_INVALID; - - return block; -} - -static void xgi_pcie_block_stuff_free(xgi_pcie_block_t *block) -{ - struct page *page; - xgi_page_block_t *page_block = block->page_block; - xgi_page_block_t *free_block; - unsigned long page_count = 0; - int i; - - //XGI_INFO("block->page_block: 0x%p \n", block->page_block); - while (page_block) - { - page_count = page_block->page_count; - - page = virt_to_page(page_block->virt_addr); - for (i = 0; i < page_count; i++, page++) - { - XGI_DEC_PAGE_COUNT(page); - XGIUnlockPage(page); - } - free_pages(page_block->virt_addr, page_block->page_order); - - page_block->phys_addr = 0; - page_block->virt_addr = 0; - page_block->page_count = 0; - page_block->page_order = 0; - - free_block = page_block; - page_block = page_block->next; - //XGI_INFO("free free_block: 0x%p \n", free_block); - kfree(free_block); - free_block = NULL; - } - - if (block->page_table) - { - //XGI_INFO("free block->page_table: 0x%p \n", block->page_table); - kfree(block->page_table); - block->page_table = NULL; - } -} - -int xgi_pcie_heap_init(xgi_info_t *info) -{ - xgi_pcie_block_t *block; - - if (!xgi_pcie_lut_init(info)) - { - XGI_ERROR("xgi_pcie_lut_init failed\n"); - return 0; - } - - xgi_pcie_heap = (xgi_pcie_heap_t *)kmalloc(sizeof(xgi_pcie_heap_t), GFP_KERNEL); - if(!xgi_pcie_heap) - { - XGI_ERROR("xgi_pcie_heap alloc failed\n"); - goto fail1; - } - INIT_LIST_HEAD(&xgi_pcie_heap->free_list); - INIT_LIST_HEAD(&xgi_pcie_heap->used_list); - INIT_LIST_HEAD(&xgi_pcie_heap->sort_list); - - xgi_pcie_heap->max_freesize = info->pcie.size; - - xgi_pcie_cache_block = kmem_cache_create("xgi_pcie_block", sizeof(xgi_pcie_block_t), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - if (NULL == xgi_pcie_cache_block) - { - XGI_ERROR("Fail to creat xgi_pcie_block\n"); - goto fail2; - } - - block = (xgi_pcie_block_t *)xgi_pcie_new_node(); - if (!block) - { - XGI_ERROR("xgi_pcie_new_node failed\n"); - goto fail3; - } - - block->offset = 0; /* block's offset in pcie memory, begin from 0 */ - block->size = info->pcie.size; - - list_add(&block->list, &xgi_pcie_heap->free_list); - - XGI_INFO("PCIE start address: 0x%lx, memory size : 0x%lx\n", block->offset, block->size); - return 1; -fail3: - if (xgi_pcie_cache_block) - { - kmem_cache_destroy(xgi_pcie_cache_block); - xgi_pcie_cache_block = NULL; - } - -fail2: - if(xgi_pcie_heap) - { - kfree(xgi_pcie_heap); - xgi_pcie_heap = NULL; - } -fail1: - xgi_pcie_lut_cleanup(info); - return 0; -} - -void xgi_pcie_heap_check(void) -{ - struct list_head *useList, *temp; - xgi_pcie_block_t *block; - unsigned int ownerIndex; - char *ownerStr[6] = {"2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE"}; - - if (xgi_pcie_heap) - { - useList = &xgi_pcie_heap->used_list; - temp = useList->next; - XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); - while (temp != useList) - { - block = list_entry(temp, struct xgi_pcie_block_s, list); - if (block->owner == PCIE_2D) - ownerIndex = 0; - else if (block->owner > PCIE_3D_TEXTURE || block->owner < PCIE_2D || block->owner < PCIE_3D) - ownerIndex = 5; - else - ownerIndex = block->owner - PCIE_3D + 1; - XGI_INFO("Allocated by %s, block->offset: 0x%lx block->size: 0x%lx \n", - ownerStr[ownerIndex], block->offset, block->size); - temp = temp->next; - } - - } -} - - -void xgi_pcie_heap_cleanup(xgi_info_t *info) -{ - struct list_head *free_list, *temp; - xgi_pcie_block_t *block; - int j; - - xgi_pcie_lut_cleanup(info); - XGI_INFO("xgi_pcie_lut_cleanup scceeded\n"); - - if (xgi_pcie_heap) - { - free_list = &xgi_pcie_heap->free_list; - for (j = 0; j < 3; j++, free_list++) - { - temp = free_list->next; - - while (temp != free_list) - { - block = list_entry(temp, struct xgi_pcie_block_s, list); - XGI_INFO("No. %d block->offset: 0x%lx block->size: 0x%lx \n", - j, block->offset, block->size); - xgi_pcie_block_stuff_free(block); - block->bus_addr = 0; - block->hw_addr = 0; - - temp = temp->next; - //XGI_INFO("No. %d free block: 0x%p \n", j, block); - kmem_cache_free(xgi_pcie_cache_block, block); - block = NULL; - } - } - - XGI_INFO("free xgi_pcie_heap: 0x%p \n", xgi_pcie_heap); - kfree(xgi_pcie_heap); - xgi_pcie_heap = NULL; - } - - if (xgi_pcie_cache_block) - { - kmem_cache_destroy(xgi_pcie_cache_block); - xgi_pcie_cache_block = NULL; - } -} - - -static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t *info, - unsigned long originalSize, - enum PcieOwner owner) -{ - struct list_head *free_list; - xgi_pcie_block_t *block, *used_block, *free_block; - xgi_page_block_t *page_block, *prev_page_block; - struct page *page; - unsigned long page_order = 0, count = 0, index =0; - unsigned long page_addr = 0; - unsigned long *lut_addr = NULL; - unsigned long lut_id = 0; - unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; - int i, j, page_count = 0; - int temp = 0; - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-Begin\n"); - XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", originalSize, size); - - if (owner == PCIE_3D) - { - if (xgi_pcie_vertex_block) - { - XGI_INFO("PCIE Vertex has been created, return directly.\n"); - return xgi_pcie_vertex_block; - } - } - - if (owner == PCIE_3D_CMDLIST) - { - if (xgi_pcie_cmdlist_block) - { - XGI_INFO("PCIE Cmdlist has been created, return directly.\n"); - return xgi_pcie_cmdlist_block; - } - } - - if (owner == PCIE_3D_SCRATCHPAD) - { - if (xgi_pcie_scratchpad_block) - { - XGI_INFO("PCIE Scratchpad has been created, return directly.\n"); - return xgi_pcie_scratchpad_block; - } - } - - if (size == 0) - { - XGI_ERROR("size == 0 \n"); - return (NULL); - } - - XGI_INFO("max_freesize: 0x%lx \n", xgi_pcie_heap->max_freesize); - if (size > xgi_pcie_heap->max_freesize) - { - XGI_ERROR("size: 0x%lx bigger than PCIE total free size: 0x%lx.\n", - size, xgi_pcie_heap->max_freesize); - return (NULL); - } - - /* Jong 05/30/2006; find next free list which has enough space*/ - free_list = xgi_pcie_heap->free_list.next; - while (free_list != &xgi_pcie_heap->free_list) - { - //XGI_INFO("free_list: 0x%px \n", free_list); - block = list_entry(free_list, struct xgi_pcie_block_s, list); - if (size <= block->size) - { - break; - } - free_list = free_list->next; - } - - if (free_list == &xgi_pcie_heap->free_list) - { - XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", size/1024); - return (NULL); - } - - free_block = block; - XGI_INFO("alloc size: 0x%lx from offset: 0x%lx size: 0x%lx \n", - size, free_block->offset, free_block->size); - - if (size == free_block->size) - { - used_block = free_block; - XGI_INFO("size==free_block->size: free_block = 0x%p\n", free_block); - list_del(&free_block->list); - } - else - { - used_block = xgi_pcie_new_node(); - if (used_block == NULL) - { - return NULL; - } - - if (used_block == free_block) - { - XGI_ERROR("used_block == free_block = 0x%p\n", used_block); - } - - used_block->offset = free_block->offset; - used_block->size = size; - - free_block->offset += size; - free_block->size -= size; - } - - xgi_pcie_heap->max_freesize -= size; - - used_block->bus_addr = info->pcie.base + used_block->offset; - used_block->hw_addr = info->pcie.base + used_block->offset; - used_block->page_count = page_count = size / PAGE_SIZE; - - /* get page_order base on page_count */ - for (used_block->page_order = 0; page_count; page_count >>= 1) - { - ++used_block->page_order; - } - - if ((used_block->page_count << 1) == (1 << used_block->page_order)) - { - used_block->page_order--; - } - XGI_INFO("used_block->offset: 0x%lx, used_block->size: 0x%lx, used_block->bus_addr: 0x%lx, used_block->hw_addr: 0x%lx, used_block->page_count: 0x%lx used_block->page_order: 0x%lx\n", - used_block->offset, used_block->size, used_block->bus_addr, used_block->hw_addr, used_block->page_count, used_block->page_order); - - used_block->page_block = NULL; - //used_block->page_block = (xgi_pages_block_t *)kmalloc(sizeof(xgi_pages_block_t), GFP_KERNEL); - //if (!used_block->page_block) return NULL; - //used_block->page_block->next = NULL; - - used_block->page_table = (xgi_pte_t *)kmalloc(sizeof(xgi_pte_t) * used_block->page_count, GFP_KERNEL); - if (used_block->page_table == NULL) - { - goto fail; - } - - lut_id = (used_block->offset >> PAGE_SHIFT); - lut_addr = info->lut_base; - lut_addr += lut_id; - XGI_INFO("lutAddr: 0x%p lutID: 0x%lx \n", lut_addr, lut_id); - - /* alloc free pages from system */ - page_count = used_block->page_count; - page_block = used_block->page_block; - prev_page_block = used_block->page_block; - for (i = 0; page_count > 0; i++) - { - /* if size is bigger than 2M bytes, it should be split */ - if (page_count > (1 << XGI_PCIE_ALLOC_MAX_ORDER)) - { - page_order = XGI_PCIE_ALLOC_MAX_ORDER; - } - else - { - count = page_count; - for (page_order = 0; count; count >>= 1, ++page_order); - - if ((page_count << 1) == (1 << page_order)) - { - page_order -= 1; - } - } - - count = (1 << page_order); - page_addr = __get_free_pages(GFP_KERNEL, page_order); - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_addr=0x%lx \n", page_addr); - - if (!page_addr) - { - XGI_ERROR("No: %d :Can't get free pages: 0x%lx from system memory !\n", - i, count); - goto fail; - } - - /* Jong 05/30/2006; test */ - memset((unsigned char *)page_addr, 0xFF, PAGE_SIZE << page_order); - /* memset((unsigned char *)page_addr, 0, PAGE_SIZE << page_order); */ - - if (page_block == NULL) - { - page_block = (xgi_page_block_t *)kmalloc(sizeof(xgi_page_block_t), GFP_KERNEL); - if (!page_block) - { - XGI_ERROR("Can't get memory for page_block! \n"); - goto fail; - } - } - - if (prev_page_block == NULL) - { - used_block->page_block = page_block; - prev_page_block = page_block; - } - else - { - prev_page_block->next = page_block; - prev_page_block = page_block; - } - - page_block->next = NULL; - page_block->phys_addr = __pa(page_addr); - page_block->virt_addr = page_addr; - page_block->page_count = count; - page_block->page_order = page_order; - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_block->phys_addr=0x%lx \n", page_block->phys_addr); - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_block->virt_addr=0x%lx \n", page_block->virt_addr); - - page = virt_to_page(page_addr); - - //XGI_INFO("No: %d page_order: 0x%lx page_count: 0x%x count: 0x%lx index: 0x%lx lut_addr: 0x%p" - // "page_block->phys_addr: 0x%lx page_block->virt_addr: 0x%lx \n", - // i, page_order, page_count, count, index, lut_addr, page_block->phys_addr, page_block->virt_addr); - - for (j = 0 ; j < count; j++, page++, lut_addr++) - { - used_block->page_table[index + j].phys_addr = __pa(page_address(page)); - used_block->page_table[index + j].virt_addr = (unsigned long)page_address(page); - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].phys_addr=0x%lx \n", used_block->page_table[index + j].phys_addr); - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].virt_addr=0x%lx \n", used_block->page_table[index + j].virt_addr); - - *lut_addr = __pa(page_address(page)); - XGI_INC_PAGE_COUNT(page); - XGILockPage(page); - - if (temp) - { - XGI_INFO("__pa(page_address(page)): 0x%lx lutAddr: 0x%p lutAddr No: 0x%x = 0x%lx \n", - __pa(page_address(page)), lut_addr, j, *lut_addr); - temp--; - } - } - - page_block = page_block->next; - page_count -= count; - index += count; - temp = 0; - } - - used_block->owner = owner; - list_add(&used_block->list, &xgi_pcie_heap->used_list); - -#if defined(__i386__) || defined(__x86_64__) - asm volatile ( "wbinvd" ::: "memory" ); -#else - mb(); -#endif - - /* Flush GART Table */ - bWriteReg(0xB03F, 0x40); - bWriteReg(0xB03F, 0x00); - - if (owner == PCIE_3D) - { - xgi_pcie_vertex_block = used_block; - } - - if (owner == PCIE_3D_CMDLIST) - { - xgi_pcie_cmdlist_block = used_block; - } - - if (owner == PCIE_3D_SCRATCHPAD) - { - xgi_pcie_scratchpad_block = used_block; - } - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-End \n"); - return (used_block); - -fail: - xgi_pcie_block_stuff_free(used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - return NULL; -} - -static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t *info, unsigned long offset) -{ - struct list_head *free_list, *used_list; - xgi_pcie_block_t *used_block, *block = NULL; - xgi_pcie_block_t *prev, *next; - unsigned long upper, lower; - - used_list = xgi_pcie_heap->used_list.next; - while (used_list != &xgi_pcie_heap->used_list) - { - block = list_entry(used_list, struct xgi_pcie_block_s, list); - if (block->offset == offset) - { - break; - } - used_list = used_list->next; - } - - if (used_list == &xgi_pcie_heap->used_list) - { - XGI_ERROR("can't find block: 0x%lx to free!\n", offset); - return (NULL); - } - - used_block = block; - XGI_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx, bus_addr = 0x%lx, hw_addr = 0x%lx\n", - used_block, used_block->offset, used_block->size, used_block->bus_addr, used_block->hw_addr); - - xgi_pcie_block_stuff_free(used_block); - - /* update xgi_pcie_heap */ - xgi_pcie_heap->max_freesize += used_block->size; - - prev = next = NULL; - upper = used_block->offset + used_block->size; - lower = used_block->offset; - - free_list = xgi_pcie_heap->free_list.next; - - while (free_list != &xgi_pcie_heap->free_list) - { - block = list_entry(free_list, struct xgi_pcie_block_s, list); - if (block->offset == upper) - { - next = block; - } - else if ((block->offset + block->size) == lower) - { - prev = block; - } - free_list = free_list->next; - } - - XGI_INFO("next = 0x%p, prev = 0x%p\n", next, prev); - list_del(&used_block->list); - - if (prev && next) - { - prev->size += (used_block->size + next->size); - list_del(&next->list); - XGI_INFO("free node 0x%p\n", next); - kmem_cache_free(xgi_pcie_cache_block, next); - kmem_cache_free(xgi_pcie_cache_block, used_block); - next = NULL; - used_block = NULL; - return (prev); - } - - if (prev) - { - prev->size += used_block->size; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - used_block = NULL; - return (prev); - } - - if (next) - { - next->size += used_block->size; - next->offset = used_block->offset; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - used_block = NULL; - return (next); - } - - used_block->bus_addr = 0; - used_block->hw_addr = 0; - used_block->page_count = 0; - used_block->page_order = 0; - list_add(&used_block->list, &xgi_pcie_heap->free_list); - XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", - used_block, used_block->offset, used_block->size); - return (used_block); -} - -void xgi_pcie_alloc(xgi_info_t *info, unsigned long size, - enum PcieOwner owner, xgi_mem_alloc_t *alloc) -{ - xgi_pcie_block_t *block; - xgi_mem_pid_t *mempid_block; - - xgi_down(info->pcie_sem); - block = xgi_pcie_mem_alloc(info, size, owner); - xgi_up(info->pcie_sem); - - if (block == NULL) - { - alloc->location = INVALID; - alloc->size = 0; - alloc->bus_addr = 0; - alloc->hw_addr = 0; - XGI_ERROR("PCIE RAM allocation failed\n"); - } - else - { - XGI_INFO("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", - block->offset, block->bus_addr); - alloc->location = NON_LOCAL; - alloc->size = block->size; - alloc->bus_addr = block->bus_addr; - alloc->hw_addr = block->hw_addr; - - /* - manage mempid, handle PCIE_3D, PCIE_3D_TEXTURE. - PCIE_3D request means a opengl process created. - PCIE_3D_TEXTURE request means texture cannot alloc from fb. - */ - if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) - { - mempid_block = kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); - if (!mempid_block) - XGI_ERROR("mempid_block alloc failed\n"); - mempid_block->location = NON_LOCAL; - if (owner == PCIE_3D) - mempid_block->bus_addr = 0xFFFFFFFF;/*xgi_pcie_vertex_block has the address*/ - else - mempid_block->bus_addr = alloc->bus_addr; - mempid_block->pid = alloc->pid; - - XGI_INFO("Memory ProcessID add one pcie block pid:%ld successfully! \n", mempid_block->pid); - list_add(&mempid_block->list, &xgi_mempid_list); - } - } -} - -void xgi_pcie_free(xgi_info_t *info, unsigned long bus_addr) -{ - xgi_pcie_block_t *block; - unsigned long offset = bus_addr - info->pcie.base; - xgi_mem_pid_t *mempid_block; - xgi_mem_pid_t *mempid_freeblock = NULL; - struct list_head *mempid_list; - char isvertex = 0; - int processcnt; - - if (xgi_pcie_vertex_block && xgi_pcie_vertex_block->bus_addr == bus_addr) - isvertex = 1; - - if (isvertex) - { - /*check is there any other process using vertex*/ - processcnt = 0; - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) - { - mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); - if (mempid_block->location == NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) - { - ++processcnt; - } - mempid_list = mempid_list->next; - } - if (processcnt > 1) - { - return; - } - } - - xgi_down(info->pcie_sem); - block = xgi_pcie_mem_free(info, offset); - xgi_up(info->pcie_sem); - - if (block == NULL) - { - XGI_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); - } - - if (isvertex) - xgi_pcie_vertex_block = NULL; - - /* manage mempid */ - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) - { - mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); - if (mempid_block->location == NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) - { - mempid_freeblock = mempid_block; - break; - } - mempid_list = mempid_list->next; - } - if (mempid_freeblock) - { - list_del(&mempid_freeblock->list); - XGI_INFO("Memory ProcessID delete one pcie block pid:%ld successfully! \n", mempid_freeblock->pid); - kfree(mempid_freeblock); - } -} - -/* - * given a bus address, fid the pcie mem block - * uses the bus address as the key. - */ -void *xgi_find_pcie_block(xgi_info_t *info, unsigned long address) -{ - struct list_head *used_list; - xgi_pcie_block_t *block; - int i; - - used_list = xgi_pcie_heap->used_list.next; - - while (used_list != &xgi_pcie_heap->used_list) - { - block = list_entry(used_list, struct xgi_pcie_block_s, list); - - if (block->bus_addr == address) - { - return block; - } - - if (block->page_table) - { - for (i = 0; i < block->page_count; i++) - { - unsigned long offset = block->bus_addr; - if ( (address >= offset) && (address < (offset + PAGE_SIZE))) - { - return block; - } - } - } - used_list = used_list->next; - } - - XGI_ERROR("could not find map for vm 0x%lx\n", address); - - return NULL; -} - -/* - address -- GE HW address - return -- CPU virtual address - - assume the CPU VAddr is continuous in not the same block -*/ -void *xgi_find_pcie_virt(xgi_info_t *info, unsigned long address) -{ - struct list_head *used_list; - xgi_pcie_block_t *block; - unsigned long offset_in_page; - unsigned long loc_in_pagetable; - void * ret; - - XGI_INFO("Jong_05292006-xgi_find_pcie_virt-Begin\n"); - - used_list = xgi_pcie_heap->used_list.next; - XGI_INFO("Jong_05292006-used_list=%ul\n", used_list); - - offset_in_page = address & (PAGE_SIZE-1); - XGI_INFO("Jong_05292006-address=0x%px, PAGE_SIZE-1=%ul, offset_in_page=%ul\n", address, PAGE_SIZE-1, offset_in_page); - - while (used_list != &xgi_pcie_heap->used_list) - { - block = list_entry(used_list, struct xgi_pcie_block_s, list); - XGI_INFO("Jong_05292006-block=0x%px\n", block); - XGI_INFO("Jong_05292006-block->hw_addr=0x%px\n", block->hw_addr); - XGI_INFO("Jong_05292006- block->size=%ul\n", block->size); - - if ((address >= block->hw_addr) && (address < (block->hw_addr + block->size))) - { - loc_in_pagetable = (address - block->hw_addr) >> PAGE_SHIFT; - ret = (void*)(block->page_table[loc_in_pagetable].virt_addr + offset_in_page); - - XGI_INFO("Jong_05292006-PAGE_SHIFT=%d\n", PAGE_SHIFT); - XGI_INFO("Jong_05292006-loc_in_pagetable=0x%px\n", loc_in_pagetable); - XGI_INFO("Jong_05292006-block->page_table[loc_in_pagetable].virt_addr=0x%px\n", block->page_table[loc_in_pagetable].virt_addr); - XGI_INFO("Jong_05292006-offset_in_page=%d\n", offset_in_page); - XGI_INFO("Jong_05292006-return(virt_addr)=0x%px\n", ret); - - return ret ; - } - else - { - XGI_INFO("Jong_05292006-used_list = used_list->next;\n"); - used_list = used_list->next; - } - } - - XGI_ERROR("could not find map for vm 0x%lx\n", address); - return NULL; -} - - -void xgi_read_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req) -{ - -} - -void xgi_write_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req) -{ -} - -/* - address -- GE hw address -*/ -void xgi_test_rwinkernel(xgi_info_t *info, unsigned long address) -{ - unsigned long * virtaddr = 0; - if (address == 0) - { - XGI_INFO("[Jong-kd] input GE HW addr is 0x00000000\n"); - return; - } - - virtaddr = (unsigned long *) xgi_find_pcie_virt(info, address); - - XGI_INFO("[Jong-kd] input GE HW addr is 0x%lx\n", address); - XGI_INFO("[Jong-kd] convert to CPU virt addr 0x%px\n", virtaddr); - XGI_INFO("[Jong-kd] origin [virtaddr] = 0x%lx\n", *virtaddr); - if (virtaddr != NULL) - { - *virtaddr = 0x00f00fff; - } - - XGI_INFO("[Jong-kd] modified [virtaddr] = 0x%lx\n", *virtaddr); -} - + +/**************************************************************************** + * Copyright (C) 2003-2006 by XGI Technology, Taiwan. + * * + * All Rights Reserved. * + * * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL XGI AND/OR + * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ***************************************************************************/ + +#include "xgi_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_regs.h" +#include "xgi_pcie.h" +#include "xgi_misc.h" + +static xgi_pcie_heap_t *xgi_pcie_heap = NULL; +static kmem_cache_t *xgi_pcie_cache_block = NULL; +static xgi_pcie_block_t *xgi_pcie_vertex_block = NULL; +static xgi_pcie_block_t *xgi_pcie_cmdlist_block = NULL; +static xgi_pcie_block_t *xgi_pcie_scratchpad_block = NULL; +extern struct list_head xgi_mempid_list; + +static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) +{ + struct page *page; + unsigned long page_addr = 0; + unsigned long page_count = 0; + int i; + + page_count = (1 << page_order); + page_addr = __get_free_pages(GFP_KERNEL, page_order); + + if (page_addr == 0UL) { + XGI_ERROR("Can't get free pages: 0x%lx from system memory !\n", + page_count); + return 0; + } + + page = virt_to_page(page_addr); + + for (i = 0; i < page_count; i++, page++) { + XGI_INC_PAGE_COUNT(page); + XGILockPage(page); + } + + XGI_INFO("page_count: 0x%lx page_order: 0x%lx page_addr: 0x%lx \n", + page_count, page_order, page_addr); + return page_addr; +} + +static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) +{ + struct page *page; + unsigned long page_count = 0; + int i; + + page_count = (1 << page_order); + page = virt_to_page(page_addr); + + for (i = 0; i < page_count; i++, page++) { + XGI_DEC_PAGE_COUNT(page); + XGIUnlockPage(page); + } + + free_pages(page_addr, page_order); +} + +static int xgi_pcie_lut_init(xgi_info_t * info) +{ + unsigned char *page_addr = NULL; + unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; + unsigned long count = 0; + u8 temp = 0; + + /* Jong 06/06/2006 */ + unsigned long pcie_aperture_size; + + info->pcie.size = 128 * 1024 * 1024; + + /* Get current FB aperture size */ + temp = In3x5(0x27); + XGI_INFO("In3x5(0x27): 0x%x \n", temp); + + if (temp & 0x01) { /* 256MB; Jong 06/05/2006; 0x10000000 */ + /* Jong 06/06/2006; allocate memory */ + pcie_aperture_size = 256 * 1024 * 1024; + /* info->pcie.base = 256 * 1024 * 1024; *//* pcie base is different from fb base */ + } else { /* 128MB; Jong 06/05/2006; 0x08000000 */ + + /* Jong 06/06/2006; allocate memory */ + pcie_aperture_size = 128 * 1024 * 1024; + /* info->pcie.base = 128 * 1024 * 1024; */ + } + + /* Jong 06/06/2006; allocate memory; it can be used for build-in kernel modules */ + /* info->pcie.base=(unsigned long)alloc_bootmem(pcie_mem_size); */ + /* total 496 MB; need 256 MB (0x10000000); start from 240 MB (0x0F000000) */ + /* info->pcie.base=ioremap(0x0F000000, 0x10000000); *//* Cause system hang */ + info->pcie.base = pcie_aperture_size; /* works */ + /* info->pcie.base=info->fb.base + info->fb.size; *//* System hang */ + /* info->pcie.base=128 * 1024 * 1024; *//* System hang */ + + XGI_INFO("Jong06062006-info->pcie.base: 0x%lx \n", info->pcie.base); + + /* Get current lookup table page size */ + temp = bReadReg(0xB00C); + if (temp & 0x04) { /* 8KB */ + info->lutPageSize = 8 * 1024; + } else { /* 4KB */ + + info->lutPageSize = 4 * 1024; + } + + XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + +#if 0 + /* Get current lookup table location */ + temp = bReadReg(0xB00C); + if (temp & 0x02) { /* LFB */ + info->isLUTInLFB = TRUE; + /* Current we only support lookup table in LFB */ + temp &= 0xFD; + bWriteReg(0xB00C, temp); + info->isLUTInLFB = FALSE; + } else { /* SFB */ + + info->isLUTInLFB = FALSE; + } + + XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + + /* Get current SDFB page size */ + temp = bReadReg(0xB00C); + if (temp & 0x08) { /* 8MB */ + info->sdfbPageSize = 8 * 1024 * 1024; + } else { /* 4MB */ + + info->sdfbPageSize = 4 * 1024 * 1024; + } +#endif + pciePageCount = (info->pcie.size + PAGE_SIZE - 1) / PAGE_SIZE; + + /* + * Allocate memory for PCIE GART table; + */ + lutEntryNum = pciePageCount; + lutPageCount = (lutEntryNum * 4 + PAGE_SIZE - 1) / PAGE_SIZE; + + /* get page_order base on page_count */ + count = lutPageCount; + for (lutPageOrder = 0; count; count >>= 1, ++lutPageOrder) ; + + if ((lutPageCount << 1) == (1 << lutPageOrder)) { + lutPageOrder -= 1; + } + + XGI_INFO("lutEntryNum: 0x%lx lutPageCount: 0x%lx lutPageOrder 0x%lx\n", + lutEntryNum, lutPageCount, lutPageOrder); + + info->lutPageOrder = lutPageOrder; + page_addr = (unsigned char *)xgi_pcie_lut_alloc(lutPageOrder); + + if (!page_addr) { + XGI_ERROR("cannot allocate PCIE lut page!\n"); + goto fail; + } + info->lut_base = (unsigned long *)page_addr; + + XGI_INFO("page_addr: 0x%p virt_to_phys(page_virtual): 0x%lx \n", + page_addr, virt_to_phys(page_addr)); + + XGI_INFO + ("info->lut_base: 0x%p __pa(info->lut_base): 0x%lx info->lutPageOrder 0x%lx\n", + info->lut_base, __pa(info->lut_base), info->lutPageOrder); + + /* + * clean all PCIE GART Entry + */ + memset(page_addr, 0, PAGE_SIZE << lutPageOrder); + +#if defined(__i386__) || defined(__x86_64__) + asm volatile ("wbinvd":::"memory"); +#else + mb(); +#endif + + /* Set GART in SFB */ + bWriteReg(0xB00C, bReadReg(0xB00C) & ~0x02); + /* Set GART base address to HW */ + dwWriteReg(0xB034, __pa(info->lut_base)); + + return 1; + fail: + return 0; +} + +static void xgi_pcie_lut_cleanup(xgi_info_t * info) +{ + if (info->lut_base) { + XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", + info->lut_base, info->lutPageOrder); + xgi_pcie_lut_free((unsigned long)info->lut_base, + info->lutPageOrder); + info->lut_base = NULL; + } +} + +static xgi_pcie_block_t *xgi_pcie_new_node(void) +{ + xgi_pcie_block_t *block = + (xgi_pcie_block_t *) kmem_cache_alloc(xgi_pcie_cache_block, + GFP_KERNEL); + if (block == NULL) { + return NULL; + } + + block->offset = 0; /* block's offset in pcie memory, begin from 0 */ + block->size = 0; /* The block size. */ + block->bus_addr = 0; /* CPU access address/bus address */ + block->hw_addr = 0; /* GE access address */ + block->page_count = 0; + block->page_order = 0; + block->page_block = NULL; + block->page_table = NULL; + block->owner = PCIE_INVALID; + + return block; +} + +static void xgi_pcie_block_stuff_free(xgi_pcie_block_t * block) +{ + struct page *page; + xgi_page_block_t *page_block = block->page_block; + xgi_page_block_t *free_block; + unsigned long page_count = 0; + int i; + + //XGI_INFO("block->page_block: 0x%p \n", block->page_block); + while (page_block) { + page_count = page_block->page_count; + + page = virt_to_page(page_block->virt_addr); + for (i = 0; i < page_count; i++, page++) { + XGI_DEC_PAGE_COUNT(page); + XGIUnlockPage(page); + } + free_pages(page_block->virt_addr, page_block->page_order); + + page_block->phys_addr = 0; + page_block->virt_addr = 0; + page_block->page_count = 0; + page_block->page_order = 0; + + free_block = page_block; + page_block = page_block->next; + //XGI_INFO("free free_block: 0x%p \n", free_block); + kfree(free_block); + free_block = NULL; + } + + if (block->page_table) { + //XGI_INFO("free block->page_table: 0x%p \n", block->page_table); + kfree(block->page_table); + block->page_table = NULL; + } +} + +int xgi_pcie_heap_init(xgi_info_t * info) +{ + xgi_pcie_block_t *block; + + if (!xgi_pcie_lut_init(info)) { + XGI_ERROR("xgi_pcie_lut_init failed\n"); + return 0; + } + + xgi_pcie_heap = + (xgi_pcie_heap_t *) kmalloc(sizeof(xgi_pcie_heap_t), GFP_KERNEL); + if (!xgi_pcie_heap) { + XGI_ERROR("xgi_pcie_heap alloc failed\n"); + goto fail1; + } + INIT_LIST_HEAD(&xgi_pcie_heap->free_list); + INIT_LIST_HEAD(&xgi_pcie_heap->used_list); + INIT_LIST_HEAD(&xgi_pcie_heap->sort_list); + + xgi_pcie_heap->max_freesize = info->pcie.size; + + xgi_pcie_cache_block = + kmem_cache_create("xgi_pcie_block", sizeof(xgi_pcie_block_t), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (NULL == xgi_pcie_cache_block) { + XGI_ERROR("Fail to creat xgi_pcie_block\n"); + goto fail2; + } + + block = (xgi_pcie_block_t *) xgi_pcie_new_node(); + if (!block) { + XGI_ERROR("xgi_pcie_new_node failed\n"); + goto fail3; + } + + block->offset = 0; /* block's offset in pcie memory, begin from 0 */ + block->size = info->pcie.size; + + list_add(&block->list, &xgi_pcie_heap->free_list); + + XGI_INFO("PCIE start address: 0x%lx, memory size : 0x%lx\n", + block->offset, block->size); + return 1; + fail3: + if (xgi_pcie_cache_block) { + kmem_cache_destroy(xgi_pcie_cache_block); + xgi_pcie_cache_block = NULL; + } + + fail2: + if (xgi_pcie_heap) { + kfree(xgi_pcie_heap); + xgi_pcie_heap = NULL; + } + fail1: + xgi_pcie_lut_cleanup(info); + return 0; +} + +void xgi_pcie_heap_check(void) +{ + struct list_head *useList, *temp; + xgi_pcie_block_t *block; + unsigned int ownerIndex; + char *ownerStr[6] = + { "2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE" }; + + if (xgi_pcie_heap) { + useList = &xgi_pcie_heap->used_list; + temp = useList->next; + XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); + while (temp != useList) { + block = list_entry(temp, struct xgi_pcie_block_s, list); + if (block->owner == PCIE_2D) + ownerIndex = 0; + else if (block->owner > PCIE_3D_TEXTURE + || block->owner < PCIE_2D + || block->owner < PCIE_3D) + ownerIndex = 5; + else + ownerIndex = block->owner - PCIE_3D + 1; + XGI_INFO + ("Allocated by %s, block->offset: 0x%lx block->size: 0x%lx \n", + ownerStr[ownerIndex], block->offset, block->size); + temp = temp->next; + } + + } +} + +void xgi_pcie_heap_cleanup(xgi_info_t * info) +{ + struct list_head *free_list, *temp; + xgi_pcie_block_t *block; + int j; + + xgi_pcie_lut_cleanup(info); + XGI_INFO("xgi_pcie_lut_cleanup scceeded\n"); + + if (xgi_pcie_heap) { + free_list = &xgi_pcie_heap->free_list; + for (j = 0; j < 3; j++, free_list++) { + temp = free_list->next; + + while (temp != free_list) { + block = + list_entry(temp, struct xgi_pcie_block_s, + list); + XGI_INFO + ("No. %d block->offset: 0x%lx block->size: 0x%lx \n", + j, block->offset, block->size); + xgi_pcie_block_stuff_free(block); + block->bus_addr = 0; + block->hw_addr = 0; + + temp = temp->next; + //XGI_INFO("No. %d free block: 0x%p \n", j, block); + kmem_cache_free(xgi_pcie_cache_block, block); + block = NULL; + } + } + + XGI_INFO("free xgi_pcie_heap: 0x%p \n", xgi_pcie_heap); + kfree(xgi_pcie_heap); + xgi_pcie_heap = NULL; + } + + if (xgi_pcie_cache_block) { + kmem_cache_destroy(xgi_pcie_cache_block); + xgi_pcie_cache_block = NULL; + } +} + +static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, + unsigned long originalSize, + enum PcieOwner owner) +{ + struct list_head *free_list; + xgi_pcie_block_t *block, *used_block, *free_block; + xgi_page_block_t *page_block, *prev_page_block; + struct page *page; + unsigned long page_order = 0, count = 0, index = 0; + unsigned long page_addr = 0; + unsigned long *lut_addr = NULL; + unsigned long lut_id = 0; + unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; + int i, j, page_count = 0; + int temp = 0; + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-Begin\n"); + XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", + originalSize, size); + + if (owner == PCIE_3D) { + if (xgi_pcie_vertex_block) { + XGI_INFO + ("PCIE Vertex has been created, return directly.\n"); + return xgi_pcie_vertex_block; + } + } + + if (owner == PCIE_3D_CMDLIST) { + if (xgi_pcie_cmdlist_block) { + XGI_INFO + ("PCIE Cmdlist has been created, return directly.\n"); + return xgi_pcie_cmdlist_block; + } + } + + if (owner == PCIE_3D_SCRATCHPAD) { + if (xgi_pcie_scratchpad_block) { + XGI_INFO + ("PCIE Scratchpad has been created, return directly.\n"); + return xgi_pcie_scratchpad_block; + } + } + + if (size == 0) { + XGI_ERROR("size == 0 \n"); + return (NULL); + } + + XGI_INFO("max_freesize: 0x%lx \n", xgi_pcie_heap->max_freesize); + if (size > xgi_pcie_heap->max_freesize) { + XGI_ERROR + ("size: 0x%lx bigger than PCIE total free size: 0x%lx.\n", + size, xgi_pcie_heap->max_freesize); + return (NULL); + } + + /* Jong 05/30/2006; find next free list which has enough space */ + free_list = xgi_pcie_heap->free_list.next; + while (free_list != &xgi_pcie_heap->free_list) { + //XGI_INFO("free_list: 0x%px \n", free_list); + block = list_entry(free_list, struct xgi_pcie_block_s, list); + if (size <= block->size) { + break; + } + free_list = free_list->next; + } + + if (free_list == &xgi_pcie_heap->free_list) { + XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", + size / 1024); + return (NULL); + } + + free_block = block; + XGI_INFO("alloc size: 0x%lx from offset: 0x%lx size: 0x%lx \n", + size, free_block->offset, free_block->size); + + if (size == free_block->size) { + used_block = free_block; + XGI_INFO("size==free_block->size: free_block = 0x%p\n", + free_block); + list_del(&free_block->list); + } else { + used_block = xgi_pcie_new_node(); + if (used_block == NULL) { + return NULL; + } + + if (used_block == free_block) { + XGI_ERROR("used_block == free_block = 0x%p\n", + used_block); + } + + used_block->offset = free_block->offset; + used_block->size = size; + + free_block->offset += size; + free_block->size -= size; + } + + xgi_pcie_heap->max_freesize -= size; + + used_block->bus_addr = info->pcie.base + used_block->offset; + used_block->hw_addr = info->pcie.base + used_block->offset; + used_block->page_count = page_count = size / PAGE_SIZE; + + /* get page_order base on page_count */ + for (used_block->page_order = 0; page_count; page_count >>= 1) { + ++used_block->page_order; + } + + if ((used_block->page_count << 1) == (1 << used_block->page_order)) { + used_block->page_order--; + } + XGI_INFO + ("used_block->offset: 0x%lx, used_block->size: 0x%lx, used_block->bus_addr: 0x%lx, used_block->hw_addr: 0x%lx, used_block->page_count: 0x%lx used_block->page_order: 0x%lx\n", + used_block->offset, used_block->size, used_block->bus_addr, + used_block->hw_addr, used_block->page_count, + used_block->page_order); + + used_block->page_block = NULL; + //used_block->page_block = (xgi_pages_block_t *)kmalloc(sizeof(xgi_pages_block_t), GFP_KERNEL); + //if (!used_block->page_block) return NULL; + //used_block->page_block->next = NULL; + + used_block->page_table = + (xgi_pte_t *) kmalloc(sizeof(xgi_pte_t) * used_block->page_count, + GFP_KERNEL); + if (used_block->page_table == NULL) { + goto fail; + } + + lut_id = (used_block->offset >> PAGE_SHIFT); + lut_addr = info->lut_base; + lut_addr += lut_id; + XGI_INFO("lutAddr: 0x%p lutID: 0x%lx \n", lut_addr, lut_id); + + /* alloc free pages from system */ + page_count = used_block->page_count; + page_block = used_block->page_block; + prev_page_block = used_block->page_block; + for (i = 0; page_count > 0; i++) { + /* if size is bigger than 2M bytes, it should be split */ + if (page_count > (1 << XGI_PCIE_ALLOC_MAX_ORDER)) { + page_order = XGI_PCIE_ALLOC_MAX_ORDER; + } else { + count = page_count; + for (page_order = 0; count; count >>= 1, ++page_order) ; + + if ((page_count << 1) == (1 << page_order)) { + page_order -= 1; + } + } + + count = (1 << page_order); + page_addr = __get_free_pages(GFP_KERNEL, page_order); + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_addr=0x%lx \n", + page_addr); + + if (!page_addr) { + XGI_ERROR + ("No: %d :Can't get free pages: 0x%lx from system memory !\n", + i, count); + goto fail; + } + + /* Jong 05/30/2006; test */ + memset((unsigned char *)page_addr, 0xFF, + PAGE_SIZE << page_order); + /* memset((unsigned char *)page_addr, 0, PAGE_SIZE << page_order); */ + + if (page_block == NULL) { + page_block = + (xgi_page_block_t *) + kmalloc(sizeof(xgi_page_block_t), GFP_KERNEL); + if (!page_block) { + XGI_ERROR + ("Can't get memory for page_block! \n"); + goto fail; + } + } + + if (prev_page_block == NULL) { + used_block->page_block = page_block; + prev_page_block = page_block; + } else { + prev_page_block->next = page_block; + prev_page_block = page_block; + } + + page_block->next = NULL; + page_block->phys_addr = __pa(page_addr); + page_block->virt_addr = page_addr; + page_block->page_count = count; + page_block->page_order = page_order; + + XGI_INFO + ("Jong05302006-xgi_pcie_mem_alloc-page_block->phys_addr=0x%lx \n", + page_block->phys_addr); + XGI_INFO + ("Jong05302006-xgi_pcie_mem_alloc-page_block->virt_addr=0x%lx \n", + page_block->virt_addr); + + page = virt_to_page(page_addr); + + //XGI_INFO("No: %d page_order: 0x%lx page_count: 0x%x count: 0x%lx index: 0x%lx lut_addr: 0x%p" + // "page_block->phys_addr: 0x%lx page_block->virt_addr: 0x%lx \n", + // i, page_order, page_count, count, index, lut_addr, page_block->phys_addr, page_block->virt_addr); + + for (j = 0; j < count; j++, page++, lut_addr++) { + used_block->page_table[index + j].phys_addr = + __pa(page_address(page)); + used_block->page_table[index + j].virt_addr = + (unsigned long)page_address(page); + + XGI_INFO + ("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].phys_addr=0x%lx \n", + used_block->page_table[index + j].phys_addr); + XGI_INFO + ("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].virt_addr=0x%lx \n", + used_block->page_table[index + j].virt_addr); + + *lut_addr = __pa(page_address(page)); + XGI_INC_PAGE_COUNT(page); + XGILockPage(page); + + if (temp) { + XGI_INFO + ("__pa(page_address(page)): 0x%lx lutAddr: 0x%p lutAddr No: 0x%x = 0x%lx \n", + __pa(page_address(page)), lut_addr, j, + *lut_addr); + temp--; + } + } + + page_block = page_block->next; + page_count -= count; + index += count; + temp = 0; + } + + used_block->owner = owner; + list_add(&used_block->list, &xgi_pcie_heap->used_list); + +#if defined(__i386__) || defined(__x86_64__) + asm volatile ("wbinvd":::"memory"); +#else + mb(); +#endif + + /* Flush GART Table */ + bWriteReg(0xB03F, 0x40); + bWriteReg(0xB03F, 0x00); + + if (owner == PCIE_3D) { + xgi_pcie_vertex_block = used_block; + } + + if (owner == PCIE_3D_CMDLIST) { + xgi_pcie_cmdlist_block = used_block; + } + + if (owner == PCIE_3D_SCRATCHPAD) { + xgi_pcie_scratchpad_block = used_block; + } + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-End \n"); + return (used_block); + + fail: + xgi_pcie_block_stuff_free(used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + return NULL; +} + +static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t * info, + unsigned long offset) +{ + struct list_head *free_list, *used_list; + xgi_pcie_block_t *used_block, *block = NULL; + xgi_pcie_block_t *prev, *next; + unsigned long upper, lower; + + used_list = xgi_pcie_heap->used_list.next; + while (used_list != &xgi_pcie_heap->used_list) { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + if (block->offset == offset) { + break; + } + used_list = used_list->next; + } + + if (used_list == &xgi_pcie_heap->used_list) { + XGI_ERROR("can't find block: 0x%lx to free!\n", offset); + return (NULL); + } + + used_block = block; + XGI_INFO + ("used_block: 0x%p, offset = 0x%lx, size = 0x%lx, bus_addr = 0x%lx, hw_addr = 0x%lx\n", + used_block, used_block->offset, used_block->size, + used_block->bus_addr, used_block->hw_addr); + + xgi_pcie_block_stuff_free(used_block); + + /* update xgi_pcie_heap */ + xgi_pcie_heap->max_freesize += used_block->size; + + prev = next = NULL; + upper = used_block->offset + used_block->size; + lower = used_block->offset; + + free_list = xgi_pcie_heap->free_list.next; + + while (free_list != &xgi_pcie_heap->free_list) { + block = list_entry(free_list, struct xgi_pcie_block_s, list); + if (block->offset == upper) { + next = block; + } else if ((block->offset + block->size) == lower) { + prev = block; + } + free_list = free_list->next; + } + + XGI_INFO("next = 0x%p, prev = 0x%p\n", next, prev); + list_del(&used_block->list); + + if (prev && next) { + prev->size += (used_block->size + next->size); + list_del(&next->list); + XGI_INFO("free node 0x%p\n", next); + kmem_cache_free(xgi_pcie_cache_block, next); + kmem_cache_free(xgi_pcie_cache_block, used_block); + next = NULL; + used_block = NULL; + return (prev); + } + + if (prev) { + prev->size += used_block->size; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + used_block = NULL; + return (prev); + } + + if (next) { + next->size += used_block->size; + next->offset = used_block->offset; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + used_block = NULL; + return (next); + } + + used_block->bus_addr = 0; + used_block->hw_addr = 0; + used_block->page_count = 0; + used_block->page_order = 0; + list_add(&used_block->list, &xgi_pcie_heap->free_list); + XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", + used_block, used_block->offset, used_block->size); + return (used_block); +} + +void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, + enum PcieOwner owner, xgi_mem_alloc_t * alloc) +{ + xgi_pcie_block_t *block; + xgi_mem_pid_t *mempid_block; + + xgi_down(info->pcie_sem); + block = xgi_pcie_mem_alloc(info, size, owner); + xgi_up(info->pcie_sem); + + if (block == NULL) { + alloc->location = INVALID; + alloc->size = 0; + alloc->bus_addr = 0; + alloc->hw_addr = 0; + XGI_ERROR("PCIE RAM allocation failed\n"); + } else { + XGI_INFO + ("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", + block->offset, block->bus_addr); + alloc->location = NON_LOCAL; + alloc->size = block->size; + alloc->bus_addr = block->bus_addr; + alloc->hw_addr = block->hw_addr; + + /* + manage mempid, handle PCIE_3D, PCIE_3D_TEXTURE. + PCIE_3D request means a opengl process created. + PCIE_3D_TEXTURE request means texture cannot alloc from fb. + */ + if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) { + mempid_block = + kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); + if (!mempid_block) + XGI_ERROR("mempid_block alloc failed\n"); + mempid_block->location = NON_LOCAL; + if (owner == PCIE_3D) + mempid_block->bus_addr = 0xFFFFFFFF; /*xgi_pcie_vertex_block has the address */ + else + mempid_block->bus_addr = alloc->bus_addr; + mempid_block->pid = alloc->pid; + + XGI_INFO + ("Memory ProcessID add one pcie block pid:%ld successfully! \n", + mempid_block->pid); + list_add(&mempid_block->list, &xgi_mempid_list); + } + } +} + +void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) +{ + xgi_pcie_block_t *block; + unsigned long offset = bus_addr - info->pcie.base; + xgi_mem_pid_t *mempid_block; + xgi_mem_pid_t *mempid_freeblock = NULL; + struct list_head *mempid_list; + char isvertex = 0; + int processcnt; + + if (xgi_pcie_vertex_block + && xgi_pcie_vertex_block->bus_addr == bus_addr) + isvertex = 1; + + if (isvertex) { + /*check is there any other process using vertex */ + processcnt = 0; + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) { + mempid_block = + list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == NON_LOCAL + && mempid_block->bus_addr == 0xFFFFFFFF) { + ++processcnt; + } + mempid_list = mempid_list->next; + } + if (processcnt > 1) { + return; + } + } + + xgi_down(info->pcie_sem); + block = xgi_pcie_mem_free(info, offset); + xgi_up(info->pcie_sem); + + if (block == NULL) { + XGI_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); + } + + if (isvertex) + xgi_pcie_vertex_block = NULL; + + /* manage mempid */ + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) { + mempid_block = + list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == NON_LOCAL + && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) + || (!isvertex && mempid_block->bus_addr == bus_addr))) { + mempid_freeblock = mempid_block; + break; + } + mempid_list = mempid_list->next; + } + if (mempid_freeblock) { + list_del(&mempid_freeblock->list); + XGI_INFO + ("Memory ProcessID delete one pcie block pid:%ld successfully! \n", + mempid_freeblock->pid); + kfree(mempid_freeblock); + } +} + +/* + * given a bus address, fid the pcie mem block + * uses the bus address as the key. + */ +void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address) +{ + struct list_head *used_list; + xgi_pcie_block_t *block; + int i; + + used_list = xgi_pcie_heap->used_list.next; + + while (used_list != &xgi_pcie_heap->used_list) { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + + if (block->bus_addr == address) { + return block; + } + + if (block->page_table) { + for (i = 0; i < block->page_count; i++) { + unsigned long offset = block->bus_addr; + if ((address >= offset) + && (address < (offset + PAGE_SIZE))) { + return block; + } + } + } + used_list = used_list->next; + } + + XGI_ERROR("could not find map for vm 0x%lx\n", address); + + return NULL; +} + +/* + address -- GE HW address + return -- CPU virtual address + + assume the CPU VAddr is continuous in not the same block +*/ +void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) +{ + struct list_head *used_list; + xgi_pcie_block_t *block; + unsigned long offset_in_page; + unsigned long loc_in_pagetable; + void *ret; + + XGI_INFO("Jong_05292006-xgi_find_pcie_virt-Begin\n"); + + used_list = xgi_pcie_heap->used_list.next; + XGI_INFO("Jong_05292006-used_list=%ul\n", used_list); + + offset_in_page = address & (PAGE_SIZE - 1); + XGI_INFO + ("Jong_05292006-address=0x%px, PAGE_SIZE-1=%ul, offset_in_page=%ul\n", + address, PAGE_SIZE - 1, offset_in_page); + + while (used_list != &xgi_pcie_heap->used_list) { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + XGI_INFO("Jong_05292006-block=0x%px\n", block); + XGI_INFO("Jong_05292006-block->hw_addr=0x%px\n", + block->hw_addr); + XGI_INFO("Jong_05292006- block->size=%ul\n", block->size); + + if ((address >= block->hw_addr) + && (address < (block->hw_addr + block->size))) { + loc_in_pagetable = + (address - block->hw_addr) >> PAGE_SHIFT; + ret = + (void *)(block->page_table[loc_in_pagetable]. + virt_addr + offset_in_page); + + XGI_INFO("Jong_05292006-PAGE_SHIFT=%d\n", PAGE_SHIFT); + XGI_INFO("Jong_05292006-loc_in_pagetable=0x%px\n", + loc_in_pagetable); + XGI_INFO + ("Jong_05292006-block->page_table[loc_in_pagetable].virt_addr=0x%px\n", + block->page_table[loc_in_pagetable].virt_addr); + XGI_INFO("Jong_05292006-offset_in_page=%d\n", + offset_in_page); + XGI_INFO("Jong_05292006-return(virt_addr)=0x%px\n", + ret); + + return ret; + } else { + XGI_INFO + ("Jong_05292006-used_list = used_list->next;\n"); + used_list = used_list->next; + } + } + + XGI_ERROR("could not find map for vm 0x%lx\n", address); + return NULL; +} + +void xgi_read_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req) +{ + +} + +void xgi_write_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req) +{ +} + +/* + address -- GE hw address +*/ +void xgi_test_rwinkernel(xgi_info_t * info, unsigned long address) +{ + unsigned long *virtaddr = 0; + if (address == 0) { + XGI_INFO("[Jong-kd] input GE HW addr is 0x00000000\n"); + return; + } + + virtaddr = (unsigned long *)xgi_find_pcie_virt(info, address); + + XGI_INFO("[Jong-kd] input GE HW addr is 0x%lx\n", address); + XGI_INFO("[Jong-kd] convert to CPU virt addr 0x%px\n", virtaddr); + XGI_INFO("[Jong-kd] origin [virtaddr] = 0x%lx\n", *virtaddr); + if (virtaddr != NULL) { + *virtaddr = 0x00f00fff; + } + + XGI_INFO("[Jong-kd] modified [virtaddr] = 0x%lx\n", *virtaddr); +} -- cgit v1.2.3 From 8cee7dca95bc2114eb90640cf83ac87c29243683 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:46:36 -0700 Subject: Clean up warnings about unused variables and functions. --- linux-core/xgi_pcie.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 9457770a..8b024e4a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -350,8 +350,10 @@ void xgi_pcie_heap_check(void) struct list_head *useList, *temp; xgi_pcie_block_t *block; unsigned int ownerIndex; +#ifdef XGI_DEBUG char *ownerStr[6] = { "2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE" }; +#endif if (xgi_pcie_heap) { useList = &xgi_pcie_heap->used_list; -- cgit v1.2.3 From 11ffe4632a097e3d579d084634eeccc63348249b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 28 Jun 2007 22:20:13 -0700 Subject: Convert comment header of xgi_find_pcie_virt to kernel doc format. --- linux-core/xgi_pcie.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 8b024e4a..b29b083d 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -938,12 +938,13 @@ void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address) return NULL; } -/* - address -- GE HW address - return -- CPU virtual address - - assume the CPU VAddr is continuous in not the same block -*/ +/** + * xgi_find_pcie_virt + * @address: GE HW address + * + * Returns CPU virtual address. Assumes the CPU VAddr is continuous in not + * the same block + */ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) { struct list_head *used_list; -- cgit v1.2.3 From 9c85fb866dc7954092b7ffd0ca9f76eb5354ace8 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 28 Jun 2007 22:26:39 -0700 Subject: Clean up debug log messages in xgi_find_pcie_block. --- linux-core/xgi_pcie.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b29b083d..b449a5fd 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -953,22 +953,18 @@ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) unsigned long loc_in_pagetable; void *ret; - XGI_INFO("Jong_05292006-xgi_find_pcie_virt-Begin\n"); - used_list = xgi_pcie_heap->used_list.next; - XGI_INFO("Jong_05292006-used_list=%ul\n", used_list); - offset_in_page = address & (PAGE_SIZE - 1); - XGI_INFO - ("Jong_05292006-address=0x%px, PAGE_SIZE-1=%ul, offset_in_page=%ul\n", - address, PAGE_SIZE - 1, offset_in_page); + + XGI_INFO("begin (used_list = 0x%p, address = 0x%lx, " + "PAGE_SIZE - 1 = %lu, offset_in_page = %lu)\n", + used_list, address, PAGE_SIZE - 1, offset_in_page); while (used_list != &xgi_pcie_heap->used_list) { block = list_entry(used_list, struct xgi_pcie_block_s, list); - XGI_INFO("Jong_05292006-block=0x%px\n", block); - XGI_INFO("Jong_05292006-block->hw_addr=0x%px\n", - block->hw_addr); - XGI_INFO("Jong_05292006- block->size=%ul\n", block->size); + + XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", + block, block->hw_addr, block->size); if ((address >= block->hw_addr) && (address < (block->hw_addr + block->size))) { @@ -978,21 +974,15 @@ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) (void *)(block->page_table[loc_in_pagetable]. virt_addr + offset_in_page); - XGI_INFO("Jong_05292006-PAGE_SHIFT=%d\n", PAGE_SHIFT); - XGI_INFO("Jong_05292006-loc_in_pagetable=0x%px\n", - loc_in_pagetable); - XGI_INFO - ("Jong_05292006-block->page_table[loc_in_pagetable].virt_addr=0x%px\n", - block->page_table[loc_in_pagetable].virt_addr); - XGI_INFO("Jong_05292006-offset_in_page=%d\n", - offset_in_page); - XGI_INFO("Jong_05292006-return(virt_addr)=0x%px\n", - ret); + XGI_INFO("PAGE_SHIFT = %d\n", PAGE_SHIFT); + XGI_INFO("block->page_table[0x%lx].virt_addr = 0x%lx\n", + loc_in_pagetable, + block->page_table[loc_in_pagetable].virt_addr); + XGI_INFO("return 0x%p\n", ret); return ret; } else { - XGI_INFO - ("Jong_05292006-used_list = used_list->next;\n"); + XGI_INFO("used_list = used_list->next;\n"); used_list = used_list->next; } } -- cgit v1.2.3 From 8fa24c53f5851a2d3ad2da31ee56a4fd5abbd543 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 28 Jun 2007 22:32:11 -0700 Subject: Minor clean up of variable declarations in xgi_find_pcie_virt. --- linux-core/xgi_pcie.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b449a5fd..d9da30e8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -947,30 +947,25 @@ void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address) */ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) { - struct list_head *used_list; - xgi_pcie_block_t *block; - unsigned long offset_in_page; - unsigned long loc_in_pagetable; - void *ret; - - used_list = xgi_pcie_heap->used_list.next; - offset_in_page = address & (PAGE_SIZE - 1); + struct list_head *used_list = xgi_pcie_heap->used_list.next; + const unsigned long offset_in_page = address & (PAGE_SIZE - 1); XGI_INFO("begin (used_list = 0x%p, address = 0x%lx, " "PAGE_SIZE - 1 = %lu, offset_in_page = %lu)\n", used_list, address, PAGE_SIZE - 1, offset_in_page); while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block_s, list); + xgi_pcie_block_t *block = + list_entry(used_list, struct xgi_pcie_block_s, list); XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", block, block->hw_addr, block->size); if ((address >= block->hw_addr) && (address < (block->hw_addr + block->size))) { - loc_in_pagetable = + const unsigned long loc_in_pagetable = (address - block->hw_addr) >> PAGE_SHIFT; - ret = + void *const ret = (void *)(block->page_table[loc_in_pagetable]. virt_addr + offset_in_page); -- cgit v1.2.3 From 33b8476dfb0f9b5045103c3a9781ba82bcae4a9d Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 09:30:02 -0700 Subject: Fix return type of xgi_find_pcie_block. This function used to return 'void *', which was then cast to 'xgi_pcie_block_t *' at the only caller. I changed the return type to 'struct xgi_pcie_block_s *' and removed the explicit cast. --- linux-core/xgi_pcie.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index d9da30e8..1a4d8e12 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -906,7 +906,8 @@ void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) * given a bus address, fid the pcie mem block * uses the bus address as the key. */ -void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address) +struct xgi_pcie_block_s *xgi_find_pcie_block(xgi_info_t * info, + unsigned long address) { struct list_head *used_list; xgi_pcie_block_t *block; -- cgit v1.2.3 From 88328d4ef007c781874aafedfef59aae0d21a37c Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 15:27:38 -0700 Subject: Eliminate structure typedefs Documentation/CodingStyle says that 'typedef struct foo foo_t' is evil. I tend to agree. Elminate all uses of such construct. --- linux-core/xgi_pcie.c | 116 +++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 58 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 1a4d8e12..a81dbe8b 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -33,11 +33,11 @@ #include "xgi_pcie.h" #include "xgi_misc.h" -static xgi_pcie_heap_t *xgi_pcie_heap = NULL; -static kmem_cache_t *xgi_pcie_cache_block = NULL; -static xgi_pcie_block_t *xgi_pcie_vertex_block = NULL; -static xgi_pcie_block_t *xgi_pcie_cmdlist_block = NULL; -static xgi_pcie_block_t *xgi_pcie_scratchpad_block = NULL; +static struct xgi_pcie_heap *xgi_pcie_heap = NULL; +static struct kmem_cache *xgi_pcie_cache_block = NULL; +static struct xgi_pcie_block *xgi_pcie_vertex_block = NULL; +static struct xgi_pcie_block *xgi_pcie_cmdlist_block = NULL; +static struct xgi_pcie_block *xgi_pcie_scratchpad_block = NULL; extern struct list_head xgi_mempid_list; static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) @@ -85,7 +85,7 @@ static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) free_pages(page_addr, page_order); } -static int xgi_pcie_lut_init(xgi_info_t * info) +static int xgi_pcie_lut_init(struct xgi_info * info) { unsigned char *page_addr = NULL; unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; @@ -214,7 +214,7 @@ static int xgi_pcie_lut_init(xgi_info_t * info) return 0; } -static void xgi_pcie_lut_cleanup(xgi_info_t * info) +static void xgi_pcie_lut_cleanup(struct xgi_info * info) { if (info->lut_base) { XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", @@ -225,10 +225,10 @@ static void xgi_pcie_lut_cleanup(xgi_info_t * info) } } -static xgi_pcie_block_t *xgi_pcie_new_node(void) +static struct xgi_pcie_block *xgi_pcie_new_node(void) { - xgi_pcie_block_t *block = - (xgi_pcie_block_t *) kmem_cache_alloc(xgi_pcie_cache_block, + struct xgi_pcie_block *block = + (struct xgi_pcie_block *) kmem_cache_alloc(xgi_pcie_cache_block, GFP_KERNEL); if (block == NULL) { return NULL; @@ -247,11 +247,11 @@ static xgi_pcie_block_t *xgi_pcie_new_node(void) return block; } -static void xgi_pcie_block_stuff_free(xgi_pcie_block_t * block) +static void xgi_pcie_block_stuff_free(struct xgi_pcie_block * block) { struct page *page; - xgi_page_block_t *page_block = block->page_block; - xgi_page_block_t *free_block; + struct xgi_page_block *page_block = block->page_block; + struct xgi_page_block *free_block; unsigned long page_count = 0; int i; @@ -285,9 +285,9 @@ static void xgi_pcie_block_stuff_free(xgi_pcie_block_t * block) } } -int xgi_pcie_heap_init(xgi_info_t * info) +int xgi_pcie_heap_init(struct xgi_info * info) { - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; if (!xgi_pcie_lut_init(info)) { XGI_ERROR("xgi_pcie_lut_init failed\n"); @@ -295,7 +295,7 @@ int xgi_pcie_heap_init(xgi_info_t * info) } xgi_pcie_heap = - (xgi_pcie_heap_t *) kmalloc(sizeof(xgi_pcie_heap_t), GFP_KERNEL); + (struct xgi_pcie_heap *) kmalloc(sizeof(struct xgi_pcie_heap), GFP_KERNEL); if (!xgi_pcie_heap) { XGI_ERROR("xgi_pcie_heap alloc failed\n"); goto fail1; @@ -307,7 +307,7 @@ int xgi_pcie_heap_init(xgi_info_t * info) xgi_pcie_heap->max_freesize = info->pcie.size; xgi_pcie_cache_block = - kmem_cache_create("xgi_pcie_block", sizeof(xgi_pcie_block_t), 0, + kmem_cache_create("xgi_pcie_block", sizeof(struct xgi_pcie_block), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (NULL == xgi_pcie_cache_block) { @@ -315,7 +315,7 @@ int xgi_pcie_heap_init(xgi_info_t * info) goto fail2; } - block = (xgi_pcie_block_t *) xgi_pcie_new_node(); + block = (struct xgi_pcie_block *) xgi_pcie_new_node(); if (!block) { XGI_ERROR("xgi_pcie_new_node failed\n"); goto fail3; @@ -348,7 +348,7 @@ int xgi_pcie_heap_init(xgi_info_t * info) void xgi_pcie_heap_check(void) { struct list_head *useList, *temp; - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; unsigned int ownerIndex; #ifdef XGI_DEBUG char *ownerStr[6] = @@ -360,7 +360,7 @@ void xgi_pcie_heap_check(void) temp = useList->next; XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); while (temp != useList) { - block = list_entry(temp, struct xgi_pcie_block_s, list); + block = list_entry(temp, struct xgi_pcie_block, list); if (block->owner == PCIE_2D) ownerIndex = 0; else if (block->owner > PCIE_3D_TEXTURE @@ -378,10 +378,10 @@ void xgi_pcie_heap_check(void) } } -void xgi_pcie_heap_cleanup(xgi_info_t * info) +void xgi_pcie_heap_cleanup(struct xgi_info * info) { struct list_head *free_list, *temp; - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; int j; xgi_pcie_lut_cleanup(info); @@ -394,7 +394,7 @@ void xgi_pcie_heap_cleanup(xgi_info_t * info) while (temp != free_list) { block = - list_entry(temp, struct xgi_pcie_block_s, + list_entry(temp, struct xgi_pcie_block, list); XGI_INFO ("No. %d block->offset: 0x%lx block->size: 0x%lx \n", @@ -421,13 +421,13 @@ void xgi_pcie_heap_cleanup(xgi_info_t * info) } } -static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, +static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, unsigned long originalSize, enum PcieOwner owner) { struct list_head *free_list; - xgi_pcie_block_t *block, *used_block, *free_block; - xgi_page_block_t *page_block, *prev_page_block; + struct xgi_pcie_block *block, *used_block, *free_block; + struct xgi_page_block *page_block, *prev_page_block; struct page *page; unsigned long page_order = 0, count = 0, index = 0; unsigned long page_addr = 0; @@ -482,7 +482,7 @@ static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, free_list = xgi_pcie_heap->free_list.next; while (free_list != &xgi_pcie_heap->free_list) { //XGI_INFO("free_list: 0x%px \n", free_list); - block = list_entry(free_list, struct xgi_pcie_block_s, list); + block = list_entry(free_list, struct xgi_pcie_block, list); if (size <= block->size) { break; } @@ -543,12 +543,12 @@ static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, used_block->page_order); used_block->page_block = NULL; - //used_block->page_block = (xgi_pages_block_t *)kmalloc(sizeof(xgi_pages_block_t), GFP_KERNEL); - //if (!used_block->page_block) return NULL; + //used_block->page_block = (struct xgi_pages_block *)kmalloc(sizeof(struct xgi_pages_block), GFP_KERNEL); + //if (!used_block->page_block) return NULL;_t //used_block->page_block->next = NULL; used_block->page_table = - (xgi_pte_t *) kmalloc(sizeof(xgi_pte_t) * used_block->page_count, + (struct xgi_pte *) kmalloc(sizeof(struct xgi_pte) * used_block->page_count, GFP_KERNEL); if (used_block->page_table == NULL) { goto fail; @@ -595,8 +595,8 @@ static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, if (page_block == NULL) { page_block = - (xgi_page_block_t *) - kmalloc(sizeof(xgi_page_block_t), GFP_KERNEL); + (struct xgi_page_block *) + kmalloc(sizeof(struct xgi_page_block), GFP_KERNEL); if (!page_block) { XGI_ERROR ("Can't get memory for page_block! \n"); @@ -697,17 +697,17 @@ static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, return NULL; } -static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t * info, +static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, unsigned long offset) { struct list_head *free_list, *used_list; - xgi_pcie_block_t *used_block, *block = NULL; - xgi_pcie_block_t *prev, *next; + struct xgi_pcie_block *used_block, *block = NULL; + struct xgi_pcie_block *prev, *next; unsigned long upper, lower; used_list = xgi_pcie_heap->used_list.next; while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block_s, list); + block = list_entry(used_list, struct xgi_pcie_block, list); if (block->offset == offset) { break; } @@ -737,7 +737,7 @@ static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t * info, free_list = xgi_pcie_heap->free_list.next; while (free_list != &xgi_pcie_heap->free_list) { - block = list_entry(free_list, struct xgi_pcie_block_s, list); + block = list_entry(free_list, struct xgi_pcie_block, list); if (block->offset == upper) { next = block; } else if ((block->offset + block->size) == lower) { @@ -787,11 +787,11 @@ static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t * info, return (used_block); } -void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, - enum PcieOwner owner, xgi_mem_alloc_t * alloc) +void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, + enum PcieOwner owner, struct xgi_mem_alloc * alloc) { - xgi_pcie_block_t *block; - xgi_mem_pid_t *mempid_block; + struct xgi_pcie_block *block; + struct xgi_mem_pid *mempid_block; xgi_down(info->pcie_sem); block = xgi_pcie_mem_alloc(info, size, owner); @@ -819,7 +819,7 @@ void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, */ if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) { mempid_block = - kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); + kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); if (!mempid_block) XGI_ERROR("mempid_block alloc failed\n"); mempid_block->location = NON_LOCAL; @@ -837,12 +837,12 @@ void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, } } -void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) +void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) { - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; unsigned long offset = bus_addr - info->pcie.base; - xgi_mem_pid_t *mempid_block; - xgi_mem_pid_t *mempid_freeblock = NULL; + struct xgi_mem_pid *mempid_block; + struct xgi_mem_pid *mempid_freeblock = NULL; struct list_head *mempid_list; char isvertex = 0; int processcnt; @@ -857,7 +857,7 @@ void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) mempid_list = xgi_mempid_list.next; while (mempid_list != &xgi_mempid_list) { mempid_block = - list_entry(mempid_list, struct xgi_mem_pid_s, list); + list_entry(mempid_list, struct xgi_mem_pid, list); if (mempid_block->location == NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) { ++processcnt; @@ -884,7 +884,7 @@ void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) mempid_list = xgi_mempid_list.next; while (mempid_list != &xgi_mempid_list) { mempid_block = - list_entry(mempid_list, struct xgi_mem_pid_s, list); + list_entry(mempid_list, struct xgi_mem_pid, list); if (mempid_block->location == NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) { @@ -906,17 +906,17 @@ void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) * given a bus address, fid the pcie mem block * uses the bus address as the key. */ -struct xgi_pcie_block_s *xgi_find_pcie_block(xgi_info_t * info, - unsigned long address) +struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, + unsigned long address) { struct list_head *used_list; - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; int i; used_list = xgi_pcie_heap->used_list.next; while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block_s, list); + block = list_entry(used_list, struct xgi_pcie_block, list); if (block->bus_addr == address) { return block; @@ -946,7 +946,7 @@ struct xgi_pcie_block_s *xgi_find_pcie_block(xgi_info_t * info, * Returns CPU virtual address. Assumes the CPU VAddr is continuous in not * the same block */ -void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) +void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) { struct list_head *used_list = xgi_pcie_heap->used_list.next; const unsigned long offset_in_page = address & (PAGE_SIZE - 1); @@ -956,8 +956,8 @@ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) used_list, address, PAGE_SIZE - 1, offset_in_page); while (used_list != &xgi_pcie_heap->used_list) { - xgi_pcie_block_t *block = - list_entry(used_list, struct xgi_pcie_block_s, list); + struct xgi_pcie_block *block = + list_entry(used_list, struct xgi_pcie_block, list); XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", block, block->hw_addr, block->size); @@ -987,19 +987,19 @@ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) return NULL; } -void xgi_read_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req) +void xgi_read_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req) { } -void xgi_write_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req) +void xgi_write_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req) { } /* address -- GE hw address */ -void xgi_test_rwinkernel(xgi_info_t * info, unsigned long address) +void xgi_test_rwinkernel(struct xgi_info * info, unsigned long address) { unsigned long *virtaddr = 0; if (address == 0) { -- cgit v1.2.3 From 4403540776c8ed3c2e28f26b6dacaab0b9e40e05 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 21:15:33 -0700 Subject: Clean up xgi_pcie_heap_check The whole purpose of xgi_pcie_heap_check is to log information about entries on the used_list. If XGI_DEBUG is not set, it doesn't print anything. Therefore we can #ifdef the whole function body. Convert open-code list iteration to use list_for_each_entry. --- linux-core/xgi_pcie.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index a81dbe8b..dd758013 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -347,35 +347,31 @@ int xgi_pcie_heap_init(struct xgi_info * info) void xgi_pcie_heap_check(void) { - struct list_head *useList, *temp; +#ifdef XGI_DEBUG struct xgi_pcie_block *block; unsigned int ownerIndex; -#ifdef XGI_DEBUG - char *ownerStr[6] = + static const char *const ownerStr[6] = { "2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE" }; -#endif - if (xgi_pcie_heap) { - useList = &xgi_pcie_heap->used_list; - temp = useList->next; - XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); - while (temp != useList) { - block = list_entry(temp, struct xgi_pcie_block, list); - if (block->owner == PCIE_2D) - ownerIndex = 0; - else if (block->owner > PCIE_3D_TEXTURE - || block->owner < PCIE_2D - || block->owner < PCIE_3D) - ownerIndex = 5; - else - ownerIndex = block->owner - PCIE_3D + 1; - XGI_INFO - ("Allocated by %s, block->offset: 0x%lx block->size: 0x%lx \n", - ownerStr[ownerIndex], block->offset, block->size); - temp = temp->next; - } + if (!xgi_pcie_heap) { + return; + } + + XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); + list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { + if (block->owner == PCIE_2D) + ownerIndex = 0; + else if (block->owner > PCIE_3D_TEXTURE + || block->owner < PCIE_2D + || block->owner < PCIE_3D) + ownerIndex = 5; + else + ownerIndex = block->owner - PCIE_3D + 1; + XGI_INFO("Allocated by %s, block offset: 0x%lx, size: 0x%lx \n", + ownerStr[ownerIndex], block->offset, block->size); } +#endif } void xgi_pcie_heap_cleanup(struct xgi_info * info) -- cgit v1.2.3 From 32584d94e6ef7c0b463794a40541eb8183c7fb02 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 21:35:27 -0700 Subject: Convert open coded list iterators to either list_for_each_entry or list_for_each_entry_safe --- linux-core/xgi_pcie.c | 75 +++++++++++++-------------------------------------- 1 file changed, 18 insertions(+), 57 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index dd758013..e451ebd5 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -376,8 +376,9 @@ void xgi_pcie_heap_check(void) void xgi_pcie_heap_cleanup(struct xgi_info * info) { - struct list_head *free_list, *temp; + struct list_head *free_list; struct xgi_pcie_block *block; + struct xgi_pcie_block *next; int j; xgi_pcie_lut_cleanup(info); @@ -386,23 +387,16 @@ void xgi_pcie_heap_cleanup(struct xgi_info * info) if (xgi_pcie_heap) { free_list = &xgi_pcie_heap->free_list; for (j = 0; j < 3; j++, free_list++) { - temp = free_list->next; - - while (temp != free_list) { - block = - list_entry(temp, struct xgi_pcie_block, - list); + list_for_each_entry_safe(block, next, free_list, list) { XGI_INFO - ("No. %d block->offset: 0x%lx block->size: 0x%lx \n", + ("No. %d block offset: 0x%lx size: 0x%lx\n", j, block->offset, block->size); xgi_pcie_block_stuff_free(block); block->bus_addr = 0; block->hw_addr = 0; - temp = temp->next; //XGI_INFO("No. %d free block: 0x%p \n", j, block); kmem_cache_free(xgi_pcie_cache_block, block); - block = NULL; } } @@ -421,7 +415,6 @@ static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, unsigned long originalSize, enum PcieOwner owner) { - struct list_head *free_list; struct xgi_pcie_block *block, *used_block, *free_block; struct xgi_page_block *page_block, *prev_page_block; struct page *page; @@ -475,17 +468,13 @@ static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, } /* Jong 05/30/2006; find next free list which has enough space */ - free_list = xgi_pcie_heap->free_list.next; - while (free_list != &xgi_pcie_heap->free_list) { - //XGI_INFO("free_list: 0x%px \n", free_list); - block = list_entry(free_list, struct xgi_pcie_block, list); + list_for_each_entry(block, &xgi_pcie_heap->free_list, list) { if (size <= block->size) { break; } - free_list = free_list->next; } - if (free_list == &xgi_pcie_heap->free_list) { + if (&block->list == &xgi_pcie_heap->free_list) { XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", size / 1024); return (NULL); @@ -696,21 +685,17 @@ static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, unsigned long offset) { - struct list_head *free_list, *used_list; - struct xgi_pcie_block *used_block, *block = NULL; + struct xgi_pcie_block *used_block, *block; struct xgi_pcie_block *prev, *next; unsigned long upper, lower; - used_list = xgi_pcie_heap->used_list.next; - while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block, list); + list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { if (block->offset == offset) { break; } - used_list = used_list->next; } - if (used_list == &xgi_pcie_heap->used_list) { + if (&block->list == &xgi_pcie_heap->used_list) { XGI_ERROR("can't find block: 0x%lx to free!\n", offset); return (NULL); } @@ -730,16 +715,12 @@ static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, upper = used_block->offset + used_block->size; lower = used_block->offset; - free_list = xgi_pcie_heap->free_list.next; - - while (free_list != &xgi_pcie_heap->free_list) { - block = list_entry(free_list, struct xgi_pcie_block, list); + list_for_each_entry(block, &xgi_pcie_heap->free_list, list) { if (block->offset == upper) { next = block; } else if ((block->offset + block->size) == lower) { prev = block; } - free_list = free_list->next; } XGI_INFO("next = 0x%p, prev = 0x%p\n", next, prev); @@ -839,7 +820,6 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) unsigned long offset = bus_addr - info->pcie.base; struct xgi_mem_pid *mempid_block; struct xgi_mem_pid *mempid_freeblock = NULL; - struct list_head *mempid_list; char isvertex = 0; int processcnt; @@ -850,15 +830,12 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) if (isvertex) { /*check is there any other process using vertex */ processcnt = 0; - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) { - mempid_block = - list_entry(mempid_list, struct xgi_mem_pid, list); + + list_for_each_entry(mempid_block, &xgi_mempid_list, list) { if (mempid_block->location == NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) { ++processcnt; } - mempid_list = mempid_list->next; } if (processcnt > 1) { return; @@ -877,17 +854,13 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) xgi_pcie_vertex_block = NULL; /* manage mempid */ - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) { - mempid_block = - list_entry(mempid_list, struct xgi_mem_pid, list); + list_for_each_entry(mempid_block, &xgi_mempid_list, list) { if (mempid_block->location == NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) { mempid_freeblock = mempid_block; break; } - mempid_list = mempid_list->next; } if (mempid_freeblock) { list_del(&mempid_freeblock->list); @@ -905,15 +878,11 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, unsigned long address) { - struct list_head *used_list; struct xgi_pcie_block *block; int i; - used_list = xgi_pcie_heap->used_list.next; - - while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block, list); + list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { if (block->bus_addr == address) { return block; } @@ -927,7 +896,6 @@ struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, } } } - used_list = used_list->next; } XGI_ERROR("could not find map for vm 0x%lx\n", address); @@ -944,17 +912,13 @@ struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, */ void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) { - struct list_head *used_list = xgi_pcie_heap->used_list.next; + struct xgi_pcie_block *block; const unsigned long offset_in_page = address & (PAGE_SIZE - 1); - XGI_INFO("begin (used_list = 0x%p, address = 0x%lx, " - "PAGE_SIZE - 1 = %lu, offset_in_page = %lu)\n", - used_list, address, PAGE_SIZE - 1, offset_in_page); - - while (used_list != &xgi_pcie_heap->used_list) { - struct xgi_pcie_block *block = - list_entry(used_list, struct xgi_pcie_block, list); + XGI_INFO("begin (address = 0x%lx, offset_in_page = %lu)\n", + address, offset_in_page); + list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", block, block->hw_addr, block->size); @@ -973,9 +937,6 @@ void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) XGI_INFO("return 0x%p\n", ret); return ret; - } else { - XGI_INFO("used_list = used_list->next;\n"); - used_list = used_list->next; } } -- cgit v1.2.3 From 49ccec1b0845ea14ab2cfd2f53704fe26e38fbef Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 21:38:48 -0700 Subject: Convert xgi_mem_location enum values to less generic names. --- linux-core/xgi_pcie.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index e451ebd5..82111249 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -775,7 +775,7 @@ void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, xgi_up(info->pcie_sem); if (block == NULL) { - alloc->location = INVALID; + alloc->location = XGI_MEMLOC_INVALID; alloc->size = 0; alloc->bus_addr = 0; alloc->hw_addr = 0; @@ -784,7 +784,7 @@ void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, XGI_INFO ("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", block->offset, block->bus_addr); - alloc->location = NON_LOCAL; + alloc->location = XGI_MEMLOC_NON_LOCAL; alloc->size = block->size; alloc->bus_addr = block->bus_addr; alloc->hw_addr = block->hw_addr; @@ -799,7 +799,7 @@ void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); if (!mempid_block) XGI_ERROR("mempid_block alloc failed\n"); - mempid_block->location = NON_LOCAL; + mempid_block->location = XGI_MEMLOC_NON_LOCAL; if (owner == PCIE_3D) mempid_block->bus_addr = 0xFFFFFFFF; /*xgi_pcie_vertex_block has the address */ else @@ -832,7 +832,7 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) processcnt = 0; list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == NON_LOCAL + if (mempid_block->location == XGI_MEMLOC_NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) { ++processcnt; } @@ -855,7 +855,7 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) /* manage mempid */ list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == NON_LOCAL + if (mempid_block->location == XGI_MEMLOC_NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) { mempid_freeblock = mempid_block; -- cgit v1.2.3 From 2f2d8b9688743ac6367bf13c3c023310a257ceb7 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 9 Jul 2007 15:59:09 -0700 Subject: Merge xgi_mem_req and xgi_mem_alloc into a single type. These two structures were used as the request and reply for certain ioctls. Having a different type for an ioctl's input and output is just wierd. In addition, each structure contained fields (e.g., pid) that had no business being there. This change requires updates to user-space. --- linux-core/xgi_pcie.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 82111249..0f82e4ec 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -764,14 +764,13 @@ static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, return (used_block); } -void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, - enum PcieOwner owner, struct xgi_mem_alloc * alloc) +void xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, + pid_t pid) { struct xgi_pcie_block *block; - struct xgi_mem_pid *mempid_block; xgi_down(info->pcie_sem); - block = xgi_pcie_mem_alloc(info, size, owner); + block = xgi_pcie_mem_alloc(info, alloc->size, alloc->owner); xgi_up(info->pcie_sem); if (block == NULL) { @@ -794,17 +793,18 @@ void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, PCIE_3D request means a opengl process created. PCIE_3D_TEXTURE request means texture cannot alloc from fb. */ - if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) { - mempid_block = + if ((alloc->owner == PCIE_3D) + || (alloc->owner == PCIE_3D_TEXTURE)) { + struct xgi_mem_pid *mempid_block = kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); if (!mempid_block) XGI_ERROR("mempid_block alloc failed\n"); mempid_block->location = XGI_MEMLOC_NON_LOCAL; - if (owner == PCIE_3D) + if (alloc->owner == PCIE_3D) mempid_block->bus_addr = 0xFFFFFFFF; /*xgi_pcie_vertex_block has the address */ else mempid_block->bus_addr = alloc->bus_addr; - mempid_block->pid = alloc->pid; + mempid_block->pid = pid; XGI_INFO ("Memory ProcessID add one pcie block pid:%ld successfully! \n", @@ -944,15 +944,6 @@ void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) return NULL; } -void xgi_read_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req) -{ - -} - -void xgi_write_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req) -{ -} - /* address -- GE hw address */ -- cgit v1.2.3 From 76ca1e858fb8e1a65ea49c0c62350d7ca91044a2 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 9 Jul 2007 18:54:25 -0700 Subject: Convert occurances of U32 to other types. Most occurances of U32 were converted to u32. These are cases where the data represents something that will be written to the hardware. Other cases were converted to 'unsigned int'. U32 was the last type in xgi_types.h, so that file is removed. --- linux-core/xgi_pcie.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 0f82e4ec..70459b2c 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -26,7 +26,6 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_types.h" #include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_regs.h" @@ -420,7 +419,7 @@ static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, struct page *page; unsigned long page_order = 0, count = 0, index = 0; unsigned long page_addr = 0; - unsigned long *lut_addr = NULL; + u32 *lut_addr = NULL; unsigned long lut_id = 0; unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; int i, j, page_count = 0; -- cgit v1.2.3 From 658ff2daf3d2a080da2d859f522a627aef841637 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Jul 2007 20:58:43 -0700 Subject: Eliminate several useless ioctls and associated cruft. The ioctlss XGI_ESC_DEVICE_INFO, XGI_ESC_MEM_COLLECT, XGI_ESC_PCIE_CHECK, XGI_ESC_GET_SCREEN_INFO, XGI_ESC_PUT_SCREEN_INFO, XGI_ESC_MMIO_INFO, and XGI_ESC_SAREA_INFO, are completely unnecessary. The will be doubly useless when the driver is converted to the DRM infrastructure. --- linux-core/xgi_pcie.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 70459b2c..0d641ab8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -344,35 +344,6 @@ int xgi_pcie_heap_init(struct xgi_info * info) return 0; } -void xgi_pcie_heap_check(void) -{ -#ifdef XGI_DEBUG - struct xgi_pcie_block *block; - unsigned int ownerIndex; - static const char *const ownerStr[6] = - { "2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE" }; - - if (!xgi_pcie_heap) { - return; - } - - XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); - list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { - if (block->owner == PCIE_2D) - ownerIndex = 0; - else if (block->owner > PCIE_3D_TEXTURE - || block->owner < PCIE_2D - || block->owner < PCIE_3D) - ownerIndex = 5; - else - ownerIndex = block->owner - PCIE_3D + 1; - - XGI_INFO("Allocated by %s, block offset: 0x%lx, size: 0x%lx \n", - ownerStr[ownerIndex], block->offset, block->size); - } -#endif -} - void xgi_pcie_heap_cleanup(struct xgi_info * info) { struct list_head *free_list; -- cgit v1.2.3 From 5b08ab258f3e541334d2b64d38e15e1431080199 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Jul 2007 21:12:30 -0700 Subject: Clean ups (primarilly log messages) in xgi_test_rwinkernel. --- linux-core/xgi_pcie.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 0d641ab8..cfc9febc 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -919,20 +919,21 @@ void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) */ void xgi_test_rwinkernel(struct xgi_info * info, unsigned long address) { - unsigned long *virtaddr = 0; + u32 *virtaddr = 0; + + XGI_INFO("input GE HW addr is 0x%x\n", address); + if (address == 0) { - XGI_INFO("[Jong-kd] input GE HW addr is 0x00000000\n"); return; } - virtaddr = (unsigned long *)xgi_find_pcie_virt(info, address); + virtaddr = (u32 *)xgi_find_pcie_virt(info, address); + + XGI_INFO("convert to CPU virt addr 0x%p\n", virtaddr); - XGI_INFO("[Jong-kd] input GE HW addr is 0x%lx\n", address); - XGI_INFO("[Jong-kd] convert to CPU virt addr 0x%px\n", virtaddr); - XGI_INFO("[Jong-kd] origin [virtaddr] = 0x%lx\n", *virtaddr); if (virtaddr != NULL) { + XGI_INFO("original [virtaddr] = 0x%x\n", *virtaddr); *virtaddr = 0x00f00fff; + XGI_INFO("modified [virtaddr] = 0x%x\n", *virtaddr); } - - XGI_INFO("[Jong-kd] modified [virtaddr] = 0x%lx\n", *virtaddr); } -- cgit v1.2.3 From 5ba94c2ab8be350fee495e5cfe94afb8f663956a Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 19 Jul 2007 10:29:18 -0700 Subject: Initial pass at converting driver to DRM infrastructure. --- linux-core/xgi_pcie.c | 941 +++++++++----------------------------------------- 1 file changed, 170 insertions(+), 771 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index cfc9febc..49c531fc 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -26,176 +26,81 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_regs.h" -#include "xgi_pcie.h" #include "xgi_misc.h" -static struct xgi_pcie_heap *xgi_pcie_heap = NULL; -static struct kmem_cache *xgi_pcie_cache_block = NULL; -static struct xgi_pcie_block *xgi_pcie_vertex_block = NULL; -static struct xgi_pcie_block *xgi_pcie_cmdlist_block = NULL; -static struct xgi_pcie_block *xgi_pcie_scratchpad_block = NULL; -extern struct list_head xgi_mempid_list; - -static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) -{ - struct page *page; - unsigned long page_addr = 0; - unsigned long page_count = 0; - int i; - - page_count = (1 << page_order); - page_addr = __get_free_pages(GFP_KERNEL, page_order); - - if (page_addr == 0UL) { - XGI_ERROR("Can't get free pages: 0x%lx from system memory !\n", - page_count); - return 0; - } - - page = virt_to_page(page_addr); - - for (i = 0; i < page_count; i++, page++) { - XGI_INC_PAGE_COUNT(page); - XGILockPage(page); - } - - XGI_INFO("page_count: 0x%lx page_order: 0x%lx page_addr: 0x%lx \n", - page_count, page_order, page_addr); - return page_addr; -} - -static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) -{ - struct page *page; - unsigned long page_count = 0; - int i; - - page_count = (1 << page_order); - page = virt_to_page(page_addr); - - for (i = 0; i < page_count; i++, page++) { - XGI_DEC_PAGE_COUNT(page); - XGIUnlockPage(page); - } - - free_pages(page_addr, page_order); -} +static struct xgi_mem_block *xgi_pcie_vertex_block = NULL; +static struct xgi_mem_block *xgi_pcie_cmdlist_block = NULL; +static struct xgi_mem_block *xgi_pcie_scratchpad_block = NULL; static int xgi_pcie_lut_init(struct xgi_info * info) { - unsigned char *page_addr = NULL; - unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; - unsigned long count = 0; u8 temp = 0; + int err; + unsigned i; + struct drm_scatter_gather request; + struct drm_sg_mem *sg; + u32 *lut; - /* Jong 06/06/2006 */ - unsigned long pcie_aperture_size; - - info->pcie.size = 128 * 1024 * 1024; /* Get current FB aperture size */ - temp = In3x5(0x27); - XGI_INFO("In3x5(0x27): 0x%x \n", temp); + temp = IN3X5B(info->mmio_map, 0x27); + DRM_INFO("In3x5(0x27): 0x%x \n", temp); if (temp & 0x01) { /* 256MB; Jong 06/05/2006; 0x10000000 */ - /* Jong 06/06/2006; allocate memory */ - pcie_aperture_size = 256 * 1024 * 1024; - /* info->pcie.base = 256 * 1024 * 1024; *//* pcie base is different from fb base */ + info->pcie.base = 256 * 1024 * 1024; } else { /* 128MB; Jong 06/05/2006; 0x08000000 */ - - /* Jong 06/06/2006; allocate memory */ - pcie_aperture_size = 128 * 1024 * 1024; - /* info->pcie.base = 128 * 1024 * 1024; */ + info->pcie.base = 128 * 1024 * 1024; } - /* Jong 06/06/2006; allocate memory; it can be used for build-in kernel modules */ - /* info->pcie.base=(unsigned long)alloc_bootmem(pcie_mem_size); */ - /* total 496 MB; need 256 MB (0x10000000); start from 240 MB (0x0F000000) */ - /* info->pcie.base=ioremap(0x0F000000, 0x10000000); *//* Cause system hang */ - info->pcie.base = pcie_aperture_size; /* works */ - /* info->pcie.base=info->fb.base + info->fb.size; *//* System hang */ - /* info->pcie.base=128 * 1024 * 1024; *//* System hang */ - XGI_INFO("Jong06062006-info->pcie.base: 0x%lx \n", info->pcie.base); + DRM_INFO("info->pcie.base: 0x%lx\n", (unsigned long) info->pcie.base); /* Get current lookup table page size */ - temp = bReadReg(0xB00C); + temp = DRM_READ8(info->mmio_map, 0xB00C); if (temp & 0x04) { /* 8KB */ info->lutPageSize = 8 * 1024; } else { /* 4KB */ - info->lutPageSize = 4 * 1024; } - XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + DRM_INFO("info->lutPageSize: 0x%x \n", info->lutPageSize); -#if 0 - /* Get current lookup table location */ - temp = bReadReg(0xB00C); - if (temp & 0x02) { /* LFB */ - info->isLUTInLFB = TRUE; - /* Current we only support lookup table in LFB */ - temp &= 0xFD; - bWriteReg(0xB00C, temp); - info->isLUTInLFB = FALSE; - } else { /* SFB */ - info->isLUTInLFB = FALSE; + request.size = info->pcie.size; + err = drm_sg_alloc(info->dev, & request); + if (err) { + DRM_ERROR("cannot allocate PCIE GART backing store! " + "size = %d\n", info->pcie.size); + return err; } - XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + sg = info->dev->sg; - /* Get current SDFB page size */ - temp = bReadReg(0xB00C); - if (temp & 0x08) { /* 8MB */ - info->sdfbPageSize = 8 * 1024 * 1024; - } else { /* 4MB */ - - info->sdfbPageSize = 4 * 1024 * 1024; + info->lut_handle = drm_pci_alloc(info->dev, + sizeof(u32) * sg->pages, + PAGE_SIZE, + DMA_31BIT_MASK); + if (info->lut_handle == NULL) { + DRM_ERROR("cannot allocate PCIE lut page!\n"); + return DRM_ERR(ENOMEM); } -#endif - pciePageCount = (info->pcie.size + PAGE_SIZE - 1) / PAGE_SIZE; - /* - * Allocate memory for PCIE GART table; - */ - lutEntryNum = pciePageCount; - lutPageCount = (lutEntryNum * 4 + PAGE_SIZE - 1) / PAGE_SIZE; - - /* get page_order base on page_count */ - count = lutPageCount; - for (lutPageOrder = 0; count; count >>= 1, ++lutPageOrder) ; - - if ((lutPageCount << 1) == (1 << lutPageOrder)) { - lutPageOrder -= 1; - } - - XGI_INFO("lutEntryNum: 0x%lx lutPageCount: 0x%lx lutPageOrder 0x%lx\n", - lutEntryNum, lutPageCount, lutPageOrder); - - info->lutPageOrder = lutPageOrder; - page_addr = (unsigned char *)xgi_pcie_lut_alloc(lutPageOrder); + lut = info->lut_handle->vaddr; + for (i = 0; i < sg->pages; i++) { + info->dev->sg->busaddr[i] = pci_map_page(info->dev->pdev, + sg->pagelist[i], + 0, + PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(info->dev->sg->busaddr[i])) { + DRM_ERROR("cannot map GART backing store for DMA!\n"); + return DRM_ERR(-(info->dev->sg->busaddr[i])); + } - if (!page_addr) { - XGI_ERROR("cannot allocate PCIE lut page!\n"); - goto fail; + lut[i] = info->dev->sg->busaddr[i]; } - info->lut_base = (unsigned long *)page_addr; - - XGI_INFO("page_addr: 0x%p virt_to_phys(page_virtual): 0x%lx \n", - page_addr, virt_to_phys(page_addr)); - - XGI_INFO - ("info->lut_base: 0x%p __pa(info->lut_base): 0x%lx info->lutPageOrder 0x%lx\n", - info->lut_base, __pa(info->lut_base), info->lutPageOrder); - - /* - * clean all PCIE GART Entry - */ - memset(page_addr, 0, PAGE_SIZE << lutPageOrder); #if defined(__i386__) || defined(__x86_64__) asm volatile ("wbinvd":::"memory"); @@ -204,675 +109,186 @@ static int xgi_pcie_lut_init(struct xgi_info * info) #endif /* Set GART in SFB */ - bWriteReg(0xB00C, bReadReg(0xB00C) & ~0x02); + temp = DRM_READ8(info->mmio_map, 0xB00C); + DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02); + /* Set GART base address to HW */ - dwWriteReg(0xB034, __pa(info->lut_base)); + dwWriteReg(info->mmio_map, 0xB034, info->lut_handle->busaddr); - return 1; - fail: return 0; } -static void xgi_pcie_lut_cleanup(struct xgi_info * info) -{ - if (info->lut_base) { - XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", - info->lut_base, info->lutPageOrder); - xgi_pcie_lut_free((unsigned long)info->lut_base, - info->lutPageOrder); - info->lut_base = NULL; - } -} - -static struct xgi_pcie_block *xgi_pcie_new_node(void) +void xgi_pcie_lut_cleanup(struct xgi_info * info) { - struct xgi_pcie_block *block = - (struct xgi_pcie_block *) kmem_cache_alloc(xgi_pcie_cache_block, - GFP_KERNEL); - if (block == NULL) { - return NULL; + if (info->dev->sg) { + drm_sg_free(info->dev, info->dev->sg->handle); } - block->offset = 0; /* block's offset in pcie memory, begin from 0 */ - block->size = 0; /* The block size. */ - block->bus_addr = 0; /* CPU access address/bus address */ - block->hw_addr = 0; /* GE access address */ - block->page_count = 0; - block->page_order = 0; - block->page_block = NULL; - block->page_table = NULL; - block->owner = PCIE_INVALID; - - return block; -} - -static void xgi_pcie_block_stuff_free(struct xgi_pcie_block * block) -{ - struct page *page; - struct xgi_page_block *page_block = block->page_block; - struct xgi_page_block *free_block; - unsigned long page_count = 0; - int i; - - //XGI_INFO("block->page_block: 0x%p \n", block->page_block); - while (page_block) { - page_count = page_block->page_count; - - page = virt_to_page(page_block->virt_addr); - for (i = 0; i < page_count; i++, page++) { - XGI_DEC_PAGE_COUNT(page); - XGIUnlockPage(page); - } - free_pages(page_block->virt_addr, page_block->page_order); - - page_block->phys_addr = 0; - page_block->virt_addr = 0; - page_block->page_count = 0; - page_block->page_order = 0; - - free_block = page_block; - page_block = page_block->next; - //XGI_INFO("free free_block: 0x%p \n", free_block); - kfree(free_block); - free_block = NULL; - } - - if (block->page_table) { - //XGI_INFO("free block->page_table: 0x%p \n", block->page_table); - kfree(block->page_table); - block->page_table = NULL; + if (info->lut_handle) { + drm_pci_free(info->dev, info->lut_handle); + info->lut_handle = NULL; } } int xgi_pcie_heap_init(struct xgi_info * info) { - struct xgi_pcie_block *block; - - if (!xgi_pcie_lut_init(info)) { - XGI_ERROR("xgi_pcie_lut_init failed\n"); - return 0; - } - - xgi_pcie_heap = - (struct xgi_pcie_heap *) kmalloc(sizeof(struct xgi_pcie_heap), GFP_KERNEL); - if (!xgi_pcie_heap) { - XGI_ERROR("xgi_pcie_heap alloc failed\n"); - goto fail1; - } - INIT_LIST_HEAD(&xgi_pcie_heap->free_list); - INIT_LIST_HEAD(&xgi_pcie_heap->used_list); - INIT_LIST_HEAD(&xgi_pcie_heap->sort_list); - - xgi_pcie_heap->max_freesize = info->pcie.size; - - xgi_pcie_cache_block = - kmem_cache_create("xgi_pcie_block", sizeof(struct xgi_pcie_block), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); + int err; - if (NULL == xgi_pcie_cache_block) { - XGI_ERROR("Fail to creat xgi_pcie_block\n"); - goto fail2; + err = xgi_pcie_lut_init(info); + if (err) { + DRM_ERROR("xgi_pcie_lut_init failed\n"); + return err; } - block = (struct xgi_pcie_block *) xgi_pcie_new_node(); - if (!block) { - XGI_ERROR("xgi_pcie_new_node failed\n"); - goto fail3; - } - - block->offset = 0; /* block's offset in pcie memory, begin from 0 */ - block->size = info->pcie.size; - - list_add(&block->list, &xgi_pcie_heap->free_list); - XGI_INFO("PCIE start address: 0x%lx, memory size : 0x%lx\n", - block->offset, block->size); - return 1; - fail3: - if (xgi_pcie_cache_block) { - kmem_cache_destroy(xgi_pcie_cache_block); - xgi_pcie_cache_block = NULL; + err = xgi_mem_heap_init(&info->pcie_heap, 0, info->pcie.size); + if (err) { + xgi_pcie_lut_cleanup(info); } - fail2: - if (xgi_pcie_heap) { - kfree(xgi_pcie_heap); - xgi_pcie_heap = NULL; - } - fail1: - xgi_pcie_lut_cleanup(info); - return 0; + return err; } -void xgi_pcie_heap_cleanup(struct xgi_info * info) -{ - struct list_head *free_list; - struct xgi_pcie_block *block; - struct xgi_pcie_block *next; - int j; - - xgi_pcie_lut_cleanup(info); - XGI_INFO("xgi_pcie_lut_cleanup scceeded\n"); - - if (xgi_pcie_heap) { - free_list = &xgi_pcie_heap->free_list; - for (j = 0; j < 3; j++, free_list++) { - list_for_each_entry_safe(block, next, free_list, list) { - XGI_INFO - ("No. %d block offset: 0x%lx size: 0x%lx\n", - j, block->offset, block->size); - xgi_pcie_block_stuff_free(block); - block->bus_addr = 0; - block->hw_addr = 0; - - //XGI_INFO("No. %d free block: 0x%p \n", j, block); - kmem_cache_free(xgi_pcie_cache_block, block); - } - } - - XGI_INFO("free xgi_pcie_heap: 0x%p \n", xgi_pcie_heap); - kfree(xgi_pcie_heap); - xgi_pcie_heap = NULL; - } - if (xgi_pcie_cache_block) { - kmem_cache_destroy(xgi_pcie_cache_block); - xgi_pcie_cache_block = NULL; - } -} - -static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, - unsigned long originalSize, - enum PcieOwner owner) +int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, + DRMFILE filp) { - struct xgi_pcie_block *block, *used_block, *free_block; - struct xgi_page_block *page_block, *prev_page_block; - struct page *page; - unsigned long page_order = 0, count = 0, index = 0; - unsigned long page_addr = 0; - u32 *lut_addr = NULL; - unsigned long lut_id = 0; - unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; - int i, j, page_count = 0; - int temp = 0; - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-Begin\n"); - XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", - originalSize, size); - - if (owner == PCIE_3D) { - if (xgi_pcie_vertex_block) { - XGI_INFO - ("PCIE Vertex has been created, return directly.\n"); - return xgi_pcie_vertex_block; - } - } + struct xgi_mem_block *block; - if (owner == PCIE_3D_CMDLIST) { - if (xgi_pcie_cmdlist_block) { - XGI_INFO - ("PCIE Cmdlist has been created, return directly.\n"); - return xgi_pcie_cmdlist_block; - } + down(&info->pcie_sem); + if ((alloc->owner == PCIE_3D) && (xgi_pcie_vertex_block)) { + DRM_INFO("PCIE Vertex has been created, return directly.\n"); + block = xgi_pcie_vertex_block; } - - if (owner == PCIE_3D_SCRATCHPAD) { - if (xgi_pcie_scratchpad_block) { - XGI_INFO - ("PCIE Scratchpad has been created, return directly.\n"); - return xgi_pcie_scratchpad_block; - } - } - - if (size == 0) { - XGI_ERROR("size == 0 \n"); - return (NULL); + else if ((alloc->owner == PCIE_3D_CMDLIST) && (xgi_pcie_cmdlist_block)) { + DRM_INFO("PCIE Cmdlist has been created, return directly.\n"); + block = xgi_pcie_cmdlist_block; } - - XGI_INFO("max_freesize: 0x%lx \n", xgi_pcie_heap->max_freesize); - if (size > xgi_pcie_heap->max_freesize) { - XGI_ERROR - ("size: 0x%lx bigger than PCIE total free size: 0x%lx.\n", - size, xgi_pcie_heap->max_freesize); - return (NULL); + else if ((alloc->owner == PCIE_3D_SCRATCHPAD) && (xgi_pcie_scratchpad_block)) { + DRM_INFO("PCIE Scratchpad has been created, return directly.\n"); + block = xgi_pcie_scratchpad_block; } + else { + block = xgi_mem_alloc(&info->pcie_heap, alloc->size, alloc->owner); - /* Jong 05/30/2006; find next free list which has enough space */ - list_for_each_entry(block, &xgi_pcie_heap->free_list, list) { - if (size <= block->size) { - break; + if (alloc->owner == PCIE_3D) { + xgi_pcie_vertex_block = block; + } + else if (alloc->owner == PCIE_3D_CMDLIST) { + xgi_pcie_cmdlist_block = block; + } + else if (alloc->owner == PCIE_3D_SCRATCHPAD) { + xgi_pcie_scratchpad_block = block; } } + up(&info->pcie_sem); - if (&block->list == &xgi_pcie_heap->free_list) { - XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", - size / 1024); - return (NULL); - } - - free_block = block; - XGI_INFO("alloc size: 0x%lx from offset: 0x%lx size: 0x%lx \n", - size, free_block->offset, free_block->size); - - if (size == free_block->size) { - used_block = free_block; - XGI_INFO("size==free_block->size: free_block = 0x%p\n", - free_block); - list_del(&free_block->list); + if (block == NULL) { + alloc->location = XGI_MEMLOC_INVALID; + alloc->size = 0; + DRM_ERROR("PCIE RAM allocation failed\n"); + return DRM_ERR(ENOMEM); } else { - used_block = xgi_pcie_new_node(); - if (used_block == NULL) { - return NULL; - } - - if (used_block == free_block) { - XGI_ERROR("used_block == free_block = 0x%p\n", - used_block); - } - - used_block->offset = free_block->offset; - used_block->size = size; + DRM_INFO("PCIE RAM allocation succeeded: offset = 0x%lx\n", + block->offset); + alloc->location = XGI_MEMLOC_NON_LOCAL; + alloc->size = block->size; + alloc->hw_addr = block->offset + info->pcie.base; + alloc->offset = block->offset; - free_block->offset += size; - free_block->size -= size; + block->filp = filp; + return 0; } +} - xgi_pcie_heap->max_freesize -= size; - used_block->bus_addr = info->pcie.base + used_block->offset; - used_block->hw_addr = info->pcie.base + used_block->offset; - used_block->page_count = page_count = size / PAGE_SIZE; +int xgi_pcie_alloc_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + struct xgi_mem_alloc alloc; + struct xgi_info *info = dev->dev_private; + int err; - /* get page_order base on page_count */ - for (used_block->page_order = 0; page_count; page_count >>= 1) { - ++used_block->page_order; - } + DRM_COPY_FROM_USER_IOCTL(alloc, (struct xgi_mem_alloc __user *) data, + sizeof(alloc)); - if ((used_block->page_count << 1) == (1 << used_block->page_order)) { - used_block->page_order--; - } - XGI_INFO - ("used_block->offset: 0x%lx, used_block->size: 0x%lx, used_block->bus_addr: 0x%lx, used_block->hw_addr: 0x%lx, used_block->page_count: 0x%lx used_block->page_order: 0x%lx\n", - used_block->offset, used_block->size, used_block->bus_addr, - used_block->hw_addr, used_block->page_count, - used_block->page_order); - - used_block->page_block = NULL; - //used_block->page_block = (struct xgi_pages_block *)kmalloc(sizeof(struct xgi_pages_block), GFP_KERNEL); - //if (!used_block->page_block) return NULL;_t - //used_block->page_block->next = NULL; - - used_block->page_table = - (struct xgi_pte *) kmalloc(sizeof(struct xgi_pte) * used_block->page_count, - GFP_KERNEL); - if (used_block->page_table == NULL) { - goto fail; + err = xgi_pcie_alloc(info, & alloc, filp); + if (err) { + return err; } + + DRM_COPY_TO_USER_IOCTL((struct xgi_mem_alloc __user *) data, + alloc, sizeof(alloc)); - lut_id = (used_block->offset >> PAGE_SHIFT); - lut_addr = info->lut_base; - lut_addr += lut_id; - XGI_INFO("lutAddr: 0x%p lutID: 0x%lx \n", lut_addr, lut_id); - - /* alloc free pages from system */ - page_count = used_block->page_count; - page_block = used_block->page_block; - prev_page_block = used_block->page_block; - for (i = 0; page_count > 0; i++) { - /* if size is bigger than 2M bytes, it should be split */ - if (page_count > (1 << XGI_PCIE_ALLOC_MAX_ORDER)) { - page_order = XGI_PCIE_ALLOC_MAX_ORDER; - } else { - count = page_count; - for (page_order = 0; count; count >>= 1, ++page_order) ; - - if ((page_count << 1) == (1 << page_order)) { - page_order -= 1; - } - } + return 0; +} - count = (1 << page_order); - page_addr = __get_free_pages(GFP_KERNEL, page_order); - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_addr=0x%lx \n", - page_addr); - if (!page_addr) { - XGI_ERROR - ("No: %d :Can't get free pages: 0x%lx from system memory !\n", - i, count); - goto fail; - } +/** + * Free all blocks associated with a particular file handle. + */ +void xgi_pcie_free_all(struct xgi_info * info, DRMFILE filp) +{ + if (!info->pcie_heap.initialized) { + return; + } - /* Jong 05/30/2006; test */ - memset((unsigned char *)page_addr, 0xFF, - PAGE_SIZE << page_order); - /* memset((unsigned char *)page_addr, 0, PAGE_SIZE << page_order); */ - - if (page_block == NULL) { - page_block = - (struct xgi_page_block *) - kmalloc(sizeof(struct xgi_page_block), GFP_KERNEL); - if (!page_block) { - XGI_ERROR - ("Can't get memory for page_block! \n"); - goto fail; - } - } + down(&info->pcie_sem); - if (prev_page_block == NULL) { - used_block->page_block = page_block; - prev_page_block = page_block; - } else { - prev_page_block->next = page_block; - prev_page_block = page_block; - } + do { + struct xgi_mem_block *block; - page_block->next = NULL; - page_block->phys_addr = __pa(page_addr); - page_block->virt_addr = page_addr; - page_block->page_count = count; - page_block->page_order = page_order; - - XGI_INFO - ("Jong05302006-xgi_pcie_mem_alloc-page_block->phys_addr=0x%lx \n", - page_block->phys_addr); - XGI_INFO - ("Jong05302006-xgi_pcie_mem_alloc-page_block->virt_addr=0x%lx \n", - page_block->virt_addr); - - page = virt_to_page(page_addr); - - //XGI_INFO("No: %d page_order: 0x%lx page_count: 0x%x count: 0x%lx index: 0x%lx lut_addr: 0x%p" - // "page_block->phys_addr: 0x%lx page_block->virt_addr: 0x%lx \n", - // i, page_order, page_count, count, index, lut_addr, page_block->phys_addr, page_block->virt_addr); - - for (j = 0; j < count; j++, page++, lut_addr++) { - used_block->page_table[index + j].phys_addr = - __pa(page_address(page)); - used_block->page_table[index + j].virt_addr = - (unsigned long)page_address(page); - - XGI_INFO - ("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].phys_addr=0x%lx \n", - used_block->page_table[index + j].phys_addr); - XGI_INFO - ("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].virt_addr=0x%lx \n", - used_block->page_table[index + j].virt_addr); - - *lut_addr = __pa(page_address(page)); - XGI_INC_PAGE_COUNT(page); - XGILockPage(page); - - if (temp) { - XGI_INFO - ("__pa(page_address(page)): 0x%lx lutAddr: 0x%p lutAddr No: 0x%x = 0x%lx \n", - __pa(page_address(page)), lut_addr, j, - *lut_addr); - temp--; + list_for_each_entry(block, &info->pcie_heap.used_list, list) { + if (block->filp == filp) { + break; } } - page_block = page_block->next; - page_count -= count; - index += count; - temp = 0; - } - - used_block->owner = owner; - list_add(&used_block->list, &xgi_pcie_heap->used_list); - -#if defined(__i386__) || defined(__x86_64__) - asm volatile ("wbinvd":::"memory"); -#else - mb(); -#endif - - /* Flush GART Table */ - bWriteReg(0xB03F, 0x40); - bWriteReg(0xB03F, 0x00); - - if (owner == PCIE_3D) { - xgi_pcie_vertex_block = used_block; - } - - if (owner == PCIE_3D_CMDLIST) { - xgi_pcie_cmdlist_block = used_block; - } - - if (owner == PCIE_3D_SCRATCHPAD) { - xgi_pcie_scratchpad_block = used_block; - } - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-End \n"); - return (used_block); - - fail: - xgi_pcie_block_stuff_free(used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - return NULL; -} - -static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, - unsigned long offset) -{ - struct xgi_pcie_block *used_block, *block; - struct xgi_pcie_block *prev, *next; - unsigned long upper, lower; - - list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { - if (block->offset == offset) { + if (&block->list == &info->pcie_heap.used_list) { break; } - } - - if (&block->list == &xgi_pcie_heap->used_list) { - XGI_ERROR("can't find block: 0x%lx to free!\n", offset); - return (NULL); - } - - used_block = block; - XGI_INFO - ("used_block: 0x%p, offset = 0x%lx, size = 0x%lx, bus_addr = 0x%lx, hw_addr = 0x%lx\n", - used_block, used_block->offset, used_block->size, - used_block->bus_addr, used_block->hw_addr); - - xgi_pcie_block_stuff_free(used_block); - /* update xgi_pcie_heap */ - xgi_pcie_heap->max_freesize += used_block->size; + (void) xgi_pcie_free(info, block->offset, filp); + } while(1); - prev = next = NULL; - upper = used_block->offset + used_block->size; - lower = used_block->offset; - - list_for_each_entry(block, &xgi_pcie_heap->free_list, list) { - if (block->offset == upper) { - next = block; - } else if ((block->offset + block->size) == lower) { - prev = block; - } - } - - XGI_INFO("next = 0x%p, prev = 0x%p\n", next, prev); - list_del(&used_block->list); - - if (prev && next) { - prev->size += (used_block->size + next->size); - list_del(&next->list); - XGI_INFO("free node 0x%p\n", next); - kmem_cache_free(xgi_pcie_cache_block, next); - kmem_cache_free(xgi_pcie_cache_block, used_block); - next = NULL; - used_block = NULL; - return (prev); - } - - if (prev) { - prev->size += used_block->size; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - used_block = NULL; - return (prev); - } - - if (next) { - next->size += used_block->size; - next->offset = used_block->offset; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - used_block = NULL; - return (next); - } - - used_block->bus_addr = 0; - used_block->hw_addr = 0; - used_block->page_count = 0; - used_block->page_order = 0; - list_add(&used_block->list, &xgi_pcie_heap->free_list); - XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", - used_block, used_block->offset, used_block->size); - return (used_block); + up(&info->pcie_sem); } -void xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - pid_t pid) -{ - struct xgi_pcie_block *block; - - xgi_down(info->pcie_sem); - block = xgi_pcie_mem_alloc(info, alloc->size, alloc->owner); - xgi_up(info->pcie_sem); - - if (block == NULL) { - alloc->location = XGI_MEMLOC_INVALID; - alloc->size = 0; - alloc->bus_addr = 0; - alloc->hw_addr = 0; - XGI_ERROR("PCIE RAM allocation failed\n"); - } else { - XGI_INFO - ("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", - block->offset, block->bus_addr); - alloc->location = XGI_MEMLOC_NON_LOCAL; - alloc->size = block->size; - alloc->bus_addr = block->bus_addr; - alloc->hw_addr = block->hw_addr; - - /* - manage mempid, handle PCIE_3D, PCIE_3D_TEXTURE. - PCIE_3D request means a opengl process created. - PCIE_3D_TEXTURE request means texture cannot alloc from fb. - */ - if ((alloc->owner == PCIE_3D) - || (alloc->owner == PCIE_3D_TEXTURE)) { - struct xgi_mem_pid *mempid_block = - kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); - if (!mempid_block) - XGI_ERROR("mempid_block alloc failed\n"); - mempid_block->location = XGI_MEMLOC_NON_LOCAL; - if (alloc->owner == PCIE_3D) - mempid_block->bus_addr = 0xFFFFFFFF; /*xgi_pcie_vertex_block has the address */ - else - mempid_block->bus_addr = alloc->bus_addr; - mempid_block->pid = pid; - - XGI_INFO - ("Memory ProcessID add one pcie block pid:%ld successfully! \n", - mempid_block->pid); - list_add(&mempid_block->list, &xgi_mempid_list); - } - } -} -void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) +int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) { - struct xgi_pcie_block *block; - unsigned long offset = bus_addr - info->pcie.base; - struct xgi_mem_pid *mempid_block; - struct xgi_mem_pid *mempid_freeblock = NULL; - char isvertex = 0; - int processcnt; - - if (xgi_pcie_vertex_block - && xgi_pcie_vertex_block->bus_addr == bus_addr) - isvertex = 1; - - if (isvertex) { - /*check is there any other process using vertex */ - processcnt = 0; - - list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == XGI_MEMLOC_NON_LOCAL - && mempid_block->bus_addr == 0xFFFFFFFF) { - ++processcnt; - } - } - if (processcnt > 1) { - return; - } - } + const bool isvertex = (xgi_pcie_vertex_block + && (xgi_pcie_vertex_block->offset == offset)); + int err; - xgi_down(info->pcie_sem); - block = xgi_pcie_mem_free(info, offset); - xgi_up(info->pcie_sem); + down(&info->pcie_sem); + err = xgi_mem_free(&info->pcie_heap, offset, filp); + up(&info->pcie_sem); - if (block == NULL) { - XGI_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); + if (err) { + DRM_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); } if (isvertex) xgi_pcie_vertex_block = NULL; - /* manage mempid */ - list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == XGI_MEMLOC_NON_LOCAL - && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) - || (!isvertex && mempid_block->bus_addr == bus_addr))) { - mempid_freeblock = mempid_block; - break; - } - } - if (mempid_freeblock) { - list_del(&mempid_freeblock->list); - XGI_INFO - ("Memory ProcessID delete one pcie block pid:%ld successfully! \n", - mempid_freeblock->pid); - kfree(mempid_freeblock); - } + return err; } -/* - * given a bus address, fid the pcie mem block - * uses the bus address as the key. - */ -struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, - unsigned long address) -{ - struct xgi_pcie_block *block; - int i; - - list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { - if (block->bus_addr == address) { - return block; - } - - if (block->page_table) { - for (i = 0; i < block->page_count; i++) { - unsigned long offset = block->bus_addr; - if ((address >= offset) - && (address < (offset + PAGE_SIZE))) { - return block; - } - } - } - } +int xgi_pcie_free_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + struct xgi_info *info = dev->dev_private; + u32 offset; - XGI_ERROR("could not find map for vm 0x%lx\n", address); + DRM_COPY_FROM_USER_IOCTL(offset, (unsigned long __user *) data, + sizeof(offset)); - return NULL; + return xgi_pcie_free(info, offset, filp); } + /** * xgi_find_pcie_virt * @address: GE HW address @@ -880,60 +296,43 @@ struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, * Returns CPU virtual address. Assumes the CPU VAddr is continuous in not * the same block */ -void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) +void *xgi_find_pcie_virt(struct xgi_info * info, u32 address) { - struct xgi_pcie_block *block; - const unsigned long offset_in_page = address & (PAGE_SIZE - 1); - - XGI_INFO("begin (address = 0x%lx, offset_in_page = %lu)\n", - address, offset_in_page); - - list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { - XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", - block, block->hw_addr, block->size); - - if ((address >= block->hw_addr) - && (address < (block->hw_addr + block->size))) { - const unsigned long loc_in_pagetable = - (address - block->hw_addr) >> PAGE_SHIFT; - void *const ret = - (void *)(block->page_table[loc_in_pagetable]. - virt_addr + offset_in_page); - - XGI_INFO("PAGE_SHIFT = %d\n", PAGE_SHIFT); - XGI_INFO("block->page_table[0x%lx].virt_addr = 0x%lx\n", - loc_in_pagetable, - block->page_table[loc_in_pagetable].virt_addr); - XGI_INFO("return 0x%p\n", ret); - - return ret; - } - } + const unsigned long offset = address - info->pcie.base; - XGI_ERROR("could not find map for vm 0x%lx\n", address); - return NULL; + return ((u8 *) info->dev->sg->virtual) + offset; } /* address -- GE hw address */ -void xgi_test_rwinkernel(struct xgi_info * info, unsigned long address) +int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS) { + DRM_DEVICE; + struct xgi_info *info = dev->dev_private; + u32 address; u32 *virtaddr = 0; - XGI_INFO("input GE HW addr is 0x%x\n", address); + DRM_COPY_FROM_USER_IOCTL(address, (unsigned long __user *) data, + sizeof(address)); + + DRM_INFO("input GE HW addr is 0x%x\n", address); if (address == 0) { - return; + return DRM_ERR(EFAULT); } virtaddr = (u32 *)xgi_find_pcie_virt(info, address); - XGI_INFO("convert to CPU virt addr 0x%p\n", virtaddr); + DRM_INFO("convert to CPU virt addr 0x%p\n", virtaddr); if (virtaddr != NULL) { - XGI_INFO("original [virtaddr] = 0x%x\n", *virtaddr); + DRM_INFO("original [virtaddr] = 0x%x\n", *virtaddr); *virtaddr = 0x00f00fff; - XGI_INFO("modified [virtaddr] = 0x%x\n", *virtaddr); + DRM_INFO("modified [virtaddr] = 0x%x\n", *virtaddr); + } else { + return DRM_ERR(EFAULT); } + + return 0; } -- cgit v1.2.3 From 15245b670e5359a7dbf9151aa9f160e929e0b46b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 19 Jul 2007 11:38:56 -0700 Subject: Rework xgi_(pcie|fb)_free_all to prevent deadlock. --- linux-core/xgi_pcie.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 49c531fc..9dee888b 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -34,6 +34,9 @@ static struct xgi_mem_block *xgi_pcie_vertex_block = NULL; static struct xgi_mem_block *xgi_pcie_cmdlist_block = NULL; static struct xgi_mem_block *xgi_pcie_scratchpad_block = NULL; +static int xgi_pcie_free_locked(struct xgi_info * info, + unsigned long offset, DRMFILE filp); + static int xgi_pcie_lut_init(struct xgi_info * info) { u8 temp = 0; @@ -248,30 +251,39 @@ void xgi_pcie_free_all(struct xgi_info * info, DRMFILE filp) break; } - (void) xgi_pcie_free(info, block->offset, filp); + (void) xgi_pcie_free_locked(info, block->offset, filp); } while(1); up(&info->pcie_sem); } -int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) +int xgi_pcie_free_locked(struct xgi_info * info, + unsigned long offset, DRMFILE filp) { const bool isvertex = (xgi_pcie_vertex_block && (xgi_pcie_vertex_block->offset == offset)); + int err = xgi_mem_free(&info->pcie_heap, offset, filp); + + if (!err && isvertex) + xgi_pcie_vertex_block = NULL; + + return err; +} + + +int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) +{ int err; down(&info->pcie_sem); - err = xgi_mem_free(&info->pcie_heap, offset, filp); + err = xgi_pcie_free_locked(info, offset, filp); up(&info->pcie_sem); if (err) { DRM_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); } - if (isvertex) - xgi_pcie_vertex_block = NULL; - return err; } -- cgit v1.2.3 From 8e64d2ae862d5fa02e23c68db6b55393e1f86005 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 24 Jul 2007 13:36:02 -0700 Subject: Fix license formatting. --- linux-core/xgi_pcie.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 9dee888b..537e82f5 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -1,29 +1,27 @@ - /**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * Copyright (C) 2003-2006 by XGI Technology, Taiwan. + * + * All Rights Reserved. + * * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation on the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL XGI AND/OR - * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. ***************************************************************************/ #include "xgi_drv.h" -- cgit v1.2.3 From b89cc0346500d9875d4acebc611db8f9ee3463f7 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 26 Jul 2007 16:58:59 -0700 Subject: Eliminate unnecessary (and now wrong) call gto drm_sg_free. --- linux-core/xgi_pcie.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 537e82f5..dc5a50b8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -121,10 +121,6 @@ static int xgi_pcie_lut_init(struct xgi_info * info) void xgi_pcie_lut_cleanup(struct xgi_info * info) { - if (info->dev->sg) { - drm_sg_free(info->dev, info->dev->sg->handle); - } - if (info->lut_handle) { drm_pci_free(info->dev, info->lut_handle); info->lut_handle = NULL; -- cgit v1.2.3 From c37ed9eca57a42b98cc67ca98dbf5135f5ab7aba Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 26 Jul 2007 17:01:16 -0700 Subject: Eliminate use of DRM_ERR. --- linux-core/xgi_pcie.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index dc5a50b8..4c369a2a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -85,7 +85,7 @@ static int xgi_pcie_lut_init(struct xgi_info * info) DMA_31BIT_MASK); if (info->lut_handle == NULL) { DRM_ERROR("cannot allocate PCIE lut page!\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } lut = info->lut_handle->vaddr; @@ -97,7 +97,7 @@ static int xgi_pcie_lut_init(struct xgi_info * info) DMA_BIDIRECTIONAL); if (dma_mapping_error(info->dev->sg->busaddr[i])) { DRM_ERROR("cannot map GART backing store for DMA!\n"); - return DRM_ERR(-(info->dev->sg->busaddr[i])); + return info->dev->sg->busaddr[i]; } lut[i] = info->dev->sg->busaddr[i]; @@ -184,7 +184,7 @@ int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, alloc->location = XGI_MEMLOC_INVALID; alloc->size = 0; DRM_ERROR("PCIE RAM allocation failed\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } else { DRM_INFO("PCIE RAM allocation succeeded: offset = 0x%lx\n", block->offset); @@ -325,7 +325,7 @@ int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS) DRM_INFO("input GE HW addr is 0x%x\n", address); if (address == 0) { - return DRM_ERR(EFAULT); + return -EFAULT; } virtaddr = (u32 *)xgi_find_pcie_virt(info, address); @@ -337,7 +337,7 @@ int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS) *virtaddr = 0x00f00fff; DRM_INFO("modified [virtaddr] = 0x%x\n", *virtaddr); } else { - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; -- cgit v1.2.3 From cd51f131389297f923798daef6c734ba93f4422b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 27 Jul 2007 15:45:59 -0700 Subject: Convert to new ioctl interface between core DRM and device-specific module. --- linux-core/xgi_pcie.c | 52 ++++++++++++++++++--------------------------------- 1 file changed, 18 insertions(+), 34 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 4c369a2a..b91471b8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -33,7 +33,7 @@ static struct xgi_mem_block *xgi_pcie_cmdlist_block = NULL; static struct xgi_mem_block *xgi_pcie_scratchpad_block = NULL; static int xgi_pcie_free_locked(struct xgi_info * info, - unsigned long offset, DRMFILE filp); + unsigned long offset, struct drm_file * filp); static int xgi_pcie_lut_init(struct xgi_info * info) { @@ -148,7 +148,7 @@ int xgi_pcie_heap_init(struct xgi_info * info) int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - DRMFILE filp) + struct drm_file * filp) { struct xgi_mem_block *block; @@ -199,32 +199,21 @@ int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, } -int xgi_pcie_alloc_ioctl(DRM_IOCTL_ARGS) +int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; - struct xgi_mem_alloc alloc; + struct xgi_mem_alloc *const alloc = + (struct xgi_mem_alloc *) data; struct xgi_info *info = dev->dev_private; - int err; - - DRM_COPY_FROM_USER_IOCTL(alloc, (struct xgi_mem_alloc __user *) data, - sizeof(alloc)); - - err = xgi_pcie_alloc(info, & alloc, filp); - if (err) { - return err; - } - - DRM_COPY_TO_USER_IOCTL((struct xgi_mem_alloc __user *) data, - alloc, sizeof(alloc)); - return 0; + return xgi_pcie_alloc(info, alloc, filp); } /** * Free all blocks associated with a particular file handle. */ -void xgi_pcie_free_all(struct xgi_info * info, DRMFILE filp) +void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) { if (!info->pcie_heap.initialized) { return; @@ -252,8 +241,8 @@ void xgi_pcie_free_all(struct xgi_info * info, DRMFILE filp) } -int xgi_pcie_free_locked(struct xgi_info * info, - unsigned long offset, DRMFILE filp) +int xgi_pcie_free_locked(struct xgi_info * info, unsigned long offset, + struct drm_file * filp) { const bool isvertex = (xgi_pcie_vertex_block && (xgi_pcie_vertex_block->offset == offset)); @@ -266,7 +255,8 @@ int xgi_pcie_free_locked(struct xgi_info * info, } -int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) +int xgi_pcie_free(struct xgi_info * info, unsigned long offset, + struct drm_file * filp) { int err; @@ -282,16 +272,12 @@ int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) } -int xgi_pcie_free_ioctl(DRM_IOCTL_ARGS) +int xgi_pcie_free_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; struct xgi_info *info = dev->dev_private; - u32 offset; - - DRM_COPY_FROM_USER_IOCTL(offset, (unsigned long __user *) data, - sizeof(offset)); - return xgi_pcie_free(info, offset, filp); + return xgi_pcie_free(info, *(u32 *) data, filp); } @@ -312,15 +298,13 @@ void *xgi_find_pcie_virt(struct xgi_info * info, u32 address) /* address -- GE hw address */ -int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS) +int xgi_test_rwinkernel_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; struct xgi_info *info = dev->dev_private; - u32 address; + u32 address = *(u32 *) data; u32 *virtaddr = 0; - DRM_COPY_FROM_USER_IOCTL(address, (unsigned long __user *) data, - sizeof(address)); DRM_INFO("input GE HW addr is 0x%x\n", address); -- cgit v1.2.3 From 997a9a738ec26cf0ef2c7dee5e30bb53bd11bf6c Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 15:31:34 -0700 Subject: Eliminate allocation "owner" usage. --- linux-core/xgi_pcie.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b91471b8..f66ffee9 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -153,31 +153,7 @@ int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, struct xgi_mem_block *block; down(&info->pcie_sem); - if ((alloc->owner == PCIE_3D) && (xgi_pcie_vertex_block)) { - DRM_INFO("PCIE Vertex has been created, return directly.\n"); - block = xgi_pcie_vertex_block; - } - else if ((alloc->owner == PCIE_3D_CMDLIST) && (xgi_pcie_cmdlist_block)) { - DRM_INFO("PCIE Cmdlist has been created, return directly.\n"); - block = xgi_pcie_cmdlist_block; - } - else if ((alloc->owner == PCIE_3D_SCRATCHPAD) && (xgi_pcie_scratchpad_block)) { - DRM_INFO("PCIE Scratchpad has been created, return directly.\n"); - block = xgi_pcie_scratchpad_block; - } - else { - block = xgi_mem_alloc(&info->pcie_heap, alloc->size, alloc->owner); - - if (alloc->owner == PCIE_3D) { - xgi_pcie_vertex_block = block; - } - else if (alloc->owner == PCIE_3D_CMDLIST) { - xgi_pcie_cmdlist_block = block; - } - else if (alloc->owner == PCIE_3D_SCRATCHPAD) { - xgi_pcie_scratchpad_block = block; - } - } + block = xgi_mem_alloc(&info->pcie_heap, alloc->size); up(&info->pcie_sem); if (block == NULL) { -- cgit v1.2.3 From a6fb93a150f90ada9af6760b52d34716497f744f Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 15:43:51 -0700 Subject: Finish removing allocation "owner" infrastructure. --- linux-core/xgi_pcie.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index f66ffee9..be6915e8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -28,10 +28,6 @@ #include "xgi_regs.h" #include "xgi_misc.h" -static struct xgi_mem_block *xgi_pcie_vertex_block = NULL; -static struct xgi_mem_block *xgi_pcie_cmdlist_block = NULL; -static struct xgi_mem_block *xgi_pcie_scratchpad_block = NULL; - static int xgi_pcie_free_locked(struct xgi_info * info, unsigned long offset, struct drm_file * filp); @@ -220,14 +216,7 @@ void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) int xgi_pcie_free_locked(struct xgi_info * info, unsigned long offset, struct drm_file * filp) { - const bool isvertex = (xgi_pcie_vertex_block - && (xgi_pcie_vertex_block->offset == offset)); - int err = xgi_mem_free(&info->pcie_heap, offset, filp); - - if (!err && isvertex) - xgi_pcie_vertex_block = NULL; - - return err; + return xgi_mem_free(&info->pcie_heap, offset, filp); } -- cgit v1.2.3 From 5362cc723e6605c31d152eb22ee3dc40c9e3f56b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 15:52:06 -0700 Subject: Eliminate unnecessary function xgi_pcie_free_locked. --- linux-core/xgi_pcie.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index be6915e8..df49615a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -28,9 +28,6 @@ #include "xgi_regs.h" #include "xgi_misc.h" -static int xgi_pcie_free_locked(struct xgi_info * info, - unsigned long offset, struct drm_file * filp); - static int xgi_pcie_lut_init(struct xgi_info * info) { u8 temp = 0; @@ -206,27 +203,20 @@ void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) break; } - (void) xgi_pcie_free_locked(info, block->offset, filp); + (void) xgi_mem_free(&info->pcie_heap, block->offset, filp); } while(1); up(&info->pcie_sem); } -int xgi_pcie_free_locked(struct xgi_info * info, unsigned long offset, - struct drm_file * filp) -{ - return xgi_mem_free(&info->pcie_heap, offset, filp); -} - - int xgi_pcie_free(struct xgi_info * info, unsigned long offset, struct drm_file * filp) { int err; down(&info->pcie_sem); - err = xgi_pcie_free_locked(info, offset, filp); + err = xgi_mem_free(&info->pcie_heap, offset, filp); up(&info->pcie_sem); if (err) { -- cgit v1.2.3 From f96bff9e213a950ab910832908d30e732435e628 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 16:09:05 -0700 Subject: Unify infrastructure for allocating (not yet freeing) on-card / GART memory. --- linux-core/xgi_pcie.c | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index df49615a..c0d424f5 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -140,34 +140,6 @@ int xgi_pcie_heap_init(struct xgi_info * info) } -int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - struct drm_file * filp) -{ - struct xgi_mem_block *block; - - down(&info->pcie_sem); - block = xgi_mem_alloc(&info->pcie_heap, alloc->size); - up(&info->pcie_sem); - - if (block == NULL) { - alloc->location = XGI_MEMLOC_INVALID; - alloc->size = 0; - DRM_ERROR("PCIE RAM allocation failed\n"); - return -ENOMEM; - } else { - DRM_INFO("PCIE RAM allocation succeeded: offset = 0x%lx\n", - block->offset); - alloc->location = XGI_MEMLOC_NON_LOCAL; - alloc->size = block->size; - alloc->hw_addr = block->offset + info->pcie.base; - alloc->offset = block->offset; - - block->filp = filp; - return 0; - } -} - - int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, struct drm_file * filp) { @@ -175,7 +147,8 @@ int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, (struct xgi_mem_alloc *) data; struct xgi_info *info = dev->dev_private; - return xgi_pcie_alloc(info, alloc, filp); + alloc->location = XGI_MEMLOC_NON_LOCAL; + return xgi_alloc(info, alloc, filp); } -- cgit v1.2.3 From 90907c59152f628d6f0efea4927a06e547f4a3c7 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 16:17:23 -0700 Subject: Replace per-heap semaphores with drm_device::struct_mutex. --- linux-core/xgi_pcie.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index c0d424f5..883fbe7e 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -161,7 +161,7 @@ void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) return; } - down(&info->pcie_sem); + mutex_lock(&info->dev->struct_mutex); do { struct xgi_mem_block *block; @@ -179,7 +179,7 @@ void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) (void) xgi_mem_free(&info->pcie_heap, block->offset, filp); } while(1); - up(&info->pcie_sem); + mutex_unlock(&info->dev->struct_mutex); } @@ -188,9 +188,9 @@ int xgi_pcie_free(struct xgi_info * info, unsigned long offset, { int err; - down(&info->pcie_sem); + mutex_lock(&info->dev->struct_mutex); err = xgi_mem_free(&info->pcie_heap, offset, filp); - up(&info->pcie_sem); + mutex_unlock(&info->dev->struct_mutex); if (err) { DRM_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); -- cgit v1.2.3 From f3072becda3a2d5fe587f20e155d4d4f9ace60a2 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 16:35:07 -0700 Subject: Refactor xgi_(fb|pcie)_free_all into xgi_free_all. --- linux-core/xgi_pcie.c | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 883fbe7e..b2edf3b1 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -152,37 +152,6 @@ int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, } -/** - * Free all blocks associated with a particular file handle. - */ -void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) -{ - if (!info->pcie_heap.initialized) { - return; - } - - mutex_lock(&info->dev->struct_mutex); - - do { - struct xgi_mem_block *block; - - list_for_each_entry(block, &info->pcie_heap.used_list, list) { - if (block->filp == filp) { - break; - } - } - - if (&block->list == &info->pcie_heap.used_list) { - break; - } - - (void) xgi_mem_free(&info->pcie_heap, block->offset, filp); - } while(1); - - mutex_unlock(&info->dev->struct_mutex); -} - - int xgi_pcie_free(struct xgi_info * info, unsigned long offset, struct drm_file * filp) { -- cgit v1.2.3 From f7ba02b7458823627097a2320bf9befa84fc9c76 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 17:27:15 -0700 Subject: Unify infrastructure for freeing on-card / GART memory. --- linux-core/xgi_pcie.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b2edf3b1..281223b3 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -152,29 +152,12 @@ int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, } -int xgi_pcie_free(struct xgi_info * info, unsigned long offset, - struct drm_file * filp) -{ - int err; - - mutex_lock(&info->dev->struct_mutex); - err = xgi_mem_free(&info->pcie_heap, offset, filp); - mutex_unlock(&info->dev->struct_mutex); - - if (err) { - DRM_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); - } - - return err; -} - - int xgi_pcie_free_ioctl(struct drm_device * dev, void * data, struct drm_file * filp) { struct xgi_info *info = dev->dev_private; - return xgi_pcie_free(info, *(u32 *) data, filp); + return xgi_free(info, XGI_MEMLOC_NON_LOCAL | *(u32 *) data, filp); } -- cgit v1.2.3 From aea6b4dea9708f66f5fc2068fe84407682570aca Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 15:30:36 -0700 Subject: Unify alloc and free ioctls. The DRM_XGI_PCIE_ALLOC and DRM_XGI_FB_ALLOC ioctls (and the matching free ioctls) are unified to DRM_XGI_ALLOC. The desired memory region is selected by xgi_mem_alloc::location. The region is magically encoded in xgi_mem_alloc::index, which is used to release the memory. Bump to version 0.11.0. This update requires a new DDX. --- linux-core/xgi_pcie.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 281223b3..4ec9b6ff 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -140,27 +140,6 @@ int xgi_pcie_heap_init(struct xgi_info * info) } -int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) -{ - struct xgi_mem_alloc *const alloc = - (struct xgi_mem_alloc *) data; - struct xgi_info *info = dev->dev_private; - - alloc->location = XGI_MEMLOC_NON_LOCAL; - return xgi_alloc(info, alloc, filp); -} - - -int xgi_pcie_free_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) -{ - struct xgi_info *info = dev->dev_private; - - return xgi_free(info, XGI_MEMLOC_NON_LOCAL | *(u32 *) data, filp); -} - - /** * xgi_find_pcie_virt * @address: GE HW address -- cgit v1.2.3 From dbd4d0597ff32458bbe4347bdea0e4b9e55a14da Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 16:01:14 -0700 Subject: Use sman memory manager instead of internal version. --- linux-core/xgi_pcie.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 4ec9b6ff..932615a4 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -131,11 +131,15 @@ int xgi_pcie_heap_init(struct xgi_info * info) } - err = xgi_mem_heap_init(&info->pcie_heap, 0, info->pcie.size); + mutex_lock(&info->dev->struct_mutex); + err = drm_sman_set_range(&info->sman, XGI_MEMLOC_NON_LOCAL, + 0, info->pcie.size); + mutex_unlock(&info->dev->struct_mutex); if (err) { xgi_pcie_lut_cleanup(info); } + info->pcie_heap_initialized = (err == 0); return err; } -- cgit v1.2.3 From 06e09842dfbdaa9502d3b3e6b657de4e3630644c Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 18:28:16 -0700 Subject: Use DRM_MEMORYBARRIER() macro instead of mb(). --- linux-core/xgi_pcie.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 932615a4..d15ea32a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -96,11 +96,7 @@ static int xgi_pcie_lut_init(struct xgi_info * info) lut[i] = info->dev->sg->busaddr[i]; } -#if defined(__i386__) || defined(__x86_64__) - asm volatile ("wbinvd":::"memory"); -#else - mb(); -#endif + DRM_MEMORYBARRIER(); /* Set GART in SFB */ temp = DRM_READ8(info->mmio_map, 0xB00C); -- cgit v1.2.3 From 15f841bd529b50901272ca35a4c57de42a51901a Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 13 Aug 2007 16:21:20 -0700 Subject: Strobe magic 0xB03F register to flush PCI-e GART table. The original XGI kernel driver strobed 0xB03F each time a page was allocated to back a GART page. When the driver was converted to use the DRM SG interface, this code was lost. Returning it fixes a long standing issue where the X-server would work fine the first time, but acceleration commands would be ignored on the second X-server invocation. --- linux-core/xgi_pcie.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index d15ea32a..a0f52740 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -103,7 +103,11 @@ static int xgi_pcie_lut_init(struct xgi_info * info) DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02); /* Set GART base address to HW */ - dwWriteReg(info->mmio_map, 0xB034, info->lut_handle->busaddr); + DRM_WRITE32(info->mmio_map, 0xB034, info->lut_handle->busaddr); + + /* Flush GART table. */ + DRM_WRITE8(info->mmio_map, 0xB03F, 0x40); + DRM_WRITE8(info->mmio_map, 0xB03F, 0x00); return 0; } -- cgit v1.2.3 From f563a50d145848ed296b63c63422caff80232ddf Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 14 Aug 2007 13:44:51 -0700 Subject: Eliminate unused / useless ioctls. --- linux-core/xgi_pcie.c | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index a0f52740..b4d204c1 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -157,35 +157,3 @@ void *xgi_find_pcie_virt(struct xgi_info * info, u32 address) return ((u8 *) info->dev->sg->virtual) + offset; } - -/* - address -- GE hw address -*/ -int xgi_test_rwinkernel_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) -{ - struct xgi_info *info = dev->dev_private; - u32 address = *(u32 *) data; - u32 *virtaddr = 0; - - - DRM_INFO("input GE HW addr is 0x%x\n", address); - - if (address == 0) { - return -EFAULT; - } - - virtaddr = (u32 *)xgi_find_pcie_virt(info, address); - - DRM_INFO("convert to CPU virt addr 0x%p\n", virtaddr); - - if (virtaddr != NULL) { - DRM_INFO("original [virtaddr] = 0x%x\n", *virtaddr); - *virtaddr = 0x00f00fff; - DRM_INFO("modified [virtaddr] = 0x%x\n", *virtaddr); - } else { - return -EFAULT; - } - - return 0; -} -- cgit v1.2.3 From 9c5b9d458bc618fb9d7d8590c866655e92f9cb0b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 29 Aug 2007 14:41:49 -0700 Subject: Use ati_pcigart for PCI-e GART table handling. --- linux-core/xgi_pcie.c | 89 ++++++++++++++++----------------------------------- 1 file changed, 28 insertions(+), 61 deletions(-) (limited to 'linux-core/xgi_pcie.c') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b4d204c1..a7d3ea24 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -28,15 +28,31 @@ #include "xgi_regs.h" #include "xgi_misc.h" -static int xgi_pcie_lut_init(struct xgi_info * info) +void xgi_gart_flush(struct drm_device *dev) +{ + struct xgi_info *const info = dev->dev_private; + u8 temp; + + DRM_MEMORYBARRIER(); + + /* Set GART in SFB */ + temp = DRM_READ8(info->mmio_map, 0xB00C); + DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02); + + /* Set GART base address to HW */ + DRM_WRITE32(info->mmio_map, 0xB034, info->gart_info.bus_addr); + + /* Flush GART table. */ + DRM_WRITE8(info->mmio_map, 0xB03F, 0x40); + DRM_WRITE8(info->mmio_map, 0xB03F, 0x00); +} + + +int xgi_pcie_heap_init(struct xgi_info * info) { u8 temp = 0; int err; - unsigned i; struct drm_scatter_gather request; - struct drm_sg_mem *sg; - u32 *lut; - /* Get current FB aperture size */ temp = IN3X5B(info->mmio_map, 0x27); @@ -70,73 +86,24 @@ static int xgi_pcie_lut_init(struct xgi_info * info) return err; } - sg = info->dev->sg; + info->gart_info.gart_table_location = DRM_ATI_GART_MAIN; + info->gart_info.gart_reg_if = DRM_ATI_GART_PCI; + info->gart_info.table_size = info->dev->sg->pages * sizeof(u32); - info->lut_handle = drm_pci_alloc(info->dev, - sizeof(u32) * sg->pages, - PAGE_SIZE, - DMA_31BIT_MASK); - if (info->lut_handle == NULL) { - DRM_ERROR("cannot allocate PCIE lut page!\n"); + if (!drm_ati_pcigart_init(info->dev, &info->gart_info)) { + DRM_ERROR("failed to init PCI GART!\n"); return -ENOMEM; } - lut = info->lut_handle->vaddr; - for (i = 0; i < sg->pages; i++) { - info->dev->sg->busaddr[i] = pci_map_page(info->dev->pdev, - sg->pagelist[i], - 0, - PAGE_SIZE, - DMA_BIDIRECTIONAL); - if (dma_mapping_error(info->dev->sg->busaddr[i])) { - DRM_ERROR("cannot map GART backing store for DMA!\n"); - return info->dev->sg->busaddr[i]; - } - - lut[i] = info->dev->sg->busaddr[i]; - } - - DRM_MEMORYBARRIER(); - - /* Set GART in SFB */ - temp = DRM_READ8(info->mmio_map, 0xB00C); - DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02); - - /* Set GART base address to HW */ - DRM_WRITE32(info->mmio_map, 0xB034, info->lut_handle->busaddr); - - /* Flush GART table. */ - DRM_WRITE8(info->mmio_map, 0xB03F, 0x40); - DRM_WRITE8(info->mmio_map, 0xB03F, 0x00); - - return 0; -} - -void xgi_pcie_lut_cleanup(struct xgi_info * info) -{ - if (info->lut_handle) { - drm_pci_free(info->dev, info->lut_handle); - info->lut_handle = NULL; - } -} - -int xgi_pcie_heap_init(struct xgi_info * info) -{ - int err; - - err = xgi_pcie_lut_init(info); - if (err) { - DRM_ERROR("xgi_pcie_lut_init failed\n"); - return err; - } + xgi_gart_flush(info->dev); mutex_lock(&info->dev->struct_mutex); err = drm_sman_set_range(&info->sman, XGI_MEMLOC_NON_LOCAL, 0, info->pcie.size); mutex_unlock(&info->dev->struct_mutex); if (err) { - xgi_pcie_lut_cleanup(info); + drm_ati_pcigart_cleanup(info->dev, &info->gart_info); } info->pcie_heap_initialized = (err == 0); -- cgit v1.2.3