Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
Note: File does not exist in v6.13.7.
  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, bool pairwise, 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, bool pairwise, const u8 *mac_addr,
185				void *cookie,
186				void (*callback)(void *cookie,
187						 struct key_params*))
188{
189	struct iwm_priv *iwm = ndev_to_iwm(ndev);
190	struct iwm_key *key = &iwm->keys[key_index];
191	struct key_params params;
192
193	IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
194
195	memset(&params, 0, sizeof(params));
196
197	params.cipher = key->cipher;
198	params.key_len = key->key_len;
199	params.seq_len = key->seq_len;
200	params.seq = key->seq;
201	params.key = key->key;
202
203	callback(cookie, &params);
204
205	return key->key_len ? 0 : -ENOENT;
206}
207
208
209static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
210				u8 key_index, bool pairwise, const u8 *mac_addr)
211{
212	struct iwm_priv *iwm = ndev_to_iwm(ndev);
213	struct iwm_key *key = &iwm->keys[key_index];
214
215	if (!iwm->keys[key_index].key_len) {
216		IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
217		return 0;
218	}
219
220	if (key_index == iwm->default_key)
221		iwm->default_key = -1;
222
223	return iwm_set_key(iwm, 1, key);
224}
225
226static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
227					struct net_device *ndev,
228					u8 key_index, bool unicast,
229					bool multicast)
230{
231	struct iwm_priv *iwm = ndev_to_iwm(ndev);
232
233	IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
234
235	if (!iwm->keys[key_index].key_len) {
236		IWM_ERR(iwm, "Key %d not used\n", key_index);
237		return -EINVAL;
238	}
239
240	iwm->default_key = key_index;
241
242	return iwm_set_tx_key(iwm, key_index);
243}
244
245static int iwm_cfg80211_get_station(struct wiphy *wiphy,
246				    struct net_device *ndev,
247				    u8 *mac, struct station_info *sinfo)
248{
249	struct iwm_priv *iwm = ndev_to_iwm(ndev);
250
251	if (memcmp(mac, iwm->bssid, ETH_ALEN))
252		return -ENOENT;
253
254	sinfo->filled |= STATION_INFO_TX_BITRATE;
255	sinfo->txrate.legacy = iwm->rate * 10;
256
257	if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
258		sinfo->filled |= STATION_INFO_SIGNAL;
259		sinfo->signal = iwm->wstats.qual.level;
260	}
261
262	return 0;
263}
264
265
266int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
267{
268	struct wiphy *wiphy = iwm_to_wiphy(iwm);
269	struct iwm_bss_info *bss;
270	struct iwm_umac_notif_bss_info *umac_bss;
271	struct ieee80211_mgmt *mgmt;
272	struct ieee80211_channel *channel;
273	struct ieee80211_supported_band *band;
274	s32 signal;
275	int freq;
276
277	list_for_each_entry(bss, &iwm->bss_list, node) {
278		umac_bss = bss->bss;
279		mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
280
281		if (umac_bss->band == UMAC_BAND_2GHZ)
282			band = wiphy->bands[IEEE80211_BAND_2GHZ];
283		else if (umac_bss->band == UMAC_BAND_5GHZ)
284			band = wiphy->bands[IEEE80211_BAND_5GHZ];
285		else {
286			IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
287			return -EINVAL;
288		}
289
290		freq = ieee80211_channel_to_frequency(umac_bss->channel,
291						      band->band);
292		channel = ieee80211_get_channel(wiphy, freq);
293		signal = umac_bss->rssi * 100;
294
295		if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
296					       le16_to_cpu(umac_bss->frame_len),
297					       signal, GFP_KERNEL))
298			return -EINVAL;
299	}
300
301	return 0;
302}
303
304static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
305				     struct net_device *ndev,
306				     enum nl80211_iftype type, u32 *flags,
307				     struct vif_params *params)
308{
309	struct wireless_dev *wdev;
310	struct iwm_priv *iwm;
311	u32 old_mode;
312
313	wdev = ndev->ieee80211_ptr;
314	iwm = ndev_to_iwm(ndev);
315	old_mode = iwm->conf.mode;
316
317	switch (type) {
318	case NL80211_IFTYPE_STATION:
319		iwm->conf.mode = UMAC_MODE_BSS;
320		break;
321	case NL80211_IFTYPE_ADHOC:
322		iwm->conf.mode = UMAC_MODE_IBSS;
323		break;
324	default:
325		return -EOPNOTSUPP;
326	}
327
328	wdev->iftype = type;
329
330	if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
331		return 0;
332
333	iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
334
335	if (iwm->umac_profile_active)
336		iwm_invalidate_mlme_profile(iwm);
337
338	return 0;
339}
340
341static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
342			     struct cfg80211_scan_request *request)
343{
344	struct iwm_priv *iwm = ndev_to_iwm(ndev);
345	int ret;
346
347	if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
348		IWM_ERR(iwm, "Scan while device is not ready\n");
349		return -EIO;
350	}
351
352	if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
353		IWM_ERR(iwm, "Scanning already\n");
354		return -EAGAIN;
355	}
356
357	if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
358		IWM_ERR(iwm, "Scanning being aborted\n");
359		return -EAGAIN;
360	}
361
362	set_bit(IWM_STATUS_SCANNING, &iwm->status);
363
364	ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
365	if (ret) {
366		clear_bit(IWM_STATUS_SCANNING, &iwm->status);
367		return ret;
368	}
369
370	iwm->scan_request = request;
371	return 0;
372}
373
374static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
375{
376	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
377
378	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
379	    (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
380		int ret;
381
382		iwm->conf.rts_threshold = wiphy->rts_threshold;
383
384		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
385					     CFG_RTS_THRESHOLD,
386					     iwm->conf.rts_threshold);
387		if (ret < 0)
388			return ret;
389	}
390
391	if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
392	    (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
393		int ret;
394
395		iwm->conf.frag_threshold = wiphy->frag_threshold;
396
397		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
398					     CFG_FRAG_THRESHOLD,
399					     iwm->conf.frag_threshold);
400		if (ret < 0)
401			return ret;
402	}
403
404	return 0;
405}
406
407static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
408				  struct cfg80211_ibss_params *params)
409{
410	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
411	struct ieee80211_channel *chan = params->channel;
412
413	if (!test_bit(IWM_STATUS_READY, &iwm->status))
414		return -EIO;
415
416	/* UMAC doesn't support creating or joining an IBSS network
417	 * with specified bssid. */
418	if (params->bssid)
419		return -EOPNOTSUPP;
420
421	iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
422	iwm->umac_profile->ibss.band = chan->band;
423	iwm->umac_profile->ibss.channel = iwm->channel;
424	iwm->umac_profile->ssid.ssid_len = params->ssid_len;
425	memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
426
427	return iwm_send_mlme_profile(iwm);
428}
429
430static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
431{
432	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
433
434	if (iwm->umac_profile_active)
435		return iwm_invalidate_mlme_profile(iwm);
436
437	return 0;
438}
439
440static int iwm_set_auth_type(struct iwm_priv *iwm,
441			     enum nl80211_auth_type sme_auth_type)
442{
443	u8 *auth_type = &iwm->umac_profile->sec.auth_type;
444
445	switch (sme_auth_type) {
446	case NL80211_AUTHTYPE_AUTOMATIC:
447	case NL80211_AUTHTYPE_OPEN_SYSTEM:
448		IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
449		*auth_type = UMAC_AUTH_TYPE_OPEN;
450		break;
451	case NL80211_AUTHTYPE_SHARED_KEY:
452		if (iwm->umac_profile->sec.flags &
453		    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
454			IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
455			*auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
456		} else {
457			IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
458			*auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
459		}
460
461		break;
462	default:
463		IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
464		return -ENOTSUPP;
465	}
466
467	return 0;
468}
469
470static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
471{
472	IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
473
474	if (!wpa_version) {
475		iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
476		return 0;
477	}
478
479	if (wpa_version & NL80211_WPA_VERSION_1)
480		iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
481
482	if (wpa_version & NL80211_WPA_VERSION_2)
483		iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
484
485	return 0;
486}
487
488static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
489{
490	u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
491		&iwm->umac_profile->sec.mcast_cipher;
492
493	if (!cipher) {
494		*profile_cipher = UMAC_CIPHER_TYPE_NONE;
495		return 0;
496	}
497
498	IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
499		     cipher);
500
501	switch (cipher) {
502	case IW_AUTH_CIPHER_NONE:
503		*profile_cipher = UMAC_CIPHER_TYPE_NONE;
504		break;
505	case WLAN_CIPHER_SUITE_WEP40:
506		*profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
507		break;
508	case WLAN_CIPHER_SUITE_WEP104:
509		*profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
510		break;
511	case WLAN_CIPHER_SUITE_TKIP:
512		*profile_cipher = UMAC_CIPHER_TYPE_TKIP;
513		break;
514	case WLAN_CIPHER_SUITE_CCMP:
515		*profile_cipher = UMAC_CIPHER_TYPE_CCMP;
516		break;
517	default:
518		IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
519		return -ENOTSUPP;
520	}
521
522	return 0;
523}
524
525static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
526{
527	u8 *auth_type = &iwm->umac_profile->sec.auth_type;
528
529	IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
530
531	if (key_mgt == WLAN_AKM_SUITE_8021X)
532		*auth_type = UMAC_AUTH_TYPE_8021X;
533	else if (key_mgt == WLAN_AKM_SUITE_PSK) {
534		if (iwm->umac_profile->sec.flags &
535		    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
536			*auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
537		else
538			*auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
539	} else {
540		IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
541		return -EINVAL;
542	}
543
544	return 0;
545}
546
547
548static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
549				 struct cfg80211_connect_params *sme)
550{
551	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
552	struct ieee80211_channel *chan = sme->channel;
553	struct key_params key_param;
554	int ret;
555
556	if (!test_bit(IWM_STATUS_READY, &iwm->status))
557		return -EIO;
558
559	if (!sme->ssid)
560		return -EINVAL;
561
562	if (iwm->umac_profile_active) {
563		ret = iwm_invalidate_mlme_profile(iwm);
564		if (ret) {
565			IWM_ERR(iwm, "Couldn't invalidate profile\n");
566			return ret;
567		}
568	}
569
570	if (chan)
571		iwm->channel =
572			ieee80211_frequency_to_channel(chan->center_freq);
573
574	iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
575	memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
576
577	if (sme->bssid) {
578		IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
579		memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
580		iwm->umac_profile->bss_num = 1;
581	} else {
582		memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
583		iwm->umac_profile->bss_num = 0;
584	}
585
586	ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
587	if (ret < 0)
588		return ret;
589
590	ret = iwm_set_auth_type(iwm, sme->auth_type);
591	if (ret < 0)
592		return ret;
593
594	if (sme->crypto.n_ciphers_pairwise) {
595		ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
596				     true);
597		if (ret < 0)
598			return ret;
599	}
600
601	ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
602	if (ret < 0)
603		return ret;
604
605	if (sme->crypto.n_akm_suites) {
606		ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
607		if (ret < 0)
608			return ret;
609	}
610
611	/*
612	 * We save the WEP key in case we want to do shared authentication.
613	 * We have to do it so because UMAC will assert whenever it gets a
614	 * key before a profile.
615	 */
616	if (sme->key) {
617		key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL);
618		if (key_param.key == NULL)
619			return -ENOMEM;
620		key_param.key_len = sme->key_len;
621		key_param.seq_len = 0;
622		key_param.cipher = sme->crypto.ciphers_pairwise[0];
623
624		ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx,
625				   NULL, &key_param);
626		kfree(key_param.key);
627		if (ret < 0) {
628			IWM_ERR(iwm, "Invalid key_params\n");
629			return ret;
630		}
631
632		iwm->default_key = sme->key_idx;
633	}
634
635	/* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */
636	if ((iwm->umac_profile->sec.flags &
637	     (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) &&
638	    iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) {
639			iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK;
640	}
641
642	ret = iwm_send_mlme_profile(iwm);
643
644	if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
645	    sme->key == NULL)
646		return ret;
647
648	/*
649	 * We want to do shared auth.
650	 * We need to actually set the key we previously cached,
651	 * and then tell the UMAC it's the default one.
652	 * That will trigger the auth+assoc UMAC machinery, and again,
653	 * this must be done after setting the profile.
654	 */
655	ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]);
656	if (ret < 0)
657		return ret;
658
659	return iwm_set_tx_key(iwm, iwm->default_key);
660}
661
662static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
663				   u16 reason_code)
664{
665	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
666
667	IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
668
669	if (iwm->umac_profile_active)
670		iwm_invalidate_mlme_profile(iwm);
671
672	return 0;
673}
674
675static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
676				    enum nl80211_tx_power_setting type, int mbm)
677{
678	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
679	int ret;
680
681	switch (type) {
682	case NL80211_TX_POWER_AUTOMATIC:
683		return 0;
684	case NL80211_TX_POWER_FIXED:
685		if (mbm < 0 || (mbm % 100))
686			return -EOPNOTSUPP;
687
688		if (!test_bit(IWM_STATUS_READY, &iwm->status))
689			return 0;
690
691		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
692					      CFG_TX_PWR_LIMIT_USR,
693					      MBM_TO_DBM(mbm) * 2);
694		if (ret < 0)
695			return ret;
696
697		return iwm_tx_power_trigger(iwm);
698	default:
699		IWM_ERR(iwm, "Unsupported power type: %d\n", type);
700		return -EOPNOTSUPP;
701	}
702
703	return 0;
704}
705
706static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
707{
708	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
709
710	*dbm = iwm->txpower >> 1;
711
712	return 0;
713}
714
715static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
716				       struct net_device *dev,
717				       bool enabled, int timeout)
718{
719	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
720	u32 power_index;
721
722	if (enabled)
723		power_index = IWM_POWER_INDEX_DEFAULT;
724	else
725		power_index = IWM_POWER_INDEX_MIN;
726
727	if (power_index == iwm->conf.power_index)
728		return 0;
729
730	iwm->conf.power_index = power_index;
731
732	return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
733				       CFG_POWER_INDEX, iwm->conf.power_index);
734}
735
736static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy,
737				  struct net_device *netdev,
738				  struct cfg80211_pmksa *pmksa)
739{
740	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
741
742	return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
743}
744
745static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy,
746				  struct net_device *netdev,
747				  struct cfg80211_pmksa *pmksa)
748{
749	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
750
751	return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
752}
753
754static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy,
755				    struct net_device *netdev)
756{
757	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
758	struct cfg80211_pmksa pmksa;
759
760	memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
761
762	return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
763}
764
765
766static struct cfg80211_ops iwm_cfg80211_ops = {
767	.change_virtual_intf = iwm_cfg80211_change_iface,
768	.add_key = iwm_cfg80211_add_key,
769	.get_key = iwm_cfg80211_get_key,
770	.del_key = iwm_cfg80211_del_key,
771	.set_default_key = iwm_cfg80211_set_default_key,
772	.get_station = iwm_cfg80211_get_station,
773	.scan = iwm_cfg80211_scan,
774	.set_wiphy_params = iwm_cfg80211_set_wiphy_params,
775	.connect = iwm_cfg80211_connect,
776	.disconnect = iwm_cfg80211_disconnect,
777	.join_ibss = iwm_cfg80211_join_ibss,
778	.leave_ibss = iwm_cfg80211_leave_ibss,
779	.set_tx_power = iwm_cfg80211_set_txpower,
780	.get_tx_power = iwm_cfg80211_get_txpower,
781	.set_power_mgmt = iwm_cfg80211_set_power_mgmt,
782	.set_pmksa = iwm_cfg80211_set_pmksa,
783	.del_pmksa = iwm_cfg80211_del_pmksa,
784	.flush_pmksa = iwm_cfg80211_flush_pmksa,
785};
786
787static const u32 cipher_suites[] = {
788	WLAN_CIPHER_SUITE_WEP40,
789	WLAN_CIPHER_SUITE_WEP104,
790	WLAN_CIPHER_SUITE_TKIP,
791	WLAN_CIPHER_SUITE_CCMP,
792};
793
794struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
795{
796	int ret = 0;
797	struct wireless_dev *wdev;
798
799	/*
800	 * We're trying to have the following memory
801	 * layout:
802	 *
803	 * +-------------------------+
804	 * | struct wiphy	     |
805	 * +-------------------------+
806	 * | struct iwm_priv         |
807	 * +-------------------------+
808	 * | bus private data        |
809	 * | (e.g. iwm_priv_sdio)    |
810	 * +-------------------------+
811	 *
812	 */
813
814	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
815	if (!wdev) {
816		dev_err(dev, "Couldn't allocate wireless device\n");
817		return ERR_PTR(-ENOMEM);
818	}
819
820	wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
821				sizeof(struct iwm_priv) + sizeof_bus);
822	if (!wdev->wiphy) {
823		dev_err(dev, "Couldn't allocate wiphy device\n");
824		ret = -ENOMEM;
825		goto out_err_new;
826	}
827
828	set_wiphy_dev(wdev->wiphy, dev);
829	wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
830	wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
831	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
832				       BIT(NL80211_IFTYPE_ADHOC);
833	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
834	wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
835	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
836
837	wdev->wiphy->cipher_suites = cipher_suites;
838	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
839
840	ret = wiphy_register(wdev->wiphy);
841	if (ret < 0) {
842		dev_err(dev, "Couldn't register wiphy device\n");
843		goto out_err_register;
844	}
845
846	return wdev;
847
848 out_err_register:
849	wiphy_free(wdev->wiphy);
850
851 out_err_new:
852	kfree(wdev);
853
854	return ERR_PTR(ret);
855}
856
857void iwm_wdev_free(struct iwm_priv *iwm)
858{
859	struct wireless_dev *wdev = iwm_to_wdev(iwm);
860
861	if (!wdev)
862		return;
863
864	wiphy_unregister(wdev->wiphy);
865	wiphy_free(wdev->wiphy);
866	kfree(wdev);
867}