hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/sound/core/pcm.c
....@@ -1,22 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Digital Audio (PCM) abstract layer
34 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
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
- *
205 */
216
227 #include <linux/init.h>
....@@ -178,7 +163,7 @@
178163
179164 #define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v
180165
181
-static char *snd_pcm_format_names[] = {
166
+static const char * const snd_pcm_format_names[] = {
182167 FORMAT(S8),
183168 FORMAT(U8),
184169 FORMAT(S16_LE),
....@@ -252,12 +237,12 @@
252237 #define START(v) [SNDRV_PCM_START_##v] = #v
253238 #define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v
254239
255
-static char *snd_pcm_stream_names[] = {
240
+static const char * const snd_pcm_stream_names[] = {
256241 STREAM(PLAYBACK),
257242 STREAM(CAPTURE),
258243 };
259244
260
-static char *snd_pcm_state_names[] = {
245
+static const char * const snd_pcm_state_names[] = {
261246 STATE(OPEN),
262247 STATE(SETUP),
263248 STATE(PREPARED),
....@@ -268,7 +253,7 @@
268253 STATE(SUSPENDED),
269254 };
270255
271
-static char *snd_pcm_access_names[] = {
256
+static const char * const snd_pcm_access_names[] = {
272257 ACCESS(MMAP_INTERLEAVED),
273258 ACCESS(MMAP_NONINTERLEAVED),
274259 ACCESS(MMAP_COMPLEX),
....@@ -276,11 +261,11 @@
276261 ACCESS(RW_NONINTERLEAVED),
277262 };
278263
279
-static char *snd_pcm_subformat_names[] = {
264
+static const char * const snd_pcm_subformat_names[] = {
280265 SUBFORMAT(STD),
281266 };
282267
283
-static char *snd_pcm_tstamp_mode_names[] = {
268
+static const char * const snd_pcm_tstamp_mode_names[] = {
284269 TSTAMP(NONE),
285270 TSTAMP(ENABLE),
286271 };
....@@ -458,7 +443,7 @@
458443 {
459444 struct snd_pcm_substream *substream = entry->private_data;
460445 struct snd_pcm_runtime *runtime;
461
- struct snd_pcm_status status;
446
+ struct snd_pcm_status64 status;
462447 int err;
463448
464449 mutex_lock(&substream->pcm->open_mutex);
....@@ -468,17 +453,17 @@
468453 goto unlock;
469454 }
470455 memset(&status, 0, sizeof(status));
471
- err = snd_pcm_status(substream, &status);
456
+ err = snd_pcm_status64(substream, &status);
472457 if (err < 0) {
473458 snd_iprintf(buffer, "error %d\n", err);
474459 goto unlock;
475460 }
476461 snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
477462 snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid));
478
- snd_iprintf(buffer, "trigger_time: %ld.%09ld\n",
479
- status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec);
480
- snd_iprintf(buffer, "tstamp : %ld.%09ld\n",
481
- status.tstamp.tv_sec, status.tstamp.tv_nsec);
463
+ snd_iprintf(buffer, "trigger_time: %lld.%09lld\n",
464
+ status.trigger_tstamp_sec, status.trigger_tstamp_nsec);
465
+ snd_iprintf(buffer, "tstamp : %lld.%09lld\n",
466
+ status.tstamp_sec, status.tstamp_nsec);
482467 snd_iprintf(buffer, "delay : %ld\n", status.delay);
483468 snd_iprintf(buffer, "avail : %ld\n", status.avail);
484469 snd_iprintf(buffer, "avail_max : %ld\n", status.avail_max);
....@@ -528,50 +513,42 @@
528513 if (!entry)
529514 return -ENOMEM;
530515 entry->mode = S_IFDIR | 0555;
531
- if (snd_info_register(entry) < 0) {
532
- snd_info_free_entry(entry);
533
- return -ENOMEM;
534
- }
535516 pstr->proc_root = entry;
536517 entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root);
537
- if (entry) {
518
+ if (entry)
538519 snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read);
539
- if (snd_info_register(entry) < 0) {
540
- snd_info_free_entry(entry);
541
- entry = NULL;
542
- }
543
- }
544
- pstr->proc_info_entry = entry;
545
-
546520 #ifdef CONFIG_SND_PCM_XRUN_DEBUG
547521 entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
548522 pstr->proc_root);
549523 if (entry) {
550
- entry->c.text.read = snd_pcm_xrun_debug_read;
524
+ snd_info_set_text_ops(entry, pstr, snd_pcm_xrun_debug_read);
551525 entry->c.text.write = snd_pcm_xrun_debug_write;
552526 entry->mode |= 0200;
553
- entry->private_data = pstr;
554
- if (snd_info_register(entry) < 0) {
555
- snd_info_free_entry(entry);
556
- entry = NULL;
557
- }
558527 }
559
- pstr->proc_xrun_debug_entry = entry;
560528 #endif
561529 return 0;
562530 }
563531
564532 static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr)
565533 {
566
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
567
- snd_info_free_entry(pstr->proc_xrun_debug_entry);
568
- pstr->proc_xrun_debug_entry = NULL;
569
-#endif
570
- snd_info_free_entry(pstr->proc_info_entry);
571
- pstr->proc_info_entry = NULL;
572534 snd_info_free_entry(pstr->proc_root);
573535 pstr->proc_root = NULL;
574536 return 0;
537
+}
538
+
539
+static struct snd_info_entry *
540
+create_substream_info_entry(struct snd_pcm_substream *substream,
541
+ const char *name,
542
+ void (*read)(struct snd_info_entry *,
543
+ struct snd_info_buffer *))
544
+{
545
+ struct snd_info_entry *entry;
546
+
547
+ entry = snd_info_create_card_entry(substream->pcm->card, name,
548
+ substream->proc_root);
549
+ if (entry)
550
+ snd_info_set_text_ops(entry, substream, read);
551
+ return entry;
575552 }
576553
577554 static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
....@@ -588,100 +565,60 @@
588565 if (!entry)
589566 return -ENOMEM;
590567 entry->mode = S_IFDIR | 0555;
591
- if (snd_info_register(entry) < 0) {
592
- snd_info_free_entry(entry);
593
- return -ENOMEM;
594
- }
595568 substream->proc_root = entry;
596
- entry = snd_info_create_card_entry(card, "info", substream->proc_root);
597
- if (entry) {
598
- snd_info_set_text_ops(entry, substream,
599
- snd_pcm_substream_proc_info_read);
600
- if (snd_info_register(entry) < 0) {
601
- snd_info_free_entry(entry);
602
- entry = NULL;
603
- }
604
- }
605
- substream->proc_info_entry = entry;
606
- entry = snd_info_create_card_entry(card, "hw_params",
607
- substream->proc_root);
608
- if (entry) {
609
- snd_info_set_text_ops(entry, substream,
610
- snd_pcm_substream_proc_hw_params_read);
611
- if (snd_info_register(entry) < 0) {
612
- snd_info_free_entry(entry);
613
- entry = NULL;
614
- }
615
- }
616
- substream->proc_hw_params_entry = entry;
617
- entry = snd_info_create_card_entry(card, "sw_params",
618
- substream->proc_root);
619
- if (entry) {
620
- snd_info_set_text_ops(entry, substream,
621
- snd_pcm_substream_proc_sw_params_read);
622
- if (snd_info_register(entry) < 0) {
623
- snd_info_free_entry(entry);
624
- entry = NULL;
625
- }
626
- }
627
- substream->proc_sw_params_entry = entry;
628
- entry = snd_info_create_card_entry(card, "status",
629
- substream->proc_root);
630
- if (entry) {
631
- snd_info_set_text_ops(entry, substream,
632
- snd_pcm_substream_proc_status_read);
633
- if (snd_info_register(entry) < 0) {
634
- snd_info_free_entry(entry);
635
- entry = NULL;
636
- }
637
- }
638
- substream->proc_status_entry = entry;
569
+
570
+ create_substream_info_entry(substream, "info",
571
+ snd_pcm_substream_proc_info_read);
572
+ create_substream_info_entry(substream, "hw_params",
573
+ snd_pcm_substream_proc_hw_params_read);
574
+ create_substream_info_entry(substream, "sw_params",
575
+ snd_pcm_substream_proc_sw_params_read);
576
+ create_substream_info_entry(substream, "status",
577
+ snd_pcm_substream_proc_status_read);
639578
640579 #ifdef CONFIG_SND_PCM_XRUN_DEBUG
641
- entry = snd_info_create_card_entry(card, "xrun_injection",
642
- substream->proc_root);
580
+ entry = create_substream_info_entry(substream, "xrun_injection", NULL);
643581 if (entry) {
644
- entry->private_data = substream;
645
- entry->c.text.read = NULL;
646582 entry->c.text.write = snd_pcm_xrun_injection_write;
647583 entry->mode = S_IFREG | 0200;
648
- if (snd_info_register(entry) < 0) {
649
- snd_info_free_entry(entry);
650
- entry = NULL;
651
- }
652584 }
653
- substream->proc_xrun_injection_entry = entry;
654585 #endif /* CONFIG_SND_PCM_XRUN_DEBUG */
655586
656587 return 0;
657588 }
658589
659
-static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
660
-{
661
- snd_info_free_entry(substream->proc_info_entry);
662
- substream->proc_info_entry = NULL;
663
- snd_info_free_entry(substream->proc_hw_params_entry);
664
- substream->proc_hw_params_entry = NULL;
665
- snd_info_free_entry(substream->proc_sw_params_entry);
666
- substream->proc_sw_params_entry = NULL;
667
- snd_info_free_entry(substream->proc_status_entry);
668
- substream->proc_status_entry = NULL;
669
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
670
- snd_info_free_entry(substream->proc_xrun_injection_entry);
671
- substream->proc_xrun_injection_entry = NULL;
672
-#endif
673
- snd_info_free_entry(substream->proc_root);
674
- substream->proc_root = NULL;
675
- return 0;
676
-}
677590 #else /* !CONFIG_SND_VERBOSE_PROCFS */
678591 static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; }
679592 static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; }
680593 static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; }
681
-static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }
682594 #endif /* CONFIG_SND_VERBOSE_PROCFS */
683595
684596 static const struct attribute_group *pcm_dev_attr_groups[];
597
+
598
+/*
599
+ * PM callbacks: we need to deal only with suspend here, as the resume is
600
+ * triggered either from user-space or the driver's resume callback
601
+ */
602
+#ifdef CONFIG_PM_SLEEP
603
+static int do_pcm_suspend(struct device *dev)
604
+{
605
+ struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev);
606
+
607
+ if (!pstr->pcm->no_device_suspend)
608
+ snd_pcm_suspend_all(pstr->pcm);
609
+ return 0;
610
+}
611
+#endif
612
+
613
+static const struct dev_pm_ops pcm_dev_pm_ops = {
614
+ SET_SYSTEM_SLEEP_PM_OPS(do_pcm_suspend, NULL)
615
+};
616
+
617
+/* device type for PCM -- basically only for passing PM callbacks */
618
+static const struct device_type pcm_dev_type = {
619
+ .name = "pcm",
620
+ .pm = &pcm_dev_pm_ops,
621
+};
685622
686623 /**
687624 * snd_pcm_new_stream - create a new PCM stream
....@@ -713,6 +650,7 @@
713650
714651 snd_device_initialize(&pstr->dev, pcm->card);
715652 pstr->dev.groups = pcm_dev_attr_groups;
653
+ pstr->dev.type = &pcm_dev_type;
716654 dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device,
717655 stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
718656
....@@ -753,9 +691,7 @@
753691 }
754692 }
755693 substream->group = &substream->self_group;
756
- spin_lock_init(&substream->self_group.lock);
757
- mutex_init(&substream->self_group.mutex);
758
- INIT_LIST_HEAD(&substream->self_group.substreams);
694
+ snd_pcm_group_init(&substream->self_group);
759695 list_add_tail(&substream->link_list, &substream->self_group.substreams);
760696 atomic_set(&substream->mmap_count, 0);
761697 prev = substream;
....@@ -770,12 +706,12 @@
770706 {
771707 struct snd_pcm *pcm;
772708 int err;
773
- static struct snd_device_ops ops = {
709
+ static const struct snd_device_ops ops = {
774710 .dev_free = snd_pcm_dev_free,
775711 .dev_register = snd_pcm_dev_register,
776712 .dev_disconnect = snd_pcm_dev_disconnect,
777713 };
778
- static struct snd_device_ops internal_ops = {
714
+ static const struct snd_device_ops internal_ops = {
779715 .dev_free = snd_pcm_dev_free,
780716 };
781717
....@@ -881,14 +817,6 @@
881817 up_write(&card->controls_rwsem);
882818 pstr->chmap_kctl = NULL;
883819 }
884
- if (pstr->vol_kctl) {
885
- snd_ctl_remove(pstr->pcm->card, pstr->vol_kctl);
886
- pstr->vol_kctl = NULL;
887
- }
888
- if (pstr->usr_kctl) {
889
- snd_ctl_remove(pstr->pcm->card, pstr->usr_kctl);
890
- pstr->usr_kctl = NULL;
891
- }
892820 }
893821
894822 static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
....@@ -897,15 +825,17 @@
897825 #if IS_ENABLED(CONFIG_SND_PCM_OSS)
898826 struct snd_pcm_oss_setup *setup, *setupn;
899827 #endif
828
+
829
+ /* free all proc files under the stream */
830
+ snd_pcm_stream_proc_done(pstr);
831
+
900832 substream = pstr->substream;
901833 while (substream) {
902834 substream_next = substream->next;
903835 snd_pcm_timer_done(substream);
904
- snd_pcm_substream_proc_done(substream);
905836 kfree(substream);
906837 substream = substream_next;
907838 }
908
- snd_pcm_stream_proc_done(pstr);
909839 #if IS_ENABLED(CONFIG_SND_PCM_OSS)
910840 for (setup = pstr->oss.setup_list; setup; setup = setupn) {
911841 setupn = setup->next;
....@@ -1018,27 +948,29 @@
1018948 return -ENOMEM;
1019949
1020950 size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status));
1021
- runtime->status = snd_malloc_pages(size, GFP_KERNEL);
951
+ runtime->status = alloc_pages_exact(size, GFP_KERNEL);
1022952 if (runtime->status == NULL) {
1023953 kfree(runtime);
1024954 return -ENOMEM;
1025955 }
1026
- memset((void*)runtime->status, 0, size);
956
+ memset(runtime->status, 0, size);
1027957
1028958 size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control));
1029
- runtime->control = snd_malloc_pages(size, GFP_KERNEL);
959
+ runtime->control = alloc_pages_exact(size, GFP_KERNEL);
1030960 if (runtime->control == NULL) {
1031
- snd_free_pages((void*)runtime->status,
961
+ free_pages_exact(runtime->status,
1032962 PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
1033963 kfree(runtime);
1034964 return -ENOMEM;
1035965 }
1036
- memset((void*)runtime->control, 0, size);
966
+ memset(runtime->control, 0, size);
1037967
1038968 init_waitqueue_head(&runtime->sleep);
1039969 init_waitqueue_head(&runtime->tsleep);
1040970
1041971 runtime->status->state = SNDRV_PCM_STATE_OPEN;
972
+ mutex_init(&runtime->buffer_mutex);
973
+ atomic_set(&runtime->buffer_accessing, 0);
1042974
1043975 substream->runtime = runtime;
1044976 substream->private_data = pcm->private_data;
....@@ -1059,17 +991,20 @@
1059991 runtime = substream->runtime;
1060992 if (runtime->private_free != NULL)
1061993 runtime->private_free(runtime);
1062
- snd_free_pages((void*)runtime->status,
994
+ free_pages_exact(runtime->status,
1063995 PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
1064
- snd_free_pages((void*)runtime->control,
996
+ free_pages_exact(runtime->control,
1065997 PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
1066998 kfree(runtime->hw_constraints.rules);
1067999 /* Avoid concurrent access to runtime via PCM timer interface */
1068
- if (substream->timer)
1000
+ if (substream->timer) {
10691001 spin_lock_irq(&substream->timer->lock);
1070
- substream->runtime = NULL;
1071
- if (substream->timer)
1002
+ substream->runtime = NULL;
10721003 spin_unlock_irq(&substream->timer->lock);
1004
+ } else {
1005
+ substream->runtime = NULL;
1006
+ }
1007
+ mutex_destroy(&runtime->buffer_mutex);
10731008 kfree(runtime);
10741009 put_pid(substream->pid);
10751010 substream->pid = NULL;
....@@ -1093,7 +1028,7 @@
10931028 str = "none";
10941029 else
10951030 str = strs[pcm->dev_class];
1096
- return snprintf(buf, PAGE_SIZE, "%s\n", str);
1031
+ return sprintf(buf, "%s\n", str);
10971032 }
10981033
10991034 static DEVICE_ATTR(pcm_class, 0444, show_pcm_class, NULL);
....@@ -1183,6 +1118,10 @@
11831118 }
11841119 }
11851120
1121
+ for (cidx = 0; cidx < 2; cidx++)
1122
+ for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
1123
+ snd_pcm_sync_stop(substream, false);
1124
+
11861125 pcm_call_notify(pcm, n_disconnect);
11871126 for (cidx = 0; cidx < 2; cidx++) {
11881127 snd_unregister_device(&pcm->streams[cidx].dev);