| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 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 | 
| John W. Linville | 5da7b2e | 2012-07-10 16:27:28 -0400 | [diff] [blame] | 49 |  * device is connected to (USB, PCI, tam-tam...non-authoritative | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 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 |  * | 
| Justin P. Mattock | 42b2aa8 | 2011-11-28 20:31:00 -0800 | [diff] [blame] | 78 |  *  - control ops: control.c - implements various commands for | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 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 | 
| Inaky Perez-Gonzalez | 8f90f3e | 2009-09-16 17:53:57 -0700 | [diff] [blame] | 120 |  * can register a network device. | 
 | 121 |  * | 
 | 122 |  * The high-level call flow is: | 
 | 123 |  * | 
 | 124 |  * bus_probe() | 
 | 125 |  *   i2400m_setup() | 
| Inaky Perez-Gonzalez | 0856ccf | 2009-09-16 18:23:27 -0700 | [diff] [blame] | 126 |  *     i2400m->bus_setup() | 
| Inaky Perez-Gonzalez | 8f90f3e | 2009-09-16 17:53:57 -0700 | [diff] [blame] | 127 |  *     boot rom initialization / read mac addr | 
 | 128 |  *     network / WiMAX stacks registration | 
 | 129 |  *     i2400m_dev_start() | 
 | 130 |  *       i2400m->bus_dev_start() | 
 | 131 |  *       i2400m_dev_initialize() | 
 | 132 |  * | 
 | 133 |  * The reverse applies for a disconnect() call: | 
 | 134 |  * | 
 | 135 |  * bus_disconnect() | 
 | 136 |  *   i2400m_release() | 
 | 137 |  *     i2400m_dev_stop() | 
 | 138 |  *       i2400m_dev_shutdown() | 
 | 139 |  *       i2400m->bus_dev_stop() | 
 | 140 |  *     network / WiMAX stack unregistration | 
| Inaky Perez-Gonzalez | 0856ccf | 2009-09-16 18:23:27 -0700 | [diff] [blame] | 141 |  *     i2400m->bus_release() | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 142 |  * | 
 | 143 |  * At this point, control and data communications are possible. | 
 | 144 |  * | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 145 |  * While the device is up, it might reset. The bus-specific driver has | 
 | 146 |  * to catch that situation and call i2400m_dev_reset_handle() to deal | 
 | 147 |  * with it (reset the internal driver structures and go back to square | 
 | 148 |  * one). | 
 | 149 |  */ | 
 | 150 |  | 
 | 151 | #ifndef __I2400M_H__ | 
 | 152 | #define __I2400M_H__ | 
 | 153 |  | 
 | 154 | #include <linux/usb.h> | 
 | 155 | #include <linux/netdevice.h> | 
 | 156 | #include <linux/completion.h> | 
 | 157 | #include <linux/rwsem.h> | 
| Arun Sharma | 60063497 | 2011-07-26 16:09:06 -0700 | [diff] [blame] | 158 | #include <linux/atomic.h> | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 159 | #include <net/wimax.h> | 
 | 160 | #include <linux/wimax/i2400m.h> | 
 | 161 | #include <asm/byteorder.h> | 
 | 162 |  | 
| Prasanna S. Panchamukhi | 080de04 | 2010-01-26 19:44:44 -0700 | [diff] [blame] | 163 | enum { | 
 | 164 | /* netdev interface */ | 
 | 165 | 	/* | 
 | 166 | 	 * Out of NWG spec (R1_v1.2.2), 3.3.3 ASN Bearer Plane MTU Size | 
 | 167 | 	 * | 
 | 168 | 	 * The MTU is 1400 or less | 
 | 169 | 	 */ | 
 | 170 | 	I2400M_MAX_MTU = 1400, | 
 | 171 | }; | 
 | 172 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 173 | /* Misc constants */ | 
 | 174 | enum { | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 175 | 	/* Size of the Boot Mode Command buffer */ | 
 | 176 | 	I2400M_BM_CMD_BUF_SIZE = 16 * 1024, | 
 | 177 | 	I2400M_BM_ACK_BUF_SIZE = 256, | 
 | 178 | }; | 
 | 179 |  | 
| Cindy H Kao | f4e4134 | 2010-04-07 19:42:42 -0700 | [diff] [blame] | 180 | enum { | 
 | 181 | 	/* Maximum number of bus reset can be retried */ | 
 | 182 | 	I2400M_BUS_RESET_RETRIES = 3, | 
 | 183 | }; | 
 | 184 |  | 
| Dirk Brandewie | 7308a0c | 2009-05-21 11:56:34 -0700 | [diff] [blame] | 185 | /** | 
 | 186 |  * struct i2400m_poke_table - Hardware poke table for the Intel 2400m | 
 | 187 |  * | 
 | 188 |  * This structure will be used to create a device specific poke table | 
| Uwe Kleine-König | a34f0b3 | 2010-12-10 14:55:42 +0100 | [diff] [blame] | 189 |  * to put the device in a consistent state at boot time. | 
| Dirk Brandewie | 7308a0c | 2009-05-21 11:56:34 -0700 | [diff] [blame] | 190 |  * | 
 | 191 |  * @address: The device address to poke | 
 | 192 |  * | 
 | 193 |  * @data: The data value to poke to the device address | 
 | 194 |  * | 
 | 195 |  */ | 
 | 196 | struct i2400m_poke_table{ | 
 | 197 | 	__le32 address; | 
 | 198 | 	__le32 data; | 
 | 199 | }; | 
 | 200 |  | 
 | 201 | #define I2400M_FW_POKE(a, d) {		\ | 
 | 202 | 	.address = cpu_to_le32(a),	\ | 
 | 203 | 	.data = cpu_to_le32(d)		\ | 
 | 204 | } | 
 | 205 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 206 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 207 | /** | 
 | 208 |  * i2400m_reset_type - methods to reset a device | 
 | 209 |  * | 
 | 210 |  * @I2400M_RT_WARM: Reset without device disconnection, device handles | 
 | 211 |  *     are kept valid but state is back to power on, with firmware | 
 | 212 |  *     re-uploaded. | 
 | 213 |  * @I2400M_RT_COLD: Tell the device to disconnect itself from the bus | 
 | 214 |  *     and reconnect. Renders all device handles invalid. | 
 | 215 |  * @I2400M_RT_BUS: Tells the bus to reset the device; last measure | 
 | 216 |  *     used when both types above don't work. | 
 | 217 |  */ | 
 | 218 | enum i2400m_reset_type { | 
 | 219 | 	I2400M_RT_WARM,	/* first measure */ | 
 | 220 | 	I2400M_RT_COLD,	/* second measure */ | 
 | 221 | 	I2400M_RT_BUS,	/* call in artillery */ | 
 | 222 | }; | 
 | 223 |  | 
 | 224 | struct i2400m_reset_ctx; | 
