Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+52 -41
+3 -1
drivers/dma/at_hdmac.c
··· 708 708 unsigned long flags) 709 709 { 710 710 struct at_dma_chan *atchan = to_at_dma_chan(chan); 711 - struct data_chunk *first = xt->sgl; 711 + struct data_chunk *first; 712 712 struct at_desc *desc = NULL; 713 713 size_t xfer_count; 714 714 unsigned int dwidth; ··· 719 719 720 720 if (unlikely(!xt || xt->numf != 1 || !xt->frame_size)) 721 721 return NULL; 722 + 723 + first = xt->sgl; 722 724 723 725 dev_info(chan2dev(chan), 724 726 "%s: src=%pad, dest=%pad, numf=%d, frame_size=%d, flags=0x%lx\n",
+3 -1
drivers/dma/dma-jz4740.c
··· 555 555 556 556 ret = dma_async_device_register(dd); 557 557 if (ret) 558 - return ret; 558 + goto err_clk; 559 559 560 560 irq = platform_get_irq(pdev, 0); 561 561 ret = request_irq(irq, jz4740_dma_irq, 0, dev_name(&pdev->dev), dmadev); ··· 568 568 569 569 err_unregister: 570 570 dma_async_device_unregister(dd); 571 + err_clk: 572 + clk_disable_unprepare(dmadev->clk); 571 573 return ret; 572 574 } 573 575
+31 -24
drivers/dma/dmatest.c
··· 155 155 #define PATTERN_COUNT_MASK 0x1f 156 156 #define PATTERN_MEMSET_IDX 0x01 157 157 158 + /* poor man's completion - we want to use wait_event_freezable() on it */ 159 + struct dmatest_done { 160 + bool done; 161 + wait_queue_head_t *wait; 162 + }; 163 + 158 164 struct dmatest_thread { 159 165 struct list_head node; 160 166 struct dmatest_info *info; ··· 171 165 u8 **dsts; 172 166 u8 **udsts; 173 167 enum dma_transaction_type type; 168 + wait_queue_head_t done_wait; 169 + struct dmatest_done test_done; 174 170 bool done; 175 171 }; 176 172 ··· 350 342 return error_count; 351 343 } 352 344 353 - /* poor man's completion - we want to use wait_event_freezable() on it */ 354 - struct dmatest_done { 355 - bool done; 356 - wait_queue_head_t *wait; 357 - }; 358 345 359 346 static void dmatest_callback(void *arg) 360 347 { 361 348 struct dmatest_done *done = arg; 362 - 363 - done->done = true; 364 - wake_up_all(done->wait); 349 + struct dmatest_thread *thread = 350 + container_of(arg, struct dmatest_thread, done_wait); 351 + if (!thread->done) { 352 + done->done = true; 353 + wake_up_all(done->wait); 354 + } else { 355 + /* 356 + * If thread->done, it means that this callback occurred 357 + * after the parent thread has cleaned up. This can 358 + * happen in the case that driver doesn't implement 359 + * the terminate_all() functionality and a dma operation 360 + * did not occur within the timeout period 361 + */ 362 + WARN(1, "dmatest: Kernel memory may be corrupted!!\n"); 363 + } 365 364 } 366 365 367 366 static unsigned int min_odd(unsigned int x, unsigned int y) ··· 439 424 */ 440 425 static int dmatest_func(void *data) 441 426 { 442 - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait); 443 427 struct dmatest_thread *thread = data; 444 - struct dmatest_done done = { .wait = &done_wait }; 428 + struct dmatest_done *done = &thread->test_done; 445 429 struct dmatest_info *info; 446 430 struct dmatest_params *params; 447 431 struct dma_chan *chan; ··· 687 673 continue; 688 674 } 689 675 690 - done.done = false; 676 + done->done = false; 691 677 tx->callback = dmatest_callback; 692 - tx->callback_param = &done; 678 + tx->callback_param = done; 693 679 cookie = tx->tx_submit(tx); 694 680 695 681 if (dma_submit_error(cookie)) { ··· 702 688 } 703 689 dma_async_issue_pending(chan); 704 690 705 - wait_event_freezable_timeout(done_wait, done.done, 691 + wait_event_freezable_timeout(thread->done_wait, done->done, 706 692 msecs_to_jiffies(params->timeout)); 707 693 708 694 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 709 695 710 - if (!done.done) { 711 - /* 712 - * We're leaving the timed out dma operation with 713 - * dangling pointer to done_wait. To make this 714 - * correct, we'll need to allocate wait_done for 715 - * each test iteration and perform "who's gonna 716 - * free it this time?" dancing. For now, just 717 - * leave it dangling. 718 - */ 719 - WARN(1, "dmatest: Kernel stack may be corrupted!!\n"); 696 + if (!done->done) { 720 697 dmaengine_unmap_put(um); 721 698 result("test timed out", total_tests, src_off, dst_off, 722 699 len, 0); ··· 794 789 dmatest_KBs(runtime, total_len), ret); 795 790 796 791 /* terminate all transfers on specified channels */ 797 - if (ret) 792 + if (ret || failed_tests) 798 793 dmaengine_terminate_all(chan); 799 794 800 795 thread->done = true; ··· 854 849 thread->info = info; 855 850 thread->chan = dtc->chan; 856 851 thread->type = type; 852 + thread->test_done.wait = &thread->done_wait; 853 + init_waitqueue_head(&thread->done_wait); 857 854 smp_wmb(); 858 855 thread->task = kthread_create(dmatest_func, thread, "%s-%s%u", 859 856 dma_chan_name(chan), op, i);
+14 -14
drivers/dma/fsl-edma.c
··· 863 863 } 864 864 } 865 865 866 - static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma) 866 + static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma, int nr_clocks) 867 867 { 868 868 int i; 869 869 870 - for (i = 0; i < DMAMUX_NR; i++) 870 + for (i = 0; i < nr_clocks; i++) 871 871 clk_disable_unprepare(fsl_edma->muxclk[i]); 872 872 } 873 873 ··· 904 904 905 905 res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i); 906 906 fsl_edma->muxbase[i] = devm_ioremap_resource(&pdev->dev, res); 907 - if (IS_ERR(fsl_edma->muxbase[i])) 907 + if (IS_ERR(fsl_edma->muxbase[i])) { 908 + /* on error: disable all previously enabled clks */ 909 + fsl_disable_clocks(fsl_edma, i); 908 910 return PTR_ERR(fsl_edma->muxbase[i]); 911 + } 909 912 910 913 sprintf(clkname, "dmamux%d", i); 911 914 fsl_edma->muxclk[i] = devm_clk_get(&pdev->dev, clkname); 912 915 if (IS_ERR(fsl_edma->muxclk[i])) { 913 916 dev_err(&pdev->dev, "Missing DMAMUX block clock.\n"); 917 + /* on error: disable all previously enabled clks */ 918 + fsl_disable_clocks(fsl_edma, i); 914 919 return PTR_ERR(fsl_edma->muxclk[i]); 915 920 } 916 921 917 922 ret = clk_prepare_enable(fsl_edma->muxclk[i]); 918 - if (ret) { 919 - /* disable only clks which were enabled on error */ 920 - for (; i >= 0; i--) 921 - clk_disable_unprepare(fsl_edma->muxclk[i]); 922 - 923 - dev_err(&pdev->dev, "DMAMUX clk block failed.\n"); 924 - return ret; 925 - } 923 + if (ret) 924 + /* on error: disable all previously enabled clks */ 925 + fsl_disable_clocks(fsl_edma, i); 926 926 927 927 } 928 928 ··· 976 976 if (ret) { 977 977 dev_err(&pdev->dev, 978 978 "Can't register Freescale eDMA engine. (%d)\n", ret); 979 - fsl_disable_clocks(fsl_edma); 979 + fsl_disable_clocks(fsl_edma, DMAMUX_NR); 980 980 return ret; 981 981 } 982 982 ··· 985 985 dev_err(&pdev->dev, 986 986 "Can't register Freescale eDMA of_dma. (%d)\n", ret); 987 987 dma_async_device_unregister(&fsl_edma->dma_dev); 988 - fsl_disable_clocks(fsl_edma); 988 + fsl_disable_clocks(fsl_edma, DMAMUX_NR); 989 989 return ret; 990 990 } 991 991 ··· 1015 1015 fsl_edma_cleanup_vchan(&fsl_edma->dma_dev); 1016 1016 of_dma_controller_free(np); 1017 1017 dma_async_device_unregister(&fsl_edma->dma_dev); 1018 - fsl_disable_clocks(fsl_edma); 1018 + fsl_disable_clocks(fsl_edma, DMAMUX_NR); 1019 1019 1020 1020 return 0; 1021 1021 }
+1 -1
drivers/dma/ioat/init.c
··· 390 390 if (memcmp(src, dest, IOAT_TEST_SIZE)) { 391 391 dev_err(dev, "Self-test copy failed compare, disabling\n"); 392 392 err = -ENODEV; 393 - goto free_resources; 393 + goto unmap_dma; 394 394 } 395 395 396 396 unmap_dma: