mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
dmaengine fixes for v4.15-rc4
Here are fixes for this round - Fix for disable clk on error path in fsl-edma driver - Disable clk fail fix in jz4740 driver - Fix long pending bug in dmatest driver for dangling pointer - Fix potential NULL pointer dereference in at_hdmac driver - Error handling path in ioat driver -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJaNp2PAAoJEHwUBw8lI4NHNfEP/RcERW0adeh4HXIges3FMW9N cqhRQpnUWmYIOTsfrWDH6WyR7pmEBOLryBzZXQ6Y8I3AOW4FTwBOG/W8NqFj+aiA JjeKRkXdpHD1eZpav72FUUhf4inb7BTtpGN5lBEFFk+gA3rWLscUw33OJLZmxsb5 Vi82pJARfst42XB/jZUBDq+YNYlgG+NspYgUWvS5EnNXJJmy+47c5TS9EQUovctM X0yrKNomSW2qEO/IEXTUvXtArxpmxBrZI1q9RU21JJvF3izElqYO9C3OhGijM27u ERHWM1iStOxOl7zrzp8JJmVswdHyW/rT5uSlhl4689S2UZEJrqBGPo67Nh5w0Isi Nk+2X8I7Z/tNByggXASHX/xXymQGJF/mxAs1KypnSE0DpCJQi7oJAG6UY7lbIOz8 CRGRt0gM8Xe/GrZa+7ZXmc7BoCrNPaGmW070XX3BoMcqT9m+SFOD2DhT351AVoOI uIPw5gAw0OCYhzkPP1c6AZPdLLFlVGrmPARRto/Af7w4Fnw4UlWGQ/+d6oQlvEyG G0kPxKE3e6uHXOizgm3GkbqpQWjTz649JMNw+xVey9e/pSVXORYIIomPmwahbh8x 7Rfojaccq3w0YYG58z/Q5+WmzWf0jU//G/Cq5LsOm/5ghZTYRna7olA6lxFcn+ab 6WQBW1rV2y8XUpDl4ScB =2egq -----END PGP SIGNATURE----- Merge tag 'dmaengine-fix-4.15-rc4' of git://git.infradead.org/users/vkoul/slave-dma Pull dmaengine fixes from Vinod Koul: "This time consisting of fixes in a bunch of drivers and the dmatest module: - Fix for disable clk on error path in fsl-edma driver - Disable clk fail fix in jz4740 driver - Fix long pending bug in dmatest driver for dangling pointer - Fix potential NULL pointer dereference in at_hdmac driver - Error handling path in ioat driver" * tag 'dmaengine-fix-4.15-rc4' of git://git.infradead.org/users/vkoul/slave-dma: dmaengine: fsl-edma: disable clks on all error paths dmaengine: jz4740: disable/unprepare clk if probe fails dmaengine: dmatest: move callback wait queue to thread context dmaengine: at_hdmac: fix potential NULL pointer dereference in atc_prep_dma_interleaved dmaengine: ioat: Fix error handling path
This commit is contained in:
commit
c43727908f
@ -708,7 +708,7 @@ atc_prep_dma_interleaved(struct dma_chan *chan,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct at_dma_chan *atchan = to_at_dma_chan(chan);
|
||||
struct data_chunk *first = xt->sgl;
|
||||
struct data_chunk *first;
|
||||
struct at_desc *desc = NULL;
|
||||
size_t xfer_count;
|
||||
unsigned int dwidth;
|
||||
@ -720,6 +720,8 @@ atc_prep_dma_interleaved(struct dma_chan *chan,
|
||||
if (unlikely(!xt || xt->numf != 1 || !xt->frame_size))
|
||||
return NULL;
|
||||
|
||||
first = xt->sgl;
|
||||
|
||||
dev_info(chan2dev(chan),
|
||||
"%s: src=%pad, dest=%pad, numf=%d, frame_size=%d, flags=0x%lx\n",
|
||||
__func__, &xt->src_start, &xt->dst_start, xt->numf,
|
||||
|
@ -555,7 +555,7 @@ static int jz4740_dma_probe(struct platform_device *pdev)
|
||||
|
||||
ret = dma_async_device_register(dd);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_clk;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
ret = request_irq(irq, jz4740_dma_irq, 0, dev_name(&pdev->dev), dmadev);
|
||||
@ -568,6 +568,8 @@ static int jz4740_dma_probe(struct platform_device *pdev)
|
||||
|
||||
err_unregister:
|
||||
dma_async_device_unregister(dd);
|
||||
err_clk:
|
||||
clk_disable_unprepare(dmadev->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -155,6 +155,12 @@ MODULE_PARM_DESC(run, "Run the test (default: false)");
|
||||
#define PATTERN_COUNT_MASK 0x1f
|
||||
#define PATTERN_MEMSET_IDX 0x01
|
||||
|
||||
/* poor man's completion - we want to use wait_event_freezable() on it */
|
||||
struct dmatest_done {
|
||||
bool done;
|
||||
wait_queue_head_t *wait;
|
||||
};
|
||||
|
||||
struct dmatest_thread {
|
||||
struct list_head node;
|
||||
struct dmatest_info *info;
|
||||
@ -165,6 +171,8 @@ struct dmatest_thread {
|
||||
u8 **dsts;
|
||||
u8 **udsts;
|
||||
enum dma_transaction_type type;
|
||||
wait_queue_head_t done_wait;
|
||||
struct dmatest_done test_done;
|
||||
bool done;
|
||||
};
|
||||
|
||||
@ -342,18 +350,25 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
|
||||
return error_count;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct dmatest_done *done = arg;
|
||||
|
||||
done->done = true;
|
||||
wake_up_all(done->wait);
|
||||
struct dmatest_thread *thread =
|
||||
container_of(arg, struct dmatest_thread, done_wait);
|
||||
if (!thread->done) {
|
||||
done->done = true;
|
||||
wake_up_all(done->wait);
|
||||
} else {
|
||||
/*
|
||||
* If thread->done, it means that this callback occurred
|
||||
* after the parent thread has cleaned up. This can
|
||||
* happen in the case that driver doesn't implement
|
||||
* the terminate_all() functionality and a dma operation
|
||||
* did not occur within the timeout period
|
||||
*/
|
||||
WARN(1, "dmatest: Kernel memory may be corrupted!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int min_odd(unsigned int x, unsigned int y)
|
||||
@ -424,9 +439,8 @@ static unsigned long long dmatest_KBs(s64 runtime, unsigned long long len)
|
||||
*/
|
||||
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 dmatest_done *done = &thread->test_done;
|
||||
struct dmatest_info *info;
|
||||
struct dmatest_params *params;
|
||||
struct dma_chan *chan;
|
||||
@ -673,9 +687,9 @@ static int dmatest_func(void *data)
|
||||
continue;
|
||||
}
|
||||
|
||||
done.done = false;
|
||||
done->done = false;
|
||||
tx->callback = dmatest_callback;
|
||||
tx->callback_param = &done;
|
||||
tx->callback_param = done;
|
||||
cookie = tx->tx_submit(tx);
|
||||
|
||||
if (dma_submit_error(cookie)) {
|
||||
@ -688,21 +702,12 @@ static int dmatest_func(void *data)
|
||||
}
|
||||
dma_async_issue_pending(chan);
|
||||
|
||||
wait_event_freezable_timeout(done_wait, done.done,
|
||||
wait_event_freezable_timeout(thread->done_wait, done->done,
|
||||
msecs_to_jiffies(params->timeout));
|
||||
|
||||
status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
|
||||
|
||||
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.
|
||||
*/
|
||||
WARN(1, "dmatest: Kernel stack may be corrupted!!\n");
|
||||
if (!done->done) {
|
||||
dmaengine_unmap_put(um);
|
||||
result("test timed out", total_tests, src_off, dst_off,
|
||||
len, 0);
|
||||
@ -789,7 +794,7 @@ err_thread_type:
|
||||
dmatest_KBs(runtime, total_len), ret);
|
||||
|
||||
/* terminate all transfers on specified channels */
|
||||
if (ret)
|
||||
if (ret || failed_tests)
|
||||
dmaengine_terminate_all(chan);
|
||||
|
||||
thread->done = true;
|
||||
@ -849,6 +854,8 @@ static int dmatest_add_threads(struct dmatest_info *info,
|
||||
thread->info = info;
|
||||
thread->chan = dtc->chan;
|
||||
thread->type = type;
|
||||
thread->test_done.wait = &thread->done_wait;
|
||||
init_waitqueue_head(&thread->done_wait);
|
||||
smp_wmb();
|
||||
thread->task = kthread_create(dmatest_func, thread, "%s-%s%u",
|
||||
dma_chan_name(chan), op, i);
|
||||
|
@ -863,11 +863,11 @@ static void fsl_edma_irq_exit(
|
||||
}
|
||||
}
|
||||
|
||||
static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma)
|
||||
static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma, int nr_clocks)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DMAMUX_NR; i++)
|
||||
for (i = 0; i < nr_clocks; i++)
|
||||
clk_disable_unprepare(fsl_edma->muxclk[i]);
|
||||
}
|
||||
|
||||
@ -904,25 +904,25 @@ static int fsl_edma_probe(struct platform_device *pdev)
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
|
||||
fsl_edma->muxbase[i] = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(fsl_edma->muxbase[i]))
|
||||
if (IS_ERR(fsl_edma->muxbase[i])) {
|
||||
/* on error: disable all previously enabled clks */
|
||||
fsl_disable_clocks(fsl_edma, i);
|
||||
return PTR_ERR(fsl_edma->muxbase[i]);
|
||||
}
|
||||
|
||||
sprintf(clkname, "dmamux%d", i);
|
||||
fsl_edma->muxclk[i] = devm_clk_get(&pdev->dev, clkname);
|
||||
if (IS_ERR(fsl_edma->muxclk[i])) {
|
||||
dev_err(&pdev->dev, "Missing DMAMUX block clock.\n");
|
||||
/* on error: disable all previously enabled clks */
|
||||
fsl_disable_clocks(fsl_edma, i);
|
||||
return PTR_ERR(fsl_edma->muxclk[i]);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(fsl_edma->muxclk[i]);
|
||||
if (ret) {
|
||||
/* disable only clks which were enabled on error */
|
||||
for (; i >= 0; i--)
|
||||
clk_disable_unprepare(fsl_edma->muxclk[i]);
|
||||
|
||||
dev_err(&pdev->dev, "DMAMUX clk block failed.\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
/* on error: disable all previously enabled clks */
|
||||
fsl_disable_clocks(fsl_edma, i);
|
||||
|
||||
}
|
||||
|
||||
@ -976,7 +976,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't register Freescale eDMA engine. (%d)\n", ret);
|
||||
fsl_disable_clocks(fsl_edma);
|
||||
fsl_disable_clocks(fsl_edma, DMAMUX_NR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -985,7 +985,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev,
|
||||
"Can't register Freescale eDMA of_dma. (%d)\n", ret);
|
||||
dma_async_device_unregister(&fsl_edma->dma_dev);
|
||||
fsl_disable_clocks(fsl_edma);
|
||||
fsl_disable_clocks(fsl_edma, DMAMUX_NR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1015,7 +1015,7 @@ static int fsl_edma_remove(struct platform_device *pdev)
|
||||
fsl_edma_cleanup_vchan(&fsl_edma->dma_dev);
|
||||
of_dma_controller_free(np);
|
||||
dma_async_device_unregister(&fsl_edma->dma_dev);
|
||||
fsl_disable_clocks(fsl_edma);
|
||||
fsl_disable_clocks(fsl_edma, DMAMUX_NR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ static int ioat_dma_self_test(struct ioatdma_device *ioat_dma)
|
||||
if (memcmp(src, dest, IOAT_TEST_SIZE)) {
|
||||
dev_err(dev, "Self-test copy failed compare, disabling\n");
|
||||
err = -ENODEV;
|
||||
goto free_resources;
|
||||
goto unmap_dma;
|
||||
}
|
||||
|
||||
unmap_dma:
|
||||
|
Loading…
Reference in New Issue
Block a user