patch-2.4.4 linux/drivers/s390/s390dyn.c
Next file: linux/drivers/s390/s390io.c
Previous file: linux/drivers/s390/net/netiucv.c
Back to the patch index
Back to the overall index
- Lines: 325
- Date:
Wed Apr 11 19:02:28 2001
- Orig file:
v2.4.3/linux/drivers/s390/s390dyn.c
- Orig date:
Tue Feb 13 14:13:44 2001
diff -u --recursive --new-file v2.4.3/linux/drivers/s390/s390dyn.c linux/drivers/s390/s390dyn.c
@@ -7,6 +7,7 @@
* Author(s): Ingo Adlung (adlung@de.ibm.com)
*/
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
@@ -14,200 +15,149 @@
#include <asm/s390io.h>
#include <asm/s390dyn.h>
-static devreg_t *devreg_anchor = NULL;
-static spinlock_t dyn_lock = SPIN_LOCK_UNLOCKED;
+static struct list_head devreg_anchor = LIST_HEAD_INIT(devreg_anchor);
+static spinlock_t dyn_lock = SPIN_LOCK_UNLOCKED;
-
-int s390_device_register( devreg_t *drinfo )
+static inline int s390_device_register_internal(devreg_t *drinfo)
{
- unsigned long flags;
- int pdevflag,drflag;
-
- int ret = 0;
- devreg_t *pdevreg = devreg_anchor;
-
- if ( drinfo == NULL )
- return( -EINVAL );
+ struct list_head *p;
- drflag = drinfo->flag;
-
- if ( (drflag & DEVREG_TYPE_DEVNO) == (drflag & DEVREG_TYPE_DEVCHARS) )
- return( -EINVAL );
-
- spin_lock_irqsave( &dyn_lock, flags );
-
- while ( (pdevreg != NULL) && (ret ==0) )
- {
- if ( pdevreg == drinfo )
- {
- ret = -EINVAL;
- }
- else
- {
- pdevflag = pdevreg->flag;
-
- /*
- * we don't allow multiple drivers to register
- * for the same device number
- */
- if ( ( (pdevflag & DEVREG_TYPE_DEVNO)
- && (pdevreg->ci.devno ) )
- && ( (drflag & DEVREG_TYPE_DEVNO )
- && (drinfo->ci.devno ) ) )
- {
- ret = -EBUSY;
- }
- else if ( drflag == ( DEVREG_TYPE_DEVCHARS
- | DEVREG_EXACT_MATCH ))
- {
- if ( !memcmp(&drinfo->ci.hc,
- &pdevreg->ci.hc,
- sizeof(devreg_hc_t)))
- ret=-EBUSY;
- } /* endif */
-
- } /* endif */
-
- pdevreg = pdevreg->next;
+ list_for_each(p, &devreg_anchor) {
+ devreg_t *pdevreg = list_entry(p, devreg_t, list);
+
+ if (pdevreg == drinfo)
+ return -EINVAL;
+ /*
+ * We don't allow multiple drivers to register
+ * for the same device number
+ */
+ if (pdevreg->ci.devno == drinfo->ci.devno &&
+ (pdevreg->flag & DEVREG_TYPE_DEVNO) &&
+ (drinfo->flag & DEVREG_TYPE_DEVNO))
+ return -EBUSY;
+
+ if (drinfo->flag == (DEVREG_TYPE_DEVCHARS |
+ DEVREG_EXACT_MATCH) &&
+ !memcmp(&drinfo->ci.hc, &pdevreg->ci.hc,
+ sizeof(devreg_hc_t)))
+ return -EBUSY;
+ }
+
+ /*
+ * no collision found, enqueue
+ */
+ list_add (&drinfo->list, &devreg_anchor);
- } /* endwhile */
+ return 0;
+}
- /*
- * only enqueue if no collision was found ...
- */
- if(ret==0)
- {
- drinfo->next = devreg_anchor;
- drinfo->prev = NULL;
-
- if ( devreg_anchor != NULL )
- {
- devreg_anchor->prev = drinfo;
-
- } /* endif */
-
- devreg_anchor=drinfo;
+int s390_device_register( devreg_t *drinfo )
+{
+ unsigned long flags;
+ int ret;
- } /* endif */
+ if (drinfo == NULL ||
+ !(drinfo->flag & (DEVREG_TYPE_DEVNO | DEVREG_TYPE_DEVCHARS)))
+ return -EINVAL;
+ spin_lock_irqsave (&dyn_lock, flags);
+ ret = s390_device_register_internal(drinfo);
spin_unlock_irqrestore( &dyn_lock, flags );
- return( ret);
+ return ret;
}
-
-int s390_device_unregister( devreg_t *dreg )
+static inline int s390_device_unregister_internal(devreg_t *dreg)
{
- unsigned long flags;
-
- int ret = -EINVAL;
- devreg_t *pdevreg = devreg_anchor;
+ struct list_head *p;
- if ( dreg == NULL )
- return( -EINVAL );
+ list_for_each(p, &devreg_anchor) {
+ devreg_t *pdevreg = list_entry(p, devreg_t, list);
- spin_lock_irqsave( &dyn_lock, flags );
-
- while ( (pdevreg != NULL )
- && ( ret != 0 ) )
- {
- if ( pdevreg == dreg )
- {
- devreg_t *dprev = pdevreg->prev;
- devreg_t *dnext = pdevreg->next;
-
- if ( (dprev != NULL) && (dnext != NULL) )
- {
- dnext->prev = dprev;
- dprev->next = dnext;
- }
- if ( (dprev != NULL) && (dnext == NULL) )
- {
- dprev->next = NULL;
- }
- if ( (dprev == NULL) && (dnext != NULL) )
- {
- dnext->prev = NULL;
-
- } /* else */
-
- ret = 0;
+ if (pdevreg == dreg) {
+ list_del (&dreg->list);
+ return 0;
}
- else
- {
- pdevreg = pdevreg->next;
+ }
+ return -EINVAL;
+}
- } /* endif */
+int s390_device_unregister(devreg_t *dreg)
+{
+ unsigned long flags;
+ int ret;
- } /* endwhile */
+ if (dreg == NULL)
+ return -EINVAL;
- spin_unlock_irqrestore( &dyn_lock, flags );
+ spin_lock_irqsave(&dyn_lock, flags);
+ ret = s390_device_unregister_internal(dreg);
+ spin_unlock_irqrestore(&dyn_lock, flags);
- return( ret);
+ return ret;
}
+static inline devreg_t *s390_search_devreg_internal(ioinfo_t *ioinfo)
+{
+ struct list_head *p;
+
+ list_for_each(p, &devreg_anchor) {
+ devreg_t *pdevreg = list_entry(p, devreg_t, list);
+ senseid_t *sid;
+ int flag;
+
+ flag = pdevreg->flag;
+ sid = &ioinfo->senseid;
+ if (flag & DEVREG_TYPE_DEVNO) {
+ if (ioinfo->ui.flags.dval != 1 ||
+ ioinfo->devno != pdevreg->ci.devno)
+ continue;
+ } else if ((flag & DEVREG_TYPE_DEVCHARS) &&
+ (flag & DEVREG_EXACT_MATCH)) {
+ if (pdevreg->ci.hc.ctype != sid->cu_type ||
+ pdevreg->ci.hc.cmode != sid->cu_model ||
+ pdevreg->ci.hc.dtype != sid->dev_type ||
+ pdevreg->ci.hc.dmode != sid->dev_model)
+ continue;
+ } else if (flag & DEVREG_TYPE_DEVCHARS) {
+ if (!(flag & DEVREG_NO_CU_INFO) &&
+ pdevreg->ci.hc.ctype != sid->cu_type)
+ continue;
+
+ if (!(flag & DEVREG_NO_CU_INFO) &&
+ !(flag & DEVREG_MATCH_CU_TYPE) &&
+ pdevreg->ci.hc.cmode != sid->cu_model)
+ continue;
+
+ if (!(flag & DEVREG_NO_DEV_INFO) &&
+ pdevreg->ci.hc.dtype != sid->dev_type)
+ continue;
+
+ if (!(flag & DEVREG_NO_DEV_INFO) &&
+ !(flag & DEVREG_MATCH_DEV_TYPE) &&
+ pdevreg->ci.hc.dmode != sid->dev_model)
+ continue;
+ }
+ return pdevreg;
+ }
+ return NULL;
+}
devreg_t * s390_search_devreg( ioinfo_t *ioinfo )
{
unsigned long flags;
- devreg_hc_t match;
- devreg_t *pdevreg = devreg_anchor;
-
- if ( ioinfo == NULL )
- return( NULL );
-
- spin_lock_irqsave( &dyn_lock, flags );
+ devreg_t *pdevreg;
- while ( pdevreg != NULL )
- {
- int flag = pdevreg->flag;
-
- if ( (flag & DEVREG_TYPE_DEVNO )
- && (ioinfo->ui.flags.dval == 1 )
- && (ioinfo->devno == pdevreg->ci.devno) )
- {
- break;
- }
- else if (flag & DEVREG_TYPE_DEVCHARS )
- {
- if ( flag & DEVREG_EXACT_MATCH )
- {
- if ( !memcmp( &pdevreg->ci.hc,
- &ioinfo->senseid.cu_type,
- sizeof(devreg_hc_t)))
- break;
- }
- else
- {
- memcpy( &match, &ioinfo->senseid.cu_type,
- sizeof(match));
-
- if( flag & DEVREG_NO_CU_INFO )
- {
- match.ctype = pdevreg->ci.hc.ctype;
- match.cmode = pdevreg->ci.hc.cmode;
- }
- if( flag & DEVREG_NO_DEV_INFO )
- {
- match.dtype = pdevreg->ci.hc.dtype;
- match.dmode = pdevreg->ci.hc.dmode;
- }
- if ( flag & DEVREG_MATCH_CU_TYPE )
- match.cmode = pdevreg->ci.hc.cmode;
- if( flag & DEVREG_MATCH_DEV_TYPE)
- match.dmode = pdevreg->ci.hc.dmode;
- if ( !memcmp( &pdevreg->ci.hc,
- &match, sizeof(match)))
- break;
- } /* endif */
- } /* endif */
+ if (ioinfo == NULL)
+ return NULL;
- pdevreg = pdevreg->next;
-
- } /* endwhile */
-
- spin_unlock_irqrestore( &dyn_lock, flags );
+ spin_lock_irqsave(&dyn_lock, flags);
+ pdevreg = s390_search_devreg_internal(ioinfo);
+ spin_unlock_irqrestore(&dyn_lock, flags);
- return( pdevreg);
+ return pdevreg;
}
+
+EXPORT_SYMBOL(s390_device_register);
+EXPORT_SYMBOL(s390_device_unregister);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)