• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/net/wireless/p54/
1/*
2 * mac80211 glue code for mac80211 Prism54 drivers
3 *
4 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
5 * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 *
8 * Based on:
9 * - the islsm (softmac prism54) driver, which is:
10 *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
11 * - stlc45xx driver
12 *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/firmware.h>
22#include <linux/etherdevice.h>
23
24#include <net/mac80211.h>
25
26#include "p54.h"
27#include "lmac.h"
28
29static int modparam_nohwcrypt;
30module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
31MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
32MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
33MODULE_DESCRIPTION("Softmac Prism54 common code");
34MODULE_LICENSE("GPL");
35MODULE_ALIAS("prism54common");
36
37static int p54_sta_add_remove(struct ieee80211_hw *hw,
38			      struct ieee80211_vif *vif,
39			      struct ieee80211_sta *sta)
40{
41	struct p54_common *priv = hw->priv;
42
43	/*
44	 * Notify the firmware that we don't want or we don't
45	 * need to buffer frames for this station anymore.
46	 */
47
48	p54_sta_unlock(priv, sta->addr);
49
50	return 0;
51}
52
53static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
54			      enum sta_notify_cmd notify_cmd,
55			      struct ieee80211_sta *sta)
56{
57	struct p54_common *priv = dev->priv;
58
59	switch (notify_cmd) {
60	case STA_NOTIFY_AWAKE:
61		/* update the firmware's filter table */
62		p54_sta_unlock(priv, sta->addr);
63		break;
64	default:
65		break;
66	}
67}
68
69static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
70			bool set)
71{
72	struct p54_common *priv = dev->priv;
73
74	return p54_update_beacon_tim(priv, sta->aid, set);
75}
76
77u8 *p54_find_ie(struct sk_buff *skb, u8 ie)
78{
79	struct ieee80211_mgmt *mgmt = (void *)skb->data;
80	u8 *pos, *end;
81
82	if (skb->len <= sizeof(mgmt))
83		return NULL;
84
85	pos = (u8 *)mgmt->u.beacon.variable;
86	end = skb->data + skb->len;
87	while (pos < end) {
88		if (pos + 2 + pos[1] > end)
89			return NULL;
90
91		if (pos[0] == ie)
92			return pos;
93
94		pos += 2 + pos[1];
95	}
96	return NULL;
97}
98
99static int p54_beacon_format_ie_tim(struct sk_buff *skb)
100{
101	/*
102	 * the good excuse for this mess is ... the firmware.
103	 * The dummy TIM MUST be at the end of the beacon frame,
104	 * because it'll be overwritten!
105	 */
106	u8 *tim;
107	u8 dtim_len;
108	u8 dtim_period;
109	u8 *next;
110
111	tim = p54_find_ie(skb, WLAN_EID_TIM);
112	if (!tim)
113		return 0;
114
115	dtim_len = tim[1];
116	dtim_period = tim[3];
117	next = tim + 2 + dtim_len;
118
119	if (dtim_len < 3)
120		return -EINVAL;
121
122	memmove(tim, next, skb_tail_pointer(skb) - next);
123	tim = skb_tail_pointer(skb) - (dtim_len + 2);
124
125	/* add the dummy at the end */
126	tim[0] = WLAN_EID_TIM;
127	tim[1] = 3;
128	tim[2] = 0;
129	tim[3] = dtim_period;
130	tim[4] = 0;
131
132	if (dtim_len > 3)
133		skb_trim(skb, skb->len - (dtim_len - 3));
134
135	return 0;
136}
137
138static int p54_beacon_update(struct p54_common *priv,
139			struct ieee80211_vif *vif)
140{
141	struct sk_buff *beacon;
142	int ret;
143
144	beacon = ieee80211_beacon_get(priv->hw, vif);
145	if (!beacon)
146		return -ENOMEM;
147	ret = p54_beacon_format_ie_tim(beacon);
148	if (ret)
149		return ret;
150
151	/*
152	 * During operation, the firmware takes care of beaconing.
153	 * The driver only needs to upload a new beacon template, once
154	 * the template was changed by the stack or userspace.
155	 *
156	 * LMAC API 3.2.2 also specifies that the driver does not need
157	 * to cancel the old beacon template by hand, instead the firmware
158	 * will release the previous one through the feedback mechanism.
159	 */
160	WARN_ON(p54_tx_80211(priv->hw, beacon));
161	priv->tsf_high32 = 0;
162	priv->tsf_low32 = 0;
163
164	return 0;
165}
166
167static int p54_start(struct ieee80211_hw *dev)
168{
169	struct p54_common *priv = dev->priv;
170	int err;
171
172	mutex_lock(&priv->conf_mutex);
173	err = priv->open(dev);
174	if (err)
175		goto out;
176	P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47);
177	P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94);
178	P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0);
179	P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0);
180	err = p54_set_edcf(priv);
181	if (err)
182		goto out;
183
184	memset(priv->bssid, ~0, ETH_ALEN);
185	priv->mode = NL80211_IFTYPE_MONITOR;
186	err = p54_setup_mac(priv);
187	if (err) {
188		priv->mode = NL80211_IFTYPE_UNSPECIFIED;
189		goto out;
190	}
191
192	ieee80211_queue_delayed_work(dev, &priv->work, 0);
193
194	priv->softled_state = 0;
195	err = p54_set_leds(priv);
196
197out:
198	mutex_unlock(&priv->conf_mutex);
199	return err;
200}
201
202static void p54_stop(struct ieee80211_hw *dev)
203{
204	struct p54_common *priv = dev->priv;
205	int i;
206
207	mutex_lock(&priv->conf_mutex);
208	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
209	priv->softled_state = 0;
210	p54_set_leds(priv);
211
212	cancel_delayed_work_sync(&priv->work);
213
214	priv->stop(dev);
215	skb_queue_purge(&priv->tx_pending);
216	skb_queue_purge(&priv->tx_queue);
217	for (i = 0; i < P54_QUEUE_NUM; i++) {
218		priv->tx_stats[i].count = 0;
219		priv->tx_stats[i].len = 0;
220	}
221
222	priv->beacon_req_id = cpu_to_le32(0);
223	priv->tsf_high32 = priv->tsf_low32 = 0;
224	mutex_unlock(&priv->conf_mutex);
225}
226
227static int p54_add_interface(struct ieee80211_hw *dev,
228			     struct ieee80211_vif *vif)
229{
230	struct p54_common *priv = dev->priv;
231
232	mutex_lock(&priv->conf_mutex);
233	if (priv->mode != NL80211_IFTYPE_MONITOR) {
234		mutex_unlock(&priv->conf_mutex);
235		return -EOPNOTSUPP;
236	}
237
238	priv->vif = vif;
239
240	switch (vif->type) {
241	case NL80211_IFTYPE_STATION:
242	case NL80211_IFTYPE_ADHOC:
243	case NL80211_IFTYPE_AP:
244	case NL80211_IFTYPE_MESH_POINT:
245		priv->mode = vif->type;
246		break;
247	default:
248		mutex_unlock(&priv->conf_mutex);
249		return -EOPNOTSUPP;
250	}
251
252	memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
253	p54_setup_mac(priv);
254	mutex_unlock(&priv->conf_mutex);
255	return 0;
256}
257
258static void p54_remove_interface(struct ieee80211_hw *dev,
259				 struct ieee80211_vif *vif)
260{
261	struct p54_common *priv = dev->priv;
262
263	mutex_lock(&priv->conf_mutex);
264	priv->vif = NULL;
265
266	/*
267	 * LMAC API 3.2.2 states that any active beacon template must be
268	 * canceled by the driver before attempting a mode transition.
269	 */
270	if (le32_to_cpu(priv->beacon_req_id) != 0) {
271		p54_tx_cancel(priv, priv->beacon_req_id);
272		wait_for_completion_interruptible_timeout(&priv->beacon_comp, HZ);
273	}
274	priv->mode = NL80211_IFTYPE_MONITOR;
275	memset(priv->mac_addr, 0, ETH_ALEN);
276	memset(priv->bssid, 0, ETH_ALEN);
277	p54_setup_mac(priv);
278	mutex_unlock(&priv->conf_mutex);
279}
280
281static int p54_config(struct ieee80211_hw *dev, u32 changed)
282{
283	int ret = 0;
284	struct p54_common *priv = dev->priv;
285	struct ieee80211_conf *conf = &dev->conf;
286
287	mutex_lock(&priv->conf_mutex);
288	if (changed & IEEE80211_CONF_CHANGE_POWER)
289		priv->output_power = conf->power_level << 2;
290	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
291		ret = p54_scan(priv, P54_SCAN_EXIT, 0);
292		if (ret)
293			goto out;
294	}
295	if (changed & IEEE80211_CONF_CHANGE_PS) {
296		ret = p54_set_ps(priv);
297		if (ret)
298			goto out;
299	}
300	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
301		ret = p54_setup_mac(priv);
302		if (ret)
303			goto out;
304	}
305
306out:
307	mutex_unlock(&priv->conf_mutex);
308	return ret;
309}
310
311static void p54_configure_filter(struct ieee80211_hw *dev,
312				 unsigned int changed_flags,
313				 unsigned int *total_flags,
314				 u64 multicast)
315{
316	struct p54_common *priv = dev->priv;
317
318	*total_flags &= FIF_PROMISC_IN_BSS |
319			FIF_OTHER_BSS;
320
321	priv->filter_flags = *total_flags;
322
323	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS))
324		p54_setup_mac(priv);
325}
326
327static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
328		       const struct ieee80211_tx_queue_params *params)
329{
330	struct p54_common *priv = dev->priv;
331	int ret;
332
333	mutex_lock(&priv->conf_mutex);
334	if (queue < dev->queues) {
335		P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
336			params->cw_min, params->cw_max, params->txop);
337		ret = p54_set_edcf(priv);
338	} else
339		ret = -EINVAL;
340	mutex_unlock(&priv->conf_mutex);
341	return ret;
342}
343
344static void p54_work(struct work_struct *work)
345{
346	struct p54_common *priv = container_of(work, struct p54_common,
347					       work.work);
348
349	if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
350		return ;
351
352	/*
353	 * TODO: walk through tx_queue and do the following tasks
354	 * 	1. initiate bursts.
355	 *      2. cancel stuck frames / reset the device if necessary.
356	 */
357
358	p54_fetch_statistics(priv);
359}
360
361static int p54_get_stats(struct ieee80211_hw *dev,
362			 struct ieee80211_low_level_stats *stats)
363{
364	struct p54_common *priv = dev->priv;
365
366	memcpy(stats, &priv->stats, sizeof(*stats));
367	return 0;
368}
369
370static void p54_bss_info_changed(struct ieee80211_hw *dev,
371				 struct ieee80211_vif *vif,
372				 struct ieee80211_bss_conf *info,
373				 u32 changed)
374{
375	struct p54_common *priv = dev->priv;
376
377	mutex_lock(&priv->conf_mutex);
378	if (changed & BSS_CHANGED_BSSID) {
379		memcpy(priv->bssid, info->bssid, ETH_ALEN);
380		p54_setup_mac(priv);
381	}
382
383	if (changed & BSS_CHANGED_BEACON) {
384		p54_scan(priv, P54_SCAN_EXIT, 0);
385		p54_setup_mac(priv);
386		p54_beacon_update(priv, vif);
387		p54_set_edcf(priv);
388	}
389
390	if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BEACON)) {
391		priv->use_short_slot = info->use_short_slot;
392		p54_set_edcf(priv);
393	}
394	if (changed & BSS_CHANGED_BASIC_RATES) {
395		if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
396			priv->basic_rate_mask = (info->basic_rates << 4);
397		else
398			priv->basic_rate_mask = info->basic_rates;
399		p54_setup_mac(priv);
400		if (priv->fw_var >= 0x500)
401			p54_scan(priv, P54_SCAN_EXIT, 0);
402	}
403	if (changed & BSS_CHANGED_ASSOC) {
404		if (info->assoc) {
405			priv->aid = info->aid;
406			priv->wakeup_timer = info->beacon_int *
407					     info->dtim_period * 5;
408			p54_setup_mac(priv);
409		} else {
410			priv->wakeup_timer = 500;
411			priv->aid = 0;
412		}
413	}
414
415	mutex_unlock(&priv->conf_mutex);
416}
417
418static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
419		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,
420		       struct ieee80211_key_conf *key)
421{
422	struct p54_common *priv = dev->priv;
423	int slot, ret = 0;
424	u8 algo = 0;
425	u8 *addr = NULL;
426
427	if (modparam_nohwcrypt)
428		return -EOPNOTSUPP;
429
430	mutex_lock(&priv->conf_mutex);
431	if (cmd == SET_KEY) {
432		switch (key->alg) {
433		case ALG_TKIP:
434			if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |
435			      BR_DESC_PRIV_CAP_TKIP))) {
436				ret = -EOPNOTSUPP;
437				goto out_unlock;
438			}
439			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
440			algo = P54_CRYPTO_TKIPMICHAEL;
441			break;
442		case ALG_WEP:
443			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) {
444				ret = -EOPNOTSUPP;
445				goto out_unlock;
446			}
447			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
448			algo = P54_CRYPTO_WEP;
449			break;
450		case ALG_CCMP:
451			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) {
452				ret = -EOPNOTSUPP;
453				goto out_unlock;
454			}
455			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
456			algo = P54_CRYPTO_AESCCMP;
457			break;
458		default:
459			ret = -EOPNOTSUPP;
460			goto out_unlock;
461		}
462		slot = bitmap_find_free_region(priv->used_rxkeys,
463					       priv->rx_keycache_size, 0);
464
465		if (slot < 0) {
466			/*
467			 * The device supports the choosen algorithm, but the
468			 * firmware does not provide enough key slots to store
469			 * all of them.
470			 * But encryption offload for outgoing frames is always
471			 * possible, so we just pretend that the upload was
472			 * successful and do the decryption in software.
473			 */
474
475			/* mark the key as invalid. */
476			key->hw_key_idx = 0xff;
477			goto out_unlock;
478		}
479	} else {
480		slot = key->hw_key_idx;
481
482		if (slot == 0xff) {
483			/* This key was not uploaded into the rx key cache. */
484
485			goto out_unlock;
486		}
487
488		bitmap_release_region(priv->used_rxkeys, slot, 0);
489		algo = 0;
490	}
491
492	if (sta)
493		addr = sta->addr;
494
495	ret = p54_upload_key(priv, algo, slot, key->keyidx,
496			     key->keylen, addr, key->key);
497	if (ret) {
498		bitmap_release_region(priv->used_rxkeys, slot, 0);
499		ret = -EOPNOTSUPP;
500		goto out_unlock;
501	}
502
503	key->hw_key_idx = slot;
504
505out_unlock:
506	mutex_unlock(&priv->conf_mutex);
507	return ret;
508}
509
510static int p54_get_survey(struct ieee80211_hw *dev, int idx,
511				struct survey_info *survey)
512{
513	struct p54_common *priv = dev->priv;
514	struct ieee80211_conf *conf = &dev->conf;
515
516	if (idx != 0)
517		return -ENOENT;
518
519	survey->channel = conf->channel;
520	survey->filled = SURVEY_INFO_NOISE_DBM;
521	survey->noise = clamp_t(s8, priv->noise, -128, 127);
522
523	return 0;
524}
525
526static const struct ieee80211_ops p54_ops = {
527	.tx			= p54_tx_80211,
528	.start			= p54_start,
529	.stop			= p54_stop,
530	.add_interface		= p54_add_interface,
531	.remove_interface	= p54_remove_interface,
532	.set_tim		= p54_set_tim,
533	.sta_notify		= p54_sta_notify,
534	.sta_add		= p54_sta_add_remove,
535	.sta_remove		= p54_sta_add_remove,
536	.set_key		= p54_set_key,
537	.config			= p54_config,
538	.bss_info_changed	= p54_bss_info_changed,
539	.configure_filter	= p54_configure_filter,
540	.conf_tx		= p54_conf_tx,
541	.get_stats		= p54_get_stats,
542	.get_survey		= p54_get_survey,
543};
544
545struct ieee80211_hw *p54_init_common(size_t priv_data_len)
546{
547	struct ieee80211_hw *dev;
548	struct p54_common *priv;
549
550	dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
551	if (!dev)
552		return NULL;
553
554	priv = dev->priv;
555	priv->hw = dev;
556	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
557	priv->basic_rate_mask = 0x15f;
558	spin_lock_init(&priv->tx_stats_lock);
559	skb_queue_head_init(&priv->tx_queue);
560	skb_queue_head_init(&priv->tx_pending);
561	dev->flags = IEEE80211_HW_RX_INCLUDES_FCS |
562		     IEEE80211_HW_SIGNAL_DBM |
563		     IEEE80211_HW_SUPPORTS_PS |
564		     IEEE80211_HW_PS_NULLFUNC_STACK |
565		     IEEE80211_HW_BEACON_FILTER |
566		     IEEE80211_HW_REPORTS_TX_ACK_STATUS;
567
568	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
569				      BIT(NL80211_IFTYPE_ADHOC) |
570				      BIT(NL80211_IFTYPE_AP) |
571				      BIT(NL80211_IFTYPE_MESH_POINT);
572
573	dev->channel_change_time = 1000;	/* TODO: find actual value */
574	priv->beacon_req_id = cpu_to_le32(0);
575	priv->tx_stats[P54_QUEUE_BEACON].limit = 1;
576	priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1;
577	priv->tx_stats[P54_QUEUE_MGMT].limit = 3;
578	priv->tx_stats[P54_QUEUE_CAB].limit = 3;
579	priv->tx_stats[P54_QUEUE_DATA].limit = 5;
580	dev->queues = 1;
581	priv->noise = -94;
582	/*
583	 * We support at most 8 tries no matter which rate they're at,
584	 * we cannot support max_rates * max_rate_tries as we set it
585	 * here, but setting it correctly to 4/2 or so would limit us
586	 * artificially if the RC algorithm wants just two rates, so
587	 * let's say 4/7, we'll redistribute it at TX time, see the
588	 * comments there.
589	 */
590	dev->max_rates = 4;
591	dev->max_rate_tries = 7;
592	dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +
593				 sizeof(struct p54_tx_data);
594
595	/*
596	 * For now, disable PS by default because it affects
597	 * link stability significantly.
598	 */
599	dev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
600
601	mutex_init(&priv->conf_mutex);
602	mutex_init(&priv->eeprom_mutex);
603	init_completion(&priv->eeprom_comp);
604	init_completion(&priv->beacon_comp);
605	INIT_DELAYED_WORK(&priv->work, p54_work);
606
607	return dev;
608}
609EXPORT_SYMBOL_GPL(p54_init_common);
610
611int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)
612{
613	struct p54_common *priv = dev->priv;
614	int err;
615
616	err = ieee80211_register_hw(dev);
617	if (err) {
618		dev_err(pdev, "Cannot register device (%d).\n", err);
619		return err;
620	}
621
622#ifdef CONFIG_P54_LEDS
623	err = p54_init_leds(priv);
624	if (err)
625		return err;
626#endif /* CONFIG_P54_LEDS */
627
628	dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy));
629	return 0;
630}
631EXPORT_SYMBOL_GPL(p54_register_common);
632
633void p54_free_common(struct ieee80211_hw *dev)
634{
635	struct p54_common *priv = dev->priv;
636	unsigned int i;
637
638	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
639		kfree(priv->band_table[i]);
640
641	kfree(priv->iq_autocal);
642	kfree(priv->output_limit);
643	kfree(priv->curve_data);
644	kfree(priv->used_rxkeys);
645	priv->iq_autocal = NULL;
646	priv->output_limit = NULL;
647	priv->curve_data = NULL;
648	priv->used_rxkeys = NULL;
649	ieee80211_free_hw(dev);
650}
651EXPORT_SYMBOL_GPL(p54_free_common);
652
653void p54_unregister_common(struct ieee80211_hw *dev)
654{
655	struct p54_common *priv = dev->priv;
656
657#ifdef CONFIG_P54_LEDS
658	p54_unregister_leds(priv);
659#endif /* CONFIG_P54_LEDS */
660
661	ieee80211_unregister_hw(dev);
662	mutex_destroy(&priv->conf_mutex);
663	mutex_destroy(&priv->eeprom_mutex);
664}
665EXPORT_SYMBOL_GPL(p54_unregister_common);
666