linux/drivers/s390/cio/crw.c
<<
>>
Prefs
   1/*
   2 *   Channel report handling code
   3 *
   4 *    Copyright IBM Corp. 2000,2009
   5 *    Author(s): Ingo Adlung <adlung@de.ibm.com>,
   6 *               Martin Schwidefsky <schwidefsky@de.ibm.com>,
   7 *               Cornelia Huck <cornelia.huck@de.ibm.com>,
   8 *               Heiko Carstens <heiko.carstens@de.ibm.com>,
   9 */
  10
  11#include <linux/mutex.h>
  12#include <linux/kthread.h>
  13#include <linux/init.h>
  14#include <linux/wait.h>
  15#include <asm/crw.h>
  16
  17static DEFINE_MUTEX(crw_handler_mutex);
  18static crw_handler_t crw_handlers[NR_RSCS];
  19static atomic_t crw_nr_req = ATOMIC_INIT(0);
  20static DECLARE_WAIT_QUEUE_HEAD(crw_handler_wait_q);
  21
  22/**
  23 * crw_register_handler() - register a channel report word handler
  24 * @rsc: reporting source code to handle
  25 * @handler: handler to be registered
  26 *
  27 * Returns %0 on success and a negative error value otherwise.
  28 */
  29int crw_register_handler(int rsc, crw_handler_t handler)
  30{
  31        int rc = 0;
  32
  33        if ((rsc < 0) || (rsc >= NR_RSCS))
  34                return -EINVAL;
  35        mutex_lock(&crw_handler_mutex);
  36        if (crw_handlers[rsc])
  37                rc = -EBUSY;
  38        else
  39                crw_handlers[rsc] = handler;
  40        mutex_unlock(&crw_handler_mutex);
  41        return rc;
  42}
  43
  44/**
  45 * crw_unregister_handler() - unregister a channel report word handler
  46 * @rsc: reporting source code to handle
  47 */
  48void crw_unregister_handler(int rsc)
  49{
  50        if ((rsc < 0) || (rsc >= NR_RSCS))
  51                return;
  52        mutex_lock(&crw_handler_mutex);
  53        crw_handlers[rsc] = NULL;
  54        mutex_unlock(&crw_handler_mutex);
  55}
  56
  57/*
  58 * Retrieve CRWs and call function to handle event.
  59 */
  60static int crw_collect_info(void *unused)
  61{
  62        struct crw crw[2];
  63        int ccode, signal;
  64        unsigned int chain;
  65
  66repeat:
  67        signal = wait_event_interruptible(crw_handler_wait_q,
  68                                          atomic_read(&crw_nr_req) > 0);
  69        if (unlikely(signal))
  70                atomic_inc(&crw_nr_req);
  71        chain = 0;
  72        while (1) {
  73                crw_handler_t handler;
  74
  75                if (unlikely(chain > 1)) {
  76                        struct crw tmp_crw;
  77
  78                        printk(KERN_WARNING"%s: Code does not support more "
  79                               "than two chained crws; please report to "
  80                               "linux390@de.ibm.com!\n", __func__);
  81                        ccode = stcrw(&tmp_crw);
  82                        printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
  83                               "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
  84                               __func__, tmp_crw.slct, tmp_crw.oflw,
  85                               tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
  86                               tmp_crw.erc, tmp_crw.rsid);
  87                        printk(KERN_WARNING"%s: This was crw number %x in the "
  88                               "chain\n", __func__, chain);
  89                        if (ccode != 0)
  90                                break;
  91                        chain = tmp_crw.chn ? chain + 1 : 0;
  92                        continue;
  93                }
  94                ccode = stcrw(&crw[chain]);
  95                if (ccode != 0)
  96                        break;
  97                printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, "
  98                       "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
  99                       crw[chain].slct, crw[chain].oflw, crw[chain].chn,
 100                       crw[chain].rsc, crw[chain].anc, crw[chain].erc,
 101                       crw[chain].rsid);
 102                /* Check for overflows. */
 103                if (crw[chain].oflw) {
 104                        int i;
 105
 106                        pr_debug("%s: crw overflow detected!\n", __func__);
 107                        mutex_lock(&crw_handler_mutex);
 108                        for (i = 0; i < NR_RSCS; i++) {
 109                                if (crw_handlers[i])
 110                                        crw_handlers[i](NULL, NULL, 1);
 111                        }
 112                        mutex_unlock(&crw_handler_mutex);
 113                        chain = 0;
 114                        continue;
 115                }
 116                if (crw[0].chn && !chain) {
 117                        chain++;
 118                        continue;
 119                }
 120                mutex_lock(&crw_handler_mutex);
 121                handler = crw_handlers[crw[chain].rsc];
 122                if (handler)
 123                        handler(&crw[0], chain ? &crw[1] : NULL, 0);
 124                mutex_unlock(&crw_handler_mutex);
 125                /* chain is always 0 or 1 here. */
 126                chain = crw[chain].chn ? chain + 1 : 0;
 127        }
 128        if (atomic_dec_and_test(&crw_nr_req))
 129                wake_up(&crw_handler_wait_q);
 130        goto repeat;
 131        return 0;
 132}
 133
 134void crw_handle_channel_report(void)
 135{
 136        atomic_inc(&crw_nr_req);
 137        wake_up(&crw_handler_wait_q);
 138}
 139
 140void crw_wait_for_channel_report(void)
 141{
 142        crw_handle_channel_report();
 143        wait_event(crw_handler_wait_q, atomic_read(&crw_nr_req) == 0);
 144}
 145
 146/*
 147 * Machine checks for the channel subsystem must be enabled
 148 * after the channel subsystem is initialized
 149 */
 150static int __init crw_machine_check_init(void)
 151{
 152        struct task_struct *task;
 153
 154        task = kthread_run(crw_collect_info, NULL, "kmcheck");
 155        if (IS_ERR(task))
 156                return PTR_ERR(task);
 157        ctl_set_bit(14, 28);    /* enable channel report MCH */
 158        return 0;
 159}
 160device_initcall(crw_machine_check_init);
 161