diff options
Diffstat (limited to 'sound/core/sgbuf.c')
| -rw-r--r-- | sound/core/sgbuf.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index d4564edd61d..0a418503ec4 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -22,6 +22,7 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/vmalloc.h> +#include <linux/export.h> #include <sound/memalloc.h> @@ -38,6 +39,10 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) if (! sgbuf) return -EINVAL; + if (dmab->area) + vunmap(dmab->area); + dmab->area = NULL; + tmpb.dev.type = SNDRV_DMA_TYPE_DEV; tmpb.dev.dev = sgbuf->dev; for (i = 0; i < sgbuf->pages; i++) { @@ -48,9 +53,6 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) tmpb.bytes = (sgbuf->table[i].addr & ~PAGE_MASK) << PAGE_SHIFT; snd_dma_free_pages(&tmpb); } - if (dmab->area) - vunmap(dmab->area); - dmab->area = NULL; kfree(sgbuf->table); kfree(sgbuf->page_table); @@ -100,7 +102,7 @@ void *snd_malloc_sgbuf_pages(struct device *device, if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, device, chunk, &tmpb) < 0) { if (!sgbuf->pages) - return NULL; + goto _failed; if (!res_size) goto _failed; size = sgbuf->pages * PAGE_SIZE; @@ -135,3 +137,29 @@ void *snd_malloc_sgbuf_pages(struct device *device, snd_free_sgbuf_pages(dmab); /* free the table */ return NULL; } + +/* + * compute the max chunk size with continuous pages on sg-buffer + */ +unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, + unsigned int ofs, unsigned int size) +{ + struct snd_sg_buf *sg = dmab->private_data; + unsigned int start, end, pg; + + start = ofs >> PAGE_SHIFT; + end = (ofs + size - 1) >> PAGE_SHIFT; + /* check page continuity */ + pg = sg->table[start].addr >> PAGE_SHIFT; + for (;;) { + start++; + if (start > end) + break; + pg++; + if ((sg->table[start].addr >> PAGE_SHIFT) != pg) + return (start << PAGE_SHIFT) - ofs; + } + /* ok, all on continuous pages */ + return size; +} +EXPORT_SYMBOL(snd_sgbuf_get_chunk_size); |
