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)
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<sizeof(buf)? count:sizeof(buf));
restore_flags(flags);
/* Read the characters out of the buffer */
......
......@@ -24,6 +24,7 @@
* called twice, causing a deadlock.
* Jeroen (PE1RXQ) Removed old MKISS_MAGIC stuff and calls to
* MOD_*_USE_COUNT
* Remove cli() and fix rtnl lock usage.
*/
#include <linux/config.h>
......@@ -167,6 +168,7 @@ 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 */
......@@ -177,7 +179,6 @@ static inline struct ax_disp *ax_alloc(void)
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);
}
......
......@@ -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
......@@ -163,6 +163,7 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/socket.h>
......@@ -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);
......
......@@ -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 */
......
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