diff options
-rw-r--r-- | net/bridge/br_if.c | 77 | ||||
-rw-r--r-- | net/bridge/br_private.h | 5 | ||||
-rw-r--r-- | net/bridge/br_sysfs_if.c | 50 |
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 | ||
109 | static 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 | |||
116 | static struct kobj_type brport_ktype = { | ||
117 | #ifdef CONFIG_SYSFS | ||
118 | .sysfs_ops = &brport_sysfs_ops, | ||
119 | #endif | ||
120 | .release = release_nbp, | ||
121 | }; | ||
122 | |||
109 | static void destroy_nbp(struct net_bridge_port *p) | 123 | static 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 | ||
120 | static void destroy_nbp_rcu(struct rcu_head *head) | 134 | static 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; | ||
444 | err2: | ||
445 | br_fdb_delete_by_port(br, p); | ||
446 | err1: | ||
447 | kobject_del(&p->kobj); | ||
448 | err0: | ||
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 */ |
235 | extern struct sysfs_ops brport_sysfs_ops; | ||
235 | extern int br_sysfs_addif(struct net_bridge_port *p); | 236 | extern int br_sysfs_addif(struct net_bridge_port *p); |
236 | extern void br_sysfs_removeif(struct net_bridge_port *p); | ||
237 | extern void br_sysfs_freeif(struct net_bridge_port *p); | ||
238 | 237 | ||
239 | /* br_sysfs_br.c */ | 238 | /* br_sysfs_br.c */ |
240 | extern int br_sysfs_addbr(struct net_device *dev); | 239 | extern 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. */ | 198 | struct sysfs_ops brport_sysfs_ops = { |
199 | static void brport_release(struct kobject *kobj) | ||
200 | { | ||
201 | kfree(container_of(kobj, struct net_bridge_port, kobj)); | ||
202 | } | ||
203 | |||
204 | static 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 | ||
209 | static 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) | 226 | out2: |
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 | |||
260 | void 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 | |||
268 | void br_sysfs_freeif(struct net_bridge_port *p) | ||
269 | { | ||
270 | pr_debug("br_sysfs_freeif\n"); | ||
271 | kobject_put(&p->kobj); | ||
272 | } | ||