2222struct dmaengine_pcm_runtime_data {
2323 struct dma_chan * dma_chan ;
2424 dma_cookie_t cookie ;
25+ struct work_struct complete_wq ; /* for nonatomic PCM */
26+ struct snd_pcm_substream * substream ;
2527
2628 unsigned int pos ;
2729};
@@ -145,6 +147,21 @@ static void dmaengine_pcm_dma_complete(void *arg)
145147 snd_pcm_period_elapsed (substream );
146148}
147149
150+ static void dmaengine_pcm_dma_complete_nonatomic (struct work_struct * wq )
151+ {
152+ struct dmaengine_pcm_runtime_data * prtd = \
153+ container_of (wq , struct dmaengine_pcm_runtime_data , complete_wq );
154+ struct snd_pcm_substream * substream = prtd -> substream ;
155+ dmaengine_pcm_dma_complete (substream );
156+ }
157+
158+ static void dmaengine_pcm_dma_complete_nonatomic_callback (void * arg )
159+ {
160+ struct snd_pcm_substream * substream = arg ;
161+ struct dmaengine_pcm_runtime_data * prtd = substream_to_prtd (substream );
162+ schedule_work (& prtd -> complete_wq );
163+ }
164+
148165static int dmaengine_pcm_prepare_and_submit (struct snd_pcm_substream * substream )
149166{
150167 struct dmaengine_pcm_runtime_data * prtd = substream_to_prtd (substream );
@@ -167,7 +184,11 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
167184 if (!desc )
168185 return - ENOMEM ;
169186
170- desc -> callback = dmaengine_pcm_dma_complete ;
187+ if (substream -> pcm -> nonatomic )
188+ desc -> callback = dmaengine_pcm_dma_complete_nonatomic_callback ;
189+ else
190+ desc -> callback = dmaengine_pcm_dma_complete ;
191+
171192 desc -> callback_param = substream ;
172193 prtd -> cookie = dmaengine_submit (desc );
173194
@@ -320,6 +341,10 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
320341 if (!prtd )
321342 return - ENOMEM ;
322343
344+ if (substream -> pcm -> nonatomic )
345+ INIT_WORK (& prtd -> complete_wq , dmaengine_pcm_dma_complete_nonatomic );
346+
347+ prtd -> substream = substream ;
323348 prtd -> dma_chan = chan ;
324349
325350 substream -> runtime -> private_data = prtd ;
@@ -380,6 +405,8 @@ static void __snd_dmaengine_pcm_close(struct snd_pcm_substream *substream,
380405 */
381406 dmaengine_terminate_async (prtd -> dma_chan );
382407 dmaengine_synchronize (prtd -> dma_chan );
408+ if (substream -> pcm -> nonatomic )
409+ flush_work (& prtd -> complete_wq );
383410 if (release_channel )
384411 dma_release_channel (prtd -> dma_chan );
385412 kfree (prtd );
0 commit comments