Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 55951
b: refs/heads/master
c: 572a103
h: refs/heads/master
i:
  55949: a87dc6f
  55947: 11e4d7a
  55943: 63010f4
  55935: a0b3bc3
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed May 11, 2007
1 parent 7d76621 commit 2957ed7
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 36 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c33be3c362f1bc98f6e2d731a274ef138ae80741
refs/heads/master: 572a103ded0ad880f75ce83e99f0512fbb80b5b0
2 changes: 2 additions & 0 deletions trunk/include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,8 @@ struct net_device
/* device index hash chain */
struct hlist_node index_hlist;

struct net_device *link_watch_next;

/* register/unregister state machine */
enum { NETREG_UNINITIALIZED=0,
NETREG_REGISTERED, /* completed register_netdevice */
Expand Down
50 changes: 15 additions & 35 deletions trunk/net/core/link_watch.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <linux/rtnetlink.h>
#include <linux/jiffies.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
Expand All @@ -28,7 +27,6 @@

enum lw_bits {
LW_RUNNING = 0,
LW_SE_USED
};

static unsigned long linkwatch_flags;
Expand All @@ -37,17 +35,9 @@ static unsigned long linkwatch_nextevent;
static void linkwatch_event(struct work_struct *dummy);
static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);

static LIST_HEAD(lweventlist);
static struct net_device *lweventlist;
static DEFINE_SPINLOCK(lweventlist_lock);

struct lw_event {
struct list_head list;
struct net_device *dev;
};

/* Avoid kmalloc() for most systems */
static struct lw_event singleevent;

static unsigned char default_operstate(const struct net_device *dev)
{
if (!netif_carrier_ok(dev))
Expand Down Expand Up @@ -90,21 +80,23 @@ static void rfc2863_policy(struct net_device *dev)
/* Must be called with the rtnl semaphore held */
void linkwatch_run_queue(void)
{
struct list_head head, *n, *next;
struct net_device *next;

spin_lock_irq(&lweventlist_lock);
list_replace_init(&lweventlist, &head);
next = lweventlist;
lweventlist = NULL;
spin_unlock_irq(&lweventlist_lock);

list_for_each_safe(n, next, &head) {
struct lw_event *event = list_entry(n, struct lw_event, list);
struct net_device *dev = event->dev;
while (next) {
struct net_device *dev = next;

if (event == &singleevent) {
clear_bit(LW_SE_USED, &linkwatch_flags);
} else {
kfree(event);
}
next = dev->link_watch_next;

/*
* Make sure the above read is complete since it can be
* rewritten as soon as we clear the bit below.
*/
smp_mb__before_clear_bit();

/* We are about to handle this device,
* so new events can be accepted
Expand Down Expand Up @@ -147,24 +139,12 @@ void linkwatch_fire_event(struct net_device *dev)
{
if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
unsigned long flags;
struct lw_event *event;

if (test_and_set_bit(LW_SE_USED, &linkwatch_flags)) {
event = kmalloc(sizeof(struct lw_event), GFP_ATOMIC);

if (unlikely(event == NULL)) {
clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
return;
}
} else {
event = &singleevent;
}

dev_hold(dev);
event->dev = dev;

spin_lock_irqsave(&lweventlist_lock, flags);
list_add_tail(&event->list, &lweventlist);
dev->link_watch_next = lweventlist;
lweventlist = dev;
spin_unlock_irqrestore(&lweventlist_lock, flags);

if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) {
Expand Down

0 comments on commit 2957ed7

Please sign in to comment.