==========
Delete spin_lock as not needed. disable/enable irq
should be enough to interlock bewteen the isr and
the main thread.
V1
===
holding the spin_lock with all interrupts disabled
is not good form when doing mdelay.
set_ios calls routines that need to delay for power to
stabalize or for chip issues when quirks are defined.
disable only our interupt and spin_lock on the chip
instead of spin_lock with all interrupts disabled.
use mmc_delay (if possible) rather then mdelay
to avoid active waits. sdhci_reset not changed.
still uses mdelay as we do not know if interrupts
have been disabled so we play "safe"
Signed-off-by: Philip Rakity <prakity@marvell.com>
---
drivers/mmc/core/core.h | 12 ------------
drivers/mmc/host/sdhci.c | 24 +++++++++++++++---------
include/linux/mmc/host.h | 11 +++++++++++
3 files changed, 26 insertions(+), 21 deletions(-)
@@ -11,8 +11,6 @@
#ifndef _MMC_CORE_CORE_H
#define _MMC_CORE_CORE_H
-#include <linux/delay.h>
-
#define MMC_CMD_RETRIES 3
struct mmc_bus_ops {
@@ -43,16 +41,6 @@ void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width,
u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
void mmc_set_timing(struct mmc_host *host, unsigned int timing);
-static inline void mmc_delay(unsigned int ms)
-{
- if (ms < 1000 / HZ) {
- cond_resched();
- mdelay(ms);
- } else {
- msleep(ms);
- }
-}
-
void mmc_rescan(struct work_struct *work);
void mmc_start_host(struct mmc_host *host);
void mmc_stop_host(struct mmc_host *host);
@@ -1043,7 +1043,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
return;
}
timeout--;
- mdelay(1);
+ mmc_delay(1);
}
clk |= SDHCI_CLOCK_CARD_EN;
@@ -1108,7 +1108,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
* can apply clock after applying power
*/
if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
- mdelay(10);
+ mmc_delay(10);
}
/*****************************************************************************\
@@ -1161,22 +1161,21 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct sdhci_host *host;
- unsigned long flags;
unsigned int lastclock;
+ unsigned long flags;
u8 ctrl;
host = mmc_priv(mmc);
- spin_lock_irqsave(&host->lock, flags);
-
if (host->flags & SDHCI_DEVICE_DEAD)
- goto out;
+ return;
/*
* get/put runtime_pm usage counter at ios->clock transitions
* We need to do it before any other chip access, as sdhci could
* be power gated
*/
+ spin_lock_irqsave(&host->lock, flags);
lastclock = host->iosclock;
host->iosclock = ios->clock;
if (lastclock == 0 && ios->clock != 0) {
@@ -1189,9 +1188,17 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
pm_runtime_put_autosuspend(host->mmc->parent);
spin_lock_irqsave(&host->lock, flags);
}
+ spin_unlock_irqrestore(&host->lock, flags);
+
/* no need to configure the rest.. */
if (host->iosclock == 0)
- goto out;
+ return;
+
+ /* disable local interrupts to lock structures so
+ * that mmc_delay can be scheduled. This cannot happen
+ * if interrupts are globally disabled
+ */
+ disable_irq(host->irq);
/*
* Reset the chip on each power off.
@@ -1255,9 +1262,8 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
-out:
mmiowb();
- spin_unlock_irqrestore(&host->lock, flags);
+ enable_irq(host->irq);
}
static int sdhci_get_ro(struct mmc_host *mmc)
@@ -15,6 +15,7 @@
#include <linux/mmc/core.h>
#include <linux/mmc/pm.h>
+#include <linux/delay.h>
struct mmc_ios {
unsigned int clock; /* clock rate */
@@ -326,5 +327,15 @@ static inline int mmc_card_is_powered_resumed(struct mmc_host *host)
return host->pm_flags & MMC_PM_KEEP_POWER;
}
+static inline void mmc_delay(unsigned int ms)
+{
+ if (ms < 1000 / HZ) {
+ cond_resched();
+ mdelay(ms);
+ } else {
+ msleep(ms);
+ }
+}
+
#endif