diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
| commit | 1ebbe2b20091d306453a5cf480a87e6cd28ae76f (patch) | |
| tree | f5cd7a0fa69b8b1938cb5a0faed2e7b0628072a5 /arch/ia64/kernel/mca.c | |
| parent | ac58c9059da8886b5e8cde012a80266b18ca146e (diff) | |
| parent | 674a396c6d2ba0341ebdd7c1c9950f32f018e2dd (diff) | |
Merge branch 'linus'
Diffstat (limited to 'arch/ia64/kernel/mca.c')
| -rw-r--r-- | arch/ia64/kernel/mca.c | 90 |
1 files changed, 60 insertions, 30 deletions
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index ee7eec9ee576..b57e723f194c 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c | |||
| @@ -281,14 +281,10 @@ ia64_mca_log_sal_error_record(int sal_info_type) | |||
| 281 | ia64_sal_clear_state_info(sal_info_type); | 281 | ia64_sal_clear_state_info(sal_info_type); |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | /* | ||
| 285 | * platform dependent error handling | ||
| 286 | */ | ||
| 287 | #ifndef PLATFORM_MCA_HANDLERS | ||
| 288 | |||
| 289 | #ifdef CONFIG_ACPI | 284 | #ifdef CONFIG_ACPI |
| 290 | 285 | ||
| 291 | int cpe_vector = -1; | 286 | int cpe_vector = -1; |
| 287 | int ia64_cpe_irq = -1; | ||
| 292 | 288 | ||
| 293 | static irqreturn_t | 289 | static irqreturn_t |
| 294 | ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) | 290 | ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) |
| @@ -377,8 +373,6 @@ ia64_mca_register_cpev (int cpev) | |||
| 377 | } | 373 | } |
| 378 | #endif /* CONFIG_ACPI */ | 374 | #endif /* CONFIG_ACPI */ |
| 379 | 375 | ||
| 380 | #endif /* PLATFORM_MCA_HANDLERS */ | ||
| 381 | |||
| 382 | /* | 376 | /* |
| 383 | * ia64_mca_cmc_vector_setup | 377 | * ia64_mca_cmc_vector_setup |
| 384 | * | 378 | * |
| @@ -630,6 +624,32 @@ copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat) | |||
| 630 | *tnat |= (nat << tslot); | 624 | *tnat |= (nat << tslot); |
| 631 | } | 625 | } |
| 632 | 626 | ||
| 627 | /* Change the comm field on the MCA/INT task to include the pid that | ||
| 628 | * was interrupted, it makes for easier debugging. If that pid was 0 | ||
| 629 | * (swapper or nested MCA/INIT) then use the start of the previous comm | ||
| 630 | * field suffixed with its cpu. | ||
| 631 | */ | ||
| 632 | |||
| 633 | static void | ||
| 634 | ia64_mca_modify_comm(const task_t *previous_current) | ||
| 635 | { | ||
| 636 | char *p, comm[sizeof(current->comm)]; | ||
| 637 | if (previous_current->pid) | ||
| 638 | snprintf(comm, sizeof(comm), "%s %d", | ||
| 639 | current->comm, previous_current->pid); | ||
| 640 | else { | ||
| 641 | int l; | ||
| 642 | if ((p = strchr(previous_current->comm, ' '))) | ||
| 643 | l = p - previous_current->comm; | ||
| 644 | else | ||
| 645 | l = strlen(previous_current->comm); | ||
| 646 | snprintf(comm, sizeof(comm), "%s %*s %d", | ||
| 647 | current->comm, l, previous_current->comm, | ||
| 648 | task_thread_info(previous_current)->cpu); | ||
| 649 | } | ||
| 650 | memcpy(current->comm, comm, sizeof(current->comm)); | ||
| 651 | } | ||
| 652 | |||
| 633 | /* On entry to this routine, we are running on the per cpu stack, see | 653 | /* On entry to this routine, we are running on the per cpu stack, see |
| 634 | * mca_asm.h. The original stack has not been touched by this event. Some of | 654 | * mca_asm.h. The original stack has not been touched by this event. Some of |
| 635 | * the original stack's registers will be in the RBS on this stack. This stack | 655 | * the original stack's registers will be in the RBS on this stack. This stack |
| @@ -648,7 +668,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, | |||
| 648 | struct ia64_sal_os_state *sos, | 668 | struct ia64_sal_os_state *sos, |
| 649 | const char *type) | 669 | const char *type) |
| 650 | { | 670 | { |
| 651 | char *p, comm[sizeof(current->comm)]; | 671 | char *p; |
| 652 | ia64_va va; | 672 | ia64_va va; |
| 653 | extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */ | 673 | extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */ |
| 654 | const pal_min_state_area_t *ms = sos->pal_min_state; | 674 | const pal_min_state_area_t *ms = sos->pal_min_state; |
| @@ -721,6 +741,10 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, | |||
| 721 | /* Verify the previous stack state before we change it */ | 741 | /* Verify the previous stack state before we change it */ |
| 722 | if (user_mode(regs)) { | 742 | if (user_mode(regs)) { |
| 723 | msg = "occurred in user space"; | 743 | msg = "occurred in user space"; |
| 744 | /* previous_current is guaranteed to be valid when the task was | ||
| 745 | * in user space, so ... | ||
| 746 | */ | ||
| 747 | ia64_mca_modify_comm(previous_current); | ||
| 724 | goto no_mod; | 748 | goto no_mod; |
| 725 | } | 749 | } |
| 726 | if (r13 != sos->prev_IA64_KR_CURRENT) { | 750 | if (r13 != sos->prev_IA64_KR_CURRENT) { |
| @@ -750,25 +774,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, | |||
| 750 | goto no_mod; | 774 | goto no_mod; |
| 751 | } | 775 | } |
| 752 | 776 | ||
| 753 | /* Change the comm field on the MCA/INT task to include the pid that | 777 | ia64_mca_modify_comm(previous_current); |
| 754 | * was interrupted, it makes for easier debugging. If that pid was 0 | ||
| 755 | * (swapper or nested MCA/INIT) then use the start of the previous comm | ||
| 756 | * field suffixed with its cpu. | ||
| 757 | */ | ||
| 758 | if (previous_current->pid) | ||
| 759 | snprintf(comm, sizeof(comm), "%s %d", | ||
| 760 | current->comm, previous_current->pid); | ||
| 761 | else { | ||
| 762 | int l; | ||
| 763 | if ((p = strchr(previous_current->comm, ' '))) | ||
| 764 | l = p - previous_current->comm; | ||
| 765 | else | ||
| 766 | l = strlen(previous_current->comm); | ||
| 767 | snprintf(comm, sizeof(comm), "%s %*s %d", | ||
| 768 | current->comm, l, previous_current->comm, | ||
| 769 | task_thread_info(previous_current)->cpu); | ||
| 770 | } | ||
| 771 | memcpy(current->comm, comm, sizeof(current->comm)); | ||
| 772 | 778 | ||
| 773 | /* Make the original task look blocked. First stack a struct pt_regs, | 779 | /* Make the original task look blocked. First stack a struct pt_regs, |
| 774 | * describing the state at the time of interrupt. mca_asm.S built a | 780 | * describing the state at the time of interrupt. mca_asm.S built a |
| @@ -908,7 +914,7 @@ no_mod: | |||
| 908 | static void | 914 | static void |
| 909 | ia64_wait_for_slaves(int monarch) | 915 | ia64_wait_for_slaves(int monarch) |
| 910 | { | 916 | { |
| 911 | int c, wait = 0; | 917 | int c, wait = 0, missing = 0; |
| 912 | for_each_online_cpu(c) { | 918 | for_each_online_cpu(c) { |
| 913 | if (c == monarch) | 919 | if (c == monarch) |
| 914 | continue; | 920 | continue; |
| @@ -919,15 +925,32 @@ ia64_wait_for_slaves(int monarch) | |||
| 919 | } | 925 | } |
| 920 | } | 926 | } |
| 921 | if (!wait) | 927 | if (!wait) |
| 922 | return; | 928 | goto all_in; |
| 923 | for_each_online_cpu(c) { | 929 | for_each_online_cpu(c) { |
| 924 | if (c == monarch) | 930 | if (c == monarch) |
| 925 | continue; | 931 | continue; |
| 926 | if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { | 932 | if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { |
| 927 | udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */ | 933 | udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */ |
| 934 | if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) | ||
| 935 | missing = 1; | ||
| 928 | break; | 936 | break; |
| 929 | } | 937 | } |
| 930 | } | 938 | } |
| 939 | if (!missing) | ||
| 940 | goto all_in; | ||
| 941 | printk(KERN_INFO "OS MCA slave did not rendezvous on cpu"); | ||
| 942 | for_each_online_cpu(c) { | ||
| 943 | if (c == monarch) | ||
| 944 | continue; | ||
| 945 | if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) | ||
| 946 | printk(" %d", c); | ||
| 947 | } | ||
| 948 | printk("\n"); | ||
| 949 | return; | ||
| 950 | |||
| 951 | all_in: | ||
| 952 | printk(KERN_INFO "All OS MCA slaves have reached rendezvous\n"); | ||
| 953 | return; | ||
| 931 | } | 954 | } |
| 932 | 955 | ||
| 933 | /* | 956 | /* |
| @@ -953,6 +976,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 953 | task_t *previous_current; | 976 | task_t *previous_current; |
| 954 | 977 | ||
| 955 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ | 978 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ |
| 979 | console_loglevel = 15; /* make sure printks make it to console */ | ||
| 980 | printk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d monarch=%ld\n", | ||
| 981 | sos->proc_state_param, cpu, sos->monarch); | ||
| 982 | |||
| 956 | previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); | 983 | previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); |
| 957 | monarch_cpu = cpu; | 984 | monarch_cpu = cpu; |
| 958 | if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0) | 985 | if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0) |
| @@ -1444,11 +1471,13 @@ void __devinit | |||
| 1444 | ia64_mca_cpu_init(void *cpu_data) | 1471 | ia64_mca_cpu_init(void *cpu_data) |
| 1445 | { | 1472 | { |
| 1446 | void *pal_vaddr; | 1473 | void *pal_vaddr; |
| 1474 | static int first_time = 1; | ||
| 1447 | 1475 | ||
| 1448 | if (smp_processor_id() == 0) { | 1476 | if (first_time) { |
| 1449 | void *mca_data; | 1477 | void *mca_data; |
| 1450 | int cpu; | 1478 | int cpu; |
| 1451 | 1479 | ||
| 1480 | first_time = 0; | ||
| 1452 | mca_data = alloc_bootmem(sizeof(struct ia64_mca_cpu) | 1481 | mca_data = alloc_bootmem(sizeof(struct ia64_mca_cpu) |
| 1453 | * NR_CPUS + KERNEL_STACK_SIZE); | 1482 | * NR_CPUS + KERNEL_STACK_SIZE); |
| 1454 | mca_data = (void *)(((unsigned long)mca_data + | 1483 | mca_data = (void *)(((unsigned long)mca_data + |
| @@ -1704,6 +1733,7 @@ ia64_mca_late_init(void) | |||
| 1704 | desc = irq_descp(irq); | 1733 | desc = irq_descp(irq); |
| 1705 | desc->status |= IRQ_PER_CPU; | 1734 | desc->status |= IRQ_PER_CPU; |
| 1706 | setup_irq(irq, &mca_cpe_irqaction); | 1735 | setup_irq(irq, &mca_cpe_irqaction); |
| 1736 | ia64_cpe_irq = irq; | ||
| 1707 | } | 1737 | } |
| 1708 | ia64_mca_register_cpev(cpe_vector); | 1738 | ia64_mca_register_cpev(cpe_vector); |
| 1709 | IA64_MCA_DEBUG("%s: CPEI/P setup and enabled.\n", __FUNCTION__); | 1739 | IA64_MCA_DEBUG("%s: CPEI/P setup and enabled.\n", __FUNCTION__); |
