Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes from Benjamin Herrenschmidt: "Here are a handful of powerpc related fixes." * 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: cpuidle/powerpc: Fix snooze state problem in the cpuidle design on pseries. cpuidle/powerpc: Fix smt_snooze_delay functionality. cpuidle/powerpc: Fix target residency initialisation in pseries cpuidle powerpc: Build fix for powerpc KVM Revert "powerpc/perf: Use pmc_overflow() to detect rolled back events"
This commit is contained in:
commit
a0a6a39ecb
@ -42,5 +42,6 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
|
||||
#define SID_SHIFT 28
|
||||
#define ESID_MASK 0xf0000000
|
||||
#define VSID_MASK 0x00fffffff0000000ULL
|
||||
#define VPN_SHIFT 12
|
||||
|
||||
#endif /* __ASM_KVM_BOOK3S_32_H__ */
|
||||
|
@ -388,9 +388,9 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */
|
||||
extern void power7_nap(void);
|
||||
|
||||
#ifdef CONFIG_PSERIES_IDLE
|
||||
extern void update_smt_snooze_delay(int snooze);
|
||||
extern void update_smt_snooze_delay(int cpu, int residency);
|
||||
#else
|
||||
static inline void update_smt_snooze_delay(int snooze) {}
|
||||
static inline void update_smt_snooze_delay(int cpu, int residency) {}
|
||||
#endif
|
||||
|
||||
extern void flush_instruction_cache(void);
|
||||
|
@ -50,7 +50,7 @@ static ssize_t store_smt_snooze_delay(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
per_cpu(smt_snooze_delay, cpu->dev.id) = snooze;
|
||||
update_smt_snooze_delay(snooze);
|
||||
update_smt_snooze_delay(cpu->dev.id, snooze);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -173,8 +173,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
|
||||
BUG_ON(!map);
|
||||
|
||||
vsid = map->host_vsid;
|
||||
vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) | ((eaddr & ~ESID_MASK) >> VPN_SHIFT)
|
||||
|
||||
vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) |
|
||||
((eaddr & ~ESID_MASK) >> VPN_SHIFT);
|
||||
next_pteg:
|
||||
if (rr == 16) {
|
||||
primary = !primary;
|
||||
|
@ -1463,7 +1463,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
|
||||
if (!event->hw.idx || is_limited_pmc(event->hw.idx))
|
||||
continue;
|
||||
val = read_pmc(event->hw.idx);
|
||||
if (pmc_overflow(val)) {
|
||||
if ((int)val < 0) {
|
||||
/* event has overflowed */
|
||||
found = 1;
|
||||
record_and_restart(event, val, regs);
|
||||
|
@ -33,13 +33,6 @@ static int max_idle_state = MAX_IDLE_STATE_COUNT - 1;
|
||||
static struct cpuidle_device __percpu *pseries_cpuidle_devices;
|
||||
static struct cpuidle_state *cpuidle_state_table;
|
||||
|
||||
void update_smt_snooze_delay(int snooze)
|
||||
{
|
||||
struct cpuidle_driver *drv = cpuidle_get_driver();
|
||||
if (drv)
|
||||
drv->states[0].target_residency = snooze;
|
||||
}
|
||||
|
||||
static inline void idle_loop_prolog(unsigned long *in_purr, ktime_t *kt_before)
|
||||
{
|
||||
|
||||
@ -66,32 +59,22 @@ static int snooze_loop(struct cpuidle_device *dev,
|
||||
{
|
||||
unsigned long in_purr;
|
||||
ktime_t kt_before;
|
||||
unsigned long start_snooze;
|
||||
long snooze = drv->states[0].target_residency;
|
||||
int cpu = dev->cpu;
|
||||
|
||||
idle_loop_prolog(&in_purr, &kt_before);
|
||||
local_irq_enable();
|
||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
|
||||
if (snooze) {
|
||||
start_snooze = get_tb() + snooze * tb_ticks_per_usec;
|
||||
local_irq_enable();
|
||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
|
||||
while ((snooze < 0) || (get_tb() < start_snooze)) {
|
||||
if (need_resched() || cpu_is_offline(dev->cpu))
|
||||
goto out;
|
||||
ppc64_runlatch_off();
|
||||
HMT_low();
|
||||
HMT_very_low();
|
||||
}
|
||||
|
||||
HMT_medium();
|
||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||
smp_mb();
|
||||
local_irq_disable();
|
||||
while ((!need_resched()) && cpu_online(cpu)) {
|
||||
ppc64_runlatch_off();
|
||||
HMT_low();
|
||||
HMT_very_low();
|
||||
}
|
||||
|
||||
out:
|
||||
HMT_medium();
|
||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||
smp_mb();
|
||||
|
||||
dev->last_residency =
|
||||
(int)idle_loop_epilog(in_purr, kt_before);
|
||||
return index;
|
||||
@ -172,8 +155,8 @@ static struct cpuidle_state dedicated_states[MAX_IDLE_STATE_COUNT] = {
|
||||
.name = "CEDE",
|
||||
.desc = "CEDE",
|
||||
.flags = CPUIDLE_FLAG_TIME_VALID,
|
||||
.exit_latency = 1,
|
||||
.target_residency = 10,
|
||||
.exit_latency = 10,
|
||||
.target_residency = 100,
|
||||
.enter = &dedicated_cede_loop },
|
||||
};
|
||||
|
||||
@ -190,6 +173,23 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = {
|
||||
.enter = &shared_cede_loop },
|
||||
};
|
||||
|
||||
void update_smt_snooze_delay(int cpu, int residency)
|
||||
{
|
||||
struct cpuidle_driver *drv = cpuidle_get_driver();
|
||||
struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
|
||||
|
||||
if (cpuidle_state_table != dedicated_states)
|
||||
return;
|
||||
|
||||
if (residency < 0) {
|
||||
/* Disable the Nap state on that cpu */
|
||||
if (dev)
|
||||
dev->states_usage[1].disable = 1;
|
||||
} else
|
||||
if (drv)
|
||||
drv->states[1].target_residency = residency;
|
||||
}
|
||||
|
||||
static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
@ -246,10 +246,6 @@ static int pseries_cpuidle_driver_init(void)
|
||||
drv->states[drv->state_count] = /* structure copy */
|
||||
cpuidle_state_table[idle_state];
|
||||
|
||||
if (cpuidle_state_table == dedicated_states)
|
||||
drv->states[drv->state_count].target_residency =
|
||||
__get_cpu_var(smt_snooze_delay);
|
||||
|
||||
drv->state_count += 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user