From 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 Mon Sep 17 00:00:00 2001 From: Yunhong Jiang Date: Tue, 4 Aug 2015 12:17:53 -0700 Subject: Add the rt linux 4.1.3-rt3 as base Import the rt linux 4.1.3-rt3 as OPNFV kvm base. It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and the base is: commit 0917f823c59692d751951bf5ea699a2d1e2f26a2 Author: Sebastian Andrzej Siewior Date: Sat Jul 25 12:13:34 2015 +0200 Prepare v4.1.3-rt3 Signed-off-by: Sebastian Andrzej Siewior We lose all the git history this way and it's not good. We should apply another opnfv project repo in future. Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423 Signed-off-by: Yunhong Jiang --- kernel/drivers/s390/cio/crw.c | 161 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 kernel/drivers/s390/cio/crw.c (limited to 'kernel/drivers/s390/cio/crw.c') diff --git a/kernel/drivers/s390/cio/crw.c b/kernel/drivers/s390/cio/crw.c new file mode 100644 index 000000000..0f8a25f98 --- /dev/null +++ b/kernel/drivers/s390/cio/crw.c @@ -0,0 +1,161 @@ +/* + * Channel report handling code + * + * Copyright IBM Corp. 2000, 2009 + * Author(s): Ingo Adlung , + * Martin Schwidefsky , + * Cornelia Huck , + * Heiko Carstens , + */ + +#include +#include +#include +#include +#include +#include + +static DEFINE_MUTEX(crw_handler_mutex); +static crw_handler_t crw_handlers[NR_RSCS]; +static atomic_t crw_nr_req = ATOMIC_INIT(0); +static DECLARE_WAIT_QUEUE_HEAD(crw_handler_wait_q); + +/** + * crw_register_handler() - register a channel report word handler + * @rsc: reporting source code to handle + * @handler: handler to be registered + * + * Returns %0 on success and a negative error value otherwise. + */ +int crw_register_handler(int rsc, crw_handler_t handler) +{ + int rc = 0; + + if ((rsc < 0) || (rsc >= NR_RSCS)) + return -EINVAL; + mutex_lock(&crw_handler_mutex); + if (crw_handlers[rsc]) + rc = -EBUSY; + else + crw_handlers[rsc] = handler; + mutex_unlock(&crw_handler_mutex); + return rc; +} + +/** + * crw_unregister_handler() - unregister a channel report word handler + * @rsc: reporting source code to handle + */ +void crw_unregister_handler(int rsc) +{ + if ((rsc < 0) || (rsc >= NR_RSCS)) + return; + mutex_lock(&crw_handler_mutex); + crw_handlers[rsc] = NULL; + mutex_unlock(&crw_handler_mutex); +} + +/* + * Retrieve CRWs and call function to handle event. + */ +static int crw_collect_info(void *unused) +{ + struct crw crw[2]; + int ccode, signal; + unsigned int chain; + +repeat: + signal = wait_event_interruptible(crw_handler_wait_q, + atomic_read(&crw_nr_req) > 0); + if (unlikely(signal)) + atomic_inc(&crw_nr_req); + chain = 0; + while (1) { + crw_handler_t handler; + + if (unlikely(chain > 1)) { + struct crw tmp_crw; + + printk(KERN_WARNING"%s: Code does not support more " + "than two chained crws; please report to " + "linux390@de.ibm.com!\n", __func__); + ccode = stcrw(&tmp_crw); + printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " + "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", + __func__, tmp_crw.slct, tmp_crw.oflw, + tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc, + tmp_crw.erc, tmp_crw.rsid); + printk(KERN_WARNING"%s: This was crw number %x in the " + "chain\n", __func__, chain); + if (ccode != 0) + break; + chain = tmp_crw.chn ? chain + 1 : 0; + continue; + } + ccode = stcrw(&crw[chain]); + if (ccode != 0) + break; + printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " + "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", + crw[chain].slct, crw[chain].oflw, crw[chain].chn, + crw[chain].rsc, crw[chain].anc, crw[chain].erc, + crw[chain].rsid); + /* Check for overflows. */ + if (crw[chain].oflw) { + int i; + + pr_debug("%s: crw overflow detected!\n", __func__); + mutex_lock(&crw_handler_mutex); + for (i = 0; i < NR_RSCS; i++) { + if (crw_handlers[i]) + crw_handlers[i](NULL, NULL, 1); + } + mutex_unlock(&crw_handler_mutex); + chain = 0; + continue; + } + if (crw[0].chn && !chain) { + chain++; + continue; + } + mutex_lock(&crw_handler_mutex); + handler = crw_handlers[crw[chain].rsc]; + if (handler) + handler(&crw[0], chain ? &crw[1] : NULL, 0); + mutex_unlock(&crw_handler_mutex); + /* chain is always 0 or 1 here. */ + chain = crw[chain].chn ? chain + 1 : 0; + } + if (atomic_dec_and_test(&crw_nr_req)) + wake_up(&crw_handler_wait_q); + goto repeat; + return 0; +} + +void crw_handle_channel_report(void) +{ + atomic_inc(&crw_nr_req); + wake_up(&crw_handler_wait_q); +} + +void crw_wait_for_channel_report(void) +{ + crw_handle_channel_report(); + wait_event(crw_handler_wait_q, atomic_read(&crw_nr_req) == 0); +} + +/* + * Machine checks for the channel subsystem must be enabled + * after the channel subsystem is initialized + */ +static int __init crw_machine_check_init(void) +{ + struct task_struct *task; + + task = kthread_run(crw_collect_info, NULL, "kmcheck"); + if (IS_ERR(task)) + return PTR_ERR(task); + ctl_set_bit(14, 28); /* enable channel report MCH */ + return 0; +} +device_initcall(crw_machine_check_init); -- cgit 1.2.3-korg