static int cci_pmu_probe()

in arm-cci.c [1642:1702]


static int cci_pmu_probe(struct platform_device *pdev)
{
	struct cci_pmu *cci_pmu;
	int i, ret, irq;

	cci_pmu = cci_pmu_alloc(&pdev->dev);
	if (IS_ERR(cci_pmu))
		return PTR_ERR(cci_pmu);

	cci_pmu->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(cci_pmu->base))
		return -ENOMEM;

	/*
	 * CCI PMU has one overflow interrupt per counter; but some may be tied
	 * together to a common interrupt.
	 */
	cci_pmu->nr_irqs = 0;
	for (i = 0; i < CCI_PMU_MAX_HW_CNTRS(cci_pmu->model); i++) {
		irq = platform_get_irq(pdev, i);
		if (irq < 0)
			break;

		if (is_duplicate_irq(irq, cci_pmu->irqs, cci_pmu->nr_irqs))
			continue;

		cci_pmu->irqs[cci_pmu->nr_irqs++] = irq;
	}

	/*
	 * Ensure that the device tree has as many interrupts as the number
	 * of counters.
	 */
	if (i < CCI_PMU_MAX_HW_CNTRS(cci_pmu->model)) {
		dev_warn(&pdev->dev, "In-correct number of interrupts: %d, should be %d\n",
			i, CCI_PMU_MAX_HW_CNTRS(cci_pmu->model));
		return -EINVAL;
	}

	raw_spin_lock_init(&cci_pmu->hw_events.pmu_lock);
	mutex_init(&cci_pmu->reserve_mutex);
	atomic_set(&cci_pmu->active_events, 0);

	cci_pmu->cpu = raw_smp_processor_id();
	g_cci_pmu = cci_pmu;
	cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_CCI_ONLINE,
				  "perf/arm/cci:online", NULL,
				  cci_pmu_offline_cpu);

	ret = cci_pmu_init(cci_pmu, pdev);
	if (ret)
		goto error_pmu_init;

	pr_info("ARM %s PMU driver probed", cci_pmu->model->name);
	return 0;

error_pmu_init:
	cpuhp_remove_state(CPUHP_AP_PERF_ARM_CCI_ONLINE);
	g_cci_pmu = NULL;
	return ret;
}