diff options
Diffstat (limited to 'sound/core/timer.c')
| -rw-r--r-- | sound/core/timer.c | 114 |
1 files changed, 63 insertions, 51 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c index 9d8184a2c2d..777a45e08e5 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -24,7 +24,8 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/mutex.h> -#include <linux/moduleparam.h> +#include <linux/device.h> +#include <linux/module.h> #include <linux/string.h> #include <sound/core.h> #include <sound/timer.h> @@ -34,9 +35,9 @@ #include <sound/initval.h> #include <linux/kmod.h> -#if defined(CONFIG_SND_HPET) || defined(CONFIG_SND_HPET_MODULE) -#define DEFAULT_TIMER_LIMIT 3 -#elif defined(CONFIG_SND_RTCTIMER) || defined(CONFIG_SND_RTCTIMER_MODULE) +#if IS_ENABLED(CONFIG_SND_HRTIMER) +#define DEFAULT_TIMER_LIMIT 4 +#elif IS_ENABLED(CONFIG_SND_RTCTIMER) #define DEFAULT_TIMER_LIMIT 2 #else #define DEFAULT_TIMER_LIMIT 1 @@ -52,6 +53,9 @@ MODULE_PARM_DESC(timer_limit, "Maximum global timers in system."); module_param(timer_tstamp_monotonic, int, 0444); MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for timestamps (default)."); +MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_TIMER); +MODULE_ALIAS("devname:snd/timer"); + struct snd_timer_user { struct snd_timer_instance *timeri; int tread; /* enhanced read with timestamps and events */ @@ -146,7 +150,7 @@ static struct snd_timer *snd_timer_find(struct snd_timer_id *tid) return NULL; } -#ifdef CONFIG_KMOD +#ifdef CONFIG_MODULES static void snd_timer_request(struct snd_timer_id *tid) { @@ -183,9 +187,8 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave) 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); - list_add_tail(&slave->open_list, - &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; @@ -237,7 +240,8 @@ int snd_timer_open(struct snd_timer_instance **ti, /* open a slave instance */ if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE || tid->dev_sclass > SNDRV_TIMER_SCLASS_OSS_SEQUENCER) { - snd_printd("invalid slave class %i\n", tid->dev_sclass); + pr_debug("ALSA: timer: invalid slave class %i\n", + tid->dev_sclass); return -EINVAL; } mutex_lock(®ister_mutex); @@ -259,8 +263,8 @@ int snd_timer_open(struct snd_timer_instance **ti, /* open a master instance */ mutex_lock(®ister_mutex); timer = snd_timer_find(tid); -#ifdef CONFIG_KMOD - if (timer == NULL) { +#ifdef CONFIG_MODULES + if (!timer) { mutex_unlock(®ister_mutex); snd_timer_request(tid); mutex_lock(®ister_mutex); @@ -306,7 +310,8 @@ int snd_timer_close(struct snd_timer_instance *timeri) struct snd_timer *timer = NULL; struct snd_timer_instance *slave, *tmp; - snd_assert(timeri != NULL, return -ENXIO); + if (snd_BUG_ON(!timeri)) + return -ENXIO; /* force to stop the timer */ snd_timer_stop(timeri); @@ -325,6 +330,8 @@ int snd_timer_close(struct snd_timer_instance *timeri) mutex_unlock(®ister_mutex); } else { timer = timeri->timer; + if (snd_BUG_ON(!timer)) + goto out; /* wait, until the active callback is finished */ spin_lock_irq(&timer->lock); while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { @@ -350,6 +357,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) } mutex_unlock(®ister_mutex); } + out: if (timeri->private_free) timeri->private_free(timeri); kfree(timeri->owner); @@ -382,16 +390,17 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) struct timespec tstamp; if (timer_tstamp_monotonic) - do_posix_clock_monotonic_gettime(&tstamp); + ktime_get_ts(&tstamp); else getnstimeofday(&tstamp); - snd_assert(event >= SNDRV_TIMER_EVENT_START && - event <= SNDRV_TIMER_EVENT_PAUSE, return); + if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START || + event > SNDRV_TIMER_EVENT_PAUSE)) + return; if (event == SNDRV_TIMER_EVENT_START || event == SNDRV_TIMER_EVENT_CONTINUE) resolution = snd_timer_resolution(ti); if (ti->ccallback) - ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution); + ti->ccallback(ti, event, &tstamp, resolution); if (ti->flags & SNDRV_TIMER_IFLG_SLAVE) return; timer = ti->timer; @@ -409,8 +418,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri, unsigned long sticks) { - list_del(&timeri->active_list); - list_add_tail(&timeri->active_list, &timer->active_list_head); + list_move_tail(&timeri->active_list, &timer->active_list_head); if (timer->running) { if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) goto __start_now; @@ -474,7 +482,8 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri, struct snd_timer *timer; unsigned long flags; - snd_assert(timeri != NULL, return -ENXIO); + if (snd_BUG_ON(!timeri)) + return -ENXIO; if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { if (!keep_flag) { @@ -527,6 +536,8 @@ int snd_timer_stop(struct snd_timer_instance *timeri) if (err < 0) return err; timer = timeri->timer; + if (!timer) + return -EINVAL; spin_lock_irqsave(&timer->lock, flags); timeri->cticks = timeri->ticks; timeri->pticks = 0; @@ -740,7 +751,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) spin_unlock_irqrestore(&timer->lock, flags); if (use_tasklet) - tasklet_hi_schedule(&timer->task_queue); + tasklet_schedule(&timer->task_queue); } /* @@ -758,12 +769,13 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, .dev_disconnect = snd_timer_dev_disconnect, }; - snd_assert(tid != NULL, return -EINVAL); - snd_assert(rtimer != NULL, return -EINVAL); - *rtimer = NULL; + if (snd_BUG_ON(!tid)) + return -EINVAL; + if (rtimer) + *rtimer = NULL; timer = kzalloc(sizeof(*timer), GFP_KERNEL); if (timer == NULL) { - snd_printk(KERN_ERR "timer: cannot allocate\n"); + pr_err("ALSA: timer: cannot allocate\n"); return -ENOMEM; } timer->tmr_class = tid->dev_class; @@ -788,19 +800,21 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, return err; } } - *rtimer = timer; + if (rtimer) + *rtimer = timer; return 0; } static int snd_timer_free(struct snd_timer *timer) { - snd_assert(timer != NULL, return -ENXIO); + if (!timer) + return 0; 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); + pr_warn("ALSA: 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); @@ -827,8 +841,8 @@ static int snd_timer_dev_register(struct snd_device *dev) struct snd_timer *timer = dev->device_data; struct snd_timer *timer1; - snd_assert(timer != NULL && timer->hw.start != NULL && - timer->hw.stop != NULL, return -ENXIO); + if (snd_BUG_ON(!timer || !timer->hw.start || !timer->hw.stop)) + return -ENXIO; if (!(timer->hw.flags & SNDRV_TIMER_HW_SLAVE) && !timer->hw.resolution && timer->hw.c_resolution == NULL) return -EINVAL; @@ -879,8 +893,9 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) return; - snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && - event <= SNDRV_TIMER_EVENT_MRESUME, return); + if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART || + event > SNDRV_TIMER_EVENT_MRESUME)) + return; spin_lock_irqsave(&timer->lock, flags); if (event == SNDRV_TIMER_EVENT_MSTART || event == SNDRV_TIMER_EVENT_MCONTINUE || @@ -1153,6 +1168,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, { struct snd_timer_user *tu = timeri->callback_data; struct snd_timer_tread r1; + unsigned long flags; if (event >= SNDRV_TIMER_EVENT_START && event <= SNDRV_TIMER_EVENT_PAUSE) @@ -1162,9 +1178,9 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, r1.event = event; r1.tstamp = *tstamp; r1.val = resolution; - spin_lock(&tu->qlock); + spin_lock_irqsave(&tu->qlock, flags); snd_timer_user_append_to_tqueue(tu, &r1); - spin_unlock(&tu->qlock); + spin_unlock_irqrestore(&tu->qlock, flags); kill_fasync(&tu->fasync, SIGIO, POLL_IN); wake_up(&tu->qchange_sleep); } @@ -1187,7 +1203,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, } if (tu->last_resolution != resolution || ticks > 0) { if (timer_tstamp_monotonic) - do_posix_clock_monotonic_gettime(&tstamp); + ktime_get_ts(&tstamp); else getnstimeofday(&tstamp); } @@ -1230,6 +1246,11 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, static int snd_timer_user_open(struct inode *inode, struct file *file) { struct snd_timer_user *tu; + int err; + + err = nonseekable_open(inode, file); + if (err < 0) + return err; tu = kzalloc(sizeof(*tu), GFP_KERNEL); if (tu == NULL) @@ -1256,7 +1277,6 @@ static int snd_timer_user_release(struct inode *inode, struct file *file) if (file->private_data) { tu = file->private_data; file->private_data = NULL; - fasync_helper(-1, file, 0, &tu->fasync); if (tu->timeri) snd_timer_close(tu->timeri); kfree(tu->queue); @@ -1389,13 +1409,10 @@ static int snd_timer_user_ginfo(struct file *file, struct list_head *p; int err = 0; - ginfo = kmalloc(sizeof(*ginfo), GFP_KERNEL); - if (! ginfo) - return -ENOMEM; - if (copy_from_user(ginfo, _ginfo, sizeof(*ginfo))) { - kfree(ginfo); - return -EFAULT; - } + ginfo = memdup_user(_ginfo, sizeof(*ginfo)); + if (IS_ERR(ginfo)) + return PTR_ERR(ginfo); + tid = ginfo->tid; memset(ginfo, 0, sizeof(*ginfo)); ginfo->tid = tid; @@ -1819,13 +1836,9 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, static int snd_timer_user_fasync(int fd, struct file * file, int on) { struct snd_timer_user *tu; - int err; tu = file->private_data; - err = fasync_helper(fd, file, on, &tu->fasync); - if (err < 0) - return err; - return 0; + return fasync_helper(fd, file, on, &tu->fasync); } static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, @@ -1922,6 +1935,7 @@ static const struct file_operations snd_timer_f_ops = .read = snd_timer_user_read, .open = snd_timer_user_open, .release = snd_timer_user_release, + .llseek = no_llseek, .poll = snd_timer_user_poll, .unlocked_ioctl = snd_timer_user_ioctl, .compat_ioctl = snd_timer_user_ioctl_compat, @@ -1942,12 +1956,10 @@ static int __init alsa_timer_init(void) #endif if ((err = snd_timer_register_system()) < 0) - snd_printk(KERN_ERR "unable to register system timer (%i)\n", - err); + pr_err("ALSA: unable to register system timer (%i)\n", err); 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); + pr_err("ALSA: unable to register timer device (%i)\n", err); snd_timer_proc_init(); return 0; } |
