From 25b9d4c43696eeab579a555ae272565aa4e9c6cf Mon Sep 17 00:00:00 2001 From: Narayanan Date: Tue, 13 Sep 2011 17:00:22 +0530 Subject: [PATCH] --- yaml --- r: 358527 b: refs/heads/master c: 0fd602235dd702d16722857da748d15c26b81ed1 h: refs/heads/master i: 358525: 3ce677df6626784b66da6ef6020dc8c93c3c5103 358523: 5b4d1c67c3c741aae6f3e21645f953f184ace056 358519: 10c7b038ff11994ab1f94e2ed40487aed6d9984d 358511: 61db5876805fcd9112f9fdbdcc80b6b4fad6f59f 358495: fca891a4b47e5fe2a8940687f581a684cb2952de 358463: b2d6f93cb1640e604f0af8e1b292170ec9604a65 358399: 13c6cfdfa75cf1bfd490bdc5a20e4b167ca7ae78 v: v3 --- [refs] | 2 +- .../devicetree/bindings/dma/dma.txt | 81 ---- .../devicetree/bindings/dma/snps-dma.txt | 44 -- trunk/arch/arm/boot/dts/spear1340.dtsi | 19 - trunk/arch/arm/boot/dts/spear13xx.dtsi | 38 -- .../arm/include/asm/hardware}/pl080.h | 2 +- trunk/arch/arm/mach-s3c64xx/dma.c | 2 +- .../arm/mach-spear13xx/include/mach/spear.h | 2 + trunk/arch/arm/mach-spear13xx/spear1310.c | 5 +- trunk/arch/arm/mach-spear13xx/spear1340.c | 33 +- trunk/arch/arm/mach-spear13xx/spear13xx.c | 55 ++- trunk/arch/arm/mach-spear3xx/spear3xx.c | 1 + trunk/arch/arm/mach-spear6xx/spear6xx.c | 2 +- trunk/crypto/async_tx/async_memcpy.c | 6 - trunk/crypto/async_tx/async_memset.c | 1 - trunk/crypto/async_tx/async_tx.c | 9 +- trunk/crypto/async_tx/async_xor.c | 4 +- trunk/drivers/dca/dca-core.c | 5 - trunk/drivers/dma/Kconfig | 7 +- trunk/drivers/dma/amba-pl08x.c | 10 +- trunk/drivers/dma/at_hdmac.c | 10 +- trunk/drivers/dma/at_hdmac_regs.h | 8 +- trunk/drivers/dma/dmaengine.c | 21 +- trunk/drivers/dma/dmatest.c | 22 +- trunk/drivers/dma/dw_dmac.c | 432 ++++++------------ trunk/drivers/dma/dw_dmac_regs.h | 24 +- trunk/drivers/dma/edma.c | 55 +-- trunk/drivers/dma/ep93xx_dma.c | 3 +- trunk/drivers/dma/ioat/dma.c | 11 +- trunk/drivers/dma/ioat/dma_v3.c | 105 +---- trunk/drivers/dma/ioat/hw.h | 11 - trunk/drivers/dma/ioat/pci.c | 11 + trunk/drivers/dma/iop-adma.c | 45 +- trunk/drivers/dma/ipu/ipu_idmac.c | 2 +- trunk/drivers/dma/ipu/ipu_irq.c | 1 + trunk/drivers/dma/mmp_pdma.c | 6 +- trunk/drivers/dma/mv_xor.c | 40 +- trunk/drivers/dma/mxs-dma.c | 8 +- trunk/drivers/dma/pch_dma.c | 13 +- trunk/drivers/dma/pl330.c | 37 +- trunk/drivers/dma/sh/shdma-base.c | 3 + trunk/drivers/dma/sh/shdma.c | 2 +- trunk/drivers/dma/sirf-dma.c | 25 +- trunk/drivers/dma/ste_dma40.c | 2 +- trunk/drivers/dma/ste_dma40_ll.c | 11 +- trunk/drivers/dma/tegra20-apb-dma.c | 56 +-- trunk/drivers/misc/carma/carma-fpga-program.c | 2 +- trunk/drivers/misc/carma/carma-fpga.c | 6 +- trunk/drivers/mtd/nand/fsmc_nand.c | 22 +- trunk/drivers/of/Makefile | 2 +- trunk/drivers/of/dma.c | 264 ----------- trunk/include/linux/dmaengine.h | 48 +- trunk/include/linux/dw_dmac.h | 45 +- trunk/include/linux/of_dma.h | 74 --- trunk/net/ipv4/tcp.c | 8 +- 55 files changed, 519 insertions(+), 1244 deletions(-) delete mode 100644 trunk/Documentation/devicetree/bindings/dma/dma.txt rename trunk/{include/linux/amba => arch/arm/include/asm/hardware}/pl080.h (99%) delete mode 100644 trunk/drivers/of/dma.c delete mode 100644 trunk/include/linux/of_dma.h diff --git a/[refs] b/[refs] index 2b1e07efe33b..556124cd29df 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 77bcc497c60ec62dbb84abc809a6e218d53409e9 +refs/heads/master: 0fd602235dd702d16722857da748d15c26b81ed1 diff --git a/trunk/Documentation/devicetree/bindings/dma/dma.txt b/trunk/Documentation/devicetree/bindings/dma/dma.txt deleted file mode 100644 index 8f504e6bae14..000000000000 --- a/trunk/Documentation/devicetree/bindings/dma/dma.txt +++ /dev/null @@ -1,81 +0,0 @@ -* Generic DMA Controller and DMA request bindings - -Generic binding to provide a way for a driver using DMA Engine to retrieve the -DMA request or channel information that goes from a hardware device to a DMA -controller. - - -* DMA controller - -Required property: -- #dma-cells: Must be at least 1. Used to provide DMA controller - specific information. See DMA client binding below for - more details. - -Optional properties: -- dma-channels: Number of DMA channels supported by the controller. -- dma-requests: Number of DMA requests signals supported by the - controller. - -Example: - - dma: dma@48000000 { - compatible = "ti,omap-sdma"; - reg = <0x48000000 0x1000>; - interrupts = <0 12 0x4 - 0 13 0x4 - 0 14 0x4 - 0 15 0x4>; - #dma-cells = <1>; - dma-channels = <32>; - dma-requests = <127>; - }; - - -* DMA client - -Client drivers should specify the DMA property using a phandle to the controller -followed by DMA controller specific data. - -Required property: -- dmas: List of one or more DMA specifiers, each consisting of - - A phandle pointing to DMA controller node - - A number of integer cells, as determined by the - #dma-cells property in the node referenced by phandle - containing DMA controller specific information. This - typically contains a DMA request line number or a - channel number, but can contain any data that is used - required for configuring a channel. -- dma-names: Contains one identifier string for each DMA specifier in - the dmas property. The specific strings that can be used - are defined in the binding of the DMA client device. - Multiple DMA specifiers can be used to represent - alternatives and in this case the dma-names for those - DMA specifiers must be identical (see examples). - -Examples: - -1. A device with one DMA read channel, one DMA write channel: - - i2c1: i2c@1 { - ... - dmas = <&dma 2 /* read channel */ - &dma 3>; /* write channel */ - dma-names = "rx", "tx"; - ... - }; - -2. A single read-write channel with three alternative DMA controllers: - - dmas = <&dma1 5 - &dma2 7 - &dma3 2>; - dma-names = "rx-tx", "rx-tx", "rx-tx"; - -3. A device with three channels, one of which has two alternatives: - - dmas = <&dma1 2 /* read channel */ - &dma1 3 /* write channel */ - &dma2 0 /* error read */ - &dma3 0>; /* alternative error read */ - dma-names = "rx", "tx", "error", "error"; diff --git a/trunk/Documentation/devicetree/bindings/dma/snps-dma.txt b/trunk/Documentation/devicetree/bindings/dma/snps-dma.txt index 5bb3dfb6f1d8..c0d85dbcada5 100644 --- a/trunk/Documentation/devicetree/bindings/dma/snps-dma.txt +++ b/trunk/Documentation/devicetree/bindings/dma/snps-dma.txt @@ -6,26 +6,6 @@ Required properties: - interrupt-parent: Should be the phandle for the interrupt controller that services interrupts for this device - interrupt: Should contain the DMAC interrupt number -- nr_channels: Number of channels supported by hardware -- is_private: The device channels should be marked as private and not for by the - general purpose DMA channel allocator. False if not passed. -- chan_allocation_order: order of allocation of channel, 0 (default): ascending, - 1: descending -- chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1: - increase from chan n->0 -- block_size: Maximum block size supported by the controller -- nr_masters: Number of AHB masters supported by the controller -- data_width: Maximum data width supported by hardware per AHB master - (0 - 8bits, 1 - 16bits, ..., 5 - 256bits) -- slave_info: - - bus_id: name of this device channel, not just a device name since - devices may have more than one channel e.g. "foo_tx". For using the - dw_generic_filter(), slave drivers must pass exactly this string as - param to filter function. - - cfg_hi: Platform-specific initializer for the CFG_HI register - - cfg_lo: Platform-specific initializer for the CFG_LO register - - src_master: src master for transfers on allocated channel. - - dst_master: dest master for transfers on allocated channel. Example: @@ -34,28 +14,4 @@ Example: reg = <0xfc000000 0x1000>; interrupt-parent = <&vic1>; interrupts = <12>; - - nr_channels = <8>; - chan_allocation_order = <1>; - chan_priority = <1>; - block_size = <0xfff>; - nr_masters = <2>; - data_width = <3 3 0 0>; - - slave_info { - uart0-tx { - bus_id = "uart0-tx"; - cfg_hi = <0x4000>; /* 0x8 << 11 */ - cfg_lo = <0>; - src_master = <0>; - dst_master = <1>; - }; - spi0-tx { - bus_id = "spi0-tx"; - cfg_hi = <0x2000>; /* 0x4 << 11 */ - cfg_lo = <0>; - src_master = <0>; - dst_master = <0>; - }; - }; }; diff --git a/trunk/arch/arm/boot/dts/spear1340.dtsi b/trunk/arch/arm/boot/dts/spear1340.dtsi index b2d41b7502bd..34da11aa6795 100644 --- a/trunk/arch/arm/boot/dts/spear1340.dtsi +++ b/trunk/arch/arm/boot/dts/spear1340.dtsi @@ -88,25 +88,6 @@ status = "disabled"; }; - dma@ea800000 { - slave_info { - uart1_tx { - bus_id = "uart1_tx"; - cfg_hi = <0x6000>; /* 0xC << 11 */ - cfg_lo = <0>; - src_master = <0>; - dst_master = <1>; - }; - uart1_tx { - bus_id = "uart1_tx"; - cfg_hi = <0x680>; /* 0xD << 7 */ - cfg_lo = <0>; - src_master = <1>; - dst_master = <0>; - }; - }; - }; - spi1: spi@5d400000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x5d400000 0x1000>; diff --git a/trunk/arch/arm/boot/dts/spear13xx.dtsi b/trunk/arch/arm/boot/dts/spear13xx.dtsi index 585f64157ea4..b4ca60f4eb42 100644 --- a/trunk/arch/arm/boot/dts/spear13xx.dtsi +++ b/trunk/arch/arm/boot/dts/spear13xx.dtsi @@ -105,37 +105,6 @@ reg = <0xea800000 0x1000>; interrupts = <0 19 0x4>; status = "disabled"; - - nr_channels = <8>; - chan_allocation_order = <1>; - chan_priority = <1>; - block_size = <0xfff>; - nr_masters = <2>; - data_width = <3 3 0 0>; - - slave_info { - ssp0_tx { - bus_id = "ssp0_tx"; - cfg_hi = <0x2000>; /* 0x4 << 11 */ - cfg_lo = <0>; - src_master = <0>; - dst_master = <0>; - }; - ssp0_rx { - bus_id = "ssp0_rx"; - cfg_hi = <0x280>; /* 0x5 << 7 */ - cfg_lo = <0>; - src_master = <0>; - dst_master = <0>; - }; - cf { - bus_id = "cf"; - cfg_hi = <0>; - cfg_lo = <0>; - src_master = <0>; - dst_master = <0>; - }; - }; }; dma@eb000000 { @@ -143,13 +112,6 @@ reg = <0xeb000000 0x1000>; interrupts = <0 59 0x4>; status = "disabled"; - - nr_channels = <8>; - chan_allocation_order = <1>; - chan_priority = <1>; - block_size = <0xfff>; - nr_masters = <2>; - data_width = <3 3 0 0>; }; fsmc: flash@b0000000 { diff --git a/trunk/include/linux/amba/pl080.h b/trunk/arch/arm/include/asm/hardware/pl080.h similarity index 99% rename from trunk/include/linux/amba/pl080.h rename to trunk/arch/arm/include/asm/hardware/pl080.h index 3e7b62fbefbd..4eea2107214b 100644 --- a/trunk/include/linux/amba/pl080.h +++ b/trunk/arch/arm/include/asm/hardware/pl080.h @@ -1,4 +1,4 @@ -/* include/linux/amba/pl080.h +/* arch/arm/include/asm/hardware/pl080.h * * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics diff --git a/trunk/arch/arm/mach-s3c64xx/dma.c b/trunk/arch/arm/mach-s3c64xx/dma.c index a77f5214bbe8..f2a7a1725596 100644 --- a/trunk/arch/arm/mach-s3c64xx/dma.c +++ b/trunk/arch/arm/mach-s3c64xx/dma.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -31,6 +30,7 @@ #include +#include /* dma channel state information */ diff --git a/trunk/arch/arm/mach-spear13xx/include/mach/spear.h b/trunk/arch/arm/mach-spear13xx/include/mach/spear.h index 972a151df34c..7cfa6818865a 100644 --- a/trunk/arch/arm/mach-spear13xx/include/mach/spear.h +++ b/trunk/arch/arm/mach-spear13xx/include/mach/spear.h @@ -43,6 +43,8 @@ #define VA_L2CC_BASE IOMEM(UL(0xFB000000)) /* others */ +#define DMAC0_BASE UL(0xEA800000) +#define DMAC1_BASE UL(0xEB000000) #define MCIF_CF_BASE UL(0xB2800000) /* Debug uart for linux, will be used for debug and uncompress messages */ diff --git a/trunk/arch/arm/mach-spear13xx/spear1310.c b/trunk/arch/arm/mach-spear13xx/spear1310.c index ec72c47c0e08..02f4724bb0d4 100644 --- a/trunk/arch/arm/mach-spear13xx/spear1310.c +++ b/trunk/arch/arm/mach-spear13xx/spear1310.c @@ -36,7 +36,7 @@ static struct arasan_cf_pdata cf_pdata = { .cf_if_clk = CF_IF_CLK_166M, .quirk = CF_BROKEN_UDMA, - .dma_priv = "cf", + .dma_priv = &cf_dma_priv, }; /* ssp device registration */ @@ -47,7 +47,10 @@ static struct pl022_ssp_controller ssp1_plat_data = { /* Add SPEAr1310 auxdata to pass platform data */ static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata), + OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data), + OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data), OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data), + OF_DEV_AUXDATA("arm,pl022", SPEAR1310_SSP1_BASE, NULL, &ssp1_plat_data), {} }; diff --git a/trunk/arch/arm/mach-spear13xx/spear1340.c b/trunk/arch/arm/mach-spear13xx/spear1340.c index 69c8f72a9ca2..081014fb314a 100644 --- a/trunk/arch/arm/mach-spear13xx/spear1340.c +++ b/trunk/arch/arm/mach-spear13xx/spear1340.c @@ -18,9 +18,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -78,16 +78,26 @@ (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \ SPEAR1340_MIPHY_PLL_RATIO_TOP(25)) -static struct amba_pl011_data uart1_data = { - .dma_filter = dw_dma_generic_filter, - .dma_tx_param = "uart1_tx", - .dma_rx_param = "uart1_rx", +static struct dw_dma_slave uart1_dma_param[] = { + { + /* Tx */ + .cfg_hi = DWC_CFGH_DST_PER(SPEAR1340_DMA_REQ_UART1_TX), + .cfg_lo = 0, + .src_master = DMA_MASTER_MEMORY, + .dst_master = SPEAR1340_DMA_MASTER_UART1, + }, { + /* Rx */ + .cfg_hi = DWC_CFGH_SRC_PER(SPEAR1340_DMA_REQ_UART1_RX), + .cfg_lo = 0, + .src_master = SPEAR1340_DMA_MASTER_UART1, + .dst_master = DMA_MASTER_MEMORY, + } }; -static struct arasan_cf_pdata cf_pdata = { - .cf_if_clk = CF_IF_CLK_166M, - .quirk = CF_BROKEN_UDMA, - .dma_priv = "cf", +static struct amba_pl011_data uart1_data = { + .dma_filter = dw_dma_filter, + .dma_tx_param = &uart1_dma_param[0], + .dma_rx_param = &uart1_dma_param[1], }; /* SATA device registration */ @@ -148,8 +158,11 @@ static struct ahci_platform_data sata_pdata = { /* Add SPEAr1340 auxdata to pass platform data */ static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata), + OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv), + OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data), + OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data), OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data), + OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL, &sata_pdata), OF_DEV_AUXDATA("arm,pl011", SPEAR1340_UART1_BASE, NULL, &uart1_data), diff --git a/trunk/arch/arm/mach-spear13xx/spear13xx.c b/trunk/arch/arm/mach-spear13xx/spear13xx.c index b074db8b109c..c4af775a8451 100644 --- a/trunk/arch/arm/mach-spear13xx/spear13xx.c +++ b/trunk/arch/arm/mach-spear13xx/spear13xx.c @@ -22,16 +22,63 @@ #include #include #include +#include #include #include +/* common dw_dma filter routine to be used by peripherals */ +bool dw_dma_filter(struct dma_chan *chan, void *slave) +{ + struct dw_dma_slave *dws = (struct dw_dma_slave *)slave; + + if (chan->device->dev == dws->dma_dev) { + chan->private = slave; + return true; + } else { + return false; + } +} + /* ssp device registration */ +static struct dw_dma_slave ssp_dma_param[] = { + { + /* Tx */ + .cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX), + .cfg_lo = 0, + .src_master = DMA_MASTER_MEMORY, + .dst_master = DMA_MASTER_SSP0, + }, { + /* Rx */ + .cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX), + .cfg_lo = 0, + .src_master = DMA_MASTER_SSP0, + .dst_master = DMA_MASTER_MEMORY, + } +}; + struct pl022_ssp_controller pl022_plat_data = { .enable_dma = 1, - .dma_filter = dw_dma_generic_filter, - .dma_rx_param = "ssp0_rx", - .dma_tx_param = "ssp0_tx", - .num_chipselect = 3, + .dma_filter = dw_dma_filter, + .dma_rx_param = &ssp_dma_param[1], + .dma_tx_param = &ssp_dma_param[0], +}; + +/* CF device registration */ +struct dw_dma_slave cf_dma_priv = { + .cfg_hi = 0, + .cfg_lo = 0, + .src_master = 0, + .dst_master = 0, +}; + +/* dmac device registeration */ +struct dw_dma_platform_data dmac_plat_data = { + .nr_channels = 8, + .chan_allocation_order = CHAN_ALLOCATION_DESCENDING, + .chan_priority = CHAN_PRIORITY_DESCENDING, + .block_size = 4095U, + .nr_masters = 2, + .data_width = { 3, 3, 0, 0 }, }; void __init spear13xx_l2x0_init(void) diff --git a/trunk/arch/arm/mach-spear3xx/spear3xx.c b/trunk/arch/arm/mach-spear3xx/spear3xx.c index 3d9b1b5e8ed9..38fe95db31a7 100644 --- a/trunk/arch/arm/mach-spear3xx/spear3xx.c +++ b/trunk/arch/arm/mach-spear3xx/spear3xx.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/arch/arm/mach-spear6xx/spear6xx.c b/trunk/arch/arm/mach-spear6xx/spear6xx.c index 8ce65a23b06e..5a5a52db252b 100644 --- a/trunk/arch/arm/mach-spear6xx/spear6xx.c +++ b/trunk/arch/arm/mach-spear6xx/spear6xx.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/crypto/async_tx/async_memcpy.c b/trunk/crypto/async_tx/async_memcpy.c index 9e62feffb374..361b5e8239bc 100644 --- a/trunk/crypto/async_tx/async_memcpy.c +++ b/trunk/crypto/async_tx/async_memcpy.c @@ -67,12 +67,6 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset, tx = device->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, dma_prep_flags); - if (!tx) { - dma_unmap_page(device->dev, dma_dest, len, - DMA_FROM_DEVICE); - dma_unmap_page(device->dev, dma_src, len, - DMA_TO_DEVICE); - } } if (tx) { diff --git a/trunk/crypto/async_tx/async_memset.c b/trunk/crypto/async_tx/async_memset.c index 05a4d1e00148..58e4a8752aee 100644 --- a/trunk/crypto/async_tx/async_memset.c +++ b/trunk/crypto/async_tx/async_memset.c @@ -25,7 +25,6 @@ */ #include #include -#include #include #include #include diff --git a/trunk/crypto/async_tx/async_tx.c b/trunk/crypto/async_tx/async_tx.c index 7be34248b450..842120979374 100644 --- a/trunk/crypto/async_tx/async_tx.c +++ b/trunk/crypto/async_tx/async_tx.c @@ -128,8 +128,8 @@ async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx, } device->device_issue_pending(chan); } else { - if (dma_wait_for_async_tx(depend_tx) != DMA_SUCCESS) - panic("%s: DMA error waiting for depend_tx\n", + if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR) + panic("%s: DMA_ERROR waiting for depend_tx\n", __func__); tx->tx_submit(tx); } @@ -280,9 +280,8 @@ void async_tx_quiesce(struct dma_async_tx_descriptor **tx) * we are referring to the correct operation */ BUG_ON(async_tx_test_ack(*tx)); - if (dma_wait_for_async_tx(*tx) != DMA_SUCCESS) - panic("%s: DMA error waiting for transaction\n", - __func__); + if (dma_wait_for_async_tx(*tx) == DMA_ERROR) + panic("DMA_ERROR waiting for transaction\n"); async_tx_ack(*tx); *tx = NULL; } diff --git a/trunk/crypto/async_tx/async_xor.c b/trunk/crypto/async_tx/async_xor.c index 8ade0a0481c6..154cc84381c2 100644 --- a/trunk/crypto/async_tx/async_xor.c +++ b/trunk/crypto/async_tx/async_xor.c @@ -230,7 +230,9 @@ EXPORT_SYMBOL_GPL(async_xor); static int page_is_zero(struct page *p, unsigned int offset, size_t len) { - return !memchr_inv(page_address(p) + offset, 0, len); + char *a = page_address(p) + offset; + return ((*(u32 *) a) == 0 && + memcmp(a, a + 4, len - 4) == 0); } static inline struct dma_chan * diff --git a/trunk/drivers/dca/dca-core.c b/trunk/drivers/dca/dca-core.c index 819dfda88236..bc6f5faa1e9e 100644 --- a/trunk/drivers/dca/dca-core.c +++ b/trunk/drivers/dca/dca-core.c @@ -420,11 +420,6 @@ void unregister_dca_provider(struct dca_provider *dca, struct device *dev) raw_spin_lock_irqsave(&dca_lock, flags); - if (list_empty(&dca_domains)) { - raw_spin_unlock_irqrestore(&dca_lock, flags); - return; - } - list_del(&dca->node); pci_rc = dca_pci_rc_from_dev(dev); diff --git a/trunk/drivers/dma/Kconfig b/trunk/drivers/dma/Kconfig index 0b408bbb6a17..d4c12180c654 100644 --- a/trunk/drivers/dma/Kconfig +++ b/trunk/drivers/dma/Kconfig @@ -51,7 +51,7 @@ config ASYNC_TX_ENABLE_CHANNEL_SWITCH config AMBA_PL08X bool "ARM PrimeCell PL080 or PL081 support" - depends on ARM_AMBA + depends on ARM_AMBA && EXPERIMENTAL select DMA_ENGINE select DMA_VIRTUAL_CHANNELS help @@ -83,6 +83,7 @@ config INTEL_IOP_ADMA config DW_DMAC tristate "Synopsys DesignWare AHB DMA support" + depends on HAVE_CLK select DMA_ENGINE default y if CPU_AT32AP7000 help @@ -212,8 +213,8 @@ config TIMB_DMA Enable support for the Timberdale FPGA DMA engine. config SIRF_DMA - tristate "CSR SiRFprimaII/SiRFmarco DMA support" - depends on ARCH_SIRF + tristate "CSR SiRFprimaII DMA support" + depends on ARCH_PRIMA2 select DMA_ENGINE help Enable support for the CSR SiRFprimaII DMA engine. diff --git a/trunk/drivers/dma/amba-pl08x.c b/trunk/drivers/dma/amba-pl08x.c index 8bad254a498d..d1cc5791476b 100644 --- a/trunk/drivers/dma/amba-pl08x.c +++ b/trunk/drivers/dma/amba-pl08x.c @@ -83,7 +83,7 @@ #include #include #include -#include +#include #include "dmaengine.h" #include "virt-dma.h" @@ -1096,9 +1096,15 @@ static void pl08x_free_txd_list(struct pl08x_driver_data *pl08x, struct pl08x_dma_chan *plchan) { LIST_HEAD(head); + struct pl08x_txd *txd; vchan_get_all_descriptors(&plchan->vc, &head); - vchan_dma_desc_free_list(&plchan->vc, &head); + + while (!list_empty(&head)) { + txd = list_first_entry(&head, struct pl08x_txd, vd.node); + list_del(&txd->vd.node); + pl08x_desc_free(&txd->vd); + } } /* diff --git a/trunk/drivers/dma/at_hdmac.c b/trunk/drivers/dma/at_hdmac.c index 6e13f262139a..13a02f4425b0 100644 --- a/trunk/drivers/dma/at_hdmac.c +++ b/trunk/drivers/dma/at_hdmac.c @@ -778,7 +778,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, */ static int atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr, - size_t period_len) + size_t period_len, enum dma_transfer_direction direction) { if (period_len > (ATC_BTSIZE_MAX << reg_width)) goto err_out; @@ -786,6 +786,8 @@ atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr, goto err_out; if (unlikely(buf_addr & ((1 << reg_width) - 1))) goto err_out; + if (unlikely(!(direction & (DMA_DEV_TO_MEM | DMA_MEM_TO_DEV)))) + goto err_out; return 0; @@ -884,16 +886,14 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, return NULL; } - if (unlikely(!is_slave_direction(direction))) - goto err_out; - if (sconfig->direction == DMA_MEM_TO_DEV) reg_width = convert_buswidth(sconfig->dst_addr_width); else reg_width = convert_buswidth(sconfig->src_addr_width); /* Check for too big/unaligned periods and unaligned DMA buffer */ - if (atc_dma_cyclic_check_values(reg_width, buf_addr, period_len)) + if (atc_dma_cyclic_check_values(reg_width, buf_addr, + period_len, direction)) goto err_out; /* build cyclic linked list */ diff --git a/trunk/drivers/dma/at_hdmac_regs.h b/trunk/drivers/dma/at_hdmac_regs.h index 0eb3c1388667..116e4adffb08 100644 --- a/trunk/drivers/dma/at_hdmac_regs.h +++ b/trunk/drivers/dma/at_hdmac_regs.h @@ -369,10 +369,10 @@ static void vdbg_dump_regs(struct at_dma_chan *atchan) {} static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli) { - dev_crit(chan2dev(&atchan->chan_common), - " desc: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n", - lli->saddr, lli->daddr, - lli->ctrla, lli->ctrlb, lli->dscr); + dev_printk(KERN_CRIT, chan2dev(&atchan->chan_common), + " desc: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n", + lli->saddr, lli->daddr, + lli->ctrla, lli->ctrlb, lli->dscr); } diff --git a/trunk/drivers/dma/dmaengine.c b/trunk/drivers/dma/dmaengine.c index 242b8c0a3de8..a815d44c70a4 100644 --- a/trunk/drivers/dma/dmaengine.c +++ b/trunk/drivers/dma/dmaengine.c @@ -62,7 +62,6 @@ #include #include #include -#include static DEFINE_MUTEX(dma_list_mutex); static DEFINE_IDR(dma_idr); @@ -267,10 +266,7 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) pr_err("%s: timeout!\n", __func__); return DMA_ERROR; } - if (status != DMA_IN_PROGRESS) - break; - cpu_relax(); - } while (1); + } while (status == DMA_IN_PROGRESS); return status; } @@ -550,21 +546,6 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v } EXPORT_SYMBOL_GPL(__dma_request_channel); -/** - * dma_request_slave_channel - try to allocate an exclusive slave channel - * @dev: pointer to client device structure - * @name: slave channel name - */ -struct dma_chan *dma_request_slave_channel(struct device *dev, char *name) -{ - /* If device-tree is present get slave info from here */ - if (dev->of_node) - return of_dma_request_slave_channel(dev->of_node, name); - - return NULL; -} -EXPORT_SYMBOL_GPL(dma_request_slave_channel); - void dma_release_channel(struct dma_chan *chan) { mutex_lock(&dma_list_mutex); diff --git a/trunk/drivers/dma/dmatest.c b/trunk/drivers/dma/dmatest.c index a2c8904b63ea..64b048d7fba7 100644 --- a/trunk/drivers/dma/dmatest.c +++ b/trunk/drivers/dma/dmatest.c @@ -242,13 +242,6 @@ static inline void unmap_dst(struct device *dev, dma_addr_t *addr, size_t len, dma_unmap_single(dev, addr[count], len, DMA_BIDIRECTIONAL); } -static unsigned int min_odd(unsigned int x, unsigned int y) -{ - unsigned int val = min(x, y); - - return val % 2 ? val : val - 1; -} - /* * This function repeatedly tests DMA transfers of various lengths and * offsets for a given operation type until it is told to exit by @@ -269,7 +262,6 @@ static int dmatest_func(void *data) struct dmatest_thread *thread = data; struct dmatest_done done = { .wait = &done_wait }; struct dma_chan *chan; - struct dma_device *dev; const char *thread_name; unsigned int src_off, dst_off, len; unsigned int error_count; @@ -291,16 +283,13 @@ static int dmatest_func(void *data) smp_rmb(); chan = thread->chan; - dev = chan->device; if (thread->type == DMA_MEMCPY) src_cnt = dst_cnt = 1; else if (thread->type == DMA_XOR) { - /* force odd to ensure dst = src */ - src_cnt = min_odd(xor_sources | 1, dev->max_xor); + src_cnt = xor_sources | 1; /* force odd to ensure dst = src */ dst_cnt = 1; } else if (thread->type == DMA_PQ) { - /* force odd to ensure dst = src */ - src_cnt = min_odd(pq_sources | 1, dma_maxpq(dev, 0)); + src_cnt = pq_sources | 1; /* force odd to ensure dst = src */ dst_cnt = 2; for (i = 0; i < src_cnt; i++) pq_coefs[i] = 1; @@ -338,6 +327,7 @@ static int dmatest_func(void *data) while (!kthread_should_stop() && !(iterations && total_tests >= iterations)) { + struct dma_device *dev = chan->device; struct dma_async_tx_descriptor *tx = NULL; dma_addr_t dma_srcs[src_cnt]; dma_addr_t dma_dsts[dst_cnt]; @@ -536,9 +526,7 @@ static int dmatest_func(void *data) thread_name, total_tests, failed_tests, ret); /* terminate all transfers on specified channels */ - if (ret) - dmaengine_terminate_all(chan); - + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); if (iterations > 0) while (!kthread_should_stop()) { DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); @@ -563,7 +551,7 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc) } /* terminate all transfers on specified channels */ - dmaengine_terminate_all(dtc->chan); + dtc->chan->device->device_control(dtc->chan, DMA_TERMINATE_ALL, 0); kfree(dtc); } diff --git a/trunk/drivers/dma/dw_dmac.c b/trunk/drivers/dma/dw_dmac.c index dc3b9558a25c..8f0b111af4de 100644 --- a/trunk/drivers/dma/dw_dmac.c +++ b/trunk/drivers/dma/dw_dmac.c @@ -1,5 +1,6 @@ /* - * Core driver for the Synopsys DesignWare DMA Controller + * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on + * AVR32 systems.) * * Copyright (C) 2007-2008 Atmel Corporation * Copyright (C) 2010-2011 ST Microelectronics @@ -8,13 +9,11 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ - #include #include #include #include #include -#include #include #include #include @@ -47,32 +46,15 @@ static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave) return slave ? slave->src_master : 1; } -#define SRC_MASTER 0 -#define DST_MASTER 1 - -static inline unsigned int dwc_get_master(struct dma_chan *chan, int master) -{ - struct dw_dma *dw = to_dw_dma(chan->device); - struct dw_dma_slave *dws = chan->private; - unsigned int m; - - if (master == SRC_MASTER) - m = dwc_get_sms(dws); - else - m = dwc_get_dms(dws); - - return min_t(unsigned int, dw->nr_masters - 1, m); -} - #define DWC_DEFAULT_CTLLO(_chan) ({ \ + struct dw_dma_slave *__slave = (_chan->private); \ struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \ struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \ - bool _is_slave = is_slave_direction(_dwc->direction); \ - int _dms = dwc_get_master(_chan, DST_MASTER); \ - int _sms = dwc_get_master(_chan, SRC_MASTER); \ - u8 _smsize = _is_slave ? _sconfig->src_maxburst : \ + int _dms = dwc_get_dms(__slave); \ + int _sms = dwc_get_sms(__slave); \ + u8 _smsize = __slave ? _sconfig->src_maxburst : \ DW_DMA_MSIZE_16; \ - u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \ + u8 _dmsize = __slave ? _sconfig->dst_maxburst : \ DW_DMA_MSIZE_16; \ \ (DWC_CTLL_DST_MSIZE(_dmsize) \ @@ -90,15 +72,16 @@ static inline unsigned int dwc_get_master(struct dma_chan *chan, int master) */ #define NR_DESCS_PER_CHANNEL 64 -static inline unsigned int dwc_get_data_width(struct dma_chan *chan, int master) -{ - struct dw_dma *dw = to_dw_dma(chan->device); - - return dw->data_width[dwc_get_master(chan, master)]; -} - /*----------------------------------------------------------------------*/ +/* + * Because we're not relying on writeback from the controller (it may not + * even be configured into the core!) we don't need to use dma_pool. These + * descriptors -- and associated data -- are cacheable. We do need to make + * sure their dcache entries are written back before handing them off to + * the controller, though. + */ + static struct device *chan2dev(struct dma_chan *chan) { return &chan->dev->device; @@ -110,7 +93,7 @@ static struct device *chan2parent(struct dma_chan *chan) static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc) { - return to_dw_desc(dwc->active_list.next); + return list_entry(dwc->active_list.next, struct dw_desc, desc_node); } static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc) @@ -137,6 +120,19 @@ static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc) return ret; } +static void dwc_sync_desc_for_cpu(struct dw_dma_chan *dwc, struct dw_desc *desc) +{ + struct dw_desc *child; + + list_for_each_entry(child, &desc->tx_list, desc_node) + dma_sync_single_for_cpu(chan2parent(&dwc->chan), + child->txd.phys, sizeof(child->lli), + DMA_TO_DEVICE); + dma_sync_single_for_cpu(chan2parent(&dwc->chan), + desc->txd.phys, sizeof(desc->lli), + DMA_TO_DEVICE); +} + /* * Move a descriptor, including any children, to the free list. * `desc' must not be on any lists. @@ -148,6 +144,8 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc) if (desc) { struct dw_desc *child; + dwc_sync_desc_for_cpu(dwc, desc); + spin_lock_irqsave(&dwc->lock, flags); list_for_each_entry(child, &desc->tx_list, desc_node) dev_vdbg(chan2dev(&dwc->chan), @@ -180,9 +178,9 @@ static void dwc_initialize(struct dw_dma_chan *dwc) cfghi = dws->cfg_hi; cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK; } else { - if (dwc->direction == DMA_MEM_TO_DEV) + if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV) cfghi = DWC_CFGH_DST_PER(dwc->dma_sconfig.slave_id); - else if (dwc->direction == DMA_DEV_TO_MEM) + else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM) cfghi = DWC_CFGH_SRC_PER(dwc->dma_sconfig.slave_id); } @@ -224,6 +222,7 @@ static inline void dwc_dump_chan_regs(struct dw_dma_chan *dwc) channel_readl(dwc, CTL_LO)); } + static inline void dwc_chan_disable(struct dw_dma *dw, struct dw_dma_chan *dwc) { channel_clear_bit(dw, CH_EN, dwc->mask); @@ -249,9 +248,6 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc, channel_writel(dwc, CTL_LO, ctllo); channel_writel(dwc, CTL_HI, desc->lli.ctlhi); channel_set_bit(dw, CH_EN, dwc->mask); - - /* Move pointer to next descriptor */ - dwc->tx_node_active = dwc->tx_node_active->next; } /* Called with dwc->lock held and bh disabled */ @@ -283,7 +279,7 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) dwc_initialize(dwc); dwc->tx_list = &first->tx_list; - dwc->tx_node_active = &first->tx_list; + dwc->tx_node_active = first->tx_list.next; dwc_do_single_block(dwc, first); @@ -320,6 +316,8 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc, param = txd->callback_param; } + dwc_sync_desc_for_cpu(dwc, desc); + /* async_tx_ack */ list_for_each_entry(child, &desc->tx_list, desc_node) async_tx_ack(&child->txd); @@ -328,7 +326,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc, list_splice_init(&desc->tx_list, &dwc->free_list); list_move(&desc->desc_node, &dwc->free_list); - if (!is_slave_direction(dwc->direction)) { + if (!dwc->chan.private) { struct device *parent = chan2parent(&dwc->chan); if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) { if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE) @@ -350,7 +348,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc, spin_unlock_irqrestore(&dwc->lock, flags); - if (callback) + if (callback_required && callback) callback(param); } @@ -400,20 +398,6 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) if (status_xfer & dwc->mask) { /* Everything we've submitted is done */ dma_writel(dw, CLEAR.XFER, dwc->mask); - - if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) { - if (dwc->tx_node_active != dwc->tx_list) { - desc = to_dw_desc(dwc->tx_node_active); - - /* Submit next block */ - dwc_do_single_block(dwc, desc); - spin_unlock_irqrestore(&dwc->lock, flags); - - return; - } - /* We are done here */ - clear_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags); - } spin_unlock_irqrestore(&dwc->lock, flags); dwc_complete_all(dw, dwc); @@ -425,12 +409,6 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) return; } - if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) { - dev_vdbg(chan2dev(&dwc->chan), "%s: soft LLP mode\n", __func__); - spin_unlock_irqrestore(&dwc->lock, flags); - return; - } - dev_vdbg(chan2dev(&dwc->chan), "%s: llp=0x%llx\n", __func__, (unsigned long long)llp); @@ -479,8 +457,9 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) static inline void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli) { - dev_crit(chan2dev(&dwc->chan), " desc: s0x%x d0x%x l0x%x c0x%x:%x\n", - lli->sar, lli->dar, lli->llp, lli->ctlhi, lli->ctllo); + dev_printk(KERN_CRIT, chan2dev(&dwc->chan), + " desc: s0x%x d0x%x l0x%x c0x%x:%x\n", + lli->sar, lli->dar, lli->llp, lli->ctlhi, lli->ctllo); } static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) @@ -508,14 +487,16 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) dwc_dostart(dwc, dwc_first_active(dwc)); /* - * WARN may seem harsh, but since this only happens + * KERN_CRITICAL may seem harsh, but since this only happens * when someone submits a bad physical address in a * descriptor, we should consider ourselves lucky that the * controller flagged an error instead of scribbling over * random memory locations. */ - dev_WARN(chan2dev(&dwc->chan), "Bad descriptor submitted for DMA!\n" - " cookie: %d\n", bad_desc->txd.cookie); + dev_printk(KERN_CRIT, chan2dev(&dwc->chan), + "Bad descriptor submitted for DMA!\n"); + dev_printk(KERN_CRIT, chan2dev(&dwc->chan), + " cookie: %d\n", bad_desc->txd.cookie); dwc_dump_lli(dwc, &bad_desc->lli); list_for_each_entry(child, &bad_desc->tx_list, desc_node) dwc_dump_lli(dwc, &child->lli); @@ -616,8 +597,36 @@ static void dw_dma_tasklet(unsigned long data) dwc_handle_cyclic(dw, dwc, status_err, status_xfer); else if (status_err & (1 << i)) dwc_handle_error(dw, dwc); - else if (status_xfer & (1 << i)) + else if (status_xfer & (1 << i)) { + unsigned long flags; + + spin_lock_irqsave(&dwc->lock, flags); + if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) { + if (dwc->tx_node_active != dwc->tx_list) { + struct dw_desc *desc = + list_entry(dwc->tx_node_active, + struct dw_desc, + desc_node); + + dma_writel(dw, CLEAR.XFER, dwc->mask); + + /* move pointer to next descriptor */ + dwc->tx_node_active = + dwc->tx_node_active->next; + + dwc_do_single_block(dwc, desc); + + spin_unlock_irqrestore(&dwc->lock, flags); + continue; + } else { + /* we are done here */ + clear_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags); + } + } + spin_unlock_irqrestore(&dwc->lock, flags); + dwc_scan_descriptors(dw, dwc); + } } /* @@ -699,6 +708,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, size_t len, unsigned long flags) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma_slave *dws = chan->private; struct dw_desc *desc; struct dw_desc *first; struct dw_desc *prev; @@ -719,10 +729,8 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, return NULL; } - dwc->direction = DMA_MEM_TO_MEM; - - data_width = min_t(unsigned int, dwc_get_data_width(chan, SRC_MASTER), - dwc_get_data_width(chan, DST_MASTER)); + data_width = min_t(unsigned int, dwc->dw->data_width[dwc_get_sms(dws)], + dwc->dw->data_width[dwc_get_dms(dws)]); src_width = dst_width = min_t(unsigned int, data_width, dwc_fast_fls(src | dest | len)); @@ -752,17 +760,25 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, first = desc; } else { prev->lli.llp = desc->txd.phys; + dma_sync_single_for_device(chan2parent(chan), + prev->txd.phys, sizeof(prev->lli), + DMA_TO_DEVICE); list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; } + if (flags & DMA_PREP_INTERRUPT) /* Trigger interrupt after last block */ prev->lli.ctllo |= DWC_CTLL_INT_EN; prev->lli.llp = 0; + dma_sync_single_for_device(chan2parent(chan), + prev->txd.phys, sizeof(prev->lli), + DMA_TO_DEVICE); + first->txd.flags = flags; first->len = len; @@ -779,6 +795,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned long flags, void *context) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma_slave *dws = chan->private; struct dma_slave_config *sconfig = &dwc->dma_sconfig; struct dw_desc *prev; struct dw_desc *first; @@ -793,11 +810,9 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, dev_vdbg(chan2dev(chan), "%s\n", __func__); - if (unlikely(!is_slave_direction(direction) || !sg_len)) + if (unlikely(!dws || !sg_len)) return NULL; - dwc->direction = direction; - prev = first = NULL; switch (direction) { @@ -812,7 +827,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) : DWC_CTLL_FC(DW_DMA_FC_D_M2P); - data_width = dwc_get_data_width(chan, SRC_MASTER); + data_width = dwc->dw->data_width[dwc_get_sms(dws)]; for_each_sg(sgl, sg, sg_len, i) { struct dw_desc *desc; @@ -850,6 +865,10 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, first = desc; } else { prev->lli.llp = desc->txd.phys; + dma_sync_single_for_device(chan2parent(chan), + prev->txd.phys, + sizeof(prev->lli), + DMA_TO_DEVICE); list_add_tail(&desc->desc_node, &first->tx_list); } @@ -871,7 +890,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) : DWC_CTLL_FC(DW_DMA_FC_D_P2M); - data_width = dwc_get_data_width(chan, DST_MASTER); + data_width = dwc->dw->data_width[dwc_get_dms(dws)]; for_each_sg(sgl, sg, sg_len, i) { struct dw_desc *desc; @@ -908,6 +927,10 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, first = desc; } else { prev->lli.llp = desc->txd.phys; + dma_sync_single_for_device(chan2parent(chan), + prev->txd.phys, + sizeof(prev->lli), + DMA_TO_DEVICE); list_add_tail(&desc->desc_node, &first->tx_list); } @@ -927,6 +950,10 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, prev->lli.ctllo |= DWC_CTLL_INT_EN; prev->lli.llp = 0; + dma_sync_single_for_device(chan2parent(chan), + prev->txd.phys, sizeof(prev->lli), + DMA_TO_DEVICE); + first->len = total_len; return &first->txd; @@ -957,12 +984,11 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); - /* Check if chan will be configured for slave transfers */ - if (!is_slave_direction(sconfig->direction)) + /* Check if it is chan is configured for slave transfers */ + if (!chan->private) return -EINVAL; memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); - dwc->direction = sconfig->direction; convert_burst(&dwc->dma_sconfig.src_maxburst); convert_burst(&dwc->dma_sconfig.dst_maxburst); @@ -970,26 +996,6 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig) return 0; } -static inline void dwc_chan_pause(struct dw_dma_chan *dwc) -{ - u32 cfglo = channel_readl(dwc, CFG_LO); - - channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP); - while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY)) - cpu_relax(); - - dwc->paused = true; -} - -static inline void dwc_chan_resume(struct dw_dma_chan *dwc) -{ - u32 cfglo = channel_readl(dwc, CFG_LO); - - channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP); - - dwc->paused = false; -} - static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) { @@ -997,13 +1003,18 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, struct dw_dma *dw = to_dw_dma(chan->device); struct dw_desc *desc, *_desc; unsigned long flags; + u32 cfglo; LIST_HEAD(list); if (cmd == DMA_PAUSE) { spin_lock_irqsave(&dwc->lock, flags); - dwc_chan_pause(dwc); + cfglo = channel_readl(dwc, CFG_LO); + channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP); + while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY)) + cpu_relax(); + dwc->paused = true; spin_unlock_irqrestore(&dwc->lock, flags); } else if (cmd == DMA_RESUME) { if (!dwc->paused) @@ -1011,7 +1022,9 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, spin_lock_irqsave(&dwc->lock, flags); - dwc_chan_resume(dwc); + cfglo = channel_readl(dwc, CFG_LO); + channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP); + dwc->paused = false; spin_unlock_irqrestore(&dwc->lock, flags); } else if (cmd == DMA_TERMINATE_ALL) { @@ -1021,7 +1034,7 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, dwc_chan_disable(dw, dwc); - dwc_chan_resume(dwc); + dwc->paused = false; /* active_list entries will end up before queued entries */ list_splice_init(&dwc->queue, &list); @@ -1100,22 +1113,22 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) spin_lock_irqsave(&dwc->lock, flags); i = dwc->descs_allocated; while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) { - dma_addr_t phys; - spin_unlock_irqrestore(&dwc->lock, flags); - desc = dma_pool_alloc(dw->desc_pool, GFP_ATOMIC, &phys); - if (!desc) - goto err_desc_alloc; - - memset(desc, 0, sizeof(struct dw_desc)); + desc = kzalloc(sizeof(struct dw_desc), GFP_KERNEL); + if (!desc) { + dev_info(chan2dev(chan), + "only allocated %d descriptors\n", i); + spin_lock_irqsave(&dwc->lock, flags); + break; + } INIT_LIST_HEAD(&desc->tx_list); dma_async_tx_descriptor_init(&desc->txd, chan); desc->txd.tx_submit = dwc_tx_submit; desc->txd.flags = DMA_CTRL_ACK; - desc->txd.phys = phys; - + desc->txd.phys = dma_map_single(chan2parent(chan), &desc->lli, + sizeof(desc->lli), DMA_TO_DEVICE); dwc_desc_put(dwc, desc); spin_lock_irqsave(&dwc->lock, flags); @@ -1126,11 +1139,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) dev_dbg(chan2dev(chan), "%s: allocated %d descriptors\n", __func__, i); - return i; - -err_desc_alloc: - dev_info(chan2dev(chan), "only allocated %d descriptors\n", i); - return i; } @@ -1163,56 +1171,14 @@ static void dwc_free_chan_resources(struct dma_chan *chan) list_for_each_entry_safe(desc, _desc, &list, desc_node) { dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc); - dma_pool_free(dw->desc_pool, desc, desc->txd.phys); + dma_unmap_single(chan2parent(chan), desc->txd.phys, + sizeof(desc->lli), DMA_TO_DEVICE); + kfree(desc); } dev_vdbg(chan2dev(chan), "%s: done\n", __func__); } -bool dw_dma_generic_filter(struct dma_chan *chan, void *param) -{ - struct dw_dma *dw = to_dw_dma(chan->device); - static struct dw_dma *last_dw; - static char *last_bus_id; - int i = -1; - - /* - * dmaengine framework calls this routine for all channels of all dma - * controller, until true is returned. If 'param' bus_id is not - * registered with a dma controller (dw), then there is no need of - * running below function for all channels of dw. - * - * This block of code does this by saving the parameters of last - * failure. If dw and param are same, i.e. trying on same dw with - * different channel, return false. - */ - if ((last_dw == dw) && (last_bus_id == param)) - return false; - /* - * Return true: - * - If dw_dma's platform data is not filled with slave info, then all - * dma controllers are fine for transfer. - * - Or if param is NULL - */ - if (!dw->sd || !param) - return true; - - while (++i < dw->sd_count) { - if (!strcmp(dw->sd[i].bus_id, param)) { - chan->private = &dw->sd[i]; - last_dw = NULL; - last_bus_id = NULL; - - return true; - } - } - - last_dw = dw; - last_bus_id = param; - return false; -} -EXPORT_SYMBOL(dw_dma_generic_filter); - /* --------------------- Cyclic DMA API extensions -------------------- */ /** @@ -1332,11 +1298,6 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, retval = ERR_PTR(-EINVAL); - if (unlikely(!is_slave_direction(direction))) - goto out_err; - - dwc->direction = direction; - if (direction == DMA_MEM_TO_DEV) reg_width = __ffs(sconfig->dst_addr_width); else @@ -1351,6 +1312,8 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, goto out_err; if (unlikely(buf_addr & ((1 << reg_width) - 1))) goto out_err; + if (unlikely(!(direction & (DMA_MEM_TO_DEV | DMA_DEV_TO_MEM)))) + goto out_err; retval = ERR_PTR(-ENOMEM); @@ -1408,14 +1371,20 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, desc->lli.ctlhi = (period_len >> reg_width); cdesc->desc[i] = desc; - if (last) + if (last) { last->lli.llp = desc->txd.phys; + dma_sync_single_for_device(chan2parent(chan), + last->txd.phys, sizeof(last->lli), + DMA_TO_DEVICE); + } last = desc; } /* lets make a cyclic list */ last->lli.llp = cdesc->desc[0]->txd.phys; + dma_sync_single_for_device(chan2parent(chan), last->txd.phys, + sizeof(last->lli), DMA_TO_DEVICE); dev_dbg(chan2dev(&dwc->chan), "cyclic prepared buf 0x%llx len %zu " "period %zu periods %d\n", (unsigned long long)buf_addr, @@ -1493,91 +1462,6 @@ static void dw_dma_off(struct dw_dma *dw) dw->chan[i].initialized = false; } -#ifdef CONFIG_OF -static struct dw_dma_platform_data * -dw_dma_parse_dt(struct platform_device *pdev) -{ - struct device_node *sn, *cn, *np = pdev->dev.of_node; - struct dw_dma_platform_data *pdata; - struct dw_dma_slave *sd; - u32 tmp, arr[4]; - - if (!np) { - dev_err(&pdev->dev, "Missing DT data\n"); - return NULL; - } - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels)) - return NULL; - - if (of_property_read_bool(np, "is_private")) - pdata->is_private = true; - - if (!of_property_read_u32(np, "chan_allocation_order", &tmp)) - pdata->chan_allocation_order = (unsigned char)tmp; - - if (!of_property_read_u32(np, "chan_priority", &tmp)) - pdata->chan_priority = tmp; - - if (!of_property_read_u32(np, "block_size", &tmp)) - pdata->block_size = tmp; - - if (!of_property_read_u32(np, "nr_masters", &tmp)) { - if (tmp > 4) - return NULL; - - pdata->nr_masters = tmp; - } - - if (!of_property_read_u32_array(np, "data_width", arr, - pdata->nr_masters)) - for (tmp = 0; tmp < pdata->nr_masters; tmp++) - pdata->data_width[tmp] = arr[tmp]; - - /* parse slave data */ - sn = of_find_node_by_name(np, "slave_info"); - if (!sn) - return pdata; - - /* calculate number of slaves */ - tmp = of_get_child_count(sn); - if (!tmp) - return NULL; - - sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL); - if (!sd) - return NULL; - - pdata->sd = sd; - pdata->sd_count = tmp; - - for_each_child_of_node(sn, cn) { - sd->dma_dev = &pdev->dev; - of_property_read_string(cn, "bus_id", &sd->bus_id); - of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi); - of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo); - if (!of_property_read_u32(cn, "src_master", &tmp)) - sd->src_master = tmp; - - if (!of_property_read_u32(cn, "dst_master", &tmp)) - sd->dst_master = tmp; - sd++; - } - - return pdata; -} -#else -static inline struct dw_dma_platform_data * -dw_dma_parse_dt(struct platform_device *pdev) -{ - return NULL; -} -#endif - static int dw_probe(struct platform_device *pdev) { struct dw_dma_platform_data *pdata; @@ -1593,6 +1477,10 @@ static int dw_probe(struct platform_device *pdev) int err; int i; + pdata = dev_get_platdata(&pdev->dev); + if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) + return -EINVAL; + io = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!io) return -EINVAL; @@ -1608,22 +1496,6 @@ static int dw_probe(struct platform_device *pdev) dw_params = dma_read_byaddr(regs, DW_PARAMS); autocfg = dw_params >> DW_PARAMS_EN & 0x1; - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) - pdata = dw_dma_parse_dt(pdev); - - if (!pdata && autocfg) { - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - /* Fill platform data with the default values */ - pdata->is_private = true; - pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; - pdata->chan_priority = CHAN_PRIORITY_ASCENDING; - } else if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) - return -EINVAL; - if (autocfg) nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1; else @@ -1640,8 +1512,6 @@ static int dw_probe(struct platform_device *pdev) clk_prepare_enable(dw->clk); dw->regs = regs; - dw->sd = pdata->sd; - dw->sd_count = pdata->sd_count; /* get hardware configuration parameters */ if (autocfg) { @@ -1673,14 +1543,6 @@ static int dw_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dw); - /* create a pool of consistent memory blocks for hardware descriptors */ - dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", &pdev->dev, - sizeof(struct dw_desc), 4, 0); - if (!dw->desc_pool) { - dev_err(&pdev->dev, "No memory for descriptors dma pool\n"); - return -ENOMEM; - } - tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw); INIT_LIST_HEAD(&dw->dma.channels); @@ -1712,7 +1574,7 @@ static int dw_probe(struct platform_device *pdev) channel_clear_bit(dw, CH_EN, dwc->mask); - dwc->direction = DMA_TRANS_NONE; + dwc->dw = dw; /* hardware configuration */ if (autocfg) { @@ -1764,8 +1626,8 @@ static int dw_probe(struct platform_device *pdev) dma_writel(dw, CFG, DW_CFG_DMA_EN); - dev_info(&pdev->dev, "DesignWare DMA Controller, %d channels\n", - nr_channels); + printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n", + dev_name(&pdev->dev), nr_channels); dma_async_device_register(&dw->dma); @@ -1795,7 +1657,7 @@ static void dw_shutdown(struct platform_device *pdev) { struct dw_dma *dw = platform_get_drvdata(pdev); - dw_dma_off(dw); + dw_dma_off(platform_get_drvdata(pdev)); clk_disable_unprepare(dw->clk); } @@ -1804,7 +1666,7 @@ static int dw_suspend_noirq(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct dw_dma *dw = platform_get_drvdata(pdev); - dw_dma_off(dw); + dw_dma_off(platform_get_drvdata(pdev)); clk_disable_unprepare(dw->clk); return 0; @@ -1817,7 +1679,6 @@ static int dw_resume_noirq(struct device *dev) clk_prepare_enable(dw->clk); dma_writel(dw, CFG, DW_CFG_DMA_EN); - return 0; } @@ -1839,7 +1700,6 @@ MODULE_DEVICE_TABLE(of, dw_dma_id_table); #endif static struct platform_driver dw_driver = { - .probe = dw_probe, .remove = dw_remove, .shutdown = dw_shutdown, .driver = { @@ -1851,7 +1711,7 @@ static struct platform_driver dw_driver = { static int __init dw_init(void) { - return platform_driver_register(&dw_driver); + return platform_driver_probe(&dw_driver, dw_probe); } subsys_initcall(dw_init); diff --git a/trunk/drivers/dma/dw_dmac_regs.h b/trunk/drivers/dma/dw_dmac_regs.h index fef296de4af1..88965597b7d0 100644 --- a/trunk/drivers/dma/dw_dmac_regs.h +++ b/trunk/drivers/dma/dw_dmac_regs.h @@ -9,7 +9,6 @@ * published by the Free Software Foundation. */ -#include #include #define DW_DMA_MAX_NR_CHANNELS 8 @@ -185,13 +184,12 @@ enum dw_dmac_flags { }; struct dw_dma_chan { - struct dma_chan chan; - void __iomem *ch_regs; - u8 mask; - u8 priority; - enum dma_transfer_direction direction; - bool paused; - bool initialized; + struct dma_chan chan; + void __iomem *ch_regs; + u8 mask; + u8 priority; + bool paused; + bool initialized; /* software emulation of the LLP transfers */ struct list_head *tx_list; @@ -214,6 +212,9 @@ struct dw_dma_chan { /* configuration passed via DMA_SLAVE_CONFIG */ struct dma_slave_config dma_sconfig; + + /* backlink to dw_dma */ + struct dw_dma *dw; }; static inline struct dw_dma_chan_regs __iomem * @@ -235,14 +236,9 @@ static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan) struct dw_dma { struct dma_device dma; void __iomem *regs; - struct dma_pool *desc_pool; struct tasklet_struct tasklet; struct clk *clk; - /* slave information */ - struct dw_dma_slave *sd; - unsigned int sd_count; - u8 all_chan_mask; /* hardware configuration */ @@ -299,8 +295,6 @@ struct dw_desc { size_t len; }; -#define to_dw_desc(h) list_entry(h, struct dw_desc, desc_node) - static inline struct dw_desc * txd_to_dw_desc(struct dma_async_tx_descriptor *txd) { diff --git a/trunk/drivers/dma/edma.c b/trunk/drivers/dma/edma.c index 82c8672f26e8..232b4583ae93 100644 --- a/trunk/drivers/dma/edma.c +++ b/trunk/drivers/dma/edma.c @@ -69,7 +69,9 @@ struct edma_chan { int ch_num; bool alloced; int slot[EDMA_MAX_SLOTS]; - struct dma_slave_config cfg; + dma_addr_t addr; + int addr_width; + int maxburst; }; struct edma_cc { @@ -176,14 +178,29 @@ static int edma_terminate_all(struct edma_chan *echan) return 0; } + static int edma_slave_config(struct edma_chan *echan, - struct dma_slave_config *cfg) + struct dma_slave_config *config) { - if (cfg->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES || - cfg->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES) + if ((config->src_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES) || + (config->dst_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES)) return -EINVAL; - memcpy(&echan->cfg, cfg, sizeof(echan->cfg)); + if (config->direction == DMA_MEM_TO_DEV) { + if (config->dst_addr) + echan->addr = config->dst_addr; + if (config->dst_addr_width) + echan->addr_width = config->dst_addr_width; + if (config->dst_maxburst) + echan->maxburst = config->dst_maxburst; + } else if (config->direction == DMA_DEV_TO_MEM) { + if (config->src_addr) + echan->addr = config->src_addr; + if (config->src_addr_width) + echan->addr_width = config->src_addr_width; + if (config->src_maxburst) + echan->maxburst = config->src_maxburst; + } return 0; } @@ -218,9 +235,6 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( struct edma_chan *echan = to_edma_chan(chan); struct device *dev = chan->device->dev; struct edma_desc *edesc; - dma_addr_t dev_addr; - enum dma_slave_buswidth dev_width; - u32 burst; struct scatterlist *sg; int i; int acnt, bcnt, ccnt, src, dst, cidx; @@ -229,20 +243,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( if (unlikely(!echan || !sgl || !sg_len)) return NULL; - if (direction == DMA_DEV_TO_MEM) { - dev_addr = echan->cfg.src_addr; - dev_width = echan->cfg.src_addr_width; - burst = echan->cfg.src_maxburst; - } else if (direction == DMA_MEM_TO_DEV) { - dev_addr = echan->cfg.dst_addr; - dev_width = echan->cfg.dst_addr_width; - burst = echan->cfg.dst_maxburst; - } else { - dev_err(dev, "%s: bad direction?\n", __func__); - return NULL; - } - - if (dev_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) { + if (echan->addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) { dev_err(dev, "Undefined slave buswidth\n"); return NULL; } @@ -274,14 +275,14 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( } } - acnt = dev_width; + acnt = echan->addr_width; /* * If the maxburst is equal to the fifo width, use * A-synced transfers. This allows for large contiguous * buffer transfers using only one PaRAM set. */ - if (burst == 1) { + if (echan->maxburst == 1) { edesc->absync = false; ccnt = sg_dma_len(sg) / acnt / (SZ_64K - 1); bcnt = sg_dma_len(sg) / acnt - ccnt * (SZ_64K - 1); @@ -301,7 +302,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( */ } else { edesc->absync = true; - bcnt = burst; + bcnt = echan->maxburst; ccnt = sg_dma_len(sg) / (acnt * bcnt); if (ccnt > (SZ_64K - 1)) { dev_err(dev, "Exceeded max SG segment size\n"); @@ -312,13 +313,13 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( if (direction == DMA_MEM_TO_DEV) { src = sg_dma_address(sg); - dst = dev_addr; + dst = echan->addr; src_bidx = acnt; src_cidx = cidx; dst_bidx = 0; dst_cidx = 0; } else { - src = dev_addr; + src = echan->addr; dst = sg_dma_address(sg); src_bidx = 0; src_cidx = 0; diff --git a/trunk/drivers/dma/ep93xx_dma.c b/trunk/drivers/dma/ep93xx_dma.c index f2bf8c0c4675..bcfde400904f 100644 --- a/trunk/drivers/dma/ep93xx_dma.c +++ b/trunk/drivers/dma/ep93xx_dma.c @@ -903,7 +903,8 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan) switch (data->port) { case EP93XX_DMA_SSP: case EP93XX_DMA_IDE: - if (!is_slave_direction(data->direction)) + if (data->direction != DMA_MEM_TO_DEV && + data->direction != DMA_DEV_TO_MEM) return -EINVAL; break; default: diff --git a/trunk/drivers/dma/ioat/dma.c b/trunk/drivers/dma/ioat/dma.c index 464138a8a782..73b2b65cb1de 100644 --- a/trunk/drivers/dma/ioat/dma.c +++ b/trunk/drivers/dma/ioat/dma.c @@ -833,14 +833,14 @@ int __devinit ioat_dma_self_test(struct ioatdma_device *device) dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE); dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE); - flags = DMA_COMPL_SKIP_SRC_UNMAP | DMA_COMPL_SKIP_DEST_UNMAP | + flags = DMA_COMPL_SRC_UNMAP_SINGLE | DMA_COMPL_DEST_UNMAP_SINGLE | DMA_PREP_INTERRUPT; tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src, IOAT_TEST_SIZE, flags); if (!tx) { dev_err(dev, "Self-test prep failed, disabling\n"); err = -ENODEV; - goto unmap_dma; + goto free_resources; } async_tx_ack(tx); @@ -851,7 +851,7 @@ int __devinit ioat_dma_self_test(struct ioatdma_device *device) if (cookie < 0) { dev_err(dev, "Self-test setup failed, disabling\n"); err = -ENODEV; - goto unmap_dma; + goto free_resources; } dma->device_issue_pending(dma_chan); @@ -862,7 +862,7 @@ int __devinit ioat_dma_self_test(struct ioatdma_device *device) != DMA_SUCCESS) { dev_err(dev, "Self-test copy timed out, disabling\n"); err = -ENODEV; - goto unmap_dma; + goto free_resources; } if (memcmp(src, dest, IOAT_TEST_SIZE)) { dev_err(dev, "Self-test copy failed compare, disabling\n"); @@ -870,9 +870,6 @@ int __devinit ioat_dma_self_test(struct ioatdma_device *device) goto free_resources; } -unmap_dma: - dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE); - dma_unmap_single(dev, dma_dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE); free_resources: dma->device_free_chan_resources(dma_chan); out: diff --git a/trunk/drivers/dma/ioat/dma_v3.c b/trunk/drivers/dma/ioat/dma_v3.c index e52cf1eb6839..f7f1dc62c15c 100644 --- a/trunk/drivers/dma/ioat/dma_v3.c +++ b/trunk/drivers/dma/ioat/dma_v3.c @@ -863,7 +863,6 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) unsigned long tmo; struct device *dev = &device->pdev->dev; struct dma_device *dma = &device->common; - u8 op = 0; dev_dbg(dev, "%s\n", __func__); @@ -909,22 +908,18 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) } /* test xor */ - op = IOAT_OP_XOR; - dest_dma = dma_map_page(dev, dest, 0, PAGE_SIZE, DMA_FROM_DEVICE); for (i = 0; i < IOAT_NUM_SRC_TEST; i++) dma_srcs[i] = dma_map_page(dev, xor_srcs[i], 0, PAGE_SIZE, DMA_TO_DEVICE); tx = dma->device_prep_dma_xor(dma_chan, dest_dma, dma_srcs, IOAT_NUM_SRC_TEST, PAGE_SIZE, - DMA_PREP_INTERRUPT | - DMA_COMPL_SKIP_SRC_UNMAP | - DMA_COMPL_SKIP_DEST_UNMAP); + DMA_PREP_INTERRUPT); if (!tx) { dev_err(dev, "Self-test xor prep failed\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } async_tx_ack(tx); @@ -935,7 +930,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (cookie < 0) { dev_err(dev, "Self-test xor setup failed\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } dma->device_issue_pending(dma_chan); @@ -944,13 +939,9 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { dev_err(dev, "Self-test xor timed out\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } - dma_unmap_page(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); - for (i = 0; i < IOAT_NUM_SRC_TEST; i++) - dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, DMA_TO_DEVICE); - dma_sync_single_for_cpu(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) { u32 *ptr = page_address(dest); @@ -966,8 +957,6 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) goto free_resources; - op = IOAT_OP_XOR_VAL; - /* validate the sources with the destintation page */ for (i = 0; i < IOAT_NUM_SRC_TEST; i++) xor_val_srcs[i] = xor_srcs[i]; @@ -980,13 +969,11 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) DMA_TO_DEVICE); tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs, IOAT_NUM_SRC_TEST + 1, PAGE_SIZE, - &xor_val_result, DMA_PREP_INTERRUPT | - DMA_COMPL_SKIP_SRC_UNMAP | - DMA_COMPL_SKIP_DEST_UNMAP); + &xor_val_result, DMA_PREP_INTERRUPT); if (!tx) { dev_err(dev, "Self-test zero prep failed\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } async_tx_ack(tx); @@ -997,7 +984,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (cookie < 0) { dev_err(dev, "Self-test zero setup failed\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } dma->device_issue_pending(dma_chan); @@ -1006,12 +993,9 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { dev_err(dev, "Self-test validate timed out\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } - for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) - dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, DMA_TO_DEVICE); - if (xor_val_result != 0) { dev_err(dev, "Self-test validate failed compare\n"); err = -ENODEV; @@ -1023,18 +1007,14 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) goto free_resources; /* test memset */ - op = IOAT_OP_FILL; - dma_addr = dma_map_page(dev, dest, 0, PAGE_SIZE, DMA_FROM_DEVICE); tx = dma->device_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE, - DMA_PREP_INTERRUPT | - DMA_COMPL_SKIP_SRC_UNMAP | - DMA_COMPL_SKIP_DEST_UNMAP); + DMA_PREP_INTERRUPT); if (!tx) { dev_err(dev, "Self-test memset prep failed\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } async_tx_ack(tx); @@ -1045,7 +1025,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (cookie < 0) { dev_err(dev, "Self-test memset setup failed\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } dma->device_issue_pending(dma_chan); @@ -1054,11 +1034,9 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { dev_err(dev, "Self-test memset timed out\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } - dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE); - for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) { u32 *ptr = page_address(dest); if (ptr[i]) { @@ -1069,21 +1047,17 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) } /* test for non-zero parity sum */ - op = IOAT_OP_XOR_VAL; - xor_val_result = 0; for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) dma_srcs[i] = dma_map_page(dev, xor_val_srcs[i], 0, PAGE_SIZE, DMA_TO_DEVICE); tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs, IOAT_NUM_SRC_TEST + 1, PAGE_SIZE, - &xor_val_result, DMA_PREP_INTERRUPT | - DMA_COMPL_SKIP_SRC_UNMAP | - DMA_COMPL_SKIP_DEST_UNMAP); + &xor_val_result, DMA_PREP_INTERRUPT); if (!tx) { dev_err(dev, "Self-test 2nd zero prep failed\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } async_tx_ack(tx); @@ -1094,7 +1068,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (cookie < 0) { dev_err(dev, "Self-test 2nd zero setup failed\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } dma->device_issue_pending(dma_chan); @@ -1103,31 +1077,15 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { dev_err(dev, "Self-test 2nd validate timed out\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } if (xor_val_result != SUM_CHECK_P_RESULT) { dev_err(dev, "Self-test validate failed compare\n"); err = -ENODEV; - goto dma_unmap; + goto free_resources; } - for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) - dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, DMA_TO_DEVICE); - - goto free_resources; -dma_unmap: - if (op == IOAT_OP_XOR) { - dma_unmap_page(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); - for (i = 0; i < IOAT_NUM_SRC_TEST; i++) - dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, - DMA_TO_DEVICE); - } else if (op == IOAT_OP_XOR_VAL) { - for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) - dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, - DMA_TO_DEVICE); - } else if (op == IOAT_OP_FILL) - dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE); free_resources: dma->device_free_chan_resources(dma_chan); out: @@ -1168,7 +1126,12 @@ static int ioat3_reset_hw(struct ioat_chan_common *chan) chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); - /* clear any pending errors */ + /* -= IOAT ver.3 workarounds =- */ + /* Write CHANERRMSK_INT with 3E07h to mask out the errors + * that can cause stability issues for IOAT ver.3, and clear any + * pending errors + */ + pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07); err = pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr); if (err) { dev_err(&pdev->dev, "channel error register unreachable\n"); @@ -1224,26 +1187,6 @@ static bool is_snb_ioat(struct pci_dev *pdev) } } -static bool is_ivb_ioat(struct pci_dev *pdev) -{ - switch (pdev->device) { - case PCI_DEVICE_ID_INTEL_IOAT_IVB0: - case PCI_DEVICE_ID_INTEL_IOAT_IVB1: - case PCI_DEVICE_ID_INTEL_IOAT_IVB2: - case PCI_DEVICE_ID_INTEL_IOAT_IVB3: - case PCI_DEVICE_ID_INTEL_IOAT_IVB4: - case PCI_DEVICE_ID_INTEL_IOAT_IVB5: - case PCI_DEVICE_ID_INTEL_IOAT_IVB6: - case PCI_DEVICE_ID_INTEL_IOAT_IVB7: - case PCI_DEVICE_ID_INTEL_IOAT_IVB8: - case PCI_DEVICE_ID_INTEL_IOAT_IVB9: - return true; - default: - return false; - } - -} - int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) { struct pci_dev *pdev = device->pdev; @@ -1264,7 +1207,7 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) dma->device_alloc_chan_resources = ioat2_alloc_chan_resources; dma->device_free_chan_resources = ioat2_free_chan_resources; - if (is_jf_ioat(pdev) || is_snb_ioat(pdev) || is_ivb_ioat(pdev)) + if (is_jf_ioat(pdev) || is_snb_ioat(pdev)) dma->copy_align = 6; dma_cap_set(DMA_INTERRUPT, dma->cap_mask); diff --git a/trunk/drivers/dma/ioat/hw.h b/trunk/drivers/dma/ioat/hw.h index 7cb74c62c719..d2ff3fda0b18 100644 --- a/trunk/drivers/dma/ioat/hw.h +++ b/trunk/drivers/dma/ioat/hw.h @@ -35,17 +35,6 @@ #define IOAT_VER_3_0 0x30 /* Version 3.0 */ #define IOAT_VER_3_2 0x32 /* Version 3.2 */ -#define PCI_DEVICE_ID_INTEL_IOAT_IVB0 0x0e20 -#define PCI_DEVICE_ID_INTEL_IOAT_IVB1 0x0e21 -#define PCI_DEVICE_ID_INTEL_IOAT_IVB2 0x0e22 -#define PCI_DEVICE_ID_INTEL_IOAT_IVB3 0x0e23 -#define PCI_DEVICE_ID_INTEL_IOAT_IVB4 0x0e24 -#define PCI_DEVICE_ID_INTEL_IOAT_IVB5 0x0e25 -#define PCI_DEVICE_ID_INTEL_IOAT_IVB6 0x0e26 -#define PCI_DEVICE_ID_INTEL_IOAT_IVB7 0x0e27 -#define PCI_DEVICE_ID_INTEL_IOAT_IVB8 0x0e2e -#define PCI_DEVICE_ID_INTEL_IOAT_IVB9 0x0e2f - int system_has_dca_enabled(struct pci_dev *pdev); struct ioat_dma_descriptor { diff --git a/trunk/drivers/dma/ioat/pci.c b/trunk/drivers/dma/ioat/pci.c index f4e6163a1e73..bfa9a3536e09 100644 --- a/trunk/drivers/dma/ioat/pci.c +++ b/trunk/drivers/dma/ioat/pci.c @@ -40,6 +40,17 @@ MODULE_VERSION(IOAT_DMA_VERSION); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Intel Corporation"); +#define PCI_DEVICE_ID_INTEL_IOAT_IVB0 0x0e20 +#define PCI_DEVICE_ID_INTEL_IOAT_IVB1 0x0e21 +#define PCI_DEVICE_ID_INTEL_IOAT_IVB2 0x0e22 +#define PCI_DEVICE_ID_INTEL_IOAT_IVB3 0x0e23 +#define PCI_DEVICE_ID_INTEL_IOAT_IVB4 0x0e24 +#define PCI_DEVICE_ID_INTEL_IOAT_IVB5 0x0e25 +#define PCI_DEVICE_ID_INTEL_IOAT_IVB6 0x0e26 +#define PCI_DEVICE_ID_INTEL_IOAT_IVB7 0x0e27 +#define PCI_DEVICE_ID_INTEL_IOAT_IVB8 0x0e2e +#define PCI_DEVICE_ID_INTEL_IOAT_IVB9 0x0e2f + static struct pci_device_id ioat_pci_tbl[] = { /* I/OAT v1 platforms */ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT) }, diff --git a/trunk/drivers/dma/iop-adma.c b/trunk/drivers/dma/iop-adma.c index 62a59fd65723..9072e173b860 100644 --- a/trunk/drivers/dma/iop-adma.c +++ b/trunk/drivers/dma/iop-adma.c @@ -936,7 +936,7 @@ static irqreturn_t iop_adma_err_handler(int irq, void *data) struct iop_adma_chan *chan = data; unsigned long status = iop_chan_get_status(chan); - dev_err(chan->device->common.dev, + dev_printk(KERN_ERR, chan->device->common.dev, "error ( %s%s%s%s%s%s%s)\n", iop_is_err_int_parity(status, chan) ? "int_parity " : "", iop_is_err_mcu_abort(status, chan) ? "mcu_abort " : "", @@ -1017,7 +1017,7 @@ static int iop_adma_memcpy_self_test(struct iop_adma_device *device) if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test copy timed out, disabling\n"); err = -ENODEV; goto free_resources; @@ -1027,7 +1027,7 @@ static int iop_adma_memcpy_self_test(struct iop_adma_device *device) dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma, IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE); if (memcmp(src, dest, IOP_ADMA_TEST_SIZE)) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test copy failed compare, disabling\n"); err = -ENODEV; goto free_resources; @@ -1117,7 +1117,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device) if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test xor timed out, disabling\n"); err = -ENODEV; goto free_resources; @@ -1129,7 +1129,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device) for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) { u32 *ptr = page_address(dest); if (ptr[i] != cmp_word) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test xor failed compare, disabling\n"); err = -ENODEV; goto free_resources; @@ -1163,14 +1163,14 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device) msleep(8); if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test zero sum timed out, disabling\n"); err = -ENODEV; goto free_resources; } if (zero_sum_result != 0) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test zero sum failed compare, disabling\n"); err = -ENODEV; goto free_resources; @@ -1187,7 +1187,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device) msleep(8); if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test memset timed out, disabling\n"); err = -ENODEV; goto free_resources; @@ -1196,7 +1196,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device) for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) { u32 *ptr = page_address(dest); if (ptr[i]) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test memset failed compare, disabling\n"); err = -ENODEV; goto free_resources; @@ -1219,14 +1219,14 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device) msleep(8); if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test non-zero sum timed out, disabling\n"); err = -ENODEV; goto free_resources; } if (zero_sum_result != 1) { - dev_err(dma_chan->device->dev, + dev_printk(KERN_ERR, dma_chan->device->dev, "Self-test non-zero sum failed compare, disabling\n"); err = -ENODEV; goto free_resources; @@ -1579,14 +1579,15 @@ static int iop_adma_probe(struct platform_device *pdev) goto err_free_iop_chan; } - dev_info(&pdev->dev, "Intel(R) IOP: ( %s%s%s%s%s%s%s)\n", - dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "pq " : "", - dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask) ? "pq_val " : "", - dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "", - dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask) ? "xor_val " : "", - dma_has_cap(DMA_MEMSET, dma_dev->cap_mask) ? "fill " : "", - dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "", - dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : ""); + dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: " + "( %s%s%s%s%s%s%s)\n", + dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "pq " : "", + dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask) ? "pq_val " : "", + dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "", + dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask) ? "xor_val " : "", + dma_has_cap(DMA_MEMSET, dma_dev->cap_mask) ? "fill " : "", + dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "", + dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : ""); dma_async_device_register(dma_dev); goto out; @@ -1650,8 +1651,8 @@ static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan) /* run the descriptor */ iop_chan_enable(iop_chan); } else - dev_err(iop_chan->device->common.dev, - "failed to allocate null descriptor\n"); + dev_printk(KERN_ERR, iop_chan->device->common.dev, + "failed to allocate null descriptor\n"); spin_unlock_bh(&iop_chan->lock); } @@ -1703,7 +1704,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan) /* run the descriptor */ iop_chan_enable(iop_chan); } else - dev_err(iop_chan->device->common.dev, + dev_printk(KERN_ERR, iop_chan->device->common.dev, "failed to allocate null descriptor\n"); spin_unlock_bh(&iop_chan->lock); } diff --git a/trunk/drivers/dma/ipu/ipu_idmac.c b/trunk/drivers/dma/ipu/ipu_idmac.c index 8c61d17a86bf..65855373cee6 100644 --- a/trunk/drivers/dma/ipu/ipu_idmac.c +++ b/trunk/drivers/dma/ipu/ipu_idmac.c @@ -1347,7 +1347,7 @@ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan chan->chan_id != IDMAC_IC_7) return NULL; - if (!is_slave_direction(direction)) { + if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) { dev_err(chan->device->dev, "Invalid DMA direction %d!\n", direction); return NULL; } diff --git a/trunk/drivers/dma/ipu/ipu_irq.c b/trunk/drivers/dma/ipu/ipu_irq.c index 2e284a4438bc..a5ee37d5320f 100644 --- a/trunk/drivers/dma/ipu/ipu_irq.c +++ b/trunk/drivers/dma/ipu/ipu_irq.c @@ -44,6 +44,7 @@ static void ipu_write_reg(struct ipu *ipu, u32 value, unsigned long reg) struct ipu_irq_bank { unsigned int control; unsigned int status; + spinlock_t lock; struct ipu *ipu; }; diff --git a/trunk/drivers/dma/mmp_pdma.c b/trunk/drivers/dma/mmp_pdma.c index 41ad6a62f838..13bdf4a7e1ec 100644 --- a/trunk/drivers/dma/mmp_pdma.c +++ b/trunk/drivers/dma/mmp_pdma.c @@ -617,8 +617,10 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, else if (maxburst == 32) chan->dcmd |= DCMD_BURST32; - chan->dir = cfg->direction; - chan->drcmr = cfg->slave_id; + if (cfg) { + chan->dir = cfg->direction; + chan->drcmr = cfg->slave_id; + } chan->dev_addr = addr; break; default: diff --git a/trunk/drivers/dma/mv_xor.c b/trunk/drivers/dma/mv_xor.c index e26de4f680e1..ac71f555dd72 100644 --- a/trunk/drivers/dma/mv_xor.c +++ b/trunk/drivers/dma/mv_xor.c @@ -210,7 +210,7 @@ static void mv_set_mode(struct mv_xor_chan *chan, break; default: dev_err(mv_chan_to_devp(chan), - "error: unsupported operation %d\n", + "error: unsupported operation %d.\n", type); BUG(); return; @@ -828,22 +828,28 @@ static void mv_dump_xor_regs(struct mv_xor_chan *chan) u32 val; val = __raw_readl(XOR_CONFIG(chan)); - dev_err(mv_chan_to_devp(chan), "config 0x%08x\n", val); + dev_err(mv_chan_to_devp(chan), + "config 0x%08x.\n", val); val = __raw_readl(XOR_ACTIVATION(chan)); - dev_err(mv_chan_to_devp(chan), "activation 0x%08x\n", val); + dev_err(mv_chan_to_devp(chan), + "activation 0x%08x.\n", val); val = __raw_readl(XOR_INTR_CAUSE(chan)); - dev_err(mv_chan_to_devp(chan), "intr cause 0x%08x\n", val); + dev_err(mv_chan_to_devp(chan), + "intr cause 0x%08x.\n", val); val = __raw_readl(XOR_INTR_MASK(chan)); - dev_err(mv_chan_to_devp(chan), "intr mask 0x%08x\n", val); + dev_err(mv_chan_to_devp(chan), + "intr mask 0x%08x.\n", val); val = __raw_readl(XOR_ERROR_CAUSE(chan)); - dev_err(mv_chan_to_devp(chan), "error cause 0x%08x\n", val); + dev_err(mv_chan_to_devp(chan), + "error cause 0x%08x.\n", val); val = __raw_readl(XOR_ERROR_ADDR(chan)); - dev_err(mv_chan_to_devp(chan), "error addr 0x%08x\n", val); + dev_err(mv_chan_to_devp(chan), + "error addr 0x%08x.\n", val); } static void mv_xor_err_interrupt_handler(struct mv_xor_chan *chan, @@ -856,7 +862,7 @@ static void mv_xor_err_interrupt_handler(struct mv_xor_chan *chan, } dev_err(mv_chan_to_devp(chan), - "error on chan %d. intr cause 0x%08x\n", + "error on chan %d. intr cause 0x%08x.\n", chan->idx, intr_cause); mv_dump_xor_regs(chan); @@ -1046,8 +1052,9 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan) u32 *ptr = page_address(dest); if (ptr[i] != cmp_word) { dev_err(dma_chan->device->dev, - "Self-test xor failed compare, disabling. index %d, data %x, expected %x\n", - i, ptr[i], cmp_word); + "Self-test xor failed compare, disabling." + " index %d, data %x, expected %x\n", i, + ptr[i], cmp_word); err = -ENODEV; goto free_resources; } @@ -1187,11 +1194,12 @@ mv_xor_channel_add(struct mv_xor_device *xordev, goto err_free_irq; } - dev_info(&pdev->dev, "Marvell XOR: ( %s%s%s%s)\n", - dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "", - dma_has_cap(DMA_MEMSET, dma_dev->cap_mask) ? "fill " : "", - dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "", - dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : ""); + dev_info(&pdev->dev, "Marvell XOR: " + "( %s%s%s%s)\n", + dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "", + dma_has_cap(DMA_MEMSET, dma_dev->cap_mask) ? "fill " : "", + dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "", + dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : ""); dma_async_device_register(dma_dev); return mv_chan; @@ -1245,7 +1253,7 @@ static int mv_xor_probe(struct platform_device *pdev) struct resource *res; int i, ret; - dev_notice(&pdev->dev, "Marvell shared XOR driver\n"); + dev_notice(&pdev->dev, "Marvell XOR driver\n"); xordev = devm_kzalloc(&pdev->dev, sizeof(*xordev), GFP_KERNEL); if (!xordev) diff --git a/trunk/drivers/dma/mxs-dma.c b/trunk/drivers/dma/mxs-dma.c index 8f6d30d37c45..9f02e794b12b 100644 --- a/trunk/drivers/dma/mxs-dma.c +++ b/trunk/drivers/dma/mxs-dma.c @@ -109,7 +109,7 @@ struct mxs_dma_chan { struct dma_chan chan; struct dma_async_tx_descriptor desc; struct tasklet_struct tasklet; - unsigned int chan_irq; + int chan_irq; struct mxs_dma_ccw *ccw; dma_addr_t ccw_phys; int desc_count; @@ -441,7 +441,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; struct mxs_dma_ccw *ccw; struct scatterlist *sg; - u32 i, j; + int i, j; u32 *pio; bool append = flags & DMA_PREP_INTERRUPT; int idx = append ? mxs_chan->desc_count : 0; @@ -537,8 +537,8 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( { struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; - u32 num_periods = buf_len / period_len; - u32 i = 0, buf = 0; + int num_periods = buf_len / period_len; + int i = 0, buf = 0; if (mxs_chan->status == DMA_IN_PROGRESS) return NULL; diff --git a/trunk/drivers/dma/pch_dma.c b/trunk/drivers/dma/pch_dma.c index aed6e0c117ed..eca1c4ddf039 100644 --- a/trunk/drivers/dma/pch_dma.c +++ b/trunk/drivers/dma/pch_dma.c @@ -1029,7 +1029,18 @@ static struct pci_driver pch_dma_driver = { #endif }; -module_pci_driver(pch_dma_driver); +static int __init pch_dma_init(void) +{ + return pci_register_driver(&pch_dma_driver); +} + +static void __exit pch_dma_exit(void) +{ + pci_unregister_driver(&pch_dma_driver); +} + +module_init(pch_dma_init); +module_exit(pch_dma_exit); MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semicon ML7213/ML7223/ML7831 IOH " "DMA controller driver"); diff --git a/trunk/drivers/dma/pl330.c b/trunk/drivers/dma/pl330.c index f7edb6f0ee87..95555f37ea6d 100644 --- a/trunk/drivers/dma/pl330.c +++ b/trunk/drivers/dma/pl330.c @@ -2866,7 +2866,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pdat = adev->dev.platform_data; /* Allocate a new DMAC and its Channels */ - pdmac = devm_kzalloc(&adev->dev, sizeof(*pdmac), GFP_KERNEL); + pdmac = kzalloc(sizeof(*pdmac), GFP_KERNEL); if (!pdmac) { dev_err(&adev->dev, "unable to allocate mem\n"); return -ENOMEM; @@ -2878,9 +2878,13 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pi->mcbufsz = pdat ? pdat->mcbuf_sz : 0; res = &adev->res; - pi->base = devm_request_and_ioremap(&adev->dev, res); - if (!pi->base) - return -ENXIO; + request_mem_region(res->start, resource_size(res), "dma-pl330"); + + pi->base = ioremap(res->start, resource_size(res)); + if (!pi->base) { + ret = -ENXIO; + goto probe_err1; + } amba_set_drvdata(adev, pdmac); @@ -2888,11 +2892,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) ret = request_irq(irq, pl330_irq_handler, 0, dev_name(&adev->dev), pi); if (ret) - return ret; + goto probe_err2; ret = pl330_add(pi); if (ret) - goto probe_err1; + goto probe_err3; INIT_LIST_HEAD(&pdmac->desc_pool); spin_lock_init(&pdmac->pool_lock); @@ -2914,7 +2918,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) if (!pdmac->peripherals) { ret = -ENOMEM; dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n"); - goto probe_err2; + goto probe_err4; } for (i = 0; i < num_chan; i++) { @@ -2958,7 +2962,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) ret = dma_async_device_register(pd); if (ret) { dev_err(&adev->dev, "unable to register DMAC\n"); - goto probe_err2; + goto probe_err4; } dev_info(&adev->dev, @@ -2971,10 +2975,15 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) return 0; -probe_err2: +probe_err4: pl330_del(pi); -probe_err1: +probe_err3: free_irq(irq, pi); +probe_err2: + iounmap(pi->base); +probe_err1: + release_mem_region(res->start, resource_size(res)); + kfree(pdmac); return ret; } @@ -2984,6 +2993,7 @@ static int __devexit pl330_remove(struct amba_device *adev) struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev); struct dma_pl330_chan *pch, *_p; struct pl330_info *pi; + struct resource *res; int irq; if (!pdmac) @@ -3010,6 +3020,13 @@ static int __devexit pl330_remove(struct amba_device *adev) irq = adev->irq[0]; free_irq(irq, pi); + iounmap(pi->base); + + res = &adev->res; + release_mem_region(res->start, resource_size(res)); + + kfree(pdmac); + return 0; } diff --git a/trunk/drivers/dma/sh/shdma-base.c b/trunk/drivers/dma/sh/shdma-base.c index 4acb85a10250..f4cd946d259d 100644 --- a/trunk/drivers/dma/sh/shdma-base.c +++ b/trunk/drivers/dma/sh/shdma-base.c @@ -638,6 +638,9 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long flags; int ret; + if (!chan) + return -EINVAL; + switch (cmd) { case DMA_TERMINATE_ALL: spin_lock_irqsave(&schan->chan_lock, flags); diff --git a/trunk/drivers/dma/sh/shdma.c b/trunk/drivers/dma/sh/shdma.c index 62eff4800521..8201bb4e0cd7 100644 --- a/trunk/drivers/dma/sh/shdma.c +++ b/trunk/drivers/dma/sh/shdma.c @@ -326,7 +326,7 @@ static int sh_dmae_set_slave(struct shdma_chan *schan, shdma_chan); const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave_id); if (!cfg) - return -ENXIO; + return -ENODEV; if (!try) sh_chan->config = cfg; diff --git a/trunk/drivers/dma/sirf-dma.c b/trunk/drivers/dma/sirf-dma.c index 3c210ba9f938..c3de6edb9651 100644 --- a/trunk/drivers/dma/sirf-dma.c +++ b/trunk/drivers/dma/sirf-dma.c @@ -32,9 +32,7 @@ #define SIRFSOC_DMA_CH_VALID 0x140 #define SIRFSOC_DMA_CH_INT 0x144 #define SIRFSOC_DMA_INT_EN 0x148 -#define SIRFSOC_DMA_INT_EN_CLR 0x14C #define SIRFSOC_DMA_CH_LOOP_CTRL 0x150 -#define SIRFSOC_DMA_CH_LOOP_CTRL_CLR 0x15C #define SIRFSOC_DMA_MODE_CTRL_BIT 4 #define SIRFSOC_DMA_DIR_CTRL_BIT 5 @@ -78,7 +76,6 @@ struct sirfsoc_dma { struct sirfsoc_dma_chan channels[SIRFSOC_DMA_CHANNELS]; void __iomem *base; int irq; - bool is_marco; }; #define DRV_NAME "sirfsoc_dma" @@ -291,20 +288,14 @@ static int sirfsoc_dma_terminate_all(struct sirfsoc_dma_chan *schan) int cid = schan->chan.chan_id; unsigned long flags; - if (!sdma->is_marco) { - writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) & - ~(1 << cid), sdma->base + SIRFSOC_DMA_INT_EN); - writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL) - & ~((1 << cid) | 1 << (cid + 16)), - sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL); - } else { - writel_relaxed(1 << cid, sdma->base + SIRFSOC_DMA_INT_EN_CLR); - writel_relaxed((1 << cid) | 1 << (cid + 16), - sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL_CLR); - } - + writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) & + ~(1 << cid), sdma->base + SIRFSOC_DMA_INT_EN); writel_relaxed(1 << cid, sdma->base + SIRFSOC_DMA_CH_VALID); + writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL) + & ~((1 << cid) | 1 << (cid + 16)), + sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL); + spin_lock_irqsave(&schan->lock, flags); list_splice_tail_init(&schan->active, &schan->free); list_splice_tail_init(&schan->queued, &schan->free); @@ -577,9 +568,6 @@ static int sirfsoc_dma_probe(struct platform_device *op) return -ENOMEM; } - if (of_device_is_compatible(dn, "sirf,marco-dmac")) - sdma->is_marco = true; - if (of_property_read_u32(dn, "cell-index", &id)) { dev_err(dev, "Fail to get DMAC index\n"); return -ENODEV; @@ -680,7 +668,6 @@ static int __devexit sirfsoc_dma_remove(struct platform_device *op) static struct of_device_id sirfsoc_dma_match[] = { { .compatible = "sirf,prima2-dmac", }, - { .compatible = "sirf,marco-dmac", }, {}, }; diff --git a/trunk/drivers/dma/ste_dma40.c b/trunk/drivers/dma/ste_dma40.c index e5e60bb68d9d..23c5573e62dd 100644 --- a/trunk/drivers/dma/ste_dma40.c +++ b/trunk/drivers/dma/ste_dma40.c @@ -2337,7 +2337,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, unsigned long dma_flags, void *context) { - if (!is_slave_direction(direction)) + if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) return NULL; return d40_prep_sg(chan, sgl, sgl, sg_len, direction, dma_flags); diff --git a/trunk/drivers/dma/ste_dma40_ll.c b/trunk/drivers/dma/ste_dma40_ll.c index 851ad56e8409..d64b72ae2dc8 100644 --- a/trunk/drivers/dma/ste_dma40_ll.c +++ b/trunk/drivers/dma/ste_dma40_ll.c @@ -102,17 +102,18 @@ void d40_phy_cfg(struct stedma40_chan_cfg *cfg, src |= cfg->src_info.data_width << D40_SREG_CFG_ESIZE_POS; dst |= cfg->dst_info.data_width << D40_SREG_CFG_ESIZE_POS; + /* Set the priority bit to high for the physical channel */ + if (cfg->high_priority) { + src |= 1 << D40_SREG_CFG_PRI_POS; + dst |= 1 << D40_SREG_CFG_PRI_POS; + } + } else { /* Logical channel */ dst |= 1 << D40_SREG_CFG_LOG_GIM_POS; src |= 1 << D40_SREG_CFG_LOG_GIM_POS; } - if (cfg->high_priority) { - src |= 1 << D40_SREG_CFG_PRI_POS; - dst |= 1 << D40_SREG_CFG_PRI_POS; - } - if (cfg->src_info.big_endian) src |= 1 << D40_SREG_CFG_LBE_POS; if (cfg->dst_info.big_endian) diff --git a/trunk/drivers/dma/tegra20-apb-dma.c b/trunk/drivers/dma/tegra20-apb-dma.c index 6c144814a896..efdfffa13349 100644 --- a/trunk/drivers/dma/tegra20-apb-dma.c +++ b/trunk/drivers/dma/tegra20-apb-dma.c @@ -62,9 +62,6 @@ #define TEGRA_APBDMA_STATUS_COUNT_SHIFT 2 #define TEGRA_APBDMA_STATUS_COUNT_MASK 0xFFFC -#define TEGRA_APBDMA_CHAN_CSRE 0x00C -#define TEGRA_APBDMA_CHAN_CSRE_PAUSE (1 << 31) - /* AHB memory address */ #define TEGRA_APBDMA_CHAN_AHBPTR 0x010 @@ -115,12 +112,10 @@ struct tegra_dma; * tegra_dma_chip_data Tegra chip specific DMA data * @nr_channels: Number of channels available in the controller. * @max_dma_count: Maximum DMA transfer count supported by DMA controller. - * @support_channel_pause: Support channel wise pause of dma. */ struct tegra_dma_chip_data { int nr_channels; int max_dma_count; - bool support_channel_pause; }; /* DMA channel registers */ @@ -358,32 +353,6 @@ static void tegra_dma_global_resume(struct tegra_dma_channel *tdc) spin_unlock(&tdma->global_lock); } -static void tegra_dma_pause(struct tegra_dma_channel *tdc, - bool wait_for_burst_complete) -{ - struct tegra_dma *tdma = tdc->tdma; - - if (tdma->chip_data->support_channel_pause) { - tdc_write(tdc, TEGRA_APBDMA_CHAN_CSRE, - TEGRA_APBDMA_CHAN_CSRE_PAUSE); - if (wait_for_burst_complete) - udelay(TEGRA_APBDMA_BURST_COMPLETE_TIME); - } else { - tegra_dma_global_pause(tdc, wait_for_burst_complete); - } -} - -static void tegra_dma_resume(struct tegra_dma_channel *tdc) -{ - struct tegra_dma *tdma = tdc->tdma; - - if (tdma->chip_data->support_channel_pause) { - tdc_write(tdc, TEGRA_APBDMA_CHAN_CSRE, 0); - } else { - tegra_dma_global_resume(tdc); - } -} - static void tegra_dma_stop(struct tegra_dma_channel *tdc) { u32 csr; @@ -439,7 +408,7 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc, * If there is already IEC status then interrupt handler need to * load new configuration. */ - tegra_dma_pause(tdc, false); + tegra_dma_global_pause(tdc, false); status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); /* @@ -449,7 +418,7 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc, if (status & TEGRA_APBDMA_STATUS_ISE_EOC) { dev_err(tdc2dev(tdc), "Skipping new configuration as interrupt is pending\n"); - tegra_dma_resume(tdc); + tegra_dma_global_resume(tdc); return; } @@ -460,7 +429,7 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc, nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB); nsg_req->configured = true; - tegra_dma_resume(tdc); + tegra_dma_global_resume(tdc); } static void tdc_start_head_req(struct tegra_dma_channel *tdc) @@ -721,7 +690,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc) goto skip_dma_stop; /* Pause DMA before checking the queue status */ - tegra_dma_pause(tdc, true); + tegra_dma_global_pause(tdc, true); status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); if (status & TEGRA_APBDMA_STATUS_ISE_EOC) { @@ -739,7 +708,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc) sgreq->dma_desc->bytes_transferred += get_current_xferred_count(tdc, sgreq, status); } - tegra_dma_resume(tdc); + tegra_dma_global_resume(tdc); skip_dma_stop: tegra_dma_abort_all(tdc); @@ -1206,7 +1175,6 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) static const struct tegra_dma_chip_data tegra20_dma_chip_data = { .nr_channels = 16, .max_dma_count = 1024UL * 64, - .support_channel_pause = false, }; #if defined(CONFIG_OF) @@ -1214,22 +1182,10 @@ static const struct tegra_dma_chip_data tegra20_dma_chip_data = { static const struct tegra_dma_chip_data tegra30_dma_chip_data = { .nr_channels = 32, .max_dma_count = 1024UL * 64, - .support_channel_pause = false, }; -/* Tegra114 specific DMA controller information */ -static const struct tegra_dma_chip_data tegra114_dma_chip_data = { - .nr_channels = 32, - .max_dma_count = 1024UL * 64, - .support_channel_pause = true, -}; - - -static const struct of_device_id tegra_dma_of_match[] = { +static const struct of_device_id tegra_dma_of_match[] __devinitconst = { { - .compatible = "nvidia,tegra114-apbdma", - .data = &tegra114_dma_chip_data, - }, { .compatible = "nvidia,tegra30-apbdma", .data = &tegra30_dma_chip_data, }, { diff --git a/trunk/drivers/misc/carma/carma-fpga-program.c b/trunk/drivers/misc/carma/carma-fpga-program.c index 736c7714f565..eaddfe9db149 100644 --- a/trunk/drivers/misc/carma/carma-fpga-program.c +++ b/trunk/drivers/misc/carma/carma-fpga-program.c @@ -546,7 +546,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv) goto out_dma_unmap; } - dma_async_issue_pending(chan); + dma_async_memcpy_issue_pending(chan); /* Set the total byte count */ fpga_set_byte_count(priv->regs, priv->bytes); diff --git a/trunk/drivers/misc/carma/carma-fpga.c b/trunk/drivers/misc/carma/carma-fpga.c index 7508cafff103..8835eabb3b87 100644 --- a/trunk/drivers/misc/carma/carma-fpga.c +++ b/trunk/drivers/misc/carma/carma-fpga.c @@ -631,8 +631,6 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf) struct dma_async_tx_descriptor *tx; dma_cookie_t cookie; dma_addr_t dst, src; - unsigned long dma_flags = DMA_COMPL_SKIP_DEST_UNMAP | - DMA_COMPL_SKIP_SRC_UNMAP; dst_sg = buf->vb.sglist; dst_nents = buf->vb.sglen; @@ -668,7 +666,7 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf) src = SYS_FPGA_BLOCK; tx = chan->device->device_prep_dma_memcpy(chan, dst, src, REG_BLOCK_SIZE, - dma_flags); + 0); if (!tx) { dev_err(priv->dev, "unable to prep SYS-FPGA DMA\n"); return -ENOMEM; @@ -751,7 +749,7 @@ static irqreturn_t data_irq(int irq, void *dev_id) submitted = true; /* Start the DMA Engine */ - dma_async_issue_pending(priv->chan); + dma_async_memcpy_issue_pending(priv->chan); out: /* If no DMA was submitted, re-enable interrupts */ diff --git a/trunk/drivers/mtd/nand/fsmc_nand.c b/trunk/drivers/mtd/nand/fsmc_nand.c index a66576863e53..1d7446434b0e 100644 --- a/trunk/drivers/mtd/nand/fsmc_nand.c +++ b/trunk/drivers/mtd/nand/fsmc_nand.c @@ -573,22 +573,23 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len, dma_dev = chan->device; dma_addr = dma_map_single(dma_dev->dev, buffer, len, direction); - flags |= DMA_COMPL_SKIP_SRC_UNMAP | DMA_COMPL_SKIP_DEST_UNMAP; - if (direction == DMA_TO_DEVICE) { dma_src = dma_addr; dma_dst = host->data_pa; + flags |= DMA_COMPL_SRC_UNMAP_SINGLE | DMA_COMPL_SKIP_DEST_UNMAP; } else { dma_src = host->data_pa; dma_dst = dma_addr; + flags |= DMA_COMPL_DEST_UNMAP_SINGLE | DMA_COMPL_SKIP_SRC_UNMAP; } tx = dma_dev->device_prep_dma_memcpy(chan, dma_dst, dma_src, len, flags); + if (!tx) { dev_err(host->dev, "device_prep_dma_memcpy error\n"); - ret = -EIO; - goto unmap_dma; + dma_unmap_single(dma_dev->dev, dma_addr, len, direction); + return -EIO; } tx->callback = dma_complete; @@ -598,7 +599,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len, ret = dma_submit_error(cookie); if (ret) { dev_err(host->dev, "dma_submit_error %d\n", cookie); - goto unmap_dma; + return ret; } dma_async_issue_pending(chan); @@ -609,17 +610,10 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len, if (ret <= 0) { chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); dev_err(host->dev, "wait_for_completion_timeout\n"); - if (!ret) - ret = -ETIMEDOUT; - goto unmap_dma; + return ret ? ret : -ETIMEDOUT; } - ret = 0; - -unmap_dma: - dma_unmap_single(dma_dev->dev, dma_addr, len, direction); - - return ret; + return 0; } /* diff --git a/trunk/drivers/of/Makefile b/trunk/drivers/of/Makefile index eafa107aed40..e027f444d10c 100644 --- a/trunk/drivers/of/Makefile +++ b/trunk/drivers/of/Makefile @@ -1,4 +1,4 @@ -obj-y = base.o dma.o +obj-y = base.o obj-$(CONFIG_OF_FLATTREE) += fdt.o obj-$(CONFIG_OF_PROMTREE) += pdt.o obj-$(CONFIG_OF_ADDRESS) += address.o diff --git a/trunk/drivers/of/dma.c b/trunk/drivers/of/dma.c deleted file mode 100644 index 59631b2c4666..000000000000 --- a/trunk/drivers/of/dma.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Device tree helpers for DMA request / controller - * - * Based on of_gpio.c - * - * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -static LIST_HEAD(of_dma_list); -static DEFINE_SPINLOCK(of_dma_lock); - -/** - * of_dma_get_controller - Get a DMA controller in DT DMA helpers list - * @dma_spec: pointer to DMA specifier as found in the device tree - * - * Finds a DMA controller with matching device node and number for dma cells - * in a list of registered DMA controllers. If a match is found the use_count - * variable is increased and a valid pointer to the DMA data stored is retuned. - * A NULL pointer is returned if no match is found. - */ -static struct of_dma *of_dma_get_controller(struct of_phandle_args *dma_spec) -{ - struct of_dma *ofdma; - - spin_lock(&of_dma_lock); - - if (list_empty(&of_dma_list)) { - spin_unlock(&of_dma_lock); - return NULL; - } - - list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers) - if ((ofdma->of_node == dma_spec->np) && - (ofdma->of_dma_nbcells == dma_spec->args_count)) { - ofdma->use_count++; - spin_unlock(&of_dma_lock); - return ofdma; - } - - spin_unlock(&of_dma_lock); - - pr_debug("%s: can't find DMA controller %s\n", __func__, - dma_spec->np->full_name); - - return NULL; -} - -/** - * of_dma_put_controller - Decrement use count for a registered DMA controller - * @of_dma: pointer to DMA controller data - * - * Decrements the use_count variable in the DMA data structure. This function - * should be called only when a valid pointer is returned from - * of_dma_get_controller() and no further accesses to data referenced by that - * pointer are needed. - */ -static void of_dma_put_controller(struct of_dma *ofdma) -{ - spin_lock(&of_dma_lock); - ofdma->use_count--; - spin_unlock(&of_dma_lock); -} - -/** - * of_dma_controller_register - Register a DMA controller to DT DMA helpers - * @np: device node of DMA controller - * @of_dma_xlate: translation function which converts a phandle - * arguments list into a dma_chan structure - * @data pointer to controller specific data to be used by - * translation function - * - * Returns 0 on success or appropriate errno value on error. - * - * Allocated memory should be freed with appropriate of_dma_controller_free() - * call. - */ -int of_dma_controller_register(struct device_node *np, - struct dma_chan *(*of_dma_xlate) - (struct of_phandle_args *, struct of_dma *), - void *data) -{ - struct of_dma *ofdma; - int nbcells; - - if (!np || !of_dma_xlate) { - pr_err("%s: not enough information provided\n", __func__); - return -EINVAL; - } - - ofdma = kzalloc(sizeof(*ofdma), GFP_KERNEL); - if (!ofdma) - return -ENOMEM; - - nbcells = be32_to_cpup(of_get_property(np, "#dma-cells", NULL)); - if (!nbcells) { - pr_err("%s: #dma-cells property is missing or invalid\n", - __func__); - return -EINVAL; - } - - ofdma->of_node = np; - ofdma->of_dma_nbcells = nbcells; - ofdma->of_dma_xlate = of_dma_xlate; - ofdma->of_dma_data = data; - ofdma->use_count = 0; - - /* Now queue of_dma controller structure in list */ - list_add_tail(&ofdma->of_dma_controllers, &of_dma_list); - - return 0; -} -EXPORT_SYMBOL_GPL(of_dma_controller_register); - -/** - * of_dma_controller_free - Remove a DMA controller from DT DMA helpers list - * @np: device node of DMA controller - * - * Memory allocated by of_dma_controller_register() is freed here. - */ -int of_dma_controller_free(struct device_node *np) -{ - struct of_dma *ofdma; - - spin_lock(&of_dma_lock); - - if (list_empty(&of_dma_list)) { - spin_unlock(&of_dma_lock); - return -ENODEV; - } - - list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers) - if (ofdma->of_node == np) { - if (ofdma->use_count) { - spin_unlock(&of_dma_lock); - return -EBUSY; - } - - list_del(&ofdma->of_dma_controllers); - spin_unlock(&of_dma_lock); - kfree(ofdma); - return 0; - } - - spin_unlock(&of_dma_lock); - return -ENODEV; -} -EXPORT_SYMBOL_GPL(of_dma_controller_free); - -/** - * of_dma_match_channel - Check if a DMA specifier matches name - * @np: device node to look for DMA channels - * @name: channel name to be matched - * @index: index of DMA specifier in list of DMA specifiers - * @dma_spec: pointer to DMA specifier as found in the device tree - * - * Check if the DMA specifier pointed to by the index in a list of DMA - * specifiers, matches the name provided. Returns 0 if the name matches and - * a valid pointer to the DMA specifier is found. Otherwise returns -ENODEV. - */ -static int of_dma_match_channel(struct device_node *np, char *name, int index, - struct of_phandle_args *dma_spec) -{ - const char *s; - - if (of_property_read_string_index(np, "dma-names", index, &s)) - return -ENODEV; - - if (strcmp(name, s)) - return -ENODEV; - - if (of_parse_phandle_with_args(np, "dmas", "#dma-cells", index, - dma_spec)) - return -ENODEV; - - return 0; -} - -/** - * of_dma_request_slave_channel - Get the DMA slave channel - * @np: device node to get DMA request from - * @name: name of desired channel - * - * Returns pointer to appropriate dma channel on success or NULL on error. - */ -struct dma_chan *of_dma_request_slave_channel(struct device_node *np, - char *name) -{ - struct of_phandle_args dma_spec; - struct of_dma *ofdma; - struct dma_chan *chan; - int count, i; - - if (!np || !name) { - pr_err("%s: not enough information provided\n", __func__); - return NULL; - } - - count = of_property_count_strings(np, "dma-names"); - if (count < 0) { - pr_err("%s: dma-names property missing or empty\n", __func__); - return NULL; - } - - for (i = 0; i < count; i++) { - if (of_dma_match_channel(np, name, i, &dma_spec)) - continue; - - ofdma = of_dma_get_controller(&dma_spec); - - if (!ofdma) - continue; - - chan = ofdma->of_dma_xlate(&dma_spec, ofdma); - - of_dma_put_controller(ofdma); - - of_node_put(dma_spec.np); - - if (chan) - return chan; - } - - return NULL; -} - -/** - * of_dma_simple_xlate - Simple DMA engine translation function - * @dma_spec: pointer to DMA specifier as found in the device tree - * @of_dma: pointer to DMA controller data - * - * A simple translation function for devices that use a 32-bit value for the - * filter_param when calling the DMA engine dma_request_channel() function. - * Note that this translation function requires that #dma-cells is equal to 1 - * and the argument of the dma specifier is the 32-bit filter_param. Returns - * pointer to appropriate dma channel on success or NULL on error. - */ -struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, - struct of_dma *ofdma) -{ - int count = dma_spec->args_count; - struct of_dma_filter_info *info = ofdma->of_dma_data; - - if (!info || !info->filter_fn) - return NULL; - - if (count != 1) - return NULL; - - return dma_request_channel(info->dma_cap, info->filter_fn, - &dma_spec->args[0]); -} -EXPORT_SYMBOL_GPL(of_dma_simple_xlate); diff --git a/trunk/include/linux/dmaengine.h b/trunk/include/linux/dmaengine.h index bfcdecb5d87a..d3201e438d16 100644 --- a/trunk/include/linux/dmaengine.h +++ b/trunk/include/linux/dmaengine.h @@ -608,10 +608,7 @@ static inline int dmaengine_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) { - if (chan->device->device_control) - return chan->device->device_control(chan, cmd, arg); - else - return -ENOSYS; + return chan->device->device_control(chan, cmd, arg); } static inline int dmaengine_slave_config(struct dma_chan *chan, @@ -621,11 +618,6 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, (unsigned long)config); } -static inline bool is_slave_direction(enum dma_transfer_direction direction) -{ - return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM); -} - static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( struct dma_chan *chan, dma_addr_t buf, size_t len, enum dma_transfer_direction dir, unsigned long flags) @@ -668,13 +660,6 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( period_len, dir, flags, NULL); } -static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma( - struct dma_chan *chan, struct dma_interleaved_template *xt, - unsigned long flags) -{ - return chan->device->device_prep_interleaved_dma(chan, xt, flags); -} - static inline int dmaengine_terminate_all(struct dma_chan *chan) { return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); @@ -864,6 +849,20 @@ static inline bool async_tx_test_ack(struct dma_async_tx_descriptor *tx) return (tx->flags & DMA_CTRL_ACK) == DMA_CTRL_ACK; } +#define first_dma_cap(mask) __first_dma_cap(&(mask)) +static inline int __first_dma_cap(const dma_cap_mask_t *srcp) +{ + return min_t(int, DMA_TX_TYPE_END, + find_first_bit(srcp->bits, DMA_TX_TYPE_END)); +} + +#define next_dma_cap(n, mask) __next_dma_cap((n), &(mask)) +static inline int __next_dma_cap(int n, const dma_cap_mask_t *srcp) +{ + return min_t(int, DMA_TX_TYPE_END, + find_next_bit(srcp->bits, DMA_TX_TYPE_END, n+1)); +} + #define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask)) static inline void __dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp) @@ -892,7 +891,9 @@ __dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp) } #define for_each_dma_cap_mask(cap, mask) \ - for_each_set_bit(cap, mask.bits, DMA_TX_TYPE_END) + for ((cap) = first_dma_cap(mask); \ + (cap) < DMA_TX_TYPE_END; \ + (cap) = next_dma_cap((cap), (mask))) /** * dma_async_issue_pending - flush pending transactions to HW @@ -906,6 +907,8 @@ static inline void dma_async_issue_pending(struct dma_chan *chan) chan->device->device_issue_pending(chan); } +#define dma_async_memcpy_issue_pending(chan) dma_async_issue_pending(chan) + /** * dma_async_is_tx_complete - poll for transaction completion * @chan: DMA channel @@ -931,13 +934,16 @@ static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, return status; } +#define dma_async_memcpy_complete(chan, cookie, last, used)\ + dma_async_is_tx_complete(chan, cookie, last, used) + /** * dma_async_is_complete - test a cookie against chan state * @cookie: transaction identifier to test status of * @last_complete: last know completed transaction * @last_used: last cookie value handed out * - * dma_async_is_complete() is used in dma_async_is_tx_complete() + * dma_async_is_complete() is used in dma_async_memcpy_complete() * the test logic is separated for lightweight testing of multiple cookies */ static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie, @@ -968,7 +974,6 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); void dma_issue_pending_all(void); struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param); -struct dma_chan *dma_request_slave_channel(struct device *dev, char *name); void dma_release_channel(struct dma_chan *chan); #else static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) @@ -983,11 +988,6 @@ static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, { return NULL; } -static inline struct dma_chan *dma_request_slave_channel(struct device *dev, - char *name) -{ - return NULL; -} static inline void dma_release_channel(struct dma_chan *chan) { } diff --git a/trunk/include/linux/dw_dmac.h b/trunk/include/linux/dw_dmac.h index 41766de66e33..e1c8c9e919ac 100644 --- a/trunk/include/linux/dw_dmac.h +++ b/trunk/include/linux/dw_dmac.h @@ -14,39 +14,15 @@ #include -/** - * struct dw_dma_slave - Controller-specific information about a slave - * - * @dma_dev: required DMA master device. Depricated. - * @bus_id: name of this device channel, not just a device name since - * devices may have more than one channel e.g. "foo_tx" - * @cfg_hi: Platform-specific initializer for the CFG_HI register - * @cfg_lo: Platform-specific initializer for the CFG_LO register - * @src_master: src master for transfers on allocated channel. - * @dst_master: dest master for transfers on allocated channel. - */ -struct dw_dma_slave { - struct device *dma_dev; - const char *bus_id; - u32 cfg_hi; - u32 cfg_lo; - u8 src_master; - u8 dst_master; -}; - /** * struct dw_dma_platform_data - Controller configuration parameters * @nr_channels: Number of channels supported by hardware (max 8) * @is_private: The device channels should be marked as private and not for * by the general purpose DMA channel allocator. - * @chan_allocation_order: Allocate channels starting from 0 or 7 - * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. * @block_size: Maximum block size supported by the controller * @nr_masters: Number of AHB masters supported by the controller * @data_width: Maximum data width supported by hardware per AHB master * (0 - 8bits, 1 - 16bits, ..., 5 - 256bits) - * @sd: slave specific data. Used for configuring channels - * @sd_count: count of slave data structures passed. */ struct dw_dma_platform_data { unsigned int nr_channels; @@ -60,9 +36,6 @@ struct dw_dma_platform_data { unsigned short block_size; unsigned char nr_masters; unsigned char data_width[4]; - - struct dw_dma_slave *sd; - unsigned int sd_count; }; /* bursts size */ @@ -77,6 +50,23 @@ enum dw_dma_msize { DW_DMA_MSIZE_256, }; +/** + * struct dw_dma_slave - Controller-specific information about a slave + * + * @dma_dev: required DMA master device + * @cfg_hi: Platform-specific initializer for the CFG_HI register + * @cfg_lo: Platform-specific initializer for the CFG_LO register + * @src_master: src master for transfers on allocated channel. + * @dst_master: dest master for transfers on allocated channel. + */ +struct dw_dma_slave { + struct device *dma_dev; + u32 cfg_hi; + u32 cfg_lo; + u8 src_master; + u8 dst_master; +}; + /* Platform-configurable bits in CFG_HI */ #define DWC_CFGH_FCMODE (1 << 0) #define DWC_CFGH_FIFO_MODE (1 << 1) @@ -114,6 +104,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan); dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan); dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan); -bool dw_dma_generic_filter(struct dma_chan *chan, void *param); #endif /* DW_DMAC_H */ diff --git a/trunk/include/linux/of_dma.h b/trunk/include/linux/of_dma.h deleted file mode 100644 index d15073e080dd..000000000000 --- a/trunk/include/linux/of_dma.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * OF helpers for DMA request / controller - * - * Based on of_gpio.h - * - * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __LINUX_OF_DMA_H -#define __LINUX_OF_DMA_H - -#include -#include - -struct device_node; - -struct of_dma { - struct list_head of_dma_controllers; - struct device_node *of_node; - int of_dma_nbcells; - struct dma_chan *(*of_dma_xlate) - (struct of_phandle_args *, struct of_dma *); - void *of_dma_data; - int use_count; -}; - -struct of_dma_filter_info { - dma_cap_mask_t dma_cap; - dma_filter_fn filter_fn; -}; - -#ifdef CONFIG_OF -extern int of_dma_controller_register(struct device_node *np, - struct dma_chan *(*of_dma_xlate) - (struct of_phandle_args *, struct of_dma *), - void *data); -extern int of_dma_controller_free(struct device_node *np); -extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np, - char *name); -extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, - struct of_dma *ofdma); -#else -static inline int of_dma_controller_register(struct device_node *np, - struct dma_chan *(*of_dma_xlate) - (struct of_phandle_args *, struct of_dma *), - void *data) -{ - return -ENODEV; -} - -static inline int of_dma_controller_free(struct device_node *np) -{ - return -ENODEV; -} - -static inline struct dma_chan *of_dma_request_slave_channel(struct device_node *np, - char *name) -{ - return NULL; -} - -static inline struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, - struct of_dma *ofdma) -{ - return NULL; -} - -#endif - -#endif /* __LINUX_OF_DMA_H */ diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index db0856ad70cb..1ca253635f7a 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -1406,10 +1406,10 @@ static void tcp_service_net_dma(struct sock *sk, bool wait) return; last_issued = tp->ucopy.dma_cookie; - dma_async_issue_pending(tp->ucopy.dma_chan); + dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); do { - if (dma_async_is_tx_complete(tp->ucopy.dma_chan, + if (dma_async_memcpy_complete(tp->ucopy.dma_chan, last_issued, &done, &used) == DMA_SUCCESS) { /* Safe to free early-copied skbs now */ @@ -1744,7 +1744,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, tcp_service_net_dma(sk, true); tcp_cleanup_rbuf(sk, copied); } else - dma_async_issue_pending(tp->ucopy.dma_chan); + dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); } #endif if (copied >= target) { @@ -1837,7 +1837,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, break; } - dma_async_issue_pending(tp->ucopy.dma_chan); + dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); if ((offset + used) == skb->len) copied_early = true;