linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: shawn.guo@linaro.org (Shawn Guo)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] mmc: sdhci: add support for pre_req and post_req
Date: Sun, 17 Apr 2011 00:48:36 +0800	[thread overview]
Message-ID: <1302972516-8673-1-git-send-email-shawn.guo@linaro.org> (raw)
In-Reply-To: <1302116833-24540-1-git-send-email-per.forlin@linaro.org>

pre_req() runs dma_map_sg() post_req() runs dma_unmap_sg.
If not calling pre_req() before sdhci_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@linaro.org>
---
I worked out the patch by referring to Per's patch below.

 omap_hsmmc: add support for pre_req and post_req

It adds pre_req and post_req support for sdhci based host drivers to
work with Per's non-blocking optimization.  But I only have imx esdhc
based hardware to test.  Unfortunately, I can not measure the
performance gain using mmc_test, because the current esdhc driver on
mainline fails on the test.  So I just did a quick test using 'dd',
but sadly, I did not see noticeable performance gain here.  The
followings are possible reasons I can think of right away.

* The patch did not add pre_req and post_req correctly.  Please help
  review to catch the mistakes if any.
* The imx esdhc driver uses SDHCI_SDMA (max_segs is 1) than SDHCI_ADAM
  (max_segs is 128), due to the broken ADMA support on imx esdhc.  So
  can people holding other sdhci based hardware give a try on the
  patch?

Hopefully, I can find some time to have a close look at the mmc_test
failure and the broken ADMA with imx esdhc.

Regards,
Shawn

 drivers/mmc/host/sdhci.c  |   95 ++++++++++++++++++++++++++++++++++++++------
 include/linux/mmc/sdhci.h |    7 +++
 2 files changed, 89 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 9e15f41..becce9a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -408,6 +408,44 @@ static void sdhci_set_adma_desc(u8 *desc, u32 addr, int len, unsigned cmd)
 	dataddr[0] = cpu_to_le32(addr);
 }
 
+static int sdhci_pre_dma_transfer(struct sdhci_host *host,
+				  struct mmc_data *data,
+				  struct sdhci_next *next)
+{
+	int sg_count;
+
+	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)) {
+		sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg,
+				      data->sg_len,
+				      (data->flags & MMC_DATA_WRITE) ?
+				      DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	} else {
+		sg_count = host->next_data.sg_count;
+		host->next_data.sg_count = 0;
+	}
+
+	if (sg_count == 0)
+		return -EINVAL;
+
+	if (next) {
+		next->sg_count = sg_count;
+		data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie;
+	} else
+		host->sg_count = sg_count;
+
+	return sg_count;
+}
+
 static int sdhci_adma_table_pre(struct sdhci_host *host,
 	struct mmc_data *data)
 {
@@ -445,9 +483,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 		goto fail;
 	BUG_ON(host->align_addr & 0x3);
 
-	host->sg_count = dma_map_sg(mmc_dev(host->mmc),
-		data->sg, data->sg_len, direction);
-	if (host->sg_count == 0)
+	host->sg_count = sdhci_pre_dma_transfer(host, data, NULL);
+	if (host->sg_count < 0)
 		goto unmap_align;
 
 	desc = host->adma_desc;
@@ -587,8 +624,9 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
 		}
 	}
 
-	dma_unmap_sg(mmc_dev(host->mmc), data->sg,
-		data->sg_len, direction);
+	if (!data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     direction);
 }
 
 static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
@@ -757,11 +795,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 		} else {
 			int sg_cnt;
 
-			sg_cnt = dma_map_sg(mmc_dev(host->mmc),
-					data->sg, data->sg_len,
-					(data->flags & MMC_DATA_READ) ?
-						DMA_FROM_DEVICE :
-						DMA_TO_DEVICE);
+			sg_cnt = sdhci_pre_dma_transfer(host, data, NULL);
 			if (sg_cnt == 0) {
 				/*
 				 * This only happens when someone fed
@@ -850,9 +884,11 @@ static void sdhci_finish_data(struct sdhci_host *host)
 		if (host->flags & SDHCI_USE_ADMA)
 			sdhci_adma_table_post(host, data);
 		else {
-			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
-				data->sg_len, (data->flags & MMC_DATA_READ) ?
-					DMA_FROM_DEVICE : DMA_TO_DEVICE);
+			if (!data->host_cookie)
+				dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+					     data->sg_len,
+					     (data->flags & MMC_DATA_READ) ?
+					     DMA_FROM_DEVICE : DMA_TO_DEVICE);
 		}
 	}
 
@@ -1116,6 +1152,35 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
  *                                                                           *
 \*****************************************************************************/
 
+static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+			  bool is_first_req)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	if (mrq->data->host_cookie) {
+		mrq->data->host_cookie = 0;
+		return;
+	}
+
+	if (host->flags & SDHCI_REQ_USE_DMA)
+		if (sdhci_pre_dma_transfer(host, mrq->data, &host->next_data) < 0)
+			mrq->data->host_cookie = 0;
+}
+
+static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+			   int err)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+
+	if (host->flags & SDHCI_REQ_USE_DMA) {
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     (data->flags & MMC_DATA_WRITE) ?
+			     DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		data->host_cookie = 0;
+	}
+}
+
 static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct sdhci_host *host;
@@ -1285,6 +1350,8 @@ out:
 }
 
 static const struct mmc_host_ops sdhci_ops = {
+	.pre_req	= sdhci_pre_req,
+	.post_req	= sdhci_post_req,
 	.request	= sdhci_request,
 	.set_ios	= sdhci_set_ios,
 	.get_ro		= sdhci_get_ro,
@@ -1867,6 +1934,8 @@ int sdhci_add_host(struct sdhci_host *host)
 	if (caps & SDHCI_TIMEOUT_CLK_UNIT)
 		host->timeout_clk *= 1000;
 
+	host->next_data.cookie = 1;
+
 	/*
 	 * Set host parameters.
 	 */
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 83bd9f7..924e84b 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -17,6 +17,11 @@
 #include <linux/io.h>
 #include <linux/mmc/host.h>
 
+struct sdhci_next {
+	unsigned int sg_count;
+	s32 cookie;
+};
+
 struct sdhci_host {
 	/* Data set by hardware interface driver */
 	const char *hw_name;	/* Hardware bus name */
@@ -145,6 +150,8 @@ struct sdhci_host {
 	unsigned int            ocr_avail_sd;
 	unsigned int            ocr_avail_mmc;
 
+	struct sdhci_next next_data;
+
 	unsigned long private[0] ____cacheline_aligned;
 };
 #endif /* __SDHCI_H */
-- 
1.7.4.1

  parent reply	other threads:[~2011-04-16 16:48 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-06 19:07 [PATCH v2 00/12] mmc: use nonblock mmc requests to minimize latency Per Forlin
2011-04-06 19:07 ` [PATCH v2 01/12] mmc: add none blocking mmc request function Per Forlin
2011-04-15 10:34   ` David Vrabel
2011-04-20  7:17     ` Per Forlin
2011-04-26 13:29       ` David Vrabel
2011-04-26 14:22         ` Per Forlin
2011-04-06 19:07 ` [PATCH v2 02/12] mmc: mmc_test: add debugfs file to list all tests Per Forlin
2011-04-06 19:07 ` [PATCH v2 03/12] mmc: mmc_test: add test for none blocking transfers Per Forlin
2011-04-17  7:09   ` Lin Tony-B19295
2011-04-20  7:30     ` Per Forlin
2011-04-17 15:46   ` Shawn Guo
2011-04-20  7:41     ` Per Forlin
2011-04-06 19:07 ` [PATCH v2 04/12] mmc: add member in mmc queue struct to hold request data Per Forlin
2011-04-06 19:07 ` [PATCH v2 05/12] mmc: add a block request prepare function Per Forlin
2011-04-06 19:07 ` [PATCH v2 06/12] mmc: move error code in mmc_block_issue_rw_rq to a separate function Per Forlin
2011-04-06 19:07 ` [PATCH v2 07/12] mmc: add a second mmc queue request member Per Forlin
2011-04-06 19:07 ` [PATCH v2 08/12] mmc: add handling for two parallel block requests in issue_rw_rq Per Forlin
2011-04-20 11:32   ` Per Forlin
2011-04-06 19:07 ` [PATCH v2 09/12] mmc: test: add random fault injection in core.c Per Forlin
2011-04-06 19:07 ` [PATCH v2 10/12] omap_hsmmc: use original sg_len for dma_unmap_sg Per Forlin
2011-04-06 19:07 ` [PATCH v2 11/12] omap_hsmmc: add support for pre_req and post_req Per Forlin
2011-04-06 19:07 ` [PATCH v2 12/12] mmci: implement pre_req() and post_req() Per Forlin
2011-04-08 16:49 ` [PATCH v2 00/12] mmc: use nonblock mmc requests to minimize latency Linus Walleij
2011-04-09 11:55   ` Jae hoon Chung
2011-04-10  3:33     ` anish singh
2011-04-11  9:03       ` Per Forlin
2011-04-11  9:07         ` Sachin Nikam
2011-04-11  9:08     ` Per Forlin
2011-04-19 14:30       ` Jae hoon Chung
2011-04-16 15:48 ` Shawn Guo
2011-04-20  8:19   ` Per Forlin
2011-04-16 16:48 ` Shawn Guo [this message]
2011-04-16 23:06   ` [PATCH] mmc: sdhci: add support for pre_req and post_req Andrei Warkentin
2011-04-22 11:01     ` Jaehoon Chung
2011-04-27  0:59       ` Andrei Warkentin
2011-04-26  1:26     ` Jaehoon Chung
2011-04-26  2:47       ` Shawn Guo
2011-04-26 10:21         ` Per Forlin
2011-04-17 16:33 ` [PATCH] mmc: mxs-mmc: " Shawn Guo
2011-04-17 16:48   ` Shawn Guo
2011-04-20  8:01     ` Per Forlin
2011-04-20 14:01       ` Shawn Guo
2011-04-20 15:22         ` Per Forlin
2011-04-21  6:25           ` Shawn Guo
2011-04-21  8:52             ` Per Forlin
2011-04-20 15:30         ` Per Forlin
2011-04-21  6:29           ` Shawn Guo
2011-04-21  8:46             ` Per Forlin
2011-04-21  9:11               ` Shawn Guo
2011-04-21  9:47                 ` Per Forlin
2011-04-21 10:15                   ` Per Forlin
2011-04-28  7:52                   ` Per Forlin
2011-04-28 10:10                     ` Russell King - ARM Linux
2011-04-20  7:58   ` Per Forlin
2011-04-20  8:17     ` Shawn Guo
2011-04-20 13:51   ` [PATCH v2] " Shawn Guo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1302972516-8673-1-git-send-email-shawn.guo@linaro.org \
    --to=shawn.guo@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).