]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/dma/shdma.c
SH: constify multiple DMA related objects and references to them
[net-next-2.6.git] / drivers / dma / shdma.c
index ea6779f3e73fada8edb714d0dc8877d00f33c634..aab352a63a4a6716b492018ecb03dc631123f05d 100644 (file)
@@ -25,8 +25,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-
-#include <asm/dmaengine.h>
+#include <linux/sh_dma.h>
 
 #include "shdma.h"
 
@@ -44,7 +43,7 @@ enum sh_dmae_desc_status {
 #define LOG2_DEFAULT_XFER_SIZE 2
 
 /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */
-static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)];
+static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
 
 static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
 
@@ -189,7 +188,7 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
        struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
                                                struct sh_dmae_device, common);
        struct sh_dmae_pdata *pdata = shdev->pdata;
-       struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
+       const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
        u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16);
        int shift = chan_pdata->dmars_bit;
 
@@ -265,8 +264,8 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan)
        return NULL;
 }
 
-static struct sh_dmae_slave_config *sh_dmae_find_slave(
-       struct sh_dmae_chan *sh_chan, enum sh_dmae_slave_chan_id slave_id)
+static const struct sh_dmae_slave_config *sh_dmae_find_slave(
+       struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param)
 {
        struct dma_device *dma_dev = sh_chan->common.device;
        struct sh_dmae_device *shdev = container_of(dma_dev,
@@ -274,11 +273,11 @@ static struct sh_dmae_slave_config *sh_dmae_find_slave(
        struct sh_dmae_pdata *pdata = shdev->pdata;
        int i;
 
-       if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER)
+       if (param->slave_id >= SH_DMA_SLAVE_NUMBER)
                return NULL;
 
        for (i = 0; i < pdata->slave_num; i++)
-               if (pdata->slave[i].slave_id == slave_id)
+               if (pdata->slave[i].slave_id == param->slave_id)
                        return pdata->slave + i;
 
        return NULL;
@@ -297,9 +296,9 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
         * never runs concurrently with itself or free_chan_resources.
         */
        if (param) {
-               struct sh_dmae_slave_config *cfg;
+               const struct sh_dmae_slave_config *cfg;
 
-               cfg = sh_dmae_find_slave(sh_chan, param->slave_id);
+               cfg = sh_dmae_find_slave(sh_chan, param);
                if (!cfg)
                        return -EINVAL;
 
@@ -558,12 +557,14 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
 {
        struct sh_dmae_slave *param;
        struct sh_dmae_chan *sh_chan;
+       dma_addr_t slave_addr;
 
        if (!chan)
                return NULL;
 
        sh_chan = to_sh_chan(chan);
        param = chan->private;
+       slave_addr = param->config->addr;
 
        /* Someone calling slave DMA on a public channel? */
        if (!param || !sg_len) {
@@ -576,7 +577,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
         * if (param != NULL), this is a successfully requested slave channel,
         * therefore param->config != NULL too.
         */
-       return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &param->config->addr,
+       return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &slave_addr,
                               direction, flags);
 }
 
@@ -587,6 +588,19 @@ static void sh_dmae_terminate_all(struct dma_chan *chan)
        if (!chan)
                return;
 
+       dmae_halt(sh_chan);
+
+       spin_lock_bh(&sh_chan->desc_lock);
+       if (!list_empty(&sh_chan->ld_queue)) {
+               /* Record partial transfer */
+               struct sh_desc *desc = list_entry(sh_chan->ld_queue.next,
+                                                 struct sh_desc, node);
+               desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
+                       sh_chan->xmit_shift;
+
+       }
+       spin_unlock_bh(&sh_chan->desc_lock);
+
        sh_dmae_chan_ld_cleanup(sh_chan, true);
 }
 
@@ -701,6 +715,9 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
        /* Find the first not transferred desciptor */
        list_for_each_entry(desc, &sh_chan->ld_queue, node)
                if (desc->mark == DESC_SUBMITTED) {
+                       dev_dbg(sh_chan->dev, "Queue #%d to %d: %u@%x -> %x\n",
+                               desc->async_tx.cookie, sh_chan->id,
+                               desc->hw.tcr, desc->hw.sar, desc->hw.dar);
                        /* Get the ld start address from ld_queue */
                        dmae_set_reg(sh_chan, &desc->hw);
                        dmae_start(sh_chan);
@@ -841,7 +858,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
                                        int irq, unsigned long flags)
 {
        int err;
-       struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id];
+       const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id];
        struct platform_device *pdev = to_platform_device(shdev->common.dev);
        struct sh_dmae_chan *new_sh_chan;