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

Commit 95b00786 authored by Len Brown's avatar Len Brown
Browse files

Pull cpuidle into release branch

parents 22201f74 ddc081a1
Loading
Loading
Loading
Loading
+63 −48
Original line number Diff line number Diff line
@@ -197,6 +197,19 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2)
		return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
}

static void acpi_safe_halt(void)
{
	current_thread_info()->status &= ~TS_POLLING;
	/*
	 * TS_POLLING-cleared state must be visible before we
	 * test NEED_RESCHED:
	 */
	smp_mb();
	if (!need_resched())
		safe_halt();
	current_thread_info()->status |= TS_POLLING;
}

#ifndef CONFIG_CPU_IDLE

static void
@@ -239,19 +252,6 @@ acpi_processor_power_activate(struct acpi_processor *pr,
	return;
}

static void acpi_safe_halt(void)
{
	current_thread_info()->status &= ~TS_POLLING;
	/*
	 * TS_POLLING-cleared state must be visible before we
	 * test NEED_RESCHED:
	 */
	smp_mb();
	if (!need_resched())
		safe_halt();
	current_thread_info()->status |= TS_POLLING;
}

static atomic_t c3_cpu_count;

/* Common C-state entry for C2, C3, .. */
@@ -1373,15 +1373,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
	if (pr->flags.bm_check)
		acpi_idle_update_bm_rld(pr, cx);

	current_thread_info()->status &= ~TS_POLLING;
	/*
	 * TS_POLLING-cleared state must be visible before we test
	 * NEED_RESCHED:
	 */
	smp_mb();
	if (!need_resched())
		safe_halt();
	current_thread_info()->status |= TS_POLLING;
	acpi_safe_halt();

	cx->usage++;

@@ -1399,6 +1391,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
	struct acpi_processor *pr;
	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
	u32 t1, t2;
	int sleep_ticks = 0;

	pr = processors[smp_processor_id()];

	if (unlikely(!pr))
@@ -1428,6 +1422,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
		ACPI_FLUSH_CPU_CACHE();

	t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
	/* Tell the scheduler that we are going deep-idle: */
	sched_clock_idle_sleep_event();
	acpi_state_timer_broadcast(pr, cx, 1);
	acpi_idle_do_entry(cx);
	t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -1436,6 +1432,10 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
	/* TSC could halt in idle, so notify users */
	mark_tsc_unstable("TSC halts in idle");;
#endif
	sleep_ticks = ticks_elapsed(t1, t2);

	/* Tell the scheduler how much we idled: */
	sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);

	local_irq_enable();
	current_thread_info()->status |= TS_POLLING;
@@ -1443,7 +1443,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
	cx->usage++;

	acpi_state_timer_broadcast(pr, cx, 0);
	cx->time += ticks_elapsed(t1, t2);
	cx->time += sleep_ticks;
	return ticks_elapsed_in_us(t1, t2);
}

@@ -1463,6 +1463,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
	struct acpi_processor *pr;
	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
	u32 t1, t2;
	int sleep_ticks = 0;

	pr = processors[smp_processor_id()];

	if (unlikely(!pr))
@@ -1471,6 +1473,15 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
	if (acpi_idle_suspend)
		return(acpi_idle_enter_c1(dev, state));

	if (acpi_idle_bm_check()) {
		if (dev->safe_state) {
			return dev->safe_state->enter(dev, dev->safe_state);
		} else {
			acpi_safe_halt();
			return 0;
		}
	}

	local_irq_disable();
	current_thread_info()->status &= ~TS_POLLING;
	/*
@@ -1485,37 +1496,44 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
		return 0;
	}

	/* Tell the scheduler that we are going deep-idle: */
	sched_clock_idle_sleep_event();
	/*
	 * Must be done before busmaster disable as we might need to
	 * access HPET !
	 */
	acpi_state_timer_broadcast(pr, cx, 1);

	if (acpi_idle_bm_check()) {
		cx = pr->power.bm_state;

		acpi_idle_update_bm_rld(pr, cx);

		t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
		acpi_idle_do_entry(cx);
		t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
	} else {
	acpi_idle_update_bm_rld(pr, cx);

	/*
	 * disable bus master
	 * bm_check implies we need ARB_DIS
	 * !bm_check implies we need cache flush
	 * bm_control implies whether we can do ARB_DIS
	 *
	 * That leaves a case where bm_check is set and bm_control is
	 * not set. In that case we cannot do much, we enter C3
	 * without doing anything.
	 */
	if (pr->flags.bm_check && pr->flags.bm_control) {
		spin_lock(&c3_lock);
		c3_cpu_count++;
		/* Disable bus master arbitration when all CPUs are in C3 */
		if (c3_cpu_count == num_online_cpus())
			acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
		spin_unlock(&c3_lock);
	} else if (!pr->flags.bm_check) {
		ACPI_FLUSH_CPU_CACHE();
	}

	t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
	acpi_idle_do_entry(cx);
	t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);

		spin_lock(&c3_lock);
	/* Re-enable bus master arbitration */
		if (c3_cpu_count == num_online_cpus())
	if (pr->flags.bm_check && pr->flags.bm_control) {
		spin_lock(&c3_lock);
		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
		c3_cpu_count--;
		spin_unlock(&c3_lock);
@@ -1525,6 +1543,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
	/* TSC could halt in idle, so notify users */
	mark_tsc_unstable("TSC halts in idle");
#endif
	sleep_ticks = ticks_elapsed(t1, t2);
	/* Tell the scheduler how much we idled: */
	sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);

	local_irq_enable();
	current_thread_info()->status |= TS_POLLING;
@@ -1532,7 +1553,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
	cx->usage++;

	acpi_state_timer_broadcast(pr, cx, 0);
	cx->time += ticks_elapsed(t1, t2);
	cx->time += sleep_ticks;
	return ticks_elapsed_in_us(t1, t2);
}

@@ -1584,12 +1605,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
			case ACPI_STATE_C1:
			state->flags |= CPUIDLE_FLAG_SHALLOW;
			state->enter = acpi_idle_enter_c1;
			dev->safe_state = state;
			break;

			case ACPI_STATE_C2:
			state->flags |= CPUIDLE_FLAG_BALANCED;
			state->flags |= CPUIDLE_FLAG_TIME_VALID;
			state->enter = acpi_idle_enter_simple;
			dev->safe_state = state;
			break;

			case ACPI_STATE_C3:
@@ -1610,14 +1633,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
	if (!count)
		return -EINVAL;

	/* find the deepest state that can handle active BM */
	if (pr->flags.bm_check) {
		for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++)
			if (pr->power.states[i].type == ACPI_STATE_C3)
				break;
		pr->power.bm_state = &pr->power.states[i-1];
	}

	return 0;
}

+0 −1
Original line number Diff line number Diff line
@@ -78,7 +78,6 @@ struct acpi_processor_cx {
struct acpi_processor_power {
	struct cpuidle_device dev;
	struct acpi_processor_cx *state;
	struct acpi_processor_cx *bm_state;
	unsigned long bm_check_timestamp;
	u32 default_state;
	u32 bm_activity;
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ struct cpuidle_device {
	struct kobject		kobj;
	struct completion	kobj_unregister;
	void			*governor_data;
	struct cpuidle_state	*safe_state;
};

DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);