hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/sound/core/oss/pcm_oss.c
....@@ -1,22 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Digital Audio (PCM) abstract layer / OSS compatible
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 #if 0
....@@ -789,6 +774,11 @@
789774
790775 if (oss_period_size < 16)
791776 return -EINVAL;
777
+
778
+ /* don't allocate too large period; 1MB period must be enough */
779
+ if (oss_period_size > 1024 * 1024)
780
+ return -ENOMEM;
781
+
792782 runtime->oss.period_bytes = oss_period_size;
793783 runtime->oss.period_frames = 1;
794784 runtime->oss.periods = oss_periods;
....@@ -918,20 +908,17 @@
918908 sformat = snd_pcm_plug_slave_format(format, sformat_mask);
919909
920910 if ((__force int)sformat < 0 ||
921
- !snd_mask_test(sformat_mask, (__force int)sformat)) {
922
- for (sformat = (__force snd_pcm_format_t)0;
923
- (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST;
924
- sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) {
925
- if (snd_mask_test(sformat_mask, (__force int)sformat) &&
911
+ !snd_mask_test_format(sformat_mask, sformat)) {
912
+ pcm_for_each_format(sformat) {
913
+ if (snd_mask_test_format(sformat_mask, sformat) &&
926914 snd_pcm_oss_format_to(sformat) >= 0)
927
- break;
915
+ goto format_found;
928916 }
929
- if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) {
930
- pcm_dbg(substream->pcm, "Cannot find a format!!!\n");
931
- err = -EINVAL;
932
- goto failure;
933
- }
917
+ pcm_dbg(substream->pcm, "Cannot find a format!!!\n");
918
+ err = -EINVAL;
919
+ goto failure;
934920 }
921
+ format_found:
935922 err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0);
936923 if (err < 0)
937924 goto failure;
....@@ -1060,10 +1047,9 @@
10601047 goto failure;
10611048 }
10621049 #endif
1063
- oss_period_size *= oss_frame_size;
1064
-
1065
- oss_buffer_size = oss_period_size * runtime->oss.periods;
1066
- if (oss_buffer_size < 0) {
1050
+ oss_period_size = array_size(oss_period_size, oss_frame_size);
1051
+ oss_buffer_size = array_size(oss_period_size, runtime->oss.periods);
1052
+ if (oss_buffer_size <= 0) {
10671053 err = -EINVAL;
10681054 goto failure;
10691055 }
....@@ -1254,8 +1240,10 @@
12541240 if (ret < 0)
12551241 break;
12561242 }
1243
+ mutex_unlock(&runtime->oss.params_lock);
12571244 ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
12581245 frames, in_kernel);
1246
+ mutex_lock(&runtime->oss.params_lock);
12591247 if (ret != -EPIPE && ret != -ESTRPIPE)
12601248 break;
12611249 /* test, if we can't store new data, because the stream */
....@@ -1291,8 +1279,10 @@
12911279 ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
12921280 if (ret < 0)
12931281 break;
1282
+ mutex_unlock(&runtime->oss.params_lock);
12941283 ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
12951284 frames, in_kernel);
1285
+ mutex_lock(&runtime->oss.params_lock);
12961286 if (ret == -EPIPE) {
12971287 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
12981288 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
....@@ -1672,13 +1662,14 @@
16721662 runtime = substream->runtime;
16731663 if (atomic_read(&substream->mmap_count))
16741664 goto __direct;
1675
- if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1676
- return err;
16771665 atomic_inc(&runtime->oss.rw_ref);
16781666 if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
16791667 atomic_dec(&runtime->oss.rw_ref);
16801668 return -ERESTARTSYS;
16811669 }
1670
+ err = snd_pcm_oss_make_ready_locked(substream);
1671
+ if (err < 0)
1672
+ goto unlock;
16821673 format = snd_pcm_oss_format_from(runtime->oss.format);
16831674 width = snd_pcm_format_physical_width(format);
16841675 if (runtime->oss.buffer_used > 0) {
....@@ -2451,7 +2442,6 @@
24512442 }
24522443
24532444 pcm_oss_file->streams[idx] = substream;
2454
- substream->file = pcm_oss_file;
24552445 snd_pcm_oss_init_substream(substream, &setup[idx], minor);
24562446 }
24572447
....@@ -2756,6 +2746,10 @@
27562746 static long snd_pcm_oss_ioctl_compat(struct file *file, unsigned int cmd,
27572747 unsigned long arg)
27582748 {
2749
+ /*
2750
+ * Everything is compatbile except SNDCTL_DSP_MAPINBUF/SNDCTL_DSP_MAPOUTBUF,
2751
+ * which are not implemented for the native case either
2752
+ */
27592753 return snd_pcm_oss_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
27602754 }
27612755 #else
....@@ -2885,7 +2879,7 @@
28852879 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
28862880 if (substream)
28872881 break;
2888
- /* Fall through */
2882
+ fallthrough;
28892883 case VM_READ:
28902884 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
28912885 break;
....@@ -2910,7 +2904,7 @@
29102904
29112905 if (runtime->oss.params) {
29122906 /* use mutex_trylock() for params_lock for avoiding a deadlock
2913
- * between mmap_sem and params_lock taken by
2907
+ * between mmap_lock and params_lock taken by
29142908 * copy_from/to_user() in snd_pcm_oss_write/read()
29152909 */
29162910 err = snd_pcm_oss_change_params(substream, true);