All of lore.kernel.org
 help / color / mirror / Atom feed
* Boot partition support patch set.
@ 2011-04-06  1:09 Andrei Warkentin
  2011-04-06  1:09 ` [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout Andrei Warkentin
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Andrei Warkentin @ 2011-04-06  1:09 UTC (permalink / raw)
  To: linux-mmc; +Cc: arnd, cjb

This is the latest version of the MMC device partition support.
It relies on a few other changes that were discussed recently.

Thanks,
A

TOC:
 [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout.
 [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE.
 [PATCH 3/4] MMC: Allow setting CMD timeout for CMD6 (SWITCH).
 [PATCH 4/4] MMC: MMC boot partitions support.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout.
  2011-04-06  1:09 Boot partition support patch set Andrei Warkentin
@ 2011-04-06  1:09 ` Andrei Warkentin
  2011-04-11 19:18   ` John Calixto
  2011-04-06  1:09 ` [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE Andrei Warkentin
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Andrei Warkentin @ 2011-04-06  1:09 UTC (permalink / raw)
  To: linux-mmc; +Cc: arnd, cjb, Andrei Warkentin

Renames erase_timeout to cmd_timeout inside struct mmc_command.
First step to making host honor timeouts for non-data-transfer
commands. Cleans up erase timeout code.

Signed-off-by: Andrei Warkentin <andreiw@motorola.com>
---
 drivers/mmc/core/core.c  |   39 +++++++++++++++++++++------------------
 include/linux/mmc/core.h |    2 +-
 2 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 1f453ac..fed232d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1187,9 +1187,8 @@ void mmc_init_erase(struct mmc_card *card)
 	}
 }
 
