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@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: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
Родитель
8fba38c937
Коммит
9c248f8896
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
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,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче