linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] ALSA fixes for non-coherent ppc32
@ 2008-06-18 10:38 Takashi Iwai
  2008-06-18 10:40 ` [PATCH 1/3] ppc: Add dma_mmap_coherent() for PPC32 Takashi Iwai
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Takashi Iwai @ 2008-06-18 10:38 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, cjg

Hi,

I've tried to renew the fixes of ALSA issues about non-coherent DMA
memories.  The last patch worked for SG-buffers somehow but would
result in a problem if many pages are allocated because of
dma_alloc_coherent() handling.  Now, I chose a more simpler
workaround: the SG-buffers are handled as simple continuous buffers.

This time I split the patches to several parts.  The first patch
contains a very lazy dma_mmap_coherent() implementation for ppc32.
The next patch adds the call of dma_mmap_coherent() for the default
mmap of ALSA PCM.  And the last one is to add the conversion of
SG-buffer handling as above.

The patches are created against the latest ALSA tree, and the last
patch won't be applicable fully to 2.6.26-rc6.  But, it's only for
snd-hda-intel and there is no PPC32 hardware supporting this, AFAIK.
So just ignore the reject.

The patches are found also on my git tree, dma-fix branch of
    git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git


Any comments and test reports are appreciated, especially about
dma_mmap_coherent() addition.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] ppc: Add dma_mmap_coherent() for PPC32
  2008-06-18 10:38 [PATCH 0/3] ALSA fixes for non-coherent ppc32 Takashi Iwai
@ 2008-06-18 10:40 ` Takashi Iwai
  2008-06-18 10:41 ` [PATCH 2/3] ALSA: Fix mapping of DMA buffers Takashi Iwai
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Takashi Iwai @ 2008-06-18 10:40 UTC (permalink / raw)
  To: benh; +Cc: cjg, linuxppc-dev

A very lazy version of dma_mmap_coherent() implementation for ppc32.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/asm-powerpc/dma-mapping.h |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index bbefb69..a6a9675 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -306,6 +306,24 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
 	/* We don't do anything here. */
 }
 
+/*
+ * A helper to mmap the pages allocated via dma_alloc_coherent()
+ */
+static inline int dma_mmap_coherent(struct device *dev,
+				    struct vm_area_struct *vma,
+				    void *cpu_addr, dma_addr_t handle,
+				    size_t size)
+{
+	struct page *pg;
+#ifdef CONFIG_NOT_COHERENT_CACHE
+	/* I'm too lazy and can't stop using bus_to_virt() here... */
+	cpu_addr = bus_to_virt(handle);
+#endif
+	pg = virt_to_page(cpu_addr);
+	return remap_pfn_range(vma, vma->vm_start,
+			       page_to_pfn(pg) + vma->vm_pgoff,
+			       size, vma->vm_page_prot);
+}
 #endif /* CONFIG_PPC64 */
 
 static inline void dma_sync_single_for_cpu(struct device *dev,
-- 
1.5.4.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] ALSA: Fix mapping of DMA buffers
  2008-06-18 10:38 [PATCH 0/3] ALSA fixes for non-coherent ppc32 Takashi Iwai
  2008-06-18 10:40 ` [PATCH 1/3] ppc: Add dma_mmap_coherent() for PPC32 Takashi Iwai
