This is the first shot at this - I've tested it on ARM, covering both ISA ALSA devices on a PCI machine, and driver model devices on a non- PCI, non-ISA machine. However, it needs more testing. Can people on alsa-devel please test these patches.
Convert PCI-based memory allocators to use the new driver model-based allocators. diff -urpN orig/sound/core/memalloc.c linux/sound/core/memalloc.c --- orig/sound/core/memalloc.c Sun Feb 29 18:32:23 2004 +++ linux/sound/core/memalloc.c Sun Feb 29 18:32:07 2004 @@ -78,9 +78,9 @@ struct snd_mem_list { #define HACK_PCI_ALLOC_CONSISTENT /* - * A hack to allocate large buffers via pci_alloc_consistent() + * A hack to allocate large buffers via dma_alloc_coherent() * - * since pci_alloc_consistent always tries GFP_DMA when the requested + * since dma_alloc_coherent always tries GFP_DMA when the requested * pci memory region is below 32bit, it happens quite often that even * 2 order of pages cannot be allocated. * @@ -88,43 +88,41 @@ struct snd_mem_list { * allocation will be done without GFP_DMA. if the area doesn't match * with the requested region, then realloate with the original dma_mask * again. + * + * Really, we want to move this type of thing into dma_alloc_coherent() + * so dma_mask doesn't have to be messed with. */ -static void *snd_pci_hack_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) +static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle) { void *ret; - u64 dma_mask, cdma_mask; - unsigned long mask; + u64 dma_mask; - if (hwdev == NULL) - return pci_alloc_consistent(hwdev, size, dma_handle); - dma_mask = hwdev->dma_mask; - cdma_mask = hwdev->consistent_dma_mask; - mask = (unsigned long)dma_mask && (unsigned long)cdma_mask; - hwdev->dma_mask = 0xffffffff; /* do without masking */ - hwdev->consistent_dma_mask = 0xffffffff; /* do without masking */ - ret = pci_alloc_consistent(hwdev, size, dma_handle); - hwdev->dma_mask = dma_mask; /* restore */ - hwdev->consistent_dma_mask = cdma_mask; /* restore */ + if (dev == NULL) + return dev_alloc_coherent(dev, size, dma_handle); + dma_mask = dev->dma_mask; + dev->dma_mask = 0xffffffff; /* do without masking */ + ret = dev_alloc_coherent(dev, size, dma_handle, GFP_KERNEL); + dev->dma_mask = dma_mask; /* restore */ if (ret) { /* obtained address is out of range? */ - if (((unsigned long)*dma_handle + size - 1) & ~mask) { + if (((unsigned long)*dma_handle + size - 1) & ~dma_mask) { /* reallocate with the proper mask */ - pci_free_consistent(hwdev, size, ret, *dma_handle); - ret = pci_alloc_consistent(hwdev, size, dma_handle); + dma_free_coherent(dev, size, ret, *dma_handle); + ret = dma_alloc_coherent(dev, size, dma_handle, GFP_KERNEL); } } else { /* wish to success now with the proper mask... */ - if (mask != 0xffffffffUL) - ret = pci_alloc_consistent(hwdev, size, dma_handle); + if (dma_mask != 0xffffffffUL) + ret = dma_alloc_coherent(dev, size, dma_handle, GFP_KERNEL); } return ret; } -/* redefine pci_alloc_consistent for some architectures */ -#undef pci_alloc_consistent -#define pci_alloc_consistent snd_pci_hack_alloc_consistent +/* redefine dma_alloc_coherent for some architectures */ +#undef dma_alloc_coherent +#define dma_alloc_coherent snd_dma_hack_alloc_coherent #endif /* arch */ #endif /* CONFIG_PCI */ @@ -667,17 +665,7 @@ void *snd_malloc_pci_pages(struct pci_de size_t size, dma_addr_t *dma_addr) { - int pg; - void *res; - - snd_assert(size > 0, return NULL); - snd_assert(dma_addr != NULL, return NULL); - for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++); - res = pci_alloc_consistent(pci, PAGE_SIZE * (1 << pg), dma_addr); - if (res != NULL) { - mark_pages(res, pg); - } - return res; + return snd_malloc_dev_pages(pci ? &pci->dev : NULL, size, dma_addr); } /** @@ -699,17 +687,8 @@ void *snd_malloc_pci_pages_fallback(stru dma_addr_t *dma_addr, size_t *res_size) { - void *res; - - snd_assert(res_size != NULL, return NULL); - do { - if ((res = snd_malloc_pci_pages(pci, size, dma_addr)) != NULL) { - *res_size = size; - return res; - } - size >>= 1; - } while (size >= PAGE_SIZE); - return NULL; + return snd_malloc_dev_pages_fallback(pci ? &pci->dev : NULL, size, + dma_addr, res_size); } /** @@ -726,24 +705,10 @@ void snd_free_pci_pages(struct pci_dev * void *ptr, dma_addr_t dma_addr) { - int pg; - - if (ptr == NULL) - return; - for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++); - unmark_pages(ptr, pg); - pci_free_consistent(pci, PAGE_SIZE * (1 << pg), ptr, dma_addr); + snd_free_dev_pages(pci ? &pci->dev : NULL, size, ptr, dma_addr); } -#if defined(__i386__) -/* - * on ix86, we allocate a page with GFP_KERNEL to assure the - * allocation. the code is almost same with kernel/i386/pci-dma.c but - * it allocates only a single page and checks the validity of the - * page address with the given pci dma mask. - */ - /** * snd_malloc_pci_page - allocate a page in the valid pci dma mask * @pci: pci device pointer @@ -757,45 +722,9 @@ void snd_free_pci_pages(struct pci_dev * */ void *snd_malloc_pci_page(struct pci_dev *pci, dma_addr_t *addrp) { - void *ptr; - dma_addr_t addr; - unsigned long mask; - - mask = pci ? (unsigned long)pci->consistent_dma_mask : 0x00ffffffUL; - ptr = (void *)__get_free_page(GFP_KERNEL); - if (ptr) { - addr = virt_to_phys(ptr); - if (((unsigned long)addr + PAGE_SIZE - 1) & ~mask) { - /* try to reallocate with the GFP_DMA */ - free_page((unsigned long)ptr); - /* use GFP_ATOMIC for the DMA zone to avoid stall */ - ptr = (void *)__get_free_page(GFP_ATOMIC | GFP_DMA); - if (ptr) /* ok, the address must be within lower 16MB... */ - addr = virt_to_phys(ptr); - else - addr = 0; - } - } else - addr = 0; - if (ptr) { - memset(ptr, 0, PAGE_SIZE); - mark_pages(ptr, 0); - } - *addrp = addr; - return ptr; -} -#else - -/* on other architectures, call snd_malloc_pci_pages() helper function - * which uses pci_alloc_consistent(). - */ -void *snd_malloc_pci_page(struct pci_dev *pci, dma_addr_t *addrp) -{ return snd_malloc_pci_pages(pci, PAGE_SIZE, addrp); } -#endif - #if 0 /* for kernel-doc */ /** * snd_free_pci_page - release a page -- Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/ 2.6 Serial core ------------------------------------------------------- SF.Net is sponsored by: Speed Start Your Linux Apps Now. Build and deploy apps & Web services for Linux with a free DVD software kit from IBM. Click Now! http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click _______________________________________________ Alsa-devel mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-devel