diff options
author | Alex Shi <alex.shi@linaro.org> | 2014-07-18 14:06:21 +0800 |
---|---|---|
committer | Alex Shi <alex.shi@linaro.org> | 2014-07-18 14:08:02 +0800 |
commit | d0bc082b9c9d792a65e062856eb559b534d81fd8 (patch) | |
tree | 1491c8cb1d65e4fe21aeaa73fb8035b68c357348 /arch/powerpc | |
parent | fa6e05294759c29b3736010aa386928d24715feb (diff) | |
parent | d02dae430d1f41f2c1dc8592f68569f90b86f6d9 (diff) |
Merge tag 'v3.10.49' into linux-linaro-lsk
This is the 3.10.49 stable release
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/perf_event_server.h | 2 | ||||
-rw-r--r-- | arch/powerpc/perf/core-book3s.c | 22 | ||||
-rw-r--r-- | arch/powerpc/perf/power8-pmu.c | 2 |
3 files changed, 22 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index f265049dd7d6..960bf64788a3 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h @@ -59,7 +59,7 @@ struct power_pmu { #define PPMU_SIAR_VALID 0x00000010 /* Processor has SIAR Valid bit */ #define PPMU_HAS_SSLOT 0x00000020 /* Has sampled slot in MMCRA */ #define PPMU_HAS_SIER 0x00000040 /* Has SIER */ -#define PPMU_BHRB 0x00000080 /* has BHRB feature enabled */ +#define PPMU_ARCH_207S 0x00000080 /* PMC is architecture v2.07S */ /* * Values for flags to get_alternatives() diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index d3ee2e50a3a6..846861a20b07 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -749,7 +749,22 @@ static void power_pmu_read(struct perf_event *event) } while (local64_cmpxchg(&event->hw.prev_count, prev, val) != prev); local64_add(delta, &event->count); - local64_sub(delta, &event->hw.period_left); + + /* + * A number of places program the PMC with (0x80000000 - period_left). + * We never want period_left to be less than 1 because we will program + * the PMC with a value >= 0x800000000 and an edge detected PMC will + * roll around to 0 before taking an exception. We have seen this + * on POWER8. + * + * To fix this, clamp the minimum value of period_left to 1. + */ + do { + prev = local64_read(&event->hw.period_left); + val = prev - delta; + if (val < 1) + val = 1; + } while (local64_cmpxchg(&event->hw.period_left, prev, val) != prev); } /* @@ -1327,6 +1342,9 @@ static int can_go_on_limited_pmc(struct perf_event *event, u64 ev, if (ppmu->limited_pmc_event(ev)) return 1; + if (ppmu->flags & PPMU_ARCH_207S) + mtspr(SPRN_MMCR2, 0); + /* * The requested event_id isn't on a limited PMC already; * see if any alternative code goes on a limited PMC. @@ -1421,7 +1439,7 @@ static int power_pmu_event_init(struct perf_event *event) if (has_branch_stack(event)) { /* PMU has BHRB enabled */ - if (!(ppmu->flags & PPMU_BHRB)) + if (!(ppmu->flags & PPMU_ARCH_207S)) return -EOPNOTSUPP; } diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index 9aefaebedef1..ee3b4048ab4d 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c @@ -592,7 +592,7 @@ static struct power_pmu power8_pmu = { .get_constraint = power8_get_constraint, .get_alternatives = power8_get_alternatives, .disable_pmc = power8_disable_pmc, - .flags = PPMU_HAS_SSLOT | PPMU_HAS_SIER | PPMU_BHRB, + .flags = PPMU_HAS_SSLOT | PPMU_HAS_SIER | PPMU_ARCH_207S, .n_generic = ARRAY_SIZE(power8_generic_events), .generic_events = power8_generic_events, .attr_groups = power8_pmu_attr_groups, |