| Inaky Perez-Gonzalez | c747583 | 2009-02-28 23:42:54 +0000 | [diff] [blame] | 225 | struct i2400m_roq; | 
| Inaky Perez-Gonzalez | aba3792a | 2009-09-03 15:14:29 -0700 | [diff] [blame] | 226 | struct i2400m_barker_db; | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 227 |  | 
 | 228 | /** | 
 | 229 |  * struct i2400m - descriptor for an Intel 2400m | 
 | 230 |  * | 
 | 231 |  * Members marked with [fill] must be filled out/initialized before | 
 | 232 |  * calling i2400m_setup(). | 
 | 233 |  * | 
| Inaky Perez-Gonzalez | 0856ccf | 2009-09-16 18:23:27 -0700 | [diff] [blame] | 234 |  * Note the @bus_setup/@bus_release, @bus_dev_start/@bus_dev_release | 
 | 235 |  * call pairs are very much doing almost the same, and depending on | 
 | 236 |  * the underlying bus, some stuff has to be put in one or the | 
 | 237 |  * other. The idea of setup/release is that they setup the minimal | 
 | 238 |  * amount needed for loading firmware, where us dev_start/stop setup | 
 | 239 |  * the rest needed to do full data/control traffic. | 
 | 240 |  * | 
| John W. Linville | 5da7b2e | 2012-07-10 16:27:28 -0400 | [diff] [blame] | 241 |  * @bus_tx_block_size: [fill] USB imposes a 16 block size, but other | 
 | 242 |  *     busses will differ.  So we have a tx_blk_size variable that the | 
 | 243 |  *     bus layer sets to tell the engine how much of that we need. | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 244 |  * | 
| Prasanna S. Panchamukhi | 2750290 | 2010-04-13 16:36:19 -0700 | [diff] [blame] | 245 |  * @bus_tx_room_min: [fill] Minimum room required while allocating | 
| John W. Linville | 5da7b2e | 2012-07-10 16:27:28 -0400 | [diff] [blame] | 246 |  *     TX queue's buffer space for message header. USB requires | 
 | 247 |  *     16 bytes. Refer to bus specific driver code for details. | 
| Prasanna S. Panchamukhi | 2750290 | 2010-04-13 16:36:19 -0700 | [diff] [blame] | 248 |  * | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 249 |  * @bus_pl_size_max: [fill] Maximum payload size. | 
 | 250 |  * | 
| Inaky Perez-Gonzalez | 0856ccf | 2009-09-16 18:23:27 -0700 | [diff] [blame] | 251 |  * @bus_setup: [optional fill] Function called by the bus-generic code | 
 | 252 |  *     [i2400m_setup()] to setup the basic bus-specific communications | 
 | 253 |  *     to the the device needed to load firmware. See LIFE CYCLE above. | 
 | 254 |  * | 
 | 255 |  *     NOTE: Doesn't need to upload the firmware, as that is taken | 
 | 256 |  *     care of by the bus-generic code. | 
 | 257 |  * | 
 | 258 |  * @bus_release: [optional fill] Function called by the bus-generic | 
 | 259 |  *     code [i2400m_release()] to shutdown the basic bus-specific | 
 | 260 |  *     communications to the the device needed to load firmware. See | 
 | 261 |  *     LIFE CYCLE above. | 
 | 262 |  * | 
 | 263 |  *     This function does not need to reset the device, just tear down | 
 | 264 |  *     all the host resources created to  handle communication with | 
 | 265 |  *     the device. | 
 | 266 |  * | 
| Inaky Perez-Gonzalez | 097acbe | 2009-10-08 12:33:50 +0900 | [diff] [blame] | 267 |  * @bus_dev_start: [optional fill] Function called by the bus-generic | 
 | 268 |  *     code [i2400m_dev_start()] to do things needed to start the | 
 | 269 |  *     device. See LIFE CYCLE above. | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 270 |  * | 
 | 271 |  *     NOTE: Doesn't need to upload the firmware, as that is taken | 
 | 272 |  *     care of by the bus-generic code. | 
 | 273 |  * | 
| Inaky Perez-Gonzalez | 097acbe | 2009-10-08 12:33:50 +0900 | [diff] [blame] | 274 |  * @bus_dev_stop: [optional fill] Function called by the bus-generic | 
 | 275 |  *     code [i2400m_dev_stop()] to do things needed for stopping the | 
 | 276 |  *     device. See LIFE CYCLE above. | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 277 |  * | 
 | 278 |  *     This function does not need to reset the device, just tear down | 
| Inaky Perez-Gonzalez | 097acbe | 2009-10-08 12:33:50 +0900 | [diff] [blame] | 279 |  *     all the host resources created to handle communication with | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 280 |  *     the device. | 
 | 281 |  * | 
 | 282 |  * @bus_tx_kick: [fill] Function called by the bus-generic code to let | 
 | 283 |  *     the bus-specific code know that there is data available in the | 
 | 284 |  *     TX FIFO for transmission to the device. | 
 | 285 |  * | 
 | 286 |  *     This function cannot sleep. | 
 | 287 |  * | 
 | 288 |  * @bus_reset: [fill] Function called by the bus-generic code to reset | 
 | 289 |  *     the device in in various ways. Doesn't need to wait for the | 
 | 290 |  *     reset to finish. | 
 | 291 |  * | 
 | 292 |  *     If warm or cold reset fail, this function is expected to do a | 
 | 293 |  *     bus-specific reset (eg: USB reset) to get the device to a | 
 | 294 |  *     working state (even if it implies device disconecction). | 
 | 295 |  * | 
 | 296 |  *     Note the warm reset is used by the firmware uploader to | 
 | 297 |  *     reinitialize the device. | 
 | 298 |  * | 
 | 299 |  *     IMPORTANT: this is called very early in the device setup | 
 | 300 |  *     process, so it cannot rely on common infrastructure being laid | 
 | 301 |  *     out. | 
 | 302 |  * | 
| Inaky Perez-Gonzalez | b9ee950 | 2009-10-07 12:34:13 +0900 | [diff] [blame] | 303 |  *     IMPORTANT: don't call reset on RT_BUS with i2400m->init_mutex | 
 | 304 |  *     held, as the .pre/.post reset handlers will deadlock. | 
 | 305 |  * | 
| Inaky Perez-Gonzalez | ecddfd5 | 2009-06-03 16:13:14 +0800 | [diff] [blame] | 306 |  * @bus_bm_retries: [fill] How many times shall a firmware upload / | 
 | 307 |  *     device initialization be retried? Different models of the same | 
 | 308 |  *     device might need different values, hence it is set by the | 
 | 309 |  *     bus-specific driver. Note this value is used in two places, | 
 | 310 |  *     i2400m_fw_dnload() and __i2400m_dev_start(); they won't become | 
 | 311 |  *     multiplicative (__i2400m_dev_start() calling N times | 
 | 312 |  *     i2400m_fw_dnload() and this trying N times to download the | 
 | 313 |  *     firmware), as if __i2400m_dev_start() only retries if the | 
 | 314 |  *     firmware crashed while initializing the device (not in a | 
 | 315 |  *     general case). | 
 | 316 |  * | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 317 |  * @bus_bm_cmd_send: [fill] Function called to send a boot-mode | 
 | 318 |  *     command. Flags are defined in 'enum i2400m_bm_cmd_flags'. This | 
 | 319 |  *     is synchronous and has to return 0 if ok or < 0 errno code in | 
 | 320 |  *     any error condition. | 
 | 321 |  * | 
 | 322 |  * @bus_bm_wait_for_ack: [fill] Function called to wait for a | 
 | 323 |  *     boot-mode notification (that can be a response to a previously | 
 | 324 |  *     issued command or an asynchronous one). Will read until all the | 
 | 325 |  *     indicated size is read or timeout. Reading more or less data | 
 | 326 |  *     than asked for is an error condition. Return 0 if ok, < 0 errno | 
 | 327 |  *     code on error. | 
 | 328 |  * | 
 | 329 |  *     The caller to this function will check if the response is a | 
 | 330 |  *     barker that indicates the device going into reset mode. | 
 | 331 |  * | 
| Inaky Perez-Gonzalez | 1039abb | 2009-02-28 23:42:47 +0000 | [diff] [blame] | 332 |  * @bus_fw_names: [fill] a NULL-terminated array with the names of the | 
 | 333 |  *     firmware images to try loading. This is made a list so we can | 
 | 334 |  *     support backward compatibility of firmware releases (eg: if we | 
 | 335 |  *     can't find the default v1.4, we try v1.3). In general, the name | 
 | 336 |  *     should be i2400m-fw-X-VERSION.sbcf, where X is the bus name. | 
 | 337 |  *     The list is tried in order and the first one that loads is | 
 | 338 |  *     used. The fw loader will set i2400m->fw_name to point to the | 
 | 339 |  *     active firmware image. | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 340 |  * | 
 | 341 |  * @bus_bm_mac_addr_impaired: [fill] Set to true if the device's MAC | 
 | 342 |  *     address provided in boot mode is kind of broken and needs to | 
 | 343 |  *     be re-read later on. | 
 | 344 |  * | 
| Dirk Brandewie | 7308a0c | 2009-05-21 11:56:34 -0700 | [diff] [blame] | 345 |  * @bus_bm_pokes_table: [fill/optional] A table of device addresses | 
 | 346 |  *     and values that will be poked at device init time to move the | 
 | 347 |  *     device to the correct state for the type of boot/firmware being | 
 | 348 |  *     used.  This table MUST be terminated with (0x000000, | 
 | 349 |  *     0x00000000) or bad things will happen. | 
 | 350 |  * | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 351 |  * | 
 | 352 |  * @wimax_dev: WiMAX generic device for linkage into the kernel WiMAX | 
 | 353 |  *     stack. Due to the way a net_device is allocated, we need to | 
 | 354 |  *     force this to be the first field so that we can get from | 
 | 355 |  *     netdev_priv() the right pointer. | 
 | 356 |  * | 
| Inaky Perez-Gonzalez | c2315b4 | 2009-09-16 17:10:55 -0700 | [diff] [blame] | 357 |  * @updown: the device is up and ready for transmitting control and | 
 | 358 |  *     data packets. This implies @ready (communication infrastructure | 
 | 359 |  *     with the device is ready) and the device's firmware has been | 
 | 360 |  *     loaded and the device initialized. | 
 | 361 |  * | 
 | 362 |  *     Write to it only inside a i2400m->init_mutex protected area | 
 | 363 |  *     followed with a wmb(); rmb() before accesing (unless locked | 
 | 364 |  *     inside i2400m->init_mutex). Read access can be loose like that | 
 | 365 |  *     [just using rmb()] because the paths that use this also do | 
 | 366 |  *     other error checks later on. | 
 | 367 |  * | 
 | 368 |  * @ready: Communication infrastructure with the device is ready, data | 
 | 369 |  *     frames can start to be passed around (this is lighter than | 
 | 370 |  *     using the WiMAX state for certain hot paths). | 
 | 371 |  * | 
 | 372 |  *     Write to it only inside a i2400m->init_mutex protected area | 
 | 373 |  *     followed with a wmb(); rmb() before accesing (unless locked | 
 | 374 |  *     inside i2400m->init_mutex). Read access can be loose like that | 
 | 375 |  *     [just using rmb()] because the paths that use this also do | 
 | 376 |  *     other error checks later on. | 
 | 377 |  * | 
| Inaky Perez-Gonzalez | c747583 | 2009-02-28 23:42:54 +0000 | [diff] [blame] | 378 |  * @rx_reorder: 1 if RX reordering is enabled; this can only be | 
 | 379 |  *     set at probe time. | 
 | 380 |  * | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 381 |  * @state: device's state (as reported by it) | 
 | 382 |  * | 
 | 383 |  * @state_wq: waitqueue that is woken up whenever the state changes | 
 | 384 |  * | 
 | 385 |  * @tx_lock: spinlock to protect TX members | 
 | 386 |  * | 
 | 387 |  * @tx_buf: FIFO buffer for TX; we queue data here | 
 | 388 |  * | 
 | 389 |  * @tx_in: FIFO index for incoming data. Note this doesn't wrap around | 
 | 390 |  *     and it is always greater than @tx_out. | 
 | 391 |  * | 
 | 392 |  * @tx_out: FIFO index for outgoing data | 
 | 393 |  * | 
 | 394 |  * @tx_msg: current TX message that is active in the FIFO for | 
 | 395 |  *     appending payloads. | 
 | 396 |  * | 
 | 397 |  * @tx_sequence: current sequence number for TX messages from the | 
 | 398 |  *     device to the host. | 
 | 399 |  * | 
 | 400 |  * @tx_msg_size: size of the current message being transmitted by the | 
 | 401 |  *     bus-specific code. | 
 | 402 |  * | 
 | 403 |  * @tx_pl_num: total number of payloads sent | 
 | 404 |  * | 
 | 405 |  * @tx_pl_max: maximum number of payloads sent in a TX message | 
 | 406 |  * | 
 | 407 |  * @tx_pl_min: minimum number of payloads sent in a TX message | 
 | 408 |  * | 
 | 409 |  * @tx_num: number of TX messages sent | 
 | 410 |  * | 
 | 411 |  * @tx_size_acc: number of bytes in all TX messages sent | 
 | 412 |  *     (this is different to net_dev's statistics as it also counts | 
 | 413 |  *     control messages). | 
 | 414 |  * | 
 | 415 |  * @tx_size_min: smallest TX message sent. | 
 | 416 |  * | 
 | 417 |  * @tx_size_max: biggest TX message sent. | 
 | 418 |  * | 
| Prasanna S. Panchamukhi | d11a6e4 | 2010-04-13 16:35:58 -0700 | [diff] [blame] | 419 |  * @rx_lock: spinlock to protect RX members and rx_roq_refcount. | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 420 |  * | 
 | 421 |  * @rx_pl_num: total number of payloads received | 
 | 422 |  * | 
 | 423 |  * @rx_pl_max: maximum number of payloads received in a RX message | 
 | 424 |  * | 
 | 425 |  * @rx_pl_min: minimum number of payloads received in a RX message | 
 | 426 |  * | 
 | 427 |  * @rx_num: number of RX messages received | 
 | 428 |  * | 
 | 429 |  * @rx_size_acc: number of bytes in all RX messages received | 
 | 430 |  *     (this is different to net_dev's statistics as it also counts | 
 | 431 |  *     control messages). | 
 | 432 |  * | 
 | 433 |  * @rx_size_min: smallest RX message received. | 
 | 434 |  * | 
 | 435 |  * @rx_size_max: buggest RX message received. | 
 | 436 |  * | 
| Inaky Perez-Gonzalez | c747583 | 2009-02-28 23:42:54 +0000 | [diff] [blame] | 437 |  * @rx_roq: RX ReOrder queues. (fw >= v1.4) When packets are received | 
 | 438 |  *     out of order, the device will ask the driver to hold certain | 
 | 439 |  *     packets until the ones that are received out of order can be | 
 | 440 |  *     delivered. Then the driver can release them to the host. See | 
 | 441 |  *     drivers/net/i2400m/rx.c for details. | 
 | 442 |  * | 
| Prasanna S. Panchamukhi | d11a6e4 | 2010-04-13 16:35:58 -0700 | [diff] [blame] | 443 |  * @rx_roq_refcount: refcount rx_roq. This refcounts any access to | 
 | 444 |  *     rx_roq thus preventing rx_roq being destroyed when rx_roq | 
 | 445 |  *     is being accessed. rx_roq_refcount is protected by rx_lock. | 
 | 446 |  * | 
| Inaky Perez-Gonzalez | a0beba2 | 2009-10-07 21:43:10 +0900 | [diff] [blame] | 447 |  * @rx_reports: reports received from the device that couldn't be | 
 | 448 |  *     processed because the driver wasn't still ready; when ready, | 
 | 449 |  *     they are pulled from here and chewed. | 
 | 450 |  * | 
 | 451 |  * @rx_reports_ws: Work struct used to kick a scan of the RX reports | 
 | 452 |  *     list and to process each. | 
 | 453 |  * | 
| Inaky Perez-Gonzalez | fe44268 | 2009-04-22 16:53:08 -0700 | [diff] [blame] | 454 |  * @src_mac_addr: MAC address used to make ethernet packets be coming | 
 | 455 |  *     from. This is generated at i2400m_setup() time and used during | 
 | 456 |  *     the life cycle of the instance. See i2400m_fake_eth_header(). | 
 | 457 |  * | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 458 |  * @init_mutex: Mutex used for serializing the device bringup | 
 | 459 |  *     sequence; this way if the device reboots in the middle, we | 
 | 460 |  *     don't try to do a bringup again while we are tearing down the | 
 | 461 |  *     one that failed. | 
 | 462 |  * | 
 | 463 |  *     Can't reuse @msg_mutex because from within the bringup sequence | 
 | 464 |  *     we need to send messages to the device and thus use @msg_mutex. | 
 | 465 |  * | 
 | 466 |  * @msg_mutex: mutex used to send control commands to the device (we | 
 | 467 |  *     only allow one at a time, per host-device interface design). | 
 | 468 |  * | 
 | 469 |  * @msg_completion: used to wait for an ack to a control command sent | 
 | 470 |  *     to the device. | 
 | 471 |  * | 
 | 472 |  * @ack_skb: used to store the actual ack to a control command if the | 
 | 473 |  *     reception of the command was successful. Otherwise, a ERR_PTR() | 
 | 474 |  *     errno code that indicates what failed with the ack reception. | 
 | 475 |  * | 
 | 476 |  *     Only valid after @msg_completion is woken up. Only updateable | 
 | 477 |  *     if @msg_completion is armed. Only touched by | 
 | 478 |  *     i2400m_msg_to_dev(). | 
 | 479 |  * | 
 | 480 |  *     Protected by @rx_lock. In theory the command execution flow is | 
 | 481 |  *     sequential, but in case the device sends an out-of-phase or | 
 | 482 |  *     very delayed response, we need to avoid it trampling current | 
 | 483 |  *     execution. | 
 | 484 |  * | 
 | 485 |  * @bm_cmd_buf: boot mode command buffer for composing firmware upload | 
 | 486 |  *     commands. | 
 | 487 |  * | 
 | 488 |  *     USB can't r/w to stack, vmalloc, etc...as well, we end up | 
 | 489 |  *     having to alloc/free a lot to compose commands, so we use these | 
 | 490 |  *     for stagging and not having to realloc all the time. | 
 | 491 |  * | 
 | 492 |  *     This assumes the code always runs serialized. Only one thread | 
 | 493 |  *     can call i2400m_bm_cmd() at the same time. | 
 | 494 |  * | 
 | 495 |  * @bm_ack_buf: boot mode acknoledge buffer for staging reception of | 
 | 496 |  *     responses to commands. | 
 | 497 |  * | 
 | 498 |  *     See @bm_cmd_buf. | 
 | 499 |  * | 
 | 500 |  * @work_queue: work queue for processing device reports. This | 
 | 501 |  *     workqueue cannot be used for processing TX or RX to the device, | 
 | 502 |  *     as from it we'll process device reports, which might require | 
 | 503 |  *     further communication with the device. | 
 | 504 |  * | 
 | 505 |  * @debugfs_dentry: hookup for debugfs files. | 
 | 506 |  *     These have to be in a separate directory, a child of | 
 | 507 |  *     (wimax_dev->debugfs_dentry) so they can be removed when the | 
 | 508 |  *     module unloads, as we don't keep each dentry. | 
| Inaky Perez-Gonzalez | 1039abb | 2009-02-28 23:42:47 +0000 | [diff] [blame] | 509 |  * | 
 | 510 |  * @fw_name: name of the firmware image that is currently being used. | 
| Inaky Perez-Gonzalez | 6a0f7ab | 2009-02-28 23:42:49 +0000 | [diff] [blame] | 511 |  * | 
 | 512 |  * @fw_version: version of the firmware interface, Major.minor, | 
 | 513 |  *     encoded in the high word and low word (major << 16 | minor). | 
| Inaky Perez-Gonzalez | aba3792a | 2009-09-03 15:14:29 -0700 | [diff] [blame] | 514 |  * | 
| Inaky Perez-Gonzalez | bfc4418 | 2009-09-04 17:07:21 -0700 | [diff] [blame] | 515 |  * @fw_hdrs: NULL terminated array of pointers to the firmware | 
 | 516 |  *     headers. This is only available during firmware load time. | 
 | 517 |  * | 
| Inaky Perez-Gonzalez | 7b43ca7 | 2009-09-14 14:10:16 -0700 | [diff] [blame] | 518 |  * @fw_cached: Used to cache firmware when the system goes to | 
 | 519 |  *     suspend/standby/hibernation (as on resume we can't read it). If | 
 | 520 |  *     NULL, no firmware was cached, read it. If ~0, you can't read | 
 | 521 |  *     any firmware files (the system still didn't come out of suspend | 
 | 522 |  *     and failed to cache one), so abort; otherwise, a valid cached | 
 | 523 |  *     firmware to be used. Access to this variable is protected by | 
 | 524 |  *     the spinlock i2400m->rx_lock. | 
 | 525 |  * | 
| Inaky Perez-Gonzalez | aba3792a | 2009-09-03 15:14:29 -0700 | [diff] [blame] | 526 |  * @barker: barker type that the device uses; this is initialized by | 
 | 527 |  *     i2400m_is_boot_barker() the first time it is called. Then it | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 528 |  *     won't change during the life cycle of the device and every time | 
| Inaky Perez-Gonzalez | aba3792a | 2009-09-03 15:14:29 -0700 | [diff] [blame] | 529 |  *     a boot barker is received, it is just verified for it being the | 
 | 530 |  *     same. | 
| Inaky Perez-Gonzalez | 7b43ca7 | 2009-09-14 14:10:16 -0700 | [diff] [blame] | 531 |  * | 
 | 532 |  * @pm_notifier: used to register for PM events | 
| Cindy H Kao | f4e4134 | 2010-04-07 19:42:42 -0700 | [diff] [blame] | 533 |  * | 
 | 534 |  * @bus_reset_retries: counter for the number of bus resets attempted for | 
 | 535 |  *	this boot. It's not for tracking the number of bus resets during | 
 | 536 |  *	the whole driver life cycle (from insmod to rmmod) but for the | 
 | 537 |  *	number of dev_start() executed until dev_start() returns a success | 
 | 538 |  *	(ie: a good boot means a dev_stop() followed by a successful | 
 | 539 |  *	dev_start()). dev_reset_handler() increments this counter whenever | 
 | 540 |  *	it is triggering a bus reset. It checks this counter to decide if a | 
 | 541 |  *	subsequent bus reset should be retried. dev_reset_handler() retries | 
 | 542 |  *	the bus reset until dev_start() succeeds or the counter reaches | 
 | 543 |  *	I2400M_BUS_RESET_RETRIES. The counter is cleared to 0 in | 
 | 544 |  *	dev_reset_handle() when dev_start() returns a success, | 
 | 545 |  *	ie: a successul boot is completed. | 
 | 546 |  * | 
 | 547 |  * @alive: flag to denote if the device *should* be alive. This flag is | 
 | 548 |  *	everything like @updown (see doc for @updown) except reflecting | 
 | 549 |  *	the device state *we expect* rather than the actual state as denoted | 
 | 550 |  *	by @updown. It is set 1 whenever @updown is set 1 in dev_start(). | 
 | 551 |  *	Then the device is expected to be alive all the time | 
 | 552 |  *	(i2400m->alive remains 1) until the driver is removed. Therefore | 
 | 553 |  *	all the device reboot events detected can be still handled properly | 
 | 554 |  *	by either dev_reset_handle() or .pre_reset/.post_reset as long as | 
 | 555 |  *	the driver presents. It is set 0 along with @updown in dev_stop(). | 
| Cindy H Kao | 599e595 | 2010-04-07 20:07:47 -0700 | [diff] [blame] | 556 |  * | 
 | 557 |  * @error_recovery: flag to denote if we are ready to take an error recovery. | 
 | 558 |  *	0 for ready to take an error recovery; 1 for not ready. It is | 
 | 559 |  *	initialized to 1 while probe() since we don't tend to take any error | 
 | 560 |  *	recovery during probe(). It is decremented by 1 whenever dev_start() | 
 | 561 |  *	succeeds to indicate we are ready to take error recovery from now on. | 
 | 562 |  *	It is checked every time we wanna schedule an error recovery. If an | 
 | 563 |  *	error recovery is already in place (error_recovery was set 1), we | 
 | 564 |  *	should not schedule another one until the last one is done. | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 565 |  */ | 
 | 566 | struct i2400m { | 
 | 567 | 	struct wimax_dev wimax_dev;	/* FIRST! See doc */ | 
 | 568 |  | 
 | 569 | 	unsigned updown:1;		/* Network device is up or down */ | 
 | 570 | 	unsigned boot_mode:1;		/* is the device in boot mode? */ | 
 | 571 | 	unsigned sboot:1;		/* signed or unsigned fw boot */ | 
| Inaky Perez-Gonzalez | c2315b4 | 2009-09-16 17:10:55 -0700 | [diff] [blame] | 572 | 	unsigned ready:1;		/* Device comm infrastructure ready */ | 
| Inaky Perez-Gonzalez | c747583 | 2009-02-28 23:42:54 +0000 | [diff] [blame] | 573 | 	unsigned rx_reorder:1;		/* RX reorder is enabled */ | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 574 | 	u8 trace_msg_from_user;		/* echo rx msgs to 'trace' pipe */ | 
| GeunSik Lim | 156f5a7 | 2009-06-02 15:01:37 +0900 | [diff] [blame] | 575 | 					/* typed u8 so /sys/kernel/debug/u8 can tweak */ | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 576 | 	enum i2400m_system_state state; | 
 | 577 | 	wait_queue_head_t state_wq;	/* Woken up when on state updates */ | 
 | 578 |  | 
 | 579 | 	size_t bus_tx_block_size; | 
| Prasanna S. Panchamukhi | 2750290 | 2010-04-13 16:36:19 -0700 | [diff] [blame] | 580 | 	size_t bus_tx_room_min; | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 581 | 	size_t bus_pl_size_max; | 
| Inaky Perez-Gonzalez | ecddfd5 | 2009-06-03 16:13:14 +0800 | [diff] [blame] | 582 | 	unsigned bus_bm_retries; | 
 | 583 |  | 
| Inaky Perez-Gonzalez | 0856ccf | 2009-09-16 18:23:27 -0700 | [diff] [blame] | 584 | 	int (*bus_setup)(struct i2400m *); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 585 | 	int (*bus_dev_start)(struct i2400m *); | 
 | 586 | 	void (*bus_dev_stop)(struct i2400m *); | 
| Inaky Perez-Gonzalez | 0856ccf | 2009-09-16 18:23:27 -0700 | [diff] [blame] | 587 | 	void (*bus_release)(struct i2400m *); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 588 | 	void (*bus_tx_kick)(struct i2400m *); | 
 | 589 | 	int (*bus_reset)(struct i2400m *, enum i2400m_reset_type); | 
 | 590 | 	ssize_t (*bus_bm_cmd_send)(struct i2400m *, | 
 | 591 | 				   const struct i2400m_bootrom_header *, | 
 | 592 | 				   size_t, int flags); | 
 | 593 | 	ssize_t (*bus_bm_wait_for_ack)(struct i2400m *, | 
 | 594 | 				       struct i2400m_bootrom_header *, size_t); | 
| Inaky Perez-Gonzalez | 1039abb | 2009-02-28 23:42:47 +0000 | [diff] [blame] | 595 | 	const char **bus_fw_names; | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 596 | 	unsigned bus_bm_mac_addr_impaired:1; | 
| Dirk Brandewie | 7308a0c | 2009-05-21 11:56:34 -0700 | [diff] [blame] | 597 | 	const struct i2400m_poke_table *bus_bm_pokes_table; | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 598 |  | 
 | 599 | 	spinlock_t tx_lock;		/* protect TX state */ | 
 | 600 | 	void *tx_buf; | 
 | 601 | 	size_t tx_in, tx_out; | 
 | 602 | 	struct i2400m_msg_hdr *tx_msg; | 
 | 603 | 	size_t tx_sequence, tx_msg_size; | 
 | 604 | 	/* TX stats */ | 
 | 605 | 	unsigned tx_pl_num, tx_pl_max, tx_pl_min, | 
 | 606 | 		tx_num, tx_size_acc, tx_size_min, tx_size_max; | 
 | 607 |  | 
| Inaky Perez-Gonzalez | c747583 | 2009-02-28 23:42:54 +0000 | [diff] [blame] | 608 | 	/* RX stuff */ | 
| Prasanna S. Panchamukhi | d11a6e4 | 2010-04-13 16:35:58 -0700 | [diff] [blame] | 609 | 	/* protect RX state and rx_roq_refcount */ | 
 | 610 | 	spinlock_t rx_lock; | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 611 | 	unsigned rx_pl_num, rx_pl_max, rx_pl_min, | 
 | 612 | 		rx_num, rx_size_acc, rx_size_min, rx_size_max; | 
| Prasanna S. Panchamukhi | d11a6e4 | 2010-04-13 16:35:58 -0700 | [diff] [blame] | 613 | 	struct i2400m_roq *rx_roq;	/* access is refcounted */ | 
 | 614 | 	struct kref rx_roq_refcount;	/* refcount access to rx_roq */ | 
| Inaky Perez-Gonzalez | fe44268 | 2009-04-22 16:53:08 -0700 | [diff] [blame] | 615 | 	u8 src_mac_addr[ETH_HLEN]; | 
| Inaky Perez-Gonzalez | a0beba2 | 2009-10-07 21:43:10 +0900 | [diff] [blame] | 616 | 	struct list_head rx_reports;	/* under rx_lock! */ | 
 | 617 | 	struct work_struct rx_report_ws; | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 618 |  | 
 | 619 | 	struct mutex msg_mutex;		/* serialize command execution */ | 
 | 620 | 	struct completion msg_completion; | 
 | 621 | 	struct sk_buff *ack_skb;	/* protected by rx_lock */ | 
 | 622 |  | 
 | 623 | 	void *bm_ack_buf;		/* for receiving acks over USB */ | 
 | 624 | 	void *bm_cmd_buf;		/* for issuing commands over USB */ | 
 | 625 |  | 
 | 626 | 	struct workqueue_struct *work_queue; | 
 | 627 |  | 
 | 628 | 	struct mutex init_mutex;	/* protect bringup seq */ | 
 | 629 | 	struct i2400m_reset_ctx *reset_ctx;	/* protected by init_mutex */ | 
 | 630 |  | 
 | 631 | 	struct work_struct wake_tx_ws; | 
 | 632 | 	struct sk_buff *wake_tx_skb; | 
 | 633 |  | 
| Tejun Heo | 781ba45 | 2010-12-12 16:45:14 +0100 | [diff] [blame] | 634 | 	struct work_struct reset_ws; | 
 | 635 | 	const char *reset_reason; | 
 | 636 |  | 
 | 637 | 	struct work_struct recovery_ws; | 
 | 638 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 639 | 	struct dentry *debugfs_dentry; | 
| Inaky Perez-Gonzalez | 1039abb | 2009-02-28 23:42:47 +0000 | [diff] [blame] | 640 | 	const char *fw_name;		/* name of the current firmware image */ | 
| Inaky Perez-Gonzalez | 6a0f7ab | 2009-02-28 23:42:49 +0000 | [diff] [blame] | 641 | 	unsigned long fw_version;	/* version of the firmware interface */ | 
| Inaky Perez-Gonzalez | bfc4418 | 2009-09-04 17:07:21 -0700 | [diff] [blame] | 642 | 	const struct i2400m_bcf_hdr **fw_hdrs; | 
| Inaky Perez-Gonzalez | 7b43ca7 | 2009-09-14 14:10:16 -0700 | [diff] [blame] | 643 | 	struct i2400m_fw *fw_cached;	/* protected by rx_lock */ | 
| Inaky Perez-Gonzalez | aba3792a | 2009-09-03 15:14:29 -0700 | [diff] [blame] | 644 | 	struct i2400m_barker_db *barker; | 
| Inaky Perez-Gonzalez | 7b43ca7 | 2009-09-14 14:10:16 -0700 | [diff] [blame] | 645 |  | 
 | 646 | 	struct notifier_block pm_notifier; | 
| Cindy H Kao | f4e4134 | 2010-04-07 19:42:42 -0700 | [diff] [blame] | 647 |  | 
 | 648 | 	/* counting bus reset retries in this boot */ | 
 | 649 | 	atomic_t bus_reset_retries; | 
 | 650 |  | 
 | 651 | 	/* if the device is expected to be alive */ | 
 | 652 | 	unsigned alive; | 
| Cindy H Kao | 599e595 | 2010-04-07 20:07:47 -0700 | [diff] [blame] | 653 |  | 
 | 654 | 	/* 0 if we are ready for error recovery; 1 if not ready  */ | 
 | 655 | 	atomic_t error_recovery; | 
 | 656 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 657 | }; | 
 | 658 |  | 
 | 659 |  | 
 | 660 | /* | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 661 |  * Bus-generic internal APIs | 
 | 662 |  * ------------------------- | 
 | 663 |  */ | 
 | 664 |  | 
 | 665 | static inline | 
 | 666 | struct i2400m *wimax_dev_to_i2400m(struct wimax_dev *wimax_dev) | 
 | 667 | { | 
 | 668 | 	return container_of(wimax_dev, struct i2400m, wimax_dev); | 
 | 669 | } | 
 | 670 |  | 
 | 671 | static inline | 
 | 672 | struct i2400m *net_dev_to_i2400m(struct net_device *net_dev) | 
 | 673 | { | 
 | 674 | 	return wimax_dev_to_i2400m(netdev_priv(net_dev)); | 
 | 675 | } | 
 | 676 |  | 
 | 677 | /* | 
 | 678 |  * Boot mode support | 
 | 679 |  */ | 
 | 680 |  | 
 | 681 | /** | 
 | 682 |  * i2400m_bm_cmd_flags - flags to i2400m_bm_cmd() | 
 | 683 |  * | 
 | 684 |  * @I2400M_BM_CMD_RAW: send the command block as-is, without doing any | 
 | 685 |  *     extra processing for adding CRC. | 
 | 686 |  */ | 
 | 687 | enum i2400m_bm_cmd_flags { | 
 | 688 | 	I2400M_BM_CMD_RAW	= 1 << 2, | 
 | 689 | }; | 
 | 690 |  | 
 | 691 | /** | 
 | 692 |  * i2400m_bri - Boot-ROM indicators | 
 | 693 |  * | 
 | 694 |  * Flags for i2400m_bootrom_init() and i2400m_dev_bootstrap() [which | 
 | 695 |  * are passed from things like i2400m_setup()]. Can be combined with | 
 | 696 |  * |. | 
 | 697 |  * | 
 | 698 |  * @I2400M_BRI_SOFT: The device rebooted already and a reboot | 
 | 699 |  *     barker received, proceed directly to ack the boot sequence. | 
 | 700 |  * @I2400M_BRI_NO_REBOOT: Do not reboot the device and proceed | 
 | 701 |  *     directly to wait for a reboot barker from the device. | 
 | 702 |  * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot | 
| Daniel Mack | 3ad2f3f | 2010-02-03 08:01:28 +0800 | [diff] [blame] | 703 |  *     rom after reading the MAC address. This is quite a dirty hack, | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 704 |  *     if you ask me -- the device requires the bootrom to be | 
| Uwe Kleine-König | b595076 | 2010-11-01 15:38:34 -0400 | [diff] [blame] | 705 |  *     initialized after reading the MAC address. | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 706 |  */ | 
 | 707 | enum i2400m_bri { | 
 | 708 | 	I2400M_BRI_SOFT       = 1 << 1, | 
 | 709 | 	I2400M_BRI_NO_REBOOT  = 1 << 2, | 
 | 710 | 	I2400M_BRI_MAC_REINIT = 1 << 3, | 
 | 711 | }; | 
 | 712 |  | 
 | 713 | extern void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *); | 
 | 714 | extern int i2400m_dev_bootstrap(struct i2400m *, enum i2400m_bri); | 
 | 715 | extern int i2400m_read_mac_addr(struct i2400m *); | 
 | 716 | extern int i2400m_bootrom_init(struct i2400m *, enum i2400m_bri); | 
