Commit 605ea295 authored by Philippe Gerum's avatar Philippe Gerum
Browse files

sound/timer: evl: convert to hard spinlocks



PCM timer handlers run over interrupt context, either inband or
out-of-band. Switch to hard locks to allow for both.
Signed-off-by: Philippe Gerum's avatarPhilippe Gerum <rpm@xenomai.org>
parent 4ce9cae3
......@@ -69,7 +69,7 @@ struct snd_timer {
void *private_data;
void (*private_free) (struct snd_timer *timer);
struct snd_timer_hardware hw;
spinlock_t lock;
hard_spinlock_t lock;
struct list_head device_list;
struct list_head open_list_head;
struct list_head active_list_head;
......
......@@ -1035,10 +1035,10 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
kfree(runtime->hw_constraints.rules);
/* Avoid concurrent access to runtime via PCM timer interface */
if (substream->timer)
spin_lock_irq(&substream->timer->lock);
raw_spin_lock_irq(&substream->timer->lock);
substream->runtime = NULL;
if (substream->timer)
spin_unlock_irq(&substream->timer->lock);
raw_spin_unlock_irq(&substream->timer->lock);
kfree(runtime);
put_pid(substream->pid);
substream->pid = NULL;
......
......@@ -118,7 +118,7 @@ static LIST_HEAD(snd_timer_list);
static LIST_HEAD(snd_timer_slave_list);
/* lock for slave active lists */
static DEFINE_SPINLOCK(slave_active_lock);
static DEFINE_HARD_SPINLOCK(slave_active_lock);
#define MAX_SLAVE_INSTANCES 1000
static int num_slaves;
......@@ -224,14 +224,14 @@ static int check_matching_master_slave(struct snd_timer_instance *master,
return -EBUSY;
list_move_tail(&slave->open_list, &master->slave_list_head);
master->timer->num_instances++;
spin_lock_irq(&slave_active_lock);
spin_lock(&master->timer->lock);
raw_spin_lock_irq(&slave_active_lock);
raw_spin_lock(&master->timer->lock);
slave->master = master;
slave->timer = master->timer;
if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
list_add_tail(&slave->active_list, &master->slave_active_head);
spin_unlock(&master->timer->lock);
spin_unlock_irq(&slave_active_lock);
raw_spin_unlock(&master->timer->lock);
raw_spin_unlock_irq(&slave_active_lock);
return 1;
}
......@@ -401,9 +401,9 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
struct snd_timer_instance *slave, *tmp;
if (timer) {
spin_lock_irq(&timer->lock);
raw_spin_lock_irq(&timer->lock);
timeri->flags |= SNDRV_TIMER_IFLG_DEAD;
spin_unlock_irq(&timer->lock);
raw_spin_unlock_irq(&timer->lock);
}
if (!list_empty(&timeri->open_list)) {
......@@ -418,17 +418,17 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
if (timer) {
timer->num_instances--;
/* wait, until the active callback is finished */
spin_lock_irq(&timer->lock);
raw_spin_lock_irq(&timer->lock);
while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
spin_unlock_irq(&timer->lock);
raw_spin_unlock_irq(&timer->lock);
udelay(10);
spin_lock_irq(&timer->lock);
raw_spin_lock_irq(&timer->lock);
}
spin_unlock_irq(&timer->lock);
raw_spin_unlock_irq(&timer->lock);
/* remove slave links */
spin_lock_irq(&slave_active_lock);
spin_lock(&timer->lock);
raw_spin_lock_irq(&slave_active_lock);
raw_spin_lock(&timer->lock);
timeri->timer = NULL;
list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
open_list) {
......@@ -439,8 +439,8 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
list_del_init(&slave->ack_list);
list_del_init(&slave->active_list);
}
spin_unlock(&timer->lock);
spin_unlock_irq(&slave_active_lock);
raw_spin_unlock(&timer->lock);
raw_spin_unlock_irq(&slave_active_lock);
/* slave doesn't need to release timer resources below */
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
......@@ -494,9 +494,9 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
return 0;
timer = timeri->timer;
if (timer) {
spin_lock_irqsave(&timer->lock, flags);
raw_spin_lock_irqsave(&timer->lock, flags);
ret = snd_timer_hw_resolution(timer);
spin_unlock_irqrestore(&timer->lock, flags);
raw_spin_unlock_irqrestore(&timer->lock, flags);
}
return ret;
}
......@@ -545,7 +545,7 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,
if (!timer)
return -EINVAL;
spin_lock_irqsave(&timer->lock, flags);
raw_spin_lock_irqsave(&timer->lock, flags);
if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) {
result = -EINVAL;
goto unlock;
......@@ -585,7 +585,7 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,
snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START :
SNDRV_TIMER_EVENT_CONTINUE);
unlock:
spin_unlock_irqrestore(&timer->lock, flags);
raw_spin_unlock_irqrestore(&timer->lock, flags);
return result;
}
......@@ -596,7 +596,7 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri,
unsigned long flags;
int err;
spin_lock_irqsave(&slave_active_lock, flags);
raw_spin_lock_irqsave(&slave_active_lock, flags);
if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) {
err = -EINVAL;
goto unlock;
......@@ -607,16 +607,16 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri,
}
timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
if (timeri->master && timeri->timer) {
spin_lock(&timeri->timer->lock);
raw_spin_lock(&timeri->timer->lock);
list_add_tail(&timeri->active_list,
&timeri->master->slave_active_head);
snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START :
SNDRV_TIMER_EVENT_CONTINUE);
spin_unlock(&timeri->timer->lock);
raw_spin_unlock(&timeri->timer->lock);
}
err = 1; /* delayed start */
unlock:
spin_unlock_irqrestore(&slave_active_lock, flags);
raw_spin_unlock_irqrestore(&slave_active_lock, flags);
return err;
}
......@@ -630,7 +630,7 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)
timer = timeri->timer;
if (!timer)
return -EINVAL;
spin_lock_irqsave(&timer->lock, flags);
raw_spin_lock_irqsave(&timer->lock, flags);
if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
SNDRV_TIMER_IFLG_START))) {
result = -EBUSY;
......@@ -664,7 +664,7 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)
snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
SNDRV_TIMER_EVENT_PAUSE);
unlock:
spin_unlock_irqrestore(&timer->lock, flags);
raw_spin_unlock_irqrestore(&timer->lock, flags);
return result;
}
......@@ -673,21 +673,21 @@ static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop)
{
unsigned long flags;
spin_lock_irqsave(&slave_active_lock, flags);
raw_spin_lock_irqsave(&slave_active_lock, flags);
if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
spin_unlock_irqrestore(&slave_active_lock, flags);
raw_spin_unlock_irqrestore(&slave_active_lock, flags);
return -EBUSY;
}
timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
if (timeri->timer) {
spin_lock(&timeri->timer->lock);
raw_spin_lock(&timeri->timer->lock);
list_del_init(&timeri->ack_list);
list_del_init(&timeri->active_list);
snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
SNDRV_TIMER_EVENT_PAUSE);
spin_unlock(&timeri->timer->lock);
raw_spin_unlock(&timeri->timer->lock);
}
spin_unlock_irqrestore(&slave_active_lock, flags);
raw_spin_unlock_irqrestore(&slave_active_lock, flags);
return 0;
}
......@@ -799,10 +799,10 @@ static void snd_timer_process_callbacks(struct snd_timer *timer,
ti->pticks = 0;
resolution = ti->resolution;
ti->flags |= SNDRV_TIMER_IFLG_CALLBACK;
spin_unlock(&timer->lock);
raw_spin_unlock(&timer->lock);
if (ti->callback)
ti->callback(ti, resolution, ticks);
spin_lock(&timer->lock);
raw_spin_lock(&timer->lock);
ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
}
}
......@@ -814,10 +814,10 @@ static void snd_timer_clear_callbacks(struct snd_timer *timer,
{
unsigned long flags;
spin_lock_irqsave(&timer->lock, flags);
raw_spin_lock_irqsave(&timer->lock, flags);
while (!list_empty(head))
list_del_init(head->next);
spin_unlock_irqrestore(&timer->lock, flags);
raw_spin_unlock_irqrestore(&timer->lock, flags);
}
/*
......@@ -834,9 +834,9 @@ static void snd_timer_tasklet(unsigned long arg)
return;
}
spin_lock_irqsave(&timer->lock, flags);
raw_spin_lock_irqsave(&timer->lock, flags);
snd_timer_process_callbacks(timer, &timer->sack_list_head);
spin_unlock_irqrestore(&timer->lock, flags);
raw_spin_unlock_irqrestore(&timer->lock, flags);
}
/*
......@@ -861,7 +861,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
return;
}
spin_lock_irqsave(&timer->lock, flags);
raw_spin_lock_irqsave(&timer->lock, flags);
/* remember the current resolution */
resolution = snd_timer_hw_resolution(timer);
......@@ -928,7 +928,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
/* do we have any slow callbacks? */
use_tasklet = !list_empty(&timer->sack_list_head);
spin_unlock_irqrestore(&timer->lock, flags);
raw_spin_unlock_irqrestore(&timer->lock, flags);
if (use_tasklet)
tasklet_schedule(&timer->task_queue);
......@@ -974,7 +974,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
INIT_LIST_HEAD(&timer->active_list_head);
INIT_LIST_HEAD(&timer->ack_list_head);
INIT_LIST_HEAD(&timer->sack_list_head);
spin_lock_init(&timer->lock);
raw_spin_lock_init(&timer->lock);
tasklet_init(&timer->task_queue, snd_timer_tasklet,
(unsigned long)timer);
timer->max_instances = 1000; /* default limit per timer */
......@@ -1092,7 +1092,7 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tst
if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART ||
event > SNDRV_TIMER_EVENT_MRESUME))
return;
spin_lock_irqsave(&timer->lock, flags);
raw_spin_lock_irqsave(&timer->lock, flags);
if (event == SNDRV_TIMER_EVENT_MSTART ||
event == SNDRV_TIMER_EVENT_MCONTINUE ||
event == SNDRV_TIMER_EVENT_MRESUME)
......@@ -1104,7 +1104,7 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tst
if (ts->ccallback)
ts->ccallback(ts, event, tstamp, resolution);
}
spin_unlock_irqrestore(&timer->lock, flags);
raw_spin_unlock_irqrestore(&timer->lock, flags);
}
EXPORT_SYMBOL(snd_timer_notify);
......@@ -1739,7 +1739,7 @@ static int snd_timer_user_gstatus(struct file *file,
mutex_lock(&register_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
spin_lock_irq(&t->lock);
raw_spin_lock_irq(&t->lock);
gstatus.resolution = snd_timer_hw_resolution(t);
if (t->hw.precise_resolution) {
t->hw.precise_resolution(t, &gstatus.resolution_num,
......@@ -1748,7 +1748,7 @@ static int snd_timer_user_gstatus(struct file *file,
gstatus.resolution_num = gstatus.resolution;
gstatus.resolution_den = 1000000000uL;
}
spin_unlock_irq(&t->lock);
raw_spin_unlock_irq(&t->lock);
} else {
err = -ENODEV;
}
......@@ -1887,7 +1887,7 @@ static int snd_timer_user_params(struct file *file,
goto _end;
}
snd_timer_stop(tu->timeri);
spin_lock_irq(&t->lock);
raw_spin_lock_irq(&t->lock);
tu->timeri->flags &= ~(SNDRV_TIMER_IFLG_AUTO|
SNDRV_TIMER_IFLG_EXCLUSIVE|
SNDRV_TIMER_IFLG_EARLY_EVENT);
......@@ -1897,7 +1897,7 @@ static int snd_timer_user_params(struct file *file,
tu->timeri->flags |= SNDRV_TIMER_IFLG_EXCLUSIVE;
if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT)
tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT;
spin_unlock_irq(&t->lock);
raw_spin_unlock_irq(&t->lock);
if (params.queue_size > 0 &&
(unsigned int)tu->queue_size != params.queue_size) {
err = realloc_user_queue(tu, params.queue_size);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment