Merge tag 'dmaengine-4.4-rc1' of git://git.infradead.org/users/vkoul/slave-dma
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Nov 2015 18:05:17 +0000 (10:05 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Nov 2015 18:05:17 +0000 (10:05 -0800)
Pull dmaengine updates from Vinod Koul:
 "This time we have a very typical update which is mostly fixes and
  updates to drivers and no new drivers.

   - the biggest change is coming from Peter for edma cleanup which even
     caused some last minute regression, things seem settled now
   - idma64 and dw updates
   - iotdma updates
   - module autoload fixes for various drivers
   - scatter gather support for hdmac"

* tag 'dmaengine-4.4-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (77 commits)
  dmaengine: edma: Add dummy driver skeleton for edma3-tptc
  Revert "ARM: DTS: am33xx: Use the new DT bindings for the eDMA3"
  Revert "ARM: DTS: am437x: Use the new DT bindings for the eDMA3"
  dmaengine: dw: some Intel devices has no memcpy support
  dmaengine: dw: platform: provide platform data for Intel
  dmaengine: dw: don't override platform data with autocfg
  dmaengine: hdmac: Add scatter-gathered memset support
  dmaengine: hdmac: factorise memset descriptor allocation
  dmaengine: virt-dma: Fix kernel-doc annotations
  ARM: DTS: am437x: Use the new DT bindings for the eDMA3
  ARM: DTS: am33xx: Use the new DT bindings for the eDMA3
  dmaengine: edma: New device tree binding
  dmaengine: Kconfig: edma: Select TI_DMA_CROSSBAR in case of ARCH_OMAP
  dmaengine: ti-dma-crossbar: Add support for crossbar on AM33xx/AM43xx
  dmaengine: edma: Merge the of parsing functions
  dmaengine: edma: Do not allocate memory for edma_rsv_info in case of DT boot
  dmaengine: edma: Refactor the dma device and channel struct initialization
  dmaengine: edma: Get qDMA channel information from HW also
  dmaengine: edma: Merge map_dmach_to_queue into assign_channel_eventq
  dmaengine: edma: Correct PaRAM access function names (_parm_ to _param_)
  ...

1  2 
arch/arm/Kconfig
arch/arm/mach-omap2/Kconfig
drivers/dma/acpi-dma.c
drivers/dma/at_xdmac.c
drivers/dma/dmaengine.c
drivers/dma/dw/core.c
drivers/dma/idma64.c
drivers/dma/xgene-dma.c
drivers/dma/zx296702_dma.c

diff --combined arch/arm/Kconfig
@@@ -645,7 -645,6 +645,7 @@@ config ARCH_SHMOBILE_LEGAC
  
  config ARCH_RPC
        bool "RiscPC"
 +      depends on MMU
        select ARCH_ACORN
        select ARCH_MAY_HAVE_PC_FDC
        select ARCH_SPARSEMEM_ENABLE
@@@ -737,7 -736,6 +737,6 @@@ config ARCH_DAVINC
        select GENERIC_CLOCKEVENTS
        select GENERIC_IRQ_CHIP
        select HAVE_IDE
-       select TI_PRIV_EDMA
        select USE_OF
        select ZONE_DMA
        help
@@@ -820,7 -818,6 +819,7 @@@ config ARCH_VIR
        bool "Dummy Virtual Machine" if ARCH_MULTI_V7
        select ARM_AMBA
        select ARM_GIC
 +      select ARM_GIC_V3
        select ARM_PSCI
        select HAVE_ARM_ARCH_TIMER
  
@@@ -1412,6 -1409,7 +1411,6 @@@ config HAVE_ARM_ARCH_TIME
  
  config HAVE_ARM_TWD
        bool
 -      depends on SMP
        select CLKSRC_OF if OF
        help
          This options enables support for the ARM timer and watchdog unit
@@@ -1471,8 -1469,6 +1470,8 @@@ choic
  
        config VMSPLIT_3G
                bool "3G/1G user/kernel split"
 +      config VMSPLIT_3G_OPT
 +              bool "3G/1G user/kernel split (for full 1G low memory)"
        config VMSPLIT_2G
                bool "2G/2G user/kernel split"
        config VMSPLIT_1G
@@@ -1484,7 -1480,6 +1483,7 @@@ config PAGE_OFFSE
        default PHYS_OFFSET if !MMU
        default 0x40000000 if VMSPLIT_1G
        default 0x80000000 if VMSPLIT_2G
 +      default 0xB0000000 if VMSPLIT_3G_OPT
        default 0xC0000000
  
  config NR_CPUS
@@@ -1699,9 -1694,8 +1698,9 @@@ config HIGHME
          If unsure, say n.
  
  config HIGHPTE
 -      bool "Allocate 2nd-level pagetables from highmem"
 +      bool "Allocate 2nd-level pagetables from highmem" if EXPERT
        depends on HIGHMEM
 +      default y
        help
          The VM uses one page of physical memory for each page table.
          For systems with a lot of processes, this can use a lot of
@@@ -44,12 -44,10 +44,12 @@@ config SOC_OMAP
        select ARM_CPU_SUSPEND if PM
        select ARM_GIC
        select HAVE_ARM_SCU if SMP
 -      select HAVE_ARM_TWD if SMP
        select HAVE_ARM_ARCH_TIMER
        select ARM_ERRATA_798181 if SMP
 +      select OMAP_INTERCONNECT
        select OMAP_INTERCONNECT_BARRIER
 +      select PM_OPP if PM
 +      select ZONE_DMA if ARM_LPAE
  
  config SOC_AM33XX
        bool "TI AM33XX"
@@@ -72,14 -70,10 +72,14 @@@ config SOC_DRA7X
        select ARCH_OMAP2PLUS
        select ARM_CPU_SUSPEND if PM
        select ARM_GIC
 +      select HAVE_ARM_SCU if SMP
        select HAVE_ARM_ARCH_TIMER
        select IRQ_CROSSBAR
        select ARM_ERRATA_798181 if SMP
 +      select OMAP_INTERCONNECT
        select OMAP_INTERCONNECT_BARRIER
 +      select PM_OPP if PM
 +      select ZONE_DMA if ARM_LPAE
  
  config ARCH_OMAP2PLUS
        bool
@@@ -96,7 -90,6 +96,6 @@@
        select OMAP_GPMC
        select PINCTRL
        select SOC_BUS
-       select TI_PRIV_EDMA
        select OMAP_IRQCHIP
        help
          Systems based on OMAP2, OMAP3, OMAP4 or OMAP5
diff --combined drivers/dma/acpi-dma.c
@@@ -21,7 -21,6 +21,7 @@@
  #include <linux/ioport.h>
  #include <linux/acpi.h>
  #include <linux/acpi_dma.h>
 +#include <linux/property.h>
  
  static LIST_HEAD(acpi_dma_list);
  static DEFINE_MUTEX(acpi_dma_lock);
@@@ -161,10 -160,8 +161,8 @@@ int acpi_dma_controller_register(struc
                return -EINVAL;
  
        /* Check if the device was enumerated by ACPI */
-       if (!ACPI_HANDLE(dev))
-               return -EINVAL;
-       if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev))
+       adev = ACPI_COMPANION(dev);
+       if (!adev)
                return -EINVAL;
  
        adma = kzalloc(sizeof(*adma), GFP_KERNEL);
@@@ -359,10 -356,11 +357,11 @@@ struct dma_chan *acpi_dma_request_slave
        int found;
  
        /* Check if the device was enumerated by ACPI */
-       if (!dev || !ACPI_HANDLE(dev))
+       if (!dev)
                return ERR_PTR(-ENODEV);
  
-       if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev))
+       adev = ACPI_COMPANION(dev);
+       if (!adev)
                return ERR_PTR(-ENODEV);
  
        memset(&pdata, 0, sizeof(pdata));
@@@ -414,29 -412,21 +413,29 @@@ EXPORT_SYMBOL_GPL(acpi_dma_request_slav
   * translate the names "tx" and "rx" here based on the most common case where
   * the first FixedDMA descriptor is TX and second is RX.
   *
 + * If the device has "dma-names" property the FixedDMA descriptor indices
 + * are retrieved based on those. Otherwise the function falls back using
 + * hardcoded indices.
 + *
   * Return:
   * Pointer to appropriate dma channel on success or an error pointer.
   */
  struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev,
                const char *name)
  {
 -      size_t index;
 -
 -      if (!strcmp(name, "tx"))
 -              index = 0;
 -      else if (!strcmp(name, "rx"))
 -              index = 1;
 -      else
 -              return ERR_PTR(-ENODEV);
 +      int index;
 +
 +      index = device_property_match_string(dev, "dma-names", name);
 +      if (index < 0) {
 +              if (!strcmp(name, "tx"))
 +                      index = 0;
 +              else if (!strcmp(name, "rx"))
 +                      index = 1;
 +              else
 +                      return ERR_PTR(-ENODEV);
 +      }
  
 +      dev_dbg(dev, "found DMA channel \"%s\" at index %d\n", name, index);
        return acpi_dma_request_slave_chan_by_index(dev, index);
  }
  EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name);
diff --combined drivers/dma/at_xdmac.c
@@@ -455,15 -455,6 +455,15 @@@ static struct at_xdmac_desc *at_xdmac_a
        return desc;
  }
  
 +void at_xdmac_init_used_desc(struct at_xdmac_desc *desc)
 +{
 +      memset(&desc->lld, 0, sizeof(desc->lld));
 +      INIT_LIST_HEAD(&desc->descs_list);
 +      desc->direction = DMA_TRANS_NONE;
 +      desc->xfer_size = 0;
 +      desc->active_xfer = false;
 +}
 +
  /* Call must be protected by lock. */
  static struct at_xdmac_desc *at_xdmac_get_desc(struct at_xdmac_chan *atchan)
  {
                desc = list_first_entry(&atchan->free_descs_list,
                                        struct at_xdmac_desc, desc_node);
                list_del(&desc->desc_node);
 -              desc->active_xfer = false;
 +              at_xdmac_init_used_desc(desc);
        }
  
        return desc;
@@@ -884,14 -875,14 +884,14 @@@ at_xdmac_interleaved_queue_desc(struct 
  
        if (xt->src_inc) {
                if (xt->src_sgl)
 -                      chan_cc |=  AT_XDMAC_CC_SAM_UBS_DS_AM;
 +                      chan_cc |=  AT_XDMAC_CC_SAM_UBS_AM;
                else
                        chan_cc |=  AT_XDMAC_CC_SAM_INCREMENTED_AM;
        }
  
        if (xt->dst_inc) {
                if (xt->dst_sgl)
 -                      chan_cc |=  AT_XDMAC_CC_DAM_UBS_DS_AM;
 +                      chan_cc |=  AT_XDMAC_CC_DAM_UBS_AM;
                else
                        chan_cc |=  AT_XDMAC_CC_DAM_INCREMENTED_AM;
        }
@@@ -938,13 -929,19 +938,19 @@@ at_xdmac_prep_interleaved(struct dma_ch
  {
        struct at_xdmac_chan    *atchan = to_at_xdmac_chan(chan);
        struct at_xdmac_desc    *prev = NULL, *first = NULL;
-       struct data_chunk       *chunk, *prev_chunk = NULL;
        dma_addr_t              dst_addr, src_addr;
-       size_t                  dst_skip, src_skip, len = 0;
-       size_t                  prev_dst_icg = 0, prev_src_icg = 0;
+       size_t                  src_skip = 0, dst_skip = 0, len = 0;
+       struct data_chunk       *chunk;
        int                     i;
  
-       if (!xt || (xt->numf != 1) || (xt->dir != DMA_MEM_TO_MEM))
+       if (!xt || !xt->numf || (xt->dir != DMA_MEM_TO_MEM))
+               return NULL;
+       /*
+        * TODO: Handle the case where we have to repeat a chain of
+        * descriptors...
+        */
+       if ((xt->numf > 1) && (xt->frame_size > 1))
                return NULL;
  
        dev_dbg(chan2dev(chan), "%s: src=0x%08x, dest=0x%08x, numf=%d, frame_size=%d, flags=0x%lx\n",
        src_addr = xt->src_start;
        dst_addr = xt->dst_start;
  
-       for (i = 0; i < xt->frame_size; i++) {
-               struct at_xdmac_desc *desc;
-               size_t src_icg, dst_icg;
+       if (xt->numf > 1) {
+               first = at_xdmac_interleaved_queue_desc(chan, atchan,
+                                                       NULL,
+                                                       src_addr, dst_addr,
+                                                       xt, xt->sgl);
+               for (i = 0; i < xt->numf; i++)
+                       at_xdmac_increment_block_count(chan, first);
+               dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
+                       __func__, first, first);
+               list_add_tail(&first->desc_node, &first->descs_list);
+       } else {
+               for (i = 0; i < xt->frame_size; i++) {
+                       size_t src_icg = 0, dst_icg = 0;
+                       struct at_xdmac_desc *desc;
  
-               chunk = xt->sgl + i;
+                       chunk = xt->sgl + i;
  
-               dst_icg = dmaengine_get_dst_icg(xt, chunk);
-               src_icg = dmaengine_get_src_icg(xt, chunk);
+                       dst_icg = dmaengine_get_dst_icg(xt, chunk);
+                       src_icg = dmaengine_get_src_icg(xt, chunk);
  
-               src_skip = chunk->size + src_icg;
-               dst_skip = chunk->size + dst_icg;
+                       src_skip = chunk->size + src_icg;
+                       dst_skip = chunk->size + dst_icg;
  
-               dev_dbg(chan2dev(chan),
-                       "%s: chunk size=%d, src icg=%d, dst icg=%d\n",
-                       __func__, chunk->size, src_icg, dst_icg);
-               /*
-                * Handle the case where we just have the same
-                * transfer to setup, we can just increase the
-                * block number and reuse the same descriptor.
-                */
-               if (prev_chunk && prev &&
-                   (prev_chunk->size == chunk->size) &&
-                   (prev_src_icg == src_icg) &&
-                   (prev_dst_icg == dst_icg)) {
                        dev_dbg(chan2dev(chan),
-                               "%s: same configuration that the previous chunk, merging the descriptors...\n",
-                               __func__);
-                       at_xdmac_increment_block_count(chan, prev);
-                       continue;
-               }
-               desc = at_xdmac_interleaved_queue_desc(chan, atchan,
-                                                      prev,
-                                                      src_addr, dst_addr,
-                                                      xt, chunk);
-               if (!desc) {
-                       list_splice_init(&first->descs_list,
-                                        &atchan->free_descs_list);
-                       return NULL;
+                               "%s: chunk size=%d, src icg=%d, dst icg=%d\n",
+                               __func__, chunk->size, src_icg, dst_icg);
+                       desc = at_xdmac_interleaved_queue_desc(chan, atchan,
+                                                              prev,
+                                                              src_addr, dst_addr,
+                                                              xt, chunk);
+                       if (!desc) {
+                               list_splice_init(&first->descs_list,
+                                                &atchan->free_descs_list);
+                               return NULL;
+                       }
+                       if (!first)
+                               first = desc;
+                       dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
+                               __func__, desc, first);
+                       list_add_tail(&desc->desc_node, &first->descs_list);
+                       if (xt->src_sgl)
+                               src_addr += src_skip;
+                       if (xt->dst_sgl)
+                               dst_addr += dst_skip;
+                       len += chunk->size;
+                       prev = desc;
                }
-               if (!first)
-                       first = desc;
-               dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
-                       __func__, desc, first);
-               list_add_tail(&desc->desc_node, &first->descs_list);
-               if (xt->src_sgl)
-                       src_addr += src_skip;
-               if (xt->dst_sgl)
-                       dst_addr += dst_skip;
-               len += chunk->size;
-               prev_chunk = chunk;
-               prev_dst_icg = dst_icg;
-               prev_src_icg = src_icg;
-               prev = desc;
        }
  
        first->tx_dma_desc.cookie = -EBUSY;
diff --combined drivers/dma/dmaengine.c
@@@ -554,18 -554,10 +554,18 @@@ struct dma_chan *dma_get_slave_channel(
        mutex_lock(&dma_list_mutex);
  
        if (chan->client_count == 0) {
 +              struct dma_device *device = chan->device;
 +
 +              dma_cap_set(DMA_PRIVATE, device->cap_mask);
 +              device->privatecnt++;
                err = dma_chan_get(chan);
 -              if (err)
 +              if (err) {
                        pr_debug("%s: failed to get %s: (%d)\n",
                                __func__, dma_chan_name(chan), err);
 +                      chan = NULL;
 +                      if (--device->privatecnt == 0)
 +                              dma_cap_clear(DMA_PRIVATE, device->cap_mask);
 +              }
        } else
                chan = NULL;
  
@@@ -1074,11 -1066,9 +1074,9 @@@ static void dmaengine_destroy_unmap_poo
        for (i = 0; i < ARRAY_SIZE(unmap_pool); i++) {
                struct dmaengine_unmap_pool *p = &unmap_pool[i];
  
-               if (p->pool)
-                       mempool_destroy(p->pool);
+               mempool_destroy(p->pool);
                p->pool = NULL;
-               if (p->cache)
-                       kmem_cache_destroy(p->cache);
+               kmem_cache_destroy(p->cache);
                p->cache = NULL;
        }
  }
diff --combined drivers/dma/dw/core.c
@@@ -163,7 -163,7 +163,7 @@@ static void dwc_initialize(struct dw_dm
  
  /*----------------------------------------------------------------------*/
  
- static inline unsigned int dwc_fast_fls(unsigned long long v)
+ static inline unsigned int dwc_fast_ffs(unsigned long long v)
  {
        /*
         * We can be a lot more clever here, but this should take care
@@@ -712,7 -712,7 +712,7 @@@ dwc_prep_dma_memcpy(struct dma_chan *ch
                           dw->data_width[dwc->dst_master]);
  
        src_width = dst_width = min_t(unsigned int, data_width,
-                                     dwc_fast_fls(src | dest | len));
+                                     dwc_fast_ffs(src | dest | len));
  
        ctllo = DWC_DEFAULT_CTLLO(chan)
                        | DWC_CTLL_DST_WIDTH(dst_width)
@@@ -791,7 -791,7 +791,7 @@@ dwc_prep_slave_sg(struct dma_chan *chan
  
        switch (direction) {
        case DMA_MEM_TO_DEV:
-               reg_width = __fls(sconfig->dst_addr_width);
+               reg_width = __ffs(sconfig->dst_addr_width);
                reg = sconfig->dst_addr;
                ctllo = (DWC_DEFAULT_CTLLO(chan)
                                | DWC_CTLL_DST_WIDTH(reg_width)
                        len = sg_dma_len(sg);
  
                        mem_width = min_t(unsigned int,
-                                         data_width, dwc_fast_fls(mem | len));
+                                         data_width, dwc_fast_ffs(mem | len));
  
  slave_sg_todev_fill_desc:
                        desc = dwc_desc_get(dwc);
                }
                break;
        case DMA_DEV_TO_MEM:
-               reg_width = __fls(sconfig->src_addr_width);
+               reg_width = __ffs(sconfig->src_addr_width);
                reg = sconfig->src_addr;
                ctllo = (DWC_DEFAULT_CTLLO(chan)
                                | DWC_CTLL_SRC_WIDTH(reg_width)
                        len = sg_dma_len(sg);
  
                        mem_width = min_t(unsigned int,
-                                         data_width, dwc_fast_fls(mem | len));
+                                         data_width, dwc_fast_ffs(mem | len));
  
  slave_sg_fromdev_fill_desc:
                        desc = dwc_desc_get(dwc);
@@@ -1499,9 -1499,8 +1499,8 @@@ EXPORT_SYMBOL(dw_dma_cyclic_free)
  int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
  {
        struct dw_dma           *dw;
-       bool                    autocfg;
+       bool                    autocfg = false;
        unsigned int            dw_params;
-       unsigned int            nr_channels;
        unsigned int            max_blk_size = 0;
        int                     err;
        int                     i;
  
        pm_runtime_get_sync(chip->dev);
  
-       dw_params = dma_read_byaddr(chip->regs, DW_PARAMS);
-       autocfg = dw_params >> DW_PARAMS_EN & 0x1;
+       if (!pdata) {
+               dw_params = dma_read_byaddr(chip->regs, DW_PARAMS);
+               dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params);
  
-       dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params);
+               autocfg = dw_params >> DW_PARAMS_EN & 1;
+               if (!autocfg) {
+                       err = -EINVAL;
+                       goto err_pdata;
+               }
  
-       if (!pdata && autocfg) {
                pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
                if (!pdata) {
                        err = -ENOMEM;
                        goto err_pdata;
                }
  
+               /* Get hardware configuration parameters */
+               pdata->nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 7) + 1;
+               pdata->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1;
+               for (i = 0; i < pdata->nr_masters; i++) {
+                       pdata->data_width[i] =
+                               (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2;
+               }
+               max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
                /* Fill platform data with the default values */
                pdata->is_private = true;
+               pdata->is_memcpy = true;
                pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING;
                pdata->chan_priority = CHAN_PRIORITY_ASCENDING;
-       } else if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) {
+       } else if (pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) {
                err = -EINVAL;
                goto err_pdata;
        }
  
-       if (autocfg)
-               nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1;
-       else
-               nr_channels = pdata->nr_channels;
-       dw->chan = devm_kcalloc(chip->dev, nr_channels, sizeof(*dw->chan),
+       dw->chan = devm_kcalloc(chip->dev, pdata->nr_channels, sizeof(*dw->chan),
                                GFP_KERNEL);
        if (!dw->chan) {
                err = -ENOMEM;
        }
  
        /* Get hardware configuration parameters */
-       if (autocfg) {
-               max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
-               dw->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1;
-               for (i = 0; i < dw->nr_masters; i++) {
-                       dw->data_width[i] =
-                               (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2;
-               }
-       } else {
-               dw->nr_masters = pdata->nr_masters;
-               for (i = 0; i < dw->nr_masters; i++)
-                       dw->data_width[i] = pdata->data_width[i];
-       }
+       dw->nr_masters = pdata->nr_masters;
+       for (i = 0; i < dw->nr_masters; i++)
+               dw->data_width[i] = pdata->data_width[i];
  
        /* Calculate all channel mask before DMA setup */
-       dw->all_chan_mask = (1 << nr_channels) - 1;
+       dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
  
        /* Force dma off, just in case */
        dw_dma_off(dw);
                goto err_pdata;
  
        INIT_LIST_HEAD(&dw->dma.channels);
-       for (i = 0; i < nr_channels; i++) {
+       for (i = 0; i < pdata->nr_channels; i++) {
                struct dw_dma_chan      *dwc = &dw->chan[i];
 -              int                     r = nr_channels - i - 1;
  
                dwc->chan.device = &dw->dma;
                dma_cookie_init(&dwc->chan);
  
                /* 7 is highest priority & 0 is lowest. */
                if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
-                       dwc->priority = nr_channels - i - 1;
+                       dwc->priority = pdata->nr_channels - i - 1;
                else
                        dwc->priority = i;
  
                /* Hardware configuration */
                if (autocfg) {
                        unsigned int dwc_params;
 +                      unsigned int r = DW_DMA_MAX_NR_CHANNELS - i - 1;
                        void __iomem *addr = chip->regs + r * sizeof(u32);
  
                        dwc_params = dma_read_byaddr(addr, DWC_PARAMS);
        dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask);
        dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask);
  
-       dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
+       /* Set capabilities */
        dma_cap_set(DMA_SLAVE, dw->dma.cap_mask);
        if (pdata->is_private)
                dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask);
+       if (pdata->is_memcpy)
+               dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
        dw->dma.dev = chip->dev;
        dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources;
        dw->dma.device_free_chan_resources = dwc_free_chan_resources;
                goto err_dma_register;
  
        dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n",
-                nr_channels);
+                pdata->nr_channels);
  
        pm_runtime_put_sync_suspend(chip->dev);
  
diff --combined drivers/dma/idma64.c
@@@ -65,9 -65,6 +65,6 @@@ static void idma64_chan_init(struct idm
        u32 cfghi = IDMA64C_CFGH_SRC_PER(1) | IDMA64C_CFGH_DST_PER(0);
        u32 cfglo = 0;
  
-       /* Enforce FIFO drain when channel is suspended */
-       cfglo |= IDMA64C_CFGL_CH_DRAIN;
        /* Set default burst alignment */
        cfglo |= IDMA64C_CFGL_DST_BURST_ALIGN | IDMA64C_CFGL_SRC_BURST_ALIGN;
  
@@@ -257,15 -254,15 +254,15 @@@ static u64 idma64_hw_desc_fill(struct i
                dar = config->dst_addr;
                ctllo |= IDMA64C_CTLL_DST_FIX | IDMA64C_CTLL_SRC_INC |
                         IDMA64C_CTLL_FC_M2P;
-               src_width = min_t(u32, 2, __fls(sar | hw->len));
-               dst_width = __fls(config->dst_addr_width);
+               src_width = __ffs(sar | hw->len | 4);
+               dst_width = __ffs(config->dst_addr_width);
        } else {        /* DMA_DEV_TO_MEM */
                sar = config->src_addr;
                dar = hw->phys;
                ctllo |= IDMA64C_CTLL_DST_INC | IDMA64C_CTLL_SRC_FIX |
                         IDMA64C_CTLL_FC_P2M;
-               src_width = __fls(config->src_addr_width);
-               dst_width = min_t(u32, 2, __fls(dar | hw->len));
+               src_width = __ffs(config->src_addr_width);
+               dst_width = __ffs(dar | hw->len | 4);
        }
  
        lli->sar = sar;
@@@ -355,23 -352,23 +352,23 @@@ static size_t idma64_active_desc_size(s
        struct idma64_desc *desc = idma64c->desc;
        struct idma64_hw_desc *hw;
        size_t bytes = desc->length;
 -      u64 llp;
 -      u32 ctlhi;
 +      u64 llp = channel_readq(idma64c, LLP);
 +      u32 ctlhi = channel_readl(idma64c, CTL_HI);
        unsigned int i = 0;
  
 -      llp = channel_readq(idma64c, LLP);
        do {
                hw = &desc->hw[i];
 -      } while ((hw->llp != llp) && (++i < desc->ndesc));
 +              if (hw->llp == llp)
 +                      break;
 +              bytes -= hw->len;
 +      } while (++i < desc->ndesc);
  
        if (!i)
                return bytes;
  
 -      do {
 -              bytes -= desc->hw[--i].len;
 -      } while (i);
 +      /* The current chunk is not fully transfered yet */
 +      bytes += desc->hw[--i].len;
  
 -      ctlhi = channel_readl(idma64c, CTL_HI);
        return bytes - IDMA64C_CTLH_BLOCK_TS(ctlhi);
  }
  
@@@ -428,12 -425,17 +425,17 @@@ static int idma64_slave_config(struct d
        return 0;
  }
  
- static void idma64_chan_deactivate(struct idma64_chan *idma64c)
+ static void idma64_chan_deactivate(struct idma64_chan *idma64c, bool drain)
  {
        unsigned short count = 100;
        u32 cfglo;
  
        cfglo = channel_readl(idma64c, CFG_LO);
+       if (drain)
+               cfglo |= IDMA64C_CFGL_CH_DRAIN;
+       else
+               cfglo &= ~IDMA64C_CFGL_CH_DRAIN;
        channel_writel(idma64c, CFG_LO, cfglo | IDMA64C_CFGL_CH_SUSP);
        do {
                udelay(1);
@@@ -456,7 -458,7 +458,7 @@@ static int idma64_pause(struct dma_cha
  
        spin_lock_irqsave(&idma64c->vchan.lock, flags);
        if (idma64c->desc && idma64c->desc->status == DMA_IN_PROGRESS) {
-               idma64_chan_deactivate(idma64c);
+               idma64_chan_deactivate(idma64c, false);
                idma64c->desc->status = DMA_PAUSED;
        }
        spin_unlock_irqrestore(&idma64c->vchan.lock, flags);
@@@ -486,7 -488,7 +488,7 @@@ static int idma64_terminate_all(struct 
        LIST_HEAD(head);
  
        spin_lock_irqsave(&idma64c->vchan.lock, flags);
-       idma64_chan_deactivate(idma64c);
+       idma64_chan_deactivate(idma64c, true);
        idma64_stop_transfer(idma64c);
        if (idma64c->desc) {
                idma64_vdesc_free(&idma64c->desc->vdesc);
diff --combined drivers/dma/xgene-dma.c
@@@ -59,6 -59,7 +59,6 @@@
  #define XGENE_DMA_RING_MEM_RAM_SHUTDOWN               0xD070
  #define XGENE_DMA_RING_BLK_MEM_RDY            0xD074
  #define XGENE_DMA_RING_BLK_MEM_RDY_VAL                0xFFFFFFFF
 -#define XGENE_DMA_RING_DESC_CNT(v)            (((v) & 0x0001FFFE) >> 1)
  #define XGENE_DMA_RING_ID_GET(owner, num)     (((owner) << 6) | (num))
  #define XGENE_DMA_RING_DST_ID(v)              ((1 << 10) | (v))
  #define XGENE_DMA_RING_CMD_OFFSET             0x2C
@@@ -378,6 -379,14 +378,6 @@@ static u8 xgene_dma_encode_xor_flyby(u3
        return flyby_type[src_cnt];
  }
  
 -static u32 xgene_dma_ring_desc_cnt(struct xgene_dma_ring *ring)
 -{
 -      u32 __iomem *cmd_base = ring->cmd_base;
 -      u32 ring_state = ioread32(&cmd_base[1]);
 -
 -      return XGENE_DMA_RING_DESC_CNT(ring_state);
 -}
 -
  static void xgene_dma_set_src_buffer(__le64 *ext8, size_t *len,
                                     dma_addr_t *paddr)
  {
@@@ -547,14 -556,12 +547,12 @@@ static struct xgene_dma_desc_sw *xgene_
        struct xgene_dma_desc_sw *desc;
        dma_addr_t phys;
  
-       desc = dma_pool_alloc(chan->desc_pool, GFP_NOWAIT, &phys);
+       desc = dma_pool_zalloc(chan->desc_pool, GFP_NOWAIT, &phys);
        if (!desc) {
                chan_err(chan, "Failed to allocate LDs\n");
                return NULL;
        }
  
-       memset(desc, 0, sizeof(*desc));
        INIT_LIST_HEAD(&desc->tx_list);
        desc->tx.phys = phys;
        desc->tx.tx_submit = xgene_dma_tx_submit;
@@@ -650,12 -657,15 +648,12 @@@ static void xgene_dma_clean_running_des
        dma_pool_free(chan->desc_pool, desc, desc->tx.phys);
  }
  
 -static int xgene_chan_xfer_request(struct xgene_dma_ring *ring,
 -                                 struct xgene_dma_desc_sw *desc_sw)
 +static void xgene_chan_xfer_request(struct xgene_dma_chan *chan,
 +                                  struct xgene_dma_desc_sw *desc_sw)
  {
 +      struct xgene_dma_ring *ring = &chan->tx_ring;
        struct xgene_dma_desc_hw *desc_hw;
  
 -      /* Check if can push more descriptor to hw for execution */
 -      if (xgene_dma_ring_desc_cnt(ring) > (ring->slots - 2))
 -              return -EBUSY;
 -
        /* Get hw descriptor from DMA tx ring */
        desc_hw = &ring->desc_hw[ring->head];
  
                memcpy(desc_hw, &desc_sw->desc2, sizeof(*desc_hw));
        }
  
 +      /* Increment the pending transaction count */
 +      chan->pending += ((desc_sw->flags &
 +                        XGENE_DMA_FLAG_64B_DESC) ? 2 : 1);
 +
        /* Notify the hw that we have descriptor ready for execution */
        iowrite32((desc_sw->flags & XGENE_DMA_FLAG_64B_DESC) ?
                  2 : 1, ring->cmd);
 -
 -      return 0;
  }
  
  /**
  static void xgene_chan_xfer_ld_pending(struct xgene_dma_chan *chan)
  {
        struct xgene_dma_desc_sw *desc_sw, *_desc_sw;
 -      int ret;
  
        /*
         * If the list of pending descriptors is empty, then we
                if (chan->pending >= chan->max_outstanding)
                        return;
  
 -              ret = xgene_chan_xfer_request(&chan->tx_ring, desc_sw);
 -              if (ret)
 -                      return;
 +              xgene_chan_xfer_request(chan, desc_sw);
  
                /*
                 * Delete this element from ld pending queue and append it to
                 * ld running queue
                 */
                list_move_tail(&desc_sw->node, &chan->ld_running);
 -
 -              /* Increment the pending transaction count */
 -              chan->pending++;
        }
  }
  
@@@ -805,8 -819,7 +803,8 @@@ static void xgene_dma_cleanup_descripto
                 * Decrement the pending transaction count
                 * as we have processed one
                 */
 -              chan->pending--;
 +              chan->pending -= ((desc_sw->flags &
 +                                XGENE_DMA_FLAG_64B_DESC) ? 2 : 1);
  
                /*
                 * Delete this node from ld running queue and append it to
@@@ -894,60 -907,6 +892,6 @@@ static void xgene_dma_free_chan_resourc
        chan->desc_pool = NULL;
  }
  
- static struct dma_async_tx_descriptor *xgene_dma_prep_memcpy(
-       struct dma_chan *dchan, dma_addr_t dst, dma_addr_t src,
-       size_t len, unsigned long flags)
- {
-       struct xgene_dma_desc_sw *first = NULL, *new;
-       struct xgene_dma_chan *chan;
-       size_t copy;
-       if (unlikely(!dchan || !len))
-               return NULL;
-       chan = to_dma_chan(dchan);
-       do {
-               /* Allocate the link descriptor from DMA pool */
-               new = xgene_dma_alloc_descriptor(chan);
-               if (!new)
-                       goto fail;
-               /* Create the largest transaction possible */
-               copy = min_t(size_t, len, XGENE_DMA_MAX_64B_DESC_BYTE_CNT);
-               /* Prepare DMA descriptor */
-               xgene_dma_prep_cpy_desc(chan, new, dst, src, copy);
-               if (!first)
-                       first = new;
-               new->tx.cookie = 0;
-               async_tx_ack(&new->tx);
-               /* Update metadata */
-               len -= copy;
-               dst += copy;
-               src += copy;
-               /* Insert the link descriptor to the LD ring */
-               list_add_tail(&new->node, &first->tx_list);
-       } while (len);
-       new->tx.flags = flags; /* client is in control of this ack */
-       new->tx.cookie = -EBUSY;
-       list_splice(&first->tx_list, &new->tx_list);
-       return &new->tx;
- fail:
-       if (!first)
-               return NULL;
-       xgene_dma_free_desc_list(chan, &first->tx_list);
-       return NULL;
- }
  static struct dma_async_tx_descriptor *xgene_dma_prep_sg(
        struct dma_chan *dchan, struct scatterlist *dst_sg,
        u32 dst_nents, struct scatterlist *src_sg,
@@@ -1406,18 -1365,15 +1350,18 @@@ static int xgene_dma_create_ring_one(st
                                     struct xgene_dma_ring *ring,
                                     enum xgene_dma_ring_cfgsize cfgsize)
  {
 +      int ret;
 +
        /* Setup DMA ring descriptor variables */
        ring->pdma = chan->pdma;
        ring->cfgsize = cfgsize;
        ring->num = chan->pdma->ring_num++;
        ring->id = XGENE_DMA_RING_ID_GET(ring->owner, ring->buf_num);
  
 -      ring->size = xgene_dma_get_ring_size(chan, cfgsize);
 -      if (ring->size <= 0)
 -              return ring->size;
 +      ret = xgene_dma_get_ring_size(chan, cfgsize);
 +      if (ret <= 0)
 +              return ret;
 +      ring->size = ret;
  
        /* Allocate memory for DMA ring descriptor */
        ring->desc_vaddr = dma_zalloc_coherent(chan->dev, ring->size,
@@@ -1470,7 -1426,7 +1414,7 @@@ static int xgene_dma_create_chan_rings(
                 tx_ring->id, tx_ring->num, tx_ring->desc_vaddr);
  
        /* Set the max outstanding request possible to this channel */
 -      chan->max_outstanding = rx_ring->slots;
 +      chan->max_outstanding = tx_ring->slots;
  
        return ret;
  }
@@@ -1707,7 -1663,6 +1651,6 @@@ static void xgene_dma_set_caps(struct x
        dma_cap_zero(dma_dev->cap_mask);
  
        /* Set DMA device capability */
-       dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
        dma_cap_set(DMA_SG, dma_dev->cap_mask);
  
        /* Basically here, the X-Gene SoC DMA engine channel 0 supports XOR
        dma_dev->device_free_chan_resources = xgene_dma_free_chan_resources;
        dma_dev->device_issue_pending = xgene_dma_issue_pending;
        dma_dev->device_tx_status = xgene_dma_tx_status;
-       dma_dev->device_prep_dma_memcpy = xgene_dma_prep_memcpy;
        dma_dev->device_prep_dma_sg = xgene_dma_prep_sg;
  
        if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
@@@ -1787,8 -1741,7 +1729,7 @@@ static int xgene_dma_async_register(str
  
        /* DMA capability info */
        dev_info(pdma->dev,
-                "%s: CAPABILITY ( %s%s%s%s)\n", dma_chan_name(&chan->dma_chan),
-                dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "MEMCPY " : "",
+                "%s: CAPABILITY ( %s%s%s)\n", dma_chan_name(&chan->dma_chan),
                 dma_has_cap(DMA_SG, dma_dev->cap_mask) ? "SGCPY " : "",
                 dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "XOR " : "",
                 dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "PQ " : "");
@@@ -441,7 -441,7 +441,7 @@@ static struct zx_dma_desc_sw *zx_alloc_
                kfree(ds);
                return NULL;
        }
-       memset(ds->desc_hw, sizeof(struct zx_desc_hw) * num, 0);
+       memset(ds->desc_hw, 0, sizeof(struct zx_desc_hw) * num);
        ds->desc_num = num;
        return ds;
  }
@@@ -739,7 -739,7 +739,7 @@@ static struct dma_chan *zx_of_dma_simpl
        struct dma_chan *chan;
        struct zx_dma_chan *c;
  
 -      if (request > d->dma_requests)
 +      if (request >= d->dma_requests)
                return NULL;
  
        chan = dma_get_any_slave_channel(&d->slave);