ext Andrew Morton wrote:
On Fri, 5 Feb 2010 01:18:15 +0200 Maxim Levitsky <maximlevitsky@xxxxxxxxx> wrote:
Currently removal of the card leads to del_disk called indirectly by mmc core.
This function expects userspace to be running, which isn't when .resume is called
Fix that by removing the code that did that in mmc_resume_host. It is possible
because card detection logic will kick it later and remove the card.
I don't really understand. The above implies that to trigger this bug,
one needs to physically remove the card during a resume operation. ie:
a human-vs-computer race. Sounds unlikely?
So... exactly what steps does the user need to take to trigger this
bug?
Also make mtd workqueue freezeable, so it won't attempt to add/remove the card
while userspace is frozen.
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 30acd52..879d48d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1257,7 +1257,6 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
if (host->caps & MMC_CAP_DISABLE)
cancel_delayed_work(&host->disable);
cancel_delayed_work(&host->detect);
- mmc_flush_scheduled_work();
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
@@ -1300,15 +1299,11 @@ int mmc_resume_host(struct mmc_host *host)
mmc_select_voltage(host, host->ocr);
BUG_ON(!host->bus_ops->resume);
err = host->bus_ops->resume(host);
+
if (err) {
printk(KERN_WARNING "%s: error %d during resume "
"(card was removed?)\n",
mmc_hostname(host), err);
- if (host->bus_ops->remove)
- host->bus_ops->remove(host);
- mmc_claim_host(host);
- mmc_detach_bus(host);
- mmc_release_host(host);
afacit that code's been there since March 2009. I'd have thought that
someone would have noticed "kernel hangs on resume" before now.
Do you think the patch should be backported into 2.6.32.x and eariler?
It looks like the code was introduced in 2.6.32.x by commit
95cdfb72b9bc568803f395c266152c71b034b461
cc'ing the author Nicolas Pitre
/* no need to bother upper layers */
err = 0;
}
@@ -1332,7 +1327,7 @@ static int __init mmc_init(void)
{
int ret;
- workqueue = create_singlethread_workqueue("kmmcd");
+ workqueue = create_freezeable_workqueue("kmmcd");
if (!workqueue)
return -ENOMEM;
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html