X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fs390%2Fnet%2Fnetiucv.c;h=2b3753d554413fc58d5fc486062d371109ef457f;hb=333b49614bac1801f614128fdcdb6346b383a0df;hp=13354dfee73c49c6d3889a8b59699a2d0bb07a9b;hpb=86090fcac5e27b630656fe3d963a6b80e26dac44;p=linux-2.6.git diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 13354dfee..2b3753d55 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1,5 +1,5 @@ /* - * $Id: netiucv.c,v 1.51 2004/04/23 08:11:21 mschwide Exp $ + * $Id: netiucv.c,v 1.53 2004/05/07 14:29:37 mschwide Exp $ * * IUCV network driver * @@ -30,7 +30,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV network driver $Revision: 1.51 $ + * RELEASE-TAG: IUCV network driver $Revision: 1.53 $ * */ @@ -60,6 +60,7 @@ #include #include #include +#include #include "iucv.h" #include "fsm.h" @@ -113,9 +114,6 @@ struct iucv_connection { */ static struct iucv_connection *connections; -/* Keep track of interfaces. */ -static int ifno; - /** * Representation of event-data for the * connection state machine. @@ -549,7 +547,7 @@ conn_action_rx(fsm_instance *fi, int event, void *arg) iucv_MessagePending *eib = (iucv_MessagePending *)ev->data; struct netiucv_priv *privptr = (struct netiucv_priv *)conn->netdev->priv; - __u16 msglen = eib->ln1msg2.ipbfln1f; + __u32 msglen = eib->ln1msg2.ipbfln1f; int rc; pr_debug("%s() called\n", __FUNCTION__); @@ -571,6 +569,7 @@ conn_action_rx(fsm_instance *fi, int event, void *arg) conn->rx_buff->data, msglen, NULL, NULL, NULL); if (rc != 0 || msglen < 5) { privptr->stats.rx_errors++; + printk(KERN_INFO "iucv_receive returned %08x\n", rc); return; } netiucv_unpack_skb(conn, conn->rx_buff); @@ -647,7 +646,7 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg) fsm_newstate(fi, CONN_STATE_IDLE); if (privptr) privptr->stats.tx_errors += txpackets; - printk(KERN_DEBUG "iucv_send returned %08x\n", + printk(KERN_INFO "iucv_send returned %08x\n", rc); } else { if (privptr) { @@ -770,7 +769,7 @@ conn_action_start(fsm_instance *fi, int event, void *arg) struct iucv_event *ev = (struct iucv_event *)arg; struct iucv_connection *conn = ev->conn; __u16 msglimit; - int rc; + int rc, len; __u8 iucvMagic[16] = { 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 @@ -778,7 +777,10 @@ conn_action_start(fsm_instance *fi, int event, void *arg) pr_debug("%s() called\n", __FUNCTION__); - memcpy(iucvMagic, conn->netdev->name, IFNAMSIZ); + len = (IFNAMSIZ < sizeof(conn->netdev->name)) ? + IFNAMSIZ : sizeof(conn->netdev->name); + memcpy(iucvMagic, conn->netdev->name, len); + ASCEBC (iucvMagic, len); if (conn->handle == 0) { conn->handle = iucv_register_program(iucvMagic, conn->userid, mask, @@ -992,6 +994,7 @@ static void dev_action_connup(fsm_instance *fi, int event, void *arg) { struct net_device *dev = (struct net_device *)arg; + struct netiucv_priv *privptr = dev->priv; pr_debug("%s() called\n", __FUNCTION__); @@ -999,8 +1002,8 @@ dev_action_connup(fsm_instance *fi, int event, void *arg) case DEV_STATE_STARTWAIT: fsm_newstate(fi, DEV_STATE_RUNNING); printk(KERN_INFO - "%s: connected with remote side\n", - dev->name); + "%s: connected with remote side %s\n", + dev->name, privptr->conn->userid); break; case DEV_STATE_STOPWAIT: printk(KERN_INFO @@ -1140,7 +1143,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) { skb_pull(skb, NETIUCV_HDRLEN); skb_trim(skb, skb->len - NETIUCV_HDRLEN); } - printk(KERN_DEBUG "iucv_send returned %08x\n", + printk(KERN_INFO "iucv_send returned %08x\n", rc); } else { if (copied) @@ -1612,7 +1615,7 @@ netiucv_remove_files(struct device *dev) } static int -netiucv_register_device(struct net_device *ndev, int ifno) +netiucv_register_device(struct net_device *ndev) { struct netiucv_priv *priv = ndev->priv; struct device *dev = kmalloc(sizeof(struct device), GFP_KERNEL); @@ -1623,7 +1626,7 @@ netiucv_register_device(struct net_device *ndev, int ifno) if (dev) { memset(dev, 0, sizeof(struct device)); - snprintf(dev->bus_id, BUS_ID_SIZE, "netiucv%x", ifno); + snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name); dev->bus = &iucv_bus; dev->parent = iucv_root; /* @@ -1801,16 +1804,15 @@ netiucv_setup_netdevice(struct net_device *dev) * Allocate and initialize everything of a net device. */ static struct net_device * -netiucv_init_netdevice(int ifno, char *username) +netiucv_init_netdevice(char *username) { struct netiucv_priv *privptr; struct net_device *dev; - dev = alloc_netdev(sizeof(struct netiucv_priv), "", + dev = alloc_netdev(sizeof(struct netiucv_priv), "iucv%d", netiucv_setup_netdevice); if (!dev) return NULL; - sprintf(dev->name, "iucv%d", ifno); privptr = (struct netiucv_priv *)dev->priv; privptr->fsm = init_fsm("netiucvdev", dev_state_names, @@ -1861,7 +1863,7 @@ conn_write(struct device_driver *drv, const char *buf, size_t count) while (i<9) username[i++] = ' '; username[9] = '\0'; - dev = netiucv_init_netdevice(ifno, username); + dev = netiucv_init_netdevice(username); if (!dev) { printk(KERN_WARNING "netiucv: Could not allocate network device structure " @@ -1869,16 +1871,18 @@ conn_write(struct device_driver *drv, const char *buf, size_t count) return -ENODEV; } - if ((ret = netiucv_register_device(dev, ifno))) - goto out_free_ndev; - /* sysfs magic */ - SET_NETDEV_DEV(dev, (struct device*)((struct netiucv_priv*)dev->priv)->dev); if ((ret = register_netdev(dev))) { - netiucv_unregister_device((struct device*)((struct netiucv_priv*)dev->priv)->dev); goto out_free_ndev; } + + if ((ret = netiucv_register_device(dev))) { + unregister_netdev(dev); + goto out_free_ndev; + } + + /* sysfs magic */ + SET_NETDEV_DEV(dev, (struct device*)((struct netiucv_priv*)dev->priv)->dev); printk(KERN_INFO "%s: '%s'\n", dev->name, netiucv_printname(username)); - ifno++; return count; @@ -1891,6 +1895,61 @@ out_free_ndev: 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 = &connections; + struct net_device *ndev; + struct netiucv_priv *priv; + struct device *dev; + char name[IFNAMSIZ]; + char *p; + int i; + + pr_debug("%s() called\n", __FUNCTION__); + + if (count >= IFNAMSIZ) + count = IFNAMSIZ-1; + + for (i=0, p=(char *)buf; inetdev; + priv = (struct netiucv_priv*)ndev->priv; + dev = priv->dev; + + if (strncmp(name, ndev->name, count)) { + clist = &((*clist)->next); + continue; + } + if (ndev->flags & (IFF_UP | IFF_RUNNING)) { + printk(KERN_WARNING + "netiucv: net device %s active with peer %s\n", + ndev->name, priv->conn->userid); + printk(KERN_WARNING + "netiucv: %s cannot be removed\n", + ndev->name); + return -EBUSY; + } + unregister_netdev(ndev); + netiucv_unregister_device(dev); + return count; + } + printk(KERN_WARNING + "netiucv: net device %s unknown\n", name); + return -EINVAL; +} + +DRIVER_ATTR(remove, 0200, NULL, remove_write); + static struct device_driver netiucv_driver = { .name = "netiucv", .bus = &iucv_bus, @@ -1899,7 +1958,7 @@ static struct device_driver netiucv_driver = { static void netiucv_banner(void) { - char vbuf[] = "$Revision: 1.51 $"; + char vbuf[] = "$Revision: 1.53 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { @@ -1924,6 +1983,7 @@ netiucv_exit(void) } driver_remove_file(&netiucv_driver, &driver_attr_connection); + driver_remove_file(&netiucv_driver, &driver_attr_remove); driver_unregister(&netiucv_driver); printk(KERN_INFO "NETIUCV driver unloaded\n"); @@ -1943,10 +2003,10 @@ netiucv_init(void) /* Add entry for specifying connections. */ ret = driver_create_file(&netiucv_driver, &driver_attr_connection); - - if (ret == 0) + if (ret == 0) { + ret = driver_create_file(&netiucv_driver, &driver_attr_remove); netiucv_banner(); - else { + } else { printk(KERN_ERR "NETIUCV: failed to add driver attribute.\n"); driver_unregister(&netiucv_driver); }