From 6ee60246ac684407a062ccfa4404d6b6e8e7d7c7 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Wed, 15 Feb 2017 14:56:32 +0100 Subject: dmaengine: cppi41: Remove usbss_mem In order to make CPPI 4.1 DMA driver more generic, accesses to USBSS have been removed. So it is not required anymore to map the "glue" register's. Remove usbss_mem. Signed-off-by: Alexandre Bailon Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index d74cee077842..34a8156eef06 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -131,7 +131,6 @@ struct cppi41_dd { u32 first_td_desc; struct cppi41_channel *chan_busy[ALLOC_DECS_NUM]; - void __iomem *usbss_mem; void __iomem *ctrl_mem; void __iomem *sched_mem; void __iomem *qmgr_mem; @@ -995,6 +994,7 @@ static int cppi41_dma_probe(struct platform_device *pdev) struct cppi41_dd *cdd; struct device *dev = &pdev->dev; const struct cppi_glue_infos *glue_info; + int index; int irq; int ret; @@ -1021,16 +1021,20 @@ static int cppi41_dma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&cdd->ddev.channels); cpp41_dma_info.dma_cap = cdd->ddev.cap_mask; - cdd->usbss_mem = of_iomap(dev->of_node, 0); - cdd->ctrl_mem = of_iomap(dev->of_node, 1); - cdd->sched_mem = of_iomap(dev->of_node, 2); - cdd->qmgr_mem = of_iomap(dev->of_node, 3); + index = of_property_match_string(dev->of_node, + "reg-names", "controller"); + if (index < 0) + return index; + + cdd->ctrl_mem = of_iomap(dev->of_node, index); + cdd->sched_mem = of_iomap(dev->of_node, index + 1); + cdd->qmgr_mem = of_iomap(dev->of_node, index + 2); spin_lock_init(&cdd->lock); INIT_LIST_HEAD(&cdd->pending); platform_set_drvdata(pdev, cdd); - if (!cdd->usbss_mem || !cdd->ctrl_mem || !cdd->sched_mem || + if (!cdd->ctrl_mem || !cdd->sched_mem || !cdd->qmgr_mem) return -ENXIO; @@ -1090,7 +1094,6 @@ err_init_cppi: err_get_sync: pm_runtime_put_sync(dev); pm_runtime_disable(dev); - iounmap(cdd->usbss_mem); iounmap(cdd->ctrl_mem); iounmap(cdd->sched_mem); iounmap(cdd->qmgr_mem); @@ -1112,7 +1115,6 @@ static int cppi41_dma_remove(struct platform_device *pdev) devm_free_irq(&pdev->dev, cdd->irq, cdd); cleanup_chans(cdd); deinit_cppi41(&pdev->dev, cdd); - iounmap(cdd->usbss_mem); iounmap(cdd->ctrl_mem); iounmap(cdd->sched_mem); iounmap(cdd->qmgr_mem); -- cgit v1.2.3 From e1f40bf02d1f8b8af42b3fad5151bcd3449e085f Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Wed, 15 Feb 2017 14:56:33 +0100 Subject: dmaengine: cppi41: rename platform variables Currently, only the AM335x is supported by the driver. Though the driver has a glue layer to support different platforms, some platform variable names are not prefixed with the platform name. To facilitate the addition of a new platform, rename some variables owned by the AM335x glue. Signed-off-by: Alexandre Bailon Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 34a8156eef06..d1b5569ef420 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -149,7 +149,7 @@ struct cppi41_dd { }; #define FIST_COMPLETION_QUEUE 93 -static struct chan_queues usb_queues_tx[] = { +static struct chan_queues am335x_usb_queues_tx[] = { /* USB0 ENDP 1 */ [ 0] = { .submit = 32, .complete = 93}, [ 1] = { .submit = 34, .complete = 94}, @@ -185,7 +185,7 @@ static struct chan_queues usb_queues_tx[] = { [29] = { .submit = 90, .complete = 139}, }; -static const struct chan_queues usb_queues_rx[] = { +static const struct chan_queues am335x_usb_queues_rx[] = { /* USB0 ENDP 1 */ [ 0] = { .submit = 1, .complete = 109}, [ 1] = { .submit = 2, .complete = 110}, @@ -932,8 +932,9 @@ static bool cpp41_dma_filter_fn(struct dma_chan *chan, void *param) else queues = cdd->queues_rx; - BUILD_BUG_ON(ARRAY_SIZE(usb_queues_rx) != ARRAY_SIZE(usb_queues_tx)); - if (WARN_ON(cchan->port_num > ARRAY_SIZE(usb_queues_rx))) + BUILD_BUG_ON(ARRAY_SIZE(am335x_usb_queues_rx) != + ARRAY_SIZE(am335x_usb_queues_tx)); + if (WARN_ON(cchan->port_num > ARRAY_SIZE(am335x_usb_queues_rx))) return false; cchan->q_num = queues[cchan->port_num].submit; @@ -961,15 +962,15 @@ static struct dma_chan *cppi41_dma_xlate(struct of_phandle_args *dma_spec, &dma_spec->args[0]); } -static const struct cppi_glue_infos usb_infos = { +static const struct cppi_glue_infos am335x_usb_infos = { .isr = cppi41_irq, - .queues_rx = usb_queues_rx, - .queues_tx = usb_queues_tx, + .queues_rx = am335x_usb_queues_rx, + .queues_tx = am335x_usb_queues_tx, .td_queue = { .submit = 31, .complete = 0 }, }; static const struct of_device_id cppi41_dma_ids[] = { - { .compatible = "ti,am3359-cppi41", .data = &usb_infos}, + { .compatible = "ti,am3359-cppi41", .data = &am335x_usb_infos}, {}, }; MODULE_DEVICE_TABLE(of, cppi41_dma_ids); -- cgit v1.2.3 From 2d535b2629bfdf30c972ea394669bd146f752091 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Wed, 15 Feb 2017 14:56:34 +0100 Subject: dmaengine: cppi41: Move some constants to glue layer Some constants are defined and use by the driver whereas they are specifics to AM335x. Add new variables to the glue layer, initialize them with the constants, and use them in the driver. Signed-off-by: Alexandre Bailon Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index d1b5569ef420..676228ff71de 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -68,7 +68,6 @@ #define QMGR_MEMCTRL_IDX_SH 16 #define QMGR_MEMCTRL_DESC_SH 8 -#define QMGR_NUM_PEND 5 #define QMGR_PEND(x) (0x90 + (x) * 4) #define QMGR_PENDING_SLOT_Q(x) (x / 32) @@ -138,6 +137,8 @@ struct cppi41_dd { const struct chan_queues *queues_rx; const struct chan_queues *queues_tx; struct chan_queues td_queue; + u16 first_completion_queue; + u16 qmgr_num_pend; struct list_head pending; /* Pending queued transfers */ spinlock_t lock; /* Lock for pending list */ @@ -148,7 +149,6 @@ struct cppi41_dd { bool is_suspended; }; -#define FIST_COMPLETION_QUEUE 93 static struct chan_queues am335x_usb_queues_tx[] = { /* USB0 ENDP 1 */ [ 0] = { .submit = 32, .complete = 93}, @@ -226,6 +226,8 @@ struct cppi_glue_infos { const struct chan_queues *queues_rx; const struct chan_queues *queues_tx; struct chan_queues td_queue; + u16 first_completion_queue; + u16 qmgr_num_pend; }; static struct cppi41_channel *to_cpp41_chan(struct dma_chan *c) @@ -284,19 +286,21 @@ static u32 cppi41_pop_desc(struct cppi41_dd *cdd, unsigned queue_num) static irqreturn_t cppi41_irq(int irq, void *data) { struct cppi41_dd *cdd = data; + u16 first_completion_queue = cdd->first_completion_queue; + u16 qmgr_num_pend = cdd->qmgr_num_pend; struct cppi41_channel *c; int i; - for (i = QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE); i < QMGR_NUM_PEND; + for (i = QMGR_PENDING_SLOT_Q(first_completion_queue); i < qmgr_num_pend; i++) { u32 val; u32 q_num; val = cppi_readl(cdd->qmgr_mem + QMGR_PEND(i)); - if (i == QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE) && val) { + if (i == QMGR_PENDING_SLOT_Q(first_completion_queue) && val) { u32 mask; /* set corresponding bit for completetion Q 93 */ - mask = 1 << QMGR_PENDING_BIT_Q(FIST_COMPLETION_QUEUE); + mask = 1 << QMGR_PENDING_BIT_Q(first_completion_queue); /* not set all bits for queues less than Q 93 */ mask--; /* now invert and keep only Q 93+ set */ @@ -884,7 +888,7 @@ static int init_cppi41(struct device *dev, struct cppi41_dd *cdd) return -ENOMEM; cppi_writel(cdd->scratch_phys, cdd->qmgr_mem + QMGR_LRAM0_BASE); - cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE); + cppi_writel(TOTAL_DESCS_NUM, cdd->qmgr_mem + QMGR_LRAM_SIZE); cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE); ret = init_descs(dev, cdd); @@ -967,6 +971,8 @@ static const struct cppi_glue_infos am335x_usb_infos = { .queues_rx = am335x_usb_queues_rx, .queues_tx = am335x_usb_queues_tx, .td_queue = { .submit = 31, .complete = 0 }, + .first_completion_queue = 93, + .qmgr_num_pend = 5, }; static const struct of_device_id cppi41_dma_ids[] = { @@ -1049,6 +1055,8 @@ static int cppi41_dma_probe(struct platform_device *pdev) cdd->queues_rx = glue_info->queues_rx; cdd->queues_tx = glue_info->queues_tx; cdd->td_queue = glue_info->td_queue; + cdd->qmgr_num_pend = glue_info->qmgr_num_pend; + cdd->first_completion_queue = glue_info->first_completion_queue; ret = init_cppi41(dev, cdd); if (ret) -- cgit v1.2.3 From 5e46fe98ab658eab817398abd895908854bb4c43 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Wed, 15 Feb 2017 14:56:35 +0100 Subject: dmaengine: cppi41: init_sched(): Get number of channels from DT Despite the driver is already using DT to get the number of channels, init_sched() is using an hardcoded value to get it. Use DT to get the number of channels. Signed-off-by: Alexandre Bailon Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 676228ff71de..54337cd0afcc 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -139,6 +139,8 @@ struct cppi41_dd { struct chan_queues td_queue; u16 first_completion_queue; u16 qmgr_num_pend; + u32 n_chans; + u8 platform; struct list_head pending; /* Pending queued transfers */ spinlock_t lock; /* Lock for pending list */ @@ -742,13 +744,8 @@ static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd) { struct cppi41_channel *cchan; int i; - int ret; - u32 n_chans; + u32 n_chans = cdd->n_chans; - ret = of_property_read_u32(dev->of_node, "#dma-channels", - &n_chans); - if (ret) - return ret; /* * The channels can only be used as TX or as RX. So we add twice * that much dma channels because USB can only do RX or TX. @@ -862,7 +859,7 @@ static void init_sched(struct cppi41_dd *cdd) word = 0; cppi_writel(0, cdd->sched_mem + DMA_SCHED_CTRL); - for (ch = 0; ch < 15 * 2; ch += 2) { + for (ch = 0; ch < cdd->n_chans; ch += 2) { reg = SCHED_ENTRY0_CHAN(ch); reg |= SCHED_ENTRY1_CHAN(ch) | SCHED_ENTRY1_IS_RX; @@ -872,7 +869,7 @@ static void init_sched(struct cppi41_dd *cdd) cppi_writel(reg, cdd->sched_mem + DMA_SCHED_WORD(word)); word++; } - reg = 15 * 2 * 2 - 1; + reg = cdd->n_chans * 2 - 1; reg |= DMA_SCHED_CTRL_EN; cppi_writel(reg, cdd->sched_mem + DMA_SCHED_CTRL); } @@ -897,6 +894,7 @@ static int init_cppi41(struct device *dev, struct cppi41_dd *cdd) cppi_writel(cdd->td_queue.submit, cdd->ctrl_mem + DMA_TDFDQ); init_sched(cdd); + return 0; err_td: deinit_cppi41(dev, cdd); @@ -1058,6 +1056,11 @@ static int cppi41_dma_probe(struct platform_device *pdev) cdd->qmgr_num_pend = glue_info->qmgr_num_pend; cdd->first_completion_queue = glue_info->first_completion_queue; + ret = of_property_read_u32(dev->of_node, + "#dma-channels", &cdd->n_chans); + if (ret) + goto err_get_n_chans; + ret = init_cppi41(dev, cdd); if (ret) goto err_init_cppi; @@ -1100,6 +1103,7 @@ err_chans: deinit_cppi41(dev, cdd); err_init_cppi: pm_runtime_dont_use_autosuspend(dev); +err_get_n_chans: err_get_sync: pm_runtime_put_sync(dev); pm_runtime_disable(dev); -- cgit v1.2.3 From a15382b75b903fa918a3a3c4d3b87e8061790312 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Wed, 15 Feb 2017 14:56:36 +0100 Subject: dmaengine: cppi41: Remove isr callback from glue layer All the platform code to manage IRQ has been moved to MUSB, and now the interrupt handler is completely generic. Remove the isr callback that is not useful anymore. Signed-off-by: Alexandre Bailon Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 54337cd0afcc..4573080e74c7 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -224,7 +224,6 @@ static const struct chan_queues am335x_usb_queues_rx[] = { }; struct cppi_glue_infos { - irqreturn_t (*isr)(int irq, void *data); const struct chan_queues *queues_rx; const struct chan_queues *queues_tx; struct chan_queues td_queue; @@ -965,7 +964,6 @@ static struct dma_chan *cppi41_dma_xlate(struct of_phandle_args *dma_spec, } static const struct cppi_glue_infos am335x_usb_infos = { - .isr = cppi41_irq, .queues_rx = am335x_usb_queues_rx, .queues_tx = am335x_usb_queues_tx, .td_queue = { .submit = 31, .complete = 0 }, @@ -1075,7 +1073,7 @@ static int cppi41_dma_probe(struct platform_device *pdev) goto err_irq; } - ret = devm_request_irq(&pdev->dev, irq, glue_info->isr, IRQF_SHARED, + ret = devm_request_irq(&pdev->dev, irq, cppi41_irq, IRQF_SHARED, dev_name(dev), cdd); if (ret) goto err_irq; -- cgit v1.2.3 From d567206e478f744f90b52f80b85debc3377ea5a0 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 30 Jan 2017 18:49:19 +0100 Subject: dt/bindings: da8xx-usb: Add binding for the CPPI 4.1 DMA controller DT binding for the TI DA8xx/OMAP-L1x/AM17xx/AM18xx CPPI 4.1 DMA controller. Signed-off-by: Alexandre Bailon Acked-by: Rob Herring Signed-off-by: Vinod Koul --- .../devicetree/bindings/usb/da8xx-usb.txt | 41 +++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/da8xx-usb.txt b/Documentation/devicetree/bindings/usb/da8xx-usb.txt index ccb844aba7d4..717c5f656237 100644 --- a/Documentation/devicetree/bindings/usb/da8xx-usb.txt +++ b/Documentation/devicetree/bindings/usb/da8xx-usb.txt @@ -18,10 +18,26 @@ Required properties: - phy-names: Should be "usb-phy" + - dmas: specifies the dma channels + + - dma-names: specifies the names of the channels. Use "rxN" for receive + and "txN" for transmit endpoints. N specifies the endpoint number. + Optional properties: ~~~~~~~~~~~~~~~~~~~~ - vbus-supply: Phandle to a regulator providing the USB bus power. +DMA +~~~ +- compatible: ti,da830-cppi41 +- reg: offset and length of the following register spaces: CPPI DMA Controller, + CPPI DMA Scheduler, Queue Manager +- reg-names: "controller", "scheduler", "queuemgr" +- #dma-cells: should be set to 2. The first number represents the + channel number (0 … 3 for endpoints 1 … 4). + The second number is 0 for RX and 1 for TX transfers. +- #dma-channels: should be set to 4 representing the 4 endpoints. + Example: usb_phy: usb-phy { compatible = "ti,da830-usb-phy"; @@ -30,7 +46,10 @@ Example: }; usb0: usb@200000 { compatible = "ti,da830-musb"; - reg = <0x00200000 0x10000>; + reg = <0x00200000 0x1000>; + ranges; + #address-cells = <1>; + #size-cells = <1>; interrupts = <58>; interrupt-names = "mc"; @@ -39,5 +58,25 @@ Example: phys = <&usb_phy 0>; phy-names = "usb-phy"; + dmas = <&cppi41dma 0 0 &cppi41dma 1 0 + &cppi41dma 2 0 &cppi41dma 3 0 + &cppi41dma 0 1 &cppi41dma 1 1 + &cppi41dma 2 1 &cppi41dma 3 1>; + dma-names = + "rx1", "rx2", "rx3", "rx4", + "tx1", "tx2", "tx3", "tx4"; + status = "okay"; + + cppi41dma: dma-controller@201000 { + compatible = "ti,da830-cppi41"; + reg = <0x201000 0x1000 + 0x202000 0x1000 + 0x204000 0x4000>; + reg-names = "controller", "scheduler", "queuemgr"; + interrupts = <58>; + #dma-cells = <2>; + #dma-channels = <4>; + }; + }; -- cgit v1.2.3 From e3fa49acf00a6db3bfdee725ac5d688dd98dc2c9 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 30 Jan 2017 18:49:20 +0100 Subject: dmaengine: cppi41: Add support of DA8xx to CPPI 4.1 The DA8xx has a CPPI 4.1 DMA controller. This is add the glue layer required to make it work on DA8xx. Signed-off-by: Alexandre Bailon Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 6 +++--- drivers/dma/cppi41.c | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index d01d59812cf3..fc3435c5240b 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -514,12 +514,12 @@ config TIMB_DMA Enable support for the Timberdale FPGA DMA engine. config TI_CPPI41 - tristate "AM33xx CPPI41 DMA support" - depends on ARCH_OMAP + tristate "CPPI 4.1 DMA support" + depends on (ARCH_OMAP || ARCH_DAVINCI_DA8XX) select DMA_ENGINE help The Communications Port Programming Interface (CPPI) 4.1 DMA engine - is currently used by the USB driver on AM335x platforms. + is currently used by the USB driver on AM335x and DA8xx platforms. config TI_DMA_CROSSBAR bool diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 4573080e74c7..135fb45a96f0 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -223,6 +223,20 @@ static const struct chan_queues am335x_usb_queues_rx[] = { [29] = { .submit = 30, .complete = 155}, }; +static const struct chan_queues da8xx_usb_queues_tx[] = { + [0] = { .submit = 16, .complete = 24}, + [1] = { .submit = 18, .complete = 24}, + [2] = { .submit = 20, .complete = 24}, + [3] = { .submit = 22, .complete = 24}, +}; + +static const struct chan_queues da8xx_usb_queues_rx[] = { + [0] = { .submit = 1, .complete = 26}, + [1] = { .submit = 3, .complete = 26}, + [2] = { .submit = 5, .complete = 26}, + [3] = { .submit = 7, .complete = 26}, +}; + struct cppi_glue_infos { const struct chan_queues *queues_rx; const struct chan_queues *queues_tx; @@ -971,8 +985,17 @@ static const struct cppi_glue_infos am335x_usb_infos = { .qmgr_num_pend = 5, }; +static const struct cppi_glue_infos da8xx_usb_infos = { + .queues_rx = da8xx_usb_queues_rx, + .queues_tx = da8xx_usb_queues_tx, + .td_queue = { .submit = 31, .complete = 0 }, + .first_completion_queue = 24, + .qmgr_num_pend = 2, +}; + static const struct of_device_id cppi41_dma_ids[] = { { .compatible = "ti,am3359-cppi41", .data = &am335x_usb_infos}, + { .compatible = "ti,da830-cppi41", .data = &da8xx_usb_infos}, {}, }; MODULE_DEVICE_TABLE(of, cppi41_dma_ids); -- cgit v1.2.3 From 4f68b09ea3ed5b9619568625d967569da055f487 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 30 Jan 2017 18:49:21 +0100 Subject: dmaengine: cppi41: Fix teardown warnings During the teardown of a RX channel, because there is only one completion queue available for RX channel, descriptor of another channel may be popped which will cause 2 warnings: - the first one because we popped a wrong descriptor (neither the channel's descriptor, nor the teardown descriptor). - the second one happen during the teardown of another channel, because we can't find the channel descriptor (that is, the one that caused the first warning). To avoid that, use one free queue instead of a transmit completion queue. Note that fix doesn't fix all the teardown warnings: I still get some when I run some corner case. Signed-off-by: Alexandre Bailon Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 135fb45a96f0..675de6a27e39 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -648,7 +648,7 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c) if (!c->is_tx) { reg |= GCR_STARV_RETRY; reg |= GCR_DESC_TYPE_HOST; - reg |= c->q_comp_num; + reg |= cdd->td_queue.complete; } reg |= GCR_TEARDOWN; cppi_writel(reg, c->gcr_reg); @@ -659,7 +659,7 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c) if (!c->td_seen || !c->td_desc_seen) { desc_phys = cppi41_pop_desc(cdd, cdd->td_queue.complete); - if (!desc_phys) + if (!desc_phys && c->is_tx) desc_phys = cppi41_pop_desc(cdd, c->q_comp_num); if (desc_phys == c->desc_phys) { -- cgit v1.2.3 From a08f2673dde1aaba22c79ed016d5901f1b042401 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 16 Mar 2017 16:18:44 +0200 Subject: dmaengine: cppi41: fix cppi41_dma_tx_status() logic It makes sense to set residue when channel is in progress. Otherwise it should be 0 since transfer is completed. Meanwhile this patch doesn't prevent to set residue value anyway. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 675de6a27e39..a583c644a7bc 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -420,11 +420,9 @@ static enum dma_status cppi41_dma_tx_status(struct dma_chan *chan, struct cppi41_channel *c = to_cpp41_chan(chan); enum dma_status ret; - /* lock */ ret = dma_cookie_status(chan, cookie, txstate); - if (txstate && ret == DMA_COMPLETE) - txstate->residue = c->residue; - /* unlock */ + + dma_set_residue(txstate, c->residue); return ret; } -- cgit v1.2.3 From 8e3ba95f41901e0da0bb3151ed696dca6f7ec511 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 16 Mar 2017 16:18:45 +0200 Subject: dmaengine: cppi41: use managed functions devm_*() This makes the error handling much more simpler than open-coding everything and in addition makes the probe function smaller an tidier. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 64 ++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index a583c644a7bc..1c63e1cf8c59 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -739,21 +739,9 @@ static int cppi41_stop_chan(struct dma_chan *chan) return 0; } -static void cleanup_chans(struct cppi41_dd *cdd) -{ - while (!list_empty(&cdd->ddev.channels)) { - struct cppi41_channel *cchan; - - cchan = list_first_entry(&cdd->ddev.channels, - struct cppi41_channel, chan.device_node); - list_del(&cchan->chan.device_node); - kfree(cchan); - } -} - static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd) { - struct cppi41_channel *cchan; + struct cppi41_channel *cchan, *chans; int i; u32 n_chans = cdd->n_chans; @@ -763,10 +751,12 @@ static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd) */ n_chans *= 2; + chans = devm_kcalloc(dev, n_chans, sizeof(*chans), GFP_KERNEL); + if (!chans) + return -ENOMEM; + for (i = 0; i < n_chans; i++) { - cchan = kzalloc(sizeof(*cchan), GFP_KERNEL); - if (!cchan) - goto err; + cchan = &chans[i]; cchan->cdd = cdd; if (i & 1) { @@ -786,9 +776,6 @@ static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd) cdd->first_td_desc = n_chans; return 0; -err: - cleanup_chans(cdd); - return -ENOMEM; } static void purge_descs(struct device *dev, struct cppi41_dd *cdd) @@ -1018,6 +1005,7 @@ static int cppi41_dma_probe(struct platform_device *pdev) struct cppi41_dd *cdd; struct device *dev = &pdev->dev; const struct cppi_glue_infos *glue_info; + struct resource *mem; int index; int irq; int ret; @@ -1050,18 +1038,26 @@ static int cppi41_dma_probe(struct platform_device *pdev) if (index < 0) return index; - cdd->ctrl_mem = of_iomap(dev->of_node, index); - cdd->sched_mem = of_iomap(dev->of_node, index + 1); - cdd->qmgr_mem = of_iomap(dev->of_node, index + 2); + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + cdd->ctrl_mem = devm_ioremap_resource(dev, mem); + if (IS_ERR(cdd->ctrl_mem)) + return PTR_ERR(cdd->ctrl_mem); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + cdd->sched_mem = devm_ioremap_resource(dev, mem); + if (IS_ERR(cdd->sched_mem)) + return PTR_ERR(cdd->sched_mem); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 2); + cdd->qmrg_mem = devm_ioremap_resource(dev, mem); + if (IS_ERR(cdd->qmrg_mem)) + return PTR_ERR(cdd->qmrg_mem); + spin_lock_init(&cdd->lock); INIT_LIST_HEAD(&cdd->pending); platform_set_drvdata(pdev, cdd); - if (!cdd->ctrl_mem || !cdd->sched_mem || - !cdd->qmgr_mem) - return -ENXIO; - pm_runtime_enable(dev); pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); @@ -1091,18 +1087,18 @@ static int cppi41_dma_probe(struct platform_device *pdev) irq = irq_of_parse_and_map(dev->of_node, 0); if (!irq) { ret = -EINVAL; - goto err_irq; + goto err_chans; } ret = devm_request_irq(&pdev->dev, irq, cppi41_irq, IRQF_SHARED, dev_name(dev), cdd); if (ret) - goto err_irq; + goto err_chans; cdd->irq = irq; ret = dma_async_device_register(&cdd->ddev); if (ret) - goto err_dma_reg; + goto err_chans; ret = of_dma_controller_register(dev->of_node, cppi41_dma_xlate, &cpp41_dma_info); @@ -1115,9 +1111,6 @@ static int cppi41_dma_probe(struct platform_device *pdev) return 0; err_of: dma_async_device_unregister(&cdd->ddev); -err_dma_reg: -err_irq: - cleanup_chans(cdd); err_chans: deinit_cppi41(dev, cdd); err_init_cppi: @@ -1126,9 +1119,6 @@ err_get_n_chans: err_get_sync: pm_runtime_put_sync(dev); pm_runtime_disable(dev); - iounmap(cdd->ctrl_mem); - iounmap(cdd->sched_mem); - iounmap(cdd->qmgr_mem); return ret; } @@ -1145,11 +1135,7 @@ static int cppi41_dma_remove(struct platform_device *pdev) dma_async_device_unregister(&cdd->ddev); devm_free_irq(&pdev->dev, cdd->irq, cdd); - cleanup_chans(cdd); deinit_cppi41(&pdev->dev, cdd); - iounmap(cdd->ctrl_mem); - iounmap(cdd->sched_mem); - iounmap(cdd->qmgr_mem); pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); -- cgit v1.2.3 From d7fd724e01939f777781a86d078c3b7142fb9c03 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 27 Mar 2017 13:33:31 +0530 Subject: dmaengine: cppi: fix build error due to bad variable Commit 8e3ba95f4190 ("dmaengine: cppi41: use managed functions devm_*()") moved the code to devm_* but erranously changed a varible name, so fix it. drivers/dma/cppi41.c:1052:5: error: 'struct cppi41_dd' has no member named 'qmrg_mem' cdd->qmrg_mem = devm_ioremap_resource(dev, mem); ^ drivers/dma/cppi41.c:1053:16: error: 'struct cppi41_dd' has no member named 'qmrg_mem' if (IS_ERR(cdd->qmrg_mem)) ^ drivers/dma/cppi41.c:1054:21: error: 'struct cppi41_dd' has no member named 'qmrg_mem' return PTR_ERR(cdd->qmrg_mem); ^ Fixes: 8e3ba95f4190 ("dmaengine: cppi41: use managed functions devm_*()") Reported-by: kbuild test robot Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 1c63e1cf8c59..0be56c971786 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -1049,9 +1049,9 @@ static int cppi41_dma_probe(struct platform_device *pdev) return PTR_ERR(cdd->sched_mem); mem = platform_get_resource(pdev, IORESOURCE_MEM, 2); - cdd->qmrg_mem = devm_ioremap_resource(dev, mem); - if (IS_ERR(cdd->qmrg_mem)) - return PTR_ERR(cdd->qmrg_mem); + cdd->qmgr_mem = devm_ioremap_resource(dev, mem); + if (IS_ERR(cdd->qmgr_mem)) + return PTR_ERR(cdd->qmgr_mem); spin_lock_init(&cdd->lock); INIT_LIST_HEAD(&cdd->pending); -- cgit v1.2.3 From eda6f4e868e74adfae8ac6b06a863a090affbb14 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Wed, 5 Apr 2017 18:35:16 +0200 Subject: dmaengine: cppi41: Fix an Oops happening in cppi41_dma_probe() This fix an Oops happening on all platforms using the old dt bindings (all platforms but da8xx). This update cppi41_dma_probe() to use the index variable which is required to keep compatibility between old and new dt bindings. Fixes: 8e3ba95f4190 ("dmaengine: cppi41: use managed functions devm_*()") Reported-by: Tony Lindgren Signed-off-by: Alexandre Bailon Signed-off-by: Vinod Koul --- drivers/dma/cppi41.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 0be56c971786..f7e965f63274 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -1038,17 +1038,17 @@ static int cppi41_dma_probe(struct platform_device *pdev) if (index < 0) return index; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mem = platform_get_resource(pdev, IORESOURCE_MEM, index); cdd->ctrl_mem = devm_ioremap_resource(dev, mem); if (IS_ERR(cdd->ctrl_mem)) return PTR_ERR(cdd->ctrl_mem); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + mem = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); cdd->sched_mem = devm_ioremap_resource(dev, mem); if (IS_ERR(cdd->sched_mem)) return PTR_ERR(cdd->sched_mem); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 2); + mem = platform_get_resource(pdev, IORESOURCE_MEM, index + 2); cdd->qmgr_mem = devm_ioremap_resource(dev, mem); if (IS_ERR(cdd->qmgr_mem)) return PTR_ERR(cdd->qmgr_mem); -- cgit v1.2.3