--- ../alsa-kernel/core/memalloc.c	2008-02-22 11:44:31.000000000 -0700
+++ memalloc.c	2008-02-22 12:53:46.000000000 -0700
@@ -1,3 +1,4 @@
+#include "memalloc.inc"
 /*
  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
  *                   Takashi Iwai <tiwai@suse.de>
@@ -83,7 +84,50 @@ struct snd_mem_list {
  *  Hacks
  */
 
-#if defined(__i386__)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5)
+static void *snd_dma_alloc_coherent1(struct device *dev, size_t size,
+				     dma_addr_t *dma_handle, int flags)
+{
+	if (dev)
+		return dma_alloc_coherent(dev, size, dma_handle, flags);
+	else /* FIXME: dma_alloc_coherent does't always accept dev=NULL */
+		return pci_alloc_consistent(NULL, size, dma_handle);
+}
+
+static void snd_dma_free_coherent1(struct device *dev, size_t size, void *dma_addr,
+				   dma_addr_t dma_handle)
+{
+	if (dev)
+		return dma_free_coherent(dev, size, dma_addr, dma_handle);
+	else
+		return pci_free_consistent(NULL, size, dma_addr, dma_handle);
+}
+
+#undef dma_alloc_coherent
+#define dma_alloc_coherent snd_dma_alloc_coherent1
+#undef dma_free_coherent
+#define dma_free_coherent snd_dma_free_coherent1
+#endif /* < 2.6.5 */
+
+#else
+
+/* for 2.2/2.4 kernels */
+#if defined(CONFIG_PCI) || defined(CONFIG_ISA) || defined(__i386__)
+#define dma_alloc_coherent(dev,size,addr,flags) pci_alloc_consistent((struct pci_dev *)(dev),size,addr)
+#define dma_free_coherent(dev,size,ptr,addr) pci_free_consistent((struct pci_dev *)(dev),size,ptr,addr)
+#elif CONFIG_SBUS
+#define dma_alloc_coherent(dev,size,addr,flags) sbus_alloc_consistent((struct sbus_dev *)(dev),size,addr)
+#define dma_free_coherent(dev,size,ptr,addr) sbus_free_consistent((struct sbus_dev *)(dev),size,ptr,addr)
+#else
+#error "Need a bus for dma_alloc_coherent()"
+#endif
+
+#endif /* >= 2.6.0 */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+#if defined(__i386__) || defined(__ppc__) || defined(__x86_64__)
+
 /*
  * A hack to allocate large buffers via dma_alloc_coherent()
  *
@@ -100,6 +144,30 @@ struct snd_mem_list {
  * so dma_mask doesn't have to be messed with.
  */
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+#define VALID_DMA_MASK(dev)	(dev)->dma_mask
+#define GET_DMA_MASK(dev)	*(dev)->dma_mask
+#define SET_DMA_MASK(dev,val)	(*(dev)->dma_mask = (val))
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 5)
+#define GET_COHERENT_DMA_MASK(dev)	(dev)->coherent_dma_mask
+#define SET_COHERENT_DMA_MASK(dev,val)	((dev)->coherent_dma_mask = (val))
+#else
+#define GET_COHERENT_DMA_MASK(dev)	0 /* dummy */
+#define SET_COHERENT_DMA_MASK(dev,val)
+#endif
+#else /* 2.4.x */
+#define VALID_DMA_MASK(dev)	1
+#define GET_DMA_MASK(dev)	((struct pci_dev *)(dev))->dma_mask
+#define SET_DMA_MASK(dev,val)	(((struct pci_dev *)(dev))->dma_mask = (val))
+#ifdef CONFIG_HAVE_PCI_CONSISTENT_DMA_MASK
+#define GET_COHERENT_DMA_MASK(dev)	((struct pci_dev *)(dev))->consistent_dma_mask
+#define SET_COHERENT_DMA_MASK(dev,val)	(((struct pci_dev *)(dev))->consistent_dma_mask = (val))
+#else
+#define GET_COHERENT_DMA_MASK(dev)	0 /* dummy */
+#define SET_COHERENT_DMA_MASK(dev,val)
+#endif
+#endif
+
 static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size,
 					 dma_addr_t *dma_handle,
 					 gfp_t flags)
@@ -107,15 +175,15 @@ static void *snd_dma_hack_alloc_coherent
 	void *ret;
 	u64 dma_mask, coherent_dma_mask;
 
-	if (dev == NULL || !dev->dma_mask)
+	if (dev == NULL || !VALID_DMA_MASK(dev))
 		return dma_alloc_coherent(dev, size, dma_handle, flags);
-	dma_mask = *dev->dma_mask;
-	coherent_dma_mask = dev->coherent_dma_mask;
-	*dev->dma_mask = 0xffffffff; 	/* do without masking */
-	dev->coherent_dma_mask = 0xffffffff; 	/* do without masking */
+	dma_mask = GET_DMA_MASK(dev);
+	coherent_dma_mask = GET_COHERENT_DMA_MASK(dev);
+	SET_DMA_MASK(dev, 0xffffffff); 	/* do without masking */
+	SET_COHERENT_DMA_MASK(dev, 0xffffffff); 	/* do without masking */
 	ret = dma_alloc_coherent(dev, size, dma_handle, flags);
-	*dev->dma_mask = dma_mask;	/* restore */
-	dev->coherent_dma_mask = coherent_dma_mask;	/* restore */
+	SET_DMA_MASK(dev, dma_mask);	/* restore */
+	SET_COHERENT_DMA_MASK(dev, coherent_dma_mask)	/* restore */;
 	if (ret) {
 		/* obtained address is out of range? */
 		if (((unsigned long)*dma_handle + size - 1) & ~dma_mask) {
@@ -140,6 +208,8 @@ static void *snd_dma_hack_alloc_coherent
 #define dma_alloc_coherent snd_dma_hack_alloc_coherent
 
 #endif /* arch */
+#endif /* >= 2.4.0 */
+
 
 /*
  *
@@ -159,6 +229,24 @@ static inline void dec_snd_pages(int ord
 	snd_allocated_pages -= 1 << order;
 }
 
+static void mark_pages(struct page *page, int order)
+{
+#if ! defined(__arm__) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+	struct page *last_page = page + (1 << order);
+	while (page < last_page)
+		SetPageReserved(page++);
+#endif
+}
+
+static void unmark_pages(struct page *page, int order)
+{
+#if ! defined(__arm__) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+	struct page *last_page = page + (1 << order);
+	while (page < last_page)
+		ClearPageReserved(page++);
+#endif
+}
+
 /**
  * snd_malloc_pages - allocate pages with the given size
  * @size: the size to allocate in bytes
@@ -177,8 +265,10 @@ void *snd_malloc_pages(size_t size, gfp_
 	snd_assert(gfp_flags != 0, return NULL);
 	gfp_flags |= __GFP_COMP;	/* compound page lets parts be mapped */
 	pg = get_order(size);
-	if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL)
+	if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) {
+		mark_pages(virt_to_page(res), pg);
 		inc_snd_pages(pg);
+	}
 	return res;
 }
 
@@ -197,6 +287,7 @@ void snd_free_pages(void *ptr, size_t si
 		return;
 	pg = get_order(size);
 	dec_snd_pages(pg);
+	unmark_pages(virt_to_page(ptr), pg);
 	free_pages((unsigned long) ptr, pg);
 }
 
@@ -221,8 +312,10 @@ static void *snd_malloc_dev_pages(struct
 		| __GFP_NORETRY /* don't trigger OOM-killer */
 		| __GFP_NOWARN; /* no stack trace print - this call is non-critical */
 	res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
-	if (res != NULL)
+	if (res != NULL) {
+		mark_pages(virt_to_page(res), pg);
 		inc_snd_pages(pg);
+	}
 
 	return res;
 }
@@ -237,6 +330,7 @@ static void snd_free_dev_pages(struct de
 		return;
 	pg = get_order(size);
 	dec_snd_pages(pg);
+	unmark_pages(virt_to_page(ptr), pg);
 	dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
 }
 
@@ -516,6 +610,7 @@ static int snd_mem_proc_open(struct inod
 
 /* FIXME: for pci only - other bus? */
 #ifdef CONFIG_PCI
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
 #define gettoken(bufp) strsep(bufp, " \t\n")
 
 static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer,
@@ -604,6 +699,7 @@ static ssize_t snd_mem_proc_write(struct
 		printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
 	return count;
 }
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) */
 #endif /* CONFIG_PCI */
 
 static const struct file_operations snd_mem_proc_fops = {
@@ -611,8 +707,10 @@ static const struct file_operations snd_
 	.open		= snd_mem_proc_open,
 	.read		= seq_read,
 #ifdef CONFIG_PCI
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
 	.write		= snd_mem_proc_write,
 #endif
+#endif
 	.llseek		= seq_lseek,
 	.release	= single_release,
 };
@@ -658,3 +756,5 @@ EXPORT_SYMBOL(snd_dma_reserve_buf);
 
 EXPORT_SYMBOL(snd_malloc_pages);
 EXPORT_SYMBOL(snd_free_pages);
+
+#include "memalloc.inc1"
