diff options
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 24 | ||||
-rw-r--r-- | include/linux/perf_event.h | 2 | ||||
-rw-r--r-- | kernel/perf_event.c | 20 |
3 files changed, 40 insertions, 6 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index a920f173a220..9173ea95f918 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1495,7 +1495,7 @@ static inline int match_prev_assignment(struct hw_perf_event *hwc, | |||
1495 | hwc->last_tag == cpuc->tags[i]; | 1495 | hwc->last_tag == cpuc->tags[i]; |
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | static void __x86_pmu_disable(struct perf_event *event, struct cpu_hw_events *cpuc); | 1498 | static void x86_pmu_stop(struct perf_event *event); |
1499 | 1499 | ||
1500 | void hw_perf_enable(void) | 1500 | void hw_perf_enable(void) |
1501 | { | 1501 | { |
@@ -1533,7 +1533,7 @@ void hw_perf_enable(void) | |||
1533 | match_prev_assignment(hwc, cpuc, i)) | 1533 | match_prev_assignment(hwc, cpuc, i)) |
1534 | continue; | 1534 | continue; |
1535 | 1535 | ||
1536 | __x86_pmu_disable(event, cpuc); | 1536 | x86_pmu_stop(event); |
1537 | 1537 | ||
1538 | hwc->idx = -1; | 1538 | hwc->idx = -1; |
1539 | } | 1539 | } |
@@ -1801,6 +1801,19 @@ static int x86_pmu_enable(struct perf_event *event) | |||
1801 | return 0; | 1801 | return 0; |
1802 | } | 1802 | } |
1803 | 1803 | ||
1804 | static int x86_pmu_start(struct perf_event *event) | ||
1805 | { | ||
1806 | struct hw_perf_event *hwc = &event->hw; | ||
1807 | |||
1808 | if (hwc->idx == -1) | ||
1809 | return -EAGAIN; | ||
1810 | |||
1811 | x86_perf_event_set_period(event, hwc, hwc->idx); | ||
1812 | x86_pmu.enable(hwc, hwc->idx); | ||
1813 | |||
1814 | return 0; | ||
1815 | } | ||
1816 | |||
1804 | static void x86_pmu_unthrottle(struct perf_event *event) | 1817 | static void x86_pmu_unthrottle(struct perf_event *event) |
1805 | { | 1818 | { |
1806 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1819 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
@@ -1924,8 +1937,9 @@ static void intel_pmu_drain_bts_buffer(struct cpu_hw_events *cpuc) | |||
1924 | event->pending_kill = POLL_IN; | 1937 | event->pending_kill = POLL_IN; |
1925 | } | 1938 | } |
1926 | 1939 | ||
1927 | static void __x86_pmu_disable(struct perf_event *event, struct cpu_hw_events *cpuc) | 1940 | static void x86_pmu_stop(struct perf_event *event) |
1928 | { | 1941 | { |
1942 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
1929 | struct hw_perf_event *hwc = &event->hw; | 1943 | struct hw_perf_event *hwc = &event->hw; |
1930 | int idx = hwc->idx; | 1944 | int idx = hwc->idx; |
1931 | 1945 | ||
@@ -1954,7 +1968,7 @@ static void x86_pmu_disable(struct perf_event *event) | |||
1954 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1968 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
1955 | int i; | 1969 | int i; |
1956 | 1970 | ||
1957 | __x86_pmu_disable(event, cpuc); | 1971 | x86_pmu_stop(event); |
1958 | 1972 | ||
1959 | for (i = 0; i < cpuc->n_events; i++) { | 1973 | for (i = 0; i < cpuc->n_events; i++) { |
1960 | if (event == cpuc->event_list[i]) { | 1974 | if (event == cpuc->event_list[i]) { |
@@ -2667,6 +2681,8 @@ static inline void x86_pmu_read(struct perf_event *event) | |||
2667 | static const struct pmu pmu = { | 2681 | static const struct pmu pmu = { |
2668 | .enable = x86_pmu_enable, | 2682 | .enable = x86_pmu_enable, |
2669 | .disable = x86_pmu_disable, | 2683 | .disable = x86_pmu_disable, |
2684 | .start = x86_pmu_start, | ||
2685 | .stop = x86_pmu_stop, | ||
2670 | .read = x86_pmu_read, | 2686 | .read = x86_pmu_read, |
2671 | .unthrottle = x86_pmu_unthrottle, | 2687 | .unthrottle = x86_pmu_unthrottle, |
2672 | }; | 2688 | }; |
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 071a7db52549..b08dfdad08cb 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
@@ -513,6 +513,8 @@ struct perf_event; | |||
513 | struct pmu { | 513 | struct pmu { |
514 | int (*enable) (struct perf_event *event); | 514 | int (*enable) (struct perf_event *event); |
515 | void (*disable) (struct perf_event *event); | 515 | void (*disable) (struct perf_event *event); |
516 | int (*start) (struct perf_event *event); | ||
517 | void (*stop) (struct perf_event *event); | ||
516 | void (*read) (struct perf_event *event); | 518 | void (*read) (struct perf_event *event); |
517 | void (*unthrottle) (struct perf_event *event); | 519 | void (*unthrottle) (struct perf_event *event); |
518 | }; | 520 | }; |
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 5a69abb05ac3..74c60021cdbc 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -1493,6 +1493,22 @@ do { \ | |||
1493 | return div64_u64(dividend, divisor); | 1493 | return div64_u64(dividend, divisor); |
1494 | } | 1494 | } |
1495 | 1495 | ||
1496 | static void perf_event_stop(struct perf_event *event) | ||
1497 | { | ||
1498 | if (!event->pmu->stop) | ||
1499 | return event->pmu->disable(event); | ||
1500 | |||
1501 | return event->pmu->stop(event); | ||
1502 | } | ||
1503 | |||
1504 | static int perf_event_start(struct perf_event *event) | ||
1505 | { | ||
1506 | if (!event->pmu->start) | ||
1507 | return event->pmu->enable(event); | ||
1508 | |||
1509 | return event->pmu->start(event); | ||
1510 | } | ||
1511 | |||
1496 | static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) | 1512 | static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) |
1497 | { | 1513 | { |
1498 | struct hw_perf_event *hwc = &event->hw; | 1514 | struct hw_perf_event *hwc = &event->hw; |
@@ -1513,9 +1529,9 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) | |||
1513 | 1529 | ||
1514 | if (atomic64_read(&hwc->period_left) > 8*sample_period) { | 1530 | if (atomic64_read(&hwc->period_left) > 8*sample_period) { |
1515 | perf_disable(); | 1531 | perf_disable(); |
1516 | event->pmu->disable(event); | 1532 | perf_event_stop(event); |
1517 | atomic64_set(&hwc->period_left, 0); | 1533 | atomic64_set(&hwc->period_left, 0); |
1518 | event->pmu->enable(event); | 1534 | perf_event_start(event); |
1519 | perf_enable(); | 1535 | perf_enable(); |
1520 | } | 1536 | } |
1521 | } | 1537 | } |