#include <sound/minors.h>
#include <sound/initval.h>
#include <linux/kmod.h>
-#ifdef CONFIG_KERNELD
-#include <linux/kerneld.h>
-#endif
#if defined(CONFIG_SND_HPET) || defined(CONFIG_SND_HPET_MODULE)
#define DEFAULT_TIMER_LIMIT 3
static int snd_timer_free(struct snd_timer *timer);
static int snd_timer_dev_free(struct snd_device *device);
static int snd_timer_dev_register(struct snd_device *device);
-static int snd_timer_dev_unregister(struct snd_device *device);
+static int snd_timer_dev_disconnect(struct snd_device *device);
static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left);
static struct snd_timer *snd_timer_find(struct snd_timer_id *tid)
{
struct snd_timer *timer = NULL;
- struct list_head *p;
-
- list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, struct snd_timer, device_list);
+ list_for_each_entry(timer, &snd_timer_list, device_list) {
if (timer->tmr_class != tid->dev_class)
continue;
if ((timer->tmr_class == SNDRV_TIMER_CLASS_CARD ||
{
struct snd_timer *timer;
struct snd_timer_instance *master;
- struct list_head *p, *q;
/* FIXME: it's really dumb to look up all entries.. */
- list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, struct snd_timer, device_list);
- list_for_each(q, &timer->open_list_head) {
- master = list_entry(q, struct snd_timer_instance, open_list);
+ list_for_each_entry(timer, &snd_timer_list, device_list) {
+ list_for_each_entry(master, &timer->open_list_head, open_list) {
if (slave->slave_class == master->slave_class &&
slave->slave_id == master->slave_id) {
list_del(&slave->open_list);
*/
static void snd_timer_check_master(struct snd_timer_instance *master)
{
- struct snd_timer_instance *slave;
- struct list_head *p, *n;
+ struct snd_timer_instance *slave, *tmp;
/* check all pending slaves */
- list_for_each_safe(p, n, &snd_timer_slave_list) {
- slave = list_entry(p, struct snd_timer_instance, open_list);
+ list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) {
if (slave->slave_class == master->slave_class &&
slave->slave_id == master->slave_id) {
- list_del(p);
- list_add_tail(p, &master->slave_list_head);
+ list_move_tail(&slave->open_list, &master->slave_list_head);
spin_lock_irq(&slave_active_lock);
slave->master = master;
slave->timer = master->timer;
int snd_timer_close(struct snd_timer_instance *timeri)
{
struct snd_timer *timer = NULL;
- struct list_head *p, *n;
- struct snd_timer_instance *slave;
+ struct snd_timer_instance *slave, *tmp;
snd_assert(timeri != NULL, return -ENXIO);
timer->hw.close)
timer->hw.close(timer);
/* remove slave links */
- list_for_each_safe(p, n, &timeri->slave_list_head) {
- slave = list_entry(p, struct snd_timer_instance, open_list);
+ list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
+ open_list) {
spin_lock_irq(&slave_active_lock);
_snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
- list_del(p);
- list_add_tail(p, &snd_timer_slave_list);
+ list_move_tail(&slave->open_list, &snd_timer_slave_list);
slave->master = NULL;
slave->timer = NULL;
spin_unlock_irq(&slave_active_lock);
unsigned long flags;
unsigned long resolution = 0;
struct snd_timer_instance *ts;
- struct list_head *n;
struct timespec tstamp;
getnstimeofday(&tstamp);
if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
return;
spin_lock_irqsave(&timer->lock, flags);
- list_for_each(n, &ti->slave_active_head) {
- ts = list_entry(n, struct snd_timer_instance, active_list);
+ list_for_each_entry(ts, &ti->slave_active_head, active_list)
if (ts->ccallback)
ts->ccallback(ti, event + 100, &tstamp, resolution);
- }
spin_unlock_irqrestore(&timer->lock, flags);
}
{
struct snd_timer_instance *ti;
unsigned long ticks = ~0UL;
- struct list_head *p;
- list_for_each(p, &timer->active_list_head) {
- ti = list_entry(p, struct snd_timer_instance, active_list);
+ list_for_each_entry(ti, &timer->active_list_head, active_list) {
if (ti->flags & SNDRV_TIMER_IFLG_START) {
ti->flags &= ~SNDRV_TIMER_IFLG_START;
ti->flags |= SNDRV_TIMER_IFLG_RUNNING;
struct snd_timer_instance *ti;
struct list_head *p;
unsigned long resolution, ticks;
+ unsigned long flags;
- spin_lock(&timer->lock);
+ spin_lock_irqsave(&timer->lock, flags);
/* now process all callbacks */
while (!list_empty(&timer->sack_list_head)) {
p = timer->sack_list_head.next; /* get first item */
spin_lock(&timer->lock);
ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
}
- spin_unlock(&timer->lock);
+ spin_unlock_irqrestore(&timer->lock, flags);
}
/*
*/
void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
{
- struct snd_timer_instance *ti, *ts;
+ struct snd_timer_instance *ti, *ts, *tmp;
unsigned long resolution, ticks;
- struct list_head *p, *q, *n, *ack_list_head;
+ struct list_head *p, *ack_list_head;
unsigned long flags;
int use_tasklet = 0;
resolution = timer->hw.resolution;
/* loop for all active instances
- * Here we cannot use list_for_each because the active_list of a
+ * Here we cannot use list_for_each_entry because the active_list of a
* processed instance is relinked to done_list_head before the callback
* is called.
*/
- list_for_each_safe(p, n, &timer->active_list_head) {
- ti = list_entry(p, struct snd_timer_instance, active_list);
+ list_for_each_entry_safe(ti, tmp, &timer->active_list_head,
+ active_list) {
if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING))
continue;
ti->pticks += ticks_left;
} else {
ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
if (--timer->running)
- list_del(p);
+ list_del(&ti->active_list);
}
if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
(ti->flags & SNDRV_TIMER_IFLG_FAST))
ack_list_head = &timer->sack_list_head;
if (list_empty(&ti->ack_list))
list_add_tail(&ti->ack_list, ack_list_head);
- list_for_each(q, &ti->slave_active_head) {
- ts = list_entry(q, struct snd_timer_instance, active_list);
+ list_for_each_entry(ts, &ti->slave_active_head, active_list) {
ts->pticks = ti->pticks;
ts->resolution = resolution;
if (list_empty(&ts->ack_list))
}
}
if (timer->flags & SNDRV_TIMER_FLG_RESCHED)
- snd_timer_reschedule(timer, ticks_left);
+ snd_timer_reschedule(timer, timer->sticks);
if (timer->running) {
if (timer->hw.flags & SNDRV_TIMER_HW_STOP) {
timer->hw.stop(timer);
static struct snd_device_ops ops = {
.dev_free = snd_timer_dev_free,
.dev_register = snd_timer_dev_register,
- .dev_unregister = snd_timer_dev_unregister
+ .dev_disconnect = snd_timer_dev_disconnect,
};
snd_assert(tid != NULL, return -EINVAL);
static int snd_timer_free(struct snd_timer *timer)
{
snd_assert(timer != NULL, return -ENXIO);
+
+ mutex_lock(®ister_mutex);
+ if (! list_empty(&timer->open_list_head)) {
+ struct list_head *p, *n;
+ struct snd_timer_instance *ti;
+ snd_printk(KERN_WARNING "timer %p is busy?\n", timer);
+ list_for_each_safe(p, n, &timer->open_list_head) {
+ list_del_init(p);
+ ti = list_entry(p, struct snd_timer_instance, open_list);
+ ti->timer = NULL;
+ }
+ }
+ list_del(&timer->device_list);
+ mutex_unlock(®ister_mutex);
+
if (timer->private_free)
timer->private_free(timer);
kfree(timer);
{
struct snd_timer *timer = dev->device_data;
struct snd_timer *timer1;
- struct list_head *p;
snd_assert(timer != NULL && timer->hw.start != NULL &&
timer->hw.stop != NULL, return -ENXIO);
return -EINVAL;
mutex_lock(®ister_mutex);
- list_for_each(p, &snd_timer_list) {
- timer1 = list_entry(p, struct snd_timer, device_list);
+ list_for_each_entry(timer1, &snd_timer_list, device_list) {
if (timer1->tmr_class > timer->tmr_class)
break;
if (timer1->tmr_class < timer->tmr_class)
mutex_unlock(®ister_mutex);
return -EBUSY;
}
- list_add_tail(&timer->device_list, p);
+ list_add_tail(&timer->device_list, &timer1->device_list);
mutex_unlock(®ister_mutex);
return 0;
}
-static int snd_timer_unregister(struct snd_timer *timer)
+static int snd_timer_dev_disconnect(struct snd_device *device)
{
- struct list_head *p, *n;
- struct snd_timer_instance *ti;
-
- snd_assert(timer != NULL, return -ENXIO);
+ struct snd_timer *timer = device->device_data;
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_init(p);
- ti = list_entry(p, struct snd_timer_instance, open_list);
- ti->timer = NULL;
- }
- }
- list_del(&timer->device_list);
+ list_del_init(&timer->device_list);
mutex_unlock(®ister_mutex);
- return snd_timer_free(timer);
-}
-
-static int snd_timer_dev_unregister(struct snd_device *device)
-{
- struct snd_timer *timer = device->device_data;
- return snd_timer_unregister(timer);
+ return 0;
}
void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp)
unsigned long flags;
unsigned long resolution = 0;
struct snd_timer_instance *ti, *ts;
- struct list_head *p, *n;
if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE))
return;
else
resolution = timer->hw.resolution;
}
- list_for_each(p, &timer->active_list_head) {
- ti = list_entry(p, struct snd_timer_instance, active_list);
+ list_for_each_entry(ti, &timer->active_list_head, active_list) {
if (ti->ccallback)
ti->ccallback(ti, event, tstamp, resolution);
- list_for_each(n, &ti->slave_active_head) {
- ts = list_entry(n, struct snd_timer_instance, active_list);
+ list_for_each_entry(ts, &ti->slave_active_head, active_list)
if (ts->ccallback)
ts->ccallback(ts, event, tstamp, resolution);
- }
}
spin_unlock_irqrestore(&timer->lock, flags);
}
return snd_timer_dev_register(&dev);
}
-int snd_timer_global_unregister(struct snd_timer *timer)
-{
- return snd_timer_unregister(timer);
-}
-
/*
* System timer
*/
struct snd_timer_system_private {
struct timer_list tlist;
- struct timer * timer;
unsigned long last_expires;
unsigned long last_jiffies;
unsigned long correction;
struct snd_timer_system_private *priv = timer->private_data;
unsigned long jiff = jiffies;
if (time_after(jiff, priv->last_expires))
- priv->correction = (long)jiff - (long)priv->last_expires;
+ priv->correction += (long)jiff - (long)priv->last_expires;
snd_timer_interrupt(timer, (long)jiff - (long)priv->last_jiffies);
}
njiff++;
} else {
njiff += timer->sticks - priv->correction;
- priv->correction -= timer->sticks;
+ priv->correction = 0;
}
priv->last_expires = priv->tlist.expires = njiff;
add_timer(&priv->tlist);
timer->sticks = priv->last_expires - jiff;
else
timer->sticks = 1;
+ priv->correction = 0;
return 0;
}
{
struct snd_timer *timer;
struct snd_timer_instance *ti;
- struct list_head *p, *q;
mutex_lock(®ister_mutex);
- list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, struct snd_timer, device_list);
+ list_for_each_entry(timer, &snd_timer_list, device_list) {
switch (timer->tmr_class) {
case SNDRV_TIMER_CLASS_GLOBAL:
snd_iprintf(buffer, "G%i: ", timer->tmr_device);
if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
snd_iprintf(buffer, " SLAVE");
snd_iprintf(buffer, "\n");
- list_for_each(q, &timer->open_list_head) {
- ti = list_entry(q, struct snd_timer_instance, open_list);
+ list_for_each_entry(ti, &timer->open_list_head, open_list)
snd_iprintf(buffer, " Client %s : %s\n",
ti->owner ? ti->owner : "unknown",
ti->flags & (SNDRV_TIMER_IFLG_START |
SNDRV_TIMER_IFLG_RUNNING)
? "running" : "stopped");
- }
}
mutex_unlock(®ister_mutex);
}
static void __exit snd_timer_proc_done(void)
{
- snd_info_unregister(snd_timer_proc_entry);
+ snd_info_free_entry(snd_timer_proc_entry);
}
#else /* !CONFIG_PROC_FS */
#define snd_timer_proc_init()
#define snd_timer_user_ioctl_compat NULL
#endif
-static struct file_operations snd_timer_f_ops =
+static const struct file_operations snd_timer_f_ops =
{
.owner = THIS_MODULE,
.read = snd_timer_user_read,
/* unregister the system timer */
list_for_each_safe(p, n, &snd_timer_list) {
struct snd_timer *timer = list_entry(p, struct snd_timer, device_list);
- snd_timer_unregister(timer);
+ snd_timer_free(timer);
}
snd_timer_proc_done();
#ifdef SNDRV_OSS_INFO_DEV_TIMERS
EXPORT_SYMBOL(snd_timer_global_new);
EXPORT_SYMBOL(snd_timer_global_free);
EXPORT_SYMBOL(snd_timer_global_register);
-EXPORT_SYMBOL(snd_timer_global_unregister);
EXPORT_SYMBOL(snd_timer_interrupt);