diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/time/tick-sched.c | 6 | ||||
| -rw-r--r-- | kernel/time/timer.c | 34 | ||||
| -rw-r--r-- | kernel/trace/msm_rtb.c | 10 |
3 files changed, 46 insertions, 4 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 651ff1a3a306..ec2102104cb8 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -19,6 +19,7 @@ #include <linux/percpu.h> #include <linux/profile.h> #include <linux/sched.h> +#include <linux/timer.h> #include <linux/module.h> #include <linux/irq_work.h> #include <linux/posix-timers.h> @@ -809,6 +810,11 @@ static void __tick_nohz_idle_enter(struct tick_sched *ts) now = tick_nohz_start_idle(ts); +#ifdef CONFIG_SMP + if (check_pending_deferrable_timers(cpu)) + raise_softirq_irqoff(TIMER_SOFTIRQ); +#endif + if (can_stop_idle_tick(cpu, ts)) { int was_stopped = ts->tick_stopped; diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 2bde2c2b1cb3..8315d4d72cc3 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -102,6 +102,7 @@ static DEFINE_PER_CPU(struct tvec_base, tvec_bases); unsigned int sysctl_timer_migration = 1; struct tvec_base tvec_base_deferrable; +static atomic_t deferrable_pending; void timers_update_migration(bool update_nohz) { @@ -150,9 +151,12 @@ static inline struct tvec_base *get_target_base(struct tvec_base *base, static inline void __run_deferrable_timers(void) { - if (smp_processor_id() == tick_do_timer_cpu && - time_after_eq(jiffies, tvec_base_deferrable.timer_jiffies)) - __run_timers(&tvec_base_deferrable); + if (time_after_eq(jiffies, tvec_base_deferrable.timer_jiffies)) { + if ((atomic_cmpxchg(&deferrable_pending, 1, 0) && + tick_do_timer_cpu == TICK_DO_TIMER_NONE) || + tick_do_timer_cpu == smp_processor_id()) + __run_timers(&tvec_base_deferrable); + } } static inline void init_timer_deferrable_global(void) @@ -1428,6 +1432,30 @@ static u64 cmp_next_hrtimer_event(u64 basem, u64 expires) return DIV_ROUND_UP_ULL(nextevt, TICK_NSEC) * TICK_NSEC; } +#ifdef CONFIG_SMP +/* + * check_pending_deferrable_timers - Check for unbound deferrable timer expiry. + * @cpu - Current CPU + * + * The function checks whether any global deferrable pending timers + * are exipired or not. This function does not check cpu bounded + * diferrable pending timers expiry. + * + * The function returns true when a cpu unbounded deferrable timer is expired. + */ +bool check_pending_deferrable_timers(int cpu) +{ + if (cpu == tick_do_timer_cpu || + tick_do_timer_cpu == TICK_DO_TIMER_NONE) { + if (time_after_eq(jiffies, tvec_base_deferrable.timer_jiffies) + && !atomic_cmpxchg(&deferrable_pending, 0, 1)) { + return true; + } + } + return false; +} +#endif + /** * get_next_timer_interrupt - return the time (clock mono) of the next timer * @basej: base time jiffies diff --git a/kernel/trace/msm_rtb.c b/kernel/trace/msm_rtb.c index 80058b544cb5..587082117842 100644 --- a/kernel/trace/msm_rtb.c +++ b/kernel/trace/msm_rtb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,6 +28,7 @@ #include <asm-generic/sizes.h> #include <linux/msm_rtb.h> #include <asm/timex.h> +#include <soc/qcom/minidump.h> #define SENTINEL_BYTE_1 0xFF #define SENTINEL_BYTE_2 0xAA @@ -243,6 +244,7 @@ EXPORT_SYMBOL(uncached_logk); static int msm_rtb_probe(struct platform_device *pdev) { struct msm_rtb_platform_data *d = pdev->dev.platform_data; + struct md_region md_entry; #if defined(CONFIG_QCOM_RTB_SEPARATE_CPUS) unsigned int cpu; #endif @@ -294,6 +296,12 @@ static int msm_rtb_probe(struct platform_device *pdev) memset(msm_rtb.rtb, 0, msm_rtb.size); + strlcpy(md_entry.name, "KRTB_BUF", sizeof(md_entry.name)); + md_entry.virt_addr = (uintptr_t)msm_rtb.rtb; + md_entry.phys_addr = msm_rtb.phys; + md_entry.size = msm_rtb.size; + if (msm_minidump_add_region(&md_entry)) + pr_info("Failed to add RTB in Minidump\n"); #if defined(CONFIG_QCOM_RTB_SEPARATE_CPUS) for_each_possible_cpu(cpu) { |
