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

Merge branch 'topic/xilinx' into for-linus

+35 -28
+35 -28
drivers/dma/xilinx/xilinx_dma.c
··· 331 331 * @seg_v: Statically allocated segments base 332 332 * @cyclic_seg_v: Statically allocated segment base for cyclic transfers 333 333 * @start_transfer: Differentiate b/w DMA IP's transfer 334 + * @stop_transfer: Differentiate b/w DMA IP's quiesce 334 335 */ 335 336 struct xilinx_dma_chan { 336 337 struct xilinx_dma_device *xdev; ··· 362 361 struct xilinx_axidma_tx_segment *seg_v; 363 362 struct xilinx_axidma_tx_segment *cyclic_seg_v; 364 363 void (*start_transfer)(struct xilinx_dma_chan *chan); 364 + int (*stop_transfer)(struct xilinx_dma_chan *chan); 365 365 u16 tdest; 366 366 }; 367 367 ··· 948 946 } 949 947 950 948 /** 951 - * xilinx_dma_halt - Halt DMA channel 949 + * xilinx_dma_stop_transfer - Halt DMA channel 952 950 * @chan: Driver specific DMA channel 953 951 */ 954 - static void xilinx_dma_halt(struct xilinx_dma_chan *chan) 952 + static int xilinx_dma_stop_transfer(struct xilinx_dma_chan *chan) 955 953 { 956 - int err; 957 954 u32 val; 958 955 959 956 dma_ctrl_clr(chan, XILINX_DMA_REG_DMACR, XILINX_DMA_DMACR_RUNSTOP); 960 957 961 958 /* Wait for the hardware to halt */ 962 - err = xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val, 963 - (val & XILINX_DMA_DMASR_HALTED), 0, 964 - XILINX_DMA_LOOP_COUNT); 959 + return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val, 960 + val & XILINX_DMA_DMASR_HALTED, 0, 961 + XILINX_DMA_LOOP_COUNT); 962 + } 965 963 966 - if (err) { 967 - dev_err(chan->dev, "Cannot stop channel %p: %x\n", 968 - chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR)); 969 - chan->err = true; 970 - } 964 + /** 965 + * xilinx_cdma_stop_transfer - Wait for the current transfer to complete 966 + * @chan: Driver specific DMA channel 967 + */ 968 + static int xilinx_cdma_stop_transfer(struct xilinx_dma_chan *chan) 969 + { 970 + u32 val; 971 + 972 + return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val, 973 + val & XILINX_DMA_DMASR_IDLE, 0, 974 + XILINX_DMA_LOOP_COUNT); 971 975 } 972 976 973 977 /** ··· 1661 1653 { 1662 1654 struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); 1663 1655 struct xilinx_dma_tx_descriptor *desc; 1664 - struct xilinx_cdma_tx_segment *segment, *prev; 1656 + struct xilinx_cdma_tx_segment *segment; 1665 1657 struct xilinx_cdma_desc_hw *hw; 1666 1658 1667 1659 if (!len || len > XILINX_DMA_MAX_TRANS_LEN) ··· 1688 1680 hw->dest_addr_msb = upper_32_bits(dma_dst); 1689 1681 } 1690 1682 1691 - /* Fill the previous next descriptor with current */ 1692 - prev = list_last_entry(&desc->segments, 1693 - struct xilinx_cdma_tx_segment, node); 1694 - prev->hw.next_desc = segment->phys; 1695 - 1696 1683 /* Insert the segment into the descriptor segments list. */ 1697 1684 list_add_tail(&segment->node, &desc->segments); 1698 1685 1699 - prev = segment; 1700 - 1701 - /* Link the last hardware descriptor with the first. */ 1702 - segment = list_first_entry(&desc->segments, 1703 - struct xilinx_cdma_tx_segment, node); 1704 1686 desc->async_tx.phys = segment->phys; 1705 - prev->hw.next_desc = segment->phys; 1687 + hw->next_desc = segment->phys; 1706 1688 1707 1689 return &desc->async_tx; 1708 1690 ··· 2001 2003 { 2002 2004 struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); 2003 2005 u32 reg; 2006 + int err; 2004 2007 2005 2008 if (chan->cyclic) 2006 2009 xilinx_dma_chan_reset(chan); 2007 2010 2008 - /* Halt the DMA engine */ 2009 - xilinx_dma_halt(chan); 2011 + err = chan->stop_transfer(chan); 2012 + if (err) { 2013 + dev_err(chan->dev, "Cannot stop channel %p: %x\n", 2014 + chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR)); 2015 + chan->err = true; 2016 + } 2010 2017 2011 2018 /* Remove and free all of the descriptors in the lists */ 2012 2019 xilinx_dma_free_descriptors(chan); ··· 2400 2397 return err; 2401 2398 } 2402 2399 2403 - if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) 2400 + if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) { 2404 2401 chan->start_transfer = xilinx_dma_start_transfer; 2405 - else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) 2402 + chan->stop_transfer = xilinx_dma_stop_transfer; 2403 + } else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) { 2406 2404 chan->start_transfer = xilinx_cdma_start_transfer; 2407 - else 2405 + chan->stop_transfer = xilinx_cdma_stop_transfer; 2406 + } else { 2408 2407 chan->start_transfer = xilinx_vdma_start_transfer; 2408 + chan->stop_transfer = xilinx_dma_stop_transfer; 2409 + } 2409 2410 2410 2411 /* Initialize the tasklet */ 2411 2412 tasklet_init(&chan->tasklet, xilinx_dma_do_tasklet,