#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;
[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 = {
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);
}
}
+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) {
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;
}
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);
}
}
struct device *
-device_get(const char *name, int create)
+__device_get(const char *name, int create, bool check_vlan)
{
struct device *dev;
dev = avl_find_element(&devices, name, dev, avl);
- if (!dev && strchr(name, '.'))
+ if (!dev && check_vlan && strchr(name, '.'))
return get_vlan_device_chain(name, create);
if (name[0] == '@')
}
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)
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
{
struct device *dev;
+ wireless_device_hotplug_event(name, add);
+
dev = device_find(name);
if (!dev || dev->type != &simple_device_type)
return;