Merge branch 'stable-4.6' of git://git.infradead.org/users/pcmoore/audit
[cascardo/linux.git] / net / batman-adv / sysfs.c
index ab4382b..e7cf513 100644 (file)
@@ -216,7 +216,7 @@ ssize_t batadv_store_vlan_##_name(struct kobject *kobj,                     \
                                              attr, &vlan->_name,       \
                                              bat_priv->soft_iface);    \
                                                                        \
-       batadv_softif_vlan_free_ref(vlan);                              \
+       batadv_softif_vlan_put(vlan);                                   \
        return res;                                                     \
 }
 
@@ -231,7 +231,7 @@ ssize_t batadv_show_vlan_##_name(struct kobject *kobj,                      \
                             atomic_read(&vlan->_name) == 0 ?           \
                             "disabled" : "enabled");                   \
                                                                        \
-       batadv_softif_vlan_free_ref(vlan);                              \
+       batadv_softif_vlan_put(vlan);                                   \
        return res;                                                     \
 }
 
@@ -242,6 +242,55 @@ ssize_t batadv_show_vlan_##_name(struct kobject *kobj,                     \
        static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \
                                batadv_store_vlan_##_name)
 
+#define BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, _max, _post_func)        \
+ssize_t batadv_store_##_name(struct kobject *kobj,                     \
+                            struct attribute *attr, char *buff,        \
+                            size_t count)                              \
+{                                                                      \
+       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
+       struct batadv_hard_iface *hard_iface;                           \
+       ssize_t length;                                                 \
+                                                                       \
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
+       if (!hard_iface)                                                \
+               return 0;                                               \
+                                                                       \
+       length = __batadv_store_uint_attr(buff, count, _min, _max,      \
+                                         _post_func, attr,             \
+                                         &hard_iface->_var, net_dev);  \
+                                                                       \
+       batadv_hardif_put(hard_iface);                          \
+       return length;                                                  \
+}
+
+#define BATADV_ATTR_HIF_SHOW_UINT(_name, _var)                         \
+ssize_t batadv_show_##_name(struct kobject *kobj,                      \
+                           struct attribute *attr, char *buff)         \
+{                                                                      \
+       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
+       struct batadv_hard_iface *hard_iface;                           \
+       ssize_t length;                                                 \
+                                                                       \
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
+       if (!hard_iface)                                                \
+               return 0;                                               \
+                                                                       \
+       length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_var)); \
+                                                                       \
+       batadv_hardif_put(hard_iface);                          \
+       return length;                                                  \
+}
+
+/* Use this, if you are going to set [name] in hard_iface to an
+ * unsigned integer value
+ */
+#define BATADV_ATTR_HIF_UINT(_name, _var, _mode, _min, _max, _post_func)\
+       static BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min,            \
+                                         _max, _post_func)             \
+       static BATADV_ATTR_HIF_SHOW_UINT(_name, _var)                   \
+       static BATADV_ATTR(_name, _mode, batadv_show_##_name,           \
+                          batadv_store_##_name)
+
 static int batadv_store_bool_attr(char *buff, size_t count,
                                  struct net_device *net_dev,
                                  const char *attr_name, atomic_t *attr,
@@ -771,7 +820,7 @@ static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
 
        length = sprintf(buff, "%s\n", ifname);
 
-       batadv_hardif_free_ref(hard_iface);
+       batadv_hardif_put(hard_iface);
 
        return length;
 }
@@ -795,7 +844,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
        if (strlen(buff) >= IFNAMSIZ) {
                pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
                       buff);
-               batadv_hardif_free_ref(hard_iface);
+               batadv_hardif_put(hard_iface);
                return -EINVAL;
        }
 
@@ -829,7 +878,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
 unlock:
        rtnl_unlock();
 out:
-       batadv_hardif_free_ref(hard_iface);
+       batadv_hardif_put(hard_iface);
        return ret;
 }
 
@@ -863,18 +912,99 @@ static ssize_t batadv_show_iface_status(struct kobject *kobj,
                break;
        }
 
-       batadv_hardif_free_ref(hard_iface);
+       batadv_hardif_put(hard_iface);
 
        return length;
 }
 
+#ifdef CONFIG_BATMAN_ADV_BATMAN_V
+
+/**
+ * batadv_store_throughput_override - parse and store throughput override
+ *  entered by the user
+ * @kobj: kobject representing the private mesh sysfs directory
+ * @attr: the batman-adv attribute the user is interacting with
+ * @buff: the buffer containing the user data
+ * @count: number of bytes in the buffer
+ *
+ * Return: 'count' on success or a negative error code in case of failure
+ */
+static ssize_t batadv_store_throughput_override(struct kobject *kobj,
+                                               struct attribute *attr,
+                                               char *buff, size_t count)
+{
+       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
+       struct batadv_hard_iface *hard_iface;
+       u32 tp_override;
+       u32 old_tp_override;
+       bool ret;
+
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);
+       if (!hard_iface)
+               return -EINVAL;
+
+       if (buff[count - 1] == '\n')
+               buff[count - 1] = '\0';
+
+       ret = batadv_parse_throughput(net_dev, buff, "throughput_override",
+                                     &tp_override);
+       if (!ret)
+               return count;
+
+       old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
+       if (old_tp_override == tp_override)
+               goto out;
+
+       batadv_info(net_dev, "%s: Changing from: %u.%u MBit to: %u.%u MBit\n",
+                   "throughput_override",
+                   old_tp_override / 10, old_tp_override % 10,
+                   tp_override / 10, tp_override % 10);
+
+       atomic_set(&hard_iface->bat_v.throughput_override, tp_override);
+
+out:
+       batadv_hardif_put(hard_iface);
+       return count;
+}
+
+static ssize_t batadv_show_throughput_override(struct kobject *kobj,
+                                              struct attribute *attr,
+                                              char *buff)
+{
+       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
+       struct batadv_hard_iface *hard_iface;
+       u32 tp_override;
+
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);
+       if (!hard_iface)
+               return -EINVAL;
+
+       tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
+
+       return sprintf(buff, "%u.%u MBit\n", tp_override / 10,
+                      tp_override % 10);
+}
+
+#endif
+
 static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
                   batadv_store_mesh_iface);
 static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
+#ifdef CONFIG_BATMAN_ADV_BATMAN_V
+BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR,
+                    2 * BATADV_JITTER, INT_MAX, NULL);
+static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR,
+                  batadv_show_throughput_override,
+                  batadv_store_throughput_override);
+#endif
 
 static struct batadv_attribute *batadv_batman_attrs[] = {
        &batadv_attr_mesh_iface,
        &batadv_attr_iface_status,
+#ifdef CONFIG_BATMAN_ADV_BATMAN_V
+       &batadv_attr_elp_interval,
+       &batadv_attr_throughput_override,
+#endif
        NULL,
 };