Re: [PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support
On Tue, Sep 06, 2016 at 12:52:03PM +0100, Jon Hunter wrote: > > + /* TODO: ADMA should support up to 8 chunks or periods */ > > + desc->num_periods = 1; > > + desc->buf_len = buf_len; > > + desc->period_len = buf_len; > What would be the benefit of using 8 periods here? My understanding is > that you will get an interrupt per period and do you really want this > for memcpy? You are right about the interrupt. And it doesn't seem to be beneficial unless the period size is over the limitation of Transfer Count, which is rare but might theoretically exist? I admit the "TODO" word here is a bit misleading for memcpy. I can remove the word and write a more appropriate comments.
Re: [PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support
On Tue, Sep 06, 2016 at 12:52:03PM +0100, Jon Hunter wrote: > > + /* TODO: ADMA should support up to 8 chunks or periods */ > > + desc->num_periods = 1; > > + desc->buf_len = buf_len; > > + desc->period_len = buf_len; > What would be the benefit of using 8 periods here? My understanding is > that you will get an interrupt per period and do you really want this > for memcpy? You are right about the interrupt. And it doesn't seem to be beneficial unless the period size is over the limitation of Transfer Count, which is rare but might theoretically exist? I admit the "TODO" word here is a bit misleading for memcpy. I can remove the word and write a more appropriate comments.
Re: [PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support
On 03/09/16 01:32, Nicolin Chen wrote: > ADMA supports non-flow controlled Memory-to-Memory direction > transactions. So this patch just adds an initial support for > that. It passed a simple dmatest: > echo dma1chan0 > /sys/module/dmatest/parameters/channel > echo 1024 > /sys/module/dmatest/parameters/iterations > echo 0 > /sys/module/dmatest/parameters/dmatest > echo 1 > /sys/module/dmatest/parameters/run > dmesg | grep dmatest > Started 1 threads using dma1chan0 > dma1chan0-copy0: summary 1024 tests, 0 failures 2054 iops 16520 KB/s (0) > > Signed-off-by: Nicolin Chen> --- > drivers/dma/tegra210-adma.c | 95 > +++-- > 1 file changed, 83 insertions(+), 12 deletions(-) > > diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c > index 5b5d298..d62b373 100644 > --- a/drivers/dma/tegra210-adma.c > +++ b/drivers/dma/tegra210-adma.c > @@ -42,9 +42,14 @@ > #define ADMA_CH_CTRL_RX_REQ(val) (((val) & 0xf) << 24) > #define ADMA_CH_CTRL_RX_REQ_MAX 10 > #define ADMA_CH_CTRL_DIR(val)(((val) & 0xf) > << 12) > +#define ADMA_CH_CTRL_DIR_MEM2MEM 1 > #define ADMA_CH_CTRL_DIR_AHUB2MEM2 > #define ADMA_CH_CTRL_DIR_MEM2AHUB4 > -#define ADMA_CH_CTRL_MODE_CONTINUOUS (2 << 8) > +#define ADMA_CH_CTRL_DIR_AHUB2AHUB 8 > +#define ADMA_CH_CTRL_MODE(val) (((val) & 0x7) > << 8) > +#define ADMA_CH_CTRL_MODE_ONCE 1 > +#define ADMA_CH_CTRL_MODE_CONTINUOUS 2 > +#define ADMA_CH_CTRL_MODE_LINKED_LIST4 > #define ADMA_CH_CTRL_FLOWCTRL_EN BIT(1) > > #define ADMA_CH_CONFIG 0x28 > @@ -264,6 +269,9 @@ static int tegra_adma_request_alloc(struct > tegra_adma_chan *tdc, > } > break; > > + case DMA_MEM_TO_MEM: > + break; > + > default: > dev_WARN(tdma->dev, "channel %s has invalid transfer type\n", >dma_chan_name(>vc.chan)); > @@ -292,6 +300,9 @@ static void tegra_adma_request_free(struct > tegra_adma_chan *tdc) > clear_bit(tdc->sreq_index, >rx_requests_reserved); > break; > > + case DMA_MEM_TO_MEM: > + break; > + > default: > dev_WARN(tdma->dev, "channel %s has invalid transfer type\n", >dma_chan_name(>vc.chan)); > @@ -409,8 +420,14 @@ static irqreturn_t tegra_adma_isr(int irq, void *dev_id) > return IRQ_NONE; > } > > - if (tdc->desc->cyclic) > + if (tdc->desc->cyclic) { > vchan_cyclic_callback(>desc->vd); > + } else { > + /* Disable the channel */ > + tdma_ch_write(tdc, ADMA_CH_CMD, 0); > + vchan_cookie_complete(>desc->vd); > + tdc->desc = NULL; > + } > > spin_unlock_irqrestore(>vc.lock, flags); > > @@ -488,42 +505,59 @@ static enum dma_status tegra_adma_tx_status(struct > dma_chan *dc, > static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, > struct tegra_adma_desc *desc, > dma_addr_t buf_addr, > + dma_addr_t buf_addr2, > enum dma_transfer_direction direction) > { > struct tegra_adma_chan_regs *ch_regs = >ch_regs; > - unsigned int burst_size, adma_dir; > + unsigned int num_periods = desc->num_periods; > + unsigned int burst_size, adma_dir, adma_mode; > > - if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS) > + if (num_periods > ADMA_CH_CONFIG_MAX_BUFS) > return -EINVAL; > > switch (direction) { > case DMA_MEM_TO_DEV: > adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB; > burst_size = fls(tdc->sconfig.dst_maxburst); > - ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1); > - ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index); > + ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(num_periods - 1); > + ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index) | > + ADMA_CH_CTRL_FLOWCTRL_EN; > ch_regs->src_addr = buf_addr; > break; > > case DMA_DEV_TO_MEM: > adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM; > burst_size = fls(tdc->sconfig.src_maxburst); > - ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1); > - ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index); > + ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(num_periods - 1); > + ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index) | > +
Re: [PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support
On 03/09/16 01:32, Nicolin Chen wrote: > ADMA supports non-flow controlled Memory-to-Memory direction > transactions. So this patch just adds an initial support for > that. It passed a simple dmatest: > echo dma1chan0 > /sys/module/dmatest/parameters/channel > echo 1024 > /sys/module/dmatest/parameters/iterations > echo 0 > /sys/module/dmatest/parameters/dmatest > echo 1 > /sys/module/dmatest/parameters/run > dmesg | grep dmatest > Started 1 threads using dma1chan0 > dma1chan0-copy0: summary 1024 tests, 0 failures 2054 iops 16520 KB/s (0) > > Signed-off-by: Nicolin Chen > --- > drivers/dma/tegra210-adma.c | 95 > +++-- > 1 file changed, 83 insertions(+), 12 deletions(-) > > diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c > index 5b5d298..d62b373 100644 > --- a/drivers/dma/tegra210-adma.c > +++ b/drivers/dma/tegra210-adma.c > @@ -42,9 +42,14 @@ > #define ADMA_CH_CTRL_RX_REQ(val) (((val) & 0xf) << 24) > #define ADMA_CH_CTRL_RX_REQ_MAX 10 > #define ADMA_CH_CTRL_DIR(val)(((val) & 0xf) > << 12) > +#define ADMA_CH_CTRL_DIR_MEM2MEM 1 > #define ADMA_CH_CTRL_DIR_AHUB2MEM2 > #define ADMA_CH_CTRL_DIR_MEM2AHUB4 > -#define ADMA_CH_CTRL_MODE_CONTINUOUS (2 << 8) > +#define ADMA_CH_CTRL_DIR_AHUB2AHUB 8 > +#define ADMA_CH_CTRL_MODE(val) (((val) & 0x7) > << 8) > +#define ADMA_CH_CTRL_MODE_ONCE 1 > +#define ADMA_CH_CTRL_MODE_CONTINUOUS 2 > +#define ADMA_CH_CTRL_MODE_LINKED_LIST4 > #define ADMA_CH_CTRL_FLOWCTRL_EN BIT(1) > > #define ADMA_CH_CONFIG 0x28 > @@ -264,6 +269,9 @@ static int tegra_adma_request_alloc(struct > tegra_adma_chan *tdc, > } > break; > > + case DMA_MEM_TO_MEM: > + break; > + > default: > dev_WARN(tdma->dev, "channel %s has invalid transfer type\n", >dma_chan_name(>vc.chan)); > @@ -292,6 +300,9 @@ static void tegra_adma_request_free(struct > tegra_adma_chan *tdc) > clear_bit(tdc->sreq_index, >rx_requests_reserved); > break; > > + case DMA_MEM_TO_MEM: > + break; > + > default: > dev_WARN(tdma->dev, "channel %s has invalid transfer type\n", >dma_chan_name(>vc.chan)); > @@ -409,8 +420,14 @@ static irqreturn_t tegra_adma_isr(int irq, void *dev_id) > return IRQ_NONE; > } > > - if (tdc->desc->cyclic) > + if (tdc->desc->cyclic) { > vchan_cyclic_callback(>desc->vd); > + } else { > + /* Disable the channel */ > + tdma_ch_write(tdc, ADMA_CH_CMD, 0); > + vchan_cookie_complete(>desc->vd); > + tdc->desc = NULL; > + } > > spin_unlock_irqrestore(>vc.lock, flags); > > @@ -488,42 +505,59 @@ static enum dma_status tegra_adma_tx_status(struct > dma_chan *dc, > static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, > struct tegra_adma_desc *desc, > dma_addr_t buf_addr, > + dma_addr_t buf_addr2, > enum dma_transfer_direction direction) > { > struct tegra_adma_chan_regs *ch_regs = >ch_regs; > - unsigned int burst_size, adma_dir; > + unsigned int num_periods = desc->num_periods; > + unsigned int burst_size, adma_dir, adma_mode; > > - if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS) > + if (num_periods > ADMA_CH_CONFIG_MAX_BUFS) > return -EINVAL; > > switch (direction) { > case DMA_MEM_TO_DEV: > adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB; > burst_size = fls(tdc->sconfig.dst_maxburst); > - ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1); > - ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index); > + ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(num_periods - 1); > + ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index) | > + ADMA_CH_CTRL_FLOWCTRL_EN; > ch_regs->src_addr = buf_addr; > break; > > case DMA_DEV_TO_MEM: > adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM; > burst_size = fls(tdc->sconfig.src_maxburst); > - ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1); > - ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index); > + ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(num_periods - 1); > + ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index) | > +
[PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support
ADMA supports non-flow controlled Memory-to-Memory direction transactions. So this patch just adds an initial support for that. It passed a simple dmatest: echo dma1chan0 > /sys/module/dmatest/parameters/channel echo 1024 > /sys/module/dmatest/parameters/iterations echo 0 > /sys/module/dmatest/parameters/dmatest echo 1 > /sys/module/dmatest/parameters/run dmesg | grep dmatest Started 1 threads using dma1chan0 dma1chan0-copy0: summary 1024 tests, 0 failures 2054 iops 16520 KB/s (0) Signed-off-by: Nicolin Chen--- drivers/dma/tegra210-adma.c | 95 +++-- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index 5b5d298..d62b373 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -42,9 +42,14 @@ #define ADMA_CH_CTRL_RX_REQ(val) (((val) & 0xf) << 24) #define ADMA_CH_CTRL_RX_REQ_MAX10 #define ADMA_CH_CTRL_DIR(val) (((val) & 0xf) << 12) +#define ADMA_CH_CTRL_DIR_MEM2MEM 1 #define ADMA_CH_CTRL_DIR_AHUB2MEM 2 #define ADMA_CH_CTRL_DIR_MEM2AHUB 4 -#define ADMA_CH_CTRL_MODE_CONTINUOUS (2 << 8) +#define ADMA_CH_CTRL_DIR_AHUB2AHUB 8 +#define ADMA_CH_CTRL_MODE(val) (((val) & 0x7) << 8) +#define ADMA_CH_CTRL_MODE_ONCE 1 +#define ADMA_CH_CTRL_MODE_CONTINUOUS 2 +#define ADMA_CH_CTRL_MODE_LINKED_LIST 4 #define ADMA_CH_CTRL_FLOWCTRL_EN BIT(1) #define ADMA_CH_CONFIG 0x28 @@ -264,6 +269,9 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc, } break; + case DMA_MEM_TO_MEM: + break; + default: dev_WARN(tdma->dev, "channel %s has invalid transfer type\n", dma_chan_name(>vc.chan)); @@ -292,6 +300,9 @@ static void tegra_adma_request_free(struct tegra_adma_chan *tdc) clear_bit(tdc->sreq_index, >rx_requests_reserved); break; + case DMA_MEM_TO_MEM: + break; + default: dev_WARN(tdma->dev, "channel %s has invalid transfer type\n", dma_chan_name(>vc.chan)); @@ -409,8 +420,14 @@ static irqreturn_t tegra_adma_isr(int irq, void *dev_id) return IRQ_NONE; } - if (tdc->desc->cyclic) + if (tdc->desc->cyclic) { vchan_cyclic_callback(>desc->vd); + } else { + /* Disable the channel */ + tdma_ch_write(tdc, ADMA_CH_CMD, 0); + vchan_cookie_complete(>desc->vd); + tdc->desc = NULL; + } spin_unlock_irqrestore(>vc.lock, flags); @@ -488,42 +505,59 @@ static enum dma_status tegra_adma_tx_status(struct dma_chan *dc, static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, struct tegra_adma_desc *desc, dma_addr_t buf_addr, + dma_addr_t buf_addr2, enum dma_transfer_direction direction) { struct tegra_adma_chan_regs *ch_regs = >ch_regs; - unsigned int burst_size, adma_dir; + unsigned int num_periods = desc->num_periods; + unsigned int burst_size, adma_dir, adma_mode; - if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS) + if (num_periods > ADMA_CH_CONFIG_MAX_BUFS) return -EINVAL; switch (direction) { case DMA_MEM_TO_DEV: adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB; burst_size = fls(tdc->sconfig.dst_maxburst); - ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1); - ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index); + ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(num_periods - 1); + ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index) | + ADMA_CH_CTRL_FLOWCTRL_EN; ch_regs->src_addr = buf_addr; break; case DMA_DEV_TO_MEM: adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM; burst_size = fls(tdc->sconfig.src_maxburst); - ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1); - ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index); + ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(num_periods - 1); + ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index) | + ADMA_CH_CTRL_FLOWCTRL_EN; ch_regs->trg_addr = buf_addr; break; + case DMA_MEM_TO_MEM: +
[PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support
ADMA supports non-flow controlled Memory-to-Memory direction transactions. So this patch just adds an initial support for that. It passed a simple dmatest: echo dma1chan0 > /sys/module/dmatest/parameters/channel echo 1024 > /sys/module/dmatest/parameters/iterations echo 0 > /sys/module/dmatest/parameters/dmatest echo 1 > /sys/module/dmatest/parameters/run dmesg | grep dmatest Started 1 threads using dma1chan0 dma1chan0-copy0: summary 1024 tests, 0 failures 2054 iops 16520 KB/s (0) Signed-off-by: Nicolin Chen --- drivers/dma/tegra210-adma.c | 95 +++-- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index 5b5d298..d62b373 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -42,9 +42,14 @@ #define ADMA_CH_CTRL_RX_REQ(val) (((val) & 0xf) << 24) #define ADMA_CH_CTRL_RX_REQ_MAX10 #define ADMA_CH_CTRL_DIR(val) (((val) & 0xf) << 12) +#define ADMA_CH_CTRL_DIR_MEM2MEM 1 #define ADMA_CH_CTRL_DIR_AHUB2MEM 2 #define ADMA_CH_CTRL_DIR_MEM2AHUB 4 -#define ADMA_CH_CTRL_MODE_CONTINUOUS (2 << 8) +#define ADMA_CH_CTRL_DIR_AHUB2AHUB 8 +#define ADMA_CH_CTRL_MODE(val) (((val) & 0x7) << 8) +#define ADMA_CH_CTRL_MODE_ONCE 1 +#define ADMA_CH_CTRL_MODE_CONTINUOUS 2 +#define ADMA_CH_CTRL_MODE_LINKED_LIST 4 #define ADMA_CH_CTRL_FLOWCTRL_EN BIT(1) #define ADMA_CH_CONFIG 0x28 @@ -264,6 +269,9 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc, } break; + case DMA_MEM_TO_MEM: + break; + default: dev_WARN(tdma->dev, "channel %s has invalid transfer type\n", dma_chan_name(>vc.chan)); @@ -292,6 +300,9 @@ static void tegra_adma_request_free(struct tegra_adma_chan *tdc) clear_bit(tdc->sreq_index, >rx_requests_reserved); break; + case DMA_MEM_TO_MEM: + break; + default: dev_WARN(tdma->dev, "channel %s has invalid transfer type\n", dma_chan_name(>vc.chan)); @@ -409,8 +420,14 @@ static irqreturn_t tegra_adma_isr(int irq, void *dev_id) return IRQ_NONE; } - if (tdc->desc->cyclic) + if (tdc->desc->cyclic) { vchan_cyclic_callback(>desc->vd); + } else { + /* Disable the channel */ + tdma_ch_write(tdc, ADMA_CH_CMD, 0); + vchan_cookie_complete(>desc->vd); + tdc->desc = NULL; + } spin_unlock_irqrestore(>vc.lock, flags); @@ -488,42 +505,59 @@ static enum dma_status tegra_adma_tx_status(struct dma_chan *dc, static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, struct tegra_adma_desc *desc, dma_addr_t buf_addr, + dma_addr_t buf_addr2, enum dma_transfer_direction direction) { struct tegra_adma_chan_regs *ch_regs = >ch_regs; - unsigned int burst_size, adma_dir; + unsigned int num_periods = desc->num_periods; + unsigned int burst_size, adma_dir, adma_mode; - if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS) + if (num_periods > ADMA_CH_CONFIG_MAX_BUFS) return -EINVAL; switch (direction) { case DMA_MEM_TO_DEV: adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB; burst_size = fls(tdc->sconfig.dst_maxburst); - ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1); - ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index); + ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(num_periods - 1); + ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index) | + ADMA_CH_CTRL_FLOWCTRL_EN; ch_regs->src_addr = buf_addr; break; case DMA_DEV_TO_MEM: adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM; burst_size = fls(tdc->sconfig.src_maxburst); - ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1); - ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index); + ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(num_periods - 1); + ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index) | + ADMA_CH_CTRL_FLOWCTRL_EN; ch_regs->trg_addr = buf_addr; break; + case DMA_MEM_TO_MEM: + adma_dir =