aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel/xpc_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/sn/kernel/xpc_main.c')
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c189
1 files changed, 129 insertions, 60 deletions
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index b617236524c6..8930586e0eb4 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. 6 * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
7 */ 7 */
8 8
9 9
@@ -59,7 +59,7 @@
59#include <asm/sn/sn_sal.h> 59#include <asm/sn/sn_sal.h>
60#include <asm/kdebug.h> 60#include <asm/kdebug.h>
61#include <asm/uaccess.h> 61#include <asm/uaccess.h>
62#include "xpc.h" 62#include <asm/sn/xpc.h>
63 63
64 64
65/* define two XPC debug device structures to be used with dev_dbg() et al */ 65/* define two XPC debug device structures to be used with dev_dbg() et al */
@@ -82,6 +82,9 @@ struct device *xpc_part = &xpc_part_dbg_subname;
82struct device *xpc_chan = &xpc_chan_dbg_subname; 82struct device *xpc_chan = &xpc_chan_dbg_subname;
83 83
84 84
85static int xpc_kdebug_ignore;
86
87
85/* systune related variables for /proc/sys directories */ 88/* systune related variables for /proc/sys directories */
86 89
87static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL; 90static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
@@ -162,6 +165,8 @@ static ctl_table xpc_sys_dir[] = {
162}; 165};
163static struct ctl_table_header *xpc_sysctl; 166static struct ctl_table_header *xpc_sysctl;
164 167
168/* non-zero if any remote partition disengage request was timed out */
169int xpc_disengage_request_timedout;
165 170
166/* #of IRQs received */ 171/* #of IRQs received */
167static atomic_t xpc_act_IRQ_rcvd; 172static atomic_t xpc_act_IRQ_rcvd;
@@ -773,7 +778,7 @@ xpc_daemonize_kthread(void *args)
773 ch->flags |= XPC_C_DISCONNECTCALLOUT; 778 ch->flags |= XPC_C_DISCONNECTCALLOUT;
774 spin_unlock_irqrestore(&ch->lock, irq_flags); 779 spin_unlock_irqrestore(&ch->lock, irq_flags);
775 780
776 xpc_disconnecting_callout(ch); 781 xpc_disconnect_callout(ch, xpcDisconnecting);
777 } else { 782 } else {
778 spin_unlock_irqrestore(&ch->lock, irq_flags); 783 spin_unlock_irqrestore(&ch->lock, irq_flags);
779 } 784 }
@@ -921,9 +926,9 @@ static void
921xpc_do_exit(enum xpc_retval reason) 926xpc_do_exit(enum xpc_retval reason)
922{ 927{
923 partid_t partid; 928 partid_t partid;
924 int active_part_count; 929 int active_part_count, printed_waiting_msg = 0;
925 struct xpc_partition *part; 930 struct xpc_partition *part;
926 unsigned long printmsg_time; 931 unsigned long printmsg_time, disengage_request_timeout = 0;
927 932
928 933
929 /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */ 934 /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
@@ -953,7 +958,8 @@ xpc_do_exit(enum xpc_retval reason)
953 958
954 /* wait for all partitions to become inactive */ 959 /* wait for all partitions to become inactive */
955 960
956 printmsg_time = jiffies; 961 printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
962 xpc_disengage_request_timedout = 0;
957 963
958 do { 964 do {
959 active_part_count = 0; 965 active_part_count = 0;
@@ -969,20 +975,39 @@ xpc_do_exit(enum xpc_retval reason)
969 active_part_count++; 975 active_part_count++;
970 976
971 XPC_DEACTIVATE_PARTITION(part, reason); 977 XPC_DEACTIVATE_PARTITION(part, reason);
972 }
973 978
974 if (active_part_count == 0) { 979 if (part->disengage_request_timeout >
975 break; 980 disengage_request_timeout) {
981 disengage_request_timeout =
982 part->disengage_request_timeout;
983 }
976 } 984 }
977 985
978 if (jiffies >= printmsg_time) { 986 if (xpc_partition_engaged(-1UL)) {
979 dev_info(xpc_part, "waiting for partitions to " 987 if (time_after(jiffies, printmsg_time)) {
980 "deactivate/disengage, active count=%d, remote " 988 dev_info(xpc_part, "waiting for remote "
981 "engaged=0x%lx\n", active_part_count, 989 "partitions to disengage, timeout in "
982 xpc_partition_engaged(1UL << partid)); 990 "%ld seconds\n",
983 991 (disengage_request_timeout - jiffies)
984 printmsg_time = jiffies + 992 / HZ);
993 printmsg_time = jiffies +
985 (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); 994 (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
995 printed_waiting_msg = 1;
996 }
997
998 } else if (active_part_count > 0) {
999 if (printed_waiting_msg) {
1000 dev_info(xpc_part, "waiting for local partition"
1001 " to disengage\n");
1002 printed_waiting_msg = 0;
1003 }
1004
1005 } else {
1006 if (!xpc_disengage_request_timedout) {
1007 dev_info(xpc_part, "all partitions have "
1008 "disengaged\n");
1009 }
1010 break;
986 } 1011 }
987 1012
988 /* sleep for a 1/3 of a second or so */ 1013 /* sleep for a 1/3 of a second or so */
@@ -1000,11 +1025,13 @@ xpc_do_exit(enum xpc_retval reason)
1000 del_timer_sync(&xpc_hb_timer); 1025 del_timer_sync(&xpc_hb_timer);
1001 DBUG_ON(xpc_vars->heartbeating_to_mask != 0); 1026 DBUG_ON(xpc_vars->heartbeating_to_mask != 0);
1002 1027
1003 /* take ourselves off of the reboot_notifier_list */ 1028 if (reason == xpcUnloading) {
1004 (void) unregister_reboot_notifier(&xpc_reboot_notifier); 1029 /* take ourselves off of the reboot_notifier_list */
1030 (void) unregister_reboot_notifier(&xpc_reboot_notifier);
1005 1031
1006 /* take ourselves off of the die_notifier list */ 1032 /* take ourselves off of the die_notifier list */
1007 (void) unregister_die_notifier(&xpc_die_notifier); 1033 (void) unregister_die_notifier(&xpc_die_notifier);
1034 }
1008 1035
1009 /* close down protections for IPI operations */ 1036 /* close down protections for IPI operations */
1010 xpc_restrict_IPI_ops(); 1037 xpc_restrict_IPI_ops();
@@ -1020,7 +1047,35 @@ xpc_do_exit(enum xpc_retval reason)
1020 1047
1021 1048
1022/* 1049/*
1023 * Called when the system is about to be either restarted or halted. 1050 * This function is called when the system is being rebooted.
1051 */
1052static int
1053xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
1054{
1055 enum xpc_retval reason;
1056
1057
1058 switch (event) {
1059 case SYS_RESTART:
1060 reason = xpcSystemReboot;
1061 break;
1062 case SYS_HALT:
1063 reason = xpcSystemHalt;
1064 break;
1065 case SYS_POWER_OFF:
1066 reason = xpcSystemPoweroff;
1067 break;
1068 default:
1069 reason = xpcSystemGoingDown;
1070 }
1071
1072 xpc_do_exit(reason);
1073 return NOTIFY_DONE;
1074}
1075
1076
1077/*
1078 * Notify other partitions to disengage from all references to our memory.
1024 */ 1079 */
1025static void 1080static void
1026xpc_die_disengage(void) 1081xpc_die_disengage(void)
@@ -1028,7 +1083,7 @@ xpc_die_disengage(void)
1028 struct xpc_partition *part; 1083 struct xpc_partition *part;
1029 partid_t partid; 1084 partid_t partid;
1030 unsigned long engaged; 1085 unsigned long engaged;
1031 long time, print_time, disengage_request_timeout; 1086 long time, printmsg_time, disengage_request_timeout;
1032 1087
1033 1088
1034 /* keep xpc_hb_checker thread from doing anything (just in case) */ 1089 /* keep xpc_hb_checker thread from doing anything (just in case) */
@@ -1055,57 +1110,53 @@ xpc_die_disengage(void)
1055 } 1110 }
1056 } 1111 }
1057 1112
1058 print_time = rtc_time(); 1113 time = rtc_time();
1059 disengage_request_timeout = print_time + 1114 printmsg_time = time +
1115 (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second);
1116 disengage_request_timeout = time +
1060 (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second); 1117 (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);
1061 1118
1062 /* wait for all other partitions to disengage from us */ 1119 /* wait for all other partitions to disengage from us */
1063 1120
1064 while ((engaged = xpc_partition_engaged(-1UL)) && 1121 while (1) {
1065 (time = rtc_time()) < disengage_request_timeout) { 1122 engaged = xpc_partition_engaged(-1UL);
1123 if (!engaged) {
1124 dev_info(xpc_part, "all partitions have disengaged\n");
1125 break;
1126 }
1066 1127
1067 if (time >= print_time) { 1128 time = rtc_time();
1129 if (time >= disengage_request_timeout) {
1130 for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
1131 if (engaged & (1UL << partid)) {
1132 dev_info(xpc_part, "disengage from "
1133 "remote partition %d timed "
1134 "out\n", partid);
1135 }
1136 }
1137 break;
1138 }
1139
1140 if (time >= printmsg_time) {
1068 dev_info(xpc_part, "waiting for remote partitions to " 1141 dev_info(xpc_part, "waiting for remote partitions to "
1069 "disengage, engaged=0x%lx\n", engaged); 1142 "disengage, timeout in %ld seconds\n",
1070 print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL * 1143 (disengage_request_timeout - time) /
1144 sn_rtc_cycles_per_second);
1145 printmsg_time = time +
1146 (XPC_DISENGAGE_PRINTMSG_INTERVAL *
1071 sn_rtc_cycles_per_second); 1147 sn_rtc_cycles_per_second);
1072 } 1148 }
1073 } 1149 }
1074 dev_info(xpc_part, "finished waiting for remote partitions to "
1075 "disengage, engaged=0x%lx\n", engaged);
1076}
1077
1078
1079/*
1080 * This function is called when the system is being rebooted.
1081 */
1082static int
1083xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
1084{
1085 enum xpc_retval reason;
1086
1087
1088 switch (event) {
1089 case SYS_RESTART:
1090 reason = xpcSystemReboot;
1091 break;
1092 case SYS_HALT:
1093 reason = xpcSystemHalt;
1094 break;
1095 case SYS_POWER_OFF:
1096 reason = xpcSystemPoweroff;
1097 break;
1098 default:
1099 reason = xpcSystemGoingDown;
1100 }
1101
1102 xpc_do_exit(reason);
1103 return NOTIFY_DONE;
1104} 1150}
1105 1151
1106 1152
1107/* 1153/*
1108 * This function is called when the system is being rebooted. 1154 * This function is called when the system is being restarted or halted due
1155 * to some sort of system failure. If this is the case we need to notify the
1156 * other partitions to disengage from all references to our memory.
1157 * This function can also be called when our heartbeater could be offlined
1158 * for a time. In this case we need to notify other partitions to not worry
1159 * about the lack of a heartbeat.
1109 */ 1160 */
1110static int 1161static int
1111xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) 1162xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
@@ -1115,11 +1166,25 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
1115 case DIE_MACHINE_HALT: 1166 case DIE_MACHINE_HALT:
1116 xpc_die_disengage(); 1167 xpc_die_disengage();
1117 break; 1168 break;
1169
1170 case DIE_KDEBUG_ENTER:
1171 /* Should lack of heartbeat be ignored by other partitions? */
1172 if (!xpc_kdebug_ignore) {
1173 break;
1174 }
1175 /* fall through */
1118 case DIE_MCA_MONARCH_ENTER: 1176 case DIE_MCA_MONARCH_ENTER:
1119 case DIE_INIT_MONARCH_ENTER: 1177 case DIE_INIT_MONARCH_ENTER:
1120 xpc_vars->heartbeat++; 1178 xpc_vars->heartbeat++;
1121 xpc_vars->heartbeat_offline = 1; 1179 xpc_vars->heartbeat_offline = 1;
1122 break; 1180 break;
1181
1182 case DIE_KDEBUG_LEAVE:
1183 /* Is lack of heartbeat being ignored by other partitions? */
1184 if (!xpc_kdebug_ignore) {
1185 break;
1186 }
1187 /* fall through */
1123 case DIE_MCA_MONARCH_LEAVE: 1188 case DIE_MCA_MONARCH_LEAVE:
1124 case DIE_INIT_MONARCH_LEAVE: 1189 case DIE_INIT_MONARCH_LEAVE:
1125 xpc_vars->heartbeat++; 1190 xpc_vars->heartbeat++;
@@ -1344,3 +1409,7 @@ module_param(xpc_disengage_request_timelimit, int, 0);
1344MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait " 1409MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "
1345 "for disengage request to complete."); 1410 "for disengage request to complete.");
1346 1411
1412module_param(xpc_kdebug_ignore, int, 0);
1413MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by "
1414 "other partitions when dropping into kdebug.");
1415