| Inaky Perez-Gonzalez | aba3792a | 2009-09-03 15:14:29 -0700 | [diff] [blame] | 717 | extern int i2400m_is_boot_barker(struct i2400m *, const void *, size_t); | 
 | 718 | static inline | 
 | 719 | int i2400m_is_d2h_barker(const void *buf) | 
 | 720 | { | 
 | 721 | 	const __le32 *barker = buf; | 
 | 722 | 	return le32_to_cpu(*barker) == I2400M_D2H_MSG_BARKER; | 
 | 723 | } | 
 | 724 | extern void i2400m_unknown_barker(struct i2400m *, const void *, size_t); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 725 |  | 
 | 726 | /* Make/grok boot-rom header commands */ | 
 | 727 |  | 
 | 728 | static inline | 
 | 729 | __le32 i2400m_brh_command(enum i2400m_brh_opcode opcode, unsigned use_checksum, | 
 | 730 | 			  unsigned direct_access) | 
 | 731 | { | 
 | 732 | 	return cpu_to_le32( | 
 | 733 | 		I2400M_BRH_SIGNATURE | 
 | 734 | 		| (direct_access ? I2400M_BRH_DIRECT_ACCESS : 0) | 
 | 735 | 		| I2400M_BRH_RESPONSE_REQUIRED /* response always required */ | 
 | 736 | 		| (use_checksum ? I2400M_BRH_USE_CHECKSUM : 0) | 
 | 737 | 		| (opcode & I2400M_BRH_OPCODE_MASK)); | 
 | 738 | } | 
 | 739 |  | 
 | 740 | static inline | 
 | 741 | void i2400m_brh_set_opcode(struct i2400m_bootrom_header *hdr, | 
 | 742 | 			   enum i2400m_brh_opcode opcode) | 
 | 743 | { | 
 | 744 | 	hdr->command = cpu_to_le32( | 
 | 745 | 		(le32_to_cpu(hdr->command) & ~I2400M_BRH_OPCODE_MASK) | 
 | 746 | 		| (opcode & I2400M_BRH_OPCODE_MASK)); | 
 | 747 | } | 
 | 748 |  | 
 | 749 | static inline | 
 | 750 | unsigned i2400m_brh_get_opcode(const struct i2400m_bootrom_header *hdr) | 
 | 751 | { | 
 | 752 | 	return le32_to_cpu(hdr->command) & I2400M_BRH_OPCODE_MASK; | 
 | 753 | } | 
 | 754 |  | 
 | 755 | static inline | 
 | 756 | unsigned i2400m_brh_get_response(const struct i2400m_bootrom_header *hdr) | 
 | 757 | { | 
 | 758 | 	return (le32_to_cpu(hdr->command) & I2400M_BRH_RESPONSE_MASK) | 
 | 759 | 		>> I2400M_BRH_RESPONSE_SHIFT; | 
 | 760 | } | 
 | 761 |  | 
 | 762 | static inline | 
 | 763 | unsigned i2400m_brh_get_use_checksum(const struct i2400m_bootrom_header *hdr) | 
 | 764 | { | 
 | 765 | 	return le32_to_cpu(hdr->command) & I2400M_BRH_USE_CHECKSUM; | 
 | 766 | } | 
 | 767 |  | 
 | 768 | static inline | 
 | 769 | unsigned i2400m_brh_get_response_required( | 
 | 770 | 	const struct i2400m_bootrom_header *hdr) | 
 | 771 | { | 
 | 772 | 	return le32_to_cpu(hdr->command) & I2400M_BRH_RESPONSE_REQUIRED; | 
 | 773 | } | 
 | 774 |  | 
 | 775 | static inline | 
 | 776 | unsigned i2400m_brh_get_direct_access(const struct i2400m_bootrom_header *hdr) | 
 | 777 | { | 
 | 778 | 	return le32_to_cpu(hdr->command) & I2400M_BRH_DIRECT_ACCESS; | 
 | 779 | } | 
 | 780 |  | 
 | 781 | static inline | 
 | 782 | unsigned i2400m_brh_get_signature(const struct i2400m_bootrom_header *hdr) | 
 | 783 | { | 
 | 784 | 	return (le32_to_cpu(hdr->command) & I2400M_BRH_SIGNATURE_MASK) | 
 | 785 | 		>> I2400M_BRH_SIGNATURE_SHIFT; | 
 | 786 | } | 
 | 787 |  | 
 | 788 |  | 
 | 789 | /* | 
 | 790 |  * Driver / device setup and internal functions | 
 | 791 |  */ | 
| Inaky Perez-Gonzalez | af77dfa | 2009-10-07 21:37:53 +0900 | [diff] [blame] | 792 | extern void i2400m_init(struct i2400m *); | 
| Inaky Perez-Gonzalez | c931cee | 2009-10-19 16:24:56 +0900 | [diff] [blame] | 793 | extern int i2400m_reset(struct i2400m *, enum i2400m_reset_type); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 794 | extern void i2400m_netdev_setup(struct net_device *net_dev); | 
| Inaky Perez-Gonzalez | 8987691 | 2009-02-28 23:42:50 +0000 | [diff] [blame] | 795 | extern int i2400m_sysfs_setup(struct device_driver *); | 
 | 796 | extern void i2400m_sysfs_release(struct device_driver *); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 797 | extern int i2400m_tx_setup(struct i2400m *); | 
 | 798 | extern void i2400m_wake_tx_work(struct work_struct *); | 
 | 799 | extern void i2400m_tx_release(struct i2400m *); | 
 | 800 |  | 
| Inaky Perez-Gonzalez | c747583 | 2009-02-28 23:42:54 +0000 | [diff] [blame] | 801 | extern int i2400m_rx_setup(struct i2400m *); | 
 | 802 | extern void i2400m_rx_release(struct i2400m *); | 
 | 803 |  | 
