aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-01-07 18:37:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-07 18:37:24 -0500
commit7c7758f99d39d529a64d4f60d22129bbf2f16d74 (patch)
tree8847b5e56812fe4c4c812cfffc78e391a91f4ebe /drivers/net/wimax
parent67acd8b4b7a3f1b183ae358e1dfdb8a80e170736 (diff)
parent8a70da82edc50aa7a4b54864babf2d72538ba1bb (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (123 commits) wimax/i2400m: add CREDITS and MAINTAINERS entries wimax: export linux/wimax.h and linux/wimax/i2400m.h with headers_install i2400m: Makefile and Kconfig i2400m/SDIO: TX and RX path backends i2400m/SDIO: firmware upload backend i2400m/SDIO: probe/disconnect, dev init/shutdown and reset backends i2400m/SDIO: header for the SDIO subdriver i2400m/USB: TX and RX path backends i2400m/USB: firmware upload backend i2400m/USB: probe/disconnect, dev init/shutdown and reset backends i2400m/USB: header for the USB bus driver i2400m: debugfs controls i2400m: various functions for device management i2400m: RX and TX data/control paths i2400m: firmware loading and bootrom initialization i2400m: linkage to the networking stack i2400m: Generic probe/disconnect, reset and message passing i2400m: host/device procotol and core driver definitions i2400m: documentation and instructions for usage wimax: Makefile, Kconfig and docbook linkage for the stack ...
Diffstat (limited to 'drivers/net/wimax')
-rw-r--r--drivers/net/wimax/Kconfig17
-rw-r--r--drivers/net/wimax/Makefile5
-rw-r--r--drivers/net/wimax/i2400m/Kconfig49
-rw-r--r--drivers/net/wimax/i2400m/Makefile29
-rw-r--r--drivers/net/wimax/i2400m/control.c1291
-rw-r--r--drivers/net/wimax/i2400m/debug-levels.h45
-rw-r--r--drivers/net/wimax/i2400m/debugfs.c392
-rw-r--r--drivers/net/wimax/i2400m/driver.c728
-rw-r--r--drivers/net/wimax/i2400m/fw.c1095
-rw-r--r--drivers/net/wimax/i2400m/i2400m-sdio.h132
-rw-r--r--drivers/net/wimax/i2400m/i2400m-usb.h264
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h755
-rw-r--r--drivers/net/wimax/i2400m/netdev.c524
-rw-r--r--drivers/net/wimax/i2400m/op-rfkill.c207
-rw-r--r--drivers/net/wimax/i2400m/rx.c534
-rw-r--r--drivers/net/wimax/i2400m/sdio-debug-levels.h22
-rw-r--r--drivers/net/wimax/i2400m/sdio-fw.c224
-rw-r--r--drivers/net/wimax/i2400m/sdio-rx.c255
-rw-r--r--drivers/net/wimax/i2400m/sdio-tx.c153
-rw-r--r--drivers/net/wimax/i2400m/sdio.c511
-rw-r--r--drivers/net/wimax/i2400m/tx.c817
-rw-r--r--drivers/net/wimax/i2400m/usb-debug-levels.h42
-rw-r--r--drivers/net/wimax/i2400m/usb-fw.c340
-rw-r--r--drivers/net/wimax/i2400m/usb-notif.c269
-rw-r--r--drivers/net/wimax/i2400m/usb-rx.c417
-rw-r--r--drivers/net/wimax/i2400m/usb-tx.c229
-rw-r--r--drivers/net/wimax/i2400m/usb.c591
27 files changed, 9937 insertions, 0 deletions
diff --git a/drivers/net/wimax/Kconfig b/drivers/net/wimax/Kconfig
new file mode 100644
index 000000000000..565018ec1e3b
--- /dev/null
+++ b/drivers/net/wimax/Kconfig
@@ -0,0 +1,17 @@
1#
2# WiMAX LAN device drivers configuration
3#
4
5
6comment "Enable WiMAX (Networking options) to see the WiMAX drivers"
7 depends on WIMAX = n
8
9if WIMAX
10
11menu "WiMAX Wireless Broadband devices"
12
13source "drivers/net/wimax/i2400m/Kconfig"
14
15endmenu
16
17endif
diff --git a/drivers/net/wimax/Makefile b/drivers/net/wimax/Makefile
new file mode 100644
index 000000000000..992bc02bc016
--- /dev/null
+++ b/drivers/net/wimax/Makefile
@@ -0,0 +1,5 @@
1
2obj-$(CONFIG_WIMAX_I2400M) += i2400m/
3
4# (from Sam Ravnborg) force kbuild to create built-in.o
5obj- := dummy.o
diff --git a/drivers/net/wimax/i2400m/Kconfig b/drivers/net/wimax/i2400m/Kconfig
new file mode 100644
index 000000000000..d623b3d99a4b
--- /dev/null
+++ b/drivers/net/wimax/i2400m/Kconfig
@@ -0,0 +1,49 @@
1
2config WIMAX_I2400M
3 tristate
4 depends on WIMAX
5 select FW_LOADER
6
7comment "Enable USB support to see WiMAX USB drivers"
8 depends on USB = n
9
10comment "Enable MMC support to see WiMAX SDIO drivers"
11 depends on MMC = n
12
13config WIMAX_I2400M_USB
14 tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)"
15 depends on WIMAX && USB
16 select WIMAX_I2400M
17 help
18 Select if you have a device based on the Intel WiMAX
19 Connection 2400 over USB (like any of the Intel Wireless
20 WiMAX/WiFi Link 5x50 series).
21
22 If unsure, it is safe to select M (module).
23
24config WIMAX_I2400M_SDIO
25 tristate "Intel Wireless WiMAX Connection 2400 over SDIO"
26 depends on WIMAX && MMC
27 select WIMAX_I2400M
28 help
29 Select if you have a device based on the Intel WiMAX
30 Connection 2400 over SDIO.
31
32 If unsure, it is safe to select M (module).
33
34config WIMAX_I2400M_DEBUG_LEVEL
35 int "WiMAX i2400m debug level"
36 depends on WIMAX_I2400M
37 default 8
38 help
39
40 Select the maximum debug verbosity level to be compiled into
41 the WiMAX i2400m driver code.
42
43 By default, this is disabled at runtime and can be
44 selectively enabled at runtime for different parts of the
45 code using the sysfs debug-levels file.
46
47 If set at zero, this will compile out all the debug code.
48
49 It is recommended that it is left at 8.
diff --git a/drivers/net/wimax/i2400m/Makefile b/drivers/net/wimax/i2400m/Makefile
new file mode 100644
index 000000000000..1696e936cf5a
--- /dev/null
+++ b/drivers/net/wimax/i2400m/Makefile
@@ -0,0 +1,29 @@
1
2obj-$(CONFIG_WIMAX_I2400M) += i2400m.o
3obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o
4obj-$(CONFIG_WIMAX_I2400M_SDIO) += i2400m-sdio.o
5
6i2400m-y := \
7 control.o \
8 driver.o \
9 fw.o \
10 op-rfkill.o \
11 netdev.o \
12 tx.o \
13 rx.o
14
15i2400m-$(CONFIG_DEBUG_FS) += debugfs.o
16
17i2400m-usb-y := \
18 usb-fw.o \
19 usb-notif.o \
20 usb-tx.o \
21 usb-rx.o \
22 usb.o
23
24
25i2400m-sdio-y := \
26 sdio.o \
27 sdio-tx.o \
28 sdio-fw.o \
29 sdio-rx.o
diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c
new file mode 100644
index 000000000000..d3d37fed6893
--- /dev/null
+++ b/drivers/net/wimax/i2400m/control.c
@@ -0,0 +1,1291 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Miscellaneous control functions for managing the device
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
37 * - Initial implementation
38 *
39 * This is a collection of functions used to control the device (plus
40 * a few helpers).
41 *
42 * There are utilities for handling TLV buffers, hooks on the device's
43 * reports to act on device changes of state [i2400m_report_hook()],
44 * on acks to commands [i2400m_msg_ack_hook()], a helper for sending
45 * commands to the device and blocking until a reply arrives
46 * [i2400m_msg_to_dev()], a few high level commands for manipulating
47 * the device state, powersving mode and configuration plus the
48 * routines to setup the device once communication is stablished with
49 * it [i2400m_dev_initialize()].
50 *
51 * ROADMAP
52 *
53 * i2400m_dev_initalize() Called by i2400m_dev_start()
54 * i2400m_set_init_config()
55 * i2400m_firmware_check()
56 * i2400m_cmd_get_state()
57 * i2400m_dev_shutdown() Called by i2400m_dev_stop()
58 * i2400m->bus_reset()
59 *
60 * i2400m_{cmd,get,set}_*()
61 * i2400m_msg_to_dev()
62 * i2400m_msg_check_status()
63 *
64 * i2400m_report_hook() Called on reception of an event
65 * i2400m_report_state_hook()
66 * i2400m_tlv_buffer_walk()
67 * i2400m_tlv_match()
68 * i2400m_report_tlv_system_state()
69 * i2400m_report_tlv_rf_switches_status()
70 * i2400m_report_tlv_media_status()
71 * i2400m_cmd_enter_powersave()
72 *
73 * i2400m_msg_ack_hook() Called on reception of a reply to a
74 * command, get or set
75 */
76
77#include <stdarg.h>
78#include "i2400m.h"
79#include <linux/kernel.h>
80#include <linux/wimax/i2400m.h>
81
82
83#define D_SUBMODULE control
84#include "debug-levels.h"
85
86
87/*
88 * Return if a TLV is of a give type and size
89 *
90 * @tlv_hdr: pointer to the TLV
91 * @tlv_type: type of the TLV we are looking for
92 * @tlv_size: expected size of the TLV we are looking for (if -1,
93 * don't check the size). This includes the header
94 * Returns: 0 if the TLV matches
95 * < 0 if it doesn't match at all
96 * > 0 total TLV + payload size, if the type matches, but not
97 * the size
98 */
99static
100ssize_t i2400m_tlv_match(const struct i2400m_tlv_hdr *tlv,
101 enum i2400m_tlv tlv_type, ssize_t tlv_size)
102{
103 if (le16_to_cpu(tlv->type) != tlv_type) /* Not our type? skip */
104 return -1;
105 if (tlv_size != -1
106 && le16_to_cpu(tlv->length) + sizeof(*tlv) != tlv_size) {
107 size_t size = le16_to_cpu(tlv->length) + sizeof(*tlv);
108 printk(KERN_WARNING "W: tlv type 0x%x mismatched because of "
109 "size (got %zu vs %zu expected)\n",
110 tlv_type, size, tlv_size);
111 return size;
112 }
113 return 0;
114}
115
116
117/*
118 * Given a buffer of TLVs, iterate over them
119 *
120 * @i2400m: device instance
121 * @tlv_buf: pointer to the beginning of the TLV buffer
122 * @buf_size: buffer size in bytes
123 * @tlv_pos: seek position; this is assumed to be a pointer returned
124 * by i2400m_tlv_buffer_walk() [and thus, validated]. The
125 * TLV returned will be the one following this one.
126 *
127 * Usage:
128 *
129 * tlv_itr = NULL;
130 * while (tlv_itr = i2400m_tlv_buffer_walk(i2400m, buf, size, tlv_itr)) {
131 * ...
132 * // Do stuff with tlv_itr, DON'T MODIFY IT
133 * ...
134 * }
135 */
136static
137const struct i2400m_tlv_hdr *i2400m_tlv_buffer_walk(
138 struct i2400m *i2400m,
139 const void *tlv_buf, size_t buf_size,
140 const struct i2400m_tlv_hdr *tlv_pos)
141{
142 struct device *dev = i2400m_dev(i2400m);
143 const struct i2400m_tlv_hdr *tlv_top = tlv_buf + buf_size;
144 size_t offset, length, avail_size;
145 unsigned type;
146
147 if (tlv_pos == NULL) /* Take the first one? */
148 tlv_pos = tlv_buf;
149 else /* Nope, the next one */
150 tlv_pos = (void *) tlv_pos
151 + le16_to_cpu(tlv_pos->length) + sizeof(*tlv_pos);
152 if (tlv_pos == tlv_top) { /* buffer done */
153 tlv_pos = NULL;
154 goto error_beyond_end;
155 }
156 if (tlv_pos > tlv_top) {
157 tlv_pos = NULL;
158 WARN_ON(1);
159 goto error_beyond_end;
160 }
161 offset = (void *) tlv_pos - (void *) tlv_buf;
162 avail_size = buf_size - offset;
163 if (avail_size < sizeof(*tlv_pos)) {
164 dev_err(dev, "HW BUG? tlv_buf %p [%zu bytes], tlv @%zu: "
165 "short header\n", tlv_buf, buf_size, offset);
166 goto error_short_header;
167 }
168 type = le16_to_cpu(tlv_pos->type);
169 length = le16_to_cpu(tlv_pos->length);
170 if (avail_size < sizeof(*tlv_pos) + length) {
171 dev_err(dev, "HW BUG? tlv_buf %p [%zu bytes], "
172 "tlv type 0x%04x @%zu: "
173 "short data (%zu bytes vs %zu needed)\n",
174 tlv_buf, buf_size, type, offset, avail_size,
175 sizeof(*tlv_pos) + length);
176 goto error_short_header;
177 }
178error_short_header:
179error_beyond_end:
180 return tlv_pos;
181}
182
183
184/*
185 * Find a TLV in a buffer of sequential TLVs
186 *
187 * @i2400m: device descriptor
188 * @tlv_hdr: pointer to the first TLV in the sequence
189 * @size: size of the buffer in bytes; all TLVs are assumed to fit
190 * fully in the buffer (otherwise we'll complain).
191 * @tlv_type: type of the TLV we are looking for
192 * @tlv_size: expected size of the TLV we are looking for (if -1,
193 * don't check the size). This includes the header
194 *
195 * Returns: NULL if the TLV is not found, otherwise a pointer to
196 * it. If the sizes don't match, an error is printed and NULL
197 * returned.
198 */
199static
200const struct i2400m_tlv_hdr *i2400m_tlv_find(
201 struct i2400m *i2400m,
202 const struct i2400m_tlv_hdr *tlv_hdr, size_t size,
203 enum i2400m_tlv tlv_type, ssize_t tlv_size)
204{
205 ssize_t match;
206 struct device *dev = i2400m_dev(i2400m);
207 const struct i2400m_tlv_hdr *tlv = NULL;
208 while ((tlv = i2400m_tlv_buffer_walk(i2400m, tlv_hdr, size, tlv))) {
209 match = i2400m_tlv_match(tlv, tlv_type, tlv_size);
210 if (match == 0) /* found it :) */
211 break;
212 if (match > 0)
213 dev_warn(dev, "TLV type 0x%04x found with size "
214 "mismatch (%zu vs %zu needed)\n",
215 tlv_type, match, tlv_size);
216 }
217 return tlv;
218}
219
220
221static const struct
222{
223 char *msg;
224 int errno;
225} ms_to_errno[I2400M_MS_MAX] = {
226 [I2400M_MS_DONE_OK] = { "", 0 },
227 [I2400M_MS_DONE_IN_PROGRESS] = { "", 0 },
228 [I2400M_MS_INVALID_OP] = { "invalid opcode", -ENOSYS },
229 [I2400M_MS_BAD_STATE] = { "invalid state", -EILSEQ },
230 [I2400M_MS_ILLEGAL_VALUE] = { "illegal value", -EINVAL },
231 [I2400M_MS_MISSING_PARAMS] = { "missing parameters", -ENOMSG },
232 [I2400M_MS_VERSION_ERROR] = { "bad version", -EIO },
233 [I2400M_MS_ACCESSIBILITY_ERROR] = { "accesibility error", -EIO },
234 [I2400M_MS_BUSY] = { "busy", -EBUSY },
235 [I2400M_MS_CORRUPTED_TLV] = { "corrupted TLV", -EILSEQ },
236 [I2400M_MS_UNINITIALIZED] = { "not unitialized", -EILSEQ },
237 [I2400M_MS_UNKNOWN_ERROR] = { "unknown error", -EIO },
238 [I2400M_MS_PRODUCTION_ERROR] = { "production error", -EIO },
239 [I2400M_MS_NO_RF] = { "no RF", -EIO },
240 [I2400M_MS_NOT_READY_FOR_POWERSAVE] =
241 { "not ready for powersave", -EACCES },
242 [I2400M_MS_THERMAL_CRITICAL] = { "thermal critical", -EL3HLT },
243};
244
245
246/*
247 * i2400m_msg_check_status - translate a message's status code
248 *
249 * @i2400m: device descriptor
250 * @l3l4_hdr: message header
251 * @strbuf: buffer to place a formatted error message (unless NULL).
252 * @strbuf_size: max amount of available space; larger messages will
253 * be truncated.
254 *
255 * Returns: errno code corresponding to the status code in @l3l4_hdr
256 * and a message in @strbuf describing the error.
257 */
258int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *l3l4_hdr,
259 char *strbuf, size_t strbuf_size)
260{
261 int result;
262 enum i2400m_ms status = le16_to_cpu(l3l4_hdr->status);
263 const char *str;
264
265 if (status == 0)
266 return 0;
267 if (status > ARRAY_SIZE(ms_to_errno)) {
268 str = "unknown status code";
269 result = -EBADR;
270 } else {
271 str = ms_to_errno[status].msg;
272 result = ms_to_errno[status].errno;
273 }
274 if (strbuf)
275 snprintf(strbuf, strbuf_size, "%s (%d)", str, status);
276 return result;
277}
278
279
280/*
281 * Act on a TLV System State reported by the device
282 *
283 * @i2400m: device descriptor
284 * @ss: validated System State TLV
285 */
286static
287void i2400m_report_tlv_system_state(struct i2400m *i2400m,
288 const struct i2400m_tlv_system_state *ss)
289{
290 struct device *dev = i2400m_dev(i2400m);
291 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
292 enum i2400m_system_state i2400m_state = le32_to_cpu(ss->state);
293
294 d_fnstart(3, dev, "(i2400m %p ss %p [%u])\n", i2400m, ss, i2400m_state);
295
296 if (unlikely(i2400m->ready == 0)) /* act if up */
297 goto out;
298 if (i2400m->state != i2400m_state) {
299 i2400m->state = i2400m_state;
300 wake_up_all(&i2400m->state_wq);
301 }
302 switch (i2400m_state) {
303 case I2400M_SS_UNINITIALIZED:
304 case I2400M_SS_INIT:
305 case I2400M_SS_CONFIG:
306 case I2400M_SS_PRODUCTION:
307 wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED);
308 break;
309
310 case I2400M_SS_RF_OFF:
311 case I2400M_SS_RF_SHUTDOWN:
312 wimax_state_change(wimax_dev, WIMAX_ST_RADIO_OFF);
313 break;
314
315 case I2400M_SS_READY:
316 case I2400M_SS_STANDBY:
317 case I2400M_SS_SLEEPACTIVE:
318 wimax_state_change(wimax_dev, WIMAX_ST_READY);
319 break;
320
321 case I2400M_SS_CONNECTING:
322 case I2400M_SS_WIMAX_CONNECTED:
323 wimax_state_change(wimax_dev, WIMAX_ST_READY);
324 break;
325
326 case I2400M_SS_SCAN:
327 case I2400M_SS_OUT_OF_ZONE:
328 wimax_state_change(wimax_dev, WIMAX_ST_SCANNING);
329 break;
330
331 case I2400M_SS_IDLE:
332 d_printf(1, dev, "entering BS-negotiated idle mode\n");
333 case I2400M_SS_DISCONNECTING:
334 case I2400M_SS_DATA_PATH_CONNECTED:
335 wimax_state_change(wimax_dev, WIMAX_ST_CONNECTED);
336 break;
337
338 default:
339 /* Huh? just in case, shut it down */
340 dev_err(dev, "HW BUG? unknown state %u: shutting down\n",
341 i2400m_state);
342 i2400m->bus_reset(i2400m, I2400M_RT_WARM);
343 break;
344 };
345out:
346 d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n",
347 i2400m, ss, i2400m_state);
348}
349
350
351/*
352 * Parse and act on a TLV Media Status sent by the device
353 *
354 * @i2400m: device descriptor
355 * @ms: validated Media Status TLV
356 *
357 * This will set the carrier up on down based on the device's link
358 * report. This is done asides of what the WiMAX stack does based on
359 * the device's state as sometimes we need to do a link-renew (the BS
360 * wants us to renew a DHCP lease, for example).
361 *
362 * In fact, doc says that everytime we get a link-up, we should do a
363 * DHCP negotiation...
364 */
365static
366void i2400m_report_tlv_media_status(struct i2400m *i2400m,
367 const struct i2400m_tlv_media_status *ms)
368{
369 struct device *dev = i2400m_dev(i2400m);
370 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
371 struct net_device *net_dev = wimax_dev->net_dev;
372 enum i2400m_media_status status = le32_to_cpu(ms->media_status);
373
374 d_fnstart(3, dev, "(i2400m %p ms %p [%u])\n", i2400m, ms, status);
375
376 if (unlikely(i2400m->ready == 0)) /* act if up */
377 goto out;
378 switch (status) {
379 case I2400M_MEDIA_STATUS_LINK_UP:
380 netif_carrier_on(net_dev);
381 break;
382 case I2400M_MEDIA_STATUS_LINK_DOWN:
383 netif_carrier_off(net_dev);
384 break;
385 /*
386 * This is the network telling us we need to retrain the DHCP
387 * lease -- so far, we are trusting the WiMAX Network Service
388 * in user space to pick this up and poke the DHCP client.
389 */
390 case I2400M_MEDIA_STATUS_LINK_RENEW:
391 netif_carrier_on(net_dev);
392 break;
393 default:
394 dev_err(dev, "HW BUG? unknown media status %u\n",
395 status);
396 };
397out:
398 d_fnend(3, dev, "(i2400m %p ms %p [%u]) = void\n",
399 i2400m, ms, status);
400}
401
402
403/*
404 * Parse a 'state report' and extract carrier on/off information
405 *
406 * @i2400m: device descriptor
407 * @l3l4_hdr: pointer to message; it has been already validated for
408 * consistent size.
409 * @size: size of the message (header + payload). The header length
410 * declaration is assumed to be congruent with @size (as in
411 * sizeof(*l3l4_hdr) + l3l4_hdr->length == size)
412 *
413 * Extract from the report state the system state TLV and infer from
414 * there if we have a carrier or not. Update our local state and tell
415 * netdev.
416 *
417 * When setting the carrier, it's fine to set OFF twice (for example),
418 * as netif_carrier_off() will not generate two OFF events (just on
419 * the transitions).
420 */
421static
422void i2400m_report_state_hook(struct i2400m *i2400m,
423 const struct i2400m_l3l4_hdr *l3l4_hdr,
424 size_t size, const char *tag)
425{
426 struct device *dev = i2400m_dev(i2400m);
427 const struct i2400m_tlv_hdr *tlv;
428 const struct i2400m_tlv_system_state *ss;
429 const struct i2400m_tlv_rf_switches_status *rfss;
430 const struct i2400m_tlv_media_status *ms;
431 size_t tlv_size = le16_to_cpu(l3l4_hdr->length);
432
433 d_fnstart(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s)\n",
434 i2400m, l3l4_hdr, size, tag);
435 tlv = NULL;
436
437 while ((tlv = i2400m_tlv_buffer_walk(i2400m, &l3l4_hdr->pl,
438 tlv_size, tlv))) {
439 if (0 == i2400m_tlv_match(tlv, I2400M_TLV_SYSTEM_STATE,
440 sizeof(*ss))) {
441 ss = container_of(tlv, typeof(*ss), hdr);
442 d_printf(2, dev, "%s: system state TLV "
443 "found (0x%04x), state 0x%08x\n",
444 tag, I2400M_TLV_SYSTEM_STATE,
445 le32_to_cpu(ss->state));
446 i2400m_report_tlv_system_state(i2400m, ss);
447 }
448 if (0 == i2400m_tlv_match(tlv, I2400M_TLV_RF_STATUS,
449 sizeof(*rfss))) {
450 rfss = container_of(tlv, typeof(*rfss), hdr);
451 d_printf(2, dev, "%s: RF status TLV "
452 "found (0x%04x), sw 0x%02x hw 0x%02x\n",
453 tag, I2400M_TLV_RF_STATUS,
454 le32_to_cpu(rfss->sw_rf_switch),
455 le32_to_cpu(rfss->hw_rf_switch));
456 i2400m_report_tlv_rf_switches_status(i2400m, rfss);
457 }
458 if (0 == i2400m_tlv_match(tlv, I2400M_TLV_MEDIA_STATUS,
459 sizeof(*ms))) {
460 ms = container_of(tlv, typeof(*ms), hdr);
461 d_printf(2, dev, "%s: Media Status TLV: %u\n",
462 tag, le32_to_cpu(ms->media_status));
463 i2400m_report_tlv_media_status(i2400m, ms);
464 }
465 }
466 d_fnend(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s) = void\n",
467 i2400m, l3l4_hdr, size, tag);
468}
469
470
471/*
472 * i2400m_report_hook - (maybe) act on a report
473 *
474 * @i2400m: device descriptor
475 * @l3l4_hdr: pointer to message; it has been already validated for
476 * consistent size.
477 * @size: size of the message (header + payload). The header length
478 * declaration is assumed to be congruent with @size (as in
479 * sizeof(*l3l4_hdr) + l3l4_hdr->length == size)
480 *
481 * Extract information we might need (like carrien on/off) from a
482 * device report.
483 */
484void i2400m_report_hook(struct i2400m *i2400m,
485 const struct i2400m_l3l4_hdr *l3l4_hdr, size_t size)
486{
487 struct device *dev = i2400m_dev(i2400m);
488 unsigned msg_type;
489
490 d_fnstart(3, dev, "(i2400m %p l3l4_hdr %p size %zu)\n",
491 i2400m, l3l4_hdr, size);
492 /* Chew on the message, we might need some information from
493 * here */
494 msg_type = le16_to_cpu(l3l4_hdr->type);
495 switch (msg_type) {
496 case I2400M_MT_REPORT_STATE: /* carrier detection... */
497 i2400m_report_state_hook(i2400m,
498 l3l4_hdr, size, "REPORT STATE");
499 break;
500 /* If the device is ready for power save, then ask it to do
501 * it. */
502 case I2400M_MT_REPORT_POWERSAVE_READY: /* zzzzz */
503 if (l3l4_hdr->status == cpu_to_le16(I2400M_MS_DONE_OK)) {
504 d_printf(1, dev, "ready for powersave, requesting\n");
505 i2400m_cmd_enter_powersave(i2400m);
506 }
507 break;
508 };
509 d_fnend(3, dev, "(i2400m %p l3l4_hdr %p size %zu) = void\n",
510 i2400m, l3l4_hdr, size);
511}
512
513
514/*
515 * i2400m_msg_ack_hook - process cmd/set/get ack for internal status
516 *
517 * @i2400m: device descriptor
518 * @l3l4_hdr: pointer to message; it has been already validated for
519 * consistent size.
520 * @size: size of the message
521 *
522 * Extract information we might need from acks to commands and act on
523 * it. This is akin to i2400m_report_hook(). Note most of this
524 * processing should be done in the function that calls the
525 * command. This is here for some cases where it can't happen...
526 */
527void i2400m_msg_ack_hook(struct i2400m *i2400m,
528 const struct i2400m_l3l4_hdr *l3l4_hdr, size_t size)
529{
530 int result;
531 struct device *dev = i2400m_dev(i2400m);
532 unsigned ack_type, ack_status;
533 char strerr[32];
534
535 /* Chew on the message, we might need some information from
536 * here */
537 ack_type = le16_to_cpu(l3l4_hdr->type);
538 ack_status = le16_to_cpu(l3l4_hdr->status);
539 switch (ack_type) {
540 case I2400M_MT_CMD_ENTER_POWERSAVE:
541 /* This is just left here for the sake of example, as
542 * the processing is done somewhere else. */
543 if (0) {
544 result = i2400m_msg_check_status(
545 l3l4_hdr, strerr, sizeof(strerr));
546 if (result >= 0)
547 d_printf(1, dev, "ready for power save: %zd\n",
548 size);
549 }
550 break;
551 };
552 return;
553}
554
555
556/*
557 * i2400m_msg_size_check() - verify message size and header are congruent
558 *
559 * It is ok if the total message size is larger than the expected
560 * size, as there can be padding.
561 */
562int i2400m_msg_size_check(struct i2400m *i2400m,
563 const struct i2400m_l3l4_hdr *l3l4_hdr,
564 size_t msg_size)
565{
566 int result;
567 struct device *dev = i2400m_dev(i2400m);
568 size_t expected_size;
569 d_fnstart(4, dev, "(i2400m %p l3l4_hdr %p msg_size %zu)\n",
570 i2400m, l3l4_hdr, msg_size);
571 if (msg_size < sizeof(*l3l4_hdr)) {
572 dev_err(dev, "bad size for message header "
573 "(expected at least %zu, got %zu)\n",
574 (size_t) sizeof(*l3l4_hdr), msg_size);
575 result = -EIO;
576 goto error_hdr_size;
577 }
578 expected_size = le16_to_cpu(l3l4_hdr->length) + sizeof(*l3l4_hdr);
579 if (msg_size < expected_size) {
580 dev_err(dev, "bad size for message code 0x%04x (expected %zu, "
581 "got %zu)\n", le16_to_cpu(l3l4_hdr->type),
582 expected_size, msg_size);
583 result = -EIO;
584 } else
585 result = 0;
586error_hdr_size:
587 d_fnend(4, dev,
588 "(i2400m %p l3l4_hdr %p msg_size %zu) = %d\n",
589 i2400m, l3l4_hdr, msg_size, result);
590 return result;
591}
592
593
594
595/*
596 * Cancel a wait for a command ACK
597 *
598 * @i2400m: device descriptor
599 * @code: [negative] errno code to cancel with (don't use
600 * -EINPROGRESS)
601 *
602 * If there is an ack already filled out, free it.
603 */
604void i2400m_msg_to_dev_cancel_wait(struct i2400m *i2400m, int code)
605{
606 struct sk_buff *ack_skb;
607 unsigned long flags;
608
609 spin_lock_irqsave(&i2400m->rx_lock, flags);
610 ack_skb = i2400m->ack_skb;
611 if (ack_skb && !IS_ERR(ack_skb))
612 kfree(ack_skb);
613 i2400m->ack_skb = ERR_PTR(code);
614 spin_unlock_irqrestore(&i2400m->rx_lock, flags);
615}
616
617
618/**
619 * i2400m_msg_to_dev - Send a control message to the device and get a response
620 *
621 * @i2400m: device descriptor
622 *
623 * @msg_skb: an skb *
624 *
625 * @buf: pointer to the buffer containing the message to be sent; it
626 * has to start with a &struct i2400M_l3l4_hdr and then
627 * followed by the payload. Once this function returns, the
628 * buffer can be reused.
629 *
630 * @buf_len: buffer size
631 *
632 * Returns:
633 *
634 * Pointer to skb containing the ack message. You need to check the
635 * pointer with IS_ERR(), as it might be an error code. Error codes
636 * could happen because:
637 *
638 * - the message wasn't formatted correctly
639 * - couldn't send the message
640 * - failed waiting for a response
641 * - the ack message wasn't formatted correctly
642 *
643 * The returned skb has been allocated with wimax_msg_to_user_alloc(),
644 * it contains the reponse in a netlink attribute and is ready to be
645 * passed up to user space with wimax_msg_to_user_send(). To access
646 * the payload and its length, use wimax_msg_{data,len}() on the skb.
647 *
648 * The skb has to be freed with kfree_skb() once done.
649 *
650 * Description:
651 *
652 * This function delivers a message/command to the device and waits
653 * for an ack to be received. The format is described in
654 * linux/wimax/i2400m.h. In summary, a command/get/set is followed by an
655 * ack.
656 *
657 * This function will not check the ack status, that's left up to the
658 * caller. Once done with the ack skb, it has to be kfree_skb()ed.
659 *
660 * The i2400m handles only one message at the same time, thus we need
661 * the mutex to exclude other players.
662 *
663 * We write the message and then wait for an answer to come back. The
664 * RX path intercepts control messages and handles them in
665 * i2400m_rx_ctl(). Reports (notifications) are (maybe) processed
666 * locally and then forwarded (as needed) to user space on the WiMAX
667 * stack message pipe. Acks are saved and passed back to us through an
668 * skb in i2400m->ack_skb which is ready to be given to generic
669 * netlink if need be.
670 */
671struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m,
672 const void *buf, size_t buf_len)
673{
674 int result;
675 struct device *dev = i2400m_dev(i2400m);
676 const struct i2400m_l3l4_hdr *msg_l3l4_hdr;
677 struct sk_buff *ack_skb;
678 const struct i2400m_l3l4_hdr *ack_l3l4_hdr;
679 size_t ack_len;
680 int ack_timeout;
681 unsigned msg_type;
682 unsigned long flags;
683
684 d_fnstart(3, dev, "(i2400m %p buf %p len %zu)\n",
685 i2400m, buf, buf_len);
686
687 if (i2400m->boot_mode)
688 return ERR_PTR(-ENODEV);
689
690 msg_l3l4_hdr = buf;
691 /* Check msg & payload consistency */
692 result = i2400m_msg_size_check(i2400m, msg_l3l4_hdr, buf_len);
693 if (result < 0)
694 goto error_bad_msg;
695 msg_type = le16_to_cpu(msg_l3l4_hdr->type);
696 d_printf(1, dev, "CMD/GET/SET 0x%04x %zu bytes\n",
697 msg_type, buf_len);
698 d_dump(2, dev, buf, buf_len);
699
700 /* Setup the completion, ack_skb ("we are waiting") and send
701 * the message to the device */
702 mutex_lock(&i2400m->msg_mutex);
703 spin_lock_irqsave(&i2400m->rx_lock, flags);
704 i2400m->ack_skb = ERR_PTR(-EINPROGRESS);
705 spin_unlock_irqrestore(&i2400m->rx_lock, flags);
706 init_completion(&i2400m->msg_completion);
707 result = i2400m_tx(i2400m, buf, buf_len, I2400M_PT_CTRL);
708 if (result < 0) {
709 dev_err(dev, "can't send message 0x%04x: %d\n",
710 le16_to_cpu(msg_l3l4_hdr->type), result);
711 goto error_tx;
712 }
713
714 /* Some commands take longer to execute because of crypto ops,
715 * so we give them some more leeway on timeout */
716 switch (msg_type) {
717 case I2400M_MT_GET_TLS_OPERATION_RESULT:
718 case I2400M_MT_CMD_SEND_EAP_RESPONSE:
719 ack_timeout = 5 * HZ;
720 break;
721 default:
722 ack_timeout = HZ;
723 };
724
725 /* The RX path in rx.c will put any response for this message
726 * in i2400m->ack_skb and wake us up. If we cancel the wait,
727 * we need to change the value of i2400m->ack_skb to something
728 * not -EINPROGRESS so RX knows there is no one waiting. */
729 result = wait_for_completion_interruptible_timeout(
730 &i2400m->msg_completion, ack_timeout);
731 if (result == 0) {
732 dev_err(dev, "timeout waiting for reply to message 0x%04x\n",
733 msg_type);
734 result = -ETIMEDOUT;
735 i2400m_msg_to_dev_cancel_wait(i2400m, result);
736 goto error_wait_for_completion;
737 } else if (result < 0) {
738 dev_err(dev, "error waiting for reply to message 0x%04x: %d\n",
739 msg_type, result);
740 i2400m_msg_to_dev_cancel_wait(i2400m, result);
741 goto error_wait_for_completion;
742 }
743
744 /* Pull out the ack data from i2400m->ack_skb -- see if it is
745 * an error and act accordingly */
746 spin_lock_irqsave(&i2400m->rx_lock, flags);
747 ack_skb = i2400m->ack_skb;
748 if (IS_ERR(ack_skb))
749 result = PTR_ERR(ack_skb);
750 else
751 result = 0;
752 i2400m->ack_skb = NULL;
753 spin_unlock_irqrestore(&i2400m->rx_lock, flags);
754 if (result < 0)
755 goto error_ack_status;
756 ack_l3l4_hdr = wimax_msg_data_len(ack_skb, &ack_len);
757
758 /* Check the ack and deliver it if it is ok */
759 result = i2400m_msg_size_check(i2400m, ack_l3l4_hdr, ack_len);
760 if (result < 0) {
761 dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n",
762 msg_type, result);
763 goto error_bad_ack_len;
764 }
765 if (msg_type != le16_to_cpu(ack_l3l4_hdr->type)) {
766 dev_err(dev, "HW BUG? bad reply 0x%04x to message 0x%04x\n",
767 le16_to_cpu(ack_l3l4_hdr->type), msg_type);
768 result = -EIO;
769 goto error_bad_ack_type;
770 }
771 i2400m_msg_ack_hook(i2400m, ack_l3l4_hdr, ack_len);
772 mutex_unlock(&i2400m->msg_mutex);
773 d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %p\n",
774 i2400m, buf, buf_len, ack_skb);
775 return ack_skb;
776
777error_bad_ack_type:
778error_bad_ack_len:
779 kfree_skb(ack_skb);
780error_ack_status:
781error_wait_for_completion:
782error_tx:
783 mutex_unlock(&i2400m->msg_mutex);
784error_bad_msg:
785 d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %d\n",
786 i2400m, buf, buf_len, result);
787 return ERR_PTR(result);
788}
789
790
791/*
792 * Definitions for the Enter Power Save command
793 *
794 * The Enter Power Save command requests the device to go into power
795 * saving mode. The device will ack or nak the command depending on it
796 * being ready for it. If it acks, we tell the USB subsystem to
797 *
798 * As well, the device might request to go into power saving mode by
799 * sending a report (REPORT_POWERSAVE_READY), in which case, we issue
800 * this command. The hookups in the RX coder allow
801 */
802enum {
803 I2400M_WAKEUP_ENABLED = 0x01,
804 I2400M_WAKEUP_DISABLED = 0x02,
805 I2400M_TLV_TYPE_WAKEUP_MODE = 144,
806};
807
808struct i2400m_cmd_enter_power_save {
809 struct i2400m_l3l4_hdr hdr;
810 struct i2400m_tlv_hdr tlv;
811 __le32 val;
812} __attribute__((packed));
813
814
815/*
816 * Request entering power save
817 *
818 * This command is (mainly) executed when the device indicates that it
819 * is ready to go into powersave mode via a REPORT_POWERSAVE_READY.
820 */
821int i2400m_cmd_enter_powersave(struct i2400m *i2400m)
822{
823 int result;
824 struct device *dev = i2400m_dev(i2400m);
825 struct sk_buff *ack_skb;
826 struct i2400m_cmd_enter_power_save *cmd;
827 char strerr[32];
828
829 result = -ENOMEM;
830 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
831 if (cmd == NULL)
832 goto error_alloc;
833 cmd->hdr.type = cpu_to_le16(I2400M_MT_CMD_ENTER_POWERSAVE);
834 cmd->hdr.length = cpu_to_le16(sizeof(*cmd) - sizeof(cmd->hdr));
835 cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION);
836 cmd->tlv.type = cpu_to_le16(I2400M_TLV_TYPE_WAKEUP_MODE);
837 cmd->tlv.length = cpu_to_le16(sizeof(cmd->val));
838 cmd->val = cpu_to_le32(I2400M_WAKEUP_ENABLED);
839
840 ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
841 result = PTR_ERR(ack_skb);
842 if (IS_ERR(ack_skb)) {
843 dev_err(dev, "Failed to issue 'Enter power save' command: %d\n",
844 result);
845 goto error_msg_to_dev;
846 }
847 result = i2400m_msg_check_status(wimax_msg_data(ack_skb),
848 strerr, sizeof(strerr));
849 if (result == -EACCES)
850 d_printf(1, dev, "Cannot enter power save mode\n");
851 else if (result < 0)
852 dev_err(dev, "'Enter power save' (0x%04x) command failed: "
853 "%d - %s\n", I2400M_MT_CMD_ENTER_POWERSAVE,
854 result, strerr);
855 else
856 d_printf(1, dev, "device ready to power save\n");
857 kfree_skb(ack_skb);
858error_msg_to_dev:
859 kfree(cmd);
860error_alloc:
861 return result;
862}
863EXPORT_SYMBOL_GPL(i2400m_cmd_enter_powersave);
864
865
866/*
867 * Definitions for getting device information
868 */
869enum {
870 I2400M_TLV_DETAILED_DEVICE_INFO = 140
871};
872
873/**
874 * i2400m_get_device_info - Query the device for detailed device information
875 *
876 * @i2400m: device descriptor
877 *
878 * Returns: an skb whose skb->data points to a 'struct
879 * i2400m_tlv_detailed_device_info'. When done, kfree_skb() it. The
880 * skb is *guaranteed* to contain the whole TLV data structure.
881 *
882 * On error, IS_ERR(skb) is true and ERR_PTR(skb) is the error
883 * code.
884 */
885struct sk_buff *i2400m_get_device_info(struct i2400m *i2400m)
886{
887 int result;
888 struct device *dev = i2400m_dev(i2400m);
889 struct sk_buff *ack_skb;
890 struct i2400m_l3l4_hdr *cmd;
891 const struct i2400m_l3l4_hdr *ack;
892 size_t ack_len;
893 const struct i2400m_tlv_hdr *tlv;
894 const struct i2400m_tlv_detailed_device_info *ddi;
895 char strerr[32];
896
897 ack_skb = ERR_PTR(-ENOMEM);
898 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
899 if (cmd == NULL)
900 goto error_alloc;
901 cmd->type = cpu_to_le16(I2400M_MT_GET_DEVICE_INFO);
902 cmd->length = 0;
903 cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
904
905 ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
906 if (IS_ERR(ack_skb)) {
907 dev_err(dev, "Failed to issue 'get device info' command: %ld\n",
908 PTR_ERR(ack_skb));
909 goto error_msg_to_dev;
910 }
911 ack = wimax_msg_data_len(ack_skb, &ack_len);
912 result = i2400m_msg_check_status(ack, strerr, sizeof(strerr));
913 if (result < 0) {
914 dev_err(dev, "'get device info' (0x%04x) command failed: "
915 "%d - %s\n", I2400M_MT_GET_DEVICE_INFO, result,
916 strerr);
917 goto error_cmd_failed;
918 }
919 tlv = i2400m_tlv_find(i2400m, ack->pl, ack_len - sizeof(*ack),
920 I2400M_TLV_DETAILED_DEVICE_INFO, sizeof(*ddi));
921 if (tlv == NULL) {
922 dev_err(dev, "GET DEVICE INFO: "
923 "detailed device info TLV not found (0x%04x)\n",
924 I2400M_TLV_DETAILED_DEVICE_INFO);
925 result = -EIO;
926 goto error_no_tlv;
927 }
928 skb_pull(ack_skb, (void *) tlv - (void *) ack_skb->data);
929error_msg_to_dev:
930 kfree(cmd);
931error_alloc:
932 return ack_skb;
933
934error_no_tlv:
935error_cmd_failed:
936 kfree_skb(ack_skb);
937 kfree(cmd);
938 return ERR_PTR(result);
939}
940
941
942/* Firmware interface versions we support */
943enum {
944 I2400M_HDIv_MAJOR = 9,
945 I2400M_HDIv_MAJOR_2 = 8,
946 I2400M_HDIv_MINOR = 1,
947};
948
949
950/**
951 * i2400m_firmware_check - check firmware versions are compatible with
952 * the driver
953 *
954 * @i2400m: device descriptor
955 *
956 * Returns: 0 if ok, < 0 errno code an error and a message in the
957 * kernel log.
958 *
959 * Long function, but quite simple; first chunk launches the command
960 * and double checks the reply for the right TLV. Then we process the
961 * TLV (where the meat is).
962 */
963int i2400m_firmware_check(struct i2400m *i2400m)
964{
965 int result;
966 struct device *dev = i2400m_dev(i2400m);
967 struct sk_buff *ack_skb;
968 struct i2400m_l3l4_hdr *cmd;
969 const struct i2400m_l3l4_hdr *ack;
970 size_t ack_len;
971 const struct i2400m_tlv_hdr *tlv;
972 const struct i2400m_tlv_l4_message_versions *l4mv;
973 char strerr[32];
974 unsigned major, minor, branch;
975
976 result = -ENOMEM;
977 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
978 if (cmd == NULL)
979 goto error_alloc;
980 cmd->type = cpu_to_le16(I2400M_MT_GET_LM_VERSION);
981 cmd->length = 0;
982 cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
983
984 ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
985 if (IS_ERR(ack_skb)) {
986 result = PTR_ERR(ack_skb);
987 dev_err(dev, "Failed to issue 'get lm version' command: %-d\n",
988 result);
989 goto error_msg_to_dev;
990 }
991 ack = wimax_msg_data_len(ack_skb, &ack_len);
992 result = i2400m_msg_check_status(ack, strerr, sizeof(strerr));
993 if (result < 0) {
994 dev_err(dev, "'get lm version' (0x%04x) command failed: "
995 "%d - %s\n", I2400M_MT_GET_LM_VERSION, result,
996 strerr);
997 goto error_cmd_failed;
998 }
999 tlv = i2400m_tlv_find(i2400m, ack->pl, ack_len - sizeof(*ack),
1000 I2400M_TLV_L4_MESSAGE_VERSIONS, sizeof(*l4mv));
1001 if (tlv == NULL) {
1002 dev_err(dev, "get lm version: TLV not found (0x%04x)\n",
1003 I2400M_TLV_L4_MESSAGE_VERSIONS);
1004 result = -EIO;
1005 goto error_no_tlv;
1006 }
1007 l4mv = container_of(tlv, typeof(*l4mv), hdr);
1008 major = le16_to_cpu(l4mv->major);
1009 minor = le16_to_cpu(l4mv->minor);
1010 branch = le16_to_cpu(l4mv->branch);
1011 result = -EINVAL;
1012 if (major != I2400M_HDIv_MAJOR
1013 && major != I2400M_HDIv_MAJOR_2) {
1014 dev_err(dev, "unsupported major fw interface version "
1015 "%u.%u.%u\n", major, minor, branch);
1016 goto error_bad_major;
1017 }
1018 if (major == I2400M_HDIv_MAJOR_2)
1019 dev_err(dev, "deprecated major fw interface version "
1020 "%u.%u.%u\n", major, minor, branch);
1021 result = 0;
1022 if (minor != I2400M_HDIv_MINOR)
1023 dev_warn(dev, "untested minor fw firmware version %u.%u.%u\n",
1024 major, minor, branch);
1025error_bad_major:
1026 dev_info(dev, "firmware interface version %u.%u.%u\n",
1027 major, minor, branch);
1028error_no_tlv:
1029error_cmd_failed:
1030 kfree_skb(ack_skb);
1031error_msg_to_dev:
1032 kfree(cmd);
1033error_alloc:
1034 return result;
1035}
1036
1037
1038/*
1039 * Send an DoExitIdle command to the device to ask it to go out of
1040 * basestation-idle mode.
1041 *
1042 * @i2400m: device descriptor
1043 *
1044 * This starts a renegotiation with the basestation that might involve
1045 * another crypto handshake with user space.
1046 *
1047 * Returns: 0 if ok, < 0 errno code on error.
1048 */
1049int i2400m_cmd_exit_idle(struct i2400m *i2400m)
1050{
1051 int result;
1052 struct device *dev = i2400m_dev(i2400m);
1053 struct sk_buff *ack_skb;
1054 struct i2400m_l3l4_hdr *cmd;
1055 char strerr[32];
1056
1057 result = -ENOMEM;
1058 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1059 if (cmd == NULL)
1060 goto error_alloc;
1061 cmd->type = cpu_to_le16(I2400M_MT_CMD_EXIT_IDLE);
1062 cmd->length = 0;
1063 cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
1064
1065 ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
1066 result = PTR_ERR(ack_skb);
1067 if (IS_ERR(ack_skb)) {
1068 dev_err(dev, "Failed to issue 'exit idle' command: %d\n",
1069 result);
1070 goto error_msg_to_dev;
1071 }
1072 result = i2400m_msg_check_status(wimax_msg_data(ack_skb),
1073 strerr, sizeof(strerr));
1074 kfree_skb(ack_skb);
1075error_msg_to_dev:
1076 kfree(cmd);
1077error_alloc:
1078 return result;
1079
1080}
1081
1082
1083/*
1084 * Query the device for its state, update the WiMAX stack's idea of it
1085 *
1086 * @i2400m: device descriptor
1087 *
1088 * Returns: 0 if ok, < 0 errno code on error.
1089 *
1090 * Executes a 'Get State' command and parses the returned
1091 * TLVs.
1092 *
1093 * Because this is almost identical to a 'Report State', we use
1094 * i2400m_report_state_hook() to parse the answer. This will set the
1095 * carrier state, as well as the RF Kill switches state.
1096 */
1097int i2400m_cmd_get_state(struct i2400m *i2400m)
1098{
1099 int result;
1100 struct device *dev = i2400m_dev(i2400m);
1101 struct sk_buff *ack_skb;
1102 struct i2400m_l3l4_hdr *cmd;
1103 const struct i2400m_l3l4_hdr *ack;
1104 size_t ack_len;
1105 char strerr[32];
1106
1107 result = -ENOMEM;
1108 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1109 if (cmd == NULL)
1110 goto error_alloc;
1111 cmd->type = cpu_to_le16(I2400M_MT_GET_STATE);
1112 cmd->length = 0;
1113 cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
1114
1115 ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
1116 if (IS_ERR(ack_skb)) {
1117 dev_err(dev, "Failed to issue 'get state' command: %ld\n",
1118 PTR_ERR(ack_skb));
1119 result = PTR_ERR(ack_skb);
1120 goto error_msg_to_dev;
1121 }
1122 ack = wimax_msg_data_len(ack_skb, &ack_len);
1123 result = i2400m_msg_check_status(ack, strerr, sizeof(strerr));
1124 if (result < 0) {
1125 dev_err(dev, "'get state' (0x%04x) command failed: "
1126 "%d - %s\n", I2400M_MT_GET_STATE, result, strerr);
1127 goto error_cmd_failed;
1128 }
1129 i2400m_report_state_hook(i2400m, ack, ack_len - sizeof(*ack),
1130 "GET STATE");
1131 result = 0;
1132 kfree_skb(ack_skb);
1133error_cmd_failed:
1134error_msg_to_dev:
1135 kfree(cmd);
1136error_alloc:
1137 return result;
1138}
1139EXPORT_SYMBOL_GPL(i2400m_cmd_get_state);
1140
1141
1142/**
1143 * Set basic configuration settings
1144 *
1145 * @i2400m: device descriptor
1146 * @args: array of pointers to the TLV headers to send for
1147 * configuration (each followed by its payload).
1148 * TLV headers and payloads must be properly initialized, with the
1149 * right endianess (LE).
1150 * @arg_size: number of pointers in the @args array
1151 */
1152int i2400m_set_init_config(struct i2400m *i2400m,
1153 const struct i2400m_tlv_hdr **arg, size_t args)
1154{
1155 int result;
1156 struct device *dev = i2400m_dev(i2400m);
1157 struct sk_buff *ack_skb;
1158 struct i2400m_l3l4_hdr *cmd;
1159 char strerr[32];
1160 unsigned argc, argsize, tlv_size;
1161 const struct i2400m_tlv_hdr *tlv_hdr;
1162 void *buf, *itr;
1163
1164 d_fnstart(3, dev, "(i2400m %p arg %p args %zu)\n", i2400m, arg, args);
1165 result = 0;
1166 if (args == 0)
1167 goto none;
1168 /* Compute the size of all the TLVs, so we can alloc a
1169 * contiguous command block to copy them. */
1170 argsize = 0;
1171 for (argc = 0; argc < args; argc++) {
1172 tlv_hdr = arg[argc];
1173 argsize += sizeof(*tlv_hdr) + le16_to_cpu(tlv_hdr->length);
1174 }
1175 WARN_ON(argc >= 9); /* As per hw spec */
1176
1177 /* Alloc the space for the command and TLVs*/
1178 result = -ENOMEM;
1179 buf = kzalloc(sizeof(*cmd) + argsize, GFP_KERNEL);
1180 if (buf == NULL)
1181 goto error_alloc;
1182 cmd = buf;
1183 cmd->type = cpu_to_le16(I2400M_MT_SET_INIT_CONFIG);
1184 cmd->length = cpu_to_le16(argsize);
1185 cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
1186
1187 /* Copy the TLVs */
1188 itr = buf + sizeof(*cmd);
1189 for (argc = 0; argc < args; argc++) {
1190 tlv_hdr = arg[argc];
1191 tlv_size = sizeof(*tlv_hdr) + le16_to_cpu(tlv_hdr->length);
1192 memcpy(itr, tlv_hdr, tlv_size);
1193 itr += tlv_size;
1194 }
1195
1196 /* Send the message! */
1197 ack_skb = i2400m_msg_to_dev(i2400m, buf, sizeof(*cmd) + argsize);
1198 result = PTR_ERR(ack_skb);
1199 if (IS_ERR(ack_skb)) {
1200 dev_err(dev, "Failed to issue 'init config' command: %d\n",
1201 result);
1202
1203 goto error_msg_to_dev;
1204 }
1205 result = i2400m_msg_check_status(wimax_msg_data(ack_skb),
1206 strerr, sizeof(strerr));
1207 if (result < 0)
1208 dev_err(dev, "'init config' (0x%04x) command failed: %d - %s\n",
1209 I2400M_MT_SET_INIT_CONFIG, result, strerr);
1210 kfree_skb(ack_skb);
1211error_msg_to_dev:
1212 kfree(buf);
1213error_alloc:
1214none:
1215 d_fnend(3, dev, "(i2400m %p arg %p args %zu) = %d\n",
1216 i2400m, arg, args, result);
1217 return result;
1218
1219}
1220EXPORT_SYMBOL_GPL(i2400m_set_init_config);
1221
1222
1223/**
1224 * i2400m_dev_initialize - Initialize the device once communications are ready
1225 *
1226 * @i2400m: device descriptor
1227 *
1228 * Returns: 0 if ok, < 0 errno code on error.
1229 *
1230 * Configures the device to work the way we like it.
1231 *
1232 * At the point of this call, the device is registered with the WiMAX
1233 * and netdev stacks, firmware is uploaded and we can talk to the
1234 * device normally.
1235 */
1236int i2400m_dev_initialize(struct i2400m *i2400m)
1237{
1238 int result;
1239 struct device *dev = i2400m_dev(i2400m);
1240 struct i2400m_tlv_config_idle_parameters idle_params;
1241 const struct i2400m_tlv_hdr *args[9];
1242 unsigned argc = 0;
1243
1244 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
1245 /* Useless for now...might change */
1246 if (i2400m_idle_mode_disabled) {
1247 idle_params.hdr.type =
1248 cpu_to_le16(I2400M_TLV_CONFIG_IDLE_PARAMETERS);
1249 idle_params.hdr.length = cpu_to_le16(
1250 sizeof(idle_params) - sizeof(idle_params.hdr));
1251 idle_params.idle_timeout = 0;
1252 idle_params.idle_paging_interval = 0;
1253 args[argc++] = &idle_params.hdr;
1254 }
1255 result = i2400m_set_init_config(i2400m, args, argc);
1256 if (result < 0)
1257 goto error;
1258 result = i2400m_firmware_check(i2400m); /* fw versions ok? */
1259 if (result < 0)
1260 goto error;
1261 /*
1262 * Update state: Here it just calls a get state; parsing the
1263 * result (System State TLV and RF Status TLV [done in the rx
1264 * path hooks]) will set the hardware and software RF-Kill
1265 * status.
1266 */
1267 result = i2400m_cmd_get_state(i2400m);
1268error:
1269 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
1270 return result;
1271}
1272
1273
1274/**
1275 * i2400m_dev_shutdown - Shutdown a running device
1276 *
1277 * @i2400m: device descriptor
1278 *
1279 * Gracefully stops the device, moving it to the lowest power
1280 * consumption state possible.
1281 */
1282void i2400m_dev_shutdown(struct i2400m *i2400m)
1283{
1284 int result = -ENODEV;
1285 struct device *dev = i2400m_dev(i2400m);
1286
1287 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
1288 result = i2400m->bus_reset(i2400m, I2400M_RT_WARM);
1289 d_fnend(3, dev, "(i2400m %p) = void [%d]\n", i2400m, result);
1290 return;
1291}
diff --git a/drivers/net/wimax/i2400m/debug-levels.h b/drivers/net/wimax/i2400m/debug-levels.h
new file mode 100644
index 000000000000..3183baa16a52
--- /dev/null
+++ b/drivers/net/wimax/i2400m/debug-levels.h
@@ -0,0 +1,45 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Debug levels control file for the i2400m module
4 *
5 *
6 * Copyright (C) 2007-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#ifndef __debug_levels__h__
24#define __debug_levels__h__
25
26/* Maximum compile and run time debug level for all submodules */
27#define D_MODULENAME i2400m
28#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL
29
30#include <linux/wimax/debug.h>
31
32/* List of all the enabled modules */
33enum d_module {
34 D_SUBMODULE_DECLARE(control),
35 D_SUBMODULE_DECLARE(driver),
36 D_SUBMODULE_DECLARE(debugfs),
37 D_SUBMODULE_DECLARE(fw),
38 D_SUBMODULE_DECLARE(netdev),
39 D_SUBMODULE_DECLARE(rfkill),
40 D_SUBMODULE_DECLARE(rx),
41 D_SUBMODULE_DECLARE(tx),
42};
43
44
45#endif /* #ifndef __debug_levels__h__ */
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
new file mode 100644
index 000000000000..626632985977
--- /dev/null
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -0,0 +1,392 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Debugfs interfaces to manipulate driver and device information
4 *
5 *
6 * Copyright (C) 2007 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#include <linux/debugfs.h>
25#include <linux/netdevice.h>
26#include <linux/etherdevice.h>
27#include <linux/spinlock.h>
28#include <linux/device.h>
29#include "i2400m.h"
30
31
32#define D_SUBMODULE debugfs
33#include "debug-levels.h"
34
35static
36int debugfs_netdev_queue_stopped_get(void *data, u64 *val)
37{
38 struct i2400m *i2400m = data;
39 *val = netif_queue_stopped(i2400m->wimax_dev.net_dev);
40 return 0;
41}
42DEFINE_SIMPLE_ATTRIBUTE(fops_netdev_queue_stopped,
43 debugfs_netdev_queue_stopped_get,
44 NULL, "%llu\n");
45
46
47static
48struct dentry *debugfs_create_netdev_queue_stopped(
49 const char *name, struct dentry *parent, struct i2400m *i2400m)
50{
51 return debugfs_create_file(name, 0400, parent, i2400m,
52 &fops_netdev_queue_stopped);
53}
54
55
56/*
57 * inode->i_private has the @data argument to debugfs_create_file()
58 */
59static
60int i2400m_stats_open(struct inode *inode, struct file *filp)
61{
62 filp->private_data = inode->i_private;
63 return 0;
64}
65
66/*
67 * We don't allow partial reads of this file, as then the reader would
68 * get weirdly confused data as it is updated.
69 *
70 * So or you read it all or nothing; if you try to read with an offset
71 * != 0, we consider you are done reading.
72 */
73static
74ssize_t i2400m_rx_stats_read(struct file *filp, char __user *buffer,
75 size_t count, loff_t *ppos)
76{
77 struct i2400m *i2400m = filp->private_data;
78 char buf[128];
79 unsigned long flags;
80
81 if (*ppos != 0)
82 return 0;
83 if (count < sizeof(buf))
84 return -ENOSPC;
85 spin_lock_irqsave(&i2400m->rx_lock, flags);
86 snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n",
87 i2400m->rx_pl_num, i2400m->rx_pl_min,
88 i2400m->rx_pl_max, i2400m->rx_num,
89 i2400m->rx_size_acc,
90 i2400m->rx_size_min, i2400m->rx_size_max);
91 spin_unlock_irqrestore(&i2400m->rx_lock, flags);
92 return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
93}
94
95
96/* Any write clears the stats */
97static
98ssize_t i2400m_rx_stats_write(struct file *filp, const char __user *buffer,
99 size_t count, loff_t *ppos)
100{
101 struct i2400m *i2400m = filp->private_data;
102 unsigned long flags;
103
104 spin_lock_irqsave(&i2400m->rx_lock, flags);
105 i2400m->rx_pl_num = 0;
106 i2400m->rx_pl_max = 0;
107 i2400m->rx_pl_min = UINT_MAX;
108 i2400m->rx_num = 0;
109 i2400m->rx_size_acc = 0;
110 i2400m->rx_size_min = UINT_MAX;
111 i2400m->rx_size_max = 0;
112 spin_unlock_irqrestore(&i2400m->rx_lock, flags);
113 return count;
114}
115
116static
117const struct file_operations i2400m_rx_stats_fops = {
118 .owner = THIS_MODULE,
119 .open = i2400m_stats_open,
120 .read = i2400m_rx_stats_read,
121 .write = i2400m_rx_stats_write,
122};
123
124
125/* See i2400m_rx_stats_read() */
126static
127ssize_t i2400m_tx_stats_read(struct file *filp, char __user *buffer,
128 size_t count, loff_t *ppos)
129{
130 struct i2400m *i2400m = filp->private_data;
131 char buf[128];
132 unsigned long flags;
133
134 if (*ppos != 0)
135 return 0;
136 if (count < sizeof(buf))
137 return -ENOSPC;
138 spin_lock_irqsave(&i2400m->tx_lock, flags);
139 snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n",
140 i2400m->tx_pl_num, i2400m->tx_pl_min,
141 i2400m->tx_pl_max, i2400m->tx_num,
142 i2400m->tx_size_acc,
143 i2400m->tx_size_min, i2400m->tx_size_max);
144 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
145 return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
146}
147
148/* Any write clears the stats */
149static
150ssize_t i2400m_tx_stats_write(struct file *filp, const char __user *buffer,
151 size_t count, loff_t *ppos)
152{
153 struct i2400m *i2400m = filp->private_data;
154 unsigned long flags;
155
156 spin_lock_irqsave(&i2400m->tx_lock, flags);
157 i2400m->tx_pl_num = 0;
158 i2400m->tx_pl_max = 0;
159 i2400m->tx_pl_min = UINT_MAX;
160 i2400m->tx_num = 0;
161 i2400m->tx_size_acc = 0;
162 i2400m->tx_size_min = UINT_MAX;
163 i2400m->tx_size_max = 0;
164 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
165 return count;
166}
167
168static
169const struct file_operations i2400m_tx_stats_fops = {
170 .owner = THIS_MODULE,
171 .open = i2400m_stats_open,
172 .read = i2400m_tx_stats_read,
173 .write = i2400m_tx_stats_write,
174};
175
176
177/* Write 1 to ask the device to go into suspend */
178static
179int debugfs_i2400m_suspend_set(void *data, u64 val)
180{
181 int result;
182 struct i2400m *i2400m = data;
183 result = i2400m_cmd_enter_powersave(i2400m);
184 if (result >= 0)
185 result = 0;
186 return result;
187}
188DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_suspend,
189 NULL, debugfs_i2400m_suspend_set,
190 "%llu\n");
191
192static
193struct dentry *debugfs_create_i2400m_suspend(
194 const char *name, struct dentry *parent, struct i2400m *i2400m)
195{
196 return debugfs_create_file(name, 0200, parent, i2400m,
197 &fops_i2400m_suspend);
198}
199
200
201/*
202 * Reset the device
203 *
204 * Write 0 to ask the device to soft reset, 1 to cold reset, 2 to bus
205 * reset (as defined by enum i2400m_reset_type).
206 */
207static
208int debugfs_i2400m_reset_set(void *data, u64 val)
209{
210 int result;
211 struct i2400m *i2400m = data;
212 enum i2400m_reset_type rt = val;
213 switch(rt) {
214 case I2400M_RT_WARM:
215 case I2400M_RT_COLD:
216 case I2400M_RT_BUS:
217 result = i2400m->bus_reset(i2400m, rt);
218 if (result >= 0)
219 result = 0;
220 default:
221 result = -EINVAL;
222 }
223 return result;
224}
225DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_reset,
226 NULL, debugfs_i2400m_reset_set,
227 "%llu\n");
228
229static
230struct dentry *debugfs_create_i2400m_reset(
231 const char *name, struct dentry *parent, struct i2400m *i2400m)
232{
233 return debugfs_create_file(name, 0200, parent, i2400m,
234 &fops_i2400m_reset);
235}
236
237/*
238 * Debug levels control; see debug.h
239 */
240struct d_level D_LEVEL[] = {
241 D_SUBMODULE_DEFINE(control),
242 D_SUBMODULE_DEFINE(driver),
243 D_SUBMODULE_DEFINE(debugfs),
244 D_SUBMODULE_DEFINE(fw),
245 D_SUBMODULE_DEFINE(netdev),
246 D_SUBMODULE_DEFINE(rfkill),
247 D_SUBMODULE_DEFINE(rx),
248 D_SUBMODULE_DEFINE(tx),
249};
250size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
251
252#define __debugfs_register(prefix, name, parent) \
253do { \
254 result = d_level_register_debugfs(prefix, name, parent); \
255 if (result < 0) \
256 goto error; \
257} while (0)
258
259
260int i2400m_debugfs_add(struct i2400m *i2400m)
261{
262 int result;
263 struct device *dev = i2400m_dev(i2400m);
264 struct dentry *dentry = i2400m->wimax_dev.debugfs_dentry;
265 struct dentry *fd;
266
267 dentry = debugfs_create_dir("i2400m", dentry);
268 result = PTR_ERR(dentry);
269 if (IS_ERR(dentry)) {
270 if (result == -ENODEV)
271 result = 0; /* No debugfs support */
272 goto error;
273 }
274 i2400m->debugfs_dentry = dentry;
275 __debugfs_register("dl_", control, dentry);
276 __debugfs_register("dl_", driver, dentry);
277 __debugfs_register("dl_", debugfs, dentry);
278 __debugfs_register("dl_", fw, dentry);
279 __debugfs_register("dl_", netdev, dentry);
280 __debugfs_register("dl_", rfkill, dentry);
281 __debugfs_register("dl_", rx, dentry);
282 __debugfs_register("dl_", tx, dentry);
283
284 fd = debugfs_create_size_t("tx_in", 0400, dentry,
285 &i2400m->tx_in);
286 result = PTR_ERR(fd);
287 if (IS_ERR(fd) && result != -ENODEV) {
288 dev_err(dev, "Can't create debugfs entry "
289 "tx_in: %d\n", result);
290 goto error;
291 }
292
293 fd = debugfs_create_size_t("tx_out", 0400, dentry,
294 &i2400m->tx_out);
295 result = PTR_ERR(fd);
296 if (IS_ERR(fd) && result != -ENODEV) {
297 dev_err(dev, "Can't create debugfs entry "
298 "tx_out: %d\n", result);
299 goto error;
300 }
301
302 fd = debugfs_create_u32("state", 0600, dentry,
303 &i2400m->state);
304 result = PTR_ERR(fd);
305 if (IS_ERR(fd) && result != -ENODEV) {
306 dev_err(dev, "Can't create debugfs entry "
307 "state: %d\n", result);
308 goto error;
309 }
310
311 /*
312 * Trace received messages from user space
313 *
314 * In order to tap the bidirectional message stream in the
315 * 'msg' pipe, user space can read from the 'msg' pipe;
316 * however, due to limitations in libnl, we can't know what
317 * the different applications are sending down to the kernel.
318 *
319 * So we have this hack where the driver will echo any message
320 * received on the msg pipe from user space [through a call to
321 * wimax_dev->op_msg_from_user() into
322 * i2400m_op_msg_from_user()] into the 'trace' pipe that this
323 * driver creates.
324 *
325 * So then, reading from both the 'trace' and 'msg' pipes in
326 * user space will provide a full dump of the traffic.
327 *
328 * Write 1 to activate, 0 to clear.
329 *
330 * It is not really very atomic, but it is also not too
331 * critical.
332 */
333 fd = debugfs_create_u8("trace_msg_from_user", 0600, dentry,
334 &i2400m->trace_msg_from_user);
335 result = PTR_ERR(fd);
336 if (IS_ERR(fd) && result != -ENODEV) {
337 dev_err(dev, "Can't create debugfs entry "
338 "trace_msg_from_user: %d\n", result);
339 goto error;
340 }
341
342 fd = debugfs_create_netdev_queue_stopped("netdev_queue_stopped",
343 dentry, i2400m);
344 result = PTR_ERR(fd);
345 if (IS_ERR(fd) && result != -ENODEV) {
346 dev_err(dev, "Can't create debugfs entry "
347 "netdev_queue_stopped: %d\n", result);
348 goto error;
349 }
350
351 fd = debugfs_create_file("rx_stats", 0600, dentry, i2400m,
352 &i2400m_rx_stats_fops);
353 result = PTR_ERR(fd);
354 if (IS_ERR(fd) && result != -ENODEV) {
355 dev_err(dev, "Can't create debugfs entry "
356 "rx_stats: %d\n", result);
357 goto error;
358 }
359
360 fd = debugfs_create_file("tx_stats", 0600, dentry, i2400m,
361 &i2400m_tx_stats_fops);
362 result = PTR_ERR(fd);
363 if (IS_ERR(fd) && result != -ENODEV) {
364 dev_err(dev, "Can't create debugfs entry "
365 "tx_stats: %d\n", result);
366 goto error;
367 }
368
369 fd = debugfs_create_i2400m_suspend("suspend", dentry, i2400m);
370 result = PTR_ERR(fd);
371 if (IS_ERR(fd) && result != -ENODEV) {
372 dev_err(dev, "Can't create debugfs entry suspend: %d\n",
373 result);
374 goto error;
375 }
376
377 fd = debugfs_create_i2400m_reset("reset", dentry, i2400m);
378 result = PTR_ERR(fd);
379 if (IS_ERR(fd) && result != -ENODEV) {
380 dev_err(dev, "Can't create debugfs entry reset: %d\n", result);
381 goto error;
382 }
383
384 result = 0;
385error:
386 return result;
387}
388
389void i2400m_debugfs_rm(struct i2400m *i2400m)
390{
391 debugfs_remove_recursive(i2400m->debugfs_dentry);
392}
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
new file mode 100644
index 000000000000..5f98047e18cf
--- /dev/null
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -0,0 +1,728 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Generic probe/disconnect, reset and message passing
4 *
5 *
6 * Copyright (C) 2007-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 * See i2400m.h for driver documentation. This contains helpers for
25 * the driver model glue [_setup()/_release()], handling device resets
26 * [_dev_reset_handle()], and the backends for the WiMAX stack ops
27 * reset [_op_reset()] and message from user [_op_msg_from_user()].
28 *
29 * ROADMAP:
30 *
31 * i2400m_op_msg_from_user()
32 * i2400m_msg_to_dev()
33 * wimax_msg_to_user_send()
34 *
35 * i2400m_op_reset()
36 * i240m->bus_reset()
37 *
38 * i2400m_dev_reset_handle()
39 * __i2400m_dev_reset_handle()
40 * __i2400m_dev_stop()
41 * __i2400m_dev_start()
42 *
43 * i2400m_setup()
44 * i2400m_bootrom_init()
45 * register_netdev()
46 * i2400m_dev_start()
47 * __i2400m_dev_start()
48 * i2400m_dev_bootstrap()
49 * i2400m_tx_setup()
50 * i2400m->bus_dev_start()
51 * i2400m_check_mac_addr()
52 * wimax_dev_add()
53 *
54 * i2400m_release()
55 * wimax_dev_rm()
56 * i2400m_dev_stop()
57 * __i2400m_dev_stop()
58 * i2400m_dev_shutdown()
59 * i2400m->bus_dev_stop()
60 * i2400m_tx_release()
61 * unregister_netdev()
62 */
63#include "i2400m.h"
64#include <linux/wimax/i2400m.h>
65#include <linux/module.h>
66#include <linux/moduleparam.h>
67
68#define D_SUBMODULE driver
69#include "debug-levels.h"
70
71
72int i2400m_idle_mode_disabled; /* 0 (idle mode enabled) by default */
73module_param_named(idle_mode_disabled, i2400m_idle_mode_disabled, int, 0644);
74MODULE_PARM_DESC(idle_mode_disabled,
75 "If true, the device will not enable idle mode negotiation "
76 "with the base station (when connected) to save power.");
77
78/**
79 * i2400m_queue_work - schedule work on a i2400m's queue
80 *
81 * @i2400m: device descriptor
82 *
83 * @fn: function to run to execute work. It gets passed a 'struct
84 * work_struct' that is wrapped in a 'struct i2400m_work'. Once
85 * done, you have to (1) i2400m_put(i2400m_work->i2400m) and then
86 * (2) kfree(i2400m_work).
87 *
88 * @gfp_flags: GFP flags for memory allocation.
89 *
90 * @pl: pointer to a payload buffer that you want to pass to the _work
91 * function. Use this to pack (for example) a struct with extra
92 * arguments.
93 *
94 * @pl_size: size of the payload buffer.
95 *
96 * We do this quite often, so this just saves typing; allocate a
97 * wrapper for a i2400m, get a ref to it, pack arguments and launch
98 * the work.
99 *
100 * A usual workflow is:
101 *
102 * struct my_work_args {
103 * void *something;
104 * int whatever;
105 * };
106 * ...
107 *
108 * struct my_work_args my_args = {
109 * .something = FOO,
110 * .whaetever = BLAH
111 * };
112 * i2400m_queue_work(i2400m, 1, my_work_function, GFP_KERNEL,
113 * &args, sizeof(args))
114 *
115 * And now the work function can unpack the arguments and call the
116 * real function (or do the job itself):
117 *
118 * static
119 * void my_work_fn((struct work_struct *ws)
120 * {
121 * struct i2400m_work *iw =
122 * container_of(ws, struct i2400m_work, ws);
123 * struct my_work_args *my_args = (void *) iw->pl;
124 *
125 * my_work(iw->i2400m, my_args->something, my_args->whatevert);
126 * }
127 */
128int i2400m_queue_work(struct i2400m *i2400m,
129 void (*fn)(struct work_struct *), gfp_t gfp_flags,
130 const void *pl, size_t pl_size)
131{
132 int result;
133 struct i2400m_work *iw;
134
135 BUG_ON(i2400m->work_queue == NULL);
136 result = -ENOMEM;
137 iw = kzalloc(sizeof(*iw) + pl_size, gfp_flags);
138 if (iw == NULL)
139 goto error_kzalloc;
140 iw->i2400m = i2400m_get(i2400m);
141 memcpy(iw->pl, pl, pl_size);
142 INIT_WORK(&iw->ws, fn);
143 result = queue_work(i2400m->work_queue, &iw->ws);
144error_kzalloc:
145 return result;
146}
147EXPORT_SYMBOL_GPL(i2400m_queue_work);
148
149
150/*
151 * Schedule i2400m's specific work on the system's queue.
152 *
153 * Used for a few cases where we really need it; otherwise, identical
154 * to i2400m_queue_work().
155 *
156 * Returns < 0 errno code on error, 1 if ok.
157 *
158 * If it returns zero, something really bad happened, as it means the
159 * works struct was already queued, but we have just allocated it, so
160 * it should not happen.
161 */
162int i2400m_schedule_work(struct i2400m *i2400m,
163 void (*fn)(struct work_struct *), gfp_t gfp_flags)
164{
165 int result;
166 struct i2400m_work *iw;
167
168 BUG_ON(i2400m->work_queue == NULL);
169 result = -ENOMEM;
170 iw = kzalloc(sizeof(*iw), gfp_flags);
171 if (iw == NULL)
172 goto error_kzalloc;
173 iw->i2400m = i2400m_get(i2400m);
174 INIT_WORK(&iw->ws, fn);
175 result = schedule_work(&iw->ws);
176 if (result == 0)
177 result = -ENXIO;
178error_kzalloc:
179 return result;
180}
181
182
183/*
184 * WiMAX stack operation: relay a message from user space
185 *
186 * @wimax_dev: device descriptor
187 * @pipe_name: named pipe the message is for
188 * @msg_buf: pointer to the message bytes
189 * @msg_len: length of the buffer
190 * @genl_info: passed by the generic netlink layer
191 *
192 * The WiMAX stack will call this function when a message was received
193 * from user space.
194 *
195 * For the i2400m, this is an L3L4 message, as specified in
196 * include/linux/wimax/i2400m.h, and thus prefixed with a 'struct
197 * i2400m_l3l4_hdr'. Driver (and device) expect the messages to be
198 * coded in Little Endian.
199 *
200 * This function just verifies that the header declaration and the
201 * payload are consistent and then deals with it, either forwarding it
202 * to the device or procesing it locally.
203 *
204 * In the i2400m, messages are basically commands that will carry an
205 * ack, so we use i2400m_msg_to_dev() and then deliver the ack back to
206 * user space. The rx.c code might intercept the response and use it
207 * to update the driver's state, but then it will pass it on so it can
208 * be relayed back to user space.
209 *
210 * Note that asynchronous events from the device are processed and
211 * sent to user space in rx.c.
212 */
213static
214int i2400m_op_msg_from_user(struct wimax_dev *wimax_dev,
215 const char *pipe_name,
216 const void *msg_buf, size_t msg_len,
217 const struct genl_info *genl_info)
218{
219 int result;
220 struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev);
221 struct device *dev = i2400m_dev(i2400m);
222 struct sk_buff *ack_skb;
223
224 d_fnstart(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p "
225 "msg_len %zu genl_info %p)\n", wimax_dev, i2400m,
226 msg_buf, msg_len, genl_info);
227 ack_skb = i2400m_msg_to_dev(i2400m, msg_buf, msg_len);
228 result = PTR_ERR(ack_skb);
229 if (IS_ERR(ack_skb))
230 goto error_msg_to_dev;
231 if (unlikely(i2400m->trace_msg_from_user))
232 wimax_msg(&i2400m->wimax_dev, "trace",
233 msg_buf, msg_len, GFP_KERNEL);
234 result = wimax_msg_send(&i2400m->wimax_dev, ack_skb);
235error_msg_to_dev:
236 d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu "
237 "genl_info %p) = %d\n", wimax_dev, i2400m, msg_buf, msg_len,
238 genl_info, result);
239 return result;
240}
241
242
243/*
244 * Context to wait for a reset to finalize
245 */
246struct i2400m_reset_ctx {
247 struct completion completion;
248 int result;
249};
250
251
252/*
253 * WiMAX stack operation: reset a device
254 *
255 * @wimax_dev: device descriptor
256 *
257 * See the documentation for wimax_reset() and wimax_dev->op_reset for
258 * the requirements of this function. The WiMAX stack guarantees
259 * serialization on calls to this function.
260 *
261 * Do a warm reset on the device; if it fails, resort to a cold reset
262 * and return -ENODEV. On successful warm reset, we need to block
263 * until it is complete.
264 *
265 * The bus-driver implementation of reset takes care of falling back
266 * to cold reset if warm fails.
267 */
268static
269int i2400m_op_reset(struct wimax_dev *wimax_dev)
270{
271 int result;
272 struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev);
273 struct device *dev = i2400m_dev(i2400m);
274 struct i2400m_reset_ctx ctx = {
275 .completion = COMPLETION_INITIALIZER_ONSTACK(ctx.completion),
276 .result = 0,
277 };
278
279 d_fnstart(4, dev, "(wimax_dev %p)\n", wimax_dev);
280 mutex_lock(&i2400m->init_mutex);
281 i2400m->reset_ctx = &ctx;
282 mutex_unlock(&i2400m->init_mutex);
283 result = i2400m->bus_reset(i2400m, I2400M_RT_WARM);
284 if (result < 0)
285 goto out;
286 result = wait_for_completion_timeout(&ctx.completion, 4*HZ);
287 if (result == 0)
288 result = -ETIMEDOUT;
289 else if (result > 0)
290 result = ctx.result;
291 /* if result < 0, pass it on */
292 mutex_lock(&i2400m->init_mutex);
293 i2400m->reset_ctx = NULL;
294 mutex_unlock(&i2400m->init_mutex);
295out:
296 d_fnend(4, dev, "(wimax_dev %p) = %d\n", wimax_dev, result);
297 return result;
298}
299
300
301/*
302 * Check the MAC address we got from boot mode is ok
303 *
304 * @i2400m: device descriptor
305 *
306 * Returns: 0 if ok, < 0 errno code on error.
307 */
308static
309int i2400m_check_mac_addr(struct i2400m *i2400m)
310{
311 int result;
312 struct device *dev = i2400m_dev(i2400m);
313 struct sk_buff *skb;
314 const struct i2400m_tlv_detailed_device_info *ddi;
315 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
316 const unsigned char zeromac[ETH_ALEN] = { 0 };
317
318 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
319 skb = i2400m_get_device_info(i2400m);
320 if (IS_ERR(skb)) {
321 result = PTR_ERR(skb);
322 dev_err(dev, "Cannot verify MAC address, error reading: %d\n",
323 result);
324 goto error;
325 }
326 /* Extract MAC addresss */
327 ddi = (void *) skb->data;
328 BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address));
329 d_printf(2, dev, "GET DEVICE INFO: mac addr "
330 "%02x:%02x:%02x:%02x:%02x:%02x\n",
331 ddi->mac_address[0], ddi->mac_address[1],
332 ddi->mac_address[2], ddi->mac_address[3],
333 ddi->mac_address[4], ddi->mac_address[5]);
334 if (!memcmp(net_dev->perm_addr, ddi->mac_address,
335 sizeof(ddi->mac_address)))
336 goto ok;
337 dev_warn(dev, "warning: device reports a different MAC address "
338 "to that of boot mode's\n");
339 dev_warn(dev, "device reports %02x:%02x:%02x:%02x:%02x:%02x\n",
340 ddi->mac_address[0], ddi->mac_address[1],
341 ddi->mac_address[2], ddi->mac_address[3],
342 ddi->mac_address[4], ddi->mac_address[5]);
343 dev_warn(dev, "boot mode reported %02x:%02x:%02x:%02x:%02x:%02x\n",
344 net_dev->perm_addr[0], net_dev->perm_addr[1],
345 net_dev->perm_addr[2], net_dev->perm_addr[3],
346 net_dev->perm_addr[4], net_dev->perm_addr[5]);
347 if (!memcmp(zeromac, ddi->mac_address, sizeof(zeromac)))
348 dev_err(dev, "device reports an invalid MAC address, "
349 "not updating\n");
350 else {
351 dev_warn(dev, "updating MAC address\n");
352 net_dev->addr_len = ETH_ALEN;
353 memcpy(net_dev->perm_addr, ddi->mac_address, ETH_ALEN);
354 memcpy(net_dev->dev_addr, ddi->mac_address, ETH_ALEN);
355 }
356ok:
357 result = 0;
358 kfree_skb(skb);
359error:
360 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
361 return result;
362}
363
364
365/**
366 * __i2400m_dev_start - Bring up driver communication with the device
367 *
368 * @i2400m: device descriptor
369 * @flags: boot mode flags
370 *
371 * Returns: 0 if ok, < 0 errno code on error.
372 *
373 * Uploads firmware and brings up all the resources needed to be able
374 * to communicate with the device.
375 *
376 * TX needs to be setup before the bus-specific code (otherwise on
377 * shutdown, the bus-tx code could try to access it).
378 */
379static
380int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags)
381{
382 int result;
383 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
384 struct net_device *net_dev = wimax_dev->net_dev;
385 struct device *dev = i2400m_dev(i2400m);
386 int times = 3;
387
388 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
389retry:
390 result = i2400m_dev_bootstrap(i2400m, flags);
391 if (result < 0) {
392 dev_err(dev, "cannot bootstrap device: %d\n", result);
393 goto error_bootstrap;
394 }
395 result = i2400m_tx_setup(i2400m);
396 if (result < 0)
397 goto error_tx_setup;
398 result = i2400m->bus_dev_start(i2400m);
399 if (result < 0)
400 goto error_bus_dev_start;
401 i2400m->work_queue = create_singlethread_workqueue(wimax_dev->name);
402 if (i2400m->work_queue == NULL) {
403 result = -ENOMEM;
404 dev_err(dev, "cannot create workqueue\n");
405 goto error_create_workqueue;
406 }
407 /* At this point is ok to send commands to the device */
408 result = i2400m_check_mac_addr(i2400m);
409 if (result < 0)
410 goto error_check_mac_addr;
411 i2400m->ready = 1;
412 wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED);
413 result = i2400m_dev_initialize(i2400m);
414 if (result < 0)
415 goto error_dev_initialize;
416 /* At this point, reports will come for the device and set it
417 * to the right state if it is different than UNINITIALIZED */
418 d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
419 net_dev, i2400m, result);
420 return result;
421
422error_dev_initialize:
423error_check_mac_addr:
424 destroy_workqueue(i2400m->work_queue);
425error_create_workqueue:
426 i2400m->bus_dev_stop(i2400m);
427error_bus_dev_start:
428 i2400m_tx_release(i2400m);
429error_tx_setup:
430error_bootstrap:
431 if (result == -ERESTARTSYS && times-- > 0) {
432 flags = I2400M_BRI_SOFT;
433 goto retry;
434 }
435 d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
436 net_dev, i2400m, result);
437 return result;
438}
439
440
441static
442int i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri bm_flags)
443{
444 int result;
445 mutex_lock(&i2400m->init_mutex); /* Well, start the device */
446 result = __i2400m_dev_start(i2400m, bm_flags);
447 if (result >= 0)
448 i2400m->updown = 1;
449 mutex_unlock(&i2400m->init_mutex);
450 return result;
451}
452
453
454/**
455 * i2400m_dev_stop - Tear down driver communication with the device
456 *
457 * @i2400m: device descriptor
458 *
459 * Returns: 0 if ok, < 0 errno code on error.
460 *
461 * Releases all the resources allocated to communicate with the device.
462 */
463static
464void __i2400m_dev_stop(struct i2400m *i2400m)
465{
466 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
467 struct device *dev = i2400m_dev(i2400m);
468
469 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
470 wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING);
471 i2400m_dev_shutdown(i2400m);
472 i2400m->ready = 0;
473 destroy_workqueue(i2400m->work_queue);
474 i2400m->bus_dev_stop(i2400m);
475 i2400m_tx_release(i2400m);
476 wimax_state_change(wimax_dev, WIMAX_ST_DOWN);
477 d_fnend(3, dev, "(i2400m %p) = 0\n", i2400m);
478}
479
480
481/*
482 * Watch out -- we only need to stop if there is a need for it. The
483 * device could have reset itself and failed to come up again (see
484 * _i2400m_dev_reset_handle()).
485 */
486static
487void i2400m_dev_stop(struct i2400m *i2400m)
488{
489 mutex_lock(&i2400m->init_mutex);
490 if (i2400m->updown) {
491 __i2400m_dev_stop(i2400m);
492 i2400m->updown = 0;
493 }
494 mutex_unlock(&i2400m->init_mutex);
495}
496
497
498/*
499 * The device has rebooted; fix up the device and the driver
500 *
501 * Tear down the driver communication with the device, reload the
502 * firmware and reinitialize the communication with the device.
503 *
504 * If someone calls a reset when the device's firmware is down, in
505 * theory we won't see it because we are not listening. However, just
506 * in case, leave the code to handle it.
507 *
508 * If there is a reset context, use it; this means someone is waiting
509 * for us to tell him when the reset operation is complete and the
510 * device is ready to rock again.
511 *
512 * NOTE: if we are in the process of bringing up or down the
513 * communication with the device [running i2400m_dev_start() or
514 * _stop()], don't do anything, let it fail and handle it.
515 *
516 * This function is ran always in a thread context
517 */
518static
519void __i2400m_dev_reset_handle(struct work_struct *ws)
520{
521 int result;
522 struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws);
523 struct i2400m *i2400m = iw->i2400m;
524 struct device *dev = i2400m_dev(i2400m);
525 enum wimax_st wimax_state;
526 struct i2400m_reset_ctx *ctx = i2400m->reset_ctx;
527
528 d_fnstart(3, dev, "(ws %p i2400m %p)\n", ws, i2400m);
529 result = 0;
530 if (mutex_trylock(&i2400m->init_mutex) == 0) {
531 /* We are still in i2400m_dev_start() [let it fail] or
532 * i2400m_dev_stop() [we are shutting down anyway, so
533 * ignore it] or we are resetting somewhere else. */
534 dev_err(dev, "device rebooted\n");
535 i2400m_msg_to_dev_cancel_wait(i2400m, -ERESTARTSYS);
536 complete(&i2400m->msg_completion);
537 goto out;
538 }
539 wimax_state = wimax_state_get(&i2400m->wimax_dev);
540 if (wimax_state < WIMAX_ST_UNINITIALIZED) {
541 dev_info(dev, "device rebooted: it is down, ignoring\n");
542 goto out_unlock; /* ifconfig up/down wasn't called */
543 }
544 dev_err(dev, "device rebooted: reinitializing driver\n");
545 __i2400m_dev_stop(i2400m);
546 i2400m->updown = 0;
547 result = __i2400m_dev_start(i2400m,
548 I2400M_BRI_SOFT | I2400M_BRI_MAC_REINIT);
549 if (result < 0) {
550 dev_err(dev, "device reboot: cannot start the device: %d\n",
551 result);
552 result = i2400m->bus_reset(i2400m, I2400M_RT_BUS);
553 if (result >= 0)
554 result = -ENODEV;
555 } else
556 i2400m->updown = 1;
557out_unlock:
558 if (i2400m->reset_ctx) {
559 ctx->result = result;
560 complete(&ctx->completion);
561 }
562 mutex_unlock(&i2400m->init_mutex);
563out:
564 i2400m_put(i2400m);
565 kfree(iw);
566 d_fnend(3, dev, "(ws %p i2400m %p) = void\n", ws, i2400m);
567 return;
568}
569
570
571/**
572 * i2400m_dev_reset_handle - Handle a device's reset in a thread context
573 *
574 * Schedule a device reset handling out on a thread context, so it
575 * is safe to call from atomic context. We can't use the i2400m's
576 * queue as we are going to destroy it and reinitialize it as part of
577 * the driver bringup/bringup process.
578 *
579 * See __i2400m_dev_reset_handle() for details; that takes care of
580 * reinitializing the driver to handle the reset, calling into the
581 * bus-specific functions ops as needed.
582 */
583int i2400m_dev_reset_handle(struct i2400m *i2400m)
584{
585 return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle,
586 GFP_ATOMIC);
587}
588EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle);
589
590
591/**
592 * i2400m_setup - bus-generic setup function for the i2400m device
593 *
594 * @i2400m: device descriptor (bus-specific parts have been initialized)
595 *
596 * Returns: 0 if ok, < 0 errno code on error.
597 *
598 * Initializes the bus-generic parts of the i2400m driver; the
599 * bus-specific parts have been initialized, function pointers filled
600 * out by the bus-specific probe function.
601 *
602 * As well, this registers the WiMAX and net device nodes. Once this
603 * function returns, the device is operative and has to be ready to
604 * receive and send network traffic and WiMAX control operations.
605 */
606int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags)
607{
608 int result = -ENODEV;
609 struct device *dev = i2400m_dev(i2400m);
610 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
611 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
612
613 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
614
615 snprintf(wimax_dev->name, sizeof(wimax_dev->name),
616 "i2400m-%s:%s", dev->bus->name, dev->bus_id);
617
618 i2400m->bm_cmd_buf = kzalloc(I2400M_BM_CMD_BUF_SIZE, GFP_KERNEL);
619 if (i2400m->bm_cmd_buf == NULL) {
620 dev_err(dev, "cannot allocate USB command buffer\n");
621 goto error_bm_cmd_kzalloc;
622 }
623 i2400m->bm_ack_buf = kzalloc(I2400M_BM_ACK_BUF_SIZE, GFP_KERNEL);
624 if (i2400m->bm_ack_buf == NULL) {
625 dev_err(dev, "cannot allocate USB ack buffer\n");
626 goto error_bm_ack_buf_kzalloc;
627 }
628 result = i2400m_bootrom_init(i2400m, bm_flags);
629 if (result < 0) {
630 dev_err(dev, "read mac addr: bootrom init "
631 "failed: %d\n", result);
632 goto error_bootrom_init;
633 }
634 result = i2400m_read_mac_addr(i2400m);
635 if (result < 0)
636 goto error_read_mac_addr;
637
638 result = register_netdev(net_dev); /* Okey dokey, bring it up */
639 if (result < 0) {
640 dev_err(dev, "cannot register i2400m network device: %d\n",
641 result);
642 goto error_register_netdev;
643 }
644 netif_carrier_off(net_dev);
645
646 result = i2400m_dev_start(i2400m, bm_flags);
647 if (result < 0)
648 goto error_dev_start;
649
650 i2400m->wimax_dev.op_msg_from_user = i2400m_op_msg_from_user;
651 i2400m->wimax_dev.op_rfkill_sw_toggle = i2400m_op_rfkill_sw_toggle;
652 i2400m->wimax_dev.op_reset = i2400m_op_reset;
653 result = wimax_dev_add(&i2400m->wimax_dev, net_dev);
654 if (result < 0)
655 goto error_wimax_dev_add;
656 /* User space needs to do some init stuff */
657 wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED);
658
659 /* Now setup all that requires a registered net and wimax device. */
660 result = i2400m_debugfs_add(i2400m);
661 if (result < 0) {
662 dev_err(dev, "cannot setup i2400m's debugfs: %d\n", result);
663 goto error_debugfs_setup;
664 }
665 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
666 return result;
667
668error_debugfs_setup:
669 wimax_dev_rm(&i2400m->wimax_dev);
670error_wimax_dev_add:
671 i2400m_dev_stop(i2400m);
672error_dev_start:
673 unregister_netdev(net_dev);
674error_register_netdev:
675error_read_mac_addr:
676error_bootrom_init:
677 kfree(i2400m->bm_ack_buf);
678error_bm_ack_buf_kzalloc:
679 kfree(i2400m->bm_cmd_buf);
680error_bm_cmd_kzalloc:
681 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
682 return result;
683}
684EXPORT_SYMBOL_GPL(i2400m_setup);
685
686
687/**
688 * i2400m_release - release the bus-generic driver resources
689 *
690 * Sends a disconnect message and undoes any setup done by i2400m_setup()
691 */
692void i2400m_release(struct i2400m *i2400m)
693{
694 struct device *dev = i2400m_dev(i2400m);
695
696 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
697 netif_stop_queue(i2400m->wimax_dev.net_dev);
698
699 i2400m_debugfs_rm(i2400m);
700 wimax_dev_rm(&i2400m->wimax_dev);
701 i2400m_dev_stop(i2400m);
702 unregister_netdev(i2400m->wimax_dev.net_dev);
703 kfree(i2400m->bm_ack_buf);
704 kfree(i2400m->bm_cmd_buf);
705 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
706}
707EXPORT_SYMBOL_GPL(i2400m_release);
708
709
710static
711int __init i2400m_driver_init(void)
712{
713 return 0;
714}
715module_init(i2400m_driver_init);
716
717static
718void __exit i2400m_driver_exit(void)
719{
720 /* for scheds i2400m_dev_reset_handle() */
721 flush_scheduled_work();
722 return;
723}
724module_exit(i2400m_driver_exit);
725
726MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
727MODULE_DESCRIPTION("Intel 2400M WiMAX networking bus-generic driver");
728MODULE_LICENSE("GPL");
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
new file mode 100644
index 000000000000..1d8271f34c38
--- /dev/null
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -0,0 +1,1095 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Firmware uploader
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
38 * - Initial implementation
39 *
40 *
41 * THE PROCEDURE
42 *
43 * (this is decribed for USB, but for SDIO is similar)
44 *
45 * The 2400m works in two modes: boot-mode or normal mode. In boot
46 * mode we can execute only a handful of commands targeted at
47 * uploading the firmware and launching it.
48 *
49 * The 2400m enters boot mode when it is first connected to the
50 * system, when it crashes and when you ask it to reboot. There are
51 * two submodes of the boot mode: signed and non-signed. Signed takes
52 * firmwares signed with a certain private key, non-signed takes any
53 * firmware. Normal hardware takes only signed firmware.
54 *
55 * Upon entrance to boot mode, the device sends a few zero length
56 * packets (ZLPs) on the notification endpoint, then a reboot barker
57 * (4 le32 words with value I2400M_{S,N}BOOT_BARKER). We ack it by
58 * sending the same barker on the bulk out endpoint. The device acks
59 * with a reboot ack barker (4 le32 words with value 0xfeedbabe) and
60 * then the device is fully rebooted. At this point we can upload the
61 * firmware.
62 *
63 * This process is accomplished by the i2400m_bootrom_init()
64 * function. All the device interaction happens through the
65 * i2400m_bm_cmd() [boot mode command]. Special return values will
66 * indicate if the device resets.
67 *
68 * After this, we read the MAC address and then (if needed)
69 * reinitialize the device. We need to read it ahead of time because
70 * in the future, we might not upload the firmware until userspace
71 * 'ifconfig up's the device.
72 *
73 * We can then upload the firmware file. The file is composed of a BCF
74 * header (basic data, keys and signatures) and a list of write
75 * commands and payloads. We first upload the header
76 * [i2400m_dnload_init()] and then pass the commands and payloads
77 * verbatim to the i2400m_bm_cmd() function
78 * [i2400m_dnload_bcf()]. Then we tell the device to jump to the new
79 * firmware [i2400m_dnload_finalize()].
80 *
81 * Once firmware is uploaded, we are good to go :)
82 *
83 * When we don't know in which mode we are, we first try by sending a
84 * warm reset request that will take us to boot-mode. If we time out
85 * waiting for a reboot barker, that means maybe we are already in
86 * boot mode, so we send a reboot barker.
87 *
88 * COMMAND EXECUTION
89 *
90 * This code (and process) is single threaded; for executing commands,
91 * we post a URB to the notification endpoint, post the command, wait
92 * for data on the notification buffer. We don't need to worry about
93 * others as we know we are the only ones in there.
94 *
95 * BACKEND IMPLEMENTATION
96 *
97 * This code is bus-generic; the bus-specific driver provides back end
98 * implementations to send a boot mode command to the device and to
99 * read an acknolwedgement from it (or an asynchronous notification)
100 * from it.
101 *
102 * ROADMAP
103 *
104 * i2400m_dev_bootstrap Called by __i2400m_dev_start()
105 * request_firmware
106 * i2400m_fw_check
107 * i2400m_fw_dnload
108 * release_firmware
109 *
110 * i2400m_fw_dnload
111 * i2400m_bootrom_init
112 * i2400m_bm_cmd
113 * i2400m->bus_reset
114 * i2400m_dnload_init
115 * i2400m_dnload_init_signed
116 * i2400m_dnload_init_nonsigned
117 * i2400m_download_chunk
118 * i2400m_bm_cmd
119 * i2400m_dnload_bcf
120 * i2400m_bm_cmd
121 * i2400m_dnload_finalize
122 * i2400m_bm_cmd
123 *
124 * i2400m_bm_cmd
125 * i2400m->bus_bm_cmd_send()
126 * i2400m->bus_bm_wait_for_ack
127 * __i2400m_bm_ack_verify
128 *
129 * i2400m_bm_cmd_prepare Used by bus-drivers to prep
130 * commands before sending
131 */
132#include <linux/firmware.h>
133#include <linux/sched.h>
134#include <linux/usb.h>
135#include "i2400m.h"
136
137
138#define D_SUBMODULE fw
139#include "debug-levels.h"
140
141
142static const __le32 i2400m_ACK_BARKER[4] = {
143 __constant_cpu_to_le32(I2400M_ACK_BARKER),
144 __constant_cpu_to_le32(I2400M_ACK_BARKER),
145 __constant_cpu_to_le32(I2400M_ACK_BARKER),
146 __constant_cpu_to_le32(I2400M_ACK_BARKER)
147};
148
149
150/**
151 * Prepare a boot-mode command for delivery
152 *
153 * @cmd: pointer to bootrom header to prepare
154 *
155 * Computes checksum if so needed. After calling this function, DO NOT
156 * modify the command or header as the checksum won't work anymore.
157 *
158 * We do it from here because some times we cannot do it in the
159 * original context the command was sent (it is a const), so when we
160 * copy it to our staging buffer, we add the checksum there.
161 */
162void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *cmd)
163{
164 if (i2400m_brh_get_use_checksum(cmd)) {
165 int i;
166 u32 checksum = 0;
167 const u32 *checksum_ptr = (void *) cmd->payload;
168 for (i = 0; i < cmd->data_size / 4; i++)
169 checksum += cpu_to_le32(*checksum_ptr++);
170 checksum += cmd->command + cmd->target_addr + cmd->data_size;
171 cmd->block_checksum = cpu_to_le32(checksum);
172 }
173}
174EXPORT_SYMBOL_GPL(i2400m_bm_cmd_prepare);
175
176
177/*
178 * Verify the ack data received
179 *
180 * Given a reply to a boot mode command, chew it and verify everything
181 * is ok.
182 *
183 * @opcode: opcode which generated this ack. For error messages.
184 * @ack: pointer to ack data we received
185 * @ack_size: size of that data buffer
186 * @flags: I2400M_BM_CMD_* flags we called the command with.
187 *
188 * Way too long function -- maybe it should be further split
189 */
190static
191ssize_t __i2400m_bm_ack_verify(struct i2400m *i2400m, int opcode,
192 struct i2400m_bootrom_header *ack,
193 size_t ack_size, int flags)
194{
195 ssize_t result = -ENOMEM;
196 struct device *dev = i2400m_dev(i2400m);
197
198 d_fnstart(8, dev, "(i2400m %p opcode %d ack %p size %zu)\n",
199 i2400m, opcode, ack, ack_size);
200 if (ack_size < sizeof(*ack)) {
201 result = -EIO;
202 dev_err(dev, "boot-mode cmd %d: HW BUG? notification didn't "
203 "return enough data (%zu bytes vs %zu expected)\n",
204 opcode, ack_size, sizeof(*ack));
205 goto error_ack_short;
206 }
207 if (ack_size == sizeof(i2400m_NBOOT_BARKER)
208 && memcmp(ack, i2400m_NBOOT_BARKER, sizeof(*ack)) == 0) {
209 result = -ERESTARTSYS;
210 i2400m->sboot = 0;
211 d_printf(6, dev, "boot-mode cmd %d: "
212 "HW non-signed boot barker\n", opcode);
213 goto error_reboot;
214 }
215 if (ack_size == sizeof(i2400m_SBOOT_BARKER)
216 && memcmp(ack, i2400m_SBOOT_BARKER, sizeof(*ack)) == 0) {
217 result = -ERESTARTSYS;
218 i2400m->sboot = 1;
219 d_printf(6, dev, "boot-mode cmd %d: HW signed reboot barker\n",
220 opcode);
221 goto error_reboot;
222 }
223 if (ack_size == sizeof(i2400m_ACK_BARKER)
224 && memcmp(ack, i2400m_ACK_BARKER, sizeof(*ack)) == 0) {
225 result = -EISCONN;
226 d_printf(3, dev, "boot-mode cmd %d: HW reboot ack barker\n",
227 opcode);
228 goto error_reboot_ack;
229 }
230 result = 0;
231 if (flags & I2400M_BM_CMD_RAW)
232 goto out_raw;
233 ack->data_size = le32_to_cpu(ack->data_size);
234 ack->target_addr = le32_to_cpu(ack->target_addr);
235 ack->block_checksum = le32_to_cpu(ack->block_checksum);
236 d_printf(5, dev, "boot-mode cmd %d: notification for opcode %u "
237 "response %u csum %u rr %u da %u\n",
238 opcode, i2400m_brh_get_opcode(ack),
239 i2400m_brh_get_response(ack),
240 i2400m_brh_get_use_checksum(ack),
241 i2400m_brh_get_response_required(ack),
242 i2400m_brh_get_direct_access(ack));
243 result = -EIO;
244 if (i2400m_brh_get_signature(ack) != 0xcbbc) {
245 dev_err(dev, "boot-mode cmd %d: HW BUG? wrong signature "
246 "0x%04x\n", opcode, i2400m_brh_get_signature(ack));
247 goto error_ack_signature;
248 }
249 if (opcode != -1 && opcode != i2400m_brh_get_opcode(ack)) {
250 dev_err(dev, "boot-mode cmd %d: HW BUG? "
251 "received response for opcode %u, expected %u\n",
252 opcode, i2400m_brh_get_opcode(ack), opcode);
253 goto error_ack_opcode;
254 }
255 if (i2400m_brh_get_response(ack) != 0) { /* failed? */
256 dev_err(dev, "boot-mode cmd %d: error; hw response %u\n",
257 opcode, i2400m_brh_get_response(ack));
258 goto error_ack_failed;
259 }
260 if (ack_size < ack->data_size + sizeof(*ack)) {
261 dev_err(dev, "boot-mode cmd %d: SW BUG "
262 "driver provided only %zu bytes for %zu bytes "
263 "of data\n", opcode, ack_size,
264 (size_t) le32_to_cpu(ack->data_size) + sizeof(*ack));
265 goto error_ack_short_buffer;
266 }
267 result = ack_size;
268 /* Don't you love this stack of empty targets? Well, I don't
269 * either, but it helps track exactly who comes in here and
270 * why :) */
271error_ack_short_buffer:
272error_ack_failed:
273error_ack_opcode:
274error_ack_signature:
275out_raw:
276error_reboot_ack:
277error_reboot:
278error_ack_short:
279 d_fnend(8, dev, "(i2400m %p opcode %d ack %p size %zu) = %d\n",
280 i2400m, opcode, ack, ack_size, (int) result);
281 return result;
282}
283
284
285/**
286 * i2400m_bm_cmd - Execute a boot mode command
287 *
288 * @cmd: buffer containing the command data (pointing at the header).
289 * This data can be ANYWHERE (for USB, we will copy it to an
290 * specific buffer). Make sure everything is in proper little
291 * endian.
292 *
293 * A raw buffer can be also sent, just cast it and set flags to
294 * I2400M_BM_CMD_RAW.
295 *
296 * This function will generate a checksum for you if the
297 * checksum bit in the command is set (unless I2400M_BM_CMD_RAW
298 * is set).
299 *
300 * You can use the i2400m->bm_cmd_buf to stage your commands and
301 * send them.
302 *
303 * If NULL, no command is sent (we just wait for an ack).
304 *
305 * @cmd_size: size of the command. Will be auto padded to the
306 * bus-specific drivers padding requirements.
307 *
308 * @ack: buffer where to place the acknowledgement. If it is a regular
309 * command response, all fields will be returned with the right,
310 * native endianess.
311 *
312 * You *cannot* use i2400m->bm_ack_buf for this buffer.
313 *
314 * @ack_size: size of @ack, 16 aligned; you need to provide at least
315 * sizeof(*ack) bytes and then enough to contain the return data
316 * from the command
317 *
318 * @flags: see I2400M_BM_CMD_* above.
319 *
320 * @returns: bytes received by the notification; if < 0, an errno code
321 * denoting an error or:
322 *
323 * -ERESTARTSYS The device has rebooted
324 *
325 * Executes a boot-mode command and waits for a response, doing basic
326 * validation on it; if a zero length response is received, it retries
327 * waiting for a response until a non-zero one is received (timing out
328 * after %I2400M_BOOT_RETRIES retries).
329 */
330static
331ssize_t i2400m_bm_cmd(struct i2400m *i2400m,
332 const struct i2400m_bootrom_header *cmd, size_t cmd_size,
333 struct i2400m_bootrom_header *ack, size_t ack_size,
334 int flags)
335{
336 ssize_t result = -ENOMEM, rx_bytes;
337 struct device *dev = i2400m_dev(i2400m);
338 int opcode = cmd == NULL ? -1 : i2400m_brh_get_opcode(cmd);
339
340 d_fnstart(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu)\n",
341 i2400m, cmd, cmd_size, ack, ack_size);
342 BUG_ON(ack_size < sizeof(*ack));
343 BUG_ON(i2400m->boot_mode == 0);
344
345 if (cmd != NULL) { /* send the command */
346 memcpy(i2400m->bm_cmd_buf, cmd, cmd_size);
347 result = i2400m->bus_bm_cmd_send(i2400m, cmd, cmd_size, flags);
348 if (result < 0)
349 goto error_cmd_send;
350 if ((flags & I2400M_BM_CMD_RAW) == 0)
351 d_printf(5, dev,
352 "boot-mode cmd %d csum %u rr %u da %u: "
353 "addr 0x%04x size %u block csum 0x%04x\n",
354 opcode, i2400m_brh_get_use_checksum(cmd),
355 i2400m_brh_get_response_required(cmd),
356 i2400m_brh_get_direct_access(cmd),
357 cmd->target_addr, cmd->data_size,
358 cmd->block_checksum);
359 }
360 result = i2400m->bus_bm_wait_for_ack(i2400m, ack, ack_size);
361 if (result < 0) {
362 dev_err(dev, "boot-mode cmd %d: error waiting for an ack: %d\n",
363 opcode, (int) result); /* bah, %zd doesn't work */
364 goto error_wait_for_ack;
365 }
366 rx_bytes = result;
367 /* verify the ack and read more if neccessary [result is the
368 * final amount of bytes we get in the ack] */
369 result = __i2400m_bm_ack_verify(i2400m, opcode, ack, ack_size, flags);
370 if (result < 0)
371 goto error_bad_ack;
372 /* Don't you love this stack of empty targets? Well, I don't
373 * either, but it helps track exactly who comes in here and
374 * why :) */
375 result = rx_bytes;
376error_bad_ack:
377error_wait_for_ack:
378error_cmd_send:
379 d_fnend(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu) = %d\n",
380 i2400m, cmd, cmd_size, ack, ack_size, (int) result);
381 return result;
382}
383
384
385/**
386 * i2400m_download_chunk - write a single chunk of data to the device's memory
387 *
388 * @i2400m: device descriptor
389 * @buf: the buffer to write
390 * @buf_len: length of the buffer to write
391 * @addr: address in the device memory space
392 * @direct: bootrom write mode
393 * @do_csum: should a checksum validation be performed
394 */
395static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk,
396 size_t __chunk_len, unsigned long addr,
397 unsigned int direct, unsigned int do_csum)
398{
399 int ret;
400 size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_PAD);
401 struct device *dev = i2400m_dev(i2400m);
402 struct {
403 struct i2400m_bootrom_header cmd;
404 u8 cmd_payload[chunk_len];
405 } __attribute__((packed)) *buf;
406 struct i2400m_bootrom_header ack;
407
408 d_fnstart(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx "
409 "direct %u do_csum %u)\n", i2400m, chunk, __chunk_len,
410 addr, direct, do_csum);
411 buf = i2400m->bm_cmd_buf;
412 memcpy(buf->cmd_payload, chunk, __chunk_len);
413 memset(buf->cmd_payload + __chunk_len, 0xad, chunk_len - __chunk_len);
414
415 buf->cmd.command = i2400m_brh_command(I2400M_BRH_WRITE,
416 __chunk_len & 0x3 ? 0 : do_csum,
417 __chunk_len & 0xf ? 0 : direct);
418 buf->cmd.target_addr = cpu_to_le32(addr);
419 buf->cmd.data_size = cpu_to_le32(__chunk_len);
420 ret = i2400m_bm_cmd(i2400m, &buf->cmd, sizeof(buf->cmd) + chunk_len,
421 &ack, sizeof(ack), 0);
422 if (ret >= 0)
423 ret = 0;
424 d_fnend(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx "
425 "direct %u do_csum %u) = %d\n", i2400m, chunk, __chunk_len,
426 addr, direct, do_csum, ret);
427 return ret;
428}
429
430
431/*
432 * Download a BCF file's sections to the device
433 *
434 * @i2400m: device descriptor
435 * @bcf: pointer to firmware data (followed by the payloads). Assumed
436 * verified and consistent.
437 * @bcf_len: length (in bytes) of the @bcf buffer.
438 *
439 * Returns: < 0 errno code on error or the offset to the jump instruction.
440 *
441 * Given a BCF file, downloads each section (a command and a payload)
442 * to the device's address space. Actually, it just executes each
443 * command i the BCF file.
444 *
445 * The section size has to be aligned to 4 bytes AND the padding has
446 * to be taken from the firmware file, as the signature takes it into
447 * account.
448 */
449static
450ssize_t i2400m_dnload_bcf(struct i2400m *i2400m,
451 const struct i2400m_bcf_hdr *bcf, size_t bcf_len)
452{
453 ssize_t ret;
454 struct device *dev = i2400m_dev(i2400m);
455 size_t offset, /* iterator offset */
456 data_size, /* Size of the data payload */
457 section_size, /* Size of the whole section (cmd + payload) */
458 section = 1;
459 const struct i2400m_bootrom_header *bh;
460 struct i2400m_bootrom_header ack;
461
462 d_fnstart(3, dev, "(i2400m %p bcf %p bcf_len %zu)\n",
463 i2400m, bcf, bcf_len);
464 /* Iterate over the command blocks in the BCF file that start
465 * after the header */
466 offset = le32_to_cpu(bcf->header_len) * sizeof(u32);
467 while (1) { /* start sending the file */
468 bh = (void *) bcf + offset;
469 data_size = le32_to_cpu(bh->data_size);
470 section_size = ALIGN(sizeof(*bh) + data_size, 4);
471 d_printf(7, dev,
472 "downloading section #%zu (@%zu %zu B) to 0x%08x\n",
473 section, offset, sizeof(*bh) + data_size,
474 le32_to_cpu(bh->target_addr));
475 if (i2400m_brh_get_opcode(bh) == I2400M_BRH_SIGNED_JUMP) {
476 /* Secure boot needs to stop here */
477 d_printf(5, dev, "signed jump found @%zu\n", offset);
478 break;
479 }
480 if (offset + section_size == bcf_len)
481 /* Non-secure boot stops here */
482 break;
483 if (offset + section_size > bcf_len) {
484 dev_err(dev, "fw %s: bad section #%zu, "
485 "end (@%zu) beyond EOF (@%zu)\n",
486 i2400m->bus_fw_name, section,
487 offset + section_size, bcf_len);
488 ret = -EINVAL;
489 goto error_section_beyond_eof;
490 }
491 __i2400m_msleep(20);
492 ret = i2400m_bm_cmd(i2400m, bh, section_size,
493 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
494 if (ret < 0) {
495 dev_err(dev, "fw %s: section #%zu (@%zu %zu B) "
496 "failed %d\n", i2400m->bus_fw_name, section,
497 offset, sizeof(*bh) + data_size, (int) ret);
498 goto error_send;
499 }
500 offset += section_size;
501 section++;
502 }
503 ret = offset;
504error_section_beyond_eof:
505error_send:
506 d_fnend(3, dev, "(i2400m %p bcf %p bcf_len %zu) = %d\n",
507 i2400m, bcf, bcf_len, (int) ret);
508 return ret;
509}
510
511
512/*
513 * Do the final steps of uploading firmware
514 *
515 * Depending on the boot mode (signed vs non-signed), different
516 * actions need to be taken.
517 */
518static
519int i2400m_dnload_finalize(struct i2400m *i2400m,
520 const struct i2400m_bcf_hdr *bcf, size_t offset)
521{
522 int ret = 0;
523 struct device *dev = i2400m_dev(i2400m);
524 struct i2400m_bootrom_header *cmd, ack;
525 struct {
526 struct i2400m_bootrom_header cmd;
527 u8 cmd_pl[0];
528 } __attribute__((packed)) *cmd_buf;
529 size_t signature_block_offset, signature_block_size;
530
531 d_fnstart(3, dev, "offset %zu\n", offset);
532 cmd = (void *) bcf + offset;
533 if (i2400m->sboot == 0) {
534 struct i2400m_bootrom_header jump_ack;
535 d_printf(3, dev, "unsecure boot, jumping to 0x%08x\n",
536 le32_to_cpu(cmd->target_addr));
537 i2400m_brh_set_opcode(cmd, I2400M_BRH_JUMP);
538 cmd->data_size = 0;
539 ret = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
540 &jump_ack, sizeof(jump_ack), 0);
541 } else {
542 d_printf(3, dev, "secure boot, jumping to 0x%08x\n",
543 le32_to_cpu(cmd->target_addr));
544 cmd_buf = i2400m->bm_cmd_buf;
545 memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd));
546 signature_block_offset =
547 sizeof(*bcf)
548 + le32_to_cpu(bcf->key_size) * sizeof(u32)
549 + le32_to_cpu(bcf->exponent_size) * sizeof(u32);
550 signature_block_size =
551 le32_to_cpu(bcf->modulus_size) * sizeof(u32);
552 memcpy(cmd_buf->cmd_pl, (void *) bcf + signature_block_offset,
553 signature_block_size);
554 ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd,
555 sizeof(cmd_buf->cmd) + signature_block_size,
556 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
557 }
558 d_fnend(3, dev, "returning %d\n", ret);
559 return ret;
560}
561
562
563/**
564 * i2400m_bootrom_init - Reboots a powered device into boot mode
565 *
566 * @i2400m: device descriptor
567 * @flags:
568 * I2400M_BRI_SOFT: a reboot notification has been seen
569 * already, so don't wait for it.
570 *
571 * I2400M_BRI_NO_REBOOT: Don't send a reboot command, but wait
572 * for a reboot barker notification. This is a one shot; if
573 * the state machine needs to send a reboot command it will.
574 *
575 * Returns:
576 *
577 * < 0 errno code on error, 0 if ok.
578 *
579 * i2400m->sboot set to 0 for unsecure boot process, 1 for secure
580 * boot process.
581 *
582 * Description:
583 *
584 * Tries hard enough to put the device in boot-mode. There are two
585 * main phases to this:
586 *
587 * a. (1) send a reboot command and (2) get a reboot barker
588 * b. (1) ack the reboot sending a reboot barker and (2) getting an
589 * ack barker in return
590 *
591 * We want to skip (a) in some cases [soft]. The state machine is
592 * horrible, but it is basically: on each phase, send what has to be
593 * sent (if any), wait for the answer and act on the answer. We might
594 * have to backtrack and retry, so we keep a max tries counter for
595 * that.
596 *
597 * If we get a timeout after sending a warm reset, we do it again.
598 */
599int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags)
600{
601 int result;
602 struct device *dev = i2400m_dev(i2400m);
603 struct i2400m_bootrom_header *cmd;
604 struct i2400m_bootrom_header ack;
605 int count = I2400M_BOOT_RETRIES;
606 int ack_timeout_cnt = 1;
607
608 BUILD_BUG_ON(sizeof(*cmd) != sizeof(i2400m_NBOOT_BARKER));
609 BUILD_BUG_ON(sizeof(ack) != sizeof(i2400m_ACK_BARKER));
610
611 d_fnstart(4, dev, "(i2400m %p flags 0x%08x)\n", i2400m, flags);
612 result = -ENOMEM;
613 cmd = i2400m->bm_cmd_buf;
614 if (flags & I2400M_BRI_SOFT)
615 goto do_reboot_ack;
616do_reboot:
617 if (--count < 0)
618 goto error_timeout;
619 d_printf(4, dev, "device reboot: reboot command [%d # left]\n",
620 count);
621 if ((flags & I2400M_BRI_NO_REBOOT) == 0)
622 i2400m->bus_reset(i2400m, I2400M_RT_WARM);
623 result = i2400m_bm_cmd(i2400m, NULL, 0, &ack, sizeof(ack),
624 I2400M_BM_CMD_RAW);
625 flags &= ~I2400M_BRI_NO_REBOOT;
626 switch (result) {
627 case -ERESTARTSYS:
628 d_printf(4, dev, "device reboot: got reboot barker\n");
629 break;
630 case -EISCONN: /* we don't know how it got here...but we follow it */
631 d_printf(4, dev, "device reboot: got ack barker - whatever\n");
632 goto do_reboot;
633 case -ETIMEDOUT: /* device has timed out, we might be in boot
634 * mode already and expecting an ack, let's try
635 * that */
636 dev_info(dev, "warm reset timed out, trying an ack\n");
637 goto do_reboot_ack;
638 case -EPROTO:
639 case -ESHUTDOWN: /* dev is gone */
640 case -EINTR: /* user cancelled */
641 goto error_dev_gone;
642 default:
643 dev_err(dev, "device reboot: error %d while waiting "
644 "for reboot barker - rebooting\n", result);
645 goto do_reboot;
646 }
647 /* At this point we ack back with 4 REBOOT barkers and expect
648 * 4 ACK barkers. This is ugly, as we send a raw command --
649 * hence the cast. _bm_cmd() will catch the reboot ack
650 * notification and report it as -EISCONN. */
651do_reboot_ack:
652 d_printf(4, dev, "device reboot ack: sending ack [%d # left]\n", count);
653 if (i2400m->sboot == 0)
654 memcpy(cmd, i2400m_NBOOT_BARKER,
655 sizeof(i2400m_NBOOT_BARKER));
656 else
657 memcpy(cmd, i2400m_SBOOT_BARKER,
658 sizeof(i2400m_SBOOT_BARKER));
659 result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
660 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
661 switch (result) {
662 case -ERESTARTSYS:
663 d_printf(4, dev, "reboot ack: got reboot barker - retrying\n");
664 if (--count < 0)
665 goto error_timeout;
666 goto do_reboot_ack;
667 case -EISCONN:
668 d_printf(4, dev, "reboot ack: got ack barker - good\n");
669 break;
670 case -ETIMEDOUT: /* no response, maybe it is the other type? */
671 if (ack_timeout_cnt-- >= 0) {
672 d_printf(4, dev, "reboot ack timedout: "
673 "trying the other type?\n");
674 i2400m->sboot = !i2400m->sboot;
675 goto do_reboot_ack;
676 } else {
677 dev_err(dev, "reboot ack timedout too long: "
678 "trying reboot\n");
679 goto do_reboot;
680 }
681 break;
682 case -EPROTO:
683 case -ESHUTDOWN: /* dev is gone */
684 goto error_dev_gone;
685 default:
686 dev_err(dev, "device reboot ack: error %d while waiting for "
687 "reboot ack barker - rebooting\n", result);
688 goto do_reboot;
689 }
690 d_printf(2, dev, "device reboot ack: got ack barker - boot done\n");
691 result = 0;
692exit_timeout:
693error_dev_gone:
694 d_fnend(4, dev, "(i2400m %p flags 0x%08x) = %d\n",
695 i2400m, flags, result);
696 return result;
697
698error_timeout:
699 dev_err(dev, "Timed out waiting for reboot ack, resetting\n");
700 i2400m->bus_reset(i2400m, I2400M_RT_BUS);
701 result = -ETIMEDOUT;
702 goto exit_timeout;
703}
704
705
706/*
707 * Read the MAC addr
708 *
709 * The position this function reads is fixed in device memory and
710 * always available, even without firmware.
711 *
712 * Note we specify we want to read only six bytes, but provide space
713 * for 16, as we always get it rounded up.
714 */
715int i2400m_read_mac_addr(struct i2400m *i2400m)
716{
717 int result;
718 struct device *dev = i2400m_dev(i2400m);
719 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
720 struct i2400m_bootrom_header *cmd;
721 struct {
722 struct i2400m_bootrom_header ack;
723 u8 ack_pl[16];
724 } __attribute__((packed)) ack_buf;
725
726 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
727 cmd = i2400m->bm_cmd_buf;
728 cmd->command = i2400m_brh_command(I2400M_BRH_READ, 0, 1);
729 cmd->target_addr = cpu_to_le32(0x00203fe8);
730 cmd->data_size = cpu_to_le32(6);
731 result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
732 &ack_buf.ack, sizeof(ack_buf), 0);
733 if (result < 0) {
734 dev_err(dev, "BM: read mac addr failed: %d\n", result);
735 goto error_read_mac;
736 }
737 d_printf(2, dev,
738 "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n",
739 ack_buf.ack_pl[0], ack_buf.ack_pl[1],
740 ack_buf.ack_pl[2], ack_buf.ack_pl[3],
741 ack_buf.ack_pl[4], ack_buf.ack_pl[5]);
742 if (i2400m->bus_bm_mac_addr_impaired == 1) {
743 ack_buf.ack_pl[0] = 0x00;
744 ack_buf.ack_pl[1] = 0x16;
745 ack_buf.ack_pl[2] = 0xd3;
746 get_random_bytes(&ack_buf.ack_pl[3], 3);
747 dev_err(dev, "BM is MAC addr impaired, faking MAC addr to "
748 "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n",
749 ack_buf.ack_pl[0], ack_buf.ack_pl[1],
750 ack_buf.ack_pl[2], ack_buf.ack_pl[3],
751 ack_buf.ack_pl[4], ack_buf.ack_pl[5]);
752 result = 0;
753 }
754 net_dev->addr_len = ETH_ALEN;
755 memcpy(net_dev->perm_addr, ack_buf.ack_pl, ETH_ALEN);
756 memcpy(net_dev->dev_addr, ack_buf.ack_pl, ETH_ALEN);
757error_read_mac:
758 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, result);
759 return result;
760}
761
762
763/*
764 * Initialize a non signed boot
765 *
766 * This implies sending some magic values to the device's memory. Note
767 * we convert the values to little endian in the same array
768 * declaration.
769 */
770static
771int i2400m_dnload_init_nonsigned(struct i2400m *i2400m)
772{
773#define POKE(a, d) { \
774 .address = __constant_cpu_to_le32(a), \
775 .data = __constant_cpu_to_le32(d) \
776}
777 static const struct {
778 __le32 address;
779 __le32 data;
780 } i2400m_pokes[] = {
781 POKE(0x081A58, 0xA7810230),
782 POKE(0x080040, 0x00000000),
783 POKE(0x080048, 0x00000082),
784 POKE(0x08004C, 0x0000081F),
785 POKE(0x080054, 0x00000085),
786 POKE(0x080058, 0x00000180),
787 POKE(0x08005C, 0x00000018),
788 POKE(0x080060, 0x00000010),
789 POKE(0x080574, 0x00000001),
790 POKE(0x080550, 0x00000005),
791 POKE(0xAE0000, 0x00000000),
792 };
793#undef POKE
794 unsigned i;
795 int ret;
796 struct device *dev = i2400m_dev(i2400m);
797
798 dev_warn(dev, "WARNING!!! non-signed boot UNTESTED PATH!\n");
799
800 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
801 for (i = 0; i < ARRAY_SIZE(i2400m_pokes); i++) {
802 ret = i2400m_download_chunk(i2400m, &i2400m_pokes[i].data,
803 sizeof(i2400m_pokes[i].data),
804 i2400m_pokes[i].address, 1, 1);
805 if (ret < 0)
806 break;
807 }
808 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
809 return ret;
810}
811
812
813/*
814 * Initialize the signed boot process
815 *
816 * @i2400m: device descriptor
817 *
818 * @bcf_hdr: pointer to the firmware header; assumes it is fully in
819 * memory (it has gone through basic validation).
820 *
821 * Returns: 0 if ok, < 0 errno code on error, -ERESTARTSYS if the hw
822 * rebooted.
823 *
824 * This writes the firmware BCF header to the device using the
825 * HASH_PAYLOAD_ONLY command.
826 */
827static
828int i2400m_dnload_init_signed(struct i2400m *i2400m,
829 const struct i2400m_bcf_hdr *bcf_hdr)
830{
831 int ret;
832 struct device *dev = i2400m_dev(i2400m);
833 struct {
834 struct i2400m_bootrom_header cmd;
835 struct i2400m_bcf_hdr cmd_pl;
836 } __attribute__((packed)) *cmd_buf;
837 struct i2400m_bootrom_header ack;
838
839 d_fnstart(5, dev, "(i2400m %p bcf_hdr %p)\n", i2400m, bcf_hdr);
840 cmd_buf = i2400m->bm_cmd_buf;
841 cmd_buf->cmd.command =
842 i2400m_brh_command(I2400M_BRH_HASH_PAYLOAD_ONLY, 0, 0);
843 cmd_buf->cmd.target_addr = 0;
844 cmd_buf->cmd.data_size = cpu_to_le32(sizeof(cmd_buf->cmd_pl));
845 memcpy(&cmd_buf->cmd_pl, bcf_hdr, sizeof(*bcf_hdr));
846 ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd, sizeof(*cmd_buf),
847 &ack, sizeof(ack), 0);
848 if (ret >= 0)
849 ret = 0;
850 d_fnend(5, dev, "(i2400m %p bcf_hdr %p) = %d\n", i2400m, bcf_hdr, ret);
851 return ret;
852}
853
854
855/*
856 * Initialize the firmware download at the device size
857 *
858 * Multiplex to the one that matters based on the device's mode
859 * (signed or non-signed).
860 */
861static
862int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf)
863{
864 int result;
865 struct device *dev = i2400m_dev(i2400m);
866 u32 module_id = le32_to_cpu(bcf->module_id);
867
868 if (i2400m->sboot == 0
869 && (module_id & I2400M_BCF_MOD_ID_POKES) == 0) {
870 /* non-signed boot process without pokes */
871 result = i2400m_dnload_init_nonsigned(i2400m);
872 if (result == -ERESTARTSYS)
873 return result;
874 if (result < 0)
875 dev_err(dev, "fw %s: non-signed download "
876 "initialization failed: %d\n",
877 i2400m->bus_fw_name, result);
878 } else if (i2400m->sboot == 0
879 && (module_id & I2400M_BCF_MOD_ID_POKES)) {
880 /* non-signed boot process with pokes, nothing to do */
881 result = 0;
882 } else { /* signed boot process */
883 result = i2400m_dnload_init_signed(i2400m, bcf);
884 if (result == -ERESTARTSYS)
885 return result;
886 if (result < 0)
887 dev_err(dev, "fw %s: signed boot download "
888 "initialization failed: %d\n",
889 i2400m->bus_fw_name, result);
890 }
891 return result;
892}
893
894
895/*
896 * Run quick consistency tests on the firmware file
897 *
898 * Check for the firmware being made for the i2400m device,
899 * etc...These checks are mostly informative, as the device will make
900 * them too; but the driver's response is more informative on what
901 * went wrong.
902 */
903static
904int i2400m_fw_check(struct i2400m *i2400m,
905 const struct i2400m_bcf_hdr *bcf,
906 size_t bcf_size)
907{
908 int result;
909 struct device *dev = i2400m_dev(i2400m);
910 unsigned module_type, header_len, major_version, minor_version,
911 module_id, module_vendor, date, size;
912
913 /* Check hard errors */
914 result = -EINVAL;
915 if (bcf_size < sizeof(*bcf)) { /* big enough header? */
916 dev_err(dev, "firmware %s too short: "
917 "%zu B vs %zu (at least) expected\n",
918 i2400m->bus_fw_name, bcf_size, sizeof(*bcf));
919 goto error;
920 }
921
922 module_type = bcf->module_type;
923 header_len = sizeof(u32) * le32_to_cpu(bcf->header_len);
924 major_version = le32_to_cpu(bcf->header_version) & 0xffff0000 >> 16;
925 minor_version = le32_to_cpu(bcf->header_version) & 0x0000ffff;
926 module_id = le32_to_cpu(bcf->module_id);
927 module_vendor = le32_to_cpu(bcf->module_vendor);
928 date = le32_to_cpu(bcf->date);
929 size = sizeof(u32) * le32_to_cpu(bcf->size);
930
931 if (bcf_size != size) { /* annoyingly paranoid */
932 dev_err(dev, "firmware %s: bad size, got "
933 "%zu B vs %u expected\n",
934 i2400m->bus_fw_name, bcf_size, size);
935 goto error;
936 }
937
938 d_printf(2, dev, "type 0x%x id 0x%x vendor 0x%x; header v%u.%u (%zu B) "
939 "date %08x (%zu B)\n",
940 module_type, module_id, module_vendor,
941 major_version, minor_version, (size_t) header_len,
942 date, (size_t) size);
943
944 if (module_type != 6) { /* built for the right hardware? */
945 dev_err(dev, "bad fw %s: unexpected module type 0x%x; "
946 "aborting\n", i2400m->bus_fw_name, module_type);
947 goto error;
948 }
949
950 /* Check soft-er errors */
951 result = 0;
952 if (module_vendor != 0x8086)
953 dev_err(dev, "bad fw %s? unexpected vendor 0x%04x\n",
954 i2400m->bus_fw_name, module_vendor);
955 if (date < 0x20080300)
956 dev_err(dev, "bad fw %s? build date too old %08x\n",
957 i2400m->bus_fw_name, date);
958error:
959 return result;
960}
961
962
963/*
964 * Download the firmware to the device
965 *
966 * @i2400m: device descriptor
967 * @bcf: pointer to loaded (and minimally verified for consistency)
968 * firmware
969 * @bcf_size: size of the @bcf buffer (header plus payloads)
970 *
971 * The process for doing this is described in this file's header.
972 *
973 * Note we only reinitialize boot-mode if the flags say so. Some hw
974 * iterations need it, some don't. In any case, if we loop, we always
975 * need to reinitialize the boot room, hence the flags modification.
976 */
977static
978int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
979 size_t bcf_size, enum i2400m_bri flags)
980{
981 int ret = 0;
982 struct device *dev = i2400m_dev(i2400m);
983 int count = I2400M_BOOT_RETRIES;
984
985 d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n",
986 i2400m, bcf, bcf_size);
987 i2400m->boot_mode = 1;
988hw_reboot:
989 if (count-- == 0) {
990 ret = -ERESTARTSYS;
991 dev_err(dev, "device rebooted too many times, aborting\n");
992 goto error_too_many_reboots;
993 }
994 if (flags & I2400M_BRI_MAC_REINIT) {
995 ret = i2400m_bootrom_init(i2400m, flags);
996 if (ret < 0) {
997 dev_err(dev, "bootrom init failed: %d\n", ret);
998 goto error_bootrom_init;
999 }
1000 }
1001 flags |= I2400M_BRI_MAC_REINIT;
1002
1003 /*
1004 * Initialize the download, push the bytes to the device and
1005 * then jump to the new firmware. Note @ret is passed with the
1006 * offset of the jump instruction to _dnload_finalize()
1007 */
1008 ret = i2400m_dnload_init(i2400m, bcf); /* Init device's dnload */
1009 if (ret == -ERESTARTSYS)
1010 goto error_dev_rebooted;
1011 if (ret < 0)
1012 goto error_dnload_init;
1013
1014 ret = i2400m_dnload_bcf(i2400m, bcf, bcf_size);
1015 if (ret == -ERESTARTSYS)
1016 goto error_dev_rebooted;
1017 if (ret < 0) {
1018 dev_err(dev, "fw %s: download failed: %d\n",
1019 i2400m->bus_fw_name, ret);
1020 goto error_dnload_bcf;
1021 }
1022
1023 ret = i2400m_dnload_finalize(i2400m, bcf, ret);
1024 if (ret == -ERESTARTSYS)
1025 goto error_dev_rebooted;
1026 if (ret < 0) {
1027 dev_err(dev, "fw %s: "
1028 "download finalization failed: %d\n",
1029 i2400m->bus_fw_name, ret);
1030 goto error_dnload_finalize;
1031 }
1032
1033 d_printf(2, dev, "fw %s successfully uploaded\n",
1034 i2400m->bus_fw_name);
1035 i2400m->boot_mode = 0;
1036error_dnload_finalize:
1037error_dnload_bcf:
1038error_dnload_init:
1039error_bootrom_init:
1040error_too_many_reboots:
1041 d_fnend(5, dev, "(i2400m %p bcf %p size %zu) = %d\n",
1042 i2400m, bcf, bcf_size, ret);
1043 return ret;
1044
1045error_dev_rebooted:
1046 dev_err(dev, "device rebooted, %d tries left\n", count);
1047 /* we got the notification already, no need to wait for it again */
1048 flags |= I2400M_BRI_SOFT;
1049 goto hw_reboot;
1050}
1051
1052
1053/**
1054 * i2400m_dev_bootstrap - Bring the device to a known state and upload firmware
1055 *
1056 * @i2400m: device descriptor
1057 *
1058 * Returns: >= 0 if ok, < 0 errno code on error.
1059 *
1060 * This sets up the firmware upload environment, loads the firmware
1061 * file from disk, verifies and then calls the firmware upload process
1062 * per se.
1063 *
1064 * Can be called either from probe, or after a warm reset. Can not be
1065 * called from within an interrupt. All the flow in this code is
1066 * single-threade; all I/Os are synchronous.
1067 */
1068int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags)
1069{
1070 int ret = 0;
1071 struct device *dev = i2400m_dev(i2400m);
1072 const struct firmware *fw;
1073 const struct i2400m_bcf_hdr *bcf; /* Firmware data */
1074
1075 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
1076 /* Load firmware files to memory. */
1077 ret = request_firmware(&fw, i2400m->bus_fw_name, dev);
1078 if (ret) {
1079 dev_err(dev, "fw %s: request failed: %d\n",
1080 i2400m->bus_fw_name, ret);
1081 goto error_fw_req;
1082 }
1083 bcf = (void *) fw->data;
1084
1085 ret = i2400m_fw_check(i2400m, bcf, fw->size);
1086 if (ret < 0)
1087 goto error_fw_bad;
1088 ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags);
1089error_fw_bad:
1090 release_firmware(fw);
1091error_fw_req:
1092 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
1093 return ret;
1094}
1095EXPORT_SYMBOL_GPL(i2400m_dev_bootstrap);
diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h
new file mode 100644
index 000000000000..08c2fb739234
--- /dev/null
+++ b/drivers/net/wimax/i2400m/i2400m-sdio.h
@@ -0,0 +1,132 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * SDIO-specific i2400m driver definitions
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Brian Bian <brian.bian@intel.com>
37 * Dirk Brandewie <dirk.j.brandewie@intel.com>
38 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
39 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
40 * - Initial implementation
41 *
42 *
43 * This driver implements the bus-specific part of the i2400m for
44 * SDIO. Check i2400m.h for a generic driver description.
45 *
46 * ARCHITECTURE
47 *
48 * This driver sits under the bus-generic i2400m driver, providing the
49 * connection to the device.
50 *
51 * When probed, all the function pointers are setup and then the
52 * bus-generic code called. The generic driver will then use the
53 * provided pointers for uploading firmware (i2400ms_bus_bm*() in
54 * sdio-fw.c) and then setting up the device (i2400ms_dev_*() in
55 * sdio.c).
56 *
57 * Once firmware is uploaded, TX functions (sdio-tx.c) are called when
58 * data is ready for transmission in the TX fifo; then the SDIO IRQ is
59 * fired and data is available (sdio-rx.c), it is sent to the generic
60 * driver for processing with i2400m_rx.
61 */
62
63#ifndef __I2400M_SDIO_H__
64#define __I2400M_SDIO_H__
65
66#include "i2400m.h"
67
68/* Host-Device interface for SDIO */
69enum {
70 I2400MS_BLK_SIZE = 256,
71 I2400MS_PL_SIZE_MAX = 0x3E00,
72
73 I2400MS_DATA_ADDR = 0x0,
74 I2400MS_INTR_STATUS_ADDR = 0x13,
75 I2400MS_INTR_CLEAR_ADDR = 0x13,
76 I2400MS_INTR_ENABLE_ADDR = 0x14,
77 I2400MS_INTR_GET_SIZE_ADDR = 0x2C,
78 /* The number of ticks to wait for the device to signal that
79 * it is ready */
80 I2400MS_INIT_SLEEP_INTERVAL = 10,
81};
82
83
84/**
85 * struct i2400ms - descriptor for a SDIO connected i2400m
86 *
87 * @i2400m: bus-generic i2400m implementation; has to be first (see
88 * it's documentation in i2400m.h).
89 *
90 * @func: pointer to our SDIO function
91 *
92 * @tx_worker: workqueue struct used to TX data when the bus-generic
93 * code signals packets are pending for transmission to the device.
94 *
95 * @tx_workqueue: workqeueue used for data TX; we don't use the
96 * system's workqueue as that might cause deadlocks with code in
97 * the bus-generic driver.
98 */
99struct i2400ms {
100 struct i2400m i2400m; /* FIRST! See doc */
101 struct sdio_func *func;
102
103 struct work_struct tx_worker;
104 struct workqueue_struct *tx_workqueue;
105 char tx_wq_name[32];
106
107 struct dentry *debugfs_dentry;
108};
109
110
111static inline
112void i2400ms_init(struct i2400ms *i2400ms)
113{
114 i2400m_init(&i2400ms->i2400m);
115}
116
117
118extern int i2400ms_rx_setup(struct i2400ms *);
119extern void i2400ms_rx_release(struct i2400ms *);
120extern ssize_t __i2400ms_rx_get_size(struct i2400ms *);
121
122extern int i2400ms_tx_setup(struct i2400ms *);
123extern void i2400ms_tx_release(struct i2400ms *);
124extern void i2400ms_bus_tx_kick(struct i2400m *);
125
126extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *,
127 const struct i2400m_bootrom_header *,
128 size_t, int);
129extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *,
130 struct i2400m_bootrom_header *,
131 size_t);
132#endif /* #ifndef __I2400M_SDIO_H__ */
diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h
new file mode 100644
index 000000000000..6f76558b170f
--- /dev/null
+++ b/drivers/net/wimax/i2400m/i2400m-usb.h
@@ -0,0 +1,264 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * USB-specific i2400m driver definitions
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
37 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
38 * - Initial implementation
39 *
40 *
41 * This driver implements the bus-specific part of the i2400m for
42 * USB. Check i2400m.h for a generic driver description.
43 *
44 * ARCHITECTURE
45 *
46 * This driver listens to notifications sent from the notification
47 * endpoint (in usb-notif.c); when data is ready to read, the code in
48 * there schedules a read from the device (usb-rx.c) and then passes
49 * the data to the generic RX code (rx.c).
50 *
51 * When the generic driver needs to send data (network or control), it
52 * queues up in the TX FIFO (tx.c) and that will notify the driver
53 * through the i2400m->bus_tx_kick() callback
54 * (usb-tx.c:i2400mu_bus_tx_kick) which will send the items in the
55 * FIFO queue.
56 *
57 * This driver, as well, implements the USB-specific ops for the generic
58 * driver to be able to setup/teardown communication with the device
59 * [i2400m_bus_dev_start() and i2400m_bus_dev_stop()], reseting the
60 * device [i2400m_bus_reset()] and performing firmware upload
61 * [i2400m_bus_bm_cmd() and i2400_bus_bm_wait_for_ack()].
62 */
63
64#ifndef __I2400M_USB_H__
65#define __I2400M_USB_H__
66
67#include "i2400m.h"
68#include <linux/kthread.h>
69
70
71/*
72 * Error Density Count: cheapo error density (over time) counter
73 *
74 * Originally by Reinette Chatre <reinette.chatre@intel.com>
75 *
76 * Embed an 'struct edc' somewhere. Each time there is a soft or
77 * retryable error, call edc_inc() and check if the error top
78 * watermark has been reached.
79 */
80enum {
81 EDC_MAX_ERRORS = 10,
82 EDC_ERROR_TIMEFRAME = HZ,
83};
84
85/* error density counter */
86struct edc {
87 unsigned long timestart;
88 u16 errorcount;
89};
90
91static inline void edc_init(struct edc *edc)
92{
93 edc->timestart = jiffies;
94}
95
96/**
97 * edc_inc - report a soft error and check if we are over the watermark
98 *
99 * @edc: pointer to error density counter.
100 * @max_err: maximum number of errors we can accept over the timeframe
101 * @timeframe: lenght of the timeframe (in jiffies).
102 *
103 * Returns: !0 1 if maximum acceptable errors per timeframe has been
104 * exceeded. 0 otherwise.
105 *
106 * This is way to determine if the number of acceptable errors per time
107 * period has been exceeded. It is not accurate as there are cases in which
108 * this scheme will not work, for example if there are periodic occurences
109 * of errors that straddle updates to the start time. This scheme is
110 * sufficient for our usage.
111 *
112 * To use, embed a 'struct edc' somewhere, initialize it with
113 * edc_init() and when an error hits:
114 *
115 * if (do_something_fails_with_a_soft_error) {
116 * if (edc_inc(&my->edc, MAX_ERRORS, MAX_TIMEFRAME))
117 * Ops, hard error, do something about it
118 * else
119 * Retry or ignore, depending on whatever
120 * }
121 */
122static inline int edc_inc(struct edc *edc, u16 max_err, u16 timeframe)
123{
124 unsigned long now;
125
126 now = jiffies;
127 if (now - edc->timestart > timeframe) {
128 edc->errorcount = 1;
129 edc->timestart = now;
130 } else if (++edc->errorcount > max_err) {
131 edc->errorcount = 0;
132 edc->timestart = now;
133 return 1;
134 }
135 return 0;
136}
137
138/* Host-Device interface for USB */
139enum {
140 I2400MU_MAX_NOTIFICATION_LEN = 256,
141 I2400MU_BLK_SIZE = 16,
142 I2400MU_PL_SIZE_MAX = 0x3EFF,
143
144 /* Endpoints */
145 I2400MU_EP_BULK_OUT = 0,
146 I2400MU_EP_NOTIFICATION,
147 I2400MU_EP_RESET_COLD,
148 I2400MU_EP_BULK_IN,
149};
150
151
152/**
153 * struct i2400mu - descriptor for a USB connected i2400m
154 *
155 * @i2400m: bus-generic i2400m implementation; has to be first (see
156 * it's documentation in i2400m.h).
157 *
158 * @usb_dev: pointer to our USB device
159 *
160 * @usb_iface: pointer to our USB interface
161 *
162 * @urb_edc: error density counter; used to keep a density-on-time tab
163 * on how many soft (retryable or ignorable) errors we get. If we
164 * go over the threshold, we consider the bus transport is failing
165 * too much and reset.
166 *
167 * @notif_urb: URB for receiving notifications from the device.
168 *
169 * @tx_kthread: thread we use for data TX. We use a thread because in
170 * order to do deep power saving and put the device to sleep, we
171 * need to call usb_autopm_*() [blocking functions].
172 *
173 * @tx_wq: waitqueue for the TX kthread to sleep when there is no data
174 * to be sent; when more data is available, it is woken up by
175 * i2400mu_bus_tx_kick().
176 *
177 * @rx_kthread: thread we use for data RX. We use a thread because in
178 * order to do deep power saving and put the device to sleep, we
179 * need to call usb_autopm_*() [blocking functions].
180 *
181 * @rx_wq: waitqueue for the RX kthread to sleep when there is no data
182 * to receive. When data is available, it is woken up by
183 * usb-notif.c:i2400mu_notification_grok().
184 *
185 * @rx_pending_count: number of rx-data-ready notifications that were
186 * still not handled by the RX kthread.
187 *
188 * @rx_size: current RX buffer size that is being used.
189 *
190 * @rx_size_acc: accumulator of the sizes of the previous read
191 * transactions.
192 *
193 * @rx_size_cnt: number of read transactions accumulated in
194 * @rx_size_acc.
195 *
196 * @do_autopm: disable(0)/enable(>0) calling the
197 * usb_autopm_get/put_interface() barriers when executing
198 * commands. See doc in i2400mu_suspend() for more information.
199 *
200 * @rx_size_auto_shrink: if true, the rx_size is shrinked
201 * automatically based on the average size of the received
202 * transactions. This allows the receive code to allocate smaller
203 * chunks of memory and thus reduce pressure on the memory
204 * allocator by not wasting so much space. By default it is
205 * enabled.
206 *
207 * @debugfs_dentry: hookup for debugfs files.
208 * These have to be in a separate directory, a child of
209 * (wimax_dev->debugfs_dentry) so they can be removed when the
210 * module unloads, as we don't keep each dentry.
211 */
212struct i2400mu {
213 struct i2400m i2400m; /* FIRST! See doc */
214
215 struct usb_device *usb_dev;
216 struct usb_interface *usb_iface;
217 struct edc urb_edc; /* Error density counter */
218
219 struct urb *notif_urb;
220 struct task_struct *tx_kthread;
221 wait_queue_head_t tx_wq;
222
223 struct task_struct *rx_kthread;
224 wait_queue_head_t rx_wq;
225 atomic_t rx_pending_count;
226 size_t rx_size, rx_size_acc, rx_size_cnt;
227 atomic_t do_autopm;
228 u8 rx_size_auto_shrink;
229
230 struct dentry *debugfs_dentry;
231};
232
233
234static inline
235void i2400mu_init(struct i2400mu *i2400mu)
236{
237 i2400m_init(&i2400mu->i2400m);
238 edc_init(&i2400mu->urb_edc);
239 init_waitqueue_head(&i2400mu->tx_wq);
240 atomic_set(&i2400mu->rx_pending_count, 0);
241 init_waitqueue_head(&i2400mu->rx_wq);
242 i2400mu->rx_size = PAGE_SIZE - sizeof(struct skb_shared_info);
243 atomic_set(&i2400mu->do_autopm, 1);
244 i2400mu->rx_size_auto_shrink = 1;
245}
246
247extern int i2400mu_notification_setup(struct i2400mu *);
248extern void i2400mu_notification_release(struct i2400mu *);
249
250extern int i2400mu_rx_setup(struct i2400mu *);
251extern void i2400mu_rx_release(struct i2400mu *);
252extern void i2400mu_rx_kick(struct i2400mu *);
253
254extern int i2400mu_tx_setup(struct i2400mu *);
255extern void i2400mu_tx_release(struct i2400mu *);
256extern void i2400mu_bus_tx_kick(struct i2400m *);
257
258extern ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *,
259 const struct i2400m_bootrom_header *,
260 size_t, int);
261extern ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *,
262 struct i2400m_bootrom_header *,
263 size_t);
264#endif /* #ifndef __I2400M_USB_H__ */
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
new file mode 100644
index 000000000000..067c871cc226
--- /dev/null
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -0,0 +1,755 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Declarations for bus-generic internal APIs
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
37 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
38 * - Initial implementation
39 *
40 *
41 * GENERAL DRIVER ARCHITECTURE
42 *
43 * The i2400m driver is split in the following two major parts:
44 *
45 * - bus specific driver
46 * - bus generic driver (this part)
47 *
48 * The bus specific driver sets up stuff specific to the bus the
49 * device is connected to (USB, SDIO, PCI, tam-tam...non-authoritative
50 * nor binding list) which is basically the device-model management
51 * (probe/disconnect, etc), moving data from device to kernel and
52 * back, doing the power saving details and reseting the device.
53 *
54 * For details on each bus-specific driver, see it's include file,
55 * i2400m-BUSNAME.h
56 *
57 * The bus-generic functionality break up is:
58 *
59 * - Firmware upload: fw.c - takes care of uploading firmware to the
60 * device. bus-specific driver just needs to provides a way to
61 * execute boot-mode commands and to reset the device.
62 *
63 * - RX handling: rx.c - receives data from the bus-specific code and
64 * feeds it to the network or WiMAX stack or uses it to modify
65 * the driver state. bus-specific driver only has to receive
66 * frames and pass them to this module.
67 *
68 * - TX handling: tx.c - manages the TX FIFO queue and provides means
69 * for the bus-specific TX code to pull data from the FIFO
70 * queue. bus-specific code just pulls frames from this module
71 * to sends them to the device.
72 *
73 * - netdev glue: netdev.c - interface with Linux networking
74 * stack. Pass around data frames, and configure when the
75 * device is up and running or shutdown (through ifconfig up /
76 * down). Bus-generic only.
77 *
78 * - control ops: control.c - implements various commmands for
79 * controlling the device. bus-generic only.
80 *
81 * - device model glue: driver.c - implements helpers for the
82 * device-model glue done by the bus-specific layer
83 * (setup/release the driver resources), turning the device on
84 * and off, handling the device reboots/resets and a few simple
85 * WiMAX stack ops.
86 *
87 * Code is also broken up in linux-glue / device-glue.
88 *
89 * Linux glue contains functions that deal mostly with gluing with the
90 * rest of the Linux kernel.
91 *
92 * Device-glue are functions that deal mostly with the way the device
93 * does things and talk the device's language.
94 *
95 * device-glue code is licensed BSD so other open source OSes can take
96 * it to implement their drivers.
97 *
98 *
99 * APIs AND HEADER FILES
100 *
101 * This bus generic code exports three APIs:
102 *
103 * - HDI (host-device interface) definitions common to all busses
104 * (include/linux/wimax/i2400m.h); these can be also used by user
105 * space code.
106 * - internal API for the bus-generic code
107 * - external API for the bus-specific drivers
108 *
109 *
110 * LIFE CYCLE:
111 *
112 * When the bus-specific driver probes, it allocates a network device
113 * with enough space for it's data structue, that must contain a
114 * &struct i2400m at the top.
115 *
116 * On probe, it needs to fill the i2400m members marked as [fill], as
117 * well as i2400m->wimax_dev.net_dev and call i2400m_setup(). The
118 * i2400m driver will only register with the WiMAX and network stacks;
119 * the only access done to the device is to read the MAC address so we
120 * can register a network device. This calls i2400m_dev_start() to
121 * load firmware, setup communication with the device and configure it
122 * for operation.
123 *
124 * At this point, control and data communications are possible.
125 *
126 * On disconnect/driver unload, the bus-specific disconnect function
127 * calls i2400m_release() to undo i2400m_setup(). i2400m_dev_stop()
128 * shuts the firmware down and releases resources uses to communicate
129 * with the device.
130 *
131 * While the device is up, it might reset. The bus-specific driver has
132 * to catch that situation and call i2400m_dev_reset_handle() to deal
133 * with it (reset the internal driver structures and go back to square
134 * one).
135 */
136
137#ifndef __I2400M_H__
138#define __I2400M_H__
139
140#include <linux/usb.h>
141#include <linux/netdevice.h>
142#include <linux/completion.h>
143#include <linux/rwsem.h>
144#include <asm/atomic.h>
145#include <net/wimax.h>
146#include <linux/wimax/i2400m.h>
147#include <asm/byteorder.h>
148
149/* Misc constants */
150enum {
151 /* Firmware uploading */
152 I2400M_BOOT_RETRIES = 3,
153 /* Size of the Boot Mode Command buffer */
154 I2400M_BM_CMD_BUF_SIZE = 16 * 1024,
155 I2400M_BM_ACK_BUF_SIZE = 256,
156};
157
158
159/* Firmware version we request when pulling the fw image file */
160#define I2400M_FW_VERSION "1.3"
161
162
163/**
164 * i2400m_reset_type - methods to reset a device
165 *
166 * @I2400M_RT_WARM: Reset without device disconnection, device handles
167 * are kept valid but state is back to power on, with firmware
168 * re-uploaded.
169 * @I2400M_RT_COLD: Tell the device to disconnect itself from the bus
170 * and reconnect. Renders all device handles invalid.
171 * @I2400M_RT_BUS: Tells the bus to reset the device; last measure
172 * used when both types above don't work.
173 */
174enum i2400m_reset_type {
175 I2400M_RT_WARM, /* first measure */
176 I2400M_RT_COLD, /* second measure */
177 I2400M_RT_BUS, /* call in artillery */
178};
179
180struct i2400m_reset_ctx;
181
182/**
183 * struct i2400m - descriptor for an Intel 2400m
184 *
185 * Members marked with [fill] must be filled out/initialized before
186 * calling i2400m_setup().
187 *
188 * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16,
189 * so we have a tx_blk_size variable that the bus layer sets to
190 * tell the engine how much of that we need.
191 *
192 * @bus_pl_size_max: [fill] Maximum payload size.
193 *
194 * @bus_dev_start: [fill] Function called by the bus-generic code
195 * [i2400m_dev_start()] to setup the bus-specific communications
196 * to the the device. See LIFE CYCLE above.
197 *
198 * NOTE: Doesn't need to upload the firmware, as that is taken
199 * care of by the bus-generic code.
200 *
201 * @bus_dev_stop: [fill] Function called by the bus-generic code
202 * [i2400m_dev_stop()] to shutdown the bus-specific communications
203 * to the the device. See LIFE CYCLE above.
204 *
205 * This function does not need to reset the device, just tear down
206 * all the host resources created to handle communication with
207 * the device.
208 *
209 * @bus_tx_kick: [fill] Function called by the bus-generic code to let
210 * the bus-specific code know that there is data available in the
211 * TX FIFO for transmission to the device.
212 *
213 * This function cannot sleep.
214 *
215 * @bus_reset: [fill] Function called by the bus-generic code to reset
216 * the device in in various ways. Doesn't need to wait for the
217 * reset to finish.
218 *
219 * If warm or cold reset fail, this function is expected to do a
220 * bus-specific reset (eg: USB reset) to get the device to a
221 * working state (even if it implies device disconecction).
222 *
223 * Note the warm reset is used by the firmware uploader to
224 * reinitialize the device.
225 *
226 * IMPORTANT: this is called very early in the device setup
227 * process, so it cannot rely on common infrastructure being laid
228 * out.
229 *
230 * @bus_bm_cmd_send: [fill] Function called to send a boot-mode
231 * command. Flags are defined in 'enum i2400m_bm_cmd_flags'. This
232 * is synchronous and has to return 0 if ok or < 0 errno code in
233 * any error condition.
234 *
235 * @bus_bm_wait_for_ack: [fill] Function called to wait for a
236 * boot-mode notification (that can be a response to a previously
237 * issued command or an asynchronous one). Will read until all the
238 * indicated size is read or timeout. Reading more or less data
239 * than asked for is an error condition. Return 0 if ok, < 0 errno
240 * code on error.
241 *
242 * The caller to this function will check if the response is a
243 * barker that indicates the device going into reset mode.
244 *
245 * @bus_fw_name: [fill] name of the firmware image (in most cases,
246 * they are all the same for a single release, except that they
247 * have the type of the bus embedded in the name (eg:
248 * i2400m-fw-X-VERSION.sbcf, where X is the bus name).
249 *
250 * @bus_bm_mac_addr_impaired: [fill] Set to true if the device's MAC
251 * address provided in boot mode is kind of broken and needs to
252 * be re-read later on.
253 *
254 *
255 * @wimax_dev: WiMAX generic device for linkage into the kernel WiMAX
256 * stack. Due to the way a net_device is allocated, we need to
257 * force this to be the first field so that we can get from
258 * netdev_priv() the right pointer.
259 *
260 * @state: device's state (as reported by it)
261 *
262 * @state_wq: waitqueue that is woken up whenever the state changes
263 *
264 * @tx_lock: spinlock to protect TX members
265 *
266 * @tx_buf: FIFO buffer for TX; we queue data here
267 *
268 * @tx_in: FIFO index for incoming data. Note this doesn't wrap around
269 * and it is always greater than @tx_out.
270 *
271 * @tx_out: FIFO index for outgoing data
272 *
273 * @tx_msg: current TX message that is active in the FIFO for
274 * appending payloads.
275 *
276 * @tx_sequence: current sequence number for TX messages from the
277 * device to the host.
278 *
279 * @tx_msg_size: size of the current message being transmitted by the
280 * bus-specific code.
281 *
282 * @tx_pl_num: total number of payloads sent
283 *
284 * @tx_pl_max: maximum number of payloads sent in a TX message
285 *
286 * @tx_pl_min: minimum number of payloads sent in a TX message
287 *
288 * @tx_num: number of TX messages sent
289 *
290 * @tx_size_acc: number of bytes in all TX messages sent
291 * (this is different to net_dev's statistics as it also counts
292 * control messages).
293 *
294 * @tx_size_min: smallest TX message sent.
295 *
296 * @tx_size_max: biggest TX message sent.
297 *
298 * @rx_lock: spinlock to protect RX members
299 *
300 * @rx_pl_num: total number of payloads received
301 *
302 * @rx_pl_max: maximum number of payloads received in a RX message
303 *
304 * @rx_pl_min: minimum number of payloads received in a RX message
305 *
306 * @rx_num: number of RX messages received
307 *
308 * @rx_size_acc: number of bytes in all RX messages received
309 * (this is different to net_dev's statistics as it also counts
310 * control messages).
311 *
312 * @rx_size_min: smallest RX message received.
313 *
314 * @rx_size_max: buggest RX message received.
315 *
316 * @init_mutex: Mutex used for serializing the device bringup
317 * sequence; this way if the device reboots in the middle, we
318 * don't try to do a bringup again while we are tearing down the
319 * one that failed.
320 *
321 * Can't reuse @msg_mutex because from within the bringup sequence
322 * we need to send messages to the device and thus use @msg_mutex.
323 *
324 * @msg_mutex: mutex used to send control commands to the device (we
325 * only allow one at a time, per host-device interface design).
326 *
327 * @msg_completion: used to wait for an ack to a control command sent
328 * to the device.
329 *
330 * @ack_skb: used to store the actual ack to a control command if the
331 * reception of the command was successful. Otherwise, a ERR_PTR()
332 * errno code that indicates what failed with the ack reception.
333 *
334 * Only valid after @msg_completion is woken up. Only updateable
335 * if @msg_completion is armed. Only touched by
336 * i2400m_msg_to_dev().
337 *
338 * Protected by @rx_lock. In theory the command execution flow is
339 * sequential, but in case the device sends an out-of-phase or
340 * very delayed response, we need to avoid it trampling current
341 * execution.
342 *
343 * @bm_cmd_buf: boot mode command buffer for composing firmware upload
344 * commands.
345 *
346 * USB can't r/w to stack, vmalloc, etc...as well, we end up
347 * having to alloc/free a lot to compose commands, so we use these
348 * for stagging and not having to realloc all the time.
349 *
350 * This assumes the code always runs serialized. Only one thread
351 * can call i2400m_bm_cmd() at the same time.
352 *
353 * @bm_ack_buf: boot mode acknoledge buffer for staging reception of
354 * responses to commands.
355 *
356 * See @bm_cmd_buf.
357 *
358 * @work_queue: work queue for processing device reports. This
359 * workqueue cannot be used for processing TX or RX to the device,
360 * as from it we'll process device reports, which might require
361 * further communication with the device.
362 *
363 * @debugfs_dentry: hookup for debugfs files.
364 * These have to be in a separate directory, a child of
365 * (wimax_dev->debugfs_dentry) so they can be removed when the
366 * module unloads, as we don't keep each dentry.
367 */
368struct i2400m {
369 struct wimax_dev wimax_dev; /* FIRST! See doc */
370
371 unsigned updown:1; /* Network device is up or down */
372 unsigned boot_mode:1; /* is the device in boot mode? */
373 unsigned sboot:1; /* signed or unsigned fw boot */
374 unsigned ready:1; /* all probing steps done */
375 u8 trace_msg_from_user; /* echo rx msgs to 'trace' pipe */
376 /* typed u8 so debugfs/u8 can tweak */
377 enum i2400m_system_state state;
378 wait_queue_head_t state_wq; /* Woken up when on state updates */
379
380 size_t bus_tx_block_size;
381 size_t bus_pl_size_max;
382 int (*bus_dev_start)(struct i2400m *);
383 void (*bus_dev_stop)(struct i2400m *);
384 void (*bus_tx_kick)(struct i2400m *);
385 int (*bus_reset)(struct i2400m *, enum i2400m_reset_type);
386 ssize_t (*bus_bm_cmd_send)(struct i2400m *,
387 const struct i2400m_bootrom_header *,
388 size_t, int flags);
389 ssize_t (*bus_bm_wait_for_ack)(struct i2400m *,
390 struct i2400m_bootrom_header *, size_t);
391 const char *bus_fw_name;
392 unsigned bus_bm_mac_addr_impaired:1;
393
394 spinlock_t tx_lock; /* protect TX state */
395 void *tx_buf;
396 size_t tx_in, tx_out;
397 struct i2400m_msg_hdr *tx_msg;
398 size_t tx_sequence, tx_msg_size;
399 /* TX stats */
400 unsigned tx_pl_num, tx_pl_max, tx_pl_min,
401 tx_num, tx_size_acc, tx_size_min, tx_size_max;
402
403 /* RX stats */
404 spinlock_t rx_lock; /* protect RX state */
405 unsigned rx_pl_num, rx_pl_max, rx_pl_min,
406 rx_num, rx_size_acc, rx_size_min, rx_size_max;
407
408 struct mutex msg_mutex; /* serialize command execution */
409 struct completion msg_completion;
410 struct sk_buff *ack_skb; /* protected by rx_lock */
411
412 void *bm_ack_buf; /* for receiving acks over USB */
413 void *bm_cmd_buf; /* for issuing commands over USB */
414
415 struct workqueue_struct *work_queue;
416
417 struct mutex init_mutex; /* protect bringup seq */
418 struct i2400m_reset_ctx *reset_ctx; /* protected by init_mutex */
419
420 struct work_struct wake_tx_ws;
421 struct sk_buff *wake_tx_skb;
422
423 struct dentry *debugfs_dentry;
424};
425
426
427/*
428 * Initialize a 'struct i2400m' from all zeroes
429 *
430 * This is a bus-generic API call.
431 */
432static inline
433void i2400m_init(struct i2400m *i2400m)
434{
435 wimax_dev_init(&i2400m->wimax_dev);
436
437 i2400m->boot_mode = 1;
438 init_waitqueue_head(&i2400m->state_wq);
439
440 spin_lock_init(&i2400m->tx_lock);
441 i2400m->tx_pl_min = UINT_MAX;
442 i2400m->tx_size_min = UINT_MAX;
443
444 spin_lock_init(&i2400m->rx_lock);
445 i2400m->rx_pl_min = UINT_MAX;
446 i2400m->rx_size_min = UINT_MAX;
447
448 mutex_init(&i2400m->msg_mutex);
449 init_completion(&i2400m->msg_completion);
450
451 mutex_init(&i2400m->init_mutex);
452 /* wake_tx_ws is initialized in i2400m_tx_setup() */
453}
454
455
456/*
457 * Bus-generic internal APIs
458 * -------------------------
459 */
460
461static inline
462struct i2400m *wimax_dev_to_i2400m(struct wimax_dev *wimax_dev)
463{
464 return container_of(wimax_dev, struct i2400m, wimax_dev);
465}
466
467static inline
468struct i2400m *net_dev_to_i2400m(struct net_device *net_dev)
469{
470 return wimax_dev_to_i2400m(netdev_priv(net_dev));
471}
472
473/*
474 * Boot mode support
475 */
476
477/**
478 * i2400m_bm_cmd_flags - flags to i2400m_bm_cmd()
479 *
480 * @I2400M_BM_CMD_RAW: send the command block as-is, without doing any
481 * extra processing for adding CRC.
482 */
483enum i2400m_bm_cmd_flags {
484 I2400M_BM_CMD_RAW = 1 << 2,
485};
486
487/**
488 * i2400m_bri - Boot-ROM indicators
489 *
490 * Flags for i2400m_bootrom_init() and i2400m_dev_bootstrap() [which
491 * are passed from things like i2400m_setup()]. Can be combined with
492 * |.
493 *
494 * @I2400M_BRI_SOFT: The device rebooted already and a reboot
495 * barker received, proceed directly to ack the boot sequence.
496 * @I2400M_BRI_NO_REBOOT: Do not reboot the device and proceed
497 * directly to wait for a reboot barker from the device.
498 * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot
499 * rom after reading the MAC adress. This is quite a dirty hack,
500 * if you ask me -- the device requires the bootrom to be
501 * intialized after reading the MAC address.
502 */
503enum i2400m_bri {
504 I2400M_BRI_SOFT = 1 << 1,
505 I2400M_BRI_NO_REBOOT = 1 << 2,
506 I2400M_BRI_MAC_REINIT = 1 << 3,
507};
508
509extern void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *);
510extern int i2400m_dev_bootstrap(struct i2400m *, enum i2400m_bri);
511extern int i2400m_read_mac_addr(struct i2400m *);
512extern int i2400m_bootrom_init(struct i2400m *, enum i2400m_bri);
513
514/* Make/grok boot-rom header commands */
515
516static inline
517__le32 i2400m_brh_command(enum i2400m_brh_opcode opcode, unsigned use_checksum,
518 unsigned direct_access)
519{
520 return cpu_to_le32(
521 I2400M_BRH_SIGNATURE
522 | (direct_access ? I2400M_BRH_DIRECT_ACCESS : 0)
523 | I2400M_BRH_RESPONSE_REQUIRED /* response always required */
524 | (use_checksum ? I2400M_BRH_USE_CHECKSUM : 0)
525 | (opcode & I2400M_BRH_OPCODE_MASK));
526}
527
528static inline
529void i2400m_brh_set_opcode(struct i2400m_bootrom_header *hdr,
530 enum i2400m_brh_opcode opcode)
531{
532 hdr->command = cpu_to_le32(
533 (le32_to_cpu(hdr->command) & ~I2400M_BRH_OPCODE_MASK)
534 | (opcode & I2400M_BRH_OPCODE_MASK));
535}
536
537static inline
538unsigned i2400m_brh_get_opcode(const struct i2400m_bootrom_header *hdr)
539{
540 return le32_to_cpu(hdr->command) & I2400M_BRH_OPCODE_MASK;
541}
542
543static inline
544unsigned i2400m_brh_get_response(const struct i2400m_bootrom_header *hdr)
545{
546 return (le32_to_cpu(hdr->command) & I2400M_BRH_RESPONSE_MASK)
547 >> I2400M_BRH_RESPONSE_SHIFT;
548}
549
550static inline
551unsigned i2400m_brh_get_use_checksum(const struct i2400m_bootrom_header *hdr)
552{
553 return le32_to_cpu(hdr->command) & I2400M_BRH_USE_CHECKSUM;
554}
555
556static inline
557unsigned i2400m_brh_get_response_required(
558 const struct i2400m_bootrom_header *hdr)
559{
560 return le32_to_cpu(hdr->command) & I2400M_BRH_RESPONSE_REQUIRED;
561}
562
563static inline
564unsigned i2400m_brh_get_direct_access(const struct i2400m_bootrom_header *hdr)
565{
566 return le32_to_cpu(hdr->command) & I2400M_BRH_DIRECT_ACCESS;
567}
568
569static inline
570unsigned i2400m_brh_get_signature(const struct i2400m_bootrom_header *hdr)
571{
572 return (le32_to_cpu(hdr->command) & I2400M_BRH_SIGNATURE_MASK)
573 >> I2400M_BRH_SIGNATURE_SHIFT;
574}
575
576
577/*
578 * Driver / device setup and internal functions
579 */
580extern void i2400m_netdev_setup(struct net_device *net_dev);
581extern int i2400m_tx_setup(struct i2400m *);
582extern void i2400m_wake_tx_work(struct work_struct *);
583extern void i2400m_tx_release(struct i2400m *);
584
585extern void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned,
586 const void *, int);
587enum i2400m_pt;
588extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt);
589
590#ifdef CONFIG_DEBUG_FS
591extern int i2400m_debugfs_add(struct i2400m *);
592extern void i2400m_debugfs_rm(struct i2400m *);
593#else
594static inline int i2400m_debugfs_add(struct i2400m *i2400m)
595{
596 return 0;
597}
598static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {}
599#endif
600
601/* Called by _dev_start()/_dev_stop() to initialize the device itself */
602extern int i2400m_dev_initialize(struct i2400m *);
603extern void i2400m_dev_shutdown(struct i2400m *);
604
605extern struct attribute_group i2400m_dev_attr_group;
606
607extern int i2400m_schedule_work(struct i2400m *,
608 void (*)(struct work_struct *), gfp_t);
609
610/* HDI message's payload description handling */
611
612static inline
613size_t i2400m_pld_size(const struct i2400m_pld *pld)
614{
615 return I2400M_PLD_SIZE_MASK & le32_to_cpu(pld->val);
616}
617
618static inline
619enum i2400m_pt i2400m_pld_type(const struct i2400m_pld *pld)
620{
621 return (I2400M_PLD_TYPE_MASK & le32_to_cpu(pld->val))
622 >> I2400M_PLD_TYPE_SHIFT;
623}
624
625static inline
626void i2400m_pld_set(struct i2400m_pld *pld, size_t size,
627 enum i2400m_pt type)
628{
629 pld->val = cpu_to_le32(
630 ((type << I2400M_PLD_TYPE_SHIFT) & I2400M_PLD_TYPE_MASK)
631 | (size & I2400M_PLD_SIZE_MASK));
632}
633
634
635/*
636 * API for the bus-specific drivers
637 * --------------------------------
638 */
639
640static inline
641struct i2400m *i2400m_get(struct i2400m *i2400m)
642{
643 dev_hold(i2400m->wimax_dev.net_dev);
644 return i2400m;
645}
646
647static inline
648void i2400m_put(struct i2400m *i2400m)
649{
650 dev_put(i2400m->wimax_dev.net_dev);
651}
652
653extern int i2400m_dev_reset_handle(struct i2400m *);
654
655/*
656 * _setup()/_release() are called by the probe/disconnect functions of
657 * the bus-specific drivers.
658 */
659extern int i2400m_setup(struct i2400m *, enum i2400m_bri bm_flags);
660extern void i2400m_release(struct i2400m *);
661
662extern int i2400m_rx(struct i2400m *, struct sk_buff *);
663extern struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *);
664extern void i2400m_tx_msg_sent(struct i2400m *);
665
666static const __le32 i2400m_NBOOT_BARKER[4] = {
667 __constant_cpu_to_le32(I2400M_NBOOT_BARKER),
668 __constant_cpu_to_le32(I2400M_NBOOT_BARKER),
669 __constant_cpu_to_le32(I2400M_NBOOT_BARKER),
670 __constant_cpu_to_le32(I2400M_NBOOT_BARKER)
671};
672
673static const __le32 i2400m_SBOOT_BARKER[4] = {
674 __constant_cpu_to_le32(I2400M_SBOOT_BARKER),
675 __constant_cpu_to_le32(I2400M_SBOOT_BARKER),
676 __constant_cpu_to_le32(I2400M_SBOOT_BARKER),
677 __constant_cpu_to_le32(I2400M_SBOOT_BARKER)
678};
679
680
681/*
682 * Utility functions
683 */
684
685static inline
686struct device *i2400m_dev(struct i2400m *i2400m)
687{
688 return i2400m->wimax_dev.net_dev->dev.parent;
689}
690
691/*
692 * Helper for scheduling simple work functions
693 *
694 * This struct can get any kind of payload attached (normally in the
695 * form of a struct where you pack the stuff you want to pass to the
696 * _work function).
697 */
698struct i2400m_work {
699 struct work_struct ws;
700 struct i2400m *i2400m;
701 u8 pl[0];
702};
703extern int i2400m_queue_work(struct i2400m *,
704 void (*)(struct work_struct *), gfp_t,
705 const void *, size_t);
706
707extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *,
708 char *, size_t);
709extern int i2400m_msg_size_check(struct i2400m *,
710 const struct i2400m_l3l4_hdr *, size_t);
711extern struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t);
712extern void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int);
713extern void i2400m_msg_ack_hook(struct i2400m *,
714 const struct i2400m_l3l4_hdr *, size_t);
715extern void i2400m_report_hook(struct i2400m *,
716 const struct i2400m_l3l4_hdr *, size_t);
717extern int i2400m_cmd_enter_powersave(struct i2400m *);
718extern int i2400m_cmd_get_state(struct i2400m *);
719extern int i2400m_cmd_exit_idle(struct i2400m *);
720extern struct sk_buff *i2400m_get_device_info(struct i2400m *);
721extern int i2400m_firmware_check(struct i2400m *);
722extern int i2400m_set_init_config(struct i2400m *,
723 const struct i2400m_tlv_hdr **, size_t);
724
725static inline
726struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep)
727{
728 return &iface->cur_altsetting->endpoint[ep].desc;
729}
730
731extern int i2400m_op_rfkill_sw_toggle(struct wimax_dev *,
732 enum wimax_rf_state);
733extern void i2400m_report_tlv_rf_switches_status(
734 struct i2400m *, const struct i2400m_tlv_rf_switches_status *);
735
736
737/*
738 * Do a millisecond-sleep for allowing wireshark to dump all the data
739 * packets. Used only for debugging.
740 */
741static inline
742void __i2400m_msleep(unsigned ms)
743{
744#if 1
745#else
746 msleep(ms);
747#endif
748}
749
750/* Module parameters */
751
752extern int i2400m_idle_mode_disabled;
753
754
755#endif /* #ifndef __I2400M_H__ */
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c
new file mode 100644
index 000000000000..63fe708e8a31
--- /dev/null
+++ b/drivers/net/wimax/i2400m/netdev.c
@@ -0,0 +1,524 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Glue with the networking stack
4 *
5 *
6 * Copyright (C) 2007 Intel Corporation <linux-wimax@intel.com>
7 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
8 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License version
12 * 2 as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 *
24 *
25 * This implements an ethernet device for the i2400m.
26 *
27 * We fake being an ethernet device to simplify the support from user
28 * space and from the other side. The world is (sadly) configured to
29 * take in only Ethernet devices...
30 *
31 * Because of this, currently there is an copy-each-rxed-packet
32 * overhead on the RX path. Each IP packet has to be reallocated to
33 * add an ethernet header (as there is no space in what we get from
34 * the device). This is a known drawback and coming versions of the
35 * device's firmware are being changed to add header space that can be
36 * used to insert the ethernet header without having to reallocate and
37 * copy.
38 *
39 * TX error handling is tricky; because we have to FIFO/queue the
40 * buffers for transmission (as the hardware likes it aggregated), we
41 * just give the skb to the TX subsystem and by the time it is
42 * transmitted, we have long forgotten about it. So we just don't care
43 * too much about it.
44 *
45 * Note that when the device is in idle mode with the basestation, we
46 * need to negotiate coming back up online. That involves negotiation
47 * and possible user space interaction. Thus, we defer to a workqueue
48 * to do all that. By default, we only queue a single packet and drop
49 * the rest, as potentially the time to go back from idle to normal is
50 * long.
51 *
52 * ROADMAP
53 *
54 * i2400m_open Called on ifconfig up
55 * i2400m_stop Called on ifconfig down
56 *
57 * i2400m_hard_start_xmit Called by the network stack to send a packet
58 * i2400m_net_wake_tx Wake up device from basestation-IDLE & TX
59 * i2400m_wake_tx_work
60 * i2400m_cmd_exit_idle
61 * i2400m_tx
62 * i2400m_net_tx TX a data frame
63 * i2400m_tx
64 *
65 * i2400m_change_mtu Called on ifconfig mtu XXX
66 *
67 * i2400m_tx_timeout Called when the device times out
68 *
69 * i2400m_net_rx Called by the RX code when a data frame is
70 * available.
71 * i2400m_netdev_setup Called to setup all the netdev stuff from
72 * alloc_netdev.
73 */
74#include <linux/if_arp.h>
75#include <linux/netdevice.h>
76#include "i2400m.h"
77
78
79#define D_SUBMODULE netdev
80#include "debug-levels.h"
81
82enum {
83/* netdev interface */
84 /*
85 * Out of NWG spec (R1_v1.2.2), 3.3.3 ASN Bearer Plane MTU Size
86 *
87 * The MTU is 1400 or less
88 */
89 I2400M_MAX_MTU = 1400,
90 I2400M_TX_TIMEOUT = HZ,
91 I2400M_TX_QLEN = 5,
92};
93
94
95static
96int i2400m_open(struct net_device *net_dev)
97{
98 int result;
99 struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
100 struct device *dev = i2400m_dev(i2400m);
101
102 d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m);
103 if (i2400m->ready == 0) {
104 dev_err(dev, "Device is still initializing\n");
105 result = -EBUSY;
106 } else
107 result = 0;
108 d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
109 net_dev, i2400m, result);
110 return result;
111}
112
113
114/*
115 *
116 * On kernel versions where cancel_work_sync() didn't return anything,
117 * we rely on wake_tx_skb() being non-NULL.
118 */
119static
120int i2400m_stop(struct net_device *net_dev)
121{
122 struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
123 struct device *dev = i2400m_dev(i2400m);
124
125 d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m);
126 /* See i2400m_hard_start_xmit(), references are taken there
127 * and here we release them if the work was still
128 * pending. Note we can't differentiate work not pending vs
129 * never scheduled, so the NULL check does that. */
130 if (cancel_work_sync(&i2400m->wake_tx_ws) == 0
131 && i2400m->wake_tx_skb != NULL) {
132 unsigned long flags;
133 struct sk_buff *wake_tx_skb;
134 spin_lock_irqsave(&i2400m->tx_lock, flags);
135 wake_tx_skb = i2400m->wake_tx_skb; /* compat help */
136 i2400m->wake_tx_skb = NULL; /* compat help */
137 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
138 i2400m_put(i2400m);
139 kfree_skb(wake_tx_skb);
140 }
141 d_fnend(3, dev, "(net_dev %p [i2400m %p]) = 0\n", net_dev, i2400m);
142 return 0;
143}
144
145
146/*
147 * Wake up the device and transmit a held SKB, then restart the net queue
148 *
149 * When the device goes into basestation-idle mode, we need to tell it
150 * to exit that mode; it will negotiate with the base station, user
151 * space may have to intervene to rehandshake crypto and then tell us
152 * when it is ready to transmit the packet we have "queued". Still we
153 * need to give it sometime after it reports being ok.
154 *
155 * On error, there is not much we can do. If the error was on TX, we
156 * still wake the queue up to see if the next packet will be luckier.
157 *
158 * If _cmd_exit_idle() fails...well, it could be many things; most
159 * commonly it is that something else took the device out of IDLE mode
160 * (for example, the base station). In that case we get an -EILSEQ and
161 * we are just going to ignore that one. If the device is back to
162 * connected, then fine -- if it is someother state, the packet will
163 * be dropped anyway.
164 */
165void i2400m_wake_tx_work(struct work_struct *ws)
166{
167 int result;
168 struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws);
169 struct device *dev = i2400m_dev(i2400m);
170 struct sk_buff *skb = i2400m->wake_tx_skb;
171 unsigned long flags;
172
173 spin_lock_irqsave(&i2400m->tx_lock, flags);
174 skb = i2400m->wake_tx_skb;
175 i2400m->wake_tx_skb = NULL;
176 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
177
178 d_fnstart(3, dev, "(ws %p i2400m %p skb %p)\n", ws, i2400m, skb);
179 result = -EINVAL;
180 if (skb == NULL) {
181 dev_err(dev, "WAKE&TX: skb dissapeared!\n");
182 goto out_put;
183 }
184 result = i2400m_cmd_exit_idle(i2400m);
185 if (result == -EILSEQ)
186 result = 0;
187 if (result < 0) {
188 dev_err(dev, "WAKE&TX: device didn't get out of idle: "
189 "%d\n", result);
190 goto error;
191 }
192 result = wait_event_timeout(i2400m->state_wq,
193 i2400m->state != I2400M_SS_IDLE, 5 * HZ);
194 if (result == 0)
195 result = -ETIMEDOUT;
196 if (result < 0) {
197 dev_err(dev, "WAKE&TX: error waiting for device to exit IDLE: "
198 "%d\n", result);
199 goto error;
200 }
201 msleep(20); /* device still needs some time or it drops it */
202 result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA);
203 netif_wake_queue(i2400m->wimax_dev.net_dev);
204error:
205 kfree_skb(skb); /* refcount transferred by _hard_start_xmit() */
206out_put:
207 i2400m_put(i2400m);
208 d_fnend(3, dev, "(ws %p i2400m %p skb %p) = void [%d]\n",
209 ws, i2400m, skb, result);
210}
211
212
213/*
214 * Prepare the data payload TX header
215 *
216 * The i2400m expects a 4 byte header in front of a data packet.
217 *
218 * Because we pretend to be an ethernet device, this packet comes with
219 * an ethernet header. Pull it and push our header.
220 */
221static
222void i2400m_tx_prep_header(struct sk_buff *skb)
223{
224 struct i2400m_pl_data_hdr *pl_hdr;
225 skb_pull(skb, ETH_HLEN);
226 pl_hdr = (struct i2400m_pl_data_hdr *) skb_push(skb, sizeof(*pl_hdr));
227 pl_hdr->reserved = 0;
228}
229
230
231/*
232 * TX an skb to an idle device
233 *
234 * When the device is in basestation-idle mode, we need to wake it up
235 * and then TX. So we queue a work_struct for doing so.
236 *
237 * We need to get an extra ref for the skb (so it is not dropped), as
238 * well as be careful not to queue more than one request (won't help
239 * at all). If more than one request comes or there are errors, we
240 * just drop the packets (see i2400m_hard_start_xmit()).
241 */
242static
243int i2400m_net_wake_tx(struct i2400m *i2400m, struct net_device *net_dev,
244 struct sk_buff *skb)
245{
246 int result;
247 struct device *dev = i2400m_dev(i2400m);
248 unsigned long flags;
249
250 d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev);
251 if (net_ratelimit()) {
252 d_printf(3, dev, "WAKE&NETTX: "
253 "skb %p sending %d bytes to radio\n",
254 skb, skb->len);
255 d_dump(4, dev, skb->data, skb->len);
256 }
257 /* We hold a ref count for i2400m and skb, so when
258 * stopping() the device, we need to cancel that work
259 * and if pending, release those resources. */
260 result = 0;
261 spin_lock_irqsave(&i2400m->tx_lock, flags);
262 if (!work_pending(&i2400m->wake_tx_ws)) {
263 netif_stop_queue(net_dev);
264 i2400m_get(i2400m);
265 i2400m->wake_tx_skb = skb_get(skb); /* transfer ref count */
266 i2400m_tx_prep_header(skb);
267 result = schedule_work(&i2400m->wake_tx_ws);
268 WARN_ON(result == 0);
269 }
270 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
271 if (result == 0) {
272 /* Yes, this happens even if we stopped the
273 * queue -- blame the queue disciplines that
274 * queue without looking -- I guess there is a reason
275 * for that. */
276 if (net_ratelimit())
277 d_printf(1, dev, "NETTX: device exiting idle, "
278 "dropping skb %p, queue running %d\n",
279 skb, netif_queue_stopped(net_dev));
280 result = -EBUSY;
281 }
282 d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result);
283 return result;
284}
285
286
287/*
288 * Transmit a packet to the base station on behalf of the network stack.
289 *
290 * Returns: 0 if ok, < 0 errno code on error.
291 *
292 * We need to pull the ethernet header and add the hardware header,
293 * which is currently set to all zeroes and reserved.
294 */
295static
296int i2400m_net_tx(struct i2400m *i2400m, struct net_device *net_dev,
297 struct sk_buff *skb)
298{
299 int result;
300 struct device *dev = i2400m_dev(i2400m);
301
302 d_fnstart(3, dev, "(i2400m %p net_dev %p skb %p)\n",
303 i2400m, net_dev, skb);
304 /* FIXME: check eth hdr, only IPv4 is routed by the device as of now */
305 net_dev->trans_start = jiffies;
306 i2400m_tx_prep_header(skb);
307 d_printf(3, dev, "NETTX: skb %p sending %d bytes to radio\n",
308 skb, skb->len);
309 d_dump(4, dev, skb->data, skb->len);
310 result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA);
311 d_fnend(3, dev, "(i2400m %p net_dev %p skb %p) = %d\n",
312 i2400m, net_dev, skb, result);
313 return result;
314}
315
316
317/*
318 * Transmit a packet to the base station on behalf of the network stack
319 *
320 *
321 * Returns: NETDEV_TX_OK (always, even in case of error)
322 *
323 * In case of error, we just drop it. Reasons:
324 *
325 * - we add a hw header to each skb, and if the network stack
326 * retries, we have no way to know if that skb has it or not.
327 *
328 * - network protocols have their own drop-recovery mechanisms
329 *
330 * - there is not much else we can do
331 *
332 * If the device is idle, we need to wake it up; that is an operation
333 * that will sleep. See i2400m_net_wake_tx() for details.
334 */
335static
336int i2400m_hard_start_xmit(struct sk_buff *skb,
337 struct net_device *net_dev)
338{
339 int result;
340 struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
341 struct device *dev = i2400m_dev(i2400m);
342
343 d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev);
344 if (i2400m->state == I2400M_SS_IDLE)
345 result = i2400m_net_wake_tx(i2400m, net_dev, skb);
346 else
347 result = i2400m_net_tx(i2400m, net_dev, skb);
348 if (result < 0)
349 net_dev->stats.tx_dropped++;
350 else {
351 net_dev->stats.tx_packets++;
352 net_dev->stats.tx_bytes += skb->len;
353 }
354 kfree_skb(skb);
355 result = NETDEV_TX_OK;
356 d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result);
357 return result;
358}
359
360
361static
362int i2400m_change_mtu(struct net_device *net_dev, int new_mtu)
363{
364 int result;
365 struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
366 struct device *dev = i2400m_dev(i2400m);
367
368 if (new_mtu >= I2400M_MAX_MTU) {
369 dev_err(dev, "Cannot change MTU to %d (max is %d)\n",
370 new_mtu, I2400M_MAX_MTU);
371 result = -EINVAL;
372 } else {
373 net_dev->mtu = new_mtu;
374 result = 0;
375 }
376 return result;
377}
378
379
380static
381void i2400m_tx_timeout(struct net_device *net_dev)
382{
383 /*
384 * We might want to kick the device
385 *
386 * There is not much we can do though, as the device requires
387 * that we send the data aggregated. By the time we receive
388 * this, there might be data pending to be sent or not...
389 */
390 net_dev->stats.tx_errors++;
391 return;
392}
393
394
395/*
396 * Create a fake ethernet header
397 *
398 * For emulating an ethernet device, every received IP header has to
399 * be prefixed with an ethernet header.
400 *
401 * What we receive has (potentially) many IP packets concatenated with
402 * no ETH_HLEN bytes prefixed. Thus there is no space for an eth
403 * header.
404 *
405 * We would have to reallocate or do ugly fragment tricks in order to
406 * add it.
407 *
408 * But what we do is use the header space of the RX transaction
409 * (*msg_hdr) as we don't need it anymore; then we'll point all the
410 * data skbs there, as they share the same backing store.
411 *
412 * We only support IPv4 for v3 firmware.
413 */
414static
415void i2400m_rx_fake_eth_header(struct net_device *net_dev,
416 void *_eth_hdr)
417{
418 struct ethhdr *eth_hdr = _eth_hdr;
419
420 memcpy(eth_hdr->h_dest, net_dev->dev_addr, sizeof(eth_hdr->h_dest));
421 memset(eth_hdr->h_source, 0, sizeof(eth_hdr->h_dest));
422 eth_hdr->h_proto = __constant_cpu_to_be16(ETH_P_IP);
423}
424
425
426/*
427 * i2400m_net_rx - pass a network packet to the stack
428 *
429 * @i2400m: device instance
430 * @skb_rx: the skb where the buffer pointed to by @buf is
431 * @i: 1 if payload is the only one
432 * @buf: pointer to the buffer containing the data
433 * @len: buffer's length
434 *
435 * We just clone the skb and set it up so that it's skb->data pointer
436 * points to "buf" and it's length.
437 *
438 * Note that if the payload is the last (or the only one) in a
439 * multi-payload message, we don't clone the SKB but just reuse it.
440 *
441 * This function is normally run from a thread context. However, we
442 * still use netif_rx() instead of netif_receive_skb() as was
443 * recommended in the mailing list. Reason is in some stress tests
444 * when sending/receiving a lot of data we seem to hit a softlock in
445 * the kernel's TCP implementation [aroudn tcp_delay_timer()]. Using
446 * netif_rx() took care of the issue.
447 *
448 * This is, of course, still open to do more research on why running
449 * with netif_receive_skb() hits this softlock. FIXME.
450 *
451 * FIXME: currently we don't do any efforts at distinguishing if what
452 * we got was an IPv4 or IPv6 header, to setup the protocol field
453 * correctly.
454 */
455void i2400m_net_rx(struct i2400m *i2400m, struct sk_buff *skb_rx,
456 unsigned i, const void *buf, int buf_len)
457{
458 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
459 struct device *dev = i2400m_dev(i2400m);
460 struct sk_buff *skb;
461
462 d_fnstart(2, dev, "(i2400m %p buf %p buf_len %d)\n",
463 i2400m, buf, buf_len);
464 if (i) {
465 skb = skb_get(skb_rx);
466 d_printf(2, dev, "RX: reusing first payload skb %p\n", skb);
467 skb_pull(skb, buf - (void *) skb->data);
468 skb_trim(skb, (void *) skb_end_pointer(skb) - buf);
469 } else {
470 /* Yes, this is bad -- a lot of overhead -- see
471 * comments at the top of the file */
472 skb = __netdev_alloc_skb(net_dev, buf_len, GFP_KERNEL);
473 if (skb == NULL) {
474 dev_err(dev, "NETRX: no memory to realloc skb\n");
475 net_dev->stats.rx_dropped++;
476 goto error_skb_realloc;
477 }
478 memcpy(skb_put(skb, buf_len), buf, buf_len);
479 }
480 i2400m_rx_fake_eth_header(i2400m->wimax_dev.net_dev,
481 skb->data - ETH_HLEN);
482 skb_set_mac_header(skb, -ETH_HLEN);
483 skb->dev = i2400m->wimax_dev.net_dev;
484 skb->protocol = htons(ETH_P_IP);
485 net_dev->stats.rx_packets++;
486 net_dev->stats.rx_bytes += buf_len;
487 d_printf(3, dev, "NETRX: receiving %d bytes to network stack\n",
488 buf_len);
489 d_dump(4, dev, buf, buf_len);
490 netif_rx_ni(skb); /* see notes in function header */
491error_skb_realloc:
492 d_fnend(2, dev, "(i2400m %p buf %p buf_len %d) = void\n",
493 i2400m, buf, buf_len);
494}
495
496
497/**
498 * i2400m_netdev_setup - Setup setup @net_dev's i2400m private data
499 *
500 * Called by alloc_netdev()
501 */
502void i2400m_netdev_setup(struct net_device *net_dev)
503{
504 d_fnstart(3, NULL, "(net_dev %p)\n", net_dev);
505 ether_setup(net_dev);
506 net_dev->mtu = I2400M_MAX_MTU;
507 net_dev->tx_queue_len = I2400M_TX_QLEN;
508 net_dev->features =
509 NETIF_F_VLAN_CHALLENGED
510 | NETIF_F_HIGHDMA;
511 net_dev->flags =
512 IFF_NOARP /* i2400m is apure IP device */
513 & (~IFF_BROADCAST /* i2400m is P2P */
514 & ~IFF_MULTICAST);
515 net_dev->watchdog_timeo = I2400M_TX_TIMEOUT;
516 net_dev->open = i2400m_open;
517 net_dev->stop = i2400m_stop;
518 net_dev->hard_start_xmit = i2400m_hard_start_xmit;
519 net_dev->change_mtu = i2400m_change_mtu;
520 net_dev->tx_timeout = i2400m_tx_timeout;
521 d_fnend(3, NULL, "(net_dev %p) = void\n", net_dev);
522}
523EXPORT_SYMBOL_GPL(i2400m_netdev_setup);
524
diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c
new file mode 100644
index 000000000000..487ec58cea46
--- /dev/null
+++ b/drivers/net/wimax/i2400m/op-rfkill.c
@@ -0,0 +1,207 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Implement backend for the WiMAX stack rfkill support
4 *
5 *
6 * Copyright (C) 2007-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 * The WiMAX kernel stack integrates into RF-Kill and keeps the
25 * switches's status. We just need to:
26 *
27 * - report changes in the HW RF Kill switch [with
28 * wimax_rfkill_{sw,hw}_report(), which happens when we detect those
29 * indications coming through hardware reports]. We also do it on
30 * initialization to let the stack know the intial HW state.
31 *
32 * - implement indications from the stack to change the SW RF Kill
33 * switch (coming from sysfs, the wimax stack or user space).
34 */
35#include "i2400m.h"
36#include <linux/wimax/i2400m.h>
37
38
39
40#define D_SUBMODULE rfkill
41#include "debug-levels.h"
42
43/*
44 * Return true if the i2400m radio is in the requested wimax_rf_state state
45 *
46 */
47static
48int i2400m_radio_is(struct i2400m *i2400m, enum wimax_rf_state state)
49{
50 if (state == WIMAX_RF_OFF)
51 return i2400m->state == I2400M_SS_RF_OFF
52 || i2400m->state == I2400M_SS_RF_SHUTDOWN;
53 else if (state == WIMAX_RF_ON)
54 /* state == WIMAX_RF_ON */
55 return i2400m->state != I2400M_SS_RF_OFF
56 && i2400m->state != I2400M_SS_RF_SHUTDOWN;
57 else
58 BUG();
59}
60
61
62/*
63 * WiMAX stack operation: implement SW RFKill toggling
64 *
65 * @wimax_dev: device descriptor
66 * @skb: skb where the message has been received; skb->data is
67 * expected to point to the message payload.
68 * @genl_info: passed by the generic netlink layer
69 *
70 * Generic Netlink will call this function when a message is sent from
71 * userspace to change the software RF-Kill switch status.
72 *
73 * This function will set the device's sofware RF-Kill switch state to
74 * match what is requested.
75 *
76 * NOTE: the i2400m has a strict state machine; we can only set the
77 * RF-Kill switch when it is on, the HW RF-Kill is on and the
78 * device is initialized. So we ignore errors steaming from not
79 * being in the right state (-EILSEQ).
80 */
81int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev,
82 enum wimax_rf_state state)
83{
84 int result;
85 struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev);
86 struct device *dev = i2400m_dev(i2400m);
87 struct sk_buff *ack_skb;
88 struct {
89 struct i2400m_l3l4_hdr hdr;
90 struct i2400m_tlv_rf_operation sw_rf;
91 } __attribute__((packed)) *cmd;
92 char strerr[32];
93
94 d_fnstart(4, dev, "(wimax_dev %p state %d)\n", wimax_dev, state);
95
96 result = -ENOMEM;
97 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
98 if (cmd == NULL)
99 goto error_alloc;
100 cmd->hdr.type = cpu_to_le16(I2400M_MT_CMD_RF_CONTROL);
101 cmd->hdr.length = sizeof(cmd->sw_rf);
102 cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION);
103 cmd->sw_rf.hdr.type = cpu_to_le16(I2400M_TLV_RF_OPERATION);
104 cmd->sw_rf.hdr.length = cpu_to_le16(sizeof(cmd->sw_rf.status));
105 switch (state) {
106 case WIMAX_RF_OFF: /* RFKILL ON, radio OFF */
107 cmd->sw_rf.status = cpu_to_le32(2);
108 break;
109 case WIMAX_RF_ON: /* RFKILL OFF, radio ON */
110 cmd->sw_rf.status = cpu_to_le32(1);
111 break;
112 default:
113 BUG();
114 }
115
116 ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
117 result = PTR_ERR(ack_skb);
118 if (IS_ERR(ack_skb)) {
119 dev_err(dev, "Failed to issue 'RF Control' command: %d\n",
120 result);
121 goto error_msg_to_dev;
122 }
123 result = i2400m_msg_check_status(wimax_msg_data(ack_skb),
124 strerr, sizeof(strerr));
125 if (result < 0) {
126 dev_err(dev, "'RF Control' (0x%04x) command failed: %d - %s\n",
127 I2400M_MT_CMD_RF_CONTROL, result, strerr);
128 goto error_cmd;
129 }
130
131 /* Now we wait for the state to change to RADIO_OFF or RADIO_ON */
132 result = wait_event_timeout(
133 i2400m->state_wq, i2400m_radio_is(i2400m, state),
134 5 * HZ);
135 if (result == 0)
136 result = -ETIMEDOUT;
137 if (result < 0)
138 dev_err(dev, "Error waiting for device to toggle RF state: "
139 "%d\n", result);
140 result = 0;
141error_cmd:
142 kfree_skb(ack_skb);
143error_msg_to_dev:
144error_alloc:
145 d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n",
146 wimax_dev, state, result);
147 return result;
148}
149
150
151/*
152 * Inform the WiMAX stack of changes in the RF Kill switches reported
153 * by the device
154 *
155 * @i2400m: device descriptor
156 * @rfss: TLV for RF Switches status; already validated
157 *
158 * NOTE: the reports on RF switch status cannot be trusted
159 * or used until the device is in a state of RADIO_OFF
160 * or greater.
161 */
162void i2400m_report_tlv_rf_switches_status(
163 struct i2400m *i2400m,
164 const struct i2400m_tlv_rf_switches_status *rfss)
165{
166 struct device *dev = i2400m_dev(i2400m);
167 enum i2400m_rf_switch_status hw, sw;
168 enum wimax_st wimax_state;
169
170 sw = le32_to_cpu(rfss->sw_rf_switch);
171 hw = le32_to_cpu(rfss->hw_rf_switch);
172
173 d_fnstart(3, dev, "(i2400m %p rfss %p [hw %u sw %u])\n",
174 i2400m, rfss, hw, sw);
175 /* We only process rw switch evens when the device has been
176 * fully initialized */
177 wimax_state = wimax_state_get(&i2400m->wimax_dev);
178 if (wimax_state < WIMAX_ST_RADIO_OFF) {
179 d_printf(3, dev, "ignoring RF switches report, state %u\n",
180 wimax_state);
181 goto out;
182 }
183 switch (sw) {
184 case I2400M_RF_SWITCH_ON: /* RF Kill disabled (radio on) */
185 wimax_report_rfkill_sw(&i2400m->wimax_dev, WIMAX_RF_ON);
186 break;
187 case I2400M_RF_SWITCH_OFF: /* RF Kill enabled (radio off) */
188 wimax_report_rfkill_sw(&i2400m->wimax_dev, WIMAX_RF_OFF);
189 break;
190 default:
191 dev_err(dev, "HW BUG? Unknown RF SW state 0x%x\n", sw);
192 }
193
194 switch (hw) {
195 case I2400M_RF_SWITCH_ON: /* RF Kill disabled (radio on) */
196 wimax_report_rfkill_hw(&i2400m->wimax_dev, WIMAX_RF_ON);
197 break;
198 case I2400M_RF_SWITCH_OFF: /* RF Kill enabled (radio off) */
199 wimax_report_rfkill_hw(&i2400m->wimax_dev, WIMAX_RF_OFF);
200 break;
201 default:
202 dev_err(dev, "HW BUG? Unknown RF HW state 0x%x\n", hw);
203 }
204out:
205 d_fnend(3, dev, "(i2400m %p rfss %p [hw %u sw %u]) = void\n",
206 i2400m, rfss, hw, sw);
207}
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c
new file mode 100644
index 000000000000..6922022710ac
--- /dev/null
+++ b/drivers/net/wimax/i2400m/rx.c
@@ -0,0 +1,534 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Handle incoming traffic and deliver it to the control or data planes
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37 * - Initial implementation
38 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
39 * - Use skb_clone(), break up processing in chunks
40 * - Split transport/device specific
41 * - Make buffer size dynamic to exert less memory pressure
42 *
43 *
44 * This handles the RX path.
45 *
46 * We receive an RX message from the bus-specific driver, which
47 * contains one or more payloads that have potentially different
48 * destinataries (data or control paths).
49 *
50 * So we just take that payload from the transport specific code in
51 * the form of an skb, break it up in chunks (a cloned skb each in the
52 * case of network packets) and pass it to netdev or to the
53 * command/ack handler (and from there to the WiMAX stack).
54 *
55 * PROTOCOL FORMAT
56 *
57 * The format of the buffer is:
58 *
59 * HEADER (struct i2400m_msg_hdr)
60 * PAYLOAD DESCRIPTOR 0 (struct i2400m_pld)
61 * PAYLOAD DESCRIPTOR 1
62 * ...
63 * PAYLOAD DESCRIPTOR N
64 * PAYLOAD 0 (raw bytes)
65 * PAYLOAD 1
66 * ...
67 * PAYLOAD N
68 *
69 * See tx.c for a deeper description on alignment requirements and
70 * other fun facts of it.
71 *
72 * ROADMAP
73 *
74 * i2400m_rx
75 * i2400m_rx_msg_hdr_check
76 * i2400m_rx_pl_descr_check
77 * i2400m_rx_payload
78 * i2400m_net_rx
79 * i2400m_rx_ctl
80 * i2400m_msg_size_check
81 * i2400m_report_hook_work [in a workqueue]
82 * i2400m_report_hook
83 * wimax_msg_to_user
84 * i2400m_rx_ctl_ack
85 * wimax_msg_to_user_alloc
86 * i2400m_rx_trace
87 * i2400m_msg_size_check
88 * wimax_msg
89 */
90#include <linux/kernel.h>
91#include <linux/if_arp.h>
92#include <linux/netdevice.h>
93#include <linux/workqueue.h>
94#include "i2400m.h"
95
96
97#define D_SUBMODULE rx
98#include "debug-levels.h"
99
100struct i2400m_report_hook_args {
101 struct sk_buff *skb_rx;
102 const struct i2400m_l3l4_hdr *l3l4_hdr;
103 size_t size;
104};
105
106
107/*
108 * Execute i2400m_report_hook in a workqueue
109 *
110 * Unpacks arguments from the deferred call, executes it and then
111 * drops the references.
112 *
113 * Obvious NOTE: References are needed because we are a separate
114 * thread; otherwise the buffer changes under us because it is
115 * released by the original caller.
116 */
117static
118void i2400m_report_hook_work(struct work_struct *ws)
119{
120 struct i2400m_work *iw =
121 container_of(ws, struct i2400m_work, ws);
122 struct i2400m_report_hook_args *args = (void *) iw->pl;
123 i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size);
124 kfree_skb(args->skb_rx);
125 i2400m_put(iw->i2400m);
126 kfree(iw);
127}
128
129
130/*
131 * Process an ack to a command
132 *
133 * @i2400m: device descriptor
134 * @payload: pointer to message
135 * @size: size of the message
136 *
137 * Pass the acknodledgment (in an skb) to the thread that is waiting
138 * for it in i2400m->msg_completion.
139 *
140 * We need to coordinate properly with the thread waiting for the
141 * ack. Check if it is waiting or if it is gone. We loose the spinlock
142 * to avoid allocating on atomic contexts (yeah, could use GFP_ATOMIC,
143 * but this is not so speed critical).
144 */
145static
146void i2400m_rx_ctl_ack(struct i2400m *i2400m,
147 const void *payload, size_t size)
148{
149 struct device *dev = i2400m_dev(i2400m);
150 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
151 unsigned long flags;
152 struct sk_buff *ack_skb;
153
154 /* Anyone waiting for an answer? */
155 spin_lock_irqsave(&i2400m->rx_lock, flags);
156 if (i2400m->ack_skb != ERR_PTR(-EINPROGRESS)) {
157 dev_err(dev, "Huh? reply to command with no waiters\n");
158 goto error_no_waiter;
159 }
160 spin_unlock_irqrestore(&i2400m->rx_lock, flags);
161
162 ack_skb = wimax_msg_alloc(wimax_dev, NULL, payload, size, GFP_KERNEL);
163
164 /* Check waiter didn't time out waiting for the answer... */
165 spin_lock_irqsave(&i2400m->rx_lock, flags);
166 if (i2400m->ack_skb != ERR_PTR(-EINPROGRESS)) {
167 d_printf(1, dev, "Huh? waiter for command reply cancelled\n");
168 goto error_waiter_cancelled;
169 }
170 if (ack_skb == NULL) {
171 dev_err(dev, "CMD/GET/SET ack: cannot allocate SKB\n");
172 i2400m->ack_skb = ERR_PTR(-ENOMEM);
173 } else
174 i2400m->ack_skb = ack_skb;
175 spin_unlock_irqrestore(&i2400m->rx_lock, flags);
176 complete(&i2400m->msg_completion);
177 return;
178
179error_waiter_cancelled:
180 if (ack_skb)
181 kfree_skb(ack_skb);
182error_no_waiter:
183 spin_unlock_irqrestore(&i2400m->rx_lock, flags);
184 return;
185}
186
187
188/*
189 * Receive and process a control payload
190 *
191 * @i2400m: device descriptor
192 * @skb_rx: skb that contains the payload (for reference counting)
193 * @payload: pointer to message
194 * @size: size of the message
195 *
196 * There are two types of control RX messages: reports (asynchronous,
197 * like your every day interrupts) and 'acks' (reponses to a command,
198 * get or set request).
199 *
200 * If it is a report, we run hooks on it (to extract information for
201 * things we need to do in the driver) and then pass it over to the
202 * WiMAX stack to send it to user space.
203 *
204 * NOTE: report processing is done in a workqueue specific to the
205 * generic driver, to avoid deadlocks in the system.
206 *
207 * If it is not a report, it is an ack to a previously executed
208 * command, set or get, so wake up whoever is waiting for it from
209 * i2400m_msg_to_dev(). i2400m_rx_ctl_ack() takes care of that.
210 *
211 * Note that the sizes we pass to other functions from here are the
212 * sizes of the _l3l4_hdr + payload, not full buffer sizes, as we have
213 * verified in _msg_size_check() that they are congruent.
214 *
215 * For reports: We can't clone the original skb where the data is
216 * because we need to send this up via netlink; netlink has to add
217 * headers and we can't overwrite what's preceeding the payload...as
218 * it is another message. So we just dup them.
219 */
220static
221void i2400m_rx_ctl(struct i2400m *i2400m, struct sk_buff *skb_rx,
222 const void *payload, size_t size)
223{
224 int result;
225 struct device *dev = i2400m_dev(i2400m);
226 const struct i2400m_l3l4_hdr *l3l4_hdr = payload;
227 unsigned msg_type;
228
229 result = i2400m_msg_size_check(i2400m, l3l4_hdr, size);
230 if (result < 0) {
231 dev_err(dev, "HW BUG? device sent a bad message: %d\n",
232 result);
233 goto error_check;
234 }
235 msg_type = le16_to_cpu(l3l4_hdr->type);
236 d_printf(1, dev, "%s 0x%04x: %zu bytes\n",
237 msg_type & I2400M_MT_REPORT_MASK ? "REPORT" : "CMD/SET/GET",
238 msg_type, size);
239 d_dump(2, dev, l3l4_hdr, size);
240 if (msg_type & I2400M_MT_REPORT_MASK) {
241 /* These hooks have to be ran serialized; as well, the
242 * handling might force the execution of commands, and
243 * that might cause reentrancy issues with
244 * bus-specific subdrivers and workqueues. So we run
245 * it in a separate workqueue. */
246 struct i2400m_report_hook_args args = {
247 .skb_rx = skb_rx,
248 .l3l4_hdr = l3l4_hdr,
249 .size = size
250 };
251 if (unlikely(i2400m->ready == 0)) /* only send if up */
252 return;
253 skb_get(skb_rx);
254 i2400m_queue_work(i2400m, i2400m_report_hook_work,
255 GFP_KERNEL, &args, sizeof(args));
256 result = wimax_msg(&i2400m->wimax_dev, NULL, l3l4_hdr, size,
257 GFP_KERNEL);
258 if (result < 0)
259 dev_err(dev, "error sending report to userspace: %d\n",
260 result);
261 } else /* an ack to a CMD, GET or SET */
262 i2400m_rx_ctl_ack(i2400m, payload, size);
263error_check:
264 return;
265}
266
267
268
269
270/*
271 * Receive and send up a trace
272 *
273 * @i2400m: device descriptor
274 * @skb_rx: skb that contains the trace (for reference counting)
275 * @payload: pointer to trace message inside the skb
276 * @size: size of the message
277 *
278 * THe i2400m might produce trace information (diagnostics) and we
279 * send them through a different kernel-to-user pipe (to avoid
280 * clogging it).
281 *
282 * As in i2400m_rx_ctl(), we can't clone the original skb where the
283 * data is because we need to send this up via netlink; netlink has to
284 * add headers and we can't overwrite what's preceeding the
285 * payload...as it is another message. So we just dup them.
286 */
287static
288void i2400m_rx_trace(struct i2400m *i2400m,
289 const void *payload, size_t size)
290{
291 int result;
292 struct device *dev = i2400m_dev(i2400m);
293 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
294 const struct i2400m_l3l4_hdr *l3l4_hdr = payload;
295 unsigned msg_type;
296
297 result = i2400m_msg_size_check(i2400m, l3l4_hdr, size);
298 if (result < 0) {
299 dev_err(dev, "HW BUG? device sent a bad trace message: %d\n",
300 result);
301 goto error_check;
302 }
303 msg_type = le16_to_cpu(l3l4_hdr->type);
304 d_printf(1, dev, "Trace %s 0x%04x: %zu bytes\n",
305 msg_type & I2400M_MT_REPORT_MASK ? "REPORT" : "CMD/SET/GET",
306 msg_type, size);
307 d_dump(2, dev, l3l4_hdr, size);
308 if (unlikely(i2400m->ready == 0)) /* only send if up */
309 return;
310 result = wimax_msg(wimax_dev, "trace", l3l4_hdr, size, GFP_KERNEL);
311 if (result < 0)
312 dev_err(dev, "error sending trace to userspace: %d\n",
313 result);
314error_check:
315 return;
316}
317
318
319/*
320 * Act on a received payload
321 *
322 * @i2400m: device instance
323 * @skb_rx: skb where the transaction was received
324 * @single: 1 if there is only one payload, 0 otherwise
325 * @pld: payload descriptor
326 * @payload: payload data
327 *
328 * Upon reception of a payload, look at its guts in the payload
329 * descriptor and decide what to do with it.
330 */
331static
332void i2400m_rx_payload(struct i2400m *i2400m, struct sk_buff *skb_rx,
333 unsigned single, const struct i2400m_pld *pld,
334 const void *payload)
335{
336 struct device *dev = i2400m_dev(i2400m);
337 size_t pl_size = i2400m_pld_size(pld);
338 enum i2400m_pt pl_type = i2400m_pld_type(pld);
339
340 switch (pl_type) {
341 case I2400M_PT_DATA:
342 d_printf(3, dev, "RX: data payload %zu bytes\n", pl_size);
343 i2400m_net_rx(i2400m, skb_rx, single, payload, pl_size);
344 break;
345 case I2400M_PT_CTRL:
346 i2400m_rx_ctl(i2400m, skb_rx, payload, pl_size);
347 break;
348 case I2400M_PT_TRACE:
349 i2400m_rx_trace(i2400m, payload, pl_size);
350 break;
351 default: /* Anything else shouldn't come to the host */
352 if (printk_ratelimit())
353 dev_err(dev, "RX: HW BUG? unexpected payload type %u\n",
354 pl_type);
355 }
356}
357
358
359/*
360 * Check a received transaction's message header
361 *
362 * @i2400m: device descriptor
363 * @msg_hdr: message header
364 * @buf_size: size of the received buffer
365 *
366 * Check that the declarations done by a RX buffer message header are
367 * sane and consistent with the amount of data that was received.
368 */
369static
370int i2400m_rx_msg_hdr_check(struct i2400m *i2400m,
371 const struct i2400m_msg_hdr *msg_hdr,
372 size_t buf_size)
373{
374 int result = -EIO;
375 struct device *dev = i2400m_dev(i2400m);
376 if (buf_size < sizeof(*msg_hdr)) {
377 dev_err(dev, "RX: HW BUG? message with short header (%zu "
378 "vs %zu bytes expected)\n", buf_size, sizeof(*msg_hdr));
379 goto error;
380 }
381 if (msg_hdr->barker != cpu_to_le32(I2400M_D2H_MSG_BARKER)) {
382 dev_err(dev, "RX: HW BUG? message received with unknown "
383 "barker 0x%08x (buf_size %zu bytes)\n",
384 le32_to_cpu(msg_hdr->barker), buf_size);
385 goto error;
386 }
387 if (msg_hdr->num_pls == 0) {
388 dev_err(dev, "RX: HW BUG? zero payload packets in message\n");
389 goto error;
390 }
391 if (le16_to_cpu(msg_hdr->num_pls) > I2400M_MAX_PLS_IN_MSG) {
392 dev_err(dev, "RX: HW BUG? message contains more payload "
393 "than maximum; ignoring.\n");
394 goto error;
395 }
396 result = 0;
397error:
398 return result;
399}
400
401
402/*
403 * Check a payload descriptor against the received data
404 *
405 * @i2400m: device descriptor
406 * @pld: payload descriptor
407 * @pl_itr: offset (in bytes) in the received buffer the payload is
408 * located
409 * @buf_size: size of the received buffer
410 *
411 * Given a payload descriptor (part of a RX buffer), check it is sane
412 * and that the data it declares fits in the buffer.
413 */
414static
415int i2400m_rx_pl_descr_check(struct i2400m *i2400m,
416 const struct i2400m_pld *pld,
417 size_t pl_itr, size_t buf_size)
418{
419 int result = -EIO;
420 struct device *dev = i2400m_dev(i2400m);
421 size_t pl_size = i2400m_pld_size(pld);
422 enum i2400m_pt pl_type = i2400m_pld_type(pld);
423
424 if (pl_size > i2400m->bus_pl_size_max) {
425 dev_err(dev, "RX: HW BUG? payload @%zu: size %zu is "
426 "bigger than maximum %zu; ignoring message\n",
427 pl_itr, pl_size, i2400m->bus_pl_size_max);
428 goto error;
429 }
430 if (pl_itr + pl_size > buf_size) { /* enough? */
431 dev_err(dev, "RX: HW BUG? payload @%zu: size %zu "
432 "goes beyond the received buffer "
433 "size (%zu bytes); ignoring message\n",
434 pl_itr, pl_size, buf_size);
435 goto error;
436 }
437 if (pl_type >= I2400M_PT_ILLEGAL) {
438 dev_err(dev, "RX: HW BUG? illegal payload type %u; "
439 "ignoring message\n", pl_type);
440 goto error;
441 }
442 result = 0;
443error:
444 return result;
445}
446
447
448/**
449 * i2400m_rx - Receive a buffer of data from the device
450 *
451 * @i2400m: device descriptor
452 * @skb: skbuff where the data has been received
453 *
454 * Parse in a buffer of data that contains an RX message sent from the
455 * device. See the file header for the format. Run all checks on the
456 * buffer header, then run over each payload's descriptors, verify
457 * their consistency and act on each payload's contents. If
458 * everything is succesful, update the device's statistics.
459 *
460 * Note: You need to set the skb to contain only the length of the
461 * received buffer; for that, use skb_trim(skb, RECEIVED_SIZE).
462 *
463 * Returns:
464 *
465 * 0 if ok, < 0 errno on error
466 *
467 * If ok, this function owns now the skb and the caller DOESN'T have
468 * to run kfree_skb() on it. However, on error, the caller still owns
469 * the skb and it is responsible for releasing it.
470 */
471int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
472{
473 int i, result;
474 struct device *dev = i2400m_dev(i2400m);
475 const struct i2400m_msg_hdr *msg_hdr;
476 size_t pl_itr, pl_size, skb_len;
477 unsigned long flags;
478 unsigned num_pls;
479
480 skb_len = skb->len;
481 d_fnstart(4, dev, "(i2400m %p skb %p [size %zu])\n",
482 i2400m, skb, skb_len);
483 result = -EIO;
484 msg_hdr = (void *) skb->data;
485 result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb->len);
486 if (result < 0)
487 goto error_msg_hdr_check;
488 result = -EIO;
489 num_pls = le16_to_cpu(msg_hdr->num_pls);
490 pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */
491 num_pls * sizeof(msg_hdr->pld[0]);
492 pl_itr = ALIGN(pl_itr, I2400M_PL_PAD);
493 if (pl_itr > skb->len) { /* got all the payload descriptors? */
494 dev_err(dev, "RX: HW BUG? message too short (%u bytes) for "
495 "%u payload descriptors (%zu each, total %zu)\n",
496 skb->len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr);
497 goto error_pl_descr_short;
498 }
499 /* Walk each payload payload--check we really got it */
500 for (i = 0; i < num_pls; i++) {
501 /* work around old gcc warnings */
502 pl_size = i2400m_pld_size(&msg_hdr->pld[i]);
503 result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i],
504 pl_itr, skb->len);
505 if (result < 0)
506 goto error_pl_descr_check;
507 i2400m_rx_payload(i2400m, skb, num_pls == 1, &msg_hdr->pld[i],
508 skb->data + pl_itr);
509 pl_itr += ALIGN(pl_size, I2400M_PL_PAD);
510 cond_resched(); /* Don't monopolize */
511 }
512 kfree_skb(skb);
513 /* Update device statistics */
514 spin_lock_irqsave(&i2400m->rx_lock, flags);
515 i2400m->rx_pl_num += i;
516 if (i > i2400m->rx_pl_max)
517 i2400m->rx_pl_max = i;
518 if (i < i2400m->rx_pl_min)
519 i2400m->rx_pl_min = i;
520 i2400m->rx_num++;
521 i2400m->rx_size_acc += skb->len;
522 if (skb->len < i2400m->rx_size_min)
523 i2400m->rx_size_min = skb->len;
524 if (skb->len > i2400m->rx_size_max)
525 i2400m->rx_size_max = skb->len;
526 spin_unlock_irqrestore(&i2400m->rx_lock, flags);
527error_pl_descr_check:
528error_pl_descr_short:
529error_msg_hdr_check:
530 d_fnend(4, dev, "(i2400m %p skb %p [size %zu]) = %d\n",
531 i2400m, skb, skb_len, result);
532 return result;
533}
534EXPORT_SYMBOL_GPL(i2400m_rx);
diff --git a/drivers/net/wimax/i2400m/sdio-debug-levels.h b/drivers/net/wimax/i2400m/sdio-debug-levels.h
new file mode 100644
index 000000000000..c51998741301
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio-debug-levels.h
@@ -0,0 +1,22 @@
1/*
2 * debug levels control file for the i2400m module's
3 */
4#ifndef __debug_levels__h__
5#define __debug_levels__h__
6
7/* Maximum compile and run time debug level for all submodules */
8#define D_MODULENAME i2400m_sdio
9#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL
10
11#include <linux/wimax/debug.h>
12
13/* List of all the enabled modules */
14enum d_module {
15 D_SUBMODULE_DECLARE(main),
16 D_SUBMODULE_DECLARE(tx),
17 D_SUBMODULE_DECLARE(rx),
18 D_SUBMODULE_DECLARE(fw)
19};
20
21
22#endif /* #ifndef __debug_levels__h__ */
diff --git a/drivers/net/wimax/i2400m/sdio-fw.c b/drivers/net/wimax/i2400m/sdio-fw.c
new file mode 100644
index 000000000000..3487205d8f50
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio-fw.c
@@ -0,0 +1,224 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Firmware uploader's SDIO specifics
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
38 * - Initial implementation
39 *
40 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
41 * - Bus generic/specific split for USB
42 *
43 * Dirk Brandewie <dirk.j.brandewie@intel.com>
44 * - Initial implementation for SDIO
45 *
46 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
47 * - SDIO rehash for changes in the bus-driver model
48 *
49 * THE PROCEDURE
50 *
51 * See fw.c for the generic description of this procedure.
52 *
53 * This file implements only the SDIO specifics. It boils down to how
54 * to send a command and waiting for an acknowledgement from the
55 * device. We do polled reads.
56 *
57 * COMMAND EXECUTION
58 *
59 * THe generic firmware upload code will call i2400m_bus_bm_cmd_send()
60 * to send commands.
61 *
62 * The SDIO devices expects things in 256 byte blocks, so it will pad
63 * it, compute the checksum (if needed) and pass it to SDIO.
64 *
65 * ACK RECEPTION
66 *
67 * This works in polling mode -- the fw loader says when to wait for
68 * data and for that it calls i2400ms_bus_bm_wait_for_ack().
69 *
70 * This will poll the device for data until it is received. We need to
71 * receive at least as much bytes as where asked for (although it'll
72 * always be a multiple of 256 bytes).
73 */
74#include <linux/mmc/sdio_func.h>
75#include "i2400m-sdio.h"
76
77
78#define D_SUBMODULE fw
79#include "sdio-debug-levels.h"
80
81/*
82 * Send a boot-mode command to the SDIO function
83 *
84 * We use a bounce buffer (i2400m->bm_cmd_buf) because we need to
85 * touch the header if the RAW flag is not set.
86 *
87 * @flags: pass thru from i2400m_bm_cmd()
88 * @return: cmd_size if ok, < 0 errno code on error.
89 *
90 * Note the command is padded to the SDIO block size for the device.
91 */
92ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m,
93 const struct i2400m_bootrom_header *_cmd,
94 size_t cmd_size, int flags)
95{
96 ssize_t result;
97 struct device *dev = i2400m_dev(i2400m);
98 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
99 int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd);
100 struct i2400m_bootrom_header *cmd;
101 /* SDIO restriction */
102 size_t cmd_size_a = ALIGN(cmd_size, I2400MS_BLK_SIZE);
103
104 d_fnstart(5, dev, "(i2400m %p cmd %p size %zu)\n",
105 i2400m, _cmd, cmd_size);
106 result = -E2BIG;
107 if (cmd_size > I2400M_BM_CMD_BUF_SIZE)
108 goto error_too_big;
109
110 memcpy(i2400m->bm_cmd_buf, _cmd, cmd_size); /* Prep command */
111 cmd = i2400m->bm_cmd_buf;
112 if (cmd_size_a > cmd_size) /* Zero pad space */
113 memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size);
114 if ((flags & I2400M_BM_CMD_RAW) == 0) {
115 if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0))
116 dev_warn(dev, "SW BUG: response_required == 0\n");
117 i2400m_bm_cmd_prepare(cmd);
118 }
119 d_printf(4, dev, "BM cmd %d: %zu bytes (%zu padded)\n",
120 opcode, cmd_size, cmd_size_a);
121 d_dump(5, dev, cmd, cmd_size);
122
123 sdio_claim_host(i2400ms->func); /* Send & check */
124 result = sdio_memcpy_toio(i2400ms->func, I2400MS_DATA_ADDR,
125 i2400m->bm_cmd_buf, cmd_size_a);
126 sdio_release_host(i2400ms->func);
127 if (result < 0) {
128 dev_err(dev, "BM cmd %d: cannot send: %ld\n",
129 opcode, (long) result);
130 goto error_cmd_send;
131 }
132 result = cmd_size;
133error_cmd_send:
134error_too_big:
135 d_fnend(5, dev, "(i2400m %p cmd %p size %zu) = %d\n",
136 i2400m, _cmd, cmd_size, (int) result);
137 return result;
138}
139
140
141/*
142 * Read an ack from the device's boot-mode (polling)
143 *
144 * @i2400m:
145 * @_ack: pointer to where to store the read data
146 * @ack_size: how many bytes we should read
147 *
148 * Returns: < 0 errno code on error; otherwise, amount of received bytes.
149 *
150 * The ACK for a BM command is always at least sizeof(*ack) bytes, so
151 * check for that. We don't need to check for device reboots
152 *
153 * NOTE: We do an artificial timeout of 1 sec over the SDIO timeout;
154 * this way we have control over it...there is no way that I know
155 * of setting an SDIO transaction timeout.
156 */
157ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m,
158 struct i2400m_bootrom_header *ack,
159 size_t ack_size)
160{
161 int result;
162 ssize_t rx_size;
163 u64 timeout;
164 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
165 struct sdio_func *func = i2400ms->func;
166 struct device *dev = &func->dev;
167
168 BUG_ON(sizeof(*ack) > ack_size);
169
170 d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n",
171 i2400m, ack, ack_size);
172
173 timeout = get_jiffies_64() + 2 * HZ;
174 sdio_claim_host(func);
175 while (1) {
176 if (time_after64(get_jiffies_64(), timeout)) {
177 rx_size = -ETIMEDOUT;
178 dev_err(dev, "timeout waiting for ack data\n");
179 goto error_timedout;
180 }
181
182 /* Find the RX size, check if it fits or not -- it if
183 * doesn't fit, fail, as we have no way to dispose of
184 * the extra data. */
185 rx_size = __i2400ms_rx_get_size(i2400ms);
186 if (rx_size < 0)
187 goto error_rx_get_size;
188 result = -ENOSPC; /* Check it fits */
189 if (rx_size < sizeof(*ack)) {
190 rx_size = -EIO;
191 dev_err(dev, "HW BUG? received is too small (%zu vs "
192 "%zu needed)\n", sizeof(*ack), rx_size);
193 goto error_too_small;
194 }
195 if (rx_size > I2400M_BM_ACK_BUF_SIZE) {
196 dev_err(dev, "SW BUG? BM_ACK_BUF is too small (%u vs "
197 "%zu needed)\n", I2400M_BM_ACK_BUF_SIZE,
198 rx_size);
199 goto error_too_small;
200 }
201
202 /* Read it */
203 result = sdio_memcpy_fromio(func, i2400m->bm_ack_buf,
204 I2400MS_DATA_ADDR, rx_size);
205 if (result == -ETIMEDOUT || result == -ETIME)
206 continue;
207 if (result < 0) {
208 dev_err(dev, "BM SDIO receive (%zu B) failed: %d\n",
209 rx_size, result);
210 goto error_read;
211 } else
212 break;
213 }
214 rx_size = min((ssize_t)ack_size, rx_size);
215 memcpy(ack, i2400m->bm_ack_buf, rx_size);
216error_read:
217error_too_small:
218error_rx_get_size:
219error_timedout:
220 sdio_release_host(func);
221 d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %ld\n",
222 i2400m, ack, ack_size, (long) rx_size);
223 return rx_size;
224}
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c
new file mode 100644
index 000000000000..a3008b904f7d
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio-rx.c
@@ -0,0 +1,255 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * SDIO RX handling
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Dirk Brandewie <dirk.j.brandewie@intel.com>
37 * - Initial implementation
38 *
39 *
40 * This handles the RX path on SDIO.
41 *
42 * The SDIO bus driver calls the "irq" routine when data is available.
43 * This is not a traditional interrupt routine since the SDIO bus
44 * driver calls us from its irq thread context. Because of this
45 * sleeping in the SDIO RX IRQ routine is okay.
46 *
47 * From there on, we obtain the size of the data that is available,
48 * allocate an skb, copy it and then pass it to the generic driver's
49 * RX routine [i2400m_rx()].
50 *
51 * ROADMAP
52 *
53 * i2400ms_irq()
54 * i2400ms_rx()
55 * __i2400ms_rx_get_size()
56 * i2400m_rx()
57 *
58 * i2400ms_rx_setup()
59 *
60 * i2400ms_rx_release()
61 */
62#include <linux/workqueue.h>
63#include <linux/wait.h>
64#include <linux/skbuff.h>
65#include <linux/mmc/sdio.h>
66#include <linux/mmc/sdio_func.h>
67#include "i2400m-sdio.h"
68
69#define D_SUBMODULE rx
70#include "sdio-debug-levels.h"
71
72
73/*
74 * Read and return the amount of bytes available for RX
75 *
76 * The RX size has to be read like this: byte reads of three
77 * sequential locations; then glue'em together.
78 *
79 * sdio_readl() doesn't work.
80 */
81ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms)
82{
83 int ret, cnt, val;
84 ssize_t rx_size;
85 unsigned xfer_size_addr;
86 struct sdio_func *func = i2400ms->func;
87 struct device *dev = &i2400ms->func->dev;
88
89 d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
90 xfer_size_addr = I2400MS_INTR_GET_SIZE_ADDR;
91 rx_size = 0;
92 for (cnt = 0; cnt < 3; cnt++) {
93 val = sdio_readb(func, xfer_size_addr + cnt, &ret);
94 if (ret < 0) {
95 dev_err(dev, "RX: Can't read byte %d of RX size from "
96 "0x%08x: %d\n", cnt, xfer_size_addr + cnt, ret);
97 rx_size = ret;
98 goto error_read;
99 }
100 rx_size = rx_size << 8 | (val & 0xff);
101 }
102 d_printf(6, dev, "RX: rx_size is %ld\n", (long) rx_size);
103error_read:
104 d_fnend(7, dev, "(i2400ms %p) = %ld\n", i2400ms, (long) rx_size);
105 return rx_size;
106}
107
108
109/*
110 * Read data from the device (when in normal)
111 *
112 * Allocate an SKB of the right size, read the data in and then
113 * deliver it to the generic layer.
114 *
115 * We also check for a reboot barker. That means the device died and
116 * we have to reboot it.
117 */
118static
119void i2400ms_rx(struct i2400ms *i2400ms)
120{
121 int ret;
122 struct sdio_func *func = i2400ms->func;
123 struct device *dev = &func->dev;
124 struct i2400m *i2400m = &i2400ms->i2400m;
125 struct sk_buff *skb;
126 ssize_t rx_size;
127
128 d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
129 rx_size = __i2400ms_rx_get_size(i2400ms);
130 if (rx_size < 0) {
131 ret = rx_size;
132 goto error_get_size;
133 }
134 ret = -ENOMEM;
135 skb = alloc_skb(rx_size, GFP_ATOMIC);
136 if (NULL == skb) {
137 dev_err(dev, "RX: unable to alloc skb\n");
138 goto error_alloc_skb;
139 }
140
141 ret = sdio_memcpy_fromio(func, skb->data,
142 I2400MS_DATA_ADDR, rx_size);
143 if (ret < 0) {
144 dev_err(dev, "RX: SDIO data read failed: %d\n", ret);
145 goto error_memcpy_fromio;
146 }
147 /* Check if device has reset */
148 if (!memcmp(skb->data, i2400m_NBOOT_BARKER,
149 sizeof(i2400m_NBOOT_BARKER))
150 || !memcmp(skb->data, i2400m_SBOOT_BARKER,
151 sizeof(i2400m_SBOOT_BARKER))) {
152 ret = i2400m_dev_reset_handle(i2400m);
153 kfree_skb(skb);
154 } else {
155 skb_put(skb, rx_size);
156 i2400m_rx(i2400m, skb);
157 }
158 d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms);
159 return;
160
161error_memcpy_fromio:
162 kfree_skb(skb);
163error_alloc_skb:
164error_get_size:
165 d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret);
166 return;
167}
168
169
170/*
171 * Process an interrupt from the SDIO card
172 *
173 * FIXME: need to process other events that are not just ready-to-read
174 *
175 * Checks there is data ready and then proceeds to read it.
176 */
177static
178void i2400ms_irq(struct sdio_func *func)
179{
180 int ret;
181 struct i2400ms *i2400ms = sdio_get_drvdata(func);
182 struct i2400m *i2400m = &i2400ms->i2400m;
183 struct device *dev = &func->dev;
184 int val;
185
186 d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms);
187 val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret);
188 if (ret < 0) {
189 dev_err(dev, "RX: Can't read interrupt status: %d\n", ret);
190 goto error_no_irq;
191 }
192 if (!val) {
193 dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n");
194 goto error_no_irq;
195 }
196 sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret);
197 if (WARN_ON(i2400m->boot_mode != 0))
198 dev_err(dev, "RX: SW BUG? boot mode and IRQ is up?\n");
199 else
200 i2400ms_rx(i2400ms);
201error_no_irq:
202 d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms);
203 return;
204}
205
206
207/*
208 * Setup SDIO RX
209 *
210 * Hooks up the IRQ handler and then enables IRQs.
211 */
212int i2400ms_rx_setup(struct i2400ms *i2400ms)
213{
214 int result;
215 struct sdio_func *func = i2400ms->func;
216 struct device *dev = &func->dev;
217
218 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
219 sdio_claim_host(func);
220 result = sdio_claim_irq(func, i2400ms_irq);
221 if (result < 0) {
222 dev_err(dev, "Cannot claim IRQ: %d\n", result);
223 goto error_irq_claim;
224 }
225 result = 0;
226 sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result);
227 if (result < 0) {
228 sdio_release_irq(func);
229 dev_err(dev, "Failed to enable interrupts %d\n", result);
230 }
231error_irq_claim:
232 sdio_release_host(func);
233 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
234 return result;
235}
236
237
238/*
239 * Tear down SDIO RX
240 *
241 * Disables IRQs in the device and removes the IRQ handler.
242 */
243void i2400ms_rx_release(struct i2400ms *i2400ms)
244{
245 int result;
246 struct sdio_func *func = i2400ms->func;
247 struct device *dev = &func->dev;
248
249 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
250 sdio_claim_host(func);
251 sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result);
252 sdio_release_irq(func);
253 sdio_release_host(func);
254 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
255}
diff --git a/drivers/net/wimax/i2400m/sdio-tx.c b/drivers/net/wimax/i2400m/sdio-tx.c
new file mode 100644
index 000000000000..5105a5ebc44f
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio-tx.c
@@ -0,0 +1,153 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * SDIO TX transaction backends
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Dirk Brandewie <dirk.j.brandewie@intel.com>
37 * - Initial implementation
38 *
39 *
40 * Takes the TX messages in the i2400m's driver TX FIFO and sends them
41 * to the device until there are no more.
42 *
43 * If we fail sending the message, we just drop it. There isn't much
44 * we can do at this point. Most of the traffic is network, which has
45 * recovery methods for dropped packets.
46 *
47 * The SDIO functions are not atomic, so we can't run from the context
48 * where i2400m->bus_tx_kick() [i2400ms_bus_tx_kick()] is being called
49 * (some times atomic). Thus, the actual TX work is deferred to a
50 * workqueue.
51 *
52 * ROADMAP
53 *
54 * i2400ms_bus_tx_kick()
55 * i2400ms_tx_submit() [through workqueue]
56 *
57 * i2400m_tx_setup()
58 *
59 * i2400m_tx_release()
60 */
61#include <linux/mmc/sdio_func.h>
62#include "i2400m-sdio.h"
63
64#define D_SUBMODULE tx
65#include "sdio-debug-levels.h"
66
67
68/*
69 * Pull TX transations from the TX FIFO and send them to the device
70 * until there are no more.
71 */
72static
73void i2400ms_tx_submit(struct work_struct *ws)
74{
75 int result;
76 struct i2400ms *i2400ms = container_of(ws, struct i2400ms, tx_worker);
77 struct i2400m *i2400m = &i2400ms->i2400m;
78 struct sdio_func *func = i2400ms->func;
79 struct device *dev = &func->dev;
80 struct i2400m_msg_hdr *tx_msg;
81 size_t tx_msg_size;
82
83 d_fnstart(4, dev, "(i2400ms %p, i2400m %p)\n", i2400ms, i2400ms);
84
85 while (NULL != (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) {
86 d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size);
87 d_dump(5, dev, tx_msg, tx_msg_size);
88
89 sdio_claim_host(func);
90 result = sdio_memcpy_toio(func, 0, tx_msg, tx_msg_size);
91 sdio_release_host(func);
92
93 i2400m_tx_msg_sent(i2400m);
94
95 if (result < 0) {
96 dev_err(dev, "TX: cannot submit TX; tx_msg @%zu %zu B:"
97 " %d\n", (void *) tx_msg - i2400m->tx_buf,
98 tx_msg_size, result);
99 }
100
101 d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size);
102 }
103
104 d_fnend(4, dev, "(i2400ms %p) = void\n", i2400ms);
105}
106
107
108/*
109 * The generic driver notifies us that there is data ready for TX
110 *
111 * Schedule a run of i2400ms_tx_submit() to handle it.
112 */
113void i2400ms_bus_tx_kick(struct i2400m *i2400m)
114{
115 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
116 struct device *dev = &i2400ms->func->dev;
117
118 d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
119
120 /* schedule tx work, this is because tx may block, therefore
121 * it has to run in a thread context.
122 */
123 queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker);
124
125 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
126}
127
128int i2400ms_tx_setup(struct i2400ms *i2400ms)
129{
130 int result;
131 struct device *dev = &i2400ms->func->dev;
132 struct i2400m *i2400m = &i2400ms->i2400m;
133
134 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
135
136 INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit);
137 snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name),
138 "%s-tx", i2400m->wimax_dev.name);
139 i2400ms->tx_workqueue =
140 create_singlethread_workqueue(i2400ms->tx_wq_name);
141 if (NULL == i2400ms->tx_workqueue) {
142 dev_err(dev, "TX: failed to create workqueue\n");
143 result = -ENOMEM;
144 } else
145 result = 0;
146 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
147 return result;
148}
149
150void i2400ms_tx_release(struct i2400ms *i2400ms)
151{
152 destroy_workqueue(i2400ms->tx_workqueue);
153}
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
new file mode 100644
index 000000000000..1bfa283bbd8a
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -0,0 +1,511 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Linux driver model glue for the SDIO device, reset & fw upload
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
7 * Dirk Brandewie <dirk.j.brandewie@intel.com>
8 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
9 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License version
13 * 2 as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * 02110-1301, USA.
24 *
25 *
26 * See i2400m-sdio.h for a general description of this driver.
27 *
28 * This file implements driver model glue, and hook ups for the
29 * generic driver to implement the bus-specific functions (device
30 * communication setup/tear down, firmware upload and resetting).
31 *
32 * ROADMAP
33 *
34 * i2400m_probe()
35 * alloc_netdev()
36 * i2400ms_netdev_setup()
37 * i2400ms_init()
38 * i2400m_netdev_setup()
39 * i2400ms_enable_function()
40 * i2400m_setup()
41 *
42 * i2400m_remove()
43 * i2400m_release()
44 * free_netdev(net_dev)
45 *
46 * i2400ms_bus_reset() Called by i2400m->bus_reset
47 * __i2400ms_reset()
48 * __i2400ms_send_barker()
49 *
50 * i2400ms_bus_dev_start() Called by i2400m_dev_start() [who is
51 * i2400ms_tx_setup() called by i2400m_setup()]
52 * i2400ms_rx_setup()
53 *
54 * i2400ms_bus_dev_stop() Called by i2400m_dev_stop() [who is
55 * i2400ms_rx_release() is called by i2400m_release()]
56 * i2400ms_tx_release()
57 *
58 */
59
60#include <linux/debugfs.h>
61#include <linux/mmc/sdio.h>
62#include <linux/mmc/sdio_func.h>
63#include "i2400m-sdio.h"
64#include <linux/wimax/i2400m.h>
65
66#define D_SUBMODULE main
67#include "sdio-debug-levels.h"
68
69/* IOE WiMAX function timeout in seconds */
70static int ioe_timeout = 2;
71module_param(ioe_timeout, int, 0);
72
73/* Our firmware file name */
74#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-" I2400M_FW_VERSION ".sbcf"
75
76/*
77 * Enable the SDIO function
78 *
79 * Tries to enable the SDIO function; might fail if it is still not
80 * ready (in some hardware, the SDIO WiMAX function is only enabled
81 * when we ask it to explicitly doing). Tries until a timeout is
82 * reached.
83 *
84 * The reverse of this is...sdio_disable_function()
85 *
86 * Returns: 0 if the SDIO function was enabled, < 0 errno code on
87 * error (-ENODEV when it was unable to enable the function).
88 */
89static
90int i2400ms_enable_function(struct sdio_func *func)
91{
92 u64 timeout;
93 int err;
94 struct device *dev = &func->dev;
95
96 d_fnstart(3, dev, "(func %p)\n", func);
97 /* Setup timeout (FIXME: This needs to read the CIS table to
98 * get a real timeout) and then wait for the device to signal
99 * it is ready */
100 timeout = get_jiffies_64() + ioe_timeout * HZ;
101 err = -ENODEV;
102 while (err != 0 && time_before64(get_jiffies_64(), timeout)) {
103 sdio_claim_host(func);
104 err = sdio_enable_func(func);
105 if (0 == err) {
106 sdio_release_host(func);
107 d_printf(2, dev, "SDIO function enabled\n");
108 goto function_enabled;
109 }
110 d_printf(2, dev, "SDIO function failed to enable: %d\n", err);
111 sdio_disable_func(func);
112 sdio_release_host(func);
113 msleep(I2400MS_INIT_SLEEP_INTERVAL);
114 }
115 /* If timed out, device is not there yet -- get -ENODEV so
116 * the device driver core will retry later on. */
117 if (err == -ETIME) {
118 dev_err(dev, "Can't enable WiMAX function; "
119 " has the function been enabled?\n");
120 err = -ENODEV;
121 }
122function_enabled:
123 d_fnend(3, dev, "(func %p) = %d\n", func, err);
124 return err;
125}
126
127
128/*
129 * Setup driver resources needed to communicate with the device
130 *
131 * The fw needs some time to settle, and it was just uploaded,
132 * so give it a break first. I'd prefer to just wait for the device to
133 * send something, but seems the poking we do to enable SDIO stuff
134 * interferes with it, so just give it a break before starting...
135 */
136static
137int i2400ms_bus_dev_start(struct i2400m *i2400m)
138{
139 int result;
140 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
141 struct sdio_func *func = i2400ms->func;
142 struct device *dev = &func->dev;
143
144 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
145 msleep(200);
146 result = i2400ms_rx_setup(i2400ms);
147 if (result < 0)
148 goto error_rx_setup;
149 result = i2400ms_tx_setup(i2400ms);
150 if (result < 0)
151 goto error_tx_setup;
152 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
153 return result;
154
155 i2400ms_tx_release(i2400ms);
156error_tx_setup:
157 i2400ms_rx_release(i2400ms);
158error_rx_setup:
159 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
160 return result;
161}
162
163
164static
165void i2400ms_bus_dev_stop(struct i2400m *i2400m)
166{
167 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
168 struct sdio_func *func = i2400ms->func;
169 struct device *dev = &func->dev;
170
171 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
172 i2400ms_rx_release(i2400ms);
173 i2400ms_tx_release(i2400ms);
174 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
175}
176
177
178/*
179 * Sends a barker buffer to the device
180 *
181 * This helper will allocate a kmalloced buffer and use it to transmit
182 * (then free it). Reason for this is that the SDIO host controller
183 * expects alignment (unknown exactly which) which the stack won't
184 * really provide and certain arches/host-controller combinations
185 * cannot use stack/vmalloc/text areas for DMA transfers.
186 */
187static
188int __i2400ms_send_barker(struct i2400ms *i2400ms,
189 const __le32 *barker, size_t barker_size)
190{
191 int ret;
192 struct sdio_func *func = i2400ms->func;
193 struct device *dev = &func->dev;
194 void *buffer;
195
196 ret = -ENOMEM;
197 buffer = kmalloc(I2400MS_BLK_SIZE, GFP_KERNEL);
198 if (buffer == NULL)
199 goto error_kzalloc;
200
201 memcpy(buffer, barker, barker_size);
202 sdio_claim_host(func);
203 ret = sdio_memcpy_toio(func, 0, buffer, I2400MS_BLK_SIZE);
204 sdio_release_host(func);
205
206 if (ret < 0)
207 d_printf(0, dev, "E: barker error: %d\n", ret);
208
209 kfree(buffer);
210error_kzalloc:
211 return ret;
212}
213
214
215/*
216 * Reset a device at different levels (warm, cold or bus)
217 *
218 * @i2400ms: device descriptor
219 * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS)
220 *
221 * FIXME: not tested -- need to confirm expected effects
222 *
223 * Warm and cold resets get an SDIO reset if they fail (unimplemented)
224 *
225 * Warm reset:
226 *
227 * The device will be fully reset internally, but won't be
228 * disconnected from the USB bus (so no reenumeration will
229 * happen). Firmware upload will be neccessary.
230 *
231 * The device will send a reboot barker in the notification endpoint
232 * that will trigger the driver to reinitialize the state
233 * automatically from notif.c:i2400m_notification_grok() into
234 * i2400m_dev_bootstrap_delayed().
235 *
236 * Cold and bus (USB) reset:
237 *
238 * The device will be fully reset internally, disconnected from the
239 * USB bus an a reenumeration will happen. Firmware upload will be
240 * neccessary. Thus, we don't do any locking or struct
241 * reinitialization, as we are going to be fully disconnected and
242 * reenumerated.
243 *
244 * Note we need to return -ENODEV if a warm reset was requested and we
245 * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset()
246 * and wimax_dev->op_reset.
247 *
248 * WARNING: no driver state saved/fixed
249 */
250static
251int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
252{
253 int result;
254 struct i2400ms *i2400ms =
255 container_of(i2400m, struct i2400ms, i2400m);
256 struct device *dev = i2400m_dev(i2400m);
257 static const __le32 i2400m_WARM_BOOT_BARKER[4] = {
258 __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
259 __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
260 __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
261 __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
262 };
263 static const __le32 i2400m_COLD_BOOT_BARKER[4] = {
264 __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
265 __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
266 __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
267 __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
268 };
269
270 if (rt == I2400M_RT_WARM)
271 result = __i2400ms_send_barker(i2400ms, i2400m_WARM_BOOT_BARKER,
272 sizeof(i2400m_WARM_BOOT_BARKER));
273 else if (rt == I2400M_RT_COLD)
274 result = __i2400ms_send_barker(i2400ms, i2400m_COLD_BOOT_BARKER,
275 sizeof(i2400m_COLD_BOOT_BARKER));
276 else if (rt == I2400M_RT_BUS) {
277do_bus_reset:
278 dev_err(dev, "FIXME: SDIO bus reset not implemented\n");
279 result = rt == I2400M_RT_WARM ? -ENODEV : -ENOSYS;
280 } else
281 BUG();
282 if (result < 0 && rt != I2400M_RT_BUS) {
283 dev_err(dev, "%s reset failed (%d); trying SDIO reset\n",
284 rt == I2400M_RT_WARM ? "warm" : "cold", result);
285 rt = I2400M_RT_BUS;
286 goto do_bus_reset;
287 }
288 return result;
289}
290
291
292static
293void i2400ms_netdev_setup(struct net_device *net_dev)
294{
295 struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
296 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
297 i2400ms_init(i2400ms);
298 i2400m_netdev_setup(net_dev);
299}
300
301
302/*
303 * Debug levels control; see debug.h
304 */
305struct d_level D_LEVEL[] = {
306 D_SUBMODULE_DEFINE(main),
307 D_SUBMODULE_DEFINE(tx),
308 D_SUBMODULE_DEFINE(rx),
309 D_SUBMODULE_DEFINE(fw),
310};
311size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
312
313
314#define __debugfs_register(prefix, name, parent) \
315do { \
316 result = d_level_register_debugfs(prefix, name, parent); \
317 if (result < 0) \
318 goto error; \
319} while (0)
320
321
322static
323int i2400ms_debugfs_add(struct i2400ms *i2400ms)
324{
325 int result;
326 struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry;
327
328 dentry = debugfs_create_dir("i2400m-usb", dentry);
329 result = PTR_ERR(dentry);
330 if (IS_ERR(dentry)) {
331 if (result == -ENODEV)
332 result = 0; /* No debugfs support */
333 goto error;
334 }
335 i2400ms->debugfs_dentry = dentry;
336 __debugfs_register("dl_", main, dentry);
337 __debugfs_register("dl_", tx, dentry);
338 __debugfs_register("dl_", rx, dentry);
339 __debugfs_register("dl_", fw, dentry);
340
341 return 0;
342
343error:
344 debugfs_remove_recursive(i2400ms->debugfs_dentry);
345 return result;
346}
347
348
349/*
350 * Probe a i2400m interface and register it
351 *
352 * @func: SDIO function
353 * @id: SDIO device ID
354 * @returns: 0 if ok, < 0 errno code on error.
355 *
356 * Alloc a net device, initialize the bus-specific details and then
357 * calls the bus-generic initialization routine. That will register
358 * the wimax and netdev devices, upload the firmware [using
359 * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
360 * communication with the device and then will start to talk to it to
361 * finnish setting it up.
362 *
363 * Initialization is tricky; some instances of the hw are packed with
364 * others in a way that requires a third driver that enables the WiMAX
365 * function. In those cases, we can't enable the SDIO function and
366 * we'll return with -ENODEV. When the driver that enables the WiMAX
367 * function does its thing, it has to do a bus_rescan_devices() on the
368 * SDIO bus so this driver is called again to enumerate the WiMAX
369 * function.
370 */
371static
372int i2400ms_probe(struct sdio_func *func,
373 const struct sdio_device_id *id)
374{
375 int result;
376 struct net_device *net_dev;
377 struct device *dev = &func->dev;
378 struct i2400m *i2400m;
379 struct i2400ms *i2400ms;
380
381 /* Allocate instance [calls i2400m_netdev_setup() on it]. */
382 result = -ENOMEM;
383 net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d",
384 i2400ms_netdev_setup);
385 if (net_dev == NULL) {
386 dev_err(dev, "no memory for network device instance\n");
387 goto error_alloc_netdev;
388 }
389 SET_NETDEV_DEV(net_dev, dev);
390 i2400m = net_dev_to_i2400m(net_dev);
391 i2400ms = container_of(i2400m, struct i2400ms, i2400m);
392 i2400m->wimax_dev.net_dev = net_dev;
393 i2400ms->func = func;
394 sdio_set_drvdata(func, i2400ms);
395
396 i2400m->bus_tx_block_size = I2400MS_BLK_SIZE;
397 i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX;
398 i2400m->bus_dev_start = i2400ms_bus_dev_start;
399 i2400m->bus_dev_stop = i2400ms_bus_dev_stop;
400 i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
401 i2400m->bus_reset = i2400ms_bus_reset;
402 i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send;
403 i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack;
404 i2400m->bus_fw_name = I2400MS_FW_FILE_NAME;
405 i2400m->bus_bm_mac_addr_impaired = 1;
406
407 result = i2400ms_enable_function(i2400ms->func);
408 if (result < 0) {
409 dev_err(dev, "Cannot enable SDIO function: %d\n", result);
410 goto error_func_enable;
411 }
412
413 sdio_claim_host(func);
414 result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
415 if (result < 0) {
416 dev_err(dev, "Failed to set block size: %d\n", result);
417 goto error_set_blk_size;
418 }
419 sdio_release_host(func);
420
421 result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT);
422 if (result < 0) {
423 dev_err(dev, "cannot setup device: %d\n", result);
424 goto error_setup;
425 }
426
427 result = i2400ms_debugfs_add(i2400ms);
428 if (result < 0) {
429 dev_err(dev, "cannot create SDIO debugfs: %d\n",
430 result);
431 goto error_debugfs_add;
432 }
433 return 0;
434
435error_debugfs_add:
436 i2400m_release(i2400m);
437error_setup:
438 sdio_set_drvdata(func, NULL);
439 sdio_claim_host(func);
440error_set_blk_size:
441 sdio_disable_func(func);
442 sdio_release_host(func);
443error_func_enable:
444 free_netdev(net_dev);
445error_alloc_netdev:
446 return result;
447}
448
449
450static
451void i2400ms_remove(struct sdio_func *func)
452{
453 struct device *dev = &func->dev;
454 struct i2400ms *i2400ms = sdio_get_drvdata(func);
455 struct i2400m *i2400m = &i2400ms->i2400m;
456 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
457
458 d_fnstart(3, dev, "SDIO func %p\n", func);
459 debugfs_remove_recursive(i2400ms->debugfs_dentry);
460 i2400m_release(i2400m);
461 sdio_set_drvdata(func, NULL);
462 sdio_claim_host(func);
463 sdio_disable_func(func);
464 sdio_release_host(func);
465 free_netdev(net_dev);
466 d_fnend(3, dev, "SDIO func %p\n", func);
467}
468
469enum {
470 I2400MS_INTEL_VID = 0x89,
471};
472
473static
474const struct sdio_device_id i2400ms_sdio_ids[] = {
475 /* Intel: i2400m WiMAX over SDIO */
476 { SDIO_DEVICE(I2400MS_INTEL_VID, 0x1402) },
477 { }, /* end: all zeroes */
478};
479MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids);
480
481
482static
483struct sdio_driver i2400m_sdio_driver = {
484 .name = KBUILD_MODNAME,
485 .probe = i2400ms_probe,
486 .remove = i2400ms_remove,
487 .id_table = i2400ms_sdio_ids,
488};
489
490
491static
492int __init i2400ms_driver_init(void)
493{
494 return sdio_register_driver(&i2400m_sdio_driver);
495}
496module_init(i2400ms_driver_init);
497
498
499static
500void __exit i2400ms_driver_exit(void)
501{
502 flush_scheduled_work(); /* for the stuff we schedule */
503 sdio_unregister_driver(&i2400m_sdio_driver);
504}
505module_exit(i2400ms_driver_exit);
506
507
508MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
509MODULE_DESCRIPTION("Intel 2400M WiMAX networking for SDIO");
510MODULE_LICENSE("GPL");
511MODULE_FIRMWARE(I2400MS_FW_FILE_NAME);
diff --git a/drivers/net/wimax/i2400m/tx.c b/drivers/net/wimax/i2400m/tx.c
new file mode 100644
index 000000000000..613a88ffd651
--- /dev/null
+++ b/drivers/net/wimax/i2400m/tx.c
@@ -0,0 +1,817 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Generic (non-bus specific) TX handling
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37 * - Initial implementation
38 *
39 * Intel Corporation <linux-wimax@intel.com>
40 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
41 * - Rewritten to use a single FIFO to lower the memory allocation
42 * pressure and optimize cache hits when copying to the queue, as
43 * well as splitting out bus-specific code.
44 *
45 *
46 * Implements data transmission to the device; this is done through a
47 * software FIFO, as data/control frames can be coalesced (while the
48 * device is reading the previous tx transaction, others accumulate).
49 *
50 * A FIFO is used because at the end it is resource-cheaper that trying
51 * to implement scatter/gather over USB. As well, most traffic is going
52 * to be download (vs upload).
53 *
54 * The format for sending/receiving data to/from the i2400m is
55 * described in detail in rx.c:PROTOCOL FORMAT. In here we implement
56 * the transmission of that. This is split between a bus-independent
57 * part that just prepares everything and a bus-specific part that
58 * does the actual transmission over the bus to the device (in the
59 * bus-specific driver).
60 *
61 *
62 * The general format of a device-host transaction is MSG-HDR, PLD1,
63 * PLD2...PLDN, PL1, PL2,...PLN, PADDING.
64 *
65 * Because we need the send payload descriptors and then payloads and
66 * because it is kind of expensive to do scatterlists in USB (one URB
67 * per node), it becomes cheaper to append all the data to a FIFO
68 * (copying to a FIFO potentially in cache is cheaper).
69 *
70 * Then the bus-specific code takes the parts of that FIFO that are
71 * written and passes them to the device.
72 *
73 * So the concepts to keep in mind there are:
74 *
75 * We use a FIFO to queue the data in a linear buffer. We first append
76 * a MSG-HDR, space for I2400M_TX_PLD_MAX payload descriptors and then
77 * go appending payloads until we run out of space or of payload
78 * descriptors. Then we append padding to make the whole transaction a
79 * multiple of i2400m->bus_tx_block_size (as defined by the bus layer).
80 *
81 * - A TX message: a combination of a message header, payload
82 * descriptors and payloads.
83 *
84 * Open: it is marked as active (i2400m->tx_msg is valid) and we
85 * can keep adding payloads to it.
86 *
87 * Closed: we are not appending more payloads to this TX message
88 * (exahusted space in the queue, too many payloads or
89 * whichever). We have appended padding so the whole message
90 * length is aligned to i2400m->bus_tx_block_size (as set by the
91 * bus/transport layer).
92 *
93 * - Most of the time we keep a TX message open to which we append
94 * payloads.
95 *
96 * - If we are going to append and there is no more space (we are at
97 * the end of the FIFO), we close the message, mark the rest of the
98 * FIFO space unusable (skip_tail), create a new message at the
99 * beginning of the FIFO (if there is space) and append the message
100 * there.
101 *
102 * This is because we need to give linear TX messages to the bus
103 * engine. So we don't write a message to the remaining FIFO space
104 * until the tail and continue at the head of it.
105 *
106 * - We overload one of the fields in the message header to use it as
107 * 'size' of the TX message, so we can iterate over them. It also
108 * contains a flag that indicates if we have to skip it or not.
109 * When we send the buffer, we update that to its real on-the-wire
110 * value.
111 *
112 * - The MSG-HDR PLD1...PLD2 stuff has to be a size multiple of 16.
113 *
114 * It follows that if MSG-HDR says we have N messages, the whole
115 * header + descriptors is 16 + 4*N; for those to be a multiple of
116 * 16, it follows that N can be 4, 8, 12, ... (32, 48, 64, 80...
117 * bytes).
118 *
119 * So if we have only 1 payload, we have to submit a header that in
120 * all truth has space for 4.
121 *
122 * The implication is that we reserve space for 12 (64 bytes); but
123 * if we fill up only (eg) 2, our header becomes 32 bytes only. So
124 * the TX engine has to shift those 32 bytes of msg header and 2
125 * payloads and padding so that right after it the payloads start
126 * and the TX engine has to know about that.
127 *
128 * It is cheaper to move the header up than the whole payloads down.
129 *
130 * We do this in i2400m_tx_close(). See 'i2400m_msg_hdr->offset'.
131 *
132 * - Each payload has to be size-padded to 16 bytes; before appending
133 * it, we just do it.
134 *
135 * - The whole message has to be padded to i2400m->bus_tx_block_size;
136 * we do this at close time. Thus, when reserving space for the
137 * payload, we always make sure there is also free space for this
138 * padding that sooner or later will happen.
139 *
140 * When we append a message, we tell the bus specific code to kick in
141 * TXs. It will TX (in parallel) until the buffer is exhausted--hence
142 * the lockin we do. The TX code will only send a TX message at the
143 * time (which remember, might contain more than one payload). Of
144 * course, when the bus-specific driver attempts to TX a message that
145 * is still open, it gets closed first.
146 *
147 * Gee, this is messy; well a picture. In the example below we have a
148 * partially full FIFO, with a closed message ready to be delivered
149 * (with a moved message header to make sure it is size-aligned to
150 * 16), TAIL room that was unusable (and thus is marked with a message
151 * header that says 'skip this') and at the head of the buffer, an
152 * imcomplete message with a couple of payloads.
153 *
154 * N ___________________________________________________
155 * | |
156 * | TAIL room |
157 * | |
158 * | msg_hdr to skip (size |= 0x80000) |
159 * |---------------------------------------------------|-------
160 * | | /|\
161 * | | |
162 * | TX message padding | |
163 * | | |
164 * | | |
165 * |- - - - - - - - - - - - - - - - - - - - - - - - - -| |
166 * | | |
167 * | payload 1 | |
168 * | | N * tx_block_size
169 * | | |
170 * |- - - - - - - - - - - - - - - - - - - - - - - - - -| |
171 * | | |
172 * | payload 1 | |
173 * | | |
174 * | | |
175 * |- - - - - - - - - - - - - - - - - - - - - - - - - -|- -|- - - -
176 * | padding 3 /|\ | | /|\
177 * | padding 2 | | | |
178 * | pld 1 32 bytes (2 * 16) | | |
179 * | pld 0 | | | |
180 * | moved msg_hdr \|/ | \|/ |
181 * |- - - - - - - - - - - - - - - - - - - - - - - - - -|- - - |
182 * | | _PLD_SIZE
183 * | unused | |
184 * | | |
185 * |- - - - - - - - - - - - - - - - - - - - - - - - - -| |
186 * | msg_hdr (size X) [this message is closed] | \|/
187 * |===================================================|========== <=== OUT
188 * | |
189 * | |
190 * | |
191 * | Free rooom |
192 * | |
193 * | |
194 * | |
195 * | |
196 * | |
197 * | |
198 * | |
199 * | |
200 * | |
201 * |===================================================|========== <=== IN
202 * | |
203 * | |
204 * | |
205 * | |
206 * | payload 1 |
207 * | |
208 * | |
209 * |- - - - - - - - - - - - - - - - - - - - - - - - - -|
210 * | |
211 * | payload 0 |
212 * | |
213 * | |
214 * |- - - - - - - - - - - - - - - - - - - - - - - - - -|
215 * | pld 11 /|\ |
216 * | ... | |
217 * | pld 1 64 bytes (2 * 16) |
218 * | pld 0 | |
219 * | msg_hdr (size X) \|/ [message is open] |
220 * 0 ---------------------------------------------------
221 *
222 *
223 * ROADMAP
224 *
225 * i2400m_tx_setup() Called by i2400m_setup
226 * i2400m_tx_release() Called by i2400m_release()
227 *
228 * i2400m_tx() Called to send data or control frames
229 * i2400m_tx_fifo_push() Allocates append-space in the FIFO
230 * i2400m_tx_new() Opens a new message in the FIFO
231 * i2400m_tx_fits() Checks if a new payload fits in the message
232 * i2400m_tx_close() Closes an open message in the FIFO
233 * i2400m_tx_skip_tail() Marks unusable FIFO tail space
234 * i2400m->bus_tx_kick()
235 *
236 * Now i2400m->bus_tx_kick() is the the bus-specific driver backend
237 * implementation; that would do:
238 *
239 * i2400m->bus_tx_kick()
240 * i2400m_tx_msg_get() Gets first message ready to go
241 * ...sends it...
242 * i2400m_tx_msg_sent() Ack the message is sent; repeat from
243 * _tx_msg_get() until it returns NULL
244 * (FIFO empty).
245 */
246#include <linux/netdevice.h>
247#include "i2400m.h"
248
249
250#define D_SUBMODULE tx
251#include "debug-levels.h"
252
253enum {
254 /**
255 * TX Buffer size
256 *
257 * Doc says maximum transaction is 16KiB. If we had 16KiB en
258 * route and 16KiB being queued, it boils down to needing
259 * 32KiB.
260 */
261 I2400M_TX_BUF_SIZE = 32768,
262 /**
263 * Message header and payload descriptors have to be 16
264 * aligned (16 + 4 * N = 16 * M). If we take that average sent
265 * packets are MTU size (~1400-~1500) it follows that we could
266 * fit at most 10-11 payloads in one transaction. To meet the
267 * alignment requirement, that means we need to leave space
268 * for 12 (64 bytes). To simplify, we leave space for that. If
269 * at the end there are less, we pad up to the nearest
270 * multiple of 16.
271 */
272 I2400M_TX_PLD_MAX = 12,
273 I2400M_TX_PLD_SIZE = sizeof(struct i2400m_msg_hdr)
274 + I2400M_TX_PLD_MAX * sizeof(struct i2400m_pld),
275 I2400M_TX_SKIP = 0x80000000,
276};
277
278#define TAIL_FULL ((void *)~(unsigned long)NULL)
279
280/*
281 * Allocate @size bytes in the TX fifo, return a pointer to it
282 *
283 * @i2400m: device descriptor
284 * @size: size of the buffer we need to allocate
285 * @padding: ensure that there is at least this many bytes of free
286 * contiguous space in the fifo. This is needed because later on
287 * we might need to add padding.
288 *
289 * Returns:
290 *
291 * Pointer to the allocated space. NULL if there is no
292 * space. TAIL_FULL if there is no space at the tail but there is at
293 * the head (Case B below).
294 *
295 * These are the two basic cases we need to keep an eye for -- it is
296 * much better explained in linux/kernel/kfifo.c, but this code
297 * basically does the same. No rocket science here.
298 *
299 * Case A Case B
300 * N ___________ ___________
301 * | tail room | | data |
302 * | | | |
303 * |<- IN ->| |<- OUT ->|
304 * | | | |
305 * | data | | room |
306 * | | | |
307 * |<- OUT ->| |<- IN ->|
308 * | | | |
309 * | head room | | data |
310 * 0 ----------- -----------
311 *
312 * We allocate only *contiguous* space.
313 *
314 * We can allocate only from 'room'. In Case B, it is simple; in case
315 * A, we only try from the tail room; if it is not enough, we just
316 * fail and return TAIL_FULL and let the caller figure out if we wants to
317 * skip the tail room and try to allocate from the head.
318 *
319 * Note:
320 *
321 * Assumes i2400m->tx_lock is taken, and we use that as a barrier
322 *
323 * The indexes keep increasing and we reset them to zero when we
324 * pop data off the queue
325 */
326static
327void *i2400m_tx_fifo_push(struct i2400m *i2400m, size_t size, size_t padding)
328{
329 struct device *dev = i2400m_dev(i2400m);
330 size_t room, tail_room, needed_size;
331 void *ptr;
332
333 needed_size = size + padding;
334 room = I2400M_TX_BUF_SIZE - (i2400m->tx_in - i2400m->tx_out);
335 if (room < needed_size) { /* this takes care of Case B */
336 d_printf(2, dev, "fifo push %zu/%zu: no space\n",
337 size, padding);
338 return NULL;
339 }
340 /* Is there space at the tail? */
341 tail_room = I2400M_TX_BUF_SIZE - i2400m->tx_in % I2400M_TX_BUF_SIZE;
342 if (tail_room < needed_size) {
343 if (i2400m->tx_out % I2400M_TX_BUF_SIZE
344 < i2400m->tx_in % I2400M_TX_BUF_SIZE) {
345 d_printf(2, dev, "fifo push %zu/%zu: tail full\n",
346 size, padding);
347 return TAIL_FULL; /* There might be head space */
348 } else {
349 d_printf(2, dev, "fifo push %zu/%zu: no head space\n",
350 size, padding);
351 return NULL; /* There is no space */
352 }
353 }
354 ptr = i2400m->tx_buf + i2400m->tx_in % I2400M_TX_BUF_SIZE;
355 d_printf(2, dev, "fifo push %zu/%zu: at @%zu\n", size, padding,
356 i2400m->tx_in % I2400M_TX_BUF_SIZE);
357 i2400m->tx_in += size;
358 return ptr;
359}
360
361
362/*
363 * Mark the tail of the FIFO buffer as 'to-skip'
364 *
365 * We should never hit the BUG_ON() because all the sizes we push to
366 * the FIFO are padded to be a multiple of 16 -- the size of *msg
367 * (I2400M_PL_PAD for the payloads, I2400M_TX_PLD_SIZE for the
368 * header).
369 *
370 * Note:
371 *
372 * Assumes i2400m->tx_lock is taken, and we use that as a barrier
373 */
374static
375void i2400m_tx_skip_tail(struct i2400m *i2400m)
376{
377 struct device *dev = i2400m_dev(i2400m);
378 size_t tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE;
379 size_t tail_room = I2400M_TX_BUF_SIZE - tx_in;
380 struct i2400m_msg_hdr *msg = i2400m->tx_buf + tx_in;
381 BUG_ON(tail_room < sizeof(*msg));
382 msg->size = tail_room | I2400M_TX_SKIP;
383 d_printf(2, dev, "skip tail: skipping %zu bytes @%zu\n",
384 tail_room, tx_in);
385 i2400m->tx_in += tail_room;
386}
387
388
389/*
390 * Check if a skb will fit in the TX queue's current active TX
391 * message (if there are still descriptors left unused).
392 *
393 * Returns:
394 * 0 if the message won't fit, 1 if it will.
395 *
396 * Note:
397 *
398 * Assumes a TX message is active (i2400m->tx_msg).
399 *
400 * Assumes i2400m->tx_lock is taken, and we use that as a barrier
401 */
402static
403unsigned i2400m_tx_fits(struct i2400m *i2400m)
404{
405 struct i2400m_msg_hdr *msg_hdr = i2400m->tx_msg;
406 return le16_to_cpu(msg_hdr->num_pls) < I2400M_TX_PLD_MAX;
407
408}
409
410
411/*
412 * Start a new TX message header in the queue.
413 *
414 * Reserve memory from the base FIFO engine and then just initialize
415 * the message header.
416 *
417 * We allocate the biggest TX message header we might need (one that'd
418 * fit I2400M_TX_PLD_MAX payloads) -- when it is closed it will be
419 * 'ironed it out' and the unneeded parts removed.
420 *
421 * NOTE:
422 *
423 * Assumes that the previous message is CLOSED (eg: either
424 * there was none or 'i2400m_tx_close()' was called on it).
425 *
426 * Assumes i2400m->tx_lock is taken, and we use that as a barrier
427 */
428static
429void i2400m_tx_new(struct i2400m *i2400m)
430{
431 struct device *dev = i2400m_dev(i2400m);
432 struct i2400m_msg_hdr *tx_msg;
433 BUG_ON(i2400m->tx_msg != NULL);
434try_head:
435 tx_msg = i2400m_tx_fifo_push(i2400m, I2400M_TX_PLD_SIZE, 0);
436 if (tx_msg == NULL)
437 goto out;
438 else if (tx_msg == TAIL_FULL) {
439 i2400m_tx_skip_tail(i2400m);
440 d_printf(2, dev, "new TX message: tail full, trying head\n");
441 goto try_head;
442 }
443 memset(tx_msg, 0, I2400M_TX_PLD_SIZE);
444 tx_msg->size = I2400M_TX_PLD_SIZE;
445out:
446 i2400m->tx_msg = tx_msg;
447 d_printf(2, dev, "new TX message: %p @%zu\n",
448 tx_msg, (void *) tx_msg - i2400m->tx_buf);
449}
450
451
452/*
453 * Finalize the current TX message header
454 *
455 * Sets the message header to be at the proper location depending on
456 * how many descriptors we have (check documentation at the file's
457 * header for more info on that).
458 *
459 * Appends padding bytes to make sure the whole TX message (counting
460 * from the 'relocated' message header) is aligned to
461 * tx_block_size. We assume the _append() code has left enough space
462 * in the FIFO for that. If there are no payloads, just pass, as it
463 * won't be transferred.
464 *
465 * The amount of padding bytes depends on how many payloads are in the
466 * TX message, as the "msg header and payload descriptors" will be
467 * shifted up in the buffer.
468 */
469static
470void i2400m_tx_close(struct i2400m *i2400m)
471{
472 struct device *dev = i2400m_dev(i2400m);
473 struct i2400m_msg_hdr *tx_msg = i2400m->tx_msg;
474 struct i2400m_msg_hdr *tx_msg_moved;
475 size_t aligned_size, padding, hdr_size;
476 void *pad_buf;
477
478 if (tx_msg->size & I2400M_TX_SKIP) /* a skipper? nothing to do */
479 goto out;
480
481 /* Relocate the message header
482 *
483 * Find the current header size, align it to 16 and if we need
484 * to move it so the tail is next to the payloads, move it and
485 * set the offset.
486 *
487 * If it moved, this header is good only for transmission; the
488 * original one (it is kept if we moved) is still used to
489 * figure out where the next TX message starts (and where the
490 * offset to the moved header is).
491 */
492 hdr_size = sizeof(*tx_msg)
493 + le16_to_cpu(tx_msg->num_pls) * sizeof(tx_msg->pld[0]);
494 hdr_size = ALIGN(hdr_size, I2400M_PL_PAD);
495 tx_msg->offset = I2400M_TX_PLD_SIZE - hdr_size;
496 tx_msg_moved = (void *) tx_msg + tx_msg->offset;
497 memmove(tx_msg_moved, tx_msg, hdr_size);
498 tx_msg_moved->size -= tx_msg->offset;
499 /*
500 * Now figure out how much we have to add to the (moved!)
501 * message so the size is a multiple of i2400m->bus_tx_block_size.
502 */
503 aligned_size = ALIGN(tx_msg_moved->size, i2400m->bus_tx_block_size);
504 padding = aligned_size - tx_msg_moved->size;
505 if (padding > 0) {
506 pad_buf = i2400m_tx_fifo_push(i2400m, padding, 0);
507 if (unlikely(WARN_ON(pad_buf == NULL
508 || pad_buf == TAIL_FULL))) {
509 /* This should not happen -- append should verify
510 * there is always space left at least to append
511 * tx_block_size */
512 dev_err(dev,
513 "SW BUG! Possible data leakage from memory the "
514 "device should not read for padding - "
515 "size %lu aligned_size %zu tx_buf %p in "
516 "%zu out %zu\n",
517 (unsigned long) tx_msg_moved->size,
518 aligned_size, i2400m->tx_buf, i2400m->tx_in,
519 i2400m->tx_out);
520 } else
521 memset(pad_buf, 0xad, padding);
522 }
523 tx_msg_moved->padding = cpu_to_le16(padding);
524 tx_msg_moved->size += padding;
525 if (tx_msg != tx_msg_moved)
526 tx_msg->size += padding;
527out:
528 i2400m->tx_msg = NULL;
529}
530
531
532/**
533 * i2400m_tx - send the data in a buffer to the device
534 *
535 * @buf: pointer to the buffer to transmit
536 *
537 * @buf_len: buffer size
538 *
539 * @pl_type: type of the payload we are sending.
540 *
541 * Returns:
542 * 0 if ok, < 0 errno code on error (-ENOSPC, if there is no more
543 * room for the message in the queue).
544 *
545 * Appends the buffer to the TX FIFO and notifies the bus-specific
546 * part of the driver that there is new data ready to transmit.
547 * Once this function returns, the buffer has been copied, so it can
548 * be reused.
549 *
550 * The steps followed to append are explained in detail in the file
551 * header.
552 *
553 * Whenever we write to a message, we increase msg->size, so it
554 * reflects exactly how big the message is. This is needed so that if
555 * we concatenate two messages before they can be sent, the code that
556 * sends the messages can find the boundaries (and it will replace the
557 * size with the real barker before sending).
558 *
559 * Note:
560 *
561 * Cold and warm reset payloads need to be sent as a single
562 * payload, so we handle that.
563 */
564int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len,
565 enum i2400m_pt pl_type)
566{
567 int result = -ENOSPC;
568 struct device *dev = i2400m_dev(i2400m);
569 unsigned long flags;
570 size_t padded_len;
571 void *ptr;
572 unsigned is_singleton = pl_type == I2400M_PT_RESET_WARM
573 || pl_type == I2400M_PT_RESET_COLD;
574
575 d_fnstart(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u)\n",
576 i2400m, buf, buf_len, pl_type);
577 padded_len = ALIGN(buf_len, I2400M_PL_PAD);
578 d_printf(5, dev, "padded_len %zd buf_len %zd\n", padded_len, buf_len);
579 /* If there is no current TX message, create one; if the
580 * current one is out of payload slots or we have a singleton,
581 * close it and start a new one */
582 spin_lock_irqsave(&i2400m->tx_lock, flags);
583try_new:
584 if (unlikely(i2400m->tx_msg == NULL))
585 i2400m_tx_new(i2400m);
586 else if (unlikely(!i2400m_tx_fits(i2400m)
587 || (is_singleton && i2400m->tx_msg->num_pls != 0))) {
588 d_printf(2, dev, "closing TX message (fits %u singleton "
589 "%u num_pls %u)\n", i2400m_tx_fits(i2400m),
590 is_singleton, i2400m->tx_msg->num_pls);
591 i2400m_tx_close(i2400m);
592 i2400m_tx_new(i2400m);
593 }
594 if (i2400m->tx_msg->size + padded_len > I2400M_TX_BUF_SIZE / 2) {
595 d_printf(2, dev, "TX: message too big, going new\n");
596 i2400m_tx_close(i2400m);
597 i2400m_tx_new(i2400m);
598 }
599 if (i2400m->tx_msg == NULL)
600 goto error_tx_new;
601 /* So we have a current message header; now append space for
602 * the message -- if there is not enough, try the head */
603 ptr = i2400m_tx_fifo_push(i2400m, padded_len,
604 i2400m->bus_tx_block_size);
605 if (ptr == TAIL_FULL) { /* Tail is full, try head */
606 d_printf(2, dev, "pl append: tail full\n");
607 i2400m_tx_close(i2400m);
608 i2400m_tx_skip_tail(i2400m);
609 goto try_new;
610 } else if (ptr == NULL) { /* All full */
611 result = -ENOSPC;
612 d_printf(2, dev, "pl append: all full\n");
613 } else { /* Got space, copy it, set padding */
614 struct i2400m_msg_hdr *tx_msg = i2400m->tx_msg;
615 unsigned num_pls = le16_to_cpu(tx_msg->num_pls);
616 memcpy(ptr, buf, buf_len);
617 memset(ptr + buf_len, 0xad, padded_len - buf_len);
618 i2400m_pld_set(&tx_msg->pld[num_pls], buf_len, pl_type);
619 d_printf(3, dev, "pld 0x%08x (type 0x%1x len 0x%04zx\n",
620 le32_to_cpu(tx_msg->pld[num_pls].val),
621 pl_type, buf_len);
622 tx_msg->num_pls = le16_to_cpu(num_pls+1);
623 tx_msg->size += padded_len;
624 d_printf(2, dev, "TX: appended %zu b (up to %u b) pl #%u \n",
625 padded_len, tx_msg->size, num_pls+1);
626 d_printf(2, dev,
627 "TX: appended hdr @%zu %zu b pl #%u @%zu %zu/%zu b\n",
628 (void *)tx_msg - i2400m->tx_buf, (size_t)tx_msg->size,
629 num_pls+1, ptr - i2400m->tx_buf, buf_len, padded_len);
630 result = 0;
631 if (is_singleton)
632 i2400m_tx_close(i2400m);
633 }
634error_tx_new:
635 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
636 i2400m->bus_tx_kick(i2400m); /* always kick, might free up space */
637 d_fnend(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u) = %d\n",
638 i2400m, buf, buf_len, pl_type, result);
639 return result;
640}
641EXPORT_SYMBOL_GPL(i2400m_tx);
642
643
644/**
645 * i2400m_tx_msg_get - Get the first TX message in the FIFO to start sending it
646 *
647 * @i2400m: device descriptors
648 * @bus_size: where to place the size of the TX message
649 *
650 * Called by the bus-specific driver to get the first TX message at
651 * the FIF that is ready for transmission.
652 *
653 * It sets the state in @i2400m to indicate the bus-specific driver is
654 * transfering that message (i2400m->tx_msg_size).
655 *
656 * Once the transfer is completed, call i2400m_tx_msg_sent().
657 *
658 * Notes:
659 *
660 * The size of the TX message to be transmitted might be smaller than
661 * that of the TX message in the FIFO (in case the header was
662 * shorter). Hence, we copy it in @bus_size, for the bus layer to
663 * use. We keep the message's size in i2400m->tx_msg_size so that
664 * when the bus later is done transferring we know how much to
665 * advance the fifo.
666 *
667 * We collect statistics here as all the data is available and we
668 * assume it is going to work [see i2400m_tx_msg_sent()].
669 */
670struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *i2400m,
671 size_t *bus_size)
672{
673 struct device *dev = i2400m_dev(i2400m);
674 struct i2400m_msg_hdr *tx_msg, *tx_msg_moved;
675 unsigned long flags, pls;
676
677 d_fnstart(3, dev, "(i2400m %p bus_size %p)\n", i2400m, bus_size);
678 spin_lock_irqsave(&i2400m->tx_lock, flags);
679skip:
680 tx_msg_moved = NULL;
681 if (i2400m->tx_in == i2400m->tx_out) { /* Empty FIFO? */
682 i2400m->tx_in = 0;
683 i2400m->tx_out = 0;
684 d_printf(2, dev, "TX: FIFO empty: resetting\n");
685 goto out_unlock;
686 }
687 tx_msg = i2400m->tx_buf + i2400m->tx_out % I2400M_TX_BUF_SIZE;
688 if (tx_msg->size & I2400M_TX_SKIP) { /* skip? */
689 d_printf(2, dev, "TX: skip: msg @%zu (%zu b)\n",
690 i2400m->tx_out % I2400M_TX_BUF_SIZE,
691 (size_t) tx_msg->size & ~I2400M_TX_SKIP);
692 i2400m->tx_out += tx_msg->size & ~I2400M_TX_SKIP;
693 goto skip;
694 }
695
696 if (tx_msg->num_pls == 0) { /* No payloads? */
697 if (tx_msg == i2400m->tx_msg) { /* open, we are done */
698 d_printf(2, dev,
699 "TX: FIFO empty: open msg w/o payloads @%zu\n",
700 (void *) tx_msg - i2400m->tx_buf);
701 tx_msg = NULL;
702 goto out_unlock;
703 } else { /* closed, skip it */
704 d_printf(2, dev,
705 "TX: skip msg w/o payloads @%zu (%zu b)\n",
706 (void *) tx_msg - i2400m->tx_buf,
707 (size_t) tx_msg->size);
708 i2400m->tx_out += tx_msg->size & ~I2400M_TX_SKIP;
709 goto skip;
710 }
711 }
712 if (tx_msg == i2400m->tx_msg) /* open msg? */
713 i2400m_tx_close(i2400m);
714
715 /* Now we have a valid TX message (with payloads) to TX */
716 tx_msg_moved = (void *) tx_msg + tx_msg->offset;
717 i2400m->tx_msg_size = tx_msg->size;
718 *bus_size = tx_msg_moved->size;
719 d_printf(2, dev, "TX: pid %d msg hdr at @%zu offset +@%zu "
720 "size %zu bus_size %zu\n",
721 current->pid, (void *) tx_msg - i2400m->tx_buf,
722 (size_t) tx_msg->offset, (size_t) tx_msg->size,
723 (size_t) tx_msg_moved->size);
724 tx_msg_moved->barker = le32_to_cpu(I2400M_H2D_PREVIEW_BARKER);
725 tx_msg_moved->sequence = le32_to_cpu(i2400m->tx_sequence++);
726
727 pls = le32_to_cpu(tx_msg_moved->num_pls);
728 i2400m->tx_pl_num += pls; /* Update stats */
729 if (pls > i2400m->tx_pl_max)
730 i2400m->tx_pl_max = pls;
731 if (pls < i2400m->tx_pl_min)
732 i2400m->tx_pl_min = pls;
733 i2400m->tx_num++;
734 i2400m->tx_size_acc += *bus_size;
735 if (*bus_size < i2400m->tx_size_min)
736 i2400m->tx_size_min = *bus_size;
737 if (*bus_size > i2400m->tx_size_max)
738 i2400m->tx_size_max = *bus_size;
739out_unlock:
740 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
741 d_fnstart(3, dev, "(i2400m %p bus_size %p [%zu]) = %p\n",
742 i2400m, bus_size, *bus_size, tx_msg_moved);
743 return tx_msg_moved;
744}
745EXPORT_SYMBOL_GPL(i2400m_tx_msg_get);
746
747
748/**
749 * i2400m_tx_msg_sent - indicate the transmission of a TX message
750 *
751 * @i2400m: device descriptor
752 *
753 * Called by the bus-specific driver when a message has been sent;
754 * this pops it from the FIFO; and as there is space, start the queue
755 * in case it was stopped.
756 *
757 * Should be called even if the message send failed and we are
758 * dropping this TX message.
759 */
760void i2400m_tx_msg_sent(struct i2400m *i2400m)
761{
762 unsigned n;
763 unsigned long flags;
764 struct device *dev = i2400m_dev(i2400m);
765
766 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
767 spin_lock_irqsave(&i2400m->tx_lock, flags);
768 i2400m->tx_out += i2400m->tx_msg_size;
769 d_printf(2, dev, "TX: sent %zu b\n", (size_t) i2400m->tx_msg_size);
770 i2400m->tx_msg_size = 0;
771 BUG_ON(i2400m->tx_out > i2400m->tx_in);
772 /* level them FIFO markers off */
773 n = i2400m->tx_out / I2400M_TX_BUF_SIZE;
774 i2400m->tx_out %= I2400M_TX_BUF_SIZE;
775 i2400m->tx_in -= n * I2400M_TX_BUF_SIZE;
776 netif_start_queue(i2400m->wimax_dev.net_dev);
777 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
778 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
779}
780EXPORT_SYMBOL_GPL(i2400m_tx_msg_sent);
781
782
783/**
784 * i2400m_tx_setup - Initialize the TX queue and infrastructure
785 *
786 * Make sure we reset the TX sequence to zero, as when this function
787 * is called, the firmware has been just restarted.
788 */
789int i2400m_tx_setup(struct i2400m *i2400m)
790{
791 int result;
792
793 /* Do this here only once -- can't do on
794 * i2400m_hard_start_xmit() as we'll cause race conditions if
795 * the WS was scheduled on another CPU */
796 INIT_WORK(&i2400m->wake_tx_ws, i2400m_wake_tx_work);
797
798 i2400m->tx_sequence = 0;
799 i2400m->tx_buf = kmalloc(I2400M_TX_BUF_SIZE, GFP_KERNEL);
800 if (i2400m->tx_buf == NULL)
801 result = -ENOMEM;
802 else
803 result = 0;
804 /* Huh? the bus layer has to define this... */
805 BUG_ON(i2400m->bus_tx_block_size == 0);
806 return result;
807
808}
809
810
811/**
812 * i2400m_tx_release - Tear down the TX queue and infrastructure
813 */
814void i2400m_tx_release(struct i2400m *i2400m)
815{
816 kfree(i2400m->tx_buf);
817}
diff --git a/drivers/net/wimax/i2400m/usb-debug-levels.h b/drivers/net/wimax/i2400m/usb-debug-levels.h
new file mode 100644
index 000000000000..e4358bd880be
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-debug-levels.h
@@ -0,0 +1,42 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Debug levels control file for the i2400m-usb module
4 *
5 *
6 * Copyright (C) 2007-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#ifndef __debug_levels__h__
24#define __debug_levels__h__
25
26/* Maximum compile and run time debug level for all submodules */
27#define D_MODULENAME i2400m_usb
28#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL
29
30#include <linux/wimax/debug.h>
31
32/* List of all the enabled modules */
33enum d_module {
34 D_SUBMODULE_DECLARE(usb),
35 D_SUBMODULE_DECLARE(fw),
36 D_SUBMODULE_DECLARE(notif),
37 D_SUBMODULE_DECLARE(rx),
38 D_SUBMODULE_DECLARE(tx),
39};
40
41
42#endif /* #ifndef __debug_levels__h__ */
diff --git a/drivers/net/wimax/i2400m/usb-fw.c b/drivers/net/wimax/i2400m/usb-fw.c
new file mode 100644
index 000000000000..5ad287c228b8
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-fw.c
@@ -0,0 +1,340 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Firmware uploader's USB specifics
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
38 * - Initial implementation
39 *
40 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
41 * - bus generic/specific split
42 *
43 * THE PROCEDURE
44 *
45 * See fw.c for the generic description of this procedure.
46 *
47 * This file implements only the USB specifics. It boils down to how
48 * to send a command and waiting for an acknowledgement from the
49 * device.
50 *
51 * This code (and process) is single threaded. It assumes it is the
52 * only thread poking around (guaranteed by fw.c).
53 *
54 * COMMAND EXECUTION
55 *
56 * A write URB is posted with the buffer to the bulk output endpoint.
57 *
58 * ACK RECEPTION
59 *
60 * We just post a URB to the notification endpoint and wait for
61 * data. We repeat until we get all the data we expect (as indicated
62 * by the call from the bus generic code).
63 *
64 * The data is not read from the bulk in endpoint for boot mode.
65 *
66 * ROADMAP
67 *
68 * i2400mu_bus_bm_cmd_send
69 * i2400m_bm_cmd_prepare...
70 * i2400mu_tx_bulk_out
71 *
72 * i2400mu_bus_bm_wait_for_ack
73 * i2400m_notif_submit
74 */
75#include <linux/usb.h>
76#include "i2400m-usb.h"
77
78
79#define D_SUBMODULE fw
80#include "usb-debug-levels.h"
81
82
83/*
84 * Synchronous write to the device
85 *
86 * Takes care of updating EDC counts and thus, handle device errors.
87 */
88static
89ssize_t i2400mu_tx_bulk_out(struct i2400mu *i2400mu, void *buf, size_t buf_size)
90{
91 int result;
92 struct device *dev = &i2400mu->usb_iface->dev;
93 int len;
94 struct usb_endpoint_descriptor *epd;
95 int pipe, do_autopm = 1;
96
97 result = usb_autopm_get_interface(i2400mu->usb_iface);
98 if (result < 0) {
99 dev_err(dev, "BM-CMD: can't get autopm: %d\n", result);
100 do_autopm = 0;
101 }
102 epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_OUT);
103 pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
104retry:
105 result = usb_bulk_msg(i2400mu->usb_dev, pipe, buf, buf_size, &len, HZ);
106 switch (result) {
107 case 0:
108 if (len != buf_size) {
109 dev_err(dev, "BM-CMD: short write (%u B vs %zu "
110 "expected)\n", len, buf_size);
111 result = -EIO;
112 break;
113 }
114 result = len;
115 break;
116 case -EINVAL: /* while removing driver */
117 case -ENODEV: /* dev disconnect ... */
118 case -ENOENT: /* just ignore it */
119 case -ESHUTDOWN: /* and exit */
120 case -ECONNRESET:
121 result = -ESHUTDOWN;
122 break;
123 case -ETIMEDOUT: /* bah... */
124 break;
125 default: /* any other? */
126 if (edc_inc(&i2400mu->urb_edc,
127 EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
128 dev_err(dev, "BM-CMD: maximum errors in "
129 "URB exceeded; resetting device\n");
130 usb_queue_reset_device(i2400mu->usb_iface);
131 result = -ENODEV;
132 break;
133 }
134 dev_err(dev, "BM-CMD: URB error %d, retrying\n",
135 result);
136 goto retry;
137 }
138 result = len;
139 if (do_autopm)
140 usb_autopm_put_interface(i2400mu->usb_iface);
141 return result;
142}
143
144
145/*
146 * Send a boot-mode command over the bulk-out pipe
147 *
148 * Command can be a raw command, which requires no preparation (and
149 * which might not even be following the command format). Checks that
150 * the right amount of data was transfered.
151 *
152 * To satisfy USB requirements (no onstack, vmalloc or in data segment
153 * buffers), we copy the command to i2400m->bm_cmd_buf and send it from
154 * there.
155 *
156 * @flags: pass thru from i2400m_bm_cmd()
157 * @return: cmd_size if ok, < 0 errno code on error.
158 */
159ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *i2400m,
160 const struct i2400m_bootrom_header *_cmd,
161 size_t cmd_size, int flags)
162{
163 ssize_t result;
164 struct device *dev = i2400m_dev(i2400m);
165 struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
166 int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd);
167 struct i2400m_bootrom_header *cmd;
168 size_t cmd_size_a = ALIGN(cmd_size, 16); /* USB restriction */
169
170 d_fnstart(8, dev, "(i2400m %p cmd %p size %zu)\n",
171 i2400m, _cmd, cmd_size);
172 result = -E2BIG;
173 if (cmd_size > I2400M_BM_CMD_BUF_SIZE)
174 goto error_too_big;
175 memcpy(i2400m->bm_cmd_buf, _cmd, cmd_size);
176 cmd = i2400m->bm_cmd_buf;
177 if (cmd_size_a > cmd_size) /* Zero pad space */
178 memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size);
179 if ((flags & I2400M_BM_CMD_RAW) == 0) {
180 if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0))
181 dev_warn(dev, "SW BUG: response_required == 0\n");
182 i2400m_bm_cmd_prepare(cmd);
183 }
184 result = i2400mu_tx_bulk_out(i2400mu, i2400m->bm_cmd_buf, cmd_size);
185 if (result < 0) {
186 dev_err(dev, "boot-mode cmd %d: cannot send: %zd\n",
187 opcode, result);
188 goto error_cmd_send;
189 }
190 if (result != cmd_size) { /* all was transferred? */
191 dev_err(dev, "boot-mode cmd %d: incomplete transfer "
192 "(%zu vs %zu submitted)\n", opcode, result, cmd_size);
193 result = -EIO;
194 goto error_cmd_size;
195 }
196error_cmd_size:
197error_cmd_send:
198error_too_big:
199 d_fnend(8, dev, "(i2400m %p cmd %p size %zu) = %zd\n",
200 i2400m, _cmd, cmd_size, result);
201 return result;
202}
203
204
205static
206void __i2400mu_bm_notif_cb(struct urb *urb)
207{
208 complete(urb->context);
209}
210
211
212/*
213 * submit a read to the notification endpoint
214 *
215 * @i2400m: device descriptor
216 * @urb: urb to use
217 * @completion: completion varible to complete when done
218 *
219 * Data is always read to i2400m->bm_ack_buf
220 */
221static
222int i2400mu_notif_submit(struct i2400mu *i2400mu, struct urb *urb,
223 struct completion *completion)
224{
225 struct i2400m *i2400m = &i2400mu->i2400m;
226 struct usb_endpoint_descriptor *epd;
227 int pipe;
228
229 epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_NOTIFICATION);
230 pipe = usb_rcvintpipe(i2400mu->usb_dev, epd->bEndpointAddress);
231 usb_fill_int_urb(urb, i2400mu->usb_dev, pipe,
232 i2400m->bm_ack_buf, I2400M_BM_ACK_BUF_SIZE,
233 __i2400mu_bm_notif_cb, completion,
234 epd->bInterval);
235 return usb_submit_urb(urb, GFP_KERNEL);
236}
237
238
239/*
240 * Read an ack from the notification endpoint
241 *
242 * @i2400m:
243 * @_ack: pointer to where to store the read data
244 * @ack_size: how many bytes we should read
245 *
246 * Returns: < 0 errno code on error; otherwise, amount of received bytes.
247 *
248 * Submits a notification read, appends the read data to the given ack
249 * buffer and then repeats (until @ack_size bytes have been
250 * received).
251 */
252ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *i2400m,
253 struct i2400m_bootrom_header *_ack,
254 size_t ack_size)
255{
256 ssize_t result = -ENOMEM;
257 struct device *dev = i2400m_dev(i2400m);
258 struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
259 struct urb notif_urb;
260 void *ack = _ack;
261 size_t offset, len;
262 long val;
263 int do_autopm = 1;
264 DECLARE_COMPLETION_ONSTACK(notif_completion);
265
266 d_fnstart(8, dev, "(i2400m %p ack %p size %zu)\n",
267 i2400m, ack, ack_size);
268 BUG_ON(_ack == i2400m->bm_ack_buf);
269 result = usb_autopm_get_interface(i2400mu->usb_iface);
270 if (result < 0) {
271 dev_err(dev, "BM-ACK: can't get autopm: %d\n", (int) result);
272 do_autopm = 0;
273 }
274 usb_init_urb(&notif_urb); /* ready notifications */
275 usb_get_urb(&notif_urb);
276 offset = 0;
277 while (offset < ack_size) {
278 init_completion(&notif_completion);
279 result = i2400mu_notif_submit(i2400mu, &notif_urb,
280 &notif_completion);
281 if (result < 0)
282 goto error_notif_urb_submit;
283 val = wait_for_completion_interruptible_timeout(
284 &notif_completion, HZ);
285 if (val == 0) {
286 result = -ETIMEDOUT;
287 usb_kill_urb(&notif_urb); /* Timedout */
288 goto error_notif_wait;
289 }
290 if (val == -ERESTARTSYS) {
291 result = -EINTR; /* Interrupted */
292 usb_kill_urb(&notif_urb);
293 goto error_notif_wait;
294 }
295 result = notif_urb.status; /* How was the ack? */
296 switch (result) {
297 case 0:
298 break;
299 case -EINVAL: /* while removing driver */
300 case -ENODEV: /* dev disconnect ... */
301 case -ENOENT: /* just ignore it */
302 case -ESHUTDOWN: /* and exit */
303 case -ECONNRESET:
304 result = -ESHUTDOWN;
305 goto error_dev_gone;
306 default: /* any other? */
307 usb_kill_urb(&notif_urb); /* Timedout */
308 if (edc_inc(&i2400mu->urb_edc,
309 EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME))
310 goto error_exceeded;
311 dev_err(dev, "BM-ACK: URB error %d, "
312 "retrying\n", notif_urb.status);
313 continue; /* retry */
314 }
315 if (notif_urb.actual_length == 0) {
316 d_printf(6, dev, "ZLP received, retrying\n");
317 continue;
318 }
319 /* Got data, append it to the buffer */
320 len = min(ack_size - offset, (size_t) notif_urb.actual_length);
321 memcpy(ack + offset, i2400m->bm_ack_buf, len);
322 offset += len;
323 }
324 result = offset;
325error_notif_urb_submit:
326error_notif_wait:
327error_dev_gone:
328out:
329 if (do_autopm)
330 usb_autopm_put_interface(i2400mu->usb_iface);
331 d_fnend(8, dev, "(i2400m %p ack %p size %zu) = %zd\n",
332 i2400m, ack, ack_size, result);
333 return result;
334
335error_exceeded:
336 dev_err(dev, "bm: maximum errors in notification URB exceeded; "
337 "resetting device\n");
338 usb_queue_reset_device(i2400mu->usb_iface);
339 goto out;
340}
diff --git a/drivers/net/wimax/i2400m/usb-notif.c b/drivers/net/wimax/i2400m/usb-notif.c
new file mode 100644
index 000000000000..9702c22b2497
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-notif.c
@@ -0,0 +1,269 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m over USB
3 * Notification handling
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
38 * - Initial implementation
39 *
40 *
41 * The notification endpoint is active when the device is not in boot
42 * mode; in here we just read and get notifications; based on those,
43 * we act to either reinitialize the device after a reboot or to
44 * submit a RX request.
45 *
46 * ROADMAP
47 *
48 * i2400mu_usb_notification_setup()
49 *
50 * i2400mu_usb_notification_release()
51 *
52 * i2400mu_usb_notification_cb() Called when a URB is ready
53 * i2400mu_notif_grok()
54 * i2400m_dev_reset_handle()
55 * i2400mu_rx_kick()
56 */
57#include <linux/usb.h>
58#include "i2400m-usb.h"
59
60
61#define D_SUBMODULE notif
62#include "usb-debug-levels.h"
63
64
65static const
66__le32 i2400m_ZERO_BARKER[4] = { 0, 0, 0, 0 };
67
68
69/*
70 * Process a received notification
71 *
72 * In normal operation mode, we can only receive two types of payloads
73 * on the notification endpoint:
74 *
75 * - a reboot barker, we do a bootstrap (the device has reseted).
76 *
77 * - a block of zeroes: there is pending data in the IN endpoint
78 */
79static
80int i2400mu_notification_grok(struct i2400mu *i2400mu, const void *buf,
81 size_t buf_len)
82{
83 int ret;
84 struct device *dev = &i2400mu->usb_iface->dev;
85 struct i2400m *i2400m = &i2400mu->i2400m;
86
87 d_fnstart(4, dev, "(i2400m %p buf %p buf_len %zu)\n",
88 i2400mu, buf, buf_len);
89 ret = -EIO;
90 if (buf_len < sizeof(i2400m_NBOOT_BARKER))
91 /* Not a bug, just ignore */
92 goto error_bad_size;
93 if (!memcmp(i2400m_NBOOT_BARKER, buf, sizeof(i2400m_NBOOT_BARKER))
94 || !memcmp(i2400m_SBOOT_BARKER, buf, sizeof(i2400m_SBOOT_BARKER)))
95 ret = i2400m_dev_reset_handle(i2400m);
96 else if (!memcmp(i2400m_ZERO_BARKER, buf, sizeof(i2400m_ZERO_BARKER))) {
97 i2400mu_rx_kick(i2400mu);
98 ret = 0;
99 } else { /* Unknown or unexpected data in the notif message */
100 char prefix[64];
101 ret = -EIO;
102 dev_err(dev, "HW BUG? Unknown/unexpected data in notification "
103 "message (%zu bytes)\n", buf_len);
104 snprintf(prefix, sizeof(prefix), "%s %s: ",
105 dev_driver_string(dev) , dev->bus_id);
106 if (buf_len > 64) {
107 print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
108 8, 4, buf, 64, 0);
109 printk(KERN_ERR "%s... (only first 64 bytes "
110 "dumped)\n", prefix);
111 } else
112 print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
113 8, 4, buf, buf_len, 0);
114 }
115error_bad_size:
116 d_fnend(4, dev, "(i2400m %p buf %p buf_len %zu) = %d\n",
117 i2400mu, buf, buf_len, ret);
118 return ret;
119}
120
121
122/*
123 * URB callback for the notification endpoint
124 *
125 * @urb: the urb received from the notification endpoint
126 *
127 * This function will just process the USB side of the transaction,
128 * checking everything is fine, pass the processing to
129 * i2400m_notification_grok() and resubmit the URB.
130 */
131static
132void i2400mu_notification_cb(struct urb *urb)
133{
134 int ret;
135 struct i2400mu *i2400mu = urb->context;
136 struct device *dev = &i2400mu->usb_iface->dev;
137
138 d_fnstart(4, dev, "(urb %p status %d actual_length %d)\n",
139 urb, urb->status, urb->actual_length);
140 ret = urb->status;
141 switch (ret) {
142 case 0:
143 ret = i2400mu_notification_grok(i2400mu, urb->transfer_buffer,
144 urb->actual_length);
145 if (ret == -EIO && edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS,
146 EDC_ERROR_TIMEFRAME))
147 goto error_exceeded;
148 if (ret == -ENOMEM) /* uff...power cycle? shutdown? */
149 goto error_exceeded;
150 break;
151 case -EINVAL: /* while removing driver */
152 case -ENODEV: /* dev disconnect ... */
153 case -ENOENT: /* ditto */
154 case -ESHUTDOWN: /* URB killed */
155 case -ECONNRESET: /* disconnection */
156 goto out; /* Notify around */
157 default: /* Some error? */
158 if (edc_inc(&i2400mu->urb_edc,
159 EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME))
160 goto error_exceeded;
161 dev_err(dev, "notification: URB error %d, retrying\n",
162 urb->status);
163 }
164 usb_mark_last_busy(i2400mu->usb_dev);
165 ret = usb_submit_urb(i2400mu->notif_urb, GFP_ATOMIC);
166 switch (ret) {
167 case 0:
168 case -EINVAL: /* while removing driver */
169 case -ENODEV: /* dev disconnect ... */
170 case -ENOENT: /* ditto */
171 case -ESHUTDOWN: /* URB killed */
172 case -ECONNRESET: /* disconnection */
173 break; /* just ignore */
174 default: /* Some error? */
175 dev_err(dev, "notification: cannot submit URB: %d\n", ret);
176 goto error_submit;
177 }
178 d_fnend(4, dev, "(urb %p status %d actual_length %d) = void\n",
179 urb, urb->status, urb->actual_length);
180 return;
181
182error_exceeded:
183 dev_err(dev, "maximum errors in notification URB exceeded; "
184 "resetting device\n");
185error_submit:
186 usb_queue_reset_device(i2400mu->usb_iface);
187out:
188 d_fnend(4, dev, "(urb %p status %d actual_length %d) = void\n",
189 urb, urb->status, urb->actual_length);
190 return;
191}
192
193
194/*
195 * setup the notification endpoint
196 *
197 * @i2400m: device descriptor
198 *
199 * This procedure prepares the notification urb and handler for receiving
200 * unsolicited barkers from the device.
201 */
202int i2400mu_notification_setup(struct i2400mu *i2400mu)
203{
204 struct device *dev = &i2400mu->usb_iface->dev;
205 int usb_pipe, ret = 0;
206 struct usb_endpoint_descriptor *epd;
207 char *buf;
208
209 d_fnstart(4, dev, "(i2400m %p)\n", i2400mu);
210 buf = kmalloc(I2400MU_MAX_NOTIFICATION_LEN, GFP_KERNEL | GFP_DMA);
211 if (buf == NULL) {
212 dev_err(dev, "notification: buffer allocation failed\n");
213 ret = -ENOMEM;
214 goto error_buf_alloc;
215 }
216
217 i2400mu->notif_urb = usb_alloc_urb(0, GFP_KERNEL);
218 if (!i2400mu->notif_urb) {
219 ret = -ENOMEM;
220 dev_err(dev, "notification: cannot allocate URB\n");
221 goto error_alloc_urb;
222 }
223 epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_NOTIFICATION);
224 usb_pipe = usb_rcvintpipe(i2400mu->usb_dev, epd->bEndpointAddress);
225 usb_fill_int_urb(i2400mu->notif_urb, i2400mu->usb_dev, usb_pipe,
226 buf, I2400MU_MAX_NOTIFICATION_LEN,
227 i2400mu_notification_cb, i2400mu, epd->bInterval);
228 ret = usb_submit_urb(i2400mu->notif_urb, GFP_KERNEL);
229 if (ret != 0) {
230 dev_err(dev, "notification: cannot submit URB: %d\n", ret);
231 goto error_submit;
232 }
233 d_fnend(4, dev, "(i2400m %p) = %d\n", i2400mu, ret);
234 return ret;
235
236error_submit:
237 usb_free_urb(i2400mu->notif_urb);
238error_alloc_urb:
239 kfree(buf);
240error_buf_alloc:
241 d_fnend(4, dev, "(i2400m %p) = %d\n", i2400mu, ret);
242 return ret;
243}
244
245
246/*
247 * Tear down of the notification mechanism
248 *
249 * @i2400m: device descriptor
250 *
251 * Kill the interrupt endpoint urb, free any allocated resources.
252 *
253 * We need to check if we have done it before as for example,
254 * _suspend() call this; if after a suspend() we get a _disconnect()
255 * (as the case is when hibernating), nothing bad happens.
256 */
257void i2400mu_notification_release(struct i2400mu *i2400mu)
258{
259 struct device *dev = &i2400mu->usb_iface->dev;
260
261 d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
262 if (i2400mu->notif_urb != NULL) {
263 usb_kill_urb(i2400mu->notif_urb);
264 kfree(i2400mu->notif_urb->transfer_buffer);
265 usb_free_urb(i2400mu->notif_urb);
266 i2400mu->notif_urb = NULL;
267 }
268 d_fnend(4, dev, "(i2400mu %p)\n", i2400mu);
269}
diff --git a/drivers/net/wimax/i2400m/usb-rx.c b/drivers/net/wimax/i2400m/usb-rx.c
new file mode 100644
index 000000000000..074cc1f89853
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-rx.c
@@ -0,0 +1,417 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * USB RX handling
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37 * - Initial implementation
38 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
39 * - Use skb_clone(), break up processing in chunks
40 * - Split transport/device specific
41 * - Make buffer size dynamic to exert less memory pressure
42 *
43 *
44 * This handles the RX path on USB.
45 *
46 * When a notification is received that says 'there is RX data ready',
47 * we call i2400mu_rx_kick(); that wakes up the RX kthread, which
48 * reads a buffer from USB and passes it to i2400m_rx() in the generic
49 * handling code. The RX buffer has an specific format that is
50 * described in rx.c.
51 *
52 * We use a kernel thread in a loop because:
53 *
54 * - we want to be able to call the USB power management get/put
55 * functions (blocking) before each transaction.
56 *
57 * - We might get a lot of notifications and we don't want to submit
58 * a zillion reads; by serializing, we are throttling.
59 *
60 * - RX data processing can get heavy enough so that it is not
61 * appropiate for doing it in the USB callback; thus we run it in a
62 * process context.
63 *
64 * We provide a read buffer of an arbitrary size (short of a page); if
65 * the callback reports -EOVERFLOW, it means it was too small, so we
66 * just double the size and retry (being careful to append, as
67 * sometimes the device provided some data). Every now and then we
68 * check if the average packet size is smaller than the current packet
69 * size and if so, we halve it. At the end, the size of the
70 * preallocated buffer should be following the average received
71 * transaction size, adapting dynamically to it.
72 *
73 * ROADMAP
74 *
75 * i2400mu_rx_kick() Called from notif.c when we get a
76 * 'data ready' notification
77 * i2400mu_rxd() Kernel RX daemon
78 * i2400mu_rx() Receive USB data
79 * i2400m_rx() Send data to generic i2400m RX handling
80 *
81 * i2400mu_rx_setup() called from i2400mu_bus_dev_start()
82 *
83 * i2400mu_rx_release() called from i2400mu_bus_dev_stop()
84 */
85#include <linux/workqueue.h>
86#include <linux/usb.h>
87#include "i2400m-usb.h"
88
89
90#define D_SUBMODULE rx
91#include "usb-debug-levels.h"
92
93/*
94 * Dynamic RX size
95 *
96 * We can't let the rx_size be a multiple of 512 bytes (the RX
97 * endpoint's max packet size). On some USB host controllers (we
98 * haven't been able to fully characterize which), if the device is
99 * about to send (for example) X bytes and we only post a buffer to
100 * receive n*512, it will fail to mark that as babble (so that
101 * i2400mu_rx() [case -EOVERFLOW] can resize the buffer and get the
102 * rest).
103 *
104 * So on growing or shrinking, if it is a multiple of the
105 * maxpacketsize, we remove some (instead of incresing some, so in a
106 * buddy allocator we try to waste less space).
107 *
108 * Note we also need a hook for this on i2400mu_rx() -- when we do the
109 * first read, we are sure we won't hit this spot because
110 * i240mm->rx_size has been set properly. However, if we have to
111 * double because of -EOVERFLOW, when we launch the read to get the
112 * rest of the data, we *have* to make sure that also is not a
113 * multiple of the max_pkt_size.
114 */
115
116static
117size_t i2400mu_rx_size_grow(struct i2400mu *i2400mu)
118{
119 struct device *dev = &i2400mu->usb_iface->dev;
120 size_t rx_size;
121 const size_t max_pkt_size = 512;
122
123 rx_size = 2 * i2400mu->rx_size;
124 if (rx_size % max_pkt_size == 0) {
125 rx_size -= 8;
126 d_printf(1, dev,
127 "RX: expected size grew to %zu [adjusted -8] "
128 "from %zu\n",
129 rx_size, i2400mu->rx_size);
130 } else
131 d_printf(1, dev,
132 "RX: expected size grew to %zu from %zu\n",
133 rx_size, i2400mu->rx_size);
134 return rx_size;
135}
136
137
138static
139void i2400mu_rx_size_maybe_shrink(struct i2400mu *i2400mu)
140{
141 const size_t max_pkt_size = 512;
142 struct device *dev = &i2400mu->usb_iface->dev;
143
144 if (unlikely(i2400mu->rx_size_cnt >= 100
145 && i2400mu->rx_size_auto_shrink)) {
146 size_t avg_rx_size =
147 i2400mu->rx_size_acc / i2400mu->rx_size_cnt;
148 size_t new_rx_size = i2400mu->rx_size / 2;
149 if (avg_rx_size < new_rx_size) {
150 if (new_rx_size % max_pkt_size == 0) {
151 new_rx_size -= 8;
152 d_printf(1, dev,
153 "RX: expected size shrank to %zu "
154 "[adjusted -8] from %zu\n",
155 new_rx_size, i2400mu->rx_size);
156 } else
157 d_printf(1, dev,
158 "RX: expected size shrank to %zu "
159 "from %zu\n",
160 new_rx_size, i2400mu->rx_size);
161 i2400mu->rx_size = new_rx_size;
162 i2400mu->rx_size_cnt = 0;
163 i2400mu->rx_size_acc = i2400mu->rx_size;
164 }
165 }
166}
167
168/*
169 * Receive a message with payloads from the USB bus into an skb
170 *
171 * @i2400mu: USB device descriptor
172 * @rx_skb: skb where to place the received message
173 *
174 * Deals with all the USB-specifics of receiving, dynamically
175 * increasing the buffer size if so needed. Returns the payload in the
176 * skb, ready to process. On a zero-length packet, we retry.
177 *
178 * On soft USB errors, we retry (until they become too frequent and
179 * then are promoted to hard); on hard USB errors, we reset the
180 * device. On other errors (skb realloacation, we just drop it and
181 * hope for the next invocation to solve it).
182 *
183 * Returns: pointer to the skb if ok, ERR_PTR on error.
184 * NOTE: this function might realloc the skb (if it is too small),
185 * so always update with the one returned.
186 * ERR_PTR() is < 0 on error.
187 */
188static
189struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb)
190{
191 int result = 0;
192 struct device *dev = &i2400mu->usb_iface->dev;
193 int usb_pipe, read_size, rx_size, do_autopm;
194 struct usb_endpoint_descriptor *epd;
195 const size_t max_pkt_size = 512;
196
197 d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
198 do_autopm = atomic_read(&i2400mu->do_autopm);
199 result = do_autopm ?
200 usb_autopm_get_interface(i2400mu->usb_iface) : 0;
201 if (result < 0) {
202 dev_err(dev, "RX: can't get autopm: %d\n", result);
203 do_autopm = 0;
204 }
205 epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_IN);
206 usb_pipe = usb_rcvbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
207retry:
208 rx_size = skb_end_pointer(rx_skb) - rx_skb->data - rx_skb->len;
209 if (unlikely(rx_size % max_pkt_size == 0)) {
210 rx_size -= 8;
211 d_printf(1, dev, "RX: rx_size adapted to %d [-8]\n", rx_size);
212 }
213 result = usb_bulk_msg(
214 i2400mu->usb_dev, usb_pipe, rx_skb->data + rx_skb->len,
215 rx_size, &read_size, HZ);
216 usb_mark_last_busy(i2400mu->usb_dev);
217 switch (result) {
218 case 0:
219 if (read_size == 0)
220 goto retry; /* ZLP, just resubmit */
221 skb_put(rx_skb, read_size);
222 break;
223 case -EINVAL: /* while removing driver */
224 case -ENODEV: /* dev disconnect ... */
225 case -ENOENT: /* just ignore it */
226 case -ESHUTDOWN:
227 case -ECONNRESET:
228 break;
229 case -EOVERFLOW: { /* too small, reallocate */
230 struct sk_buff *new_skb;
231 rx_size = i2400mu_rx_size_grow(i2400mu);
232 if (rx_size <= (1 << 16)) /* cap it */
233 i2400mu->rx_size = rx_size;
234 else if (printk_ratelimit()) {
235 dev_err(dev, "BUG? rx_size up to %d\n", rx_size);
236 result = -EINVAL;
237 goto out;
238 }
239 skb_put(rx_skb, read_size);
240 new_skb = skb_copy_expand(rx_skb, 0, rx_size - rx_skb->len,
241 GFP_KERNEL);
242 if (new_skb == NULL) {
243 if (printk_ratelimit())
244 dev_err(dev, "RX: Can't reallocate skb to %d; "
245 "RX dropped\n", rx_size);
246 kfree(rx_skb);
247 result = 0;
248 goto out; /* drop it...*/
249 }
250 kfree_skb(rx_skb);
251 rx_skb = new_skb;
252 i2400mu->rx_size_cnt = 0;
253 i2400mu->rx_size_acc = i2400mu->rx_size;
254 d_printf(1, dev, "RX: size changed to %d, received %d, "
255 "copied %d, capacity %ld\n",
256 rx_size, read_size, rx_skb->len,
257 (long) (skb_end_pointer(new_skb) - new_skb->head));
258 goto retry;
259 }
260 /* In most cases, it happens due to the hardware scheduling a
261 * read when there was no data - unfortunately, we have no way
262 * to tell this timeout from a USB timeout. So we just ignore
263 * it. */
264 case -ETIMEDOUT:
265 dev_err(dev, "RX: timeout: %d\n", result);
266 result = 0;
267 break;
268 default: /* Any error */
269 if (edc_inc(&i2400mu->urb_edc,
270 EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME))
271 goto error_reset;
272 dev_err(dev, "RX: error receiving URB: %d, retrying\n", result);
273 goto retry;
274 }
275out:
276 if (do_autopm)
277 usb_autopm_put_interface(i2400mu->usb_iface);
278 d_fnend(4, dev, "(i2400mu %p) = %p\n", i2400mu, rx_skb);
279 return rx_skb;
280
281error_reset:
282 dev_err(dev, "RX: maximum errors in URB exceeded; "
283 "resetting device\n");
284 usb_queue_reset_device(i2400mu->usb_iface);
285 rx_skb = ERR_PTR(result);
286 goto out;
287}
288
289
290/*
291 * Kernel thread for USB reception of data
292 *
293 * This thread waits for a kick; once kicked, it will allocate an skb
294 * and receive a single message to it from USB (using
295 * i2400mu_rx()). Once received, it is passed to the generic i2400m RX
296 * code for processing.
297 *
298 * When done processing, it runs some dirty statistics to verify if
299 * the last 100 messages received were smaller than half of the
300 * current RX buffer size. In that case, the RX buffer size is
301 * halved. This will helps lowering the pressure on the memory
302 * allocator.
303 *
304 * Hard errors force the thread to exit.
305 */
306static
307int i2400mu_rxd(void *_i2400mu)
308{
309 int result = 0;
310 struct i2400mu *i2400mu = _i2400mu;
311 struct i2400m *i2400m = &i2400mu->i2400m;
312 struct device *dev = &i2400mu->usb_iface->dev;
313 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
314 size_t pending;
315 int rx_size;
316 struct sk_buff *rx_skb;
317
318 d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
319 while (1) {
320 d_printf(2, dev, "TX: waiting for messages\n");
321 pending = 0;
322 wait_event_interruptible(
323 i2400mu->rx_wq,
324 (kthread_should_stop() /* check this first! */
325 || (pending = atomic_read(&i2400mu->rx_pending_count)))
326 );
327 if (kthread_should_stop())
328 break;
329 if (pending == 0)
330 continue;
331 rx_size = i2400mu->rx_size;
332 d_printf(2, dev, "RX: reading up to %d bytes\n", rx_size);
333 rx_skb = __netdev_alloc_skb(net_dev, rx_size, GFP_KERNEL);
334 if (rx_skb == NULL) {
335 dev_err(dev, "RX: can't allocate skb [%d bytes]\n",
336 rx_size);
337 msleep(50); /* give it some time? */
338 continue;
339 }
340
341 /* Receive the message with the payloads */
342 rx_skb = i2400mu_rx(i2400mu, rx_skb);
343 result = PTR_ERR(rx_skb);
344 if (IS_ERR(rx_skb))
345 goto out;
346 atomic_dec(&i2400mu->rx_pending_count);
347 if (rx_skb->len == 0) { /* some ignorable condition */
348 kfree_skb(rx_skb);
349 continue;
350 }
351
352 /* Deliver the message to the generic i2400m code */
353 i2400mu->rx_size_cnt++;
354 i2400mu->rx_size_acc += rx_skb->len;
355 result = i2400m_rx(i2400m, rx_skb);
356 if (result == -EIO
357 && edc_inc(&i2400mu->urb_edc,
358 EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
359 goto error_reset;
360 }
361
362 /* Maybe adjust RX buffer size */
363 i2400mu_rx_size_maybe_shrink(i2400mu);
364 }
365 result = 0;
366out:
367 d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result);
368 return result;
369
370error_reset:
371 dev_err(dev, "RX: maximum errors in received buffer exceeded; "
372 "resetting device\n");
373 usb_queue_reset_device(i2400mu->usb_iface);
374 goto out;
375}
376
377
378/*
379 * Start reading from the device
380 *
381 * @i2400m: device instance
382 *
383 * Notify the RX thread that there is data pending.
384 */
385void i2400mu_rx_kick(struct i2400mu *i2400mu)
386{
387 struct i2400m *i2400m = &i2400mu->i2400m;
388 struct device *dev = &i2400mu->usb_iface->dev;
389
390 d_fnstart(3, dev, "(i2400mu %p)\n", i2400m);
391 atomic_inc(&i2400mu->rx_pending_count);
392 wake_up_all(&i2400mu->rx_wq);
393 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
394}
395
396
397int i2400mu_rx_setup(struct i2400mu *i2400mu)
398{
399 int result = 0;
400 struct i2400m *i2400m = &i2400mu->i2400m;
401 struct device *dev = &i2400mu->usb_iface->dev;
402 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
403
404 i2400mu->rx_kthread = kthread_run(i2400mu_rxd, i2400mu, "%s-rx",
405 wimax_dev->name);
406 if (IS_ERR(i2400mu->rx_kthread)) {
407 result = PTR_ERR(i2400mu->rx_kthread);
408 dev_err(dev, "RX: cannot start thread: %d\n", result);
409 }
410 return result;
411}
412
413void i2400mu_rx_release(struct i2400mu *i2400mu)
414{
415 kthread_stop(i2400mu->rx_kthread);
416}
417
diff --git a/drivers/net/wimax/i2400m/usb-tx.c b/drivers/net/wimax/i2400m/usb-tx.c
new file mode 100644
index 000000000000..dfd893356f49
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-tx.c
@@ -0,0 +1,229 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * USB specific TX handling
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37 * - Initial implementation
38 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
39 * - Split transport/device specific
40 *
41 *
42 * Takes the TX messages in the i2400m's driver TX FIFO and sends them
43 * to the device until there are no more.
44 *
45 * If we fail sending the message, we just drop it. There isn't much
46 * we can do at this point. We could also retry, but the USB stack has
47 * already retried and still failed, so there is not much of a
48 * point. As well, most of the traffic is network, which has recovery
49 * methods for dropped packets.
50 *
51 * For sending we just obtain a FIFO buffer to send, send it to the
52 * USB bulk out, tell the TX FIFO code we have sent it; query for
53 * another one, etc... until done.
54 *
55 * We use a thread so we can call usb_autopm_enable() and
56 * usb_autopm_disable() for each transaction; this way when the device
57 * goes idle, it will suspend. It also has less overhead than a
58 * dedicated workqueue, as it is being used for a single task.
59 *
60 * ROADMAP
61 *
62 * i2400mu_tx_setup()
63 * i2400mu_tx_release()
64 *
65 * i2400mu_bus_tx_kick() - Called by the tx.c code when there
66 * is new data in the FIFO.
67 * i2400mu_txd()
68 * i2400m_tx_msg_get()
69 * i2400m_tx_msg_sent()
70 */
71#include "i2400m-usb.h"
72
73
74#define D_SUBMODULE tx
75#include "usb-debug-levels.h"
76
77
78/*
79 * Get the next TX message in the TX FIFO and send it to the device
80 *
81 * Note that any iteration consumes a message to be sent, no matter if
82 * it succeeds or fails (we have no real way to retry or complain).
83 *
84 * Return: 0 if ok, < 0 errno code on hard error.
85 */
86static
87int i2400mu_tx(struct i2400mu *i2400mu, struct i2400m_msg_hdr *tx_msg,
88 size_t tx_msg_size)
89{
90 int result = 0;
91 struct i2400m *i2400m = &i2400mu->i2400m;
92 struct device *dev = &i2400mu->usb_iface->dev;
93 int usb_pipe, sent_size, do_autopm;
94 struct usb_endpoint_descriptor *epd;
95
96 d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
97 do_autopm = atomic_read(&i2400mu->do_autopm);
98 result = do_autopm ?
99 usb_autopm_get_interface(i2400mu->usb_iface) : 0;
100 if (result < 0) {
101 dev_err(dev, "TX: can't get autopm: %d\n", result);
102 do_autopm = 0;
103 }
104 epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_OUT);
105 usb_pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
106retry:
107 result = usb_bulk_msg(i2400mu->usb_dev, usb_pipe,
108 tx_msg, tx_msg_size, &sent_size, HZ);
109 usb_mark_last_busy(i2400mu->usb_dev);
110 switch (result) {
111 case 0:
112 if (sent_size != tx_msg_size) { /* Too short? drop it */
113 dev_err(dev, "TX: short write (%d B vs %zu "
114 "expected)\n", sent_size, tx_msg_size);
115 result = -EIO;
116 }
117 break;
118 case -EINVAL: /* while removing driver */
119 case -ENODEV: /* dev disconnect ... */
120 case -ENOENT: /* just ignore it */
121 case -ESHUTDOWN: /* and exit */
122 case -ECONNRESET:
123 result = -ESHUTDOWN;
124 break;
125 default: /* Some error? */
126 if (edc_inc(&i2400mu->urb_edc,
127 EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
128 dev_err(dev, "TX: maximum errors in URB "
129 "exceeded; resetting device\n");
130 usb_queue_reset_device(i2400mu->usb_iface);
131 } else {
132 dev_err(dev, "TX: cannot send URB; retrying. "
133 "tx_msg @%zu %zu B [%d sent]: %d\n",
134 (void *) tx_msg - i2400m->tx_buf,
135 tx_msg_size, sent_size, result);
136 goto retry;
137 }
138 }
139 if (do_autopm)
140 usb_autopm_put_interface(i2400mu->usb_iface);
141 d_fnend(4, dev, "(i2400mu %p) = result\n", i2400mu);
142 return result;
143}
144
145
146/*
147 * Get the next TX message in the TX FIFO and send it to the device
148 *
149 * Note we exit the loop if i2400mu_tx() fails; that funtion only
150 * fails on hard error (failing to tx a buffer not being one of them,
151 * see its doc).
152 *
153 * Return: 0
154 */
155static
156int i2400mu_txd(void *_i2400mu)
157{
158 int result = 0;
159 struct i2400mu *i2400mu = _i2400mu;
160 struct i2400m *i2400m = &i2400mu->i2400m;
161 struct device *dev = &i2400mu->usb_iface->dev;
162 struct i2400m_msg_hdr *tx_msg;
163 size_t tx_msg_size;
164
165 d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
166
167 while (1) {
168 d_printf(2, dev, "TX: waiting for messages\n");
169 tx_msg = NULL;
170 wait_event_interruptible(
171 i2400mu->tx_wq,
172 (kthread_should_stop() /* check this first! */
173 || (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size)))
174 );
175 if (kthread_should_stop())
176 break;
177 WARN_ON(tx_msg == NULL); /* should not happen...*/
178 d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size);
179 d_dump(5, dev, tx_msg, tx_msg_size);
180 /* Yeah, we ignore errors ... not much we can do */
181 i2400mu_tx(i2400mu, tx_msg, tx_msg_size);
182 i2400m_tx_msg_sent(i2400m); /* ack it, advance the FIFO */
183 if (result < 0)
184 break;
185 }
186 d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result);
187 return result;
188}
189
190
191/*
192 * i2400m TX engine notifies us that there is data in the FIFO ready
193 * for TX
194 *
195 * If there is a URB in flight, don't do anything; when it finishes,
196 * it will see there is data in the FIFO and send it. Else, just
197 * submit a write.
198 */
199void i2400mu_bus_tx_kick(struct i2400m *i2400m)
200{
201 struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
202 struct device *dev = &i2400mu->usb_iface->dev;
203
204 d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
205 wake_up_all(&i2400mu->tx_wq);
206 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
207}
208
209
210int i2400mu_tx_setup(struct i2400mu *i2400mu)
211{
212 int result = 0;
213 struct i2400m *i2400m = &i2400mu->i2400m;
214 struct device *dev = &i2400mu->usb_iface->dev;
215 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
216
217 i2400mu->tx_kthread = kthread_run(i2400mu_txd, i2400mu, "%s-tx",
218 wimax_dev->name);
219 if (IS_ERR(i2400mu->tx_kthread)) {
220 result = PTR_ERR(i2400mu->tx_kthread);
221 dev_err(dev, "TX: cannot start thread: %d\n", result);
222 }
223 return result;
224}
225
226void i2400mu_tx_release(struct i2400mu *i2400mu)
227{
228 kthread_stop(i2400mu->tx_kthread);
229}
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
new file mode 100644
index 000000000000..6d4b65fd9c17
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -0,0 +1,591 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * Linux driver model glue for USB device, reset & fw upload
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
8 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License version
12 * 2 as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 *
24 *
25 * See i2400m-usb.h for a general description of this driver.
26 *
27 * This file implements driver model glue, and hook ups for the
28 * generic driver to implement the bus-specific functions (device
29 * communication setup/tear down, firmware upload and resetting).
30 *
31 * ROADMAP
32 *
33 * i2400mu_probe()
34 * alloc_netdev()...
35 * i2400mu_netdev_setup()
36 * i2400mu_init()
37 * i2400m_netdev_setup()
38 * i2400m_setup()...
39 *
40 * i2400mu_disconnect
41 * i2400m_release()
42 * free_netdev()
43 *
44 * i2400mu_suspend()
45 * i2400m_cmd_enter_powersave()
46 * i2400mu_notification_release()
47 *
48 * i2400mu_resume()
49 * i2400mu_notification_setup()
50 *
51 * i2400mu_bus_dev_start() Called by i2400m_dev_start() [who is
52 * i2400mu_tx_setup() called by i2400m_setup()]
53 * i2400mu_rx_setup()
54 * i2400mu_notification_setup()
55 *
56 * i2400mu_bus_dev_stop() Called by i2400m_dev_stop() [who is
57 * i2400mu_notification_release() called by i2400m_release()]
58 * i2400mu_rx_release()
59 * i2400mu_tx_release()
60 *
61 * i2400mu_bus_reset() Called by i2400m->bus_reset
62 * __i2400mu_reset()
63 * __i2400mu_send_barker()
64 * usb_reset_device()
65 */
66#include "i2400m-usb.h"
67#include <linux/wimax/i2400m.h>
68#include <linux/debugfs.h>
69
70
71#define D_SUBMODULE usb
72#include "usb-debug-levels.h"
73
74
75/* Our firmware file name */
76#define I2400MU_FW_FILE_NAME "i2400m-fw-usb-" I2400M_FW_VERSION ".sbcf"
77
78static
79int i2400mu_bus_dev_start(struct i2400m *i2400m)
80{
81 int result;
82 struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
83 struct device *dev = &i2400mu->usb_iface->dev;
84
85 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
86 result = i2400mu_tx_setup(i2400mu);
87 if (result < 0)
88 goto error_usb_tx_setup;
89 result = i2400mu_rx_setup(i2400mu);
90 if (result < 0)
91 goto error_usb_rx_setup;
92 result = i2400mu_notification_setup(i2400mu);
93 if (result < 0)
94 goto error_notif_setup;
95 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
96 return result;
97
98error_notif_setup:
99 i2400mu_rx_release(i2400mu);
100error_usb_rx_setup:
101 i2400mu_tx_release(i2400mu);
102error_usb_tx_setup:
103 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
104 return result;
105}
106
107
108static
109void i2400mu_bus_dev_stop(struct i2400m *i2400m)
110{
111 struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
112 struct device *dev = &i2400mu->usb_iface->dev;
113
114 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
115 i2400mu_notification_release(i2400mu);
116 i2400mu_rx_release(i2400mu);
117 i2400mu_tx_release(i2400mu);
118 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
119}
120
121
122/*
123 * Sends a barker buffer to the device
124 *
125 * This helper will allocate a kmalloced buffer and use it to transmit
126 * (then free it). Reason for this is that other arches cannot use
127 * stack/vmalloc/text areas for DMA transfers.
128 *
129 * Error recovery here is simpler: anything is considered a hard error
130 * and will move the reset code to use a last-resort bus-based reset.
131 */
132static
133int __i2400mu_send_barker(struct i2400mu *i2400mu,
134 const __le32 *barker,
135 size_t barker_size,
136 unsigned endpoint)
137{
138 struct usb_endpoint_descriptor *epd = NULL;
139 int pipe, actual_len, ret;
140 struct device *dev = &i2400mu->usb_iface->dev;
141 void *buffer;
142 int do_autopm = 1;
143
144 ret = usb_autopm_get_interface(i2400mu->usb_iface);
145 if (ret < 0) {
146 dev_err(dev, "RESET: can't get autopm: %d\n", ret);
147 do_autopm = 0;
148 }
149 ret = -ENOMEM;
150 buffer = kmalloc(barker_size, GFP_KERNEL);
151 if (buffer == NULL)
152 goto error_kzalloc;
153 epd = usb_get_epd(i2400mu->usb_iface, endpoint);
154 pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
155 memcpy(buffer, barker, barker_size);
156 ret = usb_bulk_msg(i2400mu->usb_dev, pipe, buffer, barker_size,
157 &actual_len, HZ);
158 if (ret < 0) {
159 if (ret != -EINVAL)
160 dev_err(dev, "E: barker error: %d\n", ret);
161 } else if (actual_len != barker_size) {
162 dev_err(dev, "E: only %d bytes transmitted\n", actual_len);
163 ret = -EIO;
164 }
165 kfree(buffer);
166error_kzalloc:
167 if (do_autopm)
168 usb_autopm_put_interface(i2400mu->usb_iface);
169 return ret;
170}
171
172
173/*
174 * Reset a device at different levels (warm, cold or bus)
175 *
176 * @i2400m: device descriptor
177 * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS)
178 *
179 * Warm and cold resets get a USB reset if they fail.
180 *
181 * Warm reset:
182 *
183 * The device will be fully reset internally, but won't be
184 * disconnected from the USB bus (so no reenumeration will
185 * happen). Firmware upload will be neccessary.
186 *
187 * The device will send a reboot barker in the notification endpoint
188 * that will trigger the driver to reinitialize the state
189 * automatically from notif.c:i2400m_notification_grok() into
190 * i2400m_dev_bootstrap_delayed().
191 *
192 * Cold and bus (USB) reset:
193 *
194 * The device will be fully reset internally, disconnected from the
195 * USB bus an a reenumeration will happen. Firmware upload will be
196 * neccessary. Thus, we don't do any locking or struct
197 * reinitialization, as we are going to be fully disconnected and
198 * reenumerated.
199 *
200 * Note we need to return -ENODEV if a warm reset was requested and we
201 * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset()
202 * and wimax_dev->op_reset.
203 *
204 * WARNING: no driver state saved/fixed
205 */
206static
207int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
208{
209 int result;
210 struct i2400mu *i2400mu =
211 container_of(i2400m, struct i2400mu, i2400m);
212 struct device *dev = i2400m_dev(i2400m);
213 static const __le32 i2400m_WARM_BOOT_BARKER[4] = {
214 __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
215 __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
216 __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
217 __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
218 };
219 static const __le32 i2400m_COLD_BOOT_BARKER[4] = {
220 __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
221 __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
222 __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
223 __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
224 };
225
226 d_fnstart(3, dev, "(i2400m %p rt %u)\n", i2400m, rt);
227 if (rt == I2400M_RT_WARM)
228 result = __i2400mu_send_barker(i2400mu, i2400m_WARM_BOOT_BARKER,
229 sizeof(i2400m_WARM_BOOT_BARKER),
230 I2400MU_EP_BULK_OUT);
231 else if (rt == I2400M_RT_COLD)
232 result = __i2400mu_send_barker(i2400mu, i2400m_COLD_BOOT_BARKER,
233 sizeof(i2400m_COLD_BOOT_BARKER),
234 I2400MU_EP_RESET_COLD);
235 else if (rt == I2400M_RT_BUS) {
236do_bus_reset:
237 result = usb_reset_device(i2400mu->usb_dev);
238 switch (result) {
239 case 0:
240 case -EINVAL: /* device is gone */
241 case -ENODEV:
242 case -ENOENT:
243 case -ESHUTDOWN:
244 result = rt == I2400M_RT_WARM ? -ENODEV : 0;
245 break; /* We assume the device is disconnected */
246 default:
247 dev_err(dev, "USB reset failed (%d), giving up!\n",
248 result);
249 }
250 } else
251 BUG();
252 if (result < 0
253 && result != -EINVAL /* device is gone */
254 && rt != I2400M_RT_BUS) {
255 dev_err(dev, "%s reset failed (%d); trying USB reset\n",
256 rt == I2400M_RT_WARM ? "warm" : "cold", result);
257 rt = I2400M_RT_BUS;
258 goto do_bus_reset;
259 }
260 d_fnend(3, dev, "(i2400m %p rt %u) = %d\n", i2400m, rt, result);
261 return result;
262}
263
264
265static
266void i2400mu_netdev_setup(struct net_device *net_dev)
267{
268 struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
269 struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
270 i2400mu_init(i2400mu);
271 i2400m_netdev_setup(net_dev);
272}
273
274
275/*
276 * Debug levels control; see debug.h
277 */
278struct d_level D_LEVEL[] = {
279 D_SUBMODULE_DEFINE(usb),
280 D_SUBMODULE_DEFINE(fw),
281 D_SUBMODULE_DEFINE(notif),
282 D_SUBMODULE_DEFINE(rx),
283 D_SUBMODULE_DEFINE(tx),
284};
285size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
286
287
288#define __debugfs_register(prefix, name, parent) \
289do { \
290 result = d_level_register_debugfs(prefix, name, parent); \
291 if (result < 0) \
292 goto error; \
293} while (0)
294
295
296static
297int i2400mu_debugfs_add(struct i2400mu *i2400mu)
298{
299 int result;
300 struct device *dev = &i2400mu->usb_iface->dev;
301 struct dentry *dentry = i2400mu->i2400m.wimax_dev.debugfs_dentry;
302 struct dentry *fd;
303
304 dentry = debugfs_create_dir("i2400m-usb", dentry);
305 result = PTR_ERR(dentry);
306 if (IS_ERR(dentry)) {
307 if (result == -ENODEV)
308 result = 0; /* No debugfs support */
309 goto error;
310 }
311 i2400mu->debugfs_dentry = dentry;
312 __debugfs_register("dl_", usb, dentry);
313 __debugfs_register("dl_", fw, dentry);
314 __debugfs_register("dl_", notif, dentry);
315 __debugfs_register("dl_", rx, dentry);
316 __debugfs_register("dl_", tx, dentry);
317
318 /* Don't touch these if you don't know what you are doing */
319 fd = debugfs_create_u8("rx_size_auto_shrink", 0600, dentry,
320 &i2400mu->rx_size_auto_shrink);
321 result = PTR_ERR(fd);
322 if (IS_ERR(fd) && result != -ENODEV) {
323 dev_err(dev, "Can't create debugfs entry "
324 "rx_size_auto_shrink: %d\n", result);
325 goto error;
326 }
327
328 fd = debugfs_create_size_t("rx_size", 0600, dentry,
329 &i2400mu->rx_size);
330 result = PTR_ERR(fd);
331 if (IS_ERR(fd) && result != -ENODEV) {
332 dev_err(dev, "Can't create debugfs entry "
333 "rx_size: %d\n", result);
334 goto error;
335 }
336
337 return 0;
338
339error:
340 debugfs_remove_recursive(i2400mu->debugfs_dentry);
341 return result;
342}
343
344
345/*
346 * Probe a i2400m interface and register it
347 *
348 * @iface: USB interface to link to
349 * @id: USB class/subclass/protocol id
350 * @returns: 0 if ok, < 0 errno code on error.
351 *
352 * Alloc a net device, initialize the bus-specific details and then
353 * calls the bus-generic initialization routine. That will register
354 * the wimax and netdev devices, upload the firmware [using
355 * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
356 * communication with the device and then will start to talk to it to
357 * finnish setting it up.
358 */
359static
360int i2400mu_probe(struct usb_interface *iface,
361 const struct usb_device_id *id)
362{
363 int result;
364 struct net_device *net_dev;
365 struct device *dev = &iface->dev;
366 struct i2400m *i2400m;
367 struct i2400mu *i2400mu;
368 struct usb_device *usb_dev = interface_to_usbdev(iface);
369
370 if (usb_dev->speed != USB_SPEED_HIGH)
371 dev_err(dev, "device not connected as high speed\n");
372
373 /* Allocate instance [calls i2400m_netdev_setup() on it]. */
374 result = -ENOMEM;
375 net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d",
376 i2400mu_netdev_setup);
377 if (net_dev == NULL) {
378 dev_err(dev, "no memory for network device instance\n");
379 goto error_alloc_netdev;
380 }
381 SET_NETDEV_DEV(net_dev, dev);
382 i2400m = net_dev_to_i2400m(net_dev);
383 i2400mu = container_of(i2400m, struct i2400mu, i2400m);
384 i2400m->wimax_dev.net_dev = net_dev;
385 i2400mu->usb_dev = usb_get_dev(usb_dev);
386 i2400mu->usb_iface = iface;
387 usb_set_intfdata(iface, i2400mu);
388
389 i2400m->bus_tx_block_size = I2400MU_BLK_SIZE;
390 i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX;
391 i2400m->bus_dev_start = i2400mu_bus_dev_start;
392 i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
393 i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
394 i2400m->bus_reset = i2400mu_bus_reset;
395 i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send;
396 i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
397 i2400m->bus_fw_name = I2400MU_FW_FILE_NAME;
398 i2400m->bus_bm_mac_addr_impaired = 0;
399
400 iface->needs_remote_wakeup = 1; /* autosuspend (15s delay) */
401 device_init_wakeup(dev, 1);
402 usb_autopm_enable(i2400mu->usb_iface);
403 usb_dev->autosuspend_delay = 15 * HZ;
404 usb_dev->autosuspend_disabled = 0;
405
406 result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);
407 if (result < 0) {
408 dev_err(dev, "cannot setup device: %d\n", result);
409 goto error_setup;
410 }
411 result = i2400mu_debugfs_add(i2400mu);
412 if (result < 0) {
413 dev_err(dev, "Can't register i2400mu's debugfs: %d\n", result);
414 goto error_debugfs_add;
415 }
416 return 0;
417
418error_debugfs_add:
419 i2400m_release(i2400m);
420error_setup:
421 usb_set_intfdata(iface, NULL);
422 usb_put_dev(i2400mu->usb_dev);
423 free_netdev(net_dev);
424error_alloc_netdev:
425 return result;
426}
427
428
429/*
430 * Disconect a i2400m from the system.
431 *
432 * i2400m_stop() has been called before, so al the rx and tx contexts
433 * have been taken down already. Make sure the queue is stopped,
434 * unregister netdev and i2400m, free and kill.
435 */
436static
437void i2400mu_disconnect(struct usb_interface *iface)
438{
439 struct i2400mu *i2400mu = usb_get_intfdata(iface);
440 struct i2400m *i2400m = &i2400mu->i2400m;
441 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
442 struct device *dev = &iface->dev;
443
444 d_fnstart(3, dev, "(iface %p i2400m %p)\n", iface, i2400m);
445
446 debugfs_remove_recursive(i2400mu->debugfs_dentry);
447 i2400m_release(i2400m);
448 usb_set_intfdata(iface, NULL);
449 usb_put_dev(i2400mu->usb_dev);
450 free_netdev(net_dev);
451 d_fnend(3, dev, "(iface %p i2400m %p) = void\n", iface, i2400m);
452}
453
454
455/*
456 * Get the device ready for USB port or system standby and hibernation
457 *
458 * USB port and system standby are handled the same.
459 *
460 * When the system hibernates, the USB device is powered down and then
461 * up, so we don't really have to do much here, as it will be seen as
462 * a reconnect. Still for simplicity we consider this case the same as
463 * suspend, so that the device has a chance to do notify the base
464 * station (if connected).
465 *
466 * So at the end, the three cases require common handling.
467 *
468 * If at the time of this call the device's firmware is not loaded,
469 * nothing has to be done.
470 *
471 * If the firmware is loaded, we need to:
472 *
473 * - tell the device to go into host interface power save mode, wait
474 * for it to ack
475 *
476 * This is quite more interesting than it is; we need to execute a
477 * command, but this time, we don't want the code in usb-{tx,rx}.c
478 * to call the usb_autopm_get/put_interface() barriers as it'd
479 * deadlock, so we need to decrement i2400mu->do_autopm, that acts
480 * as a poor man's semaphore. Ugly, but it works.
481 *
482 * As well, the device might refuse going to sleep for whichever
483 * reason. In this case we just fail. For system suspend/hibernate,
484 * we *can't* fail. We look at usb_dev->auto_pm to see if the
485 * suspend call comes from the USB stack or from the system and act
486 * in consequence.
487 *
488 * - stop the notification endpoint polling
489 */
490static
491int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)
492{
493 int result = 0;
494 struct device *dev = &iface->dev;
495 struct i2400mu *i2400mu = usb_get_intfdata(iface);
496 struct usb_device *usb_dev = i2400mu->usb_dev;
497 struct i2400m *i2400m = &i2400mu->i2400m;
498
499 d_fnstart(3, dev, "(iface %p pm_msg %u)\n", iface, pm_msg.event);
500 if (i2400m->updown == 0)
501 goto no_firmware;
502 d_printf(1, dev, "fw up, requesting standby\n");
503 atomic_dec(&i2400mu->do_autopm);
504 result = i2400m_cmd_enter_powersave(i2400m);
505 atomic_inc(&i2400mu->do_autopm);
506 if (result < 0 && usb_dev->auto_pm == 0) {
507 /* System suspend, can't fail */
508 dev_err(dev, "failed to suspend, will reset on resume\n");
509 result = 0;
510 }
511 if (result < 0)
512 goto error_enter_powersave;
513 i2400mu_notification_release(i2400mu);
514 d_printf(1, dev, "fw up, got standby\n");
515error_enter_powersave:
516no_firmware:
517 d_fnend(3, dev, "(iface %p pm_msg %u) = %d\n",
518 iface, pm_msg.event, result);
519 return result;
520}
521
522
523static
524int i2400mu_resume(struct usb_interface *iface)
525{
526 int ret = 0;
527 struct device *dev = &iface->dev;
528 struct i2400mu *i2400mu = usb_get_intfdata(iface);
529 struct i2400m *i2400m = &i2400mu->i2400m;
530
531 d_fnstart(3, dev, "(iface %p)\n", iface);
532 if (i2400m->updown == 0) {
533 d_printf(1, dev, "fw was down, no resume neeed\n");
534 goto out;
535 }
536 d_printf(1, dev, "fw was up, resuming\n");
537 i2400mu_notification_setup(i2400mu);
538 /* USB has flow control, so we don't need to give it time to
539 * come back; otherwise, we'd use something like a get-state
540 * command... */
541out:
542 d_fnend(3, dev, "(iface %p) = %d\n", iface, ret);
543 return ret;
544}
545
546
547static
548struct usb_device_id i2400mu_id_table[] = {
549 { USB_DEVICE(0x8086, 0x0181) },
550 { USB_DEVICE(0x8086, 0x1403) },
551 { USB_DEVICE(0x8086, 0x1405) },
552 { USB_DEVICE(0x8086, 0x0180) },
553 { USB_DEVICE(0x8086, 0x0182) },
554 { USB_DEVICE(0x8086, 0x1406) },
555 { USB_DEVICE(0x8086, 0x1403) },
556 { },
557};
558MODULE_DEVICE_TABLE(usb, i2400mu_id_table);
559
560
561static
562struct usb_driver i2400mu_driver = {
563 .name = KBUILD_MODNAME,
564 .suspend = i2400mu_suspend,
565 .resume = i2400mu_resume,
566 .probe = i2400mu_probe,
567 .disconnect = i2400mu_disconnect,
568 .id_table = i2400mu_id_table,
569 .supports_autosuspend = 1,
570};
571
572static
573int __init i2400mu_driver_init(void)
574{
575 return usb_register(&i2400mu_driver);
576}
577module_init(i2400mu_driver_init);
578
579
580static
581void __exit i2400mu_driver_exit(void)
582{
583 flush_scheduled_work(); /* for the stuff we schedule from sysfs.c */
584 usb_deregister(&i2400mu_driver);
585}
586module_exit(i2400mu_driver_exit);
587
588MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
589MODULE_DESCRIPTION("Intel 2400M WiMAX networking for USB");
590MODULE_LICENSE("GPL");
591MODULE_FIRMWARE(I2400MU_FW_FILE_NAME);