diff options
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/coh901318.c | 43 | ||||
-rw-r--r-- | drivers/dma/dmatest.c | 45 | ||||
-rw-r--r-- | drivers/dma/ste_dma40.c | 8 |
3 files changed, 71 insertions, 25 deletions
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 3b23061cdb41..9bfaddd57ef1 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -22,6 +22,7 @@ #include <linux/uaccess.h> #include <linux/debugfs.h> #include <linux/platform_data/dma-coh901318.h> +#include <linux/of_dma.h> #include "coh901318.h" #include "dmaengine.h" @@ -1788,6 +1789,35 @@ bool coh901318_filter_id(struct dma_chan *chan, void *chan_id) } EXPORT_SYMBOL(coh901318_filter_id); +struct coh901318_filter_args { + struct coh901318_base *base; + unsigned int ch_nr; +}; + +static bool coh901318_filter_base_and_id(struct dma_chan *chan, void *data) +{ + struct coh901318_filter_args *args = data; + + if (&args->base->dma_slave == chan->device && + args->ch_nr == to_coh901318_chan(chan)->id) + return true; + + return false; +} + +static struct dma_chan *coh901318_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct coh901318_filter_args args = { + .base = ofdma->of_dma_data, + .ch_nr = dma_spec->args[0], + }; + dma_cap_mask_t cap; + dma_cap_zero(cap); + dma_cap_set(DMA_SLAVE, cap); + + return dma_request_channel(cap, coh901318_filter_base_and_id, &args); +} /* * DMA channel allocation */ @@ -2735,12 +2765,19 @@ static int __init coh901318_probe(struct platform_device *pdev) if (err) goto err_register_memcpy; + err = of_dma_controller_register(pdev->dev.of_node, coh901318_xlate, + base); + if (err) + goto err_register_of_dma; + platform_set_drvdata(pdev, base); dev_info(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n", (u32) base->virtbase); return err; + err_register_of_dma: + dma_async_device_unregister(&base->dma_memcpy); err_register_memcpy: dma_async_device_unregister(&base->dma_slave); err_register_slave: @@ -2752,17 +2789,23 @@ static int coh901318_remove(struct platform_device *pdev) { struct coh901318_base *base = platform_get_drvdata(pdev); + of_dma_controller_free(pdev->dev.of_node); dma_async_device_unregister(&base->dma_memcpy); dma_async_device_unregister(&base->dma_slave); coh901318_pool_destroy(&base->pool); return 0; } +static const struct of_device_id coh901318_dt_match[] = { + { .compatible = "stericsson,coh901318" }, + {}, +}; static struct platform_driver coh901318_driver = { .remove = coh901318_remove, .driver = { .name = "coh901318", + .of_match_table = coh901318_dt_match, }, }; diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index d8ce4ecfef18..e88ded2c8d2f 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -716,8 +716,7 @@ static int dmatest_func(void *data) } dma_async_issue_pending(chan); - wait_event_freezable_timeout(done_wait, - done.done || kthread_should_stop(), + wait_event_freezable_timeout(done_wait, done.done, msecs_to_jiffies(params->timeout)); status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); @@ -997,7 +996,6 @@ static void stop_threaded_test(struct dmatest_info *info) static int __restart_threaded_test(struct dmatest_info *info, bool run) { struct dmatest_params *params = &info->params; - int ret; /* Stop any running test first */ __stop_threaded_test(info); @@ -1012,13 +1010,23 @@ static int __restart_threaded_test(struct dmatest_info *info, bool run) memcpy(params, &info->dbgfs_params, sizeof(*params)); /* Run test with new parameters */ - ret = __run_threaded_test(info); - if (ret) { - __stop_threaded_test(info); - pr_err("dmatest: Can't run test\n"); + return __run_threaded_test(info); +} + +static bool __is_threaded_test_run(struct dmatest_info *info) +{ + struct dmatest_chan *dtc; + + list_for_each_entry(dtc, &info->channels, node) { + struct dmatest_thread *thread; + + list_for_each_entry(thread, &dtc->threads, node) { + if (!thread->done) + return true; + } } - return ret; + return false; } static ssize_t dtf_write_string(void *to, size_t available, loff_t *ppos, @@ -1091,22 +1099,10 @@ static ssize_t dtf_read_run(struct file *file, char __user *user_buf, { struct dmatest_info *info = file->private_data; char buf[3]; - struct dmatest_chan *dtc; - bool alive = false; mutex_lock(&info->lock); - list_for_each_entry(dtc, &info->channels, node) { - struct dmatest_thread *thread; - - list_for_each_entry(thread, &dtc->threads, node) { - if (!thread->done) { - alive = true; - break; - } - } - } - if (alive) { + if (__is_threaded_test_run(info)) { buf[0] = 'Y'; } else { __stop_threaded_test(info); @@ -1132,7 +1128,12 @@ static ssize_t dtf_write_run(struct file *file, const char __user *user_buf, if (strtobool(buf, &bv) == 0) { mutex_lock(&info->lock); - ret = __restart_threaded_test(info, bv); + + if (__is_threaded_test_run(info)) + ret = -EBUSY; + else + ret = __restart_threaded_test(info, bv); + mutex_unlock(&info->lock); } diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 1734feec47b1..71bf4ec300ea 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1566,10 +1566,12 @@ static void dma_tc_handle(struct d40_chan *d40c) return; } - if (d40_queue_start(d40c) == NULL) + if (d40_queue_start(d40c) == NULL) { d40c->busy = false; - pm_runtime_mark_last_busy(d40c->base->dev); - pm_runtime_put_autosuspend(d40c->base->dev); + + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); + } d40_desc_remove(d40d); d40_desc_done(d40c, d40d); |