static int fsl_edma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) { struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); struct dma_slave_config *cfg = (void *)arg; unsigned long flags; LIST_HEAD(head); switch (cmd) { case DMA_TERMINATE_ALL: spin_lock_irqsave(&fsl_chan->vchan.lock, flags); fsl_edma_disable_request(fsl_chan); fsl_chan->edesc = NULL; vchan_get_all_descriptors(&fsl_chan->vchan, &head); spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags); vchan_dma_desc_free_list(&fsl_chan->vchan, &head); return 0; case DMA_SLAVE_CONFIG: fsl_chan->fsc.dir = cfg->direction; if (cfg->direction == DMA_DEV_TO_MEM) { fsl_chan->fsc.dev_addr = cfg->src_addr; fsl_chan->fsc.addr_width = cfg->src_addr_width; fsl_chan->fsc.burst = cfg->src_maxburst; fsl_chan->fsc.attr = fsl_edma_get_tcd_attr(cfg->src_addr_width); } else if (cfg->direction == DMA_MEM_TO_DEV) { fsl_chan->fsc.dev_addr = cfg->dst_addr; fsl_chan->fsc.addr_width = cfg->dst_addr_width; fsl_chan->fsc.burst = cfg->dst_maxburst; fsl_chan->fsc.attr = fsl_edma_get_tcd_attr(cfg->dst_addr_width); } else { return -EINVAL; } return 0; case DMA_PAUSE: spin_lock_irqsave(&fsl_chan->vchan.lock, flags); if (fsl_chan->edesc) { fsl_edma_disable_request(fsl_chan); fsl_chan->status = DMA_PAUSED; } spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags); return 0; case DMA_RESUME: spin_lock_irqsave(&fsl_chan->vchan.lock, flags); if (fsl_chan->edesc) { fsl_edma_enable_request(fsl_chan); fsl_chan->status = DMA_IN_PROGRESS; } spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags); return 0; default: return -ENXIO; } }
static int fsl_edma_terminate_all(struct dma_chan *chan) { struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); unsigned long flags; LIST_HEAD(head); spin_lock_irqsave(&fsl_chan->vchan.lock, flags); fsl_edma_disable_request(fsl_chan); fsl_chan->edesc = NULL; vchan_get_all_descriptors(&fsl_chan->vchan, &head); spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags); vchan_dma_desc_free_list(&fsl_chan->vchan, &head); return 0; }
static int tegra_adma_terminate_all(struct dma_chan *dc) { struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); unsigned long flags; LIST_HEAD(head); spin_lock_irqsave(&tdc->vc.lock, flags); if (tdc->desc) tegra_adma_stop(tdc); tegra_adma_request_free(tdc); vchan_get_all_descriptors(&tdc->vc, &head); spin_unlock_irqrestore(&tdc->vc.lock, flags); vchan_dma_desc_free_list(&tdc->vc, &head); return 0; }