aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-01-08 10:12:25 -0500
committerTakashi Iwai <tiwai@suse.de>2014-01-09 01:32:10 -0500
commit47d98c026ef9a9888c36f3c4f26b81f548a0ca86 (patch)
tree11601d8b6644c5a2dd75469978151d51ef6fb7e9 /sound/core
parentd7b135410e1b2f5ad64e56df09d133a23aa9fbcb (diff)
ALSA: Remove memory reservation code from memalloc helper
Nowadays we have CMA for obtaining the contiguous memory pages efficiently. Let's kill the old kludge for reserving the memory pages for large buffers. It was rarely useful (only for preserving pages among module reloading or a little help by an early boot scripting), used only by a couple of drivers, and yet it gives too much ugliness than its benefit. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/memalloc.c264
-rw-r--r--sound/core/pcm_memory.c19
2 files changed, 1 insertions, 282 deletions
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index bfaf4f04d91d..be1544ac4613 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -42,22 +42,6 @@ MODULE_LICENSE("GPL");
42 42
43 43
44/* 44/*
45 */
46
47static DEFINE_MUTEX(list_mutex);
48static LIST_HEAD(mem_list_head);
49
50/* buffer preservation list */
51struct snd_mem_list {
52 struct snd_dma_buffer buffer;
53 unsigned int id;
54 struct list_head list;
55};
56
57/* id for pre-allocated buffers */
58#define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1
59
60/*
61 * 45 *
62 * Generic memory allocators 46 * Generic memory allocators
63 * 47 *
@@ -318,251 +302,6 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
318 } 302 }
319} 303}
320 304
321
322/**
323 * snd_dma_get_reserved - get the reserved buffer for the given device
324 * @dmab: the buffer allocation record to store
325 * @id: the buffer id
326 *
327 * Looks for the reserved-buffer list and re-uses if the same buffer
328 * is found in the list. When the buffer is found, it's removed from the free list.
329 *
330 * Return: The size of buffer if the buffer is found, or zero if not found.
331 */
332size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
333{
334 struct snd_mem_list *mem;
335
336 if (WARN_ON(!dmab))
337 return 0;
338
339 mutex_lock(&list_mutex);
340 list_for_each_entry(mem, &mem_list_head, list) {
341 if (mem->id == id &&
342 (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
343 ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
344 struct device *dev = dmab->dev.dev;
345 list_del(&mem->list);
346 *dmab = mem->buffer;
347 if (dmab->dev.dev == NULL)
348 dmab->dev.dev = dev;
349 kfree(mem);
350 mutex_unlock(&list_mutex);
351 return dmab->bytes;
352 }
353 }
354 mutex_unlock(&list_mutex);
355 return 0;
356}
357
358/**
359 * snd_dma_reserve_buf - reserve the buffer
360 * @dmab: the buffer to reserve
361 * @id: the buffer id
362 *
363 * Reserves the given buffer as a reserved buffer.
364 *
365 * Return: Zero if successful, or a negative code on error.
366 */
367int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
368{
369 struct snd_mem_list *mem;
370
371 if (WARN_ON(!dmab))
372 return -EINVAL;
373 mem = kmalloc(sizeof(*mem), GFP_KERNEL);
374 if (! mem)
375 return -ENOMEM;
376 mutex_lock(&list_mutex);
377 mem->buffer = *dmab;
378 mem->id = id;
379 list_add_tail(&mem->list, &mem_list_head);
380 mutex_unlock(&list_mutex);
381 return 0;
382}
383
384/*
385 * purge all reserved buffers
386 */
387static void free_all_reserved_pages(void)
388{
389 struct list_head *p;
390 struct snd_mem_list *mem;
391
392 mutex_lock(&list_mutex);
393 while (! list_empty(&mem_list_head)) {
394 p = mem_list_head.next;
395 mem = list_entry(p, struct snd_mem_list, list);
396 list_del(p);
397 snd_dma_free_pages(&mem->buffer);
398 kfree(mem);
399 }
400 mutex_unlock(&list_mutex);
401}
402
403
404#ifdef CONFIG_PROC_FS
405/*
406 * proc file interface
407 */
408#define SND_MEM_PROC_FILE "driver/snd-page-alloc"
409static struct proc_dir_entry *snd_mem_proc;
410
411static int snd_mem_proc_read(struct seq_file *seq, void *offset)
412{
413 struct snd_mem_list *mem;
414 int devno;
415 static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" };
416
417 mutex_lock(&list_mutex);
418 devno = 0;
419 list_for_each_entry(mem, &mem_list_head, list) {
420 devno++;
421 seq_printf(seq, "buffer %d : ID %08x : type %s\n",
422 devno, mem->id, types[mem->buffer.dev.type]);
423 seq_printf(seq, " addr = 0x%lx, size = %d bytes\n",
424 (unsigned long)mem->buffer.addr,
425 (int)mem->buffer.bytes);
426 }
427 mutex_unlock(&list_mutex);
428 return 0;
429}
430
431static int snd_mem_proc_open(struct inode *inode, struct file *file)
432{
433 return single_open(file, snd_mem_proc_read, NULL);
434}
435
436/* FIXME: for pci only - other bus? */
437#ifdef CONFIG_PCI
438#define gettoken(bufp) strsep(bufp, " \t\n")
439
440static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer,
441 size_t count, loff_t * ppos)
442{
443 char buf[128];
444 char *token, *p;
445
446 if (count > sizeof(buf) - 1)
447 return -EINVAL;
448 if (copy_from_user(buf, buffer, count))
449 return -EFAULT;
450 buf[count] = '\0';
451
452 p = buf;
453 token = gettoken(&p);
454 if (! token || *token == '#')
455 return count;
456 if (strcmp(token, "add") == 0) {
457 char *endp;
458 int vendor, device, size, buffers;
459 long mask;
460 int i, alloced;
461 struct pci_dev *pci;
462
463 if ((token = gettoken(&p)) == NULL ||
464 (vendor = simple_strtol(token, NULL, 0)) <= 0 ||
465 (token = gettoken(&p)) == NULL ||
466 (device = simple_strtol(token, NULL, 0)) <= 0 ||
467 (token = gettoken(&p)) == NULL ||
468 (mask = simple_strtol(token, NULL, 0)) < 0 ||
469 (token = gettoken(&p)) == NULL ||
470 (size = memparse(token, &endp)) < 64*1024 ||
471 size > 16*1024*1024 /* too big */ ||
472 (token = gettoken(&p)) == NULL ||
473 (buffers = simple_strtol(token, NULL, 0)) <= 0 ||
474 buffers > 4) {
475 printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
476 return count;
477 }
478 vendor &= 0xffff;
479 device &= 0xffff;
480
481 alloced = 0;
482 pci = NULL;
483 while ((pci = pci_get_device(vendor, device, pci)) != NULL) {
484 if (mask > 0 && mask < 0xffffffff) {
485 if (pci_set_dma_mask(pci, mask) < 0 ||
486 pci_set_consistent_dma_mask(pci, mask) < 0) {
487 printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
488 pci_dev_put(pci);
489 return count;
490 }
491 }
492 for (i = 0; i < buffers; i++) {
493 struct snd_dma_buffer dmab;
494 memset(&dmab, 0, sizeof(dmab));
495 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
496 size, &dmab) < 0) {
497 printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
498 pci_dev_put(pci);
499 return count;
500 }
501 snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
502 }
503 alloced++;
504 }
505 if (! alloced) {
506 for (i = 0; i < buffers; i++) {
507 struct snd_dma_buffer dmab;
508 memset(&dmab, 0, sizeof(dmab));
509 /* FIXME: We can allocate only in ZONE_DMA
510 * without a device pointer!
511 */
512 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
513 size, &dmab) < 0) {
514 printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
515 break;
516 }
517 snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
518 }
519 }
520 } else if (strcmp(token, "erase") == 0)
521 /* FIXME: need for releasing each buffer chunk? */
522 free_all_reserved_pages();
523 else
524 printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
525 return count;
526}
527#endif /* CONFIG_PCI */
528
529static const struct file_operations snd_mem_proc_fops = {
530 .owner = THIS_MODULE,
531 .open = snd_mem_proc_open,
532 .read = seq_read,
533#ifdef CONFIG_PCI
534 .write = snd_mem_proc_write,
535#endif
536 .llseek = seq_lseek,
537 .release = single_release,
538};
539
540#endif /* CONFIG_PROC_FS */
541
542/*
543 * module entry
544 */
545
546static int __init snd_mem_init(void)
547{
548#ifdef CONFIG_PROC_FS
549 snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL,
550 &snd_mem_proc_fops);
551#endif
552 return 0;
553}
554
555static void __exit snd_mem_exit(void)
556{
557 remove_proc_entry(SND_MEM_PROC_FILE, NULL);
558 free_all_reserved_pages();
559}
560
561
562module_init(snd_mem_init)
563module_exit(snd_mem_exit)
564
565
566/* 305/*
567 * exports 306 * exports
568 */ 307 */
@@ -570,8 +309,5 @@ EXPORT_SYMBOL(snd_dma_alloc_pages);
570EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); 309EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
571EXPORT_SYMBOL(snd_dma_free_pages); 310EXPORT_SYMBOL(snd_dma_free_pages);
572 311
573EXPORT_SYMBOL(snd_dma_get_reserved_buf);
574EXPORT_SYMBOL(snd_dma_reserve_buf);
575
576EXPORT_SYMBOL(snd_malloc_pages); 312EXPORT_SYMBOL(snd_malloc_pages);
577EXPORT_SYMBOL(snd_free_pages); 313EXPORT_SYMBOL(snd_free_pages);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 0af622c34e19..01f8eafebda6 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -53,15 +53,6 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
53 struct snd_dma_buffer *dmab = &substream->dma_buffer; 53 struct snd_dma_buffer *dmab = &substream->dma_buffer;
54 int err; 54 int err;
55 55
56 /* already reserved? */
57 if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) {
58 if (dmab->bytes >= size)
59 return 0; /* yes */
60 /* no, free the reserved block */
61 snd_dma_free_pages(dmab);
62 dmab->bytes = 0;
63 }
64
65 do { 56 do {
66 if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev, 57 if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
67 size, dmab)) < 0) { 58 size, dmab)) < 0) {
@@ -82,10 +73,7 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream
82{ 73{
83 if (substream->dma_buffer.area == NULL) 74 if (substream->dma_buffer.area == NULL)
84 return; 75 return;
85 if (substream->dma_buf_id) 76 snd_dma_free_pages(&substream->dma_buffer);
86 snd_dma_reserve_buf(&substream->dma_buffer, substream->dma_buf_id);
87 else
88 snd_dma_free_pages(&substream->dma_buffer);
89 substream->dma_buffer.area = NULL; 77 substream->dma_buffer.area = NULL;
90} 78}
91 79
@@ -260,11 +248,6 @@ static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
260 * 248 *
261 * Do pre-allocation for the given DMA buffer type. 249 * Do pre-allocation for the given DMA buffer type.
262 * 250 *
263 * When substream->dma_buf_id is set, the function tries to look for
264 * the reserved buffer, and the buffer is not freed but reserved at
265 * destruction time. The dma_buf_id must be unique for all systems
266 * (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
267 *
268 * Return: Zero if successful, or a negative error code on failure. 251 * Return: Zero if successful, or a negative error code on failure.
269 */ 252 */
270int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, 253int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,