@@ -1054,6 +1054,7 @@ int do_dma_probe(struct dw_dma_chip *chip)
struct dw_dma *dw = chip->dw;
struct dw_dma_platform_data *pdata;
bool autocfg = false;
+ unsigned int block_size = 0;
unsigned int dw_params;
unsigned int i;
int err;
@@ -1184,6 +1185,18 @@ int do_dma_probe(struct dw_dma_chip *chip)
dwc->block_size = pdata->block_size;
dwc->nollp = !pdata->multi_block[i];
}
+
+ /*
+ * Find maximum block size to be set as the DMA device maximum
+ * segment size. By doing so we'll have size optimized SG-list
+ * items for the channels with biggest block size. This won't
+ * be a problem for the rest of the channels, since they will
+ * still be able to split the requests up by allocating
+ * multiple DW DMA LLP descriptors, which they would have done
+ * anyway.
+ */
+ if (dwc->block_size > block_size)
+ block_size = dwc->block_size;
}
/* Clear all interrupts on all channels. */
@@ -1220,6 +1233,10 @@ int do_dma_probe(struct dw_dma_chip *chip)
BIT(DMA_MEM_TO_MEM);
dw->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+ /* Block size corresponds to the maximum sg size */
+ dw->dma.dev->dma_parms = &dw->dma_parms;
+ dma_set_max_seg_size(dw->dma.dev, block_size);
+
err = dma_async_device_register(&dw->dma);
if (err)
goto err_dma_register;
@@ -8,6 +8,7 @@
*/
#include <linux/bitops.h>
+#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/dmaengine.h>
@@ -308,16 +309,17 @@ static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
}
struct dw_dma {
- struct dma_device dma;
- char name[20];
- void __iomem *regs;
- struct dma_pool *desc_pool;
- struct tasklet_struct tasklet;
+ struct dma_device dma;
+ struct device_dma_parameters dma_parms;
+ char name[20];
+ void __iomem *regs;
+ struct dma_pool *desc_pool;
+ struct tasklet_struct tasklet;
/* channels */
- struct dw_dma_chan *chan;
- u8 all_chan_mask;
- u8 in_use;
+ struct dw_dma_chan *chan;
+ u8 all_chan_mask;
+ u8 in_use;
/* Channel operations */
void (*initialize_chan)(struct dw_dma_chan *dwc);
Maximum block size DW DMAC configuration corresponds to the max segment size DMA parameter in the DMA core subsystem notation. Lets set it with a value specific to the probed DW DMA controller. It shall help the DMA clients to create size-optimized SG-list items for the controller. This in turn will cause less dw_desc allocations, less LLP reinitializations, better DMA device performance. Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Cc: Paul Burton <paulburton@kernel.org> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Rob Herring <robh+dt@kernel.org> Cc: linux-mips@vger.kernel.org Cc: devicetree@vger.kernel.org --- Changelog v2: - This is a new patch created in place of the dropped one: "dmaengine: dw: Add LLP and block size config accessors". --- drivers/dma/dw/core.c | 17 +++++++++++++++++ drivers/dma/dw/regs.h | 18 ++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-)