forked from mirrors/linux
		
	ALSA: PCM - Don't check DMA time-out too shortly
When the PCM period size is set larger than 10 seconds, currently the PCM core may abort the operation with DMA-error due to the fixed timeout for 10 seconds. A similar problem is seen in the drain operation that has a fixed timeout of 10 seconds, too. This patch fixes the timeout length depending on the period size and rate, also including the consideration of no_period_wakeup flag. Reported-by: Raymond Yau <superquad.vortex2@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									a331b0c366
								
							
						
					
					
						commit
						f2b3614cef
					
				
					 2 changed files with 23 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -1756,8 +1756,18 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
 | 
			
		|||
	wait_queue_t wait;
 | 
			
		||||
	int err = 0;
 | 
			
		||||
	snd_pcm_uframes_t avail = 0;
 | 
			
		||||
	long tout;
 | 
			
		||||
	long wait_time, tout;
 | 
			
		||||
 | 
			
		||||
	if (runtime->no_period_wakeup)
 | 
			
		||||
		wait_time = MAX_SCHEDULE_TIMEOUT;
 | 
			
		||||
	else {
 | 
			
		||||
		wait_time = 10;
 | 
			
		||||
		if (runtime->rate) {
 | 
			
		||||
			long t = runtime->period_size * 2 / runtime->rate;
 | 
			
		||||
			wait_time = max(t, wait_time);
 | 
			
		||||
		}
 | 
			
		||||
		wait_time = msecs_to_jiffies(wait_time * 1000);
 | 
			
		||||
	}
 | 
			
		||||
	init_waitqueue_entry(&wait, current);
 | 
			
		||||
	add_wait_queue(&runtime->tsleep, &wait);
 | 
			
		||||
	for (;;) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1765,9 +1775,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
 | 
			
		|||
			err = -ERESTARTSYS;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		set_current_state(TASK_INTERRUPTIBLE);
 | 
			
		||||
		snd_pcm_stream_unlock_irq(substream);
 | 
			
		||||
		tout = schedule_timeout(msecs_to_jiffies(10000));
 | 
			
		||||
		tout = schedule_timeout_interruptible(wait_time);
 | 
			
		||||
		snd_pcm_stream_lock_irq(substream);
 | 
			
		||||
		switch (runtime->status->state) {
 | 
			
		||||
		case SNDRV_PCM_STATE_SUSPENDED:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1481,11 +1481,20 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
 | 
			
		|||
			break; /* all drained */
 | 
			
		||||
		init_waitqueue_entry(&wait, current);
 | 
			
		||||
		add_wait_queue(&to_check->sleep, &wait);
 | 
			
		||||
		set_current_state(TASK_INTERRUPTIBLE);
 | 
			
		||||
		snd_pcm_stream_unlock_irq(substream);
 | 
			
		||||
		up_read(&snd_pcm_link_rwsem);
 | 
			
		||||
		snd_power_unlock(card);
 | 
			
		||||
		tout = schedule_timeout(10 * HZ);
 | 
			
		||||
		if (runtime->no_period_wakeup)
 | 
			
		||||
			tout = MAX_SCHEDULE_TIMEOUT;
 | 
			
		||||
		else {
 | 
			
		||||
			tout = 10;
 | 
			
		||||
			if (runtime->rate) {
 | 
			
		||||
				long t = runtime->period_size * 2 / runtime->rate;
 | 
			
		||||
				tout = max(t, tout);
 | 
			
		||||
			}
 | 
			
		||||
			tout = msecs_to_jiffies(tout * 1000);
 | 
			
		||||
		}
 | 
			
		||||
		tout = schedule_timeout_interruptible(tout);
 | 
			
		||||
		snd_power_lock(card);
 | 
			
		||||
		down_read(&snd_pcm_link_rwsem);
 | 
			
		||||
		snd_pcm_stream_lock_irq(substream);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue