aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2007-05-31 22:25:11 +0200
committerPierre Ossman <drzeus@drzeus.cx>2007-06-07 09:25:58 +0200
commit3373c0ae6a51085b10a95fd9d2214a9995ef7563 (patch)
tree0a25f54463f21b90d9c06b9bb4bbecb21880e18c
parent71651297a448289353b2493c6c3c183f9be7be7c (diff)
downloadkernel_samsung_smdk4412-3373c0ae6a51085b10a95fd9d2214a9995ef7563.zip
kernel_samsung_smdk4412-3373c0ae6a51085b10a95fd9d2214a9995ef7563.tar.gz
kernel_samsung_smdk4412-3373c0ae6a51085b10a95fd9d2214a9995ef7563.tar.bz2
mmc: don't call switch on old cards
Make sure we don't call the switch function on cards too old to support it. They should just ignore it, but some have been reported to lock up instead. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
-rw-r--r--drivers/mmc/core/sd.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 5afac20..41bfb5d 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -15,6 +15,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
#include "core.h"
#include "sysfs.h"
@@ -192,6 +193,16 @@ static int mmc_read_switch(struct mmc_card *card)
int err;
u8 *status;
+ if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+ return MMC_ERR_NONE;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH)) {
+ printk(KERN_WARNING "%s: card lacks mandatory switch "
+ "function, performance might suffer.\n",
+ mmc_hostname(card->host));
+ return MMC_ERR_NONE;
+ }
+
err = MMC_ERR_FAILED;
status = kmalloc(64, GFP_KERNEL);
@@ -204,10 +215,9 @@ static int mmc_read_switch(struct mmc_card *card)
err = mmc_sd_switch(card, 0, 0, 1, status);
if (err != MMC_ERR_NONE) {
- /*
- * Card not supporting high-speed will ignore the
- * command.
- */
+ printk(KERN_WARNING "%s: problem reading switch "
+ "capabilities, performance might suffer.\n",
+ mmc_hostname(card->host));
err = MMC_ERR_NONE;
goto out;
}
@@ -229,6 +239,12 @@ static int mmc_switch_hs(struct mmc_card *card)
int err;
u8 *status;
+ if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+ return MMC_ERR_NONE;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH))
+ return MMC_ERR_NONE;
+
if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
return MMC_ERR_NONE;