From b0f4ffe8b6437346ee21584bcf95346fb11a339d Mon Sep 17 00:00:00 2001 From: Jeroen Vreeken Date: Wed, 4 Feb 2004 18:48:25 -0500 Subject: [PATCH] [PATCH] hamradio driver fixes I send these a while ago but didn't get a reply. Can you apply these patches for the hamradio drivers? details: + scc.c usage of rtnl lock and register_netdev. + scc.c properly initialize timers. + remove cli() call in 6pack.c + fix init of reused devices and remove cli() + scc.c statistics --- drivers/net/hamradio/6pack.c | 4 ---- drivers/net/hamradio/mkiss.c | 40 +++++++++++++++++++++++------------- drivers/net/hamradio/mkiss.h | 1 + drivers/net/hamradio/scc.c | 10 ++++++++- include/linux/scc.h | 2 +- 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index ea53fe75059a9..91ceae8f5339e 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -516,7 +516,6 @@ static int sixpack_receive_room(struct tty_struct *tty) static void sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { unsigned char buf[512]; - unsigned long flags; int count1; struct sixpack *sp = (struct sixpack *) tty->disc_data; @@ -525,10 +524,7 @@ static void sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, !netif_running(sp->dev) || !count) return; - save_flags(flags); - cli(); memcpy(buf, cp, count @@ -167,17 +168,17 @@ static inline struct ax_disp *ax_alloc(void) /* If no channels are available, allocate one */ if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) { axp = ax25_ctrls[i]; - memset(axp, 0, sizeof(ax25_ctrl_t)); - - /* Initialize channel control data */ - set_bit(AXF_INUSE, &axp->ctrl.flags); - sprintf(axp->dev.name, "ax%d", i++); - axp->ctrl.tty = NULL; - axp->dev.base_addr = i; - axp->dev.priv = (void *)&axp->ctrl; - axp->dev.next = NULL; - axp->dev.init = ax25_init; } + memset(axp, 0, sizeof(ax25_ctrl_t)); + + /* Initialize channel control data */ + set_bit(AXF_INUSE, &axp->ctrl.flags); + sprintf(axp->dev.name, "ax%d", i++); + axp->ctrl.tty = NULL; + axp->dev.base_addr = i; + axp->dev.priv = (void *)&axp->ctrl; + axp->dev.next = NULL; + axp->dev.init = ax25_init; if (axp != NULL) { /* @@ -220,7 +221,6 @@ static void ax_changedmtu(struct ax_disp *ax) struct net_device *dev = ax->dev; unsigned char *xbuff, *rbuff, *oxbuff, *orbuff; int len; - unsigned long flags; len = dev->mtu * 2; @@ -246,8 +246,7 @@ static void ax_changedmtu(struct ax_disp *ax) return; } - save_flags(flags); - cli(); + spin_lock_bh(ax->buflock); oxbuff = ax->xbuff; ax->xbuff = xbuff; @@ -278,7 +277,7 @@ static void ax_changedmtu(struct ax_disp *ax) ax->mtu = dev->mtu + 73; ax->buffsize = len; - restore_flags(flags); + spin_unlock_bh(ax->buflock); if (oxbuff != NULL) kfree(oxbuff); @@ -306,6 +305,7 @@ static void ax_bump(struct ax_disp *ax) struct sk_buff *skb; int count; + spin_lock_bh(ax->buflock); if (ax->rbuff[0] > 0x0f) { if (ax->rbuff[0] & 0x20) { ax->crcmode = CRC_MODE_FLEX; @@ -322,6 +322,7 @@ static void ax_bump(struct ax_disp *ax) *ax->rbuff &= ~0x20; } } + spin_unlock_bh(ax->buflock); count = ax->rcount; @@ -332,7 +333,9 @@ static void ax_bump(struct ax_disp *ax) } skb->dev = ax->dev; + spin_lock_bh(ax->buflock); memcpy(skb_put(skb,count), ax->rbuff, count); + spin_unlock_bh(ax->buflock); skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_AX25); netif_rx(skb); @@ -360,6 +363,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) p = icp; + spin_lock_bh(ax->buflock); switch (ax->crcmode) { unsigned short crc; @@ -373,6 +377,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) count = kiss_esc(p, (unsigned char *)ax->xbuff, len); break; } + ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count); ax->tx_packets++; @@ -380,6 +385,8 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) ax->dev->trans_start = jiffies; ax->xleft = count - actual; ax->xhead = ax->xbuff + actual; + + spin_unlock_bh(ax->buflock); } /* @@ -511,6 +518,8 @@ static int ax_open(struct net_device *dev) ax->flags &= (1 << AXF_INUSE); /* Clear ESCAPE & ERROR flags */ + ax->buflock = SPIN_LOCK_UNLOCKED; + netif_start_queue(dev); return 0; @@ -750,15 +759,18 @@ static void kiss_unesc(struct ax_disp *ax, unsigned char s) break; } + spin_lock_bh(ax->buflock); if (!test_bit(AXF_ERROR, &ax->flags)) { if (ax->rcount < ax->buffsize) { ax->rbuff[ax->rcount++] = s; + spin_unlock_bh(ax->buflock); return; } ax->rx_over_errors++; set_bit(AXF_ERROR, &ax->flags); } + spin_unlock_bh(ax->buflock); } diff --git a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h index fa62e76829c8b..4ab7004785989 100644 --- a/drivers/net/hamradio/mkiss.h +++ b/drivers/net/hamradio/mkiss.h @@ -56,6 +56,7 @@ struct ax_disp { #define CRC_MODE_NONE 0 #define CRC_MODE_FLEX 1 #define CRC_MODE_SMACK 2 + spinlock_t buflock; /* lock for rbuf and xbuf */ }; #define AX25_MAGIC 0x5316 diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index 7d4afa3bd16a9..0e6844fc339bd 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -163,6 +163,7 @@ #include #include #include +#include #include #include #include @@ -1520,8 +1521,10 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc) dev->priv = scc; scc->dev = dev; spin_lock_init(&scc->lock); + init_timer(&scc->tx_t); + init_timer(&scc->tx_wdog); - err = register_netdev(dev); + err = register_netdevice(dev); if (err) { printk(KERN_ERR "%s: can't register network device (%d)\n", name, err); @@ -1625,6 +1628,7 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb) } scc->dev_stat.rx_packets++; + scc->dev_stat.rx_bytes += skb->len; skb->dev = scc->dev; skb->protocol = htons(ETH_P_AX25); @@ -1651,6 +1655,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev) } scc->dev_stat.tx_packets++; + scc->dev_stat.tx_bytes += skb->len; scc->stat.txframes++; kisscmd = *skb->data & 0x1f; @@ -2114,10 +2119,13 @@ static int __init scc_init_driver (void) sprintf(devname,"%s0", SCC_DriverName); + rtnl_lock(); if (scc_net_alloc(devname, SCC_Info)) { + rtnl_unlock(); printk(KERN_ERR "z8530drv: cannot initialize module\n"); return -EIO; } + rtnl_unlock(); proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops); diff --git a/include/linux/scc.h b/include/linux/scc.h index 4965e146b737d..885a4a02b23c7 100644 --- a/include/linux/scc.h +++ b/include/linux/scc.h @@ -200,7 +200,7 @@ struct scc_kiss { unsigned char fulldup; /* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */ unsigned char waittime; /* Waittime before any transmit attempt */ unsigned int maxkeyup; /* Maximum time to transmit (seconds) */ - unsigned char mintime; /* Minimal offtime after MAXKEYUP timeout (seconds) */ + unsigned int mintime; /* Minimal offtime after MAXKEYUP timeout (seconds) */ unsigned int idletime; /* Maximum idle time in ALWAYS KEYED mode (seconds) */ unsigned int maxdefer; /* Timer for CSMA channel busy limit */ unsigned char tx_inhibit; /* Transmit is not allowed when set */ -- 2.53.0