2 * arch/s390/kernel/s390dyn.c
3 * S/390 dynamic device attachment
6 * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Ingo Adlung (adlung@de.ibm.com)
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/smp_lock.h>
15 #include <asm/s390io.h>
16 #include <asm/s390dyn.h>
18 static struct list_head devreg_anchor = LIST_HEAD_INIT(devreg_anchor);
19 static spinlock_t dyn_lock = SPIN_LOCK_UNLOCKED;
21 static inline int s390_device_register_internal(devreg_t *drinfo)
25 list_for_each(p, &devreg_anchor) {
26 devreg_t *pdevreg = list_entry(p, devreg_t, list);
28 if (pdevreg == drinfo)
31 * We don't allow multiple drivers to register
32 * for the same device number
34 if (pdevreg->ci.devno == drinfo->ci.devno &&
35 (pdevreg->flag & DEVREG_TYPE_DEVNO) &&
36 (drinfo->flag & DEVREG_TYPE_DEVNO))
39 if (drinfo->flag == (DEVREG_TYPE_DEVCHARS |
40 DEVREG_EXACT_MATCH) &&
41 !memcmp(&drinfo->ci.hc, &pdevreg->ci.hc,
47 * no collision found, enqueue
49 list_add (&drinfo->list, &devreg_anchor);
54 int s390_device_register( devreg_t *drinfo )
60 !(drinfo->flag & (DEVREG_TYPE_DEVNO | DEVREG_TYPE_DEVCHARS)))
63 spin_lock_irqsave (&dyn_lock, flags);
64 ret = s390_device_register_internal(drinfo);
65 spin_unlock_irqrestore( &dyn_lock, flags );
70 static inline int s390_device_unregister_internal(devreg_t *dreg)
74 list_for_each(p, &devreg_anchor) {
75 devreg_t *pdevreg = list_entry(p, devreg_t, list);
77 if (pdevreg == dreg) {
78 list_del (&dreg->list);
85 int s390_device_unregister(devreg_t *dreg)
93 spin_lock_irqsave(&dyn_lock, flags);
94 ret = s390_device_unregister_internal(dreg);
95 spin_unlock_irqrestore(&dyn_lock, flags);
100 static inline devreg_t *s390_search_devreg_internal(ioinfo_t *ioinfo)
104 list_for_each(p, &devreg_anchor) {
105 devreg_t *pdevreg = list_entry(p, devreg_t, list);
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)
115 } else if (flag & DEVREG_TYPE_DEVCHARS) {
116 if ( (flag & DEVREG_MATCH_CU_TYPE) &&
117 pdevreg->ci.hc.ctype != sid->cu_type )
119 if ( (flag & DEVREG_MATCH_CU_MODEL) &&
120 pdevreg->ci.hc.cmode != sid->cu_model )
122 if ( (flag & DEVREG_MATCH_DEV_TYPE) &&
123 pdevreg->ci.hc.dtype != sid->dev_type )
125 if ( (flag & DEVREG_MATCH_DEV_MODEL) &&
126 pdevreg->ci.hc.dmode != sid->dev_model )
137 devreg_t * s390_search_devreg( ioinfo_t *ioinfo )
145 spin_lock_irqsave(&dyn_lock, flags);
146 pdevreg = s390_search_devreg_internal(ioinfo);
147 spin_unlock_irqrestore(&dyn_lock, flags);
152 EXPORT_SYMBOL(s390_device_register);
153 EXPORT_SYMBOL(s390_device_unregister);