Skip to contentSkip to conversation

1/3 Implement generic device DMA mapping support

PATCH In review Russell King 3 participants 15 messages Feb 29, 2004 – Mar 2, 2004 Sound

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 1/3 Implement generic device DMA mapping support

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.

This patch adds support for the generic device/driver model to ALSA for the sole purpose of supporting their DMA mapping functionality.

This patch changes snd_malloc_sgbuf_pages() to use this dma mapping functionality.

sound/core/Makefile +1 -4
diff -urpN orig/sound/core/Makefile linux/sound/core/Makefile
@@ -15,10 +15,7 @@ endif
 snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
 		pcm_memory.o
 
-snd-page-alloc-objs := memalloc.o
-ifeq ($(CONFIG_PCI),y)
-snd-page-alloc-objs += sgbuf.o
-endif
+snd-page-alloc-objs := memalloc.o sgbuf.o
 
 snd-rawmidi-objs  := rawmidi.o
 snd-timer-objs    := timer.o
sound/core/memalloc.c +122 -1

159 lines not on this page · raw message

sound/core/pcm_lib.c +0 -1
diff -urpN orig/sound/core/pcm_lib.c linux/sound/core/pcm_lib.c
@@ -2670,7 +2670,6 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pc
 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pci_pages_for_all);
 EXPORT_SYMBOL(snd_pcm_lib_preallocate_sg_pages);
 EXPORT_SYMBOL(snd_pcm_lib_preallocate_sg_pages_for_all);
-EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
 #endif
 #ifdef CONFIG_SBUS
 EXPORT_SYMBOL(snd_pcm_lib_preallocate_sbus_pages);
sound/core/pcm_memory.c +123 -18

153 lines not on this page · raw message

sound/core/sgbuf.c +6 -6
diff -urpN orig/sound/core/sgbuf.c linux/sound/core/sgbuf.c
@@ -33,8 +33,8 @@
 
 
 /**
- * snd_malloc_sgbuf_pages - allocate the pages for the PCI SG buffer
- * @pci: the pci device pointer
+ * snd_malloc_sgbuf_pages - allocate the pages for a device SG buffer
+ * @dev: the device pointer
  * @size: the requested buffer size in bytes
  * @dmab: the buffer record to store
  *
@@ -48,7 +48,7 @@
  * Returns the mapped virtual address of the buffer if allocation was
  * successful, or NULL at error.
  */
