Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1488901 > unrolled thread

[PATCH PoC 0/7] mmc: switch to blk-mq

Started byBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
First post2016-09-22 16:00 +0200
Last post2016-09-22 16:10 +0200
Articles 6 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH PoC 0/7] mmc: switch to blk-mq Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> - 2016-09-22 16:00 +0200
    [PATCH PoC 1/7] mmc-mq: add debug printks Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> - 2016-09-22 16:00 +0200
    [PATCH PoC 2/7] mmc-mq: remove async requests support Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> - 2016-09-22 16:00 +0200
    [PATCH PoC 6/7] mmc-mq: initial blk-mq support Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> - 2016-09-22 16:00 +0200
    [PATCH PoC 5/7] mmc-mq: remove some debug printks Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> - 2016-09-22 16:00 +0200
    [PATCH PoC 4/7] mmc-mq: implement checking for queue busy condition Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> - 2016-09-22 16:10 +0200

#1488901 — [PATCH PoC 0/7] mmc: switch to blk-mq

FromBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date2016-09-22 16:00 +0200
Subject[PATCH PoC 0/7] mmc: switch to blk-mq
Message-ID<skcHE-74T-7@gated-at.bofh.it>
Hi,

Since Linus Walleij is also working on that and I won't
probably have time to touch this code till the end of
upcoming month, here it is (basically a code dump of my
proof-of-concept work).  I hope that it would be useful
to somebody.

It is extremely ugly & full of bogus debug code but boots
fine on my Odroid-XU3 and benchmarks can be run.

The patchset is based on top of patches up to "[PATCH v3
24/30] mmc: block: Introduce queue semantics" patch from
"[PATCH V3 00/30] mmc: mmc: dd Software Command Queuing"
series by Adrian Hunter:

  http://www.spinics.net/lists/linux-mmc/msg38013.html

[ It was commmit f3ba397441825f99edb4833a5f52dd2355d253c7
  in swcmdq branch from:

  http://git.infradead.org/users/ahunter/linux-sdhci.git

  Unfortunalty it got rebased later to V4 -- my patchset
  probably still applies and works fine but I have not
  tested this yet. ]

PS Linus, I got async requests support working, see patch #7.
You may be able to use this method depending on the hackiness
level of your patches. ;)


Initial benchmark results:

   root@target:~# time dd if=/dev/mmcblk0 of=/dev/null bs=4k

   vanilla - performance governor - 1300MHz/1800MHz
   15758000128 bytes (16 GB) copied, 69.8334 s, 226 MB/s

   blk-mq - performance governor - 1300MHz/1800MHz
   15758000128 bytes (16 GB) copied, 79.0868 s, 199 MB/s

   vanilla - performance governor - 200MHz/200MHz
   15758000128 bytes (16 GB) copied, 228.014 s, 69.1 MB/s

   blk-mq - performance governor - 200MHz/200MHz
   15758000128 bytes (16 GB) copied, 208.536 s, 75.6 MB/s

   vanilla - on-demand governor - 1300MHz/1800MHz
   15758000128 bytes (16 GB) copied, 77.0968 s, 204 MB/s

   blk-mq - on-demand governor - 1300/1800MHz
   15758000128 bytes (16 GB) copied, 96.351 s, 164 MB/s


   root@target:~# time dd if=/dev/mmcblk0 of=/dev/null

   vanilla - on-demand governor - 1300MHz/1800MHz
   15758000128 bytes (16 GB) copied, 155.149 s, 102 MB/s

   blk-mq - on-demand governor - 1300MHz/1800MHz
   15758000128 bytes (16 GB) copied, 106.122 s, 148 MB/s


Bartlomiej Zolnierkiewicz (7):
  mmc-mq: add debug printks
  mmc-mq: remove async requests support
  mmc-mq: request completion fixes
  mmc-mq: implement checking for queue busy condition
  mmc-mq: remove some debug printks
  mmc-mq: initial blk-mq support
  mmc-mq: async request support for blk-mq mode

 drivers/mmc/card/block.c    | 174 +++++++++++++-------------
 drivers/mmc/card/mmc_test.c |   8 +-
 drivers/mmc/card/queue.c    | 262 ++++++++++++++++++++++++++------------
 drivers/mmc/card/queue.h    |  50 +++++++-
 drivers/mmc/core/bus.c      |   2 -
 drivers/mmc/core/core.c     | 299 +++++++++++++++++++++++++++++---------------
 drivers/mmc/core/core.h     |   2 -
 drivers/mmc/core/mmc_ops.c  |   9 ++
 drivers/mmc/host/dw_mmc.c   |   3 +-
 include/linux/mmc/card.h    |   1 -
 include/linux/mmc/core.h    |   6 +-
 include/linux/mmc/host.h    |  15 ---
 12 files changed, 529 insertions(+), 302 deletions(-)

-- 
1.9.1

[toc] | [next] | [standalone]


#1488907 — [PATCH PoC 1/7] mmc-mq: add debug printks

FromBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date2016-09-22 16:00 +0200
Subject[PATCH PoC 1/7] mmc-mq: add debug printks
Message-ID<skcHF-74T-41@gated-at.bofh.it>
In reply to#1488901
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/mmc/card/block.c | 18 ++++++++++++++++--
 drivers/mmc/core/core.c  | 32 ++++++++++++++++++++++++++++++--
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 7d733d0..ce56930 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1995,6 +1995,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 	const u8 packed_nr = 2;
 	u8 reqs = 0;
 
+	pr_info("%s: enter\n", __func__);
 	if (rqc) {
 		mqrq_cur = mmc_queue_req_find(mq, rqc);
 		if (!mqrq_cur) {
@@ -2004,8 +2005,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 		}
 	}
 
-	if (!mq->qcnt)
+	if (!mq->qcnt) {
+		pr_info("%s: exit (0) (!mq->qcnt)\n", __func__);
 		return 0;
+	}
 
 	if (mqrq_cur)
 		reqs = mmc_blk_prep_packed_list(mq, mqrq_cur);
@@ -2035,8 +2038,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 		} else
 			areq = NULL;
 		areq = mmc_start_req(card->host, areq, (int *) &status);
-		if (!areq)
+		if (!areq) {
+			pr_info("%s: exit (0) (!areq)\n", __func__);
 			return 0;
+		}
 
 		mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
 		brq = &mq_rq->brq;
@@ -2150,6 +2155,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 
 	mmc_queue_req_free(mq, mq_rq);
 
+	pr_info("%s: exit (1)\n", __func__);
 	return 1;
 
  cmd_abort:
@@ -2184,6 +2190,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 
 	mmc_queue_req_free(mq, mq_rq);
 
+	pr_info("%s: exit (0)\n", __func__);
 	return 0;
 }
 
@@ -2194,10 +2201,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 	struct mmc_card *card = md->queue.card;
 	unsigned int cmd_flags = req ? req->cmd_flags : 0;
 
+	pr_info("%s: enter\n", __func__);
+
 	if (req && !mq->qcnt)
 		/* claim host only for the first request */
 		mmc_get_card(card);
 
