Hi Vinod/Dan,
This patchset does following:
- Includes earlier patchset sent by Rajeev for cleanly applying this patchset
- Adds device_fc (device flow control) field in struct DMA_SLAVE_CONFIG
- Fixes existing users of DMAENGINE for device_fc.
- Updates pl08x driver according to that
- Fixes few issues/bugs in dw_dmac driver
- Adds DMA_SLAVE_CONFIG for dw_dmac driver
- Fixes existing users of dw_dmac driver
Change History:
Since V1:
- used dev_get_platdata() instead of platform_get_drvdata(), as that was
incorrect
- Lots of fixes in: dmaengine/dw_dmac: Add support for DMA_SLAVE_CONFIG
- Additional patches:
- dmaengine/dw_dmac: Add 64 bit access width support for slave xfers on
mem side
- Fix other kernel driver for device_fc and dw_dmac changes.
Rebased-on:
commit 3506c0d507144d9b0f19efd5a56d289f70611179
Author: Tushar Behera [off-list ref]
Date: Tue Dec 6 16:15:54 2011 +0530
DMA: PL330: Remove pm_runtime_xxx calls from pl330 probe/remove
Rajeev KUMAR (1):
dmaengine/dw_dmac: Hibernation support in dw_dmac
Viresh Kumar (11):
dmaengine: Add flow controller information to dma_slave_config
dmaengine: Pass dma_slave_config .device_fc = NULL for all existing
users
dmaengine/amba-pl08x: Take flow controller info from DMA_SLAVE_CONFIG
dmaengine/dw_dmac: Don't use magic number for total number of
channels
dmaengine/dw_dmac: Use dev_get_platdata() instead of accessing dev
directly
dmaengine/dw_dmac: Don't handle block interrupts
dmaengine/dw_dmac: Unmap all memory buffers after completion of slave
transfers
dmaengine/dw_dmac: Add 64 bit access width support for slave xfers on
mem side
dmaengine/dw_dmac: Add support for DMA_SLAVE_CONFIG
dmaengine/dw_dmac: Fix dw_dmac user drivers to adapt to slave_config
changes
dmaengine/dw_dmac: Remove unused fields in struct dw_dma_slave
arch/avr32/mach-at32ap/at32ap700x.c | 13 --
arch/avr32/mach-at32ap/include/mach/atmel-mci.h | 7 -
drivers/dma/amba-pl08x.c | 4 +-
drivers/dma/dw_dmac.c | 232 +++++++++++++++--------
drivers/dma/dw_dmac_regs.h | 15 ++
drivers/mmc/host/atmel-mci.c | 24 ++-
drivers/mmc/host/mmci.c | 2 +
drivers/mmc/host/mxcmmc.c | 2 +
drivers/spi/spi-dw-mid.c | 3 +
drivers/spi/spi-pl022.c | 2 +
drivers/tty/serial/amba-pl011.c | 3 +
drivers/usb/musb/ux500_dma.c | 1 +
include/linux/amba/pl08x.h | 8 +-
include/linux/dmaengine.h | 5 +
include/linux/dw_dmac.h | 38 ----
sound/atmel/abdac.c | 18 ++-
sound/atmel/ac97c.c | 41 ++++-
sound/soc/imx/imx-pcm-dma-mx2.c | 3 +
18 files changed, 255 insertions(+), 166 deletions(-)
--
1.7.8.110.g4cb5d
Flow controller is programmable for few controllers and there are few
intelligent peripherals like, Synopsys JPEG controller, that needs to be a flow
controller of DMA transfers on dest side.
For this, currently two drivers, pl08x and dw_dmac, support flow controller to
be passed from platform to these drivers.
Perhaps, this should be a part of struct dma_slave_config. This patch adds
another field device_fc to this structure. User drivers must pass this as true
if they want to be flow controller of certain transfers.
Signed-off-by: Viresh Kumar <redacted>
---
include/linux/dmaengine.h | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
Total number of channels is passed in pdata->nr_channels variable, thus we must
not use magic number '7' for total number of channels.
Signed-off-by: Viresh Kumar <redacted>
---
drivers/dma/dw_dmac.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
64 bit transfers are possible on both sides in slave transfers (memory as well
as peripherals). This patch adds support for it memory side 64 bit transfers.
Signed-off-by: Viresh Kumar <redacted>
---
drivers/dma/dw_dmac.c | 20 ++++++++++++++++----
1 files changed, 16 insertions(+), 4 deletions(-)
There are few existing user drivers of dw_dmac. They will break as soon as we
remove unused fields from struct dw_dma_slave. This patch focuses to fix these
user drivers to use dma_slave_config() routine.
Signed-off-by: Viresh Kumar <redacted>
---
arch/avr32/mach-at32ap/at32ap700x.c | 13 -------
arch/avr32/mach-at32ap/include/mach/atmel-mci.h | 7 ----
drivers/mmc/host/atmel-mci.c | 24 +++++++++----
sound/atmel/abdac.c | 18 ++++++++--
sound/atmel/ac97c.c | 41 ++++++++++++++++++----
5 files changed, 63 insertions(+), 40 deletions(-)
@@ -1353,7 +1353,6 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)gotofail;slave->sdata.dma_dev=&dw_dmac0_device.dev;-slave->sdata.reg_width=DW_DMA_SLAVE_WIDTH_32BIT;slave->sdata.cfg_hi=(DWC_CFGH_SRC_PER(0)|DWC_CFGH_DST_PER(1));slave->sdata.cfg_lo&=~(DWC_CFGL_HS_DST_POL
@@ -2048,27 +2047,19 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data,/* Check if DMA slave interface for capture should be configured. */if(flags&AC97C_CAPTURE){rx_dws->dma_dev=&dw_dmac0_device.dev;-rx_dws->reg_width=DW_DMA_SLAVE_WIDTH_16BIT;rx_dws->cfg_hi=DWC_CFGH_SRC_PER(3);rx_dws->cfg_lo&=~(DWC_CFGL_HS_DST_POL|DWC_CFGL_HS_SRC_POL);rx_dws->src_master=0;rx_dws->dst_master=1;-rx_dws->src_msize=DW_DMA_MSIZE_1;-rx_dws->dst_msize=DW_DMA_MSIZE_1;-rx_dws->fc=DW_DMA_FC_D_P2M;}/* Check if DMA slave interface for playback should be configured. */if(flags&AC97C_PLAYBACK){tx_dws->dma_dev=&dw_dmac0_device.dev;-tx_dws->reg_width=DW_DMA_SLAVE_WIDTH_16BIT;tx_dws->cfg_hi=DWC_CFGH_DST_PER(4);tx_dws->cfg_lo&=~(DWC_CFGL_HS_DST_POL|DWC_CFGL_HS_SRC_POL);tx_dws->src_master=0;tx_dws->dst_master=1;-tx_dws->src_msize=DW_DMA_MSIZE_1;-tx_dws->dst_msize=DW_DMA_MSIZE_1;-tx_dws->fc=DW_DMA_FC_D_M2P;}if(platform_device_add_data(pdev,data,
@@ -2138,14 +2129,10 @@ at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data)dws=&data->dws;dws->dma_dev=&dw_dmac0_device.dev;-dws->reg_width=DW_DMA_SLAVE_WIDTH_32BIT;dws->cfg_hi=DWC_CFGH_DST_PER(2);dws->cfg_lo&=~(DWC_CFGL_HS_DST_POL|DWC_CFGL_HS_SRC_POL);dws->src_master=0;dws->dst_master=1;-dws->src_msize=DW_DMA_MSIZE_1;-dws->dst_msize=DW_DMA_MSIZE_1;-dws->fc=DW_DMA_FC_D_M2P;if(platform_device_add_data(pdev,data,sizeof(structatmel_abdac_pdata)))
@@ -1957,22 +1960,27 @@ static void atmci_configure_dma(struct atmel_mci *host)if(pdata&&find_slave_dev(pdata->dma_slave)){dma_cap_mask_tmask;-setup_dma_addr(pdata->dma_slave,-host->mapbase+ATMCI_TDR,-host->mapbase+ATMCI_RDR);-/* Try to grab a DMA channel */dma_cap_zero(mask);dma_cap_set(DMA_SLAVE,mask);host->dma.chan=dma_request_channel(mask,atmci_filter,pdata->dma_slave);}-if(!host->dma.chan)+if(!host->dma.chan){dev_notice(&host->pdev->dev,"DMA not available, using PIO\n");-else+}else{dev_info(&host->pdev->dev,"Using %s for DMA transfers\n",dma_chan_name(host->dma.chan));++host->dma_conf.src_addr=host->mapbase+ATMCI_RDR;+host->dma_conf.src_addr_width=DMA_SLAVE_BUSWIDTH_4_BYTES;+host->dma_conf.src_maxburst=1;+host->dma_conf.dst_addr=host->mapbase+ATMCI_TDR;+host->dma_conf.dst_addr_width=DMA_SLAVE_BUSWIDTH_4_BYTES;+host->dma_conf.dst_maxburst=1;+host->dma_conf.device_fc=false;+}}staticinlineunsignedintatmci_get_version(structatmel_mci*host)
This patch adds support for DMA_SLAVE_CONFIG in dwc DMAC controller. Fields in
struct dw_dma_slave for passing similar data are preserved in this patch untill
all existing users are fixed.
That will be handled later in this patchset.
Signed-off-by: Viresh Kumar <redacted>
---
drivers/dma/dw_dmac.c | 119 +++++++++++++++++++++++++++++++++-----------
drivers/dma/dw_dmac_regs.h | 3 +
2 files changed, 93 insertions(+), 29 deletions(-)
@@ -889,6 +901,39 @@ err_desc_get:returnNULL;}+/*+*Fixsconfig'sburstsizeaccordingtodw_dmac.Weneedtoconvertthemas:+*1->0,4->1,8->2,16->3.+*+*NOTE:burstsize2isnotsupportedbycontroller.+*+*Thiscanbedonebyfindingleastsignificantbitset:n&(n-1)+*/+staticinlinevoidconvert_burst(u32*maxburst)+{+if(*maxburst>1)+*maxburst=fls(*maxburst)-2;+else+*maxburst=0;+}++staticint+set_runtime_config(structdma_chan*chan,structdma_slave_config*sconfig)+{+structdw_dma_chan*dwc=to_dw_dma_chan(chan);++/* Check if it is chan is configured for slave transfers */+if(!chan->private)+return-EINVAL;++memcpy(&dwc->dma_sconfig,sconfig,sizeof(*sconfig));++convert_burst(&dwc->dma_sconfig.src_maxburst);+convert_burst(&dwc->dma_sconfig.dst_maxburst);++return0;+}+staticintdwc_control(structdma_chan*chan,enumdma_ctrl_cmdcmd,unsignedlongarg){
@@ -938,8 +983,11 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,/* Flush all pending and queued descriptors */list_for_each_entry_safe(desc,_desc,&list,desc_node)dwc_descriptor_complete(dwc,desc,false);-}else+}elseif(cmd==DMA_SLAVE_CONFIG){+returnset_runtime_config(chan,(structdma_slave_config*)arg);+}else{return-ENXIO;+}return0;}
@@ -1208,7 +1256,12 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,}retval=ERR_PTR(-EINVAL);-reg_width=dws->reg_width;++if(direction==DMA_MEM_TO_DEV)+reg_width=__ffs(sconfig->dst_addr_width);+else+reg_width=__ffs(sconfig->src_addr_width);+periods=buf_len/period_len;/* Check for too big/unaligned periods and unaligned DMA buffer. */
Currently, after completion of transfer, source address or destination address
of only the first LLI descriptor is unmapped. And length passed for unmap is
total length of all descriptors in the list. Which means unmapping code assumed
that the memory buffers pointed to by the descriptors will be physically
contiguous, which might not be the case. It is possible for other drivers to
pass sglist to slave_sg(), in which all buffers are scattered throughout the
memory.
This patch intends to fix this wrong expectation of dw_dmac. Now, first desc
will not contain total length of transfer. But individual descriptors will
contain their individual lengths. Finally, we will call unmap for all
descriptors.
Signed-off-by: Viresh Kumar <redacted>
---
drivers/dma/dw_dmac.c | 49 +++++++++++++++++++++++++++++++------------------
1 files changed, 31 insertions(+), 18 deletions(-)
Block interrupts give interrupt on completion of every LLI, which is actually
too much interrupts. This is just not required for current functioning of
dw_dmac.
So, just don't handle them at all.
Signed-off-by: Viresh Kumar <redacted>
---
drivers/dma/dw_dmac.c | 36 ++++++------------------------------
1 files changed, 6 insertions(+), 30 deletions(-)
@@ -470,17 +463,16 @@ EXPORT_SYMBOL(dw_dma_get_dst_addr);/* called with dwc->lock held and all DMAC interrupts disabled */staticvoiddwc_handle_cyclic(structdw_dma*dw,structdw_dma_chan*dwc,-u32status_block,u32status_err,u32status_xfer)+u32status_err,u32status_xfer){unsignedlongflags;-if(status_block&dwc->mask){+if(dwc->mask){void(*callback)(void*param);void*callback_param;dev_vdbg(chan2dev(&dwc->chan),"new cyclic period llp 0x%08x\n",channel_readl(dwc,LLP));-dma_writel(dw,CLEAR.BLOCK,dwc->mask);callback=dwc->cdesc->period_callback;callback_param=dwc->cdesc->period_callback_param;
@@ -1449,13 +1427,11 @@ static int __init dw_probe(struct platform_device *pdev)/* Clear/disable all interrupts on all channels. */dma_writel(dw,CLEAR.XFER,dw->all_chan_mask);-dma_writel(dw,CLEAR.BLOCK,dw->all_chan_mask);dma_writel(dw,CLEAR.SRC_TRAN,dw->all_chan_mask);dma_writel(dw,CLEAR.DST_TRAN,dw->all_chan_mask);dma_writel(dw,CLEAR.ERROR,dw->all_chan_mask);channel_clear_bit(dw,MASK.XFER,dw->all_chan_mask);-channel_clear_bit(dw,MASK.BLOCK,dw->all_chan_mask);channel_clear_bit(dw,MASK.SRC_TRAN,dw->all_chan_mask);channel_clear_bit(dw,MASK.DST_TRAN,dw->all_chan_mask);channel_clear_bit(dw,MASK.ERROR,dw->all_chan_mask);
Flow controller information is passed now from DMA_SLAVE_CONFIG option. This
patch makes changes in pl08x driver to use device_fc from it instead of platform
data.
Signed-off-by: Viresh Kumar <redacted>
---
drivers/dma/amba-pl08x.c | 4 +++-
include/linux/amba/pl08x.h | 8 ++++----
2 files changed, 7 insertions(+), 5 deletions(-)
.device_fc is added in struct dma_slave_config recently. All user drivers, which
want DMA to be the flow controller must pass this field as false. As earlier
driver don't look to use this feature, mark it false for now.
Signed-off-by: Viresh Kumar <redacted>
---
drivers/mmc/host/mmci.c | 2 ++
drivers/mmc/host/mxcmmc.c | 2 ++
drivers/spi/spi-dw-mid.c | 3 +++
drivers/spi/spi-pl022.c | 2 ++
drivers/tty/serial/amba-pl011.c | 3 +++
drivers/usb/musb/ux500_dma.c | 1 +
sound/soc/imx/imx-pcm-dma-mx2.c | 3 +++
7 files changed, 16 insertions(+), 0 deletions(-)
@@ -370,6 +371,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,.dst_addr_width=DMA_SLAVE_BUSWIDTH_4_BYTES,.src_maxburst=variant->fifohalfsize>>2,/* # of words */.dst_maxburst=variant->fifohalfsize>>2,/* # of words */+.device_fc=false,};structdma_chan*chan;structdma_device*device;
From: Rajeev KUMAR <redacted>
The suspend and resume implementation is through dev_pm_ops in dmac. So
in order to support hibernation, freeze, thaw, restore and poweroff
features are required.
Signed-off-by: Rajeev Kumar <redacted>
Acked-by: Viresh Kumar <redacted>
---
drivers/dma/dw_dmac.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
From: Russell King - ARM Linux <hidden> Date: 2012-01-18 09:37:06
On Wed, Jan 18, 2012 at 02:41:55PM +0530, Viresh Kumar wrote:
Currently, after completion of transfer, source address or destination address
of only the first LLI descriptor is unmapped. And length passed for unmap is
total length of all descriptors in the list. Which means unmapping code assumed
that the memory buffers pointed to by the descriptors will be physically
contiguous, which might not be the case. It is possible for other drivers to
pass sglist to slave_sg(), in which all buffers are scattered throughout the
memory.
This patch intends to fix this wrong expectation of dw_dmac. Now, first desc
will not contain total length of transfer. But individual descriptors will
contain their individual lengths. Finally, we will call unmap for all
descriptors.
NAK. For reasons stated previously and subsequently ignored.
On 1/18/2012 3:06 PM, Russell King - ARM Linux wrote:
On Wed, Jan 18, 2012 at 02:41:55PM +0530, Viresh Kumar wrote:
NAK. For reasons stated previously and subsequently ignored.
.
On 1/18/2012 3:05 PM, Russell King - ARM Linux wrote:
quoted
quoted
You implemented similar stuff in amba-pl08x :) .
if (!plchan->slave)
pl08x_unmap_buffers(txd);
Take a look at that. "If *NOT* slave, unmap the buffers".
[Following is picked from current implementation of dw_dmac:]
if (!dwc->chan.private) {
struct device *parent = chan2parent(&dwc->chan);
if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
Sorry, I missed the most straight forward looking code. :(
Actually, dw_dmac is also doing the same, i.e. unmapping only for
non-slave transfers.
The same patch is still applicable, after fixing message subject and log.
I will resend it, with message log fixed, once i get more feedbacks on V2.
--
viresh
On Wed, Jan 18, 2012 at 10:11 AM, Viresh Kumar [off-list ref] wrote:
Flow controller is programmable for few controllers and there are few
intelligent peripherals like, Synopsys JPEG controller, that needs to be a flow
controller of DMA transfers on dest side.
For this, currently two drivers, pl08x and dw_dmac, support flow controller to
be passed from platform to these drivers.
Perhaps, this should be a part of struct dma_slave_config. This patch adds
another field device_fc to this structure. User drivers must pass this as true
if they want to be flow controller of certain transfers.
Signed-off-by: Viresh Kumar <redacted>
On Wed, Jan 18, 2012 at 10:11 AM, Viresh Kumar [off-list ref] wrote:
.device_fc is added in struct dma_slave_config recently. All user drivers, which
want DMA to be the flow controller must pass this field as false. As earlier
driver don't look to use this feature, mark it false for now.
Signed-off-by: Viresh Kumar <redacted>
On Wed, Jan 18, 2012 at 10:11 AM, Viresh Kumar [off-list ref] wrote:
Flow controller information is passed now from DMA_SLAVE_CONFIG option. This
patch makes changes in pl08x driver to use device_fc from it instead of platform
data.
Signed-off-by: Viresh Kumar <redacted>
On Wed, 2012-01-18 at 14:41 +0530, Viresh Kumar wrote:
quoted hunk
Flow controller is programmable for few controllers and there are few
intelligent peripherals like, Synopsys JPEG controller, that needs to be a flow
controller of DMA transfers on dest side.
For this, currently two drivers, pl08x and dw_dmac, support flow controller to
be passed from platform to these drivers.
Perhaps, this should be a part of struct dma_slave_config. This patch adds
another field device_fc to this structure. User drivers must pass this as true
if they want to be flow controller of certain transfers.
Signed-off-by: Viresh Kumar <redacted>
---
include/linux/dmaengine.h | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
ccfg maybe true for your controller, not others...
quoted hunk
+ * channels. Fill with 'true' if peripheral should be flow controller. Direction
+ * will be selected at Runtime.
*
* This struct is passed in as configuration data to a DMA engine
* in order to set up a certain channel for DMA transport at runtime.
On Wed, 2012-01-18 at 15:24 +0530, Viresh Kumar wrote:
On 1/18/2012 3:06 PM, Russell King - ARM Linux wrote:
quoted
On Wed, Jan 18, 2012 at 02:41:55PM +0530, Viresh Kumar wrote:
NAK. For reasons stated previously and subsequently ignored.
.
On 1/18/2012 3:05 PM, Russell King - ARM Linux wrote:
quoted
quoted
quoted
You implemented similar stuff in amba-pl08x :) .
if (!plchan->slave)
pl08x_unmap_buffers(txd);
Take a look at that. "If *NOT* slave, unmap the buffers".
[Following is picked from current implementation of dw_dmac:]
if (!dwc->chan.private) {
struct device *parent = chan2parent(&dwc->chan);
if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
Sorry, I missed the most straight forward looking code. :(
Actually, dw_dmac is also doing the same, i.e. unmapping only for
non-slave transfers.
The same patch is still applicable, after fixing message subject and log.
I will resend it, with message log fixed, once i get more feedbacks on V2.
But this patch seems to unmap for *all* descriptors, so you need to fix
that as well, apart from the ones stated above.
--
~Vinod
if (!dwc->chan.private) {
struct device *parent = chan2parent(&dwc->chan);
if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
Sorry, I missed the most straight forward looking code. :(
Actually, dw_dmac is also doing the same, i.e. unmapping only for
non-slave transfers.
The same patch is still applicable, after fixing message subject and log.
I will resend it, with message log fixed, once i get more feedbacks on V2.
But this patch seems to unmap for *all* descriptors, so you need to fix
that as well, apart from the ones stated above.
What do you mean by *all* here? All type of transfers ?
If that's the question, then the answer is NO.
I am unmapping all descriptors of current transfer only for non-slave transfers.
--
viresh
On Tue, 2012-01-31 at 09:37 +0530, Viresh Kumar wrote:
On 1/31/2012 9:28 AM, Vinod Koul wrote:
quoted
quoted
quoted
if (!dwc->chan.private) {
struct device *parent = chan2parent(&dwc->chan);
if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
Sorry, I missed the most straight forward looking code. :(
Actually, dw_dmac is also doing the same, i.e. unmapping only for
non-slave transfers.
The same patch is still applicable, after fixing message subject and log.
I will resend it, with message log fixed, once i get more feedbacks on V2.
But this patch seems to unmap for *all* descriptors, so you need to fix
that as well, apart from the ones stated above.
What do you mean by *all* here? All type of transfers ?
If that's the question, then the answer is NO.
I am unmapping all descriptors of current transfer only for non-slave transfers.
Yes missed that
Btw, can you also fix the driver not to use chan->private?
--
~Vinod
Btw, can you also fix the driver not to use chan->private?
Ya sure, but i am not in sync with the issue. :(
Why do we need to remove code dependency on chan->private, something
dmaengine specific has changed?
--
viresh