fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / s390 / net / ctcmain.c
index af9f212..03cc263 100644 (file)
@@ -6,7 +6,7 @@
  * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
  *            Arnaldo Carvalho de Melo <acme@conectiva.com.br>
              Peter Tiedemann (ptiedem@de.ibm.com)
- * Driver Model stuff by : Cornelia Huck <huckc@de.ibm.com>
+ * Driver Model stuff by : Cornelia Huck <cornelia.huck@de.ibm.com>
  *
  * Documentation used:
  *  - Principles of Operation (IBM doc#: SA22-7201-06)
@@ -65,7 +65,6 @@
 
 #include <asm/idals.h>
 
-#include "ctctty.h"
 #include "fsm.h"
 #include "cu3088.h"
 
@@ -479,10 +478,7 @@ ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
                skb->dev = pskb->dev;
                skb->protocol = pskb->protocol;
                pskb->ip_summed = CHECKSUM_UNNECESSARY;
-               if (ch->protocol == CTC_PROTO_LINUX_TTY)
-                       ctc_tty_netif_rx(skb);
-               else
-                       netif_rx_ni(skb);
+               netif_rx_ni(skb);
                /**
                 * Successful rx; reset logflags
                 */
@@ -557,8 +553,7 @@ ccw_unit_check(struct channel *ch, unsigned char sense)
        DBF_TEXT(trace, 5, __FUNCTION__);
        if (sense & SNS0_INTERVENTION_REQ) {
                if (sense & 0x01) {
-                       if (ch->protocol != CTC_PROTO_LINUX_TTY)
-                               ctc_pr_debug("%s: Interface disc. or Sel. reset "
+                       ctc_pr_debug("%s: Interface disc. or Sel. reset "
                                        "(remote)\n", ch->id);
                        fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch);
                } else {
@@ -1486,13 +1481,13 @@ ch_action_iofatal(fsm_instance * fi, int event, void *arg)
        }
 }
 
-static void 
+static void
 ch_action_reinit(fsm_instance *fi, int event, void *arg)
 {
        struct channel *ch = (struct channel *)arg;
        struct net_device *dev = ch->netdev;
        struct ctc_priv *privptr = dev->priv;
+
        DBF_TEXT(trace, 4, __FUNCTION__);
        ch_action_iofatal(fi, event, arg);
        fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
@@ -1624,7 +1619,7 @@ less_than(char *id1, char *id2)
        }
        dev1 = simple_strtoul(id1, &id1, 16);
        dev2 = simple_strtoul(id2, &id2, 16);
-       
+
        return (dev1 < dev2);
 }
 
@@ -1651,7 +1646,7 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
                return -1;
        }
        memset(ch, 0, sizeof (struct channel));
-       if ((ch->ccw = (struct ccw1 *) kmalloc(8*sizeof(struct ccw1),
+       if ((ch->ccw = kmalloc(8*sizeof(struct ccw1),
                                               GFP_KERNEL | GFP_DMA)) == NULL) {
                kfree(ch);
                ctc_pr_warn("ctc: Out of memory in add_channel\n");
@@ -1698,7 +1693,7 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
                return -1;
        }
        fsm_newstate(ch->fsm, CH_STATE_IDLE);
-       if ((ch->irb = (struct irb *) kmalloc(sizeof (struct irb),
+       if ((ch->irb = kmalloc(sizeof (struct irb),
                                              GFP_KERNEL)) == NULL) {
                ctc_pr_warn("ctc: Out of memory in add_channel\n");
                kfree_fsm(ch->fsm);
@@ -1719,6 +1714,9 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
                kfree(ch);
                return 0;
        }
+
+       spin_lock_init(&ch->collect_lock);
+
        fsm_settimer(ch->fsm, &ch->timer);
        skb_queue_head_init(&ch->io_queue);
        skb_queue_head_init(&ch->collect_queue);
@@ -1895,7 +1893,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                            irb->scsw.dstat);
                return;
        }
-       
+
        priv = ((struct ccwgroup_device *)cdev->dev.driver_data)
                ->dev.driver_data;
 
@@ -1909,7 +1907,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                           "device %s\n", cdev->dev.bus_id);
                return;
        }
-       
+
        dev = (struct net_device *) (ch->netdev);
        if (dev == NULL) {
                ctc_pr_crit("ctc: ctc_irq_handler dev=NULL bus_id=%s, ch=0x%p\n",
@@ -2008,12 +2006,12 @@ dev_action_stop(fsm_instance * fi, int event, void *arg)
                fsm_event(ch->fsm, CH_EVENT_STOP, ch);
        }
 }
-static void 
+static void
 dev_action_restart(fsm_instance *fi, int event, void *arg)
 {
        struct net_device *dev = (struct net_device *)arg;
        struct ctc_priv *privptr = dev->priv;
-       
+
        DBF_TEXT(trace, 3, __FUNCTION__);
        ctc_pr_debug("%s: Restarting\n", dev->name);
        dev_action_stop(fi, event, arg);
@@ -2034,7 +2032,6 @@ static void
 dev_action_chup(fsm_instance * fi, int event, void *arg)
 {
        struct net_device *dev = (struct net_device *) arg;
-       struct ctc_priv *privptr = dev->priv;
 
        DBF_TEXT(trace, 3, __FUNCTION__);
        switch (fsm_getstate(fi)) {
@@ -2049,8 +2046,6 @@ dev_action_chup(fsm_instance * fi, int event, void *arg)
                                fsm_newstate(fi, DEV_STATE_RUNNING);
                                ctc_pr_info("%s: connected with remote side\n",
                                            dev->name);
-                               if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                                       ctc_tty_setcarrier(dev, 1);
                                ctc_clear_busy(dev);
                        }
                        break;
@@ -2059,8 +2054,6 @@ dev_action_chup(fsm_instance * fi, int event, void *arg)
                                fsm_newstate(fi, DEV_STATE_RUNNING);
                                ctc_pr_info("%s: connected with remote side\n",
                                            dev->name);
-                               if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                                       ctc_tty_setcarrier(dev, 1);
                                ctc_clear_busy(dev);
                        }
                        break;
@@ -2086,14 +2079,10 @@ dev_action_chup(fsm_instance * fi, int event, void *arg)
 static void
 dev_action_chdown(fsm_instance * fi, int event, void *arg)
 {
-       struct net_device *dev = (struct net_device *) arg;
-       struct ctc_priv *privptr = dev->priv;
 
        DBF_TEXT(trace, 3, __FUNCTION__);
        switch (fsm_getstate(fi)) {
                case DEV_STATE_RUNNING:
-                       if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                               ctc_tty_setcarrier(dev, 0);
                        if (event == DEV_EVENT_TXDOWN)
                                fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
                        else
@@ -2193,7 +2182,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
 
        DBF_TEXT(trace, 5, __FUNCTION__);
        /* we need to acquire the lock for testing the state
-        * otherwise we can have an IRQ changing the state to 
+        * otherwise we can have an IRQ changing the state to
         * TXIDLE after the test but before acquiring the lock.
         */
        spin_lock_irqsave(&ch->collect_lock, saveflags);
@@ -2393,12 +2382,10 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev)
 
        /**
         * If channels are not running, try to restart them
-        * and throw away packet. 
+        * and throw away packet.
         */
        if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
                fsm_event(privptr->fsm, DEV_EVENT_START, dev);
-               if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                       return -EBUSY;
                dev_kfree_skb(skb);
                privptr->stats.tx_dropped++;
                privptr->stats.tx_errors++;
@@ -2548,7 +2535,7 @@ ctc_print_statistics(struct ctc_priv *priv)
        DBF_TEXT(trace, 4, __FUNCTION__);
        if (!priv)
                return;
-       sbuf = (char *)kmalloc(2048, GFP_KERNEL);
+       sbuf = kmalloc(2048, GFP_KERNEL);
        if (sbuf == NULL)
                return;
        p = sbuf;
@@ -2608,20 +2595,13 @@ ctc_netdev_unregister(struct net_device * dev)
        if (!dev)
                return;
        privptr = (struct ctc_priv *) dev->priv;
-       if (privptr->protocol != CTC_PROTO_LINUX_TTY)
-               unregister_netdev(dev);
-       else
-               ctc_tty_unregister_netdev(dev);
+       unregister_netdev(dev);
 }
 
 static int
 ctc_netdev_register(struct net_device * dev)
 {
-       struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
-       if (privptr->protocol != CTC_PROTO_LINUX_TTY)
-               return register_netdev(dev);
-       else
-               return ctc_tty_register_netdev(dev);
+       return register_netdev(dev);
 }
 
 static void
@@ -2667,7 +2647,9 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b
        if (!priv)
                return -ENODEV;
        sscanf(buf, "%u", &value);
-       if ((value < 0) || (value > CTC_PROTO_MAX))
+       if (!((value == CTC_PROTO_S390)  ||
+             (value == CTC_PROTO_LINUX) ||
+             (value == CTC_PROTO_OS390)))
                return -EINVAL;
        priv->protocol = value;
 
@@ -2707,9 +2689,17 @@ static struct attribute_group ctc_attr_group = {
 static int
 ctc_add_attributes(struct device *dev)
 {
-       device_create_file(dev, &dev_attr_loglevel);
-       device_create_file(dev, &dev_attr_stats);
-       return 0;
+       int rc;
+
+       rc = device_create_file(dev, &dev_attr_loglevel);
+       if (rc)
+               goto out;
+       rc = device_create_file(dev, &dev_attr_stats);
+       if (!rc)
+               goto out;
+       device_remove_file(dev, &dev_attr_loglevel);
+out:
+       return rc;
 }
 
 static void
@@ -2738,7 +2728,7 @@ ctc_remove_files(struct device *dev)
 /**
  * Add ctc specific attributes.
  * Add ctc private data.
- * 
+ *
  * @param cgdev pointer to ccwgroup_device just added
  *
  * @returns 0 on success, !0 on failure.
@@ -2869,7 +2859,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
        DBF_TEXT(setup, 3, buffer);
 
        type = get_channel_type(&cgdev->cdev[0]->id);
-       
+
        snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
        snprintf(write_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
 
@@ -2897,17 +2887,14 @@ ctc_new_device(struct ccwgroup_device *cgdev)
                goto out;
        }
 
-       if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-               strlcpy(dev->name, "ctctty%d", IFNAMSIZ);
-       else
-               strlcpy(dev->name, "ctc%d", IFNAMSIZ);
+       strlcpy(dev->name, "ctc%d", IFNAMSIZ);
 
        for (direction = READ; direction <= WRITE; direction++) {
                privptr->channel[direction] =
                    channel_get(type, direction == READ ? read_id : write_id,
                                direction);
                if (privptr->channel[direction] == NULL) {
-                       if (direction == WRITE) 
+                       if (direction == WRITE)
                                channel_free(privptr->channel[READ]);
 
                        ctc_free_netdevice(dev, 1);
@@ -2925,7 +2912,12 @@ ctc_new_device(struct ccwgroup_device *cgdev)
                goto out;
        }
 
-       ctc_add_attributes(&cgdev->dev);
+       if (ctc_add_attributes(&cgdev->dev)) {
+               ctc_netdev_unregister(dev);
+               dev->priv = NULL;
+               ctc_free_netdevice(dev, 1);
+               goto out;
+       }
 
        strlcpy(privptr->fsm->name, dev->name, sizeof (privptr->fsm->name));
 
@@ -2955,7 +2947,7 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
 {
        struct ctc_priv *priv;
        struct net_device *ndev;
-               
+
        DBF_TEXT(setup, 3, __FUNCTION__);
        pr_debug("%s() called\n", __FUNCTION__);
 
@@ -3046,7 +3038,6 @@ ctc_exit(void)
 {
        DBF_TEXT(setup, 3, __FUNCTION__);
        unregister_cu3088_discipline(&ctc_group_driver);
-       ctc_tty_cleanup();
        ctc_unregister_dbf_views();
        ctc_pr_info("CTC driver unloaded\n");
 }
@@ -3073,10 +3064,8 @@ ctc_init(void)
                ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret);
                return ret;
        }
-       ctc_tty_init();
        ret = register_cu3088_discipline(&ctc_group_driver);
        if (ret) {
-               ctc_tty_cleanup();
                ctc_unregister_dbf_views();
        }
        return ret;