• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/uwb/wlp/
1
2#include <linux/wlp.h>
3#include <linux/slab.h>
4
5#include "wlp-internal.h"
6
7static
8void wlp_neighbor_init(struct wlp_neighbor_e *neighbor)
9{
10	INIT_LIST_HEAD(&neighbor->wssid);
11}
12
13/**
14 * Create area for device information storage
15 *
16 * wlp->mutex must be held
17 */
18int __wlp_alloc_device_info(struct wlp *wlp)
19{
20	struct device *dev = &wlp->rc->uwb_dev.dev;
21	BUG_ON(wlp->dev_info != NULL);
22	wlp->dev_info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
23	if (wlp->dev_info == NULL) {
24		dev_err(dev, "WLP: Unable to allocate memory for "
25			"device information.\n");
26		return -ENOMEM;
27	}
28	return 0;
29}
30
31
32/**
33 * Fill in device information using function provided by driver
34 *
35 * wlp->mutex must be held
36 */
37static
38void __wlp_fill_device_info(struct wlp *wlp)
39{
40	wlp->fill_device_info(wlp, wlp->dev_info);
41}
42
43/**
44 * Setup device information
45 *
46 * Allocate area for device information and populate it.
47 *
48 * wlp->mutex must be held
49 */
50int __wlp_setup_device_info(struct wlp *wlp)
51{
52	int result;
53	struct device *dev = &wlp->rc->uwb_dev.dev;
54
55	result = __wlp_alloc_device_info(wlp);
56	if (result < 0) {
57		dev_err(dev, "WLP: Unable to allocate area for "
58			"device information.\n");
59		return result;
60	}
61	__wlp_fill_device_info(wlp);
62	return 0;
63}
64
65/**
66 * Remove information about neighbor stored temporarily
67 *
68 * Information learned during discovey should only be stored when the
69 * device enrolls in the neighbor's WSS. We do need to store this
70 * information temporarily in order to present it to the user.
71 *
72 * We are only interested in keeping neighbor WSS information if that
73 * neighbor is accepting enrollment.
74 *
75 * should be called with wlp->nbmutex held
76 */
77void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *neighbor)
78{
79	struct wlp_wssid_e *wssid_e, *next;
80	u8 keep;
81	if (!list_empty(&neighbor->wssid)) {
82		list_for_each_entry_safe(wssid_e, next, &neighbor->wssid,
83					 node) {
84			if (wssid_e->info != NULL) {
85				keep = wssid_e->info->accept_enroll;
86				kfree(wssid_e->info);
87				wssid_e->info = NULL;
88				if (!keep) {
89					list_del(&wssid_e->node);
90					kfree(wssid_e);
91				}
92			}
93		}
94	}
95	if (neighbor->info != NULL) {
96		kfree(neighbor->info);
97		neighbor->info = NULL;
98	}
99}
100
101/*
102 * Populate WLP neighborhood cache with neighbor information
103 *
104 * A new neighbor is found. If it is discoverable then we add it to the
105 * neighborhood cache.
106 *
107 */
108static
109int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev)
110{
111	int result = 0;
112	int discoverable;
113	struct wlp_neighbor_e *neighbor;
114
115	discoverable = 1;
116	if (discoverable) {
117		/* Add neighbor to cache for discovery */
118		neighbor = kzalloc(sizeof(*neighbor), GFP_KERNEL);
119		if (neighbor == NULL) {
120			dev_err(&dev->dev, "Unable to create memory for "
121				"new neighbor. \n");
122			result = -ENOMEM;
123			goto error_no_mem;
124		}
125		wlp_neighbor_init(neighbor);
126		uwb_dev_get(dev);
127		neighbor->uwb_dev = dev;
128		list_add(&neighbor->node, &wlp->neighbors);
129	}
130error_no_mem:
131	return result;
132}
133
134/**
135 * Remove one neighbor from cache
136 */
137static
138void __wlp_neighbor_release(struct wlp_neighbor_e *neighbor)
139{
140	struct wlp_wssid_e *wssid_e, *next_wssid_e;
141
142	list_for_each_entry_safe(wssid_e, next_wssid_e,
143				 &neighbor->wssid, node) {
144		list_del(&wssid_e->node);
145		kfree(wssid_e);
146	}
147	uwb_dev_put(neighbor->uwb_dev);
148	list_del(&neighbor->node);
149	kfree(neighbor);
150}
151
152/**
153 * Clear entire neighborhood cache.
154 */
155static
156void __wlp_neighbors_release(struct wlp *wlp)
157{
158	struct wlp_neighbor_e *neighbor, *next;
159	if (list_empty(&wlp->neighbors))
160		return;
161	list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
162		__wlp_neighbor_release(neighbor);
163	}
164}
165
166static
167void wlp_neighbors_release(struct wlp *wlp)
168{
169	mutex_lock(&wlp->nbmutex);
170	__wlp_neighbors_release(wlp);
171	mutex_unlock(&wlp->nbmutex);
172}
173
174
175
176/**
177 * Send D1 message to neighbor, receive D2 message
178 *
179 * @neighbor: neighbor to which D1 message will be sent
180 * @wss:      if not NULL, it is an enrollment request for this WSS
181 * @wssid:    if wss not NULL, this is the wssid of the WSS in which we
182 *            want to enroll
183 *
184 * A D1/D2 exchange is done for one of two reasons: discovery or
185 * enrollment. If done for discovery the D1 message is sent to the neighbor
186 * and the contents of the D2 response is stored in a temporary cache.
187 * If done for enrollment the @wss and @wssid are provided also. In this
188 * case the D1 message is sent to the neighbor, the D2 response is parsed
189 * for enrollment of the WSS with wssid.
190 *
191 * &wss->mutex is held
192 */
193static
194int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
195		      struct wlp_wss *wss, struct wlp_uuid *wssid)
196{
197	int result;
198	struct device *dev = &wlp->rc->uwb_dev.dev;
199	DECLARE_COMPLETION_ONSTACK(completion);
200	struct wlp_session session;
201	struct sk_buff  *skb;
202	struct wlp_frame_assoc *resp;
203	struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
204
205	mutex_lock(&wlp->mutex);
206	if (!wlp_uuid_is_set(&wlp->uuid)) {
207		dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
208			"proceed.\n");
209		result = -ENXIO;
210		goto out;
211	}
212	/* Send D1 association frame */
213	result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_D1);
214	if (result < 0) {
215		dev_err(dev, "Unable to send D1 frame to neighbor "
216			"%02x:%02x (%d)\n", dev_addr->data[1],
217			dev_addr->data[0], result);
218		goto out;
219	}
220	/* Create session, wait for response */
221	session.exp_message = WLP_ASSOC_D2;
222	session.cb = wlp_session_cb;
223	session.cb_priv = &completion;
224	session.neighbor_addr = *dev_addr;
225	BUG_ON(wlp->session != NULL);
226	wlp->session = &session;
227	/* Wait for D2/F0 frame */
228	result = wait_for_completion_interruptible_timeout(&completion,
229						   WLP_PER_MSG_TIMEOUT * HZ);
230	if (result == 0) {
231		result = -ETIMEDOUT;
232		dev_err(dev, "Timeout while sending D1 to neighbor "
233			     "%02x:%02x.\n", dev_addr->data[1],
234			     dev_addr->data[0]);
235		goto error_session;
236	}
237	if (result < 0) {
238		dev_err(dev, "Unable to discover/enroll neighbor %02x:%02x.\n",
239			dev_addr->data[1], dev_addr->data[0]);
240		goto error_session;
241	}
242	/* Parse message in session->data: it will be either D2 or F0 */
243	skb = session.data;
244	resp = (void *) skb->data;
245
246	if (resp->type == WLP_ASSOC_F0) {
247		result = wlp_parse_f0(wlp, skb);
248		if (result < 0)
249			dev_err(dev, "WLP: Unable to parse F0 from neighbor "
250				"%02x:%02x.\n", dev_addr->data[1],
251				dev_addr->data[0]);
252		result = -EINVAL;
253		goto error_resp_parse;
254	}
255	if (wss == NULL) {
256		/* Discovery */
257		result = wlp_parse_d2_frame_to_cache(wlp, skb, neighbor);
258		if (result < 0) {
259			dev_err(dev, "WLP: Unable to parse D2 message from "
260				"neighbor %02x:%02x for discovery.\n",
261				dev_addr->data[1], dev_addr->data[0]);
262			goto error_resp_parse;
263		}
264	} else {
265		/* Enrollment */
266		result = wlp_parse_d2_frame_to_enroll(wss, skb, neighbor,
267						      wssid);
268		if (result < 0) {
269			dev_err(dev, "WLP: Unable to parse D2 message from "
270				"neighbor %02x:%02x for enrollment.\n",
271				dev_addr->data[1], dev_addr->data[0]);
272			goto error_resp_parse;
273		}
274	}
275error_resp_parse:
276	kfree_skb(skb);
277error_session:
278	wlp->session = NULL;
279out:
280	mutex_unlock(&wlp->mutex);
281	return result;
282}
283
284/**
285 * Enroll into WSS of provided WSSID by using neighbor as registrar
286 *
287 * &wss->mutex is held
288 */
289int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
290			struct wlp_wss *wss, struct wlp_uuid *wssid)
291{
292	int result = 0;
293	struct device *dev = &wlp->rc->uwb_dev.dev;
294	char buf[WLP_WSS_UUID_STRSIZE];
295	struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
296
297	wlp_wss_uuid_print(buf, sizeof(buf), wssid);
298
299	result =  wlp_d1d2_exchange(wlp, neighbor, wss, wssid);
300	if (result < 0) {
301		dev_err(dev, "WLP: D1/D2 message exchange for enrollment "
302			"failed. result = %d \n", result);
303		goto out;
304	}
305	if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
306		dev_err(dev, "WLP: Unable to enroll into WSS %s using "
307			"neighbor %02x:%02x. \n", buf,
308			dev_addr->data[1], dev_addr->data[0]);
309		result = -EINVAL;
310		goto out;
311	}
312	if (wss->secure_status == WLP_WSS_SECURE) {
313		dev_err(dev, "FIXME: need to complete secure enrollment.\n");
314		result = -EINVAL;
315		goto error;
316	} else {
317		wss->state = WLP_WSS_STATE_ENROLLED;
318		dev_dbg(dev, "WLP: Success Enrollment into unsecure WSS "
319			"%s using neighbor %02x:%02x. \n",
320			buf, dev_addr->data[1], dev_addr->data[0]);
321	}
322out:
323	return result;
324error:
325	wlp_wss_reset(wss);
326	return result;
327}
328
329/**
330 * Discover WSS information of neighbor's active WSS
331 */
332static
333int wlp_discover_neighbor(struct wlp *wlp,
334			  struct wlp_neighbor_e *neighbor)
335{
336	return wlp_d1d2_exchange(wlp, neighbor, NULL, NULL);
337}
338
339
340/**
341 * Each neighbor in the neighborhood cache is discoverable. Discover it.
342 *
343 * Discovery is done through sending of D1 association frame and parsing
344 * the D2 association frame response. Only wssid from D2 will be included
345 * in neighbor cache, rest is just displayed to user and forgotten.
346 *
347 * The discovery is not done in parallel. This is simple and enables us to
348 * maintain only one association context.
349 *
350 * The discovery of one neighbor does not affect the other, but if the
351 * discovery of a neighbor fails it is removed from the neighborhood cache.
352 */
353static
354int wlp_discover_all_neighbors(struct wlp *wlp)
355{
356	int result = 0;
357	struct device *dev = &wlp->rc->uwb_dev.dev;
358	struct wlp_neighbor_e *neighbor, *next;
359
360	list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
361		result = wlp_discover_neighbor(wlp, neighbor);
362		if (result < 0) {
363			dev_err(dev, "WLP: Unable to discover neighbor "
364				"%02x:%02x, removing from neighborhood. \n",
365				neighbor->uwb_dev->dev_addr.data[1],
366				neighbor->uwb_dev->dev_addr.data[0]);
367			__wlp_neighbor_release(neighbor);
368		}
369	}
370	return result;
371}
372
373static int wlp_add_neighbor_helper(struct device *dev, void *priv)
374{
375	struct wlp *wlp = priv;
376	struct uwb_dev *uwb_dev = to_uwb_dev(dev);
377
378	return wlp_add_neighbor(wlp, uwb_dev);
379}
380
381/**
382 * Discover WLP neighborhood
383 *
384 * Will send D1 association frame to all devices in beacon group that have
385 * discoverable bit set in WLP IE. D2 frames will be received, information
386 * displayed to user in @buf. Partial information (from D2 association
387 * frame) will be cached to assist with future association
388 * requests.
389 *
390 * The discovery of the WLP neighborhood is triggered by the user. This
391 * should occur infrequently and we thus free current cache and re-allocate
392 * memory if needed.
393 *
394 * If one neighbor fails during initial discovery (determining if it is a
395 * neighbor or not), we fail all - note that interaction with neighbor has
396 * not occured at this point so if a failure occurs we know something went wrong
397 * locally. We thus undo everything.
398 */
399ssize_t wlp_discover(struct wlp *wlp)
400{
401	int result = 0;
402	struct device *dev = &wlp->rc->uwb_dev.dev;
403
404	mutex_lock(&wlp->nbmutex);
405	/* Clear current neighborhood cache. */
406	__wlp_neighbors_release(wlp);
407	/* Determine which devices in neighborhood. Repopulate cache. */
408	result = uwb_dev_for_each(wlp->rc, wlp_add_neighbor_helper, wlp);
409	if (result < 0) {
410		/* May have partial neighbor information, release all. */
411		__wlp_neighbors_release(wlp);
412		goto error_dev_for_each;
413	}
414	/* Discover the properties of devices in neighborhood. */
415	result = wlp_discover_all_neighbors(wlp);
416	/* In case of failure we still print our partial results. */
417	if (result < 0) {
418		dev_err(dev, "Unable to fully discover neighborhood. \n");
419		result = 0;
420	}
421error_dev_for_each:
422	mutex_unlock(&wlp->nbmutex);
423	return result;
424}
425
426/**
427 * Handle events from UWB stack
428 *
429 * We handle events conservatively. If a neighbor goes off the air we
430 * remove it from the neighborhood. If an association process is in
431 * progress this function will block waiting for the nbmutex to become
432 * free. The association process will thus be allowed to complete before it
433 * is removed.
434 */
435static
436void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev,
437		       enum uwb_notifs event)
438{
439	struct wlp *wlp = _wlp;
440	struct device *dev = &wlp->rc->uwb_dev.dev;
441	struct wlp_neighbor_e *neighbor, *next;
442	int result;
443	switch (event) {
444	case UWB_NOTIF_ONAIR:
445		result = wlp_eda_create_node(&wlp->eda,
446					     uwb_dev->mac_addr.data,
447					     &uwb_dev->dev_addr);
448		if (result < 0)
449			dev_err(dev, "WLP: Unable to add new neighbor "
450				"%02x:%02x to EDA cache.\n",
451				uwb_dev->dev_addr.data[1],
452				uwb_dev->dev_addr.data[0]);
453		break;
454	case UWB_NOTIF_OFFAIR:
455		wlp_eda_rm_node(&wlp->eda, &uwb_dev->dev_addr);
456		mutex_lock(&wlp->nbmutex);
457		list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
458			if (neighbor->uwb_dev == uwb_dev)
459				__wlp_neighbor_release(neighbor);
460		}
461		mutex_unlock(&wlp->nbmutex);
462		break;
463	default:
464		dev_err(dev, "don't know how to handle event %d from uwb\n",
465				event);
466	}
467}
468
469static void wlp_channel_changed(struct uwb_pal *pal, int channel)
470{
471	struct wlp *wlp = container_of(pal, struct wlp, pal);
472
473	if (channel < 0)
474		netif_carrier_off(wlp->ndev);
475	else
476		netif_carrier_on(wlp->ndev);
477}
478
479int wlp_setup(struct wlp *wlp, struct uwb_rc *rc, struct net_device *ndev)
480{
481	int result;
482
483	BUG_ON(wlp->fill_device_info == NULL);
484	BUG_ON(wlp->xmit_frame == NULL);
485	BUG_ON(wlp->stop_queue == NULL);
486	BUG_ON(wlp->start_queue == NULL);
487
488	wlp->rc = rc;
489	wlp->ndev = ndev;
490	wlp_eda_init(&wlp->eda);/* Set up address cache */
491	wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb;
492	wlp->uwb_notifs_handler.data = wlp;
493	uwb_notifs_register(rc, &wlp->uwb_notifs_handler);
494
495	uwb_pal_init(&wlp->pal);
496	wlp->pal.rc = rc;
497	wlp->pal.channel_changed = wlp_channel_changed;
498	result = uwb_pal_register(&wlp->pal);
499	if (result < 0)
500		uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
501
502	return result;
503}
504EXPORT_SYMBOL_GPL(wlp_setup);
505
506void wlp_remove(struct wlp *wlp)
507{
508	wlp_neighbors_release(wlp);
509	uwb_pal_unregister(&wlp->pal);
510	uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
511	wlp_eda_release(&wlp->eda);
512	mutex_lock(&wlp->mutex);
513	if (wlp->dev_info != NULL)
514		kfree(wlp->dev_info);
515	mutex_unlock(&wlp->mutex);
516	wlp->rc = NULL;
517}
518EXPORT_SYMBOL_GPL(wlp_remove);
519
520/**
521 * wlp_reset_all - reset the WLP hardware
522 * @wlp: the WLP device to reset.
523 *
524 * This schedules a full hardware reset of the WLP device.  The radio
525 * controller and any other PALs will also be reset.
526 */
527void wlp_reset_all(struct wlp *wlp)
528{
529	uwb_rc_reset_all(wlp->rc);
530}
531EXPORT_SYMBOL_GPL(wlp_reset_all);
532