diff mbox

[RFC] sdhci: allow mdelay to reschedule by not holding spin_lock

Message ID 1CE9AD0D-5B2D-4E27-96B7-F18C3A3BAA8B@marvell.com (mailing list archive)
State New, archived
Headers show

Commit Message

Philip Rakity Jan. 4, 2011, 5:26 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index cb48baa..603ea67 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1009,15 +1009,18 @@  static void sdhci_finish_command(struct sdhci_host *host)
 static void sdhci_set_ddr(struct sdhci_host *host, unsigned int ddr)
 {
 	u16 con;
+	unsigned long flags;
 
 	if (ddr == MMC_SDR_MODE)
 		return;
 
+	spin_lock_irqsave(&host->lock, flags);
 	con = sdhci_readw(host, SDHCI_HOST_CONTROL_2);
 	con |= SDCTRL_2_SDH_V18_EN;
 	sdhci_writew(host, con, SDHCI_HOST_CONTROL_2);
 
 	/* Change signaling voltage and wait for it to be stable */
+	spin_unlock_irqrestore(&host->lock, flags);
 	if (host->ops->set_signaling_voltage)
 		host->ops->set_signaling_voltage(host, ddr);
 	else
@@ -1027,10 +1030,12 @@  static void sdhci_set_ddr(struct sdhci_host *host, unsigned int ddr)
 	 * We can fail here but there is no higher level recovery
 	 * since the card is already past the switch to ddr
 	 */
+	spin_lock_irqsave(&host->lock, flags);
 	con = sdhci_readw(host, SDHCI_HOST_CONTROL_2);
 	con &= ~SDCTRL_2_UHS_MODE_MASK;
 	con |= SDCTRL_2_UHS_MODE_SEL_DDR50;
 	sdhci_writew(host, con, SDHCI_HOST_CONTROL_2);
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
@@ -1038,14 +1043,18 @@  static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 	int div;
 	u16 clk;
 	unsigned long timeout;
+	unsigned long flags;
 
 	if (clock == host->clock)
 		return;
 
+	spin_lock_irqsave(&host->lock, flags);
 	if (host->ops->set_clock) {
 		host->ops->set_clock(host, clock);
-		if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK)
+		if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
+			spin_unlock_irqrestore(&host->lock, flags);
 			return;
+		}
 	}
 
 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
@@ -1086,10 +1095,14 @@  static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 			printk(KERN_ERR "%s: Internal clock never "
 				"stabilised.\n", mmc_hostname(host->mmc));
 			sdhci_dumpregs(host);
+			spin_unlock_irqrestore(&host->lock, flags);
 			return;
 		}
 		timeout--;
+		spin_unlock_irqrestore(&host->lock, flags);
 		mdelay(1);
+		spin_lock_irqsave(&host->lock, flags);
+
 	}
 
 	clk |= SDHCI_CLOCK_CARD_EN;
@@ -1097,11 +1110,13 @@  static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 
 out:
 	host->clock = clock;
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 {
 	u8 pwr = 0;
+	unsigned long flags;
 
 	if (power != (unsigned short)-1) {
 		switch (1 << power) {
@@ -1131,6 +1146,8 @@  static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 		return;
 	}
 
+	spin_lock_irqsave(&host->lock, flags);
+
 	/*
 	 * Spec says that we should clear the power reg before setting
 	 * a new value. Some controllers don't seem to like this though.
@@ -1153,8 +1170,12 @@  static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 	 * Some controllers need an extra 10ms delay of 10ms before they
 	 * can apply clock after applying power
 	 */
-	if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
+	if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) {
+		spin_unlock_irqrestore(&host->lock, flags);
 		mdelay(10);
+		spin_lock_irqsave(&host->lock, flags);
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 /*****************************************************************************\
@@ -1226,6 +1247,7 @@  static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		sdhci_reinit(host);
 	}
 
+	spin_unlock_irqrestore(&host->lock, flags);
 	sdhci_set_clock(host, ios->clock);
 	sdhci_set_ddr(host, ios->ddr);
 
@@ -1234,6 +1256,8 @@  static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	else
 		sdhci_set_power(host, ios->vdd);
 
+	spin_lock_irqsave(&host->lock, flags);
+
 	if (host->ops->platform_send_init_74_clocks)
 		host->ops->platform_send_init_74_clocks(host, ios->power_mode);
 --