Commit f86f3b68 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: network driver fixes

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

Network driver changes:
 - ctc: move kfree of driver structure after the last use of it.
 - netiucv: stay in state startwait if peer is down.
 - lcs: initialize ipm_list and unregister netdev only if it is present.
parent 482ac593
/* /*
* $Id: ctctty.c,v 1.16 2004/02/05 12:39:55 felfert Exp $ * $Id: ctctty.c,v 1.17 2004/03/31 17:06:34 ptiedem Exp $
* *
* CTC / ESCON network driver, tty interface. * CTC / ESCON network driver, tty interface.
* *
...@@ -1232,7 +1232,7 @@ ctc_tty_cleanup(void) { ...@@ -1232,7 +1232,7 @@ ctc_tty_cleanup(void) {
ctc_tty_shuttingdown = 1; ctc_tty_shuttingdown = 1;
spin_unlock_irqrestore(&ctc_tty_lock, saveflags); spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
tty_unregister_driver(driver->ctc_tty_device); tty_unregister_driver(driver->ctc_tty_device);
kfree(driver);
put_tty_driver(driver->ctc_tty_device); put_tty_driver(driver->ctc_tty_device);
kfree(driver);
driver = NULL; driver = NULL;
} }
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and * Frank Pavlic (pavlic@de.ibm.com) and
* Martin Schwidefsky <schwidefsky@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com>
* *
* $Revision: 1.72 $ $Date: 2004/03/22 09:34:27 $ * $Revision: 1.74 $ $Date: 2004/04/05 00:01:04 $
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
/** /**
* initialization string for output * initialization string for output
*/ */
#define VERSION_LCS_C "$Revision: 1.72 $" #define VERSION_LCS_C "$Revision: 1.74 $"
static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
static char debug_buffer[255]; static char debug_buffer[255];
...@@ -206,6 +206,9 @@ lcs_alloc_card(void) ...@@ -206,6 +206,9 @@ lcs_alloc_card(void)
return NULL; return NULL;
} }
#ifdef CONFIG_IP_MULTICAST
INIT_LIST_HEAD(&card->ipm_list);
#endif
LCS_DBF_HEX(2, setup, &card, sizeof(void*)); LCS_DBF_HEX(2, setup, &card, sizeof(void*));
return card; return card;
} }
...@@ -1967,7 +1970,8 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev) ...@@ -1967,7 +1970,8 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev)
if (ccwgdev->state == CCWGROUP_ONLINE) { if (ccwgdev->state == CCWGROUP_ONLINE) {
lcs_shutdown_device(ccwgdev); lcs_shutdown_device(ccwgdev);
} }
unregister_netdev(card->dev); if (card->dev)
unregister_netdev(card->dev);
sysfs_remove_group(&ccwgdev->dev.kobj, &lcs_attr_group); sysfs_remove_group(&ccwgdev->dev.kobj, &lcs_attr_group);
lcs_cleanup_card(card); lcs_cleanup_card(card);
lcs_free_card(card); lcs_free_card(card);
......
/* /*
* $Id: netiucv.c,v 1.47 2004/03/22 07:41:42 braunu Exp $ * $Id: netiucv.c,v 1.48 2004/04/01 13:42:09 braunu Exp $
* *
* IUCV network driver * IUCV network driver
* *
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* RELEASE-TAG: IUCV network driver $Revision: 1.47 $ * RELEASE-TAG: IUCV network driver $Revision: 1.48 $
* *
*/ */
...@@ -100,7 +100,6 @@ struct iucv_connection { ...@@ -100,7 +100,6 @@ struct iucv_connection {
int max_buffsize; int max_buffsize;
int flags; int flags;
fsm_timer timer; fsm_timer timer;
int retry;
fsm_instance *fsm; fsm_instance *fsm;
struct net_device *netdev; struct net_device *netdev;
struct connection_profile prof; struct connection_profile prof;
...@@ -169,8 +168,6 @@ static __inline__ int netiucv_test_and_set_busy(struct net_device *dev) ...@@ -169,8 +168,6 @@ static __inline__ int netiucv_test_and_set_busy(struct net_device *dev)
return test_and_set_bit(0, &((struct netiucv_priv *)dev->priv)->tbusy); return test_and_set_bit(0, &((struct netiucv_priv *)dev->priv)->tbusy);
} }
#define SET_DEVICE_START(device, value)
static __u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static __u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static __u8 iucvMagic[16] = { static __u8 iucvMagic[16] = {
0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
...@@ -217,7 +214,6 @@ enum dev_states { ...@@ -217,7 +214,6 @@ enum dev_states {
DEV_STATE_STARTWAIT, DEV_STATE_STARTWAIT,
DEV_STATE_STOPWAIT, DEV_STATE_STOPWAIT,
DEV_STATE_RUNNING, DEV_STATE_RUNNING,
DEV_STATE_STARTRETRY,
/** /**
* MUST be always the last element!! * MUST be always the last element!!
*/ */
...@@ -229,7 +225,6 @@ static const char *dev_state_names[] = { ...@@ -229,7 +225,6 @@ static const char *dev_state_names[] = {
"StartWait", "StartWait",
"StopWait", "StopWait",
"Running", "Running",
"StartRetry",
}; };
/** /**
...@@ -599,7 +594,6 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg) ...@@ -599,7 +594,6 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
pr_debug("%s() called\n", __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__);
fsm_deltimer(&conn->timer);
if (conn && conn->netdev && conn->netdev->priv) if (conn && conn->netdev && conn->netdev->priv)
privptr = (struct netiucv_priv *)conn->netdev->priv; privptr = (struct netiucv_priv *)conn->netdev->priv;
conn->prof.tx_pending--; conn->prof.tx_pending--;
...@@ -639,8 +633,6 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg) ...@@ -639,8 +633,6 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header, memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,
NETIUCV_HDRLEN); NETIUCV_HDRLEN);
fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
CONN_EVENT_TIMER, conn);
conn->prof.send_stamp = xtime; conn->prof.send_stamp = xtime;
rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0, rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0,
conn->tx_buff->data, conn->tx_buff->len); conn->tx_buff->data, conn->tx_buff->len);
...@@ -650,7 +642,6 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg) ...@@ -650,7 +642,6 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
if (conn->prof.tx_pending > conn->prof.tx_max_pending) if (conn->prof.tx_pending > conn->prof.tx_max_pending)
conn->prof.tx_max_pending = conn->prof.tx_pending; conn->prof.tx_max_pending = conn->prof.tx_pending;
if (rc != 0) { if (rc != 0) {
fsm_deltimer(&conn->timer);
conn->prof.tx_pending--; conn->prof.tx_pending--;
fsm_newstate(fi, CONN_STATE_IDLE); fsm_newstate(fi, CONN_STATE_IDLE);
if (privptr) if (privptr)
...@@ -721,42 +712,43 @@ conn_action_connack(fsm_instance *fi, int event, void *arg) ...@@ -721,42 +712,43 @@ conn_action_connack(fsm_instance *fi, int event, void *arg)
pr_debug("%s() called\n", __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__);
fsm_deltimer(&conn->timer);
fsm_newstate(fi, CONN_STATE_IDLE); fsm_newstate(fi, CONN_STATE_IDLE);
conn->pathid = eib->ippathid; conn->pathid = eib->ippathid;
netdev->tx_queue_len = eib->ipmsglim; netdev->tx_queue_len = eib->ipmsglim;
fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev); fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
} }
static void
conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
{
struct iucv_connection *conn = (struct iucv_connection *)arg;
__u8 udata[16];
pr_debug("%s() called\n", __FUNCTION__);
fsm_deltimer(&conn->timer);
iucv_sever(conn->pathid, udata);
fsm_newstate(fi, CONN_STATE_STARTWAIT);
}
static void static void
conn_action_connsever(fsm_instance *fi, int event, void *arg) conn_action_connsever(fsm_instance *fi, int event, void *arg)
{ {
struct iucv_event *ev = (struct iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
// iucv_ConnectionSevered *eib = (iucv_ConnectionSevered *)ev->data;
struct net_device *netdev = conn->netdev; struct net_device *netdev = conn->netdev;
struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv; struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
int state = fsm_getstate(fi); __u8 udata[16];
pr_debug("%s() called\n", __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__);
switch (state) { fsm_deltimer(&conn->timer);
case CONN_STATE_SETUPWAIT: iucv_sever(conn->pathid, udata);
printk(KERN_INFO "%s: Remote dropped connection\n", printk(KERN_INFO "%s: Remote dropped connection\n",
netdev->name); netdev->name);
fsm_newstate(fi, CONN_STATE_STOPPED); fsm_newstate(fi, CONN_STATE_STARTWAIT);
fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev); fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
break;
case CONN_STATE_IDLE:
case CONN_STATE_TX:
printk(KERN_INFO "%s: Remote dropped connection\n",
netdev->name);
if (conn->handle)
iucv_unregister_program(conn->handle);
conn->handle = 0;
fsm_newstate(fi, CONN_STATE_STOPPED);
fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
break;
}
} }
static void static void
...@@ -798,6 +790,8 @@ conn_action_start(fsm_instance *fi, int event, void *arg) ...@@ -798,6 +790,8 @@ conn_action_start(fsm_instance *fi, int event, void *arg)
switch (rc) { switch (rc) {
case 0: case 0:
conn->netdev->tx_queue_len = msglimit; conn->netdev->tx_queue_len = msglimit;
fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
CONN_EVENT_TIMER, conn);
return; return;
case 11: case 11:
printk(KERN_NOTICE printk(KERN_NOTICE
...@@ -864,6 +858,7 @@ conn_action_stop(fsm_instance *fi, int event, void *arg) ...@@ -864,6 +858,7 @@ conn_action_stop(fsm_instance *fi, int event, void *arg)
pr_debug("%s() called\n", __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__);
fsm_deltimer(&conn->timer);
fsm_newstate(fi, CONN_STATE_STOPPED); fsm_newstate(fi, CONN_STATE_STOPPED);
netiucv_purge_skb_queue(&conn->collect_queue); netiucv_purge_skb_queue(&conn->collect_queue);
if (conn->handle) if (conn->handle)
...@@ -888,7 +883,6 @@ conn_action_inval(fsm_instance *fi, int event, void *arg) ...@@ -888,7 +883,6 @@ conn_action_inval(fsm_instance *fi, int event, void *arg)
static const fsm_node conn_fsm[] = { static const fsm_node conn_fsm[] = {
{ CONN_STATE_INVALID, CONN_EVENT_START, conn_action_inval }, { CONN_STATE_INVALID, CONN_EVENT_START, conn_action_inval },
{ CONN_STATE_STOPPED, CONN_EVENT_START, conn_action_start }, { CONN_STATE_STOPPED, CONN_EVENT_START, conn_action_start },
{ CONN_STATE_STARTWAIT, CONN_EVENT_START, conn_action_start },
{ CONN_STATE_STOPPED, CONN_EVENT_STOP, conn_action_stop }, { CONN_STATE_STOPPED, CONN_EVENT_STOP, conn_action_stop },
{ CONN_STATE_STARTWAIT, CONN_EVENT_STOP, conn_action_stop }, { CONN_STATE_STARTWAIT, CONN_EVENT_STOP, conn_action_stop },
...@@ -905,6 +899,7 @@ static const fsm_node conn_fsm[] = { ...@@ -905,6 +899,7 @@ static const fsm_node conn_fsm[] = {
{ CONN_STATE_TX, CONN_EVENT_CONN_REQ, conn_action_connreject }, { CONN_STATE_TX, CONN_EVENT_CONN_REQ, conn_action_connreject },
{ CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_ACK, conn_action_connack }, { CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_ACK, conn_action_connack },
{ CONN_STATE_SETUPWAIT, CONN_EVENT_TIMER, conn_action_conntimsev },
{ CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_REJ, conn_action_connsever }, { CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_REJ, conn_action_connsever },
{ CONN_STATE_IDLE, CONN_EVENT_CONN_REJ, conn_action_connsever }, { CONN_STATE_IDLE, CONN_EVENT_CONN_REJ, conn_action_connsever },
...@@ -940,7 +935,6 @@ dev_action_start(fsm_instance *fi, int event, void *arg) ...@@ -940,7 +935,6 @@ dev_action_start(fsm_instance *fi, int event, void *arg)
pr_debug("%s() called\n", __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__);
fsm_deltimer(&privptr->timer);
ev.conn = privptr->conn; ev.conn = privptr->conn;
fsm_newstate(fi, DEV_STATE_STARTWAIT); fsm_newstate(fi, DEV_STATE_STARTWAIT);
fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev); fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
...@@ -964,7 +958,6 @@ dev_action_stop(fsm_instance *fi, int event, void *arg) ...@@ -964,7 +958,6 @@ dev_action_stop(fsm_instance *fi, int event, void *arg)
ev.conn = privptr->conn; ev.conn = privptr->conn;
fsm_deltimer(&privptr->timer);
fsm_newstate(fi, DEV_STATE_STOPWAIT); fsm_newstate(fi, DEV_STATE_STOPWAIT);
fsm_event(privptr->conn->fsm, CONN_EVENT_STOP, &ev); fsm_event(privptr->conn->fsm, CONN_EVENT_STOP, &ev);
} }
...@@ -981,13 +974,10 @@ static void ...@@ -981,13 +974,10 @@ static void
dev_action_connup(fsm_instance *fi, int event, void *arg) dev_action_connup(fsm_instance *fi, int event, void *arg)
{ {
struct net_device *dev = (struct net_device *)arg; struct net_device *dev = (struct net_device *)arg;
struct netiucv_priv *privptr = dev->priv;
pr_debug("%s() called\n", __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__);
switch (fsm_getstate(fi)) { switch (fsm_getstate(fi)) {
case DEV_STATE_STARTRETRY:
fsm_deltimer(&privptr->timer);
case DEV_STATE_STARTWAIT: case DEV_STATE_STARTWAIT:
fsm_newstate(fi, DEV_STATE_RUNNING); fsm_newstate(fi, DEV_STATE_RUNNING);
printk(KERN_INFO printk(KERN_INFO
...@@ -1013,22 +1003,11 @@ dev_action_connup(fsm_instance *fi, int event, void *arg) ...@@ -1013,22 +1003,11 @@ dev_action_connup(fsm_instance *fi, int event, void *arg)
static void static void
dev_action_conndown(fsm_instance *fi, int event, void *arg) dev_action_conndown(fsm_instance *fi, int event, void *arg)
{ {
struct net_device *dev = (struct net_device *)arg;
struct netiucv_priv *privptr = dev->priv;
struct iucv_event ev;
pr_debug("%s() called\n", __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__);
switch (fsm_getstate(fi)) { switch (fsm_getstate(fi)) {
case DEV_STATE_RUNNING: case DEV_STATE_RUNNING:
fsm_newstate(fi, DEV_STATE_STARTWAIT); fsm_newstate(fi, DEV_STATE_STARTWAIT);
ev.conn = privptr->conn;
fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
break;
case DEV_STATE_STARTWAIT:
fsm_addtimer(&privptr->timer, NETIUCV_TIMEOUT_5SEC,
DEV_EVENT_TIMER, dev);
fsm_newstate(fi, DEV_STATE_STARTRETRY);
break; break;
case DEV_STATE_STOPWAIT: case DEV_STATE_STOPWAIT:
fsm_newstate(fi, DEV_STATE_STOPPED); fsm_newstate(fi, DEV_STATE_STOPPED);
...@@ -1044,11 +1023,6 @@ static const fsm_node dev_fsm[] = { ...@@ -1044,11 +1023,6 @@ static const fsm_node dev_fsm[] = {
{ DEV_STATE_STARTWAIT, DEV_EVENT_STOP, dev_action_stop }, { DEV_STATE_STARTWAIT, DEV_EVENT_STOP, dev_action_stop },
{ DEV_STATE_STARTWAIT, DEV_EVENT_CONUP, dev_action_connup }, { DEV_STATE_STARTWAIT, DEV_EVENT_CONUP, dev_action_connup },
{ DEV_STATE_STARTWAIT, DEV_EVENT_CONDOWN, dev_action_conndown },
{ DEV_STATE_STARTRETRY, DEV_EVENT_TIMER, dev_action_start },
{ DEV_STATE_STARTRETRY, DEV_EVENT_CONUP, dev_action_connup },
{ DEV_STATE_STARTRETRY, DEV_EVENT_STOP, dev_action_stop },
{ DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop }, { DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop },
{ DEV_STATE_RUNNING, DEV_EVENT_CONDOWN, dev_action_conndown }, { DEV_STATE_RUNNING, DEV_EVENT_CONDOWN, dev_action_conndown },
...@@ -1119,10 +1093,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) { ...@@ -1119,10 +1093,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
header.next = 0; header.next = 0;
memcpy(skb_put(nskb, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN); memcpy(skb_put(nskb, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
conn->retry = 0;
fsm_newstate(conn->fsm, CONN_STATE_TX); fsm_newstate(conn->fsm, CONN_STATE_TX);
fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
CONN_EVENT_TIMER, conn);
conn->prof.send_stamp = xtime; conn->prof.send_stamp = xtime;
rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */, rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
...@@ -1135,7 +1106,6 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) { ...@@ -1135,7 +1106,6 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
conn->prof.tx_max_pending = conn->prof.tx_pending; conn->prof.tx_max_pending = conn->prof.tx_pending;
if (rc != 0) { if (rc != 0) {
struct netiucv_priv *privptr; struct netiucv_priv *privptr;
fsm_deltimer(&conn->timer);
fsm_newstate(conn->fsm, CONN_STATE_IDLE); fsm_newstate(conn->fsm, CONN_STATE_IDLE);
conn->prof.tx_pending--; conn->prof.tx_pending--;
privptr = (struct netiucv_priv *)conn->netdev->priv; privptr = (struct netiucv_priv *)conn->netdev->priv;
...@@ -1178,7 +1148,6 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) { ...@@ -1178,7 +1148,6 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
*/ */
static int static int
netiucv_open(struct net_device *dev) { netiucv_open(struct net_device *dev) {
SET_DEVICE_START(dev, 1);
fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_START, dev); fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_START, dev);
return 0; return 0;
} }
...@@ -1193,7 +1162,6 @@ netiucv_open(struct net_device *dev) { ...@@ -1193,7 +1162,6 @@ netiucv_open(struct net_device *dev) {
*/ */
static int static int
netiucv_close(struct net_device *dev) { netiucv_close(struct net_device *dev) {
SET_DEVICE_START(dev, 0);
fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev); fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev);
return 0; return 0;
} }
...@@ -1912,7 +1880,7 @@ static struct device_driver netiucv_driver = { ...@@ -1912,7 +1880,7 @@ static struct device_driver netiucv_driver = {
static void static void
netiucv_banner(void) netiucv_banner(void)
{ {
char vbuf[] = "$Revision: 1.47 $"; char vbuf[] = "$Revision: 1.48 $";
char *version = vbuf; char *version = vbuf;
if ((version = strchr(version, ':'))) { if ((version = strchr(version, ':'))) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment