From 9804476ca07d30f7771dfc51fe3e2bd22d910817 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 10 Jan 2003 21:41:11 +0000 Subject: [ARM] Fix consistent_alloc() The old consistent memory allocator, which sat behind dma_coherent_alloc() and pci_consistent_alloc() was completely unable to handle allocations from interrupt context because we traditionally used ioremap, which in turn: - allocates memory using GFP_KERNEL for the vm_struct and the page tables themselves. - calls get_vm_area, which uses write_lock, and therefore is unsafe to call from interrupt context. In order to address this issue, a new consistent_alloc() which avoids the above issues has been implemented. Essentially, we set aside a section of the kernel VM space, and pre-allocate page tables to cover this area. We allocate "consistent" memory within this region. The handling of the allocation is designed to be generic; it should be possible to replace the vmalloc(), ioremap() and module_alloc() without too much hastle, but that would clearly be a 2.7 thing at this stage. --- include/asm-arm/dma-mapping.h | 6 +++--- include/asm-arm/pci.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h index dd85f46611e7..e3d1dbb7bebf 100644 --- a/include/asm-arm/dma-mapping.h +++ b/include/asm-arm/dma-mapping.h @@ -14,7 +14,7 @@ * devices. This is the "generic" version. The PCI specific version * is in pci.h */ -extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle); +extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle, unsigned long flags); extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle); extern void consistent_sync(void *kaddr, size_t size, int rw); @@ -84,12 +84,12 @@ static inline int dma_is_consistent(dma_addr_t handle) static inline void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle) { - int gfp = GFP_KERNEL; + int gfp = GFP_ATOMIC; if (dev == NULL || dmadev_is_sa1111(dev) || *dev->dma_mask != 0xffffffff) gfp |= GFP_DMA; - return consistent_alloc(gfp, size, handle); + return consistent_alloc(gfp, size, handle, 0); } /** diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h index 7760592d853f..7c690a057a20 100644 --- a/include/asm-arm/pci.h +++ b/include/asm-arm/pci.h @@ -40,13 +40,13 @@ static inline void pcibios_penalize_isa_irq(int irq) static inline void * pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *handle) { - int gfp = GFP_KERNEL; + int gfp = GFP_ATOMIC; if (hwdev == NULL || pcidev_is_sa1111(hwdev) || hwdev->dma_mask != 0xffffffff) gfp |= GFP_DMA; - return consistent_alloc(gfp, size, handle); + return consistent_alloc(gfp, size, handle, 0); } static inline void -- cgit v1.2.3