mmc: sdhci: Setting the host->mrq to NULL before executing tuning

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>
This commit is contained in:
Chuansheng Liu 2013-11-05 14:52:45 +08:00 committed by Chris Ball
parent 0041113547
commit 63c211803a

View file

@ -1396,6 +1396,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
mmc->card->type == MMC_TYPE_MMC ? mmc->card->type == MMC_TYPE_MMC ?
MMC_SEND_TUNING_BLOCK_HS200 : MMC_SEND_TUNING_BLOCK_HS200 :
MMC_SEND_TUNING_BLOCK; 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); spin_unlock_irqrestore(&host->lock, flags);
sdhci_execute_tuning(mmc, tuning_opcode); sdhci_execute_tuning(mmc, tuning_opcode);
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);