[PATCH 10/12] DMAENGINE: move the PL08X to full runtime allocation

From: Linus Walleij
Date: Tue Aug 31 2010 - 08:13:12 EST


This change makes the PL08X not being a singleton anymore, this
piece was missing earlier: we move the struct dma_device entries
into the driver state holder. Also flag channels as slaves and
fix up the channel freeing code.

Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxxxxxx>
---
drivers/dma/amba-pl08x.c | 112 +++++++++++++++++++++++++-------------------
include/linux/amba/pl08x.h | 2 +
2 files changed, 66 insertions(+), 48 deletions(-)

diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index f80fc4b..4573189 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -110,6 +110,8 @@ struct lli {

/**
* struct pl08x_driver_data - the local state holder for the PL08x
+ * @slave: slave engine for this instance
+ * @memcpy: memcpy engine for this instance
* @base: virtual memory base (remapped) for the PL08x
* @adev: the corresponding AMBA (PrimeCell) bus entry
* @vd: vendor data for this PL08x variant
@@ -120,6 +122,8 @@ struct lli {
* @lock: a spinlock for this struct
*/
struct pl08x_driver_data {
+ struct dma_device slave;
+ struct dma_device memcpy;
void __iomem *base;
struct amba_device *adev;
struct vendor_data *vd;
@@ -1691,38 +1695,6 @@ bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
return false;
}

-static struct dma_device dmac_memcpy = {
- .device_alloc_chan_resources = pl08x_alloc_chan_resources,
- .device_free_chan_resources = pl08x_free_chan_resources,
- .device_prep_dma_memcpy = pl08x_prep_dma_memcpy,
- .device_prep_dma_xor = NULL,
- .device_prep_dma_memset = NULL,
- .device_prep_dma_interrupt = pl08x_prep_dma_interrupt,
- .device_tx_status = pl08x_dma_tx_status,
- .device_issue_pending = pl08x_issue_pending,
- .device_control = pl08x_control,
- /*
- * Align to 4-byte boundary
- * This makes the DMAtests fail with grace on PB1176
- * broken DMA hardware instead of locking everything
- * up.
- */
- /* .copy_align = 2, */
-};
-
-static struct dma_device dmac_slave = {
- .device_alloc_chan_resources = pl08x_alloc_chan_resources,
- .device_free_chan_resources = pl08x_free_chan_resources,
- .device_prep_dma_xor = NULL,
- .device_prep_dma_memset = NULL,
- .device_prep_dma_interrupt = pl08x_prep_dma_interrupt,
- .device_tx_status = pl08x_dma_tx_status,
- .device_issue_pending = pl08x_issue_pending,
- .device_prep_slave_sg = pl08x_prep_slave_sg,
- .device_control = pl08x_control,
-};
-
-
/*
* Just check that the device is there and active
* TODO: turn this bit on/off depending on the number of
@@ -1770,6 +1742,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
chan->host = pl08x;

if (slave) {
+ chan->slave = true;
chan->name = pl08x->pd->slave_channels[i].bus_id;
chan->cd = &pl08x->pd->slave_channels[i];
} else {
@@ -1800,10 +1773,23 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
return i;
}

+static void pl08x_free_virtual_channels(struct dma_device *dmadev)
+{
+ struct pl08x_dma_chan *chan = NULL;
+ struct pl08x_dma_chan *next;
+
+ list_for_each_entry_safe(chan,
+ next, &dmadev->channels, chan.device_node) {
+ list_del(&chan->chan.device_node);
+ kfree(chan);
+ }
+}
+
#ifdef CONFIG_DEBUG_FS
static int pl08x_debugfs_show(struct seq_file *s, void *data)
{
struct pl08x_driver_data *pl08x = s->private;
+ struct pl08x_dma_chan *chan;
struct pl08x_phy_chan *ch;
unsigned long flags;
int i;
@@ -1824,6 +1810,21 @@ static int pl08x_debugfs_show(struct seq_file *s, void *data)

spin_unlock_irqrestore(&ch->lock, flags);
}
+
+ seq_printf(s, "\nPL08x virtual memcpy channels:\n");
+ seq_printf(s, "CHANNEL:\n");
+ seq_printf(s, "--------\n");
+ list_for_each_entry(chan, &pl08x->memcpy.channels, chan.device_node) {
+ seq_printf(s, "%s\n", chan->name);
+ }
+
+ seq_printf(s, "\nPL08x virtual slave channels:\n");
+ seq_printf(s, "CHANNEL:\n");
+ seq_printf(s, "--------\n");
+ list_for_each_entry(chan, &pl08x->slave.channels, chan.device_node) {
+ seq_printf(s, "%s\n", chan->name);
+ }
+
return 0;
}

@@ -1845,7 +1846,6 @@ static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
(void) debugfs_create_file(dev_name(&pl08x->adev->dev), S_IFREG | S_IRUGO,
NULL, pl08x,
&pl08x_debugfs_operations);
- return 0;
}

#else
@@ -1872,6 +1872,28 @@ static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
goto out_no_pl08x;
}

+ /* Initialize memcpy engine */
+ dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
+ pl08x->memcpy.dev = &adev->dev;
+ pl08x->memcpy.device_alloc_chan_resources = pl08x_alloc_chan_resources;
+ pl08x->memcpy.device_free_chan_resources = pl08x_free_chan_resources;
+ pl08x->memcpy.device_prep_dma_memcpy = pl08x_prep_dma_memcpy;
+ pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
+ pl08x->memcpy.device_tx_status = pl08x_dma_tx_status;
+ pl08x->memcpy.device_issue_pending = pl08x_issue_pending;
+ pl08x->memcpy.device_control = pl08x_control;
+
+ /* Initialize slave engine */
+ dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
+ pl08x->slave.dev = &adev->dev;
+ pl08x->slave.device_alloc_chan_resources = pl08x_alloc_chan_resources;
+ pl08x->slave.device_free_chan_resources = pl08x_free_chan_resources;
+ pl08x->slave.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
+ pl08x->slave.device_tx_status = pl08x_dma_tx_status;
+ pl08x->slave.device_issue_pending = pl08x_issue_pending;
+ pl08x->slave.device_prep_slave_sg = pl08x_prep_slave_sg;
+ pl08x->slave.device_control = pl08x_control;
+
/* Get the platform data */
pl08x->pd = dev_get_platdata(&adev->dev);
if (!pl08x->pd) {
@@ -1939,14 +1961,8 @@ static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
}

- /* Set caps */
- dma_cap_set(DMA_MEMCPY, dmac_memcpy.cap_mask);
- dma_cap_set(DMA_SLAVE, dmac_slave.cap_mask);
- dmac_memcpy.dev = &adev->dev;
- dmac_slave.dev = &adev->dev;
-
/* Register as many memcpy channels as there are physical channels */
- ret = pl08x_dma_init_virtual_channels(pl08x, &dmac_memcpy,
+ ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->memcpy,
pl08x->vd->channels, false);
if (ret <= 0) {
dev_warn(&pl08x->adev->dev,
@@ -1954,10 +1970,10 @@ static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
__func__, ret);
goto out_no_memcpy;
}
- dmac_memcpy.chancnt = ret;
+ pl08x->memcpy.chancnt = ret;

/* Register slave channels */
- ret = pl08x_dma_init_virtual_channels(pl08x, &dmac_slave,
+ ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
pl08x->pd->num_slave_channels,
true);
if (ret <= 0) {
@@ -1966,9 +1982,9 @@ static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
__func__, ret);
goto out_no_slave;
}
- dmac_slave.chancnt = ret;
+ pl08x->slave.chancnt = ret;

