summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAlex Shi <alex.shi@linaro.org>2015-03-12 20:13:22 +0900
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:42:02 +0900
commit7fbab276accd2f1b0f35c51ec03877b057042be3 (patch)
treeab8afcd79965d2a31a6df6759866866d2586bd0d /kernel
parent99b61b9a7433f8c1ee2713217dd454b3176e75f6 (diff)
HMP: use per cpu cpuidle driver to fix deadlock in hmp_idle_pull
Using per cpu cpuidle driver to fix deadlock in hmp_idle_pull. Otherwise a deadlock happened when do bl_idle_init. [ 113.878664] other info that might help us debug this: [ 113.878667] Possible unsafe locking scenario: [ 113.878667] [ 113.878670] CPU0 [ 113.878673] ---- [ 113.878681] lock(cpuidle_driver_lock); [ 113.878684] <Interrupt> [ 113.878691] lock(cpuidle_driver_lock); [ 113.878693] [ 113.878693] *** DEADLOCK *** [ 113.878693] [ 113.878697] 1 lock held by ksoftirqd/4/28: [ 113.878719] #0: (hmp_force_migration){+.....}, at: [<c0054da5>] hmp_idle_pull+0x49/0x508 This patch is just a quick/cheap workaround for cpuidle_driver_lock deadlock. It works for TC2 and any other platform where the idle driver cannot be changed at runtime. Signed-off-by: Alex Shi <alex.shi@linaro.org> Signed-off-by: Jon Medhurst <tixy@linaro.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/fair.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 33a6cdf9be0a..d5a39b1f3537 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -5054,10 +5054,12 @@ static enum hrtimer_restart hmp_cpu_keepalive_notify(struct hrtimer *hrtimer)
* If there are any, set ns_delay to
* ('target_residency of state with shortest too-big latency' - 1) * 1000.
*/
-static void hmp_keepalive_delay(unsigned int *ns_delay)
+static void hmp_keepalive_delay(int cpu, unsigned int *ns_delay)
{
+ struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
struct cpuidle_driver *drv;
- drv = cpuidle_driver_ref();
+
+ drv = cpuidle_get_cpu_driver(dev);
if (drv) {
unsigned int us_delay = UINT_MAX;
unsigned int us_max_delay = *ns_delay / 1000;
@@ -5076,7 +5078,6 @@ static void hmp_keepalive_delay(unsigned int *ns_delay)
else
*ns_delay = 1000 * (us_delay - 1);
}
- cpuidle_driver_unref();
}
static void hmp_cpu_keepalive_trigger(void)
@@ -5090,7 +5091,7 @@ static void hmp_cpu_keepalive_trigger(void)
CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
keepalive->timer.function = hmp_cpu_keepalive_notify;
- hmp_keepalive_delay(&ns_delay);
+ hmp_keepalive_delay(cpu, &ns_delay);
keepalive->delay = ns_to_ktime(ns_delay);
keepalive->init = true;
}