1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/wlp.h>
25
26#include "wlp-internal.h"
27
28static
29void wlp_neighbor_init(struct wlp_neighbor_e *neighbor)
30{
31 INIT_LIST_HEAD(&neighbor->wssid);
32}
33
34
35
36
37
38
39int __wlp_alloc_device_info(struct wlp *wlp)
40{
41 struct device *dev = &wlp->rc->uwb_dev.dev;
42 BUG_ON(wlp->dev_info != NULL);
43 wlp->dev_info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
44 if (wlp->dev_info == NULL) {
45 dev_err(dev, "WLP: Unable to allocate memory for "
46 "device information.\n");
47 return -ENOMEM;
48 }
49 return 0;
50}
51
52
53
54
55
56
57
58static
59void __wlp_fill_device_info(struct wlp *wlp)
60{
61 wlp->fill_device_info(wlp, wlp->dev_info);
62}
63
64
65
66
67
68
69
70
71int __wlp_setup_device_info(struct wlp *wlp)
72{
73 int result;
74 struct device *dev = &wlp->rc->uwb_dev.dev;
75
76 result = __wlp_alloc_device_info(wlp);
77 if (result < 0) {
78 dev_err(dev, "WLP: Unable to allocate area for "
79 "device information.\n");
80 return result;
81 }
82 __wlp_fill_device_info(wlp);
83 return 0;
84}
85
86
87
88
89
90
91
92
93
94
95
96
97
98void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *neighbor)
99{
100 struct wlp_wssid_e *wssid_e, *next;
101 u8 keep;
102 if (!list_empty(&neighbor->wssid)) {
103 list_for_each_entry_safe(wssid_e, next, &neighbor->wssid,
104 node) {
105 if (wssid_e->info != NULL) {
106 keep = wssid_e->info->accept_enroll;
107 kfree(wssid_e->info);
108 wssid_e->info = NULL;
109 if (!keep) {
110 list_del(&wssid_e->node);
111 kfree(wssid_e);
112 }
113 }
114 }
115 }
116 if (neighbor->info != NULL) {
117 kfree(neighbor->info);
118 neighbor->info = NULL;
119 }
120}
121
122
123
124
125
126
127
128
129static
130int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev)
131{
132 int result = 0;
133 int discoverable;
134 struct wlp_neighbor_e *neighbor;
135
136
137
138
139
140
141
142
143 discoverable = 1;
144 if (discoverable) {
145
146 neighbor = kzalloc(sizeof(*neighbor), GFP_KERNEL);
147 if (neighbor == NULL) {
148 dev_err(&dev->dev, "Unable to create memory for "
149 "new neighbor. \n");
150 result = -ENOMEM;
151 goto error_no_mem;
152 }
153 wlp_neighbor_init(neighbor);
154 uwb_dev_get(dev);
155 neighbor->uwb_dev = dev;
156 list_add(&neighbor->node, &wlp->neighbors);
157 }
158error_no_mem:
159 return result;
160}
161
162
163
164
165static
166void __wlp_neighbor_release(struct wlp_neighbor_e *neighbor)
167{
168 struct wlp_wssid_e *wssid_e, *next_wssid_e;
169
170 list_for_each_entry_safe(wssid_e, next_wssid_e,
171 &neighbor->wssid, node) {
172 list_del(&wssid_e->node);
173 kfree(wssid_e);
174 }
175 uwb_dev_put(neighbor->uwb_dev);
176 list_del(&neighbor->node);
177 kfree(neighbor);
178}
179
180
181
182
183static
184void __wlp_neighbors_release(struct wlp *wlp)
185{
186 struct wlp_neighbor_e *neighbor, *next;
187 if (list_empty(&wlp->neighbors))
188 return;
189 list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
190 __wlp_neighbor_release(neighbor);
191 }
192}
193
194static
195void wlp_neighbors_release(struct wlp *wlp)
196{
197 mutex_lock(&wlp->nbmutex);
198 __wlp_neighbors_release(wlp);
199 mutex_unlock(&wlp->nbmutex);
200}
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221static
222int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
223 struct wlp_wss *wss, struct wlp_uuid *wssid)
224{
225 int result;
226 struct device *dev = &wlp->rc->uwb_dev.dev;
227 DECLARE_COMPLETION_ONSTACK(completion);
228 struct wlp_session session;
229 struct sk_buff *skb;
230 struct wlp_frame_assoc *resp;
231 struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
232
233 mutex_lock(&wlp->mutex);
234 if (!wlp_uuid_is_set(&wlp->uuid)) {
235 dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
236 "proceed.\n");
237 result = -ENXIO;
238 goto out;
239 }
240
241 result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_D1);
242 if (result < 0) {
243 dev_err(dev, "Unable to send D1 frame to neighbor "
244 "%02x:%02x (%d)\n", dev_addr->data[1],
245 dev_addr->data[0], result);
246 goto out;
247 }
248
249 session.exp_message = WLP_ASSOC_D2;
250 session.cb = wlp_session_cb;
251 session.cb_priv = &completion;
252 session.neighbor_addr = *dev_addr;
253 BUG_ON(wlp->session != NULL);
254 wlp->session = &session;
255
256 result = wait_for_completion_interruptible_timeout(&completion,
257 WLP_PER_MSG_TIMEOUT * HZ);
258 if (result == 0) {
259 result = -ETIMEDOUT;
260 dev_err(dev, "Timeout while sending D1 to neighbor "
261 "%02x:%02x.\n", dev_addr->data[1],
262 dev_addr->data[0]);
263 goto error_session;
264 }
265 if (result < 0) {
266 dev_err(dev, "Unable to discover/enroll neighbor %02x:%02x.\n",
267 dev_addr->data[1], dev_addr->data[0]);
268 goto error_session;
269 }
270
271 skb = session.data;
272 resp = (void *) skb->data;
273
274 if (resp->type == WLP_ASSOC_F0) {
275 result = wlp_parse_f0(wlp, skb);
276 if (result < 0)
277 dev_err(dev, "WLP: Unable to parse F0 from neighbor "
278 "%02x:%02x.\n", dev_addr->data[1],
279 dev_addr->data[0]);
280 result = -EINVAL;
281 goto error_resp_parse;
282 }
283 if (wss == NULL) {
284
285 result = wlp_parse_d2_frame_to_cache(wlp, skb, neighbor);
286 if (result < 0) {
287 dev_err(dev, "WLP: Unable to parse D2 message from "
288 "neighbor %02x:%02x for discovery.\n",
289 dev_addr->data[1], dev_addr->data[0]);
290 goto error_resp_parse;
291 }
292 } else {
293
294 result = wlp_parse_d2_frame_to_enroll(wss, skb, neighbor,
295 wssid);
296 if (result < 0) {
297 dev_err(dev, "WLP: Unable to parse D2 message from "
298 "neighbor %02x:%02x for enrollment.\n",
299 dev_addr->data[1], dev_addr->data[0]);
300 goto error_resp_parse;
301 }
302 }
303error_resp_parse:
304 kfree_skb(skb);
305error_session:
306 wlp->session = NULL;
307out:
308 mutex_unlock(&wlp->mutex);
309 return result;
310}
311
312
313
314
315
316
317int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
318 struct wlp_wss *wss, struct wlp_uuid *wssid)
319{
320 int result = 0;
321 struct device *dev = &wlp->rc->uwb_dev.dev;
322 char buf[WLP_WSS_UUID_STRSIZE];
323 struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
324
325 wlp_wss_uuid_print(buf, sizeof(buf), wssid);
326
327 result = wlp_d1d2_exchange(wlp, neighbor, wss, wssid);
328 if (result < 0) {
329 dev_err(dev, "WLP: D1/D2 message exchange for enrollment "
330 "failed. result = %d \n", result);
331 goto out;
332 }
333 if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
334 dev_err(dev, "WLP: Unable to enroll into WSS %s using "
335 "neighbor %02x:%02x. \n", buf,
336 dev_addr->data[1], dev_addr->data[0]);
337 result = -EINVAL;
338 goto out;
339 }
340 if (wss->secure_status == WLP_WSS_SECURE) {
341 dev_err(dev, "FIXME: need to complete secure enrollment.\n");
342 result = -EINVAL;
343 goto error;
344 } else {
345 wss->state = WLP_WSS_STATE_ENROLLED;
346 dev_dbg(dev, "WLP: Success Enrollment into unsecure WSS "
347 "%s using neighbor %02x:%02x. \n",
348 buf, dev_addr->data[1], dev_addr->data[0]);
349 }
350out:
351 return result;
352error:
353 wlp_wss_reset(wss);
354 return result;
355}
356
357
358
359
360static
361int wlp_discover_neighbor(struct wlp *wlp,
362 struct wlp_neighbor_e *neighbor)
363{
364 return wlp_d1d2_exchange(wlp, neighbor, NULL, NULL);
365}
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381static
382int wlp_discover_all_neighbors(struct wlp *wlp)
383{
384 int result = 0;
385 struct device *dev = &wlp->rc->uwb_dev.dev;
386 struct wlp_neighbor_e *neighbor, *next;
387
388 list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
389 result = wlp_discover_neighbor(wlp, neighbor);
390 if (result < 0) {
391 dev_err(dev, "WLP: Unable to discover neighbor "
392 "%02x:%02x, removing from neighborhood. \n",
393 neighbor->uwb_dev->dev_addr.data[1],
394 neighbor->uwb_dev->dev_addr.data[0]);
395 __wlp_neighbor_release(neighbor);
396 }
397 }
398 return result;
399}
400
401static int wlp_add_neighbor_helper(struct device *dev, void *priv)
402{
403 struct wlp *wlp = priv;
404 struct uwb_dev *uwb_dev = to_uwb_dev(dev);
405
406 return wlp_add_neighbor(wlp, uwb_dev);
407}
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427ssize_t wlp_discover(struct wlp *wlp)
428{
429 int result = 0;
430 struct device *dev = &wlp->rc->uwb_dev.dev;
431
432 mutex_lock(&wlp->nbmutex);
433
434 __wlp_neighbors_release(wlp);
435
436 result = uwb_dev_for_each(wlp->rc, wlp_add_neighbor_helper, wlp);
437 if (result < 0) {
438
439 __wlp_neighbors_release(wlp);
440 goto error_dev_for_each;
441 }
442
443 result = wlp_discover_all_neighbors(wlp);
444
445 if (result < 0) {
446 dev_err(dev, "Unable to fully discover neighborhood. \n");
447 result = 0;
448 }
449error_dev_for_each:
450 mutex_unlock(&wlp->nbmutex);
451 return result;
452}
453
454
455
456
457
458
459
460
461
462
463static
464void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev,
465 enum uwb_notifs event)
466{
467 struct wlp *wlp = _wlp;
468 struct device *dev = &wlp->rc->uwb_dev.dev;
469 struct wlp_neighbor_e *neighbor, *next;
470 int result;
471 switch (event) {
472 case UWB_NOTIF_ONAIR:
473 result = wlp_eda_create_node(&wlp->eda,
474 uwb_dev->mac_addr.data,
475 &uwb_dev->dev_addr);
476 if (result < 0)
477 dev_err(dev, "WLP: Unable to add new neighbor "
478 "%02x:%02x to EDA cache.\n",
479 uwb_dev->dev_addr.data[1],
480 uwb_dev->dev_addr.data[0]);
481 break;
482 case UWB_NOTIF_OFFAIR:
483 wlp_eda_rm_node(&wlp->eda, &uwb_dev->dev_addr);
484 mutex_lock(&wlp->nbmutex);
485 list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
486 if (neighbor->uwb_dev == uwb_dev)
487 __wlp_neighbor_release(neighbor);
488 }
489 mutex_unlock(&wlp->nbmutex);
490 break;
491 default:
492 dev_err(dev, "don't know how to handle event %d from uwb\n",
493 event);
494 }
495}
496
497static void wlp_channel_changed(struct uwb_pal *pal, int channel)
498{
499 struct wlp *wlp = container_of(pal, struct wlp, pal);
500
501 if (channel < 0)
502 netif_carrier_off(wlp->ndev);
503 else
504 netif_carrier_on(wlp->ndev);
505}
506
507int wlp_setup(struct wlp *wlp, struct uwb_rc *rc, struct net_device *ndev)
508{
509 int result;
510
511 BUG_ON(wlp->fill_device_info == NULL);
512 BUG_ON(wlp->xmit_frame == NULL);
513 BUG_ON(wlp->stop_queue == NULL);
514 BUG_ON(wlp->start_queue == NULL);
515
516 wlp->rc = rc;
517 wlp->ndev = ndev;
518 wlp_eda_init(&wlp->eda);
519 wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb;
520 wlp->uwb_notifs_handler.data = wlp;
521 uwb_notifs_register(rc, &wlp->uwb_notifs_handler);
522
523 uwb_pal_init(&wlp->pal);
524 wlp->pal.rc = rc;
525 wlp->pal.channel_changed = wlp_channel_changed;
526 result = uwb_pal_register(&wlp->pal);
527 if (result < 0)
528 uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
529
530 return result;
531}
532EXPORT_SYMBOL_GPL(wlp_setup);
533
534void wlp_remove(struct wlp *wlp)
535{
536 wlp_neighbors_release(wlp);
537 uwb_pal_unregister(&wlp->pal);
538 uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
539 wlp_eda_release(&wlp->eda);
540 mutex_lock(&wlp->mutex);
541 if (wlp->dev_info != NULL)
542 kfree(wlp->dev_info);
543 mutex_unlock(&wlp->mutex);
544 wlp->rc = NULL;
545}
546EXPORT_SYMBOL_GPL(wlp_remove);
547
548
549
550
551
552
553
554
555void wlp_reset_all(struct wlp *wlp)
556{
557 uwb_rc_reset_all(wlp->rc);
558}
559EXPORT_SYMBOL_GPL(wlp_reset_all);
560