make device_claim/device_release operate on the device_user instead of the device...
authorFelix Fietkau <nbd@openwrt.org>
Sun, 4 Sep 2011 13:00:25 +0000 (15:00 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 4 Sep 2011 13:00:25 +0000 (15:00 +0200)
bridge.c
device.c
device.h
interface.c
vlan.c

index 3f8739c..c48381b 100644 (file)
--- a/bridge.c
+++ b/bridge.c
@@ -72,7 +72,7 @@ bridge_disable_member(struct bridge_member *bm)
                return 0;
 
        system_bridge_delif(&bst->dev, bm->dev.dev);
-       device_release(bm->dev.dev);
+       device_release(&bm->dev);
 
        return 0;
 }
@@ -86,7 +86,7 @@ bridge_enable_member(struct bridge_member *bm)
        if (!bm->present)
                return 0;
 
-       ret = device_claim(bm->dev.dev);
+       ret = device_claim(&bm->dev);
        if (ret < 0)
                goto error;
 
index 0019b6c..c02335c 100644 (file)
--- a/device.c
+++ b/device.c
@@ -120,10 +120,15 @@ static int set_device_state(struct device *dev, bool state)
        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;
@@ -138,8 +143,14 @@ int device_claim(struct device *dev)
        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);
@@ -254,6 +265,9 @@ void device_remove_user(struct device_user *dep)
 {
        struct device *dev = dep->dev;
 
+       if (dep->claimed)
+               device_release(dep);
+
        list_del(&dep->list);
 
        if (list_empty(&dev->users)) {
index e11df1f..63ffb21 100644 (file)
--- a/device.h
+++ b/device.h
@@ -124,6 +124,7 @@ enum device_event {
 struct device_user {
        struct list_head list;
 
+       bool claimed;
        struct device *dev;
        void (*cb)(struct device_user *, enum device_event);
 };
@@ -147,8 +148,8 @@ void device_add_user(struct device_user *dep, struct device *iface);
 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
index f08fee0..f6c32f4 100644 (file)
@@ -89,7 +89,7 @@ static 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;
 }
 
@@ -101,7 +101,7 @@ __interface_set_up(struct interface *iface)
        if (iface->state != IFS_DOWN)
                return 0;
 
-       ret = device_claim(iface->main_dev.dev);
+       ret = device_claim(&iface->main_dev);
        if (ret)
                return ret;
 
diff --git a/vlan.c b/vlan.c
index 18cb939..d00cda0 100644 (file)
--- a/vlan.c
+++ b/vlan.c
@@ -32,18 +32,18 @@ static int vlan_set_device_state(struct device *dev, bool up)
        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;
 }