wimax: Add netlink interface to get device state
authorPaulius Zaleckas <paulius.zaleckas@teltonika.lt>
Wed, 13 May 2009 13:20:29 +0000 (06:20 -0700)
committerInaky Perez-Gonzalez <inaky@linux.intel.com>
Fri, 29 May 2009 01:02:20 +0000 (18:02 -0700)
wimax connection manager / daemon has to know what is current
state of the device. Previously it was only possible to get
notification whet state has changed.

Note:

 By mistake, the new generic netlink's number for
 WIMAX_GNL_OP_STATE_GET was declared inserting into the existing list
 of API calls, not appending; thus, it'd break existing API.

 Fixed by Inaky Perez-Gonzalez <inaky@linux.intel.com> by moving to
 the tail, where we add to the interface, not modify the interface.

 Thanks to Stephen Hemminger <shemminger@vyatta.com> for catching this.

Signed-off-by: Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
include/linux/wimax.h
net/wimax/Makefile
net/wimax/debug-levels.h
net/wimax/debugfs.c
net/wimax/op-state-get.c [new file with mode: 0644]
net/wimax/stack.c

index c89de7f4e5b945fd18e4b373d09caef740ae7529..2f7a6b77d6b34c95bc8652d58cdd0f098aec18c3 100644 (file)
@@ -78,6 +78,7 @@ enum {
        WIMAX_GNL_OP_RFKILL,    /* Run wimax_rfkill() */
        WIMAX_GNL_OP_RESET,     /* Run wimax_rfkill() */
        WIMAX_GNL_RE_STATE_CHANGE,      /* Report: status change */
+       WIMAX_GNL_OP_STATE_GET,         /* Request for current state */
 };
 
 
@@ -113,6 +114,10 @@ enum {
        WIMAX_GNL_RESET_IFIDX = 1,
 };
 
+/* Atributes for wimax_state_get() */
+enum {
+       WIMAX_GNL_STGET_IFIDX = 1,
+};
 
 /*
  * Attributes for the Report State Change
index 5b80b941c2c9431e5d0e214653a0ead31e56311a..8f1510d0cc2bf54e9723bc6c07172ac4e763b634 100644 (file)
@@ -6,6 +6,7 @@ wimax-y :=              \
        op-msg.o        \
        op-reset.o      \
        op-rfkill.o     \
+       op-state-get.o  \
        stack.o
 
 wimax-$(CONFIG_DEBUG_FS) += debugfs.o
index 1c29123a3aa96a6ab5256b95224a95a290831f8e..0975adba6b71a9876bb0578420b989eca32b526d 100644 (file)
@@ -36,6 +36,7 @@ enum d_module {
        D_SUBMODULE_DECLARE(op_msg),
        D_SUBMODULE_DECLARE(op_reset),
        D_SUBMODULE_DECLARE(op_rfkill),
+       D_SUBMODULE_DECLARE(op_state_get),
        D_SUBMODULE_DECLARE(stack),
 };
 
index 94d216a464078136c890ad5333be1bc3f15449e5..6c9bedb7431e5f58d02b471c27a32981bffbccb1 100644 (file)
@@ -61,6 +61,7 @@ int wimax_debugfs_add(struct wimax_dev *wimax_dev)
        __debugfs_register("wimax_dl_", op_msg, dentry);
        __debugfs_register("wimax_dl_", op_reset, dentry);
        __debugfs_register("wimax_dl_", op_rfkill, dentry);
+       __debugfs_register("wimax_dl_", op_state_get, dentry);
        __debugfs_register("wimax_dl_", stack, dentry);
        result = 0;
 out:
diff --git a/net/wimax/op-state-get.c b/net/wimax/op-state-get.c
new file mode 100644 (file)
index 0000000..a76b8fc
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Linux WiMAX
+ * Implement and export a method for getting a WiMAX device current state
+ *
+ * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * Based on previous WiMAX core work by:
+ *  Copyright (C) 2008 Intel Corporation <linux-wimax@intel.com>
+ *  Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <net/wimax.h>
+#include <net/genetlink.h>
+#include <linux/wimax.h>
+#include <linux/security.h>
+#include "wimax-internal.h"
+
+#define D_SUBMODULE op_state_get
+#include "debug-levels.h"
+
+
+static const
+struct nla_policy wimax_gnl_state_get_policy[WIMAX_GNL_ATTR_MAX + 1] = {
+       [WIMAX_GNL_STGET_IFIDX] = {
+               .type = NLA_U32,
+       },
+};
+
+
+/*
+ * Exporting to user space over generic netlink
+ *
+ * Parse the state get command from user space, return a combination
+ * value that describe the current state.
+ *
+ * No attributes.
+ */
+static
+int wimax_gnl_doit_state_get(struct sk_buff *skb, struct genl_info *info)
+{
+       int result, ifindex;
+       struct wimax_dev *wimax_dev;
+       struct device *dev;
+
+       d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info);
+       result = -ENODEV;
+       if (info->attrs[WIMAX_GNL_STGET_IFIDX] == NULL) {
+               printk(KERN_ERR "WIMAX_GNL_OP_STATE_GET: can't find IFIDX "
+                       "attribute\n");
+               goto error_no_wimax_dev;
+       }
+       ifindex = nla_get_u32(info->attrs[WIMAX_GNL_STGET_IFIDX]);
+       wimax_dev = wimax_dev_get_by_genl_info(info, ifindex);
+       if (wimax_dev == NULL)
+               goto error_no_wimax_dev;
+       dev = wimax_dev_to_dev(wimax_dev);
+       /* Execute the operation and send the result back to user space */
+       result = wimax_state_get(wimax_dev);
+       dev_put(wimax_dev->net_dev);
+error_no_wimax_dev:
+       d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result);
+       return result;
+}
+
+
+struct genl_ops wimax_gnl_state_get = {
+       .cmd = WIMAX_GNL_OP_STATE_GET,
+       .flags = GENL_ADMIN_PERM,
+       .policy = wimax_gnl_state_get_policy,
+       .doit = wimax_gnl_doit_state_get,
+       .dumpit = NULL,
+};
index 933e1422b09f98de1939347fb4dbb92a963ea36e..79fb7d7c640f0b86869d8a8fd77a6f60de8ef4c2 100644 (file)
@@ -402,13 +402,15 @@ EXPORT_SYMBOL_GPL(wimax_dev_init);
 extern struct genl_ops
        wimax_gnl_msg_from_user,
        wimax_gnl_reset,
-       wimax_gnl_rfkill;
+       wimax_gnl_rfkill,
+       wimax_gnl_state_get;
 
 static
 struct genl_ops *wimax_gnl_ops[] = {
        &wimax_gnl_msg_from_user,
        &wimax_gnl_reset,
        &wimax_gnl_rfkill,
+       &wimax_gnl_state_get,
 };
 
 
@@ -533,6 +535,7 @@ struct d_level D_LEVEL[] = {
        D_SUBMODULE_DEFINE(op_msg),
        D_SUBMODULE_DEFINE(op_reset),
        D_SUBMODULE_DEFINE(op_rfkill),
+       D_SUBMODULE_DEFINE(op_state_get),
        D_SUBMODULE_DEFINE(stack),
 };
 size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);