diff options
author | David Vrabel <david.vrabel@csr.com> | 2010-10-25 08:57:32 -0400 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2010-10-25 09:03:45 -0400 |
commit | 446396bfab00392010ebc36b9ccf859935b0f17b (patch) | |
tree | 7612ca4ed9f6cbd9e4341e7c3deae1634d3d87d8 /drivers/uwb/wlp/txrx.c | |
parent | 229aebb873e29726b91e076161649cf45154b0bf (diff) |
uwb: Remove the WLP subsystem and drivers
The only Wimedia LLC Protocol (WLP) hardware was an Intel i1480 chip
with a beta release of firmware that was never commercially available as
a product. This hardware and firmware is no longer available as Intel
sold their UWB/WLP IP. I also see little prospect of other WLP
capable hardware ever being available.
Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/uwb/wlp/txrx.c')
-rw-r--r-- | drivers/uwb/wlp/txrx.c | 354 |
1 files changed, 0 insertions, 354 deletions
diff --git a/drivers/uwb/wlp/txrx.c b/drivers/uwb/wlp/txrx.c deleted file mode 100644 index 05dde44b3592..000000000000 --- a/drivers/uwb/wlp/txrx.c +++ /dev/null | |||
@@ -1,354 +0,0 @@ | |||
1 | /* | ||
2 | * WiMedia Logical Link Control Protocol (WLP) | ||
3 | * Message exchange infrastructure | ||
4 | * | ||
5 | * Copyright (C) 2007 Intel Corporation | ||
6 | * Reinette Chatre <reinette.chatre@intel.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version | ||
10 | * 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
20 | * 02110-1301, USA. | ||
21 | * | ||
22 | * | ||
23 | * FIXME: Docs | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/etherdevice.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/wlp.h> | ||
30 | |||
31 | #include "wlp-internal.h" | ||
32 | |||
33 | /* | ||
34 | * Direct incoming association msg to correct parsing routine | ||
35 | * | ||
36 | * We only expect D1, E1, C1, C3 messages as new. All other incoming | ||
37 | * association messages should form part of an established session that is | ||
38 | * handled elsewhere. | ||
39 | * The handling of these messages often require calling sleeping functions | ||
40 | * - this cannot be done in interrupt context. We use the kernel's | ||
41 | * workqueue to handle these messages. | ||
42 | */ | ||
43 | static | ||
44 | void wlp_direct_assoc_frame(struct wlp *wlp, struct sk_buff *skb, | ||
45 | struct uwb_dev_addr *src) | ||
46 | { | ||
47 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
48 | struct wlp_frame_assoc *assoc = (void *) skb->data; | ||
49 | struct wlp_assoc_frame_ctx *frame_ctx; | ||
50 | |||
51 | frame_ctx = kmalloc(sizeof(*frame_ctx), GFP_ATOMIC); | ||
52 | if (frame_ctx == NULL) { | ||
53 | dev_err(dev, "WLP: Unable to allocate memory for association " | ||
54 | "frame handling.\n"); | ||
55 | kfree_skb(skb); | ||
56 | return; | ||
57 | } | ||
58 | frame_ctx->wlp = wlp; | ||
59 | frame_ctx->skb = skb; | ||
60 | frame_ctx->src = *src; | ||
61 | switch (assoc->type) { | ||
62 | case WLP_ASSOC_D1: | ||
63 | INIT_WORK(&frame_ctx->ws, wlp_handle_d1_frame); | ||
64 | schedule_work(&frame_ctx->ws); | ||
65 | break; | ||
66 | case WLP_ASSOC_E1: | ||
67 | kfree_skb(skb); /* Temporary until we handle it */ | ||
68 | kfree(frame_ctx); /* Temporary until we handle it */ | ||
69 | break; | ||
70 | case WLP_ASSOC_C1: | ||
71 | INIT_WORK(&frame_ctx->ws, wlp_handle_c1_frame); | ||
72 | schedule_work(&frame_ctx->ws); | ||
73 | break; | ||
74 | case WLP_ASSOC_C3: | ||
75 | INIT_WORK(&frame_ctx->ws, wlp_handle_c3_frame); | ||
76 | schedule_work(&frame_ctx->ws); | ||
77 | break; | ||
78 | default: | ||
79 | dev_err(dev, "Received unexpected association frame. " | ||
80 | "Type = %d \n", assoc->type); | ||
81 | kfree_skb(skb); | ||
82 | kfree(frame_ctx); | ||
83 | break; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Process incoming association frame | ||
89 | * | ||
90 | * Although it could be possible to deal with some incoming association | ||
91 | * messages without creating a new session we are keeping things simple. We | ||
92 | * do not accept new association messages if there is a session in progress | ||
93 | * and the messages do not belong to that session. | ||
94 | * | ||
95 | * If an association message arrives that causes the creation of a session | ||
96 | * (WLP_ASSOC_E1) while we are in the process of creating a session then we | ||
97 | * rely on the neighbor mutex to protect the data. That is, the new session | ||
98 | * will not be started until the previous is completed. | ||
99 | */ | ||
100 | static | ||
101 | void wlp_receive_assoc_frame(struct wlp *wlp, struct sk_buff *skb, | ||
102 | struct uwb_dev_addr *src) | ||
103 | { | ||
104 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
105 | struct wlp_frame_assoc *assoc = (void *) skb->data; | ||
106 | struct wlp_session *session = wlp->session; | ||
107 | u8 version; | ||
108 | |||
109 | if (wlp_get_version(wlp, &assoc->version, &version, | ||
110 | sizeof(assoc->version)) < 0) | ||
111 | goto error; | ||
112 | if (version != WLP_VERSION) { | ||
113 | dev_err(dev, "Unsupported WLP version in association " | ||
114 | "message.\n"); | ||
115 | goto error; | ||
116 | } | ||
117 | if (session != NULL) { | ||
118 | /* Function that created this session is still holding the | ||
119 | * &wlp->mutex to protect this session. */ | ||
120 | if (assoc->type == session->exp_message || | ||
121 | assoc->type == WLP_ASSOC_F0) { | ||
122 | if (!memcmp(&session->neighbor_addr, src, | ||
123 | sizeof(*src))) { | ||
124 | session->data = skb; | ||
125 | (session->cb)(wlp); | ||
126 | } else { | ||
127 | dev_err(dev, "Received expected message from " | ||
128 | "unexpected source. Expected message " | ||
129 | "%d or F0 from %02x:%02x, but received " | ||
130 | "it from %02x:%02x. Dropping.\n", | ||
131 | session->exp_message, | ||
132 | session->neighbor_addr.data[1], | ||
133 | session->neighbor_addr.data[0], | ||
134 | src->data[1], src->data[0]); | ||
135 | goto error; | ||
136 | } | ||
137 | } else { | ||
138 | dev_err(dev, "Association already in progress. " | ||
139 | "Dropping.\n"); | ||
140 | goto error; | ||
141 | } | ||
142 | } else { | ||
143 | wlp_direct_assoc_frame(wlp, skb, src); | ||
144 | } | ||
145 | return; | ||
146 | error: | ||
147 | kfree_skb(skb); | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * Verify incoming frame is from connected neighbor, prep to pass to WLP client | ||
152 | * | ||
153 | * Verification proceeds according to WLP 0.99 [7.3.1]. The source address | ||
154 | * is used to determine which neighbor is sending the frame and the WSS tag | ||
155 | * is used to know to which WSS the frame belongs (we only support one WSS | ||
156 | * so this test is straight forward). | ||
157 | * With the WSS found we need to ensure that we are connected before | ||
158 | * allowing the exchange of data frames. | ||
159 | */ | ||
160 | static | ||
161 | int wlp_verify_prep_rx_frame(struct wlp *wlp, struct sk_buff *skb, | ||
162 | struct uwb_dev_addr *src) | ||
163 | { | ||
164 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
165 | int result = -EINVAL; | ||
166 | struct wlp_eda_node eda_entry; | ||
167 | struct wlp_frame_std_abbrv_hdr *hdr = (void *) skb->data; | ||
168 | |||
169 | /*verify*/ | ||
170 | result = wlp_copy_eda_node(&wlp->eda, src, &eda_entry); | ||
171 | if (result < 0) { | ||
172 | if (printk_ratelimit()) | ||
173 | dev_err(dev, "WLP: Incoming frame is from unknown " | ||
174 | "neighbor %02x:%02x.\n", src->data[1], | ||
175 | src->data[0]); | ||
176 | goto out; | ||
177 | } | ||
178 | if (hdr->tag != eda_entry.tag) { | ||
179 | if (printk_ratelimit()) | ||
180 | dev_err(dev, "WLP: Tag of incoming frame from " | ||
181 | "%02x:%02x does not match expected tag. " | ||
182 | "Received 0x%02x, expected 0x%02x. \n", | ||
183 | src->data[1], src->data[0], hdr->tag, | ||
184 | eda_entry.tag); | ||
185 | result = -EINVAL; | ||
186 | goto out; | ||
187 | } | ||
188 | if (eda_entry.state != WLP_WSS_CONNECTED) { | ||
189 | if (printk_ratelimit()) | ||
190 | dev_err(dev, "WLP: Incoming frame from " | ||
191 | "%02x:%02x does is not from connected WSS.\n", | ||
192 | src->data[1], src->data[0]); | ||
193 | result = -EINVAL; | ||
194 | goto out; | ||
195 | } | ||
196 | /*prep*/ | ||
197 | skb_pull(skb, sizeof(*hdr)); | ||
198 | out: | ||
199 | return result; | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * Receive a WLP frame from device | ||
204 | * | ||
205 | * @returns: 1 if calling function should free the skb | ||
206 | * 0 if it successfully handled skb and freed it | ||
207 | * 0 if error occured, will free skb in this case | ||
208 | */ | ||
209 | int wlp_receive_frame(struct device *dev, struct wlp *wlp, struct sk_buff *skb, | ||
210 | struct uwb_dev_addr *src) | ||
211 | { | ||
212 | unsigned len = skb->len; | ||
213 | void *ptr = skb->data; | ||
214 | struct wlp_frame_hdr *hdr; | ||
215 | int result = 0; | ||
216 | |||
217 | if (len < sizeof(*hdr)) { | ||
218 | dev_err(dev, "Not enough data to parse WLP header.\n"); | ||
219 | result = -EINVAL; | ||
220 | goto out; | ||
221 | } | ||
222 | hdr = ptr; | ||
223 | if (le16_to_cpu(hdr->mux_hdr) != WLP_PROTOCOL_ID) { | ||
224 | dev_err(dev, "Not a WLP frame type.\n"); | ||
225 | result = -EINVAL; | ||
226 | goto out; | ||
227 | } | ||
228 | switch (hdr->type) { | ||
229 | case WLP_FRAME_STANDARD: | ||
230 | if (len < sizeof(struct wlp_frame_std_abbrv_hdr)) { | ||
231 | dev_err(dev, "Not enough data to parse Standard " | ||
232 | "WLP header.\n"); | ||
233 | goto out; | ||
234 | } | ||
235 | result = wlp_verify_prep_rx_frame(wlp, skb, src); | ||
236 | if (result < 0) { | ||
237 | if (printk_ratelimit()) | ||
238 | dev_err(dev, "WLP: Verification of frame " | ||
239 | "from neighbor %02x:%02x failed.\n", | ||
240 | src->data[1], src->data[0]); | ||
241 | goto out; | ||
242 | } | ||
243 | result = 1; | ||
244 | break; | ||
245 | case WLP_FRAME_ABBREVIATED: | ||
246 | dev_err(dev, "Abbreviated frame received. FIXME?\n"); | ||
247 | kfree_skb(skb); | ||
248 | break; | ||
249 | case WLP_FRAME_CONTROL: | ||
250 | dev_err(dev, "Control frame received. FIXME?\n"); | ||
251 | kfree_skb(skb); | ||
252 | break; | ||
253 | case WLP_FRAME_ASSOCIATION: | ||
254 | if (len < sizeof(struct wlp_frame_assoc)) { | ||
255 | dev_err(dev, "Not enough data to parse Association " | ||
256 | "WLP header.\n"); | ||
257 | goto out; | ||
258 | } | ||
259 | wlp_receive_assoc_frame(wlp, skb, src); | ||
260 | break; | ||
261 | default: | ||
262 | dev_err(dev, "Invalid frame received.\n"); | ||
263 | result = -EINVAL; | ||
264 | break; | ||
265 | } | ||
266 | out: | ||
267 | if (result < 0) { | ||
268 | kfree_skb(skb); | ||
269 | result = 0; | ||
270 | } | ||
271 | return result; | ||
272 | } | ||
273 | EXPORT_SYMBOL_GPL(wlp_receive_frame); | ||
274 | |||
275 | |||
276 | /* | ||
277 | * Verify frame from network stack, prepare for further transmission | ||
278 | * | ||
279 | * @skb: the socket buffer that needs to be prepared for transmission (it | ||
280 | * is in need of a WLP header). If this is a broadcast frame we take | ||
281 | * over the entire transmission. | ||
282 | * If it is a unicast the WSS connection should already be established | ||
283 | * and transmission will be done by the calling function. | ||
284 | * @dst: On return this will contain the device address to which the | ||
285 | * frame is destined. | ||
286 | * @returns: 0 on success no tx : WLP header successfully applied to skb buffer, | ||
287 | * calling function can proceed with tx | ||
288 | * 1 on success with tx : WLP will take over transmission of this | ||
289 | * frame | ||
290 | * <0 on error | ||
291 | * | ||
292 | * The network stack (WLP client) is attempting to transmit a frame. We can | ||
293 | * only transmit data if a local WSS is at least active (connection will be | ||
294 | * done here if this is a broadcast frame and neighbor also has the WSS | ||
295 | * active). | ||
296 | * | ||
297 | * The frame can be either broadcast or unicast. Broadcast in a WSS is | ||
298 | * supported via multicast, but we don't support multicast yet (until | ||
299 | * devices start to support MAB IEs). If a broadcast frame needs to be | ||
300 | * transmitted it is treated as a unicast frame to each neighbor. In this | ||
301 | * case the WLP takes over transmission of the skb and returns 1 | ||
302 | * to the caller to indicate so. Also, in this case, if a neighbor has the | ||
303 | * same WSS activated but is not connected then the WSS connection will be | ||
304 | * done at this time. The neighbor's virtual address will be learned at | ||
305 | * this time. | ||
306 | * | ||
307 | * The destination address in a unicast frame is the virtual address of the | ||
308 | * neighbor. This address only becomes known when a WSS connection is | ||
309 | * established. We thus rely on a broadcast frame to trigger the setup of | ||
310 | * WSS connections to all neighbors before we are able to send unicast | ||
311 | * frames to them. This seems reasonable as IP would usually use ARP first | ||
312 | * before any unicast frames are sent. | ||
313 | * | ||
314 | * If we are already connected to the neighbor (neighbor's virtual address | ||
315 | * is known) we just prepare the WLP header and the caller will continue to | ||
316 | * send the frame. | ||
317 | * | ||
318 | * A failure in this function usually indicates something that cannot be | ||
319 | * fixed automatically. So, if this function fails (@return < 0) the calling | ||
320 | * function should not retry to send the frame as it will very likely keep | ||
321 | * failing. | ||
322 | * | ||
323 | */ | ||
324 | int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp, | ||
325 | struct sk_buff *skb, struct uwb_dev_addr *dst) | ||
326 | { | ||
327 | int result = -EINVAL; | ||
328 | struct ethhdr *eth_hdr = (void *) skb->data; | ||
329 | |||
330 | if (is_multicast_ether_addr(eth_hdr->h_dest)) { | ||
331 | result = wlp_eda_for_each(&wlp->eda, wlp_wss_send_copy, skb); | ||
332 | if (result < 0) { | ||
333 | if (printk_ratelimit()) | ||
334 | dev_err(dev, "Unable to handle broadcast " | ||
335 | "frame from WLP client.\n"); | ||
336 | goto out; | ||
337 | } | ||
338 | dev_kfree_skb_irq(skb); | ||
339 | result = 1; | ||
340 | /* Frame will be transmitted by WLP. */ | ||
341 | } else { | ||
342 | result = wlp_eda_for_virtual(&wlp->eda, eth_hdr->h_dest, dst, | ||
343 | wlp_wss_prep_hdr, skb); | ||
344 | if (unlikely(result < 0)) { | ||
345 | if (printk_ratelimit()) | ||
346 | dev_err(dev, "Unable to prepare " | ||
347 | "skb for transmission. \n"); | ||
348 | goto out; | ||
349 | } | ||
350 | } | ||
351 | out: | ||
352 | return result; | ||
353 | } | ||
354 | EXPORT_SYMBOL_GPL(wlp_prepare_tx_frame); | ||