summaryrefslogtreecommitdiffstats
path: root/sound/oss/au1550_ac97.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/oss/au1550_ac97.c')
-rw-r--r--sound/oss/au1550_ac97.c91
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 @@
#include <linux/sound.h>
#include <linux/slab.h>
#include <linux/soundcard.h>
+#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -162,19 +163,10 @@ ld2(unsigned int x)
static void
au1550_delay(int msec)
{
- unsigned long tmo;
- signed long tmo2;
-
if (in_interrupt())
return;
- tmo = jiffies + (msec * HZ) / 1000;
- for (;;) {
- tmo2 = tmo - jiffies;
- if (tmo2 <= 0)
- break;
- schedule_timeout(tmo2);
- }
+ schedule_timeout_uninterruptible(msecs_to_jiffies(msec));
}
static u16
@@ -807,7 +799,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin)
static int
au1550_open_mixdev(struct inode *inode, struct file *file)
{
+ lock_kernel();
file->private_data = &au1550_state;
+ unlock_kernel();
return 0;
}
@@ -824,22 +818,26 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
return codec->mixer_ioctl(codec, cmd, arg);
}
-static int
-au1550_ioctl_mixdev(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long
+au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg)
{
struct au1550_state *s = (struct au1550_state *)file->private_data;
struct ac97_codec *codec = s->codec;
+ int ret;
- return mixdev_ioctl(codec, cmd, arg);
+ lock_kernel();
+ ret = mixdev_ioctl(codec, cmd, arg);
+ unlock_kernel();
+
+ return ret;
}
static /*const */ struct file_operations au1550_mixer_fops = {
- owner:THIS_MODULE,
- llseek:au1550_llseek,
- ioctl:au1550_ioctl_mixdev,
- open:au1550_open_mixdev,
- release:au1550_release_mixdev,
+ .owner = THIS_MODULE,
+ .llseek = au1550_llseek,
+ .unlocked_ioctl = au1550_ioctl_mixdev,
+ .open = au1550_open_mixdev,
+ .release = au1550_release_mixdev,
};
static int
@@ -1343,8 +1341,7 @@ dma_count_done(struct dmabuf *db)
static int
-au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct au1550_state *s = (struct au1550_state *)file->private_data;
unsigned long flags;
@@ -1780,6 +1777,17 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return mixdev_ioctl(s->codec, cmd, arg);
}
+static long
+au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret;
+
+ lock_kernel();
+ ret = au1550_ioctl(file, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+}
static int
au1550_open(struct inode *inode, struct file *file)
@@ -1797,21 +1805,22 @@ au1550_open(struct inode *inode, struct file *file)
#endif
file->private_data = s;
+ lock_kernel();
/* wait for device to become free */
mutex_lock(&s->open_mutex);
while (s->open_mode & file->f_mode) {
- if (file->f_flags & O_NONBLOCK) {
- mutex_unlock(&s->open_mutex);
- return -EBUSY;
- }
+ ret = -EBUSY;
+ if (file->f_flags & O_NONBLOCK)
+ goto out;
add_wait_queue(&s->open_wait, &wait);
__set_current_state(TASK_INTERRUPTIBLE);
mutex_unlock(&s->open_mutex);
schedule();
remove_wait_queue(&s->open_wait, &wait);
set_current_state(TASK_RUNNING);
+ ret = -ERESTARTSYS;
if (signal_pending(current))
- return -ERESTARTSYS;
+ goto out2;
mutex_lock(&s->open_mutex);
}
@@ -1840,17 +1849,21 @@ au1550_open(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_READ) {
if ((ret = prog_dmabuf_adc(s)))
- return ret;
+ goto out;
}
if (file->f_mode & FMODE_WRITE) {
if ((ret = prog_dmabuf_dac(s)))
- return ret;
+ goto out;
}
s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
- mutex_unlock(&s->open_mutex);
mutex_init(&s->sem);
- return 0;
+ ret = 0;
+out:
+ mutex_unlock(&s->open_mutex);
+out2:
+ unlock_kernel();
+ return ret;
}
static int
@@ -1885,15 +1898,15 @@ au1550_release(struct inode *inode, struct file *file)
}
static /*const */ struct file_operations au1550_audio_fops = {
- owner: THIS_MODULE,
- llseek: au1550_llseek,
- read: au1550_read,
- write: au1550_write,
- poll: au1550_poll,
- ioctl: au1550_ioctl,
- mmap: au1550_mmap,
- open: au1550_open,
- release: au1550_release,
+ .owner = THIS_MODULE,
+ .llseek = au1550_llseek,
+ .read = au1550_read,
+ .write = au1550_write,
+ .poll = au1550_poll,
+ .unlocked_ioctl = au1550_unlocked_ioctl,
+ .mmap = au1550_mmap,
+ .open = au1550_open,
+ .release = au1550_release,
};
MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");
OpenPOWER on IntegriCloud