From 132919ba80ad207755fe271277bfefff865a54fe Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Sun, 27 Aug 2006 13:56:52 +0100
Subject: [MMC] Remove data->blksz_bits member

data->blksz_bits is unused now - remove it.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 include/linux/mmc/mmc.h | 1 -
 1 file changed, 1 deletion(-)

(limited to 'include/linux/mmc')

diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 627e2c08ce4..a3594dfd696 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -68,7 +68,6 @@ struct mmc_command {
 struct mmc_data {
 	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
 	unsigned int		timeout_clks;	/* data timeout (in clocks) */
-	unsigned int		blksz_bits;	/* data block size */
 	unsigned int		blksz;		/* data block size */
 	unsigned int		blocks;		/* number of blocks */
 	unsigned int		error;		/* data error */
-- 
cgit v1.2.3-70-g09d2


From db53f28b3a6d9338cca1b7e917dc063ac99e1871 Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Wed, 30 Aug 2006 15:14:56 +0100
Subject: [MMC] Add multi block-write capability

Add a capability flag for drivers to set when they can perform multi-
block transfers to cards _and_ correctly report the number of bytes
transferred should an error occur.

The last point is very important - if a driver reports more bytes than
were actually accepted by the card and an error occurs, there is the
possibility for data loss.

Pierre Ossman provided the patch for wbsd and sdhci.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/mmc/mmc_block.c  | 27 ++++++++++++++++++++-------
 drivers/mmc/mmci.c       |  1 +
 drivers/mmc/sdhci.c      |  2 +-
 drivers/mmc/wbsd.c       |  2 +-
 include/linux/mmc/host.h |  1 +
 5 files changed, 24 insertions(+), 9 deletions(-)

(limited to 'include/linux/mmc')

diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index f3a99dd8df8..8d18b87bfd3 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -32,6 +32,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -165,6 +166,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 	do {
 		struct mmc_blk_request brq;
 		struct mmc_command cmd;
+		u32 readcmd, writecmd;
 
 		memset(&brq, 0, sizeof(struct mmc_blk_request));
 		brq.mrq.cmd = &brq.cmd;
@@ -180,20 +182,31 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
 		mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
 
-		if (rq_data_dir(req) == READ) {
-			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
-			brq.data.flags |= MMC_DATA_READ;
-		} else {
-			brq.cmd.opcode = MMC_WRITE_BLOCK;
-			brq.data.flags |= MMC_DATA_WRITE;
+		/*
+		 * If the host doesn't support multiple block writes, force
+		 * block writes to single block.
+		 */
+		if (rq_data_dir(req) != READ &&
+		    !(card->host->caps & MMC_CAP_MULTIWRITE))
 			brq.data.blocks = 1;
-		}
 
 		if (brq.data.blocks > 1) {
 			brq.data.flags |= MMC_DATA_MULTI;
 			brq.mrq.stop = &brq.stop;
+			readcmd = MMC_READ_MULTIPLE_BLOCK;
+			writecmd = MMC_WRITE_MULTIPLE_BLOCK;
 		} else {
 			brq.mrq.stop = NULL;
+			readcmd = MMC_READ_SINGLE_BLOCK;
+			writecmd = MMC_WRITE_BLOCK;
+		}
+
+		if (rq_data_dir(req) == READ) {
+			brq.cmd.opcode = readcmd;
+			brq.data.flags |= MMC_DATA_READ;
+		} else {
+			brq.cmd.opcode = writecmd;
+			brq.data.flags |= MMC_DATA_WRITE;
 		}
 
 		brq.data.sg = mq->sg;
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 8419489e774..2b5a0cc9ea5 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -509,6 +509,7 @@ static int mmci_probe(struct amba_device *dev, void *id)
 	mmc->f_min = (host->mclk + 511) / 512;
 	mmc->f_max = min(host->mclk, fmax);
 	mmc->ocr_avail = plat->ocr_mask;
+	mmc->caps = MMC_CAP_MULTIWRITE;
 
 	/*
 	 * We can do SGIO
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 4e21b3b9d33..dea4edd1c43 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -1262,7 +1262,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 	mmc->ops = &sdhci_ops;
 	mmc->f_min = host->max_clk / 256;
 	mmc->f_max = host->max_clk;
-	mmc->caps = MMC_CAP_4_BIT_DATA;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
 
 	mmc->ocr_avail = 0;
 	if (caps & SDHCI_CAN_VDD_330)
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index c351c6d1a18..4a6617d9a49 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1323,7 +1323,7 @@ static int __devinit wbsd_alloc_mmc(struct device *dev)
 	mmc->f_min = 375000;
 	mmc->f_max = 24000000;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->caps = MMC_CAP_4_BIT_DATA;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
 
 	spin_lock_init(&host->lock);
 
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index ba095aebedf..b282ec9bba0 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -85,6 +85,7 @@ struct mmc_host {
 	unsigned long		caps;		/* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA	(1 << 0)	/* Can the host do 4 bit transfers */
+#define MMC_CAP_MULTIWRITE	(1 << 1)	/* Can accurately report bytes sent to card on error */
 
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
-- 
cgit v1.2.3-70-g09d2


From 42431acbac43eb47c774c29d370f5c59136805bf Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Sun, 24 Sep 2006 10:44:09 +0100
Subject: [MMC] MMC_CAP_BYTEBLOCK flag for non-log2 block sizes capable hosts

Some MMC hosts can only handle log2 block sizes.  Unfortunately,
the MMC password support needs to be able to send non-log2 block
sizes.  Provide a capability so that the MMC password support can
decide whether it should use this support or not.

The unfortunate side effect of this host limitation is that any
MMC card protected by a password which is not a log2 block size
can not be accessed on a host which only allows a log2 block size.

This change just adds the flag.  The MMC password support code
needs updating to use it (if and when it is finally submitted.)

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/mmc/at91_mci.c   | 1 +
 drivers/mmc/imxmmc.c     | 2 +-
 drivers/mmc/omap.c       | 7 ++++---
 drivers/mmc/sdhci.c      | 2 +-
 drivers/mmc/wbsd.c       | 2 +-
 include/linux/mmc/host.h | 1 +
 6 files changed, 9 insertions(+), 6 deletions(-)

(limited to 'include/linux/mmc')

diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 6b7638b8429..d34b7d9d92e 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -822,6 +822,7 @@ static int at91_mci_probe(struct platform_device *pdev)
 	mmc->f_min = 375000;
 	mmc->f_max = 25000000;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+	mmc->caps = MMC_CAP_BYTEBLOCK;
 
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index fb6565b98f3..1b79dd271aa 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -956,7 +956,7 @@ static int imxmci_probe(struct platform_device *pdev)
 	mmc->f_min = 150000;
 	mmc->f_max = CLK_RATE/2;
 	mmc->ocr_avail = MMC_VDD_32_33;
-	mmc->caps |= MMC_CAP_4_BIT_DATA;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_BYTEBLOCK;
 
 	/* MMC core transfer sizes tunable parameters */
 	mmc->max_hw_segs = 64;
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
index ddf06b32c15..52c9e52e6b7 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/omap.c
@@ -1034,13 +1034,14 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
 	host->irq = pdev->resource[1].start;
 	host->base = (void __iomem*)IO_ADDRESS(r->start);
 
-	if (minfo->wire4)
-		 mmc->caps |= MMC_CAP_4_BIT_DATA;
-
 	mmc->ops = &mmc_omap_ops;
 	mmc->f_min = 400000;
 	mmc->f_max = 24000000;
 	mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+	mmc->caps = MMC_CAP_BYTEBLOCK;
+
+	if (minfo->wire4)
+		 mmc->caps |= MMC_CAP_4_BIT_DATA;
 
 	/* Use scatterlist DMA to reduce per-transfer costs.
 	 * NOTE max_seg_size assumption that small blocks aren't
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index dea4edd1c43..fdfc3838dd7 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -1262,7 +1262,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 	mmc->ops = &sdhci_ops;
 	mmc->f_min = host->max_clk / 256;
 	mmc->f_max = host->max_clk;
-	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
 
 	mmc->ocr_avail = 0;
 	if (caps & SDHCI_CAN_VDD_330)
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 4a6617d9a49..6435a6822ad 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1323,7 +1323,7 @@ static int __devinit wbsd_alloc_mmc(struct device *dev)
 	mmc->f_min = 375000;
 	mmc->f_max = 24000000;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
 
 	spin_lock_init(&host->lock);
 
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index b282ec9bba0..587264a58d5 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -86,6 +86,7 @@ struct mmc_host {
 
 #define MMC_CAP_4_BIT_DATA	(1 << 0)	/* Can the host do 4 bit transfers */
 #define MMC_CAP_MULTIWRITE	(1 << 1)	/* Can accurately report bytes sent to card on error */
+#define MMC_CAP_BYTEBLOCK	(1 << 2)	/* Can do non-log2 block sizes */
 
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
-- 
cgit v1.2.3-70-g09d2