diff options
author | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-06-10 13:47:26 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-06-10 13:47:26 -0500 |
commit | f0cd91a68acdc9b49d7f6738b514a426da627649 (patch) | |
tree | 8ad73564015794197583b094217ae0a71e71e753 /drivers/s390/s390mach.c | |
parent | 60eef25701d25e99c991dd0f4a9f3832a0c3ad3e (diff) | |
parent | 128e6ced247cda88f96fa9f2e4ba8b2c4a681560 (diff) |
Merge ../linux-2.6
Diffstat (limited to 'drivers/s390/s390mach.c')
-rw-r--r-- | drivers/s390/s390mach.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 3bf466603512..f99e55308b32 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c @@ -13,6 +13,7 @@ #include <linux/sched.h> #include <linux/errno.h> #include <linux/workqueue.h> +#include <linux/time.h> #include <asm/lowcore.h> @@ -362,12 +363,19 @@ 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; @@ -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 */ |