2 * Intel Wireless Multicomm 3200 WiFi driver
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
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.
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.
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
24 #include <linux/kernel.h>
25 #include <linux/netdevice.h>
26 #include <linux/etherdevice.h>
27 #include <linux/wireless.h>
28 #include <linux/ieee80211.h>
29 #include <net/cfg80211.h>
36 #define RATETAB_ENT(_rate, _rateid, _flags) \
39 .hw_value = (_rateid), \
43 #define CHAN2G(_channel, _freq, _flags) { \
44 .band = IEEE80211_BAND_2GHZ, \
45 .center_freq = (_freq), \
46 .hw_value = (_channel), \
48 .max_antenna_gain = 0, \
52 #define CHAN5G(_channel, _flags) { \
53 .band = IEEE80211_BAND_5GHZ, \
54 .center_freq = 5000 + (5 * (_channel)), \
55 .hw_value = (_channel), \
57 .max_antenna_gain = 0, \
61 static struct ieee80211_rate iwm_rates[] = {
62 RATETAB_ENT(10, 0x1, 0),
63 RATETAB_ENT(20, 0x2, 0),
64 RATETAB_ENT(55, 0x4, 0),
65 RATETAB_ENT(110, 0x8, 0),
66 RATETAB_ENT(60, 0x10, 0),
67 RATETAB_ENT(90, 0x20, 0),
68 RATETAB_ENT(120, 0x40, 0),
69 RATETAB_ENT(180, 0x80, 0),
70 RATETAB_ENT(240, 0x100, 0),
71 RATETAB_ENT(360, 0x200, 0),
72 RATETAB_ENT(480, 0x400, 0),
73 RATETAB_ENT(540, 0x800, 0),
76 #define iwm_a_rates (iwm_rates + 4)
77 #define iwm_a_rates_size 8
78 #define iwm_g_rates (iwm_rates + 0)
79 #define iwm_g_rates_size 12
81 static struct ieee80211_channel iwm_2ghz_channels[] = {
98 static struct ieee80211_channel iwm_5ghz_a_channels[] = {
99 CHAN5G(34, 0), CHAN5G(36, 0),
100 CHAN5G(38, 0), CHAN5G(40, 0),
101 CHAN5G(42, 0), CHAN5G(44, 0),
102 CHAN5G(46, 0), CHAN5G(48, 0),
103 CHAN5G(52, 0), CHAN5G(56, 0),
104 CHAN5G(60, 0), CHAN5G(64, 0),
105 CHAN5G(100, 0), CHAN5G(104, 0),
106 CHAN5G(108, 0), CHAN5G(112, 0),
107 CHAN5G(116, 0), CHAN5G(120, 0),
108 CHAN5G(124, 0), CHAN5G(128, 0),
109 CHAN5G(132, 0), CHAN5G(136, 0),
110 CHAN5G(140, 0), CHAN5G(149, 0),
111 CHAN5G(153, 0), CHAN5G(157, 0),
112 CHAN5G(161, 0), CHAN5G(165, 0),
113 CHAN5G(184, 0), CHAN5G(188, 0),
114 CHAN5G(192, 0), CHAN5G(196, 0),
115 CHAN5G(200, 0), CHAN5G(204, 0),
116 CHAN5G(208, 0), CHAN5G(212, 0),
120 static struct ieee80211_supported_band iwm_band_2ghz = {
121 .channels = iwm_2ghz_channels,
122 .n_channels = ARRAY_SIZE(iwm_2ghz_channels),
123 .bitrates = iwm_g_rates,
124 .n_bitrates = iwm_g_rates_size,
127 static struct ieee80211_supported_band iwm_band_5ghz = {
128 .channels = iwm_5ghz_a_channels,
129 .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels),
130 .bitrates = iwm_a_rates,
131 .n_bitrates = iwm_a_rates_size,
134 static int iwm_key_init(struct iwm_key *key, u8 key_index,
135 const u8 *mac_addr, struct key_params *params)
137 key->hdr.key_idx = key_index;
138 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
139 key->hdr.multicast = 1;
140 memset(key->hdr.mac, 0xff, ETH_ALEN);
142 key->hdr.multicast = 0;
143 memcpy(key->hdr.mac, mac_addr, ETH_ALEN);
147 if (params->key_len > WLAN_MAX_KEY_LEN ||
148 params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
151 key->cipher = params->cipher;
152 key->key_len = params->key_len;
153 key->seq_len = params->seq_len;
154 memcpy(key->key, params->key, key->key_len);
155 memcpy(key->seq, params->seq, key->seq_len);
161 static int iwm_reset_profile(struct iwm_priv *iwm)
165 if (!iwm->umac_profile_active)
169 * If there is a current active profile, but no
170 * default key, it's not worth trying to associate again.
172 if (iwm->default_key < 0)
176 * Here we have an active profile, but a key setting changed.
177 * We thus have to invalidate the current profile, and push the
178 * new one. Keys will be pushed when association takes place.
180 ret = iwm_invalidate_mlme_profile(iwm);
182 IWM_ERR(iwm, "Couldn't invalidate profile\n");
186 return iwm_send_mlme_profile(iwm);
189 static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
190 u8 key_index, const u8 *mac_addr,
191 struct key_params *params)
193 struct iwm_priv *iwm = ndev_to_iwm(ndev);
194 struct iwm_key *key = &iwm->keys[key_index];
197 IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
199 memset(key, 0, sizeof(struct iwm_key));
200 ret = iwm_key_init(key, key_index, mac_addr, params);
202 IWM_ERR(iwm, "Invalid key_params\n");
206 return iwm_set_key(iwm, 0, key);
209 static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
210 u8 key_index, const u8 *mac_addr, void *cookie,
211 void (*callback)(void *cookie,
214 struct iwm_priv *iwm = ndev_to_iwm(ndev);
215 struct iwm_key *key = &iwm->keys[key_index];
216 struct key_params params;
218 IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
220 memset(¶ms, 0, sizeof(params));
222 params.cipher = key->cipher;
223 params.key_len = key->key_len;
224 params.seq_len = key->seq_len;
225 params.seq = key->seq;
226 params.key = key->key;
228 callback(cookie, ¶ms);
230 return key->key_len ? 0 : -ENOENT;
234 static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
235 u8 key_index, const u8 *mac_addr)
237 struct iwm_priv *iwm = ndev_to_iwm(ndev);
238 struct iwm_key *key = &iwm->keys[key_index];
240 if (!iwm->keys[key_index].key_len) {
241 IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
245 if (key_index == iwm->default_key)
246 iwm->default_key = -1;
248 /* If the interface is down, we just cache this */
249 if (!test_bit(IWM_STATUS_READY, &iwm->status))
252 return iwm_set_key(iwm, 1, key);
255 static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
256 struct net_device *ndev,
259 struct iwm_priv *iwm = ndev_to_iwm(ndev);
262 IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
264 if (!iwm->keys[key_index].key_len) {
265 IWM_ERR(iwm, "Key %d not used\n", key_index);
269 iwm->default_key = key_index;
271 /* If the interface is down, we just cache this */
272 if (!test_bit(IWM_STATUS_READY, &iwm->status))
275 ret = iwm_set_tx_key(iwm, key_index);
279 return iwm_reset_profile(iwm);
282 int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
283 u8 *mac, struct station_info *sinfo)
285 struct iwm_priv *iwm = ndev_to_iwm(ndev);
287 if (memcmp(mac, iwm->bssid, ETH_ALEN))
290 sinfo->filled |= STATION_INFO_TX_BITRATE;
291 sinfo->txrate.legacy = iwm->rate * 10;
293 if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
294 sinfo->filled |= STATION_INFO_SIGNAL;
295 sinfo->signal = iwm->wstats.qual.level;
302 int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
304 struct wiphy *wiphy = iwm_to_wiphy(iwm);
305 struct iwm_bss_info *bss, *next;
306 struct iwm_umac_notif_bss_info *umac_bss;
307 struct ieee80211_mgmt *mgmt;
308 struct ieee80211_channel *channel;
309 struct ieee80211_supported_band *band;
313 list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
315 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
317 if (umac_bss->band == UMAC_BAND_2GHZ)
318 band = wiphy->bands[IEEE80211_BAND_2GHZ];
319 else if (umac_bss->band == UMAC_BAND_5GHZ)
320 band = wiphy->bands[IEEE80211_BAND_5GHZ];
322 IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
326 freq = ieee80211_channel_to_frequency(umac_bss->channel);
327 channel = ieee80211_get_channel(wiphy, freq);
328 signal = umac_bss->rssi * 100;
330 if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
331 le16_to_cpu(umac_bss->frame_len),
339 static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
340 struct net_device *ndev,
341 enum nl80211_iftype type, u32 *flags,
342 struct vif_params *params)
344 struct wireless_dev *wdev;
345 struct iwm_priv *iwm;
348 wdev = ndev->ieee80211_ptr;
349 iwm = ndev_to_iwm(ndev);
350 old_mode = iwm->conf.mode;
353 case NL80211_IFTYPE_STATION:
354 iwm->conf.mode = UMAC_MODE_BSS;
356 case NL80211_IFTYPE_ADHOC:
357 iwm->conf.mode = UMAC_MODE_IBSS;
365 if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
368 iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
370 if (iwm->umac_profile_active) {
371 int ret = iwm_invalidate_mlme_profile(iwm);
373 IWM_ERR(iwm, "Couldn't invalidate profile\n");
379 static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
380 struct cfg80211_scan_request *request)
382 struct iwm_priv *iwm = ndev_to_iwm(ndev);
385 if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
386 IWM_ERR(iwm, "Scan while device is not ready\n");
390 if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
391 IWM_ERR(iwm, "Scanning already\n");
395 if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
396 IWM_ERR(iwm, "Scanning being aborted\n");
400 set_bit(IWM_STATUS_SCANNING, &iwm->status);
402 ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
404 clear_bit(IWM_STATUS_SCANNING, &iwm->status);
408 iwm->scan_request = request;
412 static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
414 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
416 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
417 (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
420 iwm->conf.rts_threshold = wiphy->rts_threshold;
422 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
424 iwm->conf.rts_threshold);
429 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
430 (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
433 iwm->conf.frag_threshold = wiphy->frag_threshold;
435 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
437 iwm->conf.frag_threshold);
445 static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
446 struct cfg80211_ibss_params *params)
448 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
449 struct ieee80211_channel *chan = params->channel;
450 struct cfg80211_bss *bss;
452 if (!test_bit(IWM_STATUS_READY, &iwm->status))
455 /* UMAC doesn't support creating IBSS network with specified bssid.
456 * This should be removed after we have join only mode supported. */
460 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
461 params->ssid, params->ssid_len);
463 iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
464 schedule_timeout_interruptible(2 * HZ);
465 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
466 params->ssid, params->ssid_len);
468 /* IBSS join only mode is not supported by UMAC ATM */
470 cfg80211_put_bss(bss);
474 iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
475 iwm->umac_profile->ibss.band = chan->band;
476 iwm->umac_profile->ibss.channel = iwm->channel;
477 iwm->umac_profile->ssid.ssid_len = params->ssid_len;
478 memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
481 memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
483 return iwm_send_mlme_profile(iwm);
486 static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
488 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
490 if (iwm->umac_profile_active)
491 return iwm_invalidate_mlme_profile(iwm);
496 static int iwm_set_auth_type(struct iwm_priv *iwm,
497 enum nl80211_auth_type sme_auth_type)
499 u8 *auth_type = &iwm->umac_profile->sec.auth_type;
501 switch (sme_auth_type) {
502 case NL80211_AUTHTYPE_AUTOMATIC:
503 case NL80211_AUTHTYPE_OPEN_SYSTEM:
504 IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
505 *auth_type = UMAC_AUTH_TYPE_OPEN;
507 case NL80211_AUTHTYPE_SHARED_KEY:
508 if (iwm->umac_profile->sec.flags &
509 (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
510 IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
511 *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
513 IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
514 *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
519 IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
526 static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
529 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
533 if (wpa_version & NL80211_WPA_VERSION_2)
534 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
536 if (wpa_version & NL80211_WPA_VERSION_1)
537 iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
542 static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
544 u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
545 &iwm->umac_profile->sec.mcast_cipher;
548 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
553 case IW_AUTH_CIPHER_NONE:
554 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
556 case WLAN_CIPHER_SUITE_WEP40:
557 *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
559 case WLAN_CIPHER_SUITE_WEP104:
560 *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
562 case WLAN_CIPHER_SUITE_TKIP:
563 *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
565 case WLAN_CIPHER_SUITE_CCMP:
566 *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
569 IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
576 static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
578 u8 *auth_type = &iwm->umac_profile->sec.auth_type;
580 IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
582 if (key_mgt == WLAN_AKM_SUITE_8021X)
583 *auth_type = UMAC_AUTH_TYPE_8021X;
584 else if (key_mgt == WLAN_AKM_SUITE_PSK) {
585 if (iwm->umac_profile->sec.flags &
586 (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
587 *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
589 *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
591 IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
599 static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
600 struct cfg80211_connect_params *sme)
602 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
603 struct ieee80211_channel *chan = sme->channel;
606 if (!test_bit(IWM_STATUS_READY, &iwm->status))
614 ieee80211_frequency_to_channel(chan->center_freq);
616 iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
617 memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
620 IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
621 memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
622 iwm->umac_profile->bss_num = 1;
624 memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
625 iwm->umac_profile->bss_num = 0;
628 ret = iwm_set_auth_type(iwm, sme->auth_type);
632 ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
636 if (sme->crypto.n_ciphers_pairwise) {
637 ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
643 ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
647 if (sme->crypto.n_akm_suites) {
648 ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
653 return iwm_send_mlme_profile(iwm);
656 static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
659 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
661 IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
663 if (iwm->umac_profile_active)
664 return iwm_invalidate_mlme_profile(iwm);
669 static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
670 enum tx_power_setting type, int dbm)
673 case TX_POWER_AUTOMATIC:
682 static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
684 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
691 static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
692 struct net_device *dev,
693 bool enabled, int timeout)
695 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
699 power_index = IWM_POWER_INDEX_DEFAULT;
701 power_index = IWM_POWER_INDEX_MIN;
703 if (power_index == iwm->conf.power_index)
706 iwm->conf.power_index = power_index;
708 return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
709 CFG_POWER_INDEX, iwm->conf.power_index);
712 static struct cfg80211_ops iwm_cfg80211_ops = {
713 .change_virtual_intf = iwm_cfg80211_change_iface,
714 .add_key = iwm_cfg80211_add_key,
715 .get_key = iwm_cfg80211_get_key,
716 .del_key = iwm_cfg80211_del_key,
717 .set_default_key = iwm_cfg80211_set_default_key,
718 .get_station = iwm_cfg80211_get_station,
719 .scan = iwm_cfg80211_scan,
720 .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
721 .connect = iwm_cfg80211_connect,
722 .disconnect = iwm_cfg80211_disconnect,
723 .join_ibss = iwm_cfg80211_join_ibss,
724 .leave_ibss = iwm_cfg80211_leave_ibss,
725 .set_tx_power = iwm_cfg80211_set_txpower,
726 .get_tx_power = iwm_cfg80211_get_txpower,
727 .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
730 static const u32 cipher_suites[] = {
731 WLAN_CIPHER_SUITE_WEP40,
732 WLAN_CIPHER_SUITE_WEP104,
733 WLAN_CIPHER_SUITE_TKIP,
734 WLAN_CIPHER_SUITE_CCMP,
737 struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
740 struct wireless_dev *wdev;
743 * We're trying to have the following memory
746 * +-------------------------+
748 * +-------------------------+
749 * | struct iwm_priv |
750 * +-------------------------+
751 * | bus private data |
752 * | (e.g. iwm_priv_sdio) |
753 * +-------------------------+
757 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
759 dev_err(dev, "Couldn't allocate wireless device\n");
760 return ERR_PTR(-ENOMEM);
763 wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
764 sizeof(struct iwm_priv) + sizeof_bus);
766 dev_err(dev, "Couldn't allocate wiphy device\n");
771 set_wiphy_dev(wdev->wiphy, dev);
772 wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
773 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
774 BIT(NL80211_IFTYPE_ADHOC);
775 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
776 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
777 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
779 wdev->wiphy->cipher_suites = cipher_suites;
780 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
782 ret = wiphy_register(wdev->wiphy);
784 dev_err(dev, "Couldn't register wiphy device\n");
785 goto out_err_register;
791 wiphy_free(wdev->wiphy);
799 void iwm_wdev_free(struct iwm_priv *iwm)
801 struct wireless_dev *wdev = iwm_to_wdev(iwm);
806 wiphy_unregister(wdev->wiphy);
807 wiphy_free(wdev->wiphy);