From patchwork Tue Jan 4 05:26:53 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philip Rakity X-Patchwork-Id: 449521 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p045YdtO000567 for ; Tue, 4 Jan 2011 05:34:39 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750926Ab1ADFej (ORCPT ); Tue, 4 Jan 2011 00:34:39 -0500 Received: from na3sys009aog110.obsmtp.com ([74.125.149.203]:57953 "HELO na3sys009aog110.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1750897Ab1ADFei convert rfc822-to-8bit (ORCPT ); Tue, 4 Jan 2011 00:34:38 -0500 Received: from source ([65.219.4.129]) (using TLSv1) by na3sys009aob110.postini.com ([74.125.148.12]) with SMTP ID DSNKTSKxbfxNLS8rE5ZmROdCXhe6a3zpzJQr@postini.com; Mon, 03 Jan 2011 21:34:38 PST Received: from SC-vEXCH3.marvell.com ([10.93.76.133]) by SC-OWA01.marvell.com ([10.93.76.21]) with mapi; Mon, 3 Jan 2011 21:26:54 -0800 From: Philip Rakity To: Zhangfei Gao CC: Mark Brown , "linux-mmc@vger.kernel.org" Date: Mon, 3 Jan 2011 21:26:53 -0800 Subject: [RFC] sdhci: allow mdelay to reschedule by not holding spin_lock Thread-Topic: [RFC] sdhci: allow mdelay to reschedule by not holding spin_lock Thread-Index: Acurz//M3GgEbkk4RpyTxHOh0tz6Mg== Message-ID: <1CE9AD0D-5B2D-4E27-96B7-F18C3A3BAA8B@marvell.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Tue, 04 Jan 2011 05:34:40 +0000 (UTC) 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); --