summaryrefslogtreecommitdiff
path: root/net/batman-adv/bat_sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/bat_sysfs.c')
-rw-r--r--net/batman-adv/bat_sysfs.c102
1 files changed, 90 insertions, 12 deletions
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index 497a0700cc3c..cd15deba60a1 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -28,9 +28,31 @@
#include "gateway_client.h"
#include "vis.h"
-#define to_dev(obj) container_of(obj, struct device, kobj)
-#define kobj_to_netdev(obj) to_net_dev(to_dev(obj->parent))
-#define kobj_to_batpriv(obj) netdev_priv(kobj_to_netdev(obj))
+static struct net_device *kobj_to_netdev(struct kobject *obj)
+{
+ struct device *dev = container_of(obj->parent, struct device, kobj);
+ return to_net_dev(dev);
+}
+
+static struct bat_priv *kobj_to_batpriv(struct kobject *obj)
+{
+ struct net_device *net_dev = kobj_to_netdev(obj);
+ return netdev_priv(net_dev);
+}
+
+#define UEV_TYPE_VAR "BATTYPE="
+#define UEV_ACTION_VAR "BATACTION="
+#define UEV_DATA_VAR "BATDATA="
+
+static char *uev_action_str[] = {
+ "add",
+ "del",
+ "change"
+};
+
+static char *uev_type_str[] = {
+ "gw"
+};
/* Use this, if you have customized show and store functions */
#define BAT_ATTR(_name, _mode, _show, _store) \
@@ -96,7 +118,7 @@ ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \
static int store_bool_attr(char *buff, size_t count,
struct net_device *net_dev,
- char *attr_name, atomic_t *attr)
+ const char *attr_name, atomic_t *attr)
{
int enabled = -1;
@@ -138,16 +160,15 @@ static inline ssize_t __store_bool_attr(char *buff, size_t count,
{
int ret;
- ret = store_bool_attr(buff, count, net_dev, (char *)attr->name,
- attr_store);
+ ret = store_bool_attr(buff, count, net_dev, attr->name, attr_store);
if (post_func && ret)
post_func(net_dev);
return ret;
}
-static int store_uint_attr(char *buff, size_t count,
- struct net_device *net_dev, char *attr_name,
+static int store_uint_attr(const char *buff, size_t count,
+ struct net_device *net_dev, const char *attr_name,
unsigned int min, unsigned int max, atomic_t *attr)
{
unsigned long uint_val;
@@ -183,15 +204,15 @@ static int store_uint_attr(char *buff, size_t count,
return count;
}
-static inline ssize_t __store_uint_attr(char *buff, size_t count,
+static inline ssize_t __store_uint_attr(const char *buff, size_t count,
int min, int max,
void (*post_func)(struct net_device *),
- struct attribute *attr,
+ const struct attribute *attr,
atomic_t *attr_store, struct net_device *net_dev)
{
int ret;
- ret = store_uint_attr(buff, count, net_dev, (char *)attr->name,
+ ret = store_uint_attr(buff, count, net_dev, attr->name,
min, max, attr_store);
if (post_func && ret)
post_func(net_dev);
@@ -368,7 +389,7 @@ BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE,
static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth,
store_gw_bwidth);
#ifdef CONFIG_BATMAN_ADV_DEBUG
-BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 3, NULL);
+BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 7, NULL);
#endif
static struct bat_attribute *mesh_attrs[] = {
@@ -594,3 +615,60 @@ void sysfs_del_hardif(struct kobject **hardif_obj)
kobject_put(*hardif_obj);
*hardif_obj = NULL;
}
+
+int throw_uevent(struct bat_priv *bat_priv, enum uev_type type,
+ enum uev_action action, const char *data)
+{
+ int ret = -1;
+ struct hard_iface *primary_if = NULL;
+ struct kobject *bat_kobj;
+ char *uevent_env[4] = { NULL, NULL, NULL, NULL };
+
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ bat_kobj = &primary_if->soft_iface->dev.kobj;
+
+ uevent_env[0] = kmalloc(strlen(UEV_TYPE_VAR) +
+ strlen(uev_type_str[type]) + 1,
+ GFP_ATOMIC);
+ if (!uevent_env[0])
+ goto out;
+
+ sprintf(uevent_env[0], "%s%s", UEV_TYPE_VAR, uev_type_str[type]);
+
+ uevent_env[1] = kmalloc(strlen(UEV_ACTION_VAR) +
+ strlen(uev_action_str[action]) + 1,
+ GFP_ATOMIC);
+ if (!uevent_env[1])
+ goto out;
+
+ sprintf(uevent_env[1], "%s%s", UEV_ACTION_VAR, uev_action_str[action]);
+
+ /* If the event is DEL, ignore the data field */
+ if (action != UEV_DEL) {
+ uevent_env[2] = kmalloc(strlen(UEV_DATA_VAR) +
+ strlen(data) + 1, GFP_ATOMIC);
+ if (!uevent_env[2])
+ goto out;
+
+ sprintf(uevent_env[2], "%s%s", UEV_DATA_VAR, data);
+ }
+
+ ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env);
+out:
+ kfree(uevent_env[0]);
+ kfree(uevent_env[1]);
+ kfree(uevent_env[2]);
+
+ if (primary_if)
+ hardif_free_ref(primary_if);
+
+ if (ret)
+ bat_dbg(DBG_BATMAN, bat_priv, "Impossible to send "
+ "uevent for (%s,%s,%s) event (err: %d)\n",
+ uev_type_str[type], uev_action_str[action],
+ (action == UEV_DEL ? "NULL" : data), ret);
+ return ret;
+}