On 17 April 2011 18:33, Shawn Guo <shawn.guo@xxxxxxxxxx> 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@xxxxxxxxxx> > --- > 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. -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html