aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/pcm.h12
-rw-r--r--include/sound/pcm_oss.h1
-rw-r--r--sound/core/oss/pcm_oss.c151
-rw-r--r--sound/core/pcm.c12
-rw-r--r--sound/core/pcm_lib.c49
-rw-r--r--sound/core/pcm_native.c108
6 files changed, 114 insertions, 219 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 7cf6a30c1526..66b1f08b42b9 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -369,6 +369,7 @@ struct snd_pcm_substream {
369 /* -- assigned files -- */ 369 /* -- assigned files -- */
370 struct snd_pcm_file *file; 370 struct snd_pcm_file *file;
371 struct file *ffile; 371 struct file *ffile;
372 void (*pcm_release)(struct snd_pcm_substream *);
372#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) 373#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
373 /* -- OSS things -- */ 374 /* -- OSS things -- */
374 struct snd_pcm_oss_substream oss; 375 struct snd_pcm_oss_substream oss;
@@ -381,13 +382,10 @@ struct snd_pcm_substream {
381 struct snd_info_entry *proc_prealloc_entry; 382 struct snd_info_entry *proc_prealloc_entry;
382 /* misc flags */ 383 /* misc flags */
383 unsigned int no_mmap_ctrl: 1; 384 unsigned int no_mmap_ctrl: 1;
385 unsigned int hw_opened: 1;
384}; 386};
385 387
386#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
387#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL || ((substream)->oss.file != NULL))
388#else
389#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL) 388#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL)
390#endif
391 389
392 390
393struct snd_pcm_str { 391struct snd_pcm_str {
@@ -468,8 +466,12 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream);
468int snd_pcm_suspend_all(struct snd_pcm *pcm); 466int snd_pcm_suspend_all(struct snd_pcm *pcm);
469#endif 467#endif
470int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); 468int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
471int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct snd_pcm_substream **rsubstream); 469int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file,
470 struct snd_pcm_substream **rsubstream);
472void snd_pcm_release_substream(struct snd_pcm_substream *substream); 471void snd_pcm_release_substream(struct snd_pcm_substream *substream);
472int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file,
473 struct snd_pcm_substream **rsubstream);
474void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
473void snd_pcm_vma_notify_data(void *client, void *data); 475void snd_pcm_vma_notify_data(void *client, void *data);
474int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area); 476int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
475 477
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index bff0778e1969..1d522aaa66df 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -70,7 +70,6 @@ struct snd_pcm_oss_file {
70struct snd_pcm_oss_substream { 70struct snd_pcm_oss_substream {
71 unsigned oss: 1; /* oss mode */ 71 unsigned oss: 1; /* oss mode */
72 struct snd_pcm_oss_setup *setup; /* active setup */ 72 struct snd_pcm_oss_setup *setup; /* active setup */
73 struct snd_pcm_oss_file *file;
74}; 73};
75 74
76struct snd_pcm_oss_stream { 75struct snd_pcm_oss_stream {
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 54be0bba6bd2..c056cbfe5519 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1671,6 +1671,18 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm,
1671 return NULL; 1671 return NULL;
1672} 1672}
1673 1673
1674static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
1675{
1676 struct snd_pcm_runtime *runtime;
1677 runtime = substream->runtime;
1678 vfree(runtime->oss.buffer);
1679 runtime->oss.buffer = NULL;
1680#ifdef CONFIG_SND_PCM_OSS_PLUGINS
1681 snd_pcm_oss_plugin_clear(substream);
1682#endif
1683 substream->oss.oss = 0;
1684}
1685
1674static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, 1686static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
1675 struct snd_pcm_oss_setup *setup, 1687 struct snd_pcm_oss_setup *setup,
1676 int minor) 1688 int minor)
@@ -1679,6 +1691,10 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
1679 1691
1680 substream->oss.oss = 1; 1692 substream->oss.oss = 1;
1681 substream->oss.setup = setup; 1693 substream->oss.setup = setup;
1694 if (setup->nonblock)
1695 substream->ffile->f_flags |= O_NONBLOCK;
1696 else
1697 substream->ffile->f_flags &= ~O_NONBLOCK;
1682 runtime = substream->runtime; 1698 runtime = substream->runtime;
1683 runtime->oss.params = 1; 1699 runtime->oss.params = 1;
1684 runtime->oss.trigger = 1; 1700 runtime->oss.trigger = 1;
@@ -1697,18 +1713,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
1697 runtime->oss.fragshift = 0; 1713 runtime->oss.fragshift = 0;
1698 runtime->oss.maxfrags = 0; 1714 runtime->oss.maxfrags = 0;
1699 runtime->oss.subdivision = 0; 1715 runtime->oss.subdivision = 0;
1700} 1716 substream->pcm_release = snd_pcm_oss_release_substream;
1701
1702static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
1703{
1704 struct snd_pcm_runtime *runtime;
1705 runtime = substream->runtime;
1706 vfree(runtime->oss.buffer);
1707#ifdef CONFIG_SND_PCM_OSS_PLUGINS
1708 snd_pcm_oss_plugin_clear(substream);
1709#endif
1710 substream->oss.file = NULL;
1711 substream->oss.oss = 0;
1712} 1717}
1713 1718
1714static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) 1719static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
@@ -1717,23 +1722,8 @@ static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
1717 snd_assert(pcm_oss_file != NULL, return -ENXIO); 1722 snd_assert(pcm_oss_file != NULL, return -ENXIO);
1718 for (cidx = 0; cidx < 2; ++cidx) { 1723 for (cidx = 0; cidx < 2; ++cidx) {
1719 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; 1724 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
1720 struct snd_pcm_runtime *runtime; 1725 if (substream)
1721 if (substream == NULL) 1726 snd_pcm_release_substream(substream);
1722 continue;
1723 runtime = substream->runtime;
1724
1725 snd_pcm_stream_lock_irq(substream);
1726 if (snd_pcm_running(substream))
1727 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1728 snd_pcm_stream_unlock_irq(substream);
1729 if (substream->ffile != NULL) {
1730 if (substream->ops->hw_free != NULL)
1731 substream->ops->hw_free(substream);
1732 substream->ops->close(substream);
1733 substream->ffile = NULL;
1734 }
1735 snd_pcm_oss_release_substream(substream);
1736 snd_pcm_release_substream(substream);
1737 } 1727 }
1738 kfree(pcm_oss_file); 1728 kfree(pcm_oss_file);
1739 return 0; 1729 return 0;
@@ -1743,12 +1733,11 @@ static int snd_pcm_oss_open_file(struct file *file,
1743 struct snd_pcm *pcm, 1733 struct snd_pcm *pcm,
1744 struct snd_pcm_oss_file **rpcm_oss_file, 1734 struct snd_pcm_oss_file **rpcm_oss_file,
1745 int minor, 1735 int minor,
1746 struct snd_pcm_oss_setup *psetup, 1736 struct snd_pcm_oss_setup **setup)
1747 struct snd_pcm_oss_setup *csetup)
1748{ 1737{
1749 int err = 0; 1738 int idx, err;
1750 struct snd_pcm_oss_file *pcm_oss_file; 1739 struct snd_pcm_oss_file *pcm_oss_file;
1751 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 1740 struct snd_pcm_substream *substream;
1752 unsigned int f_mode = file->f_mode; 1741 unsigned int f_mode = file->f_mode;
1753 1742
1754 snd_assert(rpcm_oss_file != NULL, return -EINVAL); 1743 snd_assert(rpcm_oss_file != NULL, return -EINVAL);
@@ -1761,73 +1750,31 @@ static int snd_pcm_oss_open_file(struct file *file,
1761 if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) && 1750 if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
1762 (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) 1751 (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
1763 f_mode = FMODE_WRITE; 1752 f_mode = FMODE_WRITE;
1764 if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) { 1753
1765 if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1754 for (idx = 0; idx < 2; idx++) {
1766 &psubstream)) < 0) { 1755 if (! setup[idx] || setup[idx]->disable)
1756 continue;
1757 if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
1758 if (! (f_mode & FMODE_WRITE))
1759 continue;
1760 } else {
1761 if (! (f_mode & FMODE_READ))
1762 continue;
1763 }
1764 err = snd_pcm_open_substream(pcm, idx, file, &substream);
1765 if (err < 0) {
1767 snd_pcm_oss_release_file(pcm_oss_file); 1766 snd_pcm_oss_release_file(pcm_oss_file);
1768 return err; 1767 return err;
1769 } 1768 }
1770 pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream; 1769
1771 } 1770 pcm_oss_file->streams[idx] = substream;
1772 if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) { 1771 snd_pcm_oss_init_substream(substream, setup[idx], minor);
1773 if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE,
1774 &csubstream)) < 0) {
1775 if (!(f_mode & FMODE_WRITE) || err != -ENODEV) {
1776 snd_pcm_oss_release_file(pcm_oss_file);
1777 return err;
1778 } else {
1779 csubstream = NULL;
1780 }
1781 }
1782 pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;
1783 } 1772 }
1784 1773
1785 if (psubstream == NULL && csubstream == NULL) { 1774 if (! pcm_oss_file->streams[0] && pcm_oss_file->streams[1]) {
1786 snd_pcm_oss_release_file(pcm_oss_file); 1775 snd_pcm_oss_release_file(pcm_oss_file);
1787 return -EINVAL; 1776 return -EINVAL;
1788 } 1777 }
1789 if (psubstream != NULL) {
1790 psubstream->oss.file = pcm_oss_file;
1791 err = snd_pcm_hw_constraints_init(psubstream);
1792 if (err < 0) {
1793 snd_printd("snd_pcm_hw_constraint_init failed\n");
1794 snd_pcm_oss_release_file(pcm_oss_file);
1795 return err;
1796 }
1797 if ((err = psubstream->ops->open(psubstream)) < 0) {
1798 snd_pcm_oss_release_file(pcm_oss_file);
1799 return err;
1800 }
1801 psubstream->ffile = file;
1802 err = snd_pcm_hw_constraints_complete(psubstream);
1803 if (err < 0) {
1804 snd_printd("snd_pcm_hw_constraint_complete failed\n");
1805 snd_pcm_oss_release_file(pcm_oss_file);
1806 return err;
1807 }
1808 snd_pcm_oss_init_substream(psubstream, psetup, minor);
1809 }
1810 if (csubstream != NULL) {
1811 csubstream->oss.file = pcm_oss_file;
1812 err = snd_pcm_hw_constraints_init(csubstream);
1813 if (err < 0) {
1814 snd_printd("snd_pcm_hw_constraint_init failed\n");
1815 snd_pcm_oss_release_file(pcm_oss_file);
1816 return err;
1817 }
1818 if ((err = csubstream->ops->open(csubstream)) < 0) {
1819 snd_pcm_oss_release_file(pcm_oss_file);
1820 return err;
1821 }
1822 csubstream->ffile = file;
1823 err = snd_pcm_hw_constraints_complete(csubstream);
1824 if (err < 0) {
1825 snd_printd("snd_pcm_hw_constraint_complete failed\n");
1826 snd_pcm_oss_release_file(pcm_oss_file);
1827 return err;
1828 }
1829 snd_pcm_oss_init_substream(csubstream, csetup, minor);
1830 }
1831 1778
1832 file->private_data = pcm_oss_file; 1779 file->private_data = pcm_oss_file;
1833 *rpcm_oss_file = pcm_oss_file; 1780 *rpcm_oss_file = pcm_oss_file;
@@ -1852,7 +1799,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1852 char task_name[32]; 1799 char task_name[32];
1853 struct snd_pcm *pcm; 1800 struct snd_pcm *pcm;
1854 struct snd_pcm_oss_file *pcm_oss_file; 1801 struct snd_pcm_oss_file *pcm_oss_file;
1855 struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL; 1802 struct snd_pcm_oss_setup *setup[2];
1856 int nonblock; 1803 int nonblock;
1857 wait_queue_t wait; 1804 wait_queue_t wait;
1858 1805
@@ -1873,23 +1820,13 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1873 err = -EFAULT; 1820 err = -EFAULT;
1874 goto __error; 1821 goto __error;
1875 } 1822 }
1823 memset(setup, 0, sizeof(*setup));
1876 if (file->f_mode & FMODE_WRITE) 1824 if (file->f_mode & FMODE_WRITE)
1877 psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name); 1825 setup[0] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
1878 if (file->f_mode & FMODE_READ) 1826 if (file->f_mode & FMODE_READ)
1879 csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name); 1827 setup[1] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
1880 1828
1881 nonblock = !!(file->f_flags & O_NONBLOCK); 1829 nonblock = !!(file->f_flags & O_NONBLOCK);
1882 if (psetup && !psetup->disable) {
1883 if (psetup->nonblock)
1884 nonblock = 1;
1885 else if (psetup->block)
1886 nonblock = 0;
1887 } else if (csetup && !csetup->disable) {
1888 if (csetup->nonblock)
1889 nonblock = 1;
1890 else if (csetup->block)
1891 nonblock = 0;
1892 }
1893 if (!nonblock) 1830 if (!nonblock)
1894 nonblock = nonblock_open; 1831 nonblock = nonblock_open;
1895 1832
@@ -1898,7 +1835,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1898 mutex_lock(&pcm->open_mutex); 1835 mutex_lock(&pcm->open_mutex);
1899 while (1) { 1836 while (1) {
1900 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, 1837 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
1901 iminor(inode), psetup, csetup); 1838 iminor(inode), setup);
1902 if (err >= 0) 1839 if (err >= 0)
1903 break; 1840 break;
1904 if (err == -EAGAIN) { 1841 if (err == -EAGAIN) {
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 1e9878fed37f..5d7eb123b999 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -777,8 +777,9 @@ static void snd_pcm_tick_timer_func(unsigned long data)
777 snd_pcm_tick_elapsed(substream); 777 snd_pcm_tick_elapsed(substream);
778} 778}
779 779
780int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, 780int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
781 struct snd_pcm_substream **rsubstream) 781 struct file *file,
782 struct snd_pcm_substream **rsubstream)
782{ 783{
783 struct snd_pcm_str * pstr; 784 struct snd_pcm_str * pstr;
784 struct snd_pcm_substream *substream; 785 struct snd_pcm_substream *substream;
@@ -793,7 +794,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
793 *rsubstream = NULL; 794 *rsubstream = NULL;
794 snd_assert(pcm != NULL, return -ENXIO); 795 snd_assert(pcm != NULL, return -ENXIO);
795 pstr = &pcm->streams[stream]; 796 pstr = &pcm->streams[stream];
796 if (pstr->substream == NULL) 797 if (pstr->substream == NULL || pstr->substream_count == 0)
797 return -ENODEV; 798 return -ENODEV;
798 799
799 card = pcm->card; 800 card = pcm->card;
@@ -807,8 +808,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
807 } 808 }
808 up_read(&card->controls_rwsem); 809 up_read(&card->controls_rwsem);
809 810
810 if (pstr->substream_count == 0)
811 return -ENODEV;
812 switch (stream) { 811 switch (stream) {
813 case SNDRV_PCM_STREAM_PLAYBACK: 812 case SNDRV_PCM_STREAM_PLAYBACK:
814 if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { 813 if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
@@ -874,12 +873,13 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
874 873
875 substream->runtime = runtime; 874 substream->runtime = runtime;
876 substream->private_data = pcm->private_data; 875 substream->private_data = pcm->private_data;
876 substream->ffile = file;
877 pstr->substream_opened++; 877 pstr->substream_opened++;
878 *rsubstream = substream; 878 *rsubstream = substream;
879 return 0; 879 return 0;
880} 880}
881 881
882void snd_pcm_release_substream(struct snd_pcm_substream *substream) 882void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
883{ 883{
884 struct snd_pcm_runtime *runtime; 884 struct snd_pcm_runtime *runtime;
885 substream->file = NULL; 885 substream->file = NULL;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index eeba2f060955..230a940d00bd 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2299,19 +2299,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v
2299 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 2299 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2300 return -EBADFD; 2300 return -EBADFD;
2301 2301
2302 snd_assert(substream->ffile != NULL, return -ENXIO);
2303 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); 2302 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
2304#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
2305 if (substream->oss.oss) {
2306 struct snd_pcm_oss_setup *setup = substream->oss.setup;
2307 if (setup != NULL) {
2308 if (setup->nonblock)
2309 nonblock = 1;
2310 else if (setup->block)
2311 nonblock = 0;
2312 }
2313 }
2314#endif
2315 2303
2316 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && 2304 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
2317 runtime->channels > 1) 2305 runtime->channels > 1)
@@ -2374,19 +2362,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
2374 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 2362 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2375 return -EBADFD; 2363 return -EBADFD;
2376 2364
2377 snd_assert(substream->ffile != NULL, return -ENXIO);
2378 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); 2365 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
2379#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
2380 if (substream->oss.oss) {
2381 struct snd_pcm_oss_setup *setup = substream->oss.setup;
2382 if (setup != NULL) {
2383 if (setup->nonblock)
2384 nonblock = 1;
2385 else if (setup->block)
2386 nonblock = 0;
2387 }
2388 }
2389#endif
2390 2366
2391 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) 2367 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2392 return -EINVAL; 2368 return -EINVAL;
@@ -2596,19 +2572,7 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u
2596 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 2572 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2597 return -EBADFD; 2573 return -EBADFD;
2598 2574
2599 snd_assert(substream->ffile != NULL, return -ENXIO);
2600 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); 2575 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
2601#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
2602 if (substream->oss.oss) {
2603 struct snd_pcm_oss_setup *setup = substream->oss.setup;
2604 if (setup != NULL) {
2605 if (setup->nonblock)
2606 nonblock = 1;
2607 else if (setup->block)
2608 nonblock = 0;
2609 }
2610 }
2611#endif
2612 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) 2576 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
2613 return -EINVAL; 2577 return -EINVAL;
2614 return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); 2578 return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
@@ -2665,20 +2629,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
2665 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 2629 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2666 return -EBADFD; 2630 return -EBADFD;
2667 2631
2668 snd_assert(substream->ffile != NULL, return -ENXIO);
2669 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); 2632 nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
2670#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
2671 if (substream->oss.oss) {
2672 struct snd_pcm_oss_setup *setup = substream->oss.setup;
2673 if (setup != NULL) {
2674 if (setup->nonblock)
2675 nonblock = 1;
2676 else if (setup->block)
2677 nonblock = 0;
2678 }
2679 }
2680#endif
2681
2682 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) 2633 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2683 return -EINVAL; 2634 return -EINVAL;
2684 return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); 2635 return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 13efe39e4cc6..964e4c47a7f1 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1995,28 +1995,63 @@ static void snd_pcm_remove_file(struct snd_pcm_str *str,
1995 } 1995 }
1996} 1996}
1997 1997
1998static int snd_pcm_release_file(struct snd_pcm_file * pcm_file) 1998static void pcm_release_private(struct snd_pcm_substream *substream)
1999{ 1999{
2000 struct snd_pcm_substream *substream; 2000 struct snd_pcm_file *pcm_file = substream->file;
2001 struct snd_pcm_runtime *runtime;
2002 struct snd_pcm_str * str;
2003 2001
2004 snd_assert(pcm_file != NULL, return -ENXIO);
2005 substream = pcm_file->substream;
2006 snd_assert(substream != NULL, return -ENXIO);
2007 runtime = substream->runtime;
2008 str = substream->pstr;
2009 snd_pcm_unlink(substream); 2002 snd_pcm_unlink(substream);
2010 if (substream->ffile != NULL) { 2003 snd_pcm_remove_file(substream->pstr, pcm_file);
2004 kfree(pcm_file);
2005}
2006
2007void snd_pcm_release_substream(struct snd_pcm_substream *substream)
2008{
2009 snd_pcm_drop(substream);
2010 if (substream->pcm_release)
2011 substream->pcm_release(substream);
2012 if (substream->hw_opened) {
2011 if (substream->ops->hw_free != NULL) 2013 if (substream->ops->hw_free != NULL)
2012 substream->ops->hw_free(substream); 2014 substream->ops->hw_free(substream);
2013 substream->ops->close(substream); 2015 substream->ops->close(substream);
2014 substream->ffile = NULL; 2016 substream->hw_opened = 0;
2015 } 2017 }
2016 snd_pcm_remove_file(str, pcm_file); 2018 snd_pcm_detach_substream(substream);
2017 snd_pcm_release_substream(substream); 2019}
2018 kfree(pcm_file); 2020
2021int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
2022 struct file *file,
2023 struct snd_pcm_substream **rsubstream)
2024{
2025 struct snd_pcm_substream *substream;
2026 int err;
2027
2028 err = snd_pcm_attach_substream(pcm, stream, file, &substream);
2029 if (err < 0)
2030 return err;
2031 substream->no_mmap_ctrl = 0;
2032 err = snd_pcm_hw_constraints_init(substream);
2033 if (err < 0) {
2034 snd_printd("snd_pcm_hw_constraints_init failed\n");
2035 goto error;
2036 }
2037
2038 if ((err = substream->ops->open(substream)) < 0)
2039 goto error;
2040
2041 substream->hw_opened = 1;
2042
2043 err = snd_pcm_hw_constraints_complete(substream);
2044 if (err < 0) {
2045 snd_printd("snd_pcm_hw_constraints_complete failed\n");
2046 goto error;
2047 }
2048
2049 *rsubstream = substream;
2019 return 0; 2050 return 0;
2051
2052 error:
2053 snd_pcm_release_substream(substream);
2054 return err;
2020} 2055}
2021 2056
2022static int snd_pcm_open_file(struct file *file, 2057static int snd_pcm_open_file(struct file *file,
@@ -2024,52 +2059,29 @@ static int snd_pcm_open_file(struct file *file,
2024 int stream, 2059 int stream,
2025 struct snd_pcm_file **rpcm_file) 2060 struct snd_pcm_file **rpcm_file)
2026{ 2061{
2027 int err = 0;
2028 struct snd_pcm_file *pcm_file; 2062 struct snd_pcm_file *pcm_file;
2029 struct snd_pcm_substream *substream; 2063 struct snd_pcm_substream *substream;
2030 struct snd_pcm_str *str; 2064 struct snd_pcm_str *str;
2065 int err;
2031 2066
2032 snd_assert(rpcm_file != NULL, return -EINVAL); 2067 snd_assert(rpcm_file != NULL, return -EINVAL);
2033 *rpcm_file = NULL; 2068 *rpcm_file = NULL;
2034 2069
2070 err = snd_pcm_open_substream(pcm, stream, file, &substream);
2071 if (err < 0)
2072 return err;
2073
2035 pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); 2074 pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
2036 if (pcm_file == NULL) { 2075 if (pcm_file == NULL) {
2076 snd_pcm_release_substream(substream);
2037 return -ENOMEM; 2077 return -ENOMEM;
2038 } 2078 }
2039
2040 if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
2041 kfree(pcm_file);
2042 return err;
2043 }
2044
2045 str = substream->pstr; 2079 str = substream->pstr;
2046 substream->file = pcm_file; 2080 substream->file = pcm_file;
2047 substream->no_mmap_ctrl = 0; 2081 substream->pcm_release = pcm_release_private;
2048
2049 pcm_file->substream = substream; 2082 pcm_file->substream = substream;
2050
2051 snd_pcm_add_file(str, pcm_file); 2083 snd_pcm_add_file(str, pcm_file);
2052 2084
2053 err = snd_pcm_hw_constraints_init(substream);
2054 if (err < 0) {
2055 snd_printd("snd_pcm_hw_constraints_init failed\n");
2056 snd_pcm_release_file(pcm_file);
2057 return err;
2058 }
2059
2060 if ((err = substream->ops->open(substream)) < 0) {
2061 snd_pcm_release_file(pcm_file);
2062 return err;
2063 }
2064 substream->ffile = file;
2065
2066 err = snd_pcm_hw_constraints_complete(substream);
2067 if (err < 0) {
2068 snd_printd("snd_pcm_hw_constraints_complete failed\n");
2069 snd_pcm_release_file(pcm_file);
2070 return err;
2071 }
2072
2073 file->private_data = pcm_file; 2085 file->private_data = pcm_file;
2074 *rpcm_file = pcm_file; 2086 *rpcm_file = pcm_file;
2075 return 0; 2087 return 0;
@@ -2158,10 +2170,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
2158 snd_assert(substream != NULL, return -ENXIO); 2170 snd_assert(substream != NULL, return -ENXIO);
2159 snd_assert(!atomic_read(&substream->runtime->mmap_count), ); 2171 snd_assert(!atomic_read(&substream->runtime->mmap_count), );
2160 pcm = substream->pcm; 2172 pcm = substream->pcm;
2161 snd_pcm_drop(substream);
2162 fasync_helper(-1, file, 0, &substream->runtime->fasync); 2173 fasync_helper(-1, file, 0, &substream->runtime->fasync);
2163 mutex_lock(&pcm->open_mutex); 2174 mutex_lock(&pcm->open_mutex);
2164 snd_pcm_release_file(pcm_file); 2175 snd_pcm_release_substream(substream);
2165 mutex_unlock(&pcm->open_mutex); 2176 mutex_unlock(&pcm->open_mutex);
2166 wake_up(&pcm->open_wait); 2177 wake_up(&pcm->open_wait);
2167 module_put(pcm->card->module); 2178 module_put(pcm->card->module);
@@ -2480,11 +2491,6 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
2480 return 0; 2491 return 0;
2481} 2492}
2482 2493
2483static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
2484 unsigned int cmd, void __user *arg);
2485static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
2486 unsigned int cmd, void __user *arg);
2487
2488static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, 2494static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
2489 unsigned int cmd, void __user *arg) 2495 unsigned int cmd, void __user *arg)
2490{ 2496{