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

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.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 8fba38c9
...@@ -360,16 +360,16 @@ static void xgene_msi_isr(struct irq_desc *desc) ...@@ -360,16 +360,16 @@ static void xgene_msi_isr(struct irq_desc *desc)
chained_irq_exit(chip, desc); chained_irq_exit(chip, desc);
} }
static enum cpuhp_state pci_xgene_online;
static int xgene_msi_remove(struct platform_device *pdev) static int xgene_msi_remove(struct platform_device *pdev)
{ {
int virq, i;
struct xgene_msi *msi = platform_get_drvdata(pdev); struct xgene_msi *msi = platform_get_drvdata(pdev);
for (i = 0; i < NR_HW_IRQS; i++) { if (pci_xgene_online)
virq = msi->msi_groups[i].gic_irq; cpuhp_remove_state(pci_xgene_online);
if (virq != 0) cpuhp_remove_state(CPUHP_PCI_XGENE_DEAD);
irq_set_chained_handler_and_data(virq, NULL, NULL);
}
kfree(msi->msi_groups); kfree(msi->msi_groups);
kfree(msi->bitmap); kfree(msi->bitmap);
...@@ -427,7 +427,7 @@ static int xgene_msi_hwirq_alloc(unsigned int cpu) ...@@ -427,7 +427,7 @@ static int xgene_msi_hwirq_alloc(unsigned int cpu)
return 0; 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 *msi = &xgene_msi_ctrl;
struct xgene_msi_group *msi_group; struct xgene_msi_group *msi_group;
...@@ -441,33 +441,9 @@ static void xgene_msi_hwirq_free(unsigned int cpu) ...@@ -441,33 +441,9 @@ static void xgene_msi_hwirq_free(unsigned int cpu)
irq_set_chained_handler_and_data(msi_group->gic_irq, NULL, irq_set_chained_handler_and_data(msi_group->gic_irq, NULL,
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[] = { static const struct of_device_id xgene_msi_match_table[] = {
{.compatible = "apm,xgene1-msi"}, {.compatible = "apm,xgene1-msi"},
{}, {},
...@@ -478,7 +454,6 @@ static int xgene_msi_probe(struct platform_device *pdev) ...@@ -478,7 +454,6 @@ static int xgene_msi_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
int rc, irq_index; int rc, irq_index;
struct xgene_msi *xgene_msi; struct xgene_msi *xgene_msi;
unsigned int cpu;
int virt_msir; int virt_msir;
u32 msi_val, msi_idx; u32 msi_val, msi_idx;
...@@ -540,28 +515,22 @@ static int xgene_msi_probe(struct platform_device *pdev) ...@@ -540,28 +515,22 @@ static int xgene_msi_probe(struct platform_device *pdev)
} }
} }
cpu_notifier_register_begin(); rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/xgene:online",
xgene_msi_hwirq_alloc, NULL);
for_each_online_cpu(cpu) if (rc)
if (xgene_msi_hwirq_alloc(cpu)) { goto err_cpuhp;
dev_err(&pdev->dev, "failed to register MSI handlers\n"); pci_xgene_online = rc;
cpu_notifier_register_done(); rc = cpuhp_setup_state(CPUHP_PCI_XGENE_DEAD, "pci/xgene:dead", NULL,
goto error; xgene_msi_hwirq_free);
} if (rc)
goto err_cpuhp;
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();
dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n"); dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n");
return 0; return 0;
err_cpuhp:
dev_err(&pdev->dev, "failed to add CPU MSI notifier\n");
error: error:
xgene_msi_remove(pdev); xgene_msi_remove(pdev);
return rc; return rc;
......
...@@ -38,6 +38,7 @@ enum cpuhp_state { ...@@ -38,6 +38,7 @@ enum cpuhp_state {
CPUHP_RADIX_DEAD, CPUHP_RADIX_DEAD,
CPUHP_PAGE_ALLOC_DEAD, CPUHP_PAGE_ALLOC_DEAD,
CPUHP_NET_DEV_DEAD, CPUHP_NET_DEV_DEAD,
CPUHP_PCI_XGENE_DEAD,
CPUHP_WORKQUEUE_PREP, CPUHP_WORKQUEUE_PREP,
CPUHP_POWER_NUMA_PREPARE, CPUHP_POWER_NUMA_PREPARE,
CPUHP_HRTIMERS_PREPARE, CPUHP_HRTIMERS_PREPARE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment