aboutsummaryrefslogtreecommitdiffstats
path: root/net/iucv/iucv.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2009-01-05 21:09:02 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-05 21:09:02 -0500
commitf1d3e4dca3f8d4f55656477e83d0afe0ea7cbaed (patch)
tree1d2d2ebc94dd4b18d26f25cd062bea741f85237e /net/iucv/iucv.c
parent65dbd7c2778f1921ef1ee2a73e47a2a126fed30f (diff)
iucv: fix cpu hotplug
If the iucv module is compiled in/loaded but no user is registered cpu hot remove doesn't work. Reason for that is that the iucv cpu hotplug notifier on CPU_DOWN_PREPARE checks if the iucv_buffer_cpumask would be empty after the corresponding bit would be cleared. However the bit was never set since iucv wasn't enable. That causes all cpu hot unplug operations to fail in this scenario. To fix this use iucv_path_table as an indicator wether iucv is enabled or not. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/iucv/iucv.c')
-rw-r--r--net/iucv/iucv.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 8f57d4f4328a..032f61e98595 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -517,6 +517,7 @@ static int iucv_enable(void)
517 size_t alloc_size; 517 size_t alloc_size;
518 int cpu, rc; 518 int cpu, rc;
519 519
520 get_online_cpus();
520 rc = -ENOMEM; 521 rc = -ENOMEM;
521 alloc_size = iucv_max_pathid * sizeof(struct iucv_path); 522 alloc_size = iucv_max_pathid * sizeof(struct iucv_path);
522 iucv_path_table = kzalloc(alloc_size, GFP_KERNEL); 523 iucv_path_table = kzalloc(alloc_size, GFP_KERNEL);
@@ -524,19 +525,17 @@ static int iucv_enable(void)
524 goto out; 525 goto out;
525 /* Declare per cpu buffers. */ 526 /* Declare per cpu buffers. */
526 rc = -EIO; 527 rc = -EIO;
527 get_online_cpus();
528 for_each_online_cpu(cpu) 528 for_each_online_cpu(cpu)
529 smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); 529 smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
530 if (cpus_empty(iucv_buffer_cpumask)) 530 if (cpus_empty(iucv_buffer_cpumask))
531 /* No cpu could declare an iucv buffer. */ 531 /* No cpu could declare an iucv buffer. */
532 goto out_path; 532 goto out;
533 put_online_cpus(); 533 put_online_cpus();
534 return 0; 534 return 0;
535
536out_path:
537 put_online_cpus();
538 kfree(iucv_path_table);
539out: 535out:
536 kfree(iucv_path_table);
537 iucv_path_table = NULL;
538 put_online_cpus();
540 return rc; 539 return rc;
541} 540}
542 541
@@ -551,8 +550,9 @@ static void iucv_disable(void)
551{ 550{
552 get_online_cpus(); 551 get_online_cpus();
553 on_each_cpu(iucv_retrieve_cpu, NULL, 1); 552 on_each_cpu(iucv_retrieve_cpu, NULL, 1);
554 put_online_cpus();
555 kfree(iucv_path_table); 553 kfree(iucv_path_table);
554 iucv_path_table = NULL;
555 put_online_cpus();
556} 556}
557 557
558static int __cpuinit iucv_cpu_notify(struct notifier_block *self, 558static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
@@ -589,10 +589,14 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
589 case CPU_ONLINE_FROZEN: 589 case CPU_ONLINE_FROZEN:
590 case CPU_DOWN_FAILED: 590 case CPU_DOWN_FAILED:
591 case CPU_DOWN_FAILED_FROZEN: 591 case CPU_DOWN_FAILED_FROZEN:
592 if (!iucv_path_table)
593 break;
592 smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); 594 smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
593 break; 595 break;
594 case CPU_DOWN_PREPARE: 596 case CPU_DOWN_PREPARE:
595 case CPU_DOWN_PREPARE_FROZEN: 597 case CPU_DOWN_PREPARE_FROZEN:
598 if (!iucv_path_table)
599 break;
596 cpumask = iucv_buffer_cpumask; 600 cpumask = iucv_buffer_cpumask;
597 cpu_clear(cpu, cpumask); 601 cpu_clear(cpu, cpumask);
598 if (cpus_empty(cpumask)) 602 if (cpus_empty(cpumask))