diff options
Diffstat (limited to 'drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h')
-rw-r--r-- | drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h b/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h new file mode 100644 index 000000000000..5f1b2951bb83 --- /dev/null +++ b/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Intel 1480 Wireless UWB Link USB | ||
3 | * Header formats, constants, general internal interfaces | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2005-2006 Intel Corporation | ||
7 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA. | ||
22 | * | ||
23 | * | ||
24 | * This is not an standard interface. | ||
25 | * | ||
26 | * FIXME: docs | ||
27 | * | ||
28 | * i1480u-wlp is pretty simple: two endpoints, one for tx, one for | ||
29 | * rx. rx is polled. Network packets (ethernet, whatever) are wrapped | ||
30 | * in i1480 TX or RX headers (for sending over the air), and these | ||
31 | * packets are wrapped in UNTD headers (for sending to the WLP UWB | ||
32 | * controller). | ||
33 | * | ||
34 | * UNTD packets (UNTD hdr + i1480 hdr + network packet) packets | ||
35 | * cannot be bigger than i1480u_MAX_FRG_SIZE. When this happens, the | ||
36 | * i1480 packet is broken in chunks/packets: | ||
37 | * | ||
38 | * UNTD-1st.hdr + i1480.hdr + payload | ||
39 | * UNTD-next.hdr + payload | ||
40 | * ... | ||
41 | * UNTD-last.hdr + payload | ||
42 | * | ||
43 | * so that each packet is smaller or equal than i1480u_MAX_FRG_SIZE. | ||
44 | * | ||
45 | * All HW structures and bitmaps are little endian, so we need to play | ||
46 | * ugly tricks when defining bitfields. Hoping for the day GCC | ||
47 | * implements __attribute__((endian(1234))). | ||
48 | * | ||
49 | * FIXME: ROADMAP to the whole implementation | ||
50 | */ | ||
51 | |||
52 | #ifndef __i1480u_wlp_h__ | ||
53 | #define __i1480u_wlp_h__ | ||
54 | |||
55 | #include <linux/usb.h> | ||
56 | #include <linux/netdevice.h> | ||
57 | #include <linux/uwb.h> /* struct uwb_rc, struct uwb_notifs_handler */ | ||
58 | #include <linux/wlp.h> | ||
59 | #include "../i1480-wlp.h" | ||
60 | |||
61 | #undef i1480u_FLOW_CONTROL /* Enable flow control code */ | ||
62 | |||
63 | /** | ||
64 | * Basic flow control | ||
65 | */ | ||
66 | enum { | ||
67 | i1480u_TX_INFLIGHT_MAX = 1000, | ||
68 | i1480u_TX_INFLIGHT_THRESHOLD = 100, | ||
69 | }; | ||
70 | |||
71 | /** Maximum size of a transaction that we can tx/rx */ | ||
72 | enum { | ||
73 | /* Maximum packet size computed as follows: max UNTD header (8) + | ||
74 | * i1480 RX header (8) + max Ethernet header and payload (4096) + | ||
75 | * Padding added by skb_reserve (2) to make post Ethernet payload | ||
76 | * start on 16 byte boundary*/ | ||
77 | i1480u_MAX_RX_PKT_SIZE = 4114, | ||
78 | i1480u_MAX_FRG_SIZE = 512, | ||
79 | i1480u_RX_BUFS = 9, | ||
80 | }; | ||
81 | |||
82 | |||
83 | /** | ||
84 | * UNTD packet type | ||
85 | * | ||
86 | * We need to fragment any payload whose UNTD packet is going to be | ||
87 | * bigger than i1480u_MAX_FRG_SIZE. | ||
88 | */ | ||
89 | enum i1480u_pkt_type { | ||
90 | i1480u_PKT_FRAG_1ST = 0x1, | ||
91 | i1480u_PKT_FRAG_NXT = 0x0, | ||
92 | i1480u_PKT_FRAG_LST = 0x2, | ||
93 | i1480u_PKT_FRAG_CMP = 0x3 | ||
94 | }; | ||
95 | enum { | ||
96 | i1480u_PKT_NONE = 0x4, | ||
97 | }; | ||
98 | |||
99 | /** USB Network Transfer Descriptor - common */ | ||
100 | struct untd_hdr { | ||
101 | u8 type; | ||
102 | __le16 len; | ||
103 | } __attribute__((packed)); | ||
104 | |||
105 | static inline enum i1480u_pkt_type untd_hdr_type(const struct untd_hdr *hdr) | ||
106 | { | ||
107 | return hdr->type & 0x03; | ||
108 | } | ||
109 | |||
110 | static inline int untd_hdr_rx_tx(const struct untd_hdr *hdr) | ||
111 | { | ||
112 | return (hdr->type >> 2) & 0x01; | ||
113 | } | ||
114 | |||
115 | static inline void untd_hdr_set_type(struct untd_hdr *hdr, enum i1480u_pkt_type type) | ||
116 | { | ||
117 | hdr->type = (hdr->type & ~0x03) | type; | ||
118 | } | ||
119 | |||
120 | static inline void untd_hdr_set_rx_tx(struct untd_hdr *hdr, int rx_tx) | ||
121 | { | ||
122 | hdr->type = (hdr->type & ~0x04) | (rx_tx << 2); | ||
123 | } | ||
124 | |||
125 | |||
126 | /** | ||
127 | * USB Network Transfer Descriptor - Complete Packet | ||
128 | * | ||
129 | * This is for a packet that is smaller (header + payload) than | ||
130 | * i1480u_MAX_FRG_SIZE. | ||
131 | * | ||
132 | * @hdr.total_len is the size of the payload; the payload doesn't | ||
133 | * count this header nor the padding, but includes the size of i1480 | ||
134 | * header. | ||
135 | */ | ||
136 | struct untd_hdr_cmp { | ||
137 | struct untd_hdr hdr; | ||
138 | u8 padding; | ||
139 | } __attribute__((packed)); | ||
140 | |||
141 | |||
142 | /** | ||
143 | * USB Network Transfer Descriptor - First fragment | ||
144 | * | ||
145 | * @hdr.len is the size of the *whole packet* (excluding UNTD | ||
146 | * headers); @fragment_len is the size of the payload (excluding UNTD | ||
147 | * headers, but including i1480 headers). | ||
148 | */ | ||
149 | struct untd_hdr_1st { | ||
150 | struct untd_hdr hdr; | ||
151 | __le16 fragment_len; | ||
152 | u8 padding[3]; | ||
153 | } __attribute__((packed)); | ||
154 | |||
155 | |||
156 | /** | ||
157 | * USB Network Transfer Descriptor - Next / Last [Rest] | ||
158 | * | ||
159 | * @hdr.len is the size of the payload, not including headrs. | ||
160 | */ | ||
161 | struct untd_hdr_rst { | ||
162 | struct untd_hdr hdr; | ||
163 | u8 padding; | ||
164 | } __attribute__((packed)); | ||
165 | |||
166 | |||
167 | /** | ||
168 | * Transmission context | ||
169 | * | ||
170 | * Wraps all the stuff needed to track a pending/active tx | ||
171 | * operation. | ||
172 | */ | ||
173 | struct i1480u_tx { | ||
174 | struct list_head list_node; | ||
175 | struct i1480u *i1480u; | ||
176 | struct urb *urb; | ||
177 | |||
178 | struct sk_buff *skb; | ||
179 | struct wlp_tx_hdr *wlp_tx_hdr; | ||
180 | |||
181 | void *buf; /* if NULL, no new buf was used */ | ||
182 | size_t buf_size; | ||
183 | }; | ||
184 | |||
185 | /** | ||
186 | * Basic flow control | ||
187 | * | ||
188 | * We maintain a basic flow control counter. "count" how many TX URBs are | ||
189 | * outstanding. Only allow "max" | ||
190 | * TX URBs to be outstanding. If this value is reached the queue will be | ||
191 | * stopped. The queue will be restarted when there are | ||
192 | * "threshold" URBs outstanding. | ||
193 | * Maintain a counter of how many time the TX queue needed to be restarted | ||
194 | * due to the "max" being exceeded and the "threshold" reached again. The | ||
195 | * timestamp "restart_ts" is to keep track from when the counter was last | ||
196 | * queried (see sysfs handling of file wlp_tx_inflight). | ||
197 | */ | ||
198 | struct i1480u_tx_inflight { | ||
199 | atomic_t count; | ||
200 | unsigned long max; | ||
201 | unsigned long threshold; | ||
202 | unsigned long restart_ts; | ||
203 | atomic_t restart_count; | ||
204 | }; | ||
205 | |||
206 | /** | ||
207 | * Instance of a i1480u WLP interface | ||
208 | * | ||
209 | * Keeps references to the USB device that wraps it, as well as it's | ||
210 | * interface and associated UWB host controller. As well, it also | ||
211 | * keeps a link to the netdevice for integration into the networking | ||
212 | * stack. | ||
213 | * We maintian separate error history for the tx and rx endpoints because | ||
214 | * the implementation does not rely on locking - having one shared | ||
215 | * structure between endpoints may cause problems. Adding locking to the | ||
216 | * implementation will have higher cost than adding a separate structure. | ||
217 | */ | ||
218 | struct i1480u { | ||
219 | struct usb_device *usb_dev; | ||
220 | struct usb_interface *usb_iface; | ||
221 | struct net_device *net_dev; | ||
222 | |||
223 | spinlock_t lock; | ||
224 | struct net_device_stats stats; | ||
225 | |||
226 | /* RX context handling */ | ||
227 | struct sk_buff *rx_skb; | ||
228 | struct uwb_dev_addr rx_srcaddr; | ||
229 | size_t rx_untd_pkt_size; | ||
230 | struct i1480u_rx_buf { | ||
231 | struct i1480u *i1480u; /* back pointer */ | ||
232 | struct urb *urb; | ||
233 | struct sk_buff *data; /* i1480u_MAX_RX_PKT_SIZE each */ | ||
234 | } rx_buf[i1480u_RX_BUFS]; /* N bufs */ | ||
235 | |||
236 | spinlock_t tx_list_lock; /* TX context */ | ||
237 | struct list_head tx_list; | ||
238 | u8 tx_stream; | ||
239 | |||
240 | struct stats lqe_stats, rssi_stats; /* radio statistics */ | ||
241 | |||
242 | /* Options we can set from sysfs */ | ||
243 | struct wlp_options options; | ||
244 | struct uwb_notifs_handler uwb_notifs_handler; | ||
245 | struct edc tx_errors; | ||
246 | struct edc rx_errors; | ||
247 | struct wlp wlp; | ||
248 | #ifdef i1480u_FLOW_CONTROL | ||
249 | struct urb *notif_urb; | ||
250 | struct edc notif_edc; /* error density counter */ | ||
251 | u8 notif_buffer[1]; | ||
252 | #endif | ||
253 | struct i1480u_tx_inflight tx_inflight; | ||
254 | }; | ||
255 | |||
256 | /* Internal interfaces */ | ||
257 | extern void i1480u_rx_cb(struct urb *urb); | ||
258 | extern int i1480u_rx_setup(struct i1480u *); | ||
259 | extern void i1480u_rx_release(struct i1480u *); | ||
260 | extern void i1480u_tx_release(struct i1480u *); | ||
261 | extern int i1480u_xmit_frame(struct wlp *, struct sk_buff *, | ||
262 | struct uwb_dev_addr *); | ||
263 | extern void i1480u_stop_queue(struct wlp *); | ||
264 | extern void i1480u_start_queue(struct wlp *); | ||
265 | extern int i1480u_sysfs_setup(struct i1480u *); | ||
266 | extern void i1480u_sysfs_release(struct i1480u *); | ||
267 | |||
268 | /* netdev interface */ | ||
269 | extern int i1480u_open(struct net_device *); | ||
270 | extern int i1480u_stop(struct net_device *); | ||
271 | extern int i1480u_hard_start_xmit(struct sk_buff *, struct net_device *); | ||
272 | extern void i1480u_tx_timeout(struct net_device *); | ||
273 | extern int i1480u_set_config(struct net_device *, struct ifmap *); | ||
274 | extern struct net_device_stats *i1480u_get_stats(struct net_device *); | ||
275 | extern int i1480u_change_mtu(struct net_device *, int); | ||
276 | extern void i1480u_uwb_notifs_cb(void *, struct uwb_dev *, enum uwb_notifs); | ||
277 | |||
278 | /* bandwidth allocation callback */ | ||
279 | extern void i1480u_bw_alloc_cb(struct uwb_rsv *); | ||
280 | |||
281 | /* Sys FS */ | ||
282 | extern struct attribute_group i1480u_wlp_attr_group; | ||
283 | |||
284 | #endif /* #ifndef __i1480u_wlp_h__ */ | ||