#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/mutex.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
#include <sound/core.h>
struct timespec tstamp; /* trigger tstamp */
wait_queue_head_t qchange_sleep;
struct fasync_struct *fasync;
- struct semaphore tread_sem;
+ struct mutex tread_sem;
};
/* list of timers */
/* lock for slave active lists */
static DEFINE_SPINLOCK(slave_active_lock);
-static DECLARE_MUTEX(register_mutex);
+static DEFINE_MUTEX(register_mutex);
static int snd_timer_free(struct snd_timer *timer);
static int snd_timer_dev_free(struct snd_device *device);
snd_printd("invalid slave class %i\n", tid->dev_sclass);
return -EINVAL;
}
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
timeri = snd_timer_instance_new(owner, NULL);
if (!timeri) {
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
return -ENOMEM;
}
timeri->slave_class = tid->dev_sclass;
timeri->flags |= SNDRV_TIMER_IFLG_SLAVE;
list_add_tail(&timeri->open_list, &snd_timer_slave_list);
snd_timer_check_slave(timeri);
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
*ti = timeri;
return 0;
}
/* open a master instance */
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
timer = snd_timer_find(tid);
#ifdef CONFIG_KMOD
if (timer == NULL) {
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
snd_timer_request(tid);
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
timer = snd_timer_find(tid);
}
#endif
if (!timer) {
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
return -ENODEV;
}
if (!list_empty(&timer->open_list_head)) {
timeri = list_entry(timer->open_list_head.next,
struct snd_timer_instance, open_list);
if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) {
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
return -EBUSY;
}
}
timeri = snd_timer_instance_new(owner, timer);
if (!timeri) {
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
return -ENOMEM;
}
timeri->slave_class = tid->dev_sclass;
timer->hw.open(timer);
list_add_tail(&timeri->open_list, &timer->open_list_head);
snd_timer_check_master(timeri);
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
*ti = timeri;
return 0;
}
spin_lock_irq(&slave_active_lock);
}
spin_unlock_irq(&slave_active_lock);
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
list_del(&timeri->open_list);
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
} else {
timer = timeri->timer;
/* wait, until the active callback is finished */
spin_lock_irq(&timer->lock);
}
spin_unlock_irq(&timer->lock);
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
list_del(&timeri->open_list);
if (timer && list_empty(&timer->open_list_head) &&
timer->hw.close)
slave->timer = NULL;
spin_unlock_irq(&slave_active_lock);
}
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
}
if (timeri->private_free)
timeri->private_free(timeri);
struct snd_timer_instance *ti, *ts;
unsigned long resolution, ticks;
struct list_head *p, *q, *n, *ack_list_head;
+ unsigned long flags;
int use_tasklet = 0;
if (timer == NULL)
return;
- spin_lock(&timer->lock);
+ spin_lock_irqsave(&timer->lock, flags);
/* remember the current resolution */
if (timer->hw.c_resolution)
/* do we have any slow callbacks? */
use_tasklet = !list_empty(&timer->sack_list_head);
- spin_unlock(&timer->lock);
+ spin_unlock_irqrestore(&timer->lock, flags);
if (use_tasklet)
tasklet_hi_schedule(&timer->task_queue);
snd_assert(rtimer != NULL, return -EINVAL);
*rtimer = NULL;
timer = kzalloc(sizeof(*timer), GFP_KERNEL);
- if (timer == NULL)
+ if (timer == NULL) {
+ snd_printk(KERN_ERR "timer: cannot allocate\n");
return -ENOMEM;
+ }
timer->tmr_class = tid->dev_class;
timer->card = card;
timer->tmr_device = tid->device;
!timer->hw.resolution && timer->hw.c_resolution == NULL)
return -EINVAL;
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
list_for_each(p, &snd_timer_list) {
timer1 = list_entry(p, struct snd_timer, device_list);
if (timer1->tmr_class > timer->tmr_class)
if (timer1->tmr_subdevice < timer->tmr_subdevice)
continue;
/* conflicts.. */
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
return -EBUSY;
}
list_add_tail(&timer->device_list, p);
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
return 0;
}
struct snd_timer_instance *ti;
snd_assert(timer != NULL, return -ENXIO);
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
if (! list_empty(&timer->open_list_head)) {
snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer);
list_for_each_safe(p, n, &timer->open_list_head) {
}
}
list_del(&timer->device_list);
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
return snd_timer_free(timer);
}
return snd_timer_global_register(timer);
}
+#ifdef CONFIG_PROC_FS
/*
* Info interface
*/
static void snd_timer_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
- unsigned long flags;
struct snd_timer *timer;
struct snd_timer_instance *ti;
struct list_head *p, *q;
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
list_for_each(p, &snd_timer_list) {
timer = list_entry(p, struct snd_timer, device_list);
switch (timer->tmr_class) {
if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
snd_iprintf(buffer, " SLAVE");
snd_iprintf(buffer, "\n");
- spin_lock_irqsave(&timer->lock, flags);
list_for_each(q, &timer->open_list_head) {
ti = list_entry(q, struct snd_timer_instance, open_list);
snd_iprintf(buffer, " Client %s : %s\n",
SNDRV_TIMER_IFLG_RUNNING)
? "running" : "stopped");
}
- spin_unlock_irqrestore(&timer->lock, flags);
}
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
+}
+
+static struct snd_info_entry *snd_timer_proc_entry;
+
+static void __init snd_timer_proc_init(void)
+{
+ struct snd_info_entry *entry;
+
+ entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL);
+ if (entry != NULL) {
+ entry->c.text.read = snd_timer_proc_read;
+ if (snd_info_register(entry) < 0) {
+ snd_info_free_entry(entry);
+ entry = NULL;
+ }
+ }
+ snd_timer_proc_entry = entry;
+}
+
+static void __exit snd_timer_proc_done(void)
+{
+ snd_info_unregister(snd_timer_proc_entry);
}
+#else /* !CONFIG_PROC_FS */
+#define snd_timer_proc_init()
+#define snd_timer_proc_done()
+#endif
/*
* USER SPACE interface
return -ENOMEM;
spin_lock_init(&tu->qlock);
init_waitqueue_head(&tu->qchange_sleep);
- init_MUTEX(&tu->tread_sem);
+ mutex_init(&tu->tread_sem);
tu->ticks = 1;
tu->queue_size = 128;
tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
if (copy_from_user(&id, _tid, sizeof(id)))
return -EFAULT;
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
if (id.dev_class < 0) { /* first item */
if (list_empty(&snd_timer_list))
snd_timer_user_zero_id(&id);
snd_timer_user_zero_id(&id);
}
}
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
if (copy_to_user(_tid, &id, sizeof(*_tid)))
return -EFAULT;
return 0;
tid = ginfo->tid;
memset(ginfo, 0, sizeof(*ginfo));
ginfo->tid = tid;
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
ginfo->card = t->card ? t->card->number : -1;
} else {
err = -ENODEV;
}
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo)))
err = -EFAULT;
kfree(ginfo);
if (copy_from_user(&gparams, _gparams, sizeof(gparams)))
return -EFAULT;
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
t = snd_timer_find(&gparams.tid);
if (!t) {
err = -ENODEV;
}
err = t->hw.set_period(t, gparams.period_num, gparams.period_den);
_error:
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
return err;
}
tid = gstatus.tid;
memset(&gstatus, 0, sizeof(gstatus));
gstatus.tid = tid;
- down(®ister_mutex);
+ mutex_lock(®ister_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
if (t->hw.c_resolution)
} else {
err = -ENODEV;
}
- up(®ister_mutex);
+ mutex_unlock(®ister_mutex);
if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus)))
err = -EFAULT;
return err;
int err = 0;
tu = file->private_data;
- down(&tu->tread_sem);
+ mutex_lock(&tu->tread_sem);
if (tu->timeri) {
snd_timer_close(tu->timeri);
tu->timeri = NULL;
}
__err:
- up(&tu->tread_sem);
+ mutex_unlock(&tu->tread_sem);
return err;
}
{
int xarg;
- down(&tu->tread_sem);
+ mutex_lock(&tu->tread_sem);
if (tu->timeri) { /* too late */
- up(&tu->tread_sem);
+ mutex_unlock(&tu->tread_sem);
return -EBUSY;
}
if (get_user(xarg, p)) {
- up(&tu->tread_sem);
+ mutex_unlock(&tu->tread_sem);
return -EFAULT;
}
tu->tread = xarg ? 1 : 0;
- up(&tu->tread_sem);
+ mutex_unlock(&tu->tread_sem);
return 0;
}
case SNDRV_TIMER_IOCTL_GINFO:
.fasync = snd_timer_user_fasync,
};
-static struct snd_minor snd_timer_reg =
-{
- .comment = "timer",
- .f_ops = &snd_timer_f_ops,
-};
-
/*
* ENTRY functions
*/
-static struct snd_info_entry *snd_timer_proc_entry = NULL;
-
static int __init alsa_timer_init(void)
{
int err;
- struct snd_info_entry *entry;
#ifdef SNDRV_OSS_INFO_DEV_TIMERS
snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1,
"system timer");
#endif
- entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL);
- if (entry != NULL) {
- entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128;
- entry->c.text.read = snd_timer_proc_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- snd_timer_proc_entry = entry;
+
if ((err = snd_timer_register_system()) < 0)
snd_printk(KERN_ERR "unable to register system timer (%i)\n",
err);
- if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER,
- NULL, 0, &snd_timer_reg, "timer"))<0)
+ if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
+ &snd_timer_f_ops, NULL, "timer")) < 0)
snd_printk(KERN_ERR "unable to register timer device (%i)\n",
err);
+ snd_timer_proc_init();
return 0;
}
struct snd_timer *timer = list_entry(p, struct snd_timer, device_list);
snd_timer_unregister(timer);
}
- if (snd_timer_proc_entry) {
- snd_info_unregister(snd_timer_proc_entry);
- snd_timer_proc_entry = NULL;
- }
+ snd_timer_proc_done();
#ifdef SNDRV_OSS_INFO_DEV_TIMERS
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1);
#endif