Update of /cvsroot/alsa/alsa-kernel/core
In directory sc8-pr-cvs1:/tmp/cvs-serv30086/core
Modified Files:
Makefile init.c memory.c pcm.c pcm_lib.c pcm_memory.c sound.c
wrappers.c
Added Files:
memalloc.c memory_wrapper.c sgbuf.c
Removed Files:
pcm_sgbuf.c
Log Message:
more unified DMA allocation
- memory allocator is put into a separte independent module, snd-alloc-pages.
it can be kept after other snd* modules unloaded, so that the big
continuous pages can be held after reload.
- use size_t for the size type.
--- NEW FILE: memalloc.c ---
/*
* Copyright (c) by Jaroslav Kysela <[EMAIL PROTECTED]>
* Takashi Iwai <[EMAIL PROTECTED]>
*
* Generic memory allocators
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/semaphore.h>
#include <sound/memalloc.h>
MODULE_AUTHOR("Takashi Iwai <[EMAIL PROTECTED]>, Jaroslav Kysela <[EMAIL PROTECTED]>");
MODULE_DESCRIPTION("Memory allocator for ALSA system.");
MODULE_LICENSE("GPL");
/*
*/
static DECLARE_MUTEX(list_mutex);
static LIST_HEAD(mem_list_head);
/* buffer preservation list */
struct snd_mem_list {
struct snd_dma_device dev;
struct snd_dma_buffer buffer;
int used;
struct list_head list;
};
#ifdef CONFIG_SND_DEBUG
#define __ASTRING__(x) #x
#define snd_assert(expr, args...) do {\
if (!(expr)) {\
printk(KERN_ERR "snd-malloc: BUG? (%s) (called from %p)\n",
__ASTRING__(expr), __builtin_return_address(0));\
args;\
}\
} while (0)
#else
#define snd_assert(expr, args...) /**/
#endif
/* redefine pci_alloc_consistent for some architectures */
#ifdef HACK_PCI_ALLOC_CONSISTENT
#undef pci_alloc_consistent
#define pci_alloc_consistent snd_pci_hack_alloc_consistent
#endif
/*
* compare the two devices
* returns non-zero if matched.
*/
static int compare_device(const struct snd_dma_device *a, const struct snd_dma_device
*b)
{
if (a->type != b->type)
return 0;
if (a->id != b->id)
return 0;
switch (a->type) {
case SNDRV_DMA_TYPE_CONTINUOUS:
#ifdef CONFIG_ISA
case SNDRV_DMA_TYPE_ISA:
#endif
return a->dev.flags == b->dev.flags;
#ifdef CONFIG_PCI
case SNDRV_DMA_TYPE_PCI:
return a->dev.pci == b->dev.pci;
#endif
#ifdef CONFIG_SBUS
case SNDRV_DMA_TYPE_SBUS:
return a->dev.sbus == b->dev.sbus;
#endif
}
return 0;
}
/**
* snd_dma_alloc_pages - allocate the buffer area according to the given type
* @dev: the buffer device info
* @size: the buffer size to allocate
* @dmab: buffer allocation record to store the allocated data
*
* Calls the memory-allocator function for the corresponding
* buffer type.
*
* Returns zero if the buffer with the given size is allocated successfuly,
* other a negative value at error.
*/
int snd_dma_alloc_pages(const struct snd_dma_device *dev, size_t size,
struct snd_dma_buffer *dmab)
{
snd_assert(dev != NULL, return -ENXIO);
snd_assert(size > 0, return -ENXIO);
snd_assert(dmab != NULL, return -ENXIO);
dmab->bytes = 0;
switch (dev->type) {
case SNDRV_DMA_TYPE_CONTINUOUS:
dmab->area = snd_malloc_pages(size, dev->dev.flags);
dmab->addr = 0;
break;
#ifdef CONFIG_ISA
case SNDRV_DMA_TYPE_ISA:
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, size, dmab);
break;
#endif
#ifdef CONFIG_SBUS
case SNDRV_DMA_TYPE_SBUS:
dmab->area = snd_malloc_pci_pages(dev->dev.sbus, size, &dmab->addr);
break;
#endif
default:
printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
dmab->area = NULL;
dmab->addr = 0;
return -ENXIO;
}
if (dmab->area)
dmab->bytes = size;
return 0;
}
/**
* snd_dma_free_pages - release the allocated buffer
* @dev: the buffer device info
* @dmbab: the buffer allocation record to release
*
* Releases the allocated buffer via snd_dma_alloc_pages().
*/
void snd_dma_free_pages(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab)
{
switch (dev->type) {
case SNDRV_DMA_TYPE_CONTINUOUS:
snd_free_pages(dmab->area, dmab->bytes);
break;
#ifdef CONFIG_ISA
case SNDRV_DMA_TYPE_ISA:
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->size, dmab->are, dmab->addr);
break;
#endif
default:
printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
}
}
/*
* search for the device
*/
static struct snd_mem_list *mem_list_find(const struct snd_dma_device *dev)
{
struct list_head *p;
struct snd_mem_list *mem;
list_for_each(p, &mem_list_head) {
mem = list_entry(p, struct snd_mem_list, list);
if (compare_device(&mem->dev, dev))
return mem;
}
return NULL;
}
/**
* snd_dma_get_reserved - get the reserved buffer for the given device
* @dev: the buffer device info
* @dmab: the buffer allocation record to store
*
* Looks for the reserved-buffer list and re-uses if the same buffer
* is found in the list. When the buffer is found, it's marked as used.
* For unmarking the buffer, call snd_dma_free_reserved().
*
* Returns the size of buffer if the buffer is found, or zero if not found.
*/
size_t snd_dma_get_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer
*dmab)
{
struct snd_mem_list *mem;
snd_assert(dev && dmab, return 0);
down(&list_mutex);
mem = mem_list_find(dev);
if (mem) {
mem->used = 1;
*dmab = mem->buffer;
up(&list_mutex);
return dmab->bytes;
}
up(&list_mutex);
return 0;
}
/**
* snd_dma_free_reserved - unmark the reserved buffer
* @dev: the buffer device info
*
* Looks for the matching reserved buffer and erases the mark on it
* if found.
*
* Returns zero.
*/
int snd_dma_free_reserved(const struct snd_dma_device *dev)
{
struct snd_mem_list *mem;
snd_assert(dev, return -EINVAL);
down(&list_mutex);
mem = mem_list_find(dev);
if (mem)
mem->used = 0;
up(&list_mutex);
return 0;
}
/**
* snd_dma_set_reserved - reserve the buffer
* @dev: the buffer device info
* @dmab: the buffer to reserve
*
* Reserves the given buffer as a reserved buffer.
* When an old reserved buffer already exists, the old one is released
* and replaced with the new one.
*
* When NULL buffer pointer or zero buffer size is given, the existing
* release buffer is released and the entry is removed.
*
* Returns zero if successful, or a negative code at error.
*/
int snd_dma_set_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab)
{
struct snd_mem_list *mem;
snd_assert(dev, return -EINVAL);
down(&list_mutex);
mem = mem_list_find(dev);
if (mem) {
snd_dma_free_pages(dev, &mem->buffer);
if (! dmab || ! dmab->bytes) {
/* remove the entry */
list_del(&mem->list);
kfree(mem);
up(&list_mutex);
return 0;
}
} else {
if (! dmab || ! dmab->bytes) {
up(&list_mutex);
return 0;
}
mem = kmalloc(sizeof(*mem), GFP_KERNEL);
mem->dev = *dev;
list_add(&mem->list, &mem_list_head);
}
/* store the entry */
mem->used = 1;
mem->buffer = *dmab;
up(&list_mutex);
return 0;
}
/*
* purge all reserved buffers
*/
static void free_all_reserved_pages(void)
{
struct list_head *p;
struct snd_mem_list *mem;
down(&list_mutex);
while (! list_empty(&mem_list_head)) {
p = mem_list_head.next;
mem = list_entry(p, struct snd_mem_list, list);
list_del(p);
snd_dma_free_pages(&mem->dev, &mem->buffer);
kfree(mem);
}
up(&list_mutex);
}
/*
*
* Generic memory allocators
*
*/
static long snd_allocated_pages; /* holding the number of allocated pages */
static void mark_pages(void *res, int order)
{
struct page *page = virt_to_page(res);
struct page *last_page = page + (1 << order);
while (page < last_page)
SetPageReserved(page++);
snd_allocated_pages += 1 << order;
}
static void unmark_pages(void *res, int order)
{
struct page *page = virt_to_page(res);
struct page *last_page = page + (1 << order);
while (page < last_page)
ClearPageReserved(page++);
snd_allocated_pages -= 1 << order;
}
/**
* snd_malloc_pages - allocate pages with the given size
* @size: the size to allocate in bytes
* @gfp_flags: the allocation conditions, GFP_XXX
*
* Allocates the physically contiguous pages with the given size.
*
* Returns the pointer of the buffer, or NULL if no enoguh memory.
*/
void *snd_malloc_pages(size_t size, unsigned int gfp_flags)
{
int pg;
void *res;
snd_assert(size > 0, return NULL);
snd_assert(gfp_flags != 0, return NULL);
for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) {
mark_pages(res, pg);
}
return res;
}
/**
* snd_malloc_pages_fallback - allocate pages with the given size with fallback
* @size: the requested size to allocate in bytes
* @gfp_flags: the allocation conditions, GFP_XXX
* @res_size: the pointer to store the size of buffer actually allocated
*
* Allocates the physically contiguous pages with the given request
* size. 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_pages_fallback(size_t size, unsigned int gfp_flags, size_t *res_size)
{
void *res;
snd_assert(size > 0, return NULL);
snd_assert(res_size != NULL, return NULL);
do {
if ((res = snd_malloc_pages(size, gfp_flags)) != NULL) {
*res_size = size;
return res;
}
size >>= 1;
} while (size >= PAGE_SIZE);
return NULL;
}
/**
* snd_free_pages - release the pages
* @ptr: the buffer pointer to release
* @size: the allocated buffer size
*
* Releases the buffer allocated via snd_malloc_pages().
*/
void snd_free_pages(void *ptr, size_t size)
{
int pg;
if (ptr == NULL)
return;
for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
unmark_pages(ptr, pg);
free_pages((unsigned long) ptr, pg);
}
#if defined(CONFIG_ISA) && ! defined(CONFIG_PCI)
/**
* snd_malloc_isa_pages - allocate pages for ISA bus with the given size
* @size: the size to allocate in bytes
* @dma_addr: the pointer to store the physical address of the buffer
*
* Allocates the physically contiguous pages with the given size for
* ISA bus.
*
* Returns the pointer of the buffer, or NULL if no enoguh memory.
*/
void *snd_malloc_isa_pages(size_t size, dma_addr_t *dma_addr)
{
void *dma_area;
dma_area = snd_malloc_pages(size, GFP_ATOMIC|GFP_DMA);
*dma_addr = dma_area ? isa_virt_to_bus(dma_area) : 0UL;
return dma_area;
}
/**
* snd_malloc_isa_pages_fallback - allocate pages with the given size with fallback
for ISA bus
* @size: the requested size to allocate in bytes
* @dma_addr: the pointer to store the physical 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 PCI bus. 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_isa_pages_fallback(size_t size,
dma_addr_t *dma_addr,
size_t *res_size)
{
void *dma_area;
dma_area = snd_malloc_pages_fallback(size, GFP_ATOMIC|GFP_DMA, res_size);
*dma_addr = dma_area ? isa_virt_to_bus(dma_area) : 0UL;
return dma_area;
}
#endif /* CONFIG_ISA && !CONFIG_PCI */
#ifdef CONFIG_PCI
/**
* snd_malloc_pci_pages - allocate pages for PCI bus with the given size
* @pci: the pci device pointer
* @size: the size to allocate in bytes
* @dma_addr: the pointer to store the physical address of the buffer
*
* Allocates the physically contiguous pages with the given size for
* PCI bus.
*
* Returns the pointer of the buffer, or NULL if no enoguh memory.
*/
void *snd_malloc_pci_pages(struct pci_dev *pci,
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;
}
/**
* snd_malloc_pci_pages_fallback - allocate pages with the given size with fallback
for PCI bus
* @pci: pci device pointer
* @size: the requested size to allocate in bytes
* @dma_addr: the pointer to store the physical 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 PCI bus. 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_pci_pages_fallback(struct pci_dev *pci,
size_t size,
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;
}
/**
* snd_free_pci_pages - release the pages
* @pci: pci device pointer
* @size: the allocated buffer size
* @ptr: the buffer pointer to release
* @dma_addr: the physical address of the buffer
*
* Releases the buffer allocated via snd_malloc_pci_pages().
*/
void snd_free_pci_pages(struct pci_dev *pci,
size_t size,
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);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && 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
* @addrp: the pointer to store the physical address of the buffer
*
* Allocates a single page for the given PCI 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_pci_page(struct pci_dev *pci, dma_addr_t *addrp)
{
void *ptr;
dma_addr_t addr;
unsigned long rmask;
rmask = ~(unsigned long)(pci ? pci->dma_mask : 0x00ffffff);
ptr = (void *)__get_free_page(GFP_KERNEL);
if (ptr) {
addr = virt_to_phys(ptr);
if (((unsigned long)addr + PAGE_SIZE - 1) & rmask) {
/* 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
* @pci: pci device pointer
* @ptr: the buffer pointer to release
* @dma_addr: the physical address of the buffer
*
* Releases the buffer allocated via snd_malloc_pci_page().
*/
void snd_free_pci_page(struct pci_dev *pci, void *ptr, dma_addr_t dma_addr);
#endif /* for kernel-doc */
#endif /* CONFIG_PCI */
#ifdef CONFIG_SBUS
/**
* snd_malloc_sbus_pages - allocate pages for SBUS with the given size
* @sdev: sbus device pointer
* @size: the size to allocate in bytes
* @dma_addr: the pointer to store the physical address of the buffer
*
* Allocates the physically contiguous pages with the given size for
* SBUS.
*
* Returns the pointer of the buffer, or NULL if no enoguh memory.
*/
void *snd_malloc_sbus_pages(struct sbus_dev *sdev,
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 = sbus_alloc_consistent(sdev, PAGE_SIZE * (1 << pg), dma_addr);
if (res != NULL) {
mark_pages(res, pg);
}
return res;
}
/**
* snd_malloc_pci_pages_fallback - allocate pages with the given size with fallback
for SBUS
* @sdev: sbus device pointer
* @size: the requested size to allocate in bytes
* @dma_addr: the pointer to store the physical 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 SBUS. 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_sbus_pages_fallback(struct sbus_dev *sdev,
size_t size,
dma_addr_t *dma_addr,
size_t *res_size)
{
void *res;
snd_assert(res_size != NULL, return NULL);
do {
if ((res = snd_malloc_sbus_pages(sdev, size, dma_addr)) != NULL) {
*res_size = size;
return res;
}
size >>= 1;
} while (size >= PAGE_SIZE);
return NULL;
}
/**
* snd_free_sbus_pages - release the pages
* @sdev: sbus device pointer
* @size: the allocated buffer size
* @ptr: the buffer pointer to release
* @dma_addr: the physical address of the buffer
*
* Releases the buffer allocated via snd_malloc_pci_pages().
*/
void snd_free_sbus_pages(struct sbus_dev *sdev,
size_t size,
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);
sbus_free_consistent(sdev, PAGE_SIZE * (1 << pg), ptr, dma_addr);
}
#endif /* CONFIG_SBUS */
#ifdef CONFIG_PROC_FS
/*
* proc file interface
*/
static int snd_mem_proc_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len = 0;
long pages = snd_allocated_pages >> (PAGE_SHIFT-12);
len += sprintf(page + len, "pages : %li bytes (%li pages per %likB)\n",
pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
return len;
}
#endif /* CONFIG_PROC_FS */
/*
* module entry
*/
static int __init snd_mem_init(void)
{
if (! create_proc_read_entry("driver/snd-page-alloc", 0, 0,
snd_mem_proc_read, NULL))
return -EIO;
return 0;
}
static void __exit snd_mem_exit(void)
{
remove_proc_entry("driver/snd-page-alloc", NULL);
free_all_reserved_pages();
if (snd_allocated_pages > 0)
printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n",
snd_allocated_pages);
}
module_init(snd_mem_init)
module_exit(snd_mem_exit)
/*
* exports
*/
EXPORT_SYMBOL(snd_dma_alloc_pages);
EXPORT_SYMBOL(snd_dma_free_pages);
EXPORT_SYMBOL(snd_dma_get_reserved);
EXPORT_SYMBOL(snd_dma_free_reserved);
EXPORT_SYMBOL(snd_dma_set_reserved);
EXPORT_SYMBOL(snd_malloc_pages);
EXPORT_SYMBOL(snd_malloc_pages_fallback);
EXPORT_SYMBOL(snd_free_pages);
#if defined(CONFIG_ISA) && ! defined(CONFIG_PCI)
EXPORT_SYMBOL(snd_malloc_isa_pages);
EXPORT_SYMBOL(snd_malloc_isa_pages_fallback);
#endif
#ifdef CONFIG_PCI
EXPORT_SYMBOL(snd_malloc_pci_pages);
EXPORT_SYMBOL(snd_malloc_pci_pages_fallback);
EXPORT_SYMBOL(snd_malloc_pci_page);
EXPORT_SYMBOL(snd_free_pci_pages);
EXPORT_SYMBOL(snd_malloc_sgbuf_pages);
EXPORT_SYMBOL(snd_free_sgbuf_pages);
#ifdef HACK_PCI_ALLOC_CONSISTENT
EXPORT_SYMBOL(snd_pci_hack_alloc_consistent);
#endif
#endif
#ifdef CONFIG_SBUS
EXPORT_SYMBOL(snd_malloc_sbus_pages);
EXPORT_SYMBOL(snd_malloc_sbus_pages_fallback);
EXPORT_SYMBOL(snd_free_sbus_pages);
#endif
--- NEW FILE: memory_wrapper.c ---
/*
* Copyright (c) by Jaroslav Kysela <[EMAIL PROTECTED]>
* Takashi Iwai <[EMAIL PROTECTED]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/config.h>
#include <linux/version.h>
#include <linux/pci.h>
#include <sound/memalloc.h>
#ifdef HACK_PCI_ALLOC_CONSISTENT
/*
* A dirty hack... when the kernel code is fixed this should be removed.
*
* since pci_alloc_consistent 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.
*
* so in the following, we allocate at first without dma_mask, so that
* 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.
*/
void *snd_pci_hack_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)
{
void *ret;
u64 dma_mask;
unsigned long rmask;
if (hwdev == NULL)
return pci_alloc_consistent(hwdev, size, dma_handle);
dma_mask = hwdev->dma_mask;
rmask = ~((unsigned long)dma_mask);
hwdev->dma_mask = 0xffffffff; /* do without masking */
ret = pci_alloc_consistent(hwdev, size, dma_handle);
hwdev->dma_mask = dma_mask; /* restore */
if (ret) {
/* obtained address is out of range? */
if (((unsigned long)*dma_handle + size - 1) & rmask) {
/* reallocate with the proper mask */
pci_free_consistent(hwdev, size, ret, *dma_handle);
ret = pci_alloc_consistent(hwdev, size, dma_handle);
}
} else {
/* wish to success now with the proper mask... */
if (dma_mask != 0xffffffff)
ret = pci_alloc_consistent(hwdev, size, dma_handle);
}
return ret;
}
#endif /* HACK_PCI_ALLOC_CONSISTENT */
--- NEW FILE: sgbuf.c ---
/*
* Scatter-Gather buffer
*
* Copyright (c) by Takashi Iwai <[EMAIL PROTECTED]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/config.h>
#include <linux/version.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <sound/memalloc.h>
/* table entries are align to 32 */
#define SGBUF_TBL_ALIGN 32
#define sgbuf_align_table(tbl) ((((tbl) + SGBUF_TBL_ALIGN - 1) / SGBUF_TBL_ALIGN) *
SGBUF_TBL_ALIGN)
/**
* snd_malloc_sgbuf_pages - allocate the pages for the PCI SG buffer
* @pci: the pci device pointer
* @size: the requested buffer size in bytes
* @dmab: the buffer record to store
*
* Initializes the SG-buffer table and allocates the buffer pages
* for the given size.
* The pages are mapped to the virtually continuous memory.
*
* This function is usually called from the middle-level functions such as
* snd_pcm_lib_malloc_pages().
*
* 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)
{
struct snd_sg_buf *sgbuf;
unsigned int i, pages;
dmab->area = NULL;
dmab->addr = 0;
dmab->private_data = sgbuf = kmalloc(sizeof(*sgbuf), GFP_KERNEL);
if (! sgbuf)
return NULL;
memset(sgbuf, 0, sizeof(*sgbuf));
sgbuf->pci = pci;
pages = snd_sgbuf_aligned_pages(size);
sgbuf->tblsize = sgbuf_align_table(pages);
sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL);
if (! sgbuf->table)
goto _failed;
memset(sgbuf->table, 0, sizeof(*sgbuf->table) * sgbuf->tblsize);
sgbuf->page_table = kmalloc(sizeof(*sgbuf->page_table) * sgbuf->tblsize,
GFP_KERNEL);
if (! sgbuf->page_table)
goto _failed;
memset(sgbuf->page_table, 0, sizeof(*sgbuf->page_table) * sgbuf->tblsize);
/* allocate each page */
for (i = 0; i < pages; i++) {
void *ptr;
dma_addr_t addr;
ptr = snd_malloc_pci_page(sgbuf->pci, &addr);
if (! ptr)
goto _failed;
sgbuf->table[i].buf = ptr;
sgbuf->table[i].addr = addr;
sgbuf->page_table[i] = virt_to_page(ptr);
sgbuf->pages++;
}
sgbuf->size = size;
dmab->area = vmap(sgbuf->page_table, sgbuf->pages);
if (! dmab->area)
goto _failed;
return dmab->area;
_failed:
snd_free_sgbuf_pages(dmab); /* free the table */
return NULL;
}
/**
* snd_free_sgbuf_pages - free the sg buffer
* @dmab: buffer record
*
* Releases the pages and the SG-buffer table.
*
* This function is called usually from the middle-level function
* such as snd_pcm_lib_free_pages().
*
* Returns zero if successful, or a negative error code on failure.
*/
int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
{
struct snd_sg_buf *sgbuf = dmab->private_data;
int i;
if (! sgbuf)
return -EINVAL;
for (i = 0; i < sgbuf->pages; i++)
snd_free_pci_page(sgbuf->pci, sgbuf->table[i].buf,
sgbuf->table[i].addr);
if (dmab->area)
vunmap(dmab->area);
dmab->area = NULL;
if (sgbuf->table)
kfree(sgbuf->table);
if (sgbuf->page_table)
kfree(sgbuf->page_table);
kfree(sgbuf);
dmab->private_data = NULL;
return 0;
}
Index: Makefile
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/Makefile,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- Makefile 9 Feb 2003 18:41:54 -0000 1.35
+++ Makefile 28 Feb 2003 14:29:15 -0000 1.36
@@ -14,8 +14,10 @@
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-pcm-objs += pcm_sgbuf.o
+snd-page-alloc-objs += sgbuf.o memory_wrapper.o
endif
snd-rawmidi-objs := rawmidi.o
@@ -31,72 +33,72 @@
obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o
obj-$(CONFIG_SND_MIXER_OSS) += oss/
-obj-$(CONFIG_SND_PCM_OSS) += snd-pcm.o snd-timer.o oss/
+obj-$(CONFIG_SND_PCM_OSS) += snd-pcm.o snd-timer.o snd-page-alloc.o oss/
obj-$(CONFIG_SND_SEQUENCER) += snd-timer.o seq/
obj-$(CONFIG_SND_BIT32_EMUL) += ioctl32/
# Toplevel Module Dependency
-obj-$(CONFIG_SND_DUMMY) += snd-pcm.o snd-timer.o snd.o
+obj-$(CONFIG_SND_DUMMY) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
obj-$(CONFIG_SND_VIRMIDI) += snd-rawmidi.o snd.o snd-timer.o
obj-$(CONFIG_SND_SERIAL_U16550) += snd-rawmidi.o snd.o snd-timer.o
obj-$(CONFIG_SND_MTPAV) += snd-rawmidi.o snd.o snd-timer.o
obj-$(CONFIG_SND_MPU401) += snd-rawmidi.o snd.o snd-timer.o
-obj-$(CONFIG_SND_ALS100) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_AZT2320) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_CMI8330) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_DT019X) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_ES18XX) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_OPL3SA2) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_SGALAXY) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_AD1816A) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_AD1848) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_CS4231) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_CS4232) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_CS4236) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_ES1688) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_GUSCLASSIC) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_GUSMAX) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_GUSEXTREME) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_INTERWAVE) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_INTERWAVE_STB) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
snd-hwdep.o
-obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
snd-hwdep.o
-obj-$(CONFIG_SND_OPTI93X) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_SB8) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_SB16) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_SBAWE) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_ES968) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_WAVEFRONT) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_ALS4000) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_CMIPCI) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_CS4281) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_ENS1370) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_ENS1371) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_ES1938) += snd-pcm.o snd-timer.o snd.o snd-hwdep.o snd-rawmidi.o
-obj-$(CONFIG_SND_ES1968) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_FM801) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_ICE1712) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_INTEL8X0) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_MAESTRO3) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_RME32) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_RME96) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_SONICVIBES) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_VIA82XX) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_ALI5451) += snd.o snd-rawmidi.o snd-timer.o snd-pcm.o
-obj-$(CONFIG_SND_CS46XX) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_EMU10K1) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_KORG1212) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_NM256) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_RME9652) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_HDSP) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_TRIDENT) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_YMFPCI) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_POWERMAC) += snd-pcm.o snd-timer.o snd.o
-obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-pcm.o snd-timer.o snd.o
+obj-$(CONFIG_SND_ALS100) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_AZT2320) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_CMI8330) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_DT019X) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_ES18XX) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_OPL3SA2) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_SGALAXY) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_AD1816A) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_AD1848) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_CS4231) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
+obj-$(CONFIG_SND_CS4232) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_CS4236) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_ES1688) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_GUSCLASSIC) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
+obj-$(CONFIG_SND_GUSMAX) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
+obj-$(CONFIG_SND_GUSEXTREME) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_INTERWAVE) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
+obj-$(CONFIG_SND_INTERWAVE_STB) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
+obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_OPTI93X) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_SB8) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
snd-hwdep.o
+obj-$(CONFIG_SND_SB16) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
snd-hwdep.o
+obj-$(CONFIG_SND_SBAWE) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
snd-hwdep.o
+obj-$(CONFIG_SND_ES968) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
+obj-$(CONFIG_SND_WAVEFRONT) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_ALS4000) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_CMIPCI) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_CS4281) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_ENS1370) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
+obj-$(CONFIG_SND_ENS1371) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
+obj-$(CONFIG_SND_ES1938) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-hwdep.o
snd-rawmidi.o
+obj-$(CONFIG_SND_ES1968) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
+obj-$(CONFIG_SND_FM801) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
snd-hwdep.o
+obj-$(CONFIG_SND_ICE1712) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
+obj-$(CONFIG_SND_INTEL8X0) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
+obj-$(CONFIG_SND_MAESTRO3) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_RME32) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_RME96) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_SONICVIBES) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_VIA82XX) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
+obj-$(CONFIG_SND_ALI5451) += snd.o snd-rawmidi.o snd-timer.o snd-page-alloc.o
snd-pcm.o
+obj-$(CONFIG_SND_CS46XX) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
+obj-$(CONFIG_SND_EMU10K1) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_KORG1212) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_NM256) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_RME9652) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_HDSP) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
+obj-$(CONFIG_SND_TRIDENT) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
+obj-$(CONFIG_SND_YMFPCI) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_POWERMAC) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
ifeq ($(CONFIG_SND_SB16_CSP),y)
obj-$(CONFIG_SND_SB16) += snd-hwdep.o
obj-$(CONFIG_SND_SBAWE) += snd-hwdep.o
endif
-obj-$(CONFIG_SND_USB_AUDIO) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
+obj-$(CONFIG_SND_USB_AUDIO) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
snd-rawmidi.o
obj-m := $(sort $(obj-m))
Index: init.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/init.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- init.c 31 Jan 2003 15:19:25 -0000 1.32
+++ init.c 28 Feb 2003 14:29:16 -0000 1.33
@@ -495,6 +495,22 @@
#endif
+#ifdef MODULE
+static snd_info_entry_t *snd_card_module_info_entry;
+static void snd_card_module_info_read(snd_info_entry_t *entry, snd_info_buffer_t *
buffer)
+{
+ int idx;
+ snd_card_t *card;
+
+ for (idx = 0; idx < SNDRV_CARDS; idx++) {
+ read_lock(&snd_card_rwlock);
+ if ((card = snd_cards[idx]) != NULL)
+ snd_iprintf(buffer, "%i %s\n", idx, card->module->name);
+ read_unlock(&snd_card_rwlock);
+ }
+}
+#endif
+
int __init snd_card_info_init(void)
{
snd_info_entry_t *entry;
@@ -509,6 +525,20 @@
return -ENOMEM;
}
snd_card_info_entry = entry;
+
+#ifdef MODULE
+ entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL);
+ if (entry) {
+ entry->content = SNDRV_INFO_CONTENT_TEXT;
+ entry->c.text.read_size = PAGE_SIZE;
+ entry->c.text.read = snd_card_module_info_read;
+ if (snd_info_register(entry) < 0)
+ snd_info_free_entry(entry);
+ else
+ snd_card_module_info_entry = entry;
+ }
+#endif
+
return 0;
}
@@ -516,6 +546,10 @@
{
if (snd_card_info_entry)
snd_info_unregister(snd_card_info_entry);
+#ifdef MODULE
+ if (snd_card_module_info_entry)
+ snd_info_unregister(snd_card_module_info_entry);
+#endif
return 0;
}
Index: memory.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/memory.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- memory.c 25 Feb 2003 15:07:34 -0000 1.25
+++ memory.c 28 Feb 2003 14:29:17 -0000 1.26
@@ -1,6 +1,7 @@
/*
* Copyright (c) by Jaroslav Kysela <[EMAIL PROTECTED]>
- * Memory allocation routines.
+ *
+ * Memory allocation helpers.
*
*
* This program is free software; you can redistribute it and/or modify
@@ -28,9 +29,6 @@
#include <linux/pci.h>
#include <sound/core.h>
#include <sound/info.h>
-#ifdef CONFIG_SBUS
-#include <asm/sbus.h>
-#endif
/*
* memory allocation helpers and debug routines
@@ -48,7 +46,6 @@
#define snd_alloc_track_entry(obj) (struct snd_alloc_track *)((char*)obj - (unsigned
long)((struct snd_alloc_track *)0)->data)
-static long snd_alloc_pages;
static long snd_alloc_kmalloc;
static long snd_alloc_vmalloc;
static LIST_HEAD(snd_alloc_kmalloc_list);
@@ -61,7 +58,6 @@
void snd_memory_init(void)
{
- snd_alloc_pages = 0;
snd_alloc_kmalloc = 0;
snd_alloc_vmalloc = 0;
}
@@ -70,8 +66,7 @@
{
struct list_head *head;
struct snd_alloc_track *t;
- if (snd_alloc_pages > 0)
- snd_printk(KERN_ERR "Not freed snd_alloc_pages = %li\n",
snd_alloc_pages);
+
if (snd_alloc_kmalloc > 0)
snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n",
snd_alloc_kmalloc);
if (snd_alloc_vmalloc > 0)
@@ -226,8 +221,6 @@
static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
{
- long pages = snd_alloc_pages >> (PAGE_SHIFT-12);
- snd_iprintf(buffer, "pages : %li bytes (%li pages per %likB)\n", pages *
PAGE_SIZE, pages, PAGE_SIZE / 1024);
snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc);
snd_iprintf(buffer, "vmalloc: %li bytes\n", snd_alloc_vmalloc);
}
@@ -263,335 +256,6 @@
#endif /* CONFIG_SND_DEBUG_MEMORY */
-
-/**
- * snd_malloc_pages - allocate pages with the given size
- * @size: the size to allocate in bytes
- * @dma_flags: the allocation conditions, GFP_XXX
- *
- * Allocates the physically contiguous pages with the given size.
- *
- * Returns the pointer of the buffer, or NULL if no enoguh memory.
- */
-void *snd_malloc_pages(unsigned long size, unsigned int dma_flags)
-{
- int pg;
- void *res;
-
- snd_assert(size > 0, return NULL);
- snd_assert(dma_flags != 0, return NULL);
- for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
- if ((res = (void *) __get_free_pages(dma_flags, pg)) != NULL) {
- struct page *page = virt_to_page(res);
- struct page *last_page = page + (1 << pg);
- while (page < last_page)
- SetPageReserved(page++);
-#ifdef CONFIG_SND_DEBUG_MEMORY
- snd_alloc_pages += 1 << pg;
-#endif
- }
- return res;
-}
-
-/**
- * snd_malloc_pages_fallback - allocate pages with the given size with fallback
- * @size: the requested size to allocate in bytes
- * @dma_flags: the allocation conditions, GFP_XXX
- * @res_size: the pointer to store the size of buffer actually allocated
- *
- * Allocates the physically contiguous pages with the given request
- * size. 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_pages_fallback(unsigned long size, unsigned int dma_flags, unsigned
long *res_size)
-{
- void *res;
-
- snd_assert(size > 0, return NULL);
- snd_assert(res_size != NULL, return NULL);
- do {
- if ((res = snd_malloc_pages(size, dma_flags)) != NULL) {
- *res_size = size;
- return res;
- }
- size >>= 1;
- } while (size >= PAGE_SIZE);
- return NULL;
-}
-
-/**
- * snd_free_pages - release the pages
- * @ptr: the buffer pointer to release
- * @size: the allocated buffer size
- *
- * Releases the buffer allocated via snd_malloc_pages().
- */
-void snd_free_pages(void *ptr, unsigned long size)
-{
- int pg;
- struct page *page, *last_page;
-
- if (ptr == NULL)
- return;
- for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
- page = virt_to_page(ptr);
- last_page = page + (1 << pg);
- while (page < last_page)
- ClearPageReserved(page++);
- free_pages((unsigned long) ptr, pg);
-#ifdef CONFIG_SND_DEBUG_MEMORY
- snd_alloc_pages -= 1 << pg;
-#endif
-}
-
-#if defined(CONFIG_ISA) && ! defined(CONFIG_PCI)
-
-/**
- * snd_malloc_isa_pages - allocate pages for ISA bus with the given size
- * @size: the size to allocate in bytes
- * @dma_addr: the pointer to store the physical address of the buffer
- *
- * Allocates the physically contiguous pages with the given size for
- * ISA bus.
- *
- * Returns the pointer of the buffer, or NULL if no enoguh memory.
- */
-void *snd_malloc_isa_pages(unsigned long size, dma_addr_t *dma_addr)
-{
- void *dma_area;
- dma_area = snd_malloc_pages(size, GFP_ATOMIC|GFP_DMA);
- *dma_addr = dma_area ? isa_virt_to_bus(dma_area) : 0UL;
- return dma_area;
-}
-
-/**
- * snd_malloc_isa_pages_fallback - allocate pages with the given size with fallback
for ISA bus
- * @size: the requested size to allocate in bytes
- * @dma_addr: the pointer to store the physical 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 PCI bus. 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_isa_pages_fallback(unsigned long size,
- dma_addr_t *dma_addr,
- unsigned long *res_size)
-{
- void *dma_area;
- dma_area = snd_malloc_pages_fallback(size, GFP_ATOMIC|GFP_DMA, res_size);
- *dma_addr = dma_area ? isa_virt_to_bus(dma_area) : 0UL;
- return dma_area;
-}
-
-#endif /* CONFIG_ISA && !CONFIG_PCI */
-
-#ifdef CONFIG_PCI
-
-/**
- * snd_malloc_pci_pages - allocate pages for PCI bus with the given size
- * @pci: the pci device pointer
- * @size: the size to allocate in bytes
- * @dma_addr: the pointer to store the physical address of the buffer
- *
- * Allocates the physically contiguous pages with the given size for
- * PCI bus.
- *
- * Returns the pointer of the buffer, or NULL if no enoguh memory.
- */
-void *snd_malloc_pci_pages(struct pci_dev *pci,
- unsigned long 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) {
- struct page *page = virt_to_page(res);
- struct page *last_page = page + (1 << pg);
- while (page < last_page)
- SetPageReserved(page++);
-#ifdef CONFIG_SND_DEBUG_MEMORY
- snd_alloc_pages += 1 << pg;
-#endif
- }
- return res;
-}
-
-/**
- * snd_malloc_pci_pages_fallback - allocate pages with the given size with fallback
for PCI bus
- * @pci: pci device pointer
- * @size: the requested size to allocate in bytes
- * @dma_addr: the pointer to store the physical 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 PCI bus. 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_pci_pages_fallback(struct pci_dev *pci,
- unsigned long size,
- dma_addr_t *dma_addr,
- unsigned long *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;
-}
-
-/**
- * snd_free_pci_pages - release the pages
- * @pci: pci device pointer
- * @size: the allocated buffer size
- * @ptr: the buffer pointer to release
- * @dma_addr: the physical address of the buffer
- *
- * Releases the buffer allocated via snd_malloc_pci_pages().
- */
-void snd_free_pci_pages(struct pci_dev *pci,
- unsigned long size,
- void *ptr,
- dma_addr_t dma_addr)
-{
- int pg;
- struct page *page, *last_page;
-
- if (ptr == NULL)
- return;
- for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
- page = virt_to_page(ptr);
- last_page = page + (1 << pg);
- while (page < last_page)
- ClearPageReserved(page++);
- pci_free_consistent(pci, PAGE_SIZE * (1 << pg), ptr, dma_addr);
-#ifdef CONFIG_SND_DEBUG_MEMORY
- snd_alloc_pages -= 1 << pg;
-#endif
-}
-
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_SBUS
-
-/**
- * snd_malloc_sbus_pages - allocate pages for SBUS with the given size
- * @sdev: sbus device pointer
- * @size: the size to allocate in bytes
- * @dma_addr: the pointer to store the physical address of the buffer
- *
- * Allocates the physically contiguous pages with the given size for
- * SBUS.
- *
- * Returns the pointer of the buffer, or NULL if no enoguh memory.
- */
-void *snd_malloc_sbus_pages(struct sbus_dev *sdev,
- unsigned long 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 = sbus_alloc_consistent(sdev, PAGE_SIZE * (1 << pg), dma_addr);
- if (res != NULL) {
- struct page *page = virt_to_page(res);
- struct page *last_page = page + (1 << pg);
- while (page < last_page)
- SetPageReserved(page++);
-#ifdef CONFIG_SND_DEBUG_MEMORY
- snd_alloc_pages += 1 << pg;
-#endif
- }
- return res;
-}
-
-/**
- * snd_malloc_pci_pages_fallback - allocate pages with the given size with fallback
for SBUS
- * @sdev: sbus device pointer
- * @size: the requested size to allocate in bytes
- * @dma_addr: the pointer to store the physical 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 SBUS. 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_sbus_pages_fallback(struct sbus_dev *sdev,
- unsigned long size,
- dma_addr_t *dma_addr,
- unsigned long *res_size)
-{
- void *res;
-
- snd_assert(res_size != NULL, return NULL);
- do {
- if ((res = snd_malloc_sbus_pages(sdev, size, dma_addr)) != NULL) {
- *res_size = size;
- return res;
- }
- size >>= 1;
- } while (size >= PAGE_SIZE);
- return NULL;
-}
-
-/**
- * snd_free_sbus_pages - release the pages
- * @sdev: sbus device pointer
- * @size: the allocated buffer size
- * @ptr: the buffer pointer to release
- * @dma_addr: the physical address of the buffer
- *
- * Releases the buffer allocated via snd_malloc_pci_pages().
- */
-void snd_free_sbus_pages(struct sbus_dev *sdev,
- unsigned long size,
- void *ptr,
- dma_addr_t dma_addr)
-{
- int pg;
- struct page *page, *last_page;
-
- if (ptr == NULL)
- return;
- for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
- page = virt_to_page(ptr);
- last_page = page + (1 << pg);
- while (page < last_page)
- ClearPageReserved(page++);
- sbus_free_consistent(sdev, PAGE_SIZE * (1 << pg), ptr, dma_addr);
-#ifdef CONFIG_SND_DEBUG_MEMORY
- snd_alloc_pages -= 1 << pg;
-#endif
-}
-
-#endif /* CONFIG_SBUS */
-
/**
* snd_kcalloc - memory allocation and zero-clear
* @size: the size to allocate in bytes
@@ -695,81 +359,3 @@
return 0;
#endif
}
-
-
-#ifdef CONFIG_PCI
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && 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
- * @addrp: the pointer to store the physical address of the buffer
- *
- * Allocates a single page for the given PCI 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_pci_page(struct pci_dev *pci, dma_addr_t *addrp)
-{
- void *ptr;
- dma_addr_t addr;
- unsigned long rmask;
-
- rmask = ~(unsigned long)(pci ? pci->dma_mask : 0x00ffffff);
- ptr = (void *)__get_free_page(GFP_KERNEL);
- if (ptr) {
- addr = virt_to_phys(ptr);
- if (((unsigned long)addr + PAGE_SIZE - 1) & rmask) {
- /* try to reallocate with the GFP_DMA */
- free_page((unsigned long)ptr);
- 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) {
- struct page *page = virt_to_page(ptr);
- memset(ptr, 0, PAGE_SIZE);
- SetPageReserved(page);
-#ifdef CONFIG_SND_DEBUG_MEMORY
- snd_alloc_pages++;
-#endif
- }
- *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 /* 2.4 && i386 */
-
-#if 0 /* for kernel-doc */
-/**
- * snd_free_pci_page - release a page
- * @pci: pci device pointer
- * @ptr: the buffer pointer to release
- * @dma_addr: the physical address of the buffer
- *
- * Releases the buffer allocated via snd_malloc_pci_page().
- */
-void snd_free_pci_page(struct pci_dev *pci, void *ptr, dma_addr_t dma_addr);
-#endif /* for kernel-doc */
-
-#endif /* CONFIG_PCI */
Index: pcm.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/pcm.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- pcm.c 31 Jan 2003 15:19:25 -0000 1.24
+++ pcm.c 28 Feb 2003 14:29:18 -0000 1.25
@@ -595,8 +595,6 @@
snd_magic_kfree(substream);
return err;
}
- substream->dma_type = SNDRV_PCM_DMA_TYPE_UNKNOWN;
- substream->dma_private = NULL;
spin_lock_init(&substream->timer_lock);
prev = substream;
}
Index: pcm_lib.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/pcm_lib.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- pcm_lib.c 27 Feb 2003 09:17:10 -0000 1.31
+++ pcm_lib.c 28 Feb 2003 14:29:19 -0000 1.32
@@ -2658,6 +2658,9 @@
#ifdef CONFIG_PCI
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pci_pages);
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);
Index: pcm_memory.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/pcm_memory.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- pcm_memory.c 10 Feb 2003 11:53:49 -0000 1.18
+++ pcm_memory.c 28 Feb 2003 14:29:19 -0000 1.19
@@ -26,9 +26,6 @@
#include <sound/pcm.h>
#include <sound/info.h>
#include <sound/initval.h>
-#ifdef CONFIG_PCI
-#include <sound/pcm_sgbuf.h>
-#endif
static int preallocate_dma = 1;
MODULE_PARM(preallocate_dma, "i");
@@ -44,59 +41,33 @@
/*
- * allocate pages on the specified bus
- */
-static int alloc_pcm_pages(snd_pcm_substream_t *substream, size_t size,
- struct snd_pcm_dma_buffer *dmab)
-{
- switch (substream->dma_type) {
- case SNDRV_PCM_DMA_TYPE_CONTINUOUS:
- dmab->area = snd_malloc_pages(size, (unsigned int)((unsigned
long)substream->dma_private & 0xffffffff));
- dmab->addr = 0UL; /* not valid */
- break;
-#ifdef CONFIG_ISA
- case SNDRV_PCM_DMA_TYPE_ISA:
- dmab->area = snd_malloc_isa_pages(size, &dmab->addr);
- break;
-#endif
-#ifdef CONFIG_PCI
- case SNDRV_PCM_DMA_TYPE_PCI:
- dmab->area = snd_malloc_pci_pages((struct pci_dev
*)substream->dma_private, size, &dmab->addr);
- break;
- case SNDRV_PCM_DMA_TYPE_PCI_SG:
- snd_pcm_sgbuf_alloc_pages((struct pci_dev *)substream->dma_private,
size, dmab);
- break;
-#endif
-#ifdef CONFIG_SBUS
- case SNDRV_PCM_DMA_TYPE_SBUS:
- dmab->area = snd_malloc_sbus_pages((struct sbus_dev
*)substream->dma_private, size, &dmab->addr);
- break;
-#endif
- default:
- dmab->area = NULL;
- dmab->addr = 0;
- return -ENXIO;
- }
- return 0;
-}
-
-/*
* try to allocate as the large pages as possible.
* stores the resultant memory size in *res_size.
*
* the minimum size is snd_minimum_buffer. it should be power of 2.
*/
-static int alloc_pcm_pages_fallback(snd_pcm_substream_t *substream,
- size_t size,
- struct snd_pcm_dma_buffer *dmab)
+static int preallocate_pcm_pages(snd_pcm_substream_t *substream, size_t size)
{
+ struct snd_dma_buffer *dmab = &substream->dma_buffer;
int err;
+
snd_assert(size > 0, return -EINVAL);
+
+ /* already reserved? */
+ if (snd_dma_get_reserved(&substream->dma_device, dmab) > 0) {
+ if (dmab->bytes >= size)
+ return 0; /* yes */
+ /* no, reset the reserved block */
+ snd_dma_free_reserved(&substream->dma_device);
+ dmab->bytes = 0;
+ }
+
do {
- if ((err = alloc_pcm_pages(substream, size, dmab)) < 0)
+ if ((err = snd_dma_alloc_pages(&substream->dma_device, size, dmab)) <
0)
return err;
if (dmab->area) {
- dmab->bytes = size;
+ /* remember this one */
+ snd_dma_set_reserved(&substream->dma_device, dmab);
return 0;
}
size >>= 1;
@@ -106,46 +77,13 @@
}
/*
- * release the pages on the specified bus
- */
-static void free_pcm_pages(snd_pcm_substream_t *substream,
- struct snd_pcm_dma_buffer *dmab)
-{
- switch (substream->dma_type) {
- case SNDRV_PCM_DMA_TYPE_CONTINUOUS:
- snd_free_pages(dmab->area, dmab->bytes);
- break;
-#ifdef CONFIG_ISA
- case SNDRV_PCM_DMA_TYPE_ISA:
- snd_free_isa_pages(dmab->bytes, dmab->area, dmab->addr);
- break;
-#endif
-#ifdef CONFIG_PCI
- case SNDRV_PCM_DMA_TYPE_PCI:
- snd_free_pci_pages((struct pci_dev *)substream->dma_private,
- dmab->bytes, dmab->area, dmab->addr);
- break;
- case SNDRV_PCM_DMA_TYPE_PCI_SG:
- snd_pcm_sgbuf_free_pages(dmab);
- break;
-#endif
-#ifdef CONFIG_SBUS
- case SNDRV_PCM_DMA_TYPE_SBUS:
- snd_free_sbus_pages((struct sbus_dev *)substream->dma_private,
- dmab->bytes, dmab->area, dmab->addr);
- break;
-#endif
- }
-}
-
-/*
* release the preallocated buffer if not yet done.
*/
static void snd_pcm_lib_preallocate_dma_free(snd_pcm_substream_t *substream)
{
if (substream->dma_buffer.area == NULL)
return;
- free_pcm_pages(substream, &substream->dma_buffer);
+ snd_dma_free_reserved(&substream->dma_device);
substream->dma_buffer.area = NULL;
}
@@ -164,7 +102,7 @@
snd_info_unregister(substream->proc_prealloc_entry);
substream->proc_prealloc_entry = NULL;
}
- substream->dma_type = SNDRV_PCM_DMA_TYPE_UNKNOWN;
+ substream->dma_device.type = SNDRV_DMA_TYPE_UNKNOWN;
return 0;
}
@@ -210,7 +148,7 @@
snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data;
char line[64], str[64];
size_t size;
- struct snd_pcm_dma_buffer new_dmab;
+ struct snd_dma_buffer new_dmab;
if (substream->runtime) {
buffer->error = -EBUSY;
@@ -228,7 +166,7 @@
memset(&new_dmab, 0, sizeof(new_dmab));
if (size > 0) {
- if (alloc_pcm_pages(substream, size, &new_dmab) < 0 ||
+ if (snd_dma_alloc_pages(&substream->dma_device, size,
&new_dmab) < 0 ||
new_dmab.area == NULL) {
buffer->error = -ENOMEM;
return;
@@ -237,7 +175,7 @@
} else {
substream->buffer_bytes_max = UINT_MAX;
}
- snd_pcm_lib_preallocate_dma_free(substream);
+ snd_dma_set_reserved(&substream->dma_device, &new_dmab);
substream->dma_buffer = new_dmab;
} else {
buffer->error = -EINVAL;
@@ -254,7 +192,7 @@
memset(&substream->dma_buffer, 0, sizeof(substream->dma_buffer));
if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
- alloc_pcm_pages_fallback(substream, size, &substream->dma_buffer);
+ preallocate_pcm_pages(substream, size);
if (substream->dma_buffer.bytes > 0)
substream->buffer_bytes_max = substream->dma_buffer.bytes;
@@ -274,6 +212,16 @@
return 0;
}
+
+/*
+ * set up the unique pcm id
+ */
+static inline void setup_pcm_id(snd_pcm_substream_t *subs)
+{
+ subs->dma_device.id = subs->pcm->device << 16 |
+ subs->stream << 8 | subs->number;
+}
+
/**
* snd_pcm_lib_preallocate_pages - pre-allocation for the continuous memory type
* @substream: the pcm substream instance
@@ -289,8 +237,9 @@
size_t size, size_t max,
unsigned int flags)
{
- substream->dma_type = SNDRV_PCM_DMA_TYPE_CONTINUOUS;
- substream->dma_private = (void *)(unsigned long)flags;
+ substream->dma_device.type = SNDRV_DMA_TYPE_CONTINUOUS;
+ substream->dma_device.dev.flags = flags;
+ setup_pcm_id(substream);
return snd_pcm_lib_preallocate_pages1(substream, size, max);
}
@@ -334,8 +283,9 @@
int snd_pcm_lib_preallocate_isa_pages(snd_pcm_substream_t *substream,
size_t size, size_t max)
{
- substream->dma_type = SNDRV_PCM_DMA_TYPE_ISA;
- substream->dma_private = NULL;
+ substream->dma_device.type = SNDRV_DMA_TYPE_ISA;
+ substream->dma_device.dev.flags = 0; /* FIXME: any good identifier? */
+ setup_pcm_id(substream);
return snd_pcm_lib_preallocate_pages1(substream, size, max);
}
@@ -379,9 +329,9 @@
int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
{
snd_pcm_runtime_t *runtime;
- struct snd_pcm_dma_buffer dmab;
+ struct snd_dma_buffer dmab;
- snd_assert(substream->dma_type != SNDRV_PCM_DMA_TYPE_UNKNOWN, return -EINVAL);
+ snd_assert(substream->dma_device.type != SNDRV_DMA_TYPE_UNKNOWN, return
-EINVAL);
snd_assert(substream != NULL, return -EINVAL);
runtime = substream->runtime;
snd_assert(runtime != NULL, return -EINVAL);
@@ -398,7 +348,7 @@
dmab = substream->dma_buffer;
} else {
memset(&dmab, 0, sizeof(dmab));
- alloc_pcm_pages(substream, size, &dmab);
+ snd_dma_alloc_pages(&substream->dma_device, size, NULL);
}
if (! dmab.area)
return -ENOMEM;
@@ -427,13 +377,13 @@
if (runtime->dma_area == NULL)
return 0;
if (runtime->dma_area != substream->dma_buffer.area) {
- struct snd_pcm_dma_buffer dmab;
+ struct snd_dma_buffer dmab;
memset(&dmab, 0, sizeof(dmab));
dmab.area = runtime->dma_area;
dmab.addr = runtime->dma_addr;
dmab.bytes = runtime->dma_bytes;
dmab.private_data = runtime->dma_private;
- free_pcm_pages(substream, &dmab);
+ snd_dma_free_pages(&substream->dma_device, &dmab);
}
runtime->dma_area = NULL;
runtime->dma_addr = 0UL;
@@ -459,8 +409,9 @@
snd_pcm_substream_t *substream,
size_t size, size_t max)
{
- substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI;
- substream->dma_private = pci;
+ 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);
}
@@ -510,8 +461,9 @@
snd_pcm_substream_t *substream,
size_t size, size_t max)
{
- substream->dma_type = SNDRV_PCM_DMA_TYPE_SBUS;
- substream->dma_private = sdev;
+ substream->dma_device.type = SNDRV_DMA_TYPE_SBUS;
+ substream->dma_device.dev.sbus = sdev;
+ setup_pcm_id(substream);
return snd_pcm_lib_preallocate_pages1(substream, size, max);
}
@@ -563,8 +515,9 @@
snd_pcm_substream_t *substream,
size_t size, size_t max)
{
- substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI_SG;
- substream->dma_private = pci;
+ 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);
}
@@ -594,6 +547,24 @@
if ((err = snd_pcm_lib_preallocate_sg_pages(pci, substream,
size, max)) < 0)
return err;
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 */
Index: sound.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/sound.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- sound.c 25 Feb 2003 13:01:16 -0000 1.36
+++ sound.c 28 Feb 2003 14:29:21 -0000 1.37
@@ -432,24 +432,6 @@
#endif
EXPORT_SYMBOL(snd_kcalloc);
EXPORT_SYMBOL(snd_kmalloc_strdup);
-EXPORT_SYMBOL(snd_malloc_pages);
-EXPORT_SYMBOL(snd_malloc_pages_fallback);
-EXPORT_SYMBOL(snd_free_pages);
-#if defined(CONFIG_ISA) && ! defined(CONFIG_PCI)
-EXPORT_SYMBOL(snd_malloc_isa_pages);
-EXPORT_SYMBOL(snd_malloc_isa_pages_fallback);
-#endif
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(snd_malloc_pci_pages);
-EXPORT_SYMBOL(snd_malloc_pci_pages_fallback);
-EXPORT_SYMBOL(snd_malloc_pci_page);
-EXPORT_SYMBOL(snd_free_pci_pages);
-#endif
-#ifdef CONFIG_SBUS
-EXPORT_SYMBOL(snd_malloc_sbus_pages);
-EXPORT_SYMBOL(snd_malloc_sbus_pages_fallback);
-EXPORT_SYMBOL(snd_free_sbus_pages);
-#endif
EXPORT_SYMBOL(copy_to_user_fromio);
EXPORT_SYMBOL(copy_from_user_toio);
/* init.c */
@@ -529,6 +511,3 @@
EXPORT_SYMBOL(snd_wrapper_vmalloc);
EXPORT_SYMBOL(snd_wrapper_vfree);
#endif
-#ifdef HACK_PCI_ALLOC_CONSISTENT
-EXPORT_SYMBOL(snd_pci_hack_alloc_consistent);
-#endif
Index: wrappers.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/wrappers.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- wrappers.c 22 Oct 2002 09:29:28 -0000 1.9
+++ wrappers.c 28 Feb 2003 14:29:21 -0000 1.10
@@ -49,59 +49,3 @@
}
#endif
-
-/* check the condition in <sound/core.h> !! */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
-#if defined(__i386__) || defined(__ppc__) || defined(__x86_64__)
-
-#include <linux/pci.h>
-
-/* to be sure... */
-#ifdef HACK_PCI_ALLOC_CONSISTENT
-#error pci_alloc_consistent hack is already defined!!
-#endif
-
-/*
- * A dirty hack... when the kernel code is fixed this should be removed.
- *
- * since pci_alloc_consistent 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.
- *
- * so in the following, we allocate at first without dma_mask, so that
- * 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.
- */
-
-void *snd_pci_hack_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t *dma_handle)
-{
- void *ret;
- u64 dma_mask;
- unsigned long rmask;
-
- if (hwdev == NULL)
- return pci_alloc_consistent(hwdev, size, dma_handle);
- dma_mask = hwdev->dma_mask;
- rmask = ~((unsigned long)dma_mask);
- hwdev->dma_mask = 0xffffffff; /* do without masking */
- ret = pci_alloc_consistent(hwdev, size, dma_handle);
- hwdev->dma_mask = dma_mask; /* restore */
- if (ret) {
- /* obtained address is out of range? */
- if (((unsigned long)*dma_handle + size - 1) & rmask) {
- /* reallocate with the proper mask */
- pci_free_consistent(hwdev, size, ret, *dma_handle);
- ret = pci_alloc_consistent(hwdev, size, dma_handle);
- }
- } else {
- /* wish to success now with the proper mask... */
- if (dma_mask != 0xffffffff)
- ret = pci_alloc_consistent(hwdev, size, dma_handle);
- }
- return ret;
-}
-
-#endif
-#endif
--- pcm_sgbuf.c DELETED ---
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog