All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/12] mmci: use sg_miter API to fix multi-page sg handling
@ 2010-06-22  9:17 ` Rabin Vincent
  0 siblings, 0 replies; 64+ messages in thread
From: Rabin Vincent @ 2010-06-22  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-mmc, STEricsson_nomadik_linux, Rabin Vincent, Linus Walleij

The mmci driver's SG list iteration logic assumes that each SG entry
spans only one page, and only maps and flushes one page of the sg.  This
is not a valid assumption.  Fix it by converting the driver to the
sg_miter API, which correctly handles sgs which span multiple pages.
Cache flushing is handled inside the sg_miter API implementation.

Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
---
 drivers/mmc/host/mmci.c |   55 ++++++++++++++++++++++------------------------
 drivers/mmc/host/mmci.h |   35 +-----------------------------
 2 files changed, 27 insertions(+), 63 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 4917af9..683516b 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -26,7 +26,6 @@
 #include <linux/amba/mmci.h>
 #include <linux/regulator/consumer.h>
 
-#include <asm/cacheflush.h>
 #include <asm/div64.h>
 #include <asm/io.h>
 #include <asm/sizes.h>
@@ -98,6 +97,18 @@ static void mmci_stop_data(struct mmci_host *host)
 	host->data = NULL;
 }
 
+static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
+{
+	unsigned int flags = SG_MITER_ATOMIC;
+
+	if (data->flags & MMC_DATA_READ)
+		flags |= SG_MITER_TO_SG;
+	else
+		flags |= SG_MITER_FROM_SG;
+
+	sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
+}
+
 static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 {
 	unsigned int datactrl, timeout, irqmask;
@@ -205,13 +216,6 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
 		else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
 			data->error = -EIO;
 		status |= MCI_DATAEND;
-
-		/*
-		 * We hit an error condition.  Ensure that any data
-		 * partially written to a page is properly coherent.
-		 */
-		if (host->sg_len && data->flags & MMC_DATA_READ)
-			flush_dcache_page(sg_page(host->sg_ptr));
 	}
 	if (status & MCI_DATAEND) {
 		mmci_stop_data(host);
@@ -314,15 +318,18 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem
 static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
 {
 	struct mmci_host *host = dev_id;
+	struct sg_mapping_iter *sg_miter = &host->sg_miter;
 	void __iomem *base = host->base;
+	unsigned long flags;
 	u32 status;
 
 	status = readl(base + MMCISTATUS);
 
 	dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status);
 
+	local_irq_save(flags);
+
 	do {
-		unsigned long flags;
 		unsigned int remain, len;
 		char *buffer;
 
@@ -336,11 +343,11 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
 		if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL)))
 			break;
 
-		/*
-		 * Map the current scatter buffer.
-		 */
-		buffer = mmci_kmap_atomic(host, &flags) + host->sg_off;
-		remain = host->sg_ptr->length - host->sg_off;
+		if (!sg_miter_next(sg_miter))
+			break;
+
+		buffer = sg_miter->addr;
+		remain = sg_miter->length;
 
 		len = 0;
 		if (status & MCI_RXACTIVE)
@@ -348,31 +355,21 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
 		if (status & MCI_TXACTIVE)
 			len = mmci_pio_write(host, buffer, remain, status);
 
-		/*
-		 * Unmap the buffer.
-		 */
-		mmci_kunmap_atomic(host, buffer, &flags);
+		sg_miter->consumed = len;
 
-		host->sg_off += len;
 		host->size -= len;
 		remain -= len;
 
 		if (remain)
 			break;
 
-		/*
-		 * If we were reading, and we have completed this
-		 * page, ensure that the data cache is coherent.
-		 */
-		if (status & MCI_RXACTIVE)
-			flush_dcache_page(sg_page(host->sg_ptr));
-
-		if (!mmci_next_sg(host))
-			break;
-
 		status = readl(base + MMCISTATUS);
 	} while (1);
 
+	sg_miter_stop(sg_miter);
+
+	local_irq_restore(flags);
+
 	/*
 	 * If we're nearing the end of the read, switch to
 	 * "any data available" mode.
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index d77062e..7cb24ab 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -171,42 +171,9 @@ struct mmci_host {
 	struct timer_list	timer;
 	unsigned int		oldstat;
 
-	unsigned int		sg_len;
-
 	/* pio stuff */
-	struct scatterlist	*sg_ptr;
-	unsigned int		sg_off;
+	struct sg_mapping_iter	sg_miter;
 	unsigned int		size;
 	struct regulator	*vcc;
 };
 
-static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
-{
-	/*
-	 * Ideally, we want the higher levels to pass us a scatter list.
-	 */
-	host->sg_len = data->sg_len;
-	host->sg_ptr = data->sg;
-	host->sg_off = 0;
-}
-
-static inline int mmci_next_sg(struct mmci_host *host)
-{
-	host->sg_ptr++;
-	host->sg_off = 0;
-	return --host->sg_len;
-}
-
-static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flags)
-{
-	struct scatterlist *sg = host->sg_ptr;
-
-	local_irq_save(*flags);
-	return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
-}
-
-static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags)
-{
-	kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
-	local_irq_restore(*flags);
-}
-- 
1.7.0


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

end of thread, other threads:[~2010-10-19 12:52 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-22  9:17 [PATCH 01/12] mmci: use sg_miter API to fix multi-page sg handling Rabin Vincent
2010-06-22  9:17 ` Rabin Vincent
2010-06-22  9:17 ` [PATCH 02/12] mmci: fix multi block transfers Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-07-29 13:18   ` Russell King - ARM Linux
2010-07-29 13:18     ` Russell King - ARM Linux
2010-07-29 13:31     ` Colin Tuckley
2010-07-29 13:36       ` Russell King - ARM Linux
2010-07-29 13:42         ` Colin Tuckley
2010-07-29 13:55           ` Russell King - ARM Linux
2010-07-29 14:14             ` Russell King - ARM Linux
2010-06-22  9:17 ` [PATCH 03/12] mmci: let core poll for card detection Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-06-22  9:17 ` [PATCH 04/12] mmci: allow the card detect status not to be inverted Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-07-29 12:34   ` Russell King - ARM Linux
2010-07-29 12:34     ` Russell King - ARM Linux
2010-07-29 13:53     ` Linus Walleij
2010-07-29 13:53       ` Linus Walleij
2010-07-29 14:20       ` Russell King - ARM Linux
2010-07-29 14:20         ` Russell King - ARM Linux
2010-08-05  6:14         ` Rabin VINCENT
2010-08-05  6:14           ` Rabin VINCENT
2010-08-05  9:25           ` Russell King - ARM Linux
2010-08-05  9:25             ` Russell King - ARM Linux
2010-08-09 10:37             ` Rabin VINCENT
2010-08-09 10:37               ` Rabin VINCENT
2010-08-09 11:25               ` Russell King - ARM Linux
2010-08-09 11:25                 ` Russell King - ARM Linux
2010-06-22  9:17 ` [PATCH 05/12] mmci: support card detection interrupts Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-06-22  9:17 ` [PATCH 06/12] mmci: allow neither ->status nor gpio_cd to be specified Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-06-22  9:17 ` [PATCH 07/12] mmci: pass power_mode to the translate_vdd callback Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-06-22 22:03   ` Linus Walleij
2010-06-22 22:03     ` Linus Walleij
2010-06-24  8:27     ` Rabin VINCENT
2010-06-24  8:27       ` Rabin VINCENT
2010-06-24  8:56       ` Linus WALLEIJ
2010-06-24  8:56         ` Linus WALLEIJ
2010-07-19 12:57   ` [PATCHv2 " Rabin Vincent
2010-07-19 12:57     ` Rabin Vincent
2010-06-22  9:17 ` [PATCH 08/12] mmci: add variant data and default MCICLOCK support Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-06-22  9:17 ` [PATCH 09/12] mmci: enable hardware flow control on Ux500 variants Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-06-22  9:17 ` [PATCH 10/12] mmci: support larger MMCIDATALENGTH register Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-06-22  9:17 ` [PATCH 11/12] mmci: support different FIFO sizes Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-06-22  9:17 ` [PATCH 12/12] mmci: support variants with only one irq Rabin Vincent
2010-06-22  9:17   ` Rabin Vincent
2010-09-23 20:04   ` Linus Walleij
2010-09-23 20:04     ` Linus Walleij
2010-10-11  0:06   ` [PATCHv2] mmci: work " Rabin Vincent
2010-10-11  9:13     ` Linus Walleij
2010-10-11  9:44     ` Russell King - ARM Linux
2010-10-11 11:10       ` Linus Walleij
2010-10-19 12:52       ` Linus Walleij
2010-07-07 20:34 ` [PATCH 01/12] mmci: use sg_miter API to fix multi-page sg handling Linus Walleij
2010-07-07 20:34   ` Linus Walleij
2010-07-19 13:23 ` [PATCHv2 " Rabin Vincent
2010-07-19 13:23   ` Rabin Vincent

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.