ARM: bL_switcher: Allow detachment of outstanding switch requests
authorDave Martin <Dave.Martin@arm.com>
Tue, 18 Jun 2013 13:37:02 +0000 (14:37 +0100)
committerNicolas Pitre <nicolas.pitre@linaro.org>
Thu, 20 Jun 2013 04:45:27 +0000 (00:45 -0400)
In rare situations, it may be neecssary to prevent a completer
registered using bL_switch_request_cb() from being called.

For example, a cpufreq driver module needs to ensure that its
completer won't get called if the module is about to be unloaded
from the kernel.

This patch provides a bL_switch_request_detach() function which
detaches the completer from an outstanding request.  The request
continues in the background, as if it had been started using
bL_switch_request().

If somebody else's completer is registered instead then the caller
shouldn't care about it, so nothing is done in this case.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
arch/arm/common/bL_switcher.c
arch/arm/include/asm/bL_switcher.h

index 6fbc73b8e0247bab1485ee498a91a951e767acc8..b9ee01717a809099da3bb0fd173397d87e223743 100644 (file)
@@ -385,6 +385,38 @@ int bL_switch_request_cb(unsigned int cpu, unsigned int new_cluster_id,
 
 EXPORT_SYMBOL_GPL(bL_switch_request_cb);
 
+/*
+ * Detach an outstanding switch request.
+ *
+ * The switcher will continue with the switch request in the background,
+ * but the completer function will not be called.
+ *
+ * This may be necessary if the completer is in a kernel module which is
+ * about to be unloaded.
+ */
+void bL_switch_request_detach(unsigned int cpu,
+                             bL_switch_completion_handler completer)
+{
+       struct bL_thread *t;
+
+       if (cpu >= ARRAY_SIZE(bL_threads)) {
+               pr_err("%s: cpu %d out of bounds\n", __func__, cpu);
+               return;
+       }
+
+       t = &bL_threads[cpu];
+
+       if (IS_ERR(t->task) || !t->task)
+               return;
+
+       spin_lock(&t->lock);
+       if (t->completer == completer)
+               t->completer = NULL;
+       spin_unlock(&t->lock);
+}
+
+EXPORT_SYMBOL_GPL(bL_switch_request_detach);
+
 /*
  * Activation and configuration code.
  */
index 98427597828609b81711f03e94bb3b81df29bc66..71d1b6a986bf2812f90af2b2e6497d52cf41eb45 100644 (file)
@@ -40,6 +40,9 @@ static inline int bL_switch_request(unsigned int cpu, unsigned int new_cluster_i
 
 #ifdef CONFIG_BL_SWITCHER
 
+void bL_switch_request_detach(unsigned int cpu,
+                             bL_switch_completion_handler completer);
+
 int bL_switcher_register_notifier(struct notifier_block *nb);
 int bL_switcher_unregister_notifier(struct notifier_block *nb);
 
@@ -55,6 +58,9 @@ bool bL_switcher_get_enabled(void);
 void bL_switcher_put_enabled(void);
 
 #else
+static void bL_switch_request_detach(unsigned int cpu,
+                                    bL_switch_completion_handler completer) { }
+
 static inline int bL_switcher_register_notifier(struct notifier_block *nb)
 {
        return 0;