Commit b0f4ffe8 authored by Jeroen Vreeken's avatar Jeroen Vreeken Committed by Jeff Garzik

[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
parent c32262de
...@@ -516,7 +516,6 @@ static int sixpack_receive_room(struct tty_struct *tty) ...@@ -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) static void sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
{ {
unsigned char buf[512]; unsigned char buf[512];
unsigned long flags;
int count1; int count1;
struct sixpack *sp = (struct sixpack *) tty->disc_data; 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, ...@@ -525,10 +524,7 @@ static void sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp,
!netif_running(sp->dev) || !count) !netif_running(sp->dev) || !count)
return; return;
save_flags(flags);
cli();
memcpy(buf, cp, count<sizeof(buf)? count:sizeof(buf)); memcpy(buf, cp, count<sizeof(buf)? count:sizeof(buf));
restore_flags(flags);
/* Read the characters out of the buffer */ /* Read the characters out of the buffer */
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
* called twice, causing a deadlock. * called twice, causing a deadlock.
* Jeroen (PE1RXQ) Removed old MKISS_MAGIC stuff and calls to * Jeroen (PE1RXQ) Removed old MKISS_MAGIC stuff and calls to
* MOD_*_USE_COUNT * MOD_*_USE_COUNT
* Remove cli() and fix rtnl lock usage.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -167,17 +168,17 @@ static inline struct ax_disp *ax_alloc(void) ...@@ -167,17 +168,17 @@ static inline struct ax_disp *ax_alloc(void)
/* If no channels are available, allocate one */ /* If no channels are available, allocate one */
if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) { if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) {
axp = ax25_ctrls[i]; 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) { if (axp != NULL) {
/* /*
...@@ -220,7 +221,6 @@ static void ax_changedmtu(struct ax_disp *ax) ...@@ -220,7 +221,6 @@ static void ax_changedmtu(struct ax_disp *ax)
struct net_device *dev = ax->dev; struct net_device *dev = ax->dev;
unsigned char *xbuff, *rbuff, *oxbuff, *orbuff; unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
int len; int len;
unsigned long flags;
len = dev->mtu * 2; len = dev->mtu * 2;
...@@ -246,8 +246,7 @@ static void ax_changedmtu(struct ax_disp *ax) ...@@ -246,8 +246,7 @@ static void ax_changedmtu(struct ax_disp *ax)
return; return;
} }
save_flags(flags); spin_lock_bh(ax->buflock);
cli();
oxbuff = ax->xbuff; oxbuff = ax->xbuff;
ax->xbuff = xbuff; ax->xbuff = xbuff;
...@@ -278,7 +277,7 @@ static void ax_changedmtu(struct ax_disp *ax) ...@@ -278,7 +277,7 @@ static void ax_changedmtu(struct ax_disp *ax)
ax->mtu = dev->mtu + 73; ax->mtu = dev->mtu + 73;
ax->buffsize = len; ax->buffsize = len;
restore_flags(flags); spin_unlock_bh(ax->buflock);
if (oxbuff != NULL) if (oxbuff != NULL)
kfree(oxbuff); kfree(oxbuff);
...@@ -306,6 +305,7 @@ static void ax_bump(struct ax_disp *ax) ...@@ -306,6 +305,7 @@ static void ax_bump(struct ax_disp *ax)
struct sk_buff *skb; struct sk_buff *skb;
int count; int count;
spin_lock_bh(ax->buflock);
if (ax->rbuff[0] > 0x0f) { if (ax->rbuff[0] > 0x0f) {
if (ax->rbuff[0] & 0x20) { if (ax->rbuff[0] & 0x20) {
ax->crcmode = CRC_MODE_FLEX; ax->crcmode = CRC_MODE_FLEX;
...@@ -322,6 +322,7 @@ static void ax_bump(struct ax_disp *ax) ...@@ -322,6 +322,7 @@ static void ax_bump(struct ax_disp *ax)
*ax->rbuff &= ~0x20; *ax->rbuff &= ~0x20;
} }
} }
spin_unlock_bh(ax->buflock);
count = ax->rcount; count = ax->rcount;
...@@ -332,7 +333,9 @@ static void ax_bump(struct ax_disp *ax) ...@@ -332,7 +333,9 @@ static void ax_bump(struct ax_disp *ax)
} }
skb->dev = ax->dev; skb->dev = ax->dev;
spin_lock_bh(ax->buflock);
memcpy(skb_put(skb,count), ax->rbuff, count); memcpy(skb_put(skb,count), ax->rbuff, count);
spin_unlock_bh(ax->buflock);
skb->mac.raw = skb->data; skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_AX25); skb->protocol = htons(ETH_P_AX25);
netif_rx(skb); netif_rx(skb);
...@@ -360,6 +363,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) ...@@ -360,6 +363,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
p = icp; p = icp;
spin_lock_bh(ax->buflock);
switch (ax->crcmode) { switch (ax->crcmode) {
unsigned short crc; unsigned short crc;
...@@ -373,6 +377,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) ...@@ -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); count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
break; break;
} }
ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count); actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count);
ax->tx_packets++; ax->tx_packets++;
...@@ -380,6 +385,8 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) ...@@ -380,6 +385,8 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
ax->dev->trans_start = jiffies; ax->dev->trans_start = jiffies;
ax->xleft = count - actual; ax->xleft = count - actual;
ax->xhead = ax->xbuff + actual; ax->xhead = ax->xbuff + actual;
spin_unlock_bh(ax->buflock);
} }
/* /*
...@@ -511,6 +518,8 @@ static int ax_open(struct net_device *dev) ...@@ -511,6 +518,8 @@ static int ax_open(struct net_device *dev)
ax->flags &= (1 << AXF_INUSE); /* Clear ESCAPE & ERROR flags */ ax->flags &= (1 << AXF_INUSE); /* Clear ESCAPE & ERROR flags */
ax->buflock = SPIN_LOCK_UNLOCKED;
netif_start_queue(dev); netif_start_queue(dev);
return 0; return 0;
...@@ -750,15 +759,18 @@ static void kiss_unesc(struct ax_disp *ax, unsigned char s) ...@@ -750,15 +759,18 @@ static void kiss_unesc(struct ax_disp *ax, unsigned char s)
break; break;
} }
spin_lock_bh(ax->buflock);
if (!test_bit(AXF_ERROR, &ax->flags)) { if (!test_bit(AXF_ERROR, &ax->flags)) {
if (ax->rcount < ax->buffsize) { if (ax->rcount < ax->buffsize) {
ax->rbuff[ax->rcount++] = s; ax->rbuff[ax->rcount++] = s;
spin_unlock_bh(ax->buflock);
return; return;
} }
ax->rx_over_errors++; ax->rx_over_errors++;
set_bit(AXF_ERROR, &ax->flags); set_bit(AXF_ERROR, &ax->flags);
} }
spin_unlock_bh(ax->buflock);
} }
......
...@@ -56,6 +56,7 @@ struct ax_disp { ...@@ -56,6 +56,7 @@ struct ax_disp {
#define CRC_MODE_NONE 0 #define CRC_MODE_NONE 0
#define CRC_MODE_FLEX 1 #define CRC_MODE_FLEX 1
#define CRC_MODE_SMACK 2 #define CRC_MODE_SMACK 2
spinlock_t buflock; /* lock for rbuf and xbuf */
}; };
#define AX25_MAGIC 0x5316 #define AX25_MAGIC 0x5316
...@@ -163,6 +163,7 @@ ...@@ -163,6 +163,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/socket.h> #include <linux/socket.h>
...@@ -1520,8 +1521,10 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc) ...@@ -1520,8 +1521,10 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc)
dev->priv = scc; dev->priv = scc;
scc->dev = dev; scc->dev = dev;
spin_lock_init(&scc->lock); 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) { if (err) {
printk(KERN_ERR "%s: can't register network device (%d)\n", printk(KERN_ERR "%s: can't register network device (%d)\n",
name, err); name, err);
...@@ -1625,6 +1628,7 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb) ...@@ -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_packets++;
scc->dev_stat.rx_bytes += skb->len;
skb->dev = scc->dev; skb->dev = scc->dev;
skb->protocol = htons(ETH_P_AX25); skb->protocol = htons(ETH_P_AX25);
...@@ -1651,6 +1655,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -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_packets++;
scc->dev_stat.tx_bytes += skb->len;
scc->stat.txframes++; scc->stat.txframes++;
kisscmd = *skb->data & 0x1f; kisscmd = *skb->data & 0x1f;
...@@ -2114,10 +2119,13 @@ static int __init scc_init_driver (void) ...@@ -2114,10 +2119,13 @@ static int __init scc_init_driver (void)
sprintf(devname,"%s0", SCC_DriverName); sprintf(devname,"%s0", SCC_DriverName);
rtnl_lock();
if (scc_net_alloc(devname, SCC_Info)) { if (scc_net_alloc(devname, SCC_Info)) {
rtnl_unlock();
printk(KERN_ERR "z8530drv: cannot initialize module\n"); printk(KERN_ERR "z8530drv: cannot initialize module\n");
return -EIO; return -EIO;
} }
rtnl_unlock();
proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops); proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops);
......
...@@ -200,7 +200,7 @@ struct scc_kiss { ...@@ -200,7 +200,7 @@ struct scc_kiss {
unsigned char fulldup; /* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */ unsigned char fulldup; /* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */
unsigned char waittime; /* Waittime before any transmit attempt */ unsigned char waittime; /* Waittime before any transmit attempt */
unsigned int maxkeyup; /* Maximum time to transmit (seconds) */ 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 idletime; /* Maximum idle time in ALWAYS KEYED mode (seconds) */
unsigned int maxdefer; /* Timer for CSMA channel busy limit */ unsigned int maxdefer; /* Timer for CSMA channel busy limit */
unsigned char tx_inhibit; /* Transmit is not allowed when set */ unsigned char tx_inhibit; /* Transmit is not allowed when set */
......
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