+	pr_info("%s: mmc_blk_part_switch\n", __func__);
 	ret = mmc_blk_part_switch(card, md);
 	if (ret) {
 		if (req) {
@@ -2208,6 +2218,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 	}
 
 	if (cmd_flags & REQ_DISCARD) {
+		pr_info("%s: DISCARD rq\n", __func__);
 		/* complete ongoing async transfer before issuing discard */
 		if (mq->qcnt)
 			mmc_blk_issue_rw_rq(mq, NULL);
@@ -2216,11 +2227,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 		else
 			ret = mmc_blk_issue_discard_rq(mq, req);
 	} else if (cmd_flags & REQ_FLUSH) {
+		pr_info("%s: FLUSH rq\n", __func__);
 		/* complete ongoing async transfer before issuing flush */
 		if (mq->qcnt)
 			mmc_blk_issue_rw_rq(mq, NULL);
 		ret = mmc_blk_issue_flush(mq, req);
 	} else {
+		pr_info("%s: RW rq\n", __func__);
 		ret = mmc_blk_issue_rw_rq(mq, req);
 	}
 
@@ -2228,6 +2241,7 @@ out:
 	/* Release host when there are no more requests */
 	if (!mq->qcnt)
 		mmc_put_card(card);
+	pr_info("%s: exit\n", __func__);
 	return ret;
 }
 
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9be42691..d2d8d9b 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -219,6 +219,8 @@ static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 {
 	int err;
 
+	pr_info("%s: enter\n", __func__);
+
 	/* Assumes host controller has been runtime resumed by mmc_claim_host */
 	err = mmc_retune(host);
 	if (err) {
@@ -256,6 +258,8 @@ static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 	trace_mmc_request_start(host, mrq);
 
 	host->ops->request(host, mrq);
+
+	pr_info("%s: exit\n", __func__);
 }
 
 static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
@@ -264,6 +268,7 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 	unsigned int i, sz;
 	struct scatterlist *sg;
 #endif
+	pr_info("%s: enter\n", __func__);
 	mmc_retune_hold(host);
 
 	if (mmc_card_removed(host->card))
@@ -327,6 +332,7 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 	led_trigger_event(host->led, LED_FULL);
 	__mmc_start_request(host, mrq);
 
+	pr_info("%s: exit\n", __func__);
 	return 0;
 }
 
@@ -466,6 +472,8 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
 {
 	int err;
 
+	pr_info("%s: enter\n", __func__);
+
 	mmc_wait_ongoing_tfr_cmd(host);
 
 	init_completion(&mrq->completion);
@@ -480,6 +488,8 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
 		complete(&mrq->completion);
 	}
 
+	pr_info("%s: exit\n", __func__);
+
 	return err;
 }
 
@@ -502,10 +512,14 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host,
 	struct mmc_context_info *context_info = &host->context_info;
 	int err;
 
+	pr_info("%s: enter\n", __func__);
+
 	while (1) {
 		wait_event_interruptible(context_info->wait,
+//				context_info->is_done_rcv);
 				(context_info->is_done_rcv ||
 				 context_info->is_new_req));
+		pr_info("%s: waiting done\n", __func__);
 		context_info->is_waiting_last_req = false;
 		if (context_info->is_done_rcv) {
 			context_info->is_done_rcv = false;
@@ -527,11 +541,14 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host,
 				continue; /* wait for done/new event again */
 			}
 		} else if (context_info->is_new_req) {
-			if (!next_req)
+			if (!next_req) {
+				pr_info("%s: exit (!next_req)\n", __func__);
 				return MMC_BLK_NEW_REQUEST;
+			}
 		}
 	}
 	mmc_retune_release(host);
+	pr_info("%s: exit (err=%d)\n", __func__, err);
 	return err;
 }
 
@@ -539,8 +556,11 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq)
 {
 	struct mmc_command *cmd;
 
+	pr_info("%s: enter\n", __func__);
+
 	while (1) {
 		wait_for_completion(&mrq->completion);
+		pr_info("%s: waiting done\n", __func__);
 
 		cmd = mrq->cmd;
 
@@ -567,7 +587,7 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq)
 
 		mmc_retune_recheck(host);
 
-		pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
+		pr_info("%s: req failed (CMD%u): %d, retrying...\n",
 			 mmc_hostname(host), cmd->opcode, cmd->error);
 		cmd->retries--;
 		cmd->error = 0;
@@ -575,6 +595,8 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq)
 	}
 
 	mmc_retune_release(host);
+
+	pr_info("%s: exit\n", __func__);
 }
 EXPORT_SYMBOL(mmc_wait_for_req_done);
 
@@ -656,6 +678,10 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
 	int start_err = 0;
 	struct mmc_async_req *data = host->areq;
 
+	pr_info("%s: enter\n", __func__);
+
+	pr_info("%s: areq=%p host->areq=%p\n", __func__, areq, host->areq);
+
 	/* Prepare a new request */
 	if (areq && !areq->pre_req_done) {
 		areq->pre_req_done = true;
@@ -671,6 +697,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
 			 * The previous request was not completed,
 			 * nothing to return
 			 */
+			pr_info("%s: exit (NULL)\n", __func__);
 			return NULL;
 		}
 		/*
@@ -714,6 +741,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
 
 	if (error)
 		*error = err;
+	pr_info("%s: exit (data=%p)\n", __func__, data);
 	return data;
 }
 EXPORT_SYMBOL(mmc_start_req);
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1488908 — [PATCH PoC 2/7] mmc-mq: remove async requests support

FromBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date2016-09-22 16:00 +0200
Subject[PATCH PoC 2/7] mmc-mq: remove async requests support
Message-ID<skcHF-74T-43@gated-at.bofh.it>
In reply to#1488901
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/mmc/card/block.c |  62 ++++++++++++--------------
 drivers/mmc/card/queue.c | 113 +++++++++++++++--------------------------------
 drivers/mmc/card/queue.h |   5 +--
 drivers/mmc/core/bus.c   |   2 -
 drivers/mmc/core/core.c  | 110 +++++++++------------------------------------
 drivers/mmc/core/core.h  |   2 -
 include/linux/mmc/card.h |   1 -
 include/linux/mmc/host.h |  15 -------
 8 files changed, 85 insertions(+), 225 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index ce56930..1d4a09f 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1192,7 +1192,7 @@ int mmc_access_rpmb(struct mmc_queue *mq)
 	return false;
 }
 
-static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
+static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req, struct mmc_queue_req *mqrq)
 {
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
@@ -1230,13 +1230,14 @@ out:
 		goto retry;
 	if (!err)
 		mmc_blk_reset_success(md, type);
+	mmc_queue_req_free(mq, mqrq);
 	blk_end_request(req, err, blk_rq_bytes(req));
 
 	return err ? 0 : 1;
 }
 
 static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
-				       struct request *req)
+				       struct request *req, struct mmc_queue_req *mqrq)
 {
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
@@ -1297,12 +1298,13 @@ out_retry:
 	if (!err)
 		mmc_blk_reset_success(md, type);
 out:
+	mmc_queue_req_free(mq, mqrq);
 	blk_end_request(req, err, blk_rq_bytes(req));
 
 	return err ? 0 : 1;
 }
 
-static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
+static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req, struct mmc_queue_req *mqrq)
 {
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
@@ -1312,6 +1314,7 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
 	if (ret)
 		ret = -EIO;
 
+	mmc_queue_req_free(mq, mqrq);
 	blk_end_request_all(req, ret);
 
 	return ret ? 0 : 1;
@@ -1918,6 +1921,7 @@ static int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq)
 	int idx = packed->idx_failure, i = 0;
 	int ret = 0;
 
+	BUG();
 	BUG_ON(!packed);
 
 	while (!list_empty(&packed->list)) {
@@ -1981,7 +1985,7 @@ static void mmc_blk_revert_packed_req(struct mmc_queue *mq,
 	mmc_blk_clear_packed(mq_rq);
 }
 
-static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
+static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
 {
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
@@ -1990,20 +1994,14 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 	enum mmc_blk_status status;
 	struct mmc_queue_req *mqrq_cur = NULL;
 	struct mmc_queue_req *mq_rq;
-	struct request *req;
+	struct request *rqc = NULL, *req;
 	struct mmc_async_req *areq;
 	const u8 packed_nr = 2;
 	u8 reqs = 0;
 
 	pr_info("%s: enter\n", __func__);
-	if (rqc) {
-		mqrq_cur = mmc_queue_req_find(mq, rqc);
-		if (!mqrq_cur) {
-			WARN_ON(1);
-			mmc_blk_requeue(mq->queue, rqc);
-			rqc = NULL;
-		}
-	}
+	mqrq_cur = mqrq;
+	rqc = mqrq_cur->req;
 
 	if (!mq->qcnt) {
 		pr_info("%s: exit (0) (!mq->qcnt)\n", __func__);
@@ -2059,10 +2057,14 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 
 			if (mmc_packed_cmd(mq_rq->cmd_type)) {
 				ret = mmc_blk_end_packed_req(mq_rq);
+				mmc_queue_req_free(mq, mq_rq); //
+				pr_info("%s: freeing mqrq (packed)\n", __func__); //
 				break;
 			} else {
-				ret = blk_end_request(req, 0,
-						brq->data.bytes_xfered);
+				int bytes = brq->data.bytes_xfered;
+				mmc_queue_req_free(mq, mq_rq); //
+				pr_info("%s: freeing mqrq\n", __func__); //
+				ret = blk_end_request(req, 0, bytes);
 			}
 
 			/*
@@ -2153,9 +2155,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 		}
 	} while (ret);
 
-	mmc_queue_req_free(mq, mq_rq);
-
-	pr_info("%s: exit (1)\n", __func__);
+	pr_info("%s: exit (1==ok)\n", __func__);
 	return 1;
 
  cmd_abort:
@@ -2194,7 +2194,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 	return 0;
 }
 
-static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
+static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req, struct mmc_queue_req *mqrq)
 {
 	int ret;
 	struct mmc_blk_data *md = mq->data;
@@ -2203,9 +2203,10 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
 	pr_info("%s: enter\n", __func__);
 
-	if (req && !mq->qcnt)
-		/* claim host only for the first request */
-		mmc_get_card(card);
+	BUG_ON(!req);
+
+	/* claim host only for the first request */
+	mmc_get_card(card);
 
 	pr_info("%s: mmc_blk_part_switch\n", __func__);
 	ret = mmc_blk_part_switch(card, md);
@@ -2219,28 +2220,21 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
 	if (cmd_flags & REQ_DISCARD) {
 		pr_info("%s: DISCARD rq\n", __func__);
-		/* complete ongoing async transfer before issuing discard */
-		if (mq->qcnt)
-			mmc_blk_issue_rw_rq(mq, NULL);
 		if (req->cmd_flags & REQ_SECURE)
-			ret = mmc_blk_issue_secdiscard_rq(mq, req);
+			ret = mmc_blk_issue_secdiscard_rq(mq, req, mqrq);
 		else
-			ret = mmc_blk_issue_discard_rq(mq, req);
+			ret = mmc_blk_issue_discard_rq(mq, req, mqrq);
 	} else if (cmd_flags & REQ_FLUSH) {
 		pr_info("%s: FLUSH rq\n", __func__);
-		/* complete ongoing async transfer before issuing flush */
-		if (mq->qcnt)
-			mmc_blk_issue_rw_rq(mq, NULL);
-		ret = mmc_blk_issue_flush(mq, req);
+		ret = mmc_blk_issue_flush(mq, req, mqrq);
 	} else {
 		pr_info("%s: RW rq\n", __func__);
-		ret = mmc_blk_issue_rw_rq(mq, req);
+		ret = mmc_blk_issue_rw_rq(mq, mqrq);
 	}
 
 out:
 	/* Release host when there are no more requests */
-	if (!mq->qcnt)
-		mmc_put_card(card);
+	mmc_put_card(card);
 	pr_info("%s: exit\n", __func__);
 	return ret;
 }
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 5a016ce..e9c9bbf 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -52,15 +52,22 @@ struct mmc_queue_req *mmc_queue_req_find(struct mmc_queue *mq,
 	struct mmc_queue_req *mqrq;
 	int i = ffz(mq->qslots);
 
+	pr_info("%s: enter (%d)\n", __func__, i);
+
+	WARN_ON(i >= mq->qdepth);
 	if (i >= mq->qdepth)
 		return NULL;
 
+////	spin_lock_irq(req->q->queue_lock);
 	mqrq = &mq->mqrq[i];
 	WARN_ON(mqrq->req || mq->qcnt >= mq->qdepth ||
 		test_bit(mqrq->task_id, &mq->qslots));
 	mqrq->req = req;
 	mq->qcnt += 1;
 	__set_bit(mqrq->task_id, &mq->qslots);
+////	spin_unlock_irq(req->q->queue_lock);
+
+	pr_info("%s: exit\n", __func__);
 
 	return mqrq;
 }
