summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-08-01 11:22:45 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-08-01 11:22:45 -0700
commitb2bbf43e60073f70a3c8663513710fa8d03a33f8 (patch)
tree2ed0eca444f1e70e1579ab5b18d62a9939e3b0b5 /drivers
parent561b35b341b1aeeab486affe1ede0ee6640ce33b (diff)
parente491d230fd398bb730e3c2dd734c5447463b9d38 (diff)
downloadlinux-b2bbf43e60073f70a3c8663513710fa8d03a33f8.tar.gz
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
  au1xmmc: raise segment size limit.
  mmc_block: use proper sg iterators
  mmc: properly iterate over sg list in debug check
  mmc_test: Revert "mmc_test: test oversized sg lists"
  sdhci: check correct return value
  sdhci: disable DMA for req, not completely
  sdhci: handle bug in JMB38x for sizes < 4 bytes
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/card/block.c17
-rw-r--r--drivers/mmc/card/mmc_test.c85
-rw-r--r--drivers/mmc/core/core.c5
-rw-r--r--drivers/mmc/host/au1xmmc.c8
-rw-r--r--drivers/mmc/host/sdhci-pci.c3
-rw-r--r--drivers/mmc/host/sdhci.c15
-rw-r--r--drivers/mmc/host/sdhci.h2
7 files changed, 40 insertions, 95 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 66e5a5487c20..86dbb366415a 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -213,7 +213,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	struct mmc_blk_request brq;
-	int ret = 1, sg_pos, data_size;
+	int ret = 1, data_size, i;
+	struct scatterlist *sg;
 
 	mmc_claim_host(card->host);
 
@@ -267,18 +268,22 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
 		mmc_queue_bounce_pre(mq);
 
