aboutsummaryrefslogtreecommitdiffstats
path: root/net/wimax/op-reset.c
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2008-12-20 19:57:38 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-07 13:00:17 -0500
commit3e65646bb12be03b14dff53907391095a52d5f49 (patch)
tree5ab2961f02a2d078990e69584af81b1197fb2392 /net/wimax/op-reset.c
parent3efb40c2c6eea315abcf19239c15d088e2498299 (diff)
wimax: basic API: kernel/user messaging, rfkill and reset
Implements the three basic operations provided by the stack's control interface to WiMAX devices: - Messaging channel between user space and driver/device This implements a direct communication channel between user space and the driver/device, by which free form messages can be sent back and forth. This is intended for device-specific features, vendor quirks, etc. - RF-kill framework integration Provide most of the RF-Kill integration for WiMAX drivers so that all device drivers have to do is after wimax_dev_add() is call wimax_report_rfkill_{hw,sw}() to update initial state and then every time it changes. Provides wimax_rfkill() for the kernel to call to set software RF-Kill status and/or query current hardware and software switch status. Exports wimax_rfkill() over generic netlink to user space. - Reset a WiMAX device Provides wimax_reset() for the kernel to reset a wimax device as needed and exports it over generic netlink to user space. This API is clearly limited, as it still provides no way to do the basic scan, connect and disconnect in a hardware independent way. The WiMAX case is more complex than WiFi due to the way networks are discovered and provisioned. The next developments are to add the basic operations so they can be offerent by different drivers. However, we'd like to get more vendors to jump in and provide feedback of how the user/kernel API/abstraction layer should be. The user space code for the i2400m, as of now, uses the messaging channel, but that will change as the API evolves. Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'net/wimax/op-reset.c')
-rw-r--r--net/wimax/op-reset.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/net/wimax/op-reset.c b/net/wimax/op-reset.c
new file mode 100644
index 000000000000..ca269178c4d4
--- /dev/null
+++ b/net/wimax/op-reset.c
@@ -0,0 +1,143 @@
1/*
2 * Linux WiMAX
3 * Implement and export a method for resetting a WiMAX device
4 *
5 *
6 * Copyright (C) 2008 Intel Corporation <linux-wimax@intel.com>
7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 *
23 *
24 * This implements a simple synchronous call to reset a WiMAX device.
25 *
26 * Resets aim at being warm, keeping the device handles active;
27 * however, when that fails, it falls back to a cold reset (that will
28 * disconnect and reconnect the device).
29 */
30
31#include <net/wimax.h>
32#include <net/genetlink.h>
33#include <linux/wimax.h>
34#include <linux/security.h>
35#include "wimax-internal.h"
36
37#define D_SUBMODULE op_reset
38#include "debug-levels.h"
39
40
41/**
42 * wimax_reset - Reset a WiMAX device
43 *
44 * @wimax_dev: WiMAX device descriptor
45 *
46 * Returns:
47 *
48 * %0 if ok and a warm reset was done (the device still exists in
49 * the system).
50 *
51 * -%ENODEV if a cold/bus reset had to be done (device has
52 * disconnected and reconnected, so current handle is not valid
53 * any more).
54 *
55 * -%EINVAL if the device is not even registered.
56 *
57 * Any other negative error code shall be considered as
58 * non-recoverable.
59 *
60 * Description:
61 *
62 * Called when wanting to reset the device for any reason. Device is
63 * taken back to power on status.
64 *
65 * This call blocks; on succesful return, the device has completed the
66 * reset process and is ready to operate.
67 */
68int wimax_reset(struct wimax_dev *wimax_dev)
69{
70 int result = -EINVAL;
71 struct device *dev = wimax_dev_to_dev(wimax_dev);
72 enum wimax_st state;
73
74 might_sleep();
75 d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev);
76 mutex_lock(&wimax_dev->mutex);
77 dev_hold(wimax_dev->net_dev);
78 state = wimax_dev->state;
79 mutex_unlock(&wimax_dev->mutex);
80
81 if (state >= WIMAX_ST_DOWN) {
82 mutex_lock(&wimax_dev->mutex_reset);
83 result = wimax_dev->op_reset(wimax_dev);
84 mutex_unlock(&wimax_dev->mutex_reset);
85 }
86 dev_put(wimax_dev->net_dev);
87
88 d_fnend(3, dev, "(wimax_dev %p) = %d\n", wimax_dev, result);
89 return result;
90}
91EXPORT_SYMBOL(wimax_reset);
92
93
94static const
95struct nla_policy wimax_gnl_reset_policy[WIMAX_GNL_ATTR_MAX + 1] = {
96 [WIMAX_GNL_RESET_IFIDX] = {
97 .type = NLA_U32,
98 },
99};
100
101
102/*
103 * Exporting to user space over generic netlink
104 *
105 * Parse the reset command from user space, return error code.
106 *
107 * No attributes.
108 */
109static
110int wimax_gnl_doit_reset(struct sk_buff *skb, struct genl_info *info)
111{
112 int result, ifindex;
113 struct wimax_dev *wimax_dev;
114 struct device *dev;
115
116 d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info);
117 result = -ENODEV;
118 if (info->attrs[WIMAX_GNL_RESET_IFIDX] == NULL) {
119 printk(KERN_ERR "WIMAX_GNL_OP_RFKILL: can't find IFIDX "
120 "attribute\n");
121 goto error_no_wimax_dev;
122 }
123 ifindex = nla_get_u32(info->attrs[WIMAX_GNL_RESET_IFIDX]);
124 wimax_dev = wimax_dev_get_by_genl_info(info, ifindex);
125 if (wimax_dev == NULL)
126 goto error_no_wimax_dev;
127 dev = wimax_dev_to_dev(wimax_dev);
128 /* Execute the operation and send the result back to user space */
129 result = wimax_reset(wimax_dev);
130 dev_put(wimax_dev->net_dev);
131error_no_wimax_dev:
132 d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result);
133 return result;
134}
135
136
137struct genl_ops wimax_gnl_reset = {
138 .cmd = WIMAX_GNL_OP_RESET,
139 .flags = GENL_ADMIN_PERM,
140 .policy = wimax_gnl_reset_policy,
141 .doit = wimax_gnl_doit_reset,
142 .dumpit = NULL,
143};