Skip to content

Commit

Permalink
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/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"
  • Loading branch information
Linus Torvalds committed Oct 18, 2012
2 parents bab5835 + 83dac59 commit a0a6a39
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 39 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/kvm_book3s_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
4 changes: 2 additions & 2 deletions arch/powerpc/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/kvm/book3s_32_mmu_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/perf/core-book3s.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
62 changes: 29 additions & 33 deletions arch/powerpc/platforms/pseries/processor_idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{

Expand All @@ -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;
Expand Down Expand Up @@ -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 },
};

Expand All @@ -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)
{
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit a0a6a39

Please sign in to comment.