diff options
author | Felix Fietkau <nbd@openwrt.org> | 2012-10-19 15:49:46 +0200 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2012-10-19 15:49:46 +0200 |
commit | a9fd870450e82f31cba681651656276dfc1c39ac (patch) | |
tree | ce680992d8a466a7610021c4bcd42c9431db9bf0 | |
parent | 8125e561e33276cf80c5146c5fa3020b6f1425b8 (diff) |
bridge: toggle device present state after freeing a bridge member to ensure that it can be reassigned to a different bridge
-rw-r--r-- | bridge.c | 27 |
1 files changed, 24 insertions, 3 deletions
@@ -189,6 +189,29 @@ bridge_remove_member(struct bridge_member *bm) } static void +bridge_free_member(struct bridge_member *bm) +{ + struct device *dev = bm->dev.dev; + + bridge_remove_member(bm); + device_remove_user(&bm->dev); + + /* + * When reloading the config and moving a device from one bridge to + * another, the other bridge may have tried to claim this device + * before it was removed here. + * Ensure that claiming the device is retried by toggling its present + * state + */ + if (dev->present) { + device_set_present(dev, false); + device_set_present(dev, true); + } + + free(bm); +} + +static void bridge_member_cb(struct device_user *dev, enum device_event ev) { struct bridge_member *bm = container_of(dev, struct bridge_member, dev); @@ -323,9 +346,7 @@ bridge_member_update(struct vlist_tree *tree, struct vlist_node *node_new, if (node_old) { bm = container_of(node_old, struct bridge_member, node); - bridge_remove_member(bm); - device_remove_user(&bm->dev); - free(bm); + bridge_free_member(bm); } } |