import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / s390x / kernel / s390_ext.c
1 /*
2  *  arch/s390/kernel/s390_ext.c
3  *
4  *  S390 version
5  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
6  *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com),
7  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
8  */
9
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/slab.h>
13 #include <asm/lowcore.h>
14 #include <asm/s390_ext.h>
15
16 /*
17  * Simple hash strategy: index = code & 0xff;
18  * ext_int_hash[index] is the start of the list for all external interrupts
19  * that hash to this index. With the current set of external interrupts 
20  * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000
21  * iucv and 0x2603 pfault) this is always the first element. 
22  */
23 ext_int_info_t *ext_int_hash[256] = { 0, };
24
25 int register_external_interrupt(__u16 code, ext_int_handler_t handler) {
26         ext_int_info_t *p;
27         int index;
28
29         p = (ext_int_info_t *) kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
30         if (p == NULL)
31                 return -ENOMEM;
32         p->code = code;
33         p->handler = handler;
34         index = code & 0xff;
35         p->next = ext_int_hash[index];
36         ext_int_hash[index] = p;
37         return 0;
38 }
39
40 int register_early_external_interrupt(__u16 code, ext_int_handler_t handler,
41                                       ext_int_info_t *p) {
42         int index;
43
44         if (p == NULL)
45                 return -EINVAL;
46         p->code = code;
47         p->handler = handler;
48         index = code & 0xff;
49         p->next = ext_int_hash[index];
50         ext_int_hash[index] = p;
51         return 0;
52 }
53
54 int unregister_external_interrupt(__u16 code, ext_int_handler_t handler) {
55         ext_int_info_t *p, *q;
56         int index;
57
58         index = code & 0xff;
59         q = NULL;
60         p = ext_int_hash[index];
61         while (p != NULL) {
62                 if (p->code == code && p->handler == handler)
63                         break;
64                 q = p;
65                 p = p->next;
66         }
67         if (p == NULL)
68                 return -ENOENT;
69         if (q != NULL)
70                 q->next = p->next;
71         else
72                 ext_int_hash[index] = p->next;
73         kfree(p);
74         return 0;
75 }
76
77 int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
78                                         ext_int_info_t *p) {
79         ext_int_info_t *q;
80         int index;
81
82         if (p == NULL || p->code != code || p->handler != handler)
83                 return -EINVAL;
84         index = code & 0xff;
85         q = ext_int_hash[index];
86         if (p != q) {
87                 while (q != NULL) {
88                         if (q->next == p)
89                                 break;
90                         q = q->next;
91                 }
92                 if (q == NULL)
93                         return -ENOENT;
94                 q->next = p->next;
95         } else
96                 ext_int_hash[index] = p->next;
97         return 0;
98 }
99
100 EXPORT_SYMBOL(register_external_interrupt);
101 EXPORT_SYMBOL(unregister_external_interrupt);
102