static int qcom_l3_cache_pmu_probe()

in qcom_l3_pmu.c [729:800]


static int qcom_l3_cache_pmu_probe(struct platform_device *pdev)
{
	struct l3cache_pmu *l3pmu;
	struct acpi_device *acpi_dev;
	struct resource *memrc;
	int ret;
	char *name;

	/* Initialize the PMU data structures */

	acpi_dev = ACPI_COMPANION(&pdev->dev);
	if (!acpi_dev)
		return -ENODEV;

	l3pmu = devm_kzalloc(&pdev->dev, sizeof(*l3pmu), GFP_KERNEL);
	name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "l3cache_%s_%s",
		      acpi_dev->parent->pnp.unique_id, acpi_dev->pnp.unique_id);
	if (!l3pmu || !name)
		return -ENOMEM;

	l3pmu->pmu = (struct pmu) {
		.task_ctx_nr	= perf_invalid_context,

		.pmu_enable	= qcom_l3_cache__pmu_enable,
		.pmu_disable	= qcom_l3_cache__pmu_disable,
		.event_init	= qcom_l3_cache__event_init,
		.add		= qcom_l3_cache__event_add,
		.del		= qcom_l3_cache__event_del,
		.start		= qcom_l3_cache__event_start,
		.stop		= qcom_l3_cache__event_stop,
		.read		= qcom_l3_cache__event_read,

		.attr_groups	= qcom_l3_cache_pmu_attr_grps,
		.capabilities	= PERF_PMU_CAP_NO_EXCLUDE,
	};

	memrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	l3pmu->regs = devm_ioremap_resource(&pdev->dev, memrc);
	if (IS_ERR(l3pmu->regs))
		return PTR_ERR(l3pmu->regs);

	qcom_l3_cache__init(l3pmu);

	ret = platform_get_irq(pdev, 0);
	if (ret <= 0)
		return ret;

	ret = devm_request_irq(&pdev->dev, ret, qcom_l3_cache__handle_irq, 0,
			       name, l3pmu);
	if (ret) {
		dev_err(&pdev->dev, "Request for IRQ failed for slice @%pa\n",
			&memrc->start);
		return ret;
	}

	/* Add this instance to the list used by the offline callback */
	ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE, &l3pmu->node);
	if (ret) {
		dev_err(&pdev->dev, "Error %d registering hotplug", ret);
		return ret;
	}

	ret = perf_pmu_register(&l3pmu->pmu, name, -1);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to register L3 cache PMU (%d)\n", ret);
		return ret;
	}

	dev_info(&pdev->dev, "Registered %s, type: %d\n", name, l3pmu->pmu.type);

	return 0;
}