aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wan
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wan')
-rw-r--r--drivers/net/wan/cosa.c22
-rw-r--r--drivers/net/wan/hdlc.c19
-rw-r--r--drivers/net/wan/hdlc_cisco.c82
-rw-r--r--drivers/net/wan/hdlc_fr.c1
-rw-r--r--drivers/net/wan/x25_asy.c3
5 files changed, 80 insertions, 47 deletions
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index b0fce1387ea..5827324e9d9 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -92,6 +92,7 @@
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/device.h>
+#include <linux/smp_lock.h>
#undef COSA_SLOW_IO /* for testing purposes only */
@@ -970,15 +971,21 @@ static int cosa_open(struct inode *inode, struct file *file)
struct channel_data *chan;
unsigned long flags;
int n;
+ int ret = 0;
+ lock_kernel();
if ((n=iminor(file->f_path.dentry->d_inode)>>CARD_MINOR_BITS)
- >= nr_cards)
- return -ENODEV;
+ >= nr_cards) {
+ ret = -ENODEV;
+ goto out;
+ }
cosa = cosa_cards+n;
if ((n=iminor(file->f_path.dentry->d_inode)
- & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels)
- return -ENODEV;
+ & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels) {
+ ret = -ENODEV;
+ goto out;
+ }
chan = cosa->chan + n;
file->private_data = chan;
@@ -987,7 +994,8 @@ static int cosa_open(struct inode *inode, struct file *file)
if (chan->usage < 0) { /* in netdev mode */
spin_unlock_irqrestore(&cosa->lock, flags);
- return -EBUSY;
+ ret = -EBUSY;
+ goto out;
}
cosa->usage++;
chan->usage++;
@@ -996,7 +1004,9 @@ static int cosa_open(struct inode *inode, struct file *file)
chan->setup_rx = chrdev_setup_rx;
chan->rx_done = chrdev_rx_done;
spin_unlock_irqrestore(&cosa->lock, flags);
- return 0;
+out:
+ unlock_kernel();
+ return ret;
}
static int cosa_release(struct inode *inode, struct file *file)
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 9a83c9d5b8c..7f984895b0d 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -43,8 +43,7 @@ static const char* version = "HDLC support module revision 1.22";
#undef DEBUG_LINK
-static struct hdlc_proto *first_proto = NULL;
-
+static struct hdlc_proto *first_proto;
static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
{
@@ -314,21 +313,25 @@ void detach_hdlc_protocol(struct net_device *dev)
void register_hdlc_protocol(struct hdlc_proto *proto)
{
+ rtnl_lock();
proto->next = first_proto;
first_proto = proto;
+ rtnl_unlock();
}
void unregister_hdlc_protocol(struct hdlc_proto *proto)
{
- struct hdlc_proto **p = &first_proto;
- while (*p) {
- if (*p == proto) {
- *p = proto->next;
- return;
- }
+ struct hdlc_proto **p;
+
+ rtnl_lock();
+ p = &first_proto;
+ while (*p != proto) {
+ BUG_ON(!*p);
p = &((*p)->next);
}
+ *p = proto->next;
+ rtnl_unlock();
}
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index 7133c688cf2..762d21c1c70 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -56,6 +56,7 @@ struct cisco_state {
cisco_proto settings;
struct timer_list timer;
+ spinlock_t lock;
unsigned long last_poll;
int up;
int request_sent;
@@ -158,6 +159,7 @@ static int cisco_rx(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
hdlc_device *hdlc = dev_to_hdlc(dev);
+ struct cisco_state *st = state(hdlc);
struct hdlc_header *data = (struct hdlc_header*)skb->data;
struct cisco_packet *cisco_data;
struct in_device *in_dev;
@@ -220,11 +222,12 @@ static int cisco_rx(struct sk_buff *skb)
goto rx_error;
case CISCO_KEEPALIVE_REQ:
- state(hdlc)->rxseq = ntohl(cisco_data->par1);
- if (state(hdlc)->request_sent &&
- ntohl(cisco_data->par2) == state(hdlc)->txseq) {
- state(hdlc)->last_poll = jiffies;
- if (!state(hdlc)->up) {
+ spin_lock(&st->lock);
+ st->rxseq = ntohl(cisco_data->par1);
+ if (st->request_sent &&
+ ntohl(cisco_data->par2) == st->txseq) {
+ st->last_poll = jiffies;
+ if (!st->up) {
u32 sec, min, hrs, days;
sec = ntohl(cisco_data->time) / 1000;
min = sec / 60; sec -= min * 60;
@@ -232,12 +235,12 @@ static int cisco_rx(struct sk_buff *skb)
days = hrs / 24; hrs -= days * 24;
printk(KERN_INFO "%s: Link up (peer "
"uptime %ud%uh%um%us)\n",
- dev->name, days, hrs,
- min, sec);
+ dev->name, days, hrs, min, sec);
netif_dormant_off(dev);
- state(hdlc)->up = 1;
+ st->up = 1;
}
}
+ spin_unlock(&st->lock);
dev_kfree_skb_any(skb);
return NET_RX_SUCCESS;
@@ -261,24 +264,25 @@ static void cisco_timer(unsigned long arg)
{
struct net_device *dev = (struct net_device *)arg;
hdlc_device *hdlc = dev_to_hdlc(dev);
+ struct cisco_state *st = state(hdlc);
- if (state(hdlc)->up &&
- time_after(jiffies, state(hdlc)->last_poll +
- state(hdlc)->settings.timeout * HZ)) {
- state(hdlc)->up = 0;
+ spin_lock(&st->lock);
+ if (st->up &&
+ time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) {
+ st->up = 0;
printk(KERN_INFO "%s: Link down\n", dev->name);
netif_dormant_on(dev);
}
- cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
- htonl(++state(hdlc)->txseq),
- htonl(state(hdlc)->rxseq));
- state(hdlc)->request_sent = 1;
- state(hdlc)->timer.expires = jiffies +
- state(hdlc)->settings.interval * HZ;
- state(hdlc)->timer.function = cisco_timer;
- state(hdlc)->timer.data = arg;
- add_timer(&state(hdlc)->timer);
+ cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, htonl(++st->txseq),
+ htonl(st->rxseq));
+ st->request_sent = 1;
+ spin_unlock(&st->lock);
+
+ st->timer.expires = jiffies + st->settings.interval * HZ;
+ st->timer.function = cisco_timer;
+ st->timer.data = arg;
+ add_timer(&st->timer);
}
@@ -286,15 +290,20 @@ static void cisco_timer(unsigned long arg)
static void cisco_start(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
- state(hdlc)->up = 0;
- state(hdlc)->request_sent = 0;
- state(hdlc)->txseq = state(hdlc)->rxseq = 0;
-
- init_timer(&state(hdlc)->timer);
- state(hdlc)->timer.expires = jiffies + HZ; /*First poll after 1s*/
- state(hdlc)->timer.function = cisco_timer;
- state(hdlc)->timer.data = (unsigned long)dev;
- add_timer(&state(hdlc)->timer);
+ struct cisco_state *st = state(hdlc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&st->lock, flags);
+ st->up = 0;
+ st->request_sent = 0;
+ st->txseq = st->rxseq = 0;
+ spin_unlock_irqrestore(&st->lock, flags);
+
+ init_timer(&st->timer);
+ st->timer.expires = jiffies + HZ; /* First poll after 1 s */
+ st->timer.function = cisco_timer;
+ st->timer.data = (unsigned long)dev;
+ add_timer(&st->timer);
}
@@ -302,10 +311,16 @@ static void cisco_start(struct net_device *dev)
static void cisco_stop(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
- del_timer_sync(&state(hdlc)->timer);
+ struct cisco_state *st = state(hdlc);
+ unsigned long flags;
+
+ del_timer_sync(&st->timer);
+
+ spin_lock_irqsave(&st->lock, flags);
netif_dormant_on(dev);
- state(hdlc)->up = 0;
- state(hdlc)->request_sent = 0;
+ st->up = 0;
+ st->request_sent = 0;
+ spin_unlock_irqrestore(&st->lock, flags);
}
@@ -367,6 +382,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
return result;
memcpy(&state(hdlc)->settings, &new_settings, size);
+ spin_lock_init(&state(hdlc)->lock);
dev->hard_start_xmit = hdlc->xmit;
dev->header_ops = &cisco_header_ops;
dev->type = ARPHRD_CISCO;
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 520bb0b1a9a..6d35155c714 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -1008,6 +1008,7 @@ static int fr_rx(struct sk_buff *skb)
stats->rx_bytes += skb->len;
if (pvc->state.becn)
stats->rx_compressed++;
+ skb->dev = dev;
netif_rx(skb);
return NET_RX_SUCCESS;
} else {
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 249e18053d5..069f8bb0a99 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -32,6 +32,7 @@
#include <linux/x25.h>
#include <linux/lapb.h>
#include <linux/init.h>
+#include <linux/rtnetlink.h>
#include "x25_asy.h"
#include <net/x25device.h>
@@ -601,8 +602,10 @@ static void x25_asy_close_tty(struct tty_struct *tty)
if (!sl || sl->magic != X25_ASY_MAGIC)
return;
+ rtnl_lock();
if (sl->dev->flags & IFF_UP)
dev_close(sl->dev);
+ rtnl_unlock();
tty->disc_data = NULL;
sl->tty = NULL;