diff options
81 files changed, 930 insertions, 437 deletions
diff --git a/Documentation/ABI/stable/sysfs-driver-dma-idxd b/Documentation/ABI/stable/sysfs-driver-dma-idxd index 1af9c4175213..b44183880935 100644 --- a/Documentation/ABI/stable/sysfs-driver-dma-idxd +++ b/Documentation/ABI/stable/sysfs-driver-dma-idxd @@ -116,6 +116,12 @@ Description: The maximum number of bandwidth tokens that may be in use at one time by operations that access low bandwidth memory in the device. +What: /sys/bus/dsa/devices/dsa<m>/cmd_status +Date: Aug 28, 2020 +KernelVersion: 5.10.0 +Contact: dmaengine@vger.kernel.org +Description: The last executed device administrative command's status/error. + What: /sys/bus/dsa/devices/wq<m>.<n>/group_id Date: Oct 25, 2019 KernelVersion: 5.6.0 @@ -170,6 +176,20 @@ Contact: dmaengine@vger.kernel.org Description: The number of entries in this work queue that may be filled via a limited portal. +What: /sys/bus/dsa/devices/wq<m>.<n>/max_transfer_size +Date: Aug 28, 2020 +KernelVersion: 5.10.0 +Contact: dmaengine@vger.kernel.org +Description: The max transfer sized for this workqueue. Cannot exceed device + max transfer size. Configurable parameter. + +What: /sys/bus/dsa/devices/wq<m>.<n>/max_batch_size +Date: Aug 28, 2020 +KernelVersion: 5.10.0 +Contact: dmaengine@vger.kernel.org +Description: The max batch size for this workqueue. Cannot exceed device + max batch size. Configurable parameter. + What: /sys/bus/dsa/devices/engine<m>.<n>/group_id Date: Oct 25, 2019 KernelVersion: 5.6.0 diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml index 13f1a46be40d..b548e4723936 100644 --- a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml +++ b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml @@ -16,6 +16,7 @@ properties: compatible: items: - enum: + - renesas,dmac-r8a7742 # RZ/G1H - renesas,dmac-r8a7743 # RZ/G1M - renesas,dmac-r8a7744 # RZ/G1N - renesas,dmac-r8a7745 # RZ/G1E diff --git a/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml b/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml index 20870f5c14dd..ef1d6879c158 100644 --- a/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml +++ b/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml @@ -18,12 +18,15 @@ properties: const: snps,dma-spear1340 "#dma-cells": - const: 3 + minimum: 3 + maximum: 4 description: | First cell is a phandle pointing to the DMA controller. Second one is the DMA request line number. Third cell is the memory master identifier for transfers on dynamically allocated channel. Fourth cell is the - peripheral master identifier for transfers on an allocated channel. + peripheral master identifier for transfers on an allocated channel. Fifth + cell is an optional mask of the DMA channels permitted to be allocated + for the corresponding client device. reg: maxItems: 1 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/drivers/dma/dmatest.c @@ -7,6 +7,7 @@ */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/err.h> #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> @@ -454,8 +455,13 @@ static unsigned int min_odd(unsigned int x, unsigned int y) static void result(const char *err, unsigned int n, unsigned int src_off, unsigned int dst_off, unsigned int len, unsigned long data) { - pr_info("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)\n", - current->comm, n, err, src_off, dst_off, len, data); + if (IS_ERR_VALUE(data)) { + pr_info("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%ld)\n", + current->comm, n, err, src_off, dst_off, len, data); + } else { + pr_info("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)\n", + current->comm, n, err, src_off, dst_off, len, data); + } } static void dbg_result(const char *err, unsigned int n, unsigned int src_off, @@ -1052,13 +1058,7 @@ static int dmatest_add_channel(struct dmatest_info *info, static bool filter(struct dma_chan *chan, void *param) { - struct dmatest_params *params = param; - - if (!dmatest_match_channel(params, chan) || - !dmatest_match_device(params, chan->device)) - return false; - else - return true; + return dmatest_match_channel(param, chan) && dmatest_match_device(param, chan->device); } static void request_channels(struct dmatest_info *info, @@ -1249,15 +1249,14 @@ static int dmatest_chan_set(const char *val, const struct kernel_param *kp) add_threaded_test(info); /* Check if channel was added successfully */ - dtc = list_last_entry(&info->channels, struct dmatest_chan, node); - - if (dtc->chan) { + if (!list_empty(&info->channels)) { /* * if new channel was not successfully added, revert the * "test_channel" string to the name of the last successfully * added channel. exception for when users issues empty string * to channel parameter. */ + dtc = list_last_entry(&info->channels, struct dmatest_chan, node); if ((strcmp(dma_chan_name(dtc->chan), strim(test_channel)) != 0) && (strcmp("", strim(test_channel)) != 0)) { ret = -EINVAL; diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c index 42739508c0d8..6f62711a4c94 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c +++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c @@ -293,7 +293,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip) if (!regs) return; - base_dir = debugfs_create_dir(dw->name, 0); + base_dir = debugfs_create_dir(dw->name, NULL); if (!base_dir) return; diff --git a/drivers/dma/dw-edma/dw-edma-v0-regs.h b/drivers/dma/dw-edma/dw-edma-v0-regs.h index cd6476884507..dfd70e223c2f 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-regs.h +++ b/drivers/dma/dw-edma/dw-edma-v0-regs.h @@ -40,7 +40,7 @@ struct dw_edma_v0_ch { struct dw_edma_v0_ch_regs wr; /* 0x200 */ u32 padding_1[55]; /* [0x224..0x2fc] */ struct dw_edma_v0_ch_regs rd; /* 0x300 */ - u32 padding_2[55]; /* [0x224..0x2fc] */ + u32 padding_2[55]; /* [0x324..0x3fc] */ }; struct dw_edma_v0_unroll { diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 4700f2e87a62..7ab83fe601ed 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -463,9 +463,9 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) dwc_descriptor_complete(dwc, bad_desc, true); } -static void dw_dma_tasklet(unsigned long data) +static void dw_dma_tasklet(struct tasklet_struct *t) { - struct dw_dma *dw = (struct dw_dma *)data; + struct dw_dma *dw = from_tasklet(dw, t, tasklet); struct dw_dma_chan *dwc; u32 status_xfer; u32 status_err; @@ -723,7 +723,7 @@ slave_sg_fromdev_fill_desc: lli_write(desc, sar, reg); lli_write(desc, dar, mem); lli_write(desc, ctlhi, ctlhi); - mem_width = __ffs(data_width | mem | dlen); + mem_width = __ffs(data_width | mem); lli_write(desc, ctllo, ctllo | DWC_CTLL_DST_WIDTH(mem_width)); desc->len = dlen; @@ -772,6 +772,10 @@ bool dw_dma_filter(struct dma_chan *chan, void *param) if (dws->dma_dev != chan->device->dev) return false; + /* permit channels in accordance with the channels mask */ + if (dws->channels && !(dws->channels & dwc->mask)) + return false; + /* We have to copy data since dws can be temporary storage */ memcpy(&dwc->dws, dws, sizeof(struct dw_dma_slave)); @@ -1138,7 +1142,7 @@ int do_dma_probe(struct dw_dma_chip *chip) goto err_pdata; } - tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw); + tasklet_setup(&dw->tasklet, dw_dma_tasklet); err = request_irq(chip->irq, dw_dma_interrupt, IRQF_SHARED, dw->name, dw); diff --git a/drivers/dma/dw/dw.c b/drivers/dma/dw/dw.c index 7a085b3c1854..a4862263ff14 100644 --- a/drivers/dma/dw/dw.c +++ b/drivers/dma/dw/dw.c @@ -14,7 +14,7 @@ static void dw_dma_initialize_chan(struct dw_dma_chan *dwc) { struct dw_dma *dw = to_dw_dma(dwc->chan.device); - u32 cfghi = DWC_CFGH_FIFO_MODE; + u32 cfghi = is_slave_direction(dwc->direction) ? 0 : DWC_CFGH_FIFO_MODE; u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); bool hs_polarity = dwc->dws.hs_polarity; @@ -67,9 +67,8 @@ static size_t dw_dma_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width) static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc) { struct dma_slave_config *sconfig = &dwc->dma_sconfig; - bool is_slave = is_slave_direction(dwc->direction); - u8 smsize = is_slave ? sconfig->src_maxburst : DW_DMA_MSIZE_16; - u8 dmsize = is_slave ? sconfig->dst_maxburst : DW_DMA_MSIZE_16; + u8 smsize = (dwc->direction == DMA_DEV_TO_MEM) ? sconfig->src_maxburst : 0; + u8 dmsize = (dwc->direction == DMA_MEM_TO_DEV) ? sconfig->dst_maxburst : 0; u8 p_master = dwc->dws.p_master; u8 m_master = dwc->dws.m_master; u8 dms = (dwc->direction == DMA_MEM_TO_DEV) ? p_master : m_master; diff --git a/drivers/dma/dw/idma32.c b/drivers/dma/dw/idma32.c index f00657308811..3ce44de25d33 100644 --- a/drivers/dma/dw/idma32.c +++ b/drivers/dma/dw/idma32.c @@ -73,9 +73,8 @@ static size_t idma32_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width) static u32 idma32_prepare_ctllo(struct dw_dma_chan *dwc) { struct dma_slave_config *sconfig = &dwc->dma_sconfig; - bool is_slave = is_slave_direction(dwc->direction); - u8 smsize = is_slave ? sconfig->src_maxburst : IDMA32_MSIZE_8; - u8 dmsize = is_slave ? sconfig->dst_maxburst : IDMA32_MSIZE_8; + u8 smsize = (dwc->direction == DMA_DEV_TO_MEM) ? sconfig->src_maxburst : 0; + u8 dmsize = (dwc->direction == DMA_MEM_TO_DEV) ? sconfig->dst_maxburst : 0; return DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN | DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize); diff --git a/drivers/dma/dw/of.c b/drivers/dma/dw/of.c index 1474b3817ef4..c1cf7675b9d1 100644 --- a/drivers/dma/dw/of.c +++ b/drivers/dma/dw/of.c @@ -22,18 +22,21 @@ static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, }; dma_cap_mask_t cap; - if (dma_spec->args_count != 3) + if (dma_spec->args_count < 3 || dma_spec->args_count > 4) return NULL; slave.src_id = dma_spec->args[0]; slave.dst_id = dma_spec->args[0]; slave.m_master = dma_spec->args[1]; slave.p_master = dma_spec->args[2]; + if (dma_spec->args_count >= 4) + slave.channels = dma_spec->args[3]; if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS || slave.dst_id >= DW_DMA_MAX_NR_REQUESTS || slave.m_master >= dw->pdata->nr_masters || - slave.p_master >= dw->pdata->nr_masters)) + slave.p_master >= dw->pdata->nr_masters || + slave.channels >= BIT(dw->pdata->nr_channels))) return NULL; dma_cap_zero(cap); diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 87a246012629..01027779beb8 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -745,9 +745,9 @@ static void ep93xx_dma_advance_work(struct ep93xx_dma_chan *edmac) spin_unlock_irqrestore(&edmac->lock, flags); } -static void ep93xx_dma_tasklet(unsigned long data) +static void ep93xx_dma_tasklet(struct tasklet_struct *t) { - struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data; + struct ep93xx_dma_chan *edmac = from_tasklet(edmac, t, tasklet); struct ep93xx_dma_desc *desc, *d; struct dmaengine_desc_callback cb; LIST_HEAD(list); @@ -1353,8 +1353,7 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&edmac->active); INIT_LIST_HEAD(&edmac->queue); INIT_LIST_HEAD(&edmac->free_list); - tasklet_init(&edmac->tasklet, ep93xx_dma_tasklet, - (unsigned long)edmac); + tasklet_setup(&edmac->tasklet, ep93xx_dma_tasklet); list_add_tail(&edmac->chan.device_node, &dma_dev->channels); diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c index 493dc6c59d1d..fdf3500d96a9 100644 --- a/drivers/dma/fsl_raid.c +++ b/drivers/dma/fsl_raid.c @@ -154,17 +154,15 @@ static void fsl_re_cleanup_descs(struct fsl_re_chan *re_chan) fsl_re_issue_pending(&re_chan->chan); } -static void fsl_re_dequeue(unsigned long data) +static void fsl_re_dequeue(struct tasklet_struct *t) { - struct fsl_re_chan *re_chan; + struct fsl_re_chan *re_chan = from_tasklet(re_chan, t, irqtask); struct fsl_re_desc *desc, *_desc; struct fsl_re_hw_desc *hwdesc; unsigned long flags; unsigned int count, oub_count; int found; - re_chan = dev_get_drvdata((struct device *)data); - fsl_re_cleanup_descs(re_chan); spin_lock_irqsave(&re_chan->desc_lock, flags); @@ -671,7 +669,7 @@ static int fsl_re_chan_probe(struct platform_device *ofdev, snprintf(chan->name, sizeof(chan->name), "re_jr%02d", q); chandev = &chan_ofdev->dev; - tasklet_init(&chan->irqtask, fsl_re_dequeue, (unsigned long)chandev); + tasklet_setup(&chan->irqtask, fsl_re_dequeue); ret = request_irq(chan->irq, fsl_re_isr, 0, chan->name, chandev); if (ret) { diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index e342cf52d296..0feb323bae1e 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -976,9 +976,9 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) return IRQ_HANDLED; } -static void dma_do_tasklet(unsigned long data) +static void dma_do_tasklet(struct tasklet_struct *t) { - struct fsldma_chan *chan = (struct fsldma_chan *)data; + struct fsldma_chan *chan = from_tasklet(chan, t, tasklet); chan_dbg(chan, "tasklet entry\n"); @@ -1151,7 +1151,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev, } fdev->chan[chan->id] = chan; - tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); + tasklet_setup(&chan->tasklet, dma_do_tasklet); snprintf(chan->name, sizeof(chan->name), "chan%d", chan->id); /* Initialize the channel */ diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index b75d699160bf..200b9109cacf 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -368,6 +368,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, dev_dbg(&idxd->pdev->dev, "%s: sending cmd: %#x op: %#x\n", __func__, cmd_code, operand); + idxd->cmd_status = 0; __set_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags); idxd->cmd_done = &done; iowrite32(cmd.bits, idxd->reg_base + IDXD_CMD_OFFSET); @@ -379,8 +380,11 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, spin_unlock_irqrestore(&idxd->dev_lock, flags); wait_for_completion(&done); spin_lock_irqsave(&idxd->dev_lock, flags); - if (status) + if (status) { *status = ioread32(idxd->reg_base + IDXD_CMDSTS_OFFSET); + idxd->cmd_status = *status & GENMASK(7, 0); + } + __clear_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags); /* Wake up other pending commands */ wake_up(&idxd->cmd_waitq); @@ -555,8 +559,8 @@ static int idxd_wq_config_write(struct idxd_wq *wq) wq->wqcfg.priority = wq->priority; /* bytes 12-15 */ - wq->wqcfg.max_xfer_shift = idxd->hw.gen_cap.max_xfer_shift; - wq->wqcfg.max_batch_shift = idxd->hw.gen_cap.max_batch_shift; + wq->wqcfg.max_xfer_shift = ilog2(wq->max_xfer_bytes); + wq->wqcfg.max_batch_shift = ilog2(wq->max_batch_size); dev_dbg(dev, "WQ %d CFGs\n", wq->id); for (i = 0; i < 8; i++) { diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index e62b4799d189..c64df197e724 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -114,6 +114,8 @@ struct idxd_wq { struct sbitmap_queue sbq; struct dma_chan dma_chan; char name[WQ_NAME_SIZE + 1]; + u64 max_xfer_bytes; + u32 max_batch_size; }; struct idxd_engine { @@ -154,6 +156,7 @@ struct idxd_device { unsigned long flags; int id; int major; + u8 cmd_status; struct pci_dev *pdev; void __iomem *reg_base; diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index c7c61974f20f..11e5ce168177 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -176,6 +176,8 @@ static int idxd_setup_internals(struct idxd_device *idxd) wq->idxd = idxd; mutex_init(&wq->wq_lock); wq->idxd_cdev.minor = -1; + wq->max_xfer_bytes = idxd->max_xfer_bytes; + wq->max_batch_size = idxd->max_batch_size; } for (i = 0; i < idxd->max_engines; i++) { diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c index 1e9e6991f543..17a65a13fb64 100644 --- a/drivers/dma/idxd/irq.c +++ b/drivers/dma/idxd/irq.c @@ -64,6 +64,7 @@ irqreturn_t idxd_misc_thread(int vec, void *data) bool err = false; cause = ioread32(idxd->reg_base + IDXD_INTCAUSE_OFFSET); + iowrite32(cause, idxd->reg_base + IDXD_INTCAUSE_OFFSET); if (cause & IDXD_INTC_ERR) { spin_lock_bh(&idxd->dev_lock); @@ -121,7 +122,6 @@ irqreturn_t idxd_misc_thread(int vec, void *data) dev_warn_once(dev, "Unexpected interrupt cause bits set: %#x\n", val); - iowrite32(cause, idxd->reg_base + IDXD_INTCAUSE_OFFSET); if (!err) goto out; diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index dcba60953217..07a5db06a29a 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -1064,6 +1064,89 @@ static ssize_t wq_cdev_minor_show(struct device *dev, static struct device_attribute dev_attr_wq_cdev_minor = __ATTR(cdev_minor, 0444, wq_cdev_minor_show, NULL); +static int __get_sysfs_u64(const char *buf, u64 *val) +{ + int rc; + + rc = kstrtou64(buf, 0, val); + if (rc < 0) + return -EINVAL; + + if (*val == 0) + return -EINVAL; + + *val = roundup_pow_of_two(*val); + return 0; +} + +static ssize_t wq_max_transfer_size_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); + + return sprintf(buf, "%llu\n", wq->max_xfer_bytes); +} + +static ssize_t wq_max_transfer_size_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); + struct idxd_device *idxd = wq->idxd; + u64 xfer_size; + int rc; + + if (wq->state != IDXD_WQ_DISABLED) + return -EPERM; + + rc = __get_sysfs_u64(buf, &xfer_size); + if (rc < 0) + return rc; + + if (xfer_size > idxd->max_xfer_bytes) + return -EINVAL; + + wq->max_xfer_bytes = xfer_size; + + return count; +} + +static struct device_attribute dev_attr_wq_max_transfer_size = + __ATTR(max_transfer_size, 0644, + wq_max_transfer_size_show, wq_max_transfer_size_store); + +static ssize_t wq_max_batch_size_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); + + return sprintf(buf, "%u\n", wq->max_batch_size); +} + +static ssize_t wq_max_batch_size_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); + struct idxd_device *idxd = wq->idxd; + u64 batch_size; + int rc; + + if (wq->state != IDXD_WQ_DISABLED) + return -EPERM; + + rc = __get_sysfs_u64(buf, &batch_size); + if (rc < 0) + return rc; + + if (batch_size > idxd->max_batch_size) + return -EINVAL; + + wq->max_batch_size = (u32)batch_size; + + return count; +} + +static struct device_attribute dev_attr_wq_max_batch_size = + __ATTR(max_batch_size, 0644, wq_max_batch_size_show, wq_max_batch_size_store); + static struct attribute *idxd_wq_attributes[] = { &dev_attr_wq_clients.attr, &dev_attr_wq_state.attr, @@ -1074,6 +1157,8 @@ static struct attribute *idxd_wq_attributes[] = { &dev_attr_wq_type.attr, &dev_attr_wq_name.attr, &dev_attr_wq_cdev_minor.attr, + &dev_attr_wq_max_transfer_size.attr, + &dev_attr_wq_max_batch_size.attr, NULL, }; @@ -1317,6 +1402,15 @@ static ssize_t cdev_major_show(struct device *dev, } static DEVICE_ATTR_RO(cdev_major); +static ssize_t cmd_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct idxd_device *idxd = container_of(dev, struct idxd_device, conf_dev); + + return sprintf(buf, "%#x\n", idxd->cmd_status); +} +static DEVICE_ATTR_RO(cmd_status); + static struct attribute *idxd_device_attributes[] = { &dev_attr_version.attr, &dev_attr_max_groups.attr, @@ -1335,6 +1429,7 @@ static struct attribute *idxd_device_attributes[] = { &dev_attr_max_tokens.attr, &dev_attr_token_limit.attr, &dev_attr_cdev_major.attr, + &dev_attr_cmd_status.attr, NULL, }; diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 88717506c1f6..670db04b0757 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -173,7 +173,6 @@ enum imx_dma_type { struct imxdma_engine { struct device *dev; - struct device_dma_parameters dma_parms; struct dma_device dma_device; void __iomem *base; struct clk *dma_ahb; @@ -613,9 +612,9 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) return 0; } -static void imxdma_tasklet(unsigned long data) +static void imxdma_tasklet(struct tasklet_struct *t) { - struct imxdma_channel *imxdmac = (void *)data; + struct imxdma_channel *imxdmac = from_tasklet(imxdmac, t, dma_tasklet); struct imxdma_engine *imxdma = imxdmac->imxdma; struct imxdma_desc *desc, *next_desc; unsigned long flags; @@ -1169,8 +1168,7 @@ static int __init imxdma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&imxdmac->ld_free); INIT_LIST_HEAD(&imxdmac->ld_active); - tasklet_init(&imxdmac->dma_tasklet, imxdma_tasklet, - (unsigned long)imxdmac); + tasklet_setup(&imxdmac->dma_tasklet, imxdma_tasklet); imxdmac->chan.device = &imxdma->dma_device; dma_cookie_init(&imxdmac->chan); imxdmac->channel = i; @@ -1196,7 +1194,6 @@ static int __init imxdma_probe(struct platform_device *pdev) platform_set_drvdata(pdev, imxdma); imxdma->dma_device.copy_align = DMAENGINE_ALIGN_4_BYTES; - imxdma->dma_device.dev->dma_parms = &imxdma->dma_parms; dma_set_max_seg_size(imxdma->dma_device.dev, 0xffffff); ret = dma_async_device_register(&imxdma->dma_device); diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 4f8d8f5e1132..16b908c77db3 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -426,7 +426,6 @@ struct sdma_driver_data { struct sdma_engine { struct device *dev; - struct device_dma_parameters dma_parms; struct sdma_channel channel[MAX_DMA_CHANNELS]; struct sdma_channel_control *channel_control; void __iomem *regs; @@ -2118,7 +2117,6 @@ static int sdma_probe(struct platform_device *pdev) sdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; sdma->dma_device.device_prep_dma_memcpy = sdma_prep_memcpy; sdma->dma_device.device_issue_pending = sdma_issue_pending; - sdma->dma_device.dev->dma_parms = &sdma->dma_parms; sdma->dma_device.copy_align = 2; dma_set_max_seg_size(sdma->dma_device.dev, SDMA_BD_MAX_CNT); diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index a814b200299b..37ff4ec7db76 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -26,11 +26,11 @@ #include "../dmaengine.h" -int completion_timeout = 200; +static int completion_timeout = 200; module_param(completion_timeout, int, 0644); MODULE_PARM_DESC(completion_timeout, "set ioat completion timeout [msec] (default 200 [msec])"); -int idle_timeout = 2000; +static int idle_timeout = 2000; module_param(idle_timeout, int, 0644); MODULE_PARM_DESC(idle_timeout, "set ioat idel timeout [msec] (default 2000 [msec])"); @@ -165,7 +165,7 @@ void ioat_stop(struct ioatdma_chan *ioat_chan) tasklet_kill(&ioat_chan->cleanup_task); /* final cleanup now that everything is quiesced and can't re-arm */ - ioat_cleanup_event((unsigned long)&ioat_chan->dma_chan); + ioat_cleanup_event(&ioat_chan->cleanup_task); } static void __ioat_issue_pending(struct ioatdma_chan *ioat_chan) @@ -389,7 +389,7 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags) struct ioat_descs *descs = &ioat_chan->descs[i]; descs->virt = dma_alloc_coherent(to_dev(ioat_chan), - SZ_2M, &descs->hw, flags); + IOAT_CHUNK_SIZE, &descs->hw, flags); if (!descs->virt) { int idx; @@ -690,9 +690,9 @@ static void ioat_cleanup(struct ioatdma_chan *ioat_chan) spin_unlock_bh(&ioat_chan->cleanup_lock); } -void ioat_cleanup_event(unsigned long data) +void ioat_cleanup_event(struct tasklet_struct *t) { - struct ioatdma_chan *ioat_chan = to_ioat_chan((void *)data); + struct ioatdma_chan *ioat_chan = from_tasklet(ioat_chan, t, cleanup_task); ioat_cleanup(ioat_chan); if (!test_bit(IOAT_RUN, &ioat_chan->state)) diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index f7f31fdf14cf..140cfe3782fb 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -393,7 +393,7 @@ int ioat_reset_hw(struct ioatdma_chan *ioat_chan); enum dma_status ioat_tx_status(struct dma_chan *c, dma_cookie_t cookie, struct dma_tx_state *txstate); -void ioat_cleanup_event(unsigned long data); +void ioat_cleanup_event(struct tasklet_struct *t); void ioat_timer_event(struct timer_list *t); int ioat_check_space_lock(struct ioatdma_chan *ioat_chan, int num_descs); void ioat_issue_pending(struct dma_chan *chan); diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c index 8a53f5c96b16..191b59279007 100644 --- a/drivers/dma/ioat/init.c +++ b/drivers/dma/ioat/init.c @@ -767,8 +767,6 @@ ioat_init_channel(struct ioatdma_device *ioat_dma, struct ioatdma_chan *ioat_chan, int idx) { struct dma_device *dma = &ioat_dma->dma_dev; - struct dma_chan *c = &ioat_chan->dma_chan; - unsigned long data = (unsigned long) c; ioat_chan->ioat_dma = ioat_dma; ioat_chan->reg_base = ioat_dma->reg_base + (0x80 * (idx + 1)); @@ -778,7 +776,7 @@ ioat_init_channel(struct ioatdma_device *ioat_dma, list_add_tail(&ioat_chan->dma_chan.device_node, &dma->channels); ioat_dma->idx[idx] = ioat_chan; timer_setup(&ioat_chan->timer, ioat_timer_event, 0); - tasklet_init(&ioat_chan->cleanup_task, ioat_cleanup_event, data); + tasklet_setup(&ioat_chan->cleanup_task, ioat_cleanup_event); } #define IOAT_NUM_SRC_TEST 6 /* must be <= 8 */ diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index 3350bffb2e93..310b899d581f 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -238,9 +238,10 @@ iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan) spin_unlock_bh(&iop_chan->lock); } -static void iop_adma_tasklet(unsigned long data) +static void iop_adma_tasklet(struct tasklet_struct *t) { - struct iop_adma_chan *iop_chan = (struct iop_adma_chan *) data; + struct iop_adma_chan *iop_chan = from_tasklet(iop_chan, t, + irq_tasklet); /* lockdep will flag depedency submissions as potentially * recursive locking, this is not the case as a dependency @@ -416,6 +417,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan); static int iop_adma_alloc_chan_resources(struct dma_chan *chan) { char *hw_desc; + dma_addr_t dma_desc; int idx; struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); struct iop_adma_desc_slot *slot = NULL; @@ -444,9 +446,8 @@ static int iop_adma_alloc_chan_resources(struct dma_chan *chan) INIT_LIST_HEAD(&slot->tx_list); INIT_LIST_HEAD(&slot->chain_node); INIT_LIST_HEAD(&slot->slot_node); - hw_desc = (char *) iop_chan->device->dma_desc_pool; - slot->async_tx.phys = - (dma_addr_t) &hw_desc[idx * IOP_ADMA_SLOT_SIZE]; + dma_desc = iop_chan->device->dma_desc_pool; + slot->async_tx.phys = dma_desc + idx * IOP_ADMA_SLOT_SIZE; slot->idx = idx; spin_lock_bh(&iop_chan->lock); @@ -1296,9 +1297,8 @@ static int iop_adma_probe(struct platform_device *pdev) goto err_free_adev; } - dev_dbg(&pdev->dev, "%s: allocated descriptor pool virt %p phys %p\n", - __func__, adev->dma_desc_pool_virt, - (void *) adev->dma_desc_pool); + dev_dbg(&pdev->dev, "%s: allocated descriptor pool virt %p phys %pad\n", + __func__, adev->dma_desc_pool_virt, &adev->dma_desc_pool); adev->id = plat_data->hw_id; @@ -1351,8 +1351,7 @@ static int iop_adma_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_free_iop_chan; } - tasklet_init(&iop_chan->irq_tasklet, iop_adma_tasklet, (unsigned long) - iop_chan); + tasklet_setup(&iop_chan->irq_tasklet, iop_adma_tasklet); /* clear errors before enabling interrupts */ iop_adma_device_clear_err_status(iop_chan); diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 0457b1f26540..38036db284cb 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1299,9 +1299,9 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void ipu_gc_tasklet(unsigned long arg) +static void ipu_gc_tasklet(struct tasklet_struct *t) { - struct ipu *ipu = (struct ipu *)arg; + struct ipu *ipu = from_tasklet(ipu, t, tasklet); int i; for (i = 0; i < IPU_CHANNELS_NUM; i++) { @@ -1740,7 +1740,7 @@ static int __init ipu_probe(struct platform_device *pdev) if (ret < 0) goto err_idmac_init; - tasklet_init(&ipu_data.tasklet, ipu_gc_tasklet, (unsigned long)&ipu_data); + tasklet_setup(&ipu_data.tasklet, ipu_gc_tasklet); ipu_data.dev = &pdev->dev; diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c index c5c1aa0dcaed..f609a84c493c 100644 --- a/drivers/dma/k3dma.c +++ b/drivers/dma/k3dma.c @@ -297,9 +297,9 @@ static int k3_dma_start_txd(struct k3_dma_chan *c) return -EAGAIN; } -static void k3_dma_tasklet(unsigned long arg) +static void k3_dma_tasklet(struct tasklet_struct *t) { - struct k3_dma_dev *d = (struct k3_dma_dev *)arg; + struct k3_dma_dev *d = from_tasklet(d, t, task); struct k3_dma_phy *p; struct k3_dma_chan *c, *cn; unsigned pch, pch_alloc = 0; @@ -962,7 +962,7 @@ static int k3_dma_probe(struct platform_device *op) spin_lock_init(&d->lock); INIT_LIST_HEAD(&d->chan_pending); - tasklet_init(&d->task, k3_dma_tasklet, (unsigned long)d); + tasklet_setup(&d->task, k3_dma_tasklet); platform_set_drvdata(op, d); dev_info(&op->dev, "initialized\n"); diff --git a/drivers/dma/mediatek/mtk-cqdma.c b/drivers/dma/mediatek/mtk-cqdma.c index 6bf838e63be1..41ef9f15d3d5 100644 --- a/drivers/dma/mediatek/mtk-cqdma.c +++ b/drivers/dma/mediatek/mtk-cqdma.c @@ -356,9 +356,9 @@ static struct mtk_cqdma_vdesc return ret; } -static void mtk_cqdma_tasklet_cb(unsigned long data) +static void mtk_cqdma_tasklet_cb(struct tasklet_struct *t) { - struct mtk_cqdma_pchan *pc = (struct mtk_cqdma_pchan *)data; + struct mtk_cqdma_pchan *pc = from_tasklet(pc, t, tasklet); struct mtk_cqdma_vdesc *cvd = NULL; unsigned long flags; @@ -878,8 +878,7 @@ static int mtk_cqdma_probe(struct platform_device *pdev) /* initialize tasklet for each PC */ for (i = 0; i < cqdma->dma_channels; ++i) - tasklet_init(&cqdma->pc[i]->tasklet, mtk_cqdma_tasklet_cb, - (unsigned long)cqdma->pc[i]); + tasklet_setup(&cqdma->pc[i]->tasklet, mtk_cqdma_tasklet_cb); dev_info(&pdev->dev, "MediaTek CQDMA driver registered\n"); diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c index 29f1223b285a..27c07350971d 100644 --- a/drivers/dma/mediatek/mtk-uart-apdma.c +++ b/drivers/dma/mediatek/mtk-uart-apdma.c @@ -624,14 +624,9 @@ static int mtk_uart_apdma_runtime_suspend(struct device *dev) static int mtk_uart_apdma_runtime_resume(struct device *dev) { - int ret; struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev); - ret = clk_prepare_enable(mtkd->clk); - if (ret) - return ret; - - return 0; + return clk_prepare_enable(mtkd->clk); } #endif /* CONFIG_PM */ diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c index f42f792db277..b84303be8edf 100644 --- a/drivers/dma/mmp_pdma.c +++ b/drivers/dma/mmp_pdma.c @@ -873,9 +873,9 @@ static void mmp_pdma_issue_pending(struct dma_chan *dchan) * Do call back * Start pending list */ -static void dma_do_tasklet(unsigned long data) +static void dma_do_tasklet(struct tasklet_struct *t) { - struct mmp_pdma_chan *chan = (struct mmp_pdma_chan *)data; + struct mmp_pdma_chan *chan = from_tasklet(chan, t, tasklet); struct mmp_pdma_desc_sw *desc, *_desc; LIST_HEAD(chain_cleanup); unsigned long flags; @@ -993,7 +993,7 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, int idx, int irq) spin_lock_init(&chan->desc_lock); chan->dev = pdev->dev; chan->chan.device = &pdev->device; - tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); + tasklet_setup(&chan->tasklet, dma_do_tasklet); INIT_LIST_HEAD(&chan->chain_pending); INIT_LIST_HEAD(&chan->chain_running); diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index 960c7c40aef7..a262e0eb4cc9 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c @@ -346,9 +346,9 @@ static irqreturn_t mmp_tdma_int_handler(int irq, void *dev_id) return IRQ_NONE; } -static void dma_do_tasklet(unsigned long data) +static void dma_do_tasklet(struct tasklet_struct *t) { - struct mmp_tdma_chan *tdmac = (struct mmp_tdma_chan *)data; + struct mmp_tdma_chan *tdmac = from_tasklet(tdmac, t, tasklet); dmaengine_desc_get_callback_invoke(&tdmac->desc, NULL); } @@ -586,7 +586,7 @@ static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev, tdmac->pool = pool; tdmac->status = DMA_COMPLETE; tdev->tdmac[tdmac->idx] = tdmac; - tasklet_init(&tdmac->tasklet, dma_do_tasklet, (unsigned long)tdmac); + tasklet_setup(&tdmac->tasklet, dma_do_tasklet); /* add the channel to tdma_chan list */ list_add_tail(&tdmac->chan.device_node, diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index dc2cae7bcf69..c1a69149c8bf 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c @@ -414,9 +414,9 @@ static void mpc_dma_process_completed(struct mpc_dma *mdma) } /* DMA Tasklet */ -static void mpc_dma_tasklet(unsigned long data) +static void mpc_dma_tasklet(struct tasklet_struct *t) { - struct mpc_dma *mdma = (void *)data; + struct mpc_dma *mdma = from_tasklet(mdma, t, tasklet); unsigned long flags; uint es; @@ -1009,7 +1009,7 @@ static int mpc_dma_probe(struct platform_device *op) list_add_tail(&mchan->chan.device_node, &dma->channels); } - tasklet_init(&mdma->tasklet, mpc_dma_tasklet, (unsigned long)mdma); + tasklet_setup(&mdma->tasklet, mpc_dma_tasklet); /* * Configure DMA Engine: diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 0ac8e7b34e12..00cd1335eeba 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -336,9 +336,9 @@ static void mv_chan_slot_cleanup(struct mv_xor_chan *mv_chan) mv_chan->dmachan.completed_cookie = cookie; } -static void mv_xor_tasklet(unsigned long data) +static void mv_xor_tasklet(struct tasklet_struct *t) { - struct mv_xor_chan *chan = (struct mv_xor_chan *) data; + struct mv_xor_chan *chan = from_tasklet(chan, t, irq_tasklet); spin_lock(&chan->lock); mv_chan_slot_cleanup(chan); @@ -1097,8 +1097,7 @@ mv_xor_channel_add(struct mv_xor_device *xordev, mv_chan->mmr_base = xordev->xor_base; mv_chan->mmr_high_base = xordev->xor_high_base; - tasklet_init(&mv_chan->irq_tasklet, mv_xor_tasklet, (unsigned long) - mv_chan); + tasklet_setup(&mv_chan->irq_tasklet, mv_xor_tasklet); /* clear errors before enabling interrupts */ mv_chan_clear_err_status(mv_chan); diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index 9225f08dfee9..2753a6b916f6 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -553,9 +553,10 @@ int mv_xor_v2_get_pending_params(struct mv_xor_v2_device *xor_dev, /* * handle the descriptors after HW process */ -static void mv_xor_v2_tasklet(unsigned long data) +static void mv_xor_v2_tasklet(struct tasklet_struct *t) { - struct mv_xor_v2_device *xor_dev = (struct mv_xor_v2_device *) data; + struct mv_xor_v2_device *xor_dev = from_tasklet(xor_dev, t, + irq_tasklet); int pending_ptr, num_of_pending, i; struct mv_xor_v2_sw_desc *next_pending_sw_desc = NULL; @@ -780,8 +781,7 @@ static int mv_xor_v2_probe(struct platform_device *pdev) if (ret) goto free_msi_irqs; - tasklet_init(&xor_dev->irq_tasklet, mv_xor_v2_tasklet, - (unsigned long) xor_dev); + tasklet_setup(&xor_dev->irq_tasklet, mv_xor_v2_tasklet); xor_dev->desc_size = mv_xor_v2_set_desc_size(xor_dev); diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 3039bba0e4d5..65f816b40c32 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -141,7 +141,6 @@ struct mxs_dma_engine { void __iomem *base; struct clk *clk; struct dma_device dma_device; - struct device_dma_parameters dma_parms; struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; struct platform_device *pdev; unsigned int nr_channels; @@ -320,9 +319,9 @@ static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx) return dma_cookie_assign(tx); } -static void mxs_dma_tasklet(unsigned long data) +static void mxs_dma_tasklet(struct tasklet_struct *t) { - struct mxs_dma_chan *mxs_chan = (struct mxs_dma_chan *) data; + struct mxs_dma_chan *mxs_chan = from_tasklet(mxs_chan, t, tasklet); dmaengine_desc_get_callback_invoke(&mxs_chan->desc, NULL); } @@ -812,8 +811,7 @@ static int __init mxs_dma_probe(struct platform_device *pdev) mxs_chan->chan.device = &mxs_dma->dma_device; dma_cookie_init(&mxs_chan->chan); - tasklet_init(&mxs_chan->tasklet, mxs_dma_tasklet, - (unsigned long) mxs_chan); + tasklet_setup(&mxs_chan->tasklet, mxs_dma_tasklet); /* Add the channel to mxs_chan list */ @@ -829,7 +827,6 @@ static int __init mxs_dma_probe(struct platform_device *pdev) mxs_dma->dma_device.dev = &pdev->dev; /* mxs_dma gets 65535 bytes maximum sg size */ - mxs_dma->dma_device.dev->dma_parms = &mxs_dma->dma_parms; dma_set_max_seg_size(mxs_dma->dma_device.dev, MAX_XFER_BYTES); mxs_dma->dma_device.device_alloc_chan_resources = mxs_dma_alloc_chan_resources; diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c index ca4e0930207a..9c52c57919c6 100644 --- a/drivers/dma/nbpfaxi.c +++ b/drivers/dma/nbpfaxi.c @@ -1113,9 +1113,9 @@ static struct dma_chan *nbpf_of_xlate(struct of_phandle_args *dma_spec, return dchan; } -static void nbpf_chan_tasklet(unsigned long data) +static void nbpf_chan_tasklet(struct tasklet_struct *t) { - struct nbpf_channel *chan = (struct nbpf_channel *)data; + struct nbpf_channel *chan = from_tasklet(chan, t, tasklet); struct nbpf_desc *desc, *tmp; struct dmaengine_desc_callback cb; @@ -1260,7 +1260,7 @@ static int nbpf_chan_probe(struct nbpf_device *nbpf, int n) snprintf(chan->name, sizeof(chan->name), "nbpf %d", n); - tasklet_init(&chan->tasklet, nbpf_chan_tasklet, (unsigned long)chan); + tasklet_setup(&chan->tasklet, nbpf_chan_tasklet); ret = devm_request_irq(dma_dev->dev, chan->irq, nbpf_chan_irq, IRQF_SHARED, chan->name, chan); diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c index 331c8d8b10a3..9fede32641e9 100644 --- a/drivers/dma/owl-dma.c +++ b/drivers/dma/owl-dma.c @@ -124,7 +124,7 @@ #define FCNT_VAL 0x1 /** - * owl_dmadesc_offsets - Describe DMA descriptor, hardware link + * enum owl_dmadesc_offsets - Describe DMA descriptor, hardware link * list for dma transfer * @OWL_DMADESC_NEXT_LLI: physical address of the next link list * @OWL_DMADESC_SADDR: source physical address @@ -135,6 +135,7 @@ * @OWL_DMADESC_CTRLA: dma_mode and linklist ctrl config * @OWL_DMADESC_CTRLB: interrupt config * @OWL_DMADESC_CONST_NUM: data for constant fill + * @OWL_DMADESC_SIZE: max size of this enum */ enum owl_dmadesc_offsets { OWL_DMADESC_NEXT_LLI = 0, diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index a3b0b4c56a19..1da04112fcdb 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -670,9 +670,9 @@ static int pd_device_terminate_all(struct dma_chan *chan) return 0; } -static void pdc_tasklet(unsigned long data) +static void pdc_tasklet(struct tasklet_struct *t) { - struct pch_dma_chan *pd_chan = (struct pch_dma_chan *)data; + struct pch_dma_chan *pd_chan = from_tasklet(pd_chan, t, tasklet); unsigned long flags; if (!pdc_is_idle(pd_chan)) { @@ -735,8 +735,7 @@ static irqreturn_t pd_irq(int irq, void *devid) return ret0 | ret2; } -#ifdef CONFIG_PM -static void pch_dma_save_regs(struct pch_dma *pd) +static void __maybe_unused pch_dma_save_regs(struct pch_dma *pd) { struct pch_dma_chan *pd_chan; struct dma_chan *chan, *_c; @@ -759,7 +758,7 @@ static void pch_dma_save_regs(struct pch_dma *pd) } } -static void pch_dma_restore_regs(struct pch_dma *pd) +static void __maybe_unused pch_dma_restore_regs(struct pch_dma *pd) { struct pch_dma_chan *pd_chan; struct dma_chan *chan, *_c; @@ -782,40 +781,25 @@ static void pch_dma_restore_regs(struct pch_dma *pd) } } -static int pch_dma_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused pch_dma_suspend(struct device *dev) { - struct pch_dma *pd = pci_get_drvdata(pdev); + struct pch_dma *pd = dev_get_drvdata(dev); if (pd) pch_dma_save_regs(pd); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; } -static int pch_dma_resume(struct pci_dev *pdev) +static int __maybe_unused pch_dma_resume(struct device *dev) { - struct pch_dma *pd = pci_get_drvdata(pdev); - int err; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - err = pci_enable_device(pdev); - if (err) { - dev_dbg(&pdev->dev, "failed to enable device\n"); - return err; - } + struct pch_dma *pd = dev_get_drvdata(dev); if (pd) pch_dma_restore_regs(pd); return 0; } -#endif static int pch_dma_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -898,8 +882,7 @@ static int pch_dma_probe(struct pci_dev *pdev, INIT_LIST_HEAD(&pd_chan->queue); INIT_LIST_HEAD(&pd_chan->free_list); - tasklet_init(&pd_chan->tasklet, pdc_tasklet, - (unsigned long)pd_chan); + tasklet_setup(&pd_chan->tasklet, pdc_tasklet); list_add_tail(&pd_chan->chan.device_node, &pd->dma.channels); } @@ -993,15 +976,14 @@ static const struct pci_device_id pch_dma_id_table[] = { { 0, }, }; +static SIMPLE_DEV_PM_OPS(pch_dma_pm_ops, pch_dma_suspend, pch_dma_resume); + static struct pci_driver pch_dma_driver = { .name = DRV_NAME, .id_table = pch_dma_id_table, .probe = pch_dma_probe, .remove = pch_dma_remove, -#ifdef CONFIG_PM - .suspend = pch_dma_suspend, - .resume = pch_dma_resume, -#endif + .driver.pm = &pch_dma_pm_ops, }; module_pci_driver(pch_dma_driver); diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 5274a0704d96..e9f0101d92fa 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -255,7 +255,7 @@ enum pl330_byteswap { static unsigned cmd_line; #define PL330_DBGCMD_DUMP(off, x...) do { \ printk("%x:", cmd_line); \ - printk(x); \ + printk(KERN_CONT x); \ cmd_line += off; \ } while (0) #define PL330_DBGMC_START(addr) (cmd_line = addr) @@ -460,9 +460,6 @@ struct pl330_dmac { /* DMA-Engine Device */ struct dma_device ddma; - /* Holds info about sg limitations */ - struct device_dma_parameters dma_parms; - /* Pool of descriptors available for the DMAC's channels */ struct list_head desc_pool; /* To protect desc_pool manipulation */ @@ -1576,9 +1573,9 @@ static void dma_pl330_rqcb(struct dma_pl330_desc *desc, enum pl330_op_err err) tasklet_schedule(&pch->task); } -static void pl330_dotask(unsigned long data) +static void pl330_dotask(struct tasklet_struct *t) { - struct pl330_dmac *pl330 = (struct pl330_dmac *) data; + struct pl330_dmac *pl330 = from_tasklet(pl330, t, tasks); unsigned long flags; int i; @@ -1982,7 +1979,7 @@ static int pl330_add(struct pl330_dmac *pl330) return ret; } - tasklet_init(&pl330->tasks, pl330_dotask, (unsigned long) pl330); + tasklet_setup(&pl330->tasks, pl330_dotask); pl330->state = INIT; @@ -2065,9 +2062,9 @@ static inline void fill_queue(struct dma_pl330_chan *pch) } } -static void pl330_tasklet(unsigned long data) +static void pl330_tasklet(struct tasklet_struct *t) { - struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; + struct dma_pl330_chan *pch = from_tasklet(pch, t, task); struct dma_pl330_desc *desc, *_dt; unsigned long flags; bool power_down = false; @@ -2175,7 +2172,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) return -ENOMEM; } - tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch); + tasklet_setup(&pch->task, pl330_tasklet); spin_unlock_irqrestore(&pl330->lock, flags); @@ -2487,7 +2484,7 @@ static void pl330_issue_pending(struct dma_chan *chan) list_splice_tail_init(&pch->submitted_list, &pch->work_list); spin_unlock_irqrestore(&pch->lock, flags); - pl330_tasklet((unsigned long)pch); + pl330_tasklet(&pch->task); } /* @@ -3034,9 +3031,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pl330->rstc = devm_reset_control_get_optional(&adev->dev, "dma"); if (IS_ERR(pl330->rstc)) { - if (PTR_ERR(pl330->rstc) != -EPROBE_DEFER) - dev_err(&adev->dev, "Failed to get reset!\n"); - return PTR_ERR(pl330->rstc); + return dev_err_probe(&adev->dev, PTR_ERR(pl330->rstc), "Failed to get reset!\n"); } else { ret = reset_control_deassert(pl330->rstc); if (ret) { @@ -3047,9 +3042,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pl330->rstc_ocp = devm_reset_control_get_optional(&adev->dev, "dma-ocp"); if (IS_ERR(pl330->rstc_ocp)) { - if (PTR_ERR(pl330->rstc_ocp) != -EPROBE_DEFER) - dev_err(&adev->dev, "Failed to get OCP reset!\n"); - return PTR_ERR(pl330->rstc_ocp); + return dev_err_probe(&adev->dev, PTR_ERR(pl330->rstc_ocp), + "Failed to get OCP reset!\n"); } else { ret = reset_control_deassert(pl330->rstc_ocp); if (ret) { @@ -3154,8 +3148,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) } } - adev->dev.dma_parms = &pl330->dma_parms; - /* * This is the limit for transfers with a buswidth of 1, larger * buswidths will have larger limits. diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c index db4c5fd453a9..f387c5bbc170 100644 --- a/drivers/dma/plx_dma.c +++ b/drivers/dma/plx_dma.c @@ -241,9 +241,9 @@ static void plx_dma_stop(struct plx_dma_dev *plxdev) rcu_read_unlock(); } -static void plx_dma_desc_task(unsigned long data) +static void plx_dma_desc_task(struct tasklet_struct *t) { - struct plx_dma_dev *plxdev = (void *)data; + struct plx_dma_dev *plxdev = from_tasklet(plxdev, t, desc_task); plx_dma_process_desc(plxdev); } @@ -513,8 +513,7 @@ static int plx_dma_create(struct pci_dev *pdev) } spin_lock_init(&plxdev->ring_lock); - tasklet_init(&plxdev->desc_task, plx_dma_desc_task, - (unsigned long)plxdev); + tasklet_setup(&plxdev->desc_task, plx_dma_desc_task); RCU_INIT_POINTER(plxdev->pdev, pdev); plxdev->bar = pcim_iomap_table(pdev)[0]; diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index 4db000d5f01c..71cdaaa8134c 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c @@ -1660,9 +1660,9 @@ static void __ppc440spe_adma_slot_cleanup(struct ppc440spe_adma_chan *chan) /** * ppc440spe_adma_tasklet - clean up watch-dog initiator */ -static void ppc440spe_adma_tasklet(unsigned long data) +static void ppc440spe_adma_tasklet(struct tasklet_struct *t) { - struct ppc440spe_adma_chan *chan = (struct ppc440spe_adma_chan *) data; + struct ppc440spe_adma_chan *chan = from_tasklet(chan, t, irq_tasklet); spin_lock_nested(&chan->lock, SINGLE_DEPTH_NESTING); __ppc440spe_adma_slot_cleanup(chan); @@ -4141,8 +4141,7 @@ static int ppc440spe_adma_probe(struct platform_device *ofdev) chan->common.device = &adev->common; dma_cookie_init(&chan->common); list_add_tail(&chan->common.device_node, &adev->common.channels); - tasklet_init(&chan->irq_tasklet, ppc440spe_adma_tasklet, - (unsigned long)chan); + tasklet_setup(&chan->irq_tasklet, ppc440spe_adma_tasklet); /* allocate and map helper pages for async validation or * async_mult/async_sum_product operations on DMA0/1. diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 5a08dd0d3388..4eeb8bb27279 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -381,7 +381,6 @@ struct bam_device { void __iomem *regs; struct device *dev; struct dma_device common; - struct device_dma_parameters dma_parms; struct bam_chan *channels; u32 num_channels; u32 num_ees; @@ -1071,13 +1070,13 @@ static void bam_start_dma(struct bam_chan *bchan) /** * dma_tasklet - DMA IRQ tasklet - * @data: tasklet argument (bam controller structure) + * @t: tasklet argument (bam controller structure) * * Sets up next DMA operation and then processes all completed transactions */ -static void dma_tasklet(unsigned long data) +static void dma_tasklet(struct tasklet_struct *t) { - struct bam_device *bdev = (struct bam_device *)data; + struct bam_device *bdev = from_tasklet(bdev, t, task); struct bam_chan *bchan; unsigned long flags; unsigned int i; @@ -1293,7 +1292,7 @@ static int bam_dma_probe(struct platform_device *pdev) if (ret) goto err_disable_clk; - tasklet_init(&bdev->task, dma_tasklet, (unsigned long)bdev); + tasklet_setup(&bdev->task, dma_tasklet); bdev->channels = devm_kcalloc(bdev->dev, bdev->num_channels, sizeof(*bdev->channels), GFP_KERNEL); @@ -1316,7 +1315,6 @@ static int bam_dma_probe(struct platform_device *pdev) /* set max dma segment size */ bdev->common.dev = bdev->dev; - bdev->common.dev->dma_parms = &bdev->dma_parms; ret = dma_set_max_seg_size(bdev->common.dev, BAM_FIFO_SIZE); if (ret) { dev_err(bdev->dev, "cannot set maximum segment size\n"); diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c index 0a6d3ea08c78..6c0f9eb8ecc6 100644 --- a/drivers/dma/qcom/hidma.c +++ b/drivers/dma/qcom/hidma.c @@ -224,9 +224,9 @@ static int hidma_chan_init(struct hidma_dev *dmadev, u32 dma_sig) return 0; } -static void hidma_issue_task(unsigned long arg) +static void hidma_issue_task(struct tasklet_struct *t) { - struct hidma_dev *dmadev = (struct hidma_dev *)arg; + struct hidma_dev *dmadev = from_tasklet(dmadev, t, task); pm_runtime_get_sync(dmadev->ddev.dev); hidma_ll_start(dmadev->lldev); @@ -885,7 +885,7 @@ static int hidma_probe(struct platform_device *pdev) goto uninit; dmadev->irq = chirq; - tasklet_init(&dmadev->task, hidma_issue_task, (unsigned long)dmadev); + tasklet_setup(&dmadev->task, hidma_issue_task); hidma_debug_init(dmadev); hidma_sysfs_init(dmadev); dev_info(&pdev->dev, "HI-DMA engine driver registration complete\n"); diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c index bb4471e84e48..53244e0e34a3 100644 --- a/drivers/dma/qcom/hidma_ll.c +++ b/drivers/dma/qcom/hidma_ll.c @@ -173,9 +173,9 @@ int hidma_ll_request(struct hidma_lldev *lldev, u32 sig, const char *dev_name, /* * Multiple TREs may be queued and waiting in the pending queue. */ -static void hidma_ll_tre_complete(unsigned long arg) +static void hidma_ll_tre_complete(struct tasklet_struct *t) { - struct hidma_lldev *lldev = (struct hidma_lldev *)arg; + struct hidma_lldev *lldev = from_tasklet(lldev, t, task); struct hidma_tre *tre; while (kfifo_out(&lldev->handoff_fifo, &tre, 1)) { @@ -792,7 +792,7 @@ struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres, return NULL; spin_lock_init(&lldev->lock); - tasklet_init(&lldev->task, hidma_ll_tre_complete, (unsigned long)lldev); + tasklet_setup(&lldev->task, hidma_ll_tre_complete); lldev->initialized = 1; writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG); return lldev; diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c index 0fa7f14a65a1..1e918e284fc0 100644 --- a/drivers/dma/sa11x0-dma.c +++ b/drivers/dma/sa11x0-dma.c @@ -323,9 +323,9 @@ static void sa11x0_dma_start_txd(struct sa11x0_dma_chan *c) } } -static void sa11x0_dma_tasklet(unsigned long arg) +static void sa11x0_dma_tasklet(struct tasklet_struct *t) { - struct sa11x0_dma_dev *d = (struct sa11x0_dma_dev *)arg; + struct sa11x0_dma_dev *d = from_tasklet(d, t, task); struct sa11x0_dma_phy *p; struct sa11x0_dma_chan *c; unsigned pch, pch_alloc = 0; @@ -928,7 +928,7 @@ static int sa11x0_dma_probe(struct platform_device *pdev) goto err_ioremap; } - tasklet_init(&d->task, sa11x0_dma_tasklet, (unsigned long)d); + tasklet_setup(&d->task, sa11x0_dma_tasklet); for (i = 0; i < NR_PHY_CHAN; i++) { struct sa11x0_dma_phy *p = &d->phy[i]; diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c index 6e530dca6d9e..528deb5d9f31 100644 --- a/drivers/dma/sf-pdma/sf-pdma.c +++ b/drivers/dma/sf-pdma/sf-pdma.c @@ -281,10 +281,9 @@ static void sf_pdma_free_desc(struct virt_dma_desc *vdesc) desc->in_use = false; } -static void sf_pdma_donebh_tasklet(unsigned long arg) +static void sf_pdma_donebh_tasklet(struct tasklet_struct *t) { - struct sf_pdma_chan *chan = (struct sf_pdma_chan *)arg; - struct sf_pdma_desc *desc = chan->desc; + struct sf_pdma_chan *chan = from_tasklet(chan, t, done_tasklet); unsigned long flags; spin_lock_irqsave(&chan->lock, flags); @@ -295,12 +294,15 @@ static void sf_pdma_donebh_tasklet(unsigned long arg) } spin_unlock_irqrestore(&chan->lock, flags); - dmaengine_desc_get_callback_invoke(desc->async_tx, NULL); + spin_lock_irqsave(&chan->vchan.lock, flags); + list_del(&chan->desc->vdesc.node); + vchan_cookie_complete(&chan->desc->vdesc); + spin_unlock_irqrestore(&chan->vchan.lock, flags); } -static void sf_pdma_errbh_tasklet(unsigned long arg) +static void sf_pdma_errbh_tasklet(struct tasklet_struct *t) { - struct sf_pdma_chan *chan = (struct sf_pdma_chan *)arg; + struct sf_pdma_chan *chan = from_tasklet(chan, t, err_tasklet); struct sf_pdma_desc *desc = chan->desc; unsigned long flags; @@ -332,8 +334,7 @@ static irqreturn_t sf_pdma_done_isr(int irq, void *dev_id) residue = readq(regs->residue); if (!residue) { - list_del(&chan->desc->vdesc.node); - vchan_cookie_complete(&chan->desc->vdesc); + tasklet_hi_schedule(&chan->done_tasklet); } else { /* submit next trascatioin if possible */ struct sf_pdma_desc *desc = chan->desc; @@ -347,8 +348,6 @@ static irqreturn_t sf_pdma_done_isr(int irq, void *dev_id) spin_unlock_irqrestore(&chan->vchan.lock, flags); - tasklet_hi_schedule(&chan->done_tasklet); - return IRQ_HANDLED; } @@ -476,10 +475,8 @@ static void sf_pdma_setup_chans(struct sf_pdma *pdma) writel(PDMA_CLEAR_CTRL, chan->regs.ctrl); - tasklet_init(&chan->done_tasklet, - sf_pdma_donebh_tasklet, (unsigned long)chan); - tasklet_init(&chan->err_tasklet, - sf_pdma_errbh_tasklet, (unsigned long)chan); + tasklet_setup(&chan->done_tasklet, sf_pdma_donebh_tasklet); + tasklet_setup(&chan->err_tasklet, sf_pdma_errbh_tasklet); } } diff --git a/drivers/dma/sh/Kconfig b/drivers/dma/sh/Kconfig index 54d5d0369d3c..13437323a85b 100644 --- a/drivers/dma/sh/Kconfig +++ b/drivers/dma/sh/Kconfig @@ -32,12 +32,12 @@ config SH_DMAE Enable support for the Renesas SuperH DMA controllers. config RCAR_DMAC - tristate "Renesas R-Car Gen2 DMA Controller" + tristate "Renesas R-Car Gen{2,3} and RZ/G{1,2} DMA Controller" depends on ARCH_RENESAS || COMPILE_TEST select RENESAS_DMA help This driver supports the general purpose DMA controller found in the - Renesas R-Car second generation SoCs. + Renesas R-Car Gen{2,3} and RZ/G{1,2} SoCs. config RENESAS_USB_DMAC tristate "Renesas USB-DMA Controller" diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 59b36ab5d684..a57705356e8b 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -199,7 +199,6 @@ struct rcar_dmac { struct dma_device engine; struct device *dev; void __iomem *iomem; - struct device_dma_parameters parms; unsigned int n_channels; struct rcar_dmac_chan *channels; @@ -1228,7 +1227,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, * Allocate the sg list dynamically as it would consume too much stack * space. */ - sgl = kcalloc(sg_len, sizeof(*sgl), GFP_NOWAIT); + sgl = kmalloc_array(sg_len, sizeof(*sgl), GFP_NOWAIT); if (!sgl) return NULL; @@ -1845,7 +1844,6 @@ static int rcar_dmac_probe(struct platform_device *pdev) dmac->dev = &pdev->dev; platform_set_drvdata(pdev, dmac); - dmac->dev->dma_parms = &dmac->parms; dma_set_max_seg_size(dmac->dev, RCAR_DMATCR_MASK); dma_set_mask_and_coherent(dmac->dev, DMA_BIT_MASK(40)); diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c index 788d696323bb..7f72b3f4cd1a 100644 --- a/drivers/dma/sh/shdma-base.c +++ b/drivers/dma/sh/shdma-base.c @@ -728,7 +728,7 @@ static struct dma_async_tx_descriptor *shdma_prep_dma_cyclic( * Allocate the sg list dynamically as it would consumer too much stack * space. */ - sgl = kcalloc(sg_len, sizeof(*sgl), GFP_KERNEL); + sgl = kmalloc_array(sg_len, sizeof(*sgl), GFP_KERNEL); if (!sgl) return NULL; diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 30064689d67f..a5c2843384fd 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -393,9 +393,9 @@ static void sirfsoc_dma_process_completed(struct sirfsoc_dma *sdma) } /* DMA Tasklet */ -static void sirfsoc_dma_tasklet(unsigned long data) +static void sirfsoc_dma_tasklet(struct tasklet_struct *t) { - struct sirfsoc_dma *sdma = (void *)data; + struct sirfsoc_dma *sdma = from_tasklet(sdma, t, tasklet); sirfsoc_dma_process_completed(sdma); } @@ -938,7 +938,7 @@ static int sirfsoc_dma_probe(struct platform_device *op) list_add_tail(&schan->chan.device_node, &dma->channels); } - tasklet_init(&sdma->tasklet, sirfsoc_dma_tasklet, (unsigned long)sdma); + tasklet_setup(&sdma->tasklet, sirfsoc_dma_tasklet); /* Register DMA engine */ dev_set_drvdata(dev, sdma); diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 21e2f1d0c210..77ab1f4730be 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -535,7 +535,6 @@ struct d40_gen_dmac { * mode" allocated physical channels. * @num_log_chans: The number of logical channels. Calculated from * num_phy_chans. - * @dma_parms: DMA parameters for the channel * @dma_both: dma_device channels that can do both memcpy and slave transfers. * @dma_slave: dma_device channels that can do only do slave transfers. * @dma_memcpy: dma_device channels that can do only do memcpy transfers. @@ -577,7 +576,6 @@ struct d40_base { int num_memcpy_chans; int num_phy_chans; int num_log_chans; - struct device_dma_parameters dma_parms; struct dma_device dma_both; struct dma_device dma_slave; struct dma_device dma_memcpy; @@ -1573,9 +1571,9 @@ static void dma_tc_handle(struct d40_chan *d40c) } -static void dma_tasklet(unsigned long data) +static void dma_tasklet(struct tasklet_struct *t) { - struct d40_chan *d40c = (struct d40_chan *) data; + struct d40_chan *d40c = from_tasklet(d40c, t, tasklet); struct d40_desc *d40d; unsigned long flags; bool callback_active; @@ -2806,8 +2804,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma, INIT_LIST_HEAD(&d40c->client); INIT_LIST_HEAD(&d40c->prepare_queue); - tasklet_init(&d40c->tasklet, dma_tasklet, - (unsigned long) d40c); + tasklet_setup(&d40c->tasklet, dma_tasklet); list_add_tail(&d40c->chan.device_node, &dma->channels); @@ -3641,7 +3638,6 @@ static int __init d40_probe(struct platform_device *pdev) if (ret) goto destroy_cache; - base->dev->dma_parms = &base->dma_parms; ret = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE); if (ret) { d40_err(&pdev->dev, "Failed to set dma max seg size\n"); diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 96ad1b3d24c6..d0055d2f0b9a 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -1311,12 +1311,8 @@ static int stm32_dma_probe(struct platform_device *pdev) return PTR_ERR(dmadev->base); dmadev->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(dmadev->clk)) { - ret = PTR_ERR(dmadev->clk); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Can't get clock\n"); - return ret; - } + if (IS_ERR(dmadev->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(dmadev->clk), "Can't get clock\n"); ret = clk_prepare_enable(dmadev->clk); if (ret < 0) { diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c index 12f7637e13a1..a10ccd964376 100644 --- a/drivers/dma/stm32-dmamux.c +++ b/drivers/dma/stm32-dmamux.c @@ -252,12 +252,9 @@ static int stm32_dmamux_probe(struct platform_device *pdev) spin_lock_init(&stm32_dmamux->lock); stm32_dmamux->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(stm32_dmamux->clk)) { - ret = PTR_ERR(stm32_dmamux->clk); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Missing clock controller\n"); - return ret; - } + if (IS_ERR(stm32_dmamux->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(stm32_dmamux->clk), + "Missing clock controller\n"); ret = clk_prepare_enable(stm32_dmamux->clk); if (ret < 0) { diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index 5469563703d1..08cfbfab837b 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1580,12 +1580,9 @@ static int stm32_mdma_probe(struct platform_device *pdev) return PTR_ERR(dmadev->base); dmadev->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(dmadev->clk)) { - ret = PTR_ERR(dmadev->clk); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Missing clock controller\n"); - return ret; - } + if (IS_ERR(dmadev->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(dmadev->clk), + "Missing clock controller\n"); ret = clk_prepare_enable(dmadev->clk); if (ret < 0) { diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 06cd7f867f7c..f5f9c86c50bc 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -467,9 +467,9 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan) return 0; } -static void sun6i_dma_tasklet(unsigned long data) +static void sun6i_dma_tasklet(struct tasklet_struct *t) { - struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data; + struct sun6i_dma_dev *sdev = from_tasklet(sdev, t, task); struct sun6i_vchan *vchan; struct sun6i_pchan *pchan; unsigned int pchan_alloc = 0; @@ -1343,7 +1343,7 @@ static int sun6i_dma_probe(struct platform_device *pdev) if (!sdc->vchans) return -ENOMEM; - tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc); + tasklet_setup(&sdc->task, sun6i_dma_tasklet); for (i = 0; i < sdc->num_pchans; i++) { struct sun6i_pchan *pchan = &sdc->pchans[i]; diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 55fc7400f717..71827d9b0aa1 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -644,9 +644,9 @@ static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc, } } -static void tegra_dma_tasklet(unsigned long data) +static void tegra_dma_tasklet(struct tasklet_struct *t) { - struct tegra_dma_channel *tdc = (struct tegra_dma_channel *)data; + struct tegra_dma_channel *tdc = from_tasklet(tdc, t, tasklet); struct dmaengine_desc_callback cb; struct tegra_dma_desc *dma_desc; unsigned int cb_count; @@ -1523,8 +1523,7 @@ static int tegra_dma_probe(struct platform_device *pdev) tdc->id = i; tdc->slave_id = TEGRA_APBDMA_SLAVE_ID_INVALID; - tasklet_init(&tdc->tasklet, tegra_dma_tasklet, - (unsigned long)tdc); + tasklet_setup(&tdc->tasklet, tegra_dma_tasklet); spin_lock_init(&tdc->lock); init_waitqueue_head(&tdc->wq); diff --git a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile index 9a29a107e374..0c67254caee6 100644 --- a/drivers/dma/ti/Makefile +++ b/drivers/dma/ti/Makefile @@ -4,5 +4,8 @@ obj-$(CONFIG_TI_EDMA) += edma.o obj-$(CONFIG_DMA_OMAP) += omap-dma.o obj-$(CONFIG_TI_K3_UDMA) += k3-udma.o obj-$(CONFIG_TI_K3_UDMA_GLUE_LAYER) += k3-udma-glue.o -obj-$(CONFIG_TI_K3_PSIL) += k3-psil.o k3-psil-am654.o k3-psil-j721e.o +obj-$(CONFIG_TI_K3_PSIL) += k3-psil.o \ + k3-psil-am654.o \ + k3-psil-j721e.o \ + k3-psil-j7200.o obj-$(CONFIG_TI_DMA_CROSSBAR) += dma-crossbar.o diff --git a/drivers/dma/ti/k3-psil-j7200.c b/drivers/dma/ti/k3-psil-j7200.c new file mode 100644 index 000000000000..5ea63ea74822 --- /dev/null +++ b/drivers/dma/ti/k3-psil-j7200.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + */ + +#include <linux/kernel.h> + +#include "k3-psil-priv.h" + +#define PSIL_PDMA_XY_TR(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + }, \ + } + +#define PSIL_PDMA_XY_PKT(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .pkt_mode = 1, \ + }, \ + } + +#define PSIL_PDMA_MCASP(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .pdma_acc32 = 1, \ + .pdma_burst = 1, \ + }, \ + } + +#define PSIL_ETHERNET(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 16, \ + }, \ + } + +#define PSIL_SA2UL(x, tx) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 64, \ + .notdpkt = tx, \ + }, \ + } + +/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ +static struct psil_ep j7200_src_ep_map[] = { + /* PDMA_MCASP - McASP0-2 */ + PSIL_PDMA_MCASP(0x4400), + PSIL_PDMA_MCASP(0x4401), + PSIL_PDMA_MCASP(0x4402), + /* PDMA_SPI_G0 - SPI0-3 */ + PSIL_PDMA_XY_PKT(0x4600), + PSIL_PDMA_XY_PKT(0x4601), + PSIL_PDMA_XY_PKT(0x4602), + PSIL_PDMA_XY_PKT(0x4603), + PSIL_PDMA_XY_PKT(0x4604), + PSIL_PDMA_XY_PKT(0x4605), + PSIL_PDMA_XY_PKT(0x4606), + PSIL_PDMA_XY_PKT(0x4607), + PSIL_PDMA_XY_PKT(0x4608), + PSIL_PDMA_XY_PKT(0x4609), + PSIL_PDMA_XY_PKT(0x460a), + PSIL_PDMA_XY_PKT(0x460b), + PSIL_PDMA_XY_PKT(0x460c), + PSIL_PDMA_XY_PKT(0x460d), + PSIL_PDMA_XY_PKT(0x460e), + PSIL_PDMA_XY_PKT(0x460f), + /* PDMA_SPI_G1 - SPI4-7 */ + PSIL_PDMA_XY_PKT(0x4610), + PSIL_PDMA_XY_PKT(0x4611), + PSIL_PDMA_XY_PKT(0x4612), + PSIL_PDMA_XY_PKT(0x4613), + PSIL_PDMA_XY_PKT(0x4614), + PSIL_PDMA_XY_PKT(0x4615), + PSIL_PDMA_XY_PKT(0x4616), + PSIL_PDMA_XY_PKT(0x4617), + PSIL_PDMA_XY_PKT(0x4618), + PSIL_PDMA_XY_PKT(0x4619), + PSIL_PDMA_XY_PKT(0x461a), + PSIL_PDMA_XY_PKT(0x461b), + PSIL_PDMA_XY_PKT(0x461c), + PSIL_PDMA_XY_PKT(0x461d), + PSIL_PDMA_XY_PKT(0x461e), + PSIL_PDMA_XY_PKT(0x461f), + /* PDMA_USART_G0 - UART0-1 */ + PSIL_PDMA_XY_PKT(0x4700), + PSIL_PDMA_XY_PKT(0x4701), + /* PDMA_USART_G1 - UART2-3 */ + PSIL_PDMA_XY_PKT(0x4702), + PSIL_PDMA_XY_PKT(0x4703), + /* PDMA_USART_G2 - UART4-9 */ + PSIL_PDMA_XY_PKT(0x4704), + PSIL_PDMA_XY_PKT(0x4705), + PSIL_PDMA_XY_PKT(0x4706), + PSIL_PDMA_XY_PKT(0x4707), + PSIL_PDMA_XY_PKT(0x4708), + PSIL_PDMA_XY_PKT(0x4709), + /* CPSW5 */ + PSIL_ETHERNET(0x4a00), + /* CPSW0 */ + PSIL_ETHERNET(0x7000), + /* MCU_PDMA_MISC_G0 - SPI0 */ + PSIL_PDMA_XY_PKT(0x7100), + PSIL_PDMA_XY_PKT(0x7101), + PSIL_PDMA_XY_PKT(0x7102), + PSIL_PDMA_XY_PKT(0x7103), + /* MCU_PDMA_MISC_G1 - SPI1-2 */ + PSIL_PDMA_XY_PKT(0x7200), + PSIL_PDMA_XY_PKT(0x7201), + PSIL_PDMA_XY_PKT(0x7202), + PSIL_PDMA_XY_PKT(0x7203), + PSIL_PDMA_XY_PKT(0x7204), + PSIL_PDMA_XY_PKT(0x7205), + PSIL_PDMA_XY_PKT(0x7206), + PSIL_PDMA_XY_PKT(0x7207), + /* MCU_PDMA_MISC_G2 - UART0 */ + PSIL_PDMA_XY_PKT(0x7300), + /* MCU_PDMA_ADC - ADC0-1 */ + PSIL_PDMA_XY_TR(0x7400), + PSIL_PDMA_XY_TR(0x7401), + /* SA2UL */ + PSIL_SA2UL(0x7500, 0), + PSIL_SA2UL(0x7501, 0), + PSIL_SA2UL(0x7502, 0), + PSIL_SA2UL(0x7503, 0), +}; + +/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ +static struct psil_ep j7200_dst_ep_map[] = { + /* CPSW5 */ + PSIL_ETHERNET(0xca00), + PSIL_ETHERNET(0xca01), + PSIL_ETHERNET(0xca02), + PSIL_ETHERNET(0xca03), + PSIL_ETHERNET(0xca04), + PSIL_ETHERNET(0xca05), + PSIL_ETHERNET(0xca06), + PSIL_ETHERNET(0xca07), + /* CPSW0 */ + PSIL_ETHERNET(0xf000), + PSIL_ETHERNET(0xf001), + PSIL_ETHERNET(0xf002), + PSIL_ETHERNET(0xf003), + PSIL_ETHERNET(0xf004), + PSIL_ETHERNET(0xf005), + PSIL_ETHERNET(0xf006), + PSIL_ETHERNET(0xf007), + /* SA2UL */ + PSIL_SA2UL(0xf500, 1), + PSIL_SA2UL(0xf501, 1), +}; + +struct psil_ep_map j7200_ep_map = { + .name = "j7200", + .src = j7200_src_ep_map, + .src_count = ARRAY_SIZE(j7200_src_ep_map), + .dst = j7200_dst_ep_map, + .dst_count = ARRAY_SIZE(j7200_dst_ep_map), +}; diff --git a/drivers/dma/ti/k3-psil-j721e.c b/drivers/dma/ti/k3-psil-j721e.c index e3cfd5f66842..7580870ed746 100644 --- a/drivers/dma/ti/k3-psil-j721e.c +++ b/drivers/dma/ti/k3-psil-j721e.c @@ -166,6 +166,8 @@ static struct psil_ep j721e_src_ep_map[] = { /* SA2UL */ PSIL_SA2UL(0x7500, 0), PSIL_SA2UL(0x7501, 0), + PSIL_SA2UL(0x7502, 0), + PSIL_SA2UL(0x7503, 0), }; /* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ @@ -211,6 +213,7 @@ static struct psil_ep j721e_dst_ep_map[] = { PSIL_ETHERNET(0xf007), /* SA2UL */ PSIL_SA2UL(0xf500, 1), + PSIL_SA2UL(0xf501, 1), }; struct psil_ep_map j721e_ep_map = { diff --git a/drivers/dma/ti/k3-psil-priv.h b/drivers/dma/ti/k3-psil-priv.h index a1f389ca371e..b4b0fb359eff 100644 --- a/drivers/dma/ti/k3-psil-priv.h +++ b/drivers/dma/ti/k3-psil-priv.h @@ -39,5 +39,6 @@ struct psil_endpoint_config *psil_get_ep_config(u32 thread_id); /* SoC PSI-L endpoint maps */ extern struct psil_ep_map am654_ep_map; extern struct psil_ep_map j721e_ep_map; +extern struct psil_ep_map j7200_ep_map; #endif /* K3_PSIL_PRIV_H_ */ diff --git a/drivers/dma/ti/k3-psil.c b/drivers/dma/ti/k3-psil.c index fb7c8150b0d1..837853aab95a 100644 --- a/drivers/dma/ti/k3-psil.c +++ b/drivers/dma/ti/k3-psil.c @@ -9,11 +9,19 @@ #include <linux/init.h> #include <linux/mutex.h> #include <linux/of.h> +#include <linux/sys_soc.h> #include "k3-psil-priv.h" static DEFINE_MUTEX(ep_map_mutex); -static struct psil_ep_map *soc_ep_map; +static const struct psil_ep_map *soc_ep_map; + +static const struct soc_device_attribute k3_soc_devices[] = { + { .family = "AM65X", .data = &am654_ep_map }, + { .family = "J721E", .data = &j721e_ep_map }, + { .family = "J7200", .data = &j7200_ep_map }, + { /* sentinel */ } +}; struct psil_endpoint_config *psil_get_ep_config(u32 thread_id) { @@ -21,10 +29,11 @@ struct psil_endpoint_config *psil_get_ep_config(u32 thread_id) mutex_lock(&ep_map_mutex); if (!soc_ep_map) { - if (of_machine_is_compatible("ti,am654")) { - soc_ep_map = &am654_ep_map; - } else if (of_machine_is_compatible("ti,j721e")) { - soc_ep_map = &j721e_ep_map; + const struct soc_device_attribute *soc; + + soc = soc_device_match(k3_soc_devices); + if (soc) { + soc_ep_map = soc->data; } else { pr_err("PSIL: No compatible machine found for map\n"); mutex_unlock(&ep_map_mutex); diff --git a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c index 3a5d33ea5ebe..42c8ad10d75e 100644 --- a/drivers/dma/ti/k3-udma-glue.c +++ b/drivers/dma/ti/k3-udma-glue.c @@ -378,17 +378,11 @@ EXPORT_SYMBOL_GPL(k3_udma_glue_pop_tx_chn); int k3_udma_glue_enable_tx_chn(struct k3_udma_glue_tx_channel *tx_chn) { - u32 txrt_ctl; - - txrt_ctl = UDMA_PEER_RT_EN_ENABLE; xudma_tchanrt_write(tx_chn->udma_tchanx, UDMA_CHAN_RT_PEER_RT_EN_REG, - txrt_ctl); + UDMA_PEER_RT_EN_ENABLE); - txrt_ctl = xudma_tchanrt_read(tx_chn->udma_tchanx, - UDMA_CHAN_RT_CTL_REG); - txrt_ctl |= UDMA_CHAN_RT_CTL_EN; xudma_tchanrt_write(tx_chn->udma_tchanx, UDMA_CHAN_RT_CTL_REG, - txrt_ctl); + UDMA_CHAN_RT_CTL_EN); k3_udma_glue_dump_tx_rt_chn(tx_chn, "txchn en"); return 0; @@ -1058,19 +1052,14 @@ EXPORT_SYMBOL_GPL(k3_udma_glue_rx_flow_disable); int k3_udma_glue_enable_rx_chn(struct k3_udma_glue_rx_channel *rx_chn) { - u32 rxrt_ctl; - if (rx_chn->remote) return -EINVAL; if (rx_chn->flows_ready < rx_chn->flow_num) return -EINVAL; - rxrt_ctl = xudma_rchanrt_read(rx_chn->udma_rchanx, - UDMA_CHAN_RT_CTL_REG); - rxrt_ctl |= UDMA_CHAN_RT_CTL_EN; xudma_rchanrt_write(rx_chn->udma_rchanx, UDMA_CHAN_RT_CTL_REG, - rxrt_ctl); + UDMA_CHAN_RT_CTL_EN); xudma_rchanrt_write(rx_chn->udma_rchanx, UDMA_CHAN_RT_PEER_RT_EN_REG, UDMA_PEER_RT_EN_ENABLE); diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index d86dba0fd8e6..82cf6c77f5c9 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -16,6 +16,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/spinlock.h> +#include <linux/sys_soc.h> #include <linux/of.h> #include <linux/of_dma.h> #include <linux/of_device.h> @@ -91,6 +92,9 @@ struct udma_match_data { bool enable_memcpy_support; u32 flags; u32 statictr_z_mask; +}; + +struct udma_soc_data { u32 rchan_oes_offset; }; @@ -117,6 +121,7 @@ struct udma_dev { struct device *dev; void __iomem *mmrs[MMR_LAST]; const struct udma_match_data *match_data; + const struct udma_soc_data *soc_data; u8 tpl_levels; u32 tpl_start_idx[3]; @@ -1679,7 +1684,7 @@ static int udma_alloc_chan_resources(struct dma_chan *chan) { struct udma_chan *uc = to_udma_chan(chan); struct udma_dev *ud = to_udma_dev(chan->device); - const struct udma_match_data *match_data = ud->match_data; + const struct udma_soc_data *soc_data = ud->soc_data; struct k3_ring *irq_ring; u32 irq_udma_idx; int ret; @@ -1779,7 +1784,7 @@ static int udma_alloc_chan_resources(struct dma_chan *chan) K3_PSIL_DST_THREAD_ID_OFFSET; irq_ring = uc->rflow->r_ring; - irq_udma_idx = match_data->rchan_oes_offset + uc->rchan->id; + irq_udma_idx = soc_data->rchan_oes_offset + uc->rchan->id; ret = udma_tisci_rx_channel_config(uc); break; @@ -2024,11 +2029,6 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl, int num_tr = 0; int tr_idx = 0; - if (!is_slave_direction(dir)) { - dev_err(uc->ud->dev, "Only slave cyclic is supported\n"); - return NULL; - } - /* estimate the number of TRs we will need */ for_each_sg(sgl, sgent, sglen, i) { if (sg_dma_len(sgent) < SZ_64K) @@ -2400,11 +2400,6 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr, unsigned int i; int num_tr; - if (!is_slave_direction(dir)) { - dev_err(uc->ud->dev, "Only slave cyclic is supported\n"); - return NULL; - } - num_tr = udma_get_tr_counters(period_len, __ffs(buf_addr), &tr0_cnt0, &tr0_cnt1, &tr1_cnt0); if (num_tr < 0) { @@ -2914,9 +2909,9 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, * This tasklet handles the completion of a DMA descriptor by * calling its callback and freeing it. */ -static void udma_vchan_complete(unsigned long arg) +static void udma_vchan_complete(struct tasklet_struct *t) { - struct virt_dma_chan *vc = (struct virt_dma_chan *)arg; + struct virt_dma_chan *vc = from_tasklet(vc, t, task); struct virt_dma_desc *vd, *_vd; struct dmaengine_desc_callback cb; LIST_HEAD(head); @@ -3101,14 +3096,12 @@ static struct udma_match_data am654_main_data = { .psil_base = 0x1000, .enable_memcpy_support = true, .statictr_z_mask = GENMASK(11, 0), - .rchan_oes_offset = 0x200, }; static struct udma_match_data am654_mcu_data = { .psil_base = 0x6000, .enable_memcpy_support = false, .statictr_z_mask = GENMASK(11, 0), - .rchan_oes_offset = 0x200, }; static struct udma_match_data j721e_main_data = { @@ -3116,7 +3109,6 @@ static struct udma_match_data j721e_main_data = { .enable_memcpy_support = true, .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST, .statictr_z_mask = GENMASK(23, 0), - .rchan_oes_offset = 0x400, }; static struct udma_match_data j721e_mcu_data = { @@ -3124,7 +3116,6 @@ static struct udma_match_data j721e_mcu_data = { .enable_memcpy_support = false, /* MEM_TO_MEM is slow via MCU UDMA */ .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST, .statictr_z_mask = GENMASK(23, 0), - .rchan_oes_offset = 0x400, }; static const struct of_device_id udma_of_match[] = { @@ -3145,15 +3136,31 @@ static const struct of_device_id udma_of_match[] = { { /* Sentinel */ }, }; +static struct udma_soc_data am654_soc_data = { + .rchan_oes_offset = 0x200, +}; + +static struct udma_soc_data j721e_soc_data = { + .rchan_oes_offset = 0x400, +}; + +static struct udma_soc_data j7200_soc_data = { + .rchan_oes_offset = 0x80, +}; + +static const struct soc_device_attribute k3_soc_devices[] = { + { .family = "AM65X", .data = &am654_soc_data }, + { .family = "J721E", .data = &j721e_soc_data }, + { .family = "J7200", .data = &j7200_soc_data }, + { /* sentinel */ } +}; + static int udma_get_mmrs(struct platform_device *pdev, struct udma_dev *ud) { - struct resource *res; int i; for (i = 0; i < MMR_LAST; i++) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - mmr_names[i]); - ud->mmrs[i] = devm_ioremap_resource(&pdev->dev, res); + ud->mmrs[i] = devm_platform_ioremap_resource_byname(pdev, mmr_names[i]); if (IS_ERR(ud->mmrs[i])) return PTR_ERR(ud->mmrs[i]); } @@ -3287,7 +3294,7 @@ static int udma_setup_resources(struct udma_dev *ud) rm_res = tisci_rm->rm_ranges[RM_RANGE_RCHAN]; for (j = 0; j < rm_res->sets; j++, i++) { irq_res.desc[i].start = rm_res->desc[j].start + - ud->match_data->rchan_oes_offset; + ud->soc_data->rchan_oes_offset; irq_res.desc[i].num = rm_res->desc[j].num; } ret = ti_sci_inta_msi_domain_alloc_irqs(ud->dev, &irq_res); @@ -3497,6 +3504,7 @@ static void udma_dbg_summary_show(struct seq_file *s, static int udma_probe(struct platform_device *pdev) { struct device_node *navss_node = pdev->dev.parent->of_node; + const struct soc_device_attribute *soc; struct device *dev = &pdev->dev; struct udma_dev *ud; const struct of_device_id *match; @@ -3561,6 +3569,13 @@ static int udma_probe(struct platform_device *pdev) } ud->match_data = match->data; + soc = soc_device_match(k3_soc_devices); + if (!soc) { + dev_err(dev, "No compatible SoC found\n"); + return -ENODEV; + } + ud->soc_data = soc->data; + dma_cap_set(DMA_SLAVE, ud->ddev.cap_mask); dma_cap_set(DMA_CYCLIC, ud->ddev.cap_mask); @@ -3649,8 +3664,7 @@ static int udma_probe(struct platform_device *pdev) vchan_init(&uc->vc, &ud->ddev); /* Use custom vchan completion handling */ - tasklet_init(&uc->vc.task, udma_vchan_complete, - (unsigned long)&uc->vc); + tasklet_setup(&uc->vc.task, udma_vchan_complete); init_completion(&uc->teardown_completed); INIT_DELAYED_WORK(&uc->tx_drain.work, udma_check_tx_completion); } diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c index 918301e17552..c9fe5e3a6b55 100644 --- a/drivers/dma/ti/omap-dma.c +++ b/drivers/dma/ti/omap-dma.c @@ -1904,7 +1904,7 @@ static struct platform_driver omap_dma_driver = { .remove = omap_dma_remove, .driver = { .name = "omap-dma-engine", - .of_match_table = of_match_ptr(omap_dma_match), + .of_match_table = omap_dma_match, }, }; diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index 68e48bf54d78..3f524be69efb 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c @@ -563,9 +563,9 @@ static int td_terminate_all(struct dma_chan *chan) return 0; } -static void td_tasklet(unsigned long data) +static void td_tasklet(struct tasklet_struct *t) { - struct timb_dma *td = (struct timb_dma *)data; + struct timb_dma *td = from_tasklet(td, t, tasklet); u32 isr; u32 ipr; u32 ier; @@ -658,7 +658,7 @@ static int td_probe(struct platform_device *pdev) iowrite32(0x0, td->membase + TIMBDMA_IER); iowrite32(0xFFFFFFFF, td->membase + TIMBDMA_ISR); - tasklet_init(&td->tasklet, td_tasklet, (unsigned long)td); + tasklet_setup(&td->tasklet, td_tasklet); err = request_irq(irq, td_irq, IRQF_SHARED, DRIVER_NAME, td); if (err) { diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index 628bdf4430c7..5b6b375a257e 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c @@ -601,13 +601,13 @@ scan_done: } } -static void txx9dmac_chan_tasklet(unsigned long data) +static void txx9dmac_chan_tasklet(struct tasklet_struct *t) { int irq; u32 csr; struct txx9dmac_chan *dc; - dc = (struct txx9dmac_chan *)data; + dc = from_tasklet(dc, t, tasklet); csr = channel_readl(dc, CSR); dev_vdbg(chan2dev(&dc->chan), "tasklet: status=%x\n", csr); @@ -638,13 +638,13 @@ static irqreturn_t txx9dmac_chan_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void txx9dmac_tasklet(unsigned long data) +static void txx9dmac_tasklet(struct tasklet_struct *t) { int irq; u32 csr; struct txx9dmac_chan *dc; - struct txx9dmac_dev *ddev = (struct txx9dmac_dev *)data; + struct txx9dmac_dev *ddev = from_tasklet(ddev, t, tasklet); u32 mcr; int i; @@ -1113,8 +1113,7 @@ static int __init txx9dmac_chan_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - tasklet_init(&dc->tasklet, txx9dmac_chan_tasklet, - (unsigned long)dc); + tasklet_setup(&dc->tasklet, txx9dmac_chan_tasklet); dc->irq = irq; err = devm_request_irq(&pdev->dev, dc->irq, txx9dmac_chan_interrupt, 0, dev_name(&pdev->dev), dc); @@ -1200,8 +1199,7 @@ static int __init txx9dmac_probe(struct platform_device *pdev) ddev->irq = platform_get_irq(pdev, 0); if (ddev->irq >= 0) { - tasklet_init(&ddev->tasklet, txx9dmac_tasklet, - (unsigned long)ddev); + tasklet_setup(&ddev->tasklet, txx9dmac_tasklet); err = devm_request_irq(&pdev->dev, ddev->irq, txx9dmac_interrupt, 0, dev_name(&pdev->dev), ddev); if (err) diff --git a/drivers/dma/virt-dma.c b/drivers/dma/virt-dma.c index 23e33a85f033..a6f4265be0c9 100644 --- a/drivers/dma/virt-dma.c +++ b/drivers/dma/virt-dma.c @@ -80,9 +80,9 @@ EXPORT_SYMBOL_GPL(vchan_find_desc); * This tasklet handles the completion of a DMA descriptor by * calling its callback and freeing it. */ -static void vchan_complete(unsigned long arg) +static void vchan_complete(struct tasklet_struct *t) { - struct virt_dma_chan *vc = (struct virt_dma_chan *)arg; + struct virt_dma_chan *vc = from_tasklet(vc, t, task); struct virt_dma_desc *vd, *_vd; struct dmaengine_desc_callback cb; LIST_HEAD(head); @@ -131,7 +131,7 @@ void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev) INIT_LIST_HEAD(&vc->desc_completed); INIT_LIST_HEAD(&vc->desc_terminated); - tasklet_init(&vc->task, vchan_complete, (unsigned long)vc); + tasklet_setup(&vc->task, vchan_complete); vc->chan.device = dmadev; list_add_tail(&vc->chan.device_node, &dmadev->channels); diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c index 4f733d37a22e..3589b4ef50b8 100644 --- a/drivers/dma/xgene-dma.c +++ b/drivers/dma/xgene-dma.c @@ -975,9 +975,9 @@ static enum dma_status xgene_dma_tx_status(struct dma_chan *dchan, return dma_cookie_status(dchan, cookie, txstate); } -static void xgene_dma_tasklet_cb(unsigned long data) +static void xgene_dma_tasklet_cb(struct tasklet_struct *t) { - struct xgene_dma_chan *chan = (struct xgene_dma_chan *)data; + struct xgene_dma_chan *chan = from_tasklet(chan, t, tasklet); /* Run all cleanup for descriptors which have been completed */ xgene_dma_cleanup_descriptors(chan); @@ -1539,8 +1539,7 @@ static int xgene_dma_async_register(struct xgene_dma *pdma, int id) INIT_LIST_HEAD(&chan->ld_pending); INIT_LIST_HEAD(&chan->ld_running); INIT_LIST_HEAD(&chan->ld_completed); - tasklet_init(&chan->tasklet, xgene_dma_tasklet_cb, - (unsigned long)chan); + tasklet_setup(&chan->tasklet, xgene_dma_tasklet_cb); chan->pending = 0; chan->desc_pool = NULL; diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index 5429497d3560..ecff35402860 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -1044,11 +1044,11 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan) /** * xilinx_dma_do_tasklet - Schedule completion tasklet - * @data: Pointer to the Xilinx DMA channel structure + * @t: Pointer to the Xilinx DMA channel structure */ -static void xilinx_dma_do_tasklet(unsigned long data) +static void xilinx_dma_do_tasklet(struct tasklet_struct *t) { - struct xilinx_dma_chan *chan = (struct xilinx_dma_chan *)data; + struct xilinx_dma_chan *chan = from_tasklet(chan, t, tasklet); xilinx_dma_chan_desc_cleanup(chan); } @@ -2536,13 +2536,8 @@ static int axidma_clk_init(struct platform_device *pdev, struct clk **axi_clk, *tmp_clk = NULL; *axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk"); - if (IS_ERR(*axi_clk)) { - err = PTR_ERR(*axi_clk); - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to get axi_aclk (%d)\n", - err); - return err; - } + if (IS_ERR(*axi_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(*axi_clk), "failed to get axi_aclk\n"); *tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk"); if (IS_ERR(*tx_clk)) @@ -2603,22 +2598,12 @@ static int axicdma_clk_init(struct platform_device *pdev, struct clk **axi_clk, *tmp2_clk = NULL; *axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk"); - if (IS_ERR(*axi_clk)) { - err = PTR_ERR(*axi_clk); - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to get axi_clk (%d)\n", - err); - return err; - } + if (IS_ERR(*axi_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(*axi_clk), "failed to get axi_aclk\n"); *dev_clk = devm_clk_get(&pdev->dev, "m_axi_aclk"); - if (IS_ERR(*dev_clk)) { - err = PTR_ERR(*dev_clk); - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to get dev_clk (%d)\n", - err); - return err; - } + if (IS_ERR(*dev_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(*dev_clk), "failed to get dev_clk\n"); err = clk_prepare_enable(*axi_clk); if (err) { @@ -2647,13 +2632,8 @@ static int axivdma_clk_init(struct platform_device *pdev, struct clk **axi_clk, int err; *axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk"); - if (IS_ERR(*axi_clk)) { - err = PTR_ERR(*axi_clk); - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to get axi_aclk (%d)\n", - err); - return err; - } + if (IS_ERR(*axi_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(*axi_clk), "failed to get axi_aclk\n"); *tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk"); if (IS_ERR(*tx_clk)) @@ -2866,8 +2846,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, } /* Initialize the tasklet */ - tasklet_init(&chan->tasklet, xilinx_dma_do_tasklet, - (unsigned long)chan); + tasklet_setup(&chan->tasklet, xilinx_dma_do_tasklet); /* * Initialize the DMA channel and add it to the DMA engine channels diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c index b37197c772aa..55df63dead8d 100644 --- a/drivers/dma/xilinx/xilinx_dpdma.c +++ b/drivers/dma/xilinx/xilinx_dpdma.c @@ -10,6 +10,7 @@ #include <linux/bitfield.h> #include <linux/bits.h> #include <linux/clk.h> +#include <linux/debugfs.h> #include <linux/delay.h> #include <linux/dmaengine.h> #include <linux/dmapool.h> @@ -267,6 +268,210 @@ 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" + +/* Match xilinx_dpdma_testcases vs dpdma_debugfs_reqs[] entry */ +enum xilinx_dpdma_testcases { + DPDMA_TC_INTR_DONE, + DPDMA_TC_NONE +}; + +struct xilinx_dpdma_debugfs { + enum xilinx_dpdma_testcases testcase; + u16 xilinx_dpdma_irq_done_count; + unsigned int chan_id; +}; + +static struct xilinx_dpdma_debugfs dpdma_debugfs; +struct xilinx_dpdma_debugfs_request { + const char *name; + enum xilinx_dpdma_testcases tc; + ssize_t (*read)(char *buf); + int (*write)(char *args); +}; + +static void xilinx_dpdma_debugfs_desc_done_irq(struct xilinx_dpdma_chan *chan) +{ + if (chan->id == dpdma_debugfs.chan_id) + dpdma_debugfs.xilinx_dpdma_irq_done_count++; +} + +static ssize_t xilinx_dpdma_debugfs_desc_done_irq_read(char *buf) +{ + size_t out_str_len; + + dpdma_debugfs.testcase = DPDMA_TC_NONE; + + out_str_len = strlen(XILINX_DPDMA_DEBUGFS_UINT16_MAX_STR); + out_str_len = min_t(size_t, XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE, + out_str_len); + snprintf(buf, out_str_len, "%d", + dpdma_debugfs.xilinx_dpdma_irq_done_count); + + return 0; +} + +static int xilinx_dpdma_debugfs_desc_done_irq_write(char *args) +{ + char *arg; + int ret; + u32 id; + + arg = strsep(&args, " "); + if (!arg || strncasecmp(arg, "start", 5)) + return -EINVAL; + + arg = strsep(&args, " "); + if (!arg) + return -EINVAL; + + ret = kstrtou32(arg, 0, &id); + if (ret < 0) + return ret; + + if (id < ZYNQMP_DPDMA_VIDEO0 || id > ZYNQMP_DPDMA_AUDIO1) + return -EINVAL; + + dpdma_debugfs.testcase = DPDMA_TC_INTR_DONE; + dpdma_debugfs.xilinx_dpdma_irq_done_count = 0; + dpdma_debugfs.chan_id = id; + + return 0; +} + +/* Match xilinx_dpdma_testcases vs dpdma_debugfs_reqs[] entry */ +static struct xilinx_dpdma_debugfs_request dpdma_debugfs_reqs[] = { + { + .name = "DESCRIPTOR_DONE_INTR", + .tc = DPDMA_TC_INTR_DONE, + .read = xilinx_dpdma_debugfs_desc_done_irq_read, + .write = xilinx_dpdma_debugfs_desc_done_irq_write, + }, +}; + +static ssize_t xilinx_dpdma_debugfs_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + enum xilinx_dpdma_testcases testcase; + char *kern_buff; + int ret = 0; + + if (*pos != 0 || size <= 0) + return -EINVAL; + + kern_buff = kzalloc(XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE, GFP_KERNEL); + if (!kern_buff) { + dpdma_debugfs.testcase = DPDMA_TC_NONE; + return -ENOMEM; + } + + testcase = READ_ONCE(dpdma_debugfs.testcase); + if (testcase != DPDMA_TC_NONE) { + ret = dpdma_debugfs_reqs[testcase].read(kern_buff); + if (ret < 0) + goto done; + } else { + strlcpy(kern_buff, "No testcase executed", + XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE); + } + + size = min(size, strlen(kern_buff)); + if (copy_to_user(buf, kern_buff, size)) + ret = -EFAULT; + +done: + kfree(kern_buff); + if (ret) + return ret; + + *pos = size + 1; + return size; +} + +static ssize_t xilinx_dpdma_debugfs_write(struct file *f, + const char __user *buf, size_t size, + loff_t *pos) +{ + char *kern_buff, *kern_buff_start; + char *testcase; + unsigned int i; + int ret; + + if (*pos != 0 || size <= 0) + return -EINVAL; + + /* Supporting single instance of test as of now. */ + if (dpdma_debugfs.testcase != DPDMA_TC_NONE) + return -EBUSY; + + kern_buff = kzalloc(size, GFP_KERNEL); + if (!kern_buff) + return -ENOMEM; + kern_buff_start = kern_buff; + + ret = strncpy_from_user(kern_buff, buf, size); + if (ret < 0) + goto done; + + /* Read the testcase name from a user request. */ + testcase = strsep(&kern_buff, " "); + + for (i = 0; i < ARRAY_SIZE(dpdma_debugfs_reqs); i++) { + if (!strcasecmp(testcase, dpdma_debugfs_reqs[i].name)) + break; + } + + if (i == ARRAY_SIZE(dpdma_debugfs_reqs)) { + ret = -EINVAL; + goto done; + } + + ret = dpdma_debugfs_reqs[i].write(kern_buff); + if (ret < 0) + goto done; + + ret = size; + +done: + kfree(kern_buff_start); + return ret; +} + +static const struct file_operations fops_xilinx_dpdma_dbgfs = { + .owner = THIS_MODULE, + .read = xilinx_dpdma_debugfs_read, + .write = xilinx_dpdma_debugfs_write, +}; + +static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev) +{ + struct dentry *dent; + + dpdma_debugfs.testcase = DPDMA_TC_NONE; + + dent = debugfs_create_file("testcase", 0444, xdev->common.dbg_dev_root, + NULL, &fops_xilinx_dpdma_dbgfs); + if (IS_ERR(dent)) + 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 */ @@ -842,6 +1047,8 @@ static void xilinx_dpdma_chan_done_irq(struct xilinx_dpdma_chan *chan) spin_lock_irqsave(&chan->lock, flags); + xilinx_dpdma_debugfs_desc_done_irq(chan); + if (active) vchan_cyclic_callback(&active->vdesc); else @@ -1251,15 +1458,15 @@ static void xilinx_dpdma_disable_irq(struct xilinx_dpdma_device *xdev) /** * xilinx_dpdma_chan_err_task - Per channel tasklet for error handling - * @data: tasklet data to be casted to DPDMA channel structure + * @t: pointer to the tasklet associated with this handler * * Per channel error handling tasklet. This function waits for the outstanding * transaction to complete and triggers error handling. After error handling, * re-enable channel error interrupts, and restart the channel if needed. */ -static void xilinx_dpdma_chan_err_task(unsigned long data) +static void xilinx_dpdma_chan_err_task(struct tasklet_struct *t) { - struct xilinx_dpdma_chan *chan = (struct xilinx_dpdma_chan *)data; + struct xilinx_dpdma_chan *chan = from_tasklet(chan, t, err_task); struct xilinx_dpdma_device *xdev = chan->xdev; unsigned long flags; @@ -1348,8 +1555,7 @@ static int xilinx_dpdma_chan_init(struct xilinx_dpdma_device *xdev, spin_lock_init(&chan->lock); init_waitqueue_head(&chan->wait_to_stop); - tasklet_init(&chan->err_task, xilinx_dpdma_chan_err_task, - (unsigned long)chan); + tasklet_setup(&chan->err_task, xilinx_dpdma_chan_err_task); chan->vchan.desc_free = xilinx_dpdma_chan_free_tx_desc; vchan_init(&chan->vchan, &xdev->common); @@ -1477,6 +1683,8 @@ static int xilinx_dpdma_probe(struct platform_device *pdev) xilinx_dpdma_enable_irq(xdev); + xilinx_dpdma_debugfs_init(xdev); + dev_info(&pdev->dev, "Xilinx DPDMA engine is probed\n"); return 0; diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index ff253696d183..d8419565b92c 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -742,11 +742,11 @@ static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data) /** * zynqmp_dma_do_tasklet - Schedule completion tasklet - * @data: Pointer to the ZynqMP DMA channel structure + * @t: Pointer to the ZynqMP DMA channel structure */ -static void zynqmp_dma_do_tasklet(unsigned long data) +static void zynqmp_dma_do_tasklet(struct tasklet_struct *t) { - struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data; + struct zynqmp_dma_chan *chan = from_tasklet(chan, t, tasklet); u32 count; unsigned long irqflags; @@ -908,7 +908,7 @@ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev, chan->is_dmacoherent = of_property_read_bool(node, "dma-coherent"); zdev->chan = chan; - tasklet_init(&chan->tasklet, zynqmp_dma_do_tasklet, (ulong)chan); + tasklet_setup(&chan->tasklet, zynqmp_dma_do_tasklet); spin_lock_init(&chan->lock); INIT_LIST_HEAD(&chan->active_list); INIT_LIST_HEAD(&chan->pending_list); diff --git a/drivers/dma/zx_dma.c b/drivers/dma/zx_dma.c index 5fe2e8b9a7b8..b057582b2fac 100644 --- a/drivers/dma/zx_dma.c +++ b/drivers/dma/zx_dma.c @@ -285,9 +285,7 @@ static irqreturn_t zx_dma_int_handler(int irq, void *dev_id) p = &d->phy[i]; c = p->vchan; if (c) { - unsigned long flags; - - spin_lock_irqsave(&c->vc.lock, flags); + spin_lock(&c->vc.lock); if (c->cyclic) { vchan_cyclic_callback(&p->ds_run->vd); } else { @@ -295,7 +293,7 @@ static irqreturn_t zx_dma_int_handler(int irq, void *dev_id) p->ds_done = p->ds_run; task = 1; } - spin_unlock_irqrestore(&c->vc.lock, flags); + spin_unlock(&c->vc.lock); irq_chan |= BIT(i); } } diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 6fbd5c99e30c..dd357a747780 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -1472,7 +1472,6 @@ void dma_issue_pending_all(void); struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param, struct device_node *np); -struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name); struct dma_chan *dma_request_chan(struct device *dev, const char *name); struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask); @@ -1502,11 +1501,6 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, { return NULL; } -static inline struct dma_chan *dma_request_slave_channel(struct device *dev, - const char *name) -{ - return NULL; -} static inline struct dma_chan *dma_request_chan(struct device *dev, const char *name) { @@ -1527,8 +1521,6 @@ static inline int dma_get_slave_caps(struct dma_chan *chan, } #endif -#define dma_request_slave_channel_reason(dev, name) dma_request_chan(dev, name) - static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx) { struct dma_slave_caps caps; @@ -1577,6 +1569,15 @@ void dma_run_dependencies(struct dma_async_tx_descriptor *tx); #define dma_request_channel(mask, x, y) \ __dma_request_channel(&(mask), x, y, NULL) +/* Deprecated, please use dma_request_chan() directly */ +static inline struct dma_chan * __deprecated +dma_request_slave_channel(struct device *dev, const char *name) +{ + struct dma_chan *ch = dma_request_chan(dev, name); + + return IS_ERR(ch) ? NULL : ch; +} + static inline struct dma_chan *dma_request_slave_channel_compat(const dma_cap_mask_t mask, dma_filter_fn fn, void *fn_param, diff --git a/include/linux/platform_data/dma-dw.h b/include/linux/platform_data/dma-dw.h index fbbeb2f6189b..b34a094b2258 100644 --- a/include/linux/platform_data/dma-dw.h +++ b/include/linux/platform_data/dma-dw.h @@ -26,6 +26,7 @@ struct device; * @dst_id: dst request line * @m_master: memory master for transfers on allocated channel * @p_master: peripheral master for transfers on allocated channel + * @channels: mask of the channels permitted for allocation (zero value means any) * @hs_polarity:set active low polarity of handshake interface */ struct dw_dma_slave { @@ -34,6 +35,7 @@ struct dw_dma_slave { u8 dst_id; u8 m_master; u8 p_master; + u8 channels; bool hs_polarity; }; |