X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fs390%2Fs390mach.c;h=ffb3677e354fe9c1a7d0848453d91353fb33cc7e;hb=60be6b9a41cb0da0df7a9f11486da56baebf04cd;hp=3bf466603512a32f2c6a933525492eed58963f33;hpb=25da0974601fc8096461f3d3f7ca3aab8e79adfb;p=powerpc.git diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 3bf4666035..ffb3677e35 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c @@ -8,11 +8,12 @@ * Martin Schwidefsky (schwidefsky@de.ibm.com) */ -#include #include #include #include #include +#include +#include #include @@ -55,8 +56,6 @@ s390_collect_crw_info(void *param) unsigned int chain; sem = (struct semaphore *)param; - /* Set a nice name. */ - daemonize("kmcheck"); repeat: down_interruptible(sem); slow = 0; @@ -362,16 +361,25 @@ s390_revalidate_registers(struct mci *mci) return kill_task; } +#define MAX_IPD_COUNT 29 +#define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */ + /* * machine check handler. */ void s390_do_machine_check(struct pt_regs *regs) { + static DEFINE_SPINLOCK(ipd_lock); + static unsigned long long last_ipd; + static int ipd_count; + unsigned long long tmp; struct mci *mci; struct mcck_struct *mcck; int umode; + lockdep_off(); + mci = (struct mci *) &S390_lowcore.mcck_interruption_code; mcck = &__get_cpu_var(cpu_mcck); umode = user_mode(regs); @@ -404,11 +412,27 @@ s390_do_machine_check(struct pt_regs *regs) s390_handle_damage("processing backup machine " "check with damage."); } - if (!umode) - s390_handle_damage("processing backup machine " - "check in kernel mode."); - mcck->kill_task = 1; - mcck->mcck_code = *(unsigned long long *) mci; + + /* + * Nullifying exigent condition, therefore we might + * retry this instruction. + */ + + spin_lock(&ipd_lock); + + tmp = get_clock(); + + if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME) + ipd_count++; + else + ipd_count = 1; + + last_ipd = tmp; + + if (ipd_count == MAX_IPD_COUNT) + s390_handle_damage("too many ipd retries."); + + spin_unlock(&ipd_lock); } else { /* Processing damage -> stopping machine */ @@ -460,6 +484,7 @@ s390_do_machine_check(struct pt_regs *regs) mcck->warning = 1; set_thread_flag(TIF_MCCK_PENDING); } + lockdep_on(); } /* @@ -492,7 +517,7 @@ arch_initcall(machine_check_init); static int __init machine_check_crw_init (void) { - kernel_thread(s390_collect_crw_info, &m_sem, CLONE_FS|CLONE_FILES); + kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); ctl_set_bit(14, 28); /* enable channel report MCH */ return 0; }