Skip to contentSkip to conversation

Fix some corner cases in bus width setting

PATCH New Andrew Gabbasov 3 participants 6 messages Dec 25, 2014 – Jan 19, 2015 MMC, SD and SDIO

lore
Share & tools
lore
#0 lore raw

cover Fix some corner cases in bus width setting

Among other fixes, the commit 786e8f818c25265d12d5d06e257fe2b1ba516134 "mmc: Fix handling of bus widths and DDR card capabilities" changed bus width setting code so that if the attempt to switch to last 1-bit width item fails, the whole initialization fails. This seems to be more correct than earlier ignoring of such error, but this makes sense if the bus width was actually switched. But if all the switching commands fail (e.g. because the card does not support bus width switching at all), then we could just skip last switching to default bus width and treat it as a success.

Also, MMC cards of earlier versions than MMC standard version 4.0 do not support wider bus widths, so it doesn't make sense to even try to switch the bus width for such cards.

Andrew Gabbasov (2):
mmc: Avoid redundant switching to 1-bit bus width for MMC cards
mmc: Skip changing bus width for MMC cards earlier than version 4.0

 drivers/mmc/mmc.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)
Signature · 1 line
2.1.0
#1 lore raw

PATCH 1/2 mmc: Avoid redundant switching to 1-bit bus width for MMC cards

If all the commands switching an MMC card to 4- or 8-bit bus width fail, and the bus width for the controller and the driver is still set to default 1 bit, there is no need to send one more command to switch the card to 1-bit bus width. Also, if the card or host controller do not support wider bus widths, there is no need to send a switch command at all.

However, if one of switch commands succeeds, but the subsequent ext_csd fields comparison fails, the card should be switched to some other bus width (next in the list for the loop), or to default 1-bit bus width as a last resort. That's why it would be incorrect to just remove the 1-bit bus width case from the list, it should still be processed in some cases.

---
 drivers/mmc/mmc.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
drivers/mmc/mmc.c +12 -0
index 1eb9c27..c0cf318 100644
@@ -1139,6 +1139,18 @@ static int mmc_startup(struct mmc *mmc)
 			unsigned int caps = ext_to_hostcaps[extw];
 
 			/*
+			 * If the bus width is still not changed,
+			 * don't try to set the default again.
+			 * Otherwise, recover from switch attempts
+			 * by switching to 1-bit bus width.
+			 */
+			if ((extw == EXT_CSD_BUS_WIDTH_1) &&
+			    (mmc->bus_width == 1)) {
+				err = 0;
+				break;
+			}
+
+			/*
 			 * Check to make sure the card and controller support
 			 * these capabilities
 			 */
Signature · 1 line
2.1.0
#2 lore raw

PATCH 1/2 mmc: Avoid redundant switching to 1-bit bus width for MMC cards

Hi Andrew,

Quoted 46 lines · Andrew Gabbasov

If all the commands switching an MMC card to 4- or 8-bit bus width fail, and the bus width for the controller and the driver is still set to default 1 bit, there is no need to send one more command to switch the card to 1-bit bus width. Also, if the card or host controller do not support wider bus widths, there is no need to send a switch command at all.

However, if one of switch commands succeeds, but the subsequent ext_csd fields comparison fails, the card should be switched to some other bus width (next in the list for the loop), or to default 1-bit bus width as a last resort. That's why it would be incorrect to just remove the 1-bit bus width case from the list, it should still be processed in some cases.

---
drivers/mmc/mmc.c | 12 ++++++++++++

1 file changed, 12 insertions(+)
drivers/mmc/mmc.c +12 -0
index 1eb9c27..c0cf318 100644
@@ -1139,6 +1139,18 @@ static int mmc_startup(struct mmc *mmc)
 			unsigned int caps = ext_to_hostcaps[extw];
 
 			/*
+			 * If the bus width is still not changed,
+			 * don't try to set the default again.
+			 * Otherwise, recover from switch attempts
+			 * by switching to 1-bit bus width.
+			 */
+			if ((extw == EXT_CSD_BUS_WIDTH_1) &&
+			    (mmc->bus_width == 1)) {
+				err = 0;
+				break;
+			}
+
+			/*
 			 * Check to make sure the card and controller support
 			 * these capabilities
 			 */
Signature · 1 line
2.1.0

Patch looks fine; taken the liberty to remove the superfluous parentheses at the if statement.

Regards

? Pantelis

#3 lore raw

PATCH 2/2 mmc: Skip changing bus width for MMC cards earlier than version 4.0

In reply to Andrew Gabbasov

Wider bus widths (larger than default 1 bit) appeared in MMC standard version 4.0. So, for MMC cards of any earlier version trying to change the bus width (including ext_csd comparison) does not make any sense. It may work incorrectly and at least cause unnecessary timeouts. So, just skip the entire bus width related activity for earlier versions.

---
 drivers/mmc/mmc.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/mmc/mmc.c +5 -2
index c0cf318..14d6a13 100644
@@ -486,7 +486,7 @@ static int mmc_change_freq(struct mmc *mmc)
 	char cardtype;
 	int err;
 
-	mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
+	mmc->card_caps = 0;
 
 	if (mmc_host_is_spi(mmc))
 		return 0;
@@ -495,6 +495,8 @@ static int mmc_change_freq(struct mmc *mmc)
 	if (mmc->version < MMC_VERSION_4)
 		return 0;
 
+	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
+
 	err = mmc_send_ext_csd(mmc, ext_csd);
 
 	if (err)
@@ -1107,7 +1109,8 @@ static int mmc_startup(struct mmc *mmc)
 			mmc->tran_speed = 50000000;
 		else
 			mmc->tran_speed = 25000000;
-	} else {
+	} else if (mmc->version >= MMC_VERSION_4) {
+		/* Only version 4 of MMC supports wider bus widths */
 		int idx;
 
 		/* An array of possible bus widths in order of preference */
Signature · 1 line
2.1.0
#4 lore raw

PATCH 2/2 mmc: Skip changing bus width for MMC cards earlier than version 4.0

Hi Pantelis,

Quoted 8 lines · Andrew Gabbasov

Wider bus widths (larger than default 1 bit) appeared in MMC standard version 4.0. So, for MMC cards of any earlier version trying to change the bus width (including ext_csd comparison) does not make any sense. It may work incorrectly and at least cause unnecessary timeouts. So, just skip the entire bus width related activity for earlier versions.

This change fixes regression introduced in
https://patchwork.ozlabs.org/patch/416442/ for MMC cards.

Please consider applying if you don't have any objections.

Regards,
Alexey

#5 lore raw

PATCH 2/2 mmc: Skip changing bus width for MMC cards earlier than version 4.0

In reply to Andrew Gabbasov

Hi Andrew,

Quoted 48 lines · Andrew Gabbasov

Wider bus widths (larger than default 1 bit) appeared in MMC standard version 4.0. So, for MMC cards of any earlier version trying to change the bus width (including ext_csd comparison) does not make any sense. It may work incorrectly and at least cause unnecessary timeouts. So, just skip the entire bus width related activity for earlier versions.

---
drivers/mmc/mmc.c | 7 +++++--

1 file changed, 5 insertions(+), 2 deletions(-)
drivers/mmc/mmc.c +5 -2
index c0cf318..14d6a13 100644
@@ -486,7 +486,7 @@ static int mmc_change_freq(struct mmc *mmc)
 	char cardtype;
 	int err;
 
-	mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
+	mmc->card_caps = 0;
 
 	if (mmc_host_is_spi(mmc))
 		return 0;
@@ -495,6 +495,8 @@ static int mmc_change_freq(struct mmc *mmc)
 	if (mmc->version < MMC_VERSION_4)
 		return 0;
 
+	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
+
 	err = mmc_send_ext_csd(mmc, ext_csd);
 
 	if (err)
@@ -1107,7 +1109,8 @@ static int mmc_startup(struct mmc *mmc)
 			mmc->tran_speed = 50000000;
 		else
 			mmc->tran_speed = 25000000;
-	} else {
+	} else if (mmc->version >= MMC_VERSION_4) {
+		/* Only version 4 of MMC supports wider bus widths */
 		int idx;
 
 		/* An array of possible bus widths in order of preference */
Signature · 1 line
2.1.0

Applied, thanks.

? Pantelis