All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
@ 2011-06-21 14:41 ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Wolfram Sang, Arnaud Patard, Eric Benard,
	Philip Rakity, linux-arm-kernel, patches

The card-present polling for sdhci based driver is very expensive
in terms of the impact to system performance.  We observe a few
system performance issues from Freescale and Linaro on mx5 platforms,
which have been proved card polling related.

The patch set extends the current sdhci-esdhc-imx card_detect and
write_protect support to cover mx5 platforms, and solves above
performance issues.

Changes since v3:
 * Address comment from Philip Rakity on sdhci_set_card_detection
 * Change a couple of dev_warn to dev_err in sdhci-esdhc-imx.c per
   Arnaud Patard's comment
 * Add Arnaud Patard's Test-by
 * Add missing Acked-by, Cc stable on patch #2

Changes since v2:
 * Fix the issue reported by Arnaud Patard:
   http://article.gmane.org/gmane.linux.ports.arm.kernel/120790

Changes since v1:
 * Rebase on today's linux-next
 * Take the suggestion from Arnaud Patard to add default pdata in
   imx_add_sdhci_esdhc_imx(), to avoid touching every single board
   file for the platform_data changes
 * Add comment for sdhci.c change
 * Change ESDHC_CD(WP)_SIGNAL to ESDHC_CD(WP)_CONTROLLER for a more
   descriptive name
 * Add missing NONE case handling in esdhc_pltfm_get_ro
 * Improve a couple comment wording per suggestion from Wolfram Sang

Shawn Guo (4):
      mmc: sdhci: fix interrupt storm from card detection
      mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared
      mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP
      mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5

 arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
 arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
 arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
 arch/arm/mach-imx/mach-pcm043.c                    |    2 +
 arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
 arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
 .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
 arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
 drivers/mmc/host/sdhci-esdhc-imx.c                 |  140 ++++++++++++--------
 drivers/mmc/host/sdhci.c                           |   29 ++++-
 10 files changed, 165 insertions(+), 69 deletions(-)

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

* [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
@ 2011-06-21 14:41 ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-arm-kernel

The card-present polling for sdhci based driver is very expensive
in terms of the impact to system performance.  We observe a few
system performance issues from Freescale and Linaro on mx5 platforms,
which have been proved card polling related.

The patch set extends the current sdhci-esdhc-imx card_detect and
write_protect support to cover mx5 platforms, and solves above
performance issues.

Changes since v3:
 * Address comment from Philip Rakity on sdhci_set_card_detection
 * Change a couple of dev_warn to dev_err in sdhci-esdhc-imx.c per
   Arnaud Patard's comment
 * Add Arnaud Patard's Test-by
 * Add missing Acked-by, Cc stable on patch #2

Changes since v2:
 * Fix the issue reported by Arnaud Patard:
   http://article.gmane.org/gmane.linux.ports.arm.kernel/120790

Changes since v1:
 * Rebase on today's linux-next
 * Take the suggestion from Arnaud Patard to add default pdata in
   imx_add_sdhci_esdhc_imx(), to avoid touching every single board
   file for the platform_data changes
 * Add comment for sdhci.c change
 * Change ESDHC_CD(WP)_SIGNAL to ESDHC_CD(WP)_CONTROLLER for a more
   descriptive name
 * Add missing NONE case handling in esdhc_pltfm_get_ro
 * Improve a couple comment wording per suggestion from Wolfram Sang

Shawn Guo (4):
      mmc: sdhci: fix interrupt storm from card detection
      mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared
      mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP
      mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5

 arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
 arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
 arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
 arch/arm/mach-imx/mach-pcm043.c                    |    2 +
 arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
 arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
 .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
 arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
 drivers/mmc/host/sdhci-esdhc-imx.c                 |  140 ++++++++++++--------
 drivers/mmc/host/sdhci.c                           |   29 ++++-
 10 files changed, 165 insertions(+), 69 deletions(-)

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

* [PATCH v4 1/4] mmc: sdhci: fix interrupt storm from card detection
  2011-06-21 14:41 ` Shawn Guo
@ 2011-06-21 14:41   ` Shawn Guo
  -1 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Wolfram Sang, Arnaud Patard, Eric Benard,
	Philip Rakity, linux-arm-kernel, patches, Shawn Guo

The issue was initially found by Eric Benard as below.

http://permalink.gmane.org/gmane.linux.ports.arm.kernel/108031

Not sure about other SDHCI based controller, but on Freescale eSDHC,
the SDHCI_INT_CARD_INSERT bits will be immediately set again when it
gets cleared, if a card is inserted. The driver need to mask the irq
to prevent interrupt storm which will freeze the system.  And the
SDHCI_INT_CARD_REMOVE gets the same situation.

The patch fixes the problem based on the initial idea from
Eric Benard.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Eric Benard <eric@eukrea.com>
Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
---
 drivers/mmc/host/sdhci.c |   29 +++++++++++++++++++++++++----
 1 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 91d9892..790f959 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
 
 static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
 {
-	u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
+	u32 present, irqs;
 
 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
 		return;
 
+	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+			      SDHCI_CARD_PRESENT;
+	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
+
 	if (enable)
 		sdhci_unmask_irqs(host, irqs);
 	else
@@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 		mmc_hostname(host->mmc), intmask);
 
 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+			      SDHCI_CARD_PRESENT;
+
+		/*
+		 * There is a observation on i.mx esdhc.  INSERT bit will be
+		 * immediately set again when it gets cleared, if a card is
+		 * inserted.  We have to mask the irq to prevent interrupt
+		 * storm which will freeze the system.  And the REMOVE gets
+		 * the same situation.
+		 *
+		 * More testing are needed here to ensure it works for other
+		 * platforms though.
+		 */
+		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
+						SDHCI_INT_CARD_REMOVE);
+		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
+						  SDHCI_INT_CARD_INSERT);
+
 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
-			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
 		tasklet_schedule(&host->card_tasklet);
 	}
 
-	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
-
 	if (intmask & SDHCI_INT_CMD_MASK) {
 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
 			SDHCI_INT_STATUS);
-- 
1.7.4.1


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

* [PATCH v4 1/4] mmc: sdhci: fix interrupt storm from card detection
@ 2011-06-21 14:41   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-arm-kernel

The issue was initially found by Eric Benard as below.

http://permalink.gmane.org/gmane.linux.ports.arm.kernel/108031

Not sure about other SDHCI based controller, but on Freescale eSDHC,
the SDHCI_INT_CARD_INSERT bits will be immediately set again when it
gets cleared, if a card is inserted. The driver need to mask the irq
to prevent interrupt storm which will freeze the system.  And the
SDHCI_INT_CARD_REMOVE gets the same situation.

The patch fixes the problem based on the initial idea from
Eric Benard.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Eric Benard <eric@eukrea.com>
Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
---
 drivers/mmc/host/sdhci.c |   29 +++++++++++++++++++++++++----
 1 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 91d9892..790f959 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
 
 static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
 {
-	u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
+	u32 present, irqs;
 
 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
 		return;
 
+	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+			      SDHCI_CARD_PRESENT;
+	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
+
 	if (enable)
 		sdhci_unmask_irqs(host, irqs);
 	else
@@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 		mmc_hostname(host->mmc), intmask);
 
 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+			      SDHCI_CARD_PRESENT;
+
+		/*
+		 * There is a observation on i.mx esdhc.  INSERT bit will be
+		 * immediately set again when it gets cleared, if a card is
+		 * inserted.  We have to mask the irq to prevent interrupt
+		 * storm which will freeze the system.  And the REMOVE gets
+		 * the same situation.
+		 *
+		 * More testing are needed here to ensure it works for other
+		 * platforms though.
+		 */
+		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
+						SDHCI_INT_CARD_REMOVE);
+		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
+						  SDHCI_INT_CARD_INSERT);
+
 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
-			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
 		tasklet_schedule(&host->card_tasklet);
 	}
 
-	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
-
 	if (intmask & SDHCI_INT_CMD_MASK) {
 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
 			SDHCI_INT_STATUS);
-- 
1.7.4.1

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

* [PATCH v4 2/4] mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared
  2011-06-21 14:41 ` Shawn Guo
@ 2011-06-21 14:41   ` Shawn Guo
  -1 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Wolfram Sang, Arnaud Patard, Eric Benard,
	Philip Rakity, linux-arm-kernel, patches, Shawn Guo, stable

The function esdhc_readl_le intends to clear bit SDHCI_CARD_PRESENT,
when the card detect gpio tells there is no card.  But it does not
clear the bit actually.  The patch gives a fix on that.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
Cc: <stable@kernel.org>
---
 drivers/mmc/host/sdhci-esdhc-imx.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 248b8e5..94097c0 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -84,7 +84,7 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 		if (boarddata && gpio_is_valid(boarddata->cd_gpio)
 				&& gpio_get_value(boarddata->cd_gpio))
 			/* no card, if a valid gpio says so... */
-			val &= SDHCI_CARD_PRESENT;
+			val &= ~SDHCI_CARD_PRESENT;
 		else
 			/* ... in all other cases assume card is present */
 			val |= SDHCI_CARD_PRESENT;
-- 
1.7.4.1


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

* [PATCH v4 2/4] mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared
@ 2011-06-21 14:41   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-arm-kernel

The function esdhc_readl_le intends to clear bit SDHCI_CARD_PRESENT,
when the card detect gpio tells there is no card.  But it does not
clear the bit actually.  The patch gives a fix on that.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
Cc: <stable@kernel.org>
---
 drivers/mmc/host/sdhci-esdhc-imx.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 248b8e5..94097c0 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -84,7 +84,7 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 		if (boarddata && gpio_is_valid(boarddata->cd_gpio)
 				&& gpio_get_value(boarddata->cd_gpio))
 			/* no card, if a valid gpio says so... */
-			val &= SDHCI_CARD_PRESENT;
+			val &= ~SDHCI_CARD_PRESENT;
 		else
 			/* ... in all other cases assume card is present */
 			val |= SDHCI_CARD_PRESENT;
-- 
1.7.4.1

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

* [PATCH v4 3/4] mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP
  2011-06-21 14:41 ` Shawn Guo
@ 2011-06-21 14:41   ` Shawn Guo
  -1 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Wolfram Sang, Arnaud Patard, Eric Benard,
	Philip Rakity, linux-arm-kernel, patches, Shawn Guo

The use of flag ESDHC_FLAG_GPIO_FOR_CD_WP is all CD related.  It does
not necessarily need to bother WP in the flag name.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 drivers/mmc/host/sdhci-esdhc-imx.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 94097c0..79b7a9a 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -29,7 +29,7 @@
 #define SDHCI_VENDOR_SPEC		0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK	0x00000002
 
-#define ESDHC_FLAG_GPIO_FOR_CD_WP	(1 << 0)
+#define ESDHC_FLAG_GPIO_FOR_CD		(1 << 0)
 /*
  * The CMDTYPE of the CMD register (offset 0xE) should be set to
  * "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -77,7 +77,7 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 	u32 val = readl(host->ioaddr + reg);
 
 	if (unlikely((reg == SDHCI_PRESENT_STATE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) {
+			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
 		struct esdhc_platform_data *boarddata =
 				host->mmc->parent->platform_data;
 
@@ -99,7 +99,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
 
 	if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP)))
+			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
 		/*
 		 * these interrupts won't work with a custom card_detect gpio
 		 * (only applied to mx25/35)
@@ -308,7 +308,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 			goto no_card_detect_irq;
 		}
 
-		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP;
+		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
 		/* Now we have a working card_detect again */
 		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 	}
-- 
1.7.4.1


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

* [PATCH v4 3/4] mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP
@ 2011-06-21 14:41   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-arm-kernel

The use of flag ESDHC_FLAG_GPIO_FOR_CD_WP is all CD related.  It does
not necessarily need to bother WP in the flag name.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 drivers/mmc/host/sdhci-esdhc-imx.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 94097c0..79b7a9a 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -29,7 +29,7 @@
 #define SDHCI_VENDOR_SPEC		0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK	0x00000002
 
-#define ESDHC_FLAG_GPIO_FOR_CD_WP	(1 << 0)
+#define ESDHC_FLAG_GPIO_FOR_CD		(1 << 0)
 /*
  * The CMDTYPE of the CMD register (offset 0xE) should be set to
  * "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -77,7 +77,7 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 	u32 val = readl(host->ioaddr + reg);
 
 	if (unlikely((reg == SDHCI_PRESENT_STATE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) {
+			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
 		struct esdhc_platform_data *boarddata =
 				host->mmc->parent->platform_data;
 
@@ -99,7 +99,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
 
 	if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP)))
+			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
 		/*
 		 * these interrupts won't work with a custom card_detect gpio
 		 * (only applied to mx25/35)
@@ -308,7 +308,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 			goto no_card_detect_irq;
 		}
 
-		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP;
+		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
 		/* Now we have a working card_detect again */
 		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 	}
-- 
1.7.4.1

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

* [PATCH v4 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5
  2011-06-21 14:41 ` Shawn Guo
@ 2011-06-21 14:41   ` Shawn Guo
  -1 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Wolfram Sang, Arnaud Patard, Eric Benard,
	Philip Rakity, linux-arm-kernel, patches, Shawn Guo

The patch extends card_detect and write_protect support to get mx5
family and more scenarios supported.  The changes include:

 * Turn platform_data from optional to mandatory
 * Add cd_types and wp_types into platform_data to cover more use
   cases
 * Remove the use of flag ESDHC_FLAG_GPIO_FOR_CD
 * Adjust some machine codes to adopt the platform_data changes
 * Work around the issue that software reset will get card detection
   circuit stop working

With this patch, card_detect and write_protect gets supported on
mx5 based platforms.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
---
 arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
 arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
 arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
 arch/arm/mach-imx/mach-pcm043.c                    |    2 +
 arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
 arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
 .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
 arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
 drivers/mmc/host/sdhci-esdhc-imx.c                 |  138 ++++++++++++--------
 9 files changed, 139 insertions(+), 64 deletions(-)

diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 01ebcb3..66e8726 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -225,7 +225,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 
 static struct esdhc_platform_data sd1_pdata = {
 	.cd_gpio = GPIO_SD1CD,
-	.wp_gpio = -EINVAL,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
 };
 
 /*
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 558eb52..0f0af02 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -236,7 +236,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 
 static struct esdhc_platform_data sd1_pdata = {
 	.cd_gpio = GPIO_SD1CD,
-	.wp_gpio = -EINVAL,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
 };
 
 /*
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 01534bb..7f66a91 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -215,6 +215,8 @@ static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
 static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
 	.wp_gpio = SD1_GPIO_WP,
 	.cd_gpio = SD1_GPIO_CD,
+	.wp_type = ESDHC_WP_GPIO,
+	.cd_type = ESDHC_CD_GPIO,
 };
 
 static void __init mx25pdk_init(void)
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 163cc31..660ec3e 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -349,6 +349,8 @@ __setup("otg_mode=", pcm043_otg_mode);
 static struct esdhc_platform_data sd1_pdata = {
 	.wp_gpio = SD1_GPIO_WP,
 	.cd_gpio = SD1_GPIO_CD,
+	.wp_type = ESDHC_WP_GPIO,
+	.cd_type = ESDHC_CD_GPIO,
 };
 
 /*
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 15c6000..e400b09 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -41,8 +41,6 @@
 #define BABBAGE_POWER_KEY	IMX_GPIO_NR(2, 21)
 #define BABBAGE_ECSPI1_CS0	IMX_GPIO_NR(4, 24)
 #define BABBAGE_ECSPI1_CS1	IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD1_CD		IMX_GPIO_NR(1, 0)
-#define BABBAGE_SD1_WP		IMX_GPIO_NR(1, 1)
 #define BABBAGE_SD2_CD		IMX_GPIO_NR(1, 6)
 #define BABBAGE_SD2_WP		IMX_GPIO_NR(1, 5)
 
@@ -146,8 +144,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 	MX51_PAD_SD1_DATA1__SD1_DATA1,
 	MX51_PAD_SD1_DATA2__SD1_DATA2,
 	MX51_PAD_SD1_DATA3__SD1_DATA3,
-	MX51_PAD_GPIO1_0__GPIO1_0,
-	MX51_PAD_GPIO1_1__GPIO1_1,
+	/* CD/WP from controller */
+	MX51_PAD_GPIO1_0__SD1_CD,
+	MX51_PAD_GPIO1_1__SD1_WP,
 
 	/* SD 2 */
 	MX51_PAD_SD2_CMD__SD2_CMD,
@@ -156,6 +155,7 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 	MX51_PAD_SD2_DATA1__SD2_DATA1,
 	MX51_PAD_SD2_DATA2__SD2_DATA2,
 	MX51_PAD_SD2_DATA3__SD2_DATA3,
+	/* CD/WP gpio */
 	MX51_PAD_GPIO1_6__GPIO1_6,
 	MX51_PAD_GPIO1_5__GPIO1_5,
 
@@ -340,13 +340,15 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
 };
 
 static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
-	.cd_gpio = BABBAGE_SD1_CD,
-	.wp_gpio = BABBAGE_SD1_WP,
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
 };
 
 static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
 	.cd_gpio = BABBAGE_SD2_CD,
 	.wp_gpio = BABBAGE_SD2_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
 };
 
 /*
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 54be525..4e1d51d 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -210,11 +210,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
 
 static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
 	.cd_gpio = LOCO_SD1_CD,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
 };
 
 static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
 	.cd_gpio = LOCO_SD3_CD,
 	.wp_gpio = LOCO_SD3_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
 };
 
 static inline void mx53_loco_fec_reset(void)
diff --git a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
index 6b2940b..79d6d71 100644
--- a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
+++ b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
@@ -65,6 +65,11 @@ imx53_sdhci_esdhc_imx_data[] __initconst = {
 };
 #endif /* ifdef CONFIG_SOC_IMX53 */
 
+static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
+	.wp_type = ESDHC_WP_NONE,
+	.cd_type = ESDHC_CD_NONE,
+};
+
 struct platform_device *__init imx_add_sdhci_esdhc_imx(
 		const struct imx_sdhci_esdhc_imx_data *data,
 		const struct esdhc_platform_data *pdata)
@@ -81,6 +86,13 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
 		},
 	};
 
+	/*
+	 * If machine does not provide pdata, use the default one
+	 * which means no WP/CD support
+	 */
+	if (!pdata)
+		pdata = &default_esdhc_pdata;
+
 	return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
 			ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index 86003f4..aaf9748 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,17 +10,34 @@
 #ifndef __ASM_ARCH_IMX_ESDHC_H
 #define __ASM_ARCH_IMX_ESDHC_H
 
+enum wp_types {
+	ESDHC_WP_NONE,		/* no WP, neither controller nor gpio */
+	ESDHC_WP_CONTROLLER,	/* mmc controller internal WP */
+	ESDHC_WP_GPIO,		/* external gpio pin for WP */
+};
+
+enum cd_types {
+	ESDHC_CD_NONE,		/* no CD, neither controller nor gpio */
+	ESDHC_CD_CONTROLLER,	/* mmc controller internal CD */
+	ESDHC_CD_GPIO,		/* external gpio pin for CD */
+	ESDHC_CD_PERMANENT,	/* no CD, card permanently wired to host */
+};
+
 /**
- * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ * struct esdhc_platform_data - platform data for esdhc on i.MX
  *
- * strongly recommended for i.MX25/35, not needed for other variants
+ * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
  *
- * @wp_gpio:	gpio for write_protect (-EINVAL if unused)
- * @cd_gpio:	gpio for card_detect interrupt (-EINVAL if unused)
+ * @wp_gpio:	gpio for write_protect
+ * @cd_gpio:	gpio for card_detect interrupt
+ * @wp_type:	type of write_protect method (see wp_types enum above)
+ * @cd_type:	type of card_detect method (see cd_types enum above)
  */
 
 struct esdhc_platform_data {
 	unsigned int wp_gpio;
 	unsigned int cd_gpio;
+	enum wp_types wp_type;
+	enum cd_types cd_type;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 79b7a9a..3cc6f61 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -29,7 +29,6 @@
 #define SDHCI_VENDOR_SPEC		0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK	0x00000002
 
-#define ESDHC_FLAG_GPIO_FOR_CD		(1 << 0)
 /*
  * The CMDTYPE of the CMD register (offset 0xE) should be set to
  * "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -70,19 +69,15 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
 
 static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 {
-	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	struct esdhc_platform_data *boarddata =
+			host->mmc->parent->platform_data;
 
-	/* fake CARD_PRESENT flag on mx25/35 */
+	/* fake CARD_PRESENT flag */
 	u32 val = readl(host->ioaddr + reg);
 
 	if (unlikely((reg == SDHCI_PRESENT_STATE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
-		struct esdhc_platform_data *boarddata =
-				host->mmc->parent->platform_data;
-
-		if (boarddata && gpio_is_valid(boarddata->cd_gpio)
-				&& gpio_get_value(boarddata->cd_gpio))
+			&& gpio_is_valid(boarddata->cd_gpio))) {
+		if (gpio_get_value(boarddata->cd_gpio))
 			/* no card, if a valid gpio says so... */
 			val &= ~SDHCI_CARD_PRESENT;
 		else
@@ -97,12 +92,13 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	struct esdhc_platform_data *boarddata =
+			host->mmc->parent->platform_data;
 
 	if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
+			&& (boarddata->cd_type == ESDHC_CD_GPIO)))
 		/*
 		 * these interrupts won't work with a custom card_detect gpio
-		 * (only applied to mx25/35)
 		 */
 		val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
 
@@ -185,6 +181,17 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
 		return;
 	}
 	esdhc_clrset_le(host, 0xff, val, reg);
+
+	/*
+	 * The esdhc has a design violation to SDHC spec which tells
+	 * that software reset should not affect card detection circuit.
+	 * But esdhc clears its SYSCTL register bits [0..2] during the
+	 * software reset.  This will stop those clocks that card detection
+	 * circuit relies on.  To work around it, we turn the clocks on back
+	 * to keep card detection circuit functional.
+	 */
+	if ((reg == SDHCI_SOFTWARE_RESET) && (val & 1))
+		esdhc_clrset_le(host, 0x7, 0x7, ESDHC_SYSTEM_CONTROL);
 }
 
 static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
@@ -201,6 +208,25 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
 	return clk_get_rate(pltfm_host->clk) / 256 / 16;
 }
 
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+	struct esdhc_platform_data *boarddata =
+			host->mmc->parent->platform_data;
+
+	switch (boarddata->wp_type) {
+	case ESDHC_WP_GPIO:
+		if (gpio_is_valid(boarddata->wp_gpio))
+			return gpio_get_value(boarddata->wp_gpio);
+	case ESDHC_WP_CONTROLLER:
+		return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
+			       SDHCI_WRITE_PROTECT);
+	case ESDHC_WP_NONE:
+		break;
+	}
+
+	return -ENOSYS;
+}
+
 static struct sdhci_ops sdhci_esdhc_ops = {
 	.read_l = esdhc_readl_le,
 	.read_w = esdhc_readw_le,
@@ -212,6 +238,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.get_min_clock = esdhc_pltfm_get_min_clock,
 	.get_max_blk_size = esdhc_pltfm_get_max_blk_size,
 	.get_max_blk_count = esdhc_pltfm_get_max_blk_count,
+	.get_ro = esdhc_pltfm_get_ro,
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -221,17 +248,6 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
 	.ops = &sdhci_esdhc_ops,
 };
 
-static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
-{
-	struct esdhc_platform_data *boarddata =
-			host->mmc->parent->platform_data;
-
-	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
-		return gpio_get_value(boarddata->wp_gpio);
-	else
-		return -ENOSYS;
-}
-
 static irqreturn_t cd_irq(int irq, void *data)
 {
 	struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -272,45 +288,61 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	if (!cpu_is_mx25())
 		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-	if (cpu_is_mx25() || cpu_is_mx35()) {
-		/* write_protect can't be routed to controller, use gpio */
-		sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
-	}
-
 	if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
 		imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
 
 	boarddata = host->mmc->parent->platform_data;
-	if (boarddata) {
+	if (!boarddata) {
+		dev_err(mmc_dev(host->mmc), "no board data!\n");
+		err = -EINVAL;
+		goto no_board_data;
+	}
+
+	/* write_protect */
+	if (boarddata->wp_type == ESDHC_WP_GPIO) {
 		err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
 		if (err) {
 			dev_warn(mmc_dev(host->mmc),
-				"no write-protect pin available!\n");
-			boarddata->wp_gpio = err;
+				 "no write-protect pin available!\n");
+			boarddata->wp_gpio = -EINVAL;
 		}
+	} else {
+		boarddata->wp_gpio = -EINVAL;
+	}
+
+	/* card_detect */
+	if (boarddata->cd_type != ESDHC_CD_GPIO)
+		boarddata->cd_gpio = -EINVAL;
 
+	switch (boarddata->cd_type) {
+	case ESDHC_CD_GPIO:
 		err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
 		if (err) {
-			dev_warn(mmc_dev(host->mmc),
+			dev_err(mmc_dev(host->mmc),
 				"no card-detect pin available!\n");
 			goto no_card_detect_pin;
 		}
 
-		/* i.MX5x has issues to be researched */
-		if (!cpu_is_mx25() && !cpu_is_mx35())
-			goto not_supported;
-
 		err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
 				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 				 mmc_hostname(host->mmc), host);
 		if (err) {
-			dev_warn(mmc_dev(host->mmc), "request irq error\n");
+			dev_err(mmc_dev(host->mmc), "request irq error\n");
 			goto no_card_detect_irq;
 		}
+		/* fall through */
 
-		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
-		/* Now we have a working card_detect again */
+	case ESDHC_CD_CONTROLLER:
+		/* we have a working card_detect back */
 		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+		break;
+
+	case ESDHC_CD_PERMANENT:
+		host->mmc->caps = MMC_CAP_NONREMOVABLE;
+		break;
+
+	case ESDHC_CD_NONE:
+		break;
 	}
 
 	err = sdhci_add_host(host);
@@ -319,16 +351,20 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
 	return 0;
 
- no_card_detect_irq:
-	gpio_free(boarddata->cd_gpio);
- no_card_detect_pin:
-	boarddata->cd_gpio = err;
- not_supported:
-	kfree(imx_data);
- err_add_host:
+err_add_host:
+	if (gpio_is_valid(boarddata->cd_gpio))
+		free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+no_card_detect_irq:
+	if (gpio_is_valid(boarddata->cd_gpio))
+		gpio_free(boarddata->cd_gpio);
+	if (gpio_is_valid(boarddata->wp_gpio))
+		gpio_free(boarddata->wp_gpio);
+no_card_detect_pin:
+no_board_data:
 	clk_disable(pltfm_host->clk);
 	clk_put(pltfm_host->clk);
- err_clk_get:
+err_clk_get:
+	kfree(imx_data);
 	sdhci_pltfm_free(pdev);
 	return err;
 }
@@ -343,14 +379,12 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
 
 	sdhci_remove_host(host, dead);
 
-	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+	if (gpio_is_valid(boarddata->wp_gpio))
 		gpio_free(boarddata->wp_gpio);
 
-	if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+	if (gpio_is_valid(boarddata->cd_gpio)) {
+		free_irq(gpio_to_irq(boarddata->cd_gpio), host);
 		gpio_free(boarddata->cd_gpio);
-
-		if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
-			free_irq(gpio_to_irq(boarddata->cd_gpio), host);
 	}
 
 	clk_disable(pltfm_host->clk);
-- 
1.7.4.1


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

* [PATCH v4 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5
@ 2011-06-21 14:41   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-21 14:41 UTC (permalink / raw)
  To: linux-arm-kernel

The patch extends card_detect and write_protect support to get mx5
family and more scenarios supported.  The changes include:

 * Turn platform_data from optional to mandatory
 * Add cd_types and wp_types into platform_data to cover more use
   cases
 * Remove the use of flag ESDHC_FLAG_GPIO_FOR_CD
 * Adjust some machine codes to adopt the platform_data changes
 * Work around the issue that software reset will get card detection
   circuit stop working

With this patch, card_detect and write_protect gets supported on
mx5 based platforms.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
---
 arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
 arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
 arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
 arch/arm/mach-imx/mach-pcm043.c                    |    2 +
 arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
 arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
 .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
 arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
 drivers/mmc/host/sdhci-esdhc-imx.c                 |  138 ++++++++++++--------
 9 files changed, 139 insertions(+), 64 deletions(-)

diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 01ebcb3..66e8726 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -225,7 +225,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 
 static struct esdhc_platform_data sd1_pdata = {
 	.cd_gpio = GPIO_SD1CD,
-	.wp_gpio = -EINVAL,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
 };
 
 /*
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 558eb52..0f0af02 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -236,7 +236,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 
 static struct esdhc_platform_data sd1_pdata = {
 	.cd_gpio = GPIO_SD1CD,
-	.wp_gpio = -EINVAL,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
 };
 
 /*
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 01534bb..7f66a91 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -215,6 +215,8 @@ static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
 static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
 	.wp_gpio = SD1_GPIO_WP,
 	.cd_gpio = SD1_GPIO_CD,
+	.wp_type = ESDHC_WP_GPIO,
+	.cd_type = ESDHC_CD_GPIO,
 };
 
 static void __init mx25pdk_init(void)
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 163cc31..660ec3e 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -349,6 +349,8 @@ __setup("otg_mode=", pcm043_otg_mode);
 static struct esdhc_platform_data sd1_pdata = {
 	.wp_gpio = SD1_GPIO_WP,
 	.cd_gpio = SD1_GPIO_CD,
+	.wp_type = ESDHC_WP_GPIO,
+	.cd_type = ESDHC_CD_GPIO,
 };
 
 /*
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 15c6000..e400b09 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -41,8 +41,6 @@
 #define BABBAGE_POWER_KEY	IMX_GPIO_NR(2, 21)
 #define BABBAGE_ECSPI1_CS0	IMX_GPIO_NR(4, 24)
 #define BABBAGE_ECSPI1_CS1	IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD1_CD		IMX_GPIO_NR(1, 0)
-#define BABBAGE_SD1_WP		IMX_GPIO_NR(1, 1)
 #define BABBAGE_SD2_CD		IMX_GPIO_NR(1, 6)
 #define BABBAGE_SD2_WP		IMX_GPIO_NR(1, 5)
 
@@ -146,8 +144,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 	MX51_PAD_SD1_DATA1__SD1_DATA1,
 	MX51_PAD_SD1_DATA2__SD1_DATA2,
 	MX51_PAD_SD1_DATA3__SD1_DATA3,
-	MX51_PAD_GPIO1_0__GPIO1_0,
-	MX51_PAD_GPIO1_1__GPIO1_1,
+	/* CD/WP from controller */
+	MX51_PAD_GPIO1_0__SD1_CD,
+	MX51_PAD_GPIO1_1__SD1_WP,
 
 	/* SD 2 */
 	MX51_PAD_SD2_CMD__SD2_CMD,
@@ -156,6 +155,7 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 	MX51_PAD_SD2_DATA1__SD2_DATA1,
 	MX51_PAD_SD2_DATA2__SD2_DATA2,
 	MX51_PAD_SD2_DATA3__SD2_DATA3,
+	/* CD/WP gpio */
 	MX51_PAD_GPIO1_6__GPIO1_6,
 	MX51_PAD_GPIO1_5__GPIO1_5,
 
@@ -340,13 +340,15 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
 };
 
 static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
-	.cd_gpio = BABBAGE_SD1_CD,
-	.wp_gpio = BABBAGE_SD1_WP,
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
 };
 
 static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
 	.cd_gpio = BABBAGE_SD2_CD,
 	.wp_gpio = BABBAGE_SD2_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
 };
 
 /*
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 54be525..4e1d51d 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -210,11 +210,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
 
 static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
 	.cd_gpio = LOCO_SD1_CD,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
 };
 
 static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
 	.cd_gpio = LOCO_SD3_CD,
 	.wp_gpio = LOCO_SD3_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
 };
 
 static inline void mx53_loco_fec_reset(void)
diff --git a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
index 6b2940b..79d6d71 100644
--- a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
+++ b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
@@ -65,6 +65,11 @@ imx53_sdhci_esdhc_imx_data[] __initconst = {
 };
 #endif /* ifdef CONFIG_SOC_IMX53 */
 
+static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
+	.wp_type = ESDHC_WP_NONE,
+	.cd_type = ESDHC_CD_NONE,
+};
+
 struct platform_device *__init imx_add_sdhci_esdhc_imx(
 		const struct imx_sdhci_esdhc_imx_data *data,
 		const struct esdhc_platform_data *pdata)
@@ -81,6 +86,13 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
 		},
 	};
 
+	/*
+	 * If machine does not provide pdata, use the default one
+	 * which means no WP/CD support
+	 */
+	if (!pdata)
+		pdata = &default_esdhc_pdata;
+
 	return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
 			ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index 86003f4..aaf9748 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,17 +10,34 @@
 #ifndef __ASM_ARCH_IMX_ESDHC_H
 #define __ASM_ARCH_IMX_ESDHC_H
 
+enum wp_types {
+	ESDHC_WP_NONE,		/* no WP, neither controller nor gpio */
+	ESDHC_WP_CONTROLLER,	/* mmc controller internal WP */
+	ESDHC_WP_GPIO,		/* external gpio pin for WP */
+};
+
+enum cd_types {
+	ESDHC_CD_NONE,		/* no CD, neither controller nor gpio */
+	ESDHC_CD_CONTROLLER,	/* mmc controller internal CD */
+	ESDHC_CD_GPIO,		/* external gpio pin for CD */
+	ESDHC_CD_PERMANENT,	/* no CD, card permanently wired to host */
+};
+
 /**
- * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ * struct esdhc_platform_data - platform data for esdhc on i.MX
  *
- * strongly recommended for i.MX25/35, not needed for other variants
+ * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
  *
- * @wp_gpio:	gpio for write_protect (-EINVAL if unused)
- * @cd_gpio:	gpio for card_detect interrupt (-EINVAL if unused)
+ * @wp_gpio:	gpio for write_protect
+ * @cd_gpio:	gpio for card_detect interrupt
+ * @wp_type:	type of write_protect method (see wp_types enum above)
+ * @cd_type:	type of card_detect method (see cd_types enum above)
  */
 
 struct esdhc_platform_data {
 	unsigned int wp_gpio;
 	unsigned int cd_gpio;
+	enum wp_types wp_type;
+	enum cd_types cd_type;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 79b7a9a..3cc6f61 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -29,7 +29,6 @@
 #define SDHCI_VENDOR_SPEC		0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK	0x00000002
 
-#define ESDHC_FLAG_GPIO_FOR_CD		(1 << 0)
 /*
  * The CMDTYPE of the CMD register (offset 0xE) should be set to
  * "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -70,19 +69,15 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
 
 static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 {
-	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	struct esdhc_platform_data *boarddata =
+			host->mmc->parent->platform_data;
 
-	/* fake CARD_PRESENT flag on mx25/35 */
+	/* fake CARD_PRESENT flag */
 	u32 val = readl(host->ioaddr + reg);
 
 	if (unlikely((reg == SDHCI_PRESENT_STATE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
-		struct esdhc_platform_data *boarddata =
-				host->mmc->parent->platform_data;
-
-		if (boarddata && gpio_is_valid(boarddata->cd_gpio)
-				&& gpio_get_value(boarddata->cd_gpio))
+			&& gpio_is_valid(boarddata->cd_gpio))) {
+		if (gpio_get_value(boarddata->cd_gpio))
 			/* no card, if a valid gpio says so... */
 			val &= ~SDHCI_CARD_PRESENT;
 		else
@@ -97,12 +92,13 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	struct esdhc_platform_data *boarddata =
+			host->mmc->parent->platform_data;
 
 	if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
+			&& (boarddata->cd_type == ESDHC_CD_GPIO)))
 		/*
 		 * these interrupts won't work with a custom card_detect gpio
-		 * (only applied to mx25/35)
 		 */
 		val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
 
@@ -185,6 +181,17 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
 		return;
 	}
 	esdhc_clrset_le(host, 0xff, val, reg);
+
+	/*
+	 * The esdhc has a design violation to SDHC spec which tells
+	 * that software reset should not affect card detection circuit.
+	 * But esdhc clears its SYSCTL register bits [0..2] during the
+	 * software reset.  This will stop those clocks that card detection
+	 * circuit relies on.  To work around it, we turn the clocks on back
+	 * to keep card detection circuit functional.
+	 */
+	if ((reg == SDHCI_SOFTWARE_RESET) && (val & 1))
+		esdhc_clrset_le(host, 0x7, 0x7, ESDHC_SYSTEM_CONTROL);
 }
 
 static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
@@ -201,6 +208,25 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
 	return clk_get_rate(pltfm_host->clk) / 256 / 16;
 }
 
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+	struct esdhc_platform_data *boarddata =
+			host->mmc->parent->platform_data;
+
+	switch (boarddata->wp_type) {
+	case ESDHC_WP_GPIO:
+		if (gpio_is_valid(boarddata->wp_gpio))
+			return gpio_get_value(boarddata->wp_gpio);
+	case ESDHC_WP_CONTROLLER:
+		return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
+			       SDHCI_WRITE_PROTECT);
+	case ESDHC_WP_NONE:
+		break;
+	}
+
+	return -ENOSYS;
+}
+
 static struct sdhci_ops sdhci_esdhc_ops = {
 	.read_l = esdhc_readl_le,
 	.read_w = esdhc_readw_le,
@@ -212,6 +238,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.get_min_clock = esdhc_pltfm_get_min_clock,
 	.get_max_blk_size = esdhc_pltfm_get_max_blk_size,
 	.get_max_blk_count = esdhc_pltfm_get_max_blk_count,
+	.get_ro = esdhc_pltfm_get_ro,
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -221,17 +248,6 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
 	.ops = &sdhci_esdhc_ops,
 };
 
-static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
-{
-	struct esdhc_platform_data *boarddata =
-			host->mmc->parent->platform_data;
-
-	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
-		return gpio_get_value(boarddata->wp_gpio);
-	else
-		return -ENOSYS;
-}
-
 static irqreturn_t cd_irq(int irq, void *data)
 {
 	struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -272,45 +288,61 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	if (!cpu_is_mx25())
 		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-	if (cpu_is_mx25() || cpu_is_mx35()) {
-		/* write_protect can't be routed to controller, use gpio */
-		sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
-	}
-
 	if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
 		imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
 
 	boarddata = host->mmc->parent->platform_data;
-	if (boarddata) {
+	if (!boarddata) {
+		dev_err(mmc_dev(host->mmc), "no board data!\n");
+		err = -EINVAL;
+		goto no_board_data;
+	}
+
+	/* write_protect */
+	if (boarddata->wp_type == ESDHC_WP_GPIO) {
 		err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
 		if (err) {
 			dev_warn(mmc_dev(host->mmc),
-				"no write-protect pin available!\n");
-			boarddata->wp_gpio = err;
+				 "no write-protect pin available!\n");
+			boarddata->wp_gpio = -EINVAL;
 		}
+	} else {
+		boarddata->wp_gpio = -EINVAL;
+	}
+
+	/* card_detect */
+	if (boarddata->cd_type != ESDHC_CD_GPIO)
+		boarddata->cd_gpio = -EINVAL;
 
+	switch (boarddata->cd_type) {
+	case ESDHC_CD_GPIO:
 		err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
 		if (err) {
-			dev_warn(mmc_dev(host->mmc),
+			dev_err(mmc_dev(host->mmc),
 				"no card-detect pin available!\n");
 			goto no_card_detect_pin;
 		}
 
-		/* i.MX5x has issues to be researched */
-		if (!cpu_is_mx25() && !cpu_is_mx35())
-			goto not_supported;
-
 		err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
 				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 				 mmc_hostname(host->mmc), host);
 		if (err) {
-			dev_warn(mmc_dev(host->mmc), "request irq error\n");
+			dev_err(mmc_dev(host->mmc), "request irq error\n");
 			goto no_card_detect_irq;
 		}
+		/* fall through */
 
-		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
-		/* Now we have a working card_detect again */
+	case ESDHC_CD_CONTROLLER:
+		/* we have a working card_detect back */
 		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+		break;
+
+	case ESDHC_CD_PERMANENT:
+		host->mmc->caps = MMC_CAP_NONREMOVABLE;
+		break;
+
+	case ESDHC_CD_NONE:
+		break;
 	}
 
 	err = sdhci_add_host(host);
@@ -319,16 +351,20 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
 	return 0;
 
- no_card_detect_irq:
-	gpio_free(boarddata->cd_gpio);
- no_card_detect_pin:
-	boarddata->cd_gpio = err;
- not_supported:
-	kfree(imx_data);
- err_add_host:
+err_add_host:
+	if (gpio_is_valid(boarddata->cd_gpio))
+		free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+no_card_detect_irq:
+	if (gpio_is_valid(boarddata->cd_gpio))
+		gpio_free(boarddata->cd_gpio);
+	if (gpio_is_valid(boarddata->wp_gpio))
+		gpio_free(boarddata->wp_gpio);
+no_card_detect_pin:
+no_board_data:
 	clk_disable(pltfm_host->clk);
 	clk_put(pltfm_host->clk);
- err_clk_get:
+err_clk_get:
+	kfree(imx_data);
 	sdhci_pltfm_free(pdev);
 	return err;
 }
@@ -343,14 +379,12 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
 
 	sdhci_remove_host(host, dead);
 
-	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+	if (gpio_is_valid(boarddata->wp_gpio))
 		gpio_free(boarddata->wp_gpio);
 
-	if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+	if (gpio_is_valid(boarddata->cd_gpio)) {
+		free_irq(gpio_to_irq(boarddata->cd_gpio), host);
 		gpio_free(boarddata->cd_gpio);
-
-		if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
-			free_irq(gpio_to_irq(boarddata->cd_gpio), host);
 	}
 
 	clk_disable(pltfm_host->clk);
-- 
1.7.4.1

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

* Re: [PATCH v4 1/4] mmc: sdhci: fix interrupt storm from card detection
  2011-06-21 14:41   ` Shawn Guo
@ 2011-06-21 16:05     ` Philip Rakity
  -1 siblings, 0 replies; 24+ messages in thread
From: Philip Rakity @ 2011-06-21 16:05 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-mmc, Chris Ball, Wolfram Sang, Arnaud Patard, Eric Benard,
	linux-arm-kernel, patches


On Jun 21, 2011, at 7:41 AM, Shawn Guo wrote:

> The issue was initially found by Eric Benard as below.
> 
> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/108031
> 
> Not sure about other SDHCI based controller, but on Freescale eSDHC,
> the SDHCI_INT_CARD_INSERT bits will be immediately set again when it
> gets cleared, if a card is inserted. The driver need to mask the irq
> to prevent interrupt storm which will freeze the system.  And the
> SDHCI_INT_CARD_REMOVE gets the same situation.
> 
> The patch fixes the problem based on the initial idea from
> Eric Benard.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Eric Benard <eric@eukrea.com>
> Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
> ---
> drivers/mmc/host/sdhci.c |   29 +++++++++++++++++++++++++----
> 1 files changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 91d9892..790f959 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
> 
> static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
> {
> -	u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
> +	u32 present, irqs;
> 
> 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
> 		return;
> 
> +	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
> +			      SDHCI_CARD_PRESENT;
> +	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
> +
> 	if (enable)
> 		sdhci_unmask_irqs(host, irqs);
> 	else
> @@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
> 		mmc_hostname(host->mmc), intmask);
> 
> 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
> +		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
> +			      SDHCI_CARD_PRESENT;
> +
> +		/*
> +		 * There is a observation on i.mx esdhc.  INSERT bit will be
> +		 * immediately set again when it gets cleared, if a card is
> +		 * inserted.  We have to mask the irq to prevent interrupt
> +		 * storm which will freeze the system.  And the REMOVE gets
> +		 * the same situation.
> +		 *
> +		 * More testing are needed here to ensure it works for other
> +		 * platforms though.
> +		 */
> +		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
> +						SDHCI_INT_CARD_REMOVE);
> +		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
> +						  SDHCI_INT_CARD_INSERT);
> +

====
> 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
> -			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
> +			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);

====
Please keep the old formatting since code does not change anything.  Makes it easier to find
the real change

> +		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
> 		tasklet_schedule(&host->card_tasklet);
> 	}
> 
> -	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
> -
> 	if (intmask & SDHCI_INT_CMD_MASK) {
> 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
> 			SDHCI_INT_STATUS);
> -- 
> 1.7.4.1
> 


Reviewed-by: Philip Rakity <prakity@marvell.com>


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

* [PATCH v4 1/4] mmc: sdhci: fix interrupt storm from card detection
@ 2011-06-21 16:05     ` Philip Rakity
  0 siblings, 0 replies; 24+ messages in thread
From: Philip Rakity @ 2011-06-21 16:05 UTC (permalink / raw)
  To: linux-arm-kernel


On Jun 21, 2011, at 7:41 AM, Shawn Guo wrote:

> The issue was initially found by Eric Benard as below.
> 
> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/108031
> 
> Not sure about other SDHCI based controller, but on Freescale eSDHC,
> the SDHCI_INT_CARD_INSERT bits will be immediately set again when it
> gets cleared, if a card is inserted. The driver need to mask the irq
> to prevent interrupt storm which will freeze the system.  And the
> SDHCI_INT_CARD_REMOVE gets the same situation.
> 
> The patch fixes the problem based on the initial idea from
> Eric Benard.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Eric Benard <eric@eukrea.com>
> Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
> ---
> drivers/mmc/host/sdhci.c |   29 +++++++++++++++++++++++++----
> 1 files changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 91d9892..790f959 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
> 
> static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
> {
> -	u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
> +	u32 present, irqs;
> 
> 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
> 		return;
> 
> +	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
> +			      SDHCI_CARD_PRESENT;
> +	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
> +
> 	if (enable)
> 		sdhci_unmask_irqs(host, irqs);
> 	else
> @@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
> 		mmc_hostname(host->mmc), intmask);
> 
> 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
> +		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
> +			      SDHCI_CARD_PRESENT;
> +
> +		/*
> +		 * There is a observation on i.mx esdhc.  INSERT bit will be
> +		 * immediately set again when it gets cleared, if a card is
> +		 * inserted.  We have to mask the irq to prevent interrupt
> +		 * storm which will freeze the system.  And the REMOVE gets
> +		 * the same situation.
> +		 *
> +		 * More testing are needed here to ensure it works for other
> +		 * platforms though.
> +		 */
> +		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
> +						SDHCI_INT_CARD_REMOVE);
> +		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
> +						  SDHCI_INT_CARD_INSERT);
> +

====
> 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
> -			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
> +			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);

====
Please keep the old formatting since code does not change anything.  Makes it easier to find
the real change

> +		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
> 		tasklet_schedule(&host->card_tasklet);
> 	}
> 
> -	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
> -
> 	if (intmask & SDHCI_INT_CMD_MASK) {
> 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
> 			SDHCI_INT_STATUS);
> -- 
> 1.7.4.1
> 


Reviewed-by: Philip Rakity <prakity@marvell.com>

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

* Re: [PATCH v4 1/4] mmc: sdhci: fix interrupt storm from card detection
  2011-06-21 16:05     ` Philip Rakity
@ 2011-06-22  4:40       ` Shawn Guo
  -1 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-22  4:40 UTC (permalink / raw)
  To: Philip Rakity
  Cc: Shawn Guo, linux-mmc, Chris Ball, Wolfram Sang, Arnaud Patard,
	Eric Benard, linux-arm-kernel, patches

On Tue, Jun 21, 2011 at 09:05:25AM -0700, Philip Rakity wrote:
> 
> On Jun 21, 2011, at 7:41 AM, Shawn Guo wrote:
> 
> > The issue was initially found by Eric Benard as below.
> > 
> > http://permalink.gmane.org/gmane.linux.ports.arm.kernel/108031
> > 
> > Not sure about other SDHCI based controller, but on Freescale eSDHC,
> > the SDHCI_INT_CARD_INSERT bits will be immediately set again when it
> > gets cleared, if a card is inserted. The driver need to mask the irq
> > to prevent interrupt storm which will freeze the system.  And the
> > SDHCI_INT_CARD_REMOVE gets the same situation.
> > 
> > The patch fixes the problem based on the initial idea from
> > Eric Benard.
> > 
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > Cc: Eric Benard <eric@eukrea.com>
> > Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
> > ---
> > drivers/mmc/host/sdhci.c |   29 +++++++++++++++++++++++++----
> > 1 files changed, 25 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 91d9892..790f959 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
> > 
> > static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
> > {
> > -	u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
> > +	u32 present, irqs;
> > 
> > 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
> > 		return;
> > 
> > +	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
> > +			      SDHCI_CARD_PRESENT;
> > +	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
> > +
> > 	if (enable)
> > 		sdhci_unmask_irqs(host, irqs);
> > 	else
> > @@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
> > 		mmc_hostname(host->mmc), intmask);
> > 
> > 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
> > +		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
> > +			      SDHCI_CARD_PRESENT;
> > +
> > +		/*
> > +		 * There is a observation on i.mx esdhc.  INSERT bit will be
> > +		 * immediately set again when it gets cleared, if a card is
> > +		 * inserted.  We have to mask the irq to prevent interrupt
> > +		 * storm which will freeze the system.  And the REMOVE gets
> > +		 * the same situation.
> > +		 *
> > +		 * More testing are needed here to ensure it works for other
> > +		 * platforms though.
> > +		 */
> > +		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
> > +						SDHCI_INT_CARD_REMOVE);
> > +		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
> > +						  SDHCI_INT_CARD_INSERT);
> > +
> 
> ====
> > 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
> > -			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
> > +			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
> 
> ====
> Please keep the old formatting since code does not change anything.  Makes it easier to find
> the real change
> 

I actually rewrote the body of the if-statement, and fixed one
indentation in that specific line.

> > +		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
> > 		tasklet_schedule(&host->card_tasklet);
> > 	}
> > 
> > -	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
> > -
> > 	if (intmask & SDHCI_INT_CMD_MASK) {
> > 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
> > 			SDHCI_INT_STATUS);
> > -- 
> > 1.7.4.1
> > 
> 
> 
> Reviewed-by: Philip Rakity <prakity@marvell.com>
> 

-- 
Regards,
Shawn


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

* [PATCH v4 1/4] mmc: sdhci: fix interrupt storm from card detection
@ 2011-06-22  4:40       ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-22  4:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jun 21, 2011 at 09:05:25AM -0700, Philip Rakity wrote:
> 
> On Jun 21, 2011, at 7:41 AM, Shawn Guo wrote:
> 
> > The issue was initially found by Eric Benard as below.
> > 
> > http://permalink.gmane.org/gmane.linux.ports.arm.kernel/108031
> > 
> > Not sure about other SDHCI based controller, but on Freescale eSDHC,
> > the SDHCI_INT_CARD_INSERT bits will be immediately set again when it
> > gets cleared, if a card is inserted. The driver need to mask the irq
> > to prevent interrupt storm which will freeze the system.  And the
> > SDHCI_INT_CARD_REMOVE gets the same situation.
> > 
> > The patch fixes the problem based on the initial idea from
> > Eric Benard.
> > 
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > Cc: Eric Benard <eric@eukrea.com>
> > Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
> > ---
> > drivers/mmc/host/sdhci.c |   29 +++++++++++++++++++++++++----
> > 1 files changed, 25 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 91d9892..790f959 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
> > 
> > static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
> > {
> > -	u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
> > +	u32 present, irqs;
> > 
> > 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
> > 		return;
> > 
> > +	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
> > +			      SDHCI_CARD_PRESENT;
> > +	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
> > +
> > 	if (enable)
> > 		sdhci_unmask_irqs(host, irqs);
> > 	else
> > @@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
> > 		mmc_hostname(host->mmc), intmask);
> > 
> > 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
> > +		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
> > +			      SDHCI_CARD_PRESENT;
> > +
> > +		/*
> > +		 * There is a observation on i.mx esdhc.  INSERT bit will be
> > +		 * immediately set again when it gets cleared, if a card is
> > +		 * inserted.  We have to mask the irq to prevent interrupt
> > +		 * storm which will freeze the system.  And the REMOVE gets
> > +		 * the same situation.
> > +		 *
> > +		 * More testing are needed here to ensure it works for other
> > +		 * platforms though.
> > +		 */
> > +		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
> > +						SDHCI_INT_CARD_REMOVE);
> > +		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
> > +						  SDHCI_INT_CARD_INSERT);
> > +
> 
> ====
> > 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
> > -			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
> > +			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
> 
> ====
> Please keep the old formatting since code does not change anything.  Makes it easier to find
> the real change
> 

I actually rewrote the body of the if-statement, and fixed one
indentation in that specific line.

> > +		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
> > 		tasklet_schedule(&host->card_tasklet);
> > 	}
> > 
> > -	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
> > -
> > 	if (intmask & SDHCI_INT_CMD_MASK) {
> > 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
> > 			SDHCI_INT_STATUS);
> > -- 
> > 1.7.4.1
> > 
> 
> 
> Reviewed-by: Philip Rakity <prakity@marvell.com>
> 

-- 
Regards,
Shawn

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

* Re: [PATCH v4 1/4] mmc: sdhci: fix interrupt storm from card detection
  2011-06-22  4:40       ` Shawn Guo
@ 2011-06-22  4:41         ` Philip Rakity
  -1 siblings, 0 replies; 24+ messages in thread
From: Philip Rakity @ 2011-06-22  4:41 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Shawn Guo, linux-mmc, Chris Ball, Wolfram Sang, Arnaud Patard,
	Eric Benard, linux-arm-kernel, patches


On Jun 21, 2011, at 9:40 PM, Shawn Guo wrote:

> On Tue, Jun 21, 2011 at 09:05:25AM -0700, Philip Rakity wrote:
>> 
>> On Jun 21, 2011, at 7:41 AM, Shawn Guo wrote:
>> 
>>> The issue was initially found by Eric Benard as below.
>>> 
>>> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/108031
>>> 
>>> Not sure about other SDHCI based controller, but on Freescale eSDHC,
>>> the SDHCI_INT_CARD_INSERT bits will be immediately set again when it
>>> gets cleared, if a card is inserted. The driver need to mask the irq
>>> to prevent interrupt storm which will freeze the system.  And the
>>> SDHCI_INT_CARD_REMOVE gets the same situation.
>>> 
>>> The patch fixes the problem based on the initial idea from
>>> Eric Benard.
>>> 
>>> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
>>> Cc: Eric Benard <eric@eukrea.com>
>>> Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
>>> ---
>>> drivers/mmc/host/sdhci.c |   29 +++++++++++++++++++++++++----
>>> 1 files changed, 25 insertions(+), 4 deletions(-)
>>> 
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 91d9892..790f959 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
>>> 
>>> static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
>>> {
>>> -	u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
>>> +	u32 present, irqs;
>>> 
>>> 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>>> 		return;
>>> 
>>> +	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
>>> +			      SDHCI_CARD_PRESENT;
>>> +	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
>>> +
>>> 	if (enable)
>>> 		sdhci_unmask_irqs(host, irqs);
>>> 	else
>>> @@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
>>> 		mmc_hostname(host->mmc), intmask);
>>> 
>>> 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
>>> +		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
>>> +			      SDHCI_CARD_PRESENT;
>>> +
>>> +		/*
>>> +		 * There is a observation on i.mx esdhc.  INSERT bit will be
>>> +		 * immediately set again when it gets cleared, if a card is
>>> +		 * inserted.  We have to mask the irq to prevent interrupt
>>> +		 * storm which will freeze the system.  And the REMOVE gets
>>> +		 * the same situation.
>>> +		 *
>>> +		 * More testing are needed here to ensure it works for other
>>> +		 * platforms though.
>>> +		 */
>>> +		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
>>> +						SDHCI_INT_CARD_REMOVE);
>>> +		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
>>> +						  SDHCI_INT_CARD_INSERT);
>>> +
>> 
>> ====
>>> 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
>>> -			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
>>> +			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
>> 
>> ====
>> Please keep the old formatting since code does not change anything.  Makes it easier to find
>> the real change
>> 
> 
> I actually rewrote the body of the if-statement, and fixed one
> indentation in that specific line.

understand -- I'm happy with the results !  
Philip

> 
>>> +		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
>>> 		tasklet_schedule(&host->card_tasklet);
>>> 	}
>>> 
>>> -	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
>>> -
>>> 	if (intmask & SDHCI_INT_CMD_MASK) {
>>> 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
>>> 			SDHCI_INT_STATUS);
>>> -- 
>>> 1.7.4.1
>>> 
>> 
>> 
>> Reviewed-by: Philip Rakity <prakity@marvell.com>
>> 
> 
> -- 
> Regards,
> Shawn
> 


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

* [PATCH v4 1/4] mmc: sdhci: fix interrupt storm from card detection
@ 2011-06-22  4:41         ` Philip Rakity
  0 siblings, 0 replies; 24+ messages in thread
From: Philip Rakity @ 2011-06-22  4:41 UTC (permalink / raw)
  To: linux-arm-kernel


On Jun 21, 2011, at 9:40 PM, Shawn Guo wrote:

> On Tue, Jun 21, 2011 at 09:05:25AM -0700, Philip Rakity wrote:
>> 
>> On Jun 21, 2011, at 7:41 AM, Shawn Guo wrote:
>> 
>>> The issue was initially found by Eric Benard as below.
>>> 
>>> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/108031
>>> 
>>> Not sure about other SDHCI based controller, but on Freescale eSDHC,
>>> the SDHCI_INT_CARD_INSERT bits will be immediately set again when it
>>> gets cleared, if a card is inserted. The driver need to mask the irq
>>> to prevent interrupt storm which will freeze the system.  And the
>>> SDHCI_INT_CARD_REMOVE gets the same situation.
>>> 
>>> The patch fixes the problem based on the initial idea from
>>> Eric Benard.
>>> 
>>> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
>>> Cc: Eric Benard <eric@eukrea.com>
>>> Tested-by: Arnaud Patard <arnaud.patard@rtp-net.org>
>>> ---
>>> drivers/mmc/host/sdhci.c |   29 +++++++++++++++++++++++++----
>>> 1 files changed, 25 insertions(+), 4 deletions(-)
>>> 
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 91d9892..790f959 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
>>> 
>>> static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
>>> {
>>> -	u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
>>> +	u32 present, irqs;
>>> 
>>> 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>>> 		return;
>>> 
>>> +	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
>>> +			      SDHCI_CARD_PRESENT;
>>> +	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
>>> +
>>> 	if (enable)
>>> 		sdhci_unmask_irqs(host, irqs);
>>> 	else
>>> @@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
>>> 		mmc_hostname(host->mmc), intmask);
>>> 
>>> 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
>>> +		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
>>> +			      SDHCI_CARD_PRESENT;
>>> +
>>> +		/*
>>> +		 * There is a observation on i.mx esdhc.  INSERT bit will be
>>> +		 * immediately set again when it gets cleared, if a card is
>>> +		 * inserted.  We have to mask the irq to prevent interrupt
>>> +		 * storm which will freeze the system.  And the REMOVE gets
>>> +		 * the same situation.
>>> +		 *
>>> +		 * More testing are needed here to ensure it works for other
>>> +		 * platforms though.
>>> +		 */
>>> +		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
>>> +						SDHCI_INT_CARD_REMOVE);
>>> +		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
>>> +						  SDHCI_INT_CARD_INSERT);
>>> +
>> 
>> ====
>>> 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
>>> -			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
>>> +			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
>> 
>> ====
>> Please keep the old formatting since code does not change anything.  Makes it easier to find
>> the real change
>> 
> 
> I actually rewrote the body of the if-statement, and fixed one
> indentation in that specific line.

understand -- I'm happy with the results !  
Philip

> 
>>> +		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
>>> 		tasklet_schedule(&host->card_tasklet);
>>> 	}
>>> 
>>> -	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
>>> -
>>> 	if (intmask & SDHCI_INT_CMD_MASK) {
>>> 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
>>> 			SDHCI_INT_STATUS);
>>> -- 
>>> 1.7.4.1
>>> 
>> 
>> 
>> Reviewed-by: Philip Rakity <prakity@marvell.com>
>> 
> 
> -- 
> Regards,
> Shawn
> 

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

