X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fdrm%2Fdrm_pci.c;h=86a0f1c2209111075eb096d971271e08082f9e76;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=192e8762571c890b0b10d536234d326b0bfcac06;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c index 192e87625..86a0f1c22 100644 --- a/drivers/char/drm/drm_pci.c +++ b/drivers/char/drm/drm_pci.c @@ -37,6 +37,7 @@ */ #include +#include #include "drmP.h" /**********************************************************************/ @@ -46,11 +47,15 @@ /** * \brief Allocate a PCI consistent memory block, for DMA. */ -void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, - dma_addr_t maxaddr, dma_addr_t * busaddr) +drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, + dma_addr_t maxaddr) { - void *address; -#if DRM_DEBUG_MEMORY + drm_dma_handle_t *dmah; +#if 1 + unsigned long addr; + size_t sz; +#endif +#ifdef DRM_DEBUG_MEMORY int area = DRM_MEM_DMA; spin_lock(&drm_mem_lock); @@ -74,13 +79,19 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, return NULL; } - address = pci_alloc_consistent(dev->pdev, size, busaddr); + dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL); + if (!dmah) + return NULL; + + dmah->size = size; + dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP); -#if DRM_DEBUG_MEMORY - if (address == NULL) { +#ifdef DRM_DEBUG_MEMORY + if (dmah->vaddr == NULL) { spin_lock(&drm_mem_lock); ++drm_mem_stats[area].fail_count; spin_unlock(&drm_mem_lock); + kfree(dmah); return NULL; } @@ -90,37 +101,59 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, drm_ram_used += size; spin_unlock(&drm_mem_lock); #else - if (address == NULL) + if (dmah->vaddr == NULL) { + kfree(dmah); return NULL; + } #endif - memset(address, 0, size); + memset(dmah->vaddr, 0, size); - return address; + /* XXX - Is virt_to_page() legal for consistent mem? */ + /* Reserve */ + for (addr = (unsigned long)dmah->vaddr, sz = size; + sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { + SetPageReserved(virt_to_page(addr)); + } + + return dmah; } + EXPORT_SYMBOL(drm_pci_alloc); /** - * \brief Free a PCI consistent memory block. + * \brief Free a PCI consistent memory block without freeing its descriptor. + * + * This function is for internal use in the Linux-specific DRM core code. */ -void -drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) +void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) { -#if DRM_DEBUG_MEMORY +#if 1 + unsigned long addr; + size_t sz; +#endif +#ifdef DRM_DEBUG_MEMORY int area = DRM_MEM_DMA; int alloc_count; int free_count; #endif - if (!vaddr) { -#if DRM_DEBUG_MEMORY + if (!dmah->vaddr) { +#ifdef DRM_DEBUG_MEMORY DRM_MEM_ERROR(area, "Attempt to free address 0\n"); #endif } else { - pci_free_consistent(dev->pdev, size, vaddr, busaddr); + /* XXX - Is virt_to_page() legal for consistent mem? */ + /* Unreserve */ + for (addr = (unsigned long)dmah->vaddr, sz = dmah->size; + sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + } + dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr, + dmah->busaddr); } -#if DRM_DEBUG_MEMORY +#ifdef DRM_DEBUG_MEMORY spin_lock(&drm_mem_lock); free_count = ++drm_mem_stats[area].free_count; alloc_count = drm_mem_stats[area].succeed_count; @@ -135,6 +168,16 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) #endif } + +/** + * \brief Free a PCI consistent memory block + */ +void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) +{ + __drm_pci_free(dev, dmah); + kfree(dmah); +} + EXPORT_SYMBOL(drm_pci_free); /*@}*/