@ 2008-06-18 10:41 ` Takashi Iwai
  2008-06-18 10:42 ` [PATCH 3/3] ALSA: Fix SG-buffer DMA with non-coherent architectures Takashi Iwai
  2008-07-09  8:31 ` [PATCH 0/3] ALSA fixes for non-coherent ppc32 Gerhard Pircher
  3 siblings, 0 replies; 9+ messages in thread
From: Takashi Iwai @ 2008-06-18 10:41 UTC (permalink / raw)
  To: benh; +Cc: cjg, linuxppc-dev

The DMA buffers allocated via dma_alloc_coherent() aren't easily mmappable
for many architectures.  This is a quick fix for some known archs that
don't work properly with the current code.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/Kconfig      |    7 +++++++
 sound/core/pcm_native.c |   42 ++++++++++++++++++++++++++++--------------
 2 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 335d45e..8e4e644 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -174,3 +174,10 @@ config SND_PCM_XRUN_DEBUG
 
 config SND_VMASTER
 	bool
+
+config SND_COHERENT_DMA
+	def_bool y
+	depends on !PPC32 || !NOT_COHERENT_CACHE
+	depends on !ARM
+	depends on !MIPS
+	depends on !PARISC
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 61f5d42..e21ad2f 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3124,6 +3124,12 @@ static struct vm_operations_struct snd_pcm_vm_ops_data =
 {
 	.open =		snd_pcm_mmap_data_open,
 	.close =	snd_pcm_mmap_data_close,
+};
+
+static struct vm_operations_struct snd_pcm_vm_ops_data_fault =
+{
+	.open =		snd_pcm_mmap_data_open,
+	.close =	snd_pcm_mmap_data_close,
 	.fault =	snd_pcm_mmap_data_fault,
 };
 
@@ -3133,10 +3139,21 @@ static struct vm_operations_struct snd_pcm_vm_ops_data =
 static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
 				struct vm_area_struct *area)
 {
-	area->vm_ops = &snd_pcm_vm_ops_data;
-	area->vm_private_data = substream;
 	area->vm_flags |= VM_RESERVED;
-	atomic_inc(&substream->mmap_count);
+#ifndef CONFIG_SND_COHERENT_DMA
+	if (!substream->ops->page) {
+		switch (substream->dma_buffer.dev.type) {
+		case SNDRV_DMA_TYPE_DEV:
+			return dma_mmap_coherent(substream->dma_buffer.dev.dev,
+						 area,
+						 substream->runtime->dma_area,
+						 substream->runtime->dma_addr,
+						 area->vm_end - area->vm_start);
+		}
+	}
+#endif /* !CONFIG_SND_COHERNT_DMA */
+	/* mmap with fault handler */
+	area->vm_ops = &snd_pcm_vm_ops_data_fault;
 	return 0;
 }
 
@@ -3144,12 +3161,6 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
  * mmap the DMA buffer on I/O memory area
  */
 #if SNDRV_PCM_INFO_MMAP_IOMEM
-static struct vm_operations_struct snd_pcm_vm_ops_data_mmio =
-{
-	.open =		snd_pcm_mmap_data_open,
-	.close =	snd_pcm_mmap_data_close,
-};
-
 int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
 			   struct vm_area_struct *area)
 {
@@ -3159,8 +3170,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
 #ifdef pgprot_noncached
 	area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
 #endif
-	area->vm_ops = &snd_pcm_vm_ops_data_mmio;
-	area->vm_private_data = substream;
 	area->vm_flags |= VM_IO;
 	size = area->vm_end - area->vm_start;
 	offset = area->vm_pgoff << PAGE_SHIFT;
@@ -3168,7 +3177,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
 				(substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
 				size, area->vm_page_prot))
 		return -EAGAIN;
-	atomic_inc(&substream->mmap_count);
 	return 0;
 }
 
@@ -3185,6 +3193,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
 	long size;
 	unsigned long offset;
 	size_t dma_bytes;
+	int err;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		if (!(area->vm_flags & (VM_WRITE|VM_READ)))
@@ -3210,10 +3219,15 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
 	if (offset > dma_bytes - size)
 		return -EINVAL;
 
+	area->vm_ops = &snd_pcm_vm_ops_data;
+	area->vm_private_data = substream;
 	if (substream->ops->mmap)
-		return substream->ops->mmap(substream, area);
+		err = substream->ops->mmap(substream, area);
 	else
-		return snd_pcm_default_mmap(substream, area);
+		err = snd_pcm_default_mmap(substream, area);
+	if (!err)
+		atomic_inc(&substream->mmap_count);
+	return err;
 }
 
 EXPORT_SYMBOL(snd_pcm_mmap_data);
-- 
1.5.4.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] ALSA: Fix SG-buffer DMA with non-coherent architectures
  2008-06-18 10:38 [PATCH 0/3] ALSA fixes for non-coherent ppc32 Takashi Iwai
  2008-06-18 10:40 ` [PATCH 1/3] ppc: Add dma_mmap_coherent() for PPC32 Takashi Iwai
  2008-06-18 10:41 ` [PATCH 2/3] ALSA: Fix mapping of DMA buffers Takashi Iwai
@ 2008-06-18 10:42 ` Takashi Iwai
  2008-07-09  8:31 ` [PATCH 0/3] ALSA fixes for non-coherent ppc32 Gerhard Pircher
  3 siblings, 0 replies; 9+ messages in thread
From: Takashi Iwai @ 2008-06-18 10:42 UTC (permalink / raw)
  To: benh; +Cc: cjg, linuxppc-dev

Using SG-buffers with dma_alloc_coherent() is messy for non-coherent
architectures.  So, simply disable SG-buffers but just allocate normal
continuous buffers instead.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/memalloc.h           |   19 +++++++++++++++
 include/sound/pcm.h                |   44 +++++++++++++++++++++++++++++++++--
 sound/core/Makefile                |    2 +-
 sound/core/memalloc.c              |   12 +++------
 sound/core/pcm_memory.c            |    2 +
 sound/pci/au88x0/au88x0.h          |    7 +----
 sound/pci/au88x0/au88x0_core.c     |   38 ++++++++++++++-----------------
 sound/pci/au88x0/au88x0_pcm.c      |   14 +---------
 sound/pci/bt87x.c                  |    5 ++-
 sound/pci/echoaudio/echoaudio.c    |   14 +++--------
 sound/pci/emu10k1/memory.c         |   12 +--------
 sound/pci/hda/hda_intel.c          |    3 +-
 sound/pci/riptide/riptide.c        |   13 +++++-----
 sound/pci/rme9652/hdspm.c          |   18 ++++++--------
 sound/pci/trident/trident_memory.c |   13 +++-------
 sound/pci/via82xx.c                |    6 ++--
 sound/pci/via82xx_modem.c          |    5 ++-
 17 files changed, 123 insertions(+), 104 deletions(-)

diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index ae2921d..0b2ccfd 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -48,7 +48,11 @@ struct snd_dma_device {
 #define SNDRV_DMA_TYPE_UNKNOWN		0	/* not defined */
 #define SNDRV_DMA_TYPE_CONTINUOUS	1	/* continuous no-DMA memory */
 #define SNDRV_DMA_TYPE_DEV		2	/* generic device continuous */
+#ifdef CONFIG_SND_COHERENT_DMA
 #define SNDRV_DMA_TYPE_DEV_SG		3	/* generic device SG-buffer */
+#else
+#define SNDRV_DMA_TYPE_DEV_SG	SNDRV_DMA_TYPE_DEV /* no SG-buf support */
+#endif
 #define SNDRV_DMA_TYPE_SBUS		4	/* SBUS continuous */
 
 /*
@@ -62,9 +66,15 @@ struct snd_dma_buffer {
 	void *private_data;	/* private for allocator; don't touch */
 };
 
+#ifdef CONFIG_SND_COHERENT_DMA
 /*
  * Scatter-Gather generic device pages
  */
+void *snd_malloc_sgbuf_pages(struct device *device,
+                             size_t size, struct snd_dma_buffer *dmab,
+			     size_t *res_size);
+int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
+
 struct snd_sg_page {
 	void *buf;
 	dma_addr_t addr;
@@ -95,6 +105,15 @@ static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t off
 	return sgbuf->table[offset >> PAGE_SHIFT].addr + offset % PAGE_SIZE;
 }
 
+/*
+ * return the virtual address at the corresponding offset
+ */
+static inline void *snd_sgbuf_get_ptr(struct snd_sg_buf *sgbuf, size_t offset)
+{
+	return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE;
+}
+#endif /* CONFIG_SND_COHERENT_DMA */
+
 
 /* allocate/release a buffer */
 int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 51d58cc..b5af9f7 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -969,11 +969,49 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
 int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream);
 
-#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data)
-#define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size)
-#define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs)
+#ifdef CONFIG_SND_COHERENT_DMA
+/*
+ * SG-buffer handling
+ */
+#define snd_pcm_substream_sgbuf(substream) \
+	((substream)->runtime->dma_buffer_p->private_data)
+
+static inline dma_addr_t
+snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs)
+{
+	struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
+	return snd_sgbuf_get_addr(sg, ofs);
+}
+
+static inline void *
+snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
+{
+	struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
+	return snd_sgbuf_get_ptr(sg, ofs);
+}
+
 struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset);
 
+#else /* !SND_COHERENT_DMA */
+/*
+ * fake using a continuous buffer
+ */
+static inline dma_addr_t
+snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs)
+{
+	return substream->runtime->dma_addr + ofs;
+}
+
+static inline void *
+snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
+{
+	return substream->runtime->dma_area + ofs;
+}
+
+#define snd_pcm_sgbuf_ops_page	NULL
+
+#endif /* SND_COHERENT_DMA */
+
 /* handle mmap counter - PCM mmap callback should handle this counter properly */
 static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
 {
diff --git a/sound/core/Makefile b/sound/core/Makefile
index da8e685..6f83f95 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -12,7 +12,7 @@ snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
 		pcm_memory.o
 
 snd-page-alloc-y := memalloc.o
-snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o
+snd-page-alloc-$(CONFIG_SND_COHERENT_DMA) += sgbuf.o
 
 snd-rawmidi-objs  := rawmidi.o
 snd-timer-objs    := timer.o
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index f5d6d8d..aa0d364 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -46,14 +46,6 @@ MODULE_LICENSE("GPL");
 /*
  */
 
-void *snd_malloc_sgbuf_pages(struct device *device,
-                             size_t size, struct snd_dma_buffer *dmab,
-			     size_t *res_size);
-int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
-
-/*
- */
-
 static DEFINE_MUTEX(list_mutex);
 static LIST_HEAD(mem_list_head);
 
@@ -256,6 +248,8 @@ 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;
+#endif
+#ifdef CONFIG_SND_COHERENT_DMA
 	case SNDRV_DMA_TYPE_DEV_SG:
 		snd_malloc_sgbuf_pages(device, size, dmab, NULL);
 		break;
@@ -329,6 +323,8 @@ 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;
+#endif
+#ifdef CONFIG_SND_COHERENT_DMA
 	case SNDRV_DMA_TYPE_DEV_SG:
 		snd_free_sgbuf_pages(dmab);
 		break;
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index ff07b4a..d3db400 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -306,6 +306,7 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
 
 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
 
+#ifdef CONFIG_SND_COHERENT_DMA
 /**
  * snd_pcm_sgbuf_ops_page - get the page struct at the given offset
  * @substream: the pcm substream instance
@@ -325,6 +326,7 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
 }
 
 EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
+#endif /* CONFIG_SND_COHERENT_DMA */
 
 /**
  * snd_pcm_lib_malloc_pages - allocate the DMA buffer
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index 4aad35b..cf46bba 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -125,7 +125,6 @@ typedef struct {
 	/* Virtual page extender stuff */
 	int nr_periods;
 	int period_bytes;
-	struct snd_sg_buf *sgbuf;	/* DMA Scatter Gather struct */
 	int period_real;
 	int period_virt;
 
@@ -195,16 +194,14 @@ static void vortex_adb_setsrc(vortex_t * vortex, int adbdma,
 
 /* DMA Engines. */
 static void vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma,
-				     struct snd_sg_buf * sgbuf, int size,
-				     int count);
+				     int size, int count);
 static void vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie,
 				  int dir, int fmt, int d,
 				  u32 offset);
 static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb);
 #ifndef CHIP_AU8810
 static void vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma,
-				    struct snd_sg_buf * sgbuf, int size,
-				    int count);
+				    int size, int count);
 static void vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d,	/*int e, */
 				 u32 offset);
 static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb);
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 333c62d..365c044 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -1097,19 +1097,12 @@ static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb)
 
 static void
 vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma,
-			 struct snd_sg_buf * sgbuf, int psize, int count)
+			 int psize, int count)
 {
 	stream_t *dma = &vortex->dma_adb[adbdma];
 
-	if (sgbuf == NULL) {
-		printk(KERN_INFO "vortex: FATAL: sgbuf is NULL!\n");
-		return;
-	}
-	//printk(KERN_INFO "vortex: page count = %d, tblcount = %d\n", count, sgbuf->tblsize);
-
 	dma->period_bytes = psize;
 	dma->nr_periods = count;
-	dma->sgbuf = sgbuf;
 
 	dma->cfg0 = 0;
 	dma->cfg1 = 0;
@@ -1120,26 +1113,26 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma,
 		dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize - 1);
 		hwwrite(vortex->mmio,
 			VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0xc,
-			snd_sgbuf_get_addr(sgbuf, psize * 3));
+			snd_pcm_sgbuf_get_addr(dma->substream, psize * 3));
 		/* 3 pages */
 	case 3:
 		dma->cfg0 |= 0x12000000;
 		dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc);
 		hwwrite(vortex->mmio,
 			VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x8,
-			snd_sgbuf_get_addr(sgbuf, psize * 2));
+			snd_pcm_sgbuf_get_addr(dma->substream, psize * 2));
 		/* 2 pages */
 	case 2:
 		dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize - 1);
 		hwwrite(vortex->mmio,
 			VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x4,
-			snd_sgbuf_get_addr(sgbuf, psize));
+			snd_pcm_sgbuf_get_addr(dma->substream, psize));
 		/* 1 page */
 	case 1:
 		dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc);
 		hwwrite(vortex->mmio,
 			VORTEX_ADBDMA_BUFBASE + (adbdma << 4),
-			snd_sgbuf_get_addr(sgbuf, 0));
+			snd_pcm_sgbuf_get_addr(dma->substream, 0));
 		break;
 	}
 	//printk("vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", dma->cfg0, dma->cfg1);
@@ -1205,7 +1198,7 @@ static int vortex_adbdma_bufshift(vortex_t * vortex, int adbdma)
 			//hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), dma->table[p].addr);
 			hwwrite(vortex->mmio,
 				VORTEX_ADBDMA_BUFBASE + (((adbdma << 2) + pp) << 2),
-				snd_sgbuf_get_addr(dma->sgbuf,
+				snd_pcm_sgbuf_get_addr(dma->substream,
 				dma->period_bytes * p));
 			/* Force write thru cache. */
 			hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE +
@@ -1244,7 +1237,10 @@ static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma) {
 			if (pp >= 4)
 				pp -= 4;
 		}
-		hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), snd_sgbuf_get_addr(dma->sgbuf, dma->period_bytes * p));
+		hwwrite(vortex->mmio,
+			VORTEX_ADBDMA_BUFBASE + (((adbdma << 2) + pp) << 2),
+			snd_pcm_sgbuf_get_addr(dma->substream,
+					       dma->period_bytes * p));
 		/* Force write thru cache. */
 		hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (((adbdma << 2)+pp) << 2));
 	}
@@ -1367,13 +1363,12 @@ static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb)
 
 static void
 vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma,
-			struct snd_sg_buf * sgbuf, int psize, int count)
+			int psize, int count)
 {
 	stream_t *dma = &vortex->dma_wt[wtdma];
 
 	dma->period_bytes = psize;
 	dma->nr_periods = count;
-	dma->sgbuf = sgbuf;
 
 	dma->cfg0 = 0;
 	dma->cfg1 = 0;
@@ -1383,23 +1378,23 @@ vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma,
 	case 4:
 		dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize-1);
 		hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0xc,
-			snd_sgbuf_get_addr(sgbuf, psize * 3));
+			snd_pcm_sgbuf_get_addr(dma->substream, psize * 3));
 		/* 3 pages */
 	case 3:
 		dma->cfg0 |= 0x12000000;
 		dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc);
 		hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4)  + 0x8,
-			snd_sgbuf_get_addr(sgbuf, psize * 2));
+			snd_pcm_sgbuf_get_addr(dma->substream, psize * 2));
 		/* 2 pages */
 	case 2:
 		dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize-1);
 		hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x4,
-			snd_sgbuf_get_addr(sgbuf, psize));
+			snd_pcm_sgbuf_get_addr(dma->substream, psize));
 		/* 1 page */
 	case 1:
 		dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc);
 		hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4),
-			snd_sgbuf_get_addr(sgbuf, 0));
+			snd_pcm_sgbuf_get_addr(dma->substream, 0));
 		break;
 	}
 	hwwrite(vortex->mmio, VORTEX_WTDMA_BUFCFG0 + (wtdma << 3), dma->cfg0);
@@ -1465,7 +1460,8 @@ static int vortex_wtdma_bufshift(vortex_t * vortex, int wtdma)
 			hwwrite(vortex->mmio,
 				VORTEX_WTDMA_BUFBASE +
 				(((wtdma << 2) + pp) << 2),
-				snd_sgbuf_get_addr(dma->sgbuf, dma->period_bytes * p));
+				snd_pcm_sgbuf_get_addr(dma->substream,
+						       dma->period_bytes * p));
 			/* Force write thru cache. */
 			hwread(vortex->mmio, VORTEX_WTDMA_BUFBASE +
 			       (((wtdma << 2) + pp) << 2));
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index f9a58b4..b9d2f20 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -189,7 +189,6 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
 {
 	vortex_t *chip = snd_pcm_substream_chip(substream);
 	stream_t *stream = (stream_t *) (substream->runtime->private_data);
-	struct snd_sg_buf *sgbuf;
 	int err;
 
 	// Alloc buffer memory.
@@ -199,8 +198,6 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
 		printk(KERN_ERR "Vortex: pcm page alloc failed!\n");
 		return err;
 	}
-	//sgbuf = (struct snd_sg_buf *) substream->runtime->dma_private;
-	sgbuf = snd_pcm_substream_sgbuf(substream);
 	/*
 	   printk(KERN_INFO "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params),
 	   params_period_bytes(hw_params), params_channels(hw_params));
@@ -226,7 +223,7 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
 		stream = substream->runtime->private_data = &chip->dma_adb[dma];
 		stream->substream = substream;
 		/* Setup Buffers. */
-		vortex_adbdma_setbuffers(chip, dma, sgbuf,
+		vortex_adbdma_setbuffers(chip, dma,
 					 params_period_bytes(hw_params),
 					 params_periods(hw_params));
 	}
@@ -240,7 +237,7 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
 		    &chip->dma_wt[substream->number];
 		stream->dma = substream->number;
 		stream->substream = substream;
-		vortex_wtdma_setbuffers(chip, substream->number, sgbuf,
+		vortex_wtdma_setbuffers(chip, substream->number,
 					params_period_bytes(hw_params),
 					params_periods(hw_params));
 	}
@@ -392,13 +389,6 @@ static snd_pcm_uframes_t snd_vortex_pcm_pointer(struct snd_pcm_substream *substr
 	return (bytes_to_frames(substream->runtime, current_ptr));
 }
 
-/* Page callback. */
-/*
-static struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset) {
-	
-	
-}
-*/
 /* operators */
 static struct snd_pcm_ops snd_vortex_playback_ops = {
 	.open = snd_vortex_pcm_open,
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 4ecdd63..3aa8d97 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -227,7 +227,6 @@ static inline void snd_bt87x_writel(struct snd_bt87x *chip, u32 reg, u32 value)
 static int snd_bt87x_create_risc(struct snd_bt87x *chip, struct snd_pcm_substream *substream,
 			       	 unsigned int periods, unsigned int period_bytes)
 {
-	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 	unsigned int i, offset;
 	u32 *risc;
 
@@ -246,6 +245,7 @@ static int snd_bt87x_create_risc(struct snd_bt87x *chip, struct snd_pcm_substrea
 		rest = period_bytes;
 		do {
 			u32 cmd, len;
+			unsigned int addr;
 
 			len = PAGE_SIZE - (offset % PAGE_SIZE);
 			if (len > rest)
@@ -260,7 +260,8 @@ static int snd_bt87x_create_risc(struct snd_bt87x *chip, struct snd_pcm_substrea
 			if (len == rest)
 				cmd |= RISC_EOL | RISC_IRQ;
 			*risc++ = cpu_to_le32(cmd);
-			*risc++ = cpu_to_le32((u32)snd_pcm_sgbuf_get_addr(sgbuf, offset));
+			addr = snd_pcm_sgbuf_get_addr(substream, offset);
+			*risc++ = cpu_to_le32(addr);
 			offset += len;
 			rest -= len;
 		} while (rest > 0);
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index e16dc92..08e8a88 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -490,7 +490,6 @@ static int init_engine(struct snd_pcm_substream *substream,
 {
 	struct echoaudio *chip;
 	int err, per, rest, page, edge, offs;
-	struct snd_sg_buf *sgbuf;
 	struct audiopipe *pipe;
 
 	chip = snd_pcm_substream_chip(substream);
@@ -531,10 +530,6 @@ static int init_engine(struct snd_pcm_substream *substream,
 		return err;
 	}
 
-	sgbuf = snd_pcm_substream_sgbuf(substream);
-
-	DE_HWP(("pcm_hw_params table size=%d pages=%d\n",
-		sgbuf->size, sgbuf->pages));
 	sglist_init(chip, pipe);
 	edge = PAGE_SIZE;
 	for (offs = page = per = 0; offs < params_buffer_bytes(hw_params);
@@ -543,16 +538,15 @@ static int init_engine(struct snd_pcm_substream *substream,
 		if (offs + rest > params_buffer_bytes(hw_params))
 			rest = params_buffer_bytes(hw_params) - offs;
 		while (rest) {
+			dma_addr_t addr;
+			addr = snd_pcm_sgbuf_get_addr(substream, offs);
 			if (rest <= edge - offs) {
-				sglist_add_mapping(chip, pipe,
-						   snd_sgbuf_get_addr(sgbuf, offs),
-						   rest);
+				sglist_add_mapping(chip, pipe, addr, rest);
 				sglist_add_irq(chip, pipe);
 				offs += rest;
 				rest = 0;
 			} else {
-				sglist_add_mapping(chip, pipe,
-						   snd_sgbuf_get_addr(sgbuf, offs),
+				sglist_add_mapping(chip, pipe, addr,
 						   edge - offs);
 				rest -= edge - offs;
 				offs = edge;
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index 7d379f5..4983e35 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -295,7 +295,6 @@ struct snd_util_memblk *
 snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 	struct snd_util_memhdr *hdr;
 	struct snd_emu10k1_memblk *blk;
 	int page, err, idx;
@@ -316,16 +315,9 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst
 	 */
 	idx = 0;
 	for (page = blk->first_page; page <= blk->last_page; page++, idx++) {
+		unsigned long ofs = idx << PAGE_SHIFT;
 		dma_addr_t addr;
-#ifdef CONFIG_SND_DEBUG
-		if (idx >= sgbuf->pages) {
-			printk(KERN_ERR "emu: pages overflow! (%d-%d) for %d\n",
-			       blk->first_page, blk->last_page, sgbuf->pages);
-			mutex_unlock(&hdr->block_mutex);
-			return NULL;
-		}
-#endif
-		addr = sgbuf->table[idx].addr;
+		addr = snd_pcm_sgbuf_get_addr(substream, ofs);
 		if (! is_valid_page(emu, addr)) {
 			printk(KERN_ERR "emu: failure page = %d\n", idx);
 			mutex_unlock(&hdr->block_mutex);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 16715a6..cc5c639 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -988,7 +988,6 @@ static int setup_bdle(struct snd_pcm_substream *substream,
 		      struct azx_dev *azx_dev, u32 **bdlp,
 		      int ofs, int size, int with_ioc)
 {
-	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 	u32 *bdl = *bdlp;
 
 	while (size > 0) {
@@ -998,7 +997,7 @@ static int setup_bdle(struct snd_pcm_substream *substream,
 		if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES)
 			return -EINVAL;
 
-		addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
+		addr = snd_pcm_sgbuf_get_addr(substream, ofs);
 		/* program the address field of the BDL entry */
 		bdl[0] = cpu_to_le32((u32)addr);
 		bdl[1] = cpu_to_le32(upper_32_bits(addr));
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 979f7da..c6b1cb8 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1482,7 +1482,6 @@ static int snd_riptide_prepare(struct snd_pcm_substream *substream)
 {
 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 	struct pcmhw *data = get_pcmhwdev(substream);
 	struct cmdif *cif = chip->cif;
 	unsigned char *lbuspath = NULL;
@@ -1513,9 +1512,9 @@ static int snd_riptide_prepare(struct snd_pcm_substream *substream)
 			lbuspath = data->paths.stereo;
 		break;
 	}
-	snd_printdd("use sgdlist at 0x%p and buffer at 0x%p\n",
-		    data->sgdlist.area, sgbuf);
-	if (data->sgdlist.area && sgbuf) {
+	snd_printdd("use sgdlist at 0x%p\n",
+		    data->sgdlist.area);
+	if (data->sgdlist.area) {
 		unsigned int i, j, size, pages, f, pt, period;
 		struct sgd *c, *p = NULL;
 
@@ -1533,6 +1532,7 @@ static int snd_riptide_prepare(struct snd_pcm_substream *substream)
 		pt = 0;
 		j = 0;
 		for (i = 0; i < pages; i++) {
+			unsigned int ofs, addr;
 			c = &data->sgdbuf[i];
 			if (p)
 				p->dwNextLink = cpu_to_le32(data->sgdlist.addr +
@@ -1540,8 +1540,9 @@ static int snd_riptide_prepare(struct snd_pcm_substream *substream)
 							     sizeof(struct
 								    sgd)));
 			c->dwNextLink = cpu_to_le32(data->sgdlist.addr);
-			c->dwSegPtrPhys =
-			    cpu_to_le32(sgbuf->table[j].addr + pt);
+			ofs = j << PAGE_SHIFT;
+			addr = snd_pcm_sgbuf_get_addr(substream, ofs) + pt;
+			c->dwSegPtrPhys = cpu_to_le32(addr);
 			pt = (pt + f) % PAGE_SIZE;
 			if (pt == 0)
 				j++;
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index ab423bc..a149829 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -535,7 +535,8 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm);
 static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm);
 static int hdspm_autosync_ref(struct hdspm * hdspm);
 static int snd_hdspm_set_defaults(struct hdspm * hdspm);
-static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
+static void hdspm_set_sgbuf(struct hdspm * hdspm,
+			    struct snd_pcm_substream *substream,
 			     unsigned int reg, int channels);
 
 static inline int HDSPM_bit2freq(int n)
@@ -3601,8 +3602,6 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 	int i;
 	pid_t this_pid;
 	pid_t other_pid;
-	struct snd_sg_buf *sgbuf;
-
 
 	spin_lock_irq(&hdspm->lock);
 
@@ -3670,11 +3669,9 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 	if (err < 0)
 		return err;
 
-	sgbuf = snd_pcm_substream_sgbuf(substream);
-
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 
-		hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut,
+		hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
 				params_channels(params));
 
 		for (i = 0; i < params_channels(params); ++i)
@@ -3685,7 +3682,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 		snd_printdd("Allocated sample buffer for playback at %p\n",
 				hdspm->playback_buffer);
 	} else {
-		hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
+		hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
 				params_channels(params));
 
 		for (i = 0; i < params_channels(params); ++i)
@@ -3700,7 +3697,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 	   snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
 	   substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
 	   "playback" : "capture",
-	   snd_pcm_sgbuf_get_addr(sgbuf, 0));
+	   snd_pcm_sgbuf_get_addr(substream, 0));
 	 */
 	/*
 	snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
@@ -4249,13 +4246,14 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
 	return 0;
 }
 
-static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
+static void hdspm_set_sgbuf(struct hdspm * hdspm,
+			    struct snd_pcm_substream *substream,
 			     unsigned int reg, int channels)
 {
 	int i;
 	for (i = 0; i < (channels * 16); i++)
 		hdspm_write(hdspm, reg + 4 * i,
-			    snd_pcm_sgbuf_get_addr(sgbuf, (size_t) 4096 * i));
+			    snd_pcm_sgbuf_get_addr(substream, 4096 * i));
 }
 
 /* ------------- ALSA Devices ---------------------------- */
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index 3fd7f1b..6dcb8c5 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -194,7 +194,6 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident,
 	struct snd_util_memblk *blk;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int idx, page;
-	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 
 	snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
 	hdr = trident->tlb.memhdr;
@@ -208,18 +207,14 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident,
 		mutex_unlock(&hdr->block_mutex);
 		return NULL;
 	}
-	if (lastpg(blk) - firstpg(blk) >= sgbuf->pages) {
-		snd_printk(KERN_ERR "page calculation doesn't match: allocated pages = %d, trident = %d/%d\n", sgbuf->pages, firstpg(blk), lastpg(blk));
-		__snd_util_mem_free(hdr, blk);
-		mutex_unlock(&hdr->block_mutex);
-		return NULL;
-	}
 			   
 	/* set TLB entries */
 	idx = 0;
 	for (page = firstpg(blk); page <= lastpg(blk); page++, idx++) {
-		dma_addr_t addr = sgbuf->table[idx].addr;
-		unsigned long ptr = (unsigned long)sgbuf->table[idx].buf;
+		unsigned long ofs = idx << PAGE_SHIFT;
+		dma_addr_t addr = snd_pcm_sgbuf_get_addr(substream, ofs);
+		unsigned long ptr = (unsigned long)
+			snd_pcm_sgbuf_get_ptr(substream, ofs);
 		if (! is_valid_page(addr)) {
 			__snd_util_mem_free(hdr, blk);
 			mutex_unlock(&hdr->block_mutex);
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index b585cc3..f4d988e 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -420,7 +420,6 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
 {
 	unsigned int i, idx, ofs, rest;
 	struct via82xx *chip = snd_pcm_substream_chip(substream);
-	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 
 	if (dev->table.area == NULL) {
 		/* the start of each lists must be aligned to 8 bytes,
@@ -449,13 +448,14 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
 		do {
 			unsigned int r;
 			unsigned int flag;
+			unsigned int addr;
 
 			if (idx >= VIA_TABLE_SIZE) {
 				snd_printk(KERN_ERR "via82xx: too much table size!\n");
 				return -EINVAL;
 			}
-			((u32 *)dev->table.area)[idx << 1] = cpu_to_le32((u32)snd_pcm_sgbuf_get_addr(sgbuf, ofs));
-			r = PAGE_SIZE - (ofs % PAGE_SIZE);
+			addr = snd_pcm_sgbuf_get_addr(substream, ofs);
+			((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr);
 			if (rest < r)
 				r = rest;
 			rest -= r;
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 31f64ee..73a4d0c 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -281,7 +281,6 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
 {
 	unsigned int i, idx, ofs, rest;
 	struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
-	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 
 	if (dev->table.area == NULL) {
 		/* the start of each lists must be aligned to 8 bytes,
@@ -310,12 +309,14 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
 		do {
 			unsigned int r;
 			unsigned int flag;
+			unsigned int addr;
 
 			if (idx >= VIA_TABLE_SIZE) {
 				snd_printk(KERN_ERR "via82xx: too much table size!\n");
 				return -EINVAL;
 			}
-			((u32 *)dev->table.area)[idx << 1] = cpu_to_le32((u32)snd_pcm_sgbuf_get_addr(sgbuf, ofs));
+			addr = snd_pcm_sgbuf_get_addr(substream, ofs);
+			((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr);
 			r = PAGE_SIZE - (ofs % PAGE_SIZE);
 			if (rest < r)
 				r = rest;
-- 
1.5.4.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/3] ALSA fixes for non-coherent ppc32
  2008-06-18 10:38 [PATCH 0/3] ALSA fixes for non-coherent ppc32 Takashi Iwai
                   ` (2 preceding siblings ...)
  2008-06-18 10:42 ` [PATCH 3/3] ALSA: Fix SG-buffer DMA with non-coherent architectures Takashi Iwai
@ 2008-07-09  8:31 ` Gerhard Pircher
  2008-07-09  8:55   ` Benjamin Herrenschmidt
  2008-07-09 17:27   ` Takashi Iwai
  3 siblings, 2 replies; 9+ messages in thread
