Skip to contentSkip to conversation

start to do BKOPS when user request queue is idle

PATCH In review Chuanxiao Dong 1 participant 1 message Dec 3, 2010 MMC, SD and SDIO

lore
Share & tools
lore
#0 lore raw

PATCH v2 2/4 start to do BKOPS when user request queue is idle

Quoted 1 line

From bd333e2303778051fbd9a0069db479e2f7dd0229 Mon Sep 17 00:00:00 2001

From: Chuanxiao Dong <[email protected]>
Date: Fri, 3 Dec 2010 19:05:19 +0800
Subject: [PATCH 2/4] mmc: Add background operations

Driver will check if need to do a BKOPS after completed each user request. If BKOPS is need, then will start BKOPS when request queue is idle.

So before start user request, driver should also check whether card is doing a BKOPS. If so, check card status until BKOPS is done or send HPI command is supported. In this patch, didnot enable HPI.

---
 drivers/mmc/card/block.c |   34 ++++++++++++++
 drivers/mmc/card/queue.c |    1 +
 drivers/mmc/core/core.c  |  115 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/card.h |   10 ++++
 include/linux/mmc/core.h |    3 +
 include/linux/mmc/mmc.h  |    7 +++
 6 files changed, 170 insertions(+), 0 deletions(-)
drivers/mmc/card/block.c +34 -0
index 217f820..de9ffd3 100644
@@ -284,6 +284,15 @@ static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
 	else
 		arg = MMC_ERASE_ARG;
 
+	/*
+	 * Before issuing a user req, host driver should
+	 * wait for the BKOPS is done or just use HPI to
+	 * interrupt it.
+	 */
+	err = mmc_wait_for_bkops(card);
+	if (err)
+		goto out;
+
 	err = mmc_erase(card, from, nr, arg);
 out:
 	spin_lock_irq(&md->lock);
@@ -318,6 +327,15 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
 	else
 		arg = MMC_SECURE_ERASE_ARG;
 
+	/*
+	 * Before issuing a user req, host driver should
+	 * wait for the BKOPS is done or just use HPI to
+	 * interrupt it.
+	 */
+	err = mmc_wait_for_bkops(card);
+	if (err)
+		goto out;
+
 	err = mmc_erase(card, from, nr, arg);
 	if (!err && arg == MMC_SECURE_TRIM1_ARG)
 		err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
@@ -422,6 +440,15 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
 
 		mmc_queue_bounce_pre(mq);
 
+		/*
+		 * Before issuing a user req, host driver should
+		 * wait for the BKOPS is done or just use HPI to
+		 * interrupt it.
+		 */
+		ret = mmc_wait_for_bkops(card);
+		if (ret)
+			goto cmd_err;
+
 		mmc_wait_for_req(card->host, &brq.mrq);
 
 		mmc_queue_bounce_post(mq);
@@ -513,6 +540,13 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
 		}
 
 		/*
+		 * Check if need to do bkops by each R1 response command
+		 */
+		if (mmc_card_mmc(card) &&
+				(brq.cmd.resp[0] & R1_URGENT_BKOPS))
+			mmc_card_set_need_bkops(card);
+
+		/*
 		 * A block was successfully transferred.
 		 */
 		spin_lock_irq(&md->lock);
drivers/mmc/card/queue.c +1 -0
index 4e42d03..9d2c0b4 100644
@@ -65,6 +65,7 @@ static int mmc_queue_thread(void *d)
 				set_current_state(TASK_RUNNING);
 				break;
 			}
+			mmc_start_do_bkops(mq->card);
 			up(&mq->thread_sem);
 			schedule();
 			down(&mq->thread_sem);
drivers/mmc/core/core.c +115 -0

127 lines not on this page · raw message

include/linux/mmc/card.h +10 -0
index 9b755cb..4142ab5 100644
@@ -56,6 +56,7 @@ struct mmc_ext_csd {
 	unsigned int		trim_timeout;		/* In milliseconds */
 	unsigned int		bkops:1; /* background support bit */
 	unsigned int		bkops_en:1; /* background enable bit */
+	unsigned int		hpi_en:1; /* HPI enable bit */
 };
 
 struct sd_scr {
@@ -117,6 +118,8 @@ struct mmc_card {
 #define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
 #define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
 #define MMC_STATE_HIGHSPEED_DDR (1<<4)		/* card is in high speed mode */
+#define MMC_STATE_NEED_BKOPS	(1<<5) /* card need to do BKOPS */
+#define MMC_STATE_DOING_BKOPS	(1<<6) /* card is doing BKOPS */
 	unsigned int		quirks; 	/* card quirks */
 #define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
@@ -159,12 +162,19 @@ struct mmc_card {
 #define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
 #define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
 #define mmc_card_ddr_mode(c)	((c)->state & MMC_STATE_HIGHSPEED_DDR)
+#define mmc_card_need_bkops(c)	((c)->state & MMC_STATE_NEED_BKOPS)
+#define mmc_card_doing_bkops(c)	((c)->state & MMC_STATE_DOING_BKOPS)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
 #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
 #define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
+#define mmc_card_set_need_bkops(c)	((c)->state |= MMC_STATE_NEED_BKOPS)
+#define mmc_card_set_doing_bkops(c)	((c)->state |= MMC_STATE_DOING_BKOPS)
+
+#define mmc_card_clr_need_bkops(c)	((c)->state &= ~MMC_STATE_NEED_BKOPS)
+#define mmc_card_clr_doing_bkops(c)	((c)->state &= ~MMC_STATE_DOING_BKOPS)
 
 static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
 {
include/linux/mmc/core.h +3 -0
index 64e013f..0011d49 100644
@@ -131,6 +131,7 @@ struct mmc_request {
 struct mmc_host;
 struct mmc_card;
 
+extern int mmc_wait_for_bkops(struct mmc_card *);
 extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
 extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
 extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
@@ -153,6 +154,8 @@ extern int mmc_can_secure_erase_trim(struct mmc_card *card);
 extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
 				   unsigned int nr);
 
+extern void mmc_start_do_bkops(struct mmc_card *card);
+
 extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
 
 extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *);
include/linux/mmc/mmc.h +7 -0
index 14f7813..2ba6a8b 100644
@@ -129,8 +129,15 @@
 #define R1_CURRENT_STATE(x)	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
 #define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
 #define R1_SWITCH_ERROR		(1 << 7)	/* sx, c */
+#define R1_URGENT_BKOPS		(1 << 6) /* sx, a */
 #define R1_APP_CMD		(1 << 5)	/* sr, c */
 
+#define R1_ERROR_RESPONSE	(R1_ERASE_RESET | R1_ERROR | R1_CC_ERROR |\
+				R1_CARD_ECC_FAILED | R1_ILLEGAL_COMMAND |\
+				R1_COM_CRC_ERROR | R1_LOCK_UNLOCK_FAILED |\
+				R1_WP_VIOLATION | R1_ERASE_PARAM |\
+				R1_ERASE_SEQ_ERROR | R1_BLOCK_LEN_ERROR |\
+				R1_ADDRESS_ERROR | R1_OUT_OF_RANGE)
 /*
  * MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
  * R1 is the low order byte; R2 is the next highest byte, when present.
Signature · 1 line
1.6.6.1