.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * DMA driver for Xilinx ZynqMP DMA Engine |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2016 Xilinx, Inc. All rights reserved. |
---|
5 | | - * |
---|
6 | | - * This program is free software: you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation, either version 2 of the License, or |
---|
9 | | - * (at your option) any later version. |
---|
10 | 6 | */ |
---|
11 | 7 | |
---|
12 | 8 | #include <linux/bitops.h> |
---|
.. | .. |
---|
236 | 232 | bool is_dmacoherent; |
---|
237 | 233 | struct tasklet_struct tasklet; |
---|
238 | 234 | bool idle; |
---|
239 | | - u32 desc_size; |
---|
| 235 | + size_t desc_size; |
---|
240 | 236 | bool err; |
---|
241 | 237 | u32 bus_width; |
---|
242 | 238 | u32 src_burst_len; |
---|
.. | .. |
---|
377 | 373 | struct zynqmp_dma_chan *chan = to_chan(tx->chan); |
---|
378 | 374 | struct zynqmp_dma_desc_sw *desc, *new; |
---|
379 | 375 | dma_cookie_t cookie; |
---|
| 376 | + unsigned long irqflags; |
---|
380 | 377 | |
---|
381 | 378 | new = tx_to_desc(tx); |
---|
382 | | - spin_lock_bh(&chan->lock); |
---|
| 379 | + spin_lock_irqsave(&chan->lock, irqflags); |
---|
383 | 380 | cookie = dma_cookie_assign(tx); |
---|
384 | 381 | |
---|
385 | 382 | if (!list_empty(&chan->pending_list)) { |
---|
.. | .. |
---|
395 | 392 | } |
---|
396 | 393 | |
---|
397 | 394 | list_add_tail(&new->node, &chan->pending_list); |
---|
398 | | - spin_unlock_bh(&chan->lock); |
---|
| 395 | + spin_unlock_irqrestore(&chan->lock, irqflags); |
---|
399 | 396 | |
---|
400 | 397 | return cookie; |
---|
401 | 398 | } |
---|
.. | .. |
---|
410 | 407 | zynqmp_dma_get_descriptor(struct zynqmp_dma_chan *chan) |
---|
411 | 408 | { |
---|
412 | 409 | struct zynqmp_dma_desc_sw *desc; |
---|
| 410 | + unsigned long irqflags; |
---|
413 | 411 | |
---|
414 | | - spin_lock_bh(&chan->lock); |
---|
| 412 | + spin_lock_irqsave(&chan->lock, irqflags); |
---|
415 | 413 | desc = list_first_entry(&chan->free_list, |
---|
416 | 414 | struct zynqmp_dma_desc_sw, node); |
---|
417 | 415 | list_del(&desc->node); |
---|
418 | | - spin_unlock_bh(&chan->lock); |
---|
| 416 | + spin_unlock_irqrestore(&chan->lock, irqflags); |
---|
419 | 417 | |
---|
420 | 418 | INIT_LIST_HEAD(&desc->tx_list); |
---|
421 | 419 | /* Clear the src and dst descriptor memory */ |
---|
.. | .. |
---|
436 | 434 | struct zynqmp_dma_desc_sw *child, *next; |
---|
437 | 435 | |
---|
438 | 436 | chan->desc_free_cnt++; |
---|
| 437 | + list_del(&sdesc->node); |
---|
439 | 438 | list_add_tail(&sdesc->node, &chan->free_list); |
---|
440 | 439 | list_for_each_entry_safe(child, next, &sdesc->tx_list, node) { |
---|
441 | 440 | chan->desc_free_cnt++; |
---|
.. | .. |
---|
469 | 468 | struct zynqmp_dma_desc_sw *desc; |
---|
470 | 469 | int i, ret; |
---|
471 | 470 | |
---|
472 | | - ret = pm_runtime_get_sync(chan->dev); |
---|
| 471 | + ret = pm_runtime_resume_and_get(chan->dev); |
---|
473 | 472 | if (ret < 0) |
---|
474 | 473 | return ret; |
---|
475 | 474 | |
---|
.. | .. |
---|
490 | 489 | list_add_tail(&desc->node, &chan->free_list); |
---|
491 | 490 | } |
---|
492 | 491 | |
---|
493 | | - chan->desc_pool_v = dma_zalloc_coherent(chan->dev, |
---|
494 | | - (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS), |
---|
495 | | - &chan->desc_pool_p, GFP_KERNEL); |
---|
| 492 | + chan->desc_pool_v = dma_alloc_coherent(chan->dev, |
---|
| 493 | + (2 * ZYNQMP_DMA_DESC_SIZE(chan) * |
---|
| 494 | + ZYNQMP_DMA_NUM_DESCS), |
---|
| 495 | + &chan->desc_pool_p, GFP_KERNEL); |
---|
496 | 496 | if (!chan->desc_pool_v) |
---|
497 | 497 | return -ENOMEM; |
---|
498 | 498 | |
---|
.. | .. |
---|
610 | 610 | dma_async_tx_callback callback; |
---|
611 | 611 | void *callback_param; |
---|
612 | 612 | |
---|
613 | | - list_del(&desc->node); |
---|
614 | | - |
---|
615 | 613 | callback = desc->async_tx.callback; |
---|
616 | 614 | callback_param = desc->async_tx.callback_param; |
---|
617 | 615 | if (callback) { |
---|
.. | .. |
---|
649 | 647 | static void zynqmp_dma_issue_pending(struct dma_chan *dchan) |
---|
650 | 648 | { |
---|
651 | 649 | struct zynqmp_dma_chan *chan = to_chan(dchan); |
---|
| 650 | + unsigned long irqflags; |
---|
652 | 651 | |
---|
653 | | - spin_lock_bh(&chan->lock); |
---|
| 652 | + spin_lock_irqsave(&chan->lock, irqflags); |
---|
654 | 653 | zynqmp_dma_start_transfer(chan); |
---|
655 | | - spin_unlock_bh(&chan->lock); |
---|
| 654 | + spin_unlock_irqrestore(&chan->lock, irqflags); |
---|
656 | 655 | } |
---|
657 | 656 | |
---|
658 | 657 | /** |
---|
.. | .. |
---|
673 | 672 | static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan) |
---|
674 | 673 | { |
---|
675 | 674 | struct zynqmp_dma_chan *chan = to_chan(dchan); |
---|
| 675 | + unsigned long irqflags; |
---|
676 | 676 | |
---|
677 | | - spin_lock_bh(&chan->lock); |
---|
| 677 | + spin_lock_irqsave(&chan->lock, irqflags); |
---|
678 | 678 | zynqmp_dma_free_descriptors(chan); |
---|
679 | | - spin_unlock_bh(&chan->lock); |
---|
| 679 | + spin_unlock_irqrestore(&chan->lock, irqflags); |
---|
680 | 680 | dma_free_coherent(chan->dev, |
---|
681 | 681 | (2 * ZYNQMP_DMA_DESC_SIZE(chan) * ZYNQMP_DMA_NUM_DESCS), |
---|
682 | 682 | chan->desc_pool_v, chan->desc_pool_p); |
---|
.. | .. |
---|
743 | 743 | |
---|
744 | 744 | /** |
---|
745 | 745 | * zynqmp_dma_do_tasklet - Schedule completion tasklet |
---|
746 | | - * @data: Pointer to the ZynqMP DMA channel structure |
---|
| 746 | + * @t: Pointer to the ZynqMP DMA channel structure |
---|
747 | 747 | */ |
---|
748 | | -static void zynqmp_dma_do_tasklet(unsigned long data) |
---|
| 748 | +static void zynqmp_dma_do_tasklet(struct tasklet_struct *t) |
---|
749 | 749 | { |
---|
750 | | - struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data; |
---|
| 750 | + struct zynqmp_dma_chan *chan = from_tasklet(chan, t, tasklet); |
---|
751 | 751 | u32 count; |
---|
| 752 | + unsigned long irqflags; |
---|
752 | 753 | |
---|
753 | | - spin_lock(&chan->lock); |
---|
| 754 | + spin_lock_irqsave(&chan->lock, irqflags); |
---|
754 | 755 | |
---|
755 | 756 | if (chan->err) { |
---|
756 | 757 | zynqmp_dma_reset(chan); |
---|
.. | .. |
---|
770 | 771 | zynqmp_dma_start_transfer(chan); |
---|
771 | 772 | |
---|
772 | 773 | unlock: |
---|
773 | | - spin_unlock(&chan->lock); |
---|
| 774 | + spin_unlock_irqrestore(&chan->lock, irqflags); |
---|
774 | 775 | } |
---|
775 | 776 | |
---|
776 | 777 | /** |
---|
.. | .. |
---|
782 | 783 | static int zynqmp_dma_device_terminate_all(struct dma_chan *dchan) |
---|
783 | 784 | { |
---|
784 | 785 | struct zynqmp_dma_chan *chan = to_chan(dchan); |
---|
| 786 | + unsigned long irqflags; |
---|
785 | 787 | |
---|
786 | | - spin_lock_bh(&chan->lock); |
---|
| 788 | + spin_lock_irqsave(&chan->lock, irqflags); |
---|
787 | 789 | writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS); |
---|
788 | 790 | zynqmp_dma_free_descriptors(chan); |
---|
789 | | - spin_unlock_bh(&chan->lock); |
---|
| 791 | + spin_unlock_irqrestore(&chan->lock, irqflags); |
---|
790 | 792 | |
---|
791 | 793 | return 0; |
---|
792 | 794 | } |
---|
.. | .. |
---|
810 | 812 | void *desc = NULL, *prev = NULL; |
---|
811 | 813 | size_t copy; |
---|
812 | 814 | u32 desc_cnt; |
---|
| 815 | + unsigned long irqflags; |
---|
813 | 816 | |
---|
814 | 817 | chan = to_chan(dchan); |
---|
815 | 818 | |
---|
816 | 819 | desc_cnt = DIV_ROUND_UP(len, ZYNQMP_DMA_MAX_TRANS_LEN); |
---|
817 | 820 | |
---|
818 | | - spin_lock_bh(&chan->lock); |
---|
| 821 | + spin_lock_irqsave(&chan->lock, irqflags); |
---|
819 | 822 | if (desc_cnt > chan->desc_free_cnt) { |
---|
820 | | - spin_unlock_bh(&chan->lock); |
---|
| 823 | + spin_unlock_irqrestore(&chan->lock, irqflags); |
---|
821 | 824 | dev_dbg(chan->dev, "chan %p descs are not available\n", chan); |
---|
822 | 825 | return NULL; |
---|
823 | 826 | } |
---|
824 | 827 | chan->desc_free_cnt = chan->desc_free_cnt - desc_cnt; |
---|
825 | | - spin_unlock_bh(&chan->lock); |
---|
| 828 | + spin_unlock_irqrestore(&chan->lock, irqflags); |
---|
826 | 829 | |
---|
827 | 830 | do { |
---|
828 | 831 | /* Allocate and populate the descriptor */ |
---|
.. | .. |
---|
906 | 909 | |
---|
907 | 910 | chan->is_dmacoherent = of_property_read_bool(node, "dma-coherent"); |
---|
908 | 911 | zdev->chan = chan; |
---|
909 | | - tasklet_init(&chan->tasklet, zynqmp_dma_do_tasklet, (ulong)chan); |
---|
| 912 | + tasklet_setup(&chan->tasklet, zynqmp_dma_do_tasklet); |
---|
910 | 913 | spin_lock_init(&chan->lock); |
---|
911 | 914 | INIT_LIST_HEAD(&chan->active_list); |
---|
912 | 915 | INIT_LIST_HEAD(&chan->pending_list); |
---|