diff options
Diffstat (limited to 'arch/ia64/kernel/mca.c')
| -rw-r--r-- | arch/ia64/kernel/mca.c | 88 |
1 files changed, 44 insertions, 44 deletions
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 63b73f3d4c9f..cc87025e8f54 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c | |||
| @@ -701,8 +701,7 @@ ia64_mca_cmc_vector_enable_keventd(struct work_struct *unused) | |||
| 701 | /* | 701 | /* |
| 702 | * ia64_mca_wakeup | 702 | * ia64_mca_wakeup |
| 703 | * | 703 | * |
| 704 | * Send an inter-cpu interrupt to wake-up a particular cpu | 704 | * Send an inter-cpu interrupt to wake-up a particular cpu. |
| 705 | * and mark that cpu to be out of rendez. | ||
| 706 | * | 705 | * |
| 707 | * Inputs : cpuid | 706 | * Inputs : cpuid |
| 708 | * Outputs : None | 707 | * Outputs : None |
| @@ -711,14 +710,12 @@ static void | |||
| 711 | ia64_mca_wakeup(int cpu) | 710 | ia64_mca_wakeup(int cpu) |
| 712 | { | 711 | { |
| 713 | platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0); | 712 | platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0); |
| 714 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | ||
| 715 | |||
| 716 | } | 713 | } |
| 717 | 714 | ||
| 718 | /* | 715 | /* |
| 719 | * ia64_mca_wakeup_all | 716 | * ia64_mca_wakeup_all |
| 720 | * | 717 | * |
| 721 | * Wakeup all the cpus which have rendez'ed previously. | 718 | * Wakeup all the slave cpus which have rendez'ed previously. |
| 722 | * | 719 | * |
| 723 | * Inputs : None | 720 | * Inputs : None |
| 724 | * Outputs : None | 721 | * Outputs : None |
| @@ -741,7 +738,10 @@ ia64_mca_wakeup_all(void) | |||
| 741 | * | 738 | * |
| 742 | * This is handler used to put slave processors into spinloop | 739 | * This is handler used to put slave processors into spinloop |
| 743 | * while the monarch processor does the mca handling and later | 740 | * while the monarch processor does the mca handling and later |
| 744 | * wake each slave up once the monarch is done. | 741 | * wake each slave up once the monarch is done. The state |
| 742 | * IA64_MCA_RENDEZ_CHECKIN_DONE indicates the cpu is rendez'ed | ||
| 743 | * in SAL. The state IA64_MCA_RENDEZ_CHECKIN_NOTDONE indicates | ||
| 744 | * the cpu has come out of OS rendezvous. | ||
| 745 | * | 745 | * |
| 746 | * Inputs : None | 746 | * Inputs : None |
| 747 | * Outputs : None | 747 | * Outputs : None |
| @@ -778,6 +778,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg) | |||
| 778 | (long)&nd, 0, 0) == NOTIFY_STOP) | 778 | (long)&nd, 0, 0) == NOTIFY_STOP) |
| 779 | ia64_mca_spin(__FUNCTION__); | 779 | ia64_mca_spin(__FUNCTION__); |
| 780 | 780 | ||
| 781 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | ||
| 781 | /* Enable all interrupts */ | 782 | /* Enable all interrupts */ |
| 782 | local_irq_restore(flags); | 783 | local_irq_restore(flags); |
| 783 | return IRQ_HANDLED; | 784 | return IRQ_HANDLED; |
| @@ -1135,30 +1136,27 @@ no_mod: | |||
| 1135 | static void | 1136 | static void |
| 1136 | ia64_wait_for_slaves(int monarch, const char *type) | 1137 | ia64_wait_for_slaves(int monarch, const char *type) |
| 1137 | { | 1138 | { |
| 1138 | int c, wait = 0, missing = 0; | 1139 | int c, i , wait; |
| 1139 | for_each_online_cpu(c) { | 1140 | |
| 1140 | if (c == monarch) | 1141 | /* |
| 1141 | continue; | 1142 | * wait 5 seconds total for slaves (arbitrary) |
| 1142 | if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { | 1143 | */ |
| 1143 | udelay(1000); /* short wait first */ | 1144 | for (i = 0; i < 5000; i++) { |
| 1144 | wait = 1; | 1145 | wait = 0; |
| 1145 | break; | 1146 | for_each_online_cpu(c) { |
| 1146 | } | 1147 | if (c == monarch) |
| 1147 | } | 1148 | continue; |
| 1148 | if (!wait) | 1149 | if (ia64_mc_info.imi_rendez_checkin[c] |
| 1149 | goto all_in; | 1150 | == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { |
| 1150 | for_each_online_cpu(c) { | 1151 | udelay(1000); /* short wait */ |
| 1151 | if (c == monarch) | 1152 | wait = 1; |
| 1152 | continue; | 1153 | break; |
| 1153 | if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { | 1154 | } |
| 1154 | udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */ | ||
| 1155 | if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) | ||
| 1156 | missing = 1; | ||
| 1157 | break; | ||
| 1158 | } | 1155 | } |
| 1156 | if (!wait) | ||
| 1157 | goto all_in; | ||
| 1159 | } | 1158 | } |
| 1160 | if (!missing) | 1159 | |
| 1161 | goto all_in; | ||
| 1162 | /* | 1160 | /* |
| 1163 | * Maybe slave(s) dead. Print buffered messages immediately. | 1161 | * Maybe slave(s) dead. Print buffered messages immediately. |
| 1164 | */ | 1162 | */ |
| @@ -1224,26 +1222,27 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 1224 | if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0) | 1222 | if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0) |
| 1225 | == NOTIFY_STOP) | 1223 | == NOTIFY_STOP) |
| 1226 | ia64_mca_spin(__FUNCTION__); | 1224 | ia64_mca_spin(__FUNCTION__); |
| 1225 | |||
| 1226 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; | ||
| 1227 | if (sos->monarch) { | 1227 | if (sos->monarch) { |
| 1228 | ia64_wait_for_slaves(cpu, "MCA"); | 1228 | ia64_wait_for_slaves(cpu, "MCA"); |
| 1229 | |||
| 1230 | /* Wakeup all the processors which are spinning in the | ||
| 1231 | * rendezvous loop. They will leave SAL, then spin in the OS | ||
| 1232 | * with interrupts disabled until this monarch cpu leaves the | ||
| 1233 | * MCA handler. That gets control back to the OS so we can | ||
| 1234 | * backtrace the other cpus, backtrace when spinning in SAL | ||
| 1235 | * does not work. | ||
| 1236 | */ | ||
| 1237 | ia64_mca_wakeup_all(); | ||
| 1238 | if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0) | ||
| 1239 | == NOTIFY_STOP) | ||
| 1240 | ia64_mca_spin(__FUNCTION__); | ||
| 1229 | } else { | 1241 | } else { |
| 1230 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; | ||
| 1231 | while (cpu_isset(cpu, mca_cpu)) | 1242 | while (cpu_isset(cpu, mca_cpu)) |
| 1232 | cpu_relax(); /* spin until monarch wakes us */ | 1243 | cpu_relax(); /* spin until monarch wakes us */ |
| 1233 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | ||
| 1234 | } | 1244 | } |
| 1235 | 1245 | ||
| 1236 | /* Wakeup all the processors which are spinning in the rendezvous loop. | ||
| 1237 | * They will leave SAL, then spin in the OS with interrupts disabled | ||
| 1238 | * until this monarch cpu leaves the MCA handler. That gets control | ||
| 1239 | * back to the OS so we can backtrace the other cpus, backtrace when | ||
| 1240 | * spinning in SAL does not work. | ||
| 1241 | */ | ||
| 1242 | ia64_mca_wakeup_all(); | ||
| 1243 | if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0) | ||
| 1244 | == NOTIFY_STOP) | ||
| 1245 | ia64_mca_spin(__FUNCTION__); | ||
| 1246 | |||
| 1247 | /* Get the MCA error record and log it */ | 1246 | /* Get the MCA error record and log it */ |
| 1248 | ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); | 1247 | ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); |
| 1249 | 1248 | ||
| @@ -1277,21 +1276,22 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 1277 | /* wake up the next monarch cpu, | 1276 | /* wake up the next monarch cpu, |
| 1278 | * and put this cpu in the rendez loop. | 1277 | * and put this cpu in the rendez loop. |
| 1279 | */ | 1278 | */ |
| 1280 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; | ||
| 1281 | for_each_online_cpu(i) { | 1279 | for_each_online_cpu(i) { |
| 1282 | if (cpu_isset(i, mca_cpu)) { | 1280 | if (cpu_isset(i, mca_cpu)) { |
| 1283 | monarch_cpu = i; | 1281 | monarch_cpu = i; |
| 1284 | cpu_clear(i, mca_cpu); /* wake next cpu */ | 1282 | cpu_clear(i, mca_cpu); /* wake next cpu */ |
| 1285 | while (monarch_cpu != -1) | 1283 | while (monarch_cpu != -1) |
| 1286 | cpu_relax(); /* spin until last cpu leaves */ | 1284 | cpu_relax(); /* spin until last cpu leaves */ |
| 1287 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | ||
| 1288 | set_curr_task(cpu, previous_current); | 1285 | set_curr_task(cpu, previous_current); |
| 1286 | ia64_mc_info.imi_rendez_checkin[cpu] | ||
| 1287 | = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | ||
| 1289 | return; | 1288 | return; |
| 1290 | } | 1289 | } |
| 1291 | } | 1290 | } |
| 1292 | } | 1291 | } |
| 1293 | set_curr_task(cpu, previous_current); | 1292 | set_curr_task(cpu, previous_current); |
| 1294 | monarch_cpu = -1; | 1293 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; |
| 1294 | monarch_cpu = -1; /* This frees the slaves and previous monarchs */ | ||
| 1295 | } | 1295 | } |
| 1296 | 1296 | ||
| 1297 | static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd); | 1297 | static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd); |
