Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcm_memory.c
Go to the documentation of this file.
1 /*
2  * Digital Audio (PCM) abstract layer
3  * Copyright (c) by Jaroslav Kysela <[email protected]>
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include <asm/io.h>
23 #include <linux/time.h>
24 #include <linux/init.h>
25 #include <linux/slab.h>
26 #include <linux/moduleparam.h>
27 #include <linux/vmalloc.h>
28 #include <linux/export.h>
29 #include <sound/core.h>
30 #include <sound/pcm.h>
31 #include <sound/info.h>
32 #include <sound/initval.h>
33 
34 static int preallocate_dma = 1;
35 module_param(preallocate_dma, int, 0444);
36 MODULE_PARM_DESC(preallocate_dma, "Preallocate DMA memory when the PCM devices are initialized.");
37 
38 static int maximum_substreams = 4;
39 module_param(maximum_substreams, int, 0444);
40 MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA memory.");
41 
42 static const size_t snd_minimum_buffer = 16384;
43 
44 
45 /*
46  * try to allocate as the large pages as possible.
47  * stores the resultant memory size in *res_size.
48  *
49  * the minimum size is snd_minimum_buffer. it should be power of 2.
50  */
51 static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
52 {
53  struct snd_dma_buffer *dmab = &substream->dma_buffer;
54  int err;
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 {
66  if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
67  size, dmab)) < 0) {
68  if (err != -ENOMEM)
69  return err; /* fatal error */
70  } else
71  return 0;
72  size >>= 1;
73  } while (size >= snd_minimum_buffer);
74  dmab->bytes = 0; /* tell error */
75  return 0;
76 }
77 
78 /*
79  * release the preallocated buffer if not yet done.
80  */
81 static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream)
82 {
83  if (substream->dma_buffer.area == NULL)
84  return;
85  if (substream->dma_buf_id)
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;
90 }
91 
101 {
102  snd_pcm_lib_preallocate_dma_free(substream);
103 #ifdef CONFIG_SND_VERBOSE_PROCFS
104  snd_info_free_entry(substream->proc_prealloc_max_entry);
105  substream->proc_prealloc_max_entry = NULL;
106  snd_info_free_entry(substream->proc_prealloc_entry);
107  substream->proc_prealloc_entry = NULL;
108 #endif
109  return 0;
110 }
111 
121 {
122  struct snd_pcm_substream *substream;
123  int stream;
124 
125  for (stream = 0; stream < 2; stream++)
126  for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
127  snd_pcm_lib_preallocate_free(substream);
128  return 0;
129 }
130 
132 
133 #ifdef CONFIG_SND_VERBOSE_PROCFS
134 /*
135  * read callback for prealloc proc file
136  *
137  * prints the current allocated size in kB.
138  */
139 static void snd_pcm_lib_preallocate_proc_read(struct snd_info_entry *entry,
140  struct snd_info_buffer *buffer)
141 {
142  struct snd_pcm_substream *substream = entry->private_data;
143  snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_buffer.bytes / 1024);
144 }
145 
146 /*
147  * read callback for prealloc_max proc file
148  *
149  * prints the maximum allowed size in kB.
150  */
151 static void snd_pcm_lib_preallocate_max_proc_read(struct snd_info_entry *entry,
152  struct snd_info_buffer *buffer)
153 {
154  struct snd_pcm_substream *substream = entry->private_data;
155  snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_max / 1024);
156 }
157 
158 /*
159  * write callback for prealloc proc file
160  *
161  * accepts the preallocation size in kB.
162  */
163 static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
164  struct snd_info_buffer *buffer)
165 {
166  struct snd_pcm_substream *substream = entry->private_data;
167  char line[64], str[64];
168  size_t size;
169  struct snd_dma_buffer new_dmab;
170 
171  if (substream->runtime) {
172  buffer->error = -EBUSY;
173  return;
174  }
175  if (!snd_info_get_line(buffer, line, sizeof(line))) {
176  snd_info_get_str(str, line, sizeof(str));
177  size = simple_strtoul(str, NULL, 10) * 1024;
178  if ((size != 0 && size < 8192) || size > substream->dma_max) {
179  buffer->error = -EINVAL;
180  return;
181  }
182  if (substream->dma_buffer.bytes == size)
183  return;
184  memset(&new_dmab, 0, sizeof(new_dmab));
185  new_dmab.dev = substream->dma_buffer.dev;
186  if (size > 0) {
187  if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
188  substream->dma_buffer.dev.dev,
189  size, &new_dmab) < 0) {
190  buffer->error = -ENOMEM;
191  return;
192  }
193  substream->buffer_bytes_max = size;
194  } else {
195  substream->buffer_bytes_max = UINT_MAX;
196  }
197  if (substream->dma_buffer.area)
198  snd_dma_free_pages(&substream->dma_buffer);
199  substream->dma_buffer = new_dmab;
200  } else {
201  buffer->error = -EINVAL;
202  }
203 }
204 
205 static inline void preallocate_info_init(struct snd_pcm_substream *substream)
206 {
207  struct snd_info_entry *entry;
208 
209  if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
210  entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
211  entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
212  entry->mode |= S_IWUSR;
213  entry->private_data = substream;
214  if (snd_info_register(entry) < 0) {
215  snd_info_free_entry(entry);
216  entry = NULL;
217  }
218  }
219  substream->proc_prealloc_entry = entry;
220  if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max", substream->proc_root)) != NULL) {
221  entry->c.text.read = snd_pcm_lib_preallocate_max_proc_read;
222  entry->private_data = substream;
223  if (snd_info_register(entry) < 0) {
224  snd_info_free_entry(entry);
225  entry = NULL;
226  }
227  }
228  substream->proc_prealloc_max_entry = entry;
229 }
230 
231 #else /* !CONFIG_SND_VERBOSE_PROCFS */
232 #define preallocate_info_init(s)
233 #endif /* CONFIG_SND_VERBOSE_PROCFS */
234 
235 /*
236  * pre-allocate the buffer and create a proc file for the substream
237  */
238 static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
239  size_t size, size_t max)
240 {
241 
242  if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
243  preallocate_pcm_pages(substream, size);
244 
245  if (substream->dma_buffer.bytes > 0)
246  substream->buffer_bytes_max = substream->dma_buffer.bytes;
247  substream->dma_max = max;
248  preallocate_info_init(substream);
249  return 0;
250 }
251 
252 
271  int type, struct device *data,
272  size_t size, size_t max)
273 {
274  substream->dma_buffer.dev.type = type;
275  substream->dma_buffer.dev.dev = data;
276  return snd_pcm_lib_preallocate_pages1(substream, size, max);
277 }
278 
280 
295  int type, void *data,
296  size_t size, size_t max)
297 {
298  struct snd_pcm_substream *substream;
299  int stream, err;
300 
301  for (stream = 0; stream < 2; stream++)
302  for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
303  if ((err = snd_pcm_lib_preallocate_pages(substream, type, data, size, max)) < 0)
304  return err;
305  return 0;
306 }
307 
309 
310 #ifdef CONFIG_SND_DMA_SGBUF
311 
319 struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset)
320 {
321  struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
322 
323  unsigned int idx = offset >> PAGE_SHIFT;
324  if (idx >= (unsigned int)sgbuf->pages)
325  return NULL;
326  return sgbuf->page_table[idx];
327 }
328 
330 #endif /* CONFIG_SND_DMA_SGBUF */
331 
343 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
344 {
345  struct snd_pcm_runtime *runtime;
346  struct snd_dma_buffer *dmab = NULL;
347 
348  if (PCM_RUNTIME_CHECK(substream))
349  return -EINVAL;
350  if (snd_BUG_ON(substream->dma_buffer.dev.type ==
352  return -EINVAL;
353  runtime = substream->runtime;
354 
355  if (runtime->dma_buffer_p) {
356  /* perphaps, we might free the large DMA memory region
357  to save some space here, but the actual solution
358  costs us less time */
359  if (runtime->dma_buffer_p->bytes >= size) {
360  runtime->dma_bytes = size;
361  return 0; /* ok, do not change */
362  }
363  snd_pcm_lib_free_pages(substream);
364  }
365  if (substream->dma_buffer.area != NULL &&
366  substream->dma_buffer.bytes >= size) {
367  dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
368  } else {
369  dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
370  if (! dmab)
371  return -ENOMEM;
372  dmab->dev = substream->dma_buffer.dev;
373  if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
374  substream->dma_buffer.dev.dev,
375  size, dmab) < 0) {
376  kfree(dmab);
377  return -ENOMEM;
378  }
379  }
380  snd_pcm_set_runtime_buffer(substream, dmab);
381  runtime->dma_bytes = size;
382  return 1; /* area was changed */
383 }
384 
386 
396 {
397  struct snd_pcm_runtime *runtime;
398 
399  if (PCM_RUNTIME_CHECK(substream))
400  return -EINVAL;
401  runtime = substream->runtime;
402  if (runtime->dma_area == NULL)
403  return 0;
404  if (runtime->dma_buffer_p != &substream->dma_buffer) {
405  /* it's a newly allocated buffer. release it now. */
407  kfree(runtime->dma_buffer_p);
408  }
409  snd_pcm_set_runtime_buffer(substream, NULL);
410  return 0;
411 }
412 
414 
416  size_t size, gfp_t gfp_flags)
417 {
418  struct snd_pcm_runtime *runtime;
419 
420  if (PCM_RUNTIME_CHECK(substream))
421  return -EINVAL;
422  runtime = substream->runtime;
423  if (runtime->dma_area) {
424  if (runtime->dma_bytes >= size)
425  return 0; /* already large enough */
426  vfree(runtime->dma_area);
427  }
428  runtime->dma_area = __vmalloc(size, gfp_flags, PAGE_KERNEL);
429  if (!runtime->dma_area)
430  return -ENOMEM;
431  runtime->dma_bytes = size;
432  return 1;
433 }
435 
442 {
443  struct snd_pcm_runtime *runtime;
444 
445  if (PCM_RUNTIME_CHECK(substream))
446  return -EINVAL;
447  runtime = substream->runtime;
448  vfree(runtime->dma_area);
449  runtime->dma_area = NULL;
450  return 0;
451 }
453 
463  unsigned long offset)
464 {
465  return vmalloc_to_page(substream->runtime->dma_area + offset);
466 }