diff options
Diffstat (limited to 'arch/ia64/kernel/mca.c')
-rw-r--r-- | arch/ia64/kernel/mca.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 92367faecbbf..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; |
@@ -1221,26 +1222,27 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
1221 | 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) |
1222 | == NOTIFY_STOP) | 1223 | == NOTIFY_STOP) |
1223 | ia64_mca_spin(__FUNCTION__); | 1224 | ia64_mca_spin(__FUNCTION__); |
1225 | |||
1226 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; | ||
1224 | if (sos->monarch) { | 1227 | if (sos->monarch) { |
1225 | 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__); | ||
1226 | } else { | 1241 | } else { |
1227 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; | ||
1228 | while (cpu_isset(cpu, mca_cpu)) | 1242 | while (cpu_isset(cpu, mca_cpu)) |
1229 | cpu_relax(); /* spin until monarch wakes us */ | 1243 | cpu_relax(); /* spin until monarch wakes us */ |
1230 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | ||
1231 | } | 1244 | } |
1232 | 1245 | ||
1233 | /* Wakeup all the processors which are spinning in the rendezvous loop. | ||
1234 | * They will leave SAL, then spin in the OS with interrupts disabled | ||
1235 | * until this monarch cpu leaves the MCA handler. That gets control | ||
1236 | * back to the OS so we can backtrace the other cpus, backtrace when | ||
1237 | * spinning in SAL does not work. | ||
1238 | */ | ||
1239 | ia64_mca_wakeup_all(); | ||
1240 | if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0) | ||
1241 | == NOTIFY_STOP) | ||
1242 | ia64_mca_spin(__FUNCTION__); | ||
1243 | |||
1244 | /* Get the MCA error record and log it */ | 1246 | /* Get the MCA error record and log it */ |
1245 | ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); | 1247 | ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); |
1246 | 1248 | ||
@@ -1274,21 +1276,22 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
1274 | /* wake up the next monarch cpu, | 1276 | /* wake up the next monarch cpu, |
1275 | * and put this cpu in the rendez loop. | 1277 | * and put this cpu in the rendez loop. |
1276 | */ | 1278 | */ |
1277 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; | ||
1278 | for_each_online_cpu(i) { | 1279 | for_each_online_cpu(i) { |
1279 | if (cpu_isset(i, mca_cpu)) { | 1280 | if (cpu_isset(i, mca_cpu)) { |
1280 | monarch_cpu = i; | 1281 | monarch_cpu = i; |
1281 | cpu_clear(i, mca_cpu); /* wake next cpu */ | 1282 | cpu_clear(i, mca_cpu); /* wake next cpu */ |
1282 | while (monarch_cpu != -1) | 1283 | while (monarch_cpu != -1) |
1283 | cpu_relax(); /* spin until last cpu leaves */ | 1284 | cpu_relax(); /* spin until last cpu leaves */ |
1284 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | ||
1285 | 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; | ||
1286 | return; | 1288 | return; |
1287 | } | 1289 | } |
1288 | } | 1290 | } |
1289 | } | 1291 | } |
1290 | set_curr_task(cpu, previous_current); | 1292 | set_curr_task(cpu, previous_current); |
1291 | 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 */ | ||
1292 | } | 1295 | } |
1293 | 1296 | ||
1294 | 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); |