Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Digital Audio (PCM) abstract layer
0004  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
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  * try to allocate as the large pages as possible.
0071  * stores the resultant memory size in *res_size.
0072  *
0073  * the minimum size is snd_minimum_buffer.  it should be power of 2.
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; /* tell error */
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  * snd_pcm_lib_preallocate_free - release the preallocated buffer of the specified substream.
0102  * @substream: the pcm substream instance
0103  *
0104  * Releases the pre-allocated buffer of the given substream.
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  * snd_pcm_lib_preallocate_free_for_all - release all pre-allocated buffers on the pcm
0113  * @pcm: the pcm instance
0114  *
0115  * Releases all the pre-allocated buffers on the given pcm.
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  * read callback for prealloc proc file
0130  *
0131  * prints the current allocated size in kB.
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  * read callback for prealloc_max proc file
0142  *
0143  * prints the maximum allowed size in kB.
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  * write callback for prealloc proc file
0154  *
0155  * accepts the preallocation size in kB.
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 /* !CONFIG_SND_VERBOSE_PROCFS */
0229 static inline void preallocate_info_init(struct snd_pcm_substream *substream)
0230 {
0231 }
0232 #endif /* CONFIG_SND_VERBOSE_PROCFS */
0233 
0234 /*
0235  * pre-allocate the buffer and create a proc file for the substream
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             /* no fallback, only also inform -ENOMEM */
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  * snd_pcm_lib_preallocate_pages - pre-allocation for the given DMA type
0290  * @substream: the pcm substream instance
0291  * @type: DMA type (SNDRV_DMA_TYPE_*)
0292  * @data: DMA type dependent data
0293  * @size: the requested pre-allocation size in bytes
0294  * @max: the max. allowed pre-allocation size
0295  *
0296  * Do pre-allocation for the given DMA buffer type.
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  * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continuous memory type (all substreams)
0308  * @pcm: the pcm instance
0309  * @type: DMA type (SNDRV_DMA_TYPE_*)
0310  * @data: DMA type dependent data
0311  * @size: the requested pre-allocation size in bytes
0312  * @max: the max. allowed pre-allocation size
0313  *
0314  * Do pre-allocation to all substreams of the given pcm for the
0315  * specified DMA type.
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  * snd_pcm_set_managed_buffer - set up buffer management for a substream
0327  * @substream: the pcm substream instance
0328  * @type: DMA type (SNDRV_DMA_TYPE_*)
0329  * @data: DMA type dependent data
0330  * @size: the requested pre-allocation size in bytes
0331  * @max: the max. allowed pre-allocation size
0332  *
0333  * Do pre-allocation for the given DMA buffer type, and set the managed
0334  * buffer allocation mode to the given substream.
0335  * In this mode, PCM core will allocate a buffer automatically before PCM
0336  * hw_params ops call, and release the buffer after PCM hw_free ops call
0337  * as well, so that the driver doesn't need to invoke the allocation and
0338  * the release explicitly in its callback.
0339  * When a buffer is actually allocated before the PCM hw_params call, it
0340  * turns on the runtime buffer_changed flag for drivers changing their h/w
0341  * parameters accordingly.
0342  *
0343  * When @size is non-zero and @max is zero, this tries to allocate for only
0344  * the exact buffer size without fallback, and may return -ENOMEM.
0345  * Otherwise, the function tries to allocate smaller chunks if the allocation
0346  * fails.  This is the behavior of snd_pcm_set_fixed_buffer().
0347  *
0348  * When both @size and @max are zero, the function only sets up the buffer
0349  * for later dynamic allocations. It's used typically for buffers with
0350  * SNDRV_DMA_TYPE_VMALLOC type.
0351  *
0352  * Upon successful buffer allocation and setup, the function returns 0.
0353  *
0354  * Return: zero if successful, or a negative error code
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  * snd_pcm_set_managed_buffer_all - set up buffer management for all substreams
0365  *  for all substreams
0366  * @pcm: the pcm instance
0367  * @type: DMA type (SNDRV_DMA_TYPE_*)
0368  * @data: DMA type dependent data
0369  * @size: the requested pre-allocation size in bytes
0370  * @max: the max. allowed pre-allocation size
0371  *
0372  * Do pre-allocation to all substreams of the given pcm for the specified DMA
0373  * type and size, and set the managed_buffer_alloc flag to each substream.
0374  *
0375  * Return: zero if successful, or a negative error code
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  * snd_pcm_lib_malloc_pages - allocate the DMA buffer
0387  * @substream: the substream to allocate the DMA buffer to
0388  * @size: the requested buffer size in bytes
0389  *
0390  * Allocates the DMA buffer on the BUS type given earlier to
0391  * snd_pcm_lib_preallocate_xxx_pages().
0392  *
0393  * Return: 1 if the buffer is changed, 0 if not changed, or a negative
0394  * code on failure.
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         /* perphaps, we might free the large DMA memory region
0412            to save some space here, but the actual solution
0413            costs us less time */
0414         if (runtime->dma_buffer_p->bytes >= size) {
0415             runtime->dma_bytes = size;
0416             return 0;   /* ok, do not change */
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; /* use the pre-allocated buffer */
0423     } else {
0424         /* dma_max=0 means the fixed size preallocation */
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;           /* area was changed */
0447 }
0448 EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
0449 
0450 /**
0451  * snd_pcm_lib_free_pages - release the allocated DMA buffer.
0452  * @substream: the substream to release the DMA buffer
0453  *
0454  * Releases the DMA buffer allocated via snd_pcm_lib_malloc_pages().
0455  *
0456  * Return: Zero if successful, or a negative error code on failure.
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         /* it's a newly allocated buffer.  release it now. */
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; /* already large enough */
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  * snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer
0502  * @substream: the substream with a buffer allocated by
0503  *  snd_pcm_lib_alloc_vmalloc_buffer()
0504  *
0505  * Return: Zero if successful, or a negative error code on failure.
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  * snd_pcm_lib_get_vmalloc_page - map vmalloc buffer offset to page struct
0522  * @substream: the substream with a buffer allocated by
0523  *  snd_pcm_lib_alloc_vmalloc_buffer()
0524  * @offset: offset in the buffer
0525  *
0526  * This function is to be used as the page callback in the PCM ops.
0527  *
0528  * Return: The page struct, or %NULL on failure.
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);