Split the virtual slave channel DMA support from the sa11x0 driver so
this code can be shared with other slave DMA engine drivers.
Signed-off-by: Russell King rmk+ker...@arm.linux.org.uk
---
drivers/dma/Kconfig |4 +
drivers/dma/Makefile |1 +
drivers/dma/sa11x0-dma.c | 249 ++---
drivers/dma/virt-dma.c | 99 ++
drivers/dma/virt-dma.h | 138 +
5 files changed, 320 insertions(+), 171 deletions(-)
create mode 100644 drivers/dma/virt-dma.c
create mode 100644 drivers/dma/virt-dma.h
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index cf9da36..5828ac4 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -255,6 +255,7 @@ config DMA_SA11X0
tristate SA-11x0 DMA support
depends on ARCH_SA1100
select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
help
Support the DMA engine found on Intel StrongARM SA-1100 and
SA-1110 SoCs. This DMA engine can only be used with on-chip
@@ -263,6 +264,9 @@ config DMA_SA11X0
config DMA_ENGINE
bool
+config DMA_VIRTUAL_CHANNELS
+ tristate
+
comment DMA Clients
depends on DMA_ENGINE
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 86b795b..fc05f7d 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -2,6 +2,7 @@ ccflags-$(CONFIG_DMADEVICES_DEBUG) := -DDEBUG
ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG
obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
+obj-$(CONFIG_DMA_VIRTUAL_CHANNELS) += virt-dma.o
obj-$(CONFIG_NET_DMA) += iovlock.o
obj-$(CONFIG_INTEL_MID_DMAC) += intel_mid_dma.o
obj-$(CONFIG_DMATEST) += dmatest.o
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index ec78cce..5f1d2e6 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -21,6 +21,8 @@
#include linux/slab.h
#include linux/spinlock.h
+#include virt-dma.h
+
#define NR_PHY_CHAN6
#define DMA_ALIGN 3
#define DMA_MAX_SIZE 0x1fff
@@ -72,12 +74,11 @@ struct sa11x0_dma_sg {
};
struct sa11x0_dma_desc {
- struct dma_async_tx_descriptor tx;
+ struct virt_dma_descvd;
+
u32 ddar;
size_t size;
- /* maybe protected by c-lock */
- struct list_headnode;
unsignedsglen;
struct sa11x0_dma_sgsg[0];
};
@@ -85,15 +86,11 @@ struct sa11x0_dma_desc {
struct sa11x0_dma_phy;
struct sa11x0_dma_chan {
- struct dma_chan chan;
- spinlock_t lock;
- dma_cookie_tlc;
+ struct virt_dma_chanvc;
- /* protected by c-lock */
+ /* protected by c-vc.lock */
struct sa11x0_dma_phy *phy;
enum dma_status status;
- struct list_headdesc_submitted;
- struct list_headdesc_issued;
/* protected by d-lock */
struct list_headnode;
@@ -109,7 +106,7 @@ struct sa11x0_dma_phy {
struct sa11x0_dma_chan *vchan;
- /* Protected by c-lock */
+ /* Protected by c-vc.lock */
unsignedsg_load;
struct sa11x0_dma_desc *txd_load;
unsignedsg_done;
@@ -127,13 +124,12 @@ struct sa11x0_dma_dev {
spinlock_t lock;
struct tasklet_struct task;
struct list_headchan_pending;
- struct list_headdesc_complete;
struct sa11x0_dma_phy phy[NR_PHY_CHAN];
};
static struct sa11x0_dma_chan *to_sa11x0_dma_chan(struct dma_chan *chan)
{
- return container_of(chan, struct sa11x0_dma_chan, chan);
+ return container_of(chan, struct sa11x0_dma_chan, vc.chan);
}
static struct sa11x0_dma_dev *to_sa11x0_dma(struct dma_device *dmadev)
@@ -141,27 +137,26 @@ static struct sa11x0_dma_dev *to_sa11x0_dma(struct
dma_device *dmadev)
return container_of(dmadev, struct sa11x0_dma_dev, slave);
}
-static struct sa11x0_dma_desc *to_sa11x0_dma_tx(struct dma_async_tx_descriptor
*tx)
+static struct sa11x0_dma_desc *sa11x0_dma_next_desc(struct sa11x0_dma_chan *c)
{
- return container_of(tx, struct sa11x0_dma_desc, tx);
+ struct virt_dma_desc *vd = vchan_next_desc(c-vc);
+
+ return vd ? container_of(vd, struct sa11x0_dma_desc, vd) : NULL;
}
-static struct sa11x0_dma_desc *sa11x0_dma_next_desc(struct sa11x0_dma_chan *c)
+static void sa11x0_dma_free_desc(struct virt_dma_desc *vd)
{
- if (list_empty(c-desc_issued))
- return NULL;
-
- return list_first_entry(c-desc_issued, struct sa11x0_dma_desc, node);
+ kfree(container_of(vd, struct sa11x0_dma_desc, vd));
}
static void sa11x0_dma_start_desc(struct sa11x0_dma_phy *p, struct
sa11x0_dma_desc *txd)
{
- list_del(txd-node);
+ list_del(txd-vd.node);
p-txd_load = txd;
p-sg_load = 0;
dev_vdbg(p-dev-slave.dev, pchan %u: txd %p[%x]: starting: