diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2016-11-17 13:35:28 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-11-22 17:34:40 -0500 |
commit | 9c248f8896e6bf0c77abb98bfea8d69b5a7cd11d (patch) | |
tree | d89f62258a35731619e5b526f5bb46a0b1af0e73 | |
parent | 8fba38c937cd585bcf562fda8db3decb25509506 (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.c | 69 | ||||
-rw-r--r-- | 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 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 | ||
363 | static enum cpuhp_state pci_xgene_online; | ||
364 | |||
363 | static int xgene_msi_remove(struct platform_device *pdev) | 365 | static 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 | ||
430 | static void xgene_msi_hwirq_free(unsigned int cpu) | 430 | static 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 | ||
446 | static 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 | |||
467 | static struct notifier_block xgene_msi_cpu_notifier = { | ||
468 | .notifier_call = xgene_msi_cpu_callback, | ||
469 | }; | ||
470 | |||
471 | static const struct of_device_id xgene_msi_match_table[] = { | 447 | static 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 | ||
532 | err_cpuhp: | ||
533 | dev_err(&pdev->dev, "failed to add CPU MSI notifier\n"); | ||
565 | error: | 534 | error: |
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, |