@@ -68,60 +75,17 @@ struct mmc_queue_req *mmc_queue_req_find(struct mmc_queue *mq,
 void mmc_queue_req_free(struct mmc_queue *mq,
 			struct mmc_queue_req *mqrq)
 {
+	struct request *req;
+	pr_info("%s: enter\n", __func__);
+	req = mqrq->req;
+	spin_lock_irq(req->q->queue_lock);
 	WARN_ON(!mqrq->req || mq->qcnt < 1 ||
 		!test_bit(mqrq->task_id, &mq->qslots));
 	mqrq->req = NULL;
 	mq->qcnt -= 1;
 	__clear_bit(mqrq->task_id, &mq->qslots);
-}
-
-static int mmc_queue_thread(void *d)
-{
-	struct mmc_queue *mq = d;
-	struct request_queue *q = mq->queue;
-	struct mmc_context_info *cntx = &mq->card->host->context_info;
-
-	current->flags |= PF_MEMALLOC;
-
-	down(&mq->thread_sem);
-	do {
-		struct request *req;
-
-		spin_lock_irq(q->queue_lock);
-		set_current_state(TASK_INTERRUPTIBLE);
-		req = blk_fetch_request(q);
-		mq->asleep = false;
-		cntx->is_waiting_last_req = false;
-		cntx->is_new_req = false;
-		if (!req) {
-			/*
-			 * Dispatch queue is empty so set flags for
-			 * mmc_request_fn() to wake us up.
-			 */
-			if (mq->qcnt)
-				cntx->is_waiting_last_req = true;
-			else
-				mq->asleep = true;
-		}
-		spin_unlock_irq(q->queue_lock);
-
-		if (req || mq->qcnt) {
-			set_current_state(TASK_RUNNING);
-			mq->issue_fn(mq, req);
-			cond_resched();
-		} else {
-			if (kthread_should_stop()) {
-				set_current_state(TASK_RUNNING);
-				break;
-			}
-			up(&mq->thread_sem);
-			schedule();
-			down(&mq->thread_sem);
-		}
-	} while (1);
-	up(&mq->thread_sem);
-
-	return 0;
+	spin_unlock_irq(req->q->queue_lock);
+	pr_info("%s: exit\n", __func__);
 }
 
 /*
@@ -134,7 +98,7 @@ static void mmc_request_fn(struct request_queue *q)
 {
 	struct mmc_queue *mq = q->queuedata;
 	struct request *req;
-	struct mmc_context_info *cntx;
+	struct mmc_queue_req *mqrq_cur = NULL;
 
 	if (!mq) {
 		while ((req = blk_fetch_request(q)) != NULL) {
@@ -143,16 +107,28 @@ static void mmc_request_fn(struct request_queue *q)
 		}
 		return;
 	}
-
-	cntx = &mq->card->host->context_info;
-
-	if (cntx->is_waiting_last_req) {
-		cntx->is_new_req = true;
-		wake_up_interruptible(&cntx->wait);
+repeat:
+	req = blk_fetch_request(q);
+	if (req && req->cmd_type == REQ_TYPE_FS) {
+		mqrq_cur = mmc_queue_req_find(mq, req);
+		if (!mqrq_cur) {
+			pr_info("%s: command already queued (%d)\n", __func__, mq->qcnt);
+//			WARN_ON(1);
+//			spin_unlock_irq(q->queue_lock);
+			blk_requeue_request(mq->queue, req);
+//			spin_lock_irq(q->queue_lock);
+			req = NULL;
+		}
 	}
-
-	if (mq->asleep)
-		wake_up_process(mq->thread);
+	if (!req) {
+		pr_info("%s: no request\n", __func__);
+		return;
+	}
+	spin_unlock_irq(q->queue_lock);
+	mq->issue_fn(mq, req, mqrq_cur);
+	spin_lock_irq(q->queue_lock);
+	goto repeat;
+//#endif
 }
 
 static struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
@@ -305,7 +281,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 	if (!mq->queue)
 		return -ENOMEM;
 
-	mq->qdepth = 2;
+	mq->qdepth = 1;
 	mq->mqrq = mmc_queue_alloc_mqrqs(mq, mq->qdepth);
 	if (!mq->mqrq)
 		goto blk_cleanup;
@@ -357,16 +333,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 			goto cleanup_queue;
 	}
 
-	sema_init(&mq->thread_sem, 1);
-
-	mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s",
-		host->index, subname ? subname : "");
-
-	if (IS_ERR(mq->thread)) {
-		ret = PTR_ERR(mq->thread);
-		goto cleanup_queue;
-	}
-
 	return 0;
 
  cleanup_queue:
@@ -386,9 +352,6 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
 	/* Make sure the queue isn't suspended, as that will deadlock */
 	mmc_queue_resume(mq);
 
-	/* Then terminate our worker thread */
-	kthread_stop(mq->thread);
-
 	/* Empty the queue */
 	spin_lock_irqsave(q->queue_lock, flags);
 	q->queuedata = NULL;
@@ -468,8 +431,6 @@ void mmc_queue_suspend(struct mmc_queue *mq)
 		spin_lock_irqsave(q->queue_lock, flags);
 		blk_stop_queue(q);
 		spin_unlock_irqrestore(q->queue_lock, flags);
-
-		down(&mq->thread_sem);
 	}
 }
 
