summaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/atmel-mci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/atmel-mci.c')
-rw-r--r--drivers/mmc/host/atmel-mci.c82
1 files changed, 15 insertions, 67 deletions
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 69e438ee043e..2cbb4516d353 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -255,7 +255,6 @@ struct atmel_mci_slot {
#define ATMCI_CARD_PRESENT 0
#define ATMCI_CARD_NEED_INIT 1
#define ATMCI_SHUTDOWN 2
-#define ATMCI_SUSPENDED 3
int detect_pin;
int wp_pin;
@@ -589,6 +588,13 @@ static void atmci_timeout_timer(unsigned long data)
if (host->mrq->cmd->data) {
host->mrq->cmd->data->error = -ETIMEDOUT;
host->data = NULL;
+ /*
+ * With some SDIO modules, sometimes DMA transfer hangs. If
+ * stop_transfer() is not called then the DMA request is not
+ * removed, following ones are queued and never computed.
+ */
+ if (host->state == STATE_DATA_XFER)
+ host->stop_transfer(host);
} else {
host->mrq->cmd->error = -ETIMEDOUT;
host->cmd = NULL;
@@ -1803,12 +1809,14 @@ static void atmci_tasklet_func(unsigned long priv)
if (unlikely(status)) {
host->stop_transfer(host);
host->data = NULL;
- if (status & ATMCI_DTOE) {
- data->error = -ETIMEDOUT;
- } else if (status & ATMCI_DCRCE) {
- data->error = -EILSEQ;
- } else {
- data->error = -EIO;
+ if (data) {
+ if (status & ATMCI_DTOE) {
+ data->error = -ETIMEDOUT;
+ } else if (status & ATMCI_DCRCE) {
+ data->error = -EILSEQ;
+ } else {
+ data->error = -EIO;
+ }
}
}
@@ -2520,70 +2528,10 @@ static int __exit atmci_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
-static int atmci_suspend(struct device *dev)
-{
- struct atmel_mci *host = dev_get_drvdata(dev);
- int i;
-
- for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
- struct atmel_mci_slot *slot = host->slot[i];
- int ret;
-
- if (!slot)
- continue;
- ret = mmc_suspend_host(slot->mmc);
- if (ret < 0) {
- while (--i >= 0) {
- slot = host->slot[i];
- if (slot
- && test_bit(ATMCI_SUSPENDED, &slot->flags)) {
- mmc_resume_host(host->slot[i]->mmc);
- clear_bit(ATMCI_SUSPENDED, &slot->flags);
- }
- }
- return ret;
- } else {
- set_bit(ATMCI_SUSPENDED, &slot->flags);
- }
- }
-
- return 0;
-}
-
-static int atmci_resume(struct device *dev)
-{
- struct atmel_mci *host = dev_get_drvdata(dev);
- int i;
- int ret = 0;
-
- for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
- struct atmel_mci_slot *slot = host->slot[i];
- int err;
-
- slot = host->slot[i];
- if (!slot)
- continue;
- if (!test_bit(ATMCI_SUSPENDED, &slot->flags))
- continue;
- err = mmc_resume_host(slot->mmc);
- if (err < 0)
- ret = err;
- else
- clear_bit(ATMCI_SUSPENDED, &slot->flags);
- }
-
- return ret;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume);
-
static struct platform_driver atmci_driver = {
.remove = __exit_p(atmci_remove),
.driver = {
.name = "atmel_mci",
- .pm = &atmci_pm,
.of_match_table = of_match_ptr(atmci_dt_ids),
},
};