aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-11-10 11:47:55 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2021-11-10 11:47:55 -0800
commite68a7d35bb17247f8129e17126352a07433f2908 (patch)
tree2bd955bc66819c236b71857eaaa9c9e601f84e26 /drivers/dma
parentMerge tag 'tag-chrome-platform-for-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux (diff)
parentdmaengine: ti: k3-udma: Set r/tchan or rflow to NULL if request fail (diff)
downloadlinux-dev-e68a7d35bb17247f8129e17126352a07433f2908.tar.xz
linux-dev-e68a7d35bb17247f8129e17126352a07433f2908.zip
Merge tag 'dmaengine-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine
Pull dmaengine updates from Vinod Koul: "A bunch of driver updates, no new driver or controller support this time though: - Another pile of idxd updates - pm routines cleanup for at_xdmac driver - Correct handling of callback_result for few drivers - zynqmp_dma driver updates and descriptor management refinement - Hardware handshaking support for dw-axi-dmac - Support for remotely powered controllers in Qcom bam dma - tegra driver updates" * tag 'dmaengine-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (69 commits) dmaengine: ti: k3-udma: Set r/tchan or rflow to NULL if request fail dmaengine: ti: k3-udma: Set bchan to NULL if a channel request fail dmaengine: stm32-dma: avoid 64-bit division in stm32_dma_get_max_width dmaengine: fsl-edma: support edma memcpy dmaengine: idxd: fix resource leak on dmaengine driver disable dmaengine: idxd: cleanup completion record allocation dmaengine: zynqmp_dma: Correctly handle descriptor callbacks dmaengine: xilinx_dma: Correctly handle cyclic descriptor callbacks dmaengine: altera-msgdma: Correctly handle descriptor callbacks dmaengine: at_xdmac: fix compilation warning dmaengine: dw-axi-dmac: Simplify assignment in dma_chan_pause() dmaengine: qcom: bam_dma: Add "powered remotely" mode dt-bindings: dmaengine: bam_dma: Add "powered remotely" mode dmaengine: sa11x0: Mark PM functions as __maybe_unused dmaengine: switch from 'pci_' to 'dma_' API dmaengine: ioat: switch from 'pci_' to 'dma_' API dmaengine: hsu: switch from 'pci_' to 'dma_' API dmaengine: hisi_dma: switch from 'pci_' to 'dma_' API dmaengine: dw: switch from 'pci_' to 'dma_' API dmaengine: dw-edma-pcie: switch from 'pci_' to 'dma_' API ...
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/dma/altera-msgdma.c10
-rw-r--r--drivers/dma/at_xdmac.c69
-rw-r--r--drivers/dma/bestcomm/ata.c2
-rw-r--r--drivers/dma/bestcomm/bestcomm.c22
-rw-r--r--drivers/dma/bestcomm/fec.c4
-rw-r--r--drivers/dma/bestcomm/gen_bd.c4
-rw-r--r--drivers/dma/dma-jz4780.c1
-rw-r--r--drivers/dma/dmaengine.c3
-rw-r--r--drivers/dma/dmaengine.h2
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c112
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac.h35
-rw-r--r--drivers/dma/dw-edma/dw-edma-core.c1
-rw-r--r--drivers/dma/dw-edma/dw-edma-pcie.c17
-rw-r--r--drivers/dma/dw/pci.c6
-rw-r--r--drivers/dma/fsl-edma-common.c35
-rw-r--r--drivers/dma/fsl-edma-common.h4
-rw-r--r--drivers/dma/fsl-edma.c7
-rw-r--r--drivers/dma/hisi_dma.c6
-rw-r--r--drivers/dma/hsu/pci.c6
-rw-r--r--drivers/dma/idxd/device.c29
-rw-r--r--drivers/dma/idxd/dma.c5
-rw-r--r--drivers/dma/idxd/idxd.h2
-rw-r--r--drivers/dma/idxd/init.c14
-rw-r--r--drivers/dma/idxd/irq.c8
-rw-r--r--drivers/dma/idxd/registers.h4
-rw-r--r--drivers/dma/imx-sdma.c28
-rw-r--r--drivers/dma/ioat/init.c10
-rw-r--r--drivers/dma/milbeaut-hdmac.c2
-rw-r--r--drivers/dma/mmp_pdma.c1
-rw-r--r--drivers/dma/plx_dma.c10
-rw-r--r--drivers/dma/qcom/bam_dma.c90
-rw-r--r--drivers/dma/sa11x0-dma.c11
-rw-r--r--drivers/dma/sh/rcar-dmac.c13
-rw-r--r--drivers/dma/sh/rz-dmac.c16
-rw-r--r--drivers/dma/stm32-dma.c24
-rw-r--r--drivers/dma/stm32-mdma.c3
-rw-r--r--drivers/dma/tegra210-adma.c58
-rw-r--r--drivers/dma/ti/k3-udma.c32
-rw-r--r--drivers/dma/xilinx/xilinx_dma.c14
-rw-r--r--drivers/dma/xilinx/xilinx_dpdma.c15
-rw-r--r--drivers/dma/xilinx/zynqmp_dma.c79
42 files changed, 488 insertions, 328 deletions
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 80c2c03cb014..6bcdb4e6a0d1 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -717,7 +717,7 @@ config XILINX_DMA
config XILINX_ZYNQMP_DMA
tristate "Xilinx ZynqMP DMA Engine"
- depends on (ARCH_ZYNQ || MICROBLAZE || ARM64)
+ depends on ARCH_ZYNQ || MICROBLAZE || ARM64 || COMPILE_TEST
select DMA_ENGINE
help
Enable support for Xilinx ZynqMP DMA controller.
diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c
index 5a2c7573b692..f5b885d69cd3 100644
--- a/drivers/dma/altera-msgdma.c
+++ b/drivers/dma/altera-msgdma.c
@@ -585,16 +585,14 @@ static void msgdma_chan_desc_cleanup(struct msgdma_device *mdev)
struct msgdma_sw_desc *desc, *next;
list_for_each_entry_safe(desc, next, &mdev->done_list, node) {
- dma_async_tx_callback callback;
- void *callback_param;
+ struct dmaengine_desc_callback cb;
list_del(&desc->node);
- callback = desc->async_tx.callback;
- callback_param = desc->async_tx.callback_param;
- if (callback) {
+ dmaengine_desc_get_callback(&desc->async_tx, &cb);
+ if (dmaengine_desc_callback_valid(&cb)) {
spin_unlock(&mdev->lock);
- callback(callback_param);
+ dmaengine_desc_callback_invoke(&cb, NULL);
spin_lock(&mdev->lock);
}
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index ab78e0f6afd7..275a76f188ae 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -155,7 +155,7 @@
#define AT_XDMAC_CC_WRIP (0x1 << 23) /* Write in Progress (read only) */
#define AT_XDMAC_CC_WRIP_DONE (0x0 << 23)
#define AT_XDMAC_CC_WRIP_IN_PROGRESS (0x1 << 23)
-#define AT_XDMAC_CC_PERID(i) (0x7f & (i) << 24) /* Channel Peripheral Identifier */
+#define AT_XDMAC_CC_PERID(i) ((0x7f & (i)) << 24) /* Channel Peripheral Identifier */
#define AT_XDMAC_CDS_MSP 0x2C /* Channel Data Stride Memory Set Pattern */
#define AT_XDMAC_CSUS 0x30 /* Channel Source Microblock Stride */
#define AT_XDMAC_CDUS 0x34 /* Channel Destination Microblock Stride */
@@ -1926,8 +1926,31 @@ static void at_xdmac_free_chan_resources(struct dma_chan *chan)
return;
}
-#ifdef CONFIG_PM
-static int atmel_xdmac_prepare(struct device *dev)
+static void at_xdmac_axi_config(struct platform_device *pdev)
+{
+ struct at_xdmac *atxdmac = (struct at_xdmac *)platform_get_drvdata(pdev);
+ bool dev_m2m = false;
+ u32 dma_requests;
+
+ if (!atxdmac->layout->axi_config)
+ return; /* Not supported */
+
+ if (!of_property_read_u32(pdev->dev.of_node, "dma-requests",
+ &dma_requests)) {
+ dev_info(&pdev->dev, "controller in mem2mem mode.\n");
+ dev_m2m = true;
+ }
+
+ if (dev_m2m) {
+ at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_M2M);
+ at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_M2M);
+ } else {
+ at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_P2M);
+ at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_P2M);
+ }
+}
+
+static int __maybe_unused atmel_xdmac_prepare(struct device *dev)
{
struct at_xdmac *atxdmac = dev_get_drvdata(dev);
struct dma_chan *chan, *_chan;
@@ -1941,12 +1964,8 @@ static int atmel_xdmac_prepare(struct device *dev)
}
return 0;
}
-#else
-# define atmel_xdmac_prepare NULL
-#endif
-#ifdef CONFIG_PM_SLEEP
-static int atmel_xdmac_suspend(struct device *dev)
+static int __maybe_unused atmel_xdmac_suspend(struct device *dev)
{
struct at_xdmac *atxdmac = dev_get_drvdata(dev);
struct dma_chan *chan, *_chan;
@@ -1970,11 +1989,12 @@ static int atmel_xdmac_suspend(struct device *dev)
return 0;
}
-static int atmel_xdmac_resume(struct device *dev)
+static int __maybe_unused atmel_xdmac_resume(struct device *dev)
{
struct at_xdmac *atxdmac = dev_get_drvdata(dev);
struct at_xdmac_chan *atchan;
struct dma_chan *chan, *_chan;
+ struct platform_device *pdev = container_of(dev, struct platform_device, dev);
int i;
int ret;
@@ -1982,6 +2002,8 @@ static int atmel_xdmac_resume(struct device *dev)
if (ret)
return ret;
+ at_xdmac_axi_config(pdev);
+
/* Clear pending interrupts. */
for (i = 0; i < atxdmac->dma.chancnt; i++) {
atchan = &atxdmac->chan[i];
@@ -2005,31 +2027,6 @@ static int atmel_xdmac_resume(struct device *dev)
}
return 0;
}
-#endif /* CONFIG_PM_SLEEP */
-
-static void at_xdmac_axi_config(struct platform_device *pdev)
-{
- struct at_xdmac *atxdmac = (struct at_xdmac *)platform_get_drvdata(pdev);
- bool dev_m2m = false;
- u32 dma_requests;
-
- if (!atxdmac->layout->axi_config)
- return; /* Not supported */
-
- if (!of_property_read_u32(pdev->dev.of_node, "dma-requests",
- &dma_requests)) {
- dev_info(&pdev->dev, "controller in mem2mem mode.\n");
- dev_m2m = true;
- }
-
- if (dev_m2m) {
- at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_M2M);
- at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_M2M);
- } else {
- at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_P2M);
- at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_P2M);
- }
-}
static int at_xdmac_probe(struct platform_device *pdev)
{
@@ -2210,7 +2207,7 @@ static int at_xdmac_remove(struct platform_device *pdev)
return 0;
}
-static const struct dev_pm_ops atmel_xdmac_dev_pm_ops = {
+static const struct dev_pm_ops __maybe_unused atmel_xdmac_dev_pm_ops = {
.prepare = atmel_xdmac_prepare,
SET_LATE_SYSTEM_SLEEP_PM_OPS(atmel_xdmac_suspend, atmel_xdmac_resume)
};
@@ -2234,7 +2231,7 @@ static struct platform_driver at_xdmac_driver = {
.driver = {
.name = "at_xdmac",
.of_match_table = of_match_ptr(atmel_xdmac_dt_ids),
- .pm = &atmel_xdmac_dev_pm_ops,
+ .pm = pm_ptr(&atmel_xdmac_dev_pm_ops),
}
};
diff --git a/drivers/dma/bestcomm/ata.c b/drivers/dma/bestcomm/ata.c
index 2fd87f83cf90..e169f18da551 100644
--- a/drivers/dma/bestcomm/ata.c
+++ b/drivers/dma/bestcomm/ata.c
@@ -133,7 +133,7 @@ void bcom_ata_reset_bd(struct bcom_task *tsk)
struct bcom_ata_var *var;
/* Reset all BD */
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
tsk->index = 0;
tsk->outdex = 0;
diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c
index d91cbbe7a48f..8c42e5ca00a9 100644
--- a/drivers/dma/bestcomm/bestcomm.c
+++ b/drivers/dma/bestcomm/bestcomm.c
@@ -95,7 +95,7 @@ bcom_task_alloc(int bd_count, int bd_size, int priv_size)
tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
if (!tsk->bd)
goto error;
- memset(tsk->bd, 0x00, bd_count * bd_size);
+ memset_io(tsk->bd, 0x00, bd_count * bd_size);
tsk->num_bd = bd_count;
tsk->bd_size = bd_size;
@@ -186,16 +186,16 @@ bcom_load_image(int task, u32 *task_image)
inc = bcom_task_inc(task);
/* Clear & copy */
- memset(var, 0x00, BCOM_VAR_SIZE);
- memset(inc, 0x00, BCOM_INC_SIZE);
+ memset_io(var, 0x00, BCOM_VAR_SIZE);
+ memset_io(inc, 0x00, BCOM_INC_SIZE);
desc_src = (u32 *)(hdr + 1);
var_src = desc_src + hdr->desc_size;
inc_src = var_src + hdr->var_size;
- memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
- memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
- memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
+ memcpy_toio(desc, desc_src, hdr->desc_size * sizeof(u32));
+ memcpy_toio(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
+ memcpy_toio(inc, inc_src, hdr->inc_size * sizeof(u32));
return 0;
}
@@ -302,13 +302,13 @@ static int bcom_engine_init(void)
return -ENOMEM;
}
- memset(bcom_eng->tdt, 0x00, tdt_size);
- memset(bcom_eng->ctx, 0x00, ctx_size);
- memset(bcom_eng->var, 0x00, var_size);
- memset(bcom_eng->fdt, 0x00, fdt_size);
+ memset_io(bcom_eng->tdt, 0x00, tdt_size);
+ memset_io(bcom_eng->ctx, 0x00, ctx_size);
+ memset_io(bcom_eng->var, 0x00, var_size);
+ memset_io(bcom_eng->fdt, 0x00, fdt_size);
/* Copy the FDT for the EU#3 */
- memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
+ memcpy_toio(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
/* Initialize Task base structure */
for (task=0; task<BCOM_MAX_TASKS; task++)
diff --git a/drivers/dma/bestcomm/fec.c b/drivers/dma/bestcomm/fec.c
index 7f1fb1c999e4..d203618ac11f 100644
--- a/drivers/dma/bestcomm/fec.c
+++ b/drivers/dma/bestcomm/fec.c
@@ -140,7 +140,7 @@ bcom_fec_rx_reset(struct bcom_task *tsk)
tsk->index = 0;
tsk->outdex = 0;
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
/* Configure some stuff */
bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_RX_BD_PRAGMA);
@@ -241,7 +241,7 @@ bcom_fec_tx_reset(struct bcom_task *tsk)
tsk->index = 0;
tsk->outdex = 0;
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
/* Configure some stuff */
bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_TX_BD_PRAGMA);
diff --git a/drivers/dma/bestcomm/gen_bd.c b/drivers/dma/bestcomm/gen_bd.c
index 906ddba6a6f5..8a24a5cbc263 100644
--- a/drivers/dma/bestcomm/gen_bd.c
+++ b/drivers/dma/bestcomm/gen_bd.c
@@ -142,7 +142,7 @@ bcom_gen_bd_rx_reset(struct bcom_task *tsk)
tsk->index = 0;
tsk->outdex = 0;
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
/* Configure some stuff */
bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
@@ -226,7 +226,7 @@ bcom_gen_bd_tx_reset(struct bcom_task *tsk)
tsk->index = 0;
tsk->outdex = 0;
- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
/* Configure some stuff */
bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
index ebee94dbd630..96701dedcac8 100644
--- a/drivers/dma/dma-jz4780.c
+++ b/drivers/dma/dma-jz4780.c
@@ -915,6 +915,7 @@ static int jz4780_dma_probe(struct platform_device *pdev)
dd->dst_addr_widths = JZ_DMA_BUSWIDTHS;
dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+ dd->max_sg_burst = JZ_DMA_MAX_DESC;
/*
* Enable DMA controller, mark all channels as not programmable.
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index af3ee288bc11..d9f7c097cfd6 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -695,13 +695,12 @@ static struct dma_chan *find_candidate(struct dma_device *device,
*/
struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
{
- int err = -EBUSY;
-
/* lock against __dma_request_channel */
mutex_lock(&dma_list_mutex);
if (chan->client_count == 0) {
struct dma_device *device = chan->device;
+ int err;
dma_cap_set(DMA_PRIVATE, device->cap_mask);
device->privatecnt++;
diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h
index 1bfbd64b1371..53f16d3f0029 100644
--- a/drivers/dma/dmaengine.h
+++ b/drivers/dma/dmaengine.h
@@ -176,7 +176,7 @@ dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx,
static inline bool
dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb)
{
- return (cb->callback) ? true : false;
+ return cb->callback || cb->callback_result;
}
struct dma_chan *dma_get_slave_channel(struct dma_chan *chan);
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index 35993ab92154..cd0d745eb071 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -79,6 +79,32 @@ axi_chan_iowrite64(struct axi_dma_chan *chan, u32 reg, u64 val)
iowrite32(upper_32_bits(val), chan->chan_regs + reg + 4);
}
+static inline void axi_chan_config_write(struct axi_dma_chan *chan,
+ struct axi_dma_chan_config *config)
+{
+ u32 cfg_lo, cfg_hi;
+
+ cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS |
+ config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
+ if (chan->chip->dw->hdata->reg_map_8_channels) {
+ cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS |
+ config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS |
+ config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS |
+ config->src_per << CH_CFG_H_SRC_PER_POS |
+ config->dst_per << CH_CFG_H_DST_PER_POS |
+ config->prior << CH_CFG_H_PRIORITY_POS;
+ } else {
+ cfg_lo |= config->src_per << CH_CFG2_L_SRC_PER_POS |
+ config->dst_per << CH_CFG2_L_DST_PER_POS;
+ cfg_hi = config->tt_fc << CH_CFG2_H_TT_FC_POS |
+ config->hs_sel_src << CH_CFG2_H_HS_SEL_SRC_POS |
+ config->hs_sel_dst << CH_CFG2_H_HS_SEL_DST_POS |
+ config->prior << CH_CFG2_H_PRIORITY_POS;
+ }
+ axi_chan_iowrite32(chan, CH_CFG_L, cfg_lo);
+ axi_chan_iowrite32(chan, CH_CFG_H, cfg_hi);
+}
+
static inline void axi_dma_disable(struct axi_dma_chip *chip)
{
u32 val;
@@ -154,7 +180,10 @@ static inline void axi_chan_disable(struct axi_dma_chan *chan)
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
- val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ if (chan->chip->dw->hdata->reg_map_8_channels)
+ val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ else
+ val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
}
@@ -163,8 +192,12 @@ static inline void axi_chan_enable(struct axi_dma_chan *chan)
u32 val;
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
- BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ if (chan->chip->dw->hdata->reg_map_8_channels)
+ val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ else
+ val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
}
@@ -179,12 +212,16 @@ static inline bool axi_chan_is_hw_enable(struct axi_dma_chan *chan)
static void axi_dma_hw_init(struct axi_dma_chip *chip)
{
+ int ret;
u32 i;
for (i = 0; i < chip->dw->hdata->nr_channels; i++) {
axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
axi_chan_disable(&chip->dw->chan[i]);
}
+ ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
+ if (ret)
+ dev_warn(chip->dev, "Unable to set coherent mask\n");
}
static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, dma_addr_t src,
@@ -336,7 +373,8 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
struct axi_dma_desc *first)
{
u32 priority = chan->chip->dw->hdata->priority[chan->id];
- u32 reg, irq_mask;
+ struct axi_dma_chan_config config;
+ u32 irq_mask;
u8 lms = 0; /* Select AXI0 master for LLI fetching */
if (unlikely(axi_chan_is_hw_enable(chan))) {
@@ -348,36 +386,36 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
axi_dma_enable(chan->chip);
- reg = (DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_DST_MULTBLK_TYPE_POS |
- DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
- axi_chan_iowrite32(chan, CH_CFG_L, reg);
-
- reg = (DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC << CH_CFG_H_TT_FC_POS |
- priority << CH_CFG_H_PRIORITY_POS |
- DWAXIDMAC_HS_SEL_HW << CH_CFG_H_HS_SEL_DST_POS |
- DWAXIDMAC_HS_SEL_HW << CH_CFG_H_HS_SEL_SRC_POS);
+ config.dst_multblk_type = DWAXIDMAC_MBLK_TYPE_LL;
+ config.src_multblk_type = DWAXIDMAC_MBLK_TYPE_LL;
+ config.tt_fc = DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC;
+ config.prior = priority;
+ config.hs_sel_dst = DWAXIDMAC_HS_SEL_HW;
+ config.hs_sel_dst = DWAXIDMAC_HS_SEL_HW;
switch (chan->direction) {
case DMA_MEM_TO_DEV:
dw_axi_dma_set_byte_halfword(chan, true);
- reg |= (chan->config.device_fc ?
- DWAXIDMAC_TT_FC_MEM_TO_PER_DST :
- DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC)
- << CH_CFG_H_TT_FC_POS;
+ config.tt_fc = chan->config.device_fc ?
+ DWAXIDMAC_TT_FC_MEM_TO_PER_DST :
+ DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC;
if (chan->chip->apb_regs)
- reg |= (chan->id << CH_CFG_H_DST_PER_POS);
+ config.dst_per = chan->id;
+ else
+ config.dst_per = chan->hw_handshake_num;
break;
case DMA_DEV_TO_MEM:
- reg |= (chan->config.device_fc ?
- DWAXIDMAC_TT_FC_PER_TO_MEM_SRC :
- DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC)
- << CH_CFG_H_TT_FC_POS;
+ config.tt_fc = chan->config.device_fc ?
+ DWAXIDMAC_TT_FC_PER_TO_MEM_SRC :
+ DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC;
if (chan->chip->apb_regs)
- reg |= (chan->id << CH_CFG_H_SRC_PER_POS);
+ config.src_per = chan->id;
+ else
+ config.src_per = chan->hw_handshake_num;
break;
default:
break;
}
- axi_chan_iowrite32(chan, CH_CFG_H, reg);
+ axi_chan_config_write(chan, &config);
write_chan_llp(chan, first->hw_desc[0].llp | lms);
@@ -1120,10 +1158,16 @@ static int dma_chan_pause(struct dma_chan *dchan)
spin_lock_irqsave(&chan->vc.lock, flags);
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
- BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ if (chan->chip->dw->hdata->reg_map_8_channels) {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ } else {
+ val = BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
+ axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
+ }
do {
if (axi_chan_irq_read(chan) & DWAXIDMAC_IRQ_SUSPENDED)
@@ -1147,9 +1191,15 @@ static inline void axi_chan_resume(struct axi_dma_chan *chan)
u32 val;
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
- val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ if (chan->chip->dw->hdata->reg_map_8_channels) {
+ val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
+ val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ } else {
+ val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
+ val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
+ axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
+ }
chan->is_paused = false;
}
@@ -1241,6 +1291,8 @@ static int parse_device_properties(struct axi_dma_chip *chip)
return -EINVAL;
chip->dw->hdata->nr_channels = tmp;
+ if (tmp <= DMA_REG_MAP_CH_REF)
+ chip->dw->hdata->reg_map_8_channels = true;
ret = device_property_read_u32(dev, "snps,dma-masters", &tmp);
if (ret)
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
index 380005afde16..be69a0b76860 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
@@ -18,7 +18,7 @@
#include "../virt-dma.h"
-#define DMAC_MAX_CHANNELS 8
+#define DMAC_MAX_CHANNELS 16
#define DMAC_MAX_MASTERS 2
#define DMAC_MAX_BLK_SIZE 0x200000
@@ -30,6 +30,8 @@ struct dw_axi_dma_hcfg {
u32 priority[DMAC_MAX_CHANNELS];
/* maximum supported axi burst length */
u32 axi_rw_burst_len;
+ /* Register map for DMAX_NUM_CHANNELS <= 8 */
+ bool reg_map_8_channels;
bool restrict_axi_burst_len;
};
@@ -103,6 +105,17 @@ struct axi_dma_desc {
u32 period_len;
};
+struct axi_dma_chan_config {
+ u8 dst_multblk_type;
+ u8 src_multblk_type;
+ u8 dst_per;
+ u8 src_per;
+ u8 tt_fc;
+ u8 prior;
+ u8 hs_sel_dst;
+ u8 hs_sel_src;
+};
+
static inline struct device *dchan2dev(struct dma_chan *dchan)
{
return &dchan->dev->device;
@@ -139,6 +152,8 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
#define DMAC_CHEN 0x018 /* R/W DMAC Channel Enable */
#define DMAC_CHEN_L 0x018 /* R/W DMAC Channel Enable 00-31 */
#define DMAC_CHEN_H 0x01C /* R/W DMAC Channel Enable 32-63 */
+#define DMAC_CHSUSPREG 0x020 /* R/W DMAC Channel Suspend */
+#define DMAC_CHABORTREG 0x028 /* R/W DMAC Channel Abort */
#define DMAC_INTSTATUS 0x030 /* R DMAC Interrupt Status */
#define DMAC_COMMON_INTCLEAR 0x038 /* W DMAC Interrupt Clear */
#define DMAC_COMMON_INTSTATUS_ENA 0x040 /* R DMAC Interrupt Status Enable */
@@ -187,6 +202,7 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
#define DMA_APB_HS_SEL_BIT_SIZE 0x08 /* HW handshake bits per channel */
#define DMA_APB_HS_SEL_MASK 0xFF /* HW handshake select masks */
#define MAX_BLOCK_SIZE 0x1000 /* 1024 blocks * 4 bytes data width */
+#define DMA_REG_MAP_CH_REF 0x08 /* Channel count to choose register map */
/* DMAC_CFG */
#define DMAC_EN_POS 0
@@ -195,12 +211,20 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
#define INT_EN_POS 1
#define INT_EN_MASK BIT(INT_EN_POS)
+/* DMAC_CHEN */
#define DMAC_CHAN_EN_SHIFT 0
#define DMAC_CHAN_EN_WE_SHIFT 8
#define DMAC_CHAN_SUSP_SHIFT 16
#define DMAC_CHAN_SUSP_WE_SHIFT 24
+/* DMAC_CHEN2 */
+#define DMAC_CHAN_EN2_WE_SHIFT 16
+
+/* DMAC_CHSUSP */
+#define DMAC_CHAN_SUSP2_SHIFT 0
+#define DMAC_CHAN_SUSP2_WE_SHIFT 16
+
/* CH_CTL_H */
#define CH_CTL_H_ARLEN_EN BIT(6)
#define CH_CTL_H_ARLEN_POS 7
@@ -289,6 +313,15 @@ enum {
DWAXIDMAC_MBLK_TYPE_LL
};
+/* CH_CFG2 */
+#define CH_CFG2_L_SRC_PER_POS 4
+#define CH_CFG2_L_DST_PER_POS 11
+
+#define CH_CFG2_H_TT_FC_POS 0
+#define CH_CFG2_H_HS_SEL_SRC_POS 3
+#define CH_CFG2_H_HS_SEL_DST_POS 4
+#define CH_CFG2_H_PRIORITY_POS 20
+
/**
* DW AXI DMA channel interrupts
*
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 53289927dd0d..468d1097a1ec 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -249,7 +249,6 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan)
{
struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
int err = 0;
- LIST_HEAD(head);
if (!chan->configured) {
/* Do nothing */
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 44f6e09bdb53..198f6cd8ac1b 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -186,27 +186,18 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
pci_set_master(pdev);
/* DMA configuration */
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (!err) {
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (err) {
- pci_err(pdev, "consistent DMA mask 64 set failed\n");
- return err;
- }
+ pci_err(pdev, "DMA mask 64 set failed\n");
+ return err;
} else {
pci_err(pdev, "DMA mask 64 set failed\n");
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (err) {
pci_err(pdev, "DMA mask 32 set failed\n");
return err;
}
-
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- if (err) {
- pci_err(pdev, "consistent DMA mask 32 set failed\n");
- return err;
- }
}
/* Data structure allocation */
diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c
index 26a3f926da02..ad2d4d012cf7 100644
--- a/drivers/dma/dw/pci.c
+++ b/drivers/dma/dw/pci.c
@@ -32,11 +32,7 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
-
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
index 930ae268c497..3ae05d1446a5 100644
--- a/drivers/dma/fsl-edma-common.c
+++ b/drivers/dma/fsl-edma-common.c
@@ -348,6 +348,7 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
struct fsl_edma_engine *edma = fsl_chan->edma;
struct edma_regs *regs = &fsl_chan->edma->regs;
u32 ch = fsl_chan->vchan.chan.chan_id;
+ u16 csr = 0;
/*
* TCD parameters are stored in struct fsl_edma_hw_tcd in little
@@ -373,6 +374,12 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
edma_writel(edma, (s32)tcd->dlast_sga,
&regs->tcd[ch].dlast_sga);
+ if (fsl_chan->is_sw) {
+ csr = le16_to_cpu(tcd->csr);
+ csr |= EDMA_TCD_CSR_START;
+ tcd->csr = cpu_to_le16(csr);
+ }
+
edma_writew(edma, (s16)tcd->csr, &regs->tcd[ch].csr);
}
@@ -587,6 +594,29 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg(
}
EXPORT_SYMBOL_GPL(fsl_edma_prep_slave_sg);
+struct dma_async_tx_descriptor *fsl_edma_prep_memcpy(struct dma_chan *chan,
+ dma_addr_t dma_dst, dma_addr_t dma_src,
+ size_t len, unsigned long flags)
+{
+ struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+ struct fsl_edma_desc *fsl_desc;
+
+ fsl_desc = fsl_edma_alloc_desc(fsl_chan, 1);
+ if (!fsl_desc)
+ return NULL;
+ fsl_desc->iscyclic = false;
+
+ fsl_chan->is_sw = true;
+
+ /* To match with copy_align and max_seg_size so 1 tcd is enough */
+ fsl_edma_fill_tcd(fsl_desc->tcd[0].vtcd, dma_src, dma_dst,
+ EDMA_TCD_ATTR_SSIZE_32BYTE | EDMA_TCD_ATTR_DSIZE_32BYTE,
+ 32, len, 0, 1, 1, 32, 0, true, true, false);
+
+ return vchan_tx_prep(&fsl_chan->vchan, &fsl_desc->vdesc, flags);
+}
+EXPORT_SYMBOL_GPL(fsl_edma_prep_memcpy);
+
void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan)
{
struct virt_dma_desc *vdesc;
@@ -638,12 +668,14 @@ EXPORT_SYMBOL_GPL(fsl_edma_alloc_chan_resources);
void fsl_edma_free_chan_resources(struct dma_chan *chan)
{
struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+ struct fsl_edma_engine *edma = fsl_chan->edma;
unsigned long flags;
LIST_HEAD(head);
spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
fsl_edma_disable_request(fsl_chan);
- fsl_edma_chan_mux(fsl_chan, 0, false);
+ if (edma->drvdata->dmamuxs)
+ fsl_edma_chan_mux(fsl_chan, 0, false);
fsl_chan->edesc = NULL;
vchan_get_all_descriptors(&fsl_chan->vchan, &head);
fsl_edma_unprep_slave_dma(fsl_chan);
@@ -652,6 +684,7 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
vchan_dma_desc_free_list(&fsl_chan->vchan, &head);
dma_pool_destroy(fsl_chan->tcd_pool);
fsl_chan->tcd_pool = NULL;
+ fsl_chan->is_sw = false;
}
EXPORT_SYMBOL_GPL(fsl_edma_free_chan_resources);
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index ec1169741de1..004ec4a6bc86 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -121,6 +121,7 @@ struct fsl_edma_chan {
struct fsl_edma_desc *edesc;
struct dma_slave_config cfg;
u32 attr;
+ bool is_sw;
struct dma_pool *tcd_pool;
dma_addr_t dma_dev_addr;
u32 dma_dev_size;
@@ -240,6 +241,9 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags, void *context);
+struct dma_async_tx_descriptor *fsl_edma_prep_memcpy(
+ struct dma_chan *chan, dma_addr_t dma_dst, dma_addr_t dma_src,
+ size_t len, unsigned long flags);
void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan);
void fsl_edma_issue_pending(struct dma_chan *chan);
int fsl_edma_alloc_chan_resources(struct dma_chan *chan);
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 90bb72af306c..76cbf54aec58 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_dma.h>
+#include <linux/dma-mapping.h>
#include "fsl-edma-common.h"
@@ -372,6 +373,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
dma_cap_set(DMA_PRIVATE, fsl_edma->dma_dev.cap_mask);
dma_cap_set(DMA_SLAVE, fsl_edma->dma_dev.cap_mask);
dma_cap_set(DMA_CYCLIC, fsl_edma->dma_dev.cap_mask);
+ dma_cap_set(DMA_MEMCPY, fsl_edma->dma_dev.cap_mask);
fsl_edma->dma_dev.dev = &pdev->dev;
fsl_edma->dma_dev.device_alloc_chan_resources
@@ -381,6 +383,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
fsl_edma->dma_dev.device_tx_status = fsl_edma_tx_status;
fsl_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
fsl_edma->dma_dev.device_prep_dma_cyclic = fsl_edma_prep_dma_cyclic;
+ fsl_edma->dma_dev.device_prep_dma_memcpy = fsl_edma_prep_memcpy;
fsl_edma->dma_dev.device_config = fsl_edma_slave_config;
fsl_edma->dma_dev.device_pause = fsl_edma_pause;
fsl_edma->dma_dev.device_resume = fsl_edma_resume;
@@ -392,6 +395,10 @@ static int fsl_edma_probe(struct platform_device *pdev)
fsl_edma->dma_dev.dst_addr_widths = FSL_EDMA_BUSWIDTHS;
fsl_edma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+ fsl_edma->dma_dev.copy_align = DMAENGINE_ALIGN_32_BYTES;
+ /* Per worst case 'nbytes = 1' take CITER as the max_seg_size */
+ dma_set_max_seg_size(fsl_edma->dma_dev.dev, 0x3fff);
+
platform_set_drvdata(pdev, fsl_edma);
ret = dma_async_device_register(&fsl_edma->dma_dev);
diff --git a/drivers/dma/hisi_dma.c b/drivers/dma/hisi_dma.c
index c855a0e4f9ff..97c87a7cba87 100644
--- a/drivers/dma/hisi_dma.c
+++ b/drivers/dma/hisi_dma.c
@@ -519,11 +519,7 @@ static int hisi_dma_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return ret;
}
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
- if (ret)
- return ret;
-
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (ret)
return ret;
diff --git a/drivers/dma/hsu/pci.c b/drivers/dma/hsu/pci.c
index 9045a6f7f589..6a2df3dd78d0 100644
--- a/drivers/dma/hsu/pci.c
+++ b/drivers/dma/hsu/pci.c
@@ -65,11 +65,7 @@ static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
-
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
index 83a5ff2ecf2a..fab412349f7f 100644
--- a/drivers/dma/idxd/device.c
+++ b/drivers/dma/idxd/device.c
@@ -135,8 +135,6 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq)
struct idxd_device *idxd = wq->idxd;
struct device *dev = &idxd->pdev->dev;
int rc, num_descs, i;
- int align;
- u64 tmp;
if (wq->type != IDXD_WQT_KERNEL)
return 0;
@@ -148,21 +146,13 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq)
if (rc < 0)
return rc;
- align = idxd->data->align;
- wq->compls_size = num_descs * idxd->data->compl_size + align;
- wq->compls_raw = dma_alloc_coherent(dev, wq->compls_size,
- &wq->compls_addr_raw, GFP_KERNEL);
- if (!wq->compls_raw) {
+ wq->compls_size = num_descs * idxd->data->compl_size;
+ wq->compls = dma_alloc_coherent(dev, wq->compls_size, &wq->compls_addr, GFP_KERNEL);
+ if (!wq->compls) {
rc = -ENOMEM;
goto fail_alloc_compls;
}
- /* Adjust alignment */
- wq->compls_addr = (wq->compls_addr_raw + (align - 1)) & ~(align - 1);
- tmp = (u64)wq->compls_raw;
- tmp = (tmp + (align - 1)) & ~(align - 1);
- wq->compls = (struct dsa_completion_record *)tmp;
-
rc = alloc_descs(wq, num_descs);
if (rc < 0)
goto fail_alloc_descs;
@@ -191,8 +181,7 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq)
fail_sbitmap_init:
free_descs(wq);
fail_alloc_descs:
- dma_free_coherent(dev, wq->compls_size, wq->compls_raw,
- wq->compls_addr_raw);
+ dma_free_coherent(dev, wq->compls_size, wq->compls, wq->compls_addr);
fail_alloc_compls:
free_hw_descs(wq);
return rc;
@@ -207,8 +196,7 @@ void idxd_wq_free_resources(struct idxd_wq *wq)
free_hw_descs(wq);
free_descs(wq);
- dma_free_coherent(dev, wq->compls_size, wq->compls_raw,
- wq->compls_addr_raw);
+ dma_free_coherent(dev, wq->compls_size, wq->compls, wq->compls_addr);
sbitmap_queue_free(&wq->sbq);
}
@@ -427,7 +415,6 @@ void idxd_wq_quiesce(struct idxd_wq *wq)
{
percpu_ref_kill(&wq->wq_active);
wait_for_completion(&wq->wq_dead);
- percpu_ref_exit(&wq->wq_active);
}
/* Device control bits */
@@ -584,6 +571,8 @@ void idxd_device_reset(struct idxd_device *idxd)
spin_lock(&idxd->dev_lock);
idxd_device_clear_state(idxd);
idxd->state = IDXD_DEV_DISABLED;
+ idxd_unmask_error_interrupts(idxd);
+ idxd_msix_perm_setup(idxd);
spin_unlock(&idxd->dev_lock);
}
@@ -792,7 +781,7 @@ static int idxd_groups_config_write(struct idxd_device *idxd)
struct device *dev = &idxd->pdev->dev;
/* Setup bandwidth token limit */
- if (idxd->token_limit) {
+ if (idxd->hw.gen_cap.config_en && idxd->token_limit) {
reg.bits = ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET);
reg.token_limit = idxd->token_limit;
iowrite32(reg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
@@ -1051,8 +1040,6 @@ static int idxd_wq_load_config(struct idxd_wq *wq)
wq->size = wq->wqcfg->wq_size;
wq->threshold = wq->wqcfg->wq_thresh;
- if (wq->wqcfg->priv)
- wq->type = IDXD_WQT_KERNEL;
/* The driver does not support shared WQ mode in read-only config yet */
if (wq->wqcfg->mode == 0 || wq->wqcfg->pasid_en)
diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c
index e0f056c1d1f5..c39e9483206a 100644
--- a/drivers/dma/idxd/dma.c
+++ b/drivers/dma/idxd/dma.c
@@ -311,6 +311,7 @@ static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev)
err_dma:
idxd_wq_quiesce(wq);
+ percpu_ref_exit(&wq->wq_active);
err_ref:
idxd_wq_free_resources(wq);
err_res_alloc:
@@ -328,9 +329,9 @@ static void idxd_dmaengine_drv_remove(struct idxd_dev *idxd_dev)
mutex_lock(&wq->wq_lock);
idxd_wq_quiesce(wq);
idxd_unregister_dma_channel(wq);
- __drv_disable_wq(wq);
idxd_wq_free_resources(wq);
- wq->type = IDXD_WQT_NONE;
+ __drv_disable_wq(wq);
+ percpu_ref_exit(&wq->wq_active);
mutex_unlock(&wq->wq_lock);
}
diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
index bfcb03329f77..0cf8d3145870 100644
--- a/drivers/dma/idxd/idxd.h
+++ b/drivers/dma/idxd/idxd.h
@@ -187,9 +187,7 @@ struct idxd_wq {
struct dsa_completion_record *compls;
struct iax_completion_record *iax_compls;
};
- void *compls_raw;
dma_addr_t compls_addr;
- dma_addr_t compls_addr_raw;
int compls_size;
struct idxd_desc **descs;
struct sbitmap_queue sbq;
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
index eb09bc591c31..7bf03f371ce1 100644
--- a/drivers/dma/idxd/init.c
+++ b/drivers/dma/idxd/init.c
@@ -797,11 +797,19 @@ static void idxd_remove(struct pci_dev *pdev)
int msixcnt = pci_msix_vec_count(pdev);
int i;
- dev_dbg(&pdev->dev, "%s called\n", __func__);
+ idxd_unregister_devices(idxd);
+ /*
+ * When ->release() is called for the idxd->conf_dev, it frees all the memory related
+ * to the idxd context. The driver still needs those bits in order to do the rest of
+ * the cleanup. However, we do need to unbound the idxd sub-driver. So take a ref
+ * on the device here to hold off the freeing while allowing the idxd sub-driver
+ * to unbind.
+ */
+ get_device(idxd_confdev(idxd));
+ device_unregister(idxd_confdev(idxd));
idxd_shutdown(pdev);
if (device_pasid_enabled(idxd))
idxd_disable_system_pasid(idxd);
- idxd_unregister_devices(idxd);
for (i = 0; i < msixcnt; i++) {
irq_entry = &idxd->irq_entries[i];
@@ -815,7 +823,7 @@ static void idxd_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
destroy_workqueue(idxd->wq);
perfmon_pmu_remove(idxd);
- device_unregister(idxd_confdev(idxd));
+ put_device(idxd_confdev(idxd));
}
static struct pci_driver idxd_pci_driver = {
diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c
index ca88fa7a328e..17f2f8a31b63 100644
--- a/drivers/dma/idxd/irq.c
+++ b/drivers/dma/idxd/irq.c
@@ -63,6 +63,9 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
int i;
bool err = false;
+ if (cause & IDXD_INTC_HALT_STATE)
+ goto halt;
+
if (cause & IDXD_INTC_ERR) {
spin_lock(&idxd->dev_lock);
for (i = 0; i < 4; i++)
@@ -121,6 +124,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
if (!err)
return 0;
+halt:
gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET);
if (gensts.state == IDXD_DEVICE_STATE_HALT) {
idxd->state = IDXD_DEV_HALTED;
@@ -134,6 +138,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
queue_work(idxd->wq, &idxd->work);
} else {
spin_lock(&idxd->dev_lock);
+ idxd->state = IDXD_DEV_HALTED;
idxd_wqs_quiesce(idxd);
idxd_wqs_unmap_portal(idxd);
idxd_device_clear_state(idxd);
@@ -221,8 +226,7 @@ static void irq_process_work_list(struct idxd_irq_entry *irq_entry)
list_for_each_entry_safe(desc, n, &irq_entry->work_list, list) {
if (desc->completion->status) {
- list_del(&desc->list);
- list_add_tail(&desc->list, &flist);
+ list_move_tail(&desc->list, &flist);
}
}
diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h
index ffc7550a77ee..262c8220adbd 100644
--- a/drivers/dma/idxd/registers.h
+++ b/drivers/dma/idxd/registers.h
@@ -36,8 +36,7 @@ union gen_cap_reg {
u64 max_batch_shift:4;
u64 max_ims_mult:6;
u64 config_en:1;
- u64 max_descs_per_engine:8;
- u64 rsvd3:24;
+ u64 rsvd3:32;
};
u64 bits;
} __packed;
@@ -158,6 +157,7 @@ enum idxd_device_reset_type {
#define IDXD_INTC_CMD 0x02
#define IDXD_INTC_OCCUPY 0x04
#define IDXD_INTC_PERFMON_OVFL 0x08
+#define IDXD_INTC_HALT_STATE 0x10
#define IDXD_CMD_OFFSET 0xa0
union idxd_command_reg {
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index cacc725ca545..75ec0754d4ad 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -741,9 +741,8 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
unsigned long flags;
buf_virt = dma_alloc_coherent(sdma->dev, size, &buf_phys, GFP_KERNEL);
- if (!buf_virt) {
+ if (!buf_virt)
return -ENOMEM;
- }
spin_lock_irqsave(&sdma->channel_0_lock, flags);
@@ -1227,8 +1226,9 @@ static int sdma_config_channel(struct dma_chan *chan)
if (sdmac->peripheral_type == IMX_DMATYPE_ASRC_SP ||
sdmac->peripheral_type == IMX_DMATYPE_ASRC)
sdma_set_watermarklevel_for_p2p(sdmac);
- } else
+ } else {
__set_bit(sdmac->event_id0, sdmac->event_mask);
+ }
/* Address */
sdmac->shp_addr = sdmac->per_address;
@@ -1241,7 +1241,7 @@ static int sdma_config_channel(struct dma_chan *chan)
}
static int sdma_set_channel_priority(struct sdma_channel *sdmac,
- unsigned int priority)
+ unsigned int priority)
{
struct sdma_engine *sdma = sdmac->sdma;
int channel = sdmac->channel;
@@ -1261,7 +1261,7 @@ static int sdma_request_channel0(struct sdma_engine *sdma)
int ret = -EBUSY;
sdma->bd0 = dma_alloc_coherent(sdma->dev, PAGE_SIZE, &sdma->bd0_phys,
- GFP_NOWAIT);
+ GFP_NOWAIT);
if (!sdma->bd0) {
ret = -ENOMEM;
goto out;
@@ -1284,7 +1284,7 @@ static int sdma_alloc_bd(struct sdma_desc *desc)
int ret = 0;
desc->bd = dma_alloc_coherent(desc->sdmac->sdma->dev, bd_size,
- &desc->bd_phys, GFP_NOWAIT);
+ &desc->bd_phys, GFP_NOWAIT);
if (!desc->bd) {
ret = -ENOMEM;
goto out;
@@ -1757,7 +1757,7 @@ static void sdma_issue_pending(struct dma_chan *chan)
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V4 46
static void sdma_add_scripts(struct sdma_engine *sdma,
- const struct sdma_script_start_addrs *addr)
+ const struct sdma_script_start_addrs *addr)
{
s32 *addr_arr = (u32 *)addr;
s32 *saddr_arr = (u32 *)sdma->script_addrs;
@@ -1840,8 +1840,8 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
clk_enable(sdma->clk_ahb);
/* download the RAM image for SDMA */
sdma_load_script(sdma, ram_code,
- header->ram_code_size,
- addr->ram_code_start_addr);
+ header->ram_code_size,
+ addr->ram_code_start_addr);
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
@@ -1850,8 +1850,8 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
sdma->fw_loaded = true;
dev_info(sdma->dev, "loaded firmware %d.%d\n",
- header->version_major,
- header->version_minor);
+ header->version_major,
+ header->version_minor);
err_firmware:
release_firmware(fw);
@@ -1955,7 +1955,7 @@ static int sdma_init(struct sdma_engine *sdma)
writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
sdma->channel_control = dma_alloc_coherent(sdma->dev,
- MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) +
+ MAX_DMA_CHANNELS * sizeof(struct sdma_channel_control) +
sizeof(struct sdma_context_data),
&ccb_phys, GFP_KERNEL);
@@ -1965,9 +1965,9 @@ static int sdma_init(struct sdma_engine *sdma)
}
sdma->context = (void *)sdma->channel_control +
- MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control);
+ MAX_DMA_CHANNELS * sizeof(struct sdma_channel_control);
sdma->context_phys = ccb_phys +
- MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control);
+ MAX_DMA_CHANNELS * sizeof(struct sdma_channel_control);
/* disable all channels */
for (i = 0; i < sdma->drvdata->num_events; i++)
diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c
index 191b59279007..373b8dac6c9b 100644
--- a/drivers/dma/ioat/init.c
+++ b/drivers/dma/ioat/init.c
@@ -1363,15 +1363,9 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!iomap)
return -ENOMEM;
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (err)
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (err)
- return err;
-
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (err)
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (err)
return err;
diff --git a/drivers/dma/milbeaut-hdmac.c b/drivers/dma/milbeaut-hdmac.c
index a8cfb59f6efe..1b0a95892627 100644
--- a/drivers/dma/milbeaut-hdmac.c
+++ b/drivers/dma/milbeaut-hdmac.c
@@ -269,7 +269,7 @@ milbeaut_hdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
if (!md)
return NULL;
- md->sgl = kzalloc(sizeof(*sgl) * sg_len, GFP_NOWAIT);
+ md->sgl = kcalloc(sg_len, sizeof(*sgl), GFP_NOWAIT);
if (!md->sgl) {
kfree(md);
return NULL;
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 89f1814ff27a..a23563cd118b 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -1123,6 +1123,7 @@ static int mmp_pdma_probe(struct platform_device *op)
mmp_pdma_dma_xlate, pdev);
if (ret < 0) {
dev_err(&op->dev, "of_dma_controller_register failed\n");
+ dma_async_device_unregister(&pdev->device);
return ret;
}
}
diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c
index 166934544161..1ffcb5ca9788 100644
--- a/drivers/dma/plx_dma.c
+++ b/drivers/dma/plx_dma.c
@@ -563,15 +563,9 @@ static int plx_dma_probe(struct pci_dev *pdev,
if (rc)
return rc;
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(48));
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48));
if (rc)
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (rc)
- return rc;
-
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(48));
- if (rc)
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (rc)
return rc;
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
index c8a77b428b52..87f6ca1541cf 100644
--- a/drivers/dma/qcom/bam_dma.c
+++ b/drivers/dma/qcom/bam_dma.c
@@ -388,6 +388,8 @@ struct bam_device {
/* execution environment ID, from DT */
u32 ee;
bool controlled_remotely;
+ bool powered_remotely;
+ u32 active_channels;
const struct reg_offset_data *layout;
@@ -416,6 +418,44 @@ static inline void __iomem *bam_addr(struct bam_device *bdev, u32 pipe,
}
/**
+ * bam_reset() - reset and initialize BAM registers
+ * @bdev: bam device
+ */
+static void bam_reset(struct bam_device *bdev)
+{
+ u32 val;
+
+ /* s/w reset bam */
+ /* after reset all pipes are disabled and idle */
+ val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
+ val |= BAM_SW_RST;
+ writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
+ val &= ~BAM_SW_RST;
+ writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
+
+ /* make sure previous stores are visible before enabling BAM */
+ wmb();
+
+ /* enable bam */
+ val |= BAM_EN;
+ writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
+
+ /* set descriptor threshhold, start with 4 bytes */
+ writel_relaxed(DEFAULT_CNT_THRSHLD,
+ bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD));
+
+ /* Enable default set of h/w workarounds, ie all except BAM_FULL_PIPE */
+ writel_relaxed(BAM_CNFG_BITS_DEFAULT, bam_addr(bdev, 0, BAM_CNFG_BITS));
+
+ /* enable irqs for errors */
+ writel_relaxed(BAM_ERROR_EN | BAM_HRESP_ERR_EN,
+ bam_addr(bdev, 0, BAM_IRQ_EN));
+
+ /* unmask global bam interrupt */
+ writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
+}
+
+/**
* bam_reset_channel - Reset individual BAM DMA channel
* @bchan: bam channel
*
@@ -512,6 +552,9 @@ static int bam_alloc_chan(struct dma_chan *chan)
return -ENOMEM;
}
+ if (bdev->active_channels++ == 0 && bdev->powered_remotely)
+ bam_reset(bdev);
+
return 0;
}
@@ -565,6 +608,13 @@ static void bam_free_chan(struct dma_chan *chan)
/* disable irq */
writel_relaxed(0, bam_addr(bdev, bchan->id, BAM_P_IRQ_EN));
+ if (--bdev->active_channels == 0 && bdev->powered_remotely) {
+ /* s/w reset bam */
+ val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
+ val |= BAM_SW_RST;
+ writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
+ }
+
err:
pm_runtime_mark_last_busy(bdev->dev);
pm_runtime_put_autosuspend(bdev->dev);
@@ -1164,37 +1214,9 @@ static int bam_init(struct bam_device *bdev)
bdev->num_channels = val & BAM_NUM_PIPES_MASK;
}
- if (bdev->controlled_remotely)
- return 0;
-
- /* s/w reset bam */
- /* after reset all pipes are disabled and idle */
- val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
- val |= BAM_SW_RST;
- writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
- val &= ~BAM_SW_RST;
- writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
-
- /* make sure previous stores are visible before enabling BAM */
- wmb();
-
- /* enable bam */
- val |= BAM_EN;
- writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
-
- /* set descriptor threshhold, start with 4 bytes */
- writel_relaxed(DEFAULT_CNT_THRSHLD,
- bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD));
-
- /* Enable default set of h/w workarounds, ie all except BAM_FULL_PIPE */
- writel_relaxed(BAM_CNFG_BITS_DEFAULT, bam_addr(bdev, 0, BAM_CNFG_BITS));
-
- /* enable irqs for errors */
- writel_relaxed(BAM_ERROR_EN | BAM_HRESP_ERR_EN,
- bam_addr(bdev, 0, BAM_IRQ_EN));
-
- /* unmask global bam interrupt */
- writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
+ /* Reset BAM now if fully controlled locally */
+ if (!bdev->controlled_remotely && !bdev->powered_remotely)
+ bam_reset(bdev);
return 0;
}
@@ -1257,8 +1279,10 @@ static int bam_dma_probe(struct platform_device *pdev)
bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node,
"qcom,controlled-remotely");
+ bdev->powered_remotely = of_property_read_bool(pdev->dev.of_node,
+ "qcom,powered-remotely");
- if (bdev->controlled_remotely) {
+ if (bdev->controlled_remotely || bdev->powered_remotely) {
ret = of_property_read_u32(pdev->dev.of_node, "num-channels",
&bdev->num_channels);
if (ret)
@@ -1270,7 +1294,7 @@ static int bam_dma_probe(struct platform_device *pdev)
dev_err(bdev->dev, "num-ees unspecified in dt\n");
}
- if (bdev->controlled_remotely)
+ if (bdev->controlled_remotely || bdev->powered_remotely)
bdev->bamclk = devm_clk_get_optional(bdev->dev, "bam_clk");
else
bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index 1e918e284fc0..a29c13cae716 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -1001,7 +1001,7 @@ static int sa11x0_dma_remove(struct platform_device *pdev)
return 0;
}
-static int sa11x0_dma_suspend(struct device *dev)
+static __maybe_unused int sa11x0_dma_suspend(struct device *dev)
{
struct sa11x0_dma_dev *d = dev_get_drvdata(dev);
unsigned pch;
@@ -1039,7 +1039,7 @@ static int sa11x0_dma_suspend(struct device *dev)
return 0;
}
-static int sa11x0_dma_resume(struct device *dev)
+static __maybe_unused int sa11x0_dma_resume(struct device *dev)
{
struct sa11x0_dma_dev *d = dev_get_drvdata(dev);
unsigned pch;
@@ -1072,12 +1072,7 @@ static int sa11x0_dma_resume(struct device *dev)
}
static const struct dev_pm_ops sa11x0_dma_pm_ops = {
- .suspend_noirq = sa11x0_dma_suspend,
- .resume_noirq = sa11x0_dma_resume,
- .freeze_noirq = sa11x0_dma_suspend,
- .thaw_noirq = sa11x0_dma_resume,
- .poweroff_noirq = sa11x0_dma_suspend,
- .restore_noirq = sa11x0_dma_resume,
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sa11x0_dma_suspend, sa11x0_dma_resume)
};
static struct platform_driver sa11x0_dma_driver = {
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 6885b3dcd7a9..5c7716fd6bc5 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1916,7 +1916,7 @@ static int rcar_dmac_probe(struct platform_device *pdev)
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "runtime PM get sync failed (%d)\n", ret);
- return ret;
+ goto err_pm_disable;
}
ret = rcar_dmac_init(dmac);
@@ -1924,7 +1924,7 @@ static int rcar_dmac_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "failed to reset device\n");
- goto error;
+ goto err_pm_disable;
}
/* Initialize engine */
@@ -1958,14 +1958,14 @@ static int rcar_dmac_probe(struct platform_device *pdev)
for_each_rcar_dmac_chan(i, dmac, chan) {
ret = rcar_dmac_chan_probe(dmac, chan);
if (ret < 0)
- goto error;
+ goto err_pm_disable;
}
/* Register the DMAC as a DMA provider for DT. */
ret = of_dma_controller_register(pdev->dev.of_node, rcar_dmac_of_xlate,
NULL);
if (ret < 0)
- goto error;
+ goto err_pm_disable;
/*
* Register the DMA engine device.
@@ -1974,12 +1974,13 @@ static int rcar_dmac_probe(struct platform_device *pdev)
*/
ret = dma_async_device_register(engine);
if (ret < 0)
- goto error;
+ goto err_dma_free;
return 0;
-error:
+err_dma_free:
of_dma_controller_free(pdev->dev.of_node);
+err_pm_disable:
pm_runtime_disable(&pdev->dev);
return ret;
}
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index f9f30cbeccbe..ee2872e7d64c 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -18,6 +18,7 @@
#include <linux/of_dma.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -573,7 +574,7 @@ static void rz_dmac_issue_pending(struct dma_chan *chan)
static u8 rz_dmac_ds_to_val_mapping(enum dma_slave_buswidth ds)
{
u8 i;
- const enum dma_slave_buswidth ds_lut[] = {
+ static const enum dma_slave_buswidth ds_lut[] = {
DMA_SLAVE_BUSWIDTH_1_BYTE,
DMA_SLAVE_BUSWIDTH_2_BYTES,
DMA_SLAVE_BUSWIDTH_4_BYTES,
@@ -872,6 +873,13 @@ static int rz_dmac_probe(struct platform_device *pdev)
/* Initialize the channels. */
INIT_LIST_HEAD(&dmac->engine.channels);
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "pm_runtime_resume_and_get failed\n");
+ goto err_pm_disable;
+ }
+
for (i = 0; i < dmac->n_channels; i++) {
ret = rz_dmac_chan_probe(dmac, &dmac->channels[i], i);
if (ret < 0)
@@ -925,6 +933,10 @@ err:
channel->lmdesc.base_dma);
}
+ pm_runtime_put(&pdev->dev);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+
return ret;
}
@@ -943,6 +955,8 @@ static int rz_dmac_remove(struct platform_device *pdev)
}
of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&dmac->engine);
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index 9063c727962e..83a37a6955a3 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -270,7 +270,6 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len,
u32 threshold)
{
enum dma_slave_buswidth max_width;
- u64 addr = buf_addr;
if (threshold == STM32_DMA_FIFO_THRESHOLD_FULL)
max_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -281,7 +280,7 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len,
max_width > DMA_SLAVE_BUSWIDTH_1_BYTE)
max_width = max_width >> 1;
- if (do_div(addr, max_width))
+ if (buf_addr & (max_width - 1))
max_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
return max_width;
@@ -497,6 +496,7 @@ static int stm32_dma_terminate_all(struct dma_chan *c)
spin_lock_irqsave(&chan->vchan.lock, flags);
if (chan->desc) {
+ dma_cookie_complete(&chan->desc->vdesc.tx);
vchan_terminate_vdesc(&chan->desc->vdesc);
if (chan->busy)
stm32_dma_stop(chan);
@@ -753,8 +753,14 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
if (src_bus_width < 0)
return src_bus_width;
- /* Set memory burst size */
- src_maxburst = STM32_DMA_MAX_BURST;
+ /*
+ * Set memory burst size - burst not possible if address is not aligned on
+ * the address boundary equal to the size of the transfer
+ */
+ if (buf_addr & (buf_len - 1))
+ src_maxburst = 1;
+ else
+ src_maxburst = STM32_DMA_MAX_BURST;
src_best_burst = stm32_dma_get_best_burst(buf_len,
src_maxburst,
fifoth,
@@ -803,8 +809,14 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
if (dst_bus_width < 0)
return dst_bus_width;
- /* Set memory burst size */
- dst_maxburst = STM32_DMA_MAX_BURST;
+ /*
+ * Set memory burst size - burst not possible if address is not aligned on
+ * the address boundary equal to the size of the transfer
+ */
+ if (buf_addr & (buf_len - 1))
+ dst_maxburst = 1;
+ else
+ dst_maxburst = STM32_DMA_MAX_BURST;
dst_best_burst = stm32_dma_get_best_burst(buf_len,
dst_maxburst,
fifoth,
diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c
index 18cbd1e43c2e..d30a4a28d3bf 100644
--- a/drivers/dma/stm32-mdma.c
+++ b/drivers/dma/stm32-mdma.c
@@ -1566,7 +1566,8 @@ static int stm32_mdma_probe(struct platform_device *pdev)
if (count < 0)
count = 0;
- dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev) + sizeof(u32) * count,
+ dmadev = devm_kzalloc(&pdev->dev,
+ struct_size(dmadev, ahb_addr_masks, count),
GFP_KERNEL);
if (!dmadev)
return -ENOMEM;
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index b1115a6d1935..ae39b52012b2 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -43,10 +43,8 @@
#define TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(reqs) (reqs << 4)
#define ADMA_CH_FIFO_CTRL 0x2c
-#define TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(val) (((val) & 0xf) << 8)
-#define TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(val) ((val) & 0xf)
-#define TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(val) (((val) & 0x1f) << 8)
-#define TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(val) ((val) & 0x1f)
+#define ADMA_CH_TX_FIFO_SIZE_SHIFT 8
+#define ADMA_CH_RX_FIFO_SIZE_SHIFT 0
#define ADMA_CH_LOWER_SRC_ADDR 0x34
#define ADMA_CH_LOWER_TRG_ADDR 0x3c
@@ -61,29 +59,26 @@
#define TEGRA_ADMA_BURST_COMPLETE_TIME 20
-#define TEGRA210_FIFO_CTRL_DEFAULT (TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \
- TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(3))
-
-#define TEGRA186_FIFO_CTRL_DEFAULT (TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \
- TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(3))
-
#define ADMA_CH_REG_FIELD_VAL(val, mask, shift) (((val) & mask) << shift)
struct tegra_adma;
/*
* struct tegra_adma_chip_data - Tegra chip specific data
+ * @adma_get_burst_config: Function callback used to set DMA burst size.
* @global_reg_offset: Register offset of DMA global register.
* @global_int_clear: Register offset of DMA global interrupt clear.
* @ch_req_tx_shift: Register offset for AHUB transmit channel select.
* @ch_req_rx_shift: Register offset for AHUB receive channel select.
* @ch_base_offset: Register offset of DMA channel registers.
- * @has_outstanding_reqs: If DMA channel can have outstanding requests.
* @ch_fifo_ctrl: Default value for channel FIFO CTRL register.
* @ch_req_mask: Mask for Tx or Rx channel select.
* @ch_req_max: Maximum number of Tx or Rx channels available.
* @ch_reg_size: Size of DMA channel register space.
* @nr_channels: Number of DMA channels available.
+ * @ch_fifo_size_mask: Mask for FIFO size field.
+ * @sreq_index_offset: Slave channel index offset.
+ * @has_outstanding_reqs: If DMA channel can have outstanding requests.
*/
struct tegra_adma_chip_data {
unsigned int (*adma_get_burst_config)(unsigned int burst_size);
@@ -97,6 +92,8 @@ struct tegra_adma_chip_data {
unsigned int ch_req_max;
unsigned int ch_reg_size;
unsigned int nr_channels;
+ unsigned int ch_fifo_size_mask;
+ unsigned int sreq_index_offset;
bool has_outstanding_reqs;
};
@@ -560,13 +557,14 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
{
struct tegra_adma_chan_regs *ch_regs = &desc->ch_regs;
const struct tegra_adma_chip_data *cdata = tdc->tdma->cdata;
- unsigned int burst_size, adma_dir;
+ unsigned int burst_size, adma_dir, fifo_size_shift;
if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS)
return -EINVAL;
switch (direction) {
case DMA_MEM_TO_DEV:
+ fifo_size_shift = ADMA_CH_TX_FIFO_SIZE_SHIFT;
adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
burst_size = tdc->sconfig.dst_maxburst;
ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
@@ -577,6 +575,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
break;
case DMA_DEV_TO_MEM:
+ fifo_size_shift = ADMA_CH_RX_FIFO_SIZE_SHIFT;
adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
burst_size = tdc->sconfig.src_maxburst;
ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
@@ -598,7 +597,27 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1);
if (cdata->has_outstanding_reqs)
ch_regs->config |= TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(8);
- ch_regs->fifo_ctrl = cdata->ch_fifo_ctrl;
+
+ /*
+ * 'sreq_index' represents the current ADMAIF channel number and as per
+ * HW recommendation its FIFO size should match with the corresponding
+ * ADMA channel.
+ *
+ * ADMA FIFO size is set as per below (based on default ADMAIF channel
+ * FIFO sizes):
+ * fifo_size = 0x2 (sreq_index > sreq_index_offset)
+ * fifo_size = 0x3 (sreq_index <= sreq_index_offset)
+ *
+ */
+ if (tdc->sreq_index > cdata->sreq_index_offset)
+ ch_regs->fifo_ctrl =
+ ADMA_CH_REG_FIELD_VAL(2, cdata->ch_fifo_size_mask,
+ fifo_size_shift);
+ else
+ ch_regs->fifo_ctrl =
+ ADMA_CH_REG_FIELD_VAL(3, cdata->ch_fifo_size_mask,
+ fifo_size_shift);
+
ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK;
return tegra_adma_request_alloc(tdc, direction);
@@ -782,12 +801,13 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
.ch_req_tx_shift = 28,
.ch_req_rx_shift = 24,
.ch_base_offset = 0,
- .has_outstanding_reqs = false,
- .ch_fifo_ctrl = TEGRA210_FIFO_CTRL_DEFAULT,
.ch_req_mask = 0xf,
.ch_req_max = 10,
.ch_reg_size = 0x80,
.nr_channels = 22,
+ .ch_fifo_size_mask = 0xf,
+ .sreq_index_offset = 2,
+ .has_outstanding_reqs = false,
};
static const struct tegra_adma_chip_data tegra186_chip_data = {
@@ -797,12 +817,13 @@ static const struct tegra_adma_chip_data tegra186_chip_data = {
.ch_req_tx_shift = 27,
.ch_req_rx_shift = 22,
.ch_base_offset = 0x10000,
- .has_outstanding_reqs = true,
- .ch_fifo_ctrl = TEGRA186_FIFO_CTRL_DEFAULT,
.ch_req_mask = 0x1f,
.ch_req_max = 20,
.ch_reg_size = 0x100,
.nr_channels = 32,
+ .ch_fifo_size_mask = 0x1f,
+ .sreq_index_offset = 4,
+ .has_outstanding_reqs = true,
};
static const struct of_device_id tegra_adma_of_match[] = {
@@ -867,7 +888,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
- ret = pm_runtime_get_sync(&pdev->dev);
+ ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0)
goto rpm_disable;
@@ -940,7 +961,6 @@ static int tegra_adma_remove(struct platform_device *pdev)
for (i = 0; i < tdma->nr_channels; ++i)
irq_dispose_mapping(tdma->channels[i].irq);
- pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index a35858610780..041d8e32d630 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -1348,6 +1348,7 @@ static int bcdma_get_bchan(struct udma_chan *uc)
{
struct udma_dev *ud = uc->ud;
enum udma_tp_level tpl;
+ int ret;
if (uc->bchan) {
dev_dbg(ud->dev, "chan%d: already have bchan%d allocated\n",
@@ -1365,8 +1366,11 @@ static int bcdma_get_bchan(struct udma_chan *uc)
tpl = ud->bchan_tpl.levels - 1;
uc->bchan = __udma_reserve_bchan(ud, tpl, -1);
- if (IS_ERR(uc->bchan))
- return PTR_ERR(uc->bchan);
+ if (IS_ERR(uc->bchan)) {
+ ret = PTR_ERR(uc->bchan);
+ uc->bchan = NULL;
+ return ret;
+ }
uc->tchan = uc->bchan;
@@ -1376,6 +1380,7 @@ static int bcdma_get_bchan(struct udma_chan *uc)
static int udma_get_tchan(struct udma_chan *uc)
{
struct udma_dev *ud = uc->ud;
+ int ret;
if (uc->tchan) {
dev_dbg(ud->dev, "chan%d: already have tchan%d allocated\n",
@@ -1390,8 +1395,11 @@ static int udma_get_tchan(struct udma_chan *uc)
*/
uc->tchan = __udma_reserve_tchan(ud, uc->config.channel_tpl,
uc->config.mapped_channel_id);
- if (IS_ERR(uc->tchan))
- return PTR_ERR(uc->tchan);
+ if (IS_ERR(uc->tchan)) {
+ ret = PTR_ERR(uc->tchan);
+ uc->tchan = NULL;
+ return ret;
+ }
if (ud->tflow_cnt) {
int tflow_id;
@@ -1421,6 +1429,7 @@ static int udma_get_tchan(struct udma_chan *uc)
static int udma_get_rchan(struct udma_chan *uc)
{
struct udma_dev *ud = uc->ud;
+ int ret;
if (uc->rchan) {
dev_dbg(ud->dev, "chan%d: already have rchan%d allocated\n",
@@ -1435,8 +1444,13 @@ static int udma_get_rchan(struct udma_chan *uc)
*/
uc->rchan = __udma_reserve_rchan(ud, uc->config.channel_tpl,
uc->config.mapped_channel_id);
+ if (IS_ERR(uc->rchan)) {
+ ret = PTR_ERR(uc->rchan);
+ uc->rchan = NULL;
+ return ret;
+ }
- return PTR_ERR_OR_ZERO(uc->rchan);
+ return 0;
}
static int udma_get_chan_pair(struct udma_chan *uc)
@@ -1490,6 +1504,7 @@ static int udma_get_chan_pair(struct udma_chan *uc)
static int udma_get_rflow(struct udma_chan *uc, int flow_id)
{
struct udma_dev *ud = uc->ud;
+ int ret;
if (!uc->rchan) {
dev_err(ud->dev, "chan%d: does not have rchan??\n", uc->id);
@@ -1503,8 +1518,13 @@ static int udma_get_rflow(struct udma_chan *uc, int flow_id)
}
uc->rflow = __udma_get_rflow(ud, flow_id);
+ if (IS_ERR(uc->rflow)) {
+ ret = PTR_ERR(uc->rflow);
+ uc->rflow = NULL;
+ return ret;
+ }
- return PTR_ERR_OR_ZERO(uc->rflow);
+ return 0;
}
static void bcdma_put_bchan(struct udma_chan *uc)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index a4450bc95466..4677ce08ed40 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -792,7 +792,7 @@ static void xilinx_vdma_free_tx_segment(struct xilinx_dma_chan *chan,
}
/**
- * xilinx_dma_tx_descriptor - Allocate transaction descriptor
+ * xilinx_dma_alloc_tx_descriptor - Allocate transaction descriptor
* @chan: Driver specific DMA channel
*
* Return: The allocated descriptor on success and NULL on failure.
@@ -998,14 +998,12 @@ static void xilinx_dma_chan_handle_cyclic(struct xilinx_dma_chan *chan,
struct xilinx_dma_tx_descriptor *desc,
unsigned long *flags)
{
- dma_async_tx_callback callback;
- void *callback_param;
+ struct dmaengine_desc_callback cb;
- callback = desc->async_tx.callback;
- callback_param = desc->async_tx.callback_param;
- if (callback) {
+ dmaengine_desc_get_callback(&desc->async_tx, &cb);
+ if (dmaengine_desc_callback_valid(&cb)) {
spin_unlock_irqrestore(&chan->lock, *flags);
- callback(callback_param);
+ dmaengine_desc_callback_invoke(&cb, NULL);
spin_lock_irqsave(&chan->lock, *flags);
}
}
@@ -2483,7 +2481,7 @@ static void xilinx_dma_synchronize(struct dma_chan *dchan)
}
/**
- * xilinx_dma_channel_set_config - Configure VDMA channel
+ * xilinx_vdma_channel_set_config - Configure VDMA channel
* Run-time configuration for Axi VDMA, supports:
* . halt the channel
* . configure interrupt coalescing and inter-packet delay threshold
diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c
index b280a53e8570..ce5c66e6897d 100644
--- a/drivers/dma/xilinx/xilinx_dpdma.c
+++ b/drivers/dma/xilinx/xilinx_dpdma.c
@@ -271,9 +271,6 @@ struct xilinx_dpdma_device {
/* -----------------------------------------------------------------------------
* DebugFS
*/
-
-#ifdef CONFIG_DEBUG_FS
-
#define XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE 32
#define XILINX_DPDMA_DEBUGFS_UINT16_MAX_STR "65535"
@@ -299,7 +296,7 @@ struct xilinx_dpdma_debugfs_request {
static void xilinx_dpdma_debugfs_desc_done_irq(struct xilinx_dpdma_chan *chan)
{
- if (chan->id == dpdma_debugfs.chan_id)
+ if (IS_ENABLED(CONFIG_DEBUG_FS) && chan->id == dpdma_debugfs.chan_id)
dpdma_debugfs.xilinx_dpdma_irq_done_count++;
}
@@ -462,16 +459,6 @@ static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev)
dev_err(xdev->dev, "Failed to create debugfs testcase file\n");
}
-#else
-static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev)
-{
-}
-
-static void xilinx_dpdma_debugfs_desc_done_irq(struct xilinx_dpdma_chan *chan)
-{
-}
-#endif /* CONFIG_DEBUG_FS */
-
/* -----------------------------------------------------------------------------
* I/O Accessors
*/
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index 97f02f8eb03a..7aa63b652027 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -6,15 +6,12 @@
*/
#include <linux/bitops.h>
-#include <linux/dmapool.h>
-#include <linux/dma/xilinx_dma.h>
+#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/of_address.h>
#include <linux/of_dma.h>
-#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
#include <linux/clk.h>
@@ -603,22 +600,25 @@ static void zynqmp_dma_start_transfer(struct zynqmp_dma_chan *chan)
static void zynqmp_dma_chan_desc_cleanup(struct zynqmp_dma_chan *chan)
{
struct zynqmp_dma_desc_sw *desc, *next;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&chan->lock, irqflags);
list_for_each_entry_safe(desc, next, &chan->done_list, node) {
- dma_async_tx_callback callback;
- void *callback_param;
-
- callback = desc->async_tx.callback;
- callback_param = desc->async_tx.callback_param;
- if (callback) {
- spin_unlock(&chan->lock);
- callback(callback_param);
- spin_lock(&chan->lock);
+ struct dmaengine_desc_callback cb;
+
+ dmaengine_desc_get_callback(&desc->async_tx, &cb);
+ if (dmaengine_desc_callback_valid(&cb)) {
+ spin_unlock_irqrestore(&chan->lock, irqflags);
+ dmaengine_desc_callback_invoke(&cb, NULL);
+ spin_lock_irqsave(&chan->lock, irqflags);
}
/* Run any dependencies, then free the descriptor */
zynqmp_dma_free_descriptor(chan, desc);
}
+
+ spin_unlock_irqrestore(&chan->lock, irqflags);
}
/**
@@ -658,9 +658,13 @@ static void zynqmp_dma_issue_pending(struct dma_chan *dchan)
*/
static void zynqmp_dma_free_descriptors(struct zynqmp_dma_chan *chan)
{
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&chan->lock, irqflags);
zynqmp_dma_free_desc_list(chan, &chan->active_list);
zynqmp_dma_free_desc_list(chan, &chan->pending_list);
zynqmp_dma_free_desc_list(chan, &chan->done_list);
+ spin_unlock_irqrestore(&chan->lock, irqflags);
}
/**
@@ -670,11 +674,8 @@ static void zynqmp_dma_free_descriptors(struct zynqmp_dma_chan *chan)
static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan)
{
struct zynqmp_dma_chan *chan = to_chan(dchan);
- unsigned long irqflags;
- spin_lock_irqsave(&chan->lock, irqflags);
zynqmp_dma_free_descriptors(chan);
- spin_unlock_irqrestore(&chan->lock, irqflags);
dma_free_coherent(chan->dev,
(2 * ZYNQMP_DMA_DESC_SIZE(chan) * ZYNQMP_DMA_NUM_DESCS),
chan->desc_pool_v, chan->desc_pool_p);
@@ -689,11 +690,16 @@ static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan)
*/
static void zynqmp_dma_reset(struct zynqmp_dma_chan *chan)
{
+ unsigned long irqflags;
+
writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
+ spin_lock_irqsave(&chan->lock, irqflags);
zynqmp_dma_complete_descriptor(chan);
+ spin_unlock_irqrestore(&chan->lock, irqflags);
zynqmp_dma_chan_desc_cleanup(chan);
zynqmp_dma_free_descriptors(chan);
+
zynqmp_dma_init(chan);
}
@@ -749,27 +755,27 @@ static void zynqmp_dma_do_tasklet(struct tasklet_struct *t)
u32 count;
unsigned long irqflags;
- spin_lock_irqsave(&chan->lock, irqflags);
-
if (chan->err) {
zynqmp_dma_reset(chan);
chan->err = false;
- goto unlock;
+ return;
}
+ spin_lock_irqsave(&chan->lock, irqflags);
count = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
-
while (count) {
zynqmp_dma_complete_descriptor(chan);
- zynqmp_dma_chan_desc_cleanup(chan);
count--;
}
+ spin_unlock_irqrestore(&chan->lock, irqflags);
- if (chan->idle)
- zynqmp_dma_start_transfer(chan);
+ zynqmp_dma_chan_desc_cleanup(chan);
-unlock:
- spin_unlock_irqrestore(&chan->lock, irqflags);
+ if (chan->idle) {
+ spin_lock_irqsave(&chan->lock, irqflags);
+ zynqmp_dma_start_transfer(chan);
+ spin_unlock_irqrestore(&chan->lock, irqflags);
+ }
}
/**
@@ -781,12 +787,9 @@ unlock:
static int zynqmp_dma_device_terminate_all(struct dma_chan *dchan)
{
struct zynqmp_dma_chan *chan = to_chan(dchan);
- unsigned long irqflags;
- spin_lock_irqsave(&chan->lock, irqflags);
writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
zynqmp_dma_free_descriptors(chan);
- spin_unlock_irqrestore(&chan->lock, irqflags);
return 0;
}
@@ -1061,16 +1064,14 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
p->dev = &pdev->dev;
zdev->clk_main = devm_clk_get(&pdev->dev, "clk_main");
- if (IS_ERR(zdev->clk_main)) {
- dev_err(&pdev->dev, "main clock not found.\n");
- return PTR_ERR(zdev->clk_main);
- }
+ if (IS_ERR(zdev->clk_main))
+ return dev_err_probe(&pdev->dev, PTR_ERR(zdev->clk_main),
+ "main clock not found.\n");
zdev->clk_apb = devm_clk_get(&pdev->dev, "clk_apb");
- if (IS_ERR(zdev->clk_apb)) {
- dev_err(&pdev->dev, "apb clock not found.\n");
- return PTR_ERR(zdev->clk_apb);
- }
+ if (IS_ERR(zdev->clk_apb))
+ return dev_err_probe(&pdev->dev, PTR_ERR(zdev->clk_apb),
+ "apb clock not found.\n");
platform_set_drvdata(pdev, zdev);
pm_runtime_set_autosuspend_delay(zdev->dev, ZDMA_PM_TIMEOUT);
@@ -1085,7 +1086,7 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
ret = zynqmp_dma_chan_probe(zdev, pdev);
if (ret) {
- dev_err(&pdev->dev, "Probing channel failed\n");
+ dev_err_probe(&pdev->dev, ret, "Probing channel failed\n");
goto err_disable_pm;
}
@@ -1097,7 +1098,7 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
ret = of_dma_controller_register(pdev->dev.of_node,
of_zynqmp_dma_xlate, zdev);
if (ret) {
- dev_err(&pdev->dev, "Unable to register DMA to DT\n");
+ dev_err_probe(&pdev->dev, ret, "Unable to register DMA to DT\n");
dma_async_device_unregister(&zdev->common);
goto free_chan_resources;
}
@@ -1105,8 +1106,6 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
pm_runtime_mark_last_busy(zdev->dev);
pm_runtime_put_sync_autosuspend(zdev->dev);
- dev_info(&pdev->dev, "ZynqMP DMA driver Probe success\n");
-
return 0;
free_chan_resources: