On 01/25/2012 02:12 PM, Seungwon Jeon wrote: > Jaehoon Chung <jh80.chung@xxxxxxxxxxx> wrote: >> Hi Mr Jeon.. >> >> Are Pre_req and post_req used with only the IDMAC..? > Currently internal dma is considered. > Do you use system dma operation? I used the IDMAC. My means...other dma system can also use this feature, right? So i just asked to you.. Best Regards, Jaehoon Chung > >> >> On 01/20/2012 01:05 PM, Seungwon Jeon wrote: >> >>> This patch implements pre_req and post_req in dw_mmc >>> to support asynchronous mmc request. >>> >>> Signed-off-by: Seungwon Jeon <tgih.jun@xxxxxxxxxxx> >>> --- >>> NOTE: >>> Performance gains the following. >>> Sequential read and write improve 23% and 5% respectively. >>> >>> drivers/mmc/host/dw_mmc.c | 136 ++++++++++++++++++++++++++++++++++++--------- >>> 1 files changed, 109 insertions(+), 27 deletions(-) >>> >>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c >>> index 0e34279..1fb8114 100644 >>> --- a/drivers/mmc/host/dw_mmc.c >>> +++ b/drivers/mmc/host/dw_mmc.c >>> @@ -297,14 +297,24 @@ static void dw_mci_stop_dma(struct dw_mci *host) >>> } >>> >>> #ifdef CONFIG_MMC_DW_IDMAC >>> +static int dw_mci_get_dma_dir(struct mmc_data *data) >>> +{ >>> + if (data->flags & MMC_DATA_WRITE) >>> + return DMA_TO_DEVICE; >>> + else >>> + return DMA_FROM_DEVICE; >>> +} >>> + >>> static void dw_mci_dma_cleanup(struct dw_mci *host) >>> { >>> struct mmc_data *data = host->data; >>> >>> if (data) >>> - dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, >>> - ((data->flags & MMC_DATA_WRITE) >>> - ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); >>> + if (!data->host_cookie) >>> + dma_unmap_sg(&host->pdev->dev, >>> + data->sg, >>> + data->sg_len, >>> + dw_mci_get_dma_dir(data)); >>> } >> >> if (!data->host_cookie) >> dma_unmap_sg(&host->pdev->dev, >> data->sg, data->sg_len, >> dw_mci_get_dma_dir(data)); >> also the below code.. > Sorry... What's mean? > > Thanks, > Seungwon Jeon. >> >> Best Regards, >> Jaehoon Chung >> >>> >>> static void dw_mci_idmac_stop_dma(struct dw_mci *host) >>> @@ -420,26 +430,15 @@ static int dw_mci_idmac_init(struct dw_mci *host) >>> return 0; >>> } >>> >>> -static struct dw_mci_dma_ops dw_mci_idmac_ops = { >>> - .init = dw_mci_idmac_init, >>> - .start = dw_mci_idmac_start_dma, >>> - .stop = dw_mci_idmac_stop_dma, >>> - .complete = dw_mci_idmac_complete_dma, >>> - .cleanup = dw_mci_dma_cleanup, >>> -}; >>> -#endif /* CONFIG_MMC_DW_IDMAC */ >>> - >>> -static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) >>> +static int dw_mci_pre_dma_transfer(struct dw_mci *host, >>> + struct mmc_data *data, >>> + bool next) >>> { >>> struct scatterlist *sg; >>> - unsigned int i, direction, sg_len; >>> - u32 temp; >>> - >>> - host->using_dma = 0; >>> + unsigned int i, sg_len; >>> >>> - /* If we don't have a channel, we can't do DMA */ >>> - if (!host->use_dma) >>> - return -ENODEV; >>> + if (!next && data->host_cookie) >>> + return data->host_cookie; >>> >>> /* >>> * We don't do DMA on "complex" transfers, i.e. with >>> @@ -448,6 +447,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) >>> */ >>> if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD) >>> return -EINVAL; >>> + >>> if (data->blksz & 3) >>> return -EINVAL; >>> >>> @@ -456,15 +456,95 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) >>> return -EINVAL; >>> } >>> >>> - host->using_dma = 1; >>> + sg_len = dma_map_sg(&host->pdev->dev, >>> + data->sg, >>> + data->sg_len, >>> + dw_mci_get_dma_dir(data)); >>> + if (sg_len == 0) >>> + return -EINVAL; >>> >>> - if (data->flags & MMC_DATA_READ) >>> - direction = DMA_FROM_DEVICE; >>> - else >>> - direction = DMA_TO_DEVICE; >>> + if (next) >>> + data->host_cookie = sg_len; >>> + >>> + return sg_len; >>> +} >>> >>> - sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, >>> - direction); >>> +static void dw_mci_pre_req(struct mmc_host *mmc, >>> + struct mmc_request *mrq, >>> + bool is_first_req) >>> +{ >>> + struct dw_mci_slot *slot = mmc_priv(mmc); >>> + struct mmc_data *data = mrq->data; >>> + >>> + if (!data) >>> + return; >>> + >>> + if (data->host_cookie) { >>> + data->host_cookie = 0; >>> + return; >>> + } >>> + >>> + if (slot->host->use_dma) { >>> + if (dw_mci_pre_dma_transfer(slot->host, mrq->data, 1) < 0) >>> + data->host_cookie = 0; >>> + } >>> +} >>> + >>> +static void dw_mci_post_req(struct mmc_host *mmc, >>> + struct mmc_request *mrq, >>> + int err) >>> +{ >>> + struct dw_mci_slot *slot = mmc_priv(mmc); >>> + struct mmc_data *data = mrq->data; >>> + >>> + if (!data) >>> + return; >>> + >>> + if (slot->host->use_dma) { >>> + if (data->host_cookie) >>> + dma_unmap_sg(&slot->host->pdev->dev, >>> + data->sg, >>> + data->sg_len, >>> + dw_mci_get_dma_dir(data)); >>> + data->host_cookie = 0; >>> + } >>> +} >>> + >>> +static struct dw_mci_dma_ops dw_mci_idmac_ops = { >>> + .init = dw_mci_idmac_init, >>> + .start = dw_mci_idmac_start_dma, >>> + .stop = dw_mci_idmac_stop_dma, >>> + .complete = dw_mci_idmac_complete_dma, >>> + .cleanup = dw_mci_dma_cleanup, >>> +}; >>> +#else >>> +static int dw_mci_pre_dma_transfer(struct dw_mci *host, >>> + struct mmc_data *data, >>> + bool next) >>> +{ >>> + return -ENOSYS; >>> +} >>> + >>> +#define dw_mci_pre_req NULL >>> +#define dw_mci_post_req NULL >>> +#endif /* CONFIG_MMC_DW_IDMAC */ >>> + >>> +static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) >>> +{ >>> + int sg_len; >>> + u32 temp; >>> + >>> + host->using_dma = 0; >>> + >>> + /* If we don't have a channel, we can't do DMA */ >>> + if (!host->use_dma) >>> + return -ENODEV; >>> + >>> + sg_len = dw_mci_pre_dma_transfer(host, data, 0); >>> + if (sg_len < 0) >>> + return sg_len; >>> + >>> + host->using_dma = 1; >>> >>> dev_vdbg(&host->pdev->dev, >>> "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", >>> @@ -795,6 +875,8 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) >>> >>> static const struct mmc_host_ops dw_mci_ops = { >>> .request = dw_mci_request, >>> + .pre_req = dw_mci_pre_req, >>> + .post_req = dw_mci_post_req, >>> .set_ios = dw_mci_set_ios, >>> .get_ro = dw_mci_get_ro, >>> .get_cd = dw_mci_get_cd, >> >> >> -- >> 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 > > -- > 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 > -- 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