return 0;
system_bridge_delif(&bst->dev, bm->dev.dev);
- device_release(bm->dev.dev);
+ device_release(&bm->dev);
return 0;
}
if (!bm->present)
return 0;
- ret = device_claim(bm->dev.dev);
+ ret = device_claim(&bm->dev);
if (ret < 0)
goto error;
return 0;
}
-int device_claim(struct device *dev)
+int device_claim(struct device_user *dep)
{
+ struct device *dev = dep->dev;
int ret;
+ if (dep->claimed)
+ return 0;
+
+ dep->claimed = true;
DPRINTF("claim device %s, new refcount: %d\n", dev->ifname, dev->active + 1);
if (++dev->active != 1)
return 0;
return ret;
}
-void device_release(struct device *dev)
+void device_release(struct device_user *dep)
{
+ struct device *dev = dep->dev;
+
+ if (!dep->claimed)
+ return;
+
+ dep->claimed = false;
dev->active--;
DPRINTF("release device %s, new refcount: %d\n", dev->ifname, dev->active);
assert(dev->active >= 0);
{
struct device *dev = dep->dev;
+ if (dep->claimed)
+ device_release(dep);
+
list_del(&dep->list);
if (list_empty(&dev->users)) {
struct device_user {
struct list_head list;
+ bool claimed;
struct device *dev;
void (*cb)(struct device_user *, enum device_event);
};
void device_remove_user(struct device_user *dep);
void device_set_present(struct device *dev, bool state);
-int device_claim(struct device *dev);
-void device_release(struct device *dev);
+int device_claim(struct device_user *dep);
+void device_release(struct device_user *dep);
int check_device_state(struct device *dev);
static inline void
mark_interface_down(struct interface *iface)
{
interface_del_ctx_addr(iface, NULL);
- device_release(iface->main_dev.dev);
+ device_release(&iface->main_dev);
iface->state = IFS_DOWN;
}
if (iface->state != IFS_DOWN)
return 0;
- ret = device_claim(iface->main_dev.dev);
+ ret = device_claim(&iface->main_dev);
if (ret)
return ret;
if (!up) {
vldev->set_state(dev, false);
system_vlan_del(dev);
- device_release(vldev->dep.dev);
+ device_release(&vldev->dep);
return 0;
}
- ret = device_claim(vldev->dep.dev);
+ ret = device_claim(&vldev->dep);
if (ret)
return ret;
system_vlan_add(vldev->dep.dev, vldev->id);
ret = vldev->set_state(dev, true);
if (ret)
- device_release(vldev->dep.dev);
+ device_release(&vldev->dep);
return ret;
}