- ret = dma_async_device_register(&dmac_memcpy);
+ ret = dma_async_device_register(&pl08x->memcpy);
if (ret) {
dev_warn(&pl08x->adev->dev,
"%s failed to register memcpy as an async device - %d\n",
@@ -1976,7 +1992,7 @@ static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
goto out_no_memcpy_reg;
}

- ret = dma_async_device_register(&dmac_slave);
+ ret = dma_async_device_register(&pl08x->slave);
if (ret) {
dev_warn(&pl08x->adev->dev,
"%s failed to register slave as an async device - %d\n",
@@ -1991,11 +2007,11 @@ static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
return 0;

out_no_slave_reg:
- dma_async_device_unregister(&dmac_memcpy);
+ dma_async_device_unregister(&pl08x->memcpy);
out_no_memcpy_reg:
- /* FIXME: free slave channels */
+ pl08x_free_virtual_channels(&pl08x->slave);
out_no_slave:
- /* FIXME: free memcpy channels */
+ pl08x_free_virtual_channels(&pl08x->memcpy);
out_no_memcpy:
kfree(pl08x->phy_chans);
out_no_phychans:
diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h
index 2bb7ac4..6db44f9 100644
--- a/include/linux/amba/pl08x.h
+++ b/include/linux/amba/pl08x.h
@@ -138,6 +138,7 @@ struct pl08x_txd {
* @lock: a lock for this channel data
* @host: a pointer to the host (internal use)
* @paused: whether the channel is paused
+ * @slave: whether this channel is a device (slave) or for memcpy
*/
struct pl08x_dma_chan {
struct dma_chan chan;
@@ -154,6 +155,7 @@ struct pl08x_dma_chan {
spinlock_t lock;
void *host;
bool paused;
+ bool slave;
};

/**
--
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/