patch-2.4.20 linux-2.4.20/arch/s390/kernel/smp.c
Next file: linux-2.4.20/arch/s390/kernel/time.c
Previous file: linux-2.4.20/arch/s390/kernel/signal.c
Back to the patch index
Back to the overall index
- Lines: 250
- Date:
Thu Nov 28 15:53:11 2002
- Orig file:
linux-2.4.19/arch/s390/kernel/smp.c
- Orig date:
Fri Aug 2 17:39:43 2002
diff -urN linux-2.4.19/arch/s390/kernel/smp.c linux-2.4.20/arch/s390/kernel/smp.c
@@ -176,61 +176,132 @@
return 0;
}
+static inline void do_send_stop(void)
+{
+ u32 dummy;
+ int i;
+
+ /* stop all processors */
+ for (i = 0; i < smp_num_cpus; i++) {
+ if (smp_processor_id() != i) {
+ int ccode;
+ do {
+ ccode = signal_processor_ps(
+ &dummy,
+ 0,
+ i,
+ sigp_stop);
+ } while(ccode == sigp_busy);
+ }
+ }
+}
+
+static inline void do_store_status(void)
+{
+ unsigned long low_core_addr;
+ u32 dummy;
+ int i;
+
+ /* store status of all processors in their lowcores (real 0) */
+ for (i = 0; i < smp_num_cpus; i++) {
+ if (smp_processor_id() != i) {
+ int ccode;
+ low_core_addr = (unsigned long)get_cpu_lowcore(i);
+ do {
+ ccode = signal_processor_ps(
+ &dummy,
+ low_core_addr,
+ i,
+ sigp_store_status_at_address);
+ } while(ccode == sigp_busy);
+ }
+ }
+}
/*
- * Various special callbacks
+ * this function sends a 'stop' sigp to all other CPUs in the system.
+ * it goes straight through.
*/
+void smp_send_stop(void)
+{
+ /* write magic number to zero page (absolute 0) */
+ get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC;
+
+ /* stop other processors. */
+ do_send_stop();
+
+ /* store status of other processors. */
+ do_store_status();
+}
-void do_machine_restart(void)
+/*
+ * Reboot, halt and power_off routines for SMP.
+ */
+static volatile unsigned long cpu_restart_map;
+
+static void do_machine_restart(void * __unused)
{
- smp_send_stop();
- reipl(S390_lowcore.ipl_device);
+ clear_bit(smp_processor_id(), &cpu_restart_map);
+ if (smp_processor_id() == 0) {
+ /* Wait for all other cpus to enter do_machine_restart. */
+ while (cpu_restart_map != 0);
+ /* Store status of other cpus. */
+ do_store_status();
+ /*
+ * Finally call reipl. Because we waited for all other
+ * cpus to enter this function we know that they do
+ * not hold any s390irq-locks (the cpus have been
+ * interrupted by an external interrupt and s390irq
+ * locks are always held disabled).
+ */
+ reipl(S390_lowcore.ipl_device);
+ }
+ signal_processor(smp_processor_id(), sigp_stop);
}
-void machine_restart(char * __unused)
+void machine_restart_smp(char * __unused)
{
- if (smp_processor_id() != 0) {
- smp_ext_bitcall(0, ec_restart);
- for (;;)
- enabled_wait();
- } else
- do_machine_restart();
+ cpu_restart_map = cpu_online_map;
+ smp_call_function(do_machine_restart, NULL, 0, 0);
+ do_machine_restart(NULL);
}
-void do_machine_halt(void)
+static void do_machine_halt(void * __unused)
{
- smp_send_stop();
- if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
- cpcmd(vmhalt_cmd, NULL, 0);
- signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+ if (smp_processor_id() == 0) {
+ smp_send_stop();
+ if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
+ cpcmd(vmhalt_cmd, NULL, 0);
+ signal_processor(smp_processor_id(),
+ sigp_stop_and_store_status);
+ }
+ for (;;)
+ enabled_wait();
}
-void machine_halt(void)
+void machine_halt_smp(void)
{
- if (smp_processor_id() != 0) {
- smp_ext_bitcall(0, ec_halt);
- for (;;)
- enabled_wait();
- } else
- do_machine_halt();
+ smp_call_function(do_machine_halt, NULL, 0, 0);
+ do_machine_halt(NULL);
}
-void do_machine_power_off(void)
+static void do_machine_power_off(void * __unused)
{
- smp_send_stop();
- if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
- cpcmd(vmpoff_cmd, NULL, 0);
- signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+ if (smp_processor_id() == 0) {
+ smp_send_stop();
+ if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
+ cpcmd(vmpoff_cmd, NULL, 0);
+ signal_processor(smp_processor_id(),
+ sigp_stop_and_store_status);
+ }
+ for (;;)
+ enabled_wait();
}
-void machine_power_off(void)
+void machine_power_off_smp(void)
{
- if (smp_processor_id() != 0) {
- smp_ext_bitcall(0, ec_power_off);
- for (;;)
- enabled_wait();
- } else
- do_machine_power_off();
+ smp_call_function(do_machine_power_off, NULL, 0, 0);
+ do_machine_power_off(NULL);
}
/*
@@ -247,19 +318,11 @@
*
* For the ec_schedule signal we have to do nothing. All the work
* is done automatically when we return from the interrupt.
- * For the ec_restart, ec_halt and ec_power_off we call the
- * appropriate routine.
*/
do {
bits = atomic_read(&S390_lowcore.ext_call_fast);
} while (atomic_compare_and_swap(bits,0,&S390_lowcore.ext_call_fast));
- if (test_bit(ec_restart, &bits))
- do_machine_restart();
- if (test_bit(ec_halt, &bits))
- do_machine_halt();
- if (test_bit(ec_power_off, &bits))
- do_machine_power_off();
if (test_bit(ec_call_function, &bits))
do_call_function();
}
@@ -288,7 +351,6 @@
static void smp_ext_bitcall_others(ec_bit_sig sig)
{
struct _lowcore *lowcore;
- sigp_ccode ccode;
int i;
for (i = 0; i < smp_num_cpus; i++) {
@@ -304,53 +366,6 @@
}
}
-/*
- * this function sends a 'stop' sigp to all other CPUs in the system.
- * it goes straight through.
- */
-
-void smp_send_stop(void)
-{
- int i;
- u32 dummy;
- unsigned long low_core_addr;
-
- /* write magic number to zero page (absolute 0) */
-
- get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC;
-
- /* stop all processors */
-
- for (i = 0; i < smp_num_cpus; i++) {
- if (smp_processor_id() != i) {
- int ccode;
- do {
- ccode = signal_processor_ps(
- &dummy,
- 0,
- i,
- sigp_stop);
- } while(ccode == sigp_busy);
- }
- }
-
- /* store status of all processors in their lowcores (real 0) */
-
- for (i = 0; i < smp_num_cpus; i++) {
- if (smp_processor_id() != i) {
- int ccode;
- low_core_addr = (unsigned long)get_cpu_lowcore(i);
- do {
- ccode = signal_processor_ps(
- &dummy,
- low_core_addr,
- i,
- sigp_store_status_at_address);
- } while(ccode == sigp_busy);
- }
- }
-}
-
/*
* this function sends a 'purge tlb' signal to another CPU.
*/
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)