aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/oss/pcm_oss.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/oss/pcm_oss.c')
-rw-r--r--sound/core/oss/pcm_oss.c185
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
826static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, 826/* parameter locking: returns immediately if tried during streaming */
827 bool trylock) 827static 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
838static void unlock_params(struct snd_pcm_runtime *runtime)
839{
840 mutex_unlock(&runtime->oss.params_lock);
841}
842
843/* call with params_lock held */
844static 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 */
1089static 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 */
1099static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) 1131static 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 */
1175static 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 }
1698unlock:
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)
1781static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) 1864static 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
2260static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) 2373static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)