| Inaky Perez-Gonzalez | 7b43ca7 | 2009-09-14 14:10:16 -0700 | [diff] [blame] | 804 | extern void i2400m_fw_cache(struct i2400m *); | 
 | 805 | extern void i2400m_fw_uncache(struct i2400m *); | 
 | 806 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 807 | extern void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned, | 
 | 808 | 			  const void *, int); | 
| Inaky Perez-Gonzalez | fd5c565 | 2009-02-28 23:42:52 +0000 | [diff] [blame] | 809 | extern void i2400m_net_erx(struct i2400m *, struct sk_buff *, | 
 | 810 | 			   enum i2400m_cs); | 
| Inaky Perez-Gonzalez | ac53aed | 2009-09-16 16:30:39 -0700 | [diff] [blame] | 811 | extern void i2400m_net_wake_stop(struct i2400m *); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 812 | enum i2400m_pt; | 
 | 813 | extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt); | 
 | 814 |  | 
 | 815 | #ifdef CONFIG_DEBUG_FS | 
 | 816 | extern int i2400m_debugfs_add(struct i2400m *); | 
 | 817 | extern void i2400m_debugfs_rm(struct i2400m *); | 
 | 818 | #else | 
 | 819 | static inline int i2400m_debugfs_add(struct i2400m *i2400m) | 
 | 820 | { | 
 | 821 | 	return 0; | 
 | 822 | } | 
 | 823 | static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {} | 
 | 824 | #endif | 
 | 825 |  | 
| Inaky Perez-Gonzalez | 8f90f3e | 2009-09-16 17:53:57 -0700 | [diff] [blame] | 826 | /* Initialize/shutdown the device */ | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 827 | extern int i2400m_dev_initialize(struct i2400m *); | 
 | 828 | extern void i2400m_dev_shutdown(struct i2400m *); | 
 | 829 |  | 
 | 830 | extern struct attribute_group i2400m_dev_attr_group; | 
 | 831 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 832 |  | 
 | 833 | /* HDI message's payload description handling */ | 
 | 834 |  | 
 | 835 | static inline | 
 | 836 | size_t i2400m_pld_size(const struct i2400m_pld *pld) | 
 | 837 | { | 
 | 838 | 	return I2400M_PLD_SIZE_MASK & le32_to_cpu(pld->val); | 
 | 839 | } | 
 | 840 |  | 
 | 841 | static inline | 
 | 842 | enum i2400m_pt i2400m_pld_type(const struct i2400m_pld *pld) | 
 | 843 | { | 
 | 844 | 	return (I2400M_PLD_TYPE_MASK & le32_to_cpu(pld->val)) | 
 | 845 | 		>> I2400M_PLD_TYPE_SHIFT; | 
 | 846 | } | 
 | 847 |  | 
 | 848 | static inline | 
 | 849 | void i2400m_pld_set(struct i2400m_pld *pld, size_t size, | 
 | 850 | 		    enum i2400m_pt type) | 
 | 851 | { | 
 | 852 | 	pld->val = cpu_to_le32( | 
 | 853 | 		((type << I2400M_PLD_TYPE_SHIFT) & I2400M_PLD_TYPE_MASK) | 
 | 854 | 		|  (size & I2400M_PLD_SIZE_MASK)); | 
 | 855 | } | 
 | 856 |  | 
 | 857 |  | 
 | 858 | /* | 
 | 859 |  * API for the bus-specific drivers | 
 | 860 |  * -------------------------------- | 
 | 861 |  */ | 
 | 862 |  | 
 | 863 | static inline | 
 | 864 | struct i2400m *i2400m_get(struct i2400m *i2400m) | 
 | 865 | { | 
 | 866 | 	dev_hold(i2400m->wimax_dev.net_dev); | 
 | 867 | 	return i2400m; | 
 | 868 | } | 
 | 869 |  | 
 | 870 | static inline | 
 | 871 | void i2400m_put(struct i2400m *i2400m) | 
 | 872 | { | 
 | 873 | 	dev_put(i2400m->wimax_dev.net_dev); | 
 | 874 | } | 
 | 875 |  | 
| Inaky Perez-Gonzalez | 3ef6129 | 2009-09-14 14:05:19 -0700 | [diff] [blame] | 876 | extern int i2400m_dev_reset_handle(struct i2400m *, const char *); | 
| Inaky Perez-Gonzalez | 3725d8c | 2009-09-17 15:20:45 -0700 | [diff] [blame] | 877 | extern int i2400m_pre_reset(struct i2400m *); | 
 | 878 | extern int i2400m_post_reset(struct i2400m *); | 
| Cindy H Kao | 599e595 | 2010-04-07 20:07:47 -0700 | [diff] [blame] | 879 | extern void i2400m_error_recovery(struct i2400m *); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 880 |  | 
 | 881 | /* | 
 | 882 |  * _setup()/_release() are called by the probe/disconnect functions of | 
 | 883 |  * the bus-specific drivers. | 
 | 884 |  */ | 
 | 885 | extern int i2400m_setup(struct i2400m *, enum i2400m_bri bm_flags); | 
 | 886 | extern void i2400m_release(struct i2400m *); | 
 | 887 |  | 
 | 888 | extern int i2400m_rx(struct i2400m *, struct sk_buff *); | 
 | 889 | extern struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *); | 
 | 890 | extern void i2400m_tx_msg_sent(struct i2400m *); | 
 | 891 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 892 |  | 
 | 893 | /* | 
 | 894 |  * Utility functions | 
 | 895 |  */ | 
 | 896 |  | 
 | 897 | static inline | 
 | 898 | struct device *i2400m_dev(struct i2400m *i2400m) | 
 | 899 | { | 
 | 900 | 	return i2400m->wimax_dev.net_dev->dev.parent; | 
 | 901 | } | 
 | 902 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 903 | extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *, | 
 | 904 | 				   char *, size_t); | 
 | 905 | extern int i2400m_msg_size_check(struct i2400m *, | 
 | 906 | 				 const struct i2400m_l3l4_hdr *, size_t); | 
 | 907 | extern struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t); | 
 | 908 | extern void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 909 | extern void i2400m_report_hook(struct i2400m *, | 
 | 910 | 			       const struct i2400m_l3l4_hdr *, size_t); | 
| Inaky Perez-Gonzalez | a0beba2 | 2009-10-07 21:43:10 +0900 | [diff] [blame] | 911 | extern void i2400m_report_hook_work(struct work_struct *); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 912 | extern int i2400m_cmd_enter_powersave(struct i2400m *); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 913 | extern int i2400m_cmd_exit_idle(struct i2400m *); | 
 | 914 | extern struct sk_buff *i2400m_get_device_info(struct i2400m *); | 
 | 915 | extern int i2400m_firmware_check(struct i2400m *); | 
| Inaky Perez-Gonzalez | 8987691 | 2009-02-28 23:42:50 +0000 | [diff] [blame] | 916 | extern int i2400m_set_idle_timeout(struct i2400m *, unsigned); | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 917 |  | 
 | 918 | static inline | 
 | 919 | struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep) | 
 | 920 | { | 
 | 921 | 	return &iface->cur_altsetting->endpoint[ep].desc; | 
 | 922 | } | 
 | 923 |  | 
 | 924 | extern int i2400m_op_rfkill_sw_toggle(struct wimax_dev *, | 
 | 925 | 				      enum wimax_rf_state); | 
 | 926 | extern void i2400m_report_tlv_rf_switches_status( | 
 | 927 | 	struct i2400m *, const struct i2400m_tlv_rf_switches_status *); | 
 | 928 |  | 
| Inaky Perez-Gonzalez | 8987691 | 2009-02-28 23:42:50 +0000 | [diff] [blame] | 929 | /* | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 930 |  * Helpers for firmware backwards compatibility | 
| Inaky Perez-Gonzalez | 8987691 | 2009-02-28 23:42:50 +0000 | [diff] [blame] | 931 |  * | 
 | 932 |  * As we aim to support at least the firmware version that was | 
 | 933 |  * released with the previous kernel/driver release, some code will be | 
 | 934 |  * conditionally executed depending on the firmware version. On each | 
 | 935 |  * release, the code to support fw releases past the last two ones | 
 | 936 |  * will be purged. | 
 | 937 |  * | 
 | 938 |  * By making it depend on this macros, it is easier to keep it a tab | 
 | 939 |  * on what has to go and what not. | 
 | 940 |  */ | 
 | 941 | static inline | 
 | 942 | unsigned i2400m_le_v1_3(struct i2400m *i2400m) | 
 | 943 | { | 
 | 944 | 	/* running fw is lower or v1.3 */ | 
 | 945 | 	return i2400m->fw_version <= 0x00090001; | 
 | 946 | } | 
 | 947 |  | 
 | 948 | static inline | 
 | 949 | unsigned i2400m_ge_v1_4(struct i2400m *i2400m) | 
 | 950 | { | 
 | 951 | 	/* running fw is higher or v1.4 */ | 
 | 952 | 	return i2400m->fw_version >= 0x00090002; | 
 | 953 | } | 
 | 954 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 955 |  | 
 | 956 | /* | 
 | 957 |  * Do a millisecond-sleep for allowing wireshark to dump all the data | 
 | 958 |  * packets. Used only for debugging. | 
 | 959 |  */ | 
 | 960 | static inline | 
 | 961 | void __i2400m_msleep(unsigned ms) | 
 | 962 | { | 
 | 963 | #if 1 | 
 | 964 | #else | 
 | 965 | 	msleep(ms); | 
 | 966 | #endif | 
 | 967 | } | 
 | 968 |  | 
| Inaky Perez-Gonzalez | aba3792a | 2009-09-03 15:14:29 -0700 | [diff] [blame] | 969 |  | 
 | 970 | /* module initialization helpers */ | 
 | 971 | extern int i2400m_barker_db_init(const char *); | 
 | 972 | extern void i2400m_barker_db_exit(void); | 
 | 973 |  | 
 | 974 |  | 
| Inaky Perez-Gonzalez | ea24652 | 2008-12-20 16:57:43 -0800 | [diff] [blame] | 975 |  | 
 | 976 | #endif /* #ifndef __I2400M_H__ */ |