summaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-21 17:46:16 +0900
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-21 17:46:16 +0900
commit69485d3e6d6839b46a56c77d2dffad18cb7d373f (patch)
tree20e9de1d5fd9f6617b05e759f9326eaffaf743ee /kernel/module.c
parentf2a93e2a4c048dfb5c7ee3f159a4a1d1cb61b4b5 (diff)
parent7881fd0fb3ecc9e367ba998a4de533e7eecbdfeb (diff)
Merge remote-tracking branch 'asoc/fix/adsp' into asoc-adsp
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 250092c1d57..b10b048367e 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3013,6 +3013,12 @@ static int do_init_module(struct module *mod)
{
int ret = 0;
+ /*
+ * We want to find out whether @mod uses async during init. Clear
+ * PF_USED_ASYNC. async_schedule*() will set it.
+ */
+ current->flags &= ~PF_USED_ASYNC;
+
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_COMING, mod);
@@ -3058,8 +3064,25 @@ static int do_init_module(struct module *mod)
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_LIVE, mod);
- /* We need to finish all async code before the module init sequence is done */
- async_synchronize_full();
+ /*
+ * We need to finish all async code before the module init sequence
+ * is done. This has potential to deadlock. For example, a newly
+ * detected block device can trigger request_module() of the
+ * default iosched from async probing task. Once userland helper
+ * reaches here, async_synchronize_full() will wait on the async
+ * task waiting on request_module() and deadlock.
+ *
+ * This deadlock is avoided by perfomring async_synchronize_full()
+ * iff module init queued any async jobs. This isn't a full
+ * solution as it will deadlock the same if module loading from
+ * async jobs nests more than once; however, due to the various
+ * constraints, this hack seems to be the best option for now.
+ * Please refer to the following thread for details.
+ *
+ * http://thread.gmane.org/gmane.linux.kernel/1420814
+ */
+ if (current->flags & PF_USED_ASYNC)
+ async_synchronize_full();
mutex_lock(&module_mutex);
/* Drop initial reference. */