aboutsummaryrefslogtreecommitdiff
path: root/sound/core/sgbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/sgbuf.c')
-rw-r--r--sound/core/sgbuf.c36
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);