Patchwork [3.5.yuz,extended,stable] Patch "ASoC: fsi: don't reschedule DMA from an atomic context" has been added to staging queue

mail settings
Submitter Herton Ronaldo Krzesinski
Date Nov. 21, 2012, 5:08 a.m.
Message ID <>
Download mbox | patch
Permalink /patch/200556/
State New
Headers show


Herton Ronaldo Krzesinski - Nov. 21, 2012, 5:08 a.m.
This is a note to let you know that I have just added a patch titled

    ASoC: fsi: don't reschedule DMA from an atomic context

to the linux-3.5.y-queue branch of the 3.5.yuz extended stable tree 
which can be found at:;a=shortlog;h=refs/heads/linux-3.5.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.yuz tree, see



From e257f20b4be63b9d17b567542b65f9a15d224197 Mon Sep 17 00:00:00 2001
From: Guennadi Liakhovetski <>
Date: Wed, 3 Oct 2012 14:33:50 +0200
Subject: [PATCH] ASoC: fsi: don't reschedule DMA from an atomic context

commit 57451e437796548d658d03c2c4aab659eafcd799 upstream.

shdma doesn't support transfer re-scheduling or triggering from callbacks
or from atomic context. The fsi driver issues DMA transfers from a tasklet
context, which is a bug. To fix it convert tasklet to a work.

Reported-by: Do Q.Thang <>
Tested-by: Do Q.Thang <>
Signed-off-by: Guennadi Liakhovetski <>
Signed-off-by: Mark Brown <>
Signed-off-by: Herton Ronaldo Krzesinski <>
 sound/soc/sh/fsi.c |   15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)



diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 2ef9853..e96c395 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -20,6 +20,7 @@ 
 #include <linux/sh_dma.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/workqueue.h>
 #include <sound/soc.h>
 #include <sound/sh_fsi.h>

@@ -223,7 +224,7 @@  struct fsi_stream {
 	struct dma_chan		*chan;
 	struct sh_dmae_slave	slave; /* see fsi_handler_init() */
-	struct tasklet_struct	tasklet;
+	struct work_struct	work;
 	dma_addr_t		dma;

@@ -1085,9 +1086,9 @@  static void fsi_dma_complete(void *data)

-static void fsi_dma_do_tasklet(unsigned long data)
+static void fsi_dma_do_work(struct work_struct *work)
-	struct fsi_stream *io = (struct fsi_stream *)data;
+	struct fsi_stream *io = container_of(work, struct fsi_stream, work);
 	struct fsi_priv *fsi = fsi_stream_to_priv(io);
 	struct dma_chan *chan;
 	struct snd_soc_dai *dai;
@@ -1140,7 +1141,7 @@  static void fsi_dma_do_tasklet(unsigned long data)
 	 * FIXME
 	 * In DMAEngine case, codec and FSI cannot be started simultaneously
-	 * since FSI is using tasklet.
+	 * since FSI is using the scheduler work queue.
 	 * Therefore, in capture case, probably FSI FIFO will have got
 	 * overflow error in this point.
 	 * in that case, DMA cannot start transfer until error was cleared.
@@ -1164,7 +1165,7 @@  static bool fsi_dma_filter(struct dma_chan *chan, void *param)

 static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
-	tasklet_schedule(&io->tasklet);
+	schedule_work(&io->work);

 	return 0;
@@ -1195,14 +1196,14 @@  static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
 	if (!io->chan)
 		return -EIO;

-	tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
+	INIT_WORK(&io->work, fsi_dma_do_work);

 	return 0;

 static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
-	tasklet_kill(&io->tasklet);
+	cancel_work_sync(&io->work);

 	fsi_stream_stop(fsi, io);