Commit 5ba85d95 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Chris Ball

mmc: sh_mmcif: fix late delayed work initialisation

If the driver is loaded with a card in the slot, mmc_add_host() will
schedule an immediate card-detection work, which will start IO and wait
for command completion. Usually the kernel first returns to the sh_mmcif
probe function, lets it finish and only then schedules the rescan work.
But sometimes, expecially under heavy system load, the work will be
scheduled immediately before returning to the probe method. In this case
it is important for the driver to be fully prepared for IO. For sh_mmcif
this means, that also the timeout work has to be initialised before
calling mmc_add_host(). It is also better to prepare interrupts
beforehand. Besides, since mmc_add_host() does card-detection itself,
there is no need to do it again immediately afterwards.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent e3de2be7
...@@ -1327,7 +1327,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) ...@@ -1327,7 +1327,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto clean_up2; goto clean_up2;
mmc_add_host(mmc); INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
...@@ -1338,22 +1338,24 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) ...@@ -1338,22 +1338,24 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
} }
ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
if (ret) { if (ret) {
free_irq(irq[0], host);
dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
goto clean_up3; goto clean_up4;
} }
INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); ret = mmc_add_host(mmc);
if (ret < 0)
mmc_detect_change(host->mmc, 0); goto clean_up5;
dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
dev_dbg(&pdev->dev, "chip ver H'%04x\n", dev_dbg(&pdev->dev, "chip ver H'%04x\n",
sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff); sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
return ret; return ret;
clean_up5:
free_irq(irq[1], host);
clean_up4:
free_irq(irq[0], host);
clean_up3: clean_up3:
mmc_remove_host(mmc);
pm_runtime_suspend(&pdev->dev); pm_runtime_suspend(&pdev->dev);
clean_up2: clean_up2:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment