diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-15 14:33:52 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-15 14:33:52 -0700 |
| commit | f065199d4df0b1512f935621d2de128ddb3fcc3a (patch) | |
| tree | e337fac0a06e9eeb7657ca0dc5cce530d730d0c6 /drivers | |
| parent | c48b75b7271db23c1b2d1204d6e8496d91f27711 (diff) | |
| parent | fc143e38ddd47d3b01ac276786ee78edf053bf5d (diff) | |
| download | linux-f065199d4df0b1512f935621d2de128ddb3fcc3a.tar.gz linux-f065199d4df0b1512f935621d2de128ddb3fcc3a.tar.bz2 linux-f065199d4df0b1512f935621d2de128ddb3fcc3a.zip | |
Merge tag 'dmaengine-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine
Pull dmaengine updates from Vinod Koul:
"Core:
- Mark dma_request_slave_channel() deprecated in favour of
dma_request_chan()
- subsystem conversion for tasklet_setup() API
- subsystem removal of local dma_parms for arm drivers
Also updates to bunch of driver notably TI, DW and AXI-DMAC"
* tag 'dmaengine-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (104 commits)
dmaengine: owl-dma: fix kernel-doc style for enum
dmaengine: zynqmp_dma: fix kernel-doc style for tasklet
dmaengine: xilinx_dma: fix kernel-doc style for tasklet
dmaengine: qcom: bam_dma: fix kernel-doc style for tasklet
dmaengine: altera-msgdma: fix kernel-doc style for tasklet
dmaengine: xilinx: dpdma: convert tasklets to use new tasklet_setup() API
dmaengine: sf-pdma: convert tasklets to use new tasklet_setup() API
dt-bindings: Fix 'reg' size issues in zynqmp examples
dmaengine: rcar-dmac: drop double zeroing
dmaengine: sh: drop double zeroing
dmaengine: ioat: Allocate correct size for descriptor chunk
dmaengine: ti: k3-udma: use devm_platform_ioremap_resource_byname
dmaengine: fsl: remove bad channel update
dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status
dmaengine: pl330: fix argument for tasklet
dmaengine: dmatest: Return boolean result directly in filter()
dmaengine: dmatest: Check list for emptiness before access its last entry
dmaengine: ti: k3-udma-glue: fix channel enable functions
dmaengine: iop-adma: Fix pointer cast warnings
dmaengine: dw-edma: Fix Using plain integer as NULL pointer in dw-edma-v0-debugfs.c
...
Diffstat (limited to 'drivers')
76 files changed, 893 insertions, 427 deletions
diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c index 321ac3a7aa41..9a841ce5f0c5 100644 --- a/drivers/dma/altera-msgdma.c +++ b/drivers/dma/altera-msgdma.c @@ -678,11 +678,11 @@ static int msgdma_alloc_chan_resources(struct dma_chan *dchan) /** * msgdma_tasklet - Schedule completion tasklet - * @data: Pointer to the Altera sSGDMA channel structure + * @t: Pointer to the Altera sSGDMA channel structure */ -static void msgdma_tasklet(unsigned long data) +static void msgdma_tasklet(struct tasklet_struct *t) { - struct msgdma_device *mdev = (struct msgdma_device *)data; + struct msgdma_device *mdev = from_tasklet(mdev, t, irq_tasklet); u32 count; u32 __maybe_unused size; u32 __maybe_unused status; @@ -830,7 +830,7 @@ static int msgdma_probe(struct platform_device *pdev) if (ret) return ret; - tasklet_init(&mdev->irq_tasklet, msgdma_tasklet, (unsigned long)mdev); + tasklet_setup(&mdev->irq_tasklet, msgdma_tasklet); dma_cookie_init(&mdev->dmachan); diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index a2cf25c6e3b3..7eaee5b705b1 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -598,9 +598,9 @@ static void atc_handle_cyclic(struct at_dma_chan *atchan) /*-- IRQ & Tasklet ---------------------------------------------------*/ -static void atc_tasklet(unsigned long data) +static void atc_tasklet(struct tasklet_struct *t) { - struct at_dma_chan *atchan = (struct at_dma_chan *)data; + struct at_dma_chan *atchan = from_tasklet(atchan, t, tasklet); if (test_and_clear_bit(ATC_IS_ERROR, &atchan->status)) return atc_handle_error(atchan); @@ -1892,8 +1892,7 @@ static int __init at_dma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&atchan->queue); INIT_LIST_HEAD(&atchan->free_list); - tasklet_init(&atchan->tasklet, atc_tasklet, - (unsigned long)atchan); + tasklet_setup(&atchan->tasklet, atc_tasklet); atc_enable_chan_irq(atdma, i); } diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index fd92f048c491..3b53115db268 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -1613,9 +1613,9 @@ static void at_xdmac_handle_error(struct at_xdmac_chan *atchan) /* Then continue with usual descriptor management */ } -static void at_xdmac_tasklet(unsigned long data) +static void at_xdmac_tasklet(struct tasklet_struct *t) { - struct at_xdmac_chan *atchan = (struct at_xdmac_chan *)data; + struct at_xdmac_chan *atchan = from_tasklet(atchan, t, tasklet); struct at_xdmac_desc *desc; u32 error_mask; @@ -2063,8 +2063,7 @@ static int at_xdmac_probe(struct platform_device *pdev) spin_lock_init(&atchan->lock); INIT_LIST_HEAD(&atchan->xfers_list); INIT_LIST_HEAD(&atchan->free_descs_list); - tasklet_init(&atchan->tasklet, at_xdmac_tasklet, - (unsigned long)atchan); + tasklet_setup(&atchan->tasklet, at_xdmac_tasklet); /* Clear pending interrupts. */ while (at_xdmac_chan_read(atchan, AT_XDMAC_CIS)) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 4768ef26013b..630dfbb01a40 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -41,14 +41,12 @@ * struct bcm2835_dmadev - BCM2835 DMA controller * @ddev: DMA device * @base: base address of register map - * @dma_parms: DMA parameters (to convey 1 GByte max segment size to clients) * @zero_page: bus address of zero page (to detect transactions copying from * zero page and avoid accessing memory if so) */ struct bcm2835_dmadev { struct dma_device ddev; void __iomem *base; - struct device_dma_parameters dma_parms; dma_addr_t zero_page; }; @@ -902,7 +900,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) if (!od) return -ENOMEM; - pdev->dev.dma_parms = &od->dma_parms; dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 1092d4ce723e..95b9b2f5358e 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -1868,9 +1868,9 @@ static struct coh901318_desc *coh901318_queue_start(struct coh901318_chan *cohc) * This tasklet is called from the interrupt handler to * handle each descriptor (DMA job) that is sent to a channel. */ -static void dma_tasklet(unsigned long data) +static void dma_tasklet(struct tasklet_struct *t) { - struct coh901318_chan *cohc = (struct coh901318_chan *) data; + struct coh901318_chan *cohc = from_tasklet(cohc, t, tasklet); struct coh901318_desc *cohd_fin; unsigned long flags; struct dmaengine_desc_callback cb; @@ -2615,8 +2615,7 @@ static void coh901318_base_init(struct dma_device *dma, const int *pick_chans, INIT_LIST_HEAD(&cohc->active); INIT_LIST_HEAD(&cohc->queue); - tasklet_init(&cohc->tasklet, dma_tasklet, - (unsigned long) cohc); + tasklet_setup(&cohc->tasklet, dma_tasklet); list_add_tail(&cohc->chan.device_node, &dma->channels); diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index f1d149e32839..5161b73c30c4 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -6,6 +6,7 @@ * Author: Lars-Peter Clausen <lars@metafoo.de> */ +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/device.h> #include <linux/dma-mapping.h> @@ -45,6 +46,16 @@ * there is no address than can or needs to be configured for the device side. */ +#define AXI_DMAC_REG_INTERFACE_DESC 0x10 +#define AXI_DMAC_DMA_SRC_TYPE_MSK GENMASK(13, 12) +#define AXI_DMAC_DMA_SRC_TYPE_GET(x) FIELD_GET(AXI_DMAC_DMA_SRC_TYPE_MSK, x) +#define AXI_DMAC_DMA_SRC_WIDTH_MSK GENMASK(11, 8) +#define AXI_DMAC_DMA_SRC_WIDTH_GET(x) FIELD_GET(AXI_DMAC_DMA_SRC_WIDTH_MSK, x) +#define AXI_DMAC_DMA_DST_TYPE_MSK GENMASK(5, 4) +#define AXI_DMAC_DMA_DST_TYPE_GET(x) FIELD_GET(AXI_DMAC_DMA_DST_TYPE_MSK, x) +#define AXI_DMAC_DMA_DST_WIDTH_MSK GENMASK(3, 0) +#define AXI_DMAC_DMA_DST_WIDTH_GET(x) FIELD_GET(AXI_DMAC_DMA_DST_WIDTH_MSK, x) + #define AXI_DMAC_REG_IRQ_MASK 0x80 #define AXI_DMAC_REG_IRQ_PENDING 0x84 #define AXI_DMAC_REG_IRQ_SOURCE 0x88 @@ -134,8 +145,6 @@ struct axi_dmac { struct dma_device dma_dev; struct axi_dmac_chan chan; - - struct device_dma_parameters dma_parms; }; static struct axi_dmac *chan_to_axi_dmac(struct axi_dmac_chan *chan) @@ -717,6 +726,20 @@ static const struct regmap_config axi_dmac_regmap_config = { .writeable_reg = axi_dmac_regmap_rdwr, }; +static void axi_dmac_adjust_chan_params(struct axi_dmac_chan *chan) +{ + chan->address_align_mask = max(chan->dest_width, chan->src_width) - 1; + + if (axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan)) + chan->direction = DMA_MEM_TO_MEM; + else if (!axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan)) + chan->direction = DMA_MEM_TO_DEV; + else if (axi_dmac_dest_is_mem(chan) && !axi_dmac_src_is_mem(chan)) + chan->direction = DMA_DEV_TO_MEM; + else + chan->direction = DMA_DEV_TO_DEV; +} + /* * The configuration stored in the devicetree matches the configuration * parameters of the peripheral instance and allows the driver to know which @@ -760,26 +783,81 @@ static int axi_dmac_parse_chan_dt(struct device_node *of_chan, return ret; chan->dest_width = val / 8; - chan->address_align_mask = max(chan->dest_width, chan->src_width) - 1; + axi_dmac_adjust_chan_params(chan); - if (axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan)) - chan->direction = DMA_MEM_TO_MEM; - else if (!axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan)) - chan->direction = DMA_MEM_TO_DEV; - else if (axi_dmac_dest_is_mem(chan) && !axi_dmac_src_is_mem(chan)) - chan->direction = DMA_DEV_TO_MEM; - else - chan->direction = DMA_DEV_TO_DEV; + return 0; +} + +static int axi_dmac_parse_dt(struct device *dev, struct axi_dmac *dmac) +{ + struct device_node *of_channels, *of_chan; + int ret; + + of_channels = of_get_child_by_name(dev->of_node, "adi,channels"); + if (of_channels == NULL) + return -ENODEV; + + for_each_child_of_node(of_channels, of_chan) { + ret = axi_dmac_parse_chan_dt(of_chan, &dmac->chan); + if (ret) { + of_node_put(of_chan); + of_node_put(of_channels); + return -EINVAL; + } + } + of_node_put(of_channels); return 0; } -static int axi_dmac_detect_caps(struct axi_dmac *dmac) +static int axi_dmac_read_chan_config(struct device *dev, struct axi_dmac *dmac) { struct axi_dmac_chan *chan = &dmac->chan; - unsigned int version; + unsigned int val, desc; - version = axi_dmac_read(dmac, ADI_AXI_REG_VERSION); + desc = axi_dmac_read(dmac, AXI_DMAC_REG_INTERFACE_DESC); + if (desc == 0) { + dev_err(dev, "DMA interface register reads zero\n"); + return -EFAULT; + } + + val = AXI_DMAC_DMA_SRC_TYPE_GET(desc); + if (val > AXI_DMAC_BUS_TYPE_FIFO) { + dev_err(dev, "Invalid source bus type read: %d\n", val); + return -EINVAL; + } + chan->src_type = val; + + val = AXI_DMAC_DMA_DST_TYPE_GET(desc); + if (val > AXI_DMAC_BUS_TYPE_FIFO) { + dev_err(dev, "Invalid destination bus type read: %d\n", val); + return -EINVAL; + } + chan->dest_type = val; + + val = AXI_DMAC_DMA_SRC_WIDTH_GET(desc); + if (val == 0) { + dev_err(dev, "Source bus width is zero\n"); + return -EINVAL; + } + /* widths are stored in log2 */ + chan->src_width = 1 << val; + + val = AXI_DMAC_DMA_DST_WIDTH_GET(desc); + if (val == 0) { + dev_err(dev, "Destination bus width is zero\n"); + return -EINVAL; + } + chan->dest_width = 1 << val; + + axi_dmac_adjust_chan_params(chan); + + return 0; +} + +static int axi_dmac_detect_caps(struct axi_dmac *dmac, unsigned int version) +{ + struct axi_dmac_chan *chan = &dmac->chan; axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, AXI_DMAC_FLAG_CYCLIC); if (axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS) == AXI_DMAC_FLAG_CYCLIC) @@ -826,11 +904,11 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac) static int axi_dmac_probe(struct platform_device *pdev) { - struct device_node *of_channels, *of_chan; struct dma_device *dma_dev; struct axi_dmac *dmac; struct resource *res; struct regmap *regmap; + unsigned int version; int ret; dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL); @@ -852,23 +930,22 @@ static int axi_dmac_probe(struct platform_device *pdev) if (IS_ERR(dmac->clk)) return PTR_ERR(dmac->clk); - INIT_LIST_HEAD(&dmac->chan.active_descs); + ret = clk_prepare_enable(dmac->clk); + if (ret < 0) + return ret; - of_channels = of_get_child_by_name(pdev->dev.of_node, "adi,channels"); - if (of_channels == NULL) - return -ENODEV; + version = axi_dmac_read(dmac, ADI_AXI_REG_VERSION); - for_each_child_of_node(of_channels, of_chan) { - ret = axi_dmac_parse_chan_dt(of_chan, &dmac->chan); - if (ret) { - of_node_put(of_chan); - of_node_put(of_channels); - return -EINVAL; - } - } - of_node_put(of_channels); + if (version >= ADI_AXI_PCORE_VER(4, 3, 'a')) + ret = axi_dmac_read_chan_config(&pdev->dev, dmac); + else + ret = axi_dmac_parse_dt(&pdev->dev, dmac); + + if (ret < 0) + goto err_clk_disable; + + INIT_LIST_HEAD(&dmac->chan.active_descs); - pdev->dev.dma_parms = &dmac->dma_parms; dma_set_max_seg_size(&pdev->dev, UINT_MAX); dma_dev = &dmac->dma_dev; @@ -894,11 +971,7 @@ static int axi_dmac_probe(struct platform_device *pdev) dmac->chan.vchan.desc_free = axi_dmac_desc_free; vchan_init(&dmac->chan.vchan, dma_dev); - ret = clk_prepare_enable(dmac->clk); - if (ret < 0) - return ret; - - ret = axi_dmac_detect_caps(dmac); + ret = axi_dmac_detect_caps(dmac, version); if (ret) goto err_clk_disable; diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c index 8beed91428bd..a608efaa435f 100644 --- a/drivers/dma/dma-jz4780.c +++ b/drivers/dma/dma-jz4780.c @@ -639,11 +639,11 @@ static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan, unsigned long flags; unsigned long residue = 0; + spin_lock_irqsave(&jzchan->vchan.lock, flags); + status = dma_cookie_status(chan, cookie, txstate); if ((status == DMA_COMPLETE) || (txstate == NULL)) - return status; - - spin_lock_irqsave(&jzchan->vchan.lock, flags); + goto out_unlock_irqrestore; vdesc = vchan_find_desc(&jzchan->vchan, cookie); if (vdesc) { @@ -660,6 +660,7 @@ static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan, && jzchan->desc->status & (JZ_DMA_DCS_AR | JZ_DMA_DCS_HLT)) status = DMA_ERROR; +out_unlock_irqrestore: spin_unlock_irqrestore(&jzchan->vchan.lock, flags); return status; } diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index a53e71d2bbd4..7974fa0400d8 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -847,8 +847,10 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name) } mutex_unlock(&dma_list_mutex); - if (IS_ERR_OR_NULL(chan)) - return chan ? chan : ERR_PTR(-EPROBE_DEFER); + if (IS_ERR(chan)) + return chan; + if (!chan) + return ERR_PTR(-EPROBE_DEFER); found: #ifdef CONFIG_DEBUG_FS @@ -872,24 +874,6 @@ found: EXPORT_SYMBOL_GPL(dma_request_chan); /** - * dma_request_slave_channel - try to allocate an exclusive slave channel - * @dev: pointer to client device structure - * @name: slave channel name - * - * Returns pointer to appropriate DMA channel on success or NULL. - */ -struct dma_chan *dma_request_slave_channel(struct device *dev, - const char *name) -{ - struct dma_chan *ch = dma_request_chan(dev, name); - if (IS_ERR(ch)) - return NULL; - - return ch; -} -EXPORT_SYMBOL_GPL(dma_request_slave_channel); - -/** * dma_request_chan_by_mask - allocate a channel satisfying certain capabilities * @mask: capabilities that the channel must satisfy * diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index a819611b8892..a3a172173e34 100644 --- a/drivers/dma/dmatest.c +++ b/ |
