diff options
author | Takashi Iwai <tiwai@suse.de> | 2018-04-02 13:50:41 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2018-04-02 13:50:59 -0400 |
commit | bc334cb61b9ee6e85b9bb01519989a3ae8fe03f6 (patch) | |
tree | 34424a812537fe11beeee727b30b19c67193fe36 /sound/core | |
parent | 5607dddbfca774fb38bffadcb077fe03aa4ac5c6 (diff) | |
parent | b44d419b98fae759b4f746186b1d1c8d01d962f2 (diff) |
Merge branch 'for-next' into for-linus
Preparation for 4.17 merge.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/control.c | 18 | ||||
-rw-r--r-- | sound/core/init.c | 4 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 185 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 8 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 19 | ||||
-rw-r--r-- | sound/core/vmaster.c | 7 |
6 files changed, 179 insertions, 62 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index 8a77620a3854..69734b0eafd0 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -105,7 +105,7 @@ static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl) | |||
105 | { | 105 | { |
106 | unsigned long flags; | 106 | unsigned long flags; |
107 | struct snd_kctl_event *cread; | 107 | struct snd_kctl_event *cread; |
108 | 108 | ||
109 | spin_lock_irqsave(&ctl->read_lock, flags); | 109 | spin_lock_irqsave(&ctl->read_lock, flags); |
110 | while (!list_empty(&ctl->events)) { | 110 | while (!list_empty(&ctl->events)) { |
111 | cread = snd_kctl_event(ctl->events.next); | 111 | cread = snd_kctl_event(ctl->events.next); |
@@ -159,7 +159,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask, | |||
159 | unsigned long flags; | 159 | unsigned long flags; |
160 | struct snd_ctl_file *ctl; | 160 | struct snd_ctl_file *ctl; |
161 | struct snd_kctl_event *ev; | 161 | struct snd_kctl_event *ev; |
162 | 162 | ||
163 | if (snd_BUG_ON(!card || !id)) | 163 | if (snd_BUG_ON(!card || !id)) |
164 | return; | 164 | return; |
165 | if (card->shutdown) | 165 | if (card->shutdown) |
@@ -213,7 +213,7 @@ static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count, | |||
213 | { | 213 | { |
214 | unsigned int size; | 214 | unsigned int size; |
215 | unsigned int idx; | 215 | unsigned int idx; |
216 | 216 | ||
217 | if (count == 0 || count > MAX_CONTROL_COUNT) | 217 | if (count == 0 || count > MAX_CONTROL_COUNT) |
218 | return -EINVAL; | 218 | return -EINVAL; |
219 | 219 | ||
@@ -238,7 +238,7 @@ static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count, | |||
238 | * @ncontrol: the initialization record | 238 | * @ncontrol: the initialization record |
239 | * @private_data: the private data to set | 239 | * @private_data: the private data to set |
240 | * | 240 | * |
241 | * Allocates a new struct snd_kcontrol instance and initialize from the given | 241 | * Allocates a new struct snd_kcontrol instance and initialize from the given |
242 | * template. When the access field of ncontrol is 0, it's assumed as | 242 | * template. When the access field of ncontrol is 0, it's assumed as |
243 | * READWRITE access. When the count field is 0, it's assumes as one. | 243 | * READWRITE access. When the count field is 0, it's assumes as one. |
244 | * | 244 | * |
@@ -251,7 +251,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, | |||
251 | unsigned int count; | 251 | unsigned int count; |
252 | unsigned int access; | 252 | unsigned int access; |
253 | int err; | 253 | int err; |
254 | 254 | ||
255 | if (snd_BUG_ON(!ncontrol || !ncontrol->info)) | 255 | if (snd_BUG_ON(!ncontrol || !ncontrol->info)) |
256 | return NULL; | 256 | return NULL; |
257 | 257 | ||
@@ -753,7 +753,7 @@ static int snd_ctl_elem_list(struct snd_card *card, | |||
753 | struct snd_ctl_elem_id id; | 753 | struct snd_ctl_elem_id id; |
754 | unsigned int offset, space, jidx; | 754 | unsigned int offset, space, jidx; |
755 | int err = 0; | 755 | int err = 0; |
756 | 756 | ||
757 | if (copy_from_user(&list, _list, sizeof(list))) | 757 | if (copy_from_user(&list, _list, sizeof(list))) |
758 | return -EFAULT; | 758 | return -EFAULT; |
759 | offset = list.offset; | 759 | offset = list.offset; |
@@ -827,7 +827,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl, | |||
827 | struct snd_kcontrol_volatile *vd; | 827 | struct snd_kcontrol_volatile *vd; |
828 | unsigned int index_offset; | 828 | unsigned int index_offset; |
829 | int result; | 829 | int result; |
830 | 830 | ||
831 | down_read(&card->controls_rwsem); | 831 | down_read(&card->controls_rwsem); |
832 | kctl = snd_ctl_find_id(card, &info->id); | 832 | kctl = snd_ctl_find_id(card, &info->id); |
833 | if (kctl == NULL) { | 833 | if (kctl == NULL) { |
@@ -992,7 +992,7 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file, | |||
992 | struct snd_kcontrol *kctl; | 992 | struct snd_kcontrol *kctl; |
993 | struct snd_kcontrol_volatile *vd; | 993 | struct snd_kcontrol_volatile *vd; |
994 | int result; | 994 | int result; |
995 | 995 | ||
996 | if (copy_from_user(&id, _id, sizeof(id))) | 996 | if (copy_from_user(&id, _id, sizeof(id))) |
997 | return -EFAULT; | 997 | return -EFAULT; |
998 | down_write(&card->controls_rwsem); | 998 | down_write(&card->controls_rwsem); |
@@ -1020,7 +1020,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file, | |||
1020 | struct snd_kcontrol *kctl; | 1020 | struct snd_kcontrol *kctl; |
1021 | struct snd_kcontrol_volatile *vd; | 1021 | struct snd_kcontrol_volatile *vd; |
1022 | int result; | 1022 | int result; |
1023 | 1023 | ||
1024 | if (copy_from_user(&id, _id, sizeof(id))) | 1024 | if (copy_from_user(&id, _id, sizeof(id))) |
1025 | return -EFAULT; | 1025 | return -EFAULT; |
1026 | down_write(&card->controls_rwsem); | 1026 | down_write(&card->controls_rwsem); |
diff --git a/sound/core/init.c b/sound/core/init.c index 4fa5dd955740..79b4df1c1dc7 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -670,7 +670,7 @@ card_id_show_attr(struct device *dev, | |||
670 | struct device_attribute *attr, char *buf) | 670 | struct device_attribute *attr, char *buf) |
671 | { | 671 | { |
672 | struct snd_card *card = container_of(dev, struct snd_card, card_dev); | 672 | struct snd_card *card = container_of(dev, struct snd_card, card_dev); |
673 | return snprintf(buf, PAGE_SIZE, "%s\n", card->id); | 673 | return scnprintf(buf, PAGE_SIZE, "%s\n", card->id); |
674 | } | 674 | } |
675 | 675 | ||
676 | static ssize_t | 676 | static ssize_t |
@@ -710,7 +710,7 @@ card_number_show_attr(struct device *dev, | |||
710 | struct device_attribute *attr, char *buf) | 710 | struct device_attribute *attr, char *buf) |
711 | { | 711 | { |
712 | struct snd_card *card = container_of(dev, struct snd_card, card_dev); | 712 | struct snd_card *card = container_of(dev, struct snd_card, card_dev); |
713 | return snprintf(buf, PAGE_SIZE, "%i\n", card->number); | 713 | return scnprintf(buf, PAGE_SIZE, "%i\n", card->number); |
714 | } | 714 | } |
715 | 715 | ||
716 | static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL); | 716 | static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL); |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 441405081195..481ab0e94ffa 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -823,8 +823,25 @@ static int choose_rate(struct snd_pcm_substream *substream, | |||
823 | return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL); | 823 | return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL); |
824 | } | 824 | } |
825 | 825 | ||
826 | static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, | 826 | /* parameter locking: returns immediately if tried during streaming */ |
827 | bool trylock) | 827 | static int lock_params(struct snd_pcm_runtime *runtime) |
828 | { | ||
829 | if (mutex_lock_interruptible(&runtime->oss.params_lock)) | ||
830 | return -ERESTARTSYS; | ||
831 | if (atomic_read(&runtime->oss.rw_ref)) { | ||
832 | mutex_unlock(&runtime->oss.params_lock); | ||
833 | return -EBUSY; | ||
834 | } | ||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | static void unlock_params(struct snd_pcm_runtime *runtime) | ||
839 | { | ||
840 | mutex_unlock(&runtime->oss.params_lock); | ||
841 | } | ||
842 | |||
843 | /* call with params_lock held */ | ||
844 | static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) | ||
828 | { | 845 | { |
829 | struct snd_pcm_runtime *runtime = substream->runtime; | 846 | struct snd_pcm_runtime *runtime = substream->runtime; |
830 | struct snd_pcm_hw_params *params, *sparams; | 847 | struct snd_pcm_hw_params *params, *sparams; |
@@ -838,11 +855,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, | |||
838 | const struct snd_mask *sformat_mask; | 855 | const struct snd_mask *sformat_mask; |
839 | struct snd_mask mask; | 856 | struct snd_mask mask; |
840 | 857 | ||
841 | if (trylock) { | 858 | if (!runtime->oss.params) |
842 | if (!(mutex_trylock(&runtime->oss.params_lock))) | 859 | return 0; |
843 | return -EAGAIN; | ||
844 | } else if (mutex_lock_interruptible(&runtime->oss.params_lock)) | ||
845 | return -ERESTARTSYS; | ||
846 | sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL); | 860 | sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL); |
847 | params = kmalloc(sizeof(*params), GFP_KERNEL); | 861 | params = kmalloc(sizeof(*params), GFP_KERNEL); |
848 | sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); | 862 | sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); |
@@ -1068,6 +1082,23 @@ failure: | |||
1068 | kfree(sw_params); | 1082 | kfree(sw_params); |
1069 | kfree(params); | 1083 | kfree(params); |
1070 | kfree(sparams); | 1084 | kfree(sparams); |
1085 | return err; | ||
1086 | } | ||
1087 | |||
1088 | /* this one takes the lock by itself */ | ||
1089 | static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, | ||
1090 | bool trylock) | ||
1091 | { | ||
1092 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1093 | int err; | ||
1094 | |||
1095 | if (trylock) { | ||
1096 | if (!(mutex_trylock(&runtime->oss.params_lock))) | ||
1097 | return -EAGAIN; | ||
1098 | } else if (mutex_lock_interruptible(&runtime->oss.params_lock)) | ||
1099 | return -ERESTARTSYS; | ||
1100 | |||
1101 | err = snd_pcm_oss_change_params_locked(substream); | ||
1071 | mutex_unlock(&runtime->oss.params_lock); | 1102 | mutex_unlock(&runtime->oss.params_lock); |
1072 | return err; | 1103 | return err; |
1073 | } | 1104 | } |
@@ -1096,11 +1127,14 @@ static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_fil | |||
1096 | return 0; | 1127 | return 0; |
1097 | } | 1128 | } |
1098 | 1129 | ||
1130 | /* call with params_lock held */ | ||
1099 | static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) | 1131 | static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) |
1100 | { | 1132 | { |
1101 | int err; | 1133 | int err; |
1102 | struct snd_pcm_runtime *runtime = substream->runtime; | 1134 | struct snd_pcm_runtime *runtime = substream->runtime; |
1103 | 1135 | ||
1136 | if (!runtime->oss.prepare) | ||
1137 | return 0; | ||
1104 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); | 1138 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); |
1105 | if (err < 0) { | 1139 | if (err < 0) { |
1106 | pcm_dbg(substream->pcm, | 1140 | pcm_dbg(substream->pcm, |
@@ -1120,8 +1154,6 @@ static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream) | |||
1120 | struct snd_pcm_runtime *runtime; | 1154 | struct snd_pcm_runtime *runtime; |
1121 | int err; | 1155 | int err; |
1122 | 1156 | ||
1123 | if (substream == NULL) | ||
1124 | return 0; | ||
1125 | runtime = substream->runtime; | 1157 | runtime = substream->runtime; |
1126 | if (runtime->oss.params) { | 1158 | if (runtime->oss.params) { |
1127 | err = snd_pcm_oss_change_params(substream, false); | 1159 | err = snd_pcm_oss_change_params(substream, false); |
@@ -1129,6 +1161,29 @@ static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream) | |||
1129 | return err; | 1161 | return err; |
1130 | } | 1162 | } |
1131 | if (runtime->oss.prepare) { | 1163 | if (runtime->oss.prepare) { |
1164 | if (mutex_lock_interruptible(&runtime->oss.params_lock)) | ||
1165 | return -ERESTARTSYS; | ||
1166 | err = snd_pcm_oss_prepare(substream); | ||
1167 | mutex_unlock(&runtime->oss.params_lock); | ||
1168 | if (err < 0) | ||
1169 | return err; | ||
1170 | } | ||
1171 | return 0; | ||
1172 | } | ||
1173 | |||
1174 | /* call with params_lock held */ | ||
1175 | static int snd_pcm_oss_make_ready_locked(struct snd_pcm_substream *substream) | ||
1176 | { | ||
1177 | struct snd_pcm_runtime *runtime; | ||
1178 | int err; | ||
1179 | |||
1180 | runtime = substream->runtime; | ||
1181 | if (runtime->oss.params) { | ||
1182 | err = snd_pcm_oss_change_params_locked(substream); | ||
1183 | if (err < 0) | ||
1184 | return err; | ||
1185 | } | ||
1186 | if (runtime->oss.prepare) { | ||
1132 | err = snd_pcm_oss_prepare(substream); | 1187 | err = snd_pcm_oss_prepare(substream); |
1133 | if (err < 0) | 1188 | if (err < 0) |
1134 | return err; | 1189 | return err; |
@@ -1332,13 +1387,15 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
1332 | if (atomic_read(&substream->mmap_count)) | 1387 | if (atomic_read(&substream->mmap_count)) |
1333 | return -ENXIO; | 1388 | return -ENXIO; |
1334 | 1389 | ||
1335 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) | 1390 | atomic_inc(&runtime->oss.rw_ref); |
1336 | return tmp; | ||
1337 | while (bytes > 0) { | 1391 | while (bytes > 0) { |
1338 | if (mutex_lock_interruptible(&runtime->oss.params_lock)) { | 1392 | if (mutex_lock_interruptible(&runtime->oss.params_lock)) { |
1339 | tmp = -ERESTARTSYS; | 1393 | tmp = -ERESTARTSYS; |
1340 | break; | 1394 | break; |
1341 | } | 1395 | } |
1396 | tmp = snd_pcm_oss_make_ready_locked(substream); | ||
1397 | if (tmp < 0) | ||
1398 | goto err; | ||
1342 | if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { | 1399 | if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { |
1343 | tmp = bytes; | 1400 | tmp = bytes; |
1344 | if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes) | 1401 | if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes) |
@@ -1394,6 +1451,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
1394 | } | 1451 | } |
1395 | tmp = 0; | 1452 | tmp = 0; |
1396 | } | 1453 | } |
1454 | atomic_dec(&runtime->oss.rw_ref); | ||
1397 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; | 1455 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; |
1398 | } | 1456 | } |
1399 | 1457 | ||
@@ -1439,13 +1497,15 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use | |||
1439 | if (atomic_read(&substream->mmap_count)) | 1497 | if (atomic_read(&substream->mmap_count)) |
1440 | return -ENXIO; | 1498 | return -ENXIO; |
1441 | 1499 | ||
1442 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) | 1500 | atomic_inc(&runtime->oss.rw_ref); |
1443 | return tmp; | ||
1444 | while (bytes > 0) { | 1501 | while (bytes > 0) { |
1445 | if (mutex_lock_interruptible(&runtime->oss.params_lock)) { | 1502 | if (mutex_lock_interruptible(&runtime->oss.params_lock)) { |
1446 | tmp = -ERESTARTSYS; | 1503 | tmp = -ERESTARTSYS; |
1447 | break; | 1504 | break; |
1448 | } | 1505 | } |
1506 | tmp = snd_pcm_oss_make_ready_locked(substream); | ||
1507 | if (tmp < 0) | ||
1508 | goto err; | ||
1449 | if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { | 1509 | if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { |
1450 | if (runtime->oss.buffer_used == 0) { | 1510 | if (runtime->oss.buffer_used == 0) { |
1451 | tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1); | 1511 | tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1); |
@@ -1486,6 +1546,7 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use | |||
1486 | } | 1546 | } |
1487 | tmp = 0; | 1547 | tmp = 0; |
1488 | } | 1548 | } |
1549 | atomic_dec(&runtime->oss.rw_ref); | ||
1489 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; | 1550 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; |
1490 | } | 1551 | } |
1491 | 1552 | ||
@@ -1501,10 +1562,12 @@ static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file) | |||
1501 | continue; | 1562 | continue; |
1502 | runtime = substream->runtime; | 1563 | runtime = substream->runtime; |
1503 | snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); | 1564 | snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); |
1565 | mutex_lock(&runtime->oss.params_lock); | ||
1504 | runtime->oss.prepare = 1; | 1566 | runtime->oss.prepare = 1; |
1505 | runtime->oss.buffer_used = 0; | 1567 | runtime->oss.buffer_used = 0; |
1506 | runtime->oss.prev_hw_ptr_period = 0; | 1568 | runtime->oss.prev_hw_ptr_period = 0; |
1507 | runtime->oss.period_ptr = 0; | 1569 | runtime->oss.period_ptr = 0; |
1570 | mutex_unlock(&runtime->oss.params_lock); | ||
1508 | } | 1571 | } |
1509 | return 0; | 1572 | return 0; |
1510 | } | 1573 | } |
@@ -1590,9 +1653,13 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1590 | goto __direct; | 1653 | goto __direct; |
1591 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) | 1654 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) |
1592 | return err; | 1655 | return err; |
1656 | atomic_inc(&runtime->oss.rw_ref); | ||
1657 | if (mutex_lock_interruptible(&runtime->oss.params_lock)) { | ||
1658 | atomic_dec(&runtime->oss.rw_ref); | ||
1659 | return -ERESTARTSYS; | ||
1660 | } | ||
1593 | format = snd_pcm_oss_format_from(runtime->oss.format); | 1661 | format = snd_pcm_oss_format_from(runtime->oss.format); |
1594 | width = snd_pcm_format_physical_width(format); | 1662 | width = snd_pcm_format_physical_width(format); |
1595 | mutex_lock(&runtime->oss.params_lock); | ||
1596 | if (runtime->oss.buffer_used > 0) { | 1663 | if (runtime->oss.buffer_used > 0) { |
1597 | #ifdef OSS_DEBUG | 1664 | #ifdef OSS_DEBUG |
1598 | pcm_dbg(substream->pcm, "sync: buffer_used\n"); | 1665 | pcm_dbg(substream->pcm, "sync: buffer_used\n"); |
@@ -1602,10 +1669,8 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1602 | runtime->oss.buffer + runtime->oss.buffer_used, | 1669 | runtime->oss.buffer + runtime->oss.buffer_used, |
1603 | size); | 1670 | size); |
1604 | err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes); | 1671 | err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes); |
1605 | if (err < 0) { | 1672 | if (err < 0) |
1606 | mutex_unlock(&runtime->oss.params_lock); | 1673 | goto unlock; |
1607 | return err; | ||
1608 | } | ||
1609 | } else if (runtime->oss.period_ptr > 0) { | 1674 | } else if (runtime->oss.period_ptr > 0) { |
1610 | #ifdef OSS_DEBUG | 1675 | #ifdef OSS_DEBUG |
1611 | pcm_dbg(substream->pcm, "sync: period_ptr\n"); | 1676 | pcm_dbg(substream->pcm, "sync: period_ptr\n"); |
@@ -1615,10 +1680,8 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1615 | runtime->oss.buffer, | 1680 | runtime->oss.buffer, |
1616 | size * 8 / width); | 1681 | size * 8 / width); |
1617 | err = snd_pcm_oss_sync1(substream, size); | 1682 | err = snd_pcm_oss_sync1(substream, size); |
1618 | if (err < 0) { | 1683 | if (err < 0) |
1619 | mutex_unlock(&runtime->oss.params_lock); | 1684 | goto unlock; |
1620 | return err; | ||
1621 | } | ||
1622 | } | 1685 | } |
1623 | /* | 1686 | /* |
1624 | * The ALSA's period might be a bit large than OSS one. | 1687 | * The ALSA's period might be a bit large than OSS one. |
@@ -1632,7 +1695,11 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1632 | else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) | 1695 | else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) |
1633 | snd_pcm_lib_writev(substream, NULL, size); | 1696 | snd_pcm_lib_writev(substream, NULL, size); |
1634 | } | 1697 | } |
1698 | unlock: | ||
1635 | mutex_unlock(&runtime->oss.params_lock); | 1699 | mutex_unlock(&runtime->oss.params_lock); |
1700 | atomic_dec(&runtime->oss.rw_ref); | ||
1701 | if (err < 0) | ||
1702 | return err; | ||
1636 | /* | 1703 | /* |
1637 | * finish sync: drain the buffer | 1704 | * finish sync: drain the buffer |
1638 | */ | 1705 | */ |
@@ -1643,7 +1710,9 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1643 | substream->f_flags = saved_f_flags; | 1710 | substream->f_flags = saved_f_flags; |
1644 | if (err < 0) | 1711 | if (err < 0) |
1645 | return err; | 1712 | return err; |
1713 | mutex_lock(&runtime->oss.params_lock); | ||
1646 | runtime->oss.prepare = 1; | 1714 | runtime->oss.prepare = 1; |
1715 | mutex_unlock(&runtime->oss.params_lock); | ||
1647 | } | 1716 | } |
1648 | 1717 | ||
1649 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; | 1718 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; |
@@ -1654,8 +1723,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1654 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); | 1723 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); |
1655 | if (err < 0) | 1724 | if (err < 0) |
1656 | return err; | 1725 | return err; |
1726 | mutex_lock(&runtime->oss.params_lock); | ||
1657 | runtime->oss.buffer_used = 0; | 1727 | runtime->oss.buffer_used = 0; |
1658 | runtime->oss.prepare = 1; | 1728 | runtime->oss.prepare = 1; |
1729 | mutex_unlock(&runtime->oss.params_lock); | ||
1659 | } | 1730 | } |
1660 | return 0; | 1731 | return 0; |
1661 | } | 1732 | } |
@@ -1667,6 +1738,8 @@ static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate) | |||
1667 | for (idx = 1; idx >= 0; --idx) { | 1738 | for (idx = 1; idx >= 0; --idx) { |
1668 | struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; | 1739 | struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; |
1669 | struct snd_pcm_runtime *runtime; | 1740 | struct snd_pcm_runtime *runtime; |
1741 | int err; | ||
1742 | |||
1670 | if (substream == NULL) | 1743 | if (substream == NULL) |
1671 | continue; | 1744 | continue; |
1672 | runtime = substream->runtime; | 1745 | runtime = substream->runtime; |
@@ -1674,10 +1747,14 @@ static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate) | |||
1674 | rate = 1000; | 1747 | rate = 1000; |
1675 | else if (rate > 192000) | 1748 | else if (rate > 192000) |
1676 | rate = 192000; | 1749 | rate = 192000; |
1750 | err = lock_params(runtime); | ||
1751 | if (err < 0) | ||
1752 | return err; | ||
1677 | if (runtime->oss.rate != rate) { | 1753 | if (runtime->oss.rate != rate) { |
1678 | runtime->oss.params = 1; | 1754 | runtime->oss.params = 1; |
1679 | runtime->oss.rate = rate; | 1755 | runtime->oss.rate = rate; |
1680 | } | 1756 | } |
1757 | unlock_params(runtime); | ||
1681 | } | 1758 | } |
1682 | return snd_pcm_oss_get_rate(pcm_oss_file); | 1759 | return snd_pcm_oss_get_rate(pcm_oss_file); |
1683 | } | 1760 | } |
@@ -1702,13 +1779,19 @@ static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsig | |||
1702 | for (idx = 1; idx >= 0; --idx) { | 1779 | for (idx = 1; idx >= 0; --idx) { |
1703 | struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; | 1780 | struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; |
1704 | struct snd_pcm_runtime *runtime; | 1781 | struct snd_pcm_runtime *runtime; |
1782 | int err; | ||
1783 | |||
1705 | if (substream == NULL) | 1784 | if (substream == NULL) |
1706 | continue; | 1785 | continue; |
1707 | runtime = substream->runtime; | 1786 | runtime = substream->runtime; |
1787 | err = lock_params(runtime); | ||
1788 | if (err < 0) | ||
1789 | return err; | ||
1708 | if (runtime->oss.channels != channels) { | 1790 | if (runtime->oss.channels != channels) { |
1709 | runtime->oss.params = 1; | 1791 | runtime->oss.params = 1; |
1710 | runtime->oss.channels = channels; | 1792 | runtime->oss.channels = channels; |
1711 | } | 1793 | } |
1794 | unlock_params(runtime); | ||
1712 | } | 1795 | } |
1713 | return snd_pcm_oss_get_channels(pcm_oss_file); | 1796 | return snd_pcm_oss_get_channels(pcm_oss_file); |
1714 | } | 1797 | } |
@@ -1781,6 +1864,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) | |||
1781 | static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) | 1864 | static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) |
1782 | { | 1865 | { |
1783 | int formats, idx; | 1866 | int formats, idx; |
1867 | int err; | ||
1784 | 1868 | ||
1785 | if (format != AFMT_QUERY) { | 1869 | if (format != AFMT_QUERY) { |
1786 | formats = snd_pcm_oss_get_formats(pcm_oss_file); | 1870 | formats = snd_pcm_oss_get_formats(pcm_oss_file); |
@@ -1794,10 +1878,14 @@ static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int for | |||
1794 | if (substream == NULL) | 1878 | if (substream == NULL) |
1795 | continue; | 1879 | continue; |
1796 | runtime = substream->runtime; | 1880 | runtime = substream->runtime; |
1881 | err = lock_params(runtime); | ||
1882 | if (err < 0) | ||
1883 | return err; | ||
1797 | if (runtime->oss.format != format) { | 1884 | if (runtime->oss.format != format) { |
1798 | runtime->oss.params = 1; | 1885 | runtime->oss.params = 1; |
1799 | runtime->oss.format = format; | 1886 | runtime->oss.format = format; |
1800 | } | 1887 | } |
1888 | unlock_params(runtime); | ||
1801 | } | 1889 | } |
1802 | } | 1890 | } |
1803 | return snd_pcm_oss_get_format(pcm_oss_file); | 1891 | return snd_pcm_oss_get_format(pcm_oss_file); |
@@ -1817,8 +1905,6 @@ static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int s | |||
1817 | { | 1905 | { |
1818 | struct snd_pcm_runtime *runtime; | 1906 | struct snd_pcm_runtime *runtime; |
1819 | 1907 | ||
1820 | if (substream == NULL) | ||
1821 | return 0; | ||
1822 | runtime = substream->runtime; | 1908 | runtime = substream->runtime; |
1823 | if (subdivide == 0) { | 1909 | if (subdivide == 0) { |
1824 | subdivide = runtime->oss.subdivision; | 1910 | subdivide = runtime->oss.subdivision; |
@@ -1842,9 +1928,17 @@ static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int | |||
1842 | 1928 | ||
1843 | for (idx = 1; idx >= 0; --idx) { | 1929 | for (idx = 1; idx >= 0; --idx) { |
1844 | struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; | 1930 | struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; |
1931 | struct snd_pcm_runtime *runtime; | ||
1932 | |||
1845 | if (substream == NULL) | 1933 | if (substream == NULL) |
1846 | continue; | 1934 | continue; |
1847 | if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0) | 1935 | runtime = substream->runtime; |
1936 | err = lock_params(runtime); | ||
1937 | if (err < 0) | ||
1938 | return err; | ||
1939 | err = snd_pcm_oss_set_subdivide1(substream, subdivide); | ||
1940 | unlock_params(runtime); | ||
1941 | if (err < 0) | ||
1848 | return err; | 1942 | return err; |
1849 | } | 1943 | } |
1850 | return err; | 1944 | return err; |
@@ -1854,8 +1948,6 @@ static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsign | |||
1854 | { | 1948 | { |
1855 | struct snd_pcm_runtime *runtime; | 1949 | struct snd_pcm_runtime *runtime; |
1856 | 1950 | ||
1857 | if (substream == NULL) | ||
1858 | return 0; | ||
1859 | runtime = substream->runtime; | 1951 | runtime = substream->runtime; |
1860 | if (runtime->oss.subdivision || runtime->oss.fragshift) | 1952 | if (runtime->oss.subdivision || runtime->oss.fragshift) |
1861 | return -EINVAL; | 1953 | return -EINVAL; |
@@ -1875,9 +1967,17 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig | |||
1875 | 1967 | ||
1876 | for (idx = 1; idx >= 0; --idx) { | 1968 | for (idx = 1; idx >= 0; --idx) { |
1877 | struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; | 1969 | struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; |
1970 | struct snd_pcm_runtime *runtime; | ||
1971 | |||
1878 | if (substream == NULL) | 1972 | if (substream == NULL) |
1879 | continue; | 1973 | continue; |
1880 | if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0) | 1974 | runtime = substream->runtime; |
1975 | err = lock_params(runtime); | ||
1976 | if (err < 0) | ||
1977 | return err; | ||
1978 | err = snd_pcm_oss_set_fragment1(substream, val); | ||
1979 | unlock_params(runtime); | ||
1980 | if (err < 0) | ||
1881 | return err; | 1981 | return err; |
1882 | } | 1982 | } |
1883 | return err; | 1983 | return err; |
@@ -1961,6 +2061,9 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr | |||
1961 | } | 2061 | } |
1962 | if (psubstream) { | 2062 | if (psubstream) { |
1963 | runtime = psubstream->runtime; | 2063 | runtime = psubstream->runtime; |
2064 | cmd = 0; | ||
2065 | if (mutex_lock_interruptible(&runtime->oss.params_lock)) | ||
2066 | return -ERESTARTSYS; | ||
1964 | if (trigger & PCM_ENABLE_OUTPUT) { | 2067 | if (trigger & PCM_ENABLE_OUTPUT) { |
1965 | if (runtime->oss.trigger) | 2068 | if (runtime->oss.trigger) |
1966 | goto _skip1; | 2069 | goto _skip1; |
@@ -1978,13 +2081,19 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr | |||
1978 | cmd = SNDRV_PCM_IOCTL_DROP; | 2081 | cmd = SNDRV_PCM_IOCTL_DROP; |
1979 | runtime->oss.prepare = 1; | 2082 | runtime->oss.prepare = 1; |
1980 | } | 2083 | } |
1981 | err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL); | ||
1982 | if (err < 0) | ||
1983 | return err; | ||
1984 | } | ||
1985 | _skip1: | 2084 | _skip1: |
2085 | mutex_unlock(&runtime->oss.params_lock); | ||
2086 | if (cmd) { | ||
2087 | err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL); | ||
2088 | if (err < 0) | ||
2089 | return err; | ||
2090 | } | ||
2091 | } | ||
1986 | if (csubstream) { | 2092 | if (csubstream) { |
1987 | runtime = csubstream->runtime; | 2093 | runtime = csubstream->runtime; |
2094 | cmd = 0; | ||
2095 | if (mutex_lock_interruptible(&runtime->oss.params_lock)) | ||
2096 | return -ERESTARTSYS; | ||
1988 | if (trigger & PCM_ENABLE_INPUT) { | 2097 | if (trigger & PCM_ENABLE_INPUT) { |
1989 | if (runtime->oss.trigger) | 2098 | if (runtime->oss.trigger) |
1990 | goto _skip2; | 2099 | goto _skip2; |
@@ -1999,11 +2108,14 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr | |||
1999 | cmd = SNDRV_PCM_IOCTL_DROP; | 2108 | cmd = SNDRV_PCM_IOCTL_DROP; |
2000 | runtime->oss.prepare = 1; | 2109 | runtime->oss.prepare = 1; |
2001 | } | 2110 | } |
2002 | err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL); | ||
2003 | if (err < 0) | ||
2004 | return err; | ||
2005 | } | ||
2006 | _skip2: | 2111 | _skip2: |
2112 | mutex_unlock(&runtime->oss.params_lock); | ||
2113 | if (cmd) { | ||
2114 | err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL); | ||
2115 | if (err < 0) | ||
2116 | return err; | ||
2117 | } | ||
2118 | } | ||
2007 | return 0; | 2119 | return 0; |
2008 | } | 2120 | } |
2009 | 2121 | ||
@@ -2255,6 +2367,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, | |||
2255 | runtime->oss.maxfrags = 0; | 2367 | runtime->oss.maxfrags = 0; |
2256 | runtime->oss.subdivision = 0; | 2368 | runtime->oss.subdivision = 0; |
2257 | substream->pcm_release = snd_pcm_oss_release_substream; | 2369 | substream->pcm_release = snd_pcm_oss_release_substream; |
2370 | atomic_set(&runtime->oss.rw_ref, 0); | ||
2258 | } | 2371 | } |
2259 | 2372 | ||
2260 | static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) | 2373 | static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index a83152e7d387..f4a19509cccf 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1129,16 +1129,12 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, | |||
1129 | if (constrs->rules_num >= constrs->rules_all) { | 1129 | if (constrs->rules_num >= constrs->rules_all) { |
1130 | struct snd_pcm_hw_rule *new; | 1130 | struct snd_pcm_hw_rule *new; |
1131 | unsigned int new_rules = constrs->rules_all + 16; | 1131 | unsigned int new_rules = constrs->rules_all + 16; |
1132 | new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL); | 1132 | new = krealloc(constrs->rules, new_rules * sizeof(*c), |
1133 | GFP_KERNEL); | ||
1133 | if (!new) { | 1134 | if (!new) { |
1134 | va_end(args); | 1135 | va_end(args); |
1135 | return -ENOMEM; | 1136 | return -ENOMEM; |
1136 | } | 1137 | } |
1137 | if (constrs->rules) { | ||
1138 | memcpy(new, constrs->rules, | ||
1139 | constrs->rules_num * sizeof(*c)); | ||
1140 | kfree(constrs->rules); | ||
1141 | } | ||
1142 | constrs->rules = new; | 1138 | constrs->rules = new; |
1143 | constrs->rules_all = new_rules; | 1139 | constrs->rules_all = new_rules; |
1144 | } | 1140 | } |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index d18b3982548b..b84554893fab 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -323,7 +323,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, | |||
323 | struct snd_pcm_hw_constraints *constrs = | 323 | struct snd_pcm_hw_constraints *constrs = |
324 | &substream->runtime->hw_constraints; | 324 | &substream->runtime->hw_constraints; |
325 | unsigned int k; | 325 | unsigned int k; |
326 | unsigned int rstamps[constrs->rules_num]; | 326 | unsigned int *rstamps; |
327 | unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; | 327 | unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; |
328 | unsigned int stamp; | 328 | unsigned int stamp; |
329 | struct snd_pcm_hw_rule *r; | 329 | struct snd_pcm_hw_rule *r; |
@@ -331,7 +331,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, | |||
331 | struct snd_mask old_mask; | 331 | struct snd_mask old_mask; |
332 | struct snd_interval old_interval; | 332 | struct snd_interval old_interval; |
333 | bool again; | 333 | bool again; |
334 | int changed; | 334 | int changed, err = 0; |
335 | 335 | ||
336 | /* | 336 | /* |
337 | * Each application of rule has own sequence number. | 337 | * Each application of rule has own sequence number. |
@@ -339,8 +339,9 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, | |||
339 | * Each member of 'rstamps' array represents the sequence number of | 339 | * Each member of 'rstamps' array represents the sequence number of |
340 | * recent application of corresponding rule. | 340 | * recent application of corresponding rule. |
341 | */ | 341 | */ |
342 | for (k = 0; k < constrs->rules_num; k++) | 342 | rstamps = kcalloc(constrs->rules_num, sizeof(unsigned int), GFP_KERNEL); |
343 | rstamps[k] = 0; | 343 | if (!rstamps) |
344 | return -ENOMEM; | ||
344 | 345 | ||
345 | /* | 346 | /* |
346 | * Each member of 'vstamps' array represents the sequence number of | 347 | * Each member of 'vstamps' array represents the sequence number of |
@@ -398,8 +399,10 @@ retry: | |||
398 | } | 399 | } |
399 | 400 | ||
400 | changed = r->func(params, r); | 401 | changed = r->func(params, r); |
401 | if (changed < 0) | 402 | if (changed < 0) { |
402 | return changed; | 403 | err = changed; |
404 | goto out; | ||
405 | } | ||
403 | 406 | ||
404 | /* | 407 | /* |
405 | * When the parameter is changed, notify it to the caller | 408 | * When the parameter is changed, notify it to the caller |
@@ -430,7 +433,9 @@ retry: | |||
430 | if (again) | 433 | if (again) |
431 | goto retry; | 434 | goto retry; |
432 | 435 | ||
433 | return 0; | 436 | out: |
437 | kfree(rstamps); | ||
438 | return err; | ||
434 | } | 439 | } |
435 | 440 | ||
436 | static int fixup_unreferenced_params(struct snd_pcm_substream *substream, | 441 | static int fixup_unreferenced_params(struct snd_pcm_substream *substream, |
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 8632301489fa..9e96186742d0 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c | |||
@@ -63,15 +63,18 @@ static int slave_update(struct link_slave *slave) | |||
63 | struct snd_ctl_elem_value *uctl; | 63 | struct snd_ctl_elem_value *uctl; |
64 | int err, ch; | 64 | int err, ch; |
65 | 65 | ||
66 | uctl = kmalloc(sizeof(*uctl), GFP_KERNEL); | 66 | uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); |
67 | if (!uctl) | 67 | if (!uctl) |
68 | return -ENOMEM; | 68 | return -ENOMEM; |
69 | uctl->id = slave->slave.id; | 69 | uctl->id = slave->slave.id; |
70 | err = slave->slave.get(&slave->slave, uctl); | 70 | err = slave->slave.get(&slave->slave, uctl); |
71 | if (err < 0) | ||
72 | goto error; | ||
71 | for (ch = 0; ch < slave->info.count; ch++) | 73 | for (ch = 0; ch < slave->info.count; ch++) |
72 | slave->vals[ch] = uctl->value.integer.value[ch]; | 74 | slave->vals[ch] = uctl->value.integer.value[ch]; |
75 | error: | ||
73 | kfree(uctl); | 76 | kfree(uctl); |
74 | return 0; | 77 | return err < 0 ? err : 0; |
75 | } | 78 | } |
76 | 79 | ||
77 | /* get the slave ctl info and save the initial values */ | 80 | /* get the slave ctl info and save the initial values */ |