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};
@@ -147,6 +149,21 @@ static void dmaengine_pcm_dma_complete(void *arg)
147149 snd_pcm_period_elapsed (substream );
148150}
149151
152+ static void dmaengine_pcm_dma_complete_nonatomic (struct work_struct * wq )
153+ {
154+ struct dmaengine_pcm_runtime_data * prtd = \
155+ container_of (wq , struct dmaengine_pcm_runtime_data , complete_wq );
156+ struct snd_pcm_substream * substream = prtd -> substream ;
157+ dmaengine_pcm_dma_complete (substream );
158+ }
159+
160+ static void dmaengine_pcm_dma_complete_nonatomic_callback (void * arg )
161+ {
162+ struct snd_pcm_substream * substream = arg ;
163+ struct dmaengine_pcm_runtime_data * prtd = substream_to_prtd (substream );
164+ schedule_work (& prtd -> complete_wq );
165+ }
166+
150167static int dmaengine_pcm_prepare_and_submit (struct snd_pcm_substream * substream )
151168{
152169 struct dmaengine_pcm_runtime_data * prtd = substream_to_prtd (substream );
@@ -169,7 +186,11 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
169186 if (!desc )
170187 return - ENOMEM ;
171188
172- desc -> callback = dmaengine_pcm_dma_complete ;
189+ if (substream -> pcm -> nonatomic )
190+ desc -> callback = dmaengine_pcm_dma_complete_nonatomic_callback ;
191+ else
192+ desc -> callback = dmaengine_pcm_dma_complete ;
193+
173194 desc -> callback_param = substream ;
174195 prtd -> cookie = dmaengine_submit (desc );
175196
@@ -322,6 +343,10 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
322343 if (!prtd )
323344 return - ENOMEM ;
324345
346+ if (substream -> pcm -> nonatomic )
347+ INIT_WORK (& prtd -> complete_wq , dmaengine_pcm_dma_complete_nonatomic );
348+
349+ prtd -> substream = substream ;
325350 prtd -> dma_chan = chan ;
326351
327352 substream -> runtime -> private_data = prtd ;
@@ -361,6 +386,8 @@ static void __snd_dmaengine_pcm_close(struct snd_pcm_substream *substream,
361386 */
362387 dmaengine_terminate_async (prtd -> dma_chan );
363388 dmaengine_synchronize (prtd -> dma_chan );
389+ if (substream -> pcm -> nonatomic )
390+ flush_work (& prtd -> complete_wq );
364391 if (release_channel )
365392 dma_release_channel (prtd -> dma_chan );
366393 kfree (prtd );
0 commit comments