linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / s390 / net / netiucv.c
index d7d1cc0..71d3853 100644 (file)
@@ -30,7 +30,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
-
+\f
 #undef DEBUG
 
 #include <linux/module.h>
@@ -65,7 +65,7 @@ MODULE_AUTHOR
     ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
 MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
 
-
+\f
 #define PRINTK_HEADER " iucv: "       /* for debugging */
 
 static struct device_driver netiucv_driver = {
@@ -112,12 +112,7 @@ struct iucv_connection {
 /**
  * Linked list of all connection structs.
  */
-struct iucv_connection_struct {
-       struct iucv_connection *iucv_connections;
-       rwlock_t iucv_rwlock;
-};
-
-static struct iucv_connection_struct iucv_conns;
+static struct iucv_connection *iucv_connections;
 
 /**
  * Representation of event-data for the
@@ -207,7 +202,7 @@ netiucv_printname(char *name)
        *p = '\0';
        return tmp;
 }
-
+\f
 /**
  * States of the interface statemachine.
  */
@@ -249,7 +244,7 @@ static const char *dev_event_names[] = {
        "Connection up",
        "Connection down",
 };
-
+\f
 /**
  * Events of the connection statemachine
  */
@@ -369,7 +364,7 @@ static const char *conn_state_names[] = {
        "Connect error",
 };
 
-
+\f
 /**
  * Debug Facility Stuff
  */
@@ -521,7 +516,7 @@ static void
 fsm_action_nop(fsm_instance *fi, int event, void *arg)
 {
 }
-
+\f
 /**
  * Actions of the connection statemachine
  *****************************************************************************/
@@ -998,7 +993,7 @@ static const fsm_node conn_fsm[] = {
 
 static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
 
-
+\f
 /**
  * Actions for interface - statemachine.
  *****************************************************************************/
@@ -1187,7 +1182,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
 
                fsm_newstate(conn->fsm, CONN_STATE_TX);
                conn->prof.send_stamp = xtime;
-
+               
                rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
                        0, nskb->data, nskb->len);
                               /* Shut up, gcc! nskb is always below 2G. */
@@ -1225,7 +1220,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
 
        return rc;
 }
-
+\f
 /**
  * Interface API for upper network layers
  *****************************************************************************/
@@ -1296,7 +1291,7 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
 
        /**
         * If connection is not running, try to restart it
-        * and throw away packet.
+        * and throw away packet. 
         */
        if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
                fsm_event(privptr->fsm, DEV_EVENT_START, dev);
@@ -1373,10 +1368,8 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf,
        struct net_device *ndev = priv->conn->netdev;
        char    *p;
        char    *tmp;
-       char    username[9];
+       char    username[10];
        int     i;
-       struct iucv_connection **clist = &iucv_conns.iucv_connections;
-       unsigned long flags;
 
        IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
        if (count>9) {
@@ -1389,7 +1382,7 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf,
        tmp = strsep((char **) &buf, "\n");
        for (i=0, p=tmp; i<8 && *p; i++, p++) {
                if (isalnum(*p) || (*p == '$'))
-                       username[i]= toupper(*p);
+                       username[i]= *p;
                else if (*p == '\n') {
                        /* trailing lf, grr */
                        break;
@@ -1402,11 +1395,11 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf,
                        return -EINVAL;
                }
        }
-       while (i<8)
+       while (i<9)
                username[i++] = ' ';
-       username[8] = '\0';
+       username[9] = '\0';
 
-       if (memcmp(username, priv->conn->userid, 9)) {
+       if (memcmp(username, priv->conn->userid, 8)) {
                /* username changed */
                if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
                        PRINT_WARN(
@@ -1417,19 +1410,6 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf,
                        return -EBUSY;
                }
        }
-       read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
-       while (*clist) {
-                if (!strncmp(username, (*clist)->userid, 9) ||
-                   ((*clist)->netdev != ndev))
-                        break;
-                clist = &((*clist)->next);
-        }
-       read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
-        if (*clist) {
-                PRINT_WARN("netiucv: Connection to %s already exists\n",
-                        username);
-                return -EEXIST;
-        }
        memcpy(priv->conn->userid, username, 9);
 
        return count;
@@ -1558,7 +1538,7 @@ static ssize_t
 maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-
+       
        IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
        priv->conn->prof.maxcqueue = 0;
        return count;
@@ -1579,7 +1559,7 @@ static ssize_t
 sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-
+       
        IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
        priv->conn->prof.doios_single = 0;
        return count;
@@ -1600,7 +1580,7 @@ static ssize_t
 mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-
+       
        IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
        priv->conn->prof.doios_multi = 0;
        return count;
@@ -1621,7 +1601,7 @@ static ssize_t
 txlen_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-
+       
        IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
        priv->conn->prof.txlen = 0;
        return count;
@@ -1642,7 +1622,7 @@ static ssize_t
 txtime_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-
+       
        IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
        priv->conn->prof.tx_time = 0;
        return count;
@@ -1748,13 +1728,14 @@ static int
 netiucv_register_device(struct net_device *ndev)
 {
        struct netiucv_priv *priv = ndev->priv;
-       struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+       struct device *dev = kmalloc(sizeof(struct device), GFP_KERNEL);
        int ret;
 
 
        IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 
        if (dev) {
+               memset(dev, 0, sizeof(struct device));
                snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name);
                dev->bus = &iucv_bus;
                dev->parent = iucv_root;
@@ -1801,15 +1782,15 @@ netiucv_unregister_device(struct device *dev)
 static struct iucv_connection *
 netiucv_new_connection(struct net_device *dev, char *username)
 {
-       unsigned long flags;
-       struct iucv_connection **clist = &iucv_conns.iucv_connections;
+       struct iucv_connection **clist = &iucv_connections;
        struct iucv_connection *conn =
-               kzalloc(sizeof(struct iucv_connection), GFP_KERNEL);
+               (struct iucv_connection *)
+               kmalloc(sizeof(struct iucv_connection), GFP_KERNEL);
 
        if (conn) {
+               memset(conn, 0, sizeof(struct iucv_connection));
                skb_queue_head_init(&conn->collect_queue);
                skb_queue_head_init(&conn->commit_queue);
-               spin_lock_init(&conn->collect_lock);
                conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
                conn->netdev = dev;
 
@@ -1844,10 +1825,8 @@ netiucv_new_connection(struct net_device *dev, char *username)
                        fsm_newstate(conn->fsm, CONN_STATE_STOPPED);
                }
 
-               write_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
                conn->next = *clist;
                *clist = conn;
-               write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
        }
        return conn;
 }
@@ -1859,17 +1838,14 @@ netiucv_new_connection(struct net_device *dev, char *username)
 static void
 netiucv_remove_connection(struct iucv_connection *conn)
 {
-       struct iucv_connection **clist = &iucv_conns.iucv_connections;
-       unsigned long flags;
+       struct iucv_connection **clist = &iucv_connections;
 
        IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
        if (conn == NULL)
                return;
-       write_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
        while (*clist) {
                if (*clist == conn) {
                        *clist = conn->next;
-                       write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
                        if (conn->handle) {
                                iucv_unregister_program(conn->handle);
                                conn->handle = NULL;
@@ -1882,7 +1858,6 @@ netiucv_remove_connection(struct iucv_connection *conn)
                }
                clist = &((*clist)->next);
        }
-       write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
 }
 
 /**
@@ -1975,11 +1950,9 @@ static ssize_t
 conn_write(struct device_driver *drv, const char *buf, size_t count)
 {
        char *p;
-       char username[9];
+       char username[10];
        int i, ret;
        struct net_device *dev;
-       struct iucv_connection **clist = &iucv_conns.iucv_connections;
-       unsigned long flags;
 
        IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
        if (count>9) {
@@ -1990,7 +1963,7 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
 
        for (i=0, p=(char *)buf; i<8 && *p; i++, p++) {
                if (isalnum(*p) || (*p == '$'))
-                       username[i]= toupper(*p);
+                       username[i]= *p;
                else if (*p == '\n') {
                        /* trailing lf, grr */
                        break;
@@ -2001,22 +1974,9 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
                        return -EINVAL;
                }
        }
-       while (i<8)
+       while (i<9)
                username[i++] = ' ';
-       username[8] = '\0';
-
-       read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
-       while (*clist) {
-               if (!strncmp(username, (*clist)->userid, 9))
-                       break;
-               clist = &((*clist)->next);
-       }
-       read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
-       if (*clist) {
-               PRINT_WARN("netiucv: Connection to %s already exists\n",
-                       username);
-               return -EEXIST;
-       }
+       username[9] = '\0';
        dev = netiucv_init_netdevice(username);
        if (!dev) {
                PRINT_WARN(
@@ -2043,7 +2003,7 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
        }
 
        PRINT_INFO("%s: '%s'\n", dev->name, netiucv_printname(username));
-
+       
        return count;
 
 out_free_ndev:
@@ -2058,8 +2018,7 @@ DRIVER_ATTR(connection, 0200, NULL, conn_write);
 static ssize_t
 remove_write (struct device_driver *drv, const char *buf, size_t count)
 {
-       struct iucv_connection **clist = &iucv_conns.iucv_connections;
-       unsigned long flags;
+       struct iucv_connection **clist = &iucv_connections;
         struct net_device *ndev;
         struct netiucv_priv *priv;
         struct device *dev;
@@ -2070,10 +2029,10 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
         IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 
         if (count >= IFNAMSIZ)
-                count = IFNAMSIZ - 1;;
+                count = IFNAMSIZ-1;
 
         for (i=0, p=(char *)buf; i<count && *p; i++, p++) {
-                if ((*p == '\n') || (*p == ' ')) {
+                if ((*p == '\n') | (*p == ' ')) {
                         /* trailing lf, grr */
                         break;
                 } else {
@@ -2082,7 +2041,6 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
         }
         name[i] = '\0';
 
-       read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
         while (*clist) {
                 ndev = (*clist)->netdev;
                 priv = (struct netiucv_priv*)ndev->priv;
@@ -2092,7 +2050,6 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
                         clist = &((*clist)->next);
                         continue;
                 }
-               read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
                 if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
                         PRINT_WARN(
                                 "netiucv: net device %s active with peer %s\n",
@@ -2106,7 +2063,6 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
                 netiucv_unregister_device(dev);
                 return count;
         }
-       read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
         PRINT_WARN("netiucv: net device %s unknown\n", name);
        IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n");
         return -EINVAL;
@@ -2124,8 +2080,8 @@ static void __exit
 netiucv_exit(void)
 {
        IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-       while (iucv_conns.iucv_connections) {
-               struct net_device *ndev = iucv_conns.iucv_connections->netdev;
+       while (iucv_connections) {
+               struct net_device *ndev = iucv_connections->netdev;
                struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv;
                struct device *dev = priv->dev;
 
@@ -2146,7 +2102,7 @@ static int __init
 netiucv_init(void)
 {
        int ret;
-
+       
        ret = iucv_register_dbf_views();
        if (ret) {
                PRINT_WARN("netiucv_init failed, "
@@ -2167,7 +2123,6 @@ netiucv_init(void)
        if (!ret) {
                ret = driver_create_file(&netiucv_driver, &driver_attr_remove);
                netiucv_banner();
-               rwlock_init(&iucv_conns.iucv_rwlock);
        } else {
                PRINT_ERR("NETIUCV: failed to add driver attribute.\n");
                IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_create_file\n", ret);
@@ -2176,7 +2131,7 @@ netiucv_init(void)
        }
        return ret;
 }
-
+       
 module_init(netiucv_init);
 module_exit(netiucv_exit);
 MODULE_LICENSE("GPL");