diff mbox

mmc: sdhci: fix possible scheduling while atomic

Message ID EEBFEDF8-5DC8-4DFC-B98B-F434DC323B9E@nvidia.com (mailing list archive)
State New, archived
Headers show

Commit Message

Philip Rakity Jan. 20, 2014, 3:03 p.m. UTC
I have no way to test this problem but I was thinking along the lines of


regards,

Philip

On Jan 20, 2014, at 9:51 AM, Philip Rakity <prakity@nvidia.com> wrote:

> 
> Chris,
> 
> The suggested fix can lock out interrupts for up to 150ms.  There needs to be another way.
> So, I would strongly recommend we find another solution.
> 
> Philip
> 
> On Jan 17, 2014, at 7:57 PM, Andrew Bresticker <abrestic@chromium.org> wrote:
> 
>> sdhci_execute_tuning() takes host->lock without disabling interrupts.
>> Use spin_lock_irq{save,restore} instead so that we avoid taking an
>> interrupt and scheduling while holding host->lock.
>> 
>> Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
>> ---
>> drivers/mmc/host/sdhci.c | 13 +++++++------
>> 1 file changed, 7 insertions(+), 6 deletions(-)
>> 
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index ec3eb30..84c80e7 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1857,12 +1857,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>> 	unsigned long timeout;
>> 	int err = 0;
>> 	bool requires_tuning_nonuhs = false;
>> +	unsigned long flags;
>> 
>> 	host = mmc_priv(mmc);
>> 
>> 	sdhci_runtime_pm_get(host);
>> 	disable_irq(host->irq);
>> -	spin_lock(&host->lock);
>> +	spin_lock_irqsave(&host->lock, flags);
> 
> 
> The disable_irq() call stops the controller from doing interrupts.  
> Please explain what problem you are seeing
> 
>> 
>> 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
>> 
>> @@ -1882,14 +1883,14 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>> 	    requires_tuning_nonuhs)
>> 		ctrl |= SDHCI_CTRL_EXEC_TUNING;
>> 	else {
>> -		spin_unlock(&host->lock);
>> +		spin_unlock_irqrestore(&host->lock, flags);
>> 		enable_irq(host->irq);
>> 		sdhci_runtime_pm_put(host);
>> 		return 0;
>> 	}
>> 
>> 	if (host->ops->platform_execute_tuning) {
>> -		spin_unlock(&host->lock);
>> +		spin_unlock_irqrestore(&host->lock, flags);
>> 		enable_irq(host->irq);
>> 		err = host->ops->platform_execute_tuning(host, opcode);
>> 		sdhci_runtime_pm_put(host);
>> @@ -1963,7 +1964,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>> 		host->cmd = NULL;
>> 		host->mrq = NULL;
>> 
>> -		spin_unlock(&host->lock);
>> +		spin_unlock_irqrestore(&host->lock, flags);
>> 		enable_irq(host->irq);
>> 
>> 		/* Wait for Buffer Read Ready interrupt */
>> @@ -1971,7 +1972,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>> 					(host->tuning_done == 1),
>> 					msecs_to_jiffies(50));
>> 		disable_irq(host->irq);
>> -		spin_lock(&host->lock);
>> +		spin_lock_irqsave(&host->lock, flags);
>> 
>> 		if (!host->tuning_done) {
>> 			pr_info(DRIVER_NAME ": Timeout waiting for "
>> @@ -2046,7 +2047,7 @@ out:
>> 		err = 0;
>> 
>> 	sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
>> -	spin_unlock(&host->lock);
>> +	spin_unlock_irqrestore(&host->lock, flags);
>> 	enable_irq(host->irq);
>> 	sdhci_runtime_pm_put(host);
>> 
>> -- 
>> 1.8.5.2
>> 
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1862,6 +1862,7 @@  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 
 
        sdhci_runtime_pm_get(host);
        disable_irq(host->irq);
+       sdhci_disable_card_detection(host);
        spin_lock(&host->lock);
 
        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
@@ -1883,6 +1884,7 @@  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 
                ctrl |= SDHCI_CTRL_EXEC_TUNING;
        else {
                spin_unlock(&host->lock);
+               sdhci_enable_card_detection(host);
                enable_irq(host->irq);
                sdhci_runtime_pm_put(host);
                return 0;
@@ -1890,6 +1892,7 @@  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 
 
        if (host->ops->platform_execute_tuning) {
                spin_unlock(&host->lock);
+               sdhci_enable_card_detection(host);
                enable_irq(host->irq);
                err = host->ops->platform_execute_tuning(host, opcode);
                sdhci_runtime_pm_put(host);
@@ -2047,6 +2050,7 @@  out:
 
        sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
        spin_unlock(&host->lock);
+       sdhci_enable_card_detection(host);
        enable_irq(host->irq);
        sdhci_runtime_pm_put(host);