aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_if.c77
-rw-r--r--net/bridge/br_private.h5
-rw-r--r--net/bridge/br_sysfs_if.c50
3 files changed, 59 insertions, 73 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 70b7ef917234..7fa3a5a9971f 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -106,6 +106,20 @@ done:
106 rtnl_unlock(); 106 rtnl_unlock();
107} 107}
108 108
109static void release_nbp(struct kobject *kobj)
110{
111 struct net_bridge_port *p
112 = container_of(kobj, struct net_bridge_port, kobj);
113 kfree(p);
114}
115
116static struct kobj_type brport_ktype = {
117#ifdef CONFIG_SYSFS
118 .sysfs_ops = &brport_sysfs_ops,
119#endif
120 .release = release_nbp,
121};
122
109static void destroy_nbp(struct net_bridge_port *p) 123static void destroy_nbp(struct net_bridge_port *p)
110{ 124{
111 struct net_device *dev = p->dev; 125 struct net_device *dev = p->dev;
@@ -114,7 +128,7 @@ static void destroy_nbp(struct net_bridge_port *p)
114 p->dev = NULL; 128 p->dev = NULL;
115 dev_put(dev); 129 dev_put(dev);
116 130
117 br_sysfs_freeif(p); 131 kobject_put(&p->kobj);
118} 132}
119 133
120static void destroy_nbp_rcu(struct rcu_head *head) 134static void destroy_nbp_rcu(struct rcu_head *head)
@@ -138,6 +152,8 @@ static void del_nbp(struct net_bridge_port *p)
138 struct net_bridge *br = p->br; 152 struct net_bridge *br = p->br;
139 struct net_device *dev = p->dev; 153 struct net_device *dev = p->dev;
140 154
155 sysfs_remove_link(&br->ifobj, dev->name);
156
141 dev_set_promiscuity(dev, -1); 157 dev_set_promiscuity(dev, -1);
142 158
143 cancel_delayed_work(&p->carrier_check); 159 cancel_delayed_work(&p->carrier_check);
@@ -152,6 +168,8 @@ static void del_nbp(struct net_bridge_port *p)
152 168
153 rcu_assign_pointer(dev->br_port, NULL); 169 rcu_assign_pointer(dev->br_port, NULL);
154 170
171 kobject_del(&p->kobj);
172
155 call_rcu(&p->rcu, destroy_nbp_rcu); 173 call_rcu(&p->rcu, destroy_nbp_rcu);
156} 174}
157 175
@@ -161,7 +179,6 @@ static void del_br(struct net_bridge *br)
161 struct net_bridge_port *p, *n; 179 struct net_bridge_port *p, *n;
162 180
163 list_for_each_entry_safe(p, n, &br->port_list, list) { 181 list_for_each_entry_safe(p, n, &br->port_list, list) {
164 br_sysfs_removeif(p);
165 del_nbp(p); 182 del_nbp(p);
166 } 183 }
167 184
@@ -261,6 +278,11 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
261 INIT_WORK(&p->carrier_check, port_carrier_check, dev); 278 INIT_WORK(&p->carrier_check, port_carrier_check, dev);
262 kobject_init(&p->kobj); 279 kobject_init(&p->kobj);
263 280
281 kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
282 p->kobj.ktype = &brport_ktype;
283 p->kobj.parent = &(dev->class_dev.kobj);
284 p->kobj.kset = NULL;
285
264 return p; 286 return p;
265} 287}
266 288
@@ -388,31 +410,43 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
388 if (dev->br_port != NULL) 410 if (dev->br_port != NULL)
389 return -EBUSY; 411 return -EBUSY;
390 412
391 if (IS_ERR(p = new_nbp(br, dev))) 413 p = new_nbp(br, dev);
414 if (IS_ERR(p))
392 return PTR_ERR(p); 415 return PTR_ERR(p);
393 416
394 if ((err = br_fdb_insert(br, p, dev->dev_addr))) 417 err = kobject_add(&p->kobj);
395 destroy_nbp(p); 418 if (err)
396 419 goto err0;
397 else if ((err = br_sysfs_addif(p)))
398 del_nbp(p);
399 else {
400 rcu_assign_pointer(dev->br_port, p);
401 dev_set_promiscuity(dev, 1);
402 420
403 list_add_rcu(&p->list, &br->port_list); 421 err = br_fdb_insert(br, p, dev->dev_addr);
422 if (err)
423 goto err1;
404 424
405 spin_lock_bh(&br->lock); 425 err = br_sysfs_addif(p);
406 br_stp_recalculate_bridge_id(br); 426 if (err)
407 br_features_recompute(br); 427 goto err2;
408 if ((br->dev->flags & IFF_UP)
409 && (dev->flags & IFF_UP) && netif_carrier_ok(dev))
410 br_stp_enable_port(p);
411 spin_unlock_bh(&br->lock);
412 428
413 dev_set_mtu(br->dev, br_min_mtu(br)); 429 rcu_assign_pointer(dev->br_port, p);
414 } 430 dev_set_promiscuity(dev, 1);
431
432 list_add_rcu(&p->list, &br->port_list);
433
434 spin_lock_bh(&br->lock);
435 br_stp_recalculate_bridge_id(br);
436 br_features_recompute(br);
437 schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
438 spin_unlock_bh(&br->lock);
439
440 dev_set_mtu(br->dev, br_min_mtu(br));
441 kobject_uevent(&p->kobj, KOBJ_ADD);
415 442
443 return 0;
444err2:
445 br_fdb_delete_by_port(br, p);
446err1:
447 kobject_del(&p->kobj);
448err0:
449 kobject_put(&p->kobj);
416 return err; 450 return err;
417} 451}
418 452
@@ -424,7 +458,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
424 if (!p || p->br != br) 458 if (!p || p->br != br)
425 return -EINVAL; 459 return -EINVAL;
426 460
427 br_sysfs_removeif(p);
428 del_nbp(p); 461 del_nbp(p);
429 462
430 spin_lock_bh(&br->lock); 463 spin_lock_bh(&br->lock);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index c5bd631ffcd5..8f10e09f251b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -232,9 +232,8 @@ extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
232 232
233#ifdef CONFIG_SYSFS 233#ifdef CONFIG_SYSFS
234/* br_sysfs_if.c */ 234/* br_sysfs_if.c */
235extern struct sysfs_ops brport_sysfs_ops;
235extern int br_sysfs_addif(struct net_bridge_port *p); 236extern int br_sysfs_addif(struct net_bridge_port *p);
236extern void br_sysfs_removeif(struct net_bridge_port *p);
237extern void br_sysfs_freeif(struct net_bridge_port *p);
238 237
239/* br_sysfs_br.c */ 238/* br_sysfs_br.c */
240extern int br_sysfs_addbr(struct net_device *dev); 239extern int br_sysfs_addbr(struct net_device *dev);
@@ -243,8 +242,6 @@ extern void br_sysfs_delbr(struct net_device *dev);
243#else 242#else
244 243
245#define br_sysfs_addif(p) (0) 244#define br_sysfs_addif(p) (0)
246#define br_sysfs_removeif(p) do { } while(0)
247#define br_sysfs_freeif(p) kfree(p)
248#define br_sysfs_addbr(dev) (0) 245#define br_sysfs_addbr(dev) (0)
249#define br_sysfs_delbr(dev) do { } while(0) 246#define br_sysfs_delbr(dev) do { } while(0)
250#endif /* CONFIG_SYSFS */ 247#endif /* CONFIG_SYSFS */
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 0ac0355d16dd..c51c9e42aeb3 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -195,23 +195,11 @@ static ssize_t brport_store(struct kobject * kobj,
195 return ret; 195 return ret;
196} 196}
197 197
198/* called from kobject_put when port ref count goes to zero. */ 198struct sysfs_ops brport_sysfs_ops = {
199static void brport_release(struct kobject *kobj)
200{
201 kfree(container_of(kobj, struct net_bridge_port, kobj));
202}
203
204static struct sysfs_ops brport_sysfs_ops = {
205 .show = brport_show, 199 .show = brport_show,
206 .store = brport_store, 200 .store = brport_store,
207}; 201};
208 202
209static struct kobj_type brport_ktype = {
210 .sysfs_ops = &brport_sysfs_ops,
211 .release = brport_release,
212};
213
214
215/* 203/*
216 * Add sysfs entries to ethernet device added to a bridge. 204 * Add sysfs entries to ethernet device added to a bridge.
217 * Creates a brport subdirectory with bridge attributes. 205 * Creates a brport subdirectory with bridge attributes.
@@ -223,17 +211,6 @@ int br_sysfs_addif(struct net_bridge_port *p)
223 struct brport_attribute **a; 211 struct brport_attribute **a;
224 int err; 212 int err;
225 213
226 ASSERT_RTNL();
227
228 kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
229 p->kobj.ktype = &brport_ktype;
230 p->kobj.parent = &(p->dev->class_dev.kobj);
231 p->kobj.kset = NULL;
232
233 err = kobject_add(&p->kobj);
234 if(err)
235 goto out1;
236
237 err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, 214 err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj,
238 SYSFS_BRIDGE_PORT_LINK); 215 SYSFS_BRIDGE_PORT_LINK);
239 if (err) 216 if (err)
@@ -245,28 +222,7 @@ int br_sysfs_addif(struct net_bridge_port *p)
245 goto out2; 222 goto out2;
246 } 223 }
247 224
248 err = sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name); 225 err= sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name);
249 if (err) 226out2:
250 goto out2;
251
252 kobject_uevent(&p->kobj, KOBJ_ADD);
253 return 0;
254 out2:
255 kobject_del(&p->kobj);
256 out1:
257 return err; 227 return err;
258} 228}
259
260void br_sysfs_removeif(struct net_bridge_port *p)
261{
262 pr_debug("br_sysfs_removeif\n");
263 sysfs_remove_link(&p->br->ifobj, p->dev->name);
264 kobject_uevent(&p->kobj, KOBJ_REMOVE);
265 kobject_del(&p->kobj);
266}
267
268void br_sysfs_freeif(struct net_bridge_port *p)
269{
270 pr_debug("br_sysfs_freeif\n");
271 kobject_put(&p->kobj);
272}