@@ -485,8 +446,6 @@ void mmc_queue_resume(struct mmc_queue *mq)
 	if (mq->flags & MMC_QUEUE_SUSPENDED) {
 		mq->flags &= ~MMC_QUEUE_SUSPENDED;
 
-		up(&mq->thread_sem);
-
 		spin_lock_irqsave(q->queue_lock, flags);
 		blk_start_queue(q);
 		spin_unlock_irqrestore(q->queue_lock, flags);
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 1afd5da..c52fa88 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -47,13 +47,10 @@ struct mmc_queue_req {
 
 struct mmc_queue {
 	struct mmc_card		*card;
-	struct task_struct	*thread;
-	struct semaphore	thread_sem;
 	unsigned int		flags;
 #define MMC_QUEUE_SUSPENDED	(1 << 0)
-	bool			asleep;
 
-	int			(*issue_fn)(struct mmc_queue *, struct request *);
+	int			(*issue_fn)(struct mmc_queue *, struct request *, struct mmc_queue_req *mqrq);
 	void			*data;
 	struct request_queue	*queue;
 	struct mmc_queue_req	*mqrq;
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index c64266f..949e569 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -346,8 +346,6 @@ int mmc_add_card(struct mmc_card *card)
 #ifdef CONFIG_DEBUG_FS
 	mmc_add_card_debugfs(card);
 #endif
-	mmc_init_context_info(card->host);
-
 	card->dev.of_node = mmc_of_find_child_device(card->host, 0);
 
 	device_enable_async_suspend(&card->dev);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d2d8d9b..7496c22 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -29,6 +29,7 @@
 #include <linux/random.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/kernel.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -44,6 +45,7 @@
 #include "host.h"
 #include "sdio_bus.h"
 #include "pwrseq.h"
+#include "../card/queue.h"
 
 #include "mmc_ops.h"
 #include "sd_ops.h"
@@ -407,19 +409,11 @@ out:
 EXPORT_SYMBOL(mmc_start_bkops);
 
 /*
- * mmc_wait_data_done() - done callback for data request
- * @mrq: done data request
+ * mmc_wait_done() - done callback for request
+ * @mrq: done request
  *
  * Wakes up mmc context, passed as a callback to host controller driver
  */
-static void mmc_wait_data_done(struct mmc_request *mrq)
-{
-	struct mmc_context_info *context_info = &mrq->host->context_info;
-
-	context_info->is_done_rcv = true;
-	wake_up_interruptible(&context_info->wait);
-}
-
 static void mmc_wait_done(struct mmc_request *mrq)
 {
 	complete(&mrq->completion);
@@ -438,36 +432,15 @@ static inline void mmc_wait_ongoing_tfr_cmd(struct mmc_host *host)
 }
 
 /*
- *__mmc_start_data_req() - starts data request
+ *__mmc_start_req() - starts request
  * @host: MMC host to start the request
- * @mrq: data request to start
+ * @mrq: request to start
  *
  * Sets the done callback to be called when request is completed by the card.
- * Starts data mmc request execution
+ * Starts mmc request execution
  * If an ongoing transfer is already in progress, wait for the command line
  * to become available before sending another command.
  */
-static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq)
-{
-	int err;
-
-	mmc_wait_ongoing_tfr_cmd(host);
-
-	mrq->done = mmc_wait_data_done;
-	mrq->host = host;
-
-	init_completion(&mrq->cmd_completion);
-
-	err = mmc_start_request(host, mrq);
-	if (err) {
-		mrq->cmd->error = err;
-		mmc_complete_cmd(mrq);
-		mmc_wait_data_done(mrq);
-	}
-
-	return err;
-}
-
 static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
 {
 	int err;
@@ -478,6 +451,7 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
 
 	init_completion(&mrq->completion);
 	mrq->done = mmc_wait_done;
+	mrq->host = host;
 
 	init_completion(&mrq->cmd_completion);
 
@@ -485,7 +459,7 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
 	if (err) {
 		mrq->cmd->error = err;
 		mmc_complete_cmd(mrq);
-		complete(&mrq->completion);
+		mmc_wait_done(mrq);
 	}
 
 	pr_info("%s: exit\n", __func__);
@@ -508,21 +482,17 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host,
 				      struct mmc_request *mrq,
 				      struct mmc_async_req *next_req)
 {
+	struct mmc_queue_req *mq_mrq = container_of(next_req, struct mmc_queue_req,
+						    mmc_active);
 	struct mmc_command *cmd;
-	struct mmc_context_info *context_info = &host->context_info;
 	int err;
 
 	pr_info("%s: enter\n", __func__);
 
 	while (1) {
-		wait_event_interruptible(context_info->wait,
-//				context_info->is_done_rcv);
-				(context_info->is_done_rcv ||
-				 context_info->is_new_req));
+		wait_for_completion(&mrq->completion);
 		pr_info("%s: waiting done\n", __func__);
-		context_info->is_waiting_last_req = false;
-		if (context_info->is_done_rcv) {
-			context_info->is_done_rcv = false;
+		if (1) {
 			cmd = mrq->cmd;
 
 			if (!cmd->error || !cmd->retries ||
@@ -540,11 +510,6 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host,
 				__mmc_start_request(host, mrq);
 				continue; /* wait for done/new event again */
 			}
-		} else if (context_info->is_new_req) {
-			if (!next_req) {
-				pr_info("%s: exit (!next_req)\n", __func__);
-				return MMC_BLK_NEW_REQUEST;
-			}
 		}
 	}
 	mmc_retune_release(host);
@@ -614,10 +579,7 @@ EXPORT_SYMBOL(mmc_wait_for_req_done);
  */
 bool mmc_is_req_done(struct mmc_host *host, struct mmc_request *mrq)
 {
-	if (host->areq)
-		return host->context_info.is_done_rcv;
-	else
-		return completion_done(&mrq->completion);
+	return completion_done(&mrq->completion);
 }
 EXPORT_SYMBOL(mmc_is_req_done);
 
@@ -688,18 +650,12 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
 		mmc_pre_req(host, areq->mrq, !host->areq);
 	}
 
+	if (areq) //
+		start_err = __mmc_start_req(host, areq->mrq); //
+
+	host->areq = areq; //
 	if (host->areq) {
 		err = mmc_wait_for_data_req_done(host, host->areq->mrq,	areq);
-		if (err == MMC_BLK_NEW_REQUEST) {
-			if (error)
-				*error = err;
-			/*
-			 * The previous request was not completed,
-			 * nothing to return
-			 */
-			pr_info("%s: exit (NULL)\n", __func__);
-			return NULL;
-		}
 		/*
 		 * Check BKOPS urgency for each R1 response
 		 */
@@ -720,24 +676,14 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
 		}
 	}
 
-	if (!err && areq)
-		start_err = __mmc_start_data_req(host, areq->mrq);
-
 	if (host->areq) {
 		host->areq->pre_req_done = false;
 		mmc_post_req(host, host->areq->mrq, 0);
 	}
 
-	 /* Cancel a prepared request if it was not started. */
-	if ((err || start_err) && areq) {
-		areq->pre_req_done = false;
-		mmc_post_req(host, areq->mrq, -EINVAL);
-	}
 
-	if (err)
-		host->areq = NULL;
-	else
-		host->areq = areq;
+	data = host->areq; //
+	host->areq = NULL; //
 
 	if (error)
 		*error = err;
@@ -2960,22 +2906,6 @@ void mmc_unregister_pm_notifier(struct mmc_host *host)
 }
 #endif
 
-/**
- * mmc_init_context_info() - init synchronization context
- * @host: mmc host
- *
- * Init struct context_info needed to implement asynchronous
- * request mechanism, used by mmc core, host driver and mmc requests
- * supplier.
- */
-void mmc_init_context_info(struct mmc_host *host)
-{
-	host->context_info.is_new_req = false;
-	host->context_info.is_done_rcv = false;
-	host->context_info.is_waiting_last_req = false;
-	init_waitqueue_head(&host->context_info.wait);
-}
-
 static int __init mmc_init(void)
 {
 	int ret;
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 0fa86a2..34e664b 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -84,8 +84,6 @@ void mmc_remove_host_debugfs(struct mmc_host *host);
 void mmc_add_card_debugfs(struct mmc_card *card);
 void mmc_remove_card_debugfs(struct mmc_card *card);
 
-void mmc_init_context_info(struct mmc_host *host);
-
 int mmc_execute_tuning(struct mmc_card *card);
 int mmc_hs200_to_hs400(struct mmc_card *card);
 int mmc_hs400_to_hs200(struct mmc_card *card);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 3d7434e..810f318 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -219,7 +219,6 @@ enum mmc_blk_status {
 	MMC_BLK_DATA_ERR,
 	MMC_BLK_ECC_ERR,
 	MMC_BLK_NOMEDIUM,
-	MMC_BLK_NEW_REQUEST,
 };
 
 /* The number of MMC physical partitions.  These consist of:
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 9fb00b7..1a46cbd 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -193,20 +193,6 @@ struct mmc_slot {
 	void *handler_priv;
 };
 
-/**
- * mmc_context_info - synchronization details for mmc context
- * @is_done_rcv		wake up reason was done request
- * @is_new_req		wake up reason was new request
- * @is_waiting_last_req	mmc context waiting for single running request
- * @wait		wait queue
- */
-struct mmc_context_info {
-	bool			is_done_rcv;
-	bool			is_new_req;
-	bool			is_waiting_last_req;
-	wait_queue_head_t	wait;
-};
-
 struct regulator;
 struct mmc_pwrseq;
 
@@ -380,7 +366,6 @@ struct mmc_host {
 	struct dentry		*debugfs_root;
 
 	struct mmc_async_req	*areq;		/* active async req */
-	struct mmc_context_info	context_info;	/* async synchronization info */
 
 	/* Ongoing data transfer that allows commands during transfer */
 	struct mmc_request	*ongoing_mrq;
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1488909 — [PATCH PoC 6/7] mmc-mq: initial blk-mq support

FromBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date2016-09-22 16:00 +0200
Subject[PATCH PoC 6/7] mmc-mq: initial blk-mq support
Message-ID<skcHF-74T-45@gated-at.bofh.it>
In reply to#1488901
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/mmc/card/block.c | 15 +++++----
 drivers/mmc/card/queue.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++--
 drivers/mmc/card/queue.h |  3 ++
 drivers/mmc/core/core.c  |  7 ++--
 4 files changed, 98 insertions(+), 12 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index ef230e8..9968623 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -27,6 +27,7 @@
 #include <linux/errno.h>
 #include <linux/hdreg.h>
 #include <linux/kdev_t.h>
+#include <linux/blk-mq.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
 #include <linux/scatterlist.h>
@@ -1235,7 +1236,7 @@ out:
 		mmc_blk_reset_success(md, type);
 	mmc_put_card(card);
 	mmc_queue_req_free(mq, mqrq);
-	blk_end_request(req, err, blk_rq_bytes(req));
+	blk_mq_end_request(req, err);
 
 	return err ? 0 : 1;
 }
@@ -1304,7 +1305,7 @@ out_retry:
 out:
 	mmc_put_card(card);
 	mmc_queue_req_free(mq, mqrq);
-	blk_end_request(req, err, blk_rq_bytes(req));
+	blk_mq_end_request(req, err);
 
 	return err ? 0 : 1;
 }
@@ -1321,16 +1322,14 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req, struct
 
 	mmc_put_card(card);
 	mmc_queue_req_free(mq, mqrq);
-	blk_end_request_all(req, ret);
+	blk_mq_end_request(req, ret);
 
 	return ret ? 0 : 1;
 }
 
 static void mmc_blk_requeue(struct request_queue *q, struct request *req)
 {
-	spin_lock_irq(q->queue_lock);
-	blk_requeue_request(q, req);
-	spin_unlock_irq(q->queue_lock);
+	blk_mq_requeue_request(req);
 }
 
 /*
@@ -2219,12 +2218,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req, struct mm
 	/* claim host only for the first request */
 	mmc_get_card(card);
 
