|
@@ -73,7 +73,7 @@ struct snd_timer_user {
|
|
struct timespec tstamp; /* trigger tstamp */
|
|
struct timespec tstamp; /* trigger tstamp */
|
|
wait_queue_head_t qchange_sleep;
|
|
wait_queue_head_t qchange_sleep;
|
|
struct fasync_struct *fasync;
|
|
struct fasync_struct *fasync;
|
|
- struct mutex tread_sem;
|
|
|
|
|
|
+ struct mutex ioctl_lock;
|
|
};
|
|
};
|
|
|
|
|
|
/* list of timers */
|
|
/* list of timers */
|
|
@@ -1253,7 +1253,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
spin_lock_init(&tu->qlock);
|
|
spin_lock_init(&tu->qlock);
|
|
init_waitqueue_head(&tu->qchange_sleep);
|
|
init_waitqueue_head(&tu->qchange_sleep);
|
|
- mutex_init(&tu->tread_sem);
|
|
|
|
|
|
+ mutex_init(&tu->ioctl_lock);
|
|
tu->ticks = 1;
|
|
tu->ticks = 1;
|
|
tu->queue_size = 128;
|
|
tu->queue_size = 128;
|
|
tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
|
|
tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
|
|
@@ -1273,8 +1273,10 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)
|
|
if (file->private_data) {
|
|
if (file->private_data) {
|
|
tu = file->private_data;
|
|
tu = file->private_data;
|
|
file->private_data = NULL;
|
|
file->private_data = NULL;
|
|
|
|
+ mutex_lock(&tu->ioctl_lock);
|
|
if (tu->timeri)
|
|
if (tu->timeri)
|
|
snd_timer_close(tu->timeri);
|
|
snd_timer_close(tu->timeri);
|
|
|
|
+ mutex_unlock(&tu->ioctl_lock);
|
|
kfree(tu->queue);
|
|
kfree(tu->queue);
|
|
kfree(tu->tqueue);
|
|
kfree(tu->tqueue);
|
|
kfree(tu);
|
|
kfree(tu);
|
|
@@ -1512,7 +1514,6 @@ static int snd_timer_user_tselect(struct file *file,
|
|
int err = 0;
|
|
int err = 0;
|
|
|
|
|
|
tu = file->private_data;
|
|
tu = file->private_data;
|
|
- mutex_lock(&tu->tread_sem);
|
|
|
|
if (tu->timeri) {
|
|
if (tu->timeri) {
|
|
snd_timer_close(tu->timeri);
|
|
snd_timer_close(tu->timeri);
|
|
tu->timeri = NULL;
|
|
tu->timeri = NULL;
|
|
@@ -1556,7 +1557,6 @@ static int snd_timer_user_tselect(struct file *file,
|
|
}
|
|
}
|
|
|
|
|
|
__err:
|
|
__err:
|
|
- mutex_unlock(&tu->tread_sem);
|
|
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1769,7 +1769,7 @@ enum {
|
|
SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
|
|
SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
|
|
};
|
|
};
|
|
|
|
|
|
-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
|
|
|
|
|
+static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
|
unsigned long arg)
|
|
unsigned long arg)
|
|
{
|
|
{
|
|
struct snd_timer_user *tu;
|
|
struct snd_timer_user *tu;
|
|
@@ -1786,17 +1786,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
|
{
|
|
{
|
|
int xarg;
|
|
int xarg;
|
|
|
|
|
|
- mutex_lock(&tu->tread_sem);
|
|
|
|
- if (tu->timeri) { /* too late */
|
|
|
|
- mutex_unlock(&tu->tread_sem);
|
|
|
|
|
|
+ if (tu->timeri) /* too late */
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
- }
|
|
|
|
- if (get_user(xarg, p)) {
|
|
|
|
- mutex_unlock(&tu->tread_sem);
|
|
|
|
|
|
+ if (get_user(xarg, p))
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
- }
|
|
|
|
tu->tread = xarg ? 1 : 0;
|
|
tu->tread = xarg ? 1 : 0;
|
|
- mutex_unlock(&tu->tread_sem);
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
case SNDRV_TIMER_IOCTL_GINFO:
|
|
case SNDRV_TIMER_IOCTL_GINFO:
|
|
@@ -1829,6 +1823,18 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
|
return -ENOTTY;
|
|
return -ENOTTY;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
|
|
|
+ unsigned long arg)
|
|
|
|
+{
|
|
|
|
+ struct snd_timer_user *tu = file->private_data;
|
|
|
|
+ long ret;
|
|
|
|
+
|
|
|
|
+ mutex_lock(&tu->ioctl_lock);
|
|
|
|
+ ret = __snd_timer_user_ioctl(file, cmd, arg);
|
|
|
|
+ mutex_unlock(&tu->ioctl_lock);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static int snd_timer_user_fasync(int fd, struct file * file, int on)
|
|
static int snd_timer_user_fasync(int fd, struct file * file, int on)
|
|
{
|
|
{
|
|
struct snd_timer_user *tu;
|
|
struct snd_timer_user *tu;
|