-static void mmc_set_mmc_erase_timeout(struct mmc_card *card,
-				      struct mmc_command *cmd,
-				      unsigned int arg, unsigned int qty)
+static unsigned int  mmc_mmc_erase_timeout(struct mmc_card *card,
+					   unsigned int arg, unsigned int qty)
 {
 	unsigned int erase_timeout;
 
@@ -1246,38 +1245,42 @@ static void mmc_set_mmc_erase_timeout(struct mmc_card *card,
 	if (mmc_host_is_spi(card->host) && erase_timeout < 1000)
 		erase_timeout = 1000;
 
-	cmd->erase_timeout = erase_timeout;
+	return erase_timeout;
 }
 
-static void mmc_set_sd_erase_timeout(struct mmc_card *card,
-				     struct mmc_command *cmd, unsigned int arg,
-				     unsigned int qty)
+static unsigned int mmc_sd_erase_timeout(struct mmc_card *card,
+					 unsigned int arg,
+					 unsigned int qty)
 {
+	unsigned int erase_timeout;
+
 	if (card->ssr.erase_timeout) {
 		/* Erase timeout specified in SD Status Register (SSR) */
-		cmd->erase_timeout = card->ssr.erase_timeout * qty +
-				     card->ssr.erase_offset;
+		erase_timeout = card->ssr.erase_timeout * qty +
+			card->ssr.erase_offset;
 	} else {
 		/*
 		 * Erase timeout not specified in SD Status Register (SSR) so
 		 * use 250ms per write block.
 		 */
-		cmd->erase_timeout = 250 * qty;
+		erase_timeout = 250 * qty;
 	}
 
 	/* Must not be less than 1 second */
-	if (cmd->erase_timeout < 1000)
-		cmd->erase_timeout = 1000;
+	if (erase_timeout < 1000)
+		erase_timeout = 1000;
+
+	return erase_timeout;
 }
 
-static void mmc_set_erase_timeout(struct mmc_card *card,
-				  struct mmc_command *cmd, unsigned int arg,
-				  unsigned int qty)
+static unsigned int mmc_erase_timeout(struct mmc_card *card,
+				      unsigned int arg,
+				      unsigned int qty)
 {
 	if (mmc_card_sd(card))
-		mmc_set_sd_erase_timeout(card, cmd, arg, qty);
+		return mmc_sd_erase_timeout(card, arg, qty);
 	else
-		mmc_set_mmc_erase_timeout(card, cmd, arg, qty);
+		return mmc_mmc_erase_timeout(card, arg, qty);
 }
 
 static int mmc_do_erase(struct mmc_card *card, unsigned int from,
@@ -1351,7 +1354,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
 	cmd.opcode = MMC_ERASE;
 	cmd.arg = arg;
 	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-	mmc_set_erase_timeout(card, &cmd, arg, qty);
+	cmd.cmd_timeout = mmc_erase_timeout(card, arg, qty);
 	err = mmc_wait_for_cmd(card->host, &cmd, 0);
 	if (err) {
 		printk(KERN_ERR "mmc_erase: erase error %d, status %#x\n",
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 07f27af..a7d7da7 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -92,7 +92,7 @@ struct mmc_command {
  *              actively failing requests
  */
 
-	unsigned int		erase_timeout;	/* in milliseconds */
+	unsigned int		cmd_timeout;	/* in milliseconds */
 
 	struct mmc_data		*data;		/* data segment associated with cmd */
 	struct mmc_request	*mrq;		/* associated request */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE.
  2011-04-06  1:09 Boot partition support patch set Andrei Warkentin
  2011-04-06  1:09 ` [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout Andrei Warkentin
@ 2011-04-06  1:09 ` Andrei Warkentin
  2011-04-06  1:09 ` [PATCH 3/4] MMC: Allow setting CMD timeout for CMD6 (SWITCH) Andrei Warkentin
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Andrei Warkentin @ 2011-04-06  1:09 UTC (permalink / raw)
  To: linux-mmc; +Cc: arnd, cjb, Andrei Warkentin

ERASE command needs R1B response, so fix R1B-type command
handling for SDHCI controller. For non-DAT commands using a busy
reponse, the cmd->cmd_timeout (in ms) field is used for timeout
calculations.

Based on patch by Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Andrei Warkentin <andreiw@motorola.com>
---
 drivers/mmc/host/sdhci.c |   43 +++++++++++++++++++++++++++----------------
 1 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 9e15f41..88aaf5e 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -40,7 +40,6 @@
 
 static unsigned int debug_quirks = 0;
 
-static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
 static void sdhci_finish_data(struct sdhci_host *);
 
 static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
@@ -591,9 +590,10 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
 		data->sg_len, direction);
 }
 
-static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
+static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 {
 	u8 count;
+	struct mmc_data *data = cmd->data;
 	unsigned target_timeout, current_timeout;
 
 	/*
@@ -605,12 +605,16 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
 	if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
 		return 0xE;
 
-	/* timeout in us */
-	target_timeout = data->timeout_ns / 1000 +
-		data->timeout_clks / host->clock;
+	/* Unspecified timeout, assume max */
+	if (!data && !cmd->cmd_timeout)
+		return 0xE;
 
-	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
-		host->timeout_clk = host->clock / 1000;
+	/* timeout in us */
+	if (!data)
+		target_timeout = cmd->cmd_timeout * 1000;
+	else
+		target_timeout = data->timeout_ns / 1000 +
+			data->timeout_clks / host->clock;
 
 	/*
 	 * Figure out needed cycles.
@@ -632,8 +636,9 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
 	}
 
 	if (count >= 0xF) {
-		printk(KERN_WARNING "%s: Too large timeout requested!\n",
-			mmc_hostname(host->mmc));
+		printk(KERN_WARNING "%s: Too large timeout requested for CMD%d!\n",
+		       mmc_hostname(host->mmc),
+		       cmd->opcode);
 		count = 0xE;
 	}
 
@@ -651,15 +656,21 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)
 		sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
 }
 
-static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
+static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
 {
 	u8 count;
 	u8 ctrl;
+	struct mmc_data *data = cmd->data;
 	int ret;
 
 	WARN_ON(host->data);
 
-	if (data == NULL)
+	if (data || (cmd->flags & MMC_RSP_BUSY)) {
+		count = sdhci_calc_timeout(host, cmd);
+		sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
+	}
+
+	if (!data)
 		return;
 
 	/* Sanity checks */
@@ -670,9 +681,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 	host->data = data;
 	host->data_early = 0;
 
-	count = sdhci_calc_timeout(host, data);
-	sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
-
 	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))
 		host->flags |= SDHCI_REQ_USE_DMA;
 
@@ -920,7 +928,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 
 	host->cmd = cmd;
 
-	sdhci_prepare_data(host, cmd->data);
+	sdhci_prepare_data(host, cmd);
 
 	sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);
 
@@ -1867,6 +1875,9 @@ int sdhci_add_host(struct sdhci_host *host)
 	if (caps & SDHCI_TIMEOUT_CLK_UNIT)
 		host->timeout_clk *= 1000;
 
+	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
+		host->timeout_clk = host->clock / 1000;
+
 	/*
 	 * Set host parameters.
 	 */
@@ -1879,7 +1890,7 @@ int sdhci_add_host(struct sdhci_host *host)
 		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
 
 	mmc->f_max = host->max_clk;
-	mmc->caps |= MMC_CAP_SDIO_IRQ;
+	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE;
 
 	/*
 	 * A controller may support 8-bit width, but the board itself
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/4] MMC: Allow setting CMD timeout for CMD6 (SWITCH).
  2011-04-06  1:09 Boot partition support patch set Andrei Warkentin
  2011-04-06  1:09 ` [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout Andrei Warkentin
  2011-04-06  1:09 ` [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE Andrei Warkentin
@ 2011-04-06  1:09 ` Andrei Warkentin
  2011-04-06  1:09 ` [PATCH 4/4] MMC: MMC boot partitions support Andrei Warkentin
  2011-04-06 23:20 ` Boot partition support patch set Andrei Warkentin
  4 siblings, 0 replies; 11+ messages in thread
From: Andrei Warkentin @ 2011-04-06  1:09 UTC (permalink / raw)
  To: linux-mmc; +Cc: arnd, cjb, Andrei Warkentin

CMD6 is R1B-type command, where DAT is used as busy. Depending
on register written using CMD6, timeout value can be different
as per spec.

Signed-off-by: Andrei Warkentin <andreiw@motorola.com>
---
 drivers/mmc/core/mmc.c     |   14 ++++++++------
 drivers/mmc/core/mmc_ops.c |   17 ++++++++++++++++-
 drivers/mmc/core/mmc_ops.h |    1 -
 include/linux/mmc/core.h   |    1 +
 4 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index caba751..a5cf423 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -548,7 +548,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.enhanced_area_en) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-				EXT_CSD_ERASE_GROUP_DEF, 1);
+				 EXT_CSD_ERASE_GROUP_DEF, 1, 0);
 
 		if (err && err != -EBADMSG)
 			goto free_card;
@@ -579,7 +579,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	if (card->ext_csd.bootconfig & 0x7) {
 		card->ext_csd.bootconfig &= ~0x7;
 		mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_CONFIG,
-			   card->ext_csd.bootconfig);
+			   card->ext_csd.bootconfig, 0);
 	}
 
 	/*
@@ -588,7 +588,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	if ((card->ext_csd.hs_max_dtr != 0) &&
 		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-			EXT_CSD_HS_TIMING, 1);
+				 EXT_CSD_HS_TIMING, 1, 0);
 		if (err && err != -EBADMSG)
 			goto free_card;
 
@@ -655,7 +655,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 				ddr = 0; /* no DDR for 1-bit width */
 			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					 EXT_CSD_BUS_WIDTH,
-					 ext_csd_bits[idx][0]);
+					 ext_csd_bits[idx][0],
+					 0);
 			if (!err) {
 				mmc_set_bus_width_ddr(card->host,
 						      bus_width, MMC_SDR_MODE);
@@ -674,8 +675,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 
 		if (!err && ddr) {
 			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-					EXT_CSD_BUS_WIDTH,
-					ext_csd_bits[idx][1]);
+					 EXT_CSD_BUS_WIDTH,
+					 ext_csd_bits[idx][1],
+					 0);
 		}
 		if (err) {
 			printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 60842f8..8b0d62e 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -387,7 +387,19 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
 	return err;
 }
 
