Prev: x86-32: Fix crashes with CPU hotplug on AMD machines
Next: [tip:x86/urgent] x86, asm: Use a lower case name for the end macro in atomic64_386_32.S
From: Sascha Hauer on 12 Aug 2010 11:10 Hi, I am currently looking into implementing the Freescale i.MX SDMA engine into the dmaengine API. The SDMA engine can handle sg transfers from/to devices. During implementation some questions came up. On the i.MX we already have a DMA engine which can do slave dma transfers, the IPU (drivers/dma/ipu/), which is exclusively used for image operations. My problem is that I found no way for the clients to select which DMA engine to use as both have the same capabilities (DMA_SLAVE). For the SDMA engine the clients have to pass some platform specific data to the SDMA engine (dma request line, word width and the like). The current mechanism is to pass this data through the dma_chan->private field, which seems more like tunneling instead of passing the data as we lose type safety. Are there any ideas to improve this? Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
From: Dan Williams on 12 Aug 2010 15:20 On Thu, Aug 12, 2010 at 8:00 AM, Sascha Hauer <s.hauer(a)pengutronix.de> wrote: > Hi, > > I am currently looking into implementing the Freescale i.MX SDMA engine > into the dmaengine API. The SDMA engine can handle sg transfers from/to > devices. During implementation some questions came up. > > On the i.MX we already have a DMA engine which can do slave dma > transfers, the IPU (drivers/dma/ipu/), which is exclusively used for > image operations. My problem is that I found no way for the clients > to select which DMA engine to use as both have the same capabilities > (DMA_SLAVE). Yes, if you need finer grained matching of channels, beyond simple capability matching, this is the intended purpose of the 'dma_filter_fn' and 'filter_param' arguments to dma_request_channel. Dmaengine will pass all available channels that match the base capability to the filter function for further, usually architecture specific, discrimination. > For the SDMA engine the clients have to pass some platform specific data > to the SDMA engine (dma request line, word width and the like). The > current mechanism is to pass this data through the dma_chan->private > field, which seems more like tunneling instead of passing the data as we > lose type safety. Are there any ideas to improve this? Hopefully dma_chan->private can eventually be phased out in favor of Linus' dma_slave_config scheme [1]. -- Dan [1]: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=c156d0a5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
From: Sascha Hauer on 12 Aug 2010 16:20 On Thu, Aug 12, 2010 at 12:14:20PM -0700, Dan Williams wrote: > On Thu, Aug 12, 2010 at 8:00 AM, Sascha Hauer <s.hauer(a)pengutronix.de> wrote: > > Hi, > > > > I am currently looking into implementing the Freescale i.MX SDMA engine > > into the dmaengine API. The SDMA engine can handle sg transfers from/to > > devices. During implementation some questions came up. > > > > On the i.MX we already have a DMA engine which can do slave dma > > transfers, the IPU (drivers/dma/ipu/), which is exclusively used for > > image operations. My problem is that I found no way for the clients > > to select which DMA engine to use as both have the same capabilities > > (DMA_SLAVE). > > Yes, if you need finer grained matching of channels, beyond simple > capability matching, this is the intended purpose of the > 'dma_filter_fn' and 'filter_param' arguments to dma_request_channel. > Dmaengine will pass all available channels that match the base > capability to the filter function for further, usually architecture > specific, discrimination. Ok, so I could do a strcmp(dev_name(chan->device->dev), "imx-sdma") in the filter function. > > > For the SDMA engine the clients have to pass some platform specific data > > to the SDMA engine (dma request line, word width and the like). The > > current mechanism is to pass this data through the dma_chan->private > > field, which seems more like tunneling instead of passing the data as we > > lose type safety. Are there any ideas to improve this? > > Hopefully dma_chan->private can eventually be phased out in favor of > Linus' dma_slave_config scheme [1]. This looks promising. Two things are missing here for the SDMA engine. First is the DMA request line which is probably needed for other dma engines aswell, so this could be added to dma_slave_config. The other one is really specific to the SDMA engine, it's the following enum. The SDMA engine is a programmable controller in the i.MX and each peripheral has its own copy function in this controller. This enum is used to determine their start addresses. typedef enum { IMX_DMATYPE_SSI, /* MCU domain SSI */ IMX_DMATYPE_SSI_SP, /* Shared SSI */ IMX_DMATYPE_MMC, /* MMC */ IMX_DMATYPE_SDHC, /* SDHC */ IMX_DMATYPE_UART, /* MCU domain UART */ IMX_DMATYPE_UART_SP, /* Shared UART */ IMX_DMATYPE_FIRI, /* FIRI */ IMX_DMATYPE_CSPI, /* MCU domain CSPI */ IMX_DMATYPE_CSPI_SP, /* Shared CSPI */ IMX_DMATYPE_SIM, /* SIM */ IMX_DMATYPE_ATA, /* ATA */ IMX_DMATYPE_CCM, /* CCM */ IMX_DMATYPE_EXT, /* External peripheral */ IMX_DMATYPE_MSHC, /* Memory Stick Host Controller */ IMX_DMATYPE_MSHC_SP, /* Shared Memory Stick Host Controller */ IMX_DMATYPE_DSP, /* DSP */ IMX_DMATYPE_MEMORY, /* Memory */ IMX_DMATYPE_FIFO_MEMORY,/* FIFO type Memory */ IMX_DMATYPE_SPDIF, /* SPDIF */ IMX_DMATYPE_IPU_MEMORY, /* IPU Memory */ IMX_DMATYPE_ASRC, /* ASRC */ IMX_DMATYPE_ESAI, /* ESAI */ } sdma_peripheral_type; Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
From: Linus Walleij on 12 Aug 2010 18:40 2010/8/12 Sascha Hauer <s.hauer(a)pengutronix.de>: > [Dan] >> Hopefully dma_chan->private can eventually be phased out in favor of >> Linus' dma_slave_config scheme [1]. > > This looks promising. Two things are missing here for the SDMA engine. > First is the DMA request line which is probably needed for other dma > engines aswell, so this could be added to dma_slave_config. Do you really need to configure this at runtime? The idea is to pass in stuff that is changed dynamically wheras things that are fixed are passed in from platform data. In the PL180 there was multiplexing functions for the lines even (so one line was shared between different devices) in that case I implemented platform-specific callbacks in the platform data to request the lines. > The other > one is really specific to the SDMA engine, it's the following enum. The > SDMA engine is a programmable controller in the i.MX and each peripheral > has its own copy function in this controller. This enum is used to > determine their start addresses. Can't you pass in the actual address in src_address for RX and dst_address for TX? The idea here is that the driver know the physical address where the bitpipe is supposed to end up, and the DMAengine does not. If it was always the same address we could pass that also through platform data but experience shows that some devices use different addresses for different kinds of configurations, that's why it's there. Maybe I'm just not getting it... Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
From: Sascha Hauer on 13 Aug 2010 03:50
On Fri, Aug 13, 2010 at 12:32:08AM +0200, Linus Walleij wrote: > 2010/8/12 Sascha Hauer <s.hauer(a)pengutronix.de>: > > [Dan] > >> Hopefully dma_chan->private can eventually be phased out in favor of > >> Linus' dma_slave_config scheme [1]. > > > > This looks promising. Two things are missing here for the SDMA engine. > > First is the DMA request line which is probably needed for other dma > > engines aswell, so this could be added to dma_slave_config. > > Do you really need to configure this at runtime? > The idea is to pass in stuff that is changed dynamically wheras > things that are fixed are passed in from platform data. It's not changed dynamically, but the information which dma request a client has to use is in its resources. So the client does a platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); to get the request line to use. Somehow this information must get to the SDMA engine. By platform data do you mean the private pointer in dma_chan? > > In the PL180 there was multiplexing functions for the lines even > (so one line was shared between different devices) in that case > I implemented platform-specific callbacks in the platform data > to request the lines. Do you have a pointer to the code? > > > The other > > one is really specific to the SDMA engine, it's the following enum. The > > SDMA engine is a programmable controller in the i.MX and each peripheral > > has its own copy function in this controller. This enum is used to > > determine their start addresses. > > Can't you pass in the actual address in src_address for RX and > dst_address for TX? I'm not talking about addresses in the physical address space of the i.MX here. I'm talking about addresses in the program address space of the SDMA controller. Let me explain this a little more in detail. The SDMA engine has a little microcontroller in it which gets a 6k or something firmware image. The firmware consists of several functions (which are running in the controller). The SDMA driver now translates the information 'sdhc controller receive' into an offset in the firmware image. The actual FIFO address of the peripheral is of course passed in src_address/dst_address. > > The idea here is that the driver know the physical address where > the bitpipe is supposed to end up, and the DMAengine does not. > If it was always the same address we could pass that also through > platform data but experience shows that some devices use different > addresses for different kinds of configurations, that's why it's there. > > Maybe I'm just not getting it... I hope my explanation above helps. The following function is the snippet in the SDMA driver which does this translation work: static void sdma_get_pc(struct sdma_channel *sdma, sdma_peripheral_type peripheral_type) { int res = 0; int per_2_emi = 0, emi_2_per = 0; int per_2_int = 0, int_2_per = 0; int per_2_per = 0, emi_2_emi = 0; sdma->pc_from_device = 0; sdma->pc_to_device = 0; switch (peripheral_type) { case IMX_DMATYPE_MEMORY: emi_2_emi = sdma_script_addrs->ap_2_ap_addr; break; case IMX_DMATYPE_DSP: emi_2_per = sdma_script_addrs->bp_2_ap_addr; per_2_emi = sdma_script_addrs->ap_2_bp_addr; break; case IMX_DMATYPE_FIRI: per_2_int = sdma_script_addrs->firi_2_per_addr; per_2_emi = sdma_script_addrs->firi_2_mcu_addr; int_2_per = sdma_script_addrs->per_2_firi_addr; emi_2_per = sdma_script_addrs->mcu_2_firi_addr; break; case IMX_DMATYPE_UART: per_2_int = sdma_script_addrs->uart_2_per_addr; per_2_emi = sdma_script_addrs->uart_2_mcu_addr; int_2_per = sdma_script_addrs->per_2_app_addr; emi_2_per = sdma_script_addrs->mcu_2_app_addr; break; case IMX_DMATYPE_UART_SP: per_2_int = sdma_script_addrs->uartsh_2_per_addr; per_2_emi = sdma_script_addrs->uartsh_2_mcu_addr; int_2_per = sdma_script_addrs->per_2_shp_addr; emi_2_per = sdma_script_addrs->mcu_2_shp_addr; break; case IMX_DMATYPE_ATA: per_2_emi = sdma_script_addrs->ata_2_mcu_addr; emi_2_per = sdma_script_addrs->mcu_2_ata_addr; break; case IMX_DMATYPE_CSPI: case IMX_DMATYPE_EXT: case IMX_DMATYPE_SSI: per_2_int = sdma_script_addrs->app_2_per_addr; per_2_emi = sdma_script_addrs->app_2_mcu_addr; int_2_per = sdma_script_addrs->per_2_app_addr; emi_2_per = sdma_script_addrs->mcu_2_app_addr; break; case IMX_DMATYPE_SSI_SP: case IMX_DMATYPE_MMC: case IMX_DMATYPE_SDHC: case IMX_DMATYPE_CSPI_SP: case IMX_DMATYPE_ESAI: case IMX_DMATYPE_MSHC_SP: per_2_int = sdma_script_addrs->shp_2_per_addr; per_2_emi = sdma_script_addrs->shp_2_mcu_addr; int_2_per = sdma_script_addrs->per_2_shp_addr; emi_2_per = sdma_script_addrs->mcu_2_shp_addr; break; case IMX_DMATYPE_ASRC: per_2_emi = sdma_script_addrs->asrc_2_mcu_addr; emi_2_per = sdma_script_addrs->asrc_2_mcu_addr; per_2_per = sdma_script_addrs->per_2_per_addr; break; case IMX_DMATYPE_MSHC: per_2_emi = sdma_script_addrs->mshc_2_mcu_addr; emi_2_per = sdma_script_addrs->mcu_2_mshc_addr; break; case IMX_DMATYPE_CCM: per_2_emi = sdma_script_addrs->dptc_dvfs_addr; break; case IMX_DMATYPE_FIFO_MEMORY: res = sdma_script_addrs->ap_2_ap_fixed_addr; break; case IMX_DMATYPE_SPDIF: per_2_emi = sdma_script_addrs->spdif_2_mcu_addr; emi_2_per = sdma_script_addrs->mcu_2_spdif_addr; break; case IMX_DMATYPE_IPU_MEMORY: emi_2_per = sdma_script_addrs->ext_mem_2_ipu_addr; break; default: break; } sdma->pc_from_device = per_2_emi; sdma->pc_to_device = emi_2_per; } Regards, Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ |