aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-07-10 16:27:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-07-11 15:40:22 -0400
commit5da7b2e05ec17d8a90ea1f463d3b7d46975ceef2 (patch)
tree07b65448a598def4b34ca59256835b875d932479 /drivers
parent650cef38263c0f4c8970265354432be154eef425 (diff)
i2400m: remove SDIO device support
SDIO support in this driver was intended to support the iwmc3200 device. This hardware never became available to normal humans. Leaving this driver imposes unwelcome maintenance costs for no clear benefit. Signed-off-by: John W. Linville <linville@tuxdriver.com> Acked-by: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wimax/i2400m/Kconfig22
-rw-r--r--drivers/net/wimax/i2400m/Makefile8
-rw-r--r--drivers/net/wimax/i2400m/driver.c3
-rw-r--r--drivers/net/wimax/i2400m/fw.c3
-rw-r--r--drivers/net/wimax/i2400m/i2400m-sdio.h157
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h13
-rw-r--r--drivers/net/wimax/i2400m/sdio-debug-levels.h22
-rw-r--r--drivers/net/wimax/i2400m/sdio-fw.c210
-rw-r--r--drivers/net/wimax/i2400m/sdio-rx.c301
-rw-r--r--drivers/net/wimax/i2400m/sdio-tx.c177
-rw-r--r--drivers/net/wimax/i2400m/sdio.c602
11 files changed, 8 insertions, 1510 deletions
diff --git a/drivers/net/wimax/i2400m/Kconfig b/drivers/net/wimax/i2400m/Kconfig
index 672de18a776..71453db1425 100644
--- a/drivers/net/wimax/i2400m/Kconfig
+++ b/drivers/net/wimax/i2400m/Kconfig
@@ -7,9 +7,6 @@ config WIMAX_I2400M
7comment "Enable USB support to see WiMAX USB drivers" 7comment "Enable USB support to see WiMAX USB drivers"
8 depends on USB = n 8 depends on USB = n
9 9
10comment "Enable MMC support to see WiMAX SDIO drivers"
11 depends on MMC = n
12
13config WIMAX_I2400M_USB 10config WIMAX_I2400M_USB
14 tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)" 11 tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)"
15 depends on WIMAX && USB 12 depends on WIMAX && USB
@@ -21,25 +18,6 @@ config WIMAX_I2400M_USB
21 18
22 If unsure, it is safe to select M (module). 19 If unsure, it is safe to select M (module).
23 20
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_IWMC3200_SDIO
35 bool "Intel Wireless Multicom WiMAX Connection 3200 over SDIO (EXPERIMENTAL)"
36 depends on WIMAX_I2400M_SDIO
37 depends on EXPERIMENTAL
38 select IWMC3200TOP
39 help
40 Select if you have a device based on the Intel Multicom WiMAX
41 Connection 3200 over SDIO.
42
43config WIMAX_I2400M_DEBUG_LEVEL 21config WIMAX_I2400M_DEBUG_LEVEL
44 int "WiMAX i2400m debug level" 22 int "WiMAX i2400m debug level"
45 depends on WIMAX_I2400M 23 depends on WIMAX_I2400M
diff --git a/drivers/net/wimax/i2400m/Makefile b/drivers/net/wimax/i2400m/Makefile
index 5d9e018d31a..f6d19c34808 100644
--- a/drivers/net/wimax/i2400m/Makefile
+++ b/drivers/net/wimax/i2400m/Makefile
@@ -1,7 +1,6 @@
1 1
2obj-$(CONFIG_WIMAX_I2400M) += i2400m.o 2obj-$(CONFIG_WIMAX_I2400M) += i2400m.o
3obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o 3obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o
4obj-$(CONFIG_WIMAX_I2400M_SDIO) += i2400m-sdio.o
5 4
6i2400m-y := \ 5i2400m-y := \
7 control.o \ 6 control.o \
@@ -21,10 +20,3 @@ i2400m-usb-y := \
21 usb-tx.o \ 20 usb-tx.o \
22 usb-rx.o \ 21 usb-rx.o \
23 usb.o 22 usb.o
24
25
26i2400m-sdio-y := \
27 sdio.o \
28 sdio-tx.o \
29 sdio-fw.o \
30 sdio-rx.o
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
index 47cae7150bc..850b8bc38be 100644
--- a/drivers/net/wimax/i2400m/driver.c
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -754,8 +754,7 @@ EXPORT_SYMBOL_GPL(i2400m_error_recovery);
754/* 754/*
755 * Alloc the command and ack buffers for boot mode 755 * Alloc the command and ack buffers for boot mode
756 * 756 *
757 * Get the buffers needed to deal with boot mode messages. These 757 * Get the buffers needed to deal with boot mode messages.
758 * buffers need to be allocated before the sdio receive irq is setup.
759 */ 758 */
760static 759static
761int i2400m_bm_buf_alloc(struct i2400m *i2400m) 760int i2400m_bm_buf_alloc(struct i2400m *i2400m)
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
index 7cbd7d231e1..7632f8cf09d 100644
--- a/drivers/net/wimax/i2400m/fw.c
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -51,8 +51,7 @@
51 * firmware. Normal hardware takes only signed firmware. 51 * firmware. Normal hardware takes only signed firmware.
52 * 52 *
53 * On boot mode, in USB, we write to the device using the bulk out 53 * On boot mode, in USB, we write to the device using the bulk out
54 * endpoint and read from it in the notification endpoint. In SDIO we 54 * endpoint and read from it in the notification endpoint.
55 * talk to it via the write address and read from the read address.
56 * 55 *
57 * Upon entrance to boot mode, the device sends (preceded with a few 56 * Upon entrance to boot mode, the device sends (preceded with a few
58 * zero length packets (ZLPs) on the notification endpoint in USB) a 57 * zero length packets (ZLPs) on the notification endpoint in USB) a
diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h
deleted file mode 100644
index 1d63ffdedfd..00000000000
--- a/drivers/net/wimax/i2400m/i2400m-sdio.h
+++ /dev/null
@@ -1,157 +0,0 @@
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 I2400M_SDIO_BOOT_RETRIES = 3,
71 I2400MS_BLK_SIZE = 256,
72 I2400MS_PL_SIZE_MAX = 0x3E00,
73
74 I2400MS_DATA_ADDR = 0x0,
75 I2400MS_INTR_STATUS_ADDR = 0x13,
76 I2400MS_INTR_CLEAR_ADDR = 0x13,
77 I2400MS_INTR_ENABLE_ADDR = 0x14,
78 I2400MS_INTR_GET_SIZE_ADDR = 0x2C,
79 /* The number of ticks to wait for the device to signal that
80 * it is ready */
81 I2400MS_INIT_SLEEP_INTERVAL = 100,
82 /* How long to wait for the device to settle after reset */
83 I2400MS_SETTLE_TIME = 40,
84 /* The number of msec to wait for IOR after sending IOE */
85 IWMC3200_IOR_TIMEOUT = 10,
86};
87
88
89/**
90 * struct i2400ms - descriptor for a SDIO connected i2400m
91 *
92 * @i2400m: bus-generic i2400m implementation; has to be first (see
93 * it's documentation in i2400m.h).
94 *
95 * @func: pointer to our SDIO function
96 *
97 * @tx_worker: workqueue struct used to TX data when the bus-generic
98 * code signals packets are pending for transmission to the device.
99 *
100 * @tx_workqueue: workqeueue used for data TX; we don't use the
101 * system's workqueue as that might cause deadlocks with code in
102 * the bus-generic driver. The read/write operation to the queue
103 * is protected with spinlock (tx_lock in struct i2400m) to avoid
104 * the queue being destroyed in the middle of a the queue read/write
105 * operation.
106 *
107 * @debugfs_dentry: dentry for the SDIO specific debugfs files
108 *
109 * Note this value is set to NULL upon destruction; this is
110 * because some routinges use it to determine if we are inside the
111 * probe() path or some other path. When debugfs is disabled,
112 * creation sets the dentry to '(void*) -ENODEV', which is valid
113 * for the test.
114 */
115struct i2400ms {
116 struct i2400m i2400m; /* FIRST! See doc */
117 struct sdio_func *func;
118
119 struct work_struct tx_worker;
120 struct workqueue_struct *tx_workqueue;
121 char tx_wq_name[32];
122
123 struct dentry *debugfs_dentry;
124
125 wait_queue_head_t bm_wfa_wq;
126 int bm_wait_result;
127 size_t bm_ack_size;
128
129 /* Device is any of the iwmc3200 SKUs */
130 unsigned iwmc3200:1;
131};
132
133
134static inline
135void i2400ms_init(struct i2400ms *i2400ms)
136{
137 i2400m_init(&i2400ms->i2400m);
138}
139
140
141extern int i2400ms_rx_setup(struct i2400ms *);
142extern void i2400ms_rx_release(struct i2400ms *);
143
144extern int i2400ms_tx_setup(struct i2400ms *);
145extern void i2400ms_tx_release(struct i2400ms *);
146extern void i2400ms_bus_tx_kick(struct i2400m *);
147
148extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *,
149 const struct i2400m_bootrom_header *,
150 size_t, int);
151extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *,
152 struct i2400m_bootrom_header *,
153 size_t);
154extern void i2400ms_bus_bm_release(struct i2400m *);
155extern int i2400ms_bus_bm_setup(struct i2400m *);
156
157#endif /* #ifndef __I2400M_SDIO_H__ */
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index c806d455021..79c6505b5c2 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -46,7 +46,7 @@
46 * - bus generic driver (this part) 46 * - bus generic driver (this part)
47 * 47 *
48 * The bus specific driver sets up stuff specific to the bus the 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 49 * device is connected to (USB, PCI, tam-tam...non-authoritative
50 * nor binding list) which is basically the device-model management 50 * nor binding list) which is basically the device-model management
51 * (probe/disconnect, etc), moving data from device to kernel and 51 * (probe/disconnect, etc), moving data from device to kernel and
52 * back, doing the power saving details and reseting the device. 52 * back, doing the power saving details and reseting the device.
@@ -238,14 +238,13 @@ struct i2400m_barker_db;
238 * amount needed for loading firmware, where us dev_start/stop setup 238 * amount needed for loading firmware, where us dev_start/stop setup
239 * the rest needed to do full data/control traffic. 239 * the rest needed to do full data/control traffic.
240 * 240 *
241 * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16, 241 * @bus_tx_block_size: [fill] USB imposes a 16 block size, but other
242 * so we have a tx_blk_size variable that the bus layer sets to 242 * busses will differ. So we have a tx_blk_size variable that the
243 * tell the engine how much of that we need. 243 * bus layer sets to tell the engine how much of that we need.
244 * 244 *
245 * @bus_tx_room_min: [fill] Minimum room required while allocating 245 * @bus_tx_room_min: [fill] Minimum room required while allocating
246 * TX queue's buffer space for message header. SDIO requires 246 * TX queue's buffer space for message header. USB requires
247 * 224 bytes and USB 16 bytes. Refer bus specific driver code 247 * 16 bytes. Refer to bus specific driver code for details.
248 * for details.
249 * 248 *
250 * @bus_pl_size_max: [fill] Maximum payload size. 249 * @bus_pl_size_max: [fill] Maximum payload size.
251 * 250 *
diff --git a/drivers/net/wimax/i2400m/sdio-debug-levels.h b/drivers/net/wimax/i2400m/sdio-debug-levels.h
deleted file mode 100644
index c5199874130..00000000000
--- a/drivers/net/wimax/i2400m/sdio-debug-levels.h
+++ /dev/null
@@ -1,22 +0,0 @@
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
deleted file mode 100644
index 8e025418f5b..00000000000
--- a/drivers/net/wimax/i2400m/sdio-fw.c
+++ /dev/null
@@ -1,210 +0,0 @@
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 * Dirk Brandewie <dirk.j.brandewie@intel.com>
50 * - Make it IRQ based, not polling
51 *
52 * THE PROCEDURE
53 *
54 * See fw.c for the generic description of this procedure.
55 *
56 * This file implements only the SDIO specifics. It boils down to how
57 * to send a command and waiting for an acknowledgement from the
58 * device.
59 *
60 * All this code is sequential -- all i2400ms_bus_bm_*() functions are
61 * executed in the same thread, except i2400ms_bm_irq() [on its own by
62 * the SDIO driver]. This makes it possible to avoid locking.
63 *
64 * COMMAND EXECUTION
65 *
66 * The generic firmware upload code will call i2400m_bus_bm_cmd_send()
67 * to send commands.
68 *
69 * The SDIO devices expects things in 256 byte blocks, so it will pad
70 * it, compute the checksum (if needed) and pass it to SDIO.
71 *
72 * ACK RECEPTION
73 *
74 * This works in IRQ mode -- the fw loader says when to wait for data
75 * and for that it calls i2400ms_bus_bm_wait_for_ack().
76 *
77 * This checks if there is any data available (RX size > 0); if not,
78 * waits for the IRQ handler to notify about it. Once there is data,
79 * it is read and passed to the caller. Doing it this way we don't
80 * need much coordination/locking, and it makes it much more difficult
81 * for an interrupt to be lost and the wait_for_ack() function getting
82 * stuck even when data is pending.
83 */
84#include <linux/mmc/sdio_func.h>
85#include "i2400m-sdio.h"
86
87
88#define D_SUBMODULE fw
89#include "sdio-debug-levels.h"
90
91
92/*
93 * Send a boot-mode command to the SDIO function
94 *
95 * We use a bounce buffer (i2400m->bm_cmd_buf) because we need to
96 * touch the header if the RAW flag is not set.
97 *
98 * @flags: pass thru from i2400m_bm_cmd()
99 * @return: cmd_size if ok, < 0 errno code on error.
100 *
101 * Note the command is padded to the SDIO block size for the device.
102 */
103ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m,
104 const struct i2400m_bootrom_header *_cmd,
105 size_t cmd_size, int flags)
106{
107 ssize_t result;
108 struct device *dev = i2400m_dev(i2400m);
109 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
110 int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd);
111 struct i2400m_bootrom_header *cmd;
112 /* SDIO restriction */
113 size_t cmd_size_a = ALIGN(cmd_size, I2400MS_BLK_SIZE);
114
115 d_fnstart(5, dev, "(i2400m %p cmd %p size %zu)\n",
116 i2400m, _cmd, cmd_size);
117 result = -E2BIG;
118 if (cmd_size > I2400M_BM_CMD_BUF_SIZE)
119 goto error_too_big;
120
121 if (_cmd != i2400m->bm_cmd_buf)
122 memmove(i2400m->bm_cmd_buf, _cmd, cmd_size);
123 cmd = i2400m->bm_cmd_buf;
124 if (cmd_size_a > cmd_size) /* Zero pad space */
125 memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size);
126 if ((flags & I2400M_BM_CMD_RAW) == 0) {
127 if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0))
128 dev_warn(dev, "SW BUG: response_required == 0\n");
129 i2400m_bm_cmd_prepare(cmd);
130 }
131 d_printf(4, dev, "BM cmd %d: %zu bytes (%zu padded)\n",
132 opcode, cmd_size, cmd_size_a);
133 d_dump(5, dev, cmd, cmd_size);
134
135 sdio_claim_host(i2400ms->func); /* Send & check */
136 result = sdio_memcpy_toio(i2400ms->func, I2400MS_DATA_ADDR,
137 i2400m->bm_cmd_buf, cmd_size_a);
138 sdio_release_host(i2400ms->func);
139 if (result < 0) {
140 dev_err(dev, "BM cmd %d: cannot send: %ld\n",
141 opcode, (long) result);
142 goto error_cmd_send;
143 }
144 result = cmd_size;
145error_cmd_send:
146error_too_big:
147 d_fnend(5, dev, "(i2400m %p cmd %p size %zu) = %d\n",
148 i2400m, _cmd, cmd_size, (int) result);
149 return result;
150}
151
152
153/*
154 * Read an ack from the device's boot-mode
155 *
156 * @i2400m:
157 * @_ack: pointer to where to store the read data
158 * @ack_size: how many bytes we should read
159 *
160 * Returns: < 0 errno code on error; otherwise, amount of received bytes.
161 *
162 * The ACK for a BM command is always at least sizeof(*ack) bytes, so
163 * check for that. We don't need to check for device reboots
164 *
165 */
166ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m,
167 struct i2400m_bootrom_header *ack,
168 size_t ack_size)
169{
170 ssize_t result;
171 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
172 struct sdio_func *func = i2400ms->func;
173 struct device *dev = &func->dev;
174 int size;
175
176 BUG_ON(sizeof(*ack) > ack_size);
177
178 d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n",
179 i2400m, ack, ack_size);
180
181 result = wait_event_timeout(i2400ms->bm_wfa_wq,
182 i2400ms->bm_ack_size != -EINPROGRESS,
183 2 * HZ);
184 if (result == 0) {
185 result = -ETIMEDOUT;
186 dev_err(dev, "BM: error waiting for an ack\n");
187 goto error_timeout;
188 }
189
190 spin_lock(&i2400m->rx_lock);
191 result = i2400ms->bm_ack_size;
192 BUG_ON(result == -EINPROGRESS);
193 if (result < 0) /* so we exit when rx_release() is called */
194 dev_err(dev, "BM: %s failed: %zd\n", __func__, result);
195 else {
196 size = min(ack_size, i2400ms->bm_ack_size);
197 memcpy(ack, i2400m->bm_ack_buf, size);
198 }
199 /*
200 * Remember always to clear the bm_ack_size to -EINPROGRESS
201 * after the RX data is processed
202 */
203 i2400ms->bm_ack_size = -EINPROGRESS;
204 spin_unlock(&i2400m->rx_lock);
205
206error_timeout:
207 d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %zd\n",
208 i2400m, ack, ack_size, result);
209 return result;
210}
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c
deleted file mode 100644
index fb6396dd115..00000000000
--- a/drivers/net/wimax/i2400m/sdio-rx.c
+++ /dev/null
@@ -1,301 +0,0 @@
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_is_boot_barker()
57 * i2400m_rx()
58 *
59 * i2400ms_rx_setup()
60 *
61 * i2400ms_rx_release()
62 */
63#include <linux/workqueue.h>
64#include <linux/wait.h>
65#include <linux/skbuff.h>
66#include <linux/mmc/sdio.h>
67#include <linux/mmc/sdio_func.h>
68#include <linux/slab.h>
69#include "i2400m-sdio.h"
70
71#define D_SUBMODULE rx
72#include "sdio-debug-levels.h"
73
74static const __le32 i2400m_ACK_BARKER[4] = {
75 __constant_cpu_to_le32(I2400M_ACK_BARKER),
76 __constant_cpu_to_le32(I2400M_ACK_BARKER),
77 __constant_cpu_to_le32(I2400M_ACK_BARKER),
78 __constant_cpu_to_le32(I2400M_ACK_BARKER)
79};
80
81
82/*
83 * Read and return the amount of bytes available for RX
84 *
85 * The RX size has to be read like this: byte reads of three
86 * sequential locations; then glue'em together.
87 *
88 * sdio_readl() doesn't work.
89 */
90static ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms)
91{
92 int ret, cnt, val;
93 ssize_t rx_size;
94 unsigned xfer_size_addr;
95 struct sdio_func *func = i2400ms->func;
96 struct device *dev = &i2400ms->func->dev;
97
98 d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
99 xfer_size_addr = I2400MS_INTR_GET_SIZE_ADDR;
100 rx_size = 0;
101 for (cnt = 0; cnt < 3; cnt++) {
102 val = sdio_readb(func, xfer_size_addr + cnt, &ret);
103 if (ret < 0) {
104 dev_err(dev, "RX: Can't read byte %d of RX size from "
105 "0x%08x: %d\n", cnt, xfer_size_addr + cnt, ret);
106 rx_size = ret;
107 goto error_read;
108 }
109 rx_size = rx_size << 8 | (val & 0xff);
110 }
111 d_printf(6, dev, "RX: rx_size is %ld\n", (long) rx_size);
112error_read:
113 d_fnend(7, dev, "(i2400ms %p) = %ld\n", i2400ms, (long) rx_size);
114 return rx_size;
115}
116
117
118/*
119 * Read data from the device (when in normal)
120 *
121 * Allocate an SKB of the right size, read the data in and then
122 * deliver it to the generic layer.
123 *
124 * We also check for a reboot barker. That means the device died and
125 * we have to reboot it.
126 */
127static
128void i2400ms_rx(struct i2400ms *i2400ms)
129{
130 int ret;
131 struct sdio_func *func = i2400ms->func;
132 struct device *dev = &func->dev;
133 struct i2400m *i2400m = &i2400ms->i2400m;
134 struct sk_buff *skb;
135 ssize_t rx_size;
136
137 d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
138 rx_size = __i2400ms_rx_get_size(i2400ms);
139 if (rx_size < 0) {
140 ret = rx_size;
141 goto error_get_size;
142 }
143 /*
144 * Hardware quirk: make sure to clear the INTR status register
145 * AFTER getting the data transfer size.
146 */
147 sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret);
148
149 ret = -ENOMEM;
150 skb = alloc_skb(rx_size, GFP_ATOMIC);
151 if (NULL == skb) {
152 dev_err(dev, "RX: unable to alloc skb\n");
153 goto error_alloc_skb;
154 }
155 ret = sdio_memcpy_fromio(func, skb->data,
156 I2400MS_DATA_ADDR, rx_size);
157 if (ret < 0) {
158 dev_err(dev, "RX: SDIO data read failed: %d\n", ret);
159 goto error_memcpy_fromio;
160 }
161
162 rmb(); /* make sure we get boot_mode from dev_reset_handle */
163 if (unlikely(i2400m->boot_mode == 1)) {
164 spin_lock(&i2400m->rx_lock);
165 i2400ms->bm_ack_size = rx_size;
166 spin_unlock(&i2400m->rx_lock);
167 memcpy(i2400m->bm_ack_buf, skb->data, rx_size);
168 wake_up(&i2400ms->bm_wfa_wq);
169 d_printf(5, dev, "RX: SDIO boot mode message\n");
170 kfree_skb(skb);
171 goto out;
172 }
173 ret = -EIO;
174 if (unlikely(rx_size < sizeof(__le32))) {
175 dev_err(dev, "HW BUG? only %zu bytes received\n", rx_size);
176 goto error_bad_size;
177 }
178 if (likely(i2400m_is_d2h_barker(skb->data))) {
179 skb_put(skb, rx_size);
180 i2400m_rx(i2400m, skb);
181 } else if (unlikely(i2400m_is_boot_barker(i2400m,
182 skb->data, rx_size))) {
183 ret = i2400m_dev_reset_handle(i2400m, "device rebooted");
184 dev_err(dev, "RX: SDIO reboot barker\n");
185 kfree_skb(skb);
186 } else {
187 i2400m_unknown_barker(i2400m, skb->data, rx_size);
188 kfree_skb(skb);
189 }
190out:
191 d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms);
192 return;
193
194error_memcpy_fromio:
195 kfree_skb(skb);
196error_alloc_skb:
197error_get_size:
198error_bad_size:
199 d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret);
200}
201
202
203/*
204 * Process an interrupt from the SDIO card
205 *
206 * FIXME: need to process other events that are not just ready-to-read
207 *
208 * Checks there is data ready and then proceeds to read it.
209 */
210static
211void i2400ms_irq(struct sdio_func *func)
212{
213 int ret;
214 struct i2400ms *i2400ms = sdio_get_drvdata(func);
215 struct device *dev = &func->dev;
216 int val;
217
218 d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms);
219 val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret);
220 if (ret < 0) {
221 dev_err(dev, "RX: Can't read interrupt status: %d\n", ret);
222 goto error_no_irq;
223 }
224 if (!val) {
225 dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n");
226 goto error_no_irq;
227 }
228 i2400ms_rx(i2400ms);
229error_no_irq:
230 d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms);
231}
232
233
234/*
235 * Setup SDIO RX
236 *
237 * Hooks up the IRQ handler and then enables IRQs.
238 */
239int i2400ms_rx_setup(struct i2400ms *i2400ms)
240{
241 int result;
242 struct sdio_func *func = i2400ms->func;
243 struct device *dev = &func->dev;
244 struct i2400m *i2400m = &i2400ms->i2400m;
245
246 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
247
248 init_waitqueue_head(&i2400ms->bm_wfa_wq);
249 spin_lock(&i2400m->rx_lock);
250 i2400ms->bm_wait_result = -EINPROGRESS;
251 /*
252 * Before we are about to enable the RX interrupt, make sure
253 * bm_ack_size is cleared to -EINPROGRESS which indicates
254 * no RX interrupt happened yet or the previous interrupt
255 * has been handled, we are ready to take the new interrupt
256 */
257 i2400ms->bm_ack_size = -EINPROGRESS;
258 spin_unlock(&i2400m->rx_lock);
259
260 sdio_claim_host(func);
261 result = sdio_claim_irq(func, i2400ms_irq);
262 if (result < 0) {
263 dev_err(dev, "Cannot claim IRQ: %d\n", result);
264 goto error_irq_claim;
265 }
266 result = 0;
267 sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result);
268 if (result < 0) {
269 sdio_release_irq(func);
270 dev_err(dev, "Failed to enable interrupts %d\n", result);
271 }
272error_irq_claim:
273 sdio_release_host(func);
274 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
275 return result;
276}
277
278
279/*
280 * Tear down SDIO RX
281 *
282 * Disables IRQs in the device and removes the IRQ handler.
283 */
284void i2400ms_rx_release(struct i2400ms *i2400ms)
285{
286 int result;
287 struct sdio_func *func = i2400ms->func;
288 struct device *dev = &func->dev;
289 struct i2400m *i2400m = &i2400ms->i2400m;
290
291 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
292 spin_lock(&i2400m->rx_lock);
293 i2400ms->bm_ack_size = -EINTR;
294 spin_unlock(&i2400m->rx_lock);
295 wake_up_all(&i2400ms->bm_wfa_wq);
296 sdio_claim_host(func);
297 sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result);
298 sdio_release_irq(func);
299 sdio_release_host(func);
300 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
301}
diff --git a/drivers/net/wimax/i2400m/sdio-tx.c b/drivers/net/wimax/i2400m/sdio-tx.c
deleted file mode 100644
index b53cd1c80e3..00000000000
--- a/drivers/net/wimax/i2400m/sdio-tx.c
+++ /dev/null
@@ -1,177 +0,0 @@
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 if (result == -ETIMEDOUT) {
102 i2400m_error_recovery(i2400m);
103 break;
104 }
105 d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size);
106 }
107
108 d_fnend(4, dev, "(i2400ms %p) = void\n", i2400ms);
109}
110
111
112/*
113 * The generic driver notifies us that there is data ready for TX
114 *
115 * Schedule a run of i2400ms_tx_submit() to handle it.
116 */
117void i2400ms_bus_tx_kick(struct i2400m *i2400m)
118{
119 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
120 struct device *dev = &i2400ms->func->dev;
121 unsigned long flags;
122
123 d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
124
125 /* schedule tx work, this is because tx may block, therefore
126 * it has to run in a thread context.
127 */
128 spin_lock_irqsave(&i2400m->tx_lock, flags);
129 if (i2400ms->tx_workqueue != NULL)
130 queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker);
131 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
132
133 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
134}
135
136int i2400ms_tx_setup(struct i2400ms *i2400ms)
137{
138 int result;
139 struct device *dev = &i2400ms->func->dev;
140 struct i2400m *i2400m = &i2400ms->i2400m;
141 struct workqueue_struct *tx_workqueue;
142 unsigned long flags;
143
144 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
145
146 INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit);
147 snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name),
148 "%s-tx", i2400m->wimax_dev.name);
149 tx_workqueue =
150 create_singlethread_workqueue(i2400ms->tx_wq_name);
151 if (tx_workqueue == NULL) {
152 dev_err(dev, "TX: failed to create workqueue\n");
153 result = -ENOMEM;
154 } else
155 result = 0;
156 spin_lock_irqsave(&i2400m->tx_lock, flags);
157 i2400ms->tx_workqueue = tx_workqueue;
158 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
159 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
160 return result;
161}
162
163void i2400ms_tx_release(struct i2400ms *i2400ms)
164{
165 struct i2400m *i2400m = &i2400ms->i2400m;
166 struct workqueue_struct *tx_workqueue;
167 unsigned long flags;
168
169 tx_workqueue = i2400ms->tx_workqueue;
170
171 spin_lock_irqsave(&i2400m->tx_lock, flags);
172 i2400ms->tx_workqueue = NULL;
173 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
174
175 if (tx_workqueue)
176 destroy_workqueue(tx_workqueue);
177}
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
deleted file mode 100644
index 21a9edd6e75..00000000000
--- a/drivers/net/wimax/i2400m/sdio.c
+++ /dev/null
@@ -1,602 +0,0 @@
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_reset
47 * __i2400ms_reset()
48 * __i2400ms_send_barker()
49 */
50
51#include <linux/slab.h>
52#include <linux/debugfs.h>
53#include <linux/mmc/sdio_ids.h>
54#include <linux/mmc/sdio.h>
55#include <linux/mmc/sdio_func.h>
56#include "i2400m-sdio.h"
57#include <linux/wimax/i2400m.h>
58#include <linux/module.h>
59
60#define D_SUBMODULE main
61#include "sdio-debug-levels.h"
62
63/* IOE WiMAX function timeout in seconds */
64static int ioe_timeout = 2;
65module_param(ioe_timeout, int, 0);
66
67static char i2400ms_debug_params[128];
68module_param_string(debug, i2400ms_debug_params, sizeof(i2400ms_debug_params),
69 0644);
70MODULE_PARM_DESC(debug,
71 "String of space-separated NAME:VALUE pairs, where NAMEs "
72 "are the different debug submodules and VALUE are the "
73 "initial debug value to set.");
74
75/* Our firmware file name list */
76static const char *i2400ms_bus_fw_names[] = {
77#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-1.3.sbcf"
78 I2400MS_FW_FILE_NAME,
79 NULL
80};
81
82
83static const struct i2400m_poke_table i2400ms_pokes[] = {
84 I2400M_FW_POKE(0x6BE260, 0x00000088),
85 I2400M_FW_POKE(0x080550, 0x00000005),
86 I2400M_FW_POKE(0xAE0000, 0x00000000),
87 I2400M_FW_POKE(0x000000, 0x00000000), /* MUST be 0 terminated or bad
88 * things will happen */
89};
90
91/*
92 * Enable the SDIO function
93 *
94 * Tries to enable the SDIO function; might fail if it is still not
95 * ready (in some hardware, the SDIO WiMAX function is only enabled
96 * when we ask it to explicitly doing). Tries until a timeout is
97 * reached.
98 *
99 * The @maxtries argument indicates how many times (at most) it should
100 * be tried to enable the function. 0 means forever. This acts along
101 * with the timeout (ie: it'll stop trying as soon as the maximum
102 * number of tries is reached _or_ as soon as the timeout is reached).
103 *
104 * The reverse of this is...sdio_disable_function()
105 *
106 * Returns: 0 if the SDIO function was enabled, < 0 errno code on
107 * error (-ENODEV when it was unable to enable the function).
108 */
109static
110int i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries)
111{
112 struct sdio_func *func = i2400ms->func;
113 u64 timeout;
114 int err;
115 struct device *dev = &func->dev;
116 unsigned tries = 0;
117
118 d_fnstart(3, dev, "(func %p)\n", func);
119 /* Setup timeout (FIXME: This needs to read the CIS table to
120 * get a real timeout) and then wait for the device to signal
121 * it is ready */
122 timeout = get_jiffies_64() + ioe_timeout * HZ;
123 err = -ENODEV;
124 while (err != 0 && time_before64(get_jiffies_64(), timeout)) {
125 sdio_claim_host(func);
126 /*
127 * There is a sillicon bug on the IWMC3200, where the
128 * IOE timeout will cause problems on Moorestown
129 * platforms (system hang). We explicitly overwrite
130 * func->enable_timeout here to work around the issue.
131 */
132 if (i2400ms->iwmc3200)
133 func->enable_timeout = IWMC3200_IOR_TIMEOUT;
134 err = sdio_enable_func(func);
135 if (0 == err) {
136 sdio_release_host(func);
137 d_printf(2, dev, "SDIO function enabled\n");
138 goto function_enabled;
139 }
140 d_printf(2, dev, "SDIO function failed to enable: %d\n", err);
141 sdio_release_host(func);
142 if (maxtries > 0 && ++tries >= maxtries) {
143 err = -ETIME;
144 break;
145 }
146 msleep(I2400MS_INIT_SLEEP_INTERVAL);
147 }
148 /* If timed out, device is not there yet -- get -ENODEV so
149 * the device driver core will retry later on. */
150 if (err == -ETIME) {
151 dev_err(dev, "Can't enable WiMAX function; "
152 " has the function been enabled?\n");
153 err = -ENODEV;
154 }
155function_enabled:
156 d_fnend(3, dev, "(func %p) = %d\n", func, err);
157 return err;
158}
159
160
161/*
162 * Setup minimal device communication infrastructure needed to at
163 * least be able to update the firmware.
164 *
165 * Note the ugly trick: if we are in the probe path
166 * (i2400ms->debugfs_dentry == NULL), we only retry function
167 * enablement one, to avoid racing with the iwmc3200 top controller.
168 */
169static
170int i2400ms_bus_setup(struct i2400m *i2400m)
171{
172 int result;
173 struct i2400ms *i2400ms =
174 container_of(i2400m, struct i2400ms, i2400m);
175 struct device *dev = i2400m_dev(i2400m);
176 struct sdio_func *func = i2400ms->func;
177 int retries;
178
179 sdio_claim_host(func);
180 result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
181 sdio_release_host(func);
182 if (result < 0) {
183 dev_err(dev, "Failed to set block size: %d\n", result);
184 goto error_set_blk_size;
185 }
186
187 if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL)
188 retries = 1;
189 else
190 retries = 0;
191 result = i2400ms_enable_function(i2400ms, retries);
192 if (result < 0) {
193 dev_err(dev, "Cannot enable SDIO function: %d\n", result);
194 goto error_func_enable;
195 }
196
197 result = i2400ms_tx_setup(i2400ms);
198 if (result < 0)
199 goto error_tx_setup;
200 result = i2400ms_rx_setup(i2400ms);
201 if (result < 0)
202 goto error_rx_setup;
203 return 0;
204
205error_rx_setup:
206 i2400ms_tx_release(i2400ms);
207error_tx_setup:
208 sdio_claim_host(func);
209 sdio_disable_func(func);
210 sdio_release_host(func);
211error_func_enable:
212error_set_blk_size:
213 return result;
214}
215
216
217/*
218 * Tear down minimal device communication infrastructure needed to at
219 * least be able to update the firmware.
220 */
221static
222void i2400ms_bus_release(struct i2400m *i2400m)
223{
224 struct i2400ms *i2400ms =
225 container_of(i2400m, struct i2400ms, i2400m);
226 struct sdio_func *func = i2400ms->func;
227
228 i2400ms_rx_release(i2400ms);
229 i2400ms_tx_release(i2400ms);
230 sdio_claim_host(func);
231 sdio_disable_func(func);
232 sdio_release_host(func);
233}
234
235
236/*
237 * Setup driver resources needed to communicate with the device
238 *
239 * The fw needs some time to settle, and it was just uploaded,
240 * so give it a break first. I'd prefer to just wait for the device to
241 * send something, but seems the poking we do to enable SDIO stuff
242 * interferes with it, so just give it a break before starting...
243 */
244static
245int i2400ms_bus_dev_start(struct i2400m *i2400m)
246{
247 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
248 struct sdio_func *func = i2400ms->func;
249 struct device *dev = &func->dev;
250
251 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
252 msleep(200);
253 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, 0);
254 return 0;
255}
256
257
258/*
259 * Sends a barker buffer to the device
260 *
261 * This helper will allocate a kmalloced buffer and use it to transmit
262 * (then free it). Reason for this is that the SDIO host controller
263 * expects alignment (unknown exactly which) which the stack won't
264 * really provide and certain arches/host-controller combinations
265 * cannot use stack/vmalloc/text areas for DMA transfers.
266 */
267static
268int __i2400ms_send_barker(struct i2400ms *i2400ms,
269 const __le32 *barker, size_t barker_size)
270{
271 int ret;
272 struct sdio_func *func = i2400ms->func;
273 struct device *dev = &func->dev;
274 void *buffer;
275
276 ret = -ENOMEM;
277 buffer = kmalloc(I2400MS_BLK_SIZE, GFP_KERNEL);
278 if (buffer == NULL)
279 goto error_kzalloc;
280
281 memcpy(buffer, barker, barker_size);
282 sdio_claim_host(func);
283 ret = sdio_memcpy_toio(func, 0, buffer, I2400MS_BLK_SIZE);
284 sdio_release_host(func);
285
286 if (ret < 0)
287 d_printf(0, dev, "E: barker error: %d\n", ret);
288
289 kfree(buffer);
290error_kzalloc:
291 return ret;
292}
293
294
295/*
296 * Reset a device at different levels (warm, cold or bus)
297 *
298 * @i2400ms: device descriptor
299 * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS)
300 *
301 * FIXME: not tested -- need to confirm expected effects
302 *
303 * Warm and cold resets get an SDIO reset if they fail (unimplemented)
304 *
305 * Warm reset:
306 *
307 * The device will be fully reset internally, but won't be
308 * disconnected from the bus (so no reenumeration will
309 * happen). Firmware upload will be necessary.
310 *
311 * The device will send a reboot barker that will trigger the driver
312 * to reinitialize the state via __i2400m_dev_reset_handle.
313 *
314 *
315 * Cold and bus reset:
316 *
317 * The device will be fully reset internally, disconnected from the
318 * bus an a reenumeration will happen. Firmware upload will be
319 * necessary. Thus, we don't do any locking or struct
320 * reinitialization, as we are going to be fully disconnected and
321 * reenumerated.
322 *
323 * Note we need to return -ENODEV if a warm reset was requested and we
324 * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset()
325 * and wimax_dev->op_reset.
326 *
327 * WARNING: no driver state saved/fixed
328 */
329static
330int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
331{
332 int result = 0;
333 struct i2400ms *i2400ms =
334 container_of(i2400m, struct i2400ms, i2400m);
335 struct device *dev = i2400m_dev(i2400m);
336 static const __le32 i2400m_WARM_BOOT_BARKER[4] = {
337 cpu_to_le32(I2400M_WARM_RESET_BARKER),
338 cpu_to_le32(I2400M_WARM_RESET_BARKER),
339 cpu_to_le32(I2400M_WARM_RESET_BARKER),
340 cpu_to_le32(I2400M_WARM_RESET_BARKER),
341 };
342 static const __le32 i2400m_COLD_BOOT_BARKER[4] = {
343 cpu_to_le32(I2400M_COLD_RESET_BARKER),
344 cpu_to_le32(I2400M_COLD_RESET_BARKER),
345 cpu_to_le32(I2400M_COLD_RESET_BARKER),
346 cpu_to_le32(I2400M_COLD_RESET_BARKER),
347 };
348
349 if (rt == I2400M_RT_WARM)
350 result = __i2400ms_send_barker(i2400ms, i2400m_WARM_BOOT_BARKER,
351 sizeof(i2400m_WARM_BOOT_BARKER));
352 else if (rt == I2400M_RT_COLD)
353 result = __i2400ms_send_barker(i2400ms, i2400m_COLD_BOOT_BARKER,
354 sizeof(i2400m_COLD_BOOT_BARKER));
355 else if (rt == I2400M_RT_BUS) {
356do_bus_reset:
357
358 i2400ms_bus_release(i2400m);
359
360 /* Wait for the device to settle */
361 msleep(40);
362
363 result = i2400ms_bus_setup(i2400m);
364 } else
365 BUG();
366 if (result < 0 && rt != I2400M_RT_BUS) {
367 dev_err(dev, "%s reset failed (%d); trying SDIO reset\n",
368 rt == I2400M_RT_WARM ? "warm" : "cold", result);
369 rt = I2400M_RT_BUS;
370 goto do_bus_reset;
371 }
372 return result;
373}
374
375
376static
377void i2400ms_netdev_setup(struct net_device *net_dev)
378{
379 struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
380 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
381 i2400ms_init(i2400ms);
382 i2400m_netdev_setup(net_dev);
383}
384
385
386/*
387 * Debug levels control; see debug.h
388 */
389struct d_level D_LEVEL[] = {
390 D_SUBMODULE_DEFINE(main),
391 D_SUBMODULE_DEFINE(tx),
392 D_SUBMODULE_DEFINE(rx),
393 D_SUBMODULE_DEFINE(fw),
394};
395size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
396
397
398#define __debugfs_register(prefix, name, parent) \
399do { \
400 result = d_level_register_debugfs(prefix, name, parent); \
401 if (result < 0) \
402 goto error; \
403} while (0)
404
405
406static
407int i2400ms_debugfs_add(struct i2400ms *i2400ms)
408{
409 int result;
410 struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry;
411
412 dentry = debugfs_create_dir("i2400m-sdio", dentry);
413 result = PTR_ERR(dentry);
414 if (IS_ERR(dentry)) {
415 if (result == -ENODEV)
416 result = 0; /* No debugfs support */
417 goto error;
418 }
419 i2400ms->debugfs_dentry = dentry;
420 __debugfs_register("dl_", main, dentry);
421 __debugfs_register("dl_", tx, dentry);
422 __debugfs_register("dl_", rx, dentry);
423 __debugfs_register("dl_", fw, dentry);
424
425 return 0;
426
427error:
428 debugfs_remove_recursive(i2400ms->debugfs_dentry);
429 i2400ms->debugfs_dentry = NULL;
430 return result;
431}
432
433
434static struct device_type i2400ms_type = {
435 .name = "wimax",
436};
437
438/*
439 * Probe a i2400m interface and register it
440 *
441 * @func: SDIO function
442 * @id: SDIO device ID
443 * @returns: 0 if ok, < 0 errno code on error.
444 *
445 * Alloc a net device, initialize the bus-specific details and then
446 * calls the bus-generic initialization routine. That will register
447 * the wimax and netdev devices, upload the firmware [using
448 * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
449 * communication with the device and then will start to talk to it to
450 * finnish setting it up.
451 *
452 * Initialization is tricky; some instances of the hw are packed with
453 * others in a way that requires a third driver that enables the WiMAX
454 * function. In those cases, we can't enable the SDIO function and
455 * we'll return with -ENODEV. When the driver that enables the WiMAX
456 * function does its thing, it has to do a bus_rescan_devices() on the
457 * SDIO bus so this driver is called again to enumerate the WiMAX
458 * function.
459 */
460static
461int i2400ms_probe(struct sdio_func *func,
462 const struct sdio_device_id *id)
463{
464 int result;
465 struct net_device *net_dev;
466 struct device *dev = &func->dev;
467 struct i2400m *i2400m;
468 struct i2400ms *i2400ms;
469
470 /* Allocate instance [calls i2400m_netdev_setup() on it]. */
471 result = -ENOMEM;
472 net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d",
473 i2400ms_netdev_setup);
474 if (net_dev == NULL) {
475 dev_err(dev, "no memory for network device instance\n");
476 goto error_alloc_netdev;
477 }
478 SET_NETDEV_DEV(net_dev, dev);
479 SET_NETDEV_DEVTYPE(net_dev, &i2400ms_type);
480 i2400m = net_dev_to_i2400m(net_dev);
481 i2400ms = container_of(i2400m, struct i2400ms, i2400m);
482 i2400m->wimax_dev.net_dev = net_dev;
483 i2400ms->func = func;
484 sdio_set_drvdata(func, i2400ms);
485
486 i2400m->bus_tx_block_size = I2400MS_BLK_SIZE;
487 /*
488 * Room required in the TX queue for SDIO message to accommodate
489 * a smallest payload while allocating header space is 224 bytes,
490 * which is the smallest message size(the block size 256 bytes)
491 * minus the smallest message header size(32 bytes).
492 */
493 i2400m->bus_tx_room_min = I2400MS_BLK_SIZE - I2400M_PL_ALIGN * 2;
494 i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX;
495 i2400m->bus_setup = i2400ms_bus_setup;
496 i2400m->bus_dev_start = i2400ms_bus_dev_start;
497 i2400m->bus_dev_stop = NULL;
498 i2400m->bus_release = i2400ms_bus_release;
499 i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
500 i2400m->bus_reset = i2400ms_bus_reset;
501 /* The iwmc3200-wimax sometimes requires the driver to try
502 * hard when we paint it into a corner. */
503 i2400m->bus_bm_retries = I2400M_SDIO_BOOT_RETRIES;
504 i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send;
505 i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack;
506 i2400m->bus_fw_names = i2400ms_bus_fw_names;
507 i2400m->bus_bm_mac_addr_impaired = 1;
508 i2400m->bus_bm_pokes_table = &i2400ms_pokes[0];
509
510 switch (func->device) {
511 case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX:
512 case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5:
513 i2400ms->iwmc3200 = 1;
514 break;
515 default:
516 i2400ms->iwmc3200 = 0;
517 }
518
519 result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT);
520 if (result < 0) {
521 dev_err(dev, "cannot setup device: %d\n", result);
522 goto error_setup;
523 }
524
525 result = i2400ms_debugfs_add(i2400ms);
526 if (result < 0) {
527 dev_err(dev, "cannot create SDIO debugfs: %d\n",
528 result);
529 goto error_debugfs_add;
530 }
531 return 0;
532
533error_debugfs_add:
534 i2400m_release(i2400m);
535error_setup:
536 sdio_set_drvdata(func, NULL);
537 free_netdev(net_dev);
538error_alloc_netdev:
539 return result;
540}
541
542
543static
544void i2400ms_remove(struct sdio_func *func)
545{
546 struct device *dev = &func->dev;
547 struct i2400ms *i2400ms = sdio_get_drvdata(func);
548 struct i2400m *i2400m = &i2400ms->i2400m;
549 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
550
551 d_fnstart(3, dev, "SDIO func %p\n", func);
552 debugfs_remove_recursive(i2400ms->debugfs_dentry);
553 i2400ms->debugfs_dentry = NULL;
554 i2400m_release(i2400m);
555 sdio_set_drvdata(func, NULL);
556 free_netdev(net_dev);
557 d_fnend(3, dev, "SDIO func %p\n", func);
558}
559
560static
561const struct sdio_device_id i2400ms_sdio_ids[] = {
562 /* Intel: i2400m WiMAX (iwmc3200) over SDIO */
563 { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
564 SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) },
565 { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
566 SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5) },
567 { /* end: all zeroes */ },
568};
569MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids);
570
571
572static
573struct sdio_driver i2400m_sdio_driver = {
574 .name = KBUILD_MODNAME,
575 .probe = i2400ms_probe,
576 .remove = i2400ms_remove,
577 .id_table = i2400ms_sdio_ids,
578};
579
580
581static
582int __init i2400ms_driver_init(void)
583{
584 d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400ms_debug_params,
585 "i2400m_sdio.debug");
586 return sdio_register_driver(&i2400m_sdio_driver);
587}
588module_init(i2400ms_driver_init);
589
590
591static
592void __exit i2400ms_driver_exit(void)
593{
594 sdio_unregister_driver(&i2400m_sdio_driver);
595}
596module_exit(i2400ms_driver_exit);
597
598
599MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
600MODULE_DESCRIPTION("Intel 2400M WiMAX networking for SDIO");
601MODULE_LICENSE("GPL");
602MODULE_FIRMWARE(I2400MS_FW_FILE_NAME);