summaryrefslogtreecommitdiffstats
path: root/drivers/mmc/mmc_sysfs.c
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2006-10-04 11:15:41 +0200
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 16:55:15 +0200
commit7104e2d5a85b4b786d6a63568beffe1e185547bb (patch)
tree1478b1076a66476a121e687dd9547d5c08d9c3ba /drivers/mmc/mmc_sysfs.c
parent[PATCH] mmc: avoid some resets without card (diff)
downloadlinux-7104e2d5a85b4b786d6a63568beffe1e185547bb.tar.xz
linux-7104e2d5a85b4b786d6a63568beffe1e185547bb.zip
[PATCH] mmc: use own work queue
The MMC layer uses the standard work queue for doing card detection. As this queue is shared with other crucial subsystems, the effects of a long (and perhaps buggy) detection can cause the system to be unusable. E.g. the keyboard stops working while the detection routine is running. The solution is to add a specific mmc work queue to run the detection code in. This is similar to how other subsystems handle detection (a full kernel thread is the most common theme). Signed-off-by: Pierre Ossman <drzeus@drzeus.cx> Cc: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to '')
-rw-r--r--drivers/mmc/mmc_sysfs.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index a2a35fd946ee..10cc9734eaa0 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/idr.h>
+#include <linux/workqueue.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -317,10 +318,41 @@ void mmc_free_host_sysfs(struct mmc_host *host)
class_device_put(&host->class_dev);
}
+static struct workqueue_struct *workqueue;
+
+/*
+ * Internal function. Schedule work in the MMC work queue.
+ */
+int mmc_schedule_work(struct work_struct *work)
+{
+ return queue_work(workqueue, work);
+}
+
+/*
+ * Internal function. Schedule delayed work in the MMC work queue.
+ */
+int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay)
+{
+ return queue_delayed_work(workqueue, work, delay);
+}
+
+/*
+ * Internal function. Flush all scheduled work from the MMC work queue.
+ */
+void mmc_flush_scheduled_work(void)
+{
+ flush_workqueue(workqueue);
+}
static int __init mmc_init(void)
{
- int ret = bus_register(&mmc_bus_type);
+ int ret;
+
+ workqueue = create_singlethread_workqueue("kmmcd");
+ if (!workqueue)
+ return -ENOMEM;
+
+ ret = bus_register(&mmc_bus_type);
if (ret == 0) {
ret = class_register(&mmc_host_class);
if (ret)
@@ -333,6 +365,7 @@ static void __exit mmc_exit(void)
{
class_unregister(&mmc_host_class);
bus_unregister(&mmc_bus_type);
+ destroy_workqueue(workqueue);
}
module_init(mmc_init);