diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-03-27 09:40:49 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-03-31 10:58:59 -0500 |
commit | 3bf75f9b90c981f18f27a0d35a44f488ab68c8ea (patch) | |
tree | 9284c90f09ce38fc3bb2ebc46624ddf3db09b526 | |
parent | bf1bbb5a49eec51c30d341606885507b501b37e8 (diff) |
[ALSA] Clean up PCM codes (take 2)
- Clean up initialization and destruction of substream instance
Now snd_pcm_open_substream() alone does most initialization jobs.
Add pcm_release callback for cleaning up at snd_pcm_release_substream()
- Tidy up PCM oss code
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | include/sound/pcm.h | 12 | ||||
-rw-r--r-- | include/sound/pcm_oss.h | 1 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 151 | ||||
-rw-r--r-- | sound/core/pcm.c | 12 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 49 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 108 |
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 | ||
393 | struct snd_pcm_str { | 391 | struct snd_pcm_str { |
@@ -468,8 +466,12 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream); | |||
468 | int snd_pcm_suspend_all(struct snd_pcm *pcm); | 466 | int snd_pcm_suspend_all(struct snd_pcm *pcm); |
469 | #endif | 467 | #endif |
470 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); | 468 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); |
471 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct snd_pcm_substream **rsubstream); | 469 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file, |
470 | struct snd_pcm_substream **rsubstream); | ||
472 | void snd_pcm_release_substream(struct snd_pcm_substream *substream); | 471 | void snd_pcm_release_substream(struct snd_pcm_substream *substream); |
472 | int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file, | ||
473 | struct snd_pcm_substream **rsubstream); | ||
474 | void snd_pcm_detach_substream(struct snd_pcm_substream *substream); | ||
473 | void snd_pcm_vma_notify_data(void *client, void *data); | 475 | void snd_pcm_vma_notify_data(void *client, void *data); |
474 | int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area); | 476 | int 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 { | |||
70 | struct snd_pcm_oss_substream { | 70 | struct 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 | ||
76 | struct snd_pcm_oss_stream { | 75 | struct 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 | ||
1674 | static 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 | |||
1674 | static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, | 1686 | static 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 | |||
1702 | static 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 | ||
1714 | static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) | 1719 | static 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 | ||
780 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | 780 | int 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 | ||
882 | void snd_pcm_release_substream(struct snd_pcm_substream *substream) | 882 | void 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 | ||
1998 | static int snd_pcm_release_file(struct snd_pcm_file * pcm_file) | 1998 | static 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 | |||
2007 | void 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 | |
2021 | int 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 | ||
2022 | static int snd_pcm_open_file(struct file *file, | 2057 | static 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 | ||
2483 | static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, | ||
2484 | unsigned int cmd, void __user *arg); | ||
2485 | static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, | ||
2486 | unsigned int cmd, void __user *arg); | ||
2487 | |||
2488 | static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, | 2494 | static 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 | { |