+	blk_mq_start_request(req);
+
 //	pr_info("%s: mmc_blk_part_switch (mq=%p md=%p)\n", __func__, mq, md);
 	ret = mmc_blk_part_switch(card, md);
 	if (ret) {
 		if (req) {
 			mmc_queue_req_free(req->q->queuedata, mqrq); //
-			blk_end_request_all(req, -EIO);
+			blk_mq_end_request(req, -EIO);
 		}
 		ret = 0;
 		goto out;
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index d4f4859..038c01e 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -11,6 +11,7 @@
  */
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/blk-mq.h>
 #include <linux/blkdev.h>
 #include <linux/freezer.h>
 #include <linux/kthread.h>
@@ -280,6 +281,59 @@ static void mmc_queue_reqs_free_bufs(struct mmc_queue *mq)
 		mmc_queue_req_free_bufs(&mq->mqrq[i]);
 }
 
+static int mmc_init_request(void *data, struct request *rq,
+		unsigned int hctx_idx, unsigned int request_idx,
+		unsigned int numa_node)
+{
+//	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+
+//	cmd->sense_buffer = kzalloc_node(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL,
+//			numa_node);
+//	if (!cmd->sense_buffer)
+//		return -ENOMEM;
+	return 0;
+}
+
+static void mmc_exit_request(void *data, struct request *rq,
+		unsigned int hctx_idx, unsigned int request_idx)
+{
+//	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+
+//	kfree(cmd->sense_buffer);
+}
+
+static int mmc_queue_rq(struct blk_mq_hw_ctx *hctx,
+			 const struct blk_mq_queue_data *bd)
+{
+	struct request *req = bd->rq;
+	struct request_queue *q = req->q;
+	struct mmc_queue *mq = q->queuedata;
+	struct mmc_queue_req *mqrq_cur;
+//	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
+	int ret;
+
+	WARN_ON(req && req->cmd_type != REQ_TYPE_FS);
+
+	if (!mmc_queue_ready(q, mq))
+		return BLK_MQ_RQ_QUEUE_BUSY;
+
+	mqrq_cur = mmc_queue_req_find(mq, req);
+	BUG_ON(!mqrq_cur);
+	mq->issue_fn(mq, req, mqrq_cur);
+
+	return BLK_MQ_RQ_QUEUE_OK;
+}
+
+static struct blk_mq_ops mmc_mq_ops = {
+	.map_queue	= blk_mq_map_queue,
+	.queue_rq	= mmc_queue_rq,
+//	.complete	= scsi_softirq_done,
+//	.timeout	= scsi_timeout,
+	.init_request	= mmc_init_request,
+	.exit_request	= mmc_exit_request,
+};
+
+
 /**
  * mmc_init_queue - initialise a queue structure.
  * @mq: mmc queue
@@ -293,6 +347,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 		   spinlock_t *lock, const char *subname)
 {
 	struct mmc_host *host = card->host;
+ 	struct request_queue *q;
 	u64 limit = BLK_BOUNCE_HIGH;
 	bool bounce = false;
 	int ret = -ENOMEM;
@@ -301,9 +356,28 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 		limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
 
 	mq->card = card;
-	mq->queue = blk_init_queue(mmc_request_fn, lock);
-	if (!mq->queue)
-		return -ENOMEM;
+//	mq->queue = blk_init_queue(mmc_request_fn, lock);
+//	if (!mq->queue)
+//		return -ENOMEM;
+	memset(&mq->tag_set, 0, sizeof(mq->tag_set));
+	mq->tag_set.ops = &mmc_mq_ops;
+	mq->tag_set.queue_depth = 1;
+	mq->tag_set.numa_node = NUMA_NO_NODE;
+	mq->tag_set.flags =
+		BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE;
+	mq->tag_set.nr_hw_queues = 1;
+	mq->tag_set.cmd_size = sizeof(struct mmc_queue_req);
+
+	ret = blk_mq_alloc_tag_set(&mq->tag_set);
+	if (ret)
+		goto out;
+
+	q = blk_mq_init_queue(&mq->tag_set);
+	if (IS_ERR(q)) {
+		ret = PTR_ERR(q);
+		goto cleanup_tag_set;
+	}
+	mq->queue = q;
 
 	mq->qdepth = 1;
 	mq->mqrq = mmc_queue_alloc_mqrqs(mq, mq->qdepth);
@@ -366,6 +440,9 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 	mq->mqrq = NULL;
 blk_cleanup:
 	blk_cleanup_queue(mq->queue);
+cleanup_tag_set:
+	blk_mq_free_tag_set(&mq->tag_set);
+out:
 	return ret;
 }
 
@@ -387,6 +464,8 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
 	kfree(mq->mqrq);
 	mq->mqrq = NULL;
 
+	blk_mq_free_tag_set(&mq->tag_set);
+
 	mq->card = NULL;
 }
 EXPORT_SYMBOL(mmc_cleanup_queue);
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 20399e4..b67ac83 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -63,6 +63,9 @@ struct mmc_queue {
 	int			testtag;
 
 	atomic_t		device_busy;
+
+	/* Block layer tags. */
+	struct blk_mq_tag_set	tag_set;
 };
 
 extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 549e65e..64687f1 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/kernel.h>
+#include <linux/blk-mq.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -489,8 +490,10 @@ BUG_ON(mq_rq && (mq_rq->req->cmd_type == REQ_TYPE_FS) && (mq_rq->req->cmd_flags
 		mmc_put_card(host->card);
 //		pr_info("%s: freeing mqrq\n", __func__); //
 		mmc_queue_req_free(req->q->queuedata, mq_rq); //
-		ret = blk_end_request(req, 0, bytes);
-
+//		ret = blk_end_request(req, 0, bytes);
+		ret = blk_update_request(req, 0, bytes);
+		if (!ret)
+			__blk_mq_end_request(req, 0);
 	}
 //out:
 //	pr_info("%s: exit (err=%d, ret=%d)\n", __func__, err, ret);
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1488910 — [PATCH PoC 5/7] mmc-mq: remove some debug printks

FromBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date2016-09-22 16:00 +0200
Subject[PATCH PoC 5/7] mmc-mq: remove some debug printks
Message-ID<skcHF-74T-51@gated-at.bofh.it>
In reply to#1488901
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/mmc/card/block.c | 16 ++++++++--------
 drivers/mmc/card/queue.c | 12 ++++++------
 drivers/mmc/core/core.c  | 45 +++++++++++++++++++++++----------------------
 3 files changed, 37 insertions(+), 36 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 3c2bdc2..ef230e8 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2008,7 +2008,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
 	const u8 packed_nr = 2;
 	u8 reqs = 0;
 
-	pr_info("%s: enter\n", __func__);
+//	pr_info("%s: enter\n", __func__);
 	mqrq_cur = mqrq;
 	rqc = mqrq_cur->req;
 