From: Gerhard Pircher @ 2008-07-09  8:31 UTC (permalink / raw)
  To: Takashi Iwai, benh; +Cc: linuxppc-dev

Hi,

-------- Original-Nachricht --------
> Datum: Wed, 18 Jun 2008 12:38:31 +0200
> Von: Takashi Iwai <tiwai@suse.de>
> An: benh@kernel.crashing.org
> CC: linuxppc-dev@ozlabs.org, cjg@cruxppc.org
> Betreff: [PATCH 0/3] ALSA fixes for non-coherent ppc32

> Hi,
> 
> I've tried to renew the fixes of ALSA issues about non-coherent DMA
> memories.  The last patch worked for SG-buffers somehow but would
> result in a problem if many pages are allocated because of
> dma_alloc_coherent() handling.  Now, I chose a more simpler
> workaround: the SG-buffers are handled as simple continuous buffers.
> 
> This time I split the patches to several parts.  The first patch
> contains a very lazy dma_mmap_coherent() implementation for ppc32.
> The next patch adds the call of dma_mmap_coherent() for the default
> mmap of ALSA PCM.  And the last one is to add the conversion of
> SG-buffer handling as above.
> 
> The patches are created against the latest ALSA tree, and the last
> patch won't be applicable fully to 2.6.26-rc6.  But, it's only for
> snd-hda-intel and there is no PPC32 hardware supporting this, AFAIK.
> So just ignore the reject.
> 
> The patches are found also on my git tree, dma-fix branch of
>     git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
> 
> Any comments and test reports are appreciated, especially about
> dma_mmap_coherent() addition.
I know this answer comes a little bit late, but my PPC machine was not
working for two weeks due to a hardware failure. I tested the patch on
2.6.26-rc9 and it seems to work fine so far with my emu10k soundcard.
I just had to add "#include <linux/dma-mapping.h>" to pcm_native.c.
Otherwise it wouldn't compile.

