Commit 423f000d authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA CVS update - Takashi Iwai <tiwai@suse.de>

Memalloc module,PCM Midlevel
- fixed buffer pre-allocation.
- improved proc output.
- check the use flag when unmarking the reserved buffer.
- clean up and add more comments.
parent 55e780e6
......@@ -207,8 +207,9 @@ int snd_dma_alloc_pages(const struct snd_dma_device *dev, size_t size,
dmab->addr = 0;
return -ENXIO;
}
if (dmab->area)
dmab->bytes = size;
if (! dmab->area)
return -ENOMEM;
dmab->bytes = size;
return 0;
}
......@@ -342,6 +343,8 @@ int snd_dma_set_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer
down(&list_mutex);
mem = mem_list_find(dev, 0);
if (mem) {
if (mem->used)
printk(KERN_WARNING "snd-page-alloc: releasing the used block (type=%d, id=0x%x\n", mem->dev.type, mem->dev.id);
snd_dma_free_pages(dev, &mem->buffer);
if (! dmab || ! dmab->bytes) {
/* remove the entry */
......@@ -361,7 +364,7 @@ int snd_dma_set_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer
return -ENOMEM;
}
mem->dev = *dev;
list_add(&mem->list, &mem_list_head);
list_add_tail(&mem->list, &mem_list_head);
}
/* store the entry */
mem->used = 1;
......@@ -824,33 +827,40 @@ static void __init preallocate_cards(void)
while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) {
struct prealloc_dev *dev;
unsigned int i;
if (card >= SNDRV_CARDS)
break;
for (dev = prealloc_devices; dev->vendor; dev++) {
unsigned int i;
if (dev->vendor != pci->vendor || dev->device != pci->device)
continue;
if (! enable[card++])
continue;
if (dev->vendor == pci->vendor && dev->device == pci->device)
break;
}
if (! dev->vendor)
continue;
if (! enable[card++]) {
printk(KERN_DEBUG "snd-page-alloc: skipping card %d, device %04x:%04x\n", card, pci->vendor, pci->device);
continue;
}
if (pci_set_consistent_dma_mask(pci, dev->dma_mask) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", dev->dma_mask, dev->vendor, dev->device);
continue;
if (pci_set_consistent_dma_mask(pci, dev->dma_mask) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", dev->dma_mask, dev->vendor, dev->device);
continue;
}
for (i = 0; i < dev->buffers; i++) {
struct snd_mem_list *mem;
mem = kmalloc(sizeof(*mem), GFP_KERNEL);
if (! mem) {
printk(KERN_WARNING "snd-page-alloc: can't malloc memlist\n");
break;
}
for (i = 0; i < dev->buffers; i++) {
struct snd_dma_device dma;
struct snd_dma_buffer buf;
snd_dma_device_pci(&dma, pci, SNDRV_DMA_DEVICE_UNUSED);
memset(&buf, 0, sizeof(buf));
snd_dma_alloc_pages(&dma, dev->size, &buf);
if (buf.bytes) {
if (snd_dma_set_reserved(&dma, &buf) < 0) {
printk(KERN_WARNING "snd-page-alloc: cannot reserve buffer\n");
snd_dma_free_pages(&dma, &buf);
}
} else
printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size);
memset(mem, 0, sizeof(*mem));
snd_dma_device_pci(&mem->dev, pci, SNDRV_DMA_DEVICE_UNUSED);
if (snd_dma_alloc_pages(&mem->dev, dev->size, &mem->buffer) < 0) {
printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size);
kfree(mem);
} else {
down(&list_mutex);
list_add_tail(&mem->list, &mem_list_head);
up(&list_mutex);
}
}
}
......@@ -894,7 +904,8 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
case SNDRV_DMA_TYPE_PCI:
case SNDRV_DMA_TYPE_PCI_SG:
if (mem->dev.dev.pci) {
len += sprintf(page + len, "PCI [%04x:%04x]",
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);
}
......
......@@ -59,14 +59,18 @@ static int preallocate_pcm_pages(snd_pcm_substream_t *substream, size_t size)
if (dmab->bytes >= size)
return 0; /* yes */
/* no, reset the reserved block */
/* if we can find bigger pages below, this block will be
* automatically removed in snd_dma_set_reserved().
*/
snd_dma_free_reserved(&substream->dma_device);
dmab->bytes = 0;
}
do {
if ((err = snd_dma_alloc_pages(&substream->dma_device, size, dmab)) < 0)
return err;
if (dmab->area) {
if ((err = snd_dma_alloc_pages(&substream->dma_device, size, dmab)) < 0) {
if (err != -ENOMEM)
return err; /* fatal error */
} else {
/* remember this one */
snd_dma_set_reserved(&substream->dma_device, dmab);
return 0;
......@@ -167,12 +171,12 @@ static void snd_pcm_lib_preallocate_proc_write(snd_info_entry_t *entry,
memset(&new_dmab, 0, sizeof(new_dmab));
if (size > 0) {
if (snd_dma_alloc_pages(&substream->dma_device, size, &new_dmab) < 0 ||
new_dmab.area == NULL) {
if (snd_dma_alloc_pages(&substream->dma_device, size, &new_dmab) < 0) {
buffer->error = -ENOMEM;
return;
}
substream->buffer_bytes_max = size;
snd_dma_free_reserved(&substream->dma_device);
} else {
substream->buffer_bytes_max = UINT_MAX;
}
......@@ -346,13 +350,12 @@ int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
snd_pcm_lib_free_pages(substream);
}
if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
dmab = substream->dma_buffer;
dmab = substream->dma_buffer; /* use the pre-allocated buffer */
} else {
memset(&dmab, 0, sizeof(dmab));
snd_dma_alloc_pages(&substream->dma_device, size, &dmab);
memset(&dmab, 0, sizeof(dmab)); /* allocate a new buffer */
if (snd_dma_alloc_pages(&substream->dma_device, size, &dmab) < 0)
return -ENOMEM;
}
if (! dmab.area)
return -ENOMEM;
runtime->dma_area = dmab.area;
runtime->dma_addr = dmab.addr;
runtime->dma_private = dmab.private_data;
......@@ -378,6 +381,7 @@ int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream)
if (runtime->dma_area == NULL)
return 0;
if (runtime->dma_area != substream->dma_buffer.area) {
/* it's a newly allocated buffer. release it now. */
struct snd_dma_buffer dmab;
memset(&dmab, 0, sizeof(dmab));
dmab.area = runtime->dma_area;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment