netifd: add devtype to ubus call
[project/netifd.git] / device.c
index c6b0b5f8de1b4a20279c44231ffecc45d942b419..b3d0e85f8550de45fbabeb8f17028ddf8af1573e 100644 (file)
--- a/device.c
+++ b/device.c
@@ -24,6 +24,7 @@
 #include "netifd.h"
 #include "system.h"
 #include "config.h"
+#include "wireless.h"
 
 static struct list_head devtypes = LIST_HEAD_INIT(devtypes);
 static struct avl_tree devices;
@@ -60,6 +61,8 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
        [DEV_ATTR_DROP_UNSOLICITED_NA] = { .name = "drop_unsolicited_na", .type = BLOBMSG_TYPE_BOOL },
        [DEV_ATTR_ARP_ACCEPT] = { .name = "arp_accept", .type = BLOBMSG_TYPE_BOOL },
        [DEV_ATTR_AUTH] = { .name = "auth", .type = BLOBMSG_TYPE_BOOL },
+       [DEV_ATTR_SPEED] = { .name = "speed", .type = BLOBMSG_TYPE_INT32 },
+       [DEV_ATTR_DUPLEX] = { .name = "duplex", .type = BLOBMSG_TYPE_BOOL },
 };
 
 const struct uci_blob_param_list device_attr_list = {
@@ -96,18 +99,6 @@ device_type_get(const char *tname)
        return NULL;
 }
 
-void device_lock(void)
-{
-       __devlock++;
-}
-
-void device_unlock(void)
-{
-       __devlock--;
-       if (!__devlock)
-               device_free_unused(NULL);
-}
-
 static int device_vlan_len(struct kvlist *kv, const void *data)
 {
        return sizeof(unsigned int);
@@ -136,6 +127,18 @@ void device_vlan_update(bool done)
        }
 }
 
+void device_stp_init(void)
+{
+       struct device *dev;
+
+       avl_for_each_element(&devices, dev, avl) {
+               if (!dev->type->stp_init)
+                       continue;
+
+               dev->type->stp_init(dev);
+       }
+}
+
 static int set_device_state(struct device *dev, bool state)
 {
        if (state) {
@@ -275,6 +278,8 @@ device_merge_settings(struct device *dev, struct device_settings *n)
        n->arp_accept = s->flags & DEV_OPT_ARP_ACCEPT ?
                s->arp_accept : os->arp_accept;
        n->auth = s->flags & DEV_OPT_AUTH ? s->auth : os->auth;
+       n->speed = s->flags & DEV_OPT_SPEED ? s->speed : os->speed;
+       n->duplex = s->flags & DEV_OPT_DUPLEX ? s->duplex : os->duplex;
        n->flags = s->flags | os->flags | os->valid_flags;
 }
 
@@ -449,6 +454,16 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
                s->flags |= DEV_OPT_AUTH;
        }
 
+       if ((cur = tb[DEV_ATTR_SPEED])) {
+               s->speed = blobmsg_get_u32(cur);
+               s->flags |= DEV_OPT_SPEED;
+       }
+
+       if ((cur = tb[DEV_ATTR_DUPLEX])) {
+               s->duplex = blobmsg_get_bool(cur);
+               s->flags |= DEV_OPT_DUPLEX;
+       }
+
        device_set_disabled(dev, disabled);
 }
 
@@ -868,14 +883,27 @@ device_free(struct device *dev)
 }
 
 static void
-__device_free_unused(struct device *dev)
+__device_free_unused(struct uloop_timeout *timeout)
 {
-       if (!safe_list_empty(&dev->users) ||
-               !safe_list_empty(&dev->aliases) ||
-           dev->current_config || __devlock)
-               return;
+       struct device *dev, *tmp;
+
+       avl_for_each_element_safe(&devices, dev, avl, tmp) {
+               if (!safe_list_empty(&dev->users) ||
+                       !safe_list_empty(&dev->aliases) ||
+                       dev->current_config)
+                       continue;
 
-       device_free(dev);
+               device_free(dev);
+       }
+}
+
+void device_free_unused(void)
+{
+       static struct uloop_timeout free_timer = {
+               .cb = __device_free_unused,
+       };
+
+       uloop_timeout_set(&free_timer, 1);
 }
 
 void device_remove_user(struct device_user *dep)
@@ -892,19 +920,7 @@ void device_remove_user(struct device_user *dep)
        safe_list_del(&dep->list);
        dep->dev = NULL;
        D(DEVICE, "Remove user for device '%s', refcount=%d\n", dev->ifname, device_refcount(dev));
-       __device_free_unused(dev);
-}
-
-void
-device_free_unused(struct device *dev)
-{
-       struct device *tmp;
-
-       if (dev)
-               return __device_free_unused(dev);
-
-       avl_for_each_element_safe(&devices, dev, avl, tmp)
-               __device_free_unused(dev);
+       device_free_unused();
 }
 
 void
@@ -1213,6 +1229,8 @@ void device_hotplug_event(const char *name, bool add)
 {
        struct device *dev;
 
+       wireless_device_hotplug_event(name, add);
+
        dev = device_find(name);
        if (!dev || dev->type != &simple_device_type)
                return;