aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-02-22 04:10:18 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-02-26 14:42:59 -0500
commit269def7c505b4d229f9ad49bf88543d1e605533e (patch)
tree341377271f16c0def001a876217a8e6f430d75b4 /net/bridge
parentac062e84d0c177c43549e7fb608152fec218e7fc (diff)
[BRIDGE]: eliminate workqueue for carrier check
Having a work queue for checking carrier leads to lots of race issues. Simpler to just get the cost when data structure is created and update on change. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_if.c30
-rw-r--r--net/bridge/br_notify.c25
-rw-r--r--net/bridge/br_private.h4
3 files changed, 17 insertions, 42 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index aff6a779c9c8..6845a258408f 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -77,26 +77,15 @@ static int port_cost(struct net_device *dev)
77 * Called from work queue to allow for calling functions that 77 * Called from work queue to allow for calling functions that
78 * might sleep (such as speed check), and to debounce. 78 * might sleep (such as speed check), and to debounce.
79 */ 79 */
80static void port_carrier_check(struct work_struct *work) 80void br_port_carrier_check(struct net_bridge_port *p)
81{ 81{
82 struct net_bridge_port *p; 82 struct net_device *dev = p->dev;
83 struct net_device *dev; 83 struct net_bridge *br = p->br;
84 struct net_bridge *br;
85
86 dev = container_of(work, struct net_bridge_port,
87 carrier_check.work)->dev;
88 work_release(work);
89
90 rtnl_lock();
91 p = dev->br_port;
92 if (!p)
93 goto done;
94 br = p->br;
95 84
96 if (netif_carrier_ok(dev)) 85 if (netif_carrier_ok(dev))
97 p->path_cost = port_cost(dev); 86 p->path_cost = port_cost(dev);
98 87
99 if (br->dev->flags & IFF_UP) { 88 if (netif_running(br->dev)) {
100 spin_lock_bh(&br->lock); 89 spin_lock_bh(&br->lock);
101 if (netif_carrier_ok(dev)) { 90 if (netif_carrier_ok(dev)) {
102 if (p->state == BR_STATE_DISABLED) 91 if (p->state == BR_STATE_DISABLED)
@@ -107,9 +96,6 @@ static void port_carrier_check(struct work_struct *work)
107 } 96 }
108 spin_unlock_bh(&br->lock); 97 spin_unlock_bh(&br->lock);
109 } 98 }
110done:
111 dev_put(dev);
112 rtnl_unlock();
113} 99}
114 100
115static void release_nbp(struct kobject *kobj) 101static void release_nbp(struct kobject *kobj)
@@ -162,9 +148,6 @@ static void del_nbp(struct net_bridge_port *p)
162 148
163 dev_set_promiscuity(dev, -1); 149 dev_set_promiscuity(dev, -1);
164 150
165 if (cancel_delayed_work(&p->carrier_check))
166 dev_put(dev);
167
168 spin_lock_bh(&br->lock); 151 spin_lock_bh(&br->lock);
169 br_stp_disable_port(p); 152 br_stp_disable_port(p);
170 spin_unlock_bh(&br->lock); 153 spin_unlock_bh(&br->lock);
@@ -282,7 +265,6 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
282 p->port_no = index; 265 p->port_no = index;
283 br_init_port(p); 266 br_init_port(p);
284 p->state = BR_STATE_DISABLED; 267 p->state = BR_STATE_DISABLED;
285 INIT_DELAYED_WORK_NAR(&p->carrier_check, port_carrier_check);
286 br_stp_port_timer_init(p); 268 br_stp_port_timer_init(p);
287 269
288 kobject_init(&p->kobj); 270 kobject_init(&p->kobj);
@@ -446,12 +428,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
446 spin_lock_bh(&br->lock); 428 spin_lock_bh(&br->lock);
447 br_stp_recalculate_bridge_id(br); 429 br_stp_recalculate_bridge_id(br);
448 br_features_recompute(br); 430 br_features_recompute(br);
449 if (schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE))
450 dev_hold(dev);
451
452 spin_unlock_bh(&br->lock); 431 spin_unlock_bh(&br->lock);
453 432
454 dev_set_mtu(br->dev, br_min_mtu(br)); 433 dev_set_mtu(br->dev, br_min_mtu(br));
434
455 kobject_uevent(&p->kobj, KOBJ_ADD); 435 kobject_uevent(&p->kobj, KOBJ_ADD);
456 436
457 return 0; 437 return 0;
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 3311c4e30829..37357ed2149b 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -42,51 +42,48 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
42 42
43 br = p->br; 43 br = p->br;
44 44
45 spin_lock_bh(&br->lock);
46 switch (event) { 45 switch (event) {
47 case NETDEV_CHANGEMTU: 46 case NETDEV_CHANGEMTU:
48 dev_set_mtu(br->dev, br_min_mtu(br)); 47 dev_set_mtu(br->dev, br_min_mtu(br));
49 break; 48 break;
50 49
51 case NETDEV_CHANGEADDR: 50 case NETDEV_CHANGEADDR:
51 spin_lock_bh(&br->lock);
52 br_fdb_changeaddr(p, dev->dev_addr); 52 br_fdb_changeaddr(p, dev->dev_addr);
53 br_ifinfo_notify(RTM_NEWLINK, p); 53 br_ifinfo_notify(RTM_NEWLINK, p);
54 br_stp_recalculate_bridge_id(br); 54 br_stp_recalculate_bridge_id(br);
55 spin_unlock_bh(&br->lock);
55 break; 56 break;
56 57
57 case NETDEV_CHANGE: 58 case NETDEV_CHANGE:
58 if (br->dev->flags & IFF_UP) 59 br_port_carrier_check(p);
59 if (schedule_delayed_work(&p->carrier_check,
60 BR_PORT_DEBOUNCE))
61 dev_hold(dev);
62 break; 60 break;
63 61
64 case NETDEV_FEAT_CHANGE: 62 case NETDEV_FEAT_CHANGE:
65 if (br->dev->flags & IFF_UP) 63 spin_lock_bh(&br->lock);
64 if (netif_running(br->dev))
66 br_features_recompute(br); 65 br_features_recompute(br);
67 66 spin_unlock_bh(&br->lock);
68 /* could do recursive feature change notification
69 * but who would care??
70 */
71 break; 67 break;
72 68
73 case NETDEV_DOWN: 69 case NETDEV_DOWN:
70 spin_lock_bh(&br->lock);
74 if (br->dev->flags & IFF_UP) 71 if (br->dev->flags & IFF_UP)
75 br_stp_disable_port(p); 72 br_stp_disable_port(p);
73 spin_unlock_bh(&br->lock);
76 break; 74 break;
77 75
78 case NETDEV_UP: 76 case NETDEV_UP:
77 spin_lock_bh(&br->lock);
79 if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) 78 if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP))
80 br_stp_enable_port(p); 79 br_stp_enable_port(p);
80 spin_unlock_bh(&br->lock);
81 break; 81 break;
82 82
83 case NETDEV_UNREGISTER: 83 case NETDEV_UNREGISTER:
84 spin_unlock_bh(&br->lock);
85 br_del_if(br, dev); 84 br_del_if(br, dev);
86 goto done; 85 break;
87 } 86 }
88 spin_unlock_bh(&br->lock);
89 87
90 done:
91 return NOTIFY_DONE; 88 return NOTIFY_DONE;
92} 89}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 16fc47a821e5..cc3f1c99261a 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -26,8 +26,6 @@
26#define BR_PORT_BITS 10 26#define BR_PORT_BITS 10
27#define BR_MAX_PORTS (1<<BR_PORT_BITS) 27#define BR_MAX_PORTS (1<<BR_PORT_BITS)
28 28
29#define BR_PORT_DEBOUNCE (HZ/10)
30
31#define BR_VERSION "2.2" 29#define BR_VERSION "2.2"
32 30
33typedef struct bridge_id bridge_id; 31typedef struct bridge_id bridge_id;
@@ -81,7 +79,6 @@ struct net_bridge_port
81 struct timer_list hold_timer; 79 struct timer_list hold_timer;
82 struct timer_list message_age_timer; 80 struct timer_list message_age_timer;
83 struct kobject kobj; 81 struct kobject kobj;
84 struct delayed_work carrier_check;
85 struct rcu_head rcu; 82 struct rcu_head rcu;
86}; 83};
87 84
@@ -172,6 +169,7 @@ extern void br_flood_forward(struct net_bridge *br,
172 int clone); 169 int clone);
173 170
174/* br_if.c */ 171/* br_if.c */
172extern void br_port_carrier_check(struct net_bridge_port *p);
175extern int br_add_bridge(const char *name); 173extern int br_add_bridge(const char *name);
176extern int br_del_bridge(const char *name); 174extern int br_del_bridge(const char *name);
177extern void br_cleanup_bridges(void); 175extern void br_cleanup_bridges(void);