Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4bb211a authored by Viresh Kumar's avatar Viresh Kumar Committed by Satya Durga Srinivasu Prabhala
Browse files

hrtimer: create hrtimer_quiesce_cpu() to isolate CPU from hrtimers



To isolate CPUs (isolate from hrtimers) from sysfs using cpusets, we need some
support from the hrtimer core. i.e. A routine hrtimer_quiesce_cpu() which would
migrate away all the unpinned hrtimers, but shouldn't touch the pinned ones.

This patch creates this routine.

Change-Id: Icf93622bdeed9c6c28eb1aca1637bc5b9522a533
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
[forward port to 3.18]
Signed-off-by: default avatarSantosh Shukla <santosh.shukla@linaro.org>
[ohaugan@codeaurora.org: Port to 4.4]
Git-commit: d4d50a0ddc35e58ee95137ba4d14e74fea8b682f
Git-repo: git://git.linaro.org/people/mike.holmes/santosh.shukla/lng-isol.git


Signed-off-by: default avatarOlav Haugan <ohaugan@codeaurora.org>
[rameezmustafa@codeaurora.org: Port to msm-4.9]
Signed-off-by: default avatarSyed Rameez Mustafa <rameezmustafa@codeaurora.org>
[satyap@codeaurora.org: Port to msm-4.19 and fix merge conflicts]
Signed-off-by: default avatarSatya Durga Srinivasu Prabhala <satyap@codeaurora.org>
parent de27e145
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -364,6 +364,9 @@ DECLARE_PER_CPU(struct tick_device, tick_cpu_device);


/* Exported timer functions: */
/* Exported timer functions: */


/* To be used from cpusets, only */
extern void hrtimer_quiesce_cpu(void *cpup);

/* Initialize timers: */
/* Initialize timers: */
extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
			 enum hrtimer_mode mode);
			 enum hrtimer_mode mode);
+44 −11
Original line number Original line Diff line number Diff line
@@ -1830,13 +1830,17 @@ int hrtimers_prepare_cpu(unsigned int cpu)
	return 0;
	return 0;
}
}


#ifdef CONFIG_HOTPLUG_CPU
#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_CPUSETS)

static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
				struct hrtimer_clock_base *new_base)
				 struct hrtimer_clock_base *new_base,
				 bool remove_pinned)
{
{
	struct hrtimer *timer;
	struct hrtimer *timer;
	struct timerqueue_node *node;
	struct timerqueue_node *node;
	struct timerqueue_head pinned;
	int is_pinned;

	timerqueue_init_head(&pinned);


	while ((node = timerqueue_getnext(&old_base->active))) {
	while ((node = timerqueue_getnext(&old_base->active))) {
		timer = container_of(node, struct hrtimer, node);
		timer = container_of(node, struct hrtimer, node);
@@ -1849,6 +1853,13 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
		 * under us on another CPU
		 * under us on another CPU
		 */
		 */
		__remove_hrtimer(timer, old_base, HRTIMER_STATE_ENQUEUED, 0);
		__remove_hrtimer(timer, old_base, HRTIMER_STATE_ENQUEUED, 0);

		is_pinned = timer->state & HRTIMER_STATE_PINNED;
		if (!remove_pinned && is_pinned) {
			timerqueue_add(&pinned, &timer->node);
			continue;
		}

		timer->base = new_base;
		timer->base = new_base;
		/*
		/*
		 * Enqueue the timers on the new cpu. This does not
		 * Enqueue the timers on the new cpu. This does not
@@ -1860,23 +1871,29 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
		 */
		 */
		enqueue_hrtimer(timer, new_base, HRTIMER_MODE_ABS);
		enqueue_hrtimer(timer, new_base, HRTIMER_MODE_ABS);
	}
	}

	/* Re-queue pinned timers for non-hotplug usecase */
	while ((node = timerqueue_getnext(&pinned))) {
		timer = container_of(node, struct hrtimer, node);

		timerqueue_del(&pinned, &timer->node);
		enqueue_hrtimer(timer, old_base, HRTIMER_MODE_ABS);
	}
}
}


int hrtimers_dead_cpu(unsigned int scpu)
static void __migrate_hrtimers(unsigned int scpu, bool remove_pinned)
{
{
	struct hrtimer_cpu_base *old_base, *new_base;
	struct hrtimer_cpu_base *old_base, *new_base;
	unsigned long flags;
	int i;
	int i;


	BUG_ON(cpu_online(scpu));
	tick_cancel_sched_timer(scpu);

	/*
	/*
	 * this BH disable ensures that raise_softirq_irqoff() does
	 * this BH disable ensures that raise_softirq_irqoff() does
	 * not wakeup ksoftirqd (and acquire the pi-lock) while
	 * not wakeup ksoftirqd (and acquire the pi-lock) while
	 * holding the cpu_base lock
	 * holding the cpu_base lock
	 */
	 */
	local_bh_disable();
	local_bh_disable();
	local_irq_disable();
	local_irq_save(flags);
	old_base = &per_cpu(hrtimer_bases, scpu);
	old_base = &per_cpu(hrtimer_bases, scpu);
	new_base = this_cpu_ptr(&hrtimer_bases);
	new_base = this_cpu_ptr(&hrtimer_bases);
	/*
	/*
@@ -1888,7 +1905,7 @@ int hrtimers_dead_cpu(unsigned int scpu)


	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
		migrate_hrtimer_list(&old_base->clock_base[i],
		migrate_hrtimer_list(&old_base->clock_base[i],
				     &new_base->clock_base[i]);
				     &new_base->clock_base[i], remove_pinned);
	}
	}


	/*
	/*
@@ -1902,13 +1919,29 @@ int hrtimers_dead_cpu(unsigned int scpu)


	/* Check, if we got expired work to do */
	/* Check, if we got expired work to do */
	__hrtimer_peek_ahead_timers();
	__hrtimer_peek_ahead_timers();
	local_irq_enable();
	local_irq_restore(flags);
	local_bh_enable();
	local_bh_enable();
	return 0;
}
}
#endif /* CONFIG_HOTPLUG_CPU || CONFIG_CPUSETS */

#ifdef CONFIG_HOTPLUG_CPU
int hrtimers_dead_cpu(unsigned int scpu)
{
	BUG_ON(cpu_online(scpu));
	tick_cancel_sched_timer(scpu);


	__migrate_hrtimers(scpu, true);
	return 0;
}
#endif /* CONFIG_HOTPLUG_CPU */
#endif /* CONFIG_HOTPLUG_CPU */


#ifdef CONFIG_CPUSETS
void hrtimer_quiesce_cpu(void *cpup)
{
	__migrate_hrtimers(*(int *)cpup, false);
}
#endif /* CONFIG_CPUSETS */

void __init hrtimers_init(void)
void __init hrtimers_init(void)
{
{
	hrtimers_prepare_cpu(smp_processor_id());
	hrtimers_prepare_cpu(smp_processor_id());