summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/stable/sysfs-driver-dma-idxd6
-rw-r--r--Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt117
-rw-r--r--Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml150
-rw-r--r--Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt55
-rw-r--r--Documentation/devicetree/bindings/dma/renesas,usb-dmac.yaml102
-rw-r--r--Documentation/devicetree/bindings/dma/st,stm32-dma.yaml5
-rw-r--r--drivers/dma/Kconfig4
-rw-r--r--drivers/dma/at_hdmac_regs.h2
-rw-r--r--drivers/dma/at_xdmac.c2
-rw-r--r--drivers/dma/dmaengine.c98
-rw-r--r--drivers/dma/dmatest.c24
-rw-r--r--drivers/dma/dw-edma/dw-edma-core.c65
-rw-r--r--drivers/dma/dw-edma/dw-edma-core.h4
-rw-r--r--drivers/dma/dw-edma/dw-edma-pcie.c10
-rw-r--r--drivers/dma/idxd/sysfs.c11
-rw-r--r--drivers/dma/imx-sdma.c2
-rw-r--r--drivers/dma/ioat/dma.c85
-rw-r--r--drivers/dma/ioat/dma.h10
-rw-r--r--drivers/dma/ioat/init.c2
-rw-r--r--drivers/dma/mmp_tdma.c26
-rw-r--r--drivers/dma/moxart-dma.c2
-rw-r--r--drivers/dma/qcom/bam_dma.c2
-rw-r--r--drivers/dma/qcom/hidma.c3
-rw-r--r--drivers/dma/sf-pdma/sf-pdma.c25
-rw-r--r--drivers/dma/stm32-dma.c41
-rw-r--r--drivers/dma/ti/Kconfig4
-rw-r--r--drivers/dma/ti/k3-udma.c34
27 files changed, 535 insertions, 356 deletions
diff --git a/Documentation/ABI/stable/sysfs-driver-dma-idxd b/Documentation/ABI/stable/sysfs-driver-dma-idxd
index f4be46cc6cb6..b5bebf642db6 100644
--- a/Documentation/ABI/stable/sysfs-driver-dma-idxd
+++ b/Documentation/ABI/stable/sysfs-driver-dma-idxd
@@ -1,3 +1,9 @@
+What: sys/bus/dsa/devices/dsa<m>/version
+Date: Apr 15, 2020
+KernelVersion: 5.8.0
+Contact: dmaengine@vger.kernel.org
+Description: The hardware version number.
+
What: sys/bus/dsa/devices/dsa<m>/cdev_major
Date: Oct 25, 2019
KernelVersion: 5.6.0
diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
deleted file mode 100644
index b7f81c63be8b..000000000000
--- a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
+++ /dev/null
@@ -1,117 +0,0 @@
-* Renesas R-Car (RZ/G) DMA Controller Device Tree bindings
-
-Renesas R-Car (Gen 2/3) and RZ/G SoCs have multiple multi-channel DMA
-controller instances named DMAC capable of serving multiple clients. Channels
-can be dedicated to specific clients or shared between a large number of
-clients.
-
-Each DMA client is connected to one dedicated port of the DMAC, identified by
-an 8-bit port number called the MID/RID. A DMA controller can thus serve up to
-256 clients in total. When the number of hardware channels is lower than the
-number of clients to be served, channels must be shared between multiple DMA
-clients. The association of DMA clients to DMAC channels is fully dynamic and
-not described in these device tree bindings.
-
-Required Properties:
-
-- compatible: "renesas,dmac-<soctype>", "renesas,rcar-dmac" as fallback.
- Examples with soctypes are:
- - "renesas,dmac-r8a7743" (RZ/G1M)
- - "renesas,dmac-r8a7744" (RZ/G1N)
- - "renesas,dmac-r8a7745" (RZ/G1E)
- - "renesas,dmac-r8a77470" (RZ/G1C)
- - "renesas,dmac-r8a774a1" (RZ/G2M)
- - "renesas,dmac-r8a774b1" (RZ/G2N)
- - "renesas,dmac-r8a774c0" (RZ/G2E)
- - "renesas,dmac-r8a7790" (R-Car H2)
- - "renesas,dmac-r8a7791" (R-Car M2-W)
- - "renesas,dmac-r8a7792" (R-Car V2H)
- - "renesas,dmac-r8a7793" (R-Car M2-N)
- - "renesas,dmac-r8a7794" (R-Car E2)
- - "renesas,dmac-r8a7795" (R-Car H3)
- - "renesas,dmac-r8a7796" (R-Car M3-W)
- - "renesas,dmac-r8a77961" (R-Car M3-W+)
- - "renesas,dmac-r8a77965" (R-Car M3-N)
- - "renesas,dmac-r8a77970" (R-Car V3M)
- - "renesas,dmac-r8a77980" (R-Car V3H)
- - "renesas,dmac-r8a77990" (R-Car E3)
- - "renesas,dmac-r8a77995" (R-Car D3)
-
-- reg: base address and length of the registers block for the DMAC
-
-- interrupts: interrupt specifiers for the DMAC, one for each entry in
- interrupt-names.
-- interrupt-names: one entry for the error interrupt, named "error", plus one
- entry per channel, named "ch%u", where %u is the channel number ranging from
- zero to the number of channels minus one.
-
-- clock-names: "fck" for the functional clock
-- clocks: a list of phandle + clock-specifier pairs, one for each entry
- in clock-names.
-- clock-names: must contain "fck" for the functional clock.
-
-- #dma-cells: must be <1>, the cell specifies the MID/RID of the DMAC port
- connected to the DMA client
-- dma-channels: number of DMA channels
-
-Example: R8A7790 (R-Car H2) SYS-DMACs
-
- dmac0: dma-controller@e6700000 {
- compatible = "renesas,dmac-r8a7790", "renesas,rcar-dmac";
- reg = <0 0xe6700000 0 0x20000>;
- interrupts = <0 197 IRQ_TYPE_LEVEL_HIGH
- 0 200 IRQ_TYPE_LEVEL_HIGH
- 0 201 IRQ_TYPE_LEVEL_HIGH
- 0 202 IRQ_TYPE_LEVEL_HIGH
- 0 203 IRQ_TYPE_LEVEL_HIGH
- 0 204 IRQ_TYPE_LEVEL_HIGH
- 0 205 IRQ_TYPE_LEVEL_HIGH
- 0 206 IRQ_TYPE_LEVEL_HIGH
- 0 207 IRQ_TYPE_LEVEL_HIGH
- 0 208 IRQ_TYPE_LEVEL_HIGH
- 0 209 IRQ_TYPE_LEVEL_HIGH
- 0 210 IRQ_TYPE_LEVEL_HIGH
- 0 211 IRQ_TYPE_LEVEL_HIGH
- 0 212 IRQ_TYPE_LEVEL_HIGH
- 0 213 IRQ_TYPE_LEVEL_HIGH
- 0 214 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14";
- clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC0>;
- clock-names = "fck";
- #dma-cells = <1>;
- dma-channels = <15>;
- };
-
- dmac1: dma-controller@e6720000 {
- compatible = "renesas,dmac-r8a7790", "renesas,rcar-dmac";
- reg = <0 0xe6720000 0 0x20000>;
- interrupts = <0 220 IRQ_TYPE_LEVEL_HIGH
- 0 216 IRQ_TYPE_LEVEL_HIGH
- 0 217 IRQ_TYPE_LEVEL_HIGH
- 0 218 IRQ_TYPE_LEVEL_HIGH
- 0 219 IRQ_TYPE_LEVEL_HIGH
- 0 308 IRQ_TYPE_LEVEL_HIGH
- 0 309 IRQ_TYPE_LEVEL_HIGH
- 0 310 IRQ_TYPE_LEVEL_HIGH
- 0 311 IRQ_TYPE_LEVEL_HIGH
- 0 312 IRQ_TYPE_LEVEL_HIGH
- 0 313 IRQ_TYPE_LEVEL_HIGH
- 0 314 IRQ_TYPE_LEVEL_HIGH
- 0 315 IRQ_TYPE_LEVEL_HIGH
- 0 316 IRQ_TYPE_LEVEL_HIGH
- 0 317 IRQ_TYPE_LEVEL_HIGH
- 0 318 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14";
- clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC1>;
- clock-names = "fck";
- #dma-cells = <1>;
- dma-channels = <15>;
- };
diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml
new file mode 100644
index 000000000000..b842dfd96a89
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml
@@ -0,0 +1,150 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/renesas,rcar-dmac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R-Car and RZ/G DMA Controller
+
+maintainers:
+ - Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+allOf:
+ - $ref: "dma-controller.yaml#"
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,dmac-r8a7743 # RZ/G1M
+ - renesas,dmac-r8a7744 # RZ/G1N
+ - renesas,dmac-r8a7745 # RZ/G1E
+ - renesas,dmac-r8a77470 # RZ/G1C
+ - renesas,dmac-r8a774a1 # RZ/G2M
+ - renesas,dmac-r8a774b1 # RZ/G2N
+ - renesas,dmac-r8a774c0 # RZ/G2E
+ - renesas,dmac-r8a7790 # R-Car H2
+ - renesas,dmac-r8a7791 # R-Car M2-W
+ - renesas,dmac-r8a7792 # R-Car V2H
+ - renesas,dmac-r8a7793 # R-Car M2-N
+ - renesas,dmac-r8a7794 # R-Car E2
+ - renesas,dmac-r8a7795 # R-Car H3
+ - renesas,dmac-r8a7796 # R-Car M3-W
+ - renesas,dmac-r8a77961 # R-Car M3-W+
+ - renesas,dmac-r8a77965 # R-Car M3-N
+ - renesas,dmac-r8a77970 # R-Car V3M
+ - renesas,dmac-r8a77980 # R-Car V3H
+ - renesas,dmac-r8a77990 # R-Car E3
+ - renesas,dmac-r8a77995 # R-Car D3
+ - const: renesas,rcar-dmac
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ minItems: 9
+ maxItems: 17
+
+ interrupt-names:
+ minItems: 9
+ maxItems: 17
+ items:
+ - const: error
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+ - pattern: "^ch([0-9]|1[0-5])$"
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ maxItems: 1
+ items:
+ - const: fck
+
+ '#dma-cells':
+ const: 1
+ description:
+ The cell specifies the MID/RID of the DMAC port connected to
+ the DMA client.
+
+ dma-channels:
+ minimum: 8
+ maximum: 16
+
+ dma-channel-mask: true
+
+ iommus:
+ minItems: 8
+ maxItems: 16
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - '#dma-cells'
+ - dma-channels
+ - power-domains
+ - resets
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r8a7790-cpg-mssr.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/r8a7790-sysc.h>
+
+ dmac0: dma-controller@e6700000 {
+ compatible = "renesas,dmac-r8a7790", "renesas,rcar-dmac";
+ reg = <0xe6700000 0x20000>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14";
+ clocks = <&cpg CPG_MOD 219>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
+ resets = <&cpg 219>;
+ #dma-cells = <1>;
+ dma-channels = <15>;
+ };
diff --git a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
deleted file mode 100644
index e8f6c42e80f2..000000000000
--- a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-* Renesas USB DMA Controller Device Tree bindings
-
-Required Properties:
--compatible: "renesas,<soctype>-usb-dmac", "renesas,usb-dmac" as fallback.
- Examples with soctypes are:
- - "renesas,r8a7743-usb-dmac" (RZ/G1M)
- - "renesas,r8a7744-usb-dmac" (RZ/G1N)
- - "renesas,r8a7745-usb-dmac" (RZ/G1E)
- - "renesas,r8a77470-usb-dmac" (RZ/G1C)
- - "renesas,r8a774a1-usb-dmac" (RZ/G2M)
- - "renesas,r8a774b1-usb-dmac" (RZ/G2N)
- - "renesas,r8a774c0-usb-dmac" (RZ/G2E)
- - "renesas,r8a7790-usb-dmac" (R-Car H2)
- - "renesas,r8a7791-usb-dmac" (R-Car M2-W)
- - "renesas,r8a7793-usb-dmac" (R-Car M2-N)
- - "renesas,r8a7794-usb-dmac" (R-Car E2)
- - "renesas,r8a7795-usb-dmac" (R-Car H3)
- - "renesas,r8a7796-usb-dmac" (R-Car M3-W)
- - "renesas,r8a77961-usb-dmac" (R-Car M3-W+)
- - "renesas,r8a77965-usb-dmac" (R-Car M3-N)
- - "renesas,r8a77990-usb-dmac" (R-Car E3)
- - "renesas,r8a77995-usb-dmac" (R-Car D3)
-- reg: base address and length of the registers block for the DMAC
-- interrupts: interrupt specifiers for the DMAC, one for each entry in
- interrupt-names.
-- interrupt-names: one entry per channel, named "ch%u", where %u is the
- channel number ranging from zero to the number of channels minus one.
-- clocks: a list of phandle + clock-specifier pairs.
-- #dma-cells: must be <1>, the cell specifies the channel number of the DMAC
- port connected to the DMA client.
-- dma-channels: number of DMA channels
-
-Example: R8A7790 (R-Car H2) USB-DMACs
-
- usb_dmac0: dma-controller@e65a0000 {
- compatible = "renesas,r8a7790-usb-dmac", "renesas,usb-dmac";
- reg = <0 0xe65a0000 0 0x100>;
- interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH
- 0 109 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ch0", "ch1";
- clocks = <&mstp3_clks R8A7790_CLK_USBDMAC0>;
- #dma-cells = <1>;
- dma-channels = <2>;
- };
-
- usb_dmac1: dma-controller@e65b0000 {
- compatible = "renesas,usb-dmac";
- reg = <0 0xe65b0000 0 0x100>;
- interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH
- 0 110 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ch0", "ch1";
- clocks = <&mstp3_clks R8A7790_CLK_USBDMAC1>;
- #dma-cells = <1>;
- dma-channels = <2>;
- };
diff --git a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.yaml b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.yaml
new file mode 100644
index 000000000000..9ca6d8ddf232
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.yaml
@@ -0,0 +1,102 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/renesas,usb-dmac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas USB DMA Controller
+
+maintainers:
+ - Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+allOf:
+ - $ref: "dma-controller.yaml#"
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r8a7743-usb-dmac # RZ/G1M
+ - renesas,r8a7744-usb-dmac # RZ/G1N
+ - renesas,r8a7745-usb-dmac # RZ/G1E
+ - renesas,r8a77470-usb-dmac # RZ/G1C
+ - renesas,r8a774a1-usb-dmac # RZ/G2M
+ - renesas,r8a774b1-usb-dmac # RZ/G2N
+ - renesas,r8a774c0-usb-dmac # RZ/G2E
+ - renesas,r8a7790-usb-dmac # R-Car H2
+ - renesas,r8a7791-usb-dmac # R-Car M2-W
+ - renesas,r8a7793-usb-dmac # R-Car M2-N
+ - renesas,r8a7794-usb-dmac # R-Car E2
+ - renesas,r8a7795-usb-dmac # R-Car H3
+ - renesas,r8a7796-usb-dmac # R-Car M3-W
+ - renesas,r8a77961-usb-dmac # R-Car M3-W+
+ - renesas,r8a77965-usb-dmac # R-Car M3-N
+ - renesas,r8a77990-usb-dmac # R-Car E3
+ - renesas,r8a77995-usb-dmac # R-Car D3
+ - const: renesas,usb-dmac
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ minItems: 2
+ maxItems: 2
+
+ interrupt-names:
+ items:
+ - pattern: ch0
+ - pattern: ch1
+
+ clocks:
+ maxItems: 1
+
+ '#dma-cells':
+ const: 1
+ description:
+ The cell specifies the channel number of the DMAC port connected to
+ the DMA client.
+
+ dma-channels:
+ const: 2
+
+ iommus:
+ minItems: 2
+ maxItems: 2
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - clocks
+ - '#dma-cells'
+ - dma-channels
+ - power-domains
+ - resets
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r8a7790-cpg-mssr.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/r8a7790-sysc.h>
+
+ usb_dmac0: dma-controller@e65a0000 {
+ compatible = "renesas,r8a7790-usb-dmac", "renesas,usb-dmac";
+ reg = <0xe65a0000 0x100>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1";
+ clocks = <&cpg CPG_MOD 330>;
+ power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
+ resets = <&cpg 330>;
+ #dma-cells = <1>;
+ dma-channels = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml
index 0c0ac11ad55f..71987878e4ae 100644
--- a/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml
@@ -36,6 +36,11 @@ description: |
0x1: 1/2 full FIFO
0x2: 3/4 full FIFO
0x3: full FIFO
+ -bit 2: DMA direct mode
+ 0x0: FIFO mode with threshold selectable with bit 0-1
+ 0x1: Direct mode: each DMA request immediately initiates a transfer
+ from/to the memory, FIFO is bypassed.
+
maintainers:
- Amelie Delaunay <amelie.delaunay@st.com>
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 023db6883d05..e9ed9165de40 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -106,7 +106,7 @@ config AXI_DMAC
select REGMAP_MMIO
help
Enable support for the Analog Devices AXI-DMAC peripheral. This DMA
- controller is often used in Analog Device's reference designs for FPGA
+ controller is often used in Analog Devices' reference designs for FPGA
platforms.
config BCM_SBA_RAID
@@ -395,12 +395,10 @@ config MMP_TDMA
bool "MMP Two-Channel DMA support"
depends on ARCH_MMP || COMPILE_TEST
select DMA_ENGINE
- select MMP_SRAM if ARCH_MMP
select GENERIC_ALLOCATOR
help
Support the MMP Two-Channel DMA engine.
This engine used for MMP Audio DMA and pxa910 SQU.
- It needs sram driver under mach-mmp.
config MOXART_DMA
tristate "MOXART DMA support"
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index 397692e937b3..80fc2fe8c77e 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -331,7 +331,7 @@ struct at_dma {
struct dma_pool *dma_desc_pool;
struct dma_pool *memset_pool;
/* AT THE END channels table */
- struct at_dma_chan chan[0];
+ struct at_dma_chan chan[];
};
#define dma_readl(atdma, name) \
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index bb0eaf38b594..fd92f048c491 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -212,7 +212,7 @@ struct at_xdmac {
struct clk *clk;
u32 save_gim;
struct dma_pool *at_xdmac_desc_pool;
- struct at_xdmac_chan chan[0];
+ struct at_xdmac_chan chan[];
};
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index d31076d9ef25..2b06a7a8629d 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -53,6 +53,8 @@
#include <linux/mempool.h>
#include <linux/numa.h>
+#include "dmaengine.h"
+
static DEFINE_MUTEX(dma_list_mutex);
static DEFINE_IDA(dma_ida);
static LIST_HEAD(dma_device_list);
@@ -145,9 +147,9 @@ static inline void dmaengine_debug_unregister(struct dma_device *dma_dev) { }
/**
* dev_to_dma_chan - convert a device pointer to its sysfs container object
- * @dev - device node
+ * @dev: device node
*
- * Must be called under dma_list_mutex
+ * Must be called under dma_list_mutex.
*/
static struct dma_chan *dev_to_dma_chan(struct device *dev)
{
@@ -243,22 +245,18 @@ static struct class dma_devclass = {
/* --- client and device registration --- */
-/**
- * dma_cap_mask_all - enable iteration over all operation types
- */
+/* enable iteration over all operation types */
static dma_cap_mask_t dma_cap_mask_all;
/**
- * dma_chan_tbl_ent - tracks channel allocations per core/operation
- * @chan - associated channel for this entry
+ * struct dma_chan_tbl_ent - tracks channel allocations per core/operation
+ * @chan: associated channel for this entry
*/
struct dma_chan_tbl_ent {
struct dma_chan *chan;
};
-/**
- * channel_table - percpu lookup table for memory-to-memory offload providers
- */
+/* percpu lookup table for memory-to-memory offload providers */
static struct dma_chan_tbl_ent __percpu *channel_table[DMA_TX_TYPE_END];
static int __init dma_channel_table_init(void)
@@ -295,8 +293,11 @@ static int __init dma_channel_table_init(void)
arch_initcall(dma_channel_table_init);
/**
- * dma_chan_is_local - returns true if the channel is in the same numa-node as
- * the cpu
+ * dma_chan_is_local - checks if the channel is in the same NUMA-node as the CPU
+ * @chan: DMA channel to test
+ * @cpu: CPU index which the channel should be close to
+ *
+ * Returns true if the channel is in the same NUMA-node as the CPU.
*/
static bool dma_chan_is_local(struct dma_chan *chan, int cpu)
{
@@ -306,14 +307,14 @@ static bool dma_chan_is_local(struct dma_chan *chan, int cpu)
}
/**
- * min_chan - returns the channel with min count and in the same numa-node as
- * the cpu
- * @cap: capability to match
- * @cpu: cpu index which the channel should be close to
+ * min_chan - finds the channel with min count and in the same NUMA-node as the CPU
+ * @cap: capability to match
+ * @cpu: CPU index which the channel should be close to
*
- * If some channels are close to the given cpu, the one with the lowest
- * reference count is returned. Otherwise, cpu is ignored and only the
+ * If some channels are close to the given CPU, the one with the lowest
+ * reference count is returned. Otherwise, CPU is ignored and only the
* reference count is taken into account.
+ *
* Must be called under dma_list_mutex.
*/
static struct dma_chan *min_chan(enum dma_transaction_type cap, int cpu)
@@ -351,10 +352,11 @@ static struct dma_chan *min_chan(enum dma_transaction_type cap, int cpu)
/**
* dma_channel_rebalance - redistribute the available channels
*
- * Optimize for cpu isolation (each cpu gets a dedicated channel for an
- * operation type) in the SMP case, and operation isolation (avoid
- * multi-tasking channels) in the non-SMP case. Must be called under
- * dma_list_mutex.
+ * Optimize for CPU isolation (each CPU gets a dedicated channel for an
+ * operation type) in the SMP case, and operation isolation (avoid
+ * multi-tasking channels) in the non-SMP case.
+ *
+ * Must be called under dma_list_mutex.
*/
static void dma_channel_rebalance(void)
{
@@ -404,9 +406,9 @@ static struct module *dma_chan_to_owner(struct dma_chan *chan)
/**
* balance_ref_count - catch up the channel reference count
- * @chan - channel to balance ->client_count versus dmaengine_ref_count
+ * @chan: channel to balance ->client_count versus dmaengine_ref_count
*
- * balance_ref_count must be called under dma_list_mutex
+ * Must be called under dma_list_mutex.
*/
static void balance_ref_count(struct dma_chan *chan)
{
@@ -436,10 +438,10 @@ static void dma_device_put(struct dma_device *device)
}
/**
- * dma_chan_get - try to grab a dma channel's parent driver module
- * @chan - channel to grab
+ * dma_chan_get - try to grab a DMA channel's parent driver module
+ * @chan: channel to grab
*
- * Must be called under dma_list_mutex
+ * Must be called under dma_list_mutex.
*/
static int dma_chan_get(struct dma_chan *chan)
{
@@ -483,10 +485,10 @@ module_put_out:
}
/**
- * dma_chan_put - drop a reference to a dma channel's parent driver module
- * @chan - channel to release
+ * dma_chan_put - drop a reference to a DMA channel's parent driver module
+ * @chan: channel to release
*
- * Must be called under dma_list_mutex
+ * Must be called under dma_list_mutex.
*/
static void dma_chan_put(struct dma_chan *chan)
{
@@ -537,7 +539,7 @@ EXPORT_SYMBOL(dma_sync_wait);
/**
* dma_find_channel - find a channel to carry out the operation
- * @tx_type: transaction type
+ * @tx_type: transaction type
*/
struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type)
{
@@ -677,7 +679,7 @@ static struct dma_chan *find_candidate(struct dma_device *device,
/**
* dma_get_slave_channel - try to get specific channel exclusively
- * @chan: target channel
+ * @chan: target channel
*/
struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
{
@@ -731,10 +733,10 @@ EXPORT_SYMBOL_GPL(dma_get_any_slave_channel);
/**
* __dma_request_channel - try to allocate an exclusive channel
- * @mask: capabilities that the channel must satisfy
- * @fn: optional callback to disposition available channels
- * @fn_param: opaque parameter to pass to dma_filter_fn
- * @np: device node to look for DMA channels
+ * @mask: capabilities that the channel must satisfy
+ * @fn: optional callback to disposition available channels
+ * @fn_param: opaque parameter to pass to dma_filter_fn()
+ * @np: device node to look for DMA channels
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
@@ -877,7 +879,7 @@ 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
+ * @mask: capabilities that the channel must satisfy
*
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
@@ -968,7 +970,7 @@ void dmaengine_get(void)
EXPORT_SYMBOL(dmaengine_get);
/**
- * dmaengine_put - let dma drivers be removed when ref_count == 0
+ * dmaengine_put - let DMA drivers be removed when ref_count == 0
*/
void dmaengine_put(void)
{
@@ -1132,7 +1134,7 @@ EXPORT_SYMBOL_GPL(dma_async_device_channel_unregister);
/**
* dma_async_device_register - registers DMA devices found
- * @device: &dma_device
+ * @device: pointer to &struct dma_device
*
* After calling this routine the structure should not be freed except in the
* device_release() callback which will be called after
@@ -1304,7 +1306,7 @@ EXPORT_SYMBOL(dma_async_device_register);
/**
* dma_async_device_unregister - unregister a DMA device
- * @device: &dma_device
+ * @device: pointer to &struct dma_device
*
* This routine is called by dma driver exit routines, dmaengine holds module
* references to prevent it being called while channels are in use.
@@ -1341,7 +1343,7 @@ static void dmam_device_release(struct device *dev, void *res)
/**
* dmaenginem_async_device_register - registers DMA devices found
- * @device: &dma_device
+ * @device: pointer to &struct dma_device
*
* The operation is managed and will be undone on driver detach.
*/
@@ -1578,8 +1580,9 @@ int dmaengine_desc_set_metadata_len(struct dma_async_tx_descriptor *desc,
}
EXPORT_SYMBOL_GPL(dmaengine_desc_set_metadata_len);
-/* dma_wait_for_async_tx - spin wait for a transaction to complete
- * @tx: in-flight transaction to wait on
+/**
+ * dma_wait_for_async_tx - spin wait for a transaction to complete
+ * @tx: in-flight transaction to wait on
*/
enum dma_status
dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
@@ -1602,9 +1605,12 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
}
EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
-/* dma_run_dependencies - helper routine for dma drivers to process
- * (start) dependent operations on their target channel
- * @tx: transaction with dependencies
+/**
+ * dma_run_dependencies - process dependent operations on the target channel
+ * @tx: transaction with dependencies
+ *
+ * Helper routine for DMA drivers to process (start) dependent operations
+ * on their target channel.
*/
void dma_run_dependencies(struct dma_async_tx_descriptor *tx)
{
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 0425984db118..b175229a4b01 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -60,9 +60,9 @@ MODULE_PARM_DESC(pq_sources,
"Number of p+q source buffers (default: 3)");
static int timeout = 3000;
-module_param(timeout, uint, S_IRUGO | S_IWUSR);
+module_param(timeout, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
- "Pass 0xFFFFFFFF (4294967295) for maximum timeout");
+ "Pass -1 for infinite timeout");
static bool noverify;
module_param(noverify, bool, S_IRUGO | S_IWUSR);
@@ -72,10 +72,6 @@ static bool norandom;
module_param(norandom, bool, 0644);
MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)");
-static bool polled;
-module_param(polled, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
-
static bool verbose;
module_param(verbose, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
@@ -88,6 +84,10 @@ static unsigned int transfer_size;
module_param(transfer_size, uint, 0644);
MODULE_PARM_DESC(transfer_size, "Optional custom transfer size in bytes (default: not used (0))");
+static bool polled;
+module_param(polled, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
+
/**
* struct dmatest_params - test parameters.
* @buf_size: size of the memcpy test buffer
@@ -98,7 +98,12 @@ MODULE_PARM_DESC(transfer_size, "Optional custom transfer size in bytes (default
* @iterations: iterations before stopping test
* @xor_sources: number of xor source buffers
* @pq_sources: number of p+q source buffers
- * @timeout: transfer timeout in msec, 0 - 0xFFFFFFFF (4294967295)
+ * @timeout: transfer timeout in msec, -1 for infinite timeout
+ * @noverify: disable data verification
+ * @norandom: disable random offset setup
+ * @alignment: custom data address alignment taken as 2^alignment
+ * @transfer_size: custom transfer size in bytes
+ * @polled: use polling for completion instead of interrupts
*/
struct dmatest_params {
unsigned int buf_size;
@@ -109,7 +114,7 @@ struct dmatest_params {
unsigned int iterations;
unsigned int xor_sources;
unsigned int pq_sources;
- unsigned int timeout;
+ int timeout;
bool noverify;
bool norandom;
int alignment;
@@ -120,7 +125,10 @@ struct dmatest_params {
/**
* struct dmatest_info - test information.
* @params: test parameters
+ * @channels: channels under test
+ * @nr_channels: number of channels under test
* @lock: access protection to the fields of this structure
+ * @did_init: module has been initialized completely
*/
static struct dmatest_info {
/* Test parameters */
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index ff392c01bad1..ed430ad9b3dd 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -13,8 +13,9 @@
#include <linux/dmaengine.h>
#include <linux/err.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/dma/edma.h>
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include "dw-edma-core.h"
#include "dw-edma-v0-core.h"
@@ -322,7 +323,7 @@ static struct dma_async_tx_descriptor *
dw_edma_device_transfer(struct dw_edma_transfer *xfer)
{
struct dw_edma_chan *chan = dchan2dw_edma_chan(xfer->dchan);
- enum dma_transfer_direction direction = xfer->direction;
+ enum dma_transfer_direction dir = xfer->direction;
phys_addr_t src_addr, dst_addr;
struct scatterlist *sg = NULL;
struct dw_edma_chunk *chunk;
@@ -331,10 +332,26 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
u32 cnt;
int i;
- if ((direction == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_WRITE) ||
- (direction == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_READ))
+ if (!chan->configured)
return NULL;
+ switch (chan->config.direction) {
+ case DMA_DEV_TO_MEM: /* local dma */
+ if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_READ)
+ break;
+ return NULL;
+ case DMA_MEM_TO_DEV: /* local dma */
+ if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_WRITE)
+ break;
+ return NULL;
+ default: /* remote dma */
+ if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_READ)
+ break;
+ if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_WRITE)
+ break;
+ return NULL;
+ }
+
if (xfer->cyclic) {
if (!xfer->xfer.cyclic.len || !xfer->xfer.cyclic.cnt)
return NULL;
@@ -343,9 +360,6 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
return NULL;
}
- if (!chan->configured)
- return NULL;
-
desc = dw_edma_alloc_desc(chan);
if (unlikely(!desc))
goto err_alloc;
@@ -386,7 +400,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
chunk->ll_region.sz += burst->sz;
desc->alloc_sz += burst->sz;
- if (direction == DMA_DEV_TO_MEM) {
+ if (chan->dir == EDMA_DIR_WRITE) {
burst->sar = src_addr;
if (xfer->cyclic) {
burst->dar = xfer->xfer.cyclic.paddr;
@@ -773,6 +787,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
u32 rd_mask = 1;
int i, err = 0;
u32 ch_cnt;
+ int irq;
ch_cnt = dw->wr_ch_cnt + dw->rd_ch_cnt;
@@ -781,16 +796,16 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
if (dw->nr_irqs == 1) {
/* Common IRQ shared among all channels */
- err = request_irq(pci_irq_vector(to_pci_dev(dev), 0),
- dw_edma_interrupt_common,
+ irq = dw->ops->irq_vector(dev, 0);
+ err = request_irq(irq, dw_edma_interrupt_common,
IRQF_SHARED, dw->name, &dw->irq[0]);
if (err) {
dw->nr_irqs = 0;
return err;
}
- get_cached_msi_msg(pci_irq_vector(to_pci_dev(dev), 0),
- &dw->irq[0].msi);
+ if (irq_get_msi_desc(irq))
+ get_cached_msi_msg(irq, &dw->irq[0].msi);
} else {
/* Distribute IRQs equally among all channels */
int tmp = dw->nr_irqs;
@@ -804,7 +819,8 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt);
for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
- err = request_irq(pci_irq_vector(to_pci_dev(dev), i),
+ irq = dw->ops->irq_vector(dev, i);
+ err = request_irq(irq,
i < *wr_alloc ?
dw_edma_interrupt_write :
dw_edma_interrupt_read,
@@ -815,8 +831,8 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
return err;
}
- get_cached_msi_msg(pci_irq_vector(to_pci_dev(dev), i),
- &dw->irq[i].msi);
+ if (irq_get_msi_desc(irq))
+ get_cached_msi_msg(irq, &dw->irq[i].msi);
}
dw->nr_irqs = i;
@@ -827,12 +843,23 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
int dw_edma_probe(struct dw_edma_chip *chip)
{
- struct device *dev = chip->dev;
- struct dw_edma *dw = chip->dw;
+ struct device *dev;
+ struct dw_edma *dw;
u32 wr_alloc = 0;
u32 rd_alloc = 0;
int i, err;
+ if (!chip)
+ return -EINVAL;
+
+ dev = chip->dev;
+ if (!dev)
+ return -EINVAL;
+
+ dw = chip->dw;
+ if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector)
+ return -EINVAL;
+
raw_spin_lock_init(&dw->lock);
/* Find out how many write channels are supported by hardware */
@@ -884,7 +911,7 @@ int dw_edma_probe(struct dw_edma_chip *chip)
err_irq_free:
for (i = (dw->nr_irqs - 1); i >= 0; i--)
- free_irq(pci_irq_vector(to_pci_dev(dev), i), &dw->irq[i]);
+ free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
dw->nr_irqs = 0;
@@ -904,7 +931,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
/* Free irqs */
for (i = (dw->nr_irqs - 1); i >= 0; i--)
- free_irq(pci_irq_vector(to_pci_dev(dev), i), &dw->irq[i]);
+ free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
/* Power management */
pm_runtime_disable(dev);
diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
index 4e5f9f6e901b..31fc50d31792 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -103,6 +103,10 @@ struct dw_edma_irq {
struct dw_edma *dw;
};
+struct dw_edma_core_ops {
+ int (*irq_vector)(struct device *dev, unsigned int nr);
+};
+
struct dw_edma {
char name[20];
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index dc85f55e1bb8..1eafc602e17e 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -54,6 +54,15 @@ static const struct dw_edma_pcie_data snps_edda_data = {
.irqs = 1,
};
+static int dw_edma_pcie_irq_vector(struct device *dev, unsigned int nr)
+{
+ return pci_irq_vector(to_pci_dev(dev), nr);
+}
+
+static const struct dw_edma_core_ops dw_edma_pcie_core_ops = {
+ .irq_vector = dw_edma_pcie_irq_vector,
+};
+
static int dw_edma_pcie_probe(struct pci_dev *pdev,
const struct pci_device_id *pid)
{
@@ -151,6 +160,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
dw->version = pdata->version;
dw->mode = pdata->mode;
dw->nr_irqs = nr_irqs;
+ dw->ops = &dw_edma_pcie_core_ops;
/* Debug info */
pci_dbg(pdev, "Version:\t%u\n", dw->version);
diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c
index 3999827970ab..052dae5d6ddd 100644
--- a/drivers/dma/idxd/sysfs.c
+++ b/drivers/dma/idxd/sysfs.c
@@ -1092,6 +1092,16 @@ static const struct attribute_group *idxd_wq_attribute_groups[] = {
};
/* IDXD device attribs */
+static ssize_t version_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->hw.version);
+}
+static DEVICE_ATTR_RO(version);
+
static ssize_t max_work_queues_size_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1313,6 +1323,7 @@ static ssize_t cdev_major_show(struct device *dev,
static DEVICE_ATTR_RO(cdev_major);
static struct attribute *idxd_device_attributes[] = {
+ &dev_attr_version.attr,
&dev_attr_max_groups.attr,
&dev_attr_max_work_queues.attr,
&dev_attr_max_work_queues_size.attr,
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 4d4477df4ede..91774039ae5d 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2063,7 +2063,7 @@ static int sdma_probe(struct platform_device *pdev)
/* initially no scripts available */
saddr_arr = (s32 *)sdma->script_addrs;
- for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
+ for (i = 0; i < sizeof(*sdma->script_addrs) / sizeof(s32); i++)
saddr_arr[i] = -EINVAL;
dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index 18c011e57592..8ad0ad861c86 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -332,8 +332,8 @@ ioat_alloc_ring_ent(struct dma_chan *chan, int idx, gfp_t flags)
u8 *pos;
off_t offs;
- chunk = idx / IOAT_DESCS_PER_2M;
- idx &= (IOAT_DESCS_PER_2M - 1);
+ chunk = idx / IOAT_DESCS_PER_CHUNK;
+ idx &= (IOAT_DESCS_PER_CHUNK - 1);
offs = idx * IOAT_DESC_SZ;
pos = (u8 *)ioat_chan->descs[chunk].virt + offs;
phys = ioat_chan->descs[chunk].hw + offs;
@@ -370,7 +370,8 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags)
if (!ring)
return NULL;
- ioat_chan->desc_chunks = chunks = (total_descs * IOAT_DESC_SZ) / SZ_2M;
+ chunks = (total_descs * IOAT_DESC_SZ) / IOAT_CHUNK_SIZE;
+ ioat_chan->desc_chunks = chunks;
for (i = 0; i < chunks; i++) {
struct ioat_descs *descs = &ioat_chan->descs[i];
@@ -382,8 +383,9 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags)
for (idx = 0; idx < i; idx++) {
descs = &ioat_chan->descs[idx];
- dma_free_coherent(to_dev(ioat_chan), SZ_2M,
- descs->virt, descs->hw);
+ dma_free_coherent(to_dev(ioat_chan),
+ IOAT_CHUNK_SIZE,
+ descs->virt, descs->hw);
descs->virt = NULL;
descs->hw = 0;
}
@@ -404,7 +406,7 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags)
for (idx = 0; idx < ioat_chan->desc_chunks; idx++) {
dma_free_coherent(to_dev(ioat_chan),
- SZ_2M,
+ IOAT_CHUNK_SIZE,
ioat_chan->descs[idx].virt,
ioat_chan->descs[idx].hw);
ioat_chan->descs[idx].virt = NULL;
@@ -867,6 +869,23 @@ static void check_active(struct ioatdma_chan *ioat_chan)
mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT);
}
+static void ioat_reboot_chan(struct ioatdma_chan *ioat_chan)
+{
+ spin_lock_bh(&ioat_chan->prep_lock);
+ set_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
+ spin_unlock_bh(&ioat_chan->prep_lock);
+
+ ioat_abort_descs(ioat_chan);
+ dev_warn(to_dev(ioat_chan), "Reset channel...\n");
+ ioat_reset_hw(ioat_chan);
+ dev_warn(to_dev(ioat_chan), "Restart channel...\n");
+ ioat_restart_channel(ioat_chan);
+
+ spin_lock_bh(&ioat_chan->prep_lock);
+ clear_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
+ spin_unlock_bh(&ioat_chan->prep_lock);
+}
+
void ioat_timer_event(struct timer_list *t)
{
struct ioatdma_chan *ioat_chan = from_timer(ioat_chan, t, timer);
@@ -889,19 +908,7 @@ void ioat_timer_event(struct timer_list *t)
if (test_bit(IOAT_RUN, &ioat_chan->state)) {
spin_lock_bh(&ioat_chan->cleanup_lock);
- spin_lock_bh(&ioat_chan->prep_lock);
- set_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
- spin_unlock_bh(&ioat_chan->prep_lock);
-
- ioat_abort_descs(ioat_chan);
- dev_warn(to_dev(ioat_chan), "Reset channel...\n");
- ioat_reset_hw(ioat_chan);
- dev_warn(to_dev(ioat_chan), "Restart channel...\n");
- ioat_restart_channel(ioat_chan);
-
- spin_lock_bh(&ioat_chan->prep_lock);
- clear_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
- spin_unlock_bh(&ioat_chan->prep_lock);
+ ioat_reboot_chan(ioat_chan);
spin_unlock_bh(&ioat_chan->cleanup_lock);
}
@@ -915,17 +922,23 @@ void ioat_timer_event(struct timer_list *t)
spin_lock_bh(&ioat_chan->prep_lock);
check_active(ioat_chan);
spin_unlock_bh(&ioat_chan->prep_lock);
- spin_unlock_bh(&ioat_chan->cleanup_lock);
- return;
+ goto unlock_out;
+ }
+
+ /* handle the missed cleanup case */
+ if (ioat_cleanup_preamble(ioat_chan, &phys_complete)) {
+ /* timer restarted in ioat_cleanup_preamble
+ * and IOAT_COMPLETION_ACK cleared
+ */
+ __cleanup(ioat_chan, phys_complete);
+ goto unlock_out;
}
/* if we haven't made progress and we have already
* acknowledged a pending completion once, then be more
* forceful with a restart
*/
- if (ioat_cleanup_preamble(ioat_chan, &phys_complete))
- __cleanup(ioat_chan, phys_complete);
- else if (test_bit(IOAT_COMPLETION_ACK, &ioat_chan->state)) {
+ if (test_bit(IOAT_COMPLETION_ACK, &ioat_chan->state)) {
u32 chanerr;
chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
@@ -937,25 +950,23 @@ void ioat_timer_event(struct timer_list *t)
dev_dbg(to_dev(ioat_chan), "Active descriptors: %d\n",
ioat_ring_active(ioat_chan));
- spin_lock_bh(&ioat_chan->prep_lock);
- set_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
- spin_unlock_bh(&ioat_chan->prep_lock);
+ ioat_reboot_chan(ioat_chan);
- ioat_abort_descs(ioat_chan);
- dev_warn(to_dev(ioat_chan), "Resetting channel...\n");
- ioat_reset_hw(ioat_chan);
- dev_warn(to_dev(ioat_chan), "Restarting channel...\n");
- ioat_restart_channel(ioat_chan);
+ goto unlock_out;
+ }
+ /* handle missed issue pending case */
+ if (ioat_ring_pending(ioat_chan)) {
+ dev_warn(to_dev(ioat_chan),
+ "Completion timeout with pending descriptors\n");
spin_lock_bh(&ioat_chan->prep_lock);
- clear_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
+ __ioat_issue_pending(ioat_chan);
spin_unlock_bh(&ioat_chan->prep_lock);
- spin_unlock_bh(&ioat_chan->cleanup_lock);
- return;
- } else
- set_bit(IOAT_COMPLETION_ACK, &ioat_chan->state);
+ }
+ set_bit(IOAT_COMPLETION_ACK, &ioat_chan->state);
mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT);
+unlock_out:
spin_unlock_bh(&ioat_chan->cleanup_lock);
}
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index b8e8e0b9693c..e6b622e1ba92 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -81,6 +81,11 @@ struct ioatdma_device {
u32 msixpba;
};
+#define IOAT_MAX_ORDER 16
+#define IOAT_MAX_DESCS (1 << IOAT_MAX_ORDER)
+#define IOAT_CHUNK_SIZE (SZ_512K)
+#define IOAT_DESCS_PER_CHUNK (IOAT_CHUNK_SIZE / IOAT_DESC_SZ)
+
struct ioat_descs {
void *virt;
dma_addr_t hw;
@@ -128,7 +133,7 @@ struct ioatdma_chan {
u16 produce;
struct ioat_ring_ent **ring;
spinlock_t prep_lock;
- struct ioat_descs descs[2];
+ struct ioat_descs descs[IOAT_MAX_DESCS / IOAT_DESCS_PER_CHUNK];
int desc_chunks;
int intr_coalesce;
int prev_intr_coalesce;
@@ -301,9 +306,6 @@ static inline bool is_ioat_bug(unsigned long err)
return !!err;
}
-#define IOAT_MAX_ORDER 16
-#define IOAT_MAX_DESCS 65536
-#define IOAT_DESCS_PER_2M 32768
static inline u32 ioat_ring_size(struct ioatdma_chan *ioat_chan)
{
diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c
index 60e9afbb896c..58d13564f88b 100644
--- a/drivers/dma/ioat/init.c
+++ b/drivers/dma/ioat/init.c
@@ -651,7 +651,7 @@ static void ioat_free_chan_resources(struct dma_chan *c)
}
for (i = 0; i < ioat_chan->desc_chunks; i++) {
- dma_free_coherent(to_dev(ioat_chan), SZ_2M,
+ dma_free_coherent(to_dev(ioat_chan), IOAT_CHUNK_SIZE,
ioat_chan->descs[i].virt,
ioat_chan->descs[i].hw);
ioat_chan->descs[i].virt = NULL;
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index d683232d7fea..dbc6a48424fa 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -235,7 +235,7 @@ static int mmp_tdma_config_chan(struct dma_chan *chan)
tdcr |= TDCR_BURSTSZ_128B;
break;
default:
- dev_err(tdmac->dev, "mmp_tdma: unknown burst size.\n");
+ dev_err(tdmac->dev, "unknown burst size.\n");
return -EINVAL;
}
@@ -250,7 +250,7 @@ static int mmp_tdma_config_chan(struct dma_chan *chan)
tdcr |= TDCR_SSZ_32_BITS;
break;
default:
- dev_err(tdmac->dev, "mmp_tdma: unknown bus size.\n");
+ dev_err(tdmac->dev, "unknown bus size.\n");
return -EINVAL;
}
} else if (tdmac->type == PXA910_SQU) {
@@ -276,7 +276,7 @@ static int mmp_tdma_config_chan(struct dma_chan *chan)
tdcr |= TDCR_BURSTSZ_SQU_32B;
break;
default:
- dev_err(tdmac->dev, "mmp_tdma: unknown burst size.\n");
+ dev_err(tdmac->dev, "unknown burst size.\n");
return -EINVAL;
}
}
@@ -429,8 +429,15 @@ static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic(
int num_periods = buf_len / period_len;
int i = 0, buf = 0;
- if (tdmac->status != DMA_COMPLETE)
+ if (!is_slave_direction(direction)) {
+ dev_err(tdmac->dev, "unsupported transfer direction\n");
return NULL;
+ }
+
+ if (tdmac->status != DMA_COMPLETE) {
+ dev_err(tdmac->dev, "controller busy");
+ return NULL;
+ }
if (period_len > TDMA_MAX_XFER_BYTES) {
dev_err(tdmac->dev,
@@ -704,6 +711,17 @@ static int mmp_tdma_probe(struct platform_device *pdev)
tdev->device.device_terminate_all = mmp_tdma_terminate_all;
tdev->device.copy_align = DMAENGINE_ALIGN_8_BYTES;
+ tdev->device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+ if (type == MMP_AUD_TDMA) {
+ tdev->device.max_burst = SZ_128;
+ tdev->device.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+ tdev->device.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+ } else if (type == PXA910_SQU) {
+ tdev->device.max_burst = SZ_32;
+ }
+ tdev->device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+ tdev->device.descriptor_reuse = true;
+
dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
platform_set_drvdata(pdev, tdev);
diff --git a/drivers/dma/moxart-dma.c b/drivers/dma/moxart-dma.c
index e04499c1f27f..4ab493d46375 100644
--- a/drivers/dma/moxart-dma.c
+++ b/drivers/dma/moxart-dma.c
@@ -568,7 +568,7 @@ static int moxart_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct resource *res;
- static void __iomem *dma_base_addr;
+ void __iomem *dma_base_addr;
int ret, i;
unsigned int irq;
struct moxart_chan *ch;
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
index ef73f65224b1..5a08dd0d3388 100644
--- a/drivers/dma/qcom/bam_dma.c
+++ b/drivers/dma/qcom/bam_dma.c
@@ -74,7 +74,7 @@ struct bam_async_desc {
struct list_head desc_node;
enum dma_transfer_direction dir;
size_t length;
- struct bam_desc_hw desc[0];
+ struct bam_desc_hw desc[];
};
enum bam_reg {
diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index 411f91fde734..0a6d3ea08c78 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -550,7 +550,7 @@ static void hidma_free_chan_resources(struct dma_chan *dmach)
kfree(mdesc);
}
- mchan->allocated = 0;
+ mchan->allocated = false;
spin_unlock_irqrestore(&mchan->lock, irqflags);
}
@@ -897,7 +897,6 @@ uninit:
if (msi)
hidma_free_msis(dmadev);
- hidma_debug_uninit(dmadev);
hidma_ll_uninit(dmadev->lldev);
dmafree:
if (dmadev)
diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c
index 6d0bec947636..5c118c7e02bd 100644
--- a/drivers/dma/sf-pdma/sf-pdma.c
+++ b/drivers/dma/sf-pdma/sf-pdma.c
@@ -506,11 +506,11 @@ static int sf_pdma_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pdma->membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pdma->membase))
- goto ERR_MEMBASE;
+ return PTR_ERR(pdma->membase);
ret = sf_pdma_irq_init(pdev, pdma);
if (ret)
- goto ERR_INITIRQ;
+ return ret;
sf_pdma_setup_chans(pdma);
@@ -544,24 +544,13 @@ static int sf_pdma_probe(struct platform_device *pdev)
"Failed to set DMA mask. Fall back to default.\n");
ret = dma_async_device_register(&pdma->dma_dev);
- if (ret)
- goto ERR_REG_DMADEVICE;
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Can't register SiFive Platform DMA. (%d)\n", ret);
+ return ret;
+ }
return 0;
-
-ERR_MEMBASE:
- devm_kfree(&pdev->dev, pdma);
- return PTR_ERR(pdma->membase);
-
-ERR_INITIRQ:
- devm_kfree(&pdev->dev, pdma);
- return ret;
-
-ERR_REG_DMADEVICE:
- devm_kfree(&pdev->dev, pdma);
- dev_err(&pdev->dev,
- "Can't register SiFive Platform DMA. (%d)\n", ret);
- return ret;
}
static int sf_pdma_remove(struct platform_device *pdev)
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index 0ddbaa4b4f0b..96ad1b3d24c6 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -117,6 +117,7 @@
#define STM32_DMA_FIFO_THRESHOLD_HALFFULL 0x01
#define STM32_DMA_FIFO_THRESHOLD_3QUARTERSFULL 0x02
#define STM32_DMA_FIFO_THRESHOLD_FULL 0x03
+#define STM32_DMA_FIFO_THRESHOLD_NONE 0x04
#define STM32_DMA_MAX_DATA_ITEMS 0xffff
/*
@@ -136,6 +137,9 @@
/* DMA Features */
#define STM32_DMA_THRESHOLD_FTR_MASK GENMASK(1, 0)
#define STM32_DMA_THRESHOLD_FTR_GET(n) ((n) & STM32_DMA_THRESHOLD_FTR_MASK)
+#define STM32_DMA_DIRECT_MODE_MASK BIT(2)
+#define STM32_DMA_DIRECT_MODE_GET(n) (((n) & STM32_DMA_DIRECT_MODE_MASK) \
+ >> 2)
enum stm32_dma_width {
STM32_DMA_BYTE,
@@ -281,6 +285,9 @@ static bool stm32_dma_fifo_threshold_is_allowed(u32 burst, u32 threshold,
{
u32 remaining;
+ if (threshold == STM32_DMA_FIFO_THRESHOLD_NONE)
+ return false;
+
if (width != DMA_SLAVE_BUSWIDTH_UNDEFINED) {
if (burst != 0) {
/*
@@ -302,6 +309,10 @@ static bool stm32_dma_fifo_threshold_is_allowed(u32 burst, u32 threshold,
static bool stm32_dma_is_burst_possible(u32 buf_len, u32 threshold)
{
+ /* If FIFO direct mode, burst is not possible */
+ if (threshold == STM32_DMA_FIFO_THRESHOLD_NONE)
+ return false;
+
/*
* Buffer or period length has to be aligned on FIFO depth.
* Otherwise bytes may be stuck within FIFO at buffer or period
@@ -657,6 +668,12 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid)
dev_dbg(chan2dev(chan), "FIFO over/underrun\n");
}
}
+ if (status & STM32_DMA_DMEI) {
+ stm32_dma_irq_clear(chan, STM32_DMA_DMEI);
+ status &= ~STM32_DMA_DMEI;
+ if (sfcr & STM32_DMA_SCR_DMEIE)
+ dev_dbg(chan2dev(chan), "Direct mode overrun\n");
+ }
if (status) {
stm32_dma_irq_clear(chan, status);
dev_err(chan2dev(chan), "DMA error: status=0x%08x\n", status);
@@ -692,13 +709,13 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
int src_bus_width, dst_bus_width;
int src_burst_size, dst_burst_size;
u32 src_maxburst, dst_maxburst, src_best_burst, dst_best_burst;
- u32 dma_scr, threshold;
+ u32 dma_scr, fifoth;
src_addr_width = chan->dma_sconfig.src_addr_width;
dst_addr_width = chan->dma_sconfig.dst_addr_width;
src_maxburst = chan->dma_sconfig.src_maxburst;
dst_maxburst = chan->dma_sconfig.dst_maxburst;
- threshold = chan->threshold;
+ fifoth = chan->threshold;
switch (direction) {
case DMA_MEM_TO_DEV:
@@ -710,7 +727,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
/* Set device burst size */
dst_best_burst = stm32_dma_get_best_burst(buf_len,
dst_maxburst,
- threshold,
+ fifoth,
dst_addr_width);
dst_burst_size = stm32_dma_get_burst(chan, dst_best_burst);
@@ -718,7 +735,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
return dst_burst_size;
/* Set memory data size */
- src_addr_width = stm32_dma_get_max_width(buf_len, threshold);
+ src_addr_width = stm32_dma_get_max_width(buf_len, fifoth);
chan->mem_width = src_addr_width;
src_bus_width = stm32_dma_get_width(chan, src_addr_width);
if (src_bus_width < 0)
@@ -728,7 +745,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
src_maxburst = STM32_DMA_MAX_BURST;
src_best_burst = stm32_dma_get_best_burst(buf_len,
src_maxburst,
- threshold,
+ fifoth,
src_addr_width);
src_burst_size = stm32_dma_get_burst(chan, src_best_burst);
if (src_burst_size < 0)
@@ -742,7 +759,8 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
/* Set FIFO threshold */
chan->chan_reg.dma_sfcr &= ~STM32_DMA_SFCR_FTH_MASK;
- chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(threshold);
+ if (fifoth != STM32_DMA_FIFO_THRESHOLD_NONE)
+ chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(fifoth);
/* Set peripheral address */
chan->chan_reg.dma_spar = chan->dma_sconfig.dst_addr;
@@ -758,7 +776,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
/* Set device burst size */
src_best_burst = stm32_dma_get_best_burst(buf_len,
src_maxburst,
- threshold,
+ fifoth,
src_addr_width);
chan->mem_burst = src_best_burst;
src_burst_size = stm32_dma_get_burst(chan, src_best_burst);
@@ -766,7 +784,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
return src_burst_size;
/* Set memory data size */
- dst_addr_width = stm32_dma_get_max_width(buf_len, threshold);
+ dst_addr_width = stm32_dma_get_max_width(buf_len, fifoth);
chan->mem_width = dst_addr_width;
dst_bus_width = stm32_dma_get_width(chan, dst_addr_width);
if (dst_bus_width < 0)
@@ -776,7 +794,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
dst_maxburst = STM32_DMA_MAX_BURST;
dst_best_burst = stm32_dma_get_best_burst(buf_len,
dst_maxburst,
- threshold,
+ fifoth,
dst_addr_width);
chan->mem_burst = dst_best_burst;
dst_burst_size = stm32_dma_get_burst(chan, dst_best_burst);
@@ -791,7 +809,8 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
/* Set FIFO threshold */
chan->chan_reg.dma_sfcr &= ~STM32_DMA_SFCR_FTH_MASK;
- chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(threshold);
+ if (fifoth != STM32_DMA_FIFO_THRESHOLD_NONE)
+ chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(fifoth);
/* Set peripheral address */
chan->chan_reg.dma_spar = chan->dma_sconfig.src_addr;
@@ -1216,6 +1235,8 @@ static void stm32_dma_set_config(struct stm32_dma_chan *chan,
chan->chan_reg.dma_scr |= STM32_DMA_SCR_TEIE | STM32_DMA_SCR_TCIE;
chan->threshold = STM32_DMA_THRESHOLD_FTR_GET(cfg->features);
+ if (STM32_DMA_DIRECT_MODE_GET(cfg->features))
+ chan->threshold = STM32_DMA_FIFO_THRESHOLD_NONE;
}
static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
diff --git a/drivers/dma/ti/Kconfig b/drivers/dma/ti/Kconfig
index f76e06651f80..79618fac119a 100644
--- a/drivers/dma/ti/Kconfig
+++ b/drivers/dma/ti/Kconfig
@@ -36,7 +36,7 @@ config DMA_OMAP
config TI_K3_UDMA
bool "Texas Instruments UDMA support"
- depends on ARCH_K3 || COMPILE_TEST
+ depends on ARCH_K3
depends on TI_SCI_PROTOCOL
depends on TI_SCI_INTA_IRQCHIP
select DMA_ENGINE
@@ -49,7 +49,7 @@ config TI_K3_UDMA
config TI_K3_UDMA_GLUE_LAYER
bool "Texas Instruments UDMA Glue layer for non DMAengine users"
- depends on ARCH_K3 || COMPILE_TEST
+ depends on ARCH_K3
depends on TI_K3_UDMA
help
Say y here to support the K3 NAVSS DMA glue interface
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index a90e154b0ae0..945b7c604f91 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -231,7 +231,6 @@ struct udma_chan {
struct udma_tx_drain tx_drain;
u32 bcnt; /* number of bytes completed since the start of the channel */
- u32 in_ring_cnt; /* number of descriptors in flight */
/* Channel configuration parameters */
struct udma_chan_config config;
@@ -574,7 +573,6 @@ static int udma_push_to_ring(struct udma_chan *uc, int idx)
struct udma_desc *d = uc->desc;
struct k3_ring *ring = NULL;
dma_addr_t paddr;
- int ret;
switch (uc->config.dir) {
case DMA_DEV_TO_MEM:
@@ -598,11 +596,7 @@ static int udma_push_to_ring(struct udma_chan *uc, int idx)
udma_sync_for_device(uc, idx);
}
- ret = k3_ringacc_ring_push(ring, &paddr);
- if (!ret)
- uc->in_ring_cnt++;
-
- return ret;
+ return k3_ringacc_ring_push(ring, &paddr);
}
static bool udma_desc_is_rx_flush(struct udma_chan *uc, dma_addr_t addr)
@@ -655,9 +649,6 @@ static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr)
d->hwdesc[0].cppi5_desc_size,
DMA_FROM_DEVICE);
rmb(); /* Ensure that reads are not moved before this point */
-
- if (!ret)
- uc->in_ring_cnt--;
}
return ret;
@@ -697,8 +688,6 @@ static void udma_reset_rings(struct udma_chan *uc)
udma_desc_free(&uc->terminated_desc->vd);
uc->terminated_desc = NULL;
}
-
- uc->in_ring_cnt = 0;
}
static void udma_reset_counters(struct udma_chan *uc)
@@ -1073,9 +1062,6 @@ static irqreturn_t udma_ring_irq_handler(int irq, void *data)
/* Teardown completion message */
if (cppi5_desc_is_tdcm(paddr)) {
- /* Compensate our internal pop/push counter */
- uc->in_ring_cnt++;
-
complete_all(&uc->teardown_completed);
if (uc->terminated_desc) {
@@ -1291,10 +1277,8 @@ static int udma_get_tchan(struct udma_chan *uc)
}
uc->tchan = __udma_reserve_tchan(ud, uc->config.channel_tpl, -1);
- if (IS_ERR(uc->tchan))
- return PTR_ERR(uc->tchan);
- return 0;
+ return PTR_ERR_OR_ZERO(uc->tchan);
}
static int udma_get_rchan(struct udma_chan *uc)
@@ -1308,10 +1292,8 @@ static int udma_get_rchan(struct udma_chan *uc)
}
uc->rchan = __udma_reserve_rchan(ud, uc->config.channel_tpl, -1);
- if (IS_ERR(uc->rchan))
- return PTR_ERR(uc->rchan);
- return 0;
+ return PTR_ERR_OR_ZERO(uc->rchan);
}
static int udma_get_chan_pair(struct udma_chan *uc)
@@ -1373,10 +1355,8 @@ static int udma_get_rflow(struct udma_chan *uc, int flow_id)
}
uc->rflow = __udma_get_rflow(ud, flow_id);
- if (IS_ERR(uc->rflow))
- return PTR_ERR(uc->rflow);
- return 0;
+ return PTR_ERR_OR_ZERO(uc->rflow);
}
static void udma_put_rchan(struct udma_chan *uc)
@@ -1870,6 +1850,7 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
udma_stop(uc);
if (udma_is_chan_running(uc)) {
dev_err(ud->dev, "chan%d: won't stop!\n", uc->id);
+ ret = -EBUSY;
goto err_res_free;
}
}
@@ -3189,7 +3170,7 @@ static struct udma_match_data am654_main_data = {
static struct udma_match_data am654_mcu_data = {
.psil_base = 0x6000,
- .enable_memcpy_support = true, /* TEST: DMA domains */
+ .enable_memcpy_support = false,
.statictr_z_mask = GENMASK(11, 0),
.rchan_oes_offset = 0x2000,
.tpl_levels = 2,
@@ -3471,6 +3452,9 @@ static int udma_setup_rx_flush(struct udma_dev *ud)
tr_req->icnt0 = rx_flush->buffer_size;
tr_req->icnt1 = 1;
+ dma_sync_single_for_device(dev, hwdesc->cppi5_desc_paddr,
+ hwdesc->cppi5_desc_size, DMA_TO_DEVICE);
+
/* Set up descriptor to be used for packet mode */
hwdesc = &rx_flush->hwdescs[1];
hwdesc->cppi5_desc_size = ALIGN(sizeof(struct cppi5_host_desc_t) +