* [PATCH] 1/3 Implement generic device DMA mapping support
@ 2004-02-29 22:38 Russell King
2004-02-29 22:42 ` [PATCH] 2/3 " Russell King
2004-03-01 15:41 ` [PATCH] 1/3 " Takashi Iwai
0 siblings, 2 replies; 15+ messages in thread
From: Russell King @ 2004-02-29 22:38 UTC (permalink / raw)
To: Jaroslav Kysela, Alsa Devel list
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.
diff -urpN orig/sound/core/Makefile linux/sound/core/Makefile
--- orig/sound/core/Makefile Wed Feb 18 22:35:45 2004
+++ linux/sound/core/Makefile Sun Feb 29 16:37:15 2004
@@ -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
diff -urpN orig/sound/core/memalloc.c linux/sound/core/memalloc.c
--- orig/sound/core/memalloc.c Wed Feb 18 22:35:45 2004
+++ linux/sound/core/memalloc.c Sun Feb 29 17:32:54 2004
@@ -157,6 +157,9 @@ static int compare_device(const struct s
case SNDRV_DMA_TYPE_SBUS:
return a->dev.sbus == b->dev.sbus;
#endif
+ case SNDRV_DMA_TYPE_DEV:
+ case SNDRV_DMA_TYPE_DEV_SG:
+ return a->dev.dev == b->dev.dev;
}
return 0;
}
@@ -196,7 +199,7 @@ int snd_dma_alloc_pages(const struct snd
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, size, dmab);
+ snd_malloc_sgbuf_pages(&dev->dev.pci->dev, size, dmab);
break;
#endif
#ifdef CONFIG_SBUS
@@ -204,6 +207,12 @@ int snd_dma_alloc_pages(const struct snd
dmab->area = snd_malloc_sbus_pages(dev->dev.sbus, size, &dmab->addr);
break;
#endif
+ case SNDRV_DMA_TYPE_DEV:
+ dmab->area = snd_malloc_dev_pages(dev->dev.dev, size, &dmab->addr);
+ break;
+ case SNDRV_DMA_TYPE_DEV_SG:
+ snd_malloc_sgbuf_pages(dev->dev.dev, size, dmab);
+ break;
default:
printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
dmab->area = NULL;
@@ -248,6 +257,12 @@ void snd_dma_free_pages(const struct snd
snd_free_sbus_pages(dev->dev.sbus, dmab->bytes, dmab->area, dmab->addr);
break;
#endif
+ case SNDRV_DMA_TYPE_DEV:
+ snd_free_dev_pages(dev->dev.dev, dmab->bytes, dmab->area, dmab->addr);
+ break;
+ case SNDRV_DMA_TYPE_DEV_SG:
+ snd_free_sgbuf_pages(dmab);
+ break;
default:
printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
}
@@ -492,6 +507,104 @@ void snd_free_pages(void *ptr, size_t si
free_pages((unsigned long) ptr, pg);
}
+/**
+ * snd_malloc_dev_pages - allocate pages for a device with the given size
+ * @dev: the device pointer
+ * @size: the size to allocate in bytes
+ * @dma: the pointer to store the DMA address of the buffer
+ *
+ * Allocates the physically contiguous pages with the given size for
+ * the device.
+ *
+ * Returns the pointer of the buffer, or NULL if not enough memory.
+ */
+void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
+{
+ int pg;
+ void *res;
+
+ snd_assert(size > 0, return NULL);
+ snd_assert(dma != NULL, return NULL);
+ pg = get_order(size);
+ res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, GFP_KERNEL);
+ if (res != NULL)
+ mark_pages(res, pg);
+
+ return res;
+}
+EXPORT_SYMBOL(snd_malloc_dev_pages);
+
+/**
+ * snd_malloc_dev_page - allocate a page in the valid device dma mask
+ * @dev: device pointer
+ * @addrp: the pointer to store the DMA address of the buffer
+ *
+ * Allocates a single page for the given device and returns
+ * the virtual address and stores the physical address on addrp.
+ *
+ * This function cannot be called from interrupt handlers or
+ * within spinlocks.
+ */
+void *snd_malloc_dev_page(struct device *dev, dma_addr_t *addrp)
+{
+ return snd_malloc_dev_pages(dev, PAGE_SIZE, addrp);
+}
+EXPORT_SYMBOL(snd_malloc_dev_page);
+
+/**
+ * snd_malloc_dev_pages_fallback - allocate pages with the given size with fallback for a device
+ * @dev: device pointer
+ * @size: the requested size to allocate in bytes
+ * @dma: the pointer to store the DMA address of the buffer
+ * @res_size: the pointer to store the size of buffer actually allocated
+ *
+ * Allocates the physically contiguous pages with the given request
+ * size for a device. When no space is left, this function reduces the size
+ * and tries to allocate again. The size actually allocated is stored in
+ * res_size argument.
+ *
+ * Returns the pointer of the buffer, or NULL if no enoguh memory.
+ */
+void *snd_malloc_dev_pages_fallback(struct device *dev, size_t size,
+ dma_addr_t *dma, size_t *res_size)
+{
+ void *res;
+
+ snd_assert(res_size != NULL, return NULL);
+ do {
+ if ((res = snd_malloc_dev_pages(dev, size, dma)) != NULL) {
+ *res_size = size;
+ return res;
+ }
+ size >>= 1;
+ } while (size >= PAGE_SIZE);
+ return NULL;
+}
+EXPORT_SYMBOL(snd_malloc_dev_pages_fallback);
+
+/**
+ * snd_free_dev_pages - release the pages
+ * @dev: device pointer
+ * @size: the allocated buffer size
+ * @ptr: the CPU address of buffer to release
+ * @dma: the DMA address of the buffer
+ *
+ * Releases the buffer allocated via snd_malloc_dev_pages().
+ */
+void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
+ dma_addr_t dma)
+{
+ int pg;
+
+ if (ptr == NULL)
+ return;
+ pg = get_order(size);
+ unmark_pages(ptr, pg);
+ dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
+}
+EXPORT_SYMBOL(snd_free_dev_pages);
+
+
#if defined(CONFIG_ISA) && ! defined(CONFIG_PCI)
/**
@@ -925,6 +1038,14 @@ static int snd_mem_proc_read(char *page,
len += sprintf(page + len, "SBUS [%x]", mem->dev.dev.sbus->slot);
break;
#endif
+ case SNDRV_DMA_TYPE_DEV:
+ case SNDRV_DMA_TYPE_DEV_SG:
+ if (mem->dev.dev.dev) {
+ len += sprintf(page + len, "%s [%s]",
+ mem->dev.type == SNDRV_DMA_TYPE_DEV_SG ? "DEV" : "DEV-SG",
+ mem->dev.dev.dev->bus_id);
+ }
+ break;
default:
len += sprintf(page + len, "UNKNOWN");
break;
diff -urpN orig/sound/core/pcm_lib.c linux/sound/core/pcm_lib.c
--- orig/sound/core/pcm_lib.c Wed Feb 18 22:35:45 2004
+++ linux/sound/core/pcm_lib.c Sun Feb 29 15:48:13 2004
@@ -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);
diff -urpN orig/sound/core/pcm_memory.c linux/sound/core/pcm_memory.c
--- orig/sound/core/pcm_memory.c Sun Feb 29 19:27:59 2004
+++ linux/sound/core/pcm_memory.c Sun Feb 29 19:27:13 2004
@@ -275,6 +275,129 @@ int snd_pcm_lib_preallocate_pages_for_al
return 0;
}
+/**
+ * snd_pcm_lib_preallocate_dev_pages - pre-allocation for a device
+ *
+ * @dev: device
+ * @substream: substream to assign the buffer
+ * @size: the requested pre-allocation size in bytes
+ * @max: max. buffer size acceptable for the changes via proc file
+ *
+ * Do pre-allocation for the device.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_lib_preallocate_dev_pages(struct device *dev,
+ snd_pcm_substream_t *substream,
+ size_t size, size_t max)
+{
+ substream->dma_device.type = SNDRV_DMA_TYPE_DEV;
+ substream->dma_device.dev.dev = dev;
+ setup_pcm_id(substream);
+ return snd_pcm_lib_preallocate_pages1(substream, size, max);
+}
+EXPORT_SYMBOL(snd_pcm_lib_preallocate_dev_pages);
+
+/*
+ * FIXME: the function name is too long for docbook!
+ *
+ * snd_pcm_lib_preallocate_dev_pages_for_all - pre-allocation for a device (all substreams)
+ * @dev: device
+ * @pcm: pcm to assign the buffer
+ * @size: the requested pre-allocation size in bytes
+ * @max: max. buffer size acceptable for the changes via proc file
+ *
+ * Do pre-allocation to all substreams of the given pcm for the
+ * device.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_lib_preallocate_dev_pages_for_all(struct device *dev,
+ 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_dev_pages(dev, substream, size, max)) < 0)
+ return err;
+ return 0;
+}
+EXPORT_SYMBOL(snd_pcm_lib_preallocate_dev_pages_for_all);
+
+/**
+ * snd_pcm_lib_preallocate_dev_sg_pages - initialize SG-buffer for a device
+ *
+ * @dev: device
+ * @substream: substream to assign the buffer
+ * @size: the requested pre-allocation size in bytes
+ * @max: max. buffer size acceptable for the changes via proc file
+ *
+ * Initializes SG-buffer for a device.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_lib_preallocate_dev_sg_pages(struct device *dev,
+ snd_pcm_substream_t *substream,
+ size_t size, size_t max)
+{
+ substream->dma_device.type = SNDRV_DMA_TYPE_DEV_SG;
+ substream->dma_device.dev.dev = dev;
+ setup_pcm_id(substream);
+ return snd_pcm_lib_preallocate_pages1(substream, size, max);
+}
+EXPORT_SYMBOL(snd_pcm_lib_preallocate_dev_sg_pages);
+
+/*
+ * FIXME: the function name is too long for docbook!
+ *
+ * snd_pcm_lib_preallocate_dev_sg_pages_for_all - initialize SG-buffer for a device (all substreams)
+ * @dev: device
+ * @pcm: pcm to assign the buffer
+ * @size: the requested pre-allocation size in bytes
+ * @max: max. buffer size acceptable for the changes via proc file
+ *
+ * Initialize the SG-buffer to all substreams of the given pcm for the
+ * device.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_lib_preallocate_dev_sg_pages_for_all(struct device *dev,
+ 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_dev_sg_pages(dev, substream, size, max)) < 0)
+ return err;
+ return 0;
+}
+EXPORT_SYMBOL(snd_pcm_lib_preallocate_dev_sg_pages_for_all);
+
+/**
+ * snd_pcm_sgbuf_ops_page - get the page struct at the given offset
+ * @substream: the pcm substream instance
+ * @offset: the buffer offset
+ *
+ * Returns the page struct at the given buffer offset.
+ * Used as the page callback of PCM ops.
+ */
+struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset)
+{
+ struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
+
+ unsigned int idx = offset >> PAGE_SHIFT;
+ if (idx >= (unsigned int)sgbuf->pages)
+ return NULL;
+ return sgbuf->page_table[idx];
+}
+EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
+
#ifdef CONFIG_ISA
/**
* snd_pcm_lib_preallocate_isa_pages - pre-allocation for the ISA bus
@@ -555,24 +678,6 @@ int snd_pcm_lib_preallocate_sg_pages_for
return 0;
}
-/**
- * snd_pcm_sgbuf_ops_page - get the page struct at the given offset
- * @substream: the pcm substream instance
- * @offset: the buffer offset
- *
- * Returns the page struct at the given buffer offset.
- * Used as the page callback of PCM ops.
- */
-struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset)
-{
- struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
-
- unsigned int idx = offset >> PAGE_SHIFT;
- if (idx >= (unsigned int)sgbuf->pages)
- return NULL;
- return sgbuf->page_table[idx];
-}
-
#endif /* CONFIG_PCI */
#ifndef MODULE
diff -urpN orig/sound/core/sgbuf.c linux/sound/core/sgbuf.c
--- orig/sound/core/sgbuf.c Sat Jun 14 22:35:05 2003
+++ linux/sound/core/sgbuf.c Sun Feb 29 16:38:53 2004
@@ -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;
diff -urpN orig/include/sound/memalloc.h linux/include/sound/memalloc.h
--- orig/include/sound/memalloc.h Sun Feb 29 20:33:35 2004
+++ linux/include/sound/memalloc.h Sun Feb 29 22:23:20 2004
@@ -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 */
diff -urpN orig/include/sound/pcm.h linux/include/sound/pcm.h
--- orig/include/sound/pcm.h Wed Feb 18 22:35:25 2004
+++ linux/include/sound/pcm.h Sun Feb 29 15:33:19 2004
@@ -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;
--
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 2/3 Implement generic device DMA mapping support
2004-02-29 22:38 [PATCH] 1/3 Implement generic device DMA mapping support Russell King
@ 2004-02-29 22:42 ` Russell King
2004-02-29 22:43 ` [PATCH] 3/3 " Russell King
2004-03-01 15:41 ` [PATCH] 1/3 " Takashi Iwai
1 sibling, 1 reply; 15+ messages in thread
From: Russell King @ 2004-02-29 22:42 UTC (permalink / raw)
To: Jaroslav Kysela, Alsa Devel list
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.
diff -urpN orig/sound/core/memalloc.c linux/sound/core/memalloc.c
--- orig/sound/core/memalloc.c Sun Feb 29 18:32:23 2004
+++ linux/sound/core/memalloc.c Sun Feb 29 18:32:07 2004
@@ -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
--
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 3/3 Implement generic device DMA mapping support
2004-02-29 22:42 ` [PATCH] 2/3 " Russell King
@ 2004-02-29 22:43 ` Russell King
0 siblings, 0 replies; 15+ messages in thread
From: Russell King @ 2004-02-29 22:43 UTC (permalink / raw)
To: Jaroslav Kysela, Alsa Devel list
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.
diff -urpN orig/sound/core/memalloc.c linux/sound/core/memalloc.c
--- orig/sound/core/memalloc.c Sun Feb 29 19:37:15 2004
+++ linux/sound/core/memalloc.c Sun Feb 29 19:39:29 2004
@@ -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);
diff -urpN orig/sound/core/pcm_memory.c linux/sound/core/pcm_memory.c
--- orig/sound/core/pcm_memory.c Sun Feb 29 19:38:37 2004
+++ linux/sound/core/pcm_memory.c Sun Feb 29 19:33:33 2004
@@ -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 */
diff -urpN orig/include/sound/memalloc.h linux/include/sound/memalloc.h
--- orig/include/sound/memalloc.h Sun Feb 29 19:37:12 2004
+++ linux/include/sound/memalloc.h Sun Feb 29 19:41:01 2004
@@ -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
--
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-01 15:41 ` [PATCH] 1/3 " Takashi Iwai
@ 2004-03-01 15:38 ` Jaroslav Kysela
2004-03-01 17:45 ` Russell King
1 sibling, 0 replies; 15+ messages in thread
From: Jaroslav Kysela @ 2004-03-01 15:38 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Russell King, Alsa Devel list
On Mon, 1 Mar 2004, Takashi Iwai wrote:
> 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 <perex@suse.cz>
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-02-29 22:38 [PATCH] 1/3 Implement generic device DMA mapping support Russell King
2004-02-29 22:42 ` [PATCH] 2/3 " Russell King
@ 2004-03-01 15:41 ` Takashi Iwai
2004-03-01 15:38 ` Jaroslav Kysela
2004-03-01 17:45 ` Russell King
1 sibling, 2 replies; 15+ messages in thread
From: Takashi Iwai @ 2004-03-01 15:41 UTC (permalink / raw)
To: Russell King; +Cc: Jaroslav Kysela, Alsa Devel list
Hi,
At Sun, 29 Feb 2004 22:38:20 +0000,
Russell King wrote:
>
> 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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-01 15:41 ` [PATCH] 1/3 " Takashi Iwai
2004-03-01 15:38 ` Jaroslav Kysela
@ 2004-03-01 17:45 ` Russell King
2004-03-01 17:51 ` Takashi Iwai
1 sibling, 1 reply; 15+ messages in thread
From: Russell King @ 2004-03-01 17:45 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Jaroslav Kysela, Alsa Devel list
On Mon, Mar 01, 2004 at 04:41:00PM +0100, Takashi Iwai wrote:
> At Sun, 29 Feb 2004 22:38:20 +0000,
> Russell King wrote:
> >
> > 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 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.
--
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-01 17:45 ` Russell King
@ 2004-03-01 17:51 ` Takashi Iwai
2004-03-01 18:22 ` Russell King
2004-03-02 14:09 ` Takashi Iwai
0 siblings, 2 replies; 15+ messages in thread
From: Takashi Iwai @ 2004-03-01 17:51 UTC (permalink / raw)
To: Russell King; +Cc: Jaroslav Kysela, Alsa Devel list
At Mon, 1 Mar 2004 17:45:17 +0000,
Russell King wrote:
>
> On Mon, Mar 01, 2004 at 04:41:00PM +0100, Takashi Iwai wrote:
> > At Sun, 29 Feb 2004 22:38:20 +0000,
> > Russell King wrote:
> > >
> > > 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 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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-01 17:51 ` Takashi Iwai
@ 2004-03-01 18:22 ` Russell King
2004-03-01 18:34 ` Takashi Iwai
2004-03-02 14:09 ` Takashi Iwai
1 sibling, 1 reply; 15+ messages in thread
From: Russell King @ 2004-03-01 18:22 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Jaroslav Kysela, Alsa Devel list
On Mon, Mar 01, 2004 at 06:51:56PM +0100, Takashi Iwai wrote:
> 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.
--
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-01 18:22 ` Russell King
@ 2004-03-01 18:34 ` Takashi Iwai
2004-03-01 18:44 ` Takashi Iwai
2004-03-02 15:23 ` Takashi Iwai
0 siblings, 2 replies; 15+ messages in thread
From: Takashi Iwai @ 2004-03-01 18:34 UTC (permalink / raw)
To: Russell King; +Cc: Jaroslav Kysela, Alsa Devel list
At Mon, 1 Mar 2004 18:22:24 +0000,
Russell King wrote:
>
> On Mon, Mar 01, 2004 at 06:51:56PM +0100, Takashi Iwai wrote:
> > 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.
> 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!
> 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.
> 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.
> 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.
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-01 18:34 ` Takashi Iwai
@ 2004-03-01 18:44 ` Takashi Iwai
2004-03-02 15:23 ` Takashi Iwai
1 sibling, 0 replies; 15+ messages in thread
From: Takashi Iwai @ 2004-03-01 18:44 UTC (permalink / raw)
To: Russell King; +Cc: Jaroslav Kysela, Alsa Devel list
At Mon, 01 Mar 2004 19:34:57 +0100,
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-01 17:51 ` Takashi Iwai
2004-03-01 18:22 ` Russell King
@ 2004-03-02 14:09 ` Takashi Iwai
2004-03-02 14:26 ` Russell King
1 sibling, 1 reply; 15+ messages in thread
From: Takashi Iwai @ 2004-03-02 14:09 UTC (permalink / raw)
To: Russell King; +Cc: Jaroslav Kysela, Alsa Devel list
At Mon, 01 Mar 2004 18:51:56 +0100,
I wrote:
>
> At Mon, 1 Mar 2004 17:45:17 +0000,
> Russell King wrote:
> >
> > On Mon, Mar 01, 2004 at 04:41:00PM +0100, Takashi Iwai wrote:
> > > At Sun, 29 Feb 2004 22:38:20 +0000,
> > > Russell King wrote:
> > > >
> > > > 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 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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-02 14:09 ` Takashi Iwai
@ 2004-03-02 14:26 ` Russell King
2004-03-02 14:38 ` Takashi Iwai
0 siblings, 1 reply; 15+ messages in thread
From: Russell King @ 2004-03-02 14:26 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Jaroslav Kysela, Alsa Devel list
On Tue, Mar 02, 2004 at 03:09:15PM +0100, Takashi Iwai wrote:
> At Mon, 01 Mar 2004 18:51:56 +0100,
> 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.
--
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-02 14:26 ` Russell King
@ 2004-03-02 14:38 ` Takashi Iwai
2004-03-02 14:55 ` Russell King
0 siblings, 1 reply; 15+ messages in thread
From: Takashi Iwai @ 2004-03-02 14:38 UTC (permalink / raw)
To: Russell King; +Cc: Jaroslav Kysela, Alsa Devel list
[-- Attachment #1: Type: text/plain, Size: 512 bytes --]
At Tue, 2 Mar 2004 14:26:32 +0000,
Russell King wrote:
>
> 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
[-- Attachment #2: Type: text/plain, Size: 3801 bytes --]
--- linux/sound/core/memalloc.c 2004-03-02 15:33:38.628633893 +0100
+++ linux/sound/core/memalloc.c 2004-03-02 15:14:15.000000000 +0100
@@ -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;
}
--- linux/sound/pci/emu10k1/memory.c 15 Jan 2004 16:43:09 -0000 1.11
+++ linux/sound/pci/emu10k1/memory.c 2 Mar 2004 14:14:57 -0000
@@ -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);
--- linux/sound/pci/trident/trident_main.c 24 Feb 2004 11:46:57 -0000 1.48
+++ linux/sound/pci/trident/trident_main.c 2 Mar 2004 14:15:55 -0000
@@ -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);
--- linux/sound/pci/trident/trident_memory.c 10 Mar 2003 13:02:27 -0000 1.9
+++ linux/sound/pci/trident/trident_memory.c 2 Mar 2004 14:16:33 -0000
@@ -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);
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-02 14:38 ` Takashi Iwai
@ 2004-03-02 14:55 ` Russell King
0 siblings, 0 replies; 15+ messages in thread
From: Russell King @ 2004-03-02 14:55 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Jaroslav Kysela, Alsa Devel list
On Tue, Mar 02, 2004 at 03:38:28PM +0100, Takashi Iwai wrote:
> 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.
--
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] 1/3 Implement generic device DMA mapping support
2004-03-01 18:34 ` Takashi Iwai
2004-03-01 18:44 ` Takashi Iwai
@ 2004-03-02 15:23 ` Takashi Iwai
1 sibling, 0 replies; 15+ messages in thread
From: Takashi Iwai @ 2004-03-02 15:23 UTC (permalink / raw)
To: Russell King; +Cc: Jaroslav Kysela, Alsa Devel list
At Mon, 01 Mar 2004 19:34:57 +0100,
I wrote:
>
> At Mon, 1 Mar 2004 18:22:24 +0000,
> Russell King wrote:
> >
> > On Mon, Mar 01, 2004 at 06:51:56PM +0100, Takashi Iwai wrote:
> > > 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.
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
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2004-03-02 15:23 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-29 22:38 [PATCH] 1/3 Implement generic device DMA mapping support Russell King
2004-02-29 22:42 ` [PATCH] 2/3 " Russell King
2004-02-29 22:43 ` [PATCH] 3/3 " Russell King
2004-03-01 15:41 ` [PATCH] 1/3 " Takashi Iwai
2004-03-01 15:38 ` Jaroslav Kysela
2004-03-01 17:45 ` Russell King
2004-03-01 17:51 ` Takashi Iwai
2004-03-01 18:22 ` Russell King
2004-03-01 18:34 ` Takashi Iwai
2004-03-01 18:44 ` Takashi Iwai
2004-03-02 15:23 ` Takashi Iwai
2004-03-02 14:09 ` Takashi Iwai
2004-03-02 14:26 ` Russell King
2004-03-02 14:38 ` Takashi Iwai
2004-03-02 14:55 ` Russell King
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.