From 5844d3caa26f5f8810476836a8b711107e4ba8d7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 24 Jul 2014 11:12:48 +0200 Subject: [PATCH] interface: fix restart after reload with external devices When an interface goes down, the main_dev is reset to NULL. Track an externally added device separately to be able to bring it back up. Signed-off-by: Felix Fietkau --- interface.c | 16 ++++++++++++++++ interface.h | 1 + 2 files changed, 17 insertions(+) diff --git a/interface.c b/interface.c index 4c92f10..e66b58a 100644 --- a/interface.c +++ b/interface.c @@ -307,6 +307,13 @@ interface_set_link_state(struct interface *iface, bool new_state) interface_check_state(iface); } +static void +interface_ext_cb(struct device_user *dep, enum device_event ev) +{ + if (ev == DEV_EVENT_REMOVE) + device_remove_user(dep); +} + static void interface_cb(struct device_user *dep, enum device_event ev) { @@ -491,6 +498,8 @@ interface_claim_device(struct interface *iface) } else if (iface->ifname && !(iface->proto_handler->flags & PROTO_FLAG_NODEV)) { dev = device_get(iface->ifname, true); + } else { + dev = iface->ext_dev.dev; } if (dev) @@ -518,6 +527,8 @@ interface_cleanup(struct interface *iface) { struct interface_user *dep, *tmp; + device_remove_user(&iface->ext_dev); + if (iface->parent_iface.iface) interface_remove_user(&iface->parent_iface); @@ -653,6 +664,7 @@ interface_alloc(const char *name, struct blob_attr *config) iface->config_ip.enabled = false; iface->main_dev.cb = interface_cb; + iface->ext_dev.cb = interface_ext_cb; blobmsg_parse(iface_attrs, IFACE_ATTR_MAX, tb, blob_data(config), blob_len(config)); @@ -807,6 +819,9 @@ interface_remove_link(struct interface *iface, struct device *dev) if (mdev && mdev->hotplug_ops) return mdev->hotplug_ops->del(mdev, dev); + if (dev == iface->ext_dev.dev) + device_remove_user(&iface->ext_dev); + if (!iface->main_dev.hotplug) return UBUS_STATUS_INVALID_ARGUMENT; @@ -835,6 +850,7 @@ interface_add_link(struct interface *iface, struct device *dev) return UBUS_STATUS_NOT_SUPPORTED; } + device_add_user(&iface->ext_dev, dev); interface_set_main_dev(iface, dev); iface->main_dev.hotplug = true; return 0; diff --git a/interface.h b/interface.h index 6cfe264..1cd7e96 100644 --- a/interface.h +++ b/interface.h @@ -119,6 +119,7 @@ struct interface { /* main interface that the interface is bound to */ struct device_user main_dev; + struct device_user ext_dev; /* interface that layer 3 communication will go through */ struct device_user l3_dev; -- 2.25.1