diff options
| author | David S. Miller <davem@davemloft.net> | 2008-05-23 03:05:14 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-05-23 03:05:14 -0400 |
| commit | 7bece8155be133cd67c41eed2b31c60a310609de (patch) | |
| tree | 906a62dcf10c1f2e6c1188a2b6e386668fcd9fe3 /drivers/net/wan | |
| parent | b9a2f2e450b0f770bb4347ae8d48eb2dea701e24 (diff) | |
| parent | bdefff1f54cb76a19700663f211350de2f65cc91 (diff) | |
Merge branch 'upstream-davem' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
Diffstat (limited to 'drivers/net/wan')
| -rw-r--r-- | drivers/net/wan/hdlc.c | 19 | ||||
| -rw-r--r-- | drivers/net/wan/hdlc_cisco.c | 82 |
2 files changed, 60 insertions, 41 deletions
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index 9a83c9d5b8cf..7f984895b0d5 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"; | |||
| 43 | 43 | ||
| 44 | #undef DEBUG_LINK | 44 | #undef DEBUG_LINK |
| 45 | 45 | ||
| 46 | static struct hdlc_proto *first_proto = NULL; | 46 | static struct hdlc_proto *first_proto; |
| 47 | |||
| 48 | 47 | ||
| 49 | static int hdlc_change_mtu(struct net_device *dev, int new_mtu) | 48 | static int hdlc_change_mtu(struct net_device *dev, int new_mtu) |
| 50 | { | 49 | { |
| @@ -314,21 +313,25 @@ void detach_hdlc_protocol(struct net_device *dev) | |||
| 314 | 313 | ||
| 315 | void register_hdlc_protocol(struct hdlc_proto *proto) | 314 | void register_hdlc_protocol(struct hdlc_proto *proto) |
| 316 | { | 315 | { |
| 316 | rtnl_lock(); | ||
| 317 | proto->next = first_proto; | 317 | proto->next = first_proto; |
| 318 | first_proto = proto; | 318 | first_proto = proto; |
| 319 | rtnl_unlock(); | ||
| 319 | } | 320 | } |
| 320 | 321 | ||
| 321 | 322 | ||
| 322 | void unregister_hdlc_protocol(struct hdlc_proto *proto) | 323 | void unregister_hdlc_protocol(struct hdlc_proto *proto) |
| 323 | { | 324 | { |
| 324 | struct hdlc_proto **p = &first_proto; | 325 | struct hdlc_proto **p; |
| 325 | while (*p) { | 326 | |
| 326 | if (*p == proto) { | 327 | rtnl_lock(); |
| 327 | *p = proto->next; | 328 | p = &first_proto; |
| 328 | return; | 329 | while (*p != proto) { |
| 329 | } | 330 | BUG_ON(!*p); |
| 330 | p = &((*p)->next); | 331 | p = &((*p)->next); |
| 331 | } | 332 | } |
| 333 | *p = proto->next; | ||
| 334 | rtnl_unlock(); | ||
| 332 | } | 335 | } |
| 333 | 336 | ||
| 334 | 337 | ||
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 7133c688cf20..762d21c1c703 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c | |||
| @@ -56,6 +56,7 @@ struct cisco_state { | |||
| 56 | cisco_proto settings; | 56 | cisco_proto settings; |
| 57 | 57 | ||
| 58 | struct timer_list timer; | 58 | struct timer_list timer; |
| 59 | spinlock_t lock; | ||
| 59 | unsigned long last_poll; | 60 | unsigned long last_poll; |
| 60 | int up; | 61 | int up; |
| 61 | int request_sent; | 62 | int request_sent; |
| @@ -158,6 +159,7 @@ static int cisco_rx(struct sk_buff *skb) | |||
| 158 | { | 159 | { |
| 159 | struct net_device *dev = skb->dev; | 160 | struct net_device *dev = skb->dev; |
| 160 | hdlc_device *hdlc = dev_to_hdlc(dev); | 161 | hdlc_device *hdlc = dev_to_hdlc(dev); |
| 162 | struct cisco_state *st = state(hdlc); | ||
| 161 | struct hdlc_header *data = (struct hdlc_header*)skb->data; | 163 | struct hdlc_header *data = (struct hdlc_header*)skb->data; |
| 162 | struct cisco_packet *cisco_data; | 164 | struct cisco_packet *cisco_data; |
| 163 | struct in_device *in_dev; | 165 | struct in_device *in_dev; |
| @@ -220,11 +222,12 @@ static int cisco_rx(struct sk_buff *skb) | |||
| 220 | goto rx_error; | 222 | goto rx_error; |
| 221 | 223 | ||
| 222 | case CISCO_KEEPALIVE_REQ: | 224 | case CISCO_KEEPALIVE_REQ: |
| 223 | state(hdlc)->rxseq = ntohl(cisco_data->par1); | 225 | spin_lock(&st->lock); |
| 224 | if (state(hdlc)->request_sent && | 226 | st->rxseq = ntohl(cisco_data->par1); |
| 225 | ntohl(cisco_data->par2) == state(hdlc)->txseq) { | 227 | if (st->request_sent && |
| 226 | state(hdlc)->last_poll = jiffies; | 228 | ntohl(cisco_data->par2) == st->txseq) { |
| 227 | if (!state(hdlc)->up) { | 229 | st->last_poll = jiffies; |
| 230 | if (!st->up) { | ||
| 228 | u32 sec, min, hrs, days; | 231 | u32 sec, min, hrs, days; |
| 229 | sec = ntohl(cisco_data->time) / 1000; | 232 | sec = ntohl(cisco_data->time) / 1000; |
| 230 | min = sec / 60; sec -= min * 60; | 233 | min = sec / 60; sec -= min * 60; |
| @@ -232,12 +235,12 @@ static int cisco_rx(struct sk_buff *skb) | |||
| 232 | days = hrs / 24; hrs -= days * 24; | 235 | days = hrs / 24; hrs -= days * 24; |
| 233 | printk(KERN_INFO "%s: Link up (peer " | 236 | printk(KERN_INFO "%s: Link up (peer " |
| 234 | "uptime %ud%uh%um%us)\n", | 237 | "uptime %ud%uh%um%us)\n", |
| 235 | dev->name, days, hrs, | 238 | dev->name, days, hrs, min, sec); |
| 236 | min, sec); | ||
| 237 | netif_dormant_off(dev); | 239 | netif_dormant_off(dev); |
| 238 | state(hdlc)->up = 1; | 240 | st->up = 1; |
| 239 | } | 241 | } |
| 240 | } | 242 | } |
| 243 | spin_unlock(&st->lock); | ||
| 241 | 244 | ||
| 242 | dev_kfree_skb_any(skb); | 245 | dev_kfree_skb_any(skb); |
| 243 | return NET_RX_SUCCESS; | 246 | return NET_RX_SUCCESS; |
| @@ -261,24 +264,25 @@ static void cisco_timer(unsigned long arg) | |||
| 261 | { | 264 | { |
| 262 | struct net_device *dev = (struct net_device *)arg; | 265 | struct net_device *dev = (struct net_device *)arg; |
| 263 | hdlc_device *hdlc = dev_to_hdlc(dev); | 266 | hdlc_device *hdlc = dev_to_hdlc(dev); |
| 267 | struct cisco_state *st = state(hdlc); | ||
| 264 | 268 | ||
| 265 | if (state(hdlc)->up && | 269 | spin_lock(&st->lock); |
| 266 | time_after(jiffies, state(hdlc)->last_poll + | 270 | if (st->up && |
| 267 | state(hdlc)->settings.timeout * HZ)) { | 271 | time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) { |
| 268 | state(hdlc)->up = 0; | 272 | st->up = 0; |
| 269 | printk(KERN_INFO "%s: Link down\n", dev->name); | 273 | printk(KERN_INFO "%s: Link down\n", dev->name); |
| 270 | netif_dormant_on(dev); | 274 | netif_dormant_on(dev); |
| 271 | } | 275 | } |
| 272 | 276 | ||
| 273 | cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, | 277 | cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, htonl(++st->txseq), |
| 274 | htonl(++state(hdlc)->txseq), | 278 | htonl(st->rxseq)); |
| 275 | htonl(state(hdlc)->rxseq)); | 279 | st->request_sent = 1; |
| 276 | state(hdlc)->request_sent = 1; | 280 | spin_unlock(&st->lock); |
| 277 | state(hdlc)->timer.expires = jiffies + | 281 | |
| 278 | state(hdlc)->settings.interval * HZ; | 282 | st->timer.expires = jiffies + st->settings.interval * HZ; |
| 279 | state(hdlc)->timer.function = cisco_timer; | 283 | st->timer.function = cisco_timer; |
| 280 | state(hdlc)->timer.data = arg; | 284 | st->timer.data = arg; |
| 281 | add_timer(&state(hdlc)->timer); | 285 | add_timer(&st->timer); |
| 282 | } | 286 | } |
| 283 | 287 | ||
| 284 | 288 | ||
| @@ -286,15 +290,20 @@ static void cisco_timer(unsigned long arg) | |||
| 286 | static void cisco_start(struct net_device *dev) | 290 | static void cisco_start(struct net_device *dev) |
| 287 | { | 291 | { |
| 288 | hdlc_device *hdlc = dev_to_hdlc(dev); | 292 | hdlc_device *hdlc = dev_to_hdlc(dev); |
| 289 | state(hdlc)->up = 0; | 293 | struct cisco_state *st = state(hdlc); |
| 290 | state(hdlc)->request_sent = 0; | 294 | unsigned long flags; |
| 291 | state(hdlc)->txseq = state(hdlc)->rxseq = 0; | 295 | |
| 292 | 296 | spin_lock_irqsave(&st->lock, flags); | |
| 293 | init_timer(&state(hdlc)->timer); | 297 | st->up = 0; |
| 294 | state(hdlc)->timer.expires = jiffies + HZ; /*First poll after 1s*/ | 298 | st->request_sent = 0; |
| 295 | state(hdlc)->timer.function = cisco_timer; | 299 | st->txseq = st->rxseq = 0; |
| 296 | state(hdlc)->timer.data = (unsigned long)dev; | 300 | spin_unlock_irqrestore(&st->lock, flags); |
| 297 | add_timer(&state(hdlc)->timer); | 301 | |
| 302 | init_timer(&st->timer); | ||
| 303 | st->timer.expires = jiffies + HZ; /* First poll after 1 s */ | ||
| 304 | st->timer.function = cisco_timer; | ||
| 305 | st->timer.data = (unsigned long)dev; | ||
| 306 | add_timer(&st->timer); | ||
| 298 | } | 307 | } |
| 299 | 308 | ||
| 300 | 309 | ||
| @@ -302,10 +311,16 @@ static void cisco_start(struct net_device *dev) | |||
| 302 | static void cisco_stop(struct net_device *dev) | 311 | static void cisco_stop(struct net_device *dev) |
| 303 | { | 312 | { |
| 304 | hdlc_device *hdlc = dev_to_hdlc(dev); | 313 | hdlc_device *hdlc = dev_to_hdlc(dev); |
| 305 | del_timer_sync(&state(hdlc)->timer); | 314 | struct cisco_state *st = state(hdlc); |
| 315 | unsigned long flags; | ||
| 316 | |||
| 317 | del_timer_sync(&st->timer); | ||
| 318 | |||
| 319 | spin_lock_irqsave(&st->lock, flags); | ||
| 306 | netif_dormant_on(dev); | 320 | netif_dormant_on(dev); |
| 307 | state(hdlc)->up = 0; | 321 | st->up = 0; |
| 308 | state(hdlc)->request_sent = 0; | 322 | st->request_sent = 0; |
| 323 | spin_unlock_irqrestore(&st->lock, flags); | ||
| 309 | } | 324 | } |
| 310 | 325 | ||
| 311 | 326 | ||
| @@ -367,6 +382,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
| 367 | return result; | 382 | return result; |
| 368 | 383 | ||
| 369 | memcpy(&state(hdlc)->settings, &new_settings, size); | 384 | memcpy(&state(hdlc)->settings, &new_settings, size); |
| 385 | spin_lock_init(&state(hdlc)->lock); | ||
| 370 | dev->hard_start_xmit = hdlc->xmit; | 386 | dev->hard_start_xmit = hdlc->xmit; |
| 371 | dev->header_ops = &cisco_header_ops; | 387 | dev->header_ops = &cisco_header_ops; |
| 372 | dev->type = ARPHRD_CISCO; | 388 | dev->type = ARPHRD_CISCO; |
