patch-2.4.20 linux-2.4.20/drivers/s390/char/hwc_rw.c

Next file: linux-2.4.20/drivers/s390/char/tuball.c
Previous file: linux-2.4.20/drivers/s390/char/hwc.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/drivers/s390/char/hwc_rw.c linux-2.4.20/drivers/s390/char/hwc_rw.c
@@ -35,6 +35,8 @@
 #define MIN(a,b) (((a<b) ? a : b))
 #endif
 
+extern void ctrl_alt_del (void);
+
 #define HWC_RW_PRINT_HEADER "hwc low level driver: "
 
 #define  USE_VM_DETECTION
@@ -172,6 +174,7 @@
 	unsigned char read_nonprio:1;
 	unsigned char read_prio:1;
 	unsigned char read_statechange:1;
+	unsigned char sig_quiesce:1;
 
 	unsigned char flags;
 
@@ -222,6 +225,7 @@
 	    0,
 	    0,
 	    0,
+	    0,
 	    NULL,
 	    NULL
 
@@ -231,6 +235,8 @@
 static unsigned long cr0_save __attribute__ ((aligned (8)));
 static unsigned char psw_mask __attribute__ ((aligned (8)));
 
+static ext_int_info_t ext_int_info_hwc;
+
 #define DELAYED_WRITE 0
 #define IMMEDIATE_WRITE 1
 
@@ -1527,6 +1533,19 @@
 				       HWC_RW_PRINT_HEADER
 				 "can not read state change notifications\n");
 
+	hwc_data.sig_quiesce
+	    = ((mask & ET_SigQuiesce_Mask) == ET_SigQuiesce_Mask);
+	if (hwc_data.sig_quiesce)
+		internal_print (
+				       DELAYED_WRITE,
+				       HWC_RW_PRINT_HEADER
+				       "can receive signal quiesce\n");
+	else
+		internal_print (
+				       DELAYED_WRITE,
+				       HWC_RW_PRINT_HEADER
+				       "can not receive signal quiesce\n");
+
 	hwc_data.read_nonprio
 	    = ((mask & ET_OpCmd_Mask) == ET_OpCmd_Mask);
 	if (hwc_data.read_nonprio)
@@ -1607,6 +1626,48 @@
 	return retval;
 }
 
+#ifdef CONFIG_SMP
+extern unsigned long cpu_online_map;
+static volatile unsigned long cpu_quiesce_map;
+
+static void 
+do_load_quiesce_psw (void)
+{
+	psw_t quiesce_psw;
+
+	clear_bit (smp_processor_id (), &cpu_quiesce_map);
+	if (smp_processor_id () == 0) {
+
+		while (cpu_quiesce_map != 0) ;
+
+		quiesce_psw.mask = _DW_PSW_MASK;
+		quiesce_psw.addr = 0xfff;
+		__load_psw (quiesce_psw);
+	}
+	signal_processor (smp_processor_id (), sigp_stop);
+}
+
+static void 
+do_machine_quiesce (void)
+{
+	cpu_quiesce_map = cpu_online_map;
+	smp_call_function (do_load_quiesce_psw, NULL, 0, 0);
+	do_load_quiesce_psw ();
+}
+
+#else
+static void 
+do_machine_quiesce (void)
+{
+	psw_t quiesce_psw;
+
+	quiesce_psw.mask = _DW_PSW_MASK;
+	queisce_psw.addr = 0xfff;
+	__load_psw (quiesce_psw);
+}
+
+#endif
+
 static int 
 process_evbufs (void *start, void *end)
 {
@@ -1642,6 +1703,13 @@
 			retval += eval_statechangebuf
 			    ((statechangebuf_t *) evbuf);
 			break;
+		case ET_SigQuiesce:
+
+			_machine_restart = do_machine_quiesce;
+			_machine_halt = do_machine_quiesce;
+			_machine_power_off = do_machine_quiesce;
+			ctrl_alt_del ();
+			break;
 		default:
 			internal_print (
 					       DELAYED_WRITE,
@@ -2004,7 +2072,8 @@
 
 #endif
 
-	if (register_external_interrupt (0x2401, hwc_interrupt_handler) != 0)
+	if (register_early_external_interrupt (0x2401, hwc_interrupt_handler,
+					       &ext_int_info_hwc) != 0)
 		panic ("Couldn't request external interrupts 0x2401");
 
 	spin_lock_init (&hwc_data.lock);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)