]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/dma/amba-pl08x.c
ARM: PL08x: use 'size_t' for lengths
[mv-sheeva.git] / drivers / dma / amba-pl08x.c
index 69cfb05e4d3ceb1361a060d0d5b0dcda8b218d84..fa78697790c0e0fdc15482e10518728e4bd3e3c8 100644 (file)
  *
  * ASSUMES default (little) endianness for DMA transfers
  *
- * Only DMAC flow control is implemented
+ * The PL08x has two flow control settings:
+ *  - DMAC flow control: the transfer size defines the number of transfers
+ *    which occur for the current LLI entry, and the DMAC raises TC at the
+ *    end of every LLI entry.  Observed behaviour shows the DMAC listening
+ *    to both the BREQ and SREQ signals (contrary to documented),
+ *    transferring data if either is active.  The LBREQ and LSREQ signals
+ *    are ignored.
+ *
+ *  - Peripheral flow control: the transfer size is ignored (and should be
+ *    zero).  The data is transferred from the current LLI entry, until
+ *    after the final transfer signalled by LBREQ or LSREQ.  The DMAC
+ *    will then move to the next LLI entry.
+ *
+ * Only the former works sanely with scatter lists, so we only implement
+ * the DMAC flow control method.  However, peripherals which use the LBREQ
+ * and LSREQ signals (eg, MMCI) are unable to use this mode, which through
+ * these hardware restrictions prevents them from using scatter DMA.
  *
  * Global TODO:
  * - Break out common code from arch/arm/mach-s3c64xx and share
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/dmapool.h>
-#include <linux/amba/bus.h>
 #include <linux/dmaengine.h>
+#include <linux/amba/bus.h>
 #include <linux/amba/pl08x.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
 #include <asm/hardware/pl080.h>
-#include <asm/dma.h>
-#include <asm/mach/dma.h>
-#include <asm/processor.h>
-#include <asm/cacheflush.h>
 
 #define DRIVER_NAME    "pl08xdmac"
 
 /**
  * struct vendor_data - vendor-specific config parameters
  * for PL08x derivatives
- * @name: the name of this specific variant
  * @channels: the number of channels available in this variant
  * @dualmaster: whether this version supports dual AHB masters
  * or not.
  */
 struct vendor_data {
-       char *name;
        u8 channels;
        bool dualmaster;
 };
@@ -98,7 +107,7 @@ struct vendor_data {
  * An LLI struct - see PL08x TRM.  Note that next uses bit[0] as a bus bit,
  * start & end do not - their bus bit info is in cctl.
  */
-struct lli {
+struct pl08x_lli {
        dma_addr_t src;
        dma_addr_t dst;
        dma_addr_t next;
@@ -123,7 +132,7 @@ struct pl08x_driver_data {
        struct dma_device memcpy;
        void __iomem *base;
        struct amba_device *adev;
-       struct vendor_data *vd;
+       const struct vendor_data *vd;
        struct pl08x_platform_data *pd;
        struct pl08x_phy_chan *phy_chans;
        struct dma_pool *pool;
@@ -151,7 +160,7 @@ struct pl08x_driver_data {
 
 /* Maximum times we call dma_pool_alloc on this pool without freeing */
 #define PL08X_MAX_ALLOCS       0x40
-#define MAX_NUM_TSFR_LLIS      (PL08X_LLI_TSFR_SIZE/sizeof(struct lli))
+#define MAX_NUM_TSFR_LLIS      (PL08X_LLI_TSFR_SIZE/sizeof(struct pl08x_lli))
 #define PL08X_ALIGN            8
 
 static inline struct pl08x_dma_chan *to_pl08x_chan(struct dma_chan *chan)
@@ -182,11 +191,11 @@ static void pl08x_set_cregs(struct pl08x_driver_data *pl08x,
 {
        /* Wait for channel inactive */
        while (pl08x_phy_channel_busy(ch))
-               ;
+               cpu_relax();
 
        dev_vdbg(&pl08x->adev->dev,
-               "WRITE channel %d: csrc=%08x, cdst=%08x, "
-                "cctl=%08x, clli=%08x, ccfg=%08x\n",
+               "WRITE channel %d: csrc=0x%08x, cdst=0x%08x, "
+                "cctl=0x%08x, clli=0x%08x, ccfg=0x%08x\n",
                ch->id,
                ch->csrc,
                ch->cdst,
@@ -246,7 +255,7 @@ static void pl08x_enable_phy_chan(struct pl08x_driver_data *pl08x,
         * Do not access config register until channel shows as disabled
         */
        while (readl(pl08x->base + PL080_EN_CHAN) & (1 << ch->id))
-               ;
+               cpu_relax();
 
        /*
         * Do not access config register until channel shows as inactive
@@ -279,7 +288,7 @@ static void pl08x_pause_phy_chan(struct pl08x_phy_chan *ch)
 
        /* Wait for channel inactive */
        while (pl08x_phy_channel_busy(ch))
-               ;
+               cpu_relax();
 }
 
 static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch)
@@ -333,7 +342,7 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
        struct pl08x_txd *txdi = NULL;
        struct pl08x_txd *txd;
        unsigned long flags;
-       u32 bytes = 0;
+       size_t bytes = 0;
 
        spin_lock_irqsave(&plchan->lock, flags);
 
@@ -345,9 +354,9 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
         * currently active transaction.
         */
        if (ch && txd) {
-               struct lli *llis_va = txd->llis_va;
-               struct lli *llis_bus = (struct lli *) txd->llis_bus;
-               u32 clli = readl(ch->base + PL080_CH_LLI);
+               struct pl08x_lli *llis_va = txd->llis_va;
+               struct pl08x_lli *llis_bus = (struct pl08x_lli *) txd->llis_bus;
+               u32 clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2;
 
                /* First get the bytes in the current active LLI */
                bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
@@ -461,7 +470,7 @@ static inline unsigned int pl08x_get_bytes_for_cctl(unsigned int coded)
 }
 
 static inline u32 pl08x_cctl_bits(u32 cctl, u8 srcwidth, u8 dstwidth,
-                                 u32 tsize)
+                                 size_t tsize)
 {
        u32 retbits = cctl;
 
@@ -510,7 +519,7 @@ static inline u32 pl08x_cctl_bits(u32 cctl, u8 srcwidth, u8 dstwidth,
  * this prefers the destination bus if both available
  * if fixed address on one bus the other will be chosen
  */
-void pl08x_choose_master_bus(struct pl08x_bus_data *src_bus,
+static void pl08x_choose_master_bus(struct pl08x_bus_data *src_bus,
        struct pl08x_bus_data *dst_bus, struct pl08x_bus_data **mbus,
        struct pl08x_bus_data **sbus, u32 cctl)
 {
@@ -545,12 +554,12 @@ void pl08x_choose_master_bus(struct pl08x_bus_data *src_bus,
  * Fills in one LLI for a certain transfer descriptor
  * and advance the counter
  */
-int pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
+static int pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
                            struct pl08x_txd *txd, int num_llis, int len,
                            u32 cctl, u32 *remainder)
 {
-       struct lli *llis_va = txd->llis_va;
-       struct lli *llis_bus = (struct lli *) txd->llis_bus;
+       struct pl08x_lli *llis_va = txd->llis_va;
+       dma_addr_t llis_bus = txd->llis_bus;
 
        BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS);
 
@@ -567,14 +576,15 @@ int pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
         * memory. So we don't manipulate this bit currently.
         */
 
-       llis_va[num_llis].next =
-               (dma_addr_t)((u32) &(llis_bus[num_llis + 1]));
+       llis_va[num_llis].next = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli);
 
        if (cctl & PL080_CONTROL_SRC_INCR)
                txd->srcbus.addr += len;
        if (cctl & PL080_CONTROL_DST_INCR)
                txd->dstbus.addr += len;
 
+       BUG_ON(*remainder < len);
+
        *remainder -= len;
 
        return num_llis + 1;
@@ -583,7 +593,7 @@ int pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
 /*
  * Return number of bytes to fill to boundary, or len
  */
-static inline u32 pl08x_pre_boundary(u32 addr, u32 len)
+static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
 {
        u32 boundary;
 
@@ -606,18 +616,12 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 {
        struct pl08x_channel_data *cd = txd->cd;
        struct pl08x_bus_data *mbus, *sbus;
-       u32 remainder;
+       size_t remainder;
        int num_llis = 0;
        u32 cctl;
-       int max_bytes_per_lli;
-       int total_bytes = 0;
-       struct lli *llis_va;
-       struct lli *llis_bus;
-
-       if (!txd) {
-               dev_err(&pl08x->adev->dev, "%s no descriptor\n", __func__);
-               return 0;
-       }
+       size_t max_bytes_per_lli;
+       size_t total_bytes = 0;
+       struct pl08x_lli *llis_va;
 
        txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT,
                                      &txd->llis_bus);
@@ -684,13 +688,13 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
        max_bytes_per_lli = min(txd->srcbus.buswidth, txd->dstbus.buswidth) *
                PL080_CONTROL_TRANSFER_SIZE_MASK;
        dev_vdbg(&pl08x->adev->dev,
-                "%s max bytes per lli = %d\n",
+                "%s max bytes per lli = %zu\n",
                 __func__, max_bytes_per_lli);
 
        /* We need to count this down to zero */
        remainder = txd->len;
        dev_vdbg(&pl08x->adev->dev,
-                "%s remainder = %d\n",
+                "%s remainder = %zu\n",
                 __func__, remainder);
 
        /*
@@ -717,7 +721,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
                while (remainder) {
                        dev_vdbg(&pl08x->adev->dev,
                                 "%s single byte LLIs for a transfer of "
-                                "less than a bus width (remain %08x)\n",
+                                "less than a bus width (remain 0x%08x)\n",
                                 __func__, remainder);
                        cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
                        num_llis =
@@ -733,7 +737,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
                while ((mbus->addr) % (mbus->buswidth)) {
                        dev_vdbg(&pl08x->adev->dev,
                                "%s adjustment lli for less than bus width "
-                                "(remain %08x)\n",
+                                "(remain 0x%08x)\n",
                                 __func__, remainder);
                        cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
                        num_llis = pl08x_fill_lli_for_desc
@@ -758,9 +762,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
                 * width left
                 */
                while (remainder > (mbus->buswidth - 1)) {
-                       int lli_len, target_len;
-                       int tsize;
-                       int odd_bytes;
+                       size_t lli_len, target_len, tsize, odd_bytes;
 
                        /*
                         * If enough left try to send max possible,
@@ -803,7 +805,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 
                        if (lli_len <= 0) {
                                dev_err(&pl08x->adev->dev,
-                                       "%s lli_len is %d, <= 0\n",
+                                       "%s lli_len is %zu, <= 0\n",
                                                __func__, lli_len);
                                return 0;
                        }
@@ -851,7 +853,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 
                                if (target_len != lli_len) {
                                        dev_vdbg(&pl08x->adev->dev,
-                                       "%s can't send what we want. Desired %08x, lli of %08x bytes in txd of %08x\n",
+                                       "%s can't send what we want. Desired 0x%08zx, lli of 0x%08zx bytes in txd of 0x%08zx\n",
                                        __func__, target_len, lli_len, txd->len);
                                }
 
@@ -861,7 +863,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
                                                       tsize);
 
                                dev_vdbg(&pl08x->adev->dev,
-                                       "%s fill lli with single lli chunk of size %08x (remainder %08x)\n",
+                                       "%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
                                        __func__, lli_len, remainder);
                                num_llis = pl08x_fill_lli_for_desc(pl08x, txd,
                                                num_llis, lli_len, cctl,
@@ -880,7 +882,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
                                                && (remainder); j++) {
                                        cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
                                        dev_vdbg(&pl08x->adev->dev,
-                                               "%s align with boundary, single byte (remain %08x)\n",
+                                               "%s align with boundary, single byte (remain 0x%08zx)\n",
                                                __func__, remainder);
                                        num_llis =
                                                pl08x_fill_lli_for_desc(pl08x,
@@ -894,16 +896,10 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
                /*
                 * Send any odd bytes
                 */
-               if (remainder < 0) {
-                       dev_err(&pl08x->adev->dev, "%s remainder not fitted 0x%08x bytes\n",
-                                       __func__, remainder);
-                       return 0;
-               }
-
                while (remainder) {
                        cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
                        dev_vdbg(&pl08x->adev->dev,
-                               "%s align with boundary, single odd byte (remain %d)\n",
+                               "%s align with boundary, single odd byte (remain %zu)\n",
                                __func__, remainder);
                        num_llis = pl08x_fill_lli_for_desc(pl08x, txd, num_llis,
                                        1, cctl, &remainder);
@@ -912,7 +908,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
        }
        if (total_bytes != txd->len) {
                dev_err(&pl08x->adev->dev,
-                       "%s size of encoded lli:s don't match total txd, transferred 0x%08x from size 0x%08x\n",
+                       "%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
                        __func__, total_bytes, txd->len);
                return 0;
        }
@@ -923,39 +919,21 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
                        __func__, (u32) MAX_NUM_TSFR_LLIS);
                return 0;
        }
+
+       llis_va = txd->llis_va;
        /*
-        * Decide whether this is a loop or a terminated transfer
+        * The final LLI terminates the LLI.
         */
-       llis_va = txd->llis_va;
-       llis_bus = (struct lli *) txd->llis_bus;
-
-       if (cd->circular_buffer) {
-               /*
-                * Loop the circular buffer so that the next element
-                * points back to the beginning of the LLI.
-                */
-               llis_va[num_llis - 1].next =
-                       (dma_addr_t)((unsigned int)&(llis_bus[0]));
-       } else {
-               /*
-                * On non-circular buffers, the final LLI terminates
-                * the LLI.
-                */
-               llis_va[num_llis - 1].next = 0;
-               /*
-                * The final LLI element shall also fire an interrupt
-                */
-               llis_va[num_llis - 1].cctl |= PL080_CONTROL_TC_IRQ_EN;
-       }
+       llis_va[num_llis - 1].next = 0;
+       /*
+        * The final LLI element shall also fire an interrupt
+        */
+       llis_va[num_llis - 1].cctl |= PL080_CONTROL_TC_IRQ_EN;
 
        /* Now store the channel register values */
        txd->csrc = llis_va[0].src;
        txd->cdst = llis_va[0].dst;
-       if (num_llis > 1)
-               txd->clli = llis_va[0].next;
-       else
-               txd->clli = 0;
-
+       txd->clli = llis_va[0].next;
        txd->cctl = llis_va[0].cctl;
        /* ccfg will be set at physical channel allocation time */
 
@@ -965,7 +943,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 
                for (i = 0; i < num_llis; i++) {
                        dev_vdbg(&pl08x->adev->dev,
-                                "lli %d @%p: csrc=%08x, cdst=%08x, cctl=%08x, clli=%08x\n",
+                                "lli %d @%p: csrc=0x%08x, cdst=0x%08x, cctl=0x%08x, clli=0x%08x\n",
                                 i,
                                 &llis_va[i],
                                 llis_va[i].src,
@@ -984,14 +962,8 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 static void pl08x_free_txd(struct pl08x_driver_data *pl08x,
                           struct pl08x_txd *txd)
 {
-       if (!txd)
-               dev_err(&pl08x->adev->dev,
-                       "%s no descriptor to free\n",
-                       __func__);
-
        /* Free the LLI */
-       dma_pool_free(pl08x->pool, txd->llis_va,
-                     txd->llis_bus);
+       dma_pool_free(pl08x->pool, txd->llis_va, txd->llis_bus);
 
        pl08x->pool_ctr--;
 
@@ -1077,6 +1049,18 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
        return 0;
 }
 
+static void release_phy_channel(struct pl08x_dma_chan *plchan)
+{
+       struct pl08x_driver_data *pl08x = plchan->host;
+
+       if ((plchan->phychan->signal >= 0) && pl08x->pd->put_signal) {
+               pl08x->pd->put_signal(plchan);
+               plchan->phychan->signal = -1;
+       }
+       pl08x_put_phy_channel(pl08x, plchan->phychan);
+       plchan->phychan = NULL;
+}
+
 static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
 {
        struct pl08x_dma_chan *plchan = to_pl08x_chan(tx->chan);
@@ -1275,7 +1259,7 @@ static void dma_set_runtime_config(struct dma_chan *chan,
 
        dev_dbg(&pl08x->adev->dev,
                "configured channel %s (%s) for %s, data width %d, "
-               "maxburst %d words, LE, CCTL=%08x, CCFG=%08x\n",
+               "maxburst %d words, LE, CCTL=0x%08x, CCFG=0x%08x\n",
                dma_chan_name(chan), plchan->name,
                (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX",
                addr_width,
@@ -1294,15 +1278,11 @@ static void pl08x_issue_pending(struct dma_chan *chan)
        unsigned long flags;
 
        spin_lock_irqsave(&plchan->lock, flags);
-       /* Something is already active */
-       if (plchan->at) {
-                       spin_unlock_irqrestore(&plchan->lock, flags);
-                       return;
-       }
-
-       /* Didn't get a physical channel so waiting for it ... */
-       if (plchan->state == PL08X_CHAN_WAITING)
+       /* Something is already active, or we're waiting for a channel... */
+       if (plchan->at || plchan->state == PL08X_CHAN_WAITING) {
+               spin_unlock_irqrestore(&plchan->lock, flags);
                return;
+       }
 
        /* Take the first element in the queue and execute it */
        if (!list_empty(&plchan->desc_list)) {
@@ -1332,25 +1312,14 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
        int ret;
 
        num_llis = pl08x_fill_llis_for_desc(pl08x, txd);
-
-       if (!num_llis)
+       if (!num_llis) {
+               kfree(txd);
                return -EINVAL;
+       }
 
        spin_lock_irqsave(&plchan->lock, plchan->lockflags);
 
-       /*
-        * If this device is not using a circular buffer then
-        * queue this new descriptor for transfer.
-        * The descriptor for a circular buffer continues
-        * to be used until the channel is freed.
-        */
-       if (txd->cd->circular_buffer)
-               dev_err(&pl08x->adev->dev,
-                       "%s attempting to queue a circular buffer\n",
-                       __func__);
-       else
-               list_add_tail(&txd->node,
-                             &plchan->desc_list);
+       list_add_tail(&txd->node, &plchan->desc_list);
 
        /*
         * See if we already have a physical channel allocated,
@@ -1397,6 +1366,18 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
        return 0;
 }
 
+static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan)
+{
+       struct pl08x_txd *txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
+
+       if (txd) {
+               dma_async_tx_descriptor_init(&txd->tx, &plchan->chan);
+               txd->tx.tx_submit = pl08x_tx_submit;
+               INIT_LIST_HEAD(&txd->node);
+       }
+       return txd;
+}
+
 /*
  * Initialize a descriptor to be used by memcpy submit
  */
@@ -1409,14 +1390,13 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
        struct pl08x_txd *txd;
        int ret;
 
-       txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
+       txd = pl08x_get_txd(plchan);
        if (!txd) {
                dev_err(&pl08x->adev->dev,
                        "%s no memory for descriptor\n", __func__);
                return NULL;
        }
 
-       dma_async_tx_descriptor_init(&txd->tx, chan);
        txd->direction = DMA_NONE;
        txd->srcbus.addr = src;
        txd->dstbus.addr = dest;
@@ -1425,12 +1405,8 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
        txd->cd = &pl08x->pd->memcpy_channel;
        /* Both to be incremented or the code will break */
        txd->cd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR;
-       txd->tx.tx_submit = pl08x_tx_submit;
-       txd->tx.callback = NULL;
-       txd->tx.callback_param = NULL;
        txd->len = len;
 
-       INIT_LIST_HEAD(&txd->node);
        ret = pl08x_prep_channel_resources(plchan, txd);
        if (ret)
                return NULL;
@@ -1442,7 +1418,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
        return &txd->tx;
 }
 
-struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
+static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_data_direction direction,
                unsigned long flags)
@@ -1464,14 +1440,12 @@ struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
        dev_dbg(&pl08x->adev->dev, "%s prepare transaction of %d bytes from %s\n",
                __func__, sgl->length, plchan->name);
 
-       txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
+       txd = pl08x_get_txd(plchan);
        if (!txd) {
                dev_err(&pl08x->adev->dev, "%s no txd\n", __func__);
                return NULL;
        }
 
-       dma_async_tx_descriptor_init(&txd->tx, chan);
-
        if (direction != plchan->runtime_direction)
                dev_err(&pl08x->adev->dev, "%s DMA setup does not match "
                        "the direction configured for the PrimeCell\n",
@@ -1501,11 +1475,7 @@ struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
                return NULL;
        }
        txd->cd = plchan->cd;
-       txd->tx.tx_submit = pl08x_tx_submit;
-       txd->tx.callback = NULL;
-       txd->tx.callback_param = NULL;
        txd->len = sgl->length;
-       INIT_LIST_HEAD(&txd->node);
 
        ret = pl08x_prep_channel_resources(plchan, txd);
        if (ret)
@@ -1555,16 +1525,8 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                         * Mark physical channel as free and free any slave
                         * signal
                         */
-                       if ((plchan->phychan->signal >= 0) &&
-                           pl08x->pd->put_signal) {
-                               pl08x->pd->put_signal(plchan);
-                               plchan->phychan->signal = -1;
-                       }
-                       pl08x_put_phy_channel(pl08x, plchan->phychan);
-                       plchan->phychan = NULL;
+                       release_phy_channel(plchan);
                }
-               /* Stop any pending tasklet */
-               tasklet_disable(&plchan->tasklet);
                /* Dequeue jobs and free LLIs */
                if (plchan->at) {
                        pl08x_free_txd(pl08x, plchan->at);
@@ -1625,13 +1587,9 @@ static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
 static void pl08x_tasklet(unsigned long data)
 {
        struct pl08x_dma_chan *plchan = (struct pl08x_dma_chan *) data;
-       struct pl08x_phy_chan *phychan = plchan->phychan;
        struct pl08x_driver_data *pl08x = plchan->host;
        unsigned long flags;
 
-       if (!plchan)
-               BUG();
-
        spin_lock_irqsave(&plchan->lock, flags);
 
        if (plchan->at) {
@@ -1652,26 +1610,10 @@ static void pl08x_tasklet(unsigned long data)
                        callback(callback_param);
 
                /*
-                * Device callbacks should NOT clear
-                * the current transaction on the channel
-                * Linus: sometimes they should?
-                */
-               if (!plchan->at)
-                       BUG();
-
-               /*
-                * Free the descriptor if it's not for a device
-                * using a circular buffer
-                */
-               if (!plchan->at->cd->circular_buffer) {
-                       pl08x_free_txd(pl08x, plchan->at);
-                       plchan->at = NULL;
-               }
-               /*
-                * else descriptor for circular
-                * buffers only freed when
-                * client has disabled dma
+                * Free the descriptor
                 */
+               pl08x_free_txd(pl08x, plchan->at);
+               plchan->at = NULL;
        }
        /*
         * If a new descriptor is queued, set it up
@@ -1696,12 +1638,7 @@ static void pl08x_tasklet(unsigned long data)
                 * No more jobs, so free up the physical channel
                 * Free any allocated signal on slave transfers too
                 */
-               if ((phychan->signal >= 0) && pl08x->pd->put_signal) {
-                       pl08x->pd->put_signal(plchan);
-                       phychan->signal = -1;
-               }
-               pl08x_put_phy_channel(pl08x, phychan);
-               plchan->phychan = NULL;
+               release_phy_channel(plchan);
                plchan->state = PL08X_CHAN_IDLE;
 
                /*
@@ -1816,6 +1753,13 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
                                return -ENOMEM;
                        }
                }
+               if (chan->cd->circular_buffer) {
+                       dev_err(&pl08x->adev->dev,
+                               "channel %s: circular buffers not supported\n",
+                               chan->name);
+                       kfree(chan);
+                       continue;
+               }
                dev_info(&pl08x->adev->dev,
                         "initialize virtual channel \"%s\"\n",
                         chan->name);
@@ -1895,7 +1839,7 @@ static int pl08x_debugfs_show(struct seq_file *s, void *data)
        seq_printf(s, "CHANNEL:\tSTATE:\n");
        seq_printf(s, "--------\t------\n");
        list_for_each_entry(chan, &pl08x->memcpy.channels, chan.device_node) {
-               seq_printf(s, "%s\t\t\%s\n", chan->name,
+               seq_printf(s, "%s\t\t%s\n", chan->name,
                           pl08x_state_str(chan->state));
        }
 
@@ -1903,7 +1847,7 @@ static int pl08x_debugfs_show(struct seq_file *s, void *data)
        seq_printf(s, "CHANNEL:\tSTATE:\n");
        seq_printf(s, "--------\t------\n");
        list_for_each_entry(chan, &pl08x->slave.channels, chan.device_node) {
-               seq_printf(s, "%s\t\t\%s\n", chan->name,
+               seq_printf(s, "%s\t\t%s\n", chan->name,
                           pl08x_state_str(chan->state));
        }
 
@@ -1939,7 +1883,7 @@ static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
 static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
 {
        struct pl08x_driver_data *pl08x;
-       struct vendor_data *vd = id->data;
+       const struct vendor_data *vd = id->data;
        int ret = 0;
        int i;
 
@@ -2013,7 +1957,7 @@ static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
        writel(0x000000FF, pl08x->base + PL080_TC_CLEAR);
 
        ret = request_irq(adev->irq[0], pl08x_irq, IRQF_DISABLED,
-                         vd->name, pl08x);
+                         DRIVER_NAME, pl08x);
        if (ret) {
                dev_err(&adev->dev, "%s failed to request interrupt %d\n",
                        __func__, adev->irq[0]);
@@ -2084,8 +2028,9 @@ static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
 
        amba_set_drvdata(adev, pl08x);
        init_pl08x_debugfs(pl08x);
-       dev_info(&pl08x->adev->dev, "ARM(R) %s DMA block initialized @%08x\n",
-               vd->name, adev->res.start);
+       dev_info(&pl08x->adev->dev, "DMA: PL%03x rev%u at 0x%08llx irq %d\n",
+                amba_part(adev), amba_rev(adev),
+                (unsigned long long)adev->res.start, adev->irq[0]);
        return 0;
 
 out_no_slave_reg:
@@ -2112,13 +2057,11 @@ out_no_pl08x:
 
 /* PL080 has 8 channels and the PL080 have just 2 */
 static struct vendor_data vendor_pl080 = {
-       .name = "PL080",
        .channels = 8,
        .dualmaster = true,
 };
 
 static struct vendor_data vendor_pl081 = {
-       .name = "PL081",
        .channels = 2,
        .dualmaster = false,
 };