ALSA: timer: keep a list of open masters for slave lookup

snd_timer_check_slave() still walks all registered timers and all open
timer instances to find a matching master for a newly opened slave.

Maintain a global list of open master instances that can accept slave
links and use it for the slave lookup path instead. This keeps the
existing matching semantics while avoiding the nested walk over
snd_timer_list and each timer open_list_head.

The reverse path in snd_timer_check_master() already scans only the
pending slave list, so this makes both lookup paths closer in shape
without changing the master/slave linking logic.

Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260316-alsa-timer-master-list-v1-1-fb95e547110a@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Cássio Gabriel
2026-03-16 10:39:38 -03:00
committed by Takashi Iwai
parent 032322b44c
commit 785639b5bf
2 changed files with 21 additions and 9 deletions

View File

@@ -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;

View File

@@ -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);