+		/*
+		 * Adjust the sg list so it is the same size as the
+		 * request.
+		 */
 		if (brq.data.blocks !=
 		    (req->nr_sectors >> (md->block_bits - 9))) {
 			data_size = brq.data.blocks * brq.data.blksz;
-			for (sg_pos = 0; sg_pos < brq.data.sg_len; sg_pos++) {
-				data_size -= mq->sg[sg_pos].length;
+			for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {
+				data_size -= sg->length;
 				if (data_size <= 0) {
-					mq->sg[sg_pos].length += data_size;
-					sg_pos++;
+					sg->length += data_size;
+					i++;
 					break;
 				}
 			}
-			brq.data.sg_len = sg_pos;
+			brq.data.sg_len = i;
 		}
 
 		mmc_wait_for_req(card->host, &brq.mrq);
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index a067fe436301..f26b01d811ae 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -388,16 +388,14 @@ static int mmc_test_transfer(struct mmc_test_card *test,
 	int ret, i;
 	unsigned long flags;
 
-	BUG_ON(blocks * blksz > BUFFER_SIZE);
-
 	if (write) {
 		for (i = 0;i < blocks * blksz;i++)
 			test->scratch[i] = i;
 	} else {
-		memset(test->scratch, 0, blocks * blksz);
+		memset(test->scratch, 0, BUFFER_SIZE);
 	}
 	local_irq_save(flags);
-	sg_copy_from_buffer(sg, sg_len, test->scratch, blocks * blksz);
+	sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
 	local_irq_restore(flags);
 
 	ret = mmc_test_set_blksize(test, blksz);
@@ -444,7 +442,7 @@ static int mmc_test_transfer(struct mmc_test_card *test,
 		}
 	} else {
 		local_irq_save(flags);
-		sg_copy_to_buffer(sg, sg_len, test->scratch, blocks * blksz);
+		sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
 		local_irq_restore(flags);
 		for (i = 0;i < blocks * blksz;i++) {
 			if (test->scratch[i] != (u8)i)
@@ -805,69 +803,6 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
 	return 0;
 }
 
-static int mmc_test_bigsg_write(struct mmc_test_card *test)
-{
-	int ret;
-	unsigned int size;
-	struct scatterlist sg;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	size = PAGE_SIZE * 2;
-	size = min(size, test->card->host->max_req_size);
-	size = min(size, test->card->host->max_seg_size);
-	size = min(size, test->card->host->max_blk_count * 512);
-
-	memset(test->buffer, 0, BUFFER_SIZE);
-
-	if (size < 1024)
-		return RESULT_UNSUP_HOST;
-
-	sg_init_table(&sg, 1);
-	sg_init_one(&sg, test->buffer, BUFFER_SIZE);
-
-	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int mmc_test_bigsg_read(struct mmc_test_card *test)
-{
-	int ret, i;
-	unsigned int size;
-	struct scatterlist sg;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	size = PAGE_SIZE * 2;
-	size = min(size, test->card->host->max_req_size);
-	size = min(size, test->card->host->max_seg_size);
-	size = min(size, test->card->host->max_blk_count * 512);
-
-	if (size < 1024)
-		return RESULT_UNSUP_HOST;
-
-	memset(test->buffer, 0xCD, BUFFER_SIZE);
-
-	sg_init_table(&sg, 1);
-	sg_init_one(&sg, test->buffer, BUFFER_SIZE);
-	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
-	if (ret)
-		return ret;
-
-	/* mmc_test_transfer() doesn't check for read overflows */
-	for (i = size;i < BUFFER_SIZE;i++) {
-		if (test->buffer[i] != 0xCD)
-			return RESULT_FAIL;
-	}
-
-	return 0;
-}
-
 #ifdef CONFIG_HIGHMEM
 
 static int mmc_test_write_high(struct mmc_test_card *test)
@@ -1071,20 +1006,6 @@ static const struct mmc_test_case mmc_test_cases[] = {
 		.run = mmc_test_multi_xfersize_read,
 	},
 
-	{
-		.name = "Over-sized SG list write",
-		.prepare = mmc_test_prepare_write,
-		.run = mmc_test_bigsg_write,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Over-sized SG list read",
-		.prepare = mmc_test_prepare_read,
-		.run = mmc_test_bigsg_read,
-		.cleanup = mmc_test_cleanup,
-	},
-
 #ifdef CONFIG_HIGHMEM
 
 	{
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 3ee5b8c3b5ce..044d84eeed7c 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -121,6 +121,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 {
 #ifdef CONFIG_MMC_DEBUG
 	unsigned int i, sz;
+	struct scatterlist *sg;
 #endif
 
 	pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
@@ -156,8 +157,8 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 
 #ifdef CONFIG_MMC_DEBUG
 		sz = 0;
-		for (i = 0;i < mrq->data->sg_len;i++)
-			sz += mrq->data->sg[i].length;
+		for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i)
+			sz += sg->length;
 		BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
 #endif
 
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 99b20917cc0f..d3f55615c099 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -61,7 +61,13 @@
 
 /* Hardware definitions */
 #define AU1XMMC_DESCRIPTOR_COUNT 1
-#define AU1XMMC_DESCRIPTOR_SIZE  2048
+
+/* max DMA seg size: 64KB on Au1100, 4MB on Au1200 */
+#ifdef CONFIG_SOC_AU1100
+#define AU1XMMC_DESCRIPTOR_SIZE 0x0000ffff
+#else	/* Au1200 */
+#define AU1XMMC_DESCRIPTOR_SIZE 0x003fffff
+#endif
 
 #define AU1XMMC_OCR (MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \
 		     MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index deb607c52c0d..fcb14c2346cc 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -143,7 +143,8 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
 		chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR |
 			  SDHCI_QUIRK_32BIT_DMA_SIZE |
 			  SDHCI_QUIRK_32BIT_ADMA_SIZE |
-			  SDHCI_QUIRK_RESET_AFTER_REQUEST;
+			  SDHCI_QUIRK_RESET_AFTER_REQUEST |
+			  SDHCI_QUIRK_BROKEN_SMALL_PIO;
 	}
 
 	/*
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 5f95e10229b5..e3a8133560a2 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -278,6 +278,15 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
 	else
 		mask = SDHCI_SPACE_AVAILABLE;
 
+	/*
+	 * Some controllers (JMicron JMB38x) mess up the buffer bits
+	 * for transfers < 4 bytes. As long as it is just one block,
+	 * we can ignore the bits.
+	 */
+	if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) &&
+		(host->data->blocks == 1))
+		mask = ~0;
+
 	while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
 		if (host->data->flags & MMC_DATA_READ)
 			sdhci_read_block_pio(host);
@@ -439,7 +448,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 
 	host->adma_addr = dma_map_single(mmc_dev(host->mmc),
 		host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
-	if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
+	if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr))
 		goto unmap_entries;
 	BUG_ON(host->adma_addr & 0x3);
 
@@ -645,7 +654,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 				 * us an invalid request.
 				 */
 				WARN_ON(1);
-				host->flags &= ~SDHCI_USE_DMA;
+				host->flags &= ~SDHCI_REQ_USE_DMA;
 			} else {
 				writel(host->adma_addr,
 					host->ioaddr + SDHCI_ADMA_ADDRESS);
@@ -664,7 +673,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 				 * us an invalid request.
 				 */
 				WARN_ON(1);
-				host->flags &= ~SDHCI_USE_DMA;
+				host->flags &= ~SDHCI_REQ_USE_DMA;
 			} else {
 				WARN_ON(sg_cnt != 1);
 				writel(sg_dma_address(data->sg),
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index e354faee5df0..197d4a05f4ae 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -206,6 +206,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER		(1<<11)
 /* Controller provides an incorrect timeout value for transfers */
 #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL			(1<<12)
+/* Controller has an issue with buffer bits for small transfers */
+#define SDHCI_QUIRK_BROKEN_SMALL_PIO			(1<<13)
 
 	int			irq;		/* Device IRQ */
 	void __iomem *		ioaddr;		/* Mapped address */