diff options
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/amba-pl08x.c | 2 | ||||
-rw-r--r-- | drivers/dma/dmatest.c | 46 | ||||
-rw-r--r-- | drivers/dma/mv_xor.c | 11 | ||||
-rw-r--r-- | drivers/dma/mxs-dma.c | 8 | ||||
-rw-r--r-- | drivers/dma/pl330.c | 102 |
5 files changed, 94 insertions, 75 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 9ebceca..8a28158 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -2057,6 +2057,8 @@ static struct amba_id pl08x_ids[] = { { 0, 0 }, }; +MODULE_DEVICE_TABLE(amba, pl08x_ids); + static struct amba_driver pl08x_amba_driver = { .drv.name = DRIVER_NAME, .id_table = pl08x_ids, diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index eb1d864..2b8661b 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -214,9 +214,18 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start, return error_count; } -static void dmatest_callback(void *completion) +/* poor man's completion - we want to use wait_event_freezable() on it */ +struct dmatest_done { + bool done; + wait_queue_head_t *wait; +}; + +static void dmatest_callback(void *arg) { - complete(completion); + struct dmatest_done *done = arg; + + done->done = true; + wake_up_all(done->wait); } /* @@ -235,7 +244,9 @@ static void dmatest_callback(void *completion) */ static int dmatest_func(void *data) { + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait); struct dmatest_thread *thread = data; + struct dmatest_done done = { .wait = &done_wait }; struct dma_chan *chan; const char *thread_name; unsigned int src_off, dst_off, len; @@ -252,7 +263,7 @@ static int dmatest_func(void *data) int i; thread_name = current->comm; - set_freezable_with_signal(); + set_freezable(); ret = -ENOMEM; @@ -306,9 +317,6 @@ static int dmatest_func(void *data) struct dma_async_tx_descriptor *tx = NULL; dma_addr_t dma_srcs[src_cnt]; dma_addr_t dma_dsts[dst_cnt]; - struct completion cmp; - unsigned long start, tmo, end = 0 /* compiler... */; - bool reload = true; u8 align = 0; total_tests++; @@ -391,9 +399,9 @@ static int dmatest_func(void *data) continue; } - init_completion(&cmp); + done.done = false; tx->callback = dmatest_callback; - tx->callback_param = &cmp; + tx->callback_param = &done; cookie = tx->tx_submit(tx); if (dma_submit_error(cookie)) { @@ -407,20 +415,20 @@ static int dmatest_func(void *data) } dma_async_issue_pending(chan); - do { - start = jiffies; - if (reload) - end = start + msecs_to_jiffies(timeout); - else if (end <= start) - end = start + 1; - tmo = wait_for_completion_interruptible_timeout(&cmp, - end - start); - reload = try_to_freeze(); - } while (tmo == -ERESTARTSYS); + wait_event_freezable_timeout(done_wait, done.done, + msecs_to_jiffies(timeout)); status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); - if (tmo == 0) { + if (!done.done) { + /* + * We're leaving the timed out dma operation with + * dangling pointer to done_wait. To make this + * correct, we'll need to allocate wait_done for + * each test iteration and perform "who's gonna + * free it this time?" dancing. For now, just + * leave it dangling. + */ pr_warning("%s: #%u: test timed out\n", thread_name, total_tests - 1); failed_tests++; diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 9a353c2..e779b43 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -1250,7 +1250,7 @@ static int __devinit mv_xor_probe(struct platform_device *pdev) static void mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp, - struct mbus_dram_target_info *dram) + const struct mbus_dram_target_info *dram) { void __iomem *base = msp->xor_base; u32 win_enable = 0; @@ -1264,7 +1264,7 @@ mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp, } for (i = 0; i < dram->num_cs; i++) { - struct mbus_dram_window *cs = dram->cs + i; + const struct mbus_dram_window *cs = dram->cs + i; writel((cs->base & 0xffff0000) | (cs->mbus_attr << 8) | @@ -1290,7 +1290,7 @@ static struct platform_driver mv_xor_driver = { static int mv_xor_shared_probe(struct platform_device *pdev) { - struct mv_xor_platform_shared_data *msd = pdev->dev.platform_data; + const struct mbus_dram_target_info *dram; struct mv_xor_shared_private *msp; struct resource *res; @@ -1323,8 +1323,9 @@ static int mv_xor_shared_probe(struct platform_device *pdev) /* * (Re-)program MBUS remapping windows if we are asked to. */ - if (msd != NULL && msd->dram != NULL) - mv_xor_conf_mbus_windows(msp, msd->dram); + dram = mv_mbus_dram_info(); + if (dram) + mv_xor_conf_mbus_windows(msp, dram); return 0; } diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 493af2f..b06cd4c 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -311,7 +311,7 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan) goto err_irq; } - ret = clk_enable(mxs_dma->clk); + ret = clk_prepare_enable(mxs_dma->clk); if (ret) goto err_clk; @@ -346,7 +346,7 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan) dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE, mxs_chan->ccw, mxs_chan->ccw_phys); - clk_disable(mxs_dma->clk); + clk_disable_unprepare(mxs_dma->clk); } static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( @@ -554,7 +554,7 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) { int ret; - ret = clk_enable(mxs_dma->clk); + ret = clk_prepare_enable(mxs_dma->clk); if (ret) return ret; @@ -581,7 +581,7 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR); err_out: - clk_disable(mxs_dma->clk); + clk_disable_unprepare(mxs_dma->clk); return ret; } diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index a573757..b8ec03e 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -19,6 +19,7 @@ #include <linux/amba/pl330.h> #include <linux/pm_runtime.h> #include <linux/scatterlist.h> +#include <linux/of.h> #define NR_DEFAULT_DESC 16 @@ -116,6 +117,9 @@ struct dma_pl330_desc { struct dma_pl330_chan *pchan; }; +/* forward declaration */ +static struct amba_driver pl330_driver; + static inline struct dma_pl330_chan * to_pchan(struct dma_chan *ch) { @@ -267,6 +271,32 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err) tasklet_schedule(&pch->task); } +bool pl330_filter(struct dma_chan *chan, void *param) +{ + u8 *peri_id; + + if (chan->device->dev->driver != &pl330_driver.drv) + return false; + +#ifdef CONFIG_OF + if (chan->device->dev->of_node) { + const __be32 *prop_value; + phandle phandle; + struct device_node *node; + + prop_value = ((struct property *)param)->value; + phandle = be32_to_cpup(prop_value++); + node = of_find_node_by_phandle(phandle); + return ((chan->private == node) && + (chan->chan_id == be32_to_cpup(prop_value))); + } +#endif + + peri_id = chan->private; + return *peri_id == (unsigned)param; +} +EXPORT_SYMBOL(pl330_filter); + static int pl330_alloc_chan_resources(struct dma_chan *chan) { struct dma_pl330_chan *pch = to_pchan(chan); @@ -497,7 +527,7 @@ pluck_desc(struct dma_pl330_dmac *pdmac) static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) { struct dma_pl330_dmac *pdmac = pch->dmac; - struct dma_pl330_peri *peri = pch->chan.private; + u8 *peri_id = pch->chan.private; struct dma_pl330_desc *desc; /* Pluck one desc from the pool of DMAC */ @@ -522,13 +552,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) desc->txd.cookie = 0; async_tx_ack(&desc->txd); - if (peri) { - desc->req.rqtype = peri->rqtype; - desc->req.peri = pch->chan.chan_id; - } else { - desc->req.rqtype = MEMTOMEM; - desc->req.peri = 0; - } + desc->req.peri = peri_id ? pch->chan.chan_id : 0; dma_async_tx_descriptor_init(&desc->txd, &pch->chan); @@ -615,12 +639,14 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( case DMA_MEM_TO_DEV: desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 0; + desc->req.rqtype = MEMTODEV; src = dma_addr; dst = pch->fifo_addr; break; case DMA_DEV_TO_MEM: desc->rqcfg.src_inc = 0; desc->rqcfg.dst_inc = 1; + desc->req.rqtype = DEVTOMEM; src = pch->fifo_addr; dst = dma_addr; break; @@ -646,16 +672,12 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, { struct dma_pl330_desc *desc; struct dma_pl330_chan *pch = to_pchan(chan); - struct dma_pl330_peri *peri = chan->private; struct pl330_info *pi; int burst; if (unlikely(!pch || !len)) return NULL; - if (peri && peri->rqtype != MEMTOMEM) - return NULL; - pi = &pch->dmac->pif; desc = __pl330_prep_dma_memcpy(pch, dst, src, len); @@ -664,6 +686,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 1; + desc->req.rqtype = MEMTOMEM; /* Select max possible burst size */ burst = pi->pcfg.data_bus_width / 8; @@ -692,25 +715,14 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, { struct dma_pl330_desc *first, *desc = NULL; struct dma_pl330_chan *pch = to_pchan(chan); - struct dma_pl330_peri *peri = chan->private; struct scatterlist *sg; unsigned long flags; int i; dma_addr_t addr; - if (unlikely(!pch || !sgl || !sg_len || !peri)) + if (unlikely(!pch || !sgl || !sg_len)) return NULL; - /* Make sure the direction is consistent */ - if ((direction == DMA_MEM_TO_DEV && - peri->rqtype != MEMTODEV) || - (direction == DMA_DEV_TO_MEM && - peri->rqtype != DEVTOMEM)) { - dev_err(pch->dmac->pif.dev, "%s:%d Invalid Direction\n", - __func__, __LINE__); - return NULL; - } - addr = pch->fifo_addr; first = NULL; @@ -750,11 +762,13 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (direction == DMA_MEM_TO_DEV) { desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 0; + desc->req.rqtype = MEMTODEV; fill_px(&desc->px, addr, sg_dma_address(sg), sg_dma_len(sg)); } else { desc->rqcfg.src_inc = 0; desc->rqcfg.dst_inc = 1; + desc->req.rqtype = DEVTOMEM; fill_px(&desc->px, sg_dma_address(sg), addr, sg_dma_len(sg)); } @@ -846,33 +860,16 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) INIT_LIST_HEAD(&pd->channels); /* Initialize channel parameters */ - num_chan = max(pdat ? (int)pdat->nr_valid_peri : 0, - (int)pi->pcfg.num_chan); + num_chan = max(pdat ? pdat->nr_valid_peri : (u8)pi->pcfg.num_peri, + (u8)pi->pcfg.num_chan); pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); for (i = 0; i < num_chan; i++) { pch = &pdmac->peripherals[i]; - if (pdat) { - struct dma_pl330_peri *peri = &pdat->peri[i]; - - switch (peri->rqtype) { - case MEMTOMEM: - dma_cap_set(DMA_MEMCPY, pd->cap_mask); - break; - case MEMTODEV: - case DEVTOMEM: - dma_cap_set(DMA_SLAVE, pd->cap_mask); - dma_cap_set(DMA_CYCLIC, pd->cap_mask); - break; - default: - dev_err(&adev->dev, "DEVTODEV Not Supported\n"); - continue; - } - pch->chan.private = peri; - } else { - dma_cap_set(DMA_MEMCPY, pd->cap_mask); - pch->chan.private = NULL; - } + if (!adev->dev.of_node) + pch->chan.private = pdat ? &pdat->peri_id[i] : NULL; + else + pch->chan.private = adev->dev.of_node; INIT_LIST_HEAD(&pch->work_list); spin_lock_init(&pch->lock); @@ -885,6 +882,15 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) } pd->dev = &adev->dev; + if (pdat) { + pd->cap_mask = pdat->cap_mask; + } else { + dma_cap_set(DMA_MEMCPY, pd->cap_mask); + if (pi->pcfg.num_peri) { + dma_cap_set(DMA_SLAVE, pd->cap_mask); + dma_cap_set(DMA_CYCLIC, pd->cap_mask); + } + } pd->device_alloc_chan_resources = pl330_alloc_chan_resources; pd->device_free_chan_resources = pl330_free_chan_resources; @@ -978,6 +984,8 @@ static struct amba_id pl330_ids[] = { { 0, 0 }, }; +MODULE_DEVICE_TABLE(amba, pl330_ids); + #ifdef CONFIG_PM_RUNTIME static int pl330_runtime_suspend(struct device *dev) { |