1
2
3
4
5
6
7
8
9
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/smp_lock.h>
13
14#include <asm/irq.h>
15#include <asm/s390io.h>
16#include <asm/s390dyn.h>
17
18static struct list_head devreg_anchor = LIST_HEAD_INIT(devreg_anchor);
19static spinlock_t dyn_lock = SPIN_LOCK_UNLOCKED;
20
21static inline int s390_device_register_internal(devreg_t *drinfo)
22{
23 struct list_head *p;
24
25 list_for_each(p, &devreg_anchor) {
26 devreg_t *pdevreg = list_entry(p, devreg_t, list);
27
28 if (pdevreg == drinfo)
29 return -EINVAL;
30
31
32
33
34 if (pdevreg->ci.devno == drinfo->ci.devno &&
35 (pdevreg->flag & DEVREG_TYPE_DEVNO) &&
36 (drinfo->flag & DEVREG_TYPE_DEVNO))
37 return -EBUSY;
38
39 if (drinfo->flag == (DEVREG_TYPE_DEVCHARS |
40 DEVREG_EXACT_MATCH) &&
41 !memcmp(&drinfo->ci.hc, &pdevreg->ci.hc,
42 sizeof(devreg_hc_t)))
43 return -EBUSY;
44 }
45
46
47
48
49 list_add (&drinfo->list, &devreg_anchor);
50
51 return 0;
52}
53
54int s390_device_register( devreg_t *drinfo )
55{
56 unsigned long flags;
57 int ret;
58
59 if (drinfo == NULL ||
60 !(drinfo->flag & (DEVREG_TYPE_DEVNO | DEVREG_TYPE_DEVCHARS)))
61 return -EINVAL;
62
63 spin_lock_irqsave (&dyn_lock, flags);
64 ret = s390_device_register_internal(drinfo);
65 spin_unlock_irqrestore( &dyn_lock, flags );
66
67 return ret;
68}
69
70static inline int s390_device_unregister_internal(devreg_t *dreg)
71{
72 struct list_head *p;
73
74 list_for_each(p, &devreg_anchor) {
75 devreg_t *pdevreg = list_entry(p, devreg_t, list);
76
77 if (pdevreg == dreg) {
78 list_del (&dreg->list);
79 return 0;
80 }
81 }
82 return -EINVAL;
83}
84
85int s390_device_unregister(devreg_t *dreg)
86{
87 unsigned long flags;
88 int ret;
89
90 if (dreg == NULL)
91 return -EINVAL;
92
93 spin_lock_irqsave(&dyn_lock, flags);
94 ret = s390_device_unregister_internal(dreg);
95 spin_unlock_irqrestore(&dyn_lock, flags);
96
97 return ret;
98}
99
100static inline devreg_t *s390_search_devreg_internal(ioinfo_t *ioinfo)
101{
102 struct list_head *p;
103
104 list_for_each(p, &devreg_anchor) {
105 devreg_t *pdevreg = list_entry(p, devreg_t, list);
106 senseid_t *sid;
107 int flag;
108
109 flag = pdevreg->flag;
110 sid = &ioinfo->senseid;
111 if (flag & DEVREG_TYPE_DEVNO) {
112 if (ioinfo->ui.flags.dval != 1 ||
113 ioinfo->devno != pdevreg->ci.devno)
114 continue;
115 } else if (flag & DEVREG_TYPE_DEVCHARS) {
116 if ( (flag & DEVREG_MATCH_CU_TYPE) &&
117 pdevreg->ci.hc.ctype != sid->cu_type )
118 continue;
119 if ( (flag & DEVREG_MATCH_CU_MODEL) &&
120 pdevreg->ci.hc.cmode != sid->cu_model )
121 continue;
122 if ( (flag & DEVREG_MATCH_DEV_TYPE) &&
123 pdevreg->ci.hc.dtype != sid->dev_type )
124 continue;
125 if ( (flag & DEVREG_MATCH_DEV_MODEL) &&
126 pdevreg->ci.hc.dmode != sid->dev_model )
127 continue;
128 } else {
129 continue;
130 }
131
132 return pdevreg;
133 }
134 return NULL;
135}
136
137devreg_t * s390_search_devreg( ioinfo_t *ioinfo )
138{
139 unsigned long flags;
140 devreg_t *pdevreg;
141
142 if (ioinfo == NULL)
143 return NULL;
144
145 spin_lock_irqsave(&dyn_lock, flags);
146 pdevreg = s390_search_devreg_internal(ioinfo);
147 spin_unlock_irqrestore(&dyn_lock, flags);
148
149 return pdevreg;
150}
151
152EXPORT_SYMBOL(s390_device_register);
153EXPORT_SYMBOL(s390_device_unregister);
154
155