aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-05-30 12:27:03 -0400
committerJaroslav Kysela <perex@suse.cz>2005-06-22 06:27:47 -0400
commitb6a969155b04416185f368bd4e2f1d49b17c1ee1 (patch)
treec6db67bdc4b4d107902cf6ced9d66fb0ab15600c /sound/core
parent4d572776d4dfa2d5385a2ec3acec3cc059149e13 (diff)
[ALSA] Add write support to snd-page-alloc proc file
Documentation,Memalloc module,RME HDSP driver,RME9652 driver Add the write support to snd-page-alloc proc file for buffer pre-allocation. Removed the pre-allocation codes via module options. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/memalloc.c201
1 files changed, 109 insertions, 92 deletions
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 344a83fd7c2e..dbc23e35fa06 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -28,6 +28,7 @@
28#include <linux/pci.h> 28#include <linux/pci.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/mm.h> 30#include <linux/mm.h>
31#include <asm/uaccess.h>
31#include <linux/dma-mapping.h> 32#include <linux/dma-mapping.h>
32#include <linux/moduleparam.h> 33#include <linux/moduleparam.h>
33#include <asm/semaphore.h> 34#include <asm/semaphore.h>
@@ -46,13 +47,6 @@ MODULE_LICENSE("GPL");
46#define SNDRV_CARDS 8 47#define SNDRV_CARDS 8
47#endif 48#endif
48 49
49/* FIXME: so far only some PCI devices have the preallocation table */
50#ifdef CONFIG_PCI
51static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
52module_param_array(enable, bool, NULL, 0444);
53MODULE_PARM_DESC(enable, "Enable cards to allocate buffers.");
54#endif
55
56/* 50/*
57 */ 51 */
58 52
@@ -451,9 +445,13 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
451 list_for_each(p, &mem_list_head) { 445 list_for_each(p, &mem_list_head) {
452 mem = list_entry(p, struct snd_mem_list, list); 446 mem = list_entry(p, struct snd_mem_list, list);
453 if (mem->id == id && 447 if (mem->id == id &&
454 ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev))) { 448 (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
449 ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
450 struct device *dev = dmab->dev.dev;
455 list_del(p); 451 list_del(p);
456 *dmab = mem->buffer; 452 *dmab = mem->buffer;
453 if (dmab->dev.dev == NULL)
454 dmab->dev.dev = dev;
457 kfree(mem); 455 kfree(mem);
458 up(&list_mutex); 456 up(&list_mutex);
459 return dmab->bytes; 457 return dmab->bytes;
@@ -508,91 +506,13 @@ static void free_all_reserved_pages(void)
508} 506}
509 507
510 508
511
512/*
513 * allocation of buffers for pre-defined devices
514 */
515
516#ifdef CONFIG_PCI
517/* FIXME: for pci only - other bus? */
518struct prealloc_dev {
519 unsigned short vendor;
520 unsigned short device;
521 unsigned long dma_mask;
522 unsigned int size;
523 unsigned int buffers;
524};
525
526#define HAMMERFALL_BUFFER_SIZE (16*1024*4*(26+1)+0x10000)
527
528static struct prealloc_dev prealloc_devices[] __initdata = {
529 {
530 /* hammerfall */
531 .vendor = 0x10ee,
532 .device = 0x3fc4,
533 .dma_mask = 0xffffffff,
534 .size = HAMMERFALL_BUFFER_SIZE,
535 .buffers = 2
536 },
537 {
538 /* HDSP */
539 .vendor = 0x10ee,
540 .device = 0x3fc5,
541 .dma_mask = 0xffffffff,
542 .size = HAMMERFALL_BUFFER_SIZE,
543 .buffers = 2
544 },
545 { }, /* terminator */
546};
547
548static void __init preallocate_cards(void)
549{
550 struct pci_dev *pci = NULL;
551 int card;
552
553 card = 0;
554
555 while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) {
556 struct prealloc_dev *dev;
557 unsigned int i;
558 if (card >= SNDRV_CARDS)
559 break;
560 for (dev = prealloc_devices; dev->vendor; dev++) {
561 if (dev->vendor == pci->vendor && dev->device == pci->device)
562 break;
563 }
564 if (! dev->vendor)
565 continue;
566 if (! enable[card++]) {
567 printk(KERN_DEBUG "snd-page-alloc: skipping card %d, device %04x:%04x\n", card, pci->vendor, pci->device);
568 continue;
569 }
570
571 if (pci_set_dma_mask(pci, dev->dma_mask) < 0 ||
572 pci_set_consistent_dma_mask(pci, dev->dma_mask) < 0) {
573 printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", dev->dma_mask, dev->vendor, dev->device);
574 continue;
575 }
576 for (i = 0; i < dev->buffers; i++) {
577 struct snd_dma_buffer dmab;
578 memset(&dmab, 0, sizeof(dmab));
579 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
580 dev->size, &dmab) < 0)
581 printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size);
582 else
583 snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
584 }
585 }
586}
587#else
588#define preallocate_cards() /* NOP */
589#endif
590
591
592#ifdef CONFIG_PROC_FS 509#ifdef CONFIG_PROC_FS
593/* 510/*
594 * proc file interface 511 * proc file interface
595 */ 512 */
513#define SND_MEM_PROC_FILE "driver/snd-page-alloc"
514struct proc_dir_entry *snd_mem_proc;
515
596static int snd_mem_proc_read(char *page, char **start, off_t off, 516static int snd_mem_proc_read(char *page, char **start, off_t off,
597 int count, int *eof, void *data) 517 int count, int *eof, void *data)
598{ 518{
@@ -621,6 +541,97 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
621 up(&list_mutex); 541 up(&list_mutex);
622 return len; 542 return len;
623} 543}
544
545/* FIXME: for pci only - other bus? */
546#ifdef CONFIG_PCI
547#define gettoken(bufp) strsep(bufp, " \t\n")
548
549static int snd_mem_proc_write(struct file *file, const char __user *buffer,
550 unsigned long count, void *data)
551{
552 char buf[128];
553 char *token, *p;
554
555 if (count > ARRAY_SIZE(buf) - 1)
556 count = ARRAY_SIZE(buf) - 1;
557 if (copy_from_user(buf, buffer, count))
558 return -EFAULT;
559 buf[ARRAY_SIZE(buf) - 1] = '\0';
560
561 p = buf;
562 token = gettoken(&p);
563 if (! token || *token == '#')
564 return (int)count;
565 if (strcmp(token, "add") == 0) {
566 char *endp;
567 int vendor, device, size, buffers;
568 long mask;
569 int i, alloced;
570 struct pci_dev *pci;
571
572 if ((token = gettoken(&p)) == NULL ||
573 (vendor = simple_strtol(token, NULL, 0)) <= 0 ||
574 (token = gettoken(&p)) == NULL ||
575 (device = simple_strtol(token, NULL, 0)) <= 0 ||
576 (token = gettoken(&p)) == NULL ||
577 (mask = simple_strtol(token, NULL, 0)) < 0 ||
578 (token = gettoken(&p)) == NULL ||
579 (size = memparse(token, &endp)) < 64*1024 ||
580 size > 16*1024*1024 /* too big */ ||
581 (token = gettoken(&p)) == NULL ||
582 (buffers = simple_strtol(token, NULL, 0)) <= 0 ||
583 buffers > 4) {
584 printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
585 return (int)count;
586 }
587 vendor &= 0xffff;
588 device &= 0xffff;
589
590 alloced = 0;
591 pci = NULL;
592 while ((pci = pci_find_device(vendor, device, pci)) != NULL) {
593 if (mask > 0 && mask < 0xffffffff) {
594 if (pci_set_dma_mask(pci, mask) < 0 ||
595 pci_set_consistent_dma_mask(pci, mask) < 0) {
596 printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
597 return (int)count;
598 }
599 }
600 for (i = 0; i < buffers; i++) {
601 struct snd_dma_buffer dmab;
602 memset(&dmab, 0, sizeof(dmab));
603 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
604 size, &dmab) < 0) {
605 printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
606 return (int)count;
607 }
608 snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
609 }
610 alloced++;
611 }
612 if (! alloced) {
613 for (i = 0; i < buffers; i++) {
614 struct snd_dma_buffer dmab;
615 memset(&dmab, 0, sizeof(dmab));
616 /* FIXME: We can allocate only in ZONE_DMA
617 * without a device pointer!
618 */
619 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
620 size, &dmab) < 0) {
621 printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
622 break;
623 }
624 snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
625 }
626 }
627 } else if (strcmp(token, "erase") == 0)
628 /* FIXME: need for releasing each buffer chunk? */
629 free_all_reserved_pages();
630 else
631 printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
632 return (int)count;
633}
634#endif /* CONFIG_PCI */
624#endif /* CONFIG_PROC_FS */ 635#endif /* CONFIG_PROC_FS */
625 636
626/* 637/*
@@ -630,15 +641,21 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
630static int __init snd_mem_init(void) 641static int __init snd_mem_init(void)
631{ 642{
632#ifdef CONFIG_PROC_FS 643#ifdef CONFIG_PROC_FS
633 create_proc_read_entry("driver/snd-page-alloc", 0, NULL, snd_mem_proc_read, NULL); 644 snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL);
645 if (snd_mem_proc) {
646 snd_mem_proc->read_proc = snd_mem_proc_read;
647#ifdef CONFIG_PCI
648 snd_mem_proc->write_proc = snd_mem_proc_write;
649#endif
650 }
634#endif 651#endif
635 preallocate_cards();
636 return 0; 652 return 0;
637} 653}
638 654
639static void __exit snd_mem_exit(void) 655static void __exit snd_mem_exit(void)
640{ 656{
641 remove_proc_entry("driver/snd-page-alloc", NULL); 657 if (snd_mem_proc)
658 remove_proc_entry(SND_MEM_PROC_FILE, NULL);
642 free_all_reserved_pages(); 659 free_all_reserved_pages();
643 if (snd_allocated_pages > 0) 660 if (snd_allocated_pages > 0)
644 printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages); 661 printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages);