aboutsummaryrefslogtreecommitdiffstats
path: root/net/iucv
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-12 22:25:04 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-12 22:25:04 -0500
commite71c3978d6f97659f6c3ee942c3e581299e4adf2 (patch)
tree0b58c76a20a79f5f5d9ada5731aa1dbb149fbcdc /net/iucv
parentf797484c26300fec842fb669c69a3a60eb66e240 (diff)
parentb18cc3de00ec3442cf40ac60787dbe0703b99e24 (diff)
Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull smp hotplug updates from Thomas Gleixner: "This is the final round of converting the notifier mess to the state machine. The removal of the notifiers and the related infrastructure will happen around rc1, as there are conversions outstanding in other trees. The whole exercise removed about 2000 lines of code in total and in course of the conversion several dozen bugs got fixed. The new mechanism allows to test almost every hotplug step standalone, so usage sites can exercise all transitions extensively. There is more room for improvement, like integrating all the pointlessly different architecture mechanisms of synchronizing, setting cpus online etc into the core code" * 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (60 commits) tracing/rb: Init the CPU mask on allocation soc/fsl/qbman: Convert to hotplug state machine soc/fsl/qbman: Convert to hotplug state machine zram: Convert to hotplug state machine KVM/PPC/Book3S HV: Convert to hotplug state machine arm64/cpuinfo: Convert to hotplug state machine arm64/cpuinfo: Make hotplug notifier symmetric mm/compaction: Convert to hotplug state machine iommu/vt-d: Convert to hotplug state machine mm/zswap: Convert pool to hotplug state machine mm/zswap: Convert dst-mem to hotplug state machine mm/zsmalloc: Convert to hotplug state machine mm/vmstat: Convert to hotplug state machine mm/vmstat: Avoid on each online CPU loops mm/vmstat: Drop get_online_cpus() from init_cpu_node_state/vmstat_cpu_dead() tracing/rb: Convert to hotplug state machine oprofile/nmi timer: Convert to hotplug state machine net/iucv: Use explicit clean up labels in iucv_init() x86/pci/amd-bus: Convert to hotplug state machine x86/oprofile/nmi: Convert to hotplug state machine ...
Diffstat (limited to 'net/iucv')
-rw-r--r--net/iucv/iucv.c124
1 files changed, 47 insertions, 77 deletions
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 88a2a3ba4212..8f7ef167c45a 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -639,7 +639,7 @@ static void iucv_disable(void)
639 put_online_cpus(); 639 put_online_cpus();
640} 640}
641 641
642static void free_iucv_data(int cpu) 642static int iucv_cpu_dead(unsigned int cpu)
643{ 643{
644 kfree(iucv_param_irq[cpu]); 644 kfree(iucv_param_irq[cpu]);
645 iucv_param_irq[cpu] = NULL; 645 iucv_param_irq[cpu] = NULL;
@@ -647,9 +647,10 @@ static void free_iucv_data(int cpu)
647 iucv_param[cpu] = NULL; 647 iucv_param[cpu] = NULL;
648 kfree(iucv_irq_data[cpu]); 648 kfree(iucv_irq_data[cpu]);
649 iucv_irq_data[cpu] = NULL; 649 iucv_irq_data[cpu] = NULL;
650 return 0;
650} 651}
651 652
652static int alloc_iucv_data(int cpu) 653static int iucv_cpu_prepare(unsigned int cpu)
653{ 654{
654 /* Note: GFP_DMA used to get memory below 2G */ 655 /* Note: GFP_DMA used to get memory below 2G */
655 iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), 656 iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data),
@@ -671,58 +672,38 @@ static int alloc_iucv_data(int cpu)
671 return 0; 672 return 0;
672 673
673out_free: 674out_free:
674 free_iucv_data(cpu); 675 iucv_cpu_dead(cpu);
675 return -ENOMEM; 676 return -ENOMEM;
676} 677}
677 678
678static int iucv_cpu_notify(struct notifier_block *self, 679static int iucv_cpu_online(unsigned int cpu)
679 unsigned long action, void *hcpu)
680{ 680{
681 cpumask_t cpumask; 681 if (!iucv_path_table)
682 long cpu = (long) hcpu; 682 return 0;
683 683 iucv_declare_cpu(NULL);
684 switch (action) { 684 return 0;
685 case CPU_UP_PREPARE:
686 case CPU_UP_PREPARE_FROZEN:
687 if (alloc_iucv_data(cpu))
688 return notifier_from_errno(-ENOMEM);
689 break;
690 case CPU_UP_CANCELED:
691 case CPU_UP_CANCELED_FROZEN:
692 case CPU_DEAD:
693 case CPU_DEAD_FROZEN:
694 free_iucv_data(cpu);
695 break;
696 case CPU_ONLINE:
697 case CPU_ONLINE_FROZEN:
698 case CPU_DOWN_FAILED:
699 case CPU_DOWN_FAILED_FROZEN:
700 if (!iucv_path_table)
701 break;
702 smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
703 break;
704 case CPU_DOWN_PREPARE:
705 case CPU_DOWN_PREPARE_FROZEN:
706 if (!iucv_path_table)
707 break;
708 cpumask_copy(&cpumask, &iucv_buffer_cpumask);
709 cpumask_clear_cpu(cpu, &cpumask);
710 if (cpumask_empty(&cpumask))
711 /* Can't offline last IUCV enabled cpu. */
712 return notifier_from_errno(-EINVAL);
713 smp_call_function_single(cpu, iucv_retrieve_cpu, NULL, 1);
714 if (cpumask_empty(&iucv_irq_cpumask))
715 smp_call_function_single(
716 cpumask_first(&iucv_buffer_cpumask),
717 iucv_allow_cpu, NULL, 1);
718 break;
719 }
720 return NOTIFY_OK;
721} 685}
722 686
723static struct notifier_block __refdata iucv_cpu_notifier = { 687static int iucv_cpu_down_prep(unsigned int cpu)
724 .notifier_call = iucv_cpu_notify, 688{
725}; 689 cpumask_t cpumask;
690
691 if (!iucv_path_table)
692 return 0;
693
694 cpumask_copy(&cpumask, &iucv_buffer_cpumask);
695 cpumask_clear_cpu(cpu, &cpumask);
696 if (cpumask_empty(&cpumask))
697 /* Can't offline last IUCV enabled cpu. */
698 return -EINVAL;
699
700 iucv_retrieve_cpu(NULL);
701 if (!cpumask_empty(&iucv_irq_cpumask))
702 return 0;
703 smp_call_function_single(cpumask_first(&iucv_buffer_cpumask),
704 iucv_allow_cpu, NULL, 1);
705 return 0;
706}
726 707
727/** 708/**
728 * iucv_sever_pathid 709 * iucv_sever_pathid
@@ -2027,6 +2008,7 @@ struct iucv_interface iucv_if = {
2027}; 2008};
2028EXPORT_SYMBOL(iucv_if); 2009EXPORT_SYMBOL(iucv_if);
2029 2010
2011static enum cpuhp_state iucv_online;
2030/** 2012/**
2031 * iucv_init 2013 * iucv_init
2032 * 2014 *
@@ -2035,7 +2017,6 @@ EXPORT_SYMBOL(iucv_if);
2035static int __init iucv_init(void) 2017static int __init iucv_init(void)
2036{ 2018{
2037 int rc; 2019 int rc;
2038 int cpu;
2039 2020
2040 if (!MACHINE_IS_VM) { 2021 if (!MACHINE_IS_VM) {
2041 rc = -EPROTONOSUPPORT; 2022 rc = -EPROTONOSUPPORT;
@@ -2054,23 +2035,19 @@ static int __init iucv_init(void)
2054 goto out_int; 2035 goto out_int;
2055 } 2036 }
2056 2037
2057 cpu_notifier_register_begin(); 2038 rc = cpuhp_setup_state(CPUHP_NET_IUCV_PREPARE, "net/iucv:prepare",
2058 2039 iucv_cpu_prepare, iucv_cpu_dead);
2059 for_each_online_cpu(cpu) {
2060 if (alloc_iucv_data(cpu)) {
2061 rc = -ENOMEM;
2062 goto out_free;
2063 }
2064 }
2065 rc = __register_hotcpu_notifier(&iucv_cpu_notifier);
2066 if (rc) 2040 if (rc)
2067 goto out_free; 2041 goto out_dev;
2068 2042 rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "net/iucv:online",
2069 cpu_notifier_register_done(); 2043 iucv_cpu_online, iucv_cpu_down_prep);
2044 if (rc < 0)
2045 goto out_prep;
2046 iucv_online = rc;
2070 2047
2071 rc = register_reboot_notifier(&iucv_reboot_notifier); 2048 rc = register_reboot_notifier(&iucv_reboot_notifier);
2072 if (rc) 2049 if (rc)
2073 goto out_cpu; 2050 goto out_remove_hp;
2074 ASCEBC(iucv_error_no_listener, 16); 2051 ASCEBC(iucv_error_no_listener, 16);
2075 ASCEBC(iucv_error_no_memory, 16); 2052 ASCEBC(iucv_error_no_memory, 16);
2076 ASCEBC(iucv_error_pathid, 16); 2053 ASCEBC(iucv_error_pathid, 16);
@@ -2084,15 +2061,11 @@ static int __init iucv_init(void)
2084 2061
2085out_reboot: 2062out_reboot:
2086 unregister_reboot_notifier(&iucv_reboot_notifier); 2063 unregister_reboot_notifier(&iucv_reboot_notifier);
2087out_cpu: 2064out_remove_hp:
2088 cpu_notifier_register_begin(); 2065 cpuhp_remove_state(iucv_online);
2089 __unregister_hotcpu_notifier(&iucv_cpu_notifier); 2066out_prep:
2090out_free: 2067 cpuhp_remove_state(CPUHP_NET_IUCV_PREPARE);
2091 for_each_possible_cpu(cpu) 2068out_dev:
2092 free_iucv_data(cpu);
2093
2094 cpu_notifier_register_done();
2095
2096 root_device_unregister(iucv_root); 2069 root_device_unregister(iucv_root);
2097out_int: 2070out_int:
2098 unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt); 2071 unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt);
@@ -2110,7 +2083,6 @@ out:
2110static void __exit iucv_exit(void) 2083static void __exit iucv_exit(void)
2111{ 2084{
2112 struct iucv_irq_list *p, *n; 2085 struct iucv_irq_list *p, *n;
2113 int cpu;
2114 2086
2115 spin_lock_irq(&iucv_queue_lock); 2087 spin_lock_irq(&iucv_queue_lock);
2116 list_for_each_entry_safe(p, n, &iucv_task_queue, list) 2088 list_for_each_entry_safe(p, n, &iucv_task_queue, list)
@@ -2119,11 +2091,9 @@ static void __exit iucv_exit(void)
2119 kfree(p); 2091 kfree(p);
2120 spin_unlock_irq(&iucv_queue_lock); 2092 spin_unlock_irq(&iucv_queue_lock);
2121 unregister_reboot_notifier(&iucv_reboot_notifier); 2093 unregister_reboot_notifier(&iucv_reboot_notifier);
2122 cpu_notifier_register_begin(); 2094
2123 __unregister_hotcpu_notifier(&iucv_cpu_notifier); 2095 cpuhp_remove_state_nocalls(iucv_online);
2124 for_each_possible_cpu(cpu) 2096 cpuhp_remove_state(CPUHP_NET_IUCV_PREPARE);
2125 free_iucv_data(cpu);
2126 cpu_notifier_register_done();
2127 root_device_unregister(iucv_root); 2097 root_device_unregister(iucv_root);
2128 bus_unregister(&iucv_bus); 2098 bus_unregister(&iucv_bus);
2129 unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt); 2099 unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt);