[PATCH] mmc: mxs-mmc: add support for pre_req and post_req
Per Forlin
per.forlin at linaro.org
Wed Apr 20 03:58:48 EDT 2011
On 17 April 2011 18:33, Shawn Guo <shawn.guo at linaro.org> wrote:
> pre_req() runs dma_map_sg() post_req() runs dma_unmap_sg.
> If not calling pre_req() before mxs_mmc_request(), request()
> will prepare the cache just like it did it before.
> It is optional to use pre_req() and post_req().
>
> Signed-off-by: Shawn Guo <shawn.guo at linaro.org>
> ---
> drivers/mmc/host/mxs-mmc.c | 75 ++++++++++++++++++++++++++++++++++++++++++--
> 1 files changed, 72 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
> index 99d39a6..63c2ae2 100644
> --- a/drivers/mmc/host/mxs-mmc.c
> +++ b/drivers/mmc/host/mxs-mmc.c
> @@ -137,6 +137,10 @@
>
> #define SSP_PIO_NUM 3
>
> +struct mxs_mmc_next {
> + s32 cookie;
> +};
> +
> struct mxs_mmc_host {
> struct mmc_host *mmc;
> struct mmc_request *mrq;
> @@ -154,6 +158,7 @@ struct mxs_mmc_host {
> struct mxs_dma_data dma_data;
> unsigned int dma_dir;
> u32 ssp_pio_words[SSP_PIO_NUM];
> + struct mxs_mmc_next next_data;
>
> unsigned int version;
> unsigned char bus_width;
> @@ -302,6 +307,31 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> +static int mxs_mmc_prep_dma_data(struct mxs_mmc_host *host,
> + struct mmc_data *data,
> + struct mxs_mmc_next *next)
> +{
> + if (!next && data->host_cookie &&
> + data->host_cookie != host->next_data.cookie) {
> + printk(KERN_WARNING "[%s] invalid cookie: data->host_cookie %d"
> + " host->next_data.cookie %d\n",
> + __func__, data->host_cookie, host->next_data.cookie);
> + data->host_cookie = 0;
> + }
> +
> + /* Check if next job is already prepared */
> + if (next || (!next && data->host_cookie != host->next_data.cookie))
> + if (dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
> + (data->flags & MMC_DATA_WRITE) ?
> + DMA_TO_DEVICE : DMA_FROM_DEVICE) == 0)
> + return -EINVAL;
> +
> + if (next)
> + data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie;
> +
> + return 0;
> +}
> +
> static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
> struct mxs_mmc_host *host, unsigned int append)
> {
> @@ -312,8 +342,8 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
>
> if (data) {
> /* data */
> - dma_map_sg(mmc_dev(host->mmc), data->sg,
> - data->sg_len, host->dma_dir);
> + if (mxs_mmc_prep_dma_data(host, data, NULL))
> + return NULL;
> sgl = data->sg;
> sg_len = data->sg_len;
> } else {
> @@ -328,9 +358,11 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
> desc->callback = mxs_mmc_dma_irq_callback;
> desc->callback_param = host;
> } else {
> - if (data)
> + if (data) {
> dma_unmap_sg(mmc_dev(host->mmc), data->sg,
> data->sg_len, host->dma_dir);
> + data->host_cookie = 0;
> + }
When is dma_unmap_sg called? If host_cookie is set dma_unmap() should
only be called from post_req.
My guess is
+ if (data && !data->host_cookie) {
It looks like only dma_map is run in parallel with transfer but not
dma_unmap. This may explain the numbers.
More information about the linux-arm-kernel
mailing list