Merge branch 'master' into upstream-fixes
[linux-2.6] / drivers / s390 / cio / airq.c
1 /*
2  *  drivers/s390/cio/airq.c
3  *   S/390 common I/O routines -- support for adapter interruptions
4  *
5  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
6  *                            IBM Corporation
7  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
8  *               Cornelia Huck (cornelia.huck@de.ibm.com)
9  *               Arnd Bergmann (arndb@de.ibm.com)
10  */
11
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/rcupdate.h>
16
17 #include "cio_debug.h"
18 #include "airq.h"
19
20 static adapter_int_handler_t adapter_handler;
21
22 /*
23  * register for adapter interrupts
24  *
25  * With HiperSockets the zSeries architecture provides for
26  *  means of adapter interrups, pseudo I/O interrupts that are
27  *  not tied to an I/O subchannel, but to an adapter. However,
28  *  it doesn't disclose the info how to enable/disable them, but
29  *  to recognize them only. Perhaps we should consider them
30  *  being shared interrupts, and thus build a linked list
31  *  of adapter handlers ... to be evaluated ...
32  */
33 int
34 s390_register_adapter_interrupt (adapter_int_handler_t handler)
35 {
36         int ret;
37         char dbf_txt[15];
38
39         CIO_TRACE_EVENT (4, "rgaint");
40
41         if (handler == NULL)
42                 ret = -EINVAL;
43         else
44                 ret = (cmpxchg(&adapter_handler, NULL, handler) ? -EBUSY : 0);
45         if (!ret)
46                 synchronize_sched();  /* Allow interrupts to complete. */
47
48         sprintf (dbf_txt, "ret:%d", ret);
49         CIO_TRACE_EVENT (4, dbf_txt);
50
51         return ret;
52 }
53
54 int
55 s390_unregister_adapter_interrupt (adapter_int_handler_t handler)
56 {
57         int ret;
58         char dbf_txt[15];
59
60         CIO_TRACE_EVENT (4, "urgaint");
61
62         if (handler == NULL)
63                 ret = -EINVAL;
64         else {
65                 adapter_handler = NULL;
66                 synchronize_sched();  /* Allow interrupts to complete. */
67                 ret = 0;
68         }
69         sprintf (dbf_txt, "ret:%d", ret);
70         CIO_TRACE_EVENT (4, dbf_txt);
71
72         return ret;
73 }
74
75 void
76 do_adapter_IO (void)
77 {
78         CIO_TRACE_EVENT (6, "doaio");
79
80         if (adapter_handler)
81                 (*adapter_handler) ();
82 }
83
84 EXPORT_SYMBOL (s390_register_adapter_interrupt);
85 EXPORT_SYMBOL (s390_unregister_adapter_interrupt);