summaryrefslogtreecommitdiff
path: root/net/wimax
diff options
context:
space:
mode:
Diffstat (limited to 'net/wimax')
-rw-r--r--net/wimax/Kconfig15
-rw-r--r--net/wimax/Makefile1
-rw-r--r--net/wimax/debug-levels.h1
-rw-r--r--net/wimax/debugfs.c1
-rw-r--r--net/wimax/op-msg.c17
-rw-r--r--net/wimax/op-rfkill.c123
-rw-r--r--net/wimax/op-state-get.c86
-rw-r--r--net/wimax/stack.c5
8 files changed, 134 insertions, 115 deletions
diff --git a/net/wimax/Kconfig b/net/wimax/Kconfig
index 1b46747a5f5a..e4d97ab476d5 100644
--- a/net/wimax/Kconfig
+++ b/net/wimax/Kconfig
@@ -1,23 +1,10 @@
#
# WiMAX LAN device configuration
#
-# Note the ugly 'depends on' on WIMAX: that disallows RFKILL to be a
-# module if WIMAX is to be linked in. The WiMAX code is done in such a
-# way that it doesn't require and explicit dependency on RFKILL in
-# case an embedded system wants to rip it out.
-#
-# As well, enablement of the RFKILL code means we need the INPUT layer
-# support to inject events coming from hw rfkill switches. That
-# dependency could be killed if input.h provided appropriate means to
-# work when input is disabled.
-
-comment "WiMAX Wireless Broadband support requires CONFIG_INPUT enabled"
- depends on INPUT = n && RFKILL != n
menuconfig WIMAX
tristate "WiMAX Wireless Broadband support"
- depends on (y && RFKILL != m) || m
- depends on (INPUT && RFKILL != n) || RFKILL = n
+ depends on RFKILL || !RFKILL
help
Select to configure support for devices that provide
diff --git a/net/wimax/Makefile b/net/wimax/Makefile
index 5b80b941c2c9..8f1510d0cc2b 100644
--- a/net/wimax/Makefile
+++ b/net/wimax/Makefile
@@ -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
diff --git a/net/wimax/debug-levels.h b/net/wimax/debug-levels.h
index 1c29123a3aa9..0975adba6b71 100644
--- a/net/wimax/debug-levels.h
+++ b/net/wimax/debug-levels.h
@@ -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),
};
diff --git a/net/wimax/debugfs.c b/net/wimax/debugfs.c
index 94d216a46407..6c9bedb7431e 100644
--- a/net/wimax/debugfs.c
+++ b/net/wimax/debugfs.c
@@ -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-msg.c b/net/wimax/op-msg.c
index 9ad4d893a566..d631a17186bc 100644
--- a/net/wimax/op-msg.c
+++ b/net/wimax/op-msg.c
@@ -108,6 +108,12 @@
* Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as
* wimax_msg_send() depends on skb->data being placed at the
* beginning of the user message.
+ *
+ * Unlike other WiMAX stack calls, this call can be used way early,
+ * even before wimax_dev_add() is called, as long as the
+ * wimax_dev->net_dev pointer is set to point to a proper
+ * net_dev. This is so that drivers can use it early in case they need
+ * to send stuff around or communicate with user space.
*/
struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev,
const char *pipe_name,
@@ -115,7 +121,7 @@ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev,
gfp_t gfp_flags)
{
int result;
- struct device *dev = wimax_dev->net_dev->dev.parent;
+ struct device *dev = wimax_dev_to_dev(wimax_dev);
size_t msg_size;
void *genl_msg;
struct sk_buff *skb;
@@ -161,7 +167,6 @@ error_genlmsg_put:
error_new:
nlmsg_free(skb);
return ERR_PTR(result);
-
}
EXPORT_SYMBOL_GPL(wimax_msg_alloc);
@@ -256,10 +261,16 @@ EXPORT_SYMBOL_GPL(wimax_msg_len);
* Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as
* wimax_msg_send() depends on skb->data being placed at the
* beginning of the user message.
+ *
+ * Unlike other WiMAX stack calls, this call can be used way early,
+ * even before wimax_dev_add() is called, as long as the
+ * wimax_dev->net_dev pointer is set to point to a proper
+ * net_dev. This is so that drivers can use it early in case they need
+ * to send stuff around or communicate with user space.
*/
int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb)
{
- struct device *dev = wimax_dev->net_dev->dev.parent;
+ struct device *dev = wimax_dev_to_dev(wimax_dev);
void *msg = skb->data;
size_t size = skb->len;
might_sleep();
diff --git a/net/wimax/op-rfkill.c b/net/wimax/op-rfkill.c
index a3616e2ccb8a..bb102e4aa3e9 100644
--- a/net/wimax/op-rfkill.c
+++ b/net/wimax/op-rfkill.c
@@ -29,8 +29,8 @@
* A non-polled generic rfkill device is embedded into the WiMAX
* subsystem's representation of a device.
*
- * FIXME: Need polled support? use a timer or add the implementation
- * to the stack.
+ * FIXME: Need polled support? Let drivers provide a poll routine
+ * and hand it to rfkill ops then?
*
* All device drivers have to do is after wimax_dev_init(), call
* wimax_report_rfkill_hw() and wimax_report_rfkill_sw() to update
@@ -43,7 +43,7 @@
* wimax_rfkill() Kernel calling wimax_rfkill()
* __wimax_rf_toggle_radio()
*
- * wimax_rfkill_toggle_radio() RF-Kill subsytem calling
+ * wimax_rfkill_set_radio_block() RF-Kill subsytem calling
* __wimax_rf_toggle_radio()
*
* __wimax_rf_toggle_radio()
@@ -65,15 +65,11 @@
#include <linux/wimax.h>
#include <linux/security.h>
#include <linux/rfkill.h>
-#include <linux/input.h>
#include "wimax-internal.h"
#define D_SUBMODULE op_rfkill
#include "debug-levels.h"
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-
-
/**
* wimax_report_rfkill_hw - Reports changes in the hardware RF switch
*
@@ -99,7 +95,6 @@ void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev,
int result;
struct device *dev = wimax_dev_to_dev(wimax_dev);
enum wimax_st wimax_state;
- enum rfkill_state rfkill_state;
d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
BUG_ON(state == WIMAX_RF_QUERY);
@@ -112,16 +107,15 @@ void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev,
if (state != wimax_dev->rf_hw) {
wimax_dev->rf_hw = state;
- rfkill_state = state == WIMAX_RF_ON ?
- RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
if (wimax_dev->rf_hw == WIMAX_RF_ON
&& wimax_dev->rf_sw == WIMAX_RF_ON)
wimax_state = WIMAX_ST_READY;
else
wimax_state = WIMAX_ST_RADIO_OFF;
+
+ rfkill_set_hw_state(wimax_dev->rfkill, state == WIMAX_RF_OFF);
+
__wimax_state_change(wimax_dev, wimax_state);
- input_report_key(wimax_dev->rfkill_input, KEY_WIMAX,
- rfkill_state);
}
error_not_ready:
mutex_unlock(&wimax_dev->mutex);
@@ -174,6 +168,7 @@ void wimax_report_rfkill_sw(struct wimax_dev *wimax_dev,
else
wimax_state = WIMAX_ST_RADIO_OFF;
__wimax_state_change(wimax_dev, wimax_state);
+ rfkill_set_sw_state(wimax_dev->rfkill, state == WIMAX_RF_OFF);
}
error_not_ready:
mutex_unlock(&wimax_dev->mutex);
@@ -249,36 +244,31 @@ out_no_change:
*
* NOTE: This call will block until the operation is completed.
*/
-static
-int wimax_rfkill_toggle_radio(void *data, enum rfkill_state state)
+static int wimax_rfkill_set_radio_block(void *data, bool blocked)
{
int result;
struct wimax_dev *wimax_dev = data;
struct device *dev = wimax_dev_to_dev(wimax_dev);
enum wimax_rf_state rf_state;
- d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
- switch (state) {
- case RFKILL_STATE_SOFT_BLOCKED:
+ d_fnstart(3, dev, "(wimax_dev %p blocked %u)\n", wimax_dev, blocked);
+ rf_state = WIMAX_RF_ON;
+ if (blocked)
rf_state = WIMAX_RF_OFF;
- break;
- case RFKILL_STATE_UNBLOCKED:
- rf_state = WIMAX_RF_ON;
- break;
- default:
- BUG();
- }
mutex_lock(&wimax_dev->mutex);
if (wimax_dev->state <= __WIMAX_ST_QUIESCING)
- result = 0; /* just pretend it didn't happen */
+ result = 0;
else
result = __wimax_rf_toggle_radio(wimax_dev, rf_state);
mutex_unlock(&wimax_dev->mutex);
- d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n",
- wimax_dev, state, result);
+ d_fnend(3, dev, "(wimax_dev %p blocked %u) = %d\n",
+ wimax_dev, blocked, result);
return result;
}
+static const struct rfkill_ops wimax_rfkill_ops = {
+ .set_block = wimax_rfkill_set_radio_block,
+};
/**
* wimax_rfkill - Set the software RF switch state for a WiMAX device
@@ -322,6 +312,7 @@ int wimax_rfkill(struct wimax_dev *wimax_dev, enum wimax_rf_state state)
result = __wimax_rf_toggle_radio(wimax_dev, state);
if (result < 0)
goto error;
+ rfkill_set_sw_state(wimax_dev->rfkill, state == WIMAX_RF_OFF);
break;
case WIMAX_RF_QUERY:
break;
@@ -349,40 +340,20 @@ int wimax_rfkill_add(struct wimax_dev *wimax_dev)
{
int result;
struct rfkill *rfkill;
- struct input_dev *input_dev;
struct device *dev = wimax_dev_to_dev(wimax_dev);
d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev);
/* Initialize RF Kill */
result = -ENOMEM;
- rfkill = rfkill_allocate(dev, RFKILL_TYPE_WIMAX);
+ rfkill = rfkill_alloc(wimax_dev->name, dev, RFKILL_TYPE_WIMAX,
+ &wimax_rfkill_ops, wimax_dev);
if (rfkill == NULL)
goto error_rfkill_allocate;
+
+ d_printf(1, dev, "rfkill %p\n", rfkill);
+
wimax_dev->rfkill = rfkill;
- rfkill->name = wimax_dev->name;
- rfkill->state = RFKILL_STATE_UNBLOCKED;
- rfkill->data = wimax_dev;
- rfkill->toggle_radio = wimax_rfkill_toggle_radio;
-
- /* Initialize the input device for the hw key */
- input_dev = input_allocate_device();
- if (input_dev == NULL)
- goto error_input_allocate;
- wimax_dev->rfkill_input = input_dev;
- d_printf(1, dev, "rfkill %p input %p\n", rfkill, input_dev);
-
- input_dev->name = wimax_dev->name;
- /* FIXME: get a real device bus ID and stuff? do we care? */
- input_dev->id.bustype = BUS_HOST;
- input_dev->id.vendor = 0xffff;
- input_dev->evbit[0] = BIT(EV_KEY);
- set_bit(KEY_WIMAX, input_dev->keybit);
-
- /* Register both */
- result = input_register_device(wimax_dev->rfkill_input);
- if (result < 0)
- goto error_input_register;
result = rfkill_register(wimax_dev->rfkill);
if (result < 0)
goto error_rfkill_register;
@@ -394,17 +365,8 @@ int wimax_rfkill_add(struct wimax_dev *wimax_dev)
d_fnend(3, dev, "(wimax_dev %p) = 0\n", wimax_dev);
return 0;
- /* if rfkill_register() suceeds, can't use rfkill_free() any
- * more, only rfkill_unregister() [it owns the refcount]; with
- * the input device we have the same issue--hence the if. */
error_rfkill_register:
- input_unregister_device(wimax_dev->rfkill_input);
- wimax_dev->rfkill_input = NULL;
-error_input_register:
- if (wimax_dev->rfkill_input)
- input_free_device(wimax_dev->rfkill_input);
-error_input_allocate:
- rfkill_free(wimax_dev->rfkill);
+ rfkill_destroy(wimax_dev->rfkill);
error_rfkill_allocate:
d_fnend(3, dev, "(wimax_dev %p) = %d\n", wimax_dev, result);
return result;
@@ -423,45 +385,12 @@ void wimax_rfkill_rm(struct wimax_dev *wimax_dev)
{
struct device *dev = wimax_dev_to_dev(wimax_dev);
d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev);
- rfkill_unregister(wimax_dev->rfkill); /* frees */
- input_unregister_device(wimax_dev->rfkill_input);
+ rfkill_unregister(wimax_dev->rfkill);
+ rfkill_destroy(wimax_dev->rfkill);
d_fnend(3, dev, "(wimax_dev %p)\n", wimax_dev);
}
-#else /* #ifdef CONFIG_RFKILL */
-
-void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev,
- enum wimax_rf_state state)
-{
-}
-EXPORT_SYMBOL_GPL(wimax_report_rfkill_hw);
-
-void wimax_report_rfkill_sw(struct wimax_dev *wimax_dev,
- enum wimax_rf_state state)
-{
-}
-EXPORT_SYMBOL_GPL(wimax_report_rfkill_sw);
-
-int wimax_rfkill(struct wimax_dev *wimax_dev,
- enum wimax_rf_state state)
-{
- return WIMAX_RF_ON << 1 | WIMAX_RF_ON;
-}
-EXPORT_SYMBOL_GPL(wimax_rfkill);
-
-int wimax_rfkill_add(struct wimax_dev *wimax_dev)
-{
- return 0;
-}
-
-void wimax_rfkill_rm(struct wimax_dev *wimax_dev)
-{
-}
-
-#endif /* #ifdef CONFIG_RFKILL */
-
-
/*
* Exporting to user space over generic netlink
*
diff --git a/net/wimax/op-state-get.c b/net/wimax/op-state-get.c
new file mode 100644
index 000000000000..a76b8fcb056d
--- /dev/null
+++ b/net/wimax/op-state-get.c
@@ -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,
+};
diff --git a/net/wimax/stack.c b/net/wimax/stack.c
index 933e1422b09f..79fb7d7c640f 100644
--- a/net/wimax/stack.c
+++ b/net/wimax/stack.c
@@ -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);