diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2006-10-04 05:15:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:15 -0400 |
commit | 7104e2d5a85b4b786d6a63568beffe1e185547bb (patch) | |
tree | 1478b1076a66476a121e687dd9547d5c08d9c3ba /drivers/mmc/mmc_sysfs.c | |
parent | 8a4da1430f7f2a16df3be9c7b5d55ba4e75b708c (diff) |
[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 'drivers/mmc/mmc_sysfs.c')
-rw-r--r-- | drivers/mmc/mmc_sysfs.c | 35 |
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 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/idr.h> | 15 | #include <linux/idr.h> |
16 | #include <linux/workqueue.h> | ||
16 | 17 | ||
17 | #include <linux/mmc/card.h> | 18 | #include <linux/mmc/card.h> |
18 | #include <linux/mmc/host.h> | 19 | #include <linux/mmc/host.h> |
@@ -317,10 +318,41 @@ void mmc_free_host_sysfs(struct mmc_host *host) | |||
317 | class_device_put(&host->class_dev); | 318 | class_device_put(&host->class_dev); |
318 | } | 319 | } |
319 | 320 | ||
321 | static struct workqueue_struct *workqueue; | ||
322 | |||
323 | /* | ||
324 | * Internal function. Schedule work in the MMC work queue. | ||
325 | */ | ||
326 | int mmc_schedule_work(struct work_struct *work) | ||
327 | { | ||
328 | return queue_work(workqueue, work); | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * Internal function. Schedule delayed work in the MMC work queue. | ||
333 | */ | ||
334 | int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay) | ||
335 | { | ||
336 | return queue_delayed_work(workqueue, work, delay); | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * Internal function. Flush all scheduled work from the MMC work queue. | ||
341 | */ | ||
342 | void mmc_flush_scheduled_work(void) | ||
343 | { | ||
344 | flush_workqueue(workqueue); | ||
345 | } | ||
320 | 346 | ||
321 | static int __init mmc_init(void) | 347 | static int __init mmc_init(void) |
322 | { | 348 | { |
323 | int ret = bus_register(&mmc_bus_type); | 349 | int ret; |
350 | |||
351 | workqueue = create_singlethread_workqueue("kmmcd"); | ||
352 | if (!workqueue) | ||
353 | return -ENOMEM; | ||
354 | |||
355 | ret = bus_register(&mmc_bus_type); | ||
324 | if (ret == 0) { | 356 | if (ret == 0) { |
325 | ret = class_register(&mmc_host_class); | 357 | ret = class_register(&mmc_host_class); |
326 | if (ret) | 358 | if (ret) |
@@ -333,6 +365,7 @@ static void __exit mmc_exit(void) | |||
333 | { | 365 | { |
334 | class_unregister(&mmc_host_class); | 366 | class_unregister(&mmc_host_class); |
335 | bus_unregister(&mmc_bus_type); | 367 | bus_unregister(&mmc_bus_type); |
368 | destroy_workqueue(workqueue); | ||
336 | } | 369 | } |
337 | 370 | ||
338 | module_init(mmc_init); | 371 | module_init(mmc_init); |