aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2016-11-17 13:35:28 -0500
committerThomas Gleixner <tglx@linutronix.de>2016-11-22 17:34:40 -0500
commit9c248f8896e6bf0c77abb98bfea8d69b5a7cd11d (patch)
treed89f62258a35731619e5b526f5bb46a0b1af0e73
parent8fba38c937cd585bcf562fda8db3decb25509506 (diff)
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>
-rw-r--r--drivers/pci/host/pci-xgene-msi.c69
-rw-r--r--include/linux/cpuhotplug.h1
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 a6456b578269..1f38d0836751 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)
360 chained_irq_exit(chip, desc); 360 chained_irq_exit(chip, desc);
361} 361}
362 362
363static enum cpuhp_state pci_xgene_online;
364
363static int xgene_msi_remove(struct platform_device *pdev) 365static int xgene_msi_remove(struct platform_device *pdev)
364{ 366{
365 int virq, i;
366 struct xgene_msi *msi = platform_get_drvdata(pdev); 367 struct xgene_msi *msi = platform_get_drvdata(pdev);
367 368
368 for (i = 0; i < NR_HW_IRQS; i++) { 369 if (pci_xgene_online)
369 virq = msi->msi_groups[i].gic_irq; 370 cpuhp_remove_state(pci_xgene_online);
370 if (virq != 0) 371 cpuhp_remove_state(CPUHP_PCI_XGENE_DEAD);
371 irq_set_chained_handler_and_data(virq, NULL, NULL); 372
372 }
373 kfree(msi->msi_groups); 373 kfree(msi->msi_groups);
374 374
375 kfree(msi->bitmap); 375 kfree(msi->bitmap);
@@ -427,7 +427,7 @@ static int xgene_msi_hwirq_alloc(unsigned int cpu)
427 return 0; 427 return 0;
428} 428}
429 429
430static void xgene_msi_hwirq_free(unsigned int cpu) 430static int xgene_msi_hwirq_free(unsigned int cpu)
431{ 431{
432 struct xgene_msi *msi = &xgene_msi_ctrl; 432 struct xgene_msi *msi = &xgene_msi_ctrl;
433 struct xgene_msi_group *msi_group; 433 struct xgene_msi_group *msi_group;
@@ -441,33 +441,9 @@ static void xgene_msi_hwirq_free(unsigned int cpu)
441 irq_set_chained_handler_and_data(msi_group->gic_irq, NULL, 441 irq_set_chained_handler_and_data(msi_group->gic_irq, NULL,
442 NULL); 442 NULL);
443 } 443 }
444 return 0;
444} 445}
445 446
446static int xgene_msi_cpu_callback(struct notifier_block *nfb,
447 unsigned long action, void *hcpu)
448{
449 unsigned cpu = (unsigned long)hcpu;
450
451 switch (action) {
452 case CPU_ONLINE:
453 case CPU_ONLINE_FROZEN:
454 xgene_msi_hwirq_alloc(cpu);
455 break;
456 case CPU_DEAD:
457 case CPU_DEAD_FROZEN:
458 xgene_msi_hwirq_free(cpu);
459 break;
460 default:
461 break;
462 }
463
464 return NOTIFY_OK;
465}
466
467static struct notifier_block xgene_msi_cpu_notifier = {
468 .notifier_call = xgene_msi_cpu_callback,
469};
470
471static const struct of_device_id xgene_msi_match_table[] = { 447static const struct of_device_id xgene_msi_match_table[] = {
472 {.compatible = "apm,xgene1-msi"}, 448 {.compatible = "apm,xgene1-msi"},
473 {}, 449 {},
@@ -478,7 +454,6 @@ static int xgene_msi_probe(struct platform_device *pdev)
478 struct resource *res; 454 struct resource *res;
479 int rc, irq_index; 455 int rc, irq_index;
480 struct xgene_msi *xgene_msi; 456 struct xgene_msi *xgene_msi;
481 unsigned int cpu;
482 int virt_msir; 457 int virt_msir;
483 u32 msi_val, msi_idx; 458 u32 msi_val, msi_idx;
484 459
@@ -540,28 +515,22 @@ static int xgene_msi_probe(struct platform_device *pdev)
540 } 515 }
541 } 516 }
542 517
543 cpu_notifier_register_begin(); 518 rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/xgene:online",
544 519 xgene_msi_hwirq_alloc, NULL);
545 for_each_online_cpu(cpu) 520 if (rc)
546 if (xgene_msi_hwirq_alloc(cpu)) { 521 goto err_cpuhp;
547 dev_err(&pdev->dev, "failed to register MSI handlers\n"); 522 pci_xgene_online = rc;
548 cpu_notifier_register_done(); 523 rc = cpuhp_setup_state(CPUHP_PCI_XGENE_DEAD, "pci/xgene:dead", NULL,
549 goto error; 524 xgene_msi_hwirq_free);
550 } 525 if (rc)
551 526 goto err_cpuhp;
552 rc = __register_hotcpu_notifier(&xgene_msi_cpu_notifier);
553 if (rc) {
554 dev_err(&pdev->dev, "failed to add CPU MSI notifier\n");
555 cpu_notifier_register_done();
556 goto error;
557 }
558
559 cpu_notifier_register_done();
560 527
561 dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n"); 528 dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n");
562 529
563 return 0; 530 return 0;
564 531
532err_cpuhp:
533 dev_err(&pdev->dev, "failed to add CPU MSI notifier\n");
565error: 534error:
566 xgene_msi_remove(pdev); 535 xgene_msi_remove(pdev);
567 return rc; 536 return rc;
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 79b96f647d64..94c6a189421f 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -38,6 +38,7 @@ enum cpuhp_state {
38 CPUHP_RADIX_DEAD, 38 CPUHP_RADIX_DEAD,
39 CPUHP_PAGE_ALLOC_DEAD, 39 CPUHP_PAGE_ALLOC_DEAD,
40 CPUHP_NET_DEV_DEAD, 40 CPUHP_NET_DEV_DEAD,
41 CPUHP_PCI_XGENE_DEAD,
41 CPUHP_WORKQUEUE_PREP, 42 CPUHP_WORKQUEUE_PREP,
42 CPUHP_POWER_NUMA_PREPARE, 43 CPUHP_POWER_NUMA_PREPARE,
43 CPUHP_HRTIMERS_PREPARE, 44 CPUHP_HRTIMERS_PREPARE,