Commit 65bdce08 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: ctc network driver.

Bug fixes for the CTC driver

also removes the bogus intparm_t typedef
parent 01613ea0
/* /*
* $Id: ctcmain.c,v 1.30 2002/12/09 13:56:20 aberg Exp $ * $Id: ctcmain.c,v 1.35 2003/01/17 13:46:13 cohuck Exp $
* *
* CTC / ESCON network driver * CTC / ESCON network driver
* *
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,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: CTC/ESCON network driver $Revision: 1.30 $ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.35 $
* *
*/ */
...@@ -105,10 +105,6 @@ MODULE_LICENSE("GPL"); ...@@ -105,10 +105,6 @@ MODULE_LICENSE("GPL");
#define CTC_ID_SIZE DEVICE_ID_SIZE+3 #define CTC_ID_SIZE DEVICE_ID_SIZE+3
/**
* If running on 64 bit, this must be changed. XXX Why? (bird)
*/
typedef unsigned long intparm_t;
struct ctc_profile { struct ctc_profile {
unsigned long maxmulti; unsigned long maxmulti;
...@@ -270,8 +266,6 @@ ctc_test_and_set_busy(struct net_device * dev) ...@@ -270,8 +266,6 @@ ctc_test_and_set_busy(struct net_device * dev)
return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy); return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
} }
#define SET_DEVICE_START(device, value)
/** /**
* Print Banner. * Print Banner.
*/ */
...@@ -279,7 +273,7 @@ static void ...@@ -279,7 +273,7 @@ static void
print_banner(void) print_banner(void)
{ {
static int printed = 0; static int printed = 0;
char vbuf[] = "$Revision: 1.30 $"; char vbuf[] = "$Revision: 1.35 $";
char *version = vbuf; char *version = vbuf;
if (printed) if (printed)
...@@ -882,7 +876,7 @@ ch_action_txdone(fsm_instance * fi, int event, void *arg) ...@@ -882,7 +876,7 @@ ch_action_txdone(fsm_instance * fi, int event, void *arg)
fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch); fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
ch->prof.send_stamp = xtime; ch->prof.send_stamp = xtime;
rc = ccw_device_start(ch->cdev, &ch->ccw[0], rc = ccw_device_start(ch->cdev, &ch->ccw[0],
(intparm_t) ch, 0xff, 0); (unsigned long) ch, 0xff, 0);
ch->prof.doios_multi++; ch->prof.doios_multi++;
if (rc != 0) { if (rc != 0) {
privptr->stats.tx_dropped += i; privptr->stats.tx_dropped += i;
...@@ -985,7 +979,7 @@ ch_action_rx(fsm_instance * fi, int event, void *arg) ...@@ -985,7 +979,7 @@ ch_action_rx(fsm_instance * fi, int event, void *arg)
if (ctc_checkalloc_buffer(ch, 1)) if (ctc_checkalloc_buffer(ch, 1))
return; return;
ch->ccw[1].count = ch->max_bufsize; ch->ccw[1].count = ch->max_bufsize;
rc = ccw_device_start(ch->cdev, &ch->ccw[0], (intparm_t) ch, 0xff, 0); rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);
if (rc != 0) if (rc != 0)
ccw_check_return_code(ch, rc); ccw_check_return_code(ch, rc);
} }
...@@ -1042,7 +1036,7 @@ ch_action_firstio(fsm_instance * fi, int event, void *arg) ...@@ -1042,7 +1036,7 @@ ch_action_firstio(fsm_instance * fi, int event, void *arg)
fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ) fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
? CH_STATE_RXINIT : CH_STATE_TXINIT); ? CH_STATE_RXINIT : CH_STATE_TXINIT);
rc = ccw_device_start(ch->cdev, &ch->ccw[0], (intparm_t) ch, 0xff, 0); rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);
if (rc != 0) { if (rc != 0) {
fsm_deltimer(&ch->timer); fsm_deltimer(&ch->timer);
fsm_newstate(fi, CH_STATE_SETUPWAIT); fsm_newstate(fi, CH_STATE_SETUPWAIT);
...@@ -1089,7 +1083,7 @@ ch_action_rxidle(fsm_instance * fi, int event, void *arg) ...@@ -1089,7 +1083,7 @@ ch_action_rxidle(fsm_instance * fi, int event, void *arg)
ch->ccw[1].count = ch->max_bufsize; ch->ccw[1].count = ch->max_bufsize;
fsm_newstate(fi, CH_STATE_RXIDLE); fsm_newstate(fi, CH_STATE_RXIDLE);
rc = ccw_device_start(ch->cdev, &ch->ccw[0], rc = ccw_device_start(ch->cdev, &ch->ccw[0],
(intparm_t) ch, 0xff, 0); (unsigned long) ch, 0xff, 0);
if (rc != 0) { if (rc != 0) {
fsm_newstate(fi, CH_STATE_RXINIT); fsm_newstate(fi, CH_STATE_RXINIT);
ccw_check_return_code(ch, rc); ccw_check_return_code(ch, rc);
...@@ -1122,7 +1116,7 @@ ch_action_setmode(fsm_instance * fi, int event, void *arg) ...@@ -1122,7 +1116,7 @@ ch_action_setmode(fsm_instance * fi, int event, void *arg)
fsm_newstate(fi, CH_STATE_SETUPWAIT); fsm_newstate(fi, CH_STATE_SETUPWAIT);
if (event == CH_EVENT_TIMER) if (event == CH_EVENT_TIMER)
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
rc = ccw_device_start(ch->cdev, &ch->ccw[6], (intparm_t) ch, 0xff, 0); rc = ccw_device_start(ch->cdev, &ch->ccw[6], (unsigned long) ch, 0xff, 0);
if (event == CH_EVENT_TIMER) if (event == CH_EVENT_TIMER)
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags); spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
if (rc != 0) { if (rc != 0) {
...@@ -1198,7 +1192,7 @@ ch_action_start(fsm_instance * fi, int event, void *arg) ...@@ -1198,7 +1192,7 @@ ch_action_start(fsm_instance * fi, int event, void *arg)
fsm_newstate(fi, CH_STATE_STARTWAIT); fsm_newstate(fi, CH_STATE_STARTWAIT);
fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch); fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
rc = ccw_device_halt(ch->cdev, (intparm_t) ch); rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags); spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
if (rc != 0) { if (rc != 0) {
fsm_deltimer(&ch->timer); fsm_deltimer(&ch->timer);
...@@ -1228,7 +1222,7 @@ ch_action_haltio(fsm_instance * fi, int event, void *arg) ...@@ -1228,7 +1222,7 @@ ch_action_haltio(fsm_instance * fi, int event, void *arg)
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
oldstate = fsm_getstate(fi); oldstate = fsm_getstate(fi);
fsm_newstate(fi, CH_STATE_TERM); fsm_newstate(fi, CH_STATE_TERM);
rc = ccw_device_halt(ch->cdev, (intparm_t) ch); rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
if (event == CH_EVENT_STOP) if (event == CH_EVENT_STOP)
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags); spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
if (rc != 0) { if (rc != 0) {
...@@ -1345,7 +1339,7 @@ ch_action_setuperr(fsm_instance * fi, int event, void *arg) ...@@ -1345,7 +1339,7 @@ ch_action_setuperr(fsm_instance * fi, int event, void *arg)
fsm_deltimer(&ch->timer); fsm_deltimer(&ch->timer);
fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch); fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
if (CHANNEL_DIRECTION(ch->flags) == READ) { if (CHANNEL_DIRECTION(ch->flags) == READ) {
int rc = ccw_device_halt(ch->cdev, (intparm_t) ch); int rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
if (rc != 0) if (rc != 0)
ccw_check_return_code(ch, rc); ccw_check_return_code(ch, rc);
} }
...@@ -1392,7 +1386,7 @@ ch_action_restart(fsm_instance * fi, int event, void *arg) ...@@ -1392,7 +1386,7 @@ ch_action_restart(fsm_instance * fi, int event, void *arg)
fsm_newstate(fi, CH_STATE_STARTWAIT); fsm_newstate(fi, CH_STATE_STARTWAIT);
if (event == CH_EVENT_TIMER) if (event == CH_EVENT_TIMER)
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
rc = ccw_device_halt(ch->cdev, (intparm_t) ch); rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
if (event == CH_EVENT_TIMER) if (event == CH_EVENT_TIMER)
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags); spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
if (rc != 0) { if (rc != 0) {
...@@ -1480,8 +1474,8 @@ ch_action_rxdisc(fsm_instance * fi, int event, void *arg) ...@@ -1480,8 +1474,8 @@ ch_action_rxdisc(fsm_instance * fi, int event, void *arg)
ch2 = ((struct ctc_priv *) dev->priv)->channel[WRITE]; ch2 = ((struct ctc_priv *) dev->priv)->channel[WRITE];
fsm_newstate(ch2->fsm, CH_STATE_DTERM); fsm_newstate(ch2->fsm, CH_STATE_DTERM);
ccw_device_halt(ch->cdev, (intparm_t) ch); ccw_device_halt(ch->cdev, (unsigned long) ch);
ccw_device_halt(ch2->cdev, (intparm_t) ch2); ccw_device_halt(ch2->cdev, (unsigned long) ch2);
} }
/** /**
...@@ -1556,7 +1550,7 @@ ch_action_txretry(fsm_instance * fi, int event, void *arg) ...@@ -1556,7 +1550,7 @@ ch_action_txretry(fsm_instance * fi, int event, void *arg)
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), spin_lock_irqsave(get_ccwdev_lock(ch->cdev),
saveflags); saveflags);
rc = ccw_device_start(ch->cdev, &ch->ccw[3], rc = ccw_device_start(ch->cdev, &ch->ccw[3],
(intparm_t) ch, 0xff, 0); (unsigned long) ch, 0xff, 0);
if (event == CH_EVENT_TIMER) if (event == CH_EVENT_TIMER)
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev),
saveflags); saveflags);
...@@ -1956,21 +1950,34 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) ...@@ -1956,21 +1950,34 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
{ {
struct channel *ch; struct channel *ch;
struct net_device *dev; struct net_device *dev;
struct ctc_priv *priv;
ch = (struct channel *) intparm; /* Check for unsolicited interrupts. */
/** if (!cdev->dev.driver_data) {
* Check for unsolicited interrupts.
* If intparm is NULL, try to get channel from ccw_device.
*/
if (ch == NULL) {
ch = container_of(&cdev, struct channel, cdev);
if (ch == NULL) {
printk(KERN_WARNING printk(KERN_WARNING
"ctc: Got unsolicited irq: %s c-%02x d-%02x\n", "ctc: Got unsolicited irq: %s c-%02x d-%02x\n",
cdev->dev.bus_id, irb->scsw.cstat, cdev->dev.bus_id, irb->scsw.cstat,
irb->scsw.dstat); irb->scsw.dstat);
return; return;
} }
priv = cdev->dev.driver_data;
ch = (struct channel *) intparm;
if ((ch != priv->channel[READ]) && (ch != priv->channel[WRITE]))
ch = NULL;
if (!ch) {
/* Try to extract channel from driver data. */
if (priv->channel[READ]->cdev == cdev)
ch = priv->channel[READ];
else if (priv->channel[WRITE]->cdev == cdev)
ch = priv->channel[READ];
else {
printk(KERN_ERR
"ctc: Can't determine channel for interrupt, "
"device %s\n", cdev->dev.bus_id);
return;
}
} }
dev = (struct net_device *) (ch->netdev); dev = (struct net_device *) (ch->netdev);
...@@ -2342,7 +2349,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) ...@@ -2342,7 +2349,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
ch->prof.send_stamp = xtime; ch->prof.send_stamp = xtime;
rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx], rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
(intparm_t) ch, 0xff, 0); (unsigned long) ch, 0xff, 0);
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags); spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
if (ccw_idx == 3) if (ccw_idx == 3)
ch->prof.doios_single++; ch->prof.doios_single++;
...@@ -2401,7 +2408,6 @@ ctc_open(struct net_device * dev) ...@@ -2401,7 +2408,6 @@ ctc_open(struct net_device * dev)
static int static int
ctc_close(struct net_device * dev) ctc_close(struct net_device * dev)
{ {
SET_DEVICE_START(dev, 0);
fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_STOP, dev); fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_STOP, dev);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return 0; return 0;
...@@ -2533,7 +2539,7 @@ buffer_write(struct device *dev, const char *buf, size_t count) ...@@ -2533,7 +2539,7 @@ buffer_write(struct device *dev, const char *buf, size_t count)
priv = dev->driver_data; priv = dev->driver_data;
if (!priv) if (!priv)
return -ENODEV; return -ENODEV;
ndev = container_of((void *) priv, struct net_device, priv); ndev = priv->channel[READ]->netdev;
if (!ndev) if (!ndev)
return -ENODEV; return -ENODEV;
sscanf(buf, "%u", &bs1); sscanf(buf, "%u", &bs1);
...@@ -2755,7 +2761,6 @@ ctc_init_netdevice(struct net_device * dev, int alloc_device, ...@@ -2755,7 +2761,6 @@ ctc_init_netdevice(struct net_device * dev, int alloc_device,
dev->addr_len = 0; dev->addr_len = 0;
dev->type = ARPHRD_SLIP; dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 100; dev->tx_queue_len = 100;
SET_DEVICE_START(dev, 1);
dev_init_buffers(dev); dev_init_buffers(dev);
dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->flags = IFF_POINTOPOINT | IFF_NOARP;
return dev; return dev;
...@@ -2881,11 +2886,14 @@ ctc_new_device(struct ccwgroup_device *cgdev) ...@@ -2881,11 +2886,14 @@ ctc_new_device(struct ccwgroup_device *cgdev)
if (add_channel(cgdev->cdev[1], type)) if (add_channel(cgdev->cdev[1], type))
return -ENOMEM; return -ENOMEM;
ccw_device_set_online(cgdev->cdev[0]);
ccw_device_set_online(cgdev->cdev[1]);
dev = ctc_init_netdevice(NULL, 1, privptr); dev = ctc_init_netdevice(NULL, 1, privptr);
if (!dev) { if (!dev) {
printk(KERN_WARNING "ctc_init_netdevice failed\n"); printk(KERN_WARNING "ctc_init_netdevice failed\n");
return -ENODEV; goto out;
} }
if (privptr->protocol == CTC_PROTO_LINUX_TTY) if (privptr->protocol == CTC_PROTO_LINUX_TTY)
...@@ -2902,7 +2910,7 @@ ctc_new_device(struct ccwgroup_device *cgdev) ...@@ -2902,7 +2910,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
channel_free(privptr->channel[READ]); channel_free(privptr->channel[READ]);
ctc_free_netdevice(dev, 1); ctc_free_netdevice(dev, 1);
return -ENODEV; goto out;
} }
privptr->channel[direction]->netdev = dev; privptr->channel[direction]->netdev = dev;
privptr->channel[direction]->protocol = privptr->protocol; privptr->channel[direction]->protocol = privptr->protocol;
...@@ -2910,7 +2918,7 @@ ctc_new_device(struct ccwgroup_device *cgdev) ...@@ -2910,7 +2918,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
} }
if (ctc_netdev_register(dev) != 0) { if (ctc_netdev_register(dev) != 0) {
ctc_free_netdevice(dev, 1); ctc_free_netdevice(dev, 1);
return -ENODEV; goto out;
} }
ctc_add_attributes(&cgdev->dev); ctc_add_attributes(&cgdev->dev);
...@@ -2925,6 +2933,11 @@ ctc_new_device(struct ccwgroup_device *cgdev) ...@@ -2925,6 +2933,11 @@ ctc_new_device(struct ccwgroup_device *cgdev)
privptr->channel[WRITE]->id, privptr->protocol); privptr->channel[WRITE]->id, privptr->protocol);
return 0; return 0;
out:
ccw_device_set_offline(cgdev->cdev[1]);
ccw_device_set_offline(cgdev->cdev[0]);
return -ENODEV;
} }
/** /**
...@@ -2944,7 +2957,7 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev) ...@@ -2944,7 +2957,7 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
priv = cgdev->dev.driver_data; priv = cgdev->dev.driver_data;
if (!priv) if (!priv)
return -ENODEV; return -ENODEV;
ndev = container_of((void *)priv, struct net_device, priv); ndev = priv->channel[READ]->netdev;
/* Close the device */ /* Close the device */
ctc_close(ndev); ctc_close(ndev);
...@@ -2961,6 +2974,9 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev) ...@@ -2961,6 +2974,9 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
kfree_fsm(priv->fsm); kfree_fsm(priv->fsm);
ccw_device_set_offline(cgdev->cdev[1]);
ccw_device_set_offline(cgdev->cdev[0]);
channel_remove(priv->channel[READ]); channel_remove(priv->channel[READ]);
channel_remove(priv->channel[WRITE]); channel_remove(priv->channel[WRITE]);
......
/* /*
* $Id: cu3088.c,v 1.22 2002/12/10 09:53:55 cohuck Exp $ * $Id: cu3088.c,v 1.26 2003/01/17 13:46:13 cohuck Exp $
* *
* CTC / LCS ccw_device driver * CTC / LCS ccw_device driver
* *
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include <asm/ccwgroup.h> #include <asm/ccwgroup.h>
...@@ -146,10 +144,8 @@ cu3088_init (void) ...@@ -146,10 +144,8 @@ cu3088_init (void)
if (rc) if (rc)
return rc; return rc;
rc = ccw_driver_register(&cu3088_driver); rc = ccw_driver_register(&cu3088_driver);
if (rc) { if (rc)
device_unregister(&cu3088_root_dev); device_unregister(&cu3088_root_dev);
return rc;
}
return rc; return rc;
} }
...@@ -168,5 +164,6 @@ MODULE_LICENSE("GPL"); ...@@ -168,5 +164,6 @@ MODULE_LICENSE("GPL");
module_init(cu3088_init); module_init(cu3088_init);
module_exit(cu3088_exit); module_exit(cu3088_exit);
EXPORT_SYMBOL_GPL(cu3088_type);
EXPORT_SYMBOL_GPL(register_cu3088_discipline); EXPORT_SYMBOL_GPL(register_cu3088_discipline);
EXPORT_SYMBOL_GPL(unregister_cu3088_discipline); EXPORT_SYMBOL_GPL(unregister_cu3088_discipline);
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