diff options
-rw-r--r-- | arch/arm/kernel/perf_event.c | 19 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_v6.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_v7.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_xscale.c | 4 |
4 files changed, 15 insertions, 12 deletions
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index e422f4c269a0..69cfee0fe00f 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -205,11 +205,9 @@ armpmu_event_set_period(struct perf_event *event, | |||
205 | static u64 | 205 | static u64 |
206 | armpmu_event_update(struct perf_event *event, | 206 | armpmu_event_update(struct perf_event *event, |
207 | struct hw_perf_event *hwc, | 207 | struct hw_perf_event *hwc, |
208 | int idx) | 208 | int idx, int overflow) |
209 | { | 209 | { |
210 | int shift = 64 - 32; | 210 | u64 delta, prev_raw_count, new_raw_count; |
211 | s64 prev_raw_count, new_raw_count; | ||
212 | u64 delta; | ||
213 | 211 | ||
214 | again: | 212 | again: |
215 | prev_raw_count = local64_read(&hwc->prev_count); | 213 | prev_raw_count = local64_read(&hwc->prev_count); |
@@ -219,8 +217,13 @@ again: | |||
219 | new_raw_count) != prev_raw_count) | 217 | new_raw_count) != prev_raw_count) |
220 | goto again; | 218 | goto again; |
221 | 219 | ||
222 | delta = (new_raw_count << shift) - (prev_raw_count << shift); | 220 | new_raw_count &= armpmu->max_period; |
223 | delta >>= shift; | 221 | prev_raw_count &= armpmu->max_period; |
222 | |||
223 | if (overflow) | ||
224 | delta = armpmu->max_period - prev_raw_count + new_raw_count; | ||
225 | else | ||
226 | delta = new_raw_count - prev_raw_count; | ||
224 | 227 | ||
225 | local64_add(delta, &event->count); | 228 | local64_add(delta, &event->count); |
226 | local64_sub(delta, &hwc->period_left); | 229 | local64_sub(delta, &hwc->period_left); |
@@ -237,7 +240,7 @@ armpmu_read(struct perf_event *event) | |||
237 | if (hwc->idx < 0) | 240 | if (hwc->idx < 0) |
238 | return; | 241 | return; |
239 | 242 | ||
240 | armpmu_event_update(event, hwc, hwc->idx); | 243 | armpmu_event_update(event, hwc, hwc->idx, 0); |
241 | } | 244 | } |
242 | 245 | ||
243 | static void | 246 | static void |
@@ -255,7 +258,7 @@ armpmu_stop(struct perf_event *event, int flags) | |||
255 | if (!(hwc->state & PERF_HES_STOPPED)) { | 258 | if (!(hwc->state & PERF_HES_STOPPED)) { |
256 | armpmu->disable(hwc, hwc->idx); | 259 | armpmu->disable(hwc, hwc->idx); |
257 | barrier(); /* why? */ | 260 | barrier(); /* why? */ |
258 | armpmu_event_update(event, hwc, hwc->idx); | 261 | armpmu_event_update(event, hwc, hwc->idx, 0); |
259 | hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; | 262 | hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; |
260 | } | 263 | } |
261 | } | 264 | } |
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index 6fc2d228db55..f1e8dd94afe8 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c | |||
@@ -474,7 +474,7 @@ armv6pmu_handle_irq(int irq_num, | |||
474 | continue; | 474 | continue; |
475 | 475 | ||
476 | hwc = &event->hw; | 476 | hwc = &event->hw; |
477 | armpmu_event_update(event, hwc, idx); | 477 | armpmu_event_update(event, hwc, idx, 1); |
478 | data.period = event->hw.last_period; | 478 | data.period = event->hw.last_period; |
479 | if (!armpmu_event_set_period(event, hwc, idx)) | 479 | if (!armpmu_event_set_period(event, hwc, idx)) |
480 | continue; | 480 | continue; |
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index c08d07a99fcc..4960686afb58 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c | |||
@@ -782,7 +782,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) | |||
782 | continue; | 782 | continue; |
783 | 783 | ||
784 | hwc = &event->hw; | 784 | hwc = &event->hw; |
785 | armpmu_event_update(event, hwc, idx); | 785 | armpmu_event_update(event, hwc, idx, 1); |
786 | data.period = event->hw.last_period; | 786 | data.period = event->hw.last_period; |
787 | if (!armpmu_event_set_period(event, hwc, idx)) | 787 | if (!armpmu_event_set_period(event, hwc, idx)) |
788 | continue; | 788 | continue; |
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index 28cd3b025bc3..39affbe4fdb2 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c | |||
@@ -246,7 +246,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev) | |||
246 | continue; | 246 | continue; |
247 | 247 | ||
248 | hwc = &event->hw; | 248 | hwc = &event->hw; |
249 | armpmu_event_update(event, hwc, idx); | 249 | armpmu_event_update(event, hwc, idx, 1); |
250 | data.period = event->hw.last_period; | 250 | data.period = event->hw.last_period; |
251 | if (!armpmu_event_set_period(event, hwc, idx)) | 251 | if (!armpmu_event_set_period(event, hwc, idx)) |
252 | continue; | 252 | continue; |
@@ -578,7 +578,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev) | |||
578 | continue; | 578 | continue; |
579 | 579 | ||
580 | hwc = &event->hw; | 580 | hwc = &event->hw; |
581 | armpmu_event_update(event, hwc, idx); | 581 | armpmu_event_update(event, hwc, idx, 1); |
582 | data.period = event->hw.last_period; | 582 | data.period = event->hw.last_period; |
583 | if (!armpmu_event_set_period(event, hwc, idx)) | 583 | if (!armpmu_event_set_period(event, hwc, idx)) |
584 | continue; | 584 | continue; |