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

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)