Thanks!

regards,

Gerhard

-- 
Psssst! Schon das coole Video vom GMX MultiMessenger gesehen?
Der Eine für Alle: http://www.gmx.net/de/go/messenger03

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/3] ALSA fixes for non-coherent ppc32
  2008-07-09  8:31 ` [PATCH 0/3] ALSA fixes for non-coherent ppc32 Gerhard Pircher
@ 2008-07-09  8:55   ` Benjamin Herrenschmidt
  2008-07-09 17:31     ` Takashi Iwai
  2008-07-09 17:27   ` Takashi Iwai
  1 sibling, 1 reply; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2008-07-09  8:55 UTC (permalink / raw)
  To: Gerhard Pircher; +Cc: Takashi Iwai, linuxppc-dev

On Wed, 2008-07-09 at 10:31 +0200, Gerhard Pircher wrote:
> > 
> > The patches are found also on my git tree, dma-fix branch of
> >
> git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
> > 
> > Any comments and test reports are appreciated, especially about
> > dma_mmap_coherent() addition.
> I know this answer comes a little bit late, but my PPC machine was not
> working for two weeks due to a hardware failure. I tested the patch on
> 2.6.26-rc9 and it seems to work fine so far with my emu10k soundcard.
> I just had to add "#include <linux/dma-mapping.h>" to pcm_native.c.
> Otherwise it wouldn't compile.

Can I get the latest powerpc-side patches so I can review-ack them in
time for the merge window ?

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/3] ALSA fixes for non-coherent ppc32
  2008-07-09  8:31 ` [PATCH 0/3] ALSA fixes for non-coherent ppc32 Gerhard Pircher
  2008-07-09  8:55   ` Benjamin Herrenschmidt
@ 2008-07-09 17:27   ` Takashi Iwai
  1 sibling, 0 replies; 9+ messages in thread
From: Takashi Iwai @ 2008-07-09 17:27 UTC (permalink / raw)
  To: Gerhard Pircher; +Cc: linuxppc-dev

At Wed, 09 Jul 2008 10:31:11 +0200,
Gerhard Pircher wrote:
> 
> Hi,
> 
> -------- Original-Nachricht --------
> > Datum: Wed, 18 Jun 2008 12:38:31 +0200
> > Von: Takashi Iwai <tiwai@suse.de>
> > An: benh@kernel.crashing.org
> > CC: linuxppc-dev@ozlabs.org, cjg@cruxppc.org
> > Betreff: [PATCH 0/3] ALSA fixes for non-coherent ppc32
> 
> > Hi,
> > 
> > I've tried to renew the fixes of ALSA issues about non-coherent DMA
> > memories.  The last patch worked for SG-buffers somehow but would
> > result in a problem if many pages are allocated because of
> > dma_alloc_coherent() handling.  Now, I chose a more simpler
> > workaround: the SG-buffers are handled as simple continuous buffers.
> > 
> > This time I split the patches to several parts.  The first patch
> > contains a very lazy dma_mmap_coherent() implementation for ppc32.
> > The next patch adds the call of dma_mmap_coherent() for the default
> > mmap of ALSA PCM.  And the last one is to add the conversion of
> > SG-buffer handling as above.
> > 
> > The patches are created against the latest ALSA tree, and the last
> > patch won't be applicable fully to 2.6.26-rc6.  But, it's only for
> > snd-hda-intel and there is no PPC32 hardware supporting this, AFAIK.
> > So just ignore the reject.
> > 
> > The patches are found also on my git tree, dma-fix branch of
> >     git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
> > 
> > Any comments and test reports are appreciated, especially about
> > dma_mmap_coherent() addition.
> I know this answer comes a little bit late, but my PPC machine was not
> working for two weeks due to a hardware failure. I tested the patch on
> 2.6.26-rc9 and it seems to work fine so far with my emu10k soundcard.
> I just had to add "#include <linux/dma-mapping.h>" to pcm_native.c.
> Otherwise it wouldn't compile.

Thanks, I fixed it now on my git tree.


Takashi

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/3] ALSA fixes for non-coherent ppc32
  2008-07-09  8:55   ` Benjamin Herrenschmidt
@ 2008-07-09 17:31     ` Takashi Iwai
  2008-07-09 20:06       ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 9+ messages in thread
From: Takashi Iwai @ 2008-07-09 17:31 UTC (permalink / raw)
  To: benh, Gerhard Pircher; +Cc: linuxppc-dev

At Wed, 09 Jul 2008 18:55:35 +1000,
Benjamin Herrenschmidt wrote:
> 
> On Wed, 2008-07-09 at 10:31 +0200, Gerhard Pircher wrote:
> > > 
> > > The patches are found also on my git tree, dma-fix branch of
> > >
> > git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
> > > 
> > > Any comments and test reports are appreciated, especially about
> > > dma_mmap_coherent() addition.
> > I know this answer comes a little bit late, but my PPC machine was not
> > working for two weeks due to a hardware failure. I tested the patch on
> > 2.6.26-rc9 and it seems to work fine so far with my emu10k soundcard.
> > I just had to add "#include <linux/dma-mapping.h>" to pcm_native.c.
> > Otherwise it wouldn't compile.
> 
> Can I get the latest powerpc-side patches so I can review-ack them in
> time for the merge window ?

The changes in ppc are only the patch below.  The others are in
sound/*.  I wrote it as an inline function simply it's so short and I
didn't want extra exports.


thanks,

Takashi

---
commit 2c8662fde57af4cf928d17e089dc3dd2096f4b30
Author: Takashi Iwai <tiwai@suse.de>
Date:   Tue Jun 17 16:39:04 2008 +0200

    ppc: Add dma_mmap_coherent() for PPC32
    
    A very lazy version of dma_mmap_coherent() implementation for ppc32.
    
    Signed-off-by: Takashi Iwai <tiwai@suse.de>

diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index bbefb69..a6a9675 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -306,6 +306,24 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
 	/* We don't do anything here. */
 }
 
+/*
+ * A helper to mmap the pages allocated via dma_alloc_coherent()
+ */
+static inline int dma_mmap_coherent(struct device *dev,
+				    struct vm_area_struct *vma,
+				    void *cpu_addr, dma_addr_t handle,
+				    size_t size)
+{
+	struct page *pg;
+#ifdef CONFIG_NOT_COHERENT_CACHE
+	/* I'm too lazy and can't stop using bus_to_virt() here... */
+	cpu_addr = bus_to_virt(handle);
+#endif
+	pg = virt_to_page(cpu_addr);
+	return remap_pfn_range(vma, vma->vm_start,
+			       page_to_pfn(pg) + vma->vm_pgoff,
+			       size, vma->vm_page_prot);
+}
 #endif /* CONFIG_PPC64 */
 
 static inline void dma_sync_single_for_cpu(struct device *dev,

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/3] ALSA fixes for non-coherent ppc32
  2008-07-09 17:31     ` Takashi Iwai
