static int arc_pmu_add()

in kernel/perf_event.c [522:559]


static int arc_pmu_add(struct perf_event *event, int flags)
{
	struct arc_pmu_cpu *pmu_cpu = this_cpu_ptr(&arc_pmu_cpu);
	struct hw_perf_event *hwc = &event->hw;
	int idx;

	idx = ffz(pmu_cpu->used_mask[0]);
	if (idx == arc_pmu->n_counters)
		return -EAGAIN;

	__set_bit(idx, pmu_cpu->used_mask);
	hwc->idx = idx;

	write_aux_reg(ARC_REG_PCT_INDEX, idx);

	pmu_cpu->act_counter[idx] = event;

	if (is_sampling_event(event)) {
		/* Mimic full counter overflow as other arches do */
		write_aux_reg(ARC_REG_PCT_INT_CNTL,
			      lower_32_bits(arc_pmu->max_period));
		write_aux_reg(ARC_REG_PCT_INT_CNTH,
			      upper_32_bits(arc_pmu->max_period));
	}

	write_aux_reg(ARC_REG_PCT_CONFIG, 0);
	write_aux_reg(ARC_REG_PCT_COUNTL, 0);
	write_aux_reg(ARC_REG_PCT_COUNTH, 0);
	local64_set(&hwc->prev_count, 0);

	hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
	if (flags & PERF_EF_START)
		arc_pmu_start(event, PERF_EF_RELOAD);

	perf_event_update_userpage(event);

	return 0;
}