aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/memalloc.h7
-rw-r--r--include/sound/pcm.h1
-rw-r--r--sound/core/memalloc.c264
-rw-r--r--sound/core/pcm_memory.c19
-rw-r--r--sound/pci/es1968.c28
-rw-r--r--sound/pci/rme9652/hdsp.c10
-rw-r--r--sound/pci/rme9652/rme9652.c10
7 files changed, 18 insertions, 321 deletions
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index 5f73785f5977..782d1df34208 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -149,13 +149,6 @@ int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
149 struct snd_dma_buffer *dmab); 149 struct snd_dma_buffer *dmab);
150void snd_dma_free_pages(struct snd_dma_buffer *dmab); 150void snd_dma_free_pages(struct snd_dma_buffer *dmab);
151 151
152/* buffer-preservation managements */
153
154#define snd_dma_pci_buf_id(pci) (((unsigned int)(pci)->vendor << 16) | (pci)->device)
155
156size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id);
157int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id);
158
159/* basic memory allocation functions */ 152/* basic memory allocation functions */
160void *snd_malloc_pages(size_t size, gfp_t gfp_flags); 153void *snd_malloc_pages(size_t size, gfp_t gfp_flags);
161void snd_free_pages(void *ptr, size_t size); 154void snd_free_pages(void *ptr, size_t size);
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 84b10f9a2832..fe6ca400b9ad 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -381,7 +381,6 @@ struct snd_pcm_substream {
381 struct pm_qos_request latency_pm_qos_req; /* pm_qos request */ 381 struct pm_qos_request latency_pm_qos_req; /* pm_qos request */
382 size_t buffer_bytes_max; /* limit ring buffer size */ 382 size_t buffer_bytes_max; /* limit ring buffer size */
383 struct snd_dma_buffer dma_buffer; 383 struct snd_dma_buffer dma_buffer;
384 unsigned int dma_buf_id;
385 size_t dma_max; 384 size_t dma_max;
386 /* -- hardware operations -- */ 385 /* -- hardware operations -- */
387 const struct snd_pcm_ops *ops; 386 const struct snd_pcm_ops *ops;
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,
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index b0e3d92c4656..772cc36f951d 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -1422,7 +1422,7 @@ static void snd_es1968_free_dmabuf(struct es1968 *chip)
1422 1422
1423 if (! chip->dma.area) 1423 if (! chip->dma.area)
1424 return; 1424 return;
1425 snd_dma_reserve_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci)); 1425 snd_dma_free_pages(&chip->dma);
1426 while ((p = chip->buf_list.next) != &chip->buf_list) { 1426 while ((p = chip->buf_list.next) != &chip->buf_list) {
1427 struct esm_memory *chunk = list_entry(p, struct esm_memory, list); 1427 struct esm_memory *chunk = list_entry(p, struct esm_memory, list);
1428 list_del(p); 1428 list_del(p);
@@ -1438,20 +1438,18 @@ snd_es1968_init_dmabuf(struct es1968 *chip)
1438 1438
1439 chip->dma.dev.type = SNDRV_DMA_TYPE_DEV; 1439 chip->dma.dev.type = SNDRV_DMA_TYPE_DEV;
1440 chip->dma.dev.dev = snd_dma_pci_data(chip->pci); 1440 chip->dma.dev.dev = snd_dma_pci_data(chip->pci);
1441 if (! snd_dma_get_reserved_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci))) { 1441 err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
1442 err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, 1442 snd_dma_pci_data(chip->pci),
1443 snd_dma_pci_data(chip->pci), 1443 chip->total_bufsize, &chip->dma);
1444 chip->total_bufsize, &chip->dma); 1444 if (err < 0 || ! chip->dma.area) {
1445 if (err < 0 || ! chip->dma.area) { 1445 snd_printk(KERN_ERR "es1968: can't allocate dma pages for size %d\n",
1446 snd_printk(KERN_ERR "es1968: can't allocate dma pages for size %d\n", 1446 chip->total_bufsize);
1447 chip->total_bufsize); 1447 return -ENOMEM;
1448 return -ENOMEM; 1448 }
1449 } 1449 if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) {
1450 if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) { 1450 snd_dma_free_pages(&chip->dma);
1451 snd_dma_free_pages(&chip->dma); 1451 snd_printk(KERN_ERR "es1968: DMA buffer beyond 256MB.\n");
1452 snd_printk(KERN_ERR "es1968: DMA buffer beyond 256MB.\n"); 1452 return -ENOMEM;
1453 return -ENOMEM;
1454 }
1455 } 1453 }
1456 1454
1457 INIT_LIST_HEAD(&chip->buf_list); 1455 INIT_LIST_HEAD(&chip->buf_list);
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index f59a321a6d6a..bd90c80bb494 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -584,10 +584,6 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
584{ 584{
585 dmab->dev.type = SNDRV_DMA_TYPE_DEV; 585 dmab->dev.type = SNDRV_DMA_TYPE_DEV;
586 dmab->dev.dev = snd_dma_pci_data(pci); 586 dmab->dev.dev = snd_dma_pci_data(pci);
587 if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
588 if (dmab->bytes >= size)
589 return 0;
590 }
591 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 587 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
592 size, dmab) < 0) 588 size, dmab) < 0)
593 return -ENOMEM; 589 return -ENOMEM;
@@ -596,10 +592,8 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
596 592
597static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) 593static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
598{ 594{
599 if (dmab->area) { 595 if (dmab->area)
600 dmab->dev.dev = NULL; /* make it anonymous */ 596 snd_dma_free_pages(dmab);
601 snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
602 }
603} 597}
604 598
605 599
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 3717f2dd30be..1503ee3585fd 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -294,10 +294,6 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
294{ 294{
295 dmab->dev.type = SNDRV_DMA_TYPE_DEV; 295 dmab->dev.type = SNDRV_DMA_TYPE_DEV;
296 dmab->dev.dev = snd_dma_pci_data(pci); 296 dmab->dev.dev = snd_dma_pci_data(pci);
297 if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
298 if (dmab->bytes >= size)
299 return 0;
300 }
301 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 297 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
302 size, dmab) < 0) 298 size, dmab) < 0)
303 return -ENOMEM; 299 return -ENOMEM;
@@ -306,10 +302,8 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
306 302
307static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) 303static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
308{ 304{
309 if (dmab->area) { 305 if (dmab->area)
310 dmab->dev.dev = NULL; /* make it anonymous */ 306 snd_dma_free_pages(dmab);
311 snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
312 }
313} 307}
314 308
315 309