Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c248f88 authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Thomas Gleixner
Browse files

PCI/xgene-msi: Convert to hotplug state machine



Install the callbacks via the state machine and let the core invoke
the callbacks on the already online CPUs.

Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: linux-pci@vger.kernel.org
Cc: Duc Dang <dhdang@apm.com>
Cc: rt@linuxtronix.de
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-arm-kernel@lists.infradead.org
Link: http://lkml.kernel.org/r/20161117183541.8588-8-bigeasy@linutronix.de


Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 8fba38c9
Loading
Loading
Loading
Loading
+19 −50
Original line number Diff line number Diff line
@@ -360,16 +360,16 @@ static void xgene_msi_isr(struct irq_desc *desc)
	chained_irq_exit(chip, desc);
}

static enum cpuhp_state pci_xgene_online;

static int xgene_msi_remove(struct platform_device *pdev)
{
	int virq, i;
	struct xgene_msi *msi = platform_get_drvdata(pdev);

	for (i = 0; i < NR_HW_IRQS; i++) {
		virq = msi->msi_groups[i].gic_irq;
		if (virq != 0)
			irq_set_chained_handler_and_data(virq, NULL, NULL);
	}
	if (pci_xgene_online)
		cpuhp_remove_state(pci_xgene_online);
	cpuhp_remove_state(CPUHP_PCI_XGENE_DEAD);

	kfree(msi->msi_groups);

	kfree(msi->bitmap);
@@ -427,7 +427,7 @@ static int xgene_msi_hwirq_alloc(unsigned int cpu)
	return 0;
}

static void xgene_msi_hwirq_free(unsigned int cpu)
static int xgene_msi_hwirq_free(unsigned int cpu)
{
	struct xgene_msi *msi = &xgene_msi_ctrl;
	struct xgene_msi_group *msi_group;
@@ -441,33 +441,9 @@ static void xgene_msi_hwirq_free(unsigned int cpu)
		irq_set_chained_handler_and_data(msi_group->gic_irq, NULL,
						 NULL);
	}
	return 0;
}

static int xgene_msi_cpu_callback(struct notifier_block *nfb,
				  unsigned long action, void *hcpu)
{
	unsigned cpu = (unsigned long)hcpu;

	switch (action) {
	case CPU_ONLINE:
	case CPU_ONLINE_FROZEN:
		xgene_msi_hwirq_alloc(cpu);
		break;
	case CPU_DEAD:
	case CPU_DEAD_FROZEN:
		xgene_msi_hwirq_free(cpu);
		break;
	default:
		break;
	}

	return NOTIFY_OK;
}

static struct notifier_block xgene_msi_cpu_notifier = {
	.notifier_call = xgene_msi_cpu_callback,
};

static const struct of_device_id xgene_msi_match_table[] = {
	{.compatible = "apm,xgene1-msi"},
	{},
@@ -478,7 +454,6 @@ static int xgene_msi_probe(struct platform_device *pdev)
	struct resource *res;
	int rc, irq_index;
	struct xgene_msi *xgene_msi;
	unsigned int cpu;
	int virt_msir;
	u32 msi_val, msi_idx;

@@ -540,28 +515,22 @@ static int xgene_msi_probe(struct platform_device *pdev)
		}
	}

	cpu_notifier_register_begin();

	for_each_online_cpu(cpu)
		if (xgene_msi_hwirq_alloc(cpu)) {
			dev_err(&pdev->dev, "failed to register MSI handlers\n");
			cpu_notifier_register_done();
			goto error;
		}

	rc = __register_hotcpu_notifier(&xgene_msi_cpu_notifier);
	if (rc) {
		dev_err(&pdev->dev, "failed to add CPU MSI notifier\n");
		cpu_notifier_register_done();
		goto error;
	}

	cpu_notifier_register_done();
	rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/xgene:online",
			       xgene_msi_hwirq_alloc, NULL);
	if (rc)
		goto err_cpuhp;
	pci_xgene_online = rc;
	rc = cpuhp_setup_state(CPUHP_PCI_XGENE_DEAD, "pci/xgene:dead", NULL,
			       xgene_msi_hwirq_free);
	if (rc)
		goto err_cpuhp;

	dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n");

	return 0;

err_cpuhp:
	dev_err(&pdev->dev, "failed to add CPU MSI notifier\n");
error:
	xgene_msi_remove(pdev);
	return rc;
+1 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ enum cpuhp_state {
	CPUHP_RADIX_DEAD,
	CPUHP_PAGE_ALLOC_DEAD,
	CPUHP_NET_DEV_DEAD,
	CPUHP_PCI_XGENE_DEAD,
	CPUHP_WORKQUEUE_PREP,
	CPUHP_POWER_NUMA_PREPARE,
	CPUHP_HRTIMERS_PREPARE,