* Re: [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
  2011-06-21 14:41 ` Shawn Guo
@ 2011-06-27  1:38   ` Shawn Guo
  -1 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-27  1:38 UTC (permalink / raw)
  To: Chris Ball
  Cc: patches, linux-mmc, Wolfram Sang, Arnaud Patard, Eric Benard,
	Philip Rakity, linux-arm-kernel

Hi Chris,

On Tue, Jun 21, 2011 at 10:41:47PM +0800, Shawn Guo wrote:
> The card-present polling for sdhci based driver is very expensive
> in terms of the impact to system performance.  We observe a few
> system performance issues from Freescale and Linaro on mx5 platforms,
> which have been proved card polling related.
> 
> The patch set extends the current sdhci-esdhc-imx card_detect and
> write_protect support to cover mx5 platforms, and solves above
> performance issues.
> 
> Changes since v3:
>  * Address comment from Philip Rakity on sdhci_set_card_detection
>  * Change a couple of dev_warn to dev_err in sdhci-esdhc-imx.c per
>    Arnaud Patard's comment
>  * Add Arnaud Patard's Test-by
>  * Add missing Acked-by, Cc stable on patch #2
> 
> Changes since v2:
>  * Fix the issue reported by Arnaud Patard:
>    http://article.gmane.org/gmane.linux.ports.arm.kernel/120790
> 
> Changes since v1:
>  * Rebase on today's linux-next
>  * Take the suggestion from Arnaud Patard to add default pdata in
>    imx_add_sdhci_esdhc_imx(), to avoid touching every single board
>    file for the platform_data changes
>  * Add comment for sdhci.c change
>  * Change ESDHC_CD(WP)_SIGNAL to ESDHC_CD(WP)_CONTROLLER for a more
>    descriptive name
>  * Add missing NONE case handling in esdhc_pltfm_get_ro
>  * Improve a couple comment wording per suggestion from Wolfram Sang
> 
> Shawn Guo (4):
>       mmc: sdhci: fix interrupt storm from card detection
>       mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared
>       mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP
>       mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5
> 
>  arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
>  arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
>  arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
>  arch/arm/mach-imx/mach-pcm043.c                    |    2 +
>  arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
>  arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
>  .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
>  arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
>  drivers/mmc/host/sdhci-esdhc-imx.c                 |  140 ++++++++++++--------
>  drivers/mmc/host/sdhci.c                           |   29 ++++-
>  10 files changed, 165 insertions(+), 69 deletions(-)

Is the series ready for being merged?  Or is there anything needs
to be done before you do so?

-- 
Regards,
Shawn

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

* [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
@ 2011-06-27  1:38   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-27  1:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Chris,

On Tue, Jun 21, 2011 at 10:41:47PM +0800, Shawn Guo wrote:
> The card-present polling for sdhci based driver is very expensive
> in terms of the impact to system performance.  We observe a few
> system performance issues from Freescale and Linaro on mx5 platforms,
> which have been proved card polling related.
> 
> The patch set extends the current sdhci-esdhc-imx card_detect and
> write_protect support to cover mx5 platforms, and solves above
> performance issues.
> 
> Changes since v3:
>  * Address comment from Philip Rakity on sdhci_set_card_detection
>  * Change a couple of dev_warn to dev_err in sdhci-esdhc-imx.c per
>    Arnaud Patard's comment
>  * Add Arnaud Patard's Test-by
>  * Add missing Acked-by, Cc stable on patch #2
> 
> Changes since v2:
>  * Fix the issue reported by Arnaud Patard:
>    http://article.gmane.org/gmane.linux.ports.arm.kernel/120790
> 
> Changes since v1:
>  * Rebase on today's linux-next
>  * Take the suggestion from Arnaud Patard to add default pdata in
>    imx_add_sdhci_esdhc_imx(), to avoid touching every single board
>    file for the platform_data changes
>  * Add comment for sdhci.c change
>  * Change ESDHC_CD(WP)_SIGNAL to ESDHC_CD(WP)_CONTROLLER for a more
>    descriptive name
>  * Add missing NONE case handling in esdhc_pltfm_get_ro
>  * Improve a couple comment wording per suggestion from Wolfram Sang
> 
> Shawn Guo (4):
>       mmc: sdhci: fix interrupt storm from card detection
>       mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared
>       mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP
>       mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5
> 
>  arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
>  arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
>  arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
>  arch/arm/mach-imx/mach-pcm043.c                    |    2 +
>  arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
>  arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
>  .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
>  arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
>  drivers/mmc/host/sdhci-esdhc-imx.c                 |  140 ++++++++++++--------
>  drivers/mmc/host/sdhci.c                           |   29 ++++-
>  10 files changed, 165 insertions(+), 69 deletions(-)

Is the series ready for being merged?  Or is there anything needs
to be done before you do so?

-- 
Regards,
Shawn

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

* Re: [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
  2011-06-27  1:38   ` Shawn Guo
@ 2011-06-27  3:47     ` Chris Ball
  -1 siblings, 0 replies; 24+ messages in thread
From: Chris Ball @ 2011-06-27  3:47 UTC (permalink / raw)
  To: Shawn Guo
  Cc: patches, linux-mmc, Wolfram Sang, Arnaud Patard, Eric Benard,
	Philip Rakity, linux-arm-kernel

Hi Shawn,

On Sun, Jun 26 2011, Shawn Guo wrote: 
>>  arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
>>  arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
>>  arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
>>  arch/arm/mach-imx/mach-pcm043.c                    |    2 +
>>  arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
>>  arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
>>  .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
>>  arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
>>  drivers/mmc/host/sdhci-esdhc-imx.c                 |  140 ++++++++++++--------
>>  drivers/mmc/host/sdhci.c                           |   29 ++++-
>>  10 files changed, 165 insertions(+), 69 deletions(-)
>
> Is the series ready for being merged?  Or is there anything needs
> to be done before you do so?

I'll need to rebase mmc-next onto linux-next before I can merge it,
because the mach-imx/ board files you're modifying do not exist in
Linus' tree.  (I don't mind doing that, but it might be easier if
you had the ARM patches go in via a different tree instead.)

Thanks,

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

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

* [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
@ 2011-06-27  3:47     ` Chris Ball
  0 siblings, 0 replies; 24+ messages in thread
From: Chris Ball @ 2011-06-27  3:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Shawn,

On Sun, Jun 26 2011, Shawn Guo wrote: 
>>  arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
>>  arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
>>  arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
>>  arch/arm/mach-imx/mach-pcm043.c                    |    2 +
>>  arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
>>  arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
>>  .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
>>  arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
>>  drivers/mmc/host/sdhci-esdhc-imx.c                 |  140 ++++++++++++--------
>>  drivers/mmc/host/sdhci.c                           |   29 ++++-
>>  10 files changed, 165 insertions(+), 69 deletions(-)
>
> Is the series ready for being merged?  Or is there anything needs
> to be done before you do so?

I'll need to rebase mmc-next onto linux-next before I can merge it,
because the mach-imx/ board files you're modifying do not exist in
Linus' tree.  (I don't mind doing that, but it might be easier if
you had the ARM patches go in via a different tree instead.)

Thanks,

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

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

* Re: [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
  2011-06-27  3:47     ` Chris Ball
@ 2011-06-27  4:23       ` Shawn Guo
  -1 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-27  4:23 UTC (permalink / raw)
  To: Chris Ball
  Cc: patches, Sascha Hauer, linux-mmc, Wolfram Sang, linux-arm-kernel,
	Eric Benard, Philip Rakity, Arnaud Patard

On Sun, Jun 26, 2011 at 11:47:57PM -0400, Chris Ball wrote:
> Hi Shawn,
> 
> On Sun, Jun 26 2011, Shawn Guo wrote: 
> >>  arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
> >>  arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
> >>  arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
> >>  arch/arm/mach-imx/mach-pcm043.c                    |    2 +
> >>  arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
> >>  arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
> >>  .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
> >>  arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
> >>  drivers/mmc/host/sdhci-esdhc-imx.c                 |  140 ++++++++++++--------
> >>  drivers/mmc/host/sdhci.c                           |   29 ++++-
> >>  10 files changed, 165 insertions(+), 69 deletions(-)
> >
> > Is the series ready for being merged?  Or is there anything needs
> > to be done before you do so?
> 
> I'll need to rebase mmc-next onto linux-next before I can merge it,
> because the mach-imx/ board files you're modifying do not exist in
> Linus' tree.  (I don't mind doing that, but it might be easier if
> you had the ARM patches go in via a different tree instead.)
> 
I can ask Sascha to pick up patch #4 with your ack.  But the problem
is patch #4 has to work with #1 applied first, otherwise the CD
interrupt storm will freeze the system.

-- 
Regards,
Shawn

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

* [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
@ 2011-06-27  4:23       ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-27  4:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Jun 26, 2011 at 11:47:57PM -0400, Chris Ball wrote:
> Hi Shawn,
> 
> On Sun, Jun 26 2011, Shawn Guo wrote: 
> >>  arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    3 +-
> >>  arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    3 +-
> >>  arch/arm/mach-imx/mach-mx25_3ds.c                  |    2 +
> >>  arch/arm/mach-imx/mach-pcm043.c                    |    2 +
> >>  arch/arm/mach-mx5/board-mx51_babbage.c             |   14 +-
> >>  arch/arm/mach-mx5/board-mx53_loco.c                |    4 +
> >>  .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |   12 ++
> >>  arch/arm/plat-mxc/include/mach/esdhc.h             |   25 +++-
> >>  drivers/mmc/host/sdhci-esdhc-imx.c                 |  140 ++++++++++++--------
> >>  drivers/mmc/host/sdhci.c                           |   29 ++++-
> >>  10 files changed, 165 insertions(+), 69 deletions(-)
> >
> > Is the series ready for being merged?  Or is there anything needs
> > to be done before you do so?
> 
> I'll need to rebase mmc-next onto linux-next before I can merge it,
> because the mach-imx/ board files you're modifying do not exist in
> Linus' tree.  (I don't mind doing that, but it might be easier if
> you had the ARM patches go in via a different tree instead.)
> 
I can ask Sascha to pick up patch #4 with your ack.  But the problem
is patch #4 has to work with #1 applied first, otherwise the CD
interrupt storm will freeze the system.

-- 
Regards,
Shawn

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

* Re: [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
  2011-06-27  4:23       ` Shawn Guo
@ 2011-07-01 23:06         ` Chris Ball
  -1 siblings, 0 replies; 24+ messages in thread
From: Chris Ball @ 2011-07-01 23:06 UTC (permalink / raw)
  To: Shawn Guo
  Cc: patches, Sascha Hauer, linux-mmc, Wolfram Sang, linux-arm-kernel,
	Eric Benard, Philip Rakity, Arnaud Patard

Hi,

On Mon, Jun 27 2011, Shawn Guo wrote:
>> I'll need to rebase mmc-next onto linux-next before I can merge it,
>> because the mach-imx/ board files you're modifying do not exist in
>> Linus' tree.  (I don't mind doing that, but it might be easier if
>> you had the ARM patches go in via a different tree instead.)
> 
> I can ask Sascha to pick up patch #4 with your ack.  But the problem
> is patch #4 has to work with #1 applied first, otherwise the CD
> interrupt storm will freeze the system.

Let's do that, please.  I've merged #1-#3 to mmc-next, and for #4:

Acked-by: Chris Ball <cjb@laptop.org>

(Sascha, please note that you'll have to send #4 to Linus after I send
the MMC pull request, as Shawn explains above.)

Thanks,

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

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

* [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5
@ 2011-07-01 23:06         ` Chris Ball
  0 siblings, 0 replies; 24+ messages in thread
From: Chris Ball @ 2011-07-01 23:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Mon, Jun 27 2011, Shawn Guo wrote:
>> I'll need to rebase mmc-next onto linux-next before I can merge it,
>> because the mach-imx/ board files you're modifying do not exist in
>> Linus' tree.  (I don't mind doing that, but it might be easier if
>> you had the ARM patches go in via a different tree instead.)
> 
> I can ask Sascha to pick up patch #4 with your ack.  But the problem
> is patch #4 has to work with #1 applied first, otherwise the CD
> interrupt storm will freeze the system.

Let's do that, please.  I've merged #1-#3 to mmc-next, and for #4:

Acked-by: Chris Ball <cjb@laptop.org>

(Sascha, please note that you'll have to send #4 to Linus after I send
the MMC pull request, as Shawn explains above.)

Thanks,

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

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

end of thread, other threads:[~2011-07-01 23:07 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-21 14:41 [PATCH v4 0/4] Extend sdhci-esdhc-imx card_detect and write_protect support for mx5 Shawn Guo
2011-06-21 14:41 ` Shawn Guo
2011-06-21 14:41 ` [PATCH v4 1/4] mmc: sdhci: fix interrupt storm from card detection Shawn Guo
2011-06-21 14:41   ` Shawn Guo
2011-06-21 16:05   ` Philip Rakity
2011-06-21 16:05     ` Philip Rakity
2011-06-22  4:40     ` Shawn Guo
2011-06-22  4:40       ` Shawn Guo
2011-06-22  4:41       ` Philip Rakity
2011-06-22  4:41         ` Philip Rakity
2011-06-21 14:41 ` [PATCH v4 2/4] mmc: sdhci-esdhc-imx: SDHCI_CARD_PRESENT does not get cleared Shawn Guo
2011-06-21 14:41   ` Shawn Guo
2011-06-21 14:41 ` [PATCH v4 3/4] mmc: sdhci-esdhc-imx: remove "WP" from flag ESDHC_FLAG_GPIO_FOR_CD_WP Shawn Guo
2011-06-21 14:41   ` Shawn Guo
2011-06-21 14:41 ` [PATCH v4 4/4] mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5 Shawn Guo
2011-06-21 14:41   ` Shawn Guo
2011-06-27  1:38 ` [PATCH v4 0/4] Extend sdhci-esdhc-imx " Shawn Guo
2011-06-27  1:38   ` Shawn Guo
2011-06-27  3:47   ` Chris Ball
2011-06-27  3:47     ` Chris Ball
2011-06-27  4:23     ` Shawn Guo
2011-06-27  4:23       ` Shawn Guo
2011-07-01 23:06       ` Chris Ball
2011-07-01 23:06         ` Chris Ball

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.