mmc: sdhci: Setting the host->mrq to NULL before executing tuning
authorChuansheng Liu <chuansheng.liu@intel.com>
Tue, 5 Nov 2013 06:52:45 +0000 (14:52 +0800)
committerChris Ball <chris@printf.net>
Mon, 13 Jan 2014 17:48:13 +0000 (12:48 -0500)
In function sdhci_request(), it is possible to do the tuning execution
like below:

sdhci_request() {
spin_lock_irqsave(&host->lock, flags);
host->mrq = mrq;
...
spin_unlock_irqrestore(&host->lock, flags);

<=== Here it is possible one pending finish_tasklet get running
     and it will operate the original mrq, and notified the mrq
     is done, and causes memory corruption.

sdhci_execute_tuning(mmc, tuning_opcode);
spin_lock_irqsave(&host->lock, flags);
host->mrq = mrq;
...
}

In the above race place, the original mrq should not be finished wrongly,
so here before unlock the spinlock, we need to set the host->mrq to NULL
to avoid this case.

Signed-off-by: Liu, Chuansheng <chuansheng.liu@intel.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/host/sdhci.c

index 6840322c12a0cbbd84edd7219f19dfb82800e7ca..cc00bed3e20091a9be56f8ee238b25e40f38fe11 100644 (file)
@@ -1396,6 +1396,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
                                        mmc->card->type == MMC_TYPE_MMC ?
                                        MMC_SEND_TUNING_BLOCK_HS200 :
                                        MMC_SEND_TUNING_BLOCK;
+
+                               /* Here we need to set the host->mrq to NULL,
+                                * in case the pending finish_tasklet
+                                * finishes it incorrectly.
+                                */
+                               host->mrq = NULL;
+
                                spin_unlock_irqrestore(&host->lock, flags);
                                sdhci_execute_tuning(mmc, tuning_opcode);
                                spin_lock_irqsave(&host->lock, flags);