]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/dma/fsldma.c
async_tx: fix multiple dependency submission
[linux-2.6-omap-h63xx.git] / drivers / dma / fsldma.c
index 72692309398af7cc214fae1ce2254c8da31d26bd..d8ae18dbf1a795c9c053625ee5b6af408440c43b 100644 (file)
@@ -696,6 +696,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
 {
        struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
        u32 stat;
+       int update_cookie = 0;
+       int xfer_ld_q = 0;
 
        stat = get_sr(fsl_chan);
        dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n",
@@ -720,8 +722,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
                         * Now, update the completed cookie, and continue the
                         * next uncompleted transfer.
                         */
-                       fsl_dma_update_completed_cookie(fsl_chan);
-                       fsl_chan_xfer_ld_queue(fsl_chan);
+                       update_cookie = 1;
+                       xfer_ld_q = 1;
                }
                stat &= ~FSL_DMA_SR_PE;
        }
@@ -734,19 +736,33 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
                dev_dbg(fsl_chan->dev, "event: clndar %p, nlndar %p\n",
                        (void *)get_cdar(fsl_chan), (void *)get_ndar(fsl_chan));
                stat &= ~FSL_DMA_SR_EOSI;
-               fsl_dma_update_completed_cookie(fsl_chan);
+               update_cookie = 1;
+       }
+
+       /* For MPC8349, EOCDI event need to update cookie
+        * and start the next transfer if it exist.
+        */
+       if (stat & FSL_DMA_SR_EOCDI) {
+               dev_dbg(fsl_chan->dev, "event: End-of-Chain link INT\n");
+               stat &= ~FSL_DMA_SR_EOCDI;
+               update_cookie = 1;
+               xfer_ld_q = 1;
        }
 
        /* If it current transfer is the end-of-transfer,
         * we should clear the Channel Start bit for
         * prepare next transfer.
         */
-       if (stat & (FSL_DMA_SR_EOLNI | FSL_DMA_SR_EOCDI)) {
+       if (stat & FSL_DMA_SR_EOLNI) {
                dev_dbg(fsl_chan->dev, "event: End-of-link INT\n");
                stat &= ~FSL_DMA_SR_EOLNI;
-               fsl_chan_xfer_ld_queue(fsl_chan);
+               xfer_ld_q = 1;
        }
 
+       if (update_cookie)
+               fsl_dma_update_completed_cookie(fsl_chan);
+       if (xfer_ld_q)
+               fsl_chan_xfer_ld_queue(fsl_chan);
        if (stat)
                dev_dbg(fsl_chan->dev, "event: unhandled sr 0x%02x\n",
                                        stat);
@@ -776,15 +792,13 @@ static void dma_do_tasklet(unsigned long data)
        fsl_chan_ld_cleanup(fsl_chan);
 }
 
-#ifdef FSL_DMA_CALLBACKTEST
-static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan)
+static void fsl_dma_callback_test(void *param)
 {
+       struct fsl_dma_chan *fsl_chan = param;
        if (fsl_chan)
-               dev_info(fsl_chan->dev, "selftest: callback is ok!\n");
+               dev_dbg(fsl_chan->dev, "selftest: callback is ok!\n");
 }
-#endif
 
-#ifdef CONFIG_FSL_DMA_SELFTEST
 static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
 {
        struct dma_chan *chan;
@@ -875,13 +889,11 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
        cookie = fsl_dma_tx_submit(tx3);
        cookie = fsl_dma_tx_submit(tx2);
 
-#ifdef FSL_DMA_CALLBACKTEST
        if (dma_has_cap(DMA_INTERRUPT, ((struct fsl_dma_device *)
            dev_get_drvdata(fsl_chan->dev->parent))->common.cap_mask)) {
                tx3->callback = fsl_dma_callback_test;
                tx3->callback_param = fsl_chan;
        }
-#endif
        fsl_dma_memcpy_issue_pending(chan);
        msleep(2);
 
@@ -906,7 +918,6 @@ out:
        kfree(src);
        return err;
 }
-#endif
 
 static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
                        const struct of_device_id *match)
@@ -997,11 +1008,9 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
                }
        }
 
-#ifdef CONFIG_FSL_DMA_SELFTEST
        err = fsl_dma_self_test(new_fsl_chan);
        if (err)
                goto err;
-#endif
 
        dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
                                match->compatible, new_fsl_chan->irq);
@@ -1021,11 +1030,11 @@ const u32 mpc8349_dma_ip_feature = FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN;
 
 static struct of_device_id of_fsl_dma_chan_ids[] = {
        {
-               .compatible = "fsl,mpc8540-dma-channel",
+               .compatible = "fsl,eloplus-dma-channel",
                .data = (void *)&mpc8540_dma_ip_feature,
        },
        {
-               .compatible = "fsl,mpc8349-dma-channel",
+               .compatible = "fsl,elo-dma-channel",
                .data = (void *)&mpc8349_dma_ip_feature,
        },
        {}
@@ -1107,8 +1116,8 @@ err:
 }
 
 static struct of_device_id of_fsl_dma_ids[] = {
-       { .compatible = "fsl,mpc8540-dma", },
-       { .compatible = "fsl,mpc8349-dma", },
+       { .compatible = "fsl,eloplus-dma", },
+       { .compatible = "fsl,elo-dma", },
        {}
 };