Messages in this thread Patch in this message | | | Date | Fri, 29 Jun 2012 14:13:10 +0200 | From | Takashi Iwai <> | Subject | Re: [PATCH 0/3] ASoC: Move pcm writecombine dma buffer allocation to core |
| |
At Fri, 29 Jun 2012 15:53:15 +0530, Laxman Dewangan wrote: > > Some of the ARM based soc allocate the writecombine dma buffer for > pcm substreams. They have the same codes for managing this buffer. > Moving this to the core/pcm files so that they can use that directly. > > Remove the code from Tegra PCM and use these new library function. > > This is enabled only for ARM specific and can be extended to other > architecture if they support the writecombine dma buffer. > > This patch is based on detail discussion on patch: > [PATCH] ASoC: snd_dmaengine: add common api for pcm_mmap > And suggestion from Lars and Takashi.
Looking through your patch, I think an easier integration is just to add writecombine option to memalloc.c which calls dma_alloc_writecombine() instead of dma_alloc_coherent().
The addition for mmap is still an open question. Again, an easier option so far looks like just add the call of dma_alloc_writecombine() in snd_pcm_lib_default_mmap(). Alternatively, we can create an individual mmap pcm_ops as we discussed.
Below is a totally untested patch, but you can imagine what I meant.
After this change, replace with snd_pcm_lib_malloc_pages with SNDRV_DMA_TYPE_DEV_WC, and that's all you need in the driver side.
Takashi
--- diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h index c425062..7840340 100644 --- a/include/sound/memalloc.h +++ b/include/sound/memalloc.h @@ -52,6 +52,7 @@ struct snd_dma_device { #else #define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */ #endif +#define SNDRV_DMA_TYPE_DEV_WC 4 /* writecombine pages */ /* * info for buffer allocation diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 6915692..11108e8 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -124,8 +124,12 @@ void snd_free_pages(void *ptr, size_t size) */ #ifdef CONFIG_HAS_DMA -/* allocate the coherent DMA pages */ -static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma) +static void *__snd_malloc_dev_pages(struct device *dev, size_t size, + dma_addr_t *dma, + void *(*func)(struct device *dev, + size_t size, + dma_addr_t *dma_handle, + gfp_t flag)) { int pg; void *res; @@ -138,16 +142,18 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d | __GFP_COMP /* compound page lets parts be mapped */ | __GFP_NORETRY /* don't trigger OOM-killer */ | __GFP_NOWARN; /* no stack trace print - this call is non-critical */ - res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags); + res = func(dev, PAGE_SIZE << pg, dma, gfp_flags); if (res != NULL) inc_snd_pages(pg); return res; } -/* free the coherent DMA pages */ -static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, - dma_addr_t dma) +static void __snd_free_dev_pages(struct device *dev, size_t size, void *ptr, + dma_addr_t dma, + void (*func)(struct device *dev, + size_t size, void *vaddr, + dma_addr_t dma_handle)) { int pg; @@ -155,8 +161,36 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, return; pg = get_order(size); dec_snd_pages(pg); - dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma); + func(dev, PAGE_SIZE << pg, ptr, dma); +} + +/* allocate the coherent DMA pages */ +static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma) +{ + return __snd_malloc_dev_pages(dev, size, dma, dma_alloc_coherent); +} + +/* free the coherent DMA pages */ +static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, + dma_addr_t dma) +{ + __snd_free_dev_pages(dev, ptr, dma, dma_free_coherent); } + +#ifdef CONFIG_ARM +/* allocate the writecombine DMA pages */ +static void *snd_malloc_dev_wc_pages(struct device *dev, size_t size, dma_addr_t *dma) +{ + return __snd_malloc_dev_pages(dev, size, dma, dma_alloc_writecombine); +} + +/* free the writecombine DMA pages */ +static void snd_free_dev_wc_pages(struct device *dev, size_t size, void *ptr, + dma_addr_t dma) +{ + __snd_free_dev_pages(dev, ptr, dma, dma_free_writecombine); +} +#endif /* CONFIG_ARM */ #endif /* CONFIG_HAS_DMA */ /* @@ -200,6 +234,11 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, case SNDRV_DMA_TYPE_DEV: dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); break; +#ifdef CONFIG_ARM + case SNDRV_DMA_TYPE_DEV_WC: + dmab->area = snd_malloc_dev_wc_pages(device, size, &dmab->addr); + break; +#endif #endif #ifdef CONFIG_SND_DMA_SGBUF case SNDRV_DMA_TYPE_DEV_SG: @@ -272,6 +311,11 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) case SNDRV_DMA_TYPE_DEV: snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); break; +#ifdef CONFIG_ARM + case SNDRV_DMA_TYPE_DEV_WC: + snd_free_dev_wc_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); + break; +#endif #endif #ifdef CONFIG_SND_DMA_SGBUF case SNDRV_DMA_TYPE_DEV_SG: @@ -378,7 +422,7 @@ static int snd_mem_proc_read(struct seq_file *seq, void *offset) long pages = snd_allocated_pages >> (PAGE_SHIFT-12); struct snd_mem_list *mem; int devno; - static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" }; + static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "WC" }; mutex_lock(&list_mutex); seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n", diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 53b5ada..c499791 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3170,6 +3170,14 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *area) { area->vm_flags |= VM_RESERVED; +#ifdef CONFIG_ARM + if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_WC) + return dma_mmap_writecombine(substream->dma_buffer.dev.dev, + area, + substream->runtime->dma_area, + substream->runtime->dma_addr, + area->vm_end - area->vm_start); +#endif #ifdef ARCH_HAS_DMA_MMAP_COHERENT if (!substream->ops->page && substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
| |