summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/timer.h1
-rw-r--r--sound/core/timer.c29
2 files changed, 21 insertions, 9 deletions
diff --git a/include/sound/timer.h b/include/sound/timer.h
index 760e132cc0cd..83bafe70cf33 100644
--- a/include/sound/timer.h
+++ b/include/sound/timer.h
@@ -102,6 +102,7 @@ struct snd_timer_instance {
unsigned int slave_id;
struct list_head open_list;
struct list_head active_list;
+ struct list_head master_list;
struct list_head ack_list;
struct list_head slave_list_head;
struct list_head slave_active_head;
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 6a70df7ae019..820901d503af 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -129,6 +129,9 @@ static LIST_HEAD(snd_timer_list);
/* list of slave instances */
static LIST_HEAD(snd_timer_slave_list);
+/* list of open master instances that can accept slave links */
+static LIST_HEAD(snd_timer_master_list);
+
/* lock for slave active lists */
static DEFINE_SPINLOCK(slave_active_lock);
@@ -161,6 +164,7 @@ struct snd_timer_instance *snd_timer_instance_new(const char *owner)
}
INIT_LIST_HEAD(&timeri->open_list);
INIT_LIST_HEAD(&timeri->active_list);
+ INIT_LIST_HEAD(&timeri->master_list);
INIT_LIST_HEAD(&timeri->ack_list);
INIT_LIST_HEAD(&timeri->slave_list_head);
INIT_LIST_HEAD(&timeri->slave_active_head);
@@ -245,6 +249,12 @@ static int check_matching_master_slave(struct snd_timer_instance *master,
return 1;
}
+static bool snd_timer_has_slave_key(const struct snd_timer_instance *timeri)
+{
+ return !(timeri->flags & SNDRV_TIMER_IFLG_SLAVE) &&
+ timeri->slave_class > SNDRV_TIMER_SCLASS_NONE;
+}
+
/*
* look for a master instance matching with the slave id of the given slave.
* when found, relink the open_link of the slave.
@@ -253,19 +263,15 @@ static int check_matching_master_slave(struct snd_timer_instance *master,
*/
static int snd_timer_check_slave(struct snd_timer_instance *slave)
{
- struct snd_timer *timer;
struct snd_timer_instance *master;
int err = 0;
- /* FIXME: it's really dumb to look up all entries.. */
- list_for_each_entry(timer, &snd_timer_list, device_list) {
- list_for_each_entry(master, &timer->open_list_head, open_list) {
- err = check_matching_master_slave(master, slave);
- if (err != 0) /* match found or error */
- goto out;
- }
+ list_for_each_entry(master, &snd_timer_master_list, master_list) {
+ err = check_matching_master_slave(master, slave);
+ if (err != 0) /* match found or error */
+ goto out;
}
- out:
+out:
return err < 0 ? err : 0;
}
@@ -377,6 +383,8 @@ int snd_timer_open(struct snd_timer_instance *timeri,
timeri->slave_id = slave_id;
list_add_tail(&timeri->open_list, &timer->open_list_head);
+ if (snd_timer_has_slave_key(timeri))
+ list_add_tail(&timeri->master_list, &snd_timer_master_list);
timer->num_instances++;
err = snd_timer_check_master(timeri);
list_added:
@@ -431,6 +439,9 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
num_slaves--;
}
+ if (!list_empty(&timeri->master_list))
+ list_del_init(&timeri->master_list);
+
/* force to stop the timer */
snd_timer_stop(timeri);