]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/bridge/br_sysfs_br.c
Merge tag 'imx-drm-fixes-2016-07-27' of git://git.pengutronix.de/git/pza/linux into...
[karo-tx-linux.git] / net / bridge / br_sysfs_br.c
index 6b8091407ca3126b333c76c5104f5a8ca6803e49..beb47071e38df5761dc96c1138833ed89b285657 100644 (file)
@@ -43,7 +43,14 @@ static ssize_t store_bridge_parm(struct device *d,
        if (endp == buf)
                return -EINVAL;
 
+       if (!rtnl_trylock())
+               return restart_syscall();
+
        err = (*set)(br, val);
+       if (!err)
+               netdev_state_change(br->dev);
+       rtnl_unlock();
+
        return err ? err : len;
 }
 
@@ -101,15 +108,7 @@ static ssize_t ageing_time_show(struct device *d,
 
 static int set_ageing_time(struct net_bridge *br, unsigned long val)
 {
-       int ret;
-
-       if (!rtnl_trylock())
-               return restart_syscall();
-
-       ret = br_set_ageing_time(br, val);
-       rtnl_unlock();
-
-       return ret;
+       return br_set_ageing_time(br, val);
 }
 
 static ssize_t ageing_time_store(struct device *d,
@@ -128,27 +127,18 @@ static ssize_t stp_state_show(struct device *d,
 }
 
 
+static int set_stp_state(struct net_bridge *br, unsigned long val)
+{
+       br_stp_set_enabled(br, val);
+
+       return 0;
+}
+
 static ssize_t stp_state_store(struct device *d,
                               struct device_attribute *attr, const char *buf,
                               size_t len)
 {
-       struct net_bridge *br = to_bridge(d);
-       char *endp;
-       unsigned long val;
-
-       if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
-               return -EPERM;
-
-       val = simple_strtoul(buf, &endp, 0);
-       if (endp == buf)
-               return -EINVAL;
-
-       if (!rtnl_trylock())
-               return restart_syscall();
-       br_stp_set_enabled(br, val);
-       rtnl_unlock();
-
-       return len;
+       return store_bridge_parm(d, buf, len, set_stp_state);
 }
 static DEVICE_ATTR_RW(stp_state);
 
@@ -160,29 +150,22 @@ static ssize_t group_fwd_mask_show(struct device *d,
        return sprintf(buf, "%#x\n", br->group_fwd_mask);
 }
 
-
-static ssize_t group_fwd_mask_store(struct device *d,
-                                   struct device_attribute *attr,
-                                   const char *buf,
-                                   size_t len)
+static int set_group_fwd_mask(struct net_bridge *br, unsigned long val)
 {
-       struct net_bridge *br = to_bridge(d);
-       char *endp;
-       unsigned long val;
-
-       if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
-               return -EPERM;
-
-       val = simple_strtoul(buf, &endp, 0);
-       if (endp == buf)
-               return -EINVAL;
-
        if (val & BR_GROUPFWD_RESTRICTED)
                return -EINVAL;
 
        br->group_fwd_mask = val;
 
-       return len;
+       return 0;
+}
+
+static ssize_t group_fwd_mask_store(struct device *d,
+                                   struct device_attribute *attr,
+                                   const char *buf,
+                                   size_t len)
+{
+       return store_bridge_parm(d, buf, len, set_group_fwd_mask);
 }
 static DEVICE_ATTR_RW(group_fwd_mask);
 
@@ -328,6 +311,7 @@ static ssize_t group_addr_store(struct device *d,
 
        br->group_addr_set = true;
        br_recalculate_fwd_mask(br);
+       netdev_state_change(br->dev);
 
        rtnl_unlock();
 
@@ -336,17 +320,17 @@ static ssize_t group_addr_store(struct device *d,
 
 static DEVICE_ATTR_RW(group_addr);
 
+static int set_flush(struct net_bridge *br, unsigned long val)
+{
+       br_fdb_flush(br);
+       return 0;
+}
+
 static ssize_t flush_store(struct device *d,
                           struct device_attribute *attr,
                           const char *buf, size_t len)
 {
-       struct net_bridge *br = to_bridge(d);
-
-       if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
-               return -EPERM;
-
-       br_fdb_flush(br);
-       return len;
+       return store_bridge_parm(d, buf, len, set_flush);
 }
 static DEVICE_ATTR_WO(flush);
 
@@ -747,6 +731,22 @@ static ssize_t default_pvid_store(struct device *d,
        return store_bridge_parm(d, buf, len, br_vlan_set_default_pvid);
 }
 static DEVICE_ATTR_RW(default_pvid);
+
+static ssize_t vlan_stats_enabled_show(struct device *d,
+                                      struct device_attribute *attr,
+                                      char *buf)
+{
+       struct net_bridge *br = to_bridge(d);
+       return sprintf(buf, "%u\n", br->vlan_stats_enabled);
+}
+
+static ssize_t vlan_stats_enabled_store(struct device *d,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t len)
+{
+       return store_bridge_parm(d, buf, len, br_vlan_set_stats);
+}
+static DEVICE_ATTR_RW(vlan_stats_enabled);
 #endif
 
 static struct attribute *bridge_attrs[] = {
@@ -794,6 +794,7 @@ static struct attribute *bridge_attrs[] = {
        &dev_attr_vlan_filtering.attr,
        &dev_attr_vlan_protocol.attr,
        &dev_attr_default_pvid.attr,
+       &dev_attr_vlan_stats_enabled.attr,
 #endif
        NULL
 };