static int arm_cmn_validate_group()

in arm-cmn.c [1133:1196]


static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
{
	struct arm_cmn_hw_event *hw = to_cmn_hw(event);
	struct arm_cmn_node *dn;
	struct perf_event *sibling, *leader = event->group_leader;
	enum cmn_node_type type;
	struct arm_cmn_val *val;
	int i, ret = -EINVAL;
	u8 occupid;

	if (leader == event)
		return 0;

	if (event->pmu != leader->pmu && !is_software_event(leader))
		return -EINVAL;

	val = kzalloc(sizeof(*val), GFP_KERNEL);
	if (!val)
		return -ENOMEM;

	arm_cmn_val_add_event(cmn, val, leader);
	for_each_sibling_event(sibling, leader)
		arm_cmn_val_add_event(cmn, val, sibling);

	type = CMN_EVENT_TYPE(event);
	if (type == CMN_TYPE_DTC) {
		ret = val->cycles ? -EINVAL : 0;
		goto done;
	}

	if (val->dtc_count == CMN_DT_NUM_COUNTERS)
		goto done;

	if (arm_cmn_is_occup_event(cmn->model, type, CMN_EVENT_EVENTID(event)))
		occupid = CMN_EVENT_OCCUPID(event) + 1;
	else
		occupid = 0;

	for_each_hw_dn(hw, dn, i) {
		int wp_idx, wp_cmb, dtm = dn->dtm;

		if (val->dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
			goto done;

		if (occupid && val->occupid[dtm] && occupid != val->occupid[dtm])
			goto done;

		if (type != CMN_TYPE_WP)
			continue;

		wp_idx = arm_cmn_wp_idx(event);
		if (val->wp[dtm][wp_idx])
			goto done;

		wp_cmb = val->wp[dtm][wp_idx ^ 1];
		if (wp_cmb && wp_cmb != CMN_EVENT_WP_COMBINE(event) + 1)
			goto done;
	}

	ret = 0;
done:
	kfree(val);
	return ret;
}