提交 a0a6a39e 编写于 作者: L Linus Torvalds

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"
...@@ -42,5 +42,6 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu) ...@@ -42,5 +42,6 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
#define SID_SHIFT 28 #define SID_SHIFT 28
#define ESID_MASK 0xf0000000 #define ESID_MASK 0xf0000000
#define VSID_MASK 0x00fffffff0000000ULL #define VSID_MASK 0x00fffffff0000000ULL
#define VPN_SHIFT 12
#endif /* __ASM_KVM_BOOK3S_32_H__ */ #endif /* __ASM_KVM_BOOK3S_32_H__ */
...@@ -388,9 +388,9 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */ ...@@ -388,9 +388,9 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */
extern void power7_nap(void); extern void power7_nap(void);
#ifdef CONFIG_PSERIES_IDLE #ifdef CONFIG_PSERIES_IDLE
extern void update_smt_snooze_delay(int snooze); extern void update_smt_snooze_delay(int cpu, int residency);
#else #else
static inline void update_smt_snooze_delay(int snooze) {} static inline void update_smt_snooze_delay(int cpu, int residency) {}
#endif #endif
extern void flush_instruction_cache(void); extern void flush_instruction_cache(void);
......
...@@ -50,7 +50,7 @@ static ssize_t store_smt_snooze_delay(struct device *dev, ...@@ -50,7 +50,7 @@ static ssize_t store_smt_snooze_delay(struct device *dev,
return -EINVAL; return -EINVAL;
per_cpu(smt_snooze_delay, cpu->dev.id) = snooze; per_cpu(smt_snooze_delay, cpu->dev.id) = snooze;
update_smt_snooze_delay(snooze); update_smt_snooze_delay(cpu->dev.id, snooze);
return count; return count;
} }
......
...@@ -173,8 +173,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) ...@@ -173,8 +173,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
BUG_ON(!map); BUG_ON(!map);
vsid = map->host_vsid; 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: next_pteg:
if (rr == 16) { if (rr == 16) {
primary = !primary; primary = !primary;
......
...@@ -1463,7 +1463,7 @@ static void perf_event_interrupt(struct pt_regs *regs) ...@@ -1463,7 +1463,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
if (!event->hw.idx || is_limited_pmc(event->hw.idx)) if (!event->hw.idx || is_limited_pmc(event->hw.idx))
continue; continue;
val = read_pmc(event->hw.idx); val = read_pmc(event->hw.idx);
if (pmc_overflow(val)) { if ((int)val < 0) {
/* event has overflowed */ /* event has overflowed */
found = 1; found = 1;
record_and_restart(event, val, regs); record_and_restart(event, val, regs);
......
...@@ -33,13 +33,6 @@ static int max_idle_state = MAX_IDLE_STATE_COUNT - 1; ...@@ -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_device __percpu *pseries_cpuidle_devices;
static struct cpuidle_state *cpuidle_state_table; 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) 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, ...@@ -66,32 +59,22 @@ static int snooze_loop(struct cpuidle_device *dev,
{ {
unsigned long in_purr; unsigned long in_purr;
ktime_t kt_before; ktime_t kt_before;
unsigned long start_snooze; int cpu = dev->cpu;
long snooze = drv->states[0].target_residency;
idle_loop_prolog(&in_purr, &kt_before); idle_loop_prolog(&in_purr, &kt_before);
local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG);
if (snooze) { while ((!need_resched()) && cpu_online(cpu)) {
start_snooze = get_tb() + snooze * tb_ticks_per_usec; ppc64_runlatch_off();
local_irq_enable(); HMT_low();
set_thread_flag(TIF_POLLING_NRFLAG); HMT_very_low();
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();
} }
out:
HMT_medium(); HMT_medium();
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb();
dev->last_residency = dev->last_residency =
(int)idle_loop_epilog(in_purr, kt_before); (int)idle_loop_epilog(in_purr, kt_before);
return index; return index;
...@@ -172,8 +155,8 @@ static struct cpuidle_state dedicated_states[MAX_IDLE_STATE_COUNT] = { ...@@ -172,8 +155,8 @@ static struct cpuidle_state dedicated_states[MAX_IDLE_STATE_COUNT] = {
.name = "CEDE", .name = "CEDE",
.desc = "CEDE", .desc = "CEDE",
.flags = CPUIDLE_FLAG_TIME_VALID, .flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 1, .exit_latency = 10,
.target_residency = 10, .target_residency = 100,
.enter = &dedicated_cede_loop }, .enter = &dedicated_cede_loop },
}; };
...@@ -190,6 +173,23 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = { ...@@ -190,6 +173,23 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = {
.enter = &shared_cede_loop }, .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, static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
unsigned long action, void *hcpu) unsigned long action, void *hcpu)
{ {
...@@ -246,10 +246,6 @@ static int pseries_cpuidle_driver_init(void) ...@@ -246,10 +246,6 @@ static int pseries_cpuidle_driver_init(void)
drv->states[drv->state_count] = /* structure copy */ drv->states[drv->state_count] = /* structure copy */
cpuidle_state_table[idle_state]; 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; drv->state_count += 1;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册