• 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.36/drivers/net/wireless/iwmc3200wifi/
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@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
24#include <linux/kernel.h>
25#include <linux/netdevice.h>
26#include <linux/sched.h>
27#include <linux/etherdevice.h>
28#include <linux/wireless.h>
29#include <linux/ieee80211.h>
30#include <linux/slab.h>
31#include <net/cfg80211.h>
32
33#include "iwm.h"
34#include "commands.h"
35#include "cfg80211.h"
36#include "debug.h"
37
38#define RATETAB_ENT(_rate, _rateid, _flags) \
39	{								\
40		.bitrate	= (_rate),				\
41		.hw_value	= (_rateid),				\
42		.flags		= (_flags),				\
43	}
44
45#define CHAN2G(_channel, _freq, _flags) {			\
46	.band			= IEEE80211_BAND_2GHZ,		\
47	.center_freq		= (_freq),			\
48	.hw_value		= (_channel),			\
49	.flags			= (_flags),			\
50	.max_antenna_gain	= 0,				\
51	.max_power		= 30,				\
52}
53
54#define CHAN5G(_channel, _flags) {				\
55	.band			= IEEE80211_BAND_5GHZ,		\
56	.center_freq		= 5000 + (5 * (_channel)),	\
57	.hw_value		= (_channel),			\
58	.flags			= (_flags),			\
59	.max_antenna_gain	= 0,				\
60	.max_power		= 30,				\
61}
62
63static struct ieee80211_rate iwm_rates[] = {
64	RATETAB_ENT(10,  0x1,   0),
65	RATETAB_ENT(20,  0x2,   0),
66	RATETAB_ENT(55,  0x4,   0),
67	RATETAB_ENT(110, 0x8,   0),
68	RATETAB_ENT(60,  0x10,  0),
69	RATETAB_ENT(90,  0x20,  0),
70	RATETAB_ENT(120, 0x40,  0),
71	RATETAB_ENT(180, 0x80,  0),
72	RATETAB_ENT(240, 0x100, 0),
73	RATETAB_ENT(360, 0x200, 0),
74	RATETAB_ENT(480, 0x400, 0),
75	RATETAB_ENT(540, 0x800, 0),
76};
77
78#define iwm_a_rates		(iwm_rates + 4)
79#define iwm_a_rates_size	8
80#define iwm_g_rates		(iwm_rates + 0)
81#define iwm_g_rates_size	12
82
83static struct ieee80211_channel iwm_2ghz_channels[] = {
84	CHAN2G(1, 2412, 0),
85	CHAN2G(2, 2417, 0),
86	CHAN2G(3, 2422, 0),
87	CHAN2G(4, 2427, 0),
88	CHAN2G(5, 2432, 0),
89	CHAN2G(6, 2437, 0),
90	CHAN2G(7, 2442, 0),
91	CHAN2G(8, 2447, 0),
92	CHAN2G(9, 2452, 0),
93	CHAN2G(10, 2457, 0),
94	CHAN2G(11, 2462, 0),
95	CHAN2G(12, 2467, 0),
96	CHAN2G(13, 2472, 0),
97	CHAN2G(14, 2484, 0),
98};
99
100static struct ieee80211_channel iwm_5ghz_a_channels[] = {
101	CHAN5G(34, 0),		CHAN5G(36, 0),
102	CHAN5G(38, 0),		CHAN5G(40, 0),
103	CHAN5G(42, 0),		CHAN5G(44, 0),
104	CHAN5G(46, 0),		CHAN5G(48, 0),
105	CHAN5G(52, 0),		CHAN5G(56, 0),
106	CHAN5G(60, 0),		CHAN5G(64, 0),
107	CHAN5G(100, 0),		CHAN5G(104, 0),
108	CHAN5G(108, 0),		CHAN5G(112, 0),
109	CHAN5G(116, 0),		CHAN5G(120, 0),
110	CHAN5G(124, 0),		CHAN5G(128, 0),
111	CHAN5G(132, 0),		CHAN5G(136, 0),
112	CHAN5G(140, 0),		CHAN5G(149, 0),
113	CHAN5G(153, 0),		CHAN5G(157, 0),
114	CHAN5G(161, 0),		CHAN5G(165, 0),
115	CHAN5G(184, 0),		CHAN5G(188, 0),
116	CHAN5G(192, 0),		CHAN5G(196, 0),
117	CHAN5G(200, 0),		CHAN5G(204, 0),
118	CHAN5G(208, 0),		CHAN5G(212, 0),
119	CHAN5G(216, 0),
120};
121
122static struct ieee80211_supported_band iwm_band_2ghz = {
123	.channels = iwm_2ghz_channels,
124	.n_channels = ARRAY_SIZE(iwm_2ghz_channels),
125	.bitrates = iwm_g_rates,
126	.n_bitrates = iwm_g_rates_size,
127};
128
129static struct ieee80211_supported_band iwm_band_5ghz = {
130	.channels = iwm_5ghz_a_channels,
131	.n_channels = ARRAY_SIZE(iwm_5ghz_a_channels),
132	.bitrates = iwm_a_rates,
133	.n_bitrates = iwm_a_rates_size,
134};
135
136static int iwm_key_init(struct iwm_key *key, u8 key_index,
137			const u8 *mac_addr, struct key_params *params)
138{
139	key->hdr.key_idx = key_index;
140	if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
141		key->hdr.multicast = 1;
142		memset(key->hdr.mac, 0xff, ETH_ALEN);
143	} else {
144		key->hdr.multicast = 0;
145		memcpy(key->hdr.mac, mac_addr, ETH_ALEN);
146	}
147
148	if (params) {
149		if (params->key_len > WLAN_MAX_KEY_LEN ||
150		    params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
151			return -EINVAL;
152
153		key->cipher = params->cipher;
154		key->key_len = params->key_len;
155		key->seq_len = params->seq_len;
156		memcpy(key->key, params->key, key->key_len);
157		memcpy(key->seq, params->seq, key->seq_len);
158	}
159
160	return 0;
161}
162
163static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
164				u8 key_index, const u8 *mac_addr,
165				struct key_params *params)
166{
167	struct iwm_priv *iwm = ndev_to_iwm(ndev);
168	struct iwm_key *key = &iwm->keys[key_index];
169	int ret;
170
171	IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
172
173	memset(key, 0, sizeof(struct iwm_key));
174	ret = iwm_key_init(key, key_index, mac_addr, params);
175	if (ret < 0) {
176		IWM_ERR(iwm, "Invalid key_params\n");
177		return ret;
178	}
179
180	return iwm_set_key(iwm, 0, key);
181}
182
183static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
184				u8 key_index, const u8 *mac_addr, void *cookie,
185				void (*callback)(void *cookie,
186						 struct key_params*))
187{
188	struct iwm_priv *iwm = ndev_to_iwm(ndev);
189	struct iwm_key *key = &iwm->keys[key_index];
190	struct key_params params;
191
192	IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
193
194	memset(&params, 0, sizeof(params));
195
196	params.cipher = key->cipher;
197	params.key_len = key->key_len;
198	params.seq_len = key->seq_len;
199	params.seq = key->seq;
200	params.key = key->key;
201
202	callback(cookie, &params);
203
204	return key->key_len ? 0 : -ENOENT;
205}
206
207
208static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
209				u8 key_index, const u8 *mac_addr)
210{
211	struct iwm_priv *iwm = ndev_to_iwm(ndev);
212	struct iwm_key *key = &iwm->keys[key_index];
213
214	if (!iwm->keys[key_index].key_len) {
215		IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
216		return 0;
217	}
218
219	if (key_index == iwm->default_key)
220		iwm->default_key = -1;
221
222	return iwm_set_key(iwm, 1, key);
223}
224
225static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
226					struct net_device *ndev,
227					u8 key_index)
228{
229	struct iwm_priv *iwm = ndev_to_iwm(ndev);
230
231	IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
232
233	if (!iwm->keys[key_index].key_len) {
234		IWM_ERR(iwm, "Key %d not used\n", key_index);
235		return -EINVAL;
236	}
237
238	iwm->default_key = key_index;
239
240	return iwm_set_tx_key(iwm, key_index);
241}
242
243static int iwm_cfg80211_get_station(struct wiphy *wiphy,
244				    struct net_device *ndev,
245				    u8 *mac, struct station_info *sinfo)
246{
247	struct iwm_priv *iwm = ndev_to_iwm(ndev);
248
249	if (memcmp(mac, iwm->bssid, ETH_ALEN))
250		return -ENOENT;
251
252	sinfo->filled |= STATION_INFO_TX_BITRATE;
253	sinfo->txrate.legacy = iwm->rate * 10;
254
255	if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
256		sinfo->filled |= STATION_INFO_SIGNAL;
257		sinfo->signal = iwm->wstats.qual.level;
258	}
259
260	return 0;
261}
262
263
264int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
265{
266	struct wiphy *wiphy = iwm_to_wiphy(iwm);
267	struct iwm_bss_info *bss;
268	struct iwm_umac_notif_bss_info *umac_bss;
269	struct ieee80211_mgmt *mgmt;
270	struct ieee80211_channel *channel;
271	struct ieee80211_supported_band *band;
272	s32 signal;
273	int freq;
274
275	list_for_each_entry(bss, &iwm->bss_list, node) {
276		umac_bss = bss->bss;
277		mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
278
279		if (umac_bss->band == UMAC_BAND_2GHZ)
280			band = wiphy->bands[IEEE80211_BAND_2GHZ];
281		else if (umac_bss->band == UMAC_BAND_5GHZ)
282			band = wiphy->bands[IEEE80211_BAND_5GHZ];
283		else {
284			IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
285			return -EINVAL;
286		}
287
288		freq = ieee80211_channel_to_frequency(umac_bss->channel);
289		channel = ieee80211_get_channel(wiphy, freq);
290		signal = umac_bss->rssi * 100;
291
292		if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
293					       le16_to_cpu(umac_bss->frame_len),
294					       signal, GFP_KERNEL))
295			return -EINVAL;
296	}
297
298	return 0;
299}
300
301static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
302				     struct net_device *ndev,
303				     enum nl80211_iftype type, u32 *flags,
304				     struct vif_params *params)
305{
306	struct wireless_dev *wdev;
307	struct iwm_priv *iwm;
308	u32 old_mode;
309
310	wdev = ndev->ieee80211_ptr;
311	iwm = ndev_to_iwm(ndev);
312	old_mode = iwm->conf.mode;
313
314	switch (type) {
315	case NL80211_IFTYPE_STATION:
316		iwm->conf.mode = UMAC_MODE_BSS;
317		break;
318	case NL80211_IFTYPE_ADHOC:
319		iwm->conf.mode = UMAC_MODE_IBSS;
320		break;
321	default:
322		return -EOPNOTSUPP;
323	}
324
325	wdev->iftype = type;
326
327	if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
328		return 0;
329
330	iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
331
332	if (iwm->umac_profile_active)
333		iwm_invalidate_mlme_profile(iwm);
334
335	return 0;
336}
337
338static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
339			     struct cfg80211_scan_request *request)
340{
341	struct iwm_priv *iwm = ndev_to_iwm(ndev);
342	int ret;
343
344	if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
345		IWM_ERR(iwm, "Scan while device is not ready\n");
346		return -EIO;
347	}
348
349	if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
350		IWM_ERR(iwm, "Scanning already\n");
351		return -EAGAIN;
352	}
353
354	if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
355		IWM_ERR(iwm, "Scanning being aborted\n");
356		return -EAGAIN;
357	}
358
359	set_bit(IWM_STATUS_SCANNING, &iwm->status);
360
361	ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
362	if (ret) {
363		clear_bit(IWM_STATUS_SCANNING, &iwm->status);
364		return ret;
365	}
366
367	iwm->scan_request = request;
368	return 0;
369}
370
371static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
372{
373	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
374
375	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
376	    (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
377		int ret;
378
379		iwm->conf.rts_threshold = wiphy->rts_threshold;
380
381		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
382					     CFG_RTS_THRESHOLD,
383					     iwm->conf.rts_threshold);
384		if (ret < 0)
385			return ret;
386	}
387
388	if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
389	    (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
390		int ret;
391
392		iwm->conf.frag_threshold = wiphy->frag_threshold;
393
394		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
395					     CFG_FRAG_THRESHOLD,
396					     iwm->conf.frag_threshold);
397		if (ret < 0)
398			return ret;
399	}
400
401	return 0;
402}
403
404static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
405				  struct cfg80211_ibss_params *params)
406{
407	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
408	struct ieee80211_channel *chan = params->channel;
409
410	if (!test_bit(IWM_STATUS_READY, &iwm->status))
411		return -EIO;
412
413	/* UMAC doesn't support creating or joining an IBSS network
414	 * with specified bssid. */
415	if (params->bssid)
416		return -EOPNOTSUPP;
417
418	iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
419	iwm->umac_profile->ibss.band = chan->band;
420	iwm->umac_profile->ibss.channel = iwm->channel;
421	iwm->umac_profile->ssid.ssid_len = params->ssid_len;
422	memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
423
424	return iwm_send_mlme_profile(iwm);
425}
426
427static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
428{
429	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
430
431	if (iwm->umac_profile_active)
432		return iwm_invalidate_mlme_profile(iwm);
433
434	return 0;
435}
436
437static int iwm_set_auth_type(struct iwm_priv *iwm,
438			     enum nl80211_auth_type sme_auth_type)
439{
440	u8 *auth_type = &iwm->umac_profile->sec.auth_type;
441
442	switch (sme_auth_type) {
443	case NL80211_AUTHTYPE_AUTOMATIC:
444	case NL80211_AUTHTYPE_OPEN_SYSTEM:
445		IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
446		*auth_type = UMAC_AUTH_TYPE_OPEN;
447		break;
448	case NL80211_AUTHTYPE_SHARED_KEY:
449		if (iwm->umac_profile->sec.flags &
450		    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
451			IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
452			*auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
453		} else {
454			IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
455			*auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
456		}
457
458		break;
459	default:
460		IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
461		return -ENOTSUPP;
462	}
463
464	return 0;
465}
466
467static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
468{
469	IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
470
471	if (!wpa_version) {
472		iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
473		return 0;
474	}
475
476	if (wpa_version & NL80211_WPA_VERSION_1)
477		iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
478
479	if (wpa_version & NL80211_WPA_VERSION_2)
480		iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
481
482	return 0;
483}
484
485static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
486{
487	u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
488		&iwm->umac_profile->sec.mcast_cipher;
489
490	if (!cipher) {
491		*profile_cipher = UMAC_CIPHER_TYPE_NONE;
492		return 0;
493	}
494
495	IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
496		     cipher);
497
498	switch (cipher) {
499	case IW_AUTH_CIPHER_NONE:
500		*profile_cipher = UMAC_CIPHER_TYPE_NONE;
501		break;
502	case WLAN_CIPHER_SUITE_WEP40:
503		*profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
504		break;
505	case WLAN_CIPHER_SUITE_WEP104:
506		*profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
507		break;
508	case WLAN_CIPHER_SUITE_TKIP:
509		*profile_cipher = UMAC_CIPHER_TYPE_TKIP;
510		break;
511	case WLAN_CIPHER_SUITE_CCMP:
512		*profile_cipher = UMAC_CIPHER_TYPE_CCMP;
513		break;
514	default:
515		IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
516		return -ENOTSUPP;
517	}
518
519	return 0;
520}
521
522static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
523{
524	u8 *auth_type = &iwm->umac_profile->sec.auth_type;
525
526	IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
527
528	if (key_mgt == WLAN_AKM_SUITE_8021X)
529		*auth_type = UMAC_AUTH_TYPE_8021X;
530	else if (key_mgt == WLAN_AKM_SUITE_PSK) {
531		if (iwm->umac_profile->sec.flags &
532		    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
533			*auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
534		else
535			*auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
536	} else {
537		IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
538		return -EINVAL;
539	}
540
541	return 0;
542}
543
544
545static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
546				 struct cfg80211_connect_params *sme)
547{
548	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
549	struct ieee80211_channel *chan = sme->channel;
550	struct key_params key_param;
551	int ret;
552
553	if (!test_bit(IWM_STATUS_READY, &iwm->status))
554		return -EIO;
555
556	if (!sme->ssid)
557		return -EINVAL;
558
559	if (iwm->umac_profile_active) {
560		ret = iwm_invalidate_mlme_profile(iwm);
561		if (ret) {
562			IWM_ERR(iwm, "Couldn't invalidate profile\n");
563			return ret;
564		}
565	}
566
567	if (chan)
568		iwm->channel =
569			ieee80211_frequency_to_channel(chan->center_freq);
570
571	iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
572	memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
573
574	if (sme->bssid) {
575		IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
576		memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
577		iwm->umac_profile->bss_num = 1;
578	} else {
579		memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
580		iwm->umac_profile->bss_num = 0;
581	}
582
583	ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
584	if (ret < 0)
585		return ret;
586
587	ret = iwm_set_auth_type(iwm, sme->auth_type);
588	if (ret < 0)
589		return ret;
590
591	if (sme->crypto.n_ciphers_pairwise) {
592		ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
593				     true);
594		if (ret < 0)
595			return ret;
596	}
597
598	ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
599	if (ret < 0)
600		return ret;
601
602	if (sme->crypto.n_akm_suites) {
603		ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
604		if (ret < 0)
605			return ret;
606	}
607
608	/*
609	 * We save the WEP key in case we want to do shared authentication.
610	 * We have to do it so because UMAC will assert whenever it gets a
611	 * key before a profile.
612	 */
613	if (sme->key) {
614		key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL);
615		if (key_param.key == NULL)
616			return -ENOMEM;
617		key_param.key_len = sme->key_len;
618		key_param.seq_len = 0;
619		key_param.cipher = sme->crypto.ciphers_pairwise[0];
620
621		ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx,
622				   NULL, &key_param);
623		kfree(key_param.key);
624		if (ret < 0) {
625			IWM_ERR(iwm, "Invalid key_params\n");
626			return ret;
627		}
628
629		iwm->default_key = sme->key_idx;
630	}
631
632	/* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */
633	if ((iwm->umac_profile->sec.flags &
634	     (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) &&
635	    iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) {
636			iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK;
637	}
638
639	ret = iwm_send_mlme_profile(iwm);
640
641	if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
642	    sme->key == NULL)
643		return ret;
644
645	/*
646	 * We want to do shared auth.
647	 * We need to actually set the key we previously cached,
648	 * and then tell the UMAC it's the default one.
649	 * That will trigger the auth+assoc UMAC machinery, and again,
650	 * this must be done after setting the profile.
651	 */
652	ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]);
653	if (ret < 0)
654		return ret;
655
656	return iwm_set_tx_key(iwm, iwm->default_key);
657}
658
659static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
660				   u16 reason_code)
661{
662	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
663
664	IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
665
666	if (iwm->umac_profile_active)
667		iwm_invalidate_mlme_profile(iwm);
668
669	return 0;
670}
671
672static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
673				    enum nl80211_tx_power_setting type, int mbm)
674{
675	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
676	int ret;
677
678	switch (type) {
679	case NL80211_TX_POWER_AUTOMATIC:
680		return 0;
681	case NL80211_TX_POWER_FIXED:
682		if (mbm < 0 || (mbm % 100))
683			return -EOPNOTSUPP;
684
685		if (!test_bit(IWM_STATUS_READY, &iwm->status))
686			return 0;
687
688		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
689					      CFG_TX_PWR_LIMIT_USR,
690					      MBM_TO_DBM(mbm) * 2);
691		if (ret < 0)
692			return ret;
693
694		return iwm_tx_power_trigger(iwm);
695	default:
696		IWM_ERR(iwm, "Unsupported power type: %d\n", type);
697		return -EOPNOTSUPP;
698	}
699
700	return 0;
701}
702
703static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
704{
705	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
706
707	*dbm = iwm->txpower >> 1;
708
709	return 0;
710}
711
712static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
713				       struct net_device *dev,
714				       bool enabled, int timeout)
715{
716	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
717	u32 power_index;
718
719	if (enabled)
720		power_index = IWM_POWER_INDEX_DEFAULT;
721	else
722		power_index = IWM_POWER_INDEX_MIN;
723
724	if (power_index == iwm->conf.power_index)
725		return 0;
726
727	iwm->conf.power_index = power_index;
728
729	return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
730				       CFG_POWER_INDEX, iwm->conf.power_index);
731}
732
733static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy,
734				  struct net_device *netdev,
735				  struct cfg80211_pmksa *pmksa)
736{
737	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
738
739	return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
740}
741
742static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy,
743				  struct net_device *netdev,
744				  struct cfg80211_pmksa *pmksa)
745{
746	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
747
748	return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
749}
750
751static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy,
752				    struct net_device *netdev)
753{
754	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
755	struct cfg80211_pmksa pmksa;
756
757	memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
758
759	return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
760}
761
762
763static struct cfg80211_ops iwm_cfg80211_ops = {
764	.change_virtual_intf = iwm_cfg80211_change_iface,
765	.add_key = iwm_cfg80211_add_key,
766	.get_key = iwm_cfg80211_get_key,
767	.del_key = iwm_cfg80211_del_key,
768	.set_default_key = iwm_cfg80211_set_default_key,
769	.get_station = iwm_cfg80211_get_station,
770	.scan = iwm_cfg80211_scan,
771	.set_wiphy_params = iwm_cfg80211_set_wiphy_params,
772	.connect = iwm_cfg80211_connect,
773	.disconnect = iwm_cfg80211_disconnect,
774	.join_ibss = iwm_cfg80211_join_ibss,
775	.leave_ibss = iwm_cfg80211_leave_ibss,
776	.set_tx_power = iwm_cfg80211_set_txpower,
777	.get_tx_power = iwm_cfg80211_get_txpower,
778	.set_power_mgmt = iwm_cfg80211_set_power_mgmt,
779	.set_pmksa = iwm_cfg80211_set_pmksa,
780	.del_pmksa = iwm_cfg80211_del_pmksa,
781	.flush_pmksa = iwm_cfg80211_flush_pmksa,
782};
783
784static const u32 cipher_suites[] = {
785	WLAN_CIPHER_SUITE_WEP40,
786	WLAN_CIPHER_SUITE_WEP104,
787	WLAN_CIPHER_SUITE_TKIP,
788	WLAN_CIPHER_SUITE_CCMP,
789};
790
791struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
792{
793	int ret = 0;
794	struct wireless_dev *wdev;
795
796	/*
797	 * We're trying to have the following memory
798	 * layout:
799	 *
800	 * +-------------------------+
801	 * | struct wiphy	     |
802	 * +-------------------------+
803	 * | struct iwm_priv         |
804	 * +-------------------------+
805	 * | bus private data        |
806	 * | (e.g. iwm_priv_sdio)    |
807	 * +-------------------------+
808	 *
809	 */
810
811	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
812	if (!wdev) {
813		dev_err(dev, "Couldn't allocate wireless device\n");
814		return ERR_PTR(-ENOMEM);
815	}
816
817	wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
818				sizeof(struct iwm_priv) + sizeof_bus);
819	if (!wdev->wiphy) {
820		dev_err(dev, "Couldn't allocate wiphy device\n");
821		ret = -ENOMEM;
822		goto out_err_new;
823	}
824
825	set_wiphy_dev(wdev->wiphy, dev);
826	wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
827	wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
828	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
829				       BIT(NL80211_IFTYPE_ADHOC);
830	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
831	wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
832	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
833
834	wdev->wiphy->cipher_suites = cipher_suites;
835	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
836
837	ret = wiphy_register(wdev->wiphy);
838	if (ret < 0) {
839		dev_err(dev, "Couldn't register wiphy device\n");
840		goto out_err_register;
841	}
842
843	return wdev;
844
845 out_err_register:
846	wiphy_free(wdev->wiphy);
847
848 out_err_new:
849	kfree(wdev);
850
851	return ERR_PTR(ret);
852}
853
854void iwm_wdev_free(struct iwm_priv *iwm)
855{
856	struct wireless_dev *wdev = iwm_to_wdev(iwm);
857
858	if (!wdev)
859		return;
860
861	wiphy_unregister(wdev->wiphy);
862	wiphy_free(wdev->wiphy);
863	kfree(wdev);
864}
865