diff options
Diffstat (limited to 'sound/core/timer.c')
| -rw-r--r-- | sound/core/timer.c | 442 | 
1 files changed, 180 insertions, 262 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c index e6e551d4a29e..4d2ee99c12a3 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -224,14 +224,12 @@ 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); +	guard(spinlock_irq)(&slave_active_lock); +	guard(spinlock)(&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);  	return 1;  } @@ -382,6 +380,25 @@ list_added:  }  EXPORT_SYMBOL(snd_timer_open); +/* remove slave links, called from snd_timer_close_locked() below */ +static void remove_slave_links(struct snd_timer_instance *timeri, +			       struct snd_timer *timer) +{ +	struct snd_timer_instance *slave, *tmp; + +	guard(spinlock_irq)(&slave_active_lock); +	guard(spinlock)(&timer->lock); +	timeri->timer = NULL; +	list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, open_list) { +		list_move_tail(&slave->open_list, &snd_timer_slave_list); +		timer->num_instances--; +		slave->master = NULL; +		slave->timer = NULL; +		list_del_init(&slave->ack_list); +		list_del_init(&slave->active_list); +	} +} +  /*   * close a timer instance   * call this with register_mutex down. @@ -390,12 +407,10 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,  				   struct device **card_devp_to_put)  {  	struct snd_timer *timer = timeri->timer; -	struct snd_timer_instance *slave, *tmp;  	if (timer) { -		spin_lock_irq(&timer->lock); +		guard(spinlock_irq)(&timer->lock);  		timeri->flags |= SNDRV_TIMER_IFLG_DEAD; -		spin_unlock_irq(&timer->lock);  	}  	if (!list_empty(&timeri->open_list)) { @@ -418,21 +433,7 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,  		}  		spin_unlock_irq(&timer->lock); -		/* remove slave links */ -		spin_lock_irq(&slave_active_lock); -		spin_lock(&timer->lock); -		timeri->timer = NULL; -		list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, -					 open_list) { -			list_move_tail(&slave->open_list, &snd_timer_slave_list); -			timer->num_instances--; -			slave->master = NULL; -			slave->timer = NULL; -			list_del_init(&slave->ack_list); -			list_del_init(&slave->active_list); -		} -		spin_unlock(&timer->lock); -		spin_unlock_irq(&slave_active_lock); +		remove_slave_links(timeri, timer);  		/* slave doesn't need to release timer resources below */  		if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) @@ -459,9 +460,8 @@ void snd_timer_close(struct snd_timer_instance *timeri)  	if (snd_BUG_ON(!timeri))  		return; -	mutex_lock(®ister_mutex); -	snd_timer_close_locked(timeri, &card_dev_to_put); -	mutex_unlock(®ister_mutex); +	scoped_guard(mutex, ®ister_mutex) +		snd_timer_close_locked(timeri, &card_dev_to_put);  	/* put_device() is called after unlock for avoiding deadlock */  	if (card_dev_to_put)  		put_device(card_dev_to_put); @@ -480,15 +480,13 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)  {  	struct snd_timer * timer;  	unsigned long ret = 0; -	unsigned long flags;  	if (timeri == NULL)  		return 0;  	timer = timeri->timer;  	if (timer) { -		spin_lock_irqsave(&timer->lock, flags); +		guard(spinlock_irqsave)(&timer->lock);  		ret = snd_timer_hw_resolution(timer); -		spin_unlock_irqrestore(&timer->lock, flags);  	}  	return ret;  } @@ -532,26 +530,19 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,  {  	struct snd_timer *timer;  	int result; -	unsigned long flags;  	timer = timeri->timer;  	if (!timer)  		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; -	} +	guard(spinlock_irqsave)(&timer->lock); +	if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) +		return -EINVAL; +	if (timer->card && timer->card->shutdown) +		return -ENODEV;  	if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | -			     SNDRV_TIMER_IFLG_START)) { -		result = -EBUSY; -		goto unlock; -	} +			     SNDRV_TIMER_IFLG_START)) +		return -EBUSY;  	if (start)  		timeri->ticks = timeri->cticks = ticks; @@ -577,8 +568,6 @@ 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);  	return result;  } @@ -586,53 +575,38 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,  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) { -		err = -EBUSY; -		goto unlock; -	} +	guard(spinlock_irqsave)(&slave_active_lock); +	if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) +		return -EINVAL; +	if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) +		return -EBUSY;  	timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;  	if (timeri->master && timeri->timer) { -		spin_lock(&timeri->timer->lock); +		guard(spinlock)(&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);  	} -	err = 1; /* delayed start */ - unlock: -	spin_unlock_irqrestore(&slave_active_lock, flags); -	return err; +	return 1; /* delayed start */  }  /* stop/pause a master timer */  static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)  {  	struct snd_timer *timer; -	int result = 0; -	unsigned long flags;  	timer = timeri->timer;  	if (!timer)  		return -EINVAL; -	spin_lock_irqsave(&timer->lock, flags); +	guard(spinlock_irqsave)(&timer->lock);  	list_del_init(&timeri->ack_list);  	list_del_init(&timeri->active_list);  	if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | -			       SNDRV_TIMER_IFLG_START))) { -		result = -EBUSY; -		goto unlock; -	} +			       SNDRV_TIMER_IFLG_START))) +		return -EBUSY;  	if (timer->card && timer->card->shutdown) -		goto unlock; +		return 0;  	if (stop) {  		timeri->cticks = timeri->ticks;  		timeri->pticks = 0; @@ -656,30 +630,25 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)  		timeri->flags |= SNDRV_TIMER_IFLG_PAUSED;  	snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :  			  SNDRV_TIMER_EVENT_PAUSE); - unlock: -	spin_unlock_irqrestore(&timer->lock, flags); -	return result; +	return 0;  }  /* stop/pause a slave timer */  static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop)  { -	unsigned long flags;  	bool running; -	spin_lock_irqsave(&slave_active_lock, flags); +	guard(spinlock_irqsave)(&slave_active_lock);  	running = timeri->flags & SNDRV_TIMER_IFLG_RUNNING;  	timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;  	if (timeri->timer) { -		spin_lock(&timeri->timer->lock); +		guard(spinlock)(&timeri->timer->lock);  		list_del_init(&timeri->ack_list);  		list_del_init(&timeri->active_list);  		if (running)  			snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :  					  SNDRV_TIMER_EVENT_PAUSE); -		spin_unlock(&timeri->timer->lock);  	} -	spin_unlock_irqrestore(&slave_active_lock, flags);  	return running ? 0 : -EBUSY;  } @@ -804,12 +773,9 @@ static void snd_timer_process_callbacks(struct snd_timer *timer,  static void snd_timer_clear_callbacks(struct snd_timer *timer,  				      struct list_head *head)  { -	unsigned long flags; - -	spin_lock_irqsave(&timer->lock, flags); +	guard(spinlock_irqsave)(&timer->lock);  	while (!list_empty(head))  		list_del_init(head->next); -	spin_unlock_irqrestore(&timer->lock, flags);  }  /* @@ -819,16 +785,14 @@ static void snd_timer_clear_callbacks(struct snd_timer *timer,  static void snd_timer_work(struct work_struct *work)  {  	struct snd_timer *timer = container_of(work, struct snd_timer, task_work); -	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); +	guard(spinlock_irqsave)(&timer->lock);  	snd_timer_process_callbacks(timer, &timer->sack_list_head); -	spin_unlock_irqrestore(&timer->lock, flags);  }  /* @@ -842,8 +806,6 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)  	struct snd_timer_instance *ti, *ts, *tmp;  	unsigned long resolution;  	struct list_head *ack_list_head; -	unsigned long flags; -	bool use_work = false;  	if (timer == NULL)  		return; @@ -853,7 +815,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)  		return;  	} -	spin_lock_irqsave(&timer->lock, flags); +	guard(spinlock_irqsave)(&timer->lock);  	/* remember the current resolution */  	resolution = snd_timer_hw_resolution(timer); @@ -919,10 +881,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)  	snd_timer_process_callbacks(timer, &timer->ack_list_head);  	/* do we have any slow callbacks? */ -	use_work = !list_empty(&timer->sack_list_head); -	spin_unlock_irqrestore(&timer->lock, flags); - -	if (use_work) +	if (!list_empty(&timer->sack_list_head))  		queue_work(system_highpri_wq, &timer->task_work);  }  EXPORT_SYMBOL(snd_timer_interrupt); @@ -988,7 +947,7 @@ static int snd_timer_free(struct snd_timer *timer)  	if (!timer)  		return 0; -	mutex_lock(®ister_mutex); +	guard(mutex)(®ister_mutex);  	if (! list_empty(&timer->open_list_head)) {  		struct list_head *p, *n;  		struct snd_timer_instance *ti; @@ -1000,7 +959,6 @@ static int snd_timer_free(struct snd_timer *timer)  		}  	}  	list_del(&timer->device_list); -	mutex_unlock(®ister_mutex);  	if (timer->private_free)  		timer->private_free(timer); @@ -1025,7 +983,7 @@ static int snd_timer_dev_register(struct snd_device *dev)  	    !timer->hw.resolution && timer->hw.c_resolution == NULL)  	    	return -EINVAL; -	mutex_lock(®ister_mutex); +	guard(mutex)(®ister_mutex);  	list_for_each_entry(timer1, &snd_timer_list, device_list) {  		if (timer1->tmr_class > timer->tmr_class)  			break; @@ -1046,11 +1004,9 @@ static int snd_timer_dev_register(struct snd_device *dev)  		if (timer1->tmr_subdevice < timer->tmr_subdevice)  			continue;  		/* conflicts.. */ -		mutex_unlock(®ister_mutex);  		return -EBUSY;  	}  	list_add_tail(&timer->device_list, &timer1->device_list); -	mutex_unlock(®ister_mutex);  	return 0;  } @@ -1059,20 +1015,18 @@ static int snd_timer_dev_disconnect(struct snd_device *device)  	struct snd_timer *timer = device->device_data;  	struct snd_timer_instance *ti; -	mutex_lock(®ister_mutex); +	guard(mutex)(®ister_mutex);  	list_del_init(&timer->device_list);  	/* wake up pending sleepers */  	list_for_each_entry(ti, &timer->open_list_head, open_list) {  		if (ti->disconnect)  			ti->disconnect(ti);  	} -	mutex_unlock(®ister_mutex);  	return 0;  }  void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp)  { -	unsigned long flags;  	unsigned long resolution = 0;  	struct snd_timer_instance *ti, *ts; @@ -1083,7 +1037,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); +	guard(spinlock_irqsave)(&timer->lock);  	if (event == SNDRV_TIMER_EVENT_MSTART ||  	    event == SNDRV_TIMER_EVENT_MCONTINUE ||  	    event == SNDRV_TIMER_EVENT_MRESUME) @@ -1095,7 +1049,6 @@ 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);  }  EXPORT_SYMBOL(snd_timer_notify); @@ -1248,7 +1201,7 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,  	struct snd_timer_instance *ti;  	unsigned long resolution; -	mutex_lock(®ister_mutex); +	guard(mutex)(®ister_mutex);  	list_for_each_entry(timer, &snd_timer_list, device_list) {  		if (timer->card && timer->card->shutdown)  			continue; @@ -1270,9 +1223,8 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,  				    timer->tmr_device, timer->tmr_subdevice);  		}  		snd_iprintf(buffer, "%s :", timer->name); -		spin_lock_irq(&timer->lock); -		resolution = snd_timer_hw_resolution(timer); -		spin_unlock_irq(&timer->lock); +		scoped_guard(spinlock_irq, &timer->lock) +			resolution = snd_timer_hw_resolution(timer);  		if (resolution)  			snd_iprintf(buffer, " %lu.%03luus (%lu ticks)",  				    resolution / 1000, @@ -1288,7 +1240,6 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,  						  SNDRV_TIMER_IFLG_RUNNING))  				    ? "running" : "stopped");  	} -	mutex_unlock(®ister_mutex);  }  static struct snd_info_entry *snd_timer_proc_entry; @@ -1329,7 +1280,7 @@ static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,  	struct snd_timer_read *r;  	int prev; -	spin_lock(&tu->qlock); +	guard(spinlock)(&tu->qlock);  	if (tu->qused > 0) {  		prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;  		r = &tu->queue[prev]; @@ -1348,7 +1299,6 @@ static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,  		tu->qused++;  	}        __wake: -	spin_unlock(&tu->qlock);  	snd_kill_fasync(tu->fasync, SIGIO, POLL_IN);  	wake_up(&tu->qchange_sleep);  } @@ -1372,7 +1322,6 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,  {  	struct snd_timer_user *tu = timeri->callback_data;  	struct snd_timer_tread64 r1; -	unsigned long flags;  	if (event >= SNDRV_TIMER_EVENT_START &&  	    event <= SNDRV_TIMER_EVENT_PAUSE) @@ -1384,9 +1333,8 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,  	r1.tstamp_sec = tstamp->tv_sec;  	r1.tstamp_nsec = tstamp->tv_nsec;  	r1.val = resolution; -	spin_lock_irqsave(&tu->qlock, flags); -	snd_timer_user_append_to_tqueue(tu, &r1); -	spin_unlock_irqrestore(&tu->qlock, flags); +	scoped_guard(spinlock_irqsave, &tu->qlock) +		snd_timer_user_append_to_tqueue(tu, &r1);  	snd_kill_fasync(tu->fasync, SIGIO, POLL_IN);  	wake_up(&tu->qchange_sleep);  } @@ -1410,51 +1358,48 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,  	memset(&r1, 0, sizeof(r1));  	memset(&tstamp, 0, sizeof(tstamp)); -	spin_lock(&tu->qlock); -	if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) | -			   (1 << SNDRV_TIMER_EVENT_TICK))) == 0) { -		spin_unlock(&tu->qlock); -		return; -	} -	if (tu->last_resolution != resolution || ticks > 0) { -		if (timer_tstamp_monotonic) -			ktime_get_ts64(&tstamp); -		else -			ktime_get_real_ts64(&tstamp); -	} -	if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && -	    tu->last_resolution != resolution) { -		r1.event = SNDRV_TIMER_EVENT_RESOLUTION; +	scoped_guard(spinlock, &tu->qlock) { +		if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) | +				   (1 << SNDRV_TIMER_EVENT_TICK))) == 0) +			return; +		if (tu->last_resolution != resolution || ticks > 0) { +			if (timer_tstamp_monotonic) +				ktime_get_ts64(&tstamp); +			else +				ktime_get_real_ts64(&tstamp); +		} +		if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && +		    tu->last_resolution != resolution) { +			r1.event = SNDRV_TIMER_EVENT_RESOLUTION; +			r1.tstamp_sec = tstamp.tv_sec; +			r1.tstamp_nsec = tstamp.tv_nsec; +			r1.val = resolution; +			snd_timer_user_append_to_tqueue(tu, &r1); +			tu->last_resolution = resolution; +			append++; +		} +		if ((tu->filter & (1 << SNDRV_TIMER_EVENT_TICK)) == 0) +			break; +		if (ticks == 0) +			break; +		if (tu->qused > 0) { +			prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1; +			r = &tu->tqueue[prev]; +			if (r->event == SNDRV_TIMER_EVENT_TICK) { +				r->tstamp_sec = tstamp.tv_sec; +				r->tstamp_nsec = tstamp.tv_nsec; +				r->val += ticks; +				append++; +				break; +			} +		} +		r1.event = SNDRV_TIMER_EVENT_TICK;  		r1.tstamp_sec = tstamp.tv_sec;  		r1.tstamp_nsec = tstamp.tv_nsec; -		r1.val = resolution; +		r1.val = ticks;  		snd_timer_user_append_to_tqueue(tu, &r1); -		tu->last_resolution = resolution;  		append++;  	} -	if ((tu->filter & (1 << SNDRV_TIMER_EVENT_TICK)) == 0) -		goto __wake; -	if (ticks == 0) -		goto __wake; -	if (tu->qused > 0) { -		prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1; -		r = &tu->tqueue[prev]; -		if (r->event == SNDRV_TIMER_EVENT_TICK) { -			r->tstamp_sec = tstamp.tv_sec; -			r->tstamp_nsec = tstamp.tv_nsec; -			r->val += ticks; -			append++; -			goto __wake; -		} -	} -	r1.event = SNDRV_TIMER_EVENT_TICK; -	r1.tstamp_sec = tstamp.tv_sec; -	r1.tstamp_nsec = tstamp.tv_nsec; -	r1.val = ticks; -	snd_timer_user_append_to_tqueue(tu, &r1); -	append++; -      __wake: -	spin_unlock(&tu->qlock);  	if (append == 0)  		return;  	snd_kill_fasync(tu->fasync, SIGIO, POLL_IN); @@ -1476,14 +1421,13 @@ static int realloc_user_queue(struct snd_timer_user *tu, int size)  			return -ENOMEM;  	} -	spin_lock_irq(&tu->qlock); +	guard(spinlock_irq)(&tu->qlock);  	kfree(tu->queue);  	kfree(tu->tqueue);  	tu->queue_size = size;  	tu->queue = queue;  	tu->tqueue = tqueue;  	tu->qhead = tu->qtail = tu->qused = 0; -	spin_unlock_irq(&tu->qlock);  	return 0;  } @@ -1519,12 +1463,12 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)  	if (file->private_data) {  		tu = file->private_data;  		file->private_data = NULL; -		mutex_lock(&tu->ioctl_lock); -		if (tu->timeri) { -			snd_timer_close(tu->timeri); -			snd_timer_instance_free(tu->timeri); +		scoped_guard(mutex, &tu->ioctl_lock) { +			if (tu->timeri) { +				snd_timer_close(tu->timeri); +				snd_timer_instance_free(tu->timeri); +			}  		} -		mutex_unlock(&tu->ioctl_lock);  		snd_fasync_free(tu->fasync);  		kfree(tu->queue);  		kfree(tu->tqueue); @@ -1559,7 +1503,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)  	if (copy_from_user(&id, _tid, sizeof(id)))  		return -EFAULT; -	mutex_lock(®ister_mutex); +	guard(mutex)(®ister_mutex);  	if (id.dev_class < 0) {		/* first item */  		if (list_empty(&snd_timer_list))  			snd_timer_user_zero_id(&id); @@ -1636,7 +1580,6 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)  			snd_timer_user_zero_id(&id);  		}  	} -	mutex_unlock(®ister_mutex);  	if (copy_to_user(_tid, &id, sizeof(*_tid)))  		return -EFAULT;  	return 0; @@ -1645,70 +1588,54 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)  static int snd_timer_user_ginfo(struct file *file,  				struct snd_timer_ginfo __user *_ginfo)  { -	struct snd_timer_ginfo *ginfo; +	struct snd_timer_ginfo *ginfo __free(kfree) = NULL;  	struct snd_timer_id tid;  	struct snd_timer *t;  	struct list_head *p; -	int err = 0;  	ginfo = memdup_user(_ginfo, sizeof(*ginfo));  	if (IS_ERR(ginfo)) -		return PTR_ERR(ginfo); +		return PTR_ERR(no_free_ptr(ginfo));  	tid = ginfo->tid;  	memset(ginfo, 0, sizeof(*ginfo));  	ginfo->tid = tid; -	mutex_lock(®ister_mutex); +	guard(mutex)(®ister_mutex);  	t = snd_timer_find(&tid); -	if (t != NULL) { -		ginfo->card = t->card ? t->card->number : -1; -		if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) -			ginfo->flags |= SNDRV_TIMER_FLG_SLAVE; -		strscpy(ginfo->id, t->id, sizeof(ginfo->id)); -		strscpy(ginfo->name, t->name, sizeof(ginfo->name)); -		spin_lock_irq(&t->lock); +	if (!t) +		return -ENODEV; +	ginfo->card = t->card ? t->card->number : -1; +	if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) +		ginfo->flags |= SNDRV_TIMER_FLG_SLAVE; +	strscpy(ginfo->id, t->id, sizeof(ginfo->id)); +	strscpy(ginfo->name, t->name, sizeof(ginfo->name)); +	scoped_guard(spinlock_irq, &t->lock)  		ginfo->resolution = snd_timer_hw_resolution(t); -		spin_unlock_irq(&t->lock); -		if (t->hw.resolution_min > 0) { -			ginfo->resolution_min = t->hw.resolution_min; -			ginfo->resolution_max = t->hw.resolution_max; -		} -		list_for_each(p, &t->open_list_head) { -			ginfo->clients++; -		} -	} else { -		err = -ENODEV; +	if (t->hw.resolution_min > 0) { +		ginfo->resolution_min = t->hw.resolution_min; +		ginfo->resolution_max = t->hw.resolution_max;  	} -	mutex_unlock(®ister_mutex); -	if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo))) -		err = -EFAULT; -	kfree(ginfo); -	return err; +	list_for_each(p, &t->open_list_head) { +		ginfo->clients++; +	} +	if (copy_to_user(_ginfo, ginfo, sizeof(*ginfo))) +		return -EFAULT; +	return 0;  }  static int timer_set_gparams(struct snd_timer_gparams *gparams)  {  	struct snd_timer *t; -	int err; -	mutex_lock(®ister_mutex); +	guard(mutex)(®ister_mutex);  	t = snd_timer_find(&gparams->tid); -	if (!t) { -		err = -ENODEV; -		goto _error; -	} -	if (!list_empty(&t->open_list_head)) { -		err = -EBUSY; -		goto _error; -	} -	if (!t->hw.set_period) { -		err = -ENOSYS; -		goto _error; -	} -	err = t->hw.set_period(t, gparams->period_num, gparams->period_den); -_error: -	mutex_unlock(®ister_mutex); -	return err; +	if (!t) +		return -ENODEV; +	if (!list_empty(&t->open_list_head)) +		return -EBUSY; +	if (!t->hw.set_period) +		return -ENOSYS; +	return t->hw.set_period(t, gparams->period_num, gparams->period_den);  }  static int snd_timer_user_gparams(struct file *file, @@ -1734,10 +1661,10 @@ static int snd_timer_user_gstatus(struct file *file,  	tid = gstatus.tid;  	memset(&gstatus, 0, sizeof(gstatus));  	gstatus.tid = tid; -	mutex_lock(®ister_mutex); +	guard(mutex)(®ister_mutex);  	t = snd_timer_find(&tid);  	if (t != NULL) { -		spin_lock_irq(&t->lock); +		guard(spinlock_irq)(&t->lock);  		gstatus.resolution = snd_timer_hw_resolution(t);  		if (t->hw.precise_resolution) {  			t->hw.precise_resolution(t, &gstatus.resolution_num, @@ -1746,11 +1673,9 @@ static int snd_timer_user_gstatus(struct file *file,  			gstatus.resolution_num = gstatus.resolution;  			gstatus.resolution_den = 1000000000uL;  		} -		spin_unlock_irq(&t->lock);  	} else {  		err = -ENODEV;  	} -	mutex_unlock(®ister_mutex);  	if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus)))  		err = -EFAULT;  	return err; @@ -1804,9 +1729,8 @@ static int snd_timer_user_info(struct file *file,  			       struct snd_timer_info __user *_info)  {  	struct snd_timer_user *tu; -	struct snd_timer_info *info; +	struct snd_timer_info *info __free(kfree) = NULL;  	struct snd_timer *t; -	int err = 0;  	tu = file->private_data;  	if (!tu->timeri) @@ -1823,13 +1747,11 @@ static int snd_timer_user_info(struct file *file,  		info->flags |= SNDRV_TIMER_FLG_SLAVE;  	strscpy(info->id, t->id, sizeof(info->id));  	strscpy(info->name, t->name, sizeof(info->name)); -	spin_lock_irq(&t->lock); -	info->resolution = snd_timer_hw_resolution(t); -	spin_unlock_irq(&t->lock); +	scoped_guard(spinlock_irq, &t->lock) +		info->resolution = snd_timer_hw_resolution(t);  	if (copy_to_user(_info, info, sizeof(*_info))) -		err = -EFAULT; -	kfree(info); -	return err; +		return -EFAULT; +	return 0;  }  static int snd_timer_user_params(struct file *file, @@ -1887,45 +1809,47 @@ static int snd_timer_user_params(struct file *file,  		goto _end;  	}  	snd_timer_stop(tu->timeri); -	spin_lock_irq(&t->lock); -	tu->timeri->flags &= ~(SNDRV_TIMER_IFLG_AUTO| -			       SNDRV_TIMER_IFLG_EXCLUSIVE| -			       SNDRV_TIMER_IFLG_EARLY_EVENT); -	if (params.flags & SNDRV_TIMER_PSFLG_AUTO) -		tu->timeri->flags |= SNDRV_TIMER_IFLG_AUTO; -	if (params.flags & SNDRV_TIMER_PSFLG_EXCLUSIVE) -		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); +	scoped_guard(spinlock_irq, &t->lock) { +		tu->timeri->flags &= ~(SNDRV_TIMER_IFLG_AUTO| +				       SNDRV_TIMER_IFLG_EXCLUSIVE| +				       SNDRV_TIMER_IFLG_EARLY_EVENT); +		if (params.flags & SNDRV_TIMER_PSFLG_AUTO) +			tu->timeri->flags |= SNDRV_TIMER_IFLG_AUTO; +		if (params.flags & SNDRV_TIMER_PSFLG_EXCLUSIVE) +			tu->timeri->flags |= SNDRV_TIMER_IFLG_EXCLUSIVE; +		if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT) +			tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT; +	}  	if (params.queue_size > 0 &&  	    (unsigned int)tu->queue_size != params.queue_size) {  		err = realloc_user_queue(tu, params.queue_size);  		if (err < 0)  			goto _end;  	} -	spin_lock_irq(&tu->qlock); -	tu->qhead = tu->qtail = tu->qused = 0; -	if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { -		if (tu->tread) { -			struct snd_timer_tread64 tread; -			memset(&tread, 0, sizeof(tread)); -			tread.event = SNDRV_TIMER_EVENT_EARLY; -			tread.tstamp_sec = 0; -			tread.tstamp_nsec = 0; -			tread.val = 0; -			snd_timer_user_append_to_tqueue(tu, &tread); -		} else { -			struct snd_timer_read *r = &tu->queue[0]; -			r->resolution = 0; -			r->ticks = 0; -			tu->qused++; -			tu->qtail++; +	scoped_guard(spinlock_irq, &tu->qlock) { +		tu->qhead = tu->qtail = tu->qused = 0; +		if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { +			if (tu->tread) { +				struct snd_timer_tread64 tread; + +				memset(&tread, 0, sizeof(tread)); +				tread.event = SNDRV_TIMER_EVENT_EARLY; +				tread.tstamp_sec = 0; +				tread.tstamp_nsec = 0; +				tread.val = 0; +				snd_timer_user_append_to_tqueue(tu, &tread); +			} else { +				struct snd_timer_read *r = &tu->queue[0]; + +				r->resolution = 0; +				r->ticks = 0; +				tu->qused++; +				tu->qtail++; +			}  		} +		tu->filter = params.filter; +		tu->ticks = params.ticks;  	} -	tu->filter = params.filter; -	tu->ticks = params.ticks; -	spin_unlock_irq(&tu->qlock);  	err = 0;   _end:  	if (copy_to_user(_params, ¶ms, sizeof(params))) @@ -1948,9 +1872,8 @@ static int snd_timer_user_status32(struct file *file,  	status.resolution = snd_timer_resolution(tu->timeri);  	status.lost = tu->timeri->lost;  	status.overrun = tu->overrun; -	spin_lock_irq(&tu->qlock); -	status.queue = tu->qused; -	spin_unlock_irq(&tu->qlock); +	scoped_guard(spinlock_irq, &tu->qlock) +		status.queue = tu->qused;  	if (copy_to_user(_status, &status, sizeof(status)))  		return -EFAULT;  	return 0; @@ -1971,9 +1894,8 @@ static int snd_timer_user_status64(struct file *file,  	status.resolution = snd_timer_resolution(tu->timeri);  	status.lost = tu->timeri->lost;  	status.overrun = tu->overrun; -	spin_lock_irq(&tu->qlock); -	status.queue = tu->qused; -	spin_unlock_irq(&tu->qlock); +	scoped_guard(spinlock_irq, &tu->qlock) +		status.queue = tu->qused;  	if (copy_to_user(_status, &status, sizeof(status)))  		return -EFAULT;  	return 0; @@ -2131,12 +2053,9 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,  				 unsigned long arg)  {  	struct snd_timer_user *tu = file->private_data; -	long ret; -	mutex_lock(&tu->ioctl_lock); -	ret = __snd_timer_user_ioctl(file, cmd, arg, false); -	mutex_unlock(&tu->ioctl_lock); -	return ret; +	guard(mutex)(&tu->ioctl_lock); +	return __snd_timer_user_ioctl(file, cmd, arg, false);  }  static int snd_timer_user_fasync(int fd, struct file * file, int on) @@ -2263,12 +2182,11 @@ static __poll_t snd_timer_user_poll(struct file *file, poll_table * wait)          poll_wait(file, &tu->qchange_sleep, wait);  	mask = 0; -	spin_lock_irq(&tu->qlock); +	guard(spinlock_irq)(&tu->qlock);  	if (tu->qused)  		mask |= EPOLLIN | EPOLLRDNORM;  	if (tu->disconnected)  		mask |= EPOLLERR; -	spin_unlock_irq(&tu->qlock);  	return mask;  }  | 
