diff options
Diffstat (limited to 'drivers/s390/s390mach.c')
-rw-r--r-- | drivers/s390/s390mach.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 3bf466603512..5ae14803091f 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c | |||
@@ -362,12 +362,19 @@ s390_revalidate_registers(struct mci *mci) | |||
362 | return kill_task; | 362 | return kill_task; |
363 | } | 363 | } |
364 | 364 | ||
365 | #define MAX_IPD_COUNT 29 | ||
366 | #define MAX_IPD_TIME (5 * 60 * 100 * 1000) /* 5 minutes */ | ||
367 | |||
365 | /* | 368 | /* |
366 | * machine check handler. | 369 | * machine check handler. |
367 | */ | 370 | */ |
368 | void | 371 | void |
369 | s390_do_machine_check(struct pt_regs *regs) | 372 | s390_do_machine_check(struct pt_regs *regs) |
370 | { | 373 | { |
374 | static DEFINE_SPINLOCK(ipd_lock); | ||
375 | static unsigned long long last_ipd; | ||
376 | static int ipd_count; | ||
377 | unsigned long long tmp; | ||
371 | struct mci *mci; | 378 | struct mci *mci; |
372 | struct mcck_struct *mcck; | 379 | struct mcck_struct *mcck; |
373 | int umode; | 380 | int umode; |
@@ -404,11 +411,27 @@ s390_do_machine_check(struct pt_regs *regs) | |||
404 | s390_handle_damage("processing backup machine " | 411 | s390_handle_damage("processing backup machine " |
405 | "check with damage."); | 412 | "check with damage."); |
406 | } | 413 | } |
407 | if (!umode) | 414 | |
408 | s390_handle_damage("processing backup machine " | 415 | /* |
409 | "check in kernel mode."); | 416 | * Nullifying exigent condition, therefore we might |
410 | mcck->kill_task = 1; | 417 | * retry this instruction. |
411 | mcck->mcck_code = *(unsigned long long *) mci; | 418 | */ |
419 | |||
420 | spin_lock(&ipd_lock); | ||
421 | |||
422 | tmp = get_clock(); | ||
423 | |||
424 | if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME) | ||
425 | ipd_count++; | ||
426 | else | ||
427 | ipd_count = 1; | ||
428 | |||
429 | last_ipd = tmp; | ||
430 | |||
431 | if (ipd_count == MAX_IPD_COUNT) | ||
432 | s390_handle_damage("too many ipd retries."); | ||
433 | |||
434 | spin_unlock(&ipd_lock); | ||
412 | } | 435 | } |
413 | else { | 436 | else { |
414 | /* Processing damage -> stopping machine */ | 437 | /* Processing damage -> stopping machine */ |