Loading include/sound/timer.h +0 −1 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ #define SNDRV_TIMER_IFLG_START 0x00000004 #define SNDRV_TIMER_IFLG_AUTO 0x00000008 /* auto restart */ #define SNDRV_TIMER_IFLG_FAST 0x00000010 /* fast callback (do not use tasklet) */ #define SNDRV_TIMER_IFLG_CALLBACK 0x00000020 /* timer callback is active */ #define SNDRV_TIMER_IFLG_EXCLUSIVE 0x00000040 /* exclusive owner - no more instances */ #define SNDRV_TIMER_IFLG_EARLY_EVENT 0x00000080 /* write early event to the poll queue */ Loading sound/core/timer.c +74 −49 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ /* internal flags */ #define SNDRV_TIMER_IFLG_PAUSED 0x00010000 #define SNDRV_TIMER_IFLG_DEAD 0x00020000 #if IS_ENABLED(CONFIG_SND_HRTIMER) #define DEFAULT_TIMER_LIMIT 4 Loading Loading @@ -353,20 +354,25 @@ EXPORT_SYMBOL(snd_timer_open); */ static int snd_timer_close_locked(struct snd_timer_instance *timeri) { struct snd_timer *timer = NULL; struct snd_timer *timer = timeri->timer; struct snd_timer_instance *slave, *tmp; if (timer) { spin_lock_irq(&timer->lock); timeri->flags |= SNDRV_TIMER_IFLG_DEAD; spin_unlock_irq(&timer->lock); } list_del(&timeri->open_list); /* force to stop the timer */ snd_timer_stop(timeri); timer = timeri->timer; if (timer) { timer->num_instances--; /* wait, until the active callback is finished */ spin_lock_irq(&timer->lock); while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { while (!list_empty(&timeri->ack_list)) { spin_unlock_irq(&timer->lock); udelay(10); spin_lock_irq(&timer->lock); Loading Loading @@ -497,6 +503,10 @@ static int snd_timer_start1(struct snd_timer_instance *timeri, return -EINVAL; spin_lock_irqsave(&timer->lock, flags); if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) { result = -EINVAL; goto unlock; } if (timer->card && timer->card->shutdown) { result = -ENODEV; goto unlock; Loading Loading @@ -541,11 +551,16 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri, bool start) { unsigned long flags; int err; spin_lock_irqsave(&slave_active_lock, flags); if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) { err = -EINVAL; goto unlock; } if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { spin_unlock_irqrestore(&slave_active_lock, flags); return -EBUSY; err = -EBUSY; goto unlock; } timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; if (timeri->master && timeri->timer) { Loading @@ -556,8 +571,10 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri, SNDRV_TIMER_EVENT_CONTINUE); spin_unlock(&timeri->timer->lock); } err = 1; /* delayed start */ unlock: spin_unlock_irqrestore(&slave_active_lock, flags); return 1; /* delayed start */ return err; } /* stop/pause a master timer */ Loading Loading @@ -720,41 +737,61 @@ static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_l timer->sticks = ticks; } /* * timer tasklet * */ static void snd_timer_tasklet(unsigned long arg) /* call callbacks in timer ack list */ static void snd_timer_process_callbacks(struct snd_timer *timer, struct list_head *head) { struct snd_timer *timer = (struct snd_timer *) arg; struct snd_timer_instance *ti; struct list_head *p; unsigned long resolution, ticks; unsigned long flags; if (timer->card && timer->card->shutdown) return; 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 */ ti = list_entry(p, struct snd_timer_instance, ack_list); /* remove from ack_list and make empty */ list_del_init(p); while (!list_empty(head)) { ti = list_first_entry(head, struct snd_timer_instance, ack_list); if (!(ti->flags & SNDRV_TIMER_IFLG_DEAD)) { ticks = ti->pticks; ti->pticks = 0; resolution = ti->resolution; ti->flags |= SNDRV_TIMER_IFLG_CALLBACK; spin_unlock(&timer->lock); if (ti->callback) ti->callback(ti, resolution, ticks); spin_lock(&timer->lock); ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; } /* remove from ack_list and make empty */ list_del_init(&ti->ack_list); } } /* clear pending instances from ack list */ static void snd_timer_clear_callbacks(struct snd_timer *timer, struct list_head *head) { unsigned long flags; spin_lock_irqsave(&timer->lock, flags); while (!list_empty(head)) list_del_init(head->next); spin_unlock_irqrestore(&timer->lock, flags); } /* * timer tasklet * */ static void snd_timer_tasklet(unsigned long arg) { struct snd_timer *timer = (struct snd_timer *) arg; unsigned long flags; if (timer->card && timer->card->shutdown) { snd_timer_clear_callbacks(timer, &timer->sack_list_head); return; } spin_lock_irqsave(&timer->lock, flags); snd_timer_process_callbacks(timer, &timer->sack_list_head); spin_unlock_irqrestore(&timer->lock, flags); } Loading @@ -767,16 +804,18 @@ static void snd_timer_tasklet(unsigned long arg) void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) { struct snd_timer_instance *ti, *ts, *tmp; unsigned long resolution, ticks; struct list_head *p, *ack_list_head; unsigned long resolution; struct list_head *ack_list_head; unsigned long flags; int use_tasklet = 0; if (timer == NULL) return; if (timer->card && timer->card->shutdown) if (timer->card && timer->card->shutdown) { snd_timer_clear_callbacks(timer, &timer->ack_list_head); return; } spin_lock_irqsave(&timer->lock, flags); Loading @@ -790,6 +829,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) */ list_for_each_entry_safe(ti, tmp, &timer->active_list_head, active_list) { if (ti->flags & SNDRV_TIMER_IFLG_DEAD) continue; if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING)) continue; ti->pticks += ticks_left; Loading Loading @@ -839,23 +880,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) } /* now process all fast callbacks */ while (!list_empty(&timer->ack_list_head)) { p = timer->ack_list_head.next; /* get first item */ ti = list_entry(p, struct snd_timer_instance, ack_list); /* remove from ack_list and make empty */ list_del_init(p); ticks = ti->pticks; ti->pticks = 0; ti->flags |= SNDRV_TIMER_IFLG_CALLBACK; spin_unlock(&timer->lock); if (ti->callback) ti->callback(ti, resolution, ticks); spin_lock(&timer->lock); ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; } snd_timer_process_callbacks(timer, &timer->ack_list_head); /* do we have any slow callbacks? */ use_tasklet = !list_empty(&timer->sack_list_head); Loading Loading
include/sound/timer.h +0 −1 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ #define SNDRV_TIMER_IFLG_START 0x00000004 #define SNDRV_TIMER_IFLG_AUTO 0x00000008 /* auto restart */ #define SNDRV_TIMER_IFLG_FAST 0x00000010 /* fast callback (do not use tasklet) */ #define SNDRV_TIMER_IFLG_CALLBACK 0x00000020 /* timer callback is active */ #define SNDRV_TIMER_IFLG_EXCLUSIVE 0x00000040 /* exclusive owner - no more instances */ #define SNDRV_TIMER_IFLG_EARLY_EVENT 0x00000080 /* write early event to the poll queue */ Loading
sound/core/timer.c +74 −49 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ /* internal flags */ #define SNDRV_TIMER_IFLG_PAUSED 0x00010000 #define SNDRV_TIMER_IFLG_DEAD 0x00020000 #if IS_ENABLED(CONFIG_SND_HRTIMER) #define DEFAULT_TIMER_LIMIT 4 Loading Loading @@ -353,20 +354,25 @@ EXPORT_SYMBOL(snd_timer_open); */ static int snd_timer_close_locked(struct snd_timer_instance *timeri) { struct snd_timer *timer = NULL; struct snd_timer *timer = timeri->timer; struct snd_timer_instance *slave, *tmp; if (timer) { spin_lock_irq(&timer->lock); timeri->flags |= SNDRV_TIMER_IFLG_DEAD; spin_unlock_irq(&timer->lock); } list_del(&timeri->open_list); /* force to stop the timer */ snd_timer_stop(timeri); timer = timeri->timer; if (timer) { timer->num_instances--; /* wait, until the active callback is finished */ spin_lock_irq(&timer->lock); while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { while (!list_empty(&timeri->ack_list)) { spin_unlock_irq(&timer->lock); udelay(10); spin_lock_irq(&timer->lock); Loading Loading @@ -497,6 +503,10 @@ static int snd_timer_start1(struct snd_timer_instance *timeri, return -EINVAL; spin_lock_irqsave(&timer->lock, flags); if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) { result = -EINVAL; goto unlock; } if (timer->card && timer->card->shutdown) { result = -ENODEV; goto unlock; Loading Loading @@ -541,11 +551,16 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri, bool start) { unsigned long flags; int err; spin_lock_irqsave(&slave_active_lock, flags); if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) { err = -EINVAL; goto unlock; } if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { spin_unlock_irqrestore(&slave_active_lock, flags); return -EBUSY; err = -EBUSY; goto unlock; } timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; if (timeri->master && timeri->timer) { Loading @@ -556,8 +571,10 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri, SNDRV_TIMER_EVENT_CONTINUE); spin_unlock(&timeri->timer->lock); } err = 1; /* delayed start */ unlock: spin_unlock_irqrestore(&slave_active_lock, flags); return 1; /* delayed start */ return err; } /* stop/pause a master timer */ Loading Loading @@ -720,41 +737,61 @@ static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_l timer->sticks = ticks; } /* * timer tasklet * */ static void snd_timer_tasklet(unsigned long arg) /* call callbacks in timer ack list */ static void snd_timer_process_callbacks(struct snd_timer *timer, struct list_head *head) { struct snd_timer *timer = (struct snd_timer *) arg; struct snd_timer_instance *ti; struct list_head *p; unsigned long resolution, ticks; unsigned long flags; if (timer->card && timer->card->shutdown) return; 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 */ ti = list_entry(p, struct snd_timer_instance, ack_list); /* remove from ack_list and make empty */ list_del_init(p); while (!list_empty(head)) { ti = list_first_entry(head, struct snd_timer_instance, ack_list); if (!(ti->flags & SNDRV_TIMER_IFLG_DEAD)) { ticks = ti->pticks; ti->pticks = 0; resolution = ti->resolution; ti->flags |= SNDRV_TIMER_IFLG_CALLBACK; spin_unlock(&timer->lock); if (ti->callback) ti->callback(ti, resolution, ticks); spin_lock(&timer->lock); ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; } /* remove from ack_list and make empty */ list_del_init(&ti->ack_list); } } /* clear pending instances from ack list */ static void snd_timer_clear_callbacks(struct snd_timer *timer, struct list_head *head) { unsigned long flags; spin_lock_irqsave(&timer->lock, flags); while (!list_empty(head)) list_del_init(head->next); spin_unlock_irqrestore(&timer->lock, flags); } /* * timer tasklet * */ static void snd_timer_tasklet(unsigned long arg) { struct snd_timer *timer = (struct snd_timer *) arg; unsigned long flags; if (timer->card && timer->card->shutdown) { snd_timer_clear_callbacks(timer, &timer->sack_list_head); return; } spin_lock_irqsave(&timer->lock, flags); snd_timer_process_callbacks(timer, &timer->sack_list_head); spin_unlock_irqrestore(&timer->lock, flags); } Loading @@ -767,16 +804,18 @@ static void snd_timer_tasklet(unsigned long arg) void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) { struct snd_timer_instance *ti, *ts, *tmp; unsigned long resolution, ticks; struct list_head *p, *ack_list_head; unsigned long resolution; struct list_head *ack_list_head; unsigned long flags; int use_tasklet = 0; if (timer == NULL) return; if (timer->card && timer->card->shutdown) if (timer->card && timer->card->shutdown) { snd_timer_clear_callbacks(timer, &timer->ack_list_head); return; } spin_lock_irqsave(&timer->lock, flags); Loading @@ -790,6 +829,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) */ list_for_each_entry_safe(ti, tmp, &timer->active_list_head, active_list) { if (ti->flags & SNDRV_TIMER_IFLG_DEAD) continue; if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING)) continue; ti->pticks += ticks_left; Loading Loading @@ -839,23 +880,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) } /* now process all fast callbacks */ while (!list_empty(&timer->ack_list_head)) { p = timer->ack_list_head.next; /* get first item */ ti = list_entry(p, struct snd_timer_instance, ack_list); /* remove from ack_list and make empty */ list_del_init(p); ticks = ti->pticks; ti->pticks = 0; ti->flags |= SNDRV_TIMER_IFLG_CALLBACK; spin_unlock(&timer->lock); if (ti->callback) ti->callback(ti, resolution, ticks); spin_lock(&timer->lock); ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; } snd_timer_process_callbacks(timer, &timer->ack_list_head); /* do we have any slow callbacks? */ use_tasklet = !list_empty(&timer->sack_list_head); Loading