[tip:smp/hotplug] PCI/xgene-msi: Convert to hotplug state machine

From: tip-bot for Sebastian Andrzej Siewior
Date: Tue Nov 22 2016 - 18:15:30 EST


Commit-ID: 9c248f8896e6bf0c77abb98bfea8d69b5a7cd11d
Gitweb: http://git.kernel.org/tip/9c248f8896e6bf0c77abb98bfea8d69b5a7cd11d
Author: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
AuthorDate: Thu, 17 Nov 2016 19:35:28 +0100
Committer: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
CommitDate: Tue, 22 Nov 2016 23:34:40 +0100

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: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
Cc: linux-pci@xxxxxxxxxxxxxxx
Cc: Duc Dang <dhdang@xxxxxxx>
Cc: rt@xxxxxxxxxxxxxx
Cc: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx
Link: http://lkml.kernel.org/r/20161117183541.8588-8-bigeasy@xxxxxxxxxxxxx
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>

---
drivers/pci/host/pci-xgene-msi.c | 69 +++++++++++-----------------------------
include/linux/cpuhotplug.h | 1 +
2 files changed, 20 insertions(+), 50 deletions(-)

diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
index a6456b5..1f38d08 100644
--- a/drivers/pci/host/pci-xgene-msi.c
+++ b/drivers/pci/host/pci-xgene-msi.c
@@ -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;
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 79b96f6..94c6a18 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -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,