aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/perf_event.c24
-rw-r--r--include/linux/perf_event.h2
-rw-r--r--kernel/perf_event.c20
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
1498static void __x86_pmu_disable(struct perf_event *event, struct cpu_hw_events *cpuc); 1498static void x86_pmu_stop(struct perf_event *event);
1499 1499
1500void hw_perf_enable(void) 1500void 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
1804static 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
1804static void x86_pmu_unthrottle(struct perf_event *event) 1817static 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
1927static void __x86_pmu_disable(struct perf_event *event, struct cpu_hw_events *cpuc) 1940static 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)
2667static const struct pmu pmu = { 2681static 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;
513struct pmu { 513struct 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
1496static 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
1504static 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
1496static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) 1512static 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}