@@ -574,6 +574,8 @@ static inline int snd_pcm_suspend_all(struct snd_pcm *pcm)
}
#endif
int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
+struct snd_pcm_runtime *snd_pcm_runtime_alloc(void);
+void snd_pcm_runtime_free(struct snd_pcm_runtime *runtime);
int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file,
struct snd_pcm_substream **rsubstream);
void snd_pcm_release_substream(struct snd_pcm_substream *substream);
@@ -876,6 +876,53 @@ static int snd_pcm_dev_free(struct snd_device *device)
return snd_pcm_free(pcm);
}
+struct snd_pcm_runtime *snd_pcm_runtime_alloc(void)
+{
+ struct snd_pcm_runtime *runtime;
+ size_t size;
+
+ runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+ if (!runtime)
+ return NULL;
+
+ size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status));
+ runtime->status = alloc_pages_exact(size, GFP_KERNEL);
+ if (!runtime->status) {
+ kfree(runtime);
+ return NULL;
+ }
+ memset(runtime->status, 0, size);
+
+ size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control));
+ runtime->control = alloc_pages_exact(size, GFP_KERNEL);
+ if (!runtime->control) {
+ free_pages_exact(runtime->status,
+ PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
+ kfree(runtime);
+ return NULL;
+ }
+ memset(runtime->control, 0, size);
+
+ init_waitqueue_head(&runtime->sleep);
+ init_waitqueue_head(&runtime->tsleep);
+
+ runtime->status->state = SNDRV_PCM_STATE_OPEN;
+
+ return runtime;
+}
+EXPORT_SYMBOL_GPL(snd_pcm_runtime_alloc);
+
+void snd_pcm_runtime_free(struct snd_pcm_runtime *runtime)
+{
+ free_pages_exact(runtime->status,
+ PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
+ free_pages_exact(runtime->control,
+ PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
+ kfree(runtime->hw_constraints.rules);
+ kfree(runtime);
+}
+EXPORT_SYMBOL_GPL(snd_pcm_runtime_free);
+
int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
struct file *file,
struct snd_pcm_substream **rsubstream)
@@ -885,7 +932,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
struct snd_pcm_runtime *runtime;
struct snd_card *card;
int prefer_subdevice;
- size_t size;
if (snd_BUG_ON(!pcm || !rsubstream))
return -ENXIO;
@@ -939,33 +985,10 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
if (substream == NULL)
return -EAGAIN;
- runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
- if (runtime == NULL)
+ runtime = snd_pcm_runtime_alloc();
+ if (!runtime)
return -ENOMEM;
- size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status));
- runtime->status = alloc_pages_exact(size, GFP_KERNEL);
- if (runtime->status == NULL) {
- kfree(runtime);
- return -ENOMEM;
- }
- memset(runtime->status, 0, size);
-
- size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control));
- runtime->control = alloc_pages_exact(size, GFP_KERNEL);
- if (runtime->control == NULL) {
- free_pages_exact(runtime->status,
- PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
- kfree(runtime);
- return -ENOMEM;
- }
- memset(runtime->control, 0, size);
-
- init_waitqueue_head(&runtime->sleep);
- init_waitqueue_head(&runtime->tsleep);
-
- runtime->status->state = SNDRV_PCM_STATE_OPEN;
-
substream->runtime = runtime;
substream->private_data = pcm->private_data;
substream->ref_count = 1;
@@ -985,11 +1008,6 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
runtime = substream->runtime;
if (runtime->private_free != NULL)
runtime->private_free(runtime);
- free_pages_exact(runtime->status,
- PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
- free_pages_exact(runtime->control,
- PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
- kfree(runtime->hw_constraints.rules);
/* Avoid concurrent access to runtime via PCM timer interface */
if (substream->timer) {
spin_lock_irq(&substream->timer->lock);
@@ -998,7 +1016,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
} else {
substream->runtime = NULL;
}
- kfree(runtime);
+ snd_pcm_runtime_free(runtime);
put_pid(substream->pid);
substream->pid = NULL;
substream->pstr->substream_opened--;
Create helpers to be able to reuse code for allocation and freeing of struct snd_pcm_runtime. Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com> --- include/sound/pcm.h | 2 ++ sound/core/pcm.c | 82 +++++++++++++++++++++++++++------------------ 2 files changed, 52 insertions(+), 32 deletions(-)