@@ -2166,7 +2166,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
 #endif
 	} while (ret);
 
-	pr_info("%s: exit (1==ok)\n", __func__);
+//	pr_info("%s: exit (1==ok)\n", __func__);
 	return 1;
 
  cmd_abort:
@@ -2212,14 +2212,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req, struct mm
 	struct mmc_card *card = md->queue.card;
 	unsigned int cmd_flags = req ? req->cmd_flags : 0;
 
-	pr_info("%s: enter (mq=%p md=%p)\n", __func__, mq, md);
+//	pr_info("%s: enter (mq=%p md=%p)\n", __func__, mq, md);
 
 	BUG_ON(!req);
 
 	/* claim host only for the first request */
 	mmc_get_card(card);
 
-	pr_info("%s: mmc_blk_part_switch (mq=%p md=%p)\n", __func__, mq, md);
+//	pr_info("%s: mmc_blk_part_switch (mq=%p md=%p)\n", __func__, mq, md);
 	ret = mmc_blk_part_switch(card, md);
 	if (ret) {
 		if (req) {
@@ -2231,23 +2231,23 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req, struct mm
 	}
 
 	if (cmd_flags & REQ_DISCARD) {
-		pr_info("%s: DISCARD rq (mq=%p md=%p)\n", __func__, mq, md);
+//		pr_info("%s: DISCARD rq (mq=%p md=%p)\n", __func__, mq, md);
 		if (req->cmd_flags & REQ_SECURE)
 			ret = mmc_blk_issue_secdiscard_rq(mq, req, mqrq);
 		else
 			ret = mmc_blk_issue_discard_rq(mq, req, mqrq);
 	} else if (cmd_flags & REQ_FLUSH) {
-		pr_info("%s: FLUSH rq (mq=%p md=%p)\n", __func__, mq, md);
+//		pr_info("%s: FLUSH rq (mq=%p md=%p)\n", __func__, mq, md);
 		ret = mmc_blk_issue_flush(mq, req, mqrq);
 	} else {
-		pr_info("%s: RW rq (mq=%p md=%p)\n", __func__, mq, md);
+//		pr_info("%s: RW rq (mq=%p md=%p)\n", __func__, mq, md);
 		ret = mmc_blk_issue_rw_rq(mq, mqrq);
 	}
 
 out:
 	/* Release host when there are no more requests */
 /////	mmc_put_card(card);
-	pr_info("%s: exit (mq=%p md=%p)\n", __func__, mq, md);
+//	pr_info("%s: exit (mq=%p md=%p)\n", __func__, mq, md);
 	return ret;
 }
 
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 3ed4477..d4f4859 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -67,7 +67,7 @@ struct mmc_queue_req *mmc_queue_req_find(struct mmc_queue *mq,
 	struct mmc_queue_req *mqrq;
 	int i = ffz(mq->qslots);
 
-	pr_info("%s: enter (%d) (testtag=%d qdepth=%d 0.testtag=%d\n", __func__, i, mq->testtag, mq->qdepth, mq->mqrq[0].testtag);
+//	pr_info("%s: enter (%d) (testtag=%d qdepth=%d 0.testtag=%d\n", __func__, i, mq->testtag, mq->qdepth, mq->mqrq[0].testtag);
 
 	WARN_ON(mq->testtag == 0);
 //////	WARN_ON(i >= mq->qdepth);
@@ -85,7 +85,7 @@ struct mmc_queue_req *mmc_queue_req_find(struct mmc_queue *mq,
 	__set_bit(mqrq->task_id, &mq->qslots);
 ////	spin_unlock_irq(req->q->queue_lock);
 
-	pr_info("%s: exit\n", __func__);
+//	pr_info("%s: exit\n", __func__);
 
 	return mqrq;
 }
@@ -94,7 +94,7 @@ void mmc_queue_req_free(struct mmc_queue *mq,
 			struct mmc_queue_req *mqrq)
 {
 	struct request *req;
-	pr_info("%s: enter\n", __func__);
+//	pr_info("%s: enter\n", __func__);
 	req = mqrq->req;
 ////	spin_lock_irq(req->q->queue_lock);
 	WARN_ON(!mqrq->req || mq->qcnt < 1 ||
@@ -104,7 +104,7 @@ void mmc_queue_req_free(struct mmc_queue *mq,
 	__clear_bit(mqrq->task_id, &mq->qslots);
 ////	spin_unlock_irq(req->q->queue_lock);
 	atomic_dec(&mq->device_busy);
-	pr_info("%s: exit\n", __func__);
+//	pr_info("%s: exit\n", __func__);
 }
 
 /*
@@ -132,7 +132,7 @@ repeat:
 	if (req && req->cmd_type == REQ_TYPE_FS) {
 		if (mmc_queue_ready(q, mq)) {
 		} else {
-			pr_info("%s: command already queued\n", __func__);
+//			pr_info("%s: command already queued\n", __func__);
 //			WARN_ON(1);
 //			spin_unlock_irq(q->queue_lock);
 			blk_requeue_request(mq->queue, req);
@@ -141,7 +141,7 @@ repeat:
 		}
 	}
 	if (!req) {
-		pr_info("%s: no request\n", __func__);
+//		pr_info("%s: no request\n", __func__);
 		return;
 	}
 	spin_unlock_irq(q->queue_lock);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 22052f0..549e65e 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -221,7 +221,7 @@ static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 {
 	int err;
 
-	pr_info("%s: enter\n", __func__);
+//	pr_info("%s: enter\n", __func__);
 
 	/* Assumes host controller has been runtime resumed by mmc_claim_host */
 	err = mmc_retune(host);
@@ -264,7 +264,7 @@ static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 
 	host->ops->request(host, mrq);
 
-	pr_info("%s: exit\n", __func__);
+//	pr_info("%s: exit\n", __func__);
 }
 
 static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
@@ -273,7 +273,7 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 	unsigned int i, sz;
 	struct scatterlist *sg;
 #endif
-	pr_info("%s: enter\n", __func__);
+//	pr_info("%s: enter\n", __func__);
 	mmc_retune_hold(host);
 
 	if (mmc_card_removed(host->card))
@@ -337,7 +337,7 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 	led_trigger_event(host->led, LED_FULL);
 	__mmc_start_request(host, mrq);
 
-	pr_info("%s: exit\n", __func__);
+//	pr_info("%s: exit\n", __func__);
 	return 0;
 }
 
@@ -431,10 +431,10 @@ static void mmc_wait_done(struct mmc_request *mrq)
 	struct mmc_command *cmd;
 	int err = 0, ret = 0;
 
-	pr_info("%s: enter\n", __func__);
+//	pr_info("%s: enter\n", __func__);
 
 	cmd = mrq->cmd;
-	pr_info("%s: cmd->opcode=%d mq_rq=%p\n", __func__, cmd->opcode, mq_rq);
+//	pr_info("%s: cmd->opcode=%d mq_rq=%p\n", __func__, cmd->opcode, mq_rq);
 
 	if (mq_rq)
 		areq = &mq_rq->mmc_active;
@@ -457,7 +457,8 @@ static void mmc_wait_done(struct mmc_request *mrq)
 		cmd->retries--;
 		cmd->error = 0;
 		__mmc_start_request(host, mrq);
-		goto out;
+//		goto out;
+		return;
 	}
 
 	mmc_retune_release(host);
@@ -486,13 +487,13 @@ BUG_ON(mq_rq && (mq_rq->req->cmd_type == REQ_TYPE_FS) && (mq_rq->req->cmd_flags
 
 		bytes = brq->data.bytes_xfered;
 		mmc_put_card(host->card);
-		pr_info("%s: freeing mqrq\n", __func__); //
+//		pr_info("%s: freeing mqrq\n", __func__); //
 		mmc_queue_req_free(req->q->queuedata, mq_rq); //
 		ret = blk_end_request(req, 0, bytes);
 
 	}
-out:
-	pr_info("%s: exit (err=%d, ret=%d)\n", __func__, err, ret);
+//out:
+//	pr_info("%s: exit (err=%d, ret=%d)\n", __func__, err, ret);
 }
 
 static inline void mmc_wait_ongoing_tfr_cmd(struct mmc_host *host)
@@ -521,7 +522,7 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq, struc
 {
 	int err;
 
-	pr_info("%s: enter\n", __func__);
+//	pr_info("%s: enter\n", __func__);
 
 	mmc_wait_ongoing_tfr_cmd(host);
 
@@ -539,7 +540,7 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq, struc
 		mmc_wait_done(mrq);
 	}
 
-	pr_info("%s: exit\n", __func__);
+//	pr_info("%s: exit\n", __func__);
 
 	return err;
 }
@@ -717,9 +718,9 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
 	int start_err = 0;
 	struct mmc_async_req *data = host->areq;
 
-	pr_info("%s: enter\n", __func__);
+//	pr_info("%s: enter\n", __func__);
 
-	pr_info("%s: areq=%p host->areq=%p\n", __func__, areq, host->areq);
+//	pr_info("%s: areq=%p host->areq=%p\n", __func__, areq, host->areq);
 
 	/* Prepare a new request */
 //	if (areq && !areq->pre_req_done) {
@@ -767,7 +768,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
 	if (error)
 		*error = err;
 #endif
-	pr_info("%s: exit (data=%p)\n", __func__, data);
+//	pr_info("%s: exit (data=%p)\n", __func__, data);
 	return data;
 }
 EXPORT_SYMBOL(mmc_start_req);
@@ -786,19 +787,19 @@ EXPORT_SYMBOL(mmc_start_req);
  */
 void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
 {
-	pr_info("%s: enter\n", __func__);
+//	pr_info("%s: enter\n", __func__);
 
 	__mmc_start_req(host, mrq, NULL);
 
 	if (!mrq->cap_cmd_during_tfr) {
 //		mmc_wait_for_req_done(host, mrq);
 //		BUG(); //
-		pr_info("%s: wait start\n", __func__);
+//		pr_info("%s: wait start\n", __func__);
 		wait_for_completion(&mrq->completion);
-		pr_info("%s: wait done\n", __func__);
+//		pr_info("%s: wait done\n", __func__);
 	}
 
-	pr_info("%s: exit\n", __func__);
+//	pr_info("%s: exit\n", __func__);
 }
 EXPORT_SYMBOL(mmc_wait_for_req);
 
@@ -883,7 +884,7 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
 {
 	struct mmc_request mrq = {NULL};
 
-	pr_info("%s: enter (cmd->opcode=%d retries=%d)\n", __func__, cmd->opcode, cmd->retries);
+//	pr_info("%s: enter (cmd->opcode=%d retries=%d)\n", __func__, cmd->opcode, cmd->retries);
 
 	WARN_ON(!host->claimed);
 
@@ -892,10 +893,10 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
 
 	mrq.cmd = cmd;
 	cmd->data = NULL;
-	pr_info("%s: cmd->opcode=%d retries=%d\n", __func__, cmd->opcode, cmd->retries);
+//	pr_info("%s: cmd->opcode=%d retries=%d\n", __func__, cmd->opcode, cmd->retries);
 
 	mmc_wait_for_req(host, &mrq);
-	pr_info("%s: exit (cmd->opcode=%d retries=%d cmd->error=%d)\n", __func__, cmd->opcode, cmd->retries, cmd->error);
+//	pr_info("%s: exit (cmd->opcode=%d retries=%d cmd->error=%d)\n", __func__, cmd->opcode, cmd->retries, cmd->error);
 
 	return cmd->error;
 }
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1488912 — [PATCH PoC 4/7] mmc-mq: implement checking for queue busy condition

FromBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date2016-09-22 16:10 +0200
Subject[PATCH PoC 4/7] mmc-mq: implement checking for queue busy condition
Message-ID<skcRj-7nx-11@gated-at.bofh.it>
In reply to#1488901
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/mmc/card/queue.c | 28 +++++++++++++++++++++++-----
 drivers/mmc/card/queue.h |  2 ++
 2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 6fd711d..3ed4477 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -46,6 +46,21 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
 	return BLKPREP_OK;
 }
 
+int mmc_queue_ready(struct request_queue *q, struct mmc_queue *mq)
+{
+	unsigned int busy;
+
+	busy = atomic_inc_return(&mq->device_busy) - 1;
+
+	if (busy >= mq->qdepth)
+		goto out_dec;
+
+	return 1;
+out_dec:
+	atomic_dec(&mq->device_busy);
+	return 0;
+}
+
 struct mmc_queue_req *mmc_queue_req_find(struct mmc_queue *mq,
 					 struct request *req)
 {
@@ -81,13 +96,14 @@ void mmc_queue_req_free(struct mmc_queue *mq,
 	struct request *req;
 	pr_info("%s: enter\n", __func__);
 	req = mqrq->req;
-	spin_lock_irq(req->q->queue_lock);
+////	spin_lock_irq(req->q->queue_lock);
 	WARN_ON(!mqrq->req || mq->qcnt < 1 ||
 		!test_bit(mqrq->task_id, &mq->qslots));
 	mqrq->req = NULL;
 	mq->qcnt -= 1;
 	__clear_bit(mqrq->task_id, &mq->qslots);
-	spin_unlock_irq(req->q->queue_lock);
+////	spin_unlock_irq(req->q->queue_lock);
+	atomic_dec(&mq->device_busy);
 	pr_info("%s: exit\n", __func__);
 }
 
@@ -114,9 +130,9 @@ repeat:
 	req = blk_fetch_request(q);
 	WARN_ON(req && req->cmd_type != REQ_TYPE_FS);
 	if (req && req->cmd_type == REQ_TYPE_FS) {
-		mqrq_cur = mmc_queue_req_find(mq, req);
-		if (!mqrq_cur) {
-			pr_info("%s: command already queued (%d)\n", __func__, mq->qcnt);
+		if (mmc_queue_ready(q, mq)) {
+		} else {
+			pr_info("%s: command already queued\n", __func__);
 //			WARN_ON(1);
 //			spin_unlock_irq(q->queue_lock);
 			blk_requeue_request(mq->queue, req);
@@ -129,6 +145,8 @@ repeat:
 		return;
 	}
 	spin_unlock_irq(q->queue_lock);
+	mqrq_cur = mmc_queue_req_find(mq, req);
+	BUG_ON(!mqrq_cur);
 	mq->issue_fn(mq, req, mqrq_cur);
 	spin_lock_irq(q->queue_lock);
 	goto repeat;
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 3adf1bc..20399e4 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -61,6 +61,8 @@ struct mmc_queue {
 	unsigned long		qslots;
 
 	int			testtag;
+
+	atomic_t		device_busy;
 };
 
 extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
-- 
1.9.1

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web