* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
+#include <linux/config.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/workqueue.h>
-#include <linux/time.h>
-#include <linux/kthread.h>
#include <asm/lowcore.h>
unsigned int chain;
sem = (struct semaphore *)param;
+ /* Set a nice name. */
+ daemonize("kmcheck");
repeat:
down_interruptible(sem);
slow = 0;
break;
case CRW_RSC_CPATH:
pr_debug("source is channel path %02X\n", crw[0].rsid);
- /*
- * Check for solicited machine checks. These are
- * created by reset channel path and need not be
- * reported to the common I/O layer.
- */
- if (crw[chain].slct) {
- DBG(KERN_INFO"solicited machine check for "
- "channel path %02X\n", crw[0].rsid);
- break;
- }
switch (crw[0].erc) {
case CRW_ERC_IPARM: /* Path has come. */
ret = chp_process_crw(crw[0].rsid, 1);
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);
s390_handle_damage("processing backup machine "
"check with damage.");
}
-
- /*
- * 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);
+ if (!umode)
+ s390_handle_damage("processing backup machine "
+ "check in kernel mode.");
+ mcck->kill_task = 1;
+ mcck->mcck_code = *(unsigned long long *) mci;
}
else {
/* Processing damage -> stopping machine */
mcck->warning = 1;
set_thread_flag(TIF_MCCK_PENDING);
}
- lockdep_on();
}
/*
static int __init
machine_check_crw_init (void)
{
- kthread_run(s390_collect_crw_info, &m_sem, "kmcheck");
+ kernel_thread(s390_collect_crw_info, &m_sem, CLONE_FS|CLONE_FILES);
ctl_set_bit(14, 28); /* enable channel report MCH */
return 0;
}