aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax/i2400m/i2400m-usb.h
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2008-12-20 19:57:50 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-07 13:00:21 -0500
commit11a7d0e3140d2f3e8052a856e8582ce9b021972c (patch)
tree460a24023722ec55468a6c313b1e2cfda232b141 /drivers/net/wimax/i2400m/i2400m-usb.h
parentc71228caf91ec6320b489dec5cd0087b64da9fb5 (diff)
i2400m/USB: header for the USB bus driver
This contains the common function declaration and constants for the USB driver for the 2400m Wireless WiMAX Connection, as well as it's debug level settings. Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/net/wimax/i2400m/i2400m-usb.h')
-rw-r--r--drivers/net/wimax/i2400m/i2400m-usb.h264
1 files changed, 264 insertions, 0 deletions
diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h
new file mode 100644
index 000000000000..6f76558b170f
--- /dev/null
+++ b/drivers/net/wimax/i2400m/i2400m-usb.h
@@ -0,0 +1,264 @@
1/*
2 * Intel Wireless WiMAX Connection 2400m
3 * USB-specific i2400m driver definitions
4 *
5 *
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 *
35 * Intel Corporation <linux-wimax@intel.com>
36 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
37 * Yanir Lubetkin <yanirx.lubetkin@intel.com>
38 * - Initial implementation
39 *
40 *
41 * This driver implements the bus-specific part of the i2400m for
42 * USB. Check i2400m.h for a generic driver description.
43 *
44 * ARCHITECTURE
45 *
46 * This driver listens to notifications sent from the notification
47 * endpoint (in usb-notif.c); when data is ready to read, the code in
48 * there schedules a read from the device (usb-rx.c) and then passes
49 * the data to the generic RX code (rx.c).
50 *
51 * When the generic driver needs to send data (network or control), it
52 * queues up in the TX FIFO (tx.c) and that will notify the driver
53 * through the i2400m->bus_tx_kick() callback
54 * (usb-tx.c:i2400mu_bus_tx_kick) which will send the items in the
55 * FIFO queue.
56 *
57 * This driver, as well, implements the USB-specific ops for the generic
58 * driver to be able to setup/teardown communication with the device
59 * [i2400m_bus_dev_start() and i2400m_bus_dev_stop()], reseting the
60 * device [i2400m_bus_reset()] and performing firmware upload
61 * [i2400m_bus_bm_cmd() and i2400_bus_bm_wait_for_ack()].
62 */
63
64#ifndef __I2400M_USB_H__
65#define __I2400M_USB_H__
66
67#include "i2400m.h"
68#include <linux/kthread.h>
69
70
71/*
72 * Error Density Count: cheapo error density (over time) counter
73 *
74 * Originally by Reinette Chatre <reinette.chatre@intel.com>
75 *
76 * Embed an 'struct edc' somewhere. Each time there is a soft or
77 * retryable error, call edc_inc() and check if the error top
78 * watermark has been reached.
79 */
80enum {
81 EDC_MAX_ERRORS = 10,
82 EDC_ERROR_TIMEFRAME = HZ,
83};
84
85/* error density counter */
86struct edc {
87 unsigned long timestart;
88 u16 errorcount;
89};
90
91static inline void edc_init(struct edc *edc)
92{
93 edc->timestart = jiffies;
94}
95
96/**
97 * edc_inc - report a soft error and check if we are over the watermark
98 *
99 * @edc: pointer to error density counter.
100 * @max_err: maximum number of errors we can accept over the timeframe
101 * @timeframe: lenght of the timeframe (in jiffies).
102 *
103 * Returns: !0 1 if maximum acceptable errors per timeframe has been
104 * exceeded. 0 otherwise.
105 *
106 * This is way to determine if the number of acceptable errors per time
107 * period has been exceeded. It is not accurate as there are cases in which
108 * this scheme will not work, for example if there are periodic occurences
109 * of errors that straddle updates to the start time. This scheme is
110 * sufficient for our usage.
111 *
112 * To use, embed a 'struct edc' somewhere, initialize it with
113 * edc_init() and when an error hits:
114 *
115 * if (do_something_fails_with_a_soft_error) {
116 * if (edc_inc(&my->edc, MAX_ERRORS, MAX_TIMEFRAME))
117 * Ops, hard error, do something about it
118 * else
119 * Retry or ignore, depending on whatever
120 * }
121 */
122static inline int edc_inc(struct edc *edc, u16 max_err, u16 timeframe)
123{
124 unsigned long now;
125
126 now = jiffies;
127 if (now - edc->timestart > timeframe) {
128 edc->errorcount = 1;
129 edc->timestart = now;
130 } else if (++edc->errorcount > max_err) {
131 edc->errorcount = 0;
132 edc->timestart = now;
133 return 1;
134 }
135 return 0;
136}
137
138/* Host-Device interface for USB */
139enum {
140 I2400MU_MAX_NOTIFICATION_LEN = 256,
141 I2400MU_BLK_SIZE = 16,
142 I2400MU_PL_SIZE_MAX = 0x3EFF,
143
144 /* Endpoints */
145 I2400MU_EP_BULK_OUT = 0,
146 I2400MU_EP_NOTIFICATION,
147 I2400MU_EP_RESET_COLD,
148 I2400MU_EP_BULK_IN,
149};
150
151
152/**
153 * struct i2400mu - descriptor for a USB connected i2400m
154 *
155 * @i2400m: bus-generic i2400m implementation; has to be first (see
156 * it's documentation in i2400m.h).
157 *
158 * @usb_dev: pointer to our USB device
159 *
160 * @usb_iface: pointer to our USB interface
161 *
162 * @urb_edc: error density counter; used to keep a density-on-time tab
163 * on how many soft (retryable or ignorable) errors we get. If we
164 * go over the threshold, we consider the bus transport is failing
165 * too much and reset.
166 *
167 * @notif_urb: URB for receiving notifications from the device.
168 *
169 * @tx_kthread: thread we use for data TX. We use a thread because in
170 * order to do deep power saving and put the device to sleep, we
171 * need to call usb_autopm_*() [blocking functions].
172 *
173 * @tx_wq: waitqueue for the TX kthread to sleep when there is no data
174 * to be sent; when more data is available, it is woken up by
175 * i2400mu_bus_tx_kick().
176 *
177 * @rx_kthread: thread we use for data RX. We use a thread because in
178 * order to do deep power saving and put the device to sleep, we
179 * need to call usb_autopm_*() [blocking functions].
180 *
181 * @rx_wq: waitqueue for the RX kthread to sleep when there is no data
182 * to receive. When data is available, it is woken up by
183 * usb-notif.c:i2400mu_notification_grok().
184 *
185 * @rx_pending_count: number of rx-data-ready notifications that were
186 * still not handled by the RX kthread.
187 *
188 * @rx_size: current RX buffer size that is being used.
189 *
190 * @rx_size_acc: accumulator of the sizes of the previous read
191 * transactions.
192 *
193 * @rx_size_cnt: number of read transactions accumulated in
194 * @rx_size_acc.
195 *
196 * @do_autopm: disable(0)/enable(>0) calling the
197 * usb_autopm_get/put_interface() barriers when executing
198 * commands. See doc in i2400mu_suspend() for more information.
199 *
200 * @rx_size_auto_shrink: if true, the rx_size is shrinked
201 * automatically based on the average size of the received
202 * transactions. This allows the receive code to allocate smaller
203 * chunks of memory and thus reduce pressure on the memory
204 * allocator by not wasting so much space. By default it is
205 * enabled.
206 *
207 * @debugfs_dentry: hookup for debugfs files.
208 * These have to be in a separate directory, a child of
209 * (wimax_dev->debugfs_dentry) so they can be removed when the
210 * module unloads, as we don't keep each dentry.
211 */
212struct i2400mu {
213 struct i2400m i2400m; /* FIRST! See doc */
214
215 struct usb_device *usb_dev;
216 struct usb_interface *usb_iface;
217 struct edc urb_edc; /* Error density counter */
218
219 struct urb *notif_urb;
220 struct task_struct *tx_kthread;
221 wait_queue_head_t tx_wq;
222
223 struct task_struct *rx_kthread;
224 wait_queue_head_t rx_wq;
225 atomic_t rx_pending_count;
226 size_t rx_size, rx_size_acc, rx_size_cnt;
227 atomic_t do_autopm;
228 u8 rx_size_auto_shrink;
229
230 struct dentry *debugfs_dentry;
231};
232
233
234static inline
235void i2400mu_init(struct i2400mu *i2400mu)
236{
237 i2400m_init(&i2400mu->i2400m);
238 edc_init(&i2400mu->urb_edc);
239 init_waitqueue_head(&i2400mu->tx_wq);
240 atomic_set(&i2400mu->rx_pending_count, 0);
241 init_waitqueue_head(&i2400mu->rx_wq);
242 i2400mu->rx_size = PAGE_SIZE - sizeof(struct skb_shared_info);
243 atomic_set(&i2400mu->do_autopm, 1);
244 i2400mu->rx_size_auto_shrink = 1;
245}
246
247extern int i2400mu_notification_setup(struct i2400mu *);
248extern void i2400mu_notification_release(struct i2400mu *);
249
250extern int i2400mu_rx_setup(struct i2400mu *);
251extern void i2400mu_rx_release(struct i2400mu *);
252extern void i2400mu_rx_kick(struct i2400mu *);
253
254extern int i2400mu_tx_setup(struct i2400mu *);
255extern void i2400mu_tx_release(struct i2400mu *);
256extern void i2400mu_bus_tx_kick(struct i2400m *);
257
258extern ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *,
259 const struct i2400m_bootrom_header *,
260 size_t, int);
261extern ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *,
262 struct i2400m_bootrom_header *,
263 size_t);
264#endif /* #ifndef __I2400M_USB_H__ */