diff options
Diffstat (limited to 'net/iucv')
-rw-r--r-- | net/iucv/iucv.c | 121 |
1 files changed, 57 insertions, 64 deletions
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index cd5b8ec9be04..79a0ce95799f 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -621,6 +621,42 @@ static void iucv_disable(void) | |||
621 | put_online_cpus(); | 621 | put_online_cpus(); |
622 | } | 622 | } |
623 | 623 | ||
624 | static void free_iucv_data(int cpu) | ||
625 | { | ||
626 | kfree(iucv_param_irq[cpu]); | ||
627 | iucv_param_irq[cpu] = NULL; | ||
628 | kfree(iucv_param[cpu]); | ||
629 | iucv_param[cpu] = NULL; | ||
630 | kfree(iucv_irq_data[cpu]); | ||
631 | iucv_irq_data[cpu] = NULL; | ||
632 | } | ||
633 | |||
634 | static int alloc_iucv_data(int cpu) | ||
635 | { | ||
636 | /* Note: GFP_DMA used to get memory below 2G */ | ||
637 | iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), | ||
638 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
639 | if (!iucv_irq_data[cpu]) | ||
640 | goto out_free; | ||
641 | |||
642 | /* Allocate parameter blocks. */ | ||
643 | iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
644 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
645 | if (!iucv_param[cpu]) | ||
646 | goto out_free; | ||
647 | |||
648 | iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
649 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
650 | if (!iucv_param_irq[cpu]) | ||
651 | goto out_free; | ||
652 | |||
653 | return 0; | ||
654 | |||
655 | out_free: | ||
656 | free_iucv_data(cpu); | ||
657 | return -ENOMEM; | ||
658 | } | ||
659 | |||
624 | static int iucv_cpu_notify(struct notifier_block *self, | 660 | static int iucv_cpu_notify(struct notifier_block *self, |
625 | unsigned long action, void *hcpu) | 661 | unsigned long action, void *hcpu) |
626 | { | 662 | { |
@@ -630,38 +666,14 @@ static int iucv_cpu_notify(struct notifier_block *self, | |||
630 | switch (action) { | 666 | switch (action) { |
631 | case CPU_UP_PREPARE: | 667 | case CPU_UP_PREPARE: |
632 | case CPU_UP_PREPARE_FROZEN: | 668 | case CPU_UP_PREPARE_FROZEN: |
633 | iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), | 669 | if (alloc_iucv_data(cpu)) |
634 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
635 | if (!iucv_irq_data[cpu]) | ||
636 | return notifier_from_errno(-ENOMEM); | ||
637 | |||
638 | iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
639 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
640 | if (!iucv_param[cpu]) { | ||
641 | kfree(iucv_irq_data[cpu]); | ||
642 | iucv_irq_data[cpu] = NULL; | ||
643 | return notifier_from_errno(-ENOMEM); | 670 | return notifier_from_errno(-ENOMEM); |
644 | } | ||
645 | iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
646 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
647 | if (!iucv_param_irq[cpu]) { | ||
648 | kfree(iucv_param[cpu]); | ||
649 | iucv_param[cpu] = NULL; | ||
650 | kfree(iucv_irq_data[cpu]); | ||
651 | iucv_irq_data[cpu] = NULL; | ||
652 | return notifier_from_errno(-ENOMEM); | ||
653 | } | ||
654 | break; | 671 | break; |
655 | case CPU_UP_CANCELED: | 672 | case CPU_UP_CANCELED: |
656 | case CPU_UP_CANCELED_FROZEN: | 673 | case CPU_UP_CANCELED_FROZEN: |
657 | case CPU_DEAD: | 674 | case CPU_DEAD: |
658 | case CPU_DEAD_FROZEN: | 675 | case CPU_DEAD_FROZEN: |
659 | kfree(iucv_param_irq[cpu]); | 676 | free_iucv_data(cpu); |
660 | iucv_param_irq[cpu] = NULL; | ||
661 | kfree(iucv_param[cpu]); | ||
662 | iucv_param[cpu] = NULL; | ||
663 | kfree(iucv_irq_data[cpu]); | ||
664 | iucv_irq_data[cpu] = NULL; | ||
665 | break; | 677 | break; |
666 | case CPU_ONLINE: | 678 | case CPU_ONLINE: |
667 | case CPU_ONLINE_FROZEN: | 679 | case CPU_ONLINE_FROZEN: |
@@ -2025,33 +2037,20 @@ static int __init iucv_init(void) | |||
2025 | goto out_int; | 2037 | goto out_int; |
2026 | } | 2038 | } |
2027 | 2039 | ||
2028 | for_each_online_cpu(cpu) { | 2040 | cpu_notifier_register_begin(); |
2029 | /* Note: GFP_DMA used to get memory below 2G */ | ||
2030 | iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), | ||
2031 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
2032 | if (!iucv_irq_data[cpu]) { | ||
2033 | rc = -ENOMEM; | ||
2034 | goto out_free; | ||
2035 | } | ||
2036 | 2041 | ||
2037 | /* Allocate parameter blocks. */ | 2042 | for_each_online_cpu(cpu) { |
2038 | iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), | 2043 | if (alloc_iucv_data(cpu)) { |
2039 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
2040 | if (!iucv_param[cpu]) { | ||
2041 | rc = -ENOMEM; | ||
2042 | goto out_free; | ||
2043 | } | ||
2044 | iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
2045 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
2046 | if (!iucv_param_irq[cpu]) { | ||
2047 | rc = -ENOMEM; | 2044 | rc = -ENOMEM; |
2048 | goto out_free; | 2045 | goto out_free; |
2049 | } | 2046 | } |
2050 | |||
2051 | } | 2047 | } |
2052 | rc = register_hotcpu_notifier(&iucv_cpu_notifier); | 2048 | rc = __register_hotcpu_notifier(&iucv_cpu_notifier); |
2053 | if (rc) | 2049 | if (rc) |
2054 | goto out_free; | 2050 | goto out_free; |
2051 | |||
2052 | cpu_notifier_register_done(); | ||
2053 | |||
2055 | rc = register_reboot_notifier(&iucv_reboot_notifier); | 2054 | rc = register_reboot_notifier(&iucv_reboot_notifier); |
2056 | if (rc) | 2055 | if (rc) |
2057 | goto out_cpu; | 2056 | goto out_cpu; |
@@ -2069,16 +2068,14 @@ static int __init iucv_init(void) | |||
2069 | out_reboot: | 2068 | out_reboot: |
2070 | unregister_reboot_notifier(&iucv_reboot_notifier); | 2069 | unregister_reboot_notifier(&iucv_reboot_notifier); |
2071 | out_cpu: | 2070 | out_cpu: |
2072 | unregister_hotcpu_notifier(&iucv_cpu_notifier); | 2071 | cpu_notifier_register_begin(); |
2072 | __unregister_hotcpu_notifier(&iucv_cpu_notifier); | ||
2073 | out_free: | 2073 | out_free: |
2074 | for_each_possible_cpu(cpu) { | 2074 | for_each_possible_cpu(cpu) |
2075 | kfree(iucv_param_irq[cpu]); | 2075 | free_iucv_data(cpu); |
2076 | iucv_param_irq[cpu] = NULL; | 2076 | |
2077 | kfree(iucv_param[cpu]); | 2077 | cpu_notifier_register_done(); |
2078 | iucv_param[cpu] = NULL; | 2078 | |
2079 | kfree(iucv_irq_data[cpu]); | ||
2080 | iucv_irq_data[cpu] = NULL; | ||
2081 | } | ||
2082 | root_device_unregister(iucv_root); | 2079 | root_device_unregister(iucv_root); |
2083 | out_int: | 2080 | out_int: |
2084 | unregister_external_interrupt(0x4000, iucv_external_interrupt); | 2081 | unregister_external_interrupt(0x4000, iucv_external_interrupt); |
@@ -2105,15 +2102,11 @@ static void __exit iucv_exit(void) | |||
2105 | kfree(p); | 2102 | kfree(p); |
2106 | spin_unlock_irq(&iucv_queue_lock); | 2103 | spin_unlock_irq(&iucv_queue_lock); |
2107 | unregister_reboot_notifier(&iucv_reboot_notifier); | 2104 | unregister_reboot_notifier(&iucv_reboot_notifier); |
2108 | unregister_hotcpu_notifier(&iucv_cpu_notifier); | 2105 | cpu_notifier_register_begin(); |
2109 | for_each_possible_cpu(cpu) { | 2106 | __unregister_hotcpu_notifier(&iucv_cpu_notifier); |
2110 | kfree(iucv_param_irq[cpu]); | 2107 | for_each_possible_cpu(cpu) |
2111 | iucv_param_irq[cpu] = NULL; | 2108 | free_iucv_data(cpu); |
2112 | kfree(iucv_param[cpu]); | 2109 | cpu_notifier_register_done(); |
2113 | iucv_param[cpu] = NULL; | ||
2114 | kfree(iucv_irq_data[cpu]); | ||
2115 | iucv_irq_data[cpu] = NULL; | ||
2116 | } | ||
2117 | root_device_unregister(iucv_root); | 2110 | root_device_unregister(iucv_root); |
2118 | bus_unregister(&iucv_bus); | 2111 | bus_unregister(&iucv_bus); |
2119 | unregister_external_interrupt(0x4000, iucv_external_interrupt); | 2112 | unregister_external_interrupt(0x4000, iucv_external_interrupt); |