0001
0002
0003
0004
0005
0006
0007 #include <linux/io.h>
0008 #include <linux/time.h>
0009 #include <linux/init.h>
0010 #include <linux/slab.h>
0011 #include <linux/moduleparam.h>
0012 #include <linux/vmalloc.h>
0013 #include <linux/export.h>
0014 #include <sound/core.h>
0015 #include <sound/pcm.h>
0016 #include <sound/info.h>
0017 #include <sound/initval.h>
0018 #include "pcm_local.h"
0019
0020 static int preallocate_dma = 1;
0021 module_param(preallocate_dma, int, 0444);
0022 MODULE_PARM_DESC(preallocate_dma, "Preallocate DMA memory when the PCM devices are initialized.");
0023
0024 static int maximum_substreams = 4;
0025 module_param(maximum_substreams, int, 0444);
0026 MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA memory.");
0027
0028 static const size_t snd_minimum_buffer = 16384;
0029
0030 static unsigned long max_alloc_per_card = 32UL * 1024UL * 1024UL;
0031 module_param(max_alloc_per_card, ulong, 0644);
0032 MODULE_PARM_DESC(max_alloc_per_card, "Max total allocation bytes per card.");
0033
0034 static int do_alloc_pages(struct snd_card *card, int type, struct device *dev,
0035 int str, size_t size, struct snd_dma_buffer *dmab)
0036 {
0037 enum dma_data_direction dir;
0038 int err;
0039
0040 if (max_alloc_per_card &&
0041 card->total_pcm_alloc_bytes + size > max_alloc_per_card)
0042 return -ENOMEM;
0043
0044 if (str == SNDRV_PCM_STREAM_PLAYBACK)
0045 dir = DMA_TO_DEVICE;
0046 else
0047 dir = DMA_FROM_DEVICE;
0048 err = snd_dma_alloc_dir_pages(type, dev, dir, size, dmab);
0049 if (!err) {
0050 mutex_lock(&card->memory_mutex);
0051 card->total_pcm_alloc_bytes += dmab->bytes;
0052 mutex_unlock(&card->memory_mutex);
0053 }
0054 return err;
0055 }
0056
0057 static void do_free_pages(struct snd_card *card, struct snd_dma_buffer *dmab)
0058 {
0059 if (!dmab->area)
0060 return;
0061 mutex_lock(&card->memory_mutex);
0062 WARN_ON(card->total_pcm_alloc_bytes < dmab->bytes);
0063 card->total_pcm_alloc_bytes -= dmab->bytes;
0064 mutex_unlock(&card->memory_mutex);
0065 snd_dma_free_pages(dmab);
0066 dmab->area = NULL;
0067 }
0068
0069
0070
0071
0072
0073
0074
0075 static int preallocate_pcm_pages(struct snd_pcm_substream *substream,
0076 size_t size, bool no_fallback)
0077 {
0078 struct snd_dma_buffer *dmab = &substream->dma_buffer;
0079 struct snd_card *card = substream->pcm->card;
0080 size_t orig_size = size;
0081 int err;
0082
0083 do {
0084 err = do_alloc_pages(card, dmab->dev.type, dmab->dev.dev,
0085 substream->stream, size, dmab);
0086 if (err != -ENOMEM)
0087 return err;
0088 if (no_fallback)
0089 break;
0090 size >>= 1;
0091 } while (size >= snd_minimum_buffer);
0092 dmab->bytes = 0;
0093 pr_warn("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
0094 substream->pcm->card->number, substream->pcm->device,
0095 substream->stream ? 'c' : 'p', substream->number,
0096 substream->pcm->name, orig_size);
0097 return -ENOMEM;
0098 }
0099
0100
0101
0102
0103
0104
0105
0106 void snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
0107 {
0108 do_free_pages(substream->pcm->card, &substream->dma_buffer);
0109 }
0110
0111
0112
0113
0114
0115
0116
0117 void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
0118 {
0119 struct snd_pcm_substream *substream;
0120 int stream;
0121
0122 for_each_pcm_substream(pcm, stream, substream)
0123 snd_pcm_lib_preallocate_free(substream);
0124 }
0125 EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
0126
0127 #ifdef CONFIG_SND_VERBOSE_PROCFS
0128
0129
0130
0131
0132
0133 static void snd_pcm_lib_preallocate_proc_read(struct snd_info_entry *entry,
0134 struct snd_info_buffer *buffer)
0135 {
0136 struct snd_pcm_substream *substream = entry->private_data;
0137 snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_buffer.bytes / 1024);
0138 }
0139
0140
0141
0142
0143
0144
0145 static void snd_pcm_lib_preallocate_max_proc_read(struct snd_info_entry *entry,
0146 struct snd_info_buffer *buffer)
0147 {
0148 struct snd_pcm_substream *substream = entry->private_data;
0149 snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_max / 1024);
0150 }
0151
0152
0153
0154
0155
0156
0157 static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
0158 struct snd_info_buffer *buffer)
0159 {
0160 struct snd_pcm_substream *substream = entry->private_data;
0161 struct snd_card *card = substream->pcm->card;
0162 char line[64], str[64];
0163 size_t size;
0164 struct snd_dma_buffer new_dmab;
0165
0166 mutex_lock(&substream->pcm->open_mutex);
0167 if (substream->runtime) {
0168 buffer->error = -EBUSY;
0169 goto unlock;
0170 }
0171 if (!snd_info_get_line(buffer, line, sizeof(line))) {
0172 snd_info_get_str(str, line, sizeof(str));
0173 size = simple_strtoul(str, NULL, 10) * 1024;
0174 if ((size != 0 && size < 8192) || size > substream->dma_max) {
0175 buffer->error = -EINVAL;
0176 goto unlock;
0177 }
0178 if (substream->dma_buffer.bytes == size)
0179 goto unlock;
0180 memset(&new_dmab, 0, sizeof(new_dmab));
0181 new_dmab.dev = substream->dma_buffer.dev;
0182 if (size > 0) {
0183 if (do_alloc_pages(card,
0184 substream->dma_buffer.dev.type,
0185 substream->dma_buffer.dev.dev,
0186 substream->stream,
0187 size, &new_dmab) < 0) {
0188 buffer->error = -ENOMEM;
0189 pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
0190 substream->pcm->card->number, substream->pcm->device,
0191 substream->stream ? 'c' : 'p', substream->number,
0192 substream->pcm->name, size);
0193 goto unlock;
0194 }
0195 substream->buffer_bytes_max = size;
0196 } else {
0197 substream->buffer_bytes_max = UINT_MAX;
0198 }
0199 if (substream->dma_buffer.area)
0200 do_free_pages(card, &substream->dma_buffer);
0201 substream->dma_buffer = new_dmab;
0202 } else {
0203 buffer->error = -EINVAL;
0204 }
0205 unlock:
0206 mutex_unlock(&substream->pcm->open_mutex);
0207 }
0208
0209 static inline void preallocate_info_init(struct snd_pcm_substream *substream)
0210 {
0211 struct snd_info_entry *entry;
0212
0213 entry = snd_info_create_card_entry(substream->pcm->card, "prealloc",
0214 substream->proc_root);
0215 if (entry) {
0216 snd_info_set_text_ops(entry, substream,
0217 snd_pcm_lib_preallocate_proc_read);
0218 entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
0219 entry->mode |= 0200;
0220 }
0221 entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max",
0222 substream->proc_root);
0223 if (entry)
0224 snd_info_set_text_ops(entry, substream,
0225 snd_pcm_lib_preallocate_max_proc_read);
0226 }
0227
0228 #else
0229 static inline void preallocate_info_init(struct snd_pcm_substream *substream)
0230 {
0231 }
0232 #endif
0233
0234
0235
0236
0237 static int preallocate_pages(struct snd_pcm_substream *substream,
0238 int type, struct device *data,
0239 size_t size, size_t max, bool managed)
0240 {
0241 int err;
0242
0243 if (snd_BUG_ON(substream->dma_buffer.dev.type))
0244 return -EINVAL;
0245
0246 substream->dma_buffer.dev.type = type;
0247 substream->dma_buffer.dev.dev = data;
0248
0249 if (size > 0) {
0250 if (!max) {
0251
0252 err = preallocate_pcm_pages(substream, size, true);
0253 if (err < 0)
0254 return err;
0255 } else if (preallocate_dma &&
0256 substream->number < maximum_substreams) {
0257 err = preallocate_pcm_pages(substream, size, false);
0258 if (err < 0 && err != -ENOMEM)
0259 return err;
0260 }
0261 }
0262
0263 if (substream->dma_buffer.bytes > 0)
0264 substream->buffer_bytes_max = substream->dma_buffer.bytes;
0265 substream->dma_max = max;
0266 if (max > 0)
0267 preallocate_info_init(substream);
0268 if (managed)
0269 substream->managed_buffer_alloc = 1;
0270 return 0;
0271 }
0272
0273 static int preallocate_pages_for_all(struct snd_pcm *pcm, int type,
0274 void *data, size_t size, size_t max,
0275 bool managed)
0276 {
0277 struct snd_pcm_substream *substream;
0278 int stream, err;
0279
0280 for_each_pcm_substream(pcm, stream, substream) {
0281 err = preallocate_pages(substream, type, data, size, max, managed);
0282 if (err < 0)
0283 return err;
0284 }
0285 return 0;
0286 }
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 void snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
0299 int type, struct device *data,
0300 size_t size, size_t max)
0301 {
0302 preallocate_pages(substream, type, data, size, max, false);
0303 }
0304 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317 void snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
0318 int type, void *data,
0319 size_t size, size_t max)
0320 {
0321 preallocate_pages_for_all(pcm, type, data, size, max, false);
0322 }
0323 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
0357 struct device *data, size_t size, size_t max)
0358 {
0359 return preallocate_pages(substream, type, data, size, max, true);
0360 }
0361 EXPORT_SYMBOL(snd_pcm_set_managed_buffer);
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377 int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
0378 struct device *data,
0379 size_t size, size_t max)
0380 {
0381 return preallocate_pages_for_all(pcm, type, data, size, max, true);
0382 }
0383 EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all);
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
0397 {
0398 struct snd_card *card;
0399 struct snd_pcm_runtime *runtime;
0400 struct snd_dma_buffer *dmab = NULL;
0401
0402 if (PCM_RUNTIME_CHECK(substream))
0403 return -EINVAL;
0404 if (snd_BUG_ON(substream->dma_buffer.dev.type ==
0405 SNDRV_DMA_TYPE_UNKNOWN))
0406 return -EINVAL;
0407 runtime = substream->runtime;
0408 card = substream->pcm->card;
0409
0410 if (runtime->dma_buffer_p) {
0411
0412
0413
0414 if (runtime->dma_buffer_p->bytes >= size) {
0415 runtime->dma_bytes = size;
0416 return 0;
0417 }
0418 snd_pcm_lib_free_pages(substream);
0419 }
0420 if (substream->dma_buffer.area != NULL &&
0421 substream->dma_buffer.bytes >= size) {
0422 dmab = &substream->dma_buffer;
0423 } else {
0424
0425 if (substream->dma_buffer.area && !substream->dma_max)
0426 return -ENOMEM;
0427 dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
0428 if (! dmab)
0429 return -ENOMEM;
0430 dmab->dev = substream->dma_buffer.dev;
0431 if (do_alloc_pages(card,
0432 substream->dma_buffer.dev.type,
0433 substream->dma_buffer.dev.dev,
0434 substream->stream,
0435 size, dmab) < 0) {
0436 kfree(dmab);
0437 pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
0438 substream->pcm->card->number, substream->pcm->device,
0439 substream->stream ? 'c' : 'p', substream->number,
0440 substream->pcm->name, size);
0441 return -ENOMEM;
0442 }
0443 }
0444 snd_pcm_set_runtime_buffer(substream, dmab);
0445 runtime->dma_bytes = size;
0446 return 1;
0447 }
0448 EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458 int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
0459 {
0460 struct snd_pcm_runtime *runtime;
0461
0462 if (PCM_RUNTIME_CHECK(substream))
0463 return -EINVAL;
0464 runtime = substream->runtime;
0465 if (runtime->dma_area == NULL)
0466 return 0;
0467 if (runtime->dma_buffer_p != &substream->dma_buffer) {
0468 struct snd_card *card = substream->pcm->card;
0469
0470
0471 do_free_pages(card, runtime->dma_buffer_p);
0472 kfree(runtime->dma_buffer_p);
0473 }
0474 snd_pcm_set_runtime_buffer(substream, NULL);
0475 return 0;
0476 }
0477 EXPORT_SYMBOL(snd_pcm_lib_free_pages);
0478
0479 int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
0480 size_t size, gfp_t gfp_flags)
0481 {
0482 struct snd_pcm_runtime *runtime;
0483
0484 if (PCM_RUNTIME_CHECK(substream))
0485 return -EINVAL;
0486 runtime = substream->runtime;
0487 if (runtime->dma_area) {
0488 if (runtime->dma_bytes >= size)
0489 return 0;
0490 vfree(runtime->dma_area);
0491 }
0492 runtime->dma_area = __vmalloc(size, gfp_flags);
0493 if (!runtime->dma_area)
0494 return -ENOMEM;
0495 runtime->dma_bytes = size;
0496 return 1;
0497 }
0498 EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer);
0499
0500
0501
0502
0503
0504
0505
0506
0507 int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream)
0508 {
0509 struct snd_pcm_runtime *runtime;
0510
0511 if (PCM_RUNTIME_CHECK(substream))
0512 return -EINVAL;
0513 runtime = substream->runtime;
0514 vfree(runtime->dma_area);
0515 runtime->dma_area = NULL;
0516 return 0;
0517 }
0518 EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer);
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530 struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
0531 unsigned long offset)
0532 {
0533 return vmalloc_to_page(substream->runtime->dma_area + offset);
0534 }
0535 EXPORT_SYMBOL(snd_pcm_lib_get_vmalloc_page);