@@ -108,14 +108,16 @@ struct pcmtst_buf_iter {
108108 size_t total_bytes ; // Total bytes read/written
109109 size_t chan_block ; // Bytes in one channel buffer when non-interleaved
110110 struct snd_pcm_substream * substream ;
111+ bool suspend ; // We need to pause timer without shutting it down
111112 struct timer_list timer_instance ;
112113};
113114
114115static struct snd_pcm_hardware snd_pcmtst_hw = {
115116 .info = (SNDRV_PCM_INFO_INTERLEAVED |
116117 SNDRV_PCM_INFO_BLOCK_TRANSFER |
117118 SNDRV_PCM_INFO_NONINTERLEAVED |
118- SNDRV_PCM_INFO_MMAP_VALID ),
119+ SNDRV_PCM_INFO_MMAP_VALID |
120+ SNDRV_PCM_INFO_PAUSE ),
119121 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE ,
120122 .rates = SNDRV_PCM_RATE_8000_48000 ,
121123 .rate_min = 8000 ,
@@ -346,6 +348,9 @@ static void timer_timeout(struct timer_list *data)
346348 v_iter = from_timer (v_iter , data , timer_instance );
347349 substream = v_iter -> substream ;
348350
351+ if (v_iter -> suspend )
352+ return ;
353+
349354 if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK && !v_iter -> is_buf_corrupted )
350355 check_buf_block (v_iter , substream -> runtime );
351356 else if (substream -> stream == SNDRV_PCM_STREAM_CAPTURE )
@@ -358,7 +363,9 @@ static void timer_timeout(struct timer_list *data)
358363 v_iter -> period_pos %= v_iter -> period_bytes ;
359364 snd_pcm_period_elapsed (substream );
360365 }
361- mod_timer (& v_iter -> timer_instance , jiffies + TIMER_INTERVAL + inject_delay );
366+
367+ if (!v_iter -> suspend )
368+ mod_timer (& v_iter -> timer_instance , jiffies + TIMER_INTERVAL + inject_delay );
362369}
363370
364371static int snd_pcmtst_pcm_open (struct snd_pcm_substream * substream )
@@ -373,19 +380,15 @@ static int snd_pcmtst_pcm_open(struct snd_pcm_substream *substream)
373380 if (!v_iter )
374381 return - ENOMEM ;
375382
383+ v_iter -> substream = substream ;
376384 runtime -> hw = snd_pcmtst_hw ;
377385 runtime -> private_data = v_iter ;
378- v_iter -> substream = substream ;
379- v_iter -> buf_pos = 0 ;
380- v_iter -> is_buf_corrupted = false;
381- v_iter -> period_pos = 0 ;
382- v_iter -> total_bytes = 0 ;
383386
384387 playback_capture_test = 0 ;
385388 ioctl_reset_test = 0 ;
386389
387390 timer_setup (& v_iter -> timer_instance , timer_timeout , 0 );
388- mod_timer ( & v_iter -> timer_instance , jiffies + TIMER_INTERVAL );
391+
389392 return 0 ;
390393}
391394
@@ -400,10 +403,40 @@ static int snd_pcmtst_pcm_close(struct snd_pcm_substream *substream)
400403 return 0 ;
401404}
402405
406+ static inline void reset_buf_iterator (struct pcmtst_buf_iter * v_iter )
407+ {
408+ v_iter -> buf_pos = 0 ;
409+ v_iter -> is_buf_corrupted = false;
410+ v_iter -> period_pos = 0 ;
411+ v_iter -> total_bytes = 0 ;
412+ }
413+
414+ static inline void start_pcmtest_timer (struct pcmtst_buf_iter * v_iter )
415+ {
416+ v_iter -> suspend = false;
417+ mod_timer (& v_iter -> timer_instance , jiffies + TIMER_INTERVAL );
418+ }
419+
403420static int snd_pcmtst_pcm_trigger (struct snd_pcm_substream * substream , int cmd )
404421{
422+ struct pcmtst_buf_iter * v_iter = substream -> runtime -> private_data ;
423+
405424 if (inject_trigger_err )
406425 return - EINVAL ;
426+ switch (cmd ) {
427+ case SNDRV_PCM_TRIGGER_START :
428+ reset_buf_iterator (v_iter );
429+ start_pcmtest_timer (v_iter );
430+ break ;
431+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
432+ start_pcmtest_timer (v_iter );
433+ break ;
434+ case SNDRV_PCM_TRIGGER_STOP :
435+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
436+ // We can't call timer_shutdown_sync here, as it is forbidden to sleep here
437+ v_iter -> suspend = true;
438+ break ;
439+ }
407440
408441 return 0 ;
409442}
0 commit comments