diff options
Diffstat (limited to 'arch/alpha/kernel/perf_event.c')
| -rw-r--r-- | arch/alpha/kernel/perf_event.c | 71 | 
1 files changed, 53 insertions, 18 deletions
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c index 3e260731f8e..380ef02d557 100644 --- a/arch/alpha/kernel/perf_event.c +++ b/arch/alpha/kernel/perf_event.c @@ -307,7 +307,7 @@ again:  			     new_raw_count) != prev_raw_count)  		goto again; -	delta = (new_raw_count  - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf; +	delta = (new_raw_count - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;  	/* It is possible on very rare occasions that the PMC has overflowed  	 * but the interrupt is yet to come.  Detect and fix this situation. @@ -402,14 +402,13 @@ static void maybe_change_configuration(struct cpu_hw_events *cpuc)  		struct hw_perf_event *hwc = &pe->hw;  		int idx = hwc->idx; -		if (cpuc->current_idx[j] != PMC_NO_INDEX) { -			cpuc->idx_mask |= (1<<cpuc->current_idx[j]); -			continue; +		if (cpuc->current_idx[j] == PMC_NO_INDEX) { +			alpha_perf_event_set_period(pe, hwc, idx); +			cpuc->current_idx[j] = idx;  		} -		alpha_perf_event_set_period(pe, hwc, idx); -		cpuc->current_idx[j] = idx; -		cpuc->idx_mask |= (1<<cpuc->current_idx[j]); +		if (!(hwc->state & PERF_HES_STOPPED)) +			cpuc->idx_mask |= (1<<cpuc->current_idx[j]);  	}  	cpuc->config = cpuc->event[0]->hw.config_base;  } @@ -420,7 +419,7 @@ static void maybe_change_configuration(struct cpu_hw_events *cpuc)   *  - this function is called from outside this module via the pmu struct   *    returned from perf event initialisation.   */ -static int alpha_pmu_enable(struct perf_event *event) +static int alpha_pmu_add(struct perf_event *event, int flags)  {  	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);  	int n0; @@ -455,6 +454,10 @@ static int alpha_pmu_enable(struct perf_event *event)  		}  	} +	hwc->state = PERF_HES_UPTODATE; +	if (!(flags & PERF_EF_START)) +		hwc->state |= PERF_HES_STOPPED; +  	local_irq_restore(flags);  	perf_pmu_enable(event->pmu); @@ -467,7 +470,7 @@ static int alpha_pmu_enable(struct perf_event *event)   *  - this function is called from outside this module via the pmu struct   *    returned from perf event initialisation.   */ -static void alpha_pmu_disable(struct perf_event *event) +static void alpha_pmu_del(struct perf_event *event, int flags)  {  	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);  	struct hw_perf_event *hwc = &event->hw; @@ -514,13 +517,44 @@ static void alpha_pmu_read(struct perf_event *event)  } -static void alpha_pmu_unthrottle(struct perf_event *event) +static void alpha_pmu_stop(struct perf_event *event, int flags)  {  	struct hw_perf_event *hwc = &event->hw;  	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); +	if (!(hwc->state & PERF_HES_STOPPED)) { +		cpuc->idx_mask &= !(1UL<<hwc->idx); +		hwc->state |= PERF_HES_STOPPED; +	} + +	if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { +		alpha_perf_event_update(event, hwc, hwc->idx, 0); +		hwc->state |= PERF_HES_UPTODATE; +	} + +	if (cpuc->enabled) +		wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx)); +} + + +static void alpha_pmu_start(struct perf_event *event, int flags) +{ +	struct hw_perf_event *hwc = &event->hw; +	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + +	if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) +		return; + +	if (flags & PERF_EF_RELOAD) { +		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); +		alpha_perf_event_set_period(event, hwc, hwc->idx); +	} + +	hwc->state = 0; +  	cpuc->idx_mask |= 1UL<<hwc->idx; -	wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx)); +	if (cpuc->enabled) +		wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));  } @@ -671,7 +705,7 @@ static int alpha_pmu_event_init(struct perf_event *event)  /*   * Main entry point - enable HW performance counters.   */ -static void alpha_pmu_pmu_enable(struct pmu *pmu) +static void alpha_pmu_enable(struct pmu *pmu)  {  	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -697,7 +731,7 @@ static void alpha_pmu_pmu_enable(struct pmu *pmu)   * Main entry point - disable HW performance counters.   */ -static void alpha_pmu_pmu_disable(struct pmu *pmu) +static void alpha_pmu_disable(struct pmu *pmu)  {  	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -711,13 +745,14 @@ static void alpha_pmu_pmu_disable(struct pmu *pmu)  }  static struct pmu pmu = { -	.pmu_enable	= alpha_pmu_pmu_enable, -	.pmu_disable	= alpha_pmu_pmu_disable, +	.pmu_enable	= alpha_pmu_enable, +	.pmu_disable	= alpha_pmu_disable,  	.event_init	= alpha_pmu_event_init, -	.enable		= alpha_pmu_enable, -	.disable	= alpha_pmu_disable, +	.add		= alpha_pmu_add, +	.del		= alpha_pmu_del, +	.start		= alpha_pmu_start, +	.stop		= alpha_pmu_stop,  	.read		= alpha_pmu_read, -	.unthrottle	= alpha_pmu_unthrottle,  };  |