-void *snd_malloc_sgbuf_pages(struct pci_dev *pci, size_t size, struct snd_dma_buffer *dmab)
+void *snd_malloc_sgbuf_pages(struct device *dev, size_t size, struct snd_dma_buffer *dmab)
 {
 	struct snd_sg_buf *sgbuf;
 	unsigned int i, pages;
@@ -59,7 +59,7 @@ void *snd_malloc_sgbuf_pages(struct pci_
 	if (! sgbuf)
 		return NULL;
 	memset(sgbuf, 0, sizeof(*sgbuf));
-	sgbuf->pci = pci;
+	sgbuf->dev = dev;
 	pages = snd_sgbuf_aligned_pages(size);
 	sgbuf->tblsize = sgbuf_align_table(pages);
 	sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL);
@@ -75,7 +75,7 @@ void *snd_malloc_sgbuf_pages(struct pci_
 	for (i = 0; i < pages; i++) {
 		void *ptr;
 		dma_addr_t addr;
-		ptr = snd_malloc_pci_page(sgbuf->pci, &addr);
+		ptr = snd_malloc_dev_page(sgbuf->dev, &addr);
 		if (! ptr)
 			goto _failed;
 		sgbuf->table[i].buf = ptr;
@@ -115,7 +115,7 @@ int snd_free_sgbuf_pages(struct snd_dma_
 		return -EINVAL;
 
 	for (i = 0; i < sgbuf->pages; i++)
-		snd_free_pci_page(sgbuf->pci, sgbuf->table[i].buf, sgbuf->table[i].addr);
+		snd_free_dev_page(sgbuf->dev, sgbuf->table[i].buf, sgbuf->table[i].addr);
 	if (dmab->area)
 		vunmap(dmab->area);
 	dmab->area = NULL;
include/sound/memalloc.h +18 -5
diff -urpN orig/include/sound/memalloc.h linux/include/sound/memalloc.h
@@ -29,12 +29,15 @@
 #include <asm/sbus.h>
 #endif
 
+struct device;
+
 /*
  * buffer device info
  */
 struct snd_dma_device {
 	int type;			/* SNDRV_MEM_TYPE_XXX */
 	union {
+		struct device *dev;	/* generic device */
 		struct pci_dev *pci;	/* for PCI and PCI-SG types */
 		unsigned int flags;	/* GFP_XXX for continous and ISA types */
 #ifdef CONFIG_SBUS
@@ -53,6 +56,8 @@ struct snd_dma_device {
 #define SNDRV_DMA_TYPE_PCI		3	/* PCI continuous */
 #define SNDRV_DMA_TYPE_SBUS		4	/* SBUS continuous */
 #define SNDRV_DMA_TYPE_PCI_SG		5	/* PCI SG-buffer */
+#define SNDRV_DMA_TYPE_DEV		6	/* generic device continuous */
+#define SNDRV_DMA_TYPE_DEV_SG		7	/* generic device SG-buffer */
 
 #ifdef CONFIG_PCI
 /*
@@ -99,6 +104,16 @@ void *snd_malloc_pages(size_t size, unsi
 void *snd_malloc_pages_fallback(size_t size, unsigned int gfp_flags, size_t *res_size);
 void snd_free_pages(void *ptr, size_t size);
 
+/*
+ * Generic device continuous pages
+ */
+void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma_addr);
+void *snd_malloc_dev_pages_fallback(struct device *dev, size_t size, dma_addr_t *dma_addr, size_t *res_size);
+void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, dma_addr_t dma_addr);
+/* one page allocation */
+void *snd_malloc_dev_page(struct device *dev, dma_addr_t *dma_addr);
+#define snd_free_dev_page(dev,ptr,addr) snd_free_dev_pages(dev,PAGE_SIZE,ptr,addr)
+
 #ifdef CONFIG_PCI
 /*
  * PCI continuous pages
@@ -136,9 +151,8 @@ void snd_free_isa_pages(size_t size, voi
 #endif /* CONFIG_PCI */
 #endif /* CONFIG_ISA */
 
-#ifdef CONFIG_PCI
 /*
- * Scatter-Gather PCI pages
+ * Scatter-Gather generic device pages
  */
 struct snd_sg_page {
 	void *buf;
@@ -151,10 +165,10 @@ struct snd_sg_buf {
 	int tblsize;	/* allocated table size */
 	struct snd_sg_page *table;	/* address table */
 	struct page **page_table;	/* page table (for vmap/vunmap) */
-	struct pci_dev *pci;
+	struct device *dev;
 };
 
-void *snd_malloc_sgbuf_pages(struct pci_dev *pci, size_t size, struct snd_dma_buffer *dmab);
+void *snd_malloc_sgbuf_pages(struct device *dev, size_t size, struct snd_dma_buffer *dmab);
 int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
 
 /*
@@ -172,6 +186,5 @@ static inline dma_addr_t snd_sgbuf_get_a
 {
 	return sgbuf->table[offset >> PAGE_SHIFT].addr + offset % PAGE_SIZE;
 }
-#endif /* CONFIG_PCI */
 
 #endif /* __SOUND_MEMALLOC_H */
include/sound/pcm.h +18 -4
diff -urpN orig/include/sound/pcm.h linux/include/sound/pcm.h
@@ -932,10 +932,6 @@ int snd_pcm_lib_preallocate_sg_pages(str
 int snd_pcm_lib_preallocate_sg_pages_for_all(struct pci_dev *pci,
 					     snd_pcm_t *pcm,
 					     size_t size, size_t max);
-#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_private)
-#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)
-struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
 #endif
 
 #ifdef CONFIG_SBUS
@@ -948,6 +944,24 @@ int snd_pcm_lib_preallocate_sbus_pages_f
 					       size_t max);
 #endif
 
+int snd_pcm_lib_preallocate_dev_pages(struct device *dev,
+				      snd_pcm_substream_t *substream,
+				      size_t size, size_t max);
+int snd_pcm_lib_preallocate_dev_pages_for_all(struct device *dev,
+					      snd_pcm_t *pcm,
+					      size_t size,
+					      size_t max);
+int snd_pcm_lib_preallocate_dev_sg_pages(struct device *dev,
+					 snd_pcm_substream_t *substream,
+					 size_t size, size_t max);
+int snd_pcm_lib_preallocate_dev_sg_pages_for_all(struct device *dev,
+						 snd_pcm_t *pcm,
+						 size_t size, size_t max);
+#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_private)
+#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)
+struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
+
 static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
 {
 	*max = dma < 4 ? 64 * 1024 : 128 * 1024;
Signature · 11 lines
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
#1 lore raw

Re: [PATCH] 2/3 Implement generic device DMA mapping support

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.

sound/core/memalloc.c +26 -97
diff -urpN orig/sound/core/memalloc.c linux/sound/core/memalloc.c
@@ -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
Signature · 11 lines
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
#2 lore raw

Re: [PATCH] 3/3 Implement generic device DMA mapping support

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 remaining PCI-using functions to use the driver model functions.

sound/core/memalloc.c +0 -32
diff -urpN orig/sound/core/memalloc.c linux/sound/core/memalloc.c
@@ -146,11 +146,6 @@ static int compare_device(const struct s
 	case SNDRV_DMA_TYPE_ISA:
 #endif
 		return a->dev.flags == b->dev.flags;
-#ifdef CONFIG_PCI
-	case SNDRV_DMA_TYPE_PCI:
-	case SNDRV_DMA_TYPE_PCI_SG:
-		return a->dev.pci == b->dev.pci;
-#endif
 #ifdef CONFIG_SBUS
 	case SNDRV_DMA_TYPE_SBUS:
 		return a->dev.sbus == b->dev.sbus;
@@ -192,14 +187,6 @@ int snd_dma_alloc_pages(const struct snd
 		dmab->area = snd_malloc_isa_pages(size, &dmab->addr);
 		break;
 #endif
-#ifdef CONFIG_PCI
-	case SNDRV_DMA_TYPE_PCI:
-		dmab->area = snd_malloc_pci_pages(dev->dev.pci, size, &dmab->addr);
-		break;
-	case SNDRV_DMA_TYPE_PCI_SG:
-		snd_malloc_sgbuf_pages(&dev->dev.pci->dev, size, dmab);
-		break;
-#endif
 #ifdef CONFIG_SBUS
 	case SNDRV_DMA_TYPE_SBUS:
 		dmab->area = snd_malloc_sbus_pages(dev->dev.sbus, size, &dmab->addr);
@@ -242,14 +229,6 @@ void snd_dma_free_pages(const struct snd
 		snd_free_isa_pages(dmab->bytes, dmab->area, dmab->addr);
 		break;
 #endif
-#ifdef CONFIG_PCI
-	case SNDRV_DMA_TYPE_PCI:
-		snd_free_pci_pages(dev->dev.pci, dmab->bytes, dmab->area, dmab->addr);
-		break;
-	case SNDRV_DMA_TYPE_PCI_SG:
-		snd_free_sgbuf_pages(dmab);
-		break;
-#endif
 #ifdef CONFIG_SBUS
 	case SNDRV_DMA_TYPE_SBUS:
 		snd_free_sbus_pages(dev->dev.sbus, dmab->bytes, dmab->area, dmab->addr);
@@ -946,17 +925,6 @@ static int snd_mem_proc_read(char *page,
 		case SNDRV_DMA_TYPE_CONTINUOUS:
 			len += sprintf(page + len, "CONT [%x]", mem->dev.dev.flags);
 			break;
-#ifdef CONFIG_PCI
-		case SNDRV_DMA_TYPE_PCI:
-		case SNDRV_DMA_TYPE_PCI_SG:
-			if (mem->dev.dev.pci) {
-				len += sprintf(page + len, "%s [%04x:%04x]",
-					       mem->dev.type == SNDRV_DMA_TYPE_PCI ? "PCI" : "PCI-SG",
-					       mem->dev.dev.pci->vendor,
-					       mem->dev.dev.pci->device);
-			}
-			break;
-#endif
 #ifdef CONFIG_ISA
 		case SNDRV_DMA_TYPE_ISA:
 			len += sprintf(page + len, "ISA [%x]", mem->dev.dev.flags);
sound/core/pcm_memory.c +8 -24
diff -urpN orig/sound/core/pcm_memory.c linux/sound/core/pcm_memory.c
@@ -538,10 +538,8 @@ int snd_pcm_lib_preallocate_pci_pages(st
 				      snd_pcm_substream_t *substream,
 				      size_t size, size_t max)
 {
-	substream->dma_device.type = SNDRV_DMA_TYPE_PCI;
-	substream->dma_device.dev.pci = pci;
-	setup_pcm_id(substream);
-	return snd_pcm_lib_preallocate_pages1(substream, size, max);
+	return snd_pcm_lib_preallocate_dev_pages(pci ? &pci->dev : NULL,
+						 substream, size, max);
 }
 
 /*
@@ -562,14 +560,8 @@ int snd_pcm_lib_preallocate_pci_pages_fo
 					      snd_pcm_t *pcm,
 					      size_t size, size_t max)
 {
-	snd_pcm_substream_t *substream;
-	int stream, err;
-
-	for (stream = 0; stream < 2; stream++)
-		for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
-			if ((err = snd_pcm_lib_preallocate_pci_pages(pci, substream, size, max)) < 0)
-				return err;
-	return 0;
+	return snd_pcm_lib_preallocate_dev_pages_for_all(pci ? &pci->dev : NULL,
+							 pcm, size, max);
 }
 
 #endif /* CONFIG_PCI */
@@ -644,10 +636,8 @@ int snd_pcm_lib_preallocate_sg_pages(str
 				     snd_pcm_substream_t *substream,
 				     size_t size, size_t max)
 {
-	substream->dma_device.type = SNDRV_DMA_TYPE_PCI_SG;
-	substream->dma_device.dev.pci = pci;
-	setup_pcm_id(substream);
-	return snd_pcm_lib_preallocate_pages1(substream, size, max);
+	return snd_pcm_lib_preallocate_dev_sg_pages(pci ? &pci->dev : NULL,
+						    substream, size, max);
 }
 
 /*
@@ -668,14 +658,8 @@ int snd_pcm_lib_preallocate_sg_pages_for
 					     snd_pcm_t *pcm,
 					     size_t size, size_t max)
 {
-	snd_pcm_substream_t *substream;
-	int stream, err;
-
-	for (stream = 0; stream < 2; stream++)
-		for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
-			if ((err = snd_pcm_lib_preallocate_sg_pages(pci, substream, size, max)) < 0)
-				return err;
-	return 0;
+	return snd_pcm_lib_preallocate_dev_sg_pages_for_all(pci ? &pci->dev : NULL,
+							    pcm, size, max);
 }
 
 #endif /* CONFIG_PCI */
include/sound/memalloc.h +2 -5
diff -urpN orig/include/sound/memalloc.h linux/include/sound/memalloc.h
@@ -38,7 +38,6 @@ struct snd_dma_device {
 	int type;			/* SNDRV_MEM_TYPE_XXX */
 	union {
 		struct device *dev;	/* generic device */
-		struct pci_dev *pci;	/* for PCI and PCI-SG types */
 		unsigned int flags;	/* GFP_XXX for continous and ISA types */
 #ifdef CONFIG_SBUS
 		struct sbus_dev *sbus;	/* for SBUS type */
@@ -53,9 +52,7 @@ 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_ISA		2	/* ISA continuous */
-#define SNDRV_DMA_TYPE_PCI		3	/* PCI continuous */
 #define SNDRV_DMA_TYPE_SBUS		4	/* SBUS continuous */
-#define SNDRV_DMA_TYPE_PCI_SG		5	/* PCI SG-buffer */
 #define SNDRV_DMA_TYPE_DEV		6	/* generic device continuous */
 #define SNDRV_DMA_TYPE_DEV_SG		7	/* generic device SG-buffer */
 
@@ -66,8 +63,8 @@ struct snd_dma_device {
 static inline void snd_dma_device_pci(struct snd_dma_device *dev, struct pci_dev *pci, unsigned int id)
 {
 	memset(dev, 0, sizeof(*dev));
-	dev->type = SNDRV_DMA_TYPE_PCI;
-	dev->dev.pci = pci;
+	dev->type = SNDRV_DMA_TYPE_DEV;
+	dev->dev.dev = &pci->dev;
 	dev->id = id;
 }
 #endif
Signature · 11 lines
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
#3 lore raw
In reply to Russell King

Hi,

At Sun, 29 Feb 2004 22:38:20 +0000,

Quoted 11 lines · Russell King

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.

This patch adds support for the generic device/driver model to ALSA for the sole purpose of supporting their DMA mapping functionality.

This patch changes snd_malloc_sgbuf_pages() to use this dma mapping functionality.

thanks for the patch. using struct device is nice for generalization.

after a short glance, the only drawback i found is that you disabled the single pci page allocation hack for i386. this was needed to cover the non-atomic page allocation.
for example, sb live needs to allocate more than 100MB single pages for the wavetable data. the allocation with GFP_ATOMIC can fail easily in such a case, althogh there is enough memory after swapping. maybe we can leave this function as another...

i also think that we can split pre-allocate stuffs and initialization stuffs to simplify. that is, we provide the initializer

	snd_pcm_lib_set_dma_type(pcm, SND_DMA_PCI, ...);

or somethine like that. and call a single function, snd_pcm_lib_preallocate_buffers_for_all().
having preallocate_*() stuffs for each DMA type is not necessary.

Takashi

-------------------------------------------------------
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

#4 lore raw
Quoted 6 lines · Takashi Iwai

i also think that we can split pre-allocate stuffs and initialization stuffs to simplify. that is, we provide the initializer

	snd_pcm_lib_set_dma_type(pcm, SND_DMA_PCI, ...);

or somethine like that. and call a single function, snd_pcm_lib_preallocate_buffers_for_all().
having preallocate_*() stuffs for each DMA type is not necessary.

We can do this step later.

Jaroslav

-----
Jaroslav Kysela <[email protected]>
Linux Kernel Sound Maintainer
ALSA Project, SuSE Labs

-------------------------------------------------------
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

#5 lore raw
In reply to Takashi Iwai
Quoted 17 lines · Takashi Iwai

At Sun, 29 Feb 2004 22:38:20 +0000,

Quoted 11 lines · Russell King

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.

This patch adds support for the generic device/driver model to ALSA for the sole purpose of supporting their DMA mapping functionality.

This patch changes snd_malloc_sgbuf_pages() to use this dma mapping functionality.

thanks for the patch. using struct device is nice for generalization.

Quoted 7 lines

after a short glance, the only drawback i found is that you disabled the single pci page allocation hack for i386. this was needed to cover the non-atomic page allocation.
for example, sb live needs to allocate more than 100MB single pages for the wavetable data. the allocation with GFP_ATOMIC can fail easily in such a case, althogh there is enough memory after swapping. maybe we can leave this function as another...

I think you've assumed that:

+ res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, GFP_KERNEL);

in snd_malloc_dev_pages() uses GFP_ATOMIC. Please look closer.

Signature · 11 lines
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
#6 lore raw

At Mon, 1 Mar 2004 17:45:17 +0000,

Quoted 27 lines · Russell King
Quoted 17 lines · Takashi Iwai

At Sun, 29 Feb 2004 22:38:20 +0000,

Quoted 11 lines · Russell King

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.

This patch adds support for the generic device/driver model to ALSA for the sole purpose of supporting their DMA mapping functionality.

This patch changes snd_malloc_sgbuf_pages() to use this dma mapping functionality.

thanks for the patch. using struct device is nice for generalization.

Quoted 7 lines

after a short glance, the only drawback i found is that you disabled the single pci page allocation hack for i386. this was needed to cover the non-atomic page allocation.
for example, sb live needs to allocate more than 100MB single pages for the wavetable data. the allocation with GFP_ATOMIC can fail easily in such a case, althogh there is enough memory after swapping. maybe we can leave this function as another...

Quoted 5 lines

I think you've assumed that:

+ res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, GFP_KERNEL);

in snd_malloc_dev_pages() uses GFP_ATOMIC. Please look closer.

ah, yes, then it's fine. thanks.

a small concern about GFP_KERNEL is that i experienced the stall when the kernel tried to allocate large continuous pages with GFP_KERNEL, e.g. modprobe stops infinitely in the module init phase (and you cannot even interrupt that process).

does dma_alloc_coherent(GFP_KERNEL) with big pages work without stall?

Takashi

-------------------------------------------------------
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

#7 lore raw
Quoted 6 lines · Takashi Iwai

a small concern about GFP_KERNEL is that i experienced the stall when the kernel tried to allocate large continuous pages with GFP_KERNEL, e.g. modprobe stops infinitely in the module init phase (and you cannot even interrupt that process).

does dma_alloc_coherent(GFP_KERNEL) with big pages work without stall?

It depends where the stall was coming from. Do you have any further details?

Also, on a similar note, I hope someone noticed one of the comments I added in the second patch:

+ *
+ * Really, we want to move this type of thing into dma_alloc_coherent()
+ * so dma_mask doesn't have to be messed with.

(referring to the hack towards the top of memalloc.c.)

This is something which really needs solving more cleanly. What I think you're trying to do is to allocate pages for devices whose DMA mask indicates (eg) 28 bit addressing is possible, but without the "ISA DMA" (<16MB) restriction? Could you confirm this?

If this is correct, I suspect it may be something which is not limited to sound devices, and as such should probably be covered by the generic code (iow, dma_alloc_coherent.) However, that's going to require discussion with other several people.

Currently, x86 dma_alloc_coherent() is:

        if (dev == NULL || (*dev->dma_mask < 0xffffffff))
                gfp |= GFP_DMA;
        ret = (void *)__get_free_pages(gfp, get_order(size));
 
        if (ret != NULL) {
                memset(ret, 0, size);
                *dma_handle = virt_to_phys(ret);
        }
        return ret;

I'm thinking of something more like:

	order = get_order(size);

	mask = 16*1024*1024-1;
	if (dev)
		mask = dev->dma_mask;

	while (1) {
		ret = (void *)__get_free_pages(gfp, order);

		if (ret == NULL || gfp & GFP_DMA)
			break;

		handle = virt_to_phys(ret);
		if ((handle & ~mask) == 0) {
			memset(ret, 0, size);
			*dma_handle = handle;
			break;
		}

		free_pages((unsigned long)ret, order);
		gfp |= GFP_DMA;
	}

	return ret;

Does that look reasonable? If so, I'll float the idea around x86 people.

Signature · 11 lines
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
#8 lore raw

At Mon, 1 Mar 2004 18:22:24 +0000,

Quoted 11 lines · Russell King
Quoted 6 lines · Takashi Iwai

a small concern about GFP_KERNEL is that i experienced the stall when the kernel tried to allocate large continuous pages with GFP_KERNEL, e.g. modprobe stops infinitely in the module init phase (and you cannot even interrupt that process).

does dma_alloc_coherent(GFP_KERNEL) with big pages work without stall?

It depends where the stall was coming from. Do you have any further details?

first of alll, i have to mention that it happend in the time of 2.4 kernels. i've not tested with 2.6 kernels at all.

a typical case was es1968 driver, which allocates the all buffer pages at the initialization. when __get_free_pages() for 256MB with GFP_KERNEL is called, it goes to sleep and never gets back. since the context is uninterruptible, modprobe stucks and doesn't accept SIGKILL.

anyway, i need to this behavior again with the recent kernel.

Quoted 10 lines

Also, on a similar note, I hope someone noticed one of the comments I added in the second patch:

+ *
+ * Really, we want to move this type of thing into dma_alloc_coherent()
+ * so dma_mask doesn't have to be messed with.

(referring to the hack towards the top of memalloc.c.)

This is something which really needs solving more cleanly.

yep!

Quoted 4 lines

What I
think you're trying to do is to allocate pages for devices whose DMA mask indicates (eg) 28 bit addressing is possible, but without the "ISA DMA" (<16MB) restriction? Could you confirm this?

yes, that's it.

Quoted 4 lines

If this is correct, I suspect it may be something which is not limited to sound devices, and as such should probably be covered by the generic code (iow, dma_alloc_coherent.) However, that's going to require discussion with other several people.

i hope it, too. for example, this kind of large buffer allocation might be needed for video devices, too.

Quoted 39 lines

Currently, x86 dma_alloc_coherent() is:

        if (dev == NULL || (*dev->dma_mask < 0xffffffff))
                gfp |= GFP_DMA;
        ret = (void *)__get_free_pages(gfp, get_order(size));
 
        if (ret != NULL) {
                memset(ret, 0, size);
                *dma_handle = virt_to_phys(ret);
        }
        return ret;

I'm thinking of something more like:

	order = get_order(size);

	mask = 16*1024*1024-1;
	if (dev)
		mask = dev->dma_mask;

	while (1) {
		ret = (void *)__get_free_pages(gfp, order);

		if (ret == NULL || gfp & GFP_DMA)
			break;

		handle = virt_to_phys(ret);
		if ((handle & ~mask) == 0) {
			memset(ret, 0, size);
			*dma_handle = handle;
			break;
		}

		free_pages((unsigned long)ret, order);
		gfp |= GFP_DMA;
	}

	return ret;
Quoted 2 lines

Does that look reasonable? If so, I'll float the idea around x86 people.

yes, it looks fine. thanks!

Takashi

-------------------------------------------------------
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

#9 lore raw

At Mon, 01 Mar 2004 19:34:57 +0100,

Quoted 3 lines · I wrote:

at the initialization. when __get_free_pages() for 256MB with GFP_KERNEL is called, it goes to sleep and never gets back.

additional note: 256MB might be wrong but anyway it was a large number. the driver tries to allocate as large buffers as possible at the initialization.

but, the stall did happen even with much smaller sizes, when the memory pages are fragmented. and, yes, it's logical that it happens :)

anyway, that's why GFP_KERNEL was introduced only for allocation of a single page in the old codes as a hack.

Takashi

-------------------------------------------------------
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

#10 lore raw
In reply to Takashi Iwai

At Mon, 01 Mar 2004 19:34:57 +0100,

Quoted 18 lines · I wrote:

At Mon, 1 Mar 2004 18:22:24 +0000,

Quoted 11 lines · Russell King
Quoted 6 lines · Takashi Iwai

a small concern about GFP_KERNEL is that i experienced the stall when the kernel tried to allocate large continuous pages with GFP_KERNEL, e.g. modprobe stops infinitely in the module init phase (and you cannot even interrupt that process).

does dma_alloc_coherent(GFP_KERNEL) with big pages work without stall?

It depends where the stall was coming from. Do you have any further details?

first of alll, i have to mention that it happend in the time of 2.4 kernels. i've not tested with 2.6 kernels at all.

Quoted 7 lines

a typical case was es1968 driver, which allocates the all buffer pages at the initialization. when __get_free_pages() for 256MB with GFP_KERNEL is called, it goes to sleep and never gets back. since the context is uninterruptible, modprobe stucks and doesn't accept SIGKILL.

anyway, i need to this behavior again with the recent kernel.

ok, i tested the new code now.
it seems working fine without stall even for es1968 driver.

the only problem is the call traces for each allocation like:

	modprobe: page allocation failure. order:8, mode:0xd0
	Call Trace:
	 [<c013939c>] __alloc_pages+0x2ec/0x300
	 [<c0139418>] __get_free_pages+0x18/0x30
	...

i know it's just a warning but surely it's annoying if the caller knows the allocation may fail. it would be nice if we can shut it up.

Takashi

-------------------------------------------------------
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

#11 lore raw
In reply to Takashi Iwai

At Mon, 01 Mar 2004 18:51:56 +0100,

Quoted 30 lines · I wrote:

At Mon, 1 Mar 2004 17:45:17 +0000,

Quoted 27 lines · Russell King
Quoted 24 lines · Takashi Iwai

At Sun, 29 Feb 2004 22:38:20 +0000,

Quoted 11 lines · Russell King

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.

This patch adds support for the generic device/driver model to ALSA for the sole purpose of supporting their DMA mapping functionality.

This patch changes snd_malloc_sgbuf_pages() to use this dma mapping functionality.

thanks for the patch. using struct device is nice for generalization.

after a short glance, the only drawback i found is that you disabled the single pci page allocation hack for i386. this was needed to cover the non-atomic page allocation.
for example, sb live needs to allocate more than 100MB single pages for the wavetable data. the allocation with GFP_ATOMIC can fail easily in such a case, althogh there is enough memory after swapping. maybe we can leave this function as another...

Quoted 7 lines
Quoted 5 lines

I think you've assumed that:

+ res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, GFP_KERNEL);

in snd_malloc_dev_pages() uses GFP_ATOMIC. Please look closer.

ah, yes, then it's fine. thanks.

i was too fast to confirm that -- it turned out that this doesn't help.

since dma_alloc_coherent() is just a wrapper to pci_alloc_consistent() on x86, GFP_KERNEL is ignored. instead, GFP_ATOMIC is used always. sigh...

IOW, the large page allocation problem i described doesn't exist (on x86, at least). only the GFP_KERNEL allocation of single pages is missing.

Takashi

-------------------------------------------------------
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

#12 lore raw
Quoted 10 lines · Takashi Iwai

At Mon, 01 Mar 2004 18:51:56 +0100,

Quoted 1 line · I wrote:

ah, yes, then it's fine. thanks.

i was too fast to confirm that -- it turned out that this doesn't help.

since dma_alloc_coherent() is just a wrapper to pci_alloc_consistent() on x86, GFP_KERNEL is ignored. instead, GFP_ATOMIC is used always. sigh...

include/asm-i386/dma-mapping.h:

void *dma_alloc_coherent(struct device *dev, size_t size,

                           dma_addr_t *dma_handle, int flag);

arch/i386/kernel/pci-dma.c:

void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, int gfp)

{
        void *ret;
        /* ignore region specifiers */
        gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
        if (dev == NULL || (*dev->dma_mask < 0xffffffff))
                gfp |= GFP_DMA;
        ret = (void *)__get_free_pages(gfp, get_order(size));
 
        if (ret != NULL) {
                memset(ret, 0, size);
                *dma_handle = virt_to_phys(ret);
        }
        return ret;
}

I, therefore, suggest that you're not looking at a 2.6.3 kernel. This was changed from pci_alloc_consistent to dma_alloc_coherent on 22 Dec, and was modified to take the GFP flags on 13 Jan.

dma_alloc_coherent() is therefore not a wrapper for pci_alloc_consistent().

However, include/asm-generic/pci-dma-compat.h which is included by include/asm-i386/pci.h contains:

static inline void * pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)

{
        return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC);
}

I'm not sure which kernel are you looking at, because it doesn't seem to match mainline kernels.

Signature · 11 lines
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
#13 lore raw

At Tue, 2 Mar 2004 14:26:32 +0000,

Quoted 6 lines · Russell King

I, therefore, suggest that you're not looking at a 2.6.3 kernel. This was changed from pci_alloc_consistent to dma_alloc_coherent on 22 Dec, and was modified to take the GFP flags on 13 Jan.

dma_alloc_coherent() is therefore not a wrapper for pci_alloc_consistent().

sorry, my bad. forget my last post...

BTW, there are some typos in your patches, and missing replacement of PCI -> DEV dma type. the attached patch should fix.

Takashi

sound/core/memalloc.c +8 -8
@@ -94,28 +94,28 @@
  */
 
 static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size,
-					 dma_addr_t *dma_handle)
+					 dma_addr_t *dma_handle, int gfp_flags)
 {
 	void *ret;
 	u64 dma_mask;
 
 	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 */
+		return dma_alloc_coherent(dev, size, dma_handle, gfp_flags);
+	dma_mask = *dev->dma_mask;
+	*dev->dma_mask = 0xffffffff; /* do without masking */
+	ret = dma_alloc_coherent(dev, size, dma_handle, gfp_flags);
+	*dev->dma_mask = dma_mask; /* restore */
 	if (ret) {
 		/* obtained address is out of range? */
 		if (((unsigned long)*dma_handle + size - 1) & ~dma_mask) {
 			/* reallocate with the proper mask */
 			dma_free_coherent(dev, size, ret, *dma_handle);
-			ret = dma_alloc_coherent(dev, size, dma_handle, GFP_KERNEL);
+			ret = dma_alloc_coherent(dev, size, dma_handle, gfp_flags);
 		}
 	} else {
 		/* wish to success now with the proper mask... */
 		if (dma_mask != 0xffffffffUL)
-			ret = dma_alloc_coherent(dev, size, dma_handle, GFP_KERNEL);
+			ret = dma_alloc_coherent(dev, size, dma_handle, gfp_flags);
 	}
 	return ret;
 }
sound/pci/emu10k1/memory.c +1 -1
@@ -297,7 +297,7 @@
 	int page, err, idx;
 
 	snd_assert(emu, return NULL);
-	snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_PCI_SG, return NULL);
+	snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_DEV_SG, return NULL);
 	snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes < MAXPAGES * EMUPAGESIZE, return NULL);
 	hdr = emu->memhdr;
 	snd_assert(hdr, return NULL);
sound/pci/trident/trident_main.c +1 -1
@@ -1009,7 +1009,7 @@
 	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
 	unsigned int val, ESO_bytes;
 
-	snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_PCI, return -EIO);
+	snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_DEV, return -EIO);
 
 	spin_lock(&trident->reg_lock);
 
sound/pci/trident/trident_memory.c +3 -3
@@ -191,7 +191,7 @@
 	int idx, page;
 	struct snd_sg_buf *sgbuf = runtime->dma_private;
 
-	snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_PCI_SG, return NULL);
+	snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_DEV_SG, return NULL);
 	snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
 	hdr = trident->tlb.memhdr;
 	snd_assert(hdr != NULL, return NULL);
@@ -240,7 +240,7 @@
 	dma_addr_t addr;
 	unsigned long ptr;
 
-	snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_PCI, return NULL);
+	snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_DEV, return NULL);
 	snd_assert(runtime->dma_bytes> 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
 	hdr = trident->tlb.memhdr;
 	snd_assert(hdr != NULL, return NULL);
@@ -276,7 +276,7 @@
 {
 	snd_assert(trident != NULL, return NULL);
 	snd_assert(substream != NULL, return NULL);
-	if (substream->dma_device.type == SNDRV_DMA_TYPE_PCI_SG)
+	if (substream->dma_device.type == SNDRV_DMA_TYPE_DEV_SG)
 		return snd_trident_alloc_sg_pages(trident, substream);
 	else
 		return snd_trident_alloc_cont_pages(trident, substream);
#14 lore raw
Quoted 2 lines · Takashi Iwai

BTW, there are some typos in your patches, and missing replacement of PCI -> DEV dma type. the attached patch should fix.

Thanks for finding these - as you can guess, the code didn't get built for x86 when I tested it, neither was debugging enabled.

Signature · 11 lines
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