From ec111d70fee0647c4c68a02c723d4a3729c93b56 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 26 Apr 2005 05:19:11 +0000 Subject: Convert BSD code to mostly use bus_dma, the dma abstraction for dealing with IOMMUs and such. There is one usage of the forbidden vtophys() left in drm_scatter.c which will be fixed up soon. This required a KPI change for drm_pci_alloc/free() to return/use a drm_dma_handle_t that keeps track of os-specific bits, rather than just passing around the vaddr/busaddr/size. Submitted by: Tonnerre Lombard (partially) Tested on: FreeBSD: Rage128 AGP/PCI Linux: Savage4 AGP/PCI --- linux-core/drmP.h | 14 +++++++++----- linux-core/drm_bufs.c | 17 +++++++++++------ linux-core/drm_drv.c | 8 ++++++-- linux-core/drm_pci.c | 34 +++++++++++++++++++++------------- linux-core/drm_vm.c | 8 ++++++-- 5 files changed, 53 insertions(+), 28 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drmP.h b/linux-core/drmP.h index cdf7e76f..b7f4640f 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -482,6 +482,12 @@ typedef struct drm_sigdata { drm_hw_lock_t *lock; } drm_sigdata_t; +typedef struct drm_dma_handle { + dma_addr_t busaddr; + void *vaddr; + size_t size; +} drm_dma_handle_t; + /** * Mappings list */ @@ -959,11 +965,9 @@ extern int drm_ati_pcigart_init(drm_device_t * dev, extern int drm_ati_pcigart_cleanup(drm_device_t * dev, unsigned long addr, dma_addr_t bus_addr); -extern void *drm_pci_alloc(drm_device_t * dev, size_t size, - size_t align, dma_addr_t maxaddr, - dma_addr_t * busaddr); -extern void drm_pci_free(drm_device_t * dev, size_t size, - void *vaddr, dma_addr_t busaddr); +extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, + size_t align, dma_addr_t maxaddr); +extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah); /* sysfs support (drm_sysfs.c) */ struct drm_sysfs_class; diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index 6339ac21..5f1336ff 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -130,6 +130,7 @@ int drm_addmap(struct inode *inode, struct file *filp, drm_map_t *map; drm_map_t __user *argp = (void __user *)arg; drm_map_list_t *list; + drm_dma_handle_t *dmah; if (!(filp->f_mode & 3)) return -EACCES; /* Require read/write */ @@ -261,14 +262,13 @@ int drm_addmap(struct inode *inode, struct file *filp, * As we're limiting the address to 2^32-1 (or less), * casting it down to 32 bits is no problem, but we * need to point to a 64bit variable first. */ - dma_addr_t bus_addr; - map->handle = drm_pci_alloc(dev, map->size, map->size, - 0xffffffffUL, &bus_addr); - map->offset = (unsigned long)bus_addr; - if (!map->handle) { + dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL); + if (!dmah) { drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -ENOMEM; } + map->handle = dmah->vaddr; + map->offset = (unsigned long)dmah->busaddr; break; } default: @@ -364,6 +364,8 @@ int drm_rmmap(struct inode *inode, struct file *filp, } if (!found_maps) { + drm_dma_handle_t dmah; + switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: @@ -375,7 +377,10 @@ int drm_rmmap(struct inode *inode, struct file *filp, case _DRM_SCATTER_GATHER: break; case _DRM_CONSISTENT: - drm_pci_free(dev, map->size, map->handle, map->offset); + dmah.vaddr = map->handle; + dmah.busaddr = map->offset; + dmah.size = map->size; + drm_pci_free(dev, &dmah); break; } drm_free(map, sizeof(*map), DRM_MEM_MAPS); diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 42ca3c3b..069ecd3e 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -207,6 +207,8 @@ int drm_takedown(drm_device_t * dev) r_list = (drm_map_list_t *) list; if ((map = r_list->map)) { + drm_dma_handle_t dmah; + switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: @@ -230,8 +232,10 @@ int drm_takedown(drm_device_t * dev) } break; case _DRM_CONSISTENT: - drm_pci_free(dev, map->size, - map->handle, map->offset); + dmah.vaddr = map->handle; + dmah.busaddr = map->offset; + dmah.size = map->size; + drm_pci_free(dev, &dmah); break; } drm_free(map, sizeof(*map), DRM_MEM_MAPS); diff --git a/linux-core/drm_pci.c b/linux-core/drm_pci.c index 30e1ba8d..f8f221cd 100644 --- a/linux-core/drm_pci.c +++ b/linux-core/drm_pci.c @@ -46,10 +46,10 @@ /** * \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; + drm_dma_handle_t *dmah; #if 0 unsigned long addr; size_t sz; @@ -78,13 +78,18 @@ 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->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr); #if DRM_DEBUG_MEMORY - if (address == NULL) { + if (dmah->vaddr == NULL) { spin_lock(&drm_mem_lock); ++drm_mem_stats[area].fail_count; spin_unlock(&drm_mem_lock); + kfree(dmah); return NULL; } @@ -94,22 +99,24 @@ 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); #if 0 /* XXX - Is virt_to_page() legal for consistent mem? */ /* Reserve */ - for (addr = (unsigned long)address, sz = size; + for (addr = (unsigned long)dmah->vaddr, sz = size; sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { SetPageReserved(virt_to_page(addr)); } #endif - return address; + return dmah; } EXPORT_SYMBOL(drm_pci_alloc); @@ -117,7 +124,7 @@ EXPORT_SYMBOL(drm_pci_alloc); * \brief Free a PCI consistent memory block. */ void -drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) +drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah) { #if 0 unsigned long addr; @@ -129,7 +136,7 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) int free_count; #endif - if (!vaddr) { + if (!dmah->vaddr) { #if DRM_DEBUG_MEMORY DRM_MEM_ERROR(area, "Attempt to free address 0\n"); #endif @@ -137,12 +144,13 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) #if 0 /* XXX - Is virt_to_page() legal for consistent mem? */ /* Unreserve */ - for (addr = (unsigned long)vaddr, sz = size; + for (addr = (unsigned long)dmah->vaddr, sz = size; sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); } #endif - pci_free_consistent(dev->pdev, size, vaddr, busaddr); + pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr, + dmah->busaddr); } #if DRM_DEBUG_MEMORY diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 02520c76..bb982b80 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -218,6 +218,8 @@ void drm_vm_shm_close(struct vm_area_struct *vma) } if (!found_maps) { + drm_dma_handle_t dmah; + switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: @@ -237,8 +239,10 @@ void drm_vm_shm_close(struct vm_area_struct *vma) case _DRM_SCATTER_GATHER: break; case _DRM_CONSISTENT: - drm_pci_free(dev, map->size, map->handle, - map->offset); + dmah.vaddr = map->handle; + dmah.busaddr = map->offset; + dmah.size = map->size; + drm_pci_free(dev, &dmah); break; } drm_free(map, sizeof(*map), DRM_MEM_MAPS); -- cgit v1.2.3