diff options
Diffstat (limited to 'sound/core/oss/pcm_oss.c')
-rw-r--r-- | sound/core/oss/pcm_oss.c | 185 |
1 files changed, 149 insertions, 36 deletions
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) |