@ 2008-07-09 20:06       ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2008-07-09 20:06 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev


> The changes in ppc are only the patch below.  The others are in
> sound/*.  I wrote it as an inline function simply it's so short and I
> didn't want extra exports.

Thanks. I -may- do something nicer, we'll see, but in any case, I'll
try to have something in .27

Cheers,
Ben.

> 
> thanks,
> 
> Takashi
> 
> ---
> commit 2c8662fde57af4cf928d17e089dc3dd2096f4b30
> Author: Takashi Iwai <tiwai@suse.de>
> Date:   Tue Jun 17 16:39:04 2008 +0200
> 
>     ppc: Add dma_mmap_coherent() for PPC32
>     
>     A very lazy version of dma_mmap_coherent() implementation for ppc32.
>     
>     Signed-off-by: Takashi Iwai <tiwai@suse.de>
> 
> diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
> index bbefb69..a6a9675 100644
> --- a/include/asm-powerpc/dma-mapping.h
> +++ b/include/asm-powerpc/dma-mapping.h
> @@ -306,6 +306,24 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
>  	/* We don't do anything here. */
>  }
>  
> +/*
> + * A helper to mmap the pages allocated via dma_alloc_coherent()
> + */
> +static inline int dma_mmap_coherent(struct device *dev,
> +				    struct vm_area_struct *vma,
> +				    void *cpu_addr, dma_addr_t handle,
> +				    size_t size)
> +{
> +	struct page *pg;
> +#ifdef CONFIG_NOT_COHERENT_CACHE
> +	/* I'm too lazy and can't stop using bus_to_virt() here... */
> +	cpu_addr = bus_to_virt(handle);
> +#endif
> +	pg = virt_to_page(cpu_addr);
> +	return remap_pfn_range(vma, vma->vm_start,
> +			       page_to_pfn(pg) + vma->vm_pgoff,
> +			       size, vma->vm_page_prot);
> +}
>  #endif /* CONFIG_PPC64 */
>  
>  static inline void dma_sync_single_for_cpu(struct device *dev,

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2008-07-09 20:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-18 10:38 [PATCH 0/3] ALSA fixes for non-coherent ppc32 Takashi Iwai
2008-06-18 10:40 ` [PATCH 1/3] ppc: Add dma_mmap_coherent() for PPC32 Takashi Iwai
2008-06-18 10:41 ` [PATCH 2/3] ALSA: Fix mapping of DMA buffers Takashi Iwai
2008-06-18 10:42 ` [PATCH 3/3] ALSA: Fix SG-buffer DMA with non-coherent architectures Takashi Iwai
2008-07-09  8:31 ` [PATCH 0/3] ALSA fixes for non-coherent ppc32 Gerhard Pircher
2008-07-09  8:55   ` Benjamin Herrenschmidt
2008-07-09 17:31     ` Takashi Iwai
2008-07-09 20:06       ` Benjamin Herrenschmidt
2008-07-09 17:27   ` Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).