diff options
Diffstat (limited to 'sound/oss/au1550_ac97.c')
-rw-r--r-- | sound/oss/au1550_ac97.c | 91 |
1 files changed, 52 insertions, 39 deletions
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index c1070e33b32f..c4a4cdc07ab9 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/sound.h> | 43 | #include <linux/sound.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/soundcard.h> | 45 | #include <linux/soundcard.h> |
46 | #include <linux/smp_lock.h> | ||
46 | #include <linux/init.h> | 47 | #include <linux/init.h> |
47 | #include <linux/interrupt.h> | 48 | #include <linux/interrupt.h> |
48 | #include <linux/kernel.h> | 49 | #include <linux/kernel.h> |
@@ -162,19 +163,10 @@ ld2(unsigned int x) | |||
162 | static void | 163 | static void |
163 | au1550_delay(int msec) | 164 | au1550_delay(int msec) |
164 | { | 165 | { |
165 | unsigned long tmo; | ||
166 | signed long tmo2; | ||
167 | |||
168 | if (in_interrupt()) | 166 | if (in_interrupt()) |
169 | return; | 167 | return; |
170 | 168 | ||
171 | tmo = jiffies + (msec * HZ) / 1000; | 169 | schedule_timeout_uninterruptible(msecs_to_jiffies(msec)); |
172 | for (;;) { | ||
173 | tmo2 = tmo - jiffies; | ||
174 | if (tmo2 <= 0) | ||
175 | break; | ||
176 | schedule_timeout(tmo2); | ||
177 | } | ||
178 | } | 170 | } |
179 | 171 | ||
180 | static u16 | 172 | static u16 |
@@ -807,7 +799,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin) | |||
807 | static int | 799 | static int |
808 | au1550_open_mixdev(struct inode *inode, struct file *file) | 800 | au1550_open_mixdev(struct inode *inode, struct file *file) |
809 | { | 801 | { |
802 | lock_kernel(); | ||
810 | file->private_data = &au1550_state; | 803 | file->private_data = &au1550_state; |
804 | unlock_kernel(); | ||
811 | return 0; | 805 | return 0; |
812 | } | 806 | } |
813 | 807 | ||
@@ -824,22 +818,26 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, | |||
824 | return codec->mixer_ioctl(codec, cmd, arg); | 818 | return codec->mixer_ioctl(codec, cmd, arg); |
825 | } | 819 | } |
826 | 820 | ||
827 | static int | 821 | static long |
828 | au1550_ioctl_mixdev(struct inode *inode, struct file *file, | 822 | au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg) |
829 | unsigned int cmd, unsigned long arg) | ||
830 | { | 823 | { |
831 | struct au1550_state *s = (struct au1550_state *)file->private_data; | 824 | struct au1550_state *s = (struct au1550_state *)file->private_data; |
832 | struct ac97_codec *codec = s->codec; | 825 | struct ac97_codec *codec = s->codec; |
826 | int ret; | ||
833 | 827 | ||
834 | return mixdev_ioctl(codec, cmd, arg); | 828 | lock_kernel(); |
829 | ret = mixdev_ioctl(codec, cmd, arg); | ||
830 | unlock_kernel(); | ||
831 | |||
832 | return ret; | ||
835 | } | 833 | } |
836 | 834 | ||
837 | static /*const */ struct file_operations au1550_mixer_fops = { | 835 | static /*const */ struct file_operations au1550_mixer_fops = { |
838 | owner:THIS_MODULE, | 836 | .owner = THIS_MODULE, |
839 | llseek:au1550_llseek, | 837 | .llseek = au1550_llseek, |
840 | ioctl:au1550_ioctl_mixdev, | 838 | .unlocked_ioctl = au1550_ioctl_mixdev, |
841 | open:au1550_open_mixdev, | 839 | .open = au1550_open_mixdev, |
842 | release:au1550_release_mixdev, | 840 | .release = au1550_release_mixdev, |
843 | }; | 841 | }; |
844 | 842 | ||
845 | static int | 843 | static int |
@@ -1343,8 +1341,7 @@ dma_count_done(struct dmabuf *db) | |||
1343 | 1341 | ||
1344 | 1342 | ||
1345 | static int | 1343 | static int |
1346 | au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 1344 | au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1347 | unsigned long arg) | ||
1348 | { | 1345 | { |
1349 | struct au1550_state *s = (struct au1550_state *)file->private_data; | 1346 | struct au1550_state *s = (struct au1550_state *)file->private_data; |
1350 | unsigned long flags; | 1347 | unsigned long flags; |
@@ -1780,6 +1777,17 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
1780 | return mixdev_ioctl(s->codec, cmd, arg); | 1777 | return mixdev_ioctl(s->codec, cmd, arg); |
1781 | } | 1778 | } |
1782 | 1779 | ||
1780 | static long | ||
1781 | au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1782 | { | ||
1783 | int ret; | ||
1784 | |||
1785 | lock_kernel(); | ||
1786 | ret = au1550_ioctl(file, cmd, arg); | ||
1787 | unlock_kernel(); | ||
1788 | |||
1789 | return ret; | ||
1790 | } | ||
1783 | 1791 | ||
1784 | static int | 1792 | static int |
1785 | au1550_open(struct inode *inode, struct file *file) | 1793 | au1550_open(struct inode *inode, struct file *file) |
@@ -1797,21 +1805,22 @@ au1550_open(struct inode *inode, struct file *file) | |||
1797 | #endif | 1805 | #endif |
1798 | 1806 | ||
1799 | file->private_data = s; | 1807 | file->private_data = s; |
1808 | lock_kernel(); | ||
1800 | /* wait for device to become free */ | 1809 | /* wait for device to become free */ |
1801 | mutex_lock(&s->open_mutex); | 1810 | mutex_lock(&s->open_mutex); |
1802 | while (s->open_mode & file->f_mode) { | 1811 | while (s->open_mode & file->f_mode) { |
1803 | if (file->f_flags & O_NONBLOCK) { | 1812 | ret = -EBUSY; |
1804 | mutex_unlock(&s->open_mutex); | 1813 | if (file->f_flags & O_NONBLOCK) |
1805 | return -EBUSY; | 1814 | goto out; |
1806 | } | ||
1807 | add_wait_queue(&s->open_wait, &wait); | 1815 | add_wait_queue(&s->open_wait, &wait); |
1808 | __set_current_state(TASK_INTERRUPTIBLE); | 1816 | __set_current_state(TASK_INTERRUPTIBLE); |
1809 | mutex_unlock(&s->open_mutex); | 1817 | mutex_unlock(&s->open_mutex); |
1810 | schedule(); | 1818 | schedule(); |
1811 | remove_wait_queue(&s->open_wait, &wait); | 1819 | remove_wait_queue(&s->open_wait, &wait); |
1812 | set_current_state(TASK_RUNNING); | 1820 | set_current_state(TASK_RUNNING); |
1821 | ret = -ERESTARTSYS; | ||
1813 | if (signal_pending(current)) | 1822 | if (signal_pending(current)) |
1814 | return -ERESTARTSYS; | 1823 | goto out2; |
1815 | mutex_lock(&s->open_mutex); | 1824 | mutex_lock(&s->open_mutex); |
1816 | } | 1825 | } |
1817 | 1826 | ||
@@ -1840,17 +1849,21 @@ au1550_open(struct inode *inode, struct file *file) | |||
1840 | 1849 | ||
1841 | if (file->f_mode & FMODE_READ) { | 1850 | if (file->f_mode & FMODE_READ) { |
1842 | if ((ret = prog_dmabuf_adc(s))) | 1851 | if ((ret = prog_dmabuf_adc(s))) |
1843 | return ret; | 1852 | goto out; |
1844 | } | 1853 | } |
1845 | if (file->f_mode & FMODE_WRITE) { | 1854 | if (file->f_mode & FMODE_WRITE) { |
1846 | if ((ret = prog_dmabuf_dac(s))) | 1855 | if ((ret = prog_dmabuf_dac(s))) |
1847 | return ret; | 1856 | goto out; |
1848 | } | 1857 | } |
1849 | 1858 | ||
1850 | s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); | 1859 | s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); |
1851 | mutex_unlock(&s->open_mutex); | ||
1852 | mutex_init(&s->sem); | 1860 | mutex_init(&s->sem); |
1853 | return 0; | 1861 | ret = 0; |
1862 | out: | ||
1863 | mutex_unlock(&s->open_mutex); | ||
1864 | out2: | ||
1865 | unlock_kernel(); | ||
1866 | return ret; | ||
1854 | } | 1867 | } |
1855 | 1868 | ||
1856 | static int | 1869 | static int |
@@ -1885,15 +1898,15 @@ au1550_release(struct inode *inode, struct file *file) | |||
1885 | } | 1898 | } |
1886 | 1899 | ||
1887 | static /*const */ struct file_operations au1550_audio_fops = { | 1900 | static /*const */ struct file_operations au1550_audio_fops = { |
1888 | owner: THIS_MODULE, | 1901 | .owner = THIS_MODULE, |
1889 | llseek: au1550_llseek, | 1902 | .llseek = au1550_llseek, |
1890 | read: au1550_read, | 1903 | .read = au1550_read, |
1891 | write: au1550_write, | 1904 | .write = au1550_write, |
1892 | poll: au1550_poll, | 1905 | .poll = au1550_poll, |
1893 | ioctl: au1550_ioctl, | 1906 | .unlocked_ioctl = au1550_unlocked_ioctl, |
1894 | mmap: au1550_mmap, | 1907 | .mmap = au1550_mmap, |
1895 | open: au1550_open, | 1908 | .open = au1550_open, |
1896 | release: au1550_release, | 1909 | .release = au1550_release, |
1897 | }; | 1910 | }; |
1898 | 1911 | ||
1899 | MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com"); | 1912 | MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com"); |