-int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
+/**
+ *	mmc_switch - modify EXT_CSD register
+ *	@card: the MMC card associated with the data transfer
+ *	@set: cmd set values
+ *	@index: EXT_CSD register index
+ *	@value: value to program into EXT_CSD register
+ *	@timeout: timeout for operation performed by register write,
+ *                timeout of zero implies maximum possible timeout
+ *
+ *	Modifies the EXT_CSD register for selected card.
+ */
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
+	unsigned int timeout)
 {
 	int err;
 	struct mmc_command cmd;
@@ -404,6 +416,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
 		  (value << 8) |
 		  set;
 	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+	cmd.cmd_timeout = timeout;
 
 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
 	if (err)
@@ -434,6 +447,8 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
 	return 0;
 }
 
+EXPORT_SYMBOL(mmc_switch);
+
 int mmc_send_status(struct mmc_card *card, u32 *status)
 {
 	int err;
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index e6d44b8..9276946 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -20,7 +20,6 @@ int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
 int mmc_set_relative_addr(struct mmc_card *card);
 int mmc_send_csd(struct mmc_card *card, u32 *csd);
 int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
-int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value);
 int mmc_send_status(struct mmc_card *card, u32 *status);
 int mmc_send_cid(struct mmc_host *host, u32 *cid);
 int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index a7d7da7..6d4f3df 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -135,6 +135,7 @@ 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 *,
 	struct mmc_command *, int);
+extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
 
 #define MMC_ERASE_ARG		0x00000000
 #define MMC_SECURE_ERASE_ARG	0x80000000
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/4] MMC: MMC boot partitions support.
  2011-04-06  1:09 Boot partition support patch set Andrei Warkentin
                   ` (2 preceding siblings ...)
  2011-04-06  1:09 ` [PATCH 3/4] MMC: Allow setting CMD timeout for CMD6 (SWITCH) Andrei Warkentin
@ 2011-04-06  1:09 ` Andrei Warkentin
  2011-04-06 23:20 ` Boot partition support patch set Andrei Warkentin
  4 siblings, 0 replies; 11+ messages in thread
From: Andrei Warkentin @ 2011-04-06  1:09 UTC (permalink / raw)
  To: linux-mmc; +Cc: arnd, cjb, Andrei Warkentin

Allows device MMC boot partitions to be accessed. MMC partitions
are treated effectively as separate block devices on the same
MMC card.

Signed-off-by: Andrei Warkentin <andreiw@motorola.com>
---
 Documentation/mmc/00-INDEX          |    2 +
 Documentation/mmc/mmc-dev-attrs.txt |   10 ++
 Documentation/mmc/mmc-dev-parts.txt |   26 +++
 drivers/mmc/card/block.c            |  305 +++++++++++++++++++++++++++++------
 drivers/mmc/core/mmc.c              |   22 ++-
 include/linux/mmc/card.h            |    4 +-
 include/linux/mmc/mmc.h             |    8 +-
 7 files changed, 317 insertions(+), 60 deletions(-)
 create mode 100644 Documentation/mmc/mmc-dev-parts.txt

diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX
index fca586f..93dd7a7 100644
--- a/Documentation/mmc/00-INDEX
+++ b/Documentation/mmc/00-INDEX
@@ -2,3 +2,5 @@
         - this file
 mmc-dev-attrs.txt
         - info on SD and MMC device attributes
+mmc-dev-parts.txt
+        - info on SD and MMC device partitions
diff --git a/Documentation/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt
index ff2bd68..8898a95 100644
--- a/Documentation/mmc/mmc-dev-attrs.txt
+++ b/Documentation/mmc/mmc-dev-attrs.txt
@@ -1,3 +1,13 @@
+SD and MMC Block Device Attributes
+==================================
+
+These attributes are defined for the block devices associated with the
+SD or MMC device.
+
+The following attributes are read/write.
+
+	force_ro		Enforce read-only access even if write protect switch is off.
+
 SD and MMC Device Attributes
 ============================
 
diff --git a/Documentation/mmc/mmc-dev-parts.txt b/Documentation/mmc/mmc-dev-parts.txt
new file mode 100644
index 0000000..8821909
--- /dev/null
+++ b/Documentation/mmc/mmc-dev-parts.txt
@@ -0,0 +1,26 @@
+SD and MMC Device Partitions
+============================
+
+Device partitions are additional logical block devices present
+on the SD/MMC device.
+
+As of this writing, MMC boot partitions as supported and exposed as 
+/dev/mmcblkXboot0 and /dev/mmcblkXboot1, where X is the index of the
+parent /dev/mmcblkX.
+
+MMC Boot Partitions
+===================
+
+Read and write access is provided to the two MMC boot partitions. Due
+to the sensitive nature of the boot partition contents, which often store
+a bootloader or bootloader configuration tables crucial to booting the platform,
+write access is by default disabled to reduce the chance of accidental bricking.
+
+To enable write access to /dev/mmcblkXbootY, disable the forced read-only
+access:
+
+echo 0 > /sys/block/mmcblkXbootY/force_ro
+
+To re-enable read-only access:
+
+echo 1 > /sys/block/mmcblkXbootY/force_ro
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 91a6767..1e6bd91 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -76,9 +76,19 @@ struct mmc_blk_data {
 	spinlock_t	lock;
 	struct gendisk	*disk;
 	struct mmc_queue queue;
+	struct list_head part;
 
 	unsigned int	usage;
 	unsigned int	read_only;
+	unsigned int	part_type;
+
+	/*
+	 * Only set in main mmc_blk_data associated
+	 * with mmc_card with mmc_set_drvdata, and keeps
+	 * track of the current selected device partition.
+	 */
+	unsigned int	part_curr;
+	struct device_attribute force_ro;
 };
 
 static DEFINE_MUTEX(open_lock);
@@ -101,17 +111,22 @@ static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
 	return md;
 }
 
+static inline int mmc_get_devidx(struct gendisk *disk)
+{
+	int devmaj = MAJOR(disk_devt(disk));
+	int devidx = MINOR(disk_devt(disk)) / perdev_minors;
+
+	if (!devmaj)
+		devidx = disk->first_minor / perdev_minors;
+	return devidx;
+}
+
 static void mmc_blk_put(struct mmc_blk_data *md)
 {
 	mutex_lock(&open_lock);
 	md->usage--;
 	if (md->usage == 0) {
-		int devmaj = MAJOR(disk_devt(md->disk));
-		int devidx = MINOR(disk_devt(md->disk)) / perdev_minors;
-
-		if (!devmaj)
-			devidx = md->disk->first_minor / perdev_minors;
-
+		int devidx = mmc_get_devidx(md->disk);
 		blk_cleanup_queue(md->queue.queue);
 
 		__clear_bit(devidx, dev_use);
@@ -122,6 +137,38 @@ static void mmc_blk_put(struct mmc_blk_data *md)
 	mutex_unlock(&open_lock);
 }
 
+static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	int ret;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+
+	ret = snprintf(buf, PAGE_SIZE, "%d",
+		       get_disk_ro(dev_to_disk(dev)) ^
+		       md->read_only);
+	mmc_blk_put(md);
+	return ret;
+}
+
+static ssize_t force_ro_store(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	int ret;
+	char *end;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	unsigned long set = simple_strtoul(buf, &end, 0);
+	if (end == buf) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	set_disk_ro(dev_to_disk(dev), set || md->read_only);
+	ret = count;
+out:
+	mmc_blk_put(md);
+	return ret;
+}
+
 static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
 {
 	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
@@ -176,6 +223,29 @@ struct mmc_blk_request {
 	struct mmc_data		data;
 };
 
+static inline int mmc_blk_part_switch(struct mmc_card *card,
+				      struct mmc_blk_data *md)
+{
+	int ret;
+	struct mmc_blk_data *main_md = mmc_get_drvdata(card);
+	if (main_md->part_curr == md->part_type)
+		return 0;
+
+	if (mmc_card_mmc(card)) {
+		card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
+		card->ext_csd.part_config |= md->part_type;
+
+		ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				 EXT_CSD_PART_CONFIG, card->ext_csd.part_config,
+				 card->ext_csd.part_time);
+		if (ret)
+			return ret;
+}
+
+	main_md->part_curr = md->part_type;
+	return 0;
+}
+
 static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
 {
 	int err;
@@ -273,8 +343,6 @@ static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
 	unsigned int from, nr, arg;
 	int err = 0;
 
-	mmc_claim_host(card->host);
-
 	if (!mmc_can_erase(card)) {
 		err = -EOPNOTSUPP;
 		goto out;
@@ -294,8 +362,6 @@ out:
 	__blk_end_request(req, err, blk_rq_bytes(req));
 	spin_unlock_irq(&md->lock);
 
-	mmc_release_host(card->host);
-
 	return err ? 0 : 1;
 }
 
@@ -307,8 +373,6 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
 	unsigned int from, nr, arg;
 	int err = 0;
 
-	mmc_claim_host(card->host);
-
 	if (!mmc_can_secure_erase_trim(card)) {
 		err = -EOPNOTSUPP;
 		goto out;
@@ -330,8 +394,6 @@ out:
 	__blk_end_request(req, err, blk_rq_bytes(req));
 	spin_unlock_irq(&md->lock);
 
-	mmc_release_host(card->host);
-
 	return err ? 0 : 1;
 }
 
@@ -402,8 +464,6 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
 		(rq_data_dir(req) == WRITE) &&
 		REL_WRITES_SUPPORTED(card);
 
-	mmc_claim_host(card->host);
-
 	do {
 		struct mmc_command cmd;
 		u32 readcmd, writecmd, status = 0;
@@ -589,8 +649,6 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
 		spin_unlock_irq(&md->lock);
 	} while (ret);
 
-	mmc_release_host(card->host);
-
 	return 1;
 
  cmd_err:
@@ -617,8 +675,6 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
 		spin_unlock_irq(&md->lock);
 	}
 
-	mmc_release_host(card->host);
-
 	spin_lock_irq(&md->lock);
 	while (ret)
 		ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
@@ -629,16 +685,31 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
 
 static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 {
+	int ret;
+	struct mmc_blk_data *md = mq->data;
+	struct mmc_card *card = md->queue.card;
+
+	mmc_claim_host(card->host);
+	ret = mmc_blk_part_switch(card, md);
+	if (ret) {
+		ret = 0;
+		goto out;
+	}
+
 	if (req->cmd_flags & REQ_DISCARD) {
 		if (req->cmd_flags & REQ_SECURE)
-			return mmc_blk_issue_secdiscard_rq(mq, req);
+			ret = mmc_blk_issue_secdiscard_rq(mq, req);
 		else
-			return mmc_blk_issue_discard_rq(mq, req);
+			ret = mmc_blk_issue_discard_rq(mq, req);
 	} else if (req->cmd_flags & REQ_FLUSH) {
-		return mmc_blk_issue_flush(mq, req);
+		ret = mmc_blk_issue_flush(mq, req);
 	} else {
-		return mmc_blk_issue_rw_rq(mq, req);
+		ret = mmc_blk_issue_rw_rq(mq, req);
 	}
+
+out:
+	mmc_release_host(card->host);
+	return ret;
 }
 
 static inline int mmc_blk_readonly(struct mmc_card *card)
@@ -647,7 +718,11 @@ static inline int mmc_blk_readonly(struct mmc_card *card)
 	       !(card->csd.cmdclass & CCC_BLOCK_WRITE);
 }
 
-static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
+static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
+					      struct device *parent,
+					      sector_t size,
+					      bool default_ro,
+					      const char *subname)
 {
 	struct mmc_blk_data *md;
 	int devidx, ret;
@@ -663,7 +738,6 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 		goto out;
 	}
 
-
 	/*
 	 * Set the read-only status based on the supported commands
 	 * and the write protect switch.
@@ -677,6 +751,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 	}
 
 	spin_lock_init(&md->lock);
+	INIT_LIST_HEAD(&md->part);
 	md->usage = 1;
 
 	ret = mmc_init_queue(&md->queue, card, &md->lock);
@@ -691,8 +766,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 	md->disk->fops = &mmc_bdops;
 	md->disk->private_data = md;
 	md->disk->queue = md->queue.queue;
-	md->disk->driverfs_dev = &card->dev;
-	set_disk_ro(md->disk, md->read_only);
+	md->disk->driverfs_dev = parent;
+	set_disk_ro(md->disk, md->read_only || default_ro);
 	if (REL_WRITES_SUPPORTED(card))
 		blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA);
 
@@ -708,33 +783,97 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 	 * messages to tell when the card is present.
 	 */
 
-	snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
-		"mmcblk%d", devidx);
+	if (subname)
+		snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
+			 "mmcblk%d%s",
+			 mmc_get_devidx(dev_to_disk(parent)), subname);
+	else
+		snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
+			 "mmcblk%d", devidx);
 
 	blk_queue_logical_block_size(md->queue.queue, 512);
+	set_capacity(md->disk, size);
+	return md;
+
+ err_putdisk:
+	put_disk(md->disk);
+ err_kfree:
+	kfree(md);
+ out:
+	return ERR_PTR(ret);
+}
+
+static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
+{
+	sector_t size;
+	struct mmc_blk_data *md;
 
 	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
 		/*
 		 * The EXT_CSD sector count is in number or 512 byte
 		 * sectors.
 		 */
-		set_capacity(md->disk, card->ext_csd.sectors);
+		size = card->ext_csd.sectors;
 	} else {
 		/*
 		 * The CSD capacity field is in units of read_blkbits.
 		 * set_capacity takes units of 512 bytes.
 		 */
-		set_capacity(md->disk,
-			card->csd.capacity << (card->csd.read_blkbits - 9));
+		size = card->csd.capacity << (card->csd.read_blkbits - 9);
 	}
+
+	md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL);
 	return md;
+}
 
- err_putdisk:
-	put_disk(md->disk);
- err_kfree:
-	kfree(md);
- out:
-	return ERR_PTR(ret);
+static int mmc_blk_alloc_part(struct mmc_card *card,
+			      struct mmc_blk_data *md,
+			      unsigned int part_type,
+			      sector_t size,
+			      bool default_ro,
+			      const char *subname)
+{
+	char cap_str[10];
+	struct mmc_blk_data *part_md;
+
+	part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
+				    subname);
+	if (IS_ERR(part_md))
+		return PTR_ERR(part_md);
+	part_md->part_type = part_type;
+	list_add(&part_md->part, &md->part);
+
+	string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2,
+			cap_str, sizeof(cap_str));
+	printk(KERN_INFO "%s: %s %s partition %u %s\n",
+	       part_md->disk->disk_name, mmc_card_id(card),
+	       mmc_card_name(card), part_md->part_type, cap_str);
+	return 0;
+}
+
+static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
+{
+	int ret = 0;
+
+	if (!mmc_card_mmc(card))
+		return 0;
+
+	if (card->ext_csd.boot_size) {
+		ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT0,
+					 card->ext_csd.boot_size >> 9,
+					 true,
+					 "boot0");
+		if (ret)
+			return ret;
+		ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT1,
+					 card->ext_csd.boot_size >> 9,
+					 true,
+					 "boot1");
+		if (ret)
+			return ret;
+	}
+
+	return ret;
 }
 
 static int
@@ -755,9 +894,54 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
 	return 0;
 }
 
+static void mmc_blk_remove_req(struct mmc_blk_data *md)
+{
+	if (md) {
+		if (md->disk->flags & GENHD_FL_UP) {
+			device_remove_file(disk_to_dev(md->disk), &md->force_ro);
+
+			/* Stop new requests from getting into the queue */
+			del_gendisk(md->disk);
+		}
+
+		/* Then flush out any already in there */
+		mmc_cleanup_queue(&md->queue);
+		mmc_blk_put(md);
+	}
+}
+
+static void mmc_blk_remove_parts(struct mmc_card *card,
+				 struct mmc_blk_data *md)
+{
+	struct list_head *pos, *q;
+	struct mmc_blk_data *part_md;
+
+	list_for_each_safe(pos, q, &md->part) {
+		part_md = list_entry(pos, struct mmc_blk_data, part);
+		list_del(pos);
+		mmc_blk_remove_req(part_md);
+	}
+}
+
+static int mmc_add_disk(struct mmc_blk_data *md)
+{
+	int ret;
+
+	add_disk(md->disk);
+	md->force_ro.show = force_ro_show;
+	md->force_ro.store = force_ro_store;
+	md->force_ro.attr.name = "force_ro";
+	md->force_ro.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
+	if (ret)
+		del_gendisk(md->disk);
+
+	return ret;
+}
+
 static int mmc_blk_probe(struct mmc_card *card)
 {
-	struct mmc_blk_data *md;
+	struct mmc_blk_data *md, *part_md;
 	int err;
 	char cap_str[10];
 
@@ -781,14 +965,22 @@ static int mmc_blk_probe(struct mmc_card *card)
 		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
 		cap_str, md->read_only ? "(ro)" : "");
 
+	if (mmc_blk_alloc_parts(card, md))
+		goto out;
+
 	mmc_set_drvdata(card, md);
-	add_disk(md->disk);
+	if (mmc_add_disk(md))
+		goto out;
+
+	list_for_each_entry(part_md, &md->part, part) {
+		if (mmc_add_disk(part_md))
+			goto out;
+	}
 	return 0;
 
  out:
-	mmc_cleanup_queue(&md->queue);
-	mmc_blk_put(md);
-
+	mmc_blk_remove_parts(card, md);
+	mmc_blk_remove_req(md);
 	return err;
 }
 
@@ -796,36 +988,43 @@ static void mmc_blk_remove(struct mmc_card *card)
 {
 	struct mmc_blk_data *md = mmc_get_drvdata(card);
 
-	if (md) {
-		/* Stop new requests from getting into the queue */
-		del_gendisk(md->disk);
-
-		/* Then flush out any already in there */
-		mmc_cleanup_queue(&md->queue);
-
-		mmc_blk_put(md);
-	}
+	mmc_blk_remove_parts(card, md);
+	mmc_blk_remove_req(md);
 	mmc_set_drvdata(card, NULL);
 }
 
 #ifdef CONFIG_PM
 static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
 {
+	struct mmc_blk_data *part_md;
 	struct mmc_blk_data *md = mmc_get_drvdata(card);
 
 	if (md) {
 		mmc_queue_suspend(&md->queue);
+		list_for_each_entry(part_md, &md->part, part) {
+			mmc_queue_suspend(&part_md->queue);
+		}
 	}
 	return 0;
 }
 
 static int mmc_blk_resume(struct mmc_card *card)
 {
+	struct mmc_blk_data *part_md;
 	struct mmc_blk_data *md = mmc_get_drvdata(card);
 
 	if (md) {
 		mmc_blk_set_blksize(md, card);
+
+		/*
+		 * Resume involves the card going into idle state,
+		 * so current partition is always the main one.
+		 */
+		md->part_curr = md->part_type;
 		mmc_queue_resume(&md->queue);
+		list_for_each_entry(part_md, &md->part, part) {
+			mmc_queue_resume(&part_md->queue);
+		}
 	}
 	return 0;
 }
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index a5cf423..ba1c878 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -288,7 +288,10 @@ static int mmc_read_ext_csd(struct mmc_card *card)
 
 	if (card->ext_csd.rev >= 3) {
 		u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT];
-		card->ext_csd.bootconfig = ext_csd[EXT_CSD_BOOT_CONFIG];
+		card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG];
+
+		/* EXT_CSD value is in units of 10ms, but we store in ms */
+		card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME];
 
 		/* Sleep / awake timeout in 100ns units */
 		if (sa_shift > 0 && sa_shift <= 0x17)
@@ -302,6 +305,12 @@ static int mmc_read_ext_csd(struct mmc_card *card)
 			ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10;
 
 		card->ext_csd.rel_sectors = ext_csd[EXT_CSD_REL_WR_SEC_C];
+
+		/*
+		 * There are two boot regions of equal size, defined in
+		 * multiples of 128K.
+		 */
+		card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT] << 17;
 	}
 
 	if (card->ext_csd.rev >= 4) {
@@ -576,10 +585,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Ensure eMMC user default partition is enabled
 	 */
-	if (card->ext_csd.bootconfig & 0x7) {
-		card->ext_csd.bootconfig &= ~0x7;
-		mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_CONFIG,
-			   card->ext_csd.bootconfig, 0);
+	if (card->ext_csd.part_config & EXT_CSD_PART_CONFIG_ACC_MASK) {
+		card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONFIG,
+				 card->ext_csd.part_config,
+				 card->ext_csd.part_time);
+		if (err && err != -EBADMSG)
+			goto free_card;
 	}
 
 	/*
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index c4e96fa..b90cacc 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -47,7 +47,8 @@ struct mmc_ext_csd {
 	u8			sec_feature_support;
 	u8			rel_sectors;
 	u8			rel_param;
-	u8			bootconfig;
+	u8			part_config;
+	unsigned int		part_time;		/* Units: ms */
 	unsigned int		sa_timeout;		/* Units: 100ns */
 	unsigned int		hs_max_dtr;
 	unsigned int		sectors;
@@ -60,6 +61,7 @@ struct mmc_ext_csd {
 	bool			enhanced_area_en;	/* enable bit */
 	unsigned long long	enhanced_area_offset;	/* Units: Byte */
 	unsigned int		enhanced_area_size;	/* Units: KB */
+	unsigned int		boot_size;		/* in bytes */
 };
 
 struct sd_scr {
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 390aa6e..373b2bf 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -257,19 +257,21 @@ struct _mmc_csd {
 #define EXT_CSD_PARTITION_SUPPORT	160	/* RO */
 #define EXT_CSD_WR_REL_PARAM		166	/* RO */
 #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */
-#define EXT_CSD_BOOT_CONFIG		179	/* R/W */
+#define EXT_CSD_PART_CONFIG		179	/* R/W */
 #define EXT_CSD_ERASED_MEM_CONT		181	/* RO */
 #define EXT_CSD_BUS_WIDTH		183	/* R/W */
 #define EXT_CSD_HS_TIMING		185	/* R/W */
 #define EXT_CSD_REV			192	/* RO */
 #define EXT_CSD_STRUCTURE		194	/* RO */
 #define EXT_CSD_CARD_TYPE		196	/* RO */
+#define EXT_CSD_PART_SWITCH_TIME        199     /* RO */
 #define EXT_CSD_SEC_CNT			212	/* RO, 4 bytes */
 #define EXT_CSD_S_A_TIMEOUT		217	/* RO */
 #define EXT_CSD_REL_WR_SEC_C		222	/* RO */
 #define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */
 #define EXT_CSD_ERASE_TIMEOUT_MULT	223	/* RO */
 #define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */
+#define EXT_CSD_BOOT_MULT		226	/* RO */
 #define EXT_CSD_SEC_TRIM_MULT		229	/* RO */
 #define EXT_CSD_SEC_ERASE_MULT		230	/* RO */
 #define EXT_CSD_SEC_FEATURE_SUPPORT	231	/* RO */
@@ -281,6 +283,10 @@ struct _mmc_csd {
 
 #define EXT_CSD_WR_REL_PARAM_EN		(1<<2)
 
+#define EXT_CSD_PART_CONFIG_ACC_MASK	(0x7)
+#define EXT_CSD_PART_CONFIG_ACC_BOOT0	(0x1)
+#define EXT_CSD_PART_CONFIG_ACC_BOOT1	(0x2)
+
 #define EXT_CSD_CMD_SET_NORMAL		(1<<0)
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: Boot partition support patch set.
  2011-04-06  1:09 Boot partition support patch set Andrei Warkentin
                   ` (3 preceding siblings ...)
  2011-04-06  1:09 ` [PATCH 4/4] MMC: MMC boot partitions support Andrei Warkentin
@ 2011-04-06 23:20 ` Andrei Warkentin
  2011-04-07 21:23   ` Chris Ball
  4 siblings, 1 reply; 11+ messages in thread
From: Andrei Warkentin @ 2011-04-06 23:20 UTC (permalink / raw)
  To: linux-mmc; +Cc: arnd, cjb

On Tue, Apr 5, 2011 at 8:09 PM, Andrei Warkentin <andreiw@motorola.com> wrote:
> This is the latest version of the MMC device partition support.
> It relies on a few other changes that were discussed recently.
>
> Thanks,
> A
>
> TOC:
>  [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout.
>  [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE.
>  [PATCH 3/4] MMC: Allow setting CMD timeout for CMD6 (SWITCH).
>  [PATCH 4/4] MMC: MMC boot partitions support.
>

Any problems, comments?

A

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Boot partition support patch set.
  2011-04-06 23:20 ` Boot partition support patch set Andrei Warkentin
@ 2011-04-07 21:23   ` Chris Ball
  2011-04-08  3:47     ` Arnd Bergmann
  0 siblings, 1 reply; 11+ messages in thread
From: Chris Ball @ 2011-04-07 21:23 UTC (permalink / raw)
  To: Andrei Warkentin; +Cc: linux-mmc, arnd

Hi,

On Wed, Apr 06 2011, Andrei Warkentin wrote:
>> This is the latest version of the MMC device partition support.
>> It relies on a few other changes that were discussed recently.
>>
>> Thanks,
>> A
>>
>> TOC:
>> [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout.
>> [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE.
>> [PATCH 3/4] MMC: Allow setting CMD timeout for CMD6 (SWITCH).
>> [PATCH 4/4] MMC: MMC boot partitions support.
>
> Any problems, comments?

Looks good to me -- Arnd, did you want to add your Reviewed/Acked-by
to this?

Thanks,

- Chris.
-- 
Chris Ball   <cjb@laptop.org>   <http://printf.net/>
One Laptop Per Child

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Boot partition support patch set.
  2011-04-07 21:23   ` Chris Ball
@ 2011-04-08  3:47     ` Arnd Bergmann
  2011-04-08  6:58       ` Andrei Warkentin
  0 siblings, 1 reply; 11+ messages in thread
From: Arnd Bergmann @ 2011-04-08  3:47 UTC (permalink / raw)
  To: Chris Ball; +Cc: Andrei Warkentin, linux-mmc

On Thursday 07 April 2011, Chris Ball wrote:
> On Wed, Apr 06 2011, Andrei Warkentin wrote:
> >> This is the latest version of the MMC device partition support.
> >> It relies on a few other changes that were discussed recently.
> >>
> >> Thanks,
> >> A
> >>
> >> TOC:
> >> [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout.
> >> [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE.
> >> [PATCH 3/4] MMC: Allow setting CMD timeout for CMD6 (SWITCH).
> >> [PATCH 4/4] MMC: MMC boot partitions support.
> >
> > Any problems, comments?
> 
> Looks good to me -- Arnd, did you want to add your Reviewed/Acked-by
> to this?
> 

I haven't done an in-depth review, but please add my Acked-by to the last
patch. For the other three, I have no idea what they do, but they all
seem harmless to me ;-)

	Arnd

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Boot partition support patch set.
  2011-04-08  3:47     ` Arnd Bergmann
@ 2011-04-08  6:58       ` Andrei Warkentin
  0 siblings, 0 replies; 11+ messages in thread
From: Andrei Warkentin @ 2011-04-08  6:58 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Chris Ball, linux-mmc

Hi Arnd,

On Thu, Apr 7, 2011 at 10:47 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thursday 07 April 2011, Chris Ball wrote:
>> On Wed, Apr 06 2011, Andrei Warkentin wrote:
>> >> This is the latest version of the MMC device partition support.
>> >> It relies on a few other changes that were discussed recently.
>> >>
>> >> Thanks,
>> >> A
>> >>
>> >> TOC:
>> >> [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout.
>> >> [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE.
>> >> [PATCH 3/4] MMC: Allow setting CMD timeout for CMD6 (SWITCH).
>> >> [PATCH 4/4] MMC: MMC boot partitions support.
>> >
>> > Any problems, comments?
>>
>> Looks good to me -- Arnd, did you want to add your Reviewed/Acked-by
>> to this?
>>
>
> I haven't done an in-depth review, but please add my Acked-by to the last
> patch. For the other three, I have no idea what they do, but they all
> seem harmless to me ;-)
>
>

Thanks for the Ack.

Patch 1 paves the way for using erase timeout (which is otherwise dead code).

Patch 2 enables proper handling of R1B-response type commands in SDHCI
host. R1B commands use the DAT line as busy, hence DAT timeout
applies. Previously, DAT timeout is only calculated for data-bearing
commands. Now for non-data commands with a cmd_timeout, the timeout is
honored. This allows proper handling of CMD38 (erase). This also
allows proper handling of CMD6 (SWITCH) writes to EXT_CSD register
offsets, as certain operations invoked via this command (such as
partition switch times) have different timeouts associated with them.
Since erase timeout is now honored, the erase cap is turned on.

Please note that all the work in Patch 2 applies only to SDHCI. I'm
not familiar with other hosts, but a cursory glance revealed that they
all have similar issues (no handling of R1B timeouts). I could roll
patches, but I'd have no way of verifying (unless someone wants to
volunteer and help out). If you (as a Linaro person) are interested,
this is something you could add under (Write performance drop -
https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfEMMC).

Patch 3 exposes mmc_switch to block driver, and lets a timeout
parameter be passed, as writes to different fields of EXT_CSD can have
differerent timeouts.

Thanks,
A

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout.
  2011-04-06  1:09 ` [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout Andrei Warkentin
@ 2011-04-11 19:18   ` John Calixto
  2011-04-11 20:34     ` Andrei Warkentin
  0 siblings, 1 reply; 11+ messages in thread
From: John Calixto @ 2011-04-11 19:18 UTC (permalink / raw)
  To: Andrei Warkentin; +Cc: linux-mmc, Arnd Bergmann, Chris Ball

Hi Andrei,

On Tue, 5 Apr 2011, Andrei Warkentin wrote:
> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
> index 07f27af..a7d7da7 100644
> --- a/include/linux/mmc/core.h
> +++ b/include/linux/mmc/core.h
> @@ -92,7 +92,7 @@ struct mmc_command {
>   *              actively failing requests
>   */
>  
> -	unsigned int		erase_timeout;	/* in milliseconds */
> +	unsigned int		cmd_timeout;	/* in milliseconds */
>  
>  	struct mmc_data		*data;		/* data segment associated with cmd */
>  	struct mmc_request	*mrq;		/* associated request */

Could you rename this field to "cmd_timeout_ms"?  When I was testing the
addition of cmd_timeout to my ioctl patch, I noticed that data timeout
was being specified in ns and I had to scale cmd_timeout appropriately.

Cheers,

John

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout.
  2011-04-11 19:18   ` John Calixto
@ 2011-04-11 20:34     ` Andrei Warkentin
  0 siblings, 0 replies; 11+ messages in thread
From: Andrei Warkentin @ 2011-04-11 20:34 UTC (permalink / raw)
  To: John Calixto; +Cc: linux-mmc, Arnd Bergmann, Chris Ball

On Mon, Apr 11, 2011 at 2:18 PM, John Calixto
<john.calixto@modsystems.com> wrote:
> Hi Andrei,
>
> On Tue, 5 Apr 2011, Andrei Warkentin wrote:
>> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
>> index 07f27af..a7d7da7 100644
>> --- a/include/linux/mmc/core.h
>> +++ b/include/linux/mmc/core.h
>> @@ -92,7 +92,7 @@ struct mmc_command {
>>   *              actively failing requests
>>   */
>>
>> -     unsigned int            erase_timeout;  /* in milliseconds */
>> +     unsigned int            cmd_timeout;    /* in milliseconds */
>>
>>       struct mmc_data         *data;          /* data segment associated with cmd */
>>       struct mmc_request      *mrq;           /* associated request */
>
> Could you rename this field to "cmd_timeout_ms"?  When I was testing the
> addition of cmd_timeout to my ioctl patch, I noticed that data timeout
> was being specified in ns and I had to scale cmd_timeout appropriately.
>

Yes! Absolutely. Just sent the updated patch set.

A

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-04-11 20:35 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-06  1:09 Boot partition support patch set Andrei Warkentin
2011-04-06  1:09 ` [PATCH 1/4] MMC: Rename erase_timeout to cmd_timeout Andrei Warkentin
2011-04-11 19:18   ` John Calixto
2011-04-11 20:34     ` Andrei Warkentin
2011-04-06  1:09 ` [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE Andrei Warkentin
2011-04-06  1:09 ` [PATCH 3/4] MMC: Allow setting CMD timeout for CMD6 (SWITCH) Andrei Warkentin
2011-04-06  1:09 ` [PATCH 4/4] MMC: MMC boot partitions support Andrei Warkentin
2011-04-06 23:20 ` Boot partition support patch set Andrei Warkentin
2011-04-07 21:23   ` Chris Ball
2011-04-08  3:47     ` Arnd Bergmann
2011-04-08  6:58       ` Andrei Warkentin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.