502 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Digital Audio (PCM) abstract layer4 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>5 */6 7#include <linux/io.h>8#include <linux/time.h>9#include <linux/init.h>10#include <linux/slab.h>11#include <linux/moduleparam.h>12#include <linux/export.h>13#include <sound/core.h>14#include <sound/pcm.h>15#include <sound/info.h>16#include <sound/initval.h>17#include "pcm_local.h"18 19static int preallocate_dma = 1;20module_param(preallocate_dma, int, 0444);21MODULE_PARM_DESC(preallocate_dma, "Preallocate DMA memory when the PCM devices are initialized.");22 23static int maximum_substreams = 4;24module_param(maximum_substreams, int, 0444);25MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA memory.");26 27static const size_t snd_minimum_buffer = 16384;28 29static unsigned long max_alloc_per_card = 32UL * 1024UL * 1024UL;30module_param(max_alloc_per_card, ulong, 0644);31MODULE_PARM_DESC(max_alloc_per_card, "Max total allocation bytes per card.");32 33static void __update_allocated_size(struct snd_card *card, ssize_t bytes)34{35 card->total_pcm_alloc_bytes += bytes;36}37 38static void update_allocated_size(struct snd_card *card, ssize_t bytes)39{40 guard(mutex)(&card->memory_mutex);41 __update_allocated_size(card, bytes);42}43 44static void decrease_allocated_size(struct snd_card *card, size_t bytes)45{46 guard(mutex)(&card->memory_mutex);47 WARN_ON(card->total_pcm_alloc_bytes < bytes);48 __update_allocated_size(card, -(ssize_t)bytes);49}50 51static int do_alloc_pages(struct snd_card *card, int type, struct device *dev,52 int str, size_t size, struct snd_dma_buffer *dmab)53{54 enum dma_data_direction dir;55 int err;56 57 /* check and reserve the requested size */58 scoped_guard(mutex, &card->memory_mutex) {59 if (max_alloc_per_card &&60 card->total_pcm_alloc_bytes + size > max_alloc_per_card)61 return -ENOMEM;62 __update_allocated_size(card, size);63 }64 65 if (str == SNDRV_PCM_STREAM_PLAYBACK)66 dir = DMA_TO_DEVICE;67 else68 dir = DMA_FROM_DEVICE;69 err = snd_dma_alloc_dir_pages(type, dev, dir, size, dmab);70 if (!err) {71 /* the actual allocation size might be bigger than requested,72 * and we need to correct the account73 */74 if (dmab->bytes != size)75 update_allocated_size(card, dmab->bytes - size);76 } else {77 /* take back on allocation failure */78 decrease_allocated_size(card, size);79 }80 return err;81}82 83static void do_free_pages(struct snd_card *card, struct snd_dma_buffer *dmab)84{85 if (!dmab->area)86 return;87 decrease_allocated_size(card, dmab->bytes);88 snd_dma_free_pages(dmab);89 dmab->area = NULL;90}91 92/*93 * try to allocate as the large pages as possible.94 * stores the resultant memory size in *res_size.95 *96 * the minimum size is snd_minimum_buffer. it should be power of 2.97 */98static int preallocate_pcm_pages(struct snd_pcm_substream *substream,99 size_t size, bool no_fallback)100{101 struct snd_dma_buffer *dmab = &substream->dma_buffer;102 struct snd_card *card = substream->pcm->card;103 size_t orig_size = size;104 int err;105 106 do {107 err = do_alloc_pages(card, dmab->dev.type, dmab->dev.dev,108 substream->stream, size, dmab);109 if (err != -ENOMEM)110 return err;111 if (no_fallback)112 break;113 size >>= 1;114 } while (size >= snd_minimum_buffer);115 dmab->bytes = 0; /* tell error */116 pr_warn("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",117 substream->pcm->card->number, substream->pcm->device,118 substream->stream ? 'c' : 'p', substream->number,119 substream->pcm->name, orig_size);120 return -ENOMEM;121}122 123/**124 * snd_pcm_lib_preallocate_free - release the preallocated buffer of the specified substream.125 * @substream: the pcm substream instance126 *127 * Releases the pre-allocated buffer of the given substream.128 */129void snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)130{131 do_free_pages(substream->pcm->card, &substream->dma_buffer);132}133 134/**135 * snd_pcm_lib_preallocate_free_for_all - release all pre-allocated buffers on the pcm136 * @pcm: the pcm instance137 *138 * Releases all the pre-allocated buffers on the given pcm.139 */140void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)141{142 struct snd_pcm_substream *substream;143 int stream;144 145 for_each_pcm_substream(pcm, stream, substream)146 snd_pcm_lib_preallocate_free(substream);147}148EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);149 150#ifdef CONFIG_SND_VERBOSE_PROCFS151/*152 * read callback for prealloc proc file153 *154 * prints the current allocated size in kB.155 */156static void snd_pcm_lib_preallocate_proc_read(struct snd_info_entry *entry,157 struct snd_info_buffer *buffer)158{159 struct snd_pcm_substream *substream = entry->private_data;160 snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_buffer.bytes / 1024);161}162 163/*164 * read callback for prealloc_max proc file165 *166 * prints the maximum allowed size in kB.167 */168static void snd_pcm_lib_preallocate_max_proc_read(struct snd_info_entry *entry,169 struct snd_info_buffer *buffer)170{171 struct snd_pcm_substream *substream = entry->private_data;172 snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_max / 1024);173}174 175/*176 * write callback for prealloc proc file177 *178 * accepts the preallocation size in kB.179 */180static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,181 struct snd_info_buffer *buffer)182{183 struct snd_pcm_substream *substream = entry->private_data;184 struct snd_card *card = substream->pcm->card;185 char line[64], str[64];186 unsigned long size;187 struct snd_dma_buffer new_dmab;188 189 guard(mutex)(&substream->pcm->open_mutex);190 if (substream->runtime) {191 buffer->error = -EBUSY;192 return;193 }194 if (!snd_info_get_line(buffer, line, sizeof(line))) {195 snd_info_get_str(str, line, sizeof(str));196 buffer->error = kstrtoul(str, 10, &size);197 if (buffer->error != 0)198 return;199 size *= 1024;200 if ((size != 0 && size < 8192) || size > substream->dma_max) {201 buffer->error = -EINVAL;202 return;203 }204 if (substream->dma_buffer.bytes == size)205 return;206 memset(&new_dmab, 0, sizeof(new_dmab));207 new_dmab.dev = substream->dma_buffer.dev;208 if (size > 0) {209 if (do_alloc_pages(card,210 substream->dma_buffer.dev.type,211 substream->dma_buffer.dev.dev,212 substream->stream,213 size, &new_dmab) < 0) {214 buffer->error = -ENOMEM;215 pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %lu\n",216 substream->pcm->card->number, substream->pcm->device,217 substream->stream ? 'c' : 'p', substream->number,218 substream->pcm->name, size);219 return;220 }221 substream->buffer_bytes_max = size;222 } else {223 substream->buffer_bytes_max = UINT_MAX;224 }225 if (substream->dma_buffer.area)226 do_free_pages(card, &substream->dma_buffer);227 substream->dma_buffer = new_dmab;228 } else {229 buffer->error = -EINVAL;230 }231}232 233static inline void preallocate_info_init(struct snd_pcm_substream *substream)234{235 struct snd_info_entry *entry;236 237 entry = snd_info_create_card_entry(substream->pcm->card, "prealloc",238 substream->proc_root);239 if (entry) {240 snd_info_set_text_ops(entry, substream,241 snd_pcm_lib_preallocate_proc_read);242 entry->c.text.write = snd_pcm_lib_preallocate_proc_write;243 entry->mode |= 0200;244 }245 entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max",246 substream->proc_root);247 if (entry)248 snd_info_set_text_ops(entry, substream,249 snd_pcm_lib_preallocate_max_proc_read);250}251 252#else /* !CONFIG_SND_VERBOSE_PROCFS */253static inline void preallocate_info_init(struct snd_pcm_substream *substream)254{255}256#endif /* CONFIG_SND_VERBOSE_PROCFS */257 258/*259 * pre-allocate the buffer and create a proc file for the substream260 */261static int preallocate_pages(struct snd_pcm_substream *substream,262 int type, struct device *data,263 size_t size, size_t max, bool managed)264{265 int err;266 267 if (snd_BUG_ON(substream->dma_buffer.dev.type))268 return -EINVAL;269 270 substream->dma_buffer.dev.type = type;271 substream->dma_buffer.dev.dev = data;272 273 if (size > 0) {274 if (!max) {275 /* no fallback, only also inform -ENOMEM */276 err = preallocate_pcm_pages(substream, size, true);277 if (err < 0)278 return err;279 } else if (preallocate_dma &&280 substream->number < maximum_substreams) {281 err = preallocate_pcm_pages(substream, size, false);282 if (err < 0 && err != -ENOMEM)283 return err;284 }285 }286 287 if (substream->dma_buffer.bytes > 0)288 substream->buffer_bytes_max = substream->dma_buffer.bytes;289 substream->dma_max = max;290 if (max > 0)291 preallocate_info_init(substream);292 if (managed)293 substream->managed_buffer_alloc = 1;294 return 0;295}296 297static int preallocate_pages_for_all(struct snd_pcm *pcm, int type,298 void *data, size_t size, size_t max,299 bool managed)300{301 struct snd_pcm_substream *substream;302 int stream, err;303 304 for_each_pcm_substream(pcm, stream, substream) {305 err = preallocate_pages(substream, type, data, size, max, managed);306 if (err < 0)307 return err;308 }309 return 0;310}311 312/**313 * snd_pcm_lib_preallocate_pages - pre-allocation for the given DMA type314 * @substream: the pcm substream instance315 * @type: DMA type (SNDRV_DMA_TYPE_*)316 * @data: DMA type dependent data317 * @size: the requested pre-allocation size in bytes318 * @max: the max. allowed pre-allocation size319 *320 * Do pre-allocation for the given DMA buffer type.321 */322void snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,323 int type, struct device *data,324 size_t size, size_t max)325{326 preallocate_pages(substream, type, data, size, max, false);327}328EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);329 330/**331 * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continuous memory type (all substreams)332 * @pcm: the pcm instance333 * @type: DMA type (SNDRV_DMA_TYPE_*)334 * @data: DMA type dependent data335 * @size: the requested pre-allocation size in bytes336 * @max: the max. allowed pre-allocation size337 *338 * Do pre-allocation to all substreams of the given pcm for the339 * specified DMA type.340 */341void snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,342 int type, void *data,343 size_t size, size_t max)344{345 preallocate_pages_for_all(pcm, type, data, size, max, false);346}347EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);348 349/**350 * snd_pcm_set_managed_buffer - set up buffer management for a substream351 * @substream: the pcm substream instance352 * @type: DMA type (SNDRV_DMA_TYPE_*)353 * @data: DMA type dependent data354 * @size: the requested pre-allocation size in bytes355 * @max: the max. allowed pre-allocation size356 *357 * Do pre-allocation for the given DMA buffer type, and set the managed358 * buffer allocation mode to the given substream.359 * In this mode, PCM core will allocate a buffer automatically before PCM360 * hw_params ops call, and release the buffer after PCM hw_free ops call361 * as well, so that the driver doesn't need to invoke the allocation and362 * the release explicitly in its callback.363 * When a buffer is actually allocated before the PCM hw_params call, it364 * turns on the runtime buffer_changed flag for drivers changing their h/w365 * parameters accordingly.366 *367 * When @size is non-zero and @max is zero, this tries to allocate for only368 * the exact buffer size without fallback, and may return -ENOMEM.369 * Otherwise, the function tries to allocate smaller chunks if the allocation370 * fails. This is the behavior of snd_pcm_set_fixed_buffer().371 *372 * When both @size and @max are zero, the function only sets up the buffer373 * for later dynamic allocations. It's used typically for buffers with374 * SNDRV_DMA_TYPE_VMALLOC type.375 *376 * Upon successful buffer allocation and setup, the function returns 0.377 *378 * Return: zero if successful, or a negative error code379 */380int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,381 struct device *data, size_t size, size_t max)382{383 return preallocate_pages(substream, type, data, size, max, true);384}385EXPORT_SYMBOL(snd_pcm_set_managed_buffer);386 387/**388 * snd_pcm_set_managed_buffer_all - set up buffer management for all substreams389 * for all substreams390 * @pcm: the pcm instance391 * @type: DMA type (SNDRV_DMA_TYPE_*)392 * @data: DMA type dependent data393 * @size: the requested pre-allocation size in bytes394 * @max: the max. allowed pre-allocation size395 *396 * Do pre-allocation to all substreams of the given pcm for the specified DMA397 * type and size, and set the managed_buffer_alloc flag to each substream.398 *399 * Return: zero if successful, or a negative error code400 */401int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,402 struct device *data,403 size_t size, size_t max)404{405 return preallocate_pages_for_all(pcm, type, data, size, max, true);406}407EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all);408 409/**410 * snd_pcm_lib_malloc_pages - allocate the DMA buffer411 * @substream: the substream to allocate the DMA buffer to412 * @size: the requested buffer size in bytes413 *414 * Allocates the DMA buffer on the BUS type given earlier to415 * snd_pcm_lib_preallocate_xxx_pages().416 *417 * Return: 1 if the buffer is changed, 0 if not changed, or a negative418 * code on failure.419 */420int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)421{422 struct snd_card *card;423 struct snd_pcm_runtime *runtime;424 struct snd_dma_buffer *dmab = NULL;425 426 if (PCM_RUNTIME_CHECK(substream))427 return -EINVAL;428 if (snd_BUG_ON(substream->dma_buffer.dev.type ==429 SNDRV_DMA_TYPE_UNKNOWN))430 return -EINVAL;431 runtime = substream->runtime;432 card = substream->pcm->card;433 434 if (runtime->dma_buffer_p) {435 /* perphaps, we might free the large DMA memory region436 to save some space here, but the actual solution437 costs us less time */438 if (runtime->dma_buffer_p->bytes >= size) {439 runtime->dma_bytes = size;440 return 0; /* ok, do not change */441 }442 snd_pcm_lib_free_pages(substream);443 }444 if (substream->dma_buffer.area != NULL &&445 substream->dma_buffer.bytes >= size) {446 dmab = &substream->dma_buffer; /* use the pre-allocated buffer */447 } else {448 /* dma_max=0 means the fixed size preallocation */449 if (substream->dma_buffer.area && !substream->dma_max)450 return -ENOMEM;451 dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);452 if (! dmab)453 return -ENOMEM;454 dmab->dev = substream->dma_buffer.dev;455 if (do_alloc_pages(card,456 substream->dma_buffer.dev.type,457 substream->dma_buffer.dev.dev,458 substream->stream,459 size, dmab) < 0) {460 kfree(dmab);461 pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",462 substream->pcm->card->number, substream->pcm->device,463 substream->stream ? 'c' : 'p', substream->number,464 substream->pcm->name, size);465 return -ENOMEM;466 }467 }468 snd_pcm_set_runtime_buffer(substream, dmab);469 runtime->dma_bytes = size;470 return 1; /* area was changed */471}472EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);473 474/**475 * snd_pcm_lib_free_pages - release the allocated DMA buffer.476 * @substream: the substream to release the DMA buffer477 *478 * Releases the DMA buffer allocated via snd_pcm_lib_malloc_pages().479 *480 * Return: Zero if successful, or a negative error code on failure.481 */482int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)483{484 struct snd_pcm_runtime *runtime;485 486 if (PCM_RUNTIME_CHECK(substream))487 return -EINVAL;488 runtime = substream->runtime;489 if (runtime->dma_area == NULL)490 return 0;491 if (runtime->dma_buffer_p != &substream->dma_buffer) {492 struct snd_card *card = substream->pcm->card;493 494 /* it's a newly allocated buffer. release it now. */495 do_free_pages(card, runtime->dma_buffer_p);496 kfree(runtime->dma_buffer_p);497 }498 snd_pcm_set_runtime_buffer(substream, NULL);499 return 0;500}501EXPORT_SYMBOL(snd_pcm_lib_free_pages);502