diff options
Diffstat (limited to 'arch/arm/kernel/perf_event_xscale.c')
| -rw-r--r-- | arch/arm/kernel/perf_event_xscale.c | 20 | 
1 files changed, 16 insertions, 4 deletions
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index 3b99d826982..71a21e6712f 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c @@ -255,11 +255,14 @@ xscale1pmu_handle_irq(int irq_num, void *dev)  		struct perf_event *event = cpuc->events[idx];  		struct hw_perf_event *hwc; +		if (!event) +			continue; +  		if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))  			continue;  		hwc = &event->hw; -		armpmu_event_update(event, hwc, idx, 1); +		armpmu_event_update(event, hwc, idx);  		data.period = event->hw.last_period;  		if (!armpmu_event_set_period(event, hwc, idx))  			continue; @@ -592,11 +595,14 @@ xscale2pmu_handle_irq(int irq_num, void *dev)  		struct perf_event *event = cpuc->events[idx];  		struct hw_perf_event *hwc; -		if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx)) +		if (!event) +			continue; + +		if (!xscale2_pmnc_counter_has_overflowed(of_flags, idx))  			continue;  		hwc = &event->hw; -		armpmu_event_update(event, hwc, idx, 1); +		armpmu_event_update(event, hwc, idx);  		data.period = event->hw.last_period;  		if (!armpmu_event_set_period(event, hwc, idx))  			continue; @@ -663,7 +669,7 @@ xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)  static void  xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)  { -	unsigned long flags, ien, evtsel; +	unsigned long flags, ien, evtsel, of_flags;  	struct pmu_hw_events *events = cpu_pmu->get_hw_events();  	ien = xscale2pmu_read_int_enable(); @@ -672,26 +678,31 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)  	switch (idx) {  	case XSCALE_CYCLE_COUNTER:  		ien &= ~XSCALE2_CCOUNT_INT_EN; +		of_flags = XSCALE2_CCOUNT_OVERFLOW;  		break;  	case XSCALE_COUNTER0:  		ien &= ~XSCALE2_COUNT0_INT_EN;  		evtsel &= ~XSCALE2_COUNT0_EVT_MASK;  		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT; +		of_flags = XSCALE2_COUNT0_OVERFLOW;  		break;  	case XSCALE_COUNTER1:  		ien &= ~XSCALE2_COUNT1_INT_EN;  		evtsel &= ~XSCALE2_COUNT1_EVT_MASK;  		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT; +		of_flags = XSCALE2_COUNT1_OVERFLOW;  		break;  	case XSCALE_COUNTER2:  		ien &= ~XSCALE2_COUNT2_INT_EN;  		evtsel &= ~XSCALE2_COUNT2_EVT_MASK;  		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT; +		of_flags = XSCALE2_COUNT2_OVERFLOW;  		break;  	case XSCALE_COUNTER3:  		ien &= ~XSCALE2_COUNT3_INT_EN;  		evtsel &= ~XSCALE2_COUNT3_EVT_MASK;  		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT; +		of_flags = XSCALE2_COUNT3_OVERFLOW;  		break;  	default:  		WARN_ONCE(1, "invalid counter number (%d)\n", idx); @@ -701,6 +712,7 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)  	raw_spin_lock_irqsave(&events->pmu_lock, flags);  	xscale2pmu_write_event_select(evtsel);  	xscale2pmu_write_int_enable(ien); +	xscale2pmu_write_overflow_flags(of_flags);  	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);  }  |