1bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi/* 2bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * Intel Wireless Multicomm 3200 WiFi driver 3bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * 4bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com> 5bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * Samuel Ortiz <samuel.ortiz@intel.com> 6bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * Zhu Yi <yi.zhu@intel.com> 7bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * 8bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * This program is free software; you can redistribute it and/or 9bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * modify it under the terms of the GNU General Public License version 10bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * 2 as published by the Free Software Foundation. 11bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * 12bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * This program is distributed in the hope that it will be useful, 13bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * but WITHOUT ANY WARRANTY; without even the implied warranty of 14bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * GNU General Public License for more details. 16bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * 17bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * You should have received a copy of the GNU General Public License 18bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * along with this program; if not, write to the Free Software 19bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * 02110-1301, USA. 21bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * 22bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi */ 23bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 24bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#include <linux/kernel.h> 25bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#include <linux/netdevice.h> 26d43c36dc6b357fa1806800f18aa30123c747a6d1Alexey Dobriyan#include <linux/sched.h> 2713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz#include <linux/etherdevice.h> 28bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#include <linux/wireless.h> 29bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#include <linux/ieee80211.h> 305a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 31bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#include <net/cfg80211.h> 32bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 33bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#include "iwm.h" 34bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#include "commands.h" 35bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#include "cfg80211.h" 36bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#include "debug.h" 37bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 38bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#define RATETAB_ENT(_rate, _rateid, _flags) \ 39bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi { \ 40bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .bitrate = (_rate), \ 41bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .hw_value = (_rateid), \ 42bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .flags = (_flags), \ 43bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 44bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 45bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#define CHAN2G(_channel, _freq, _flags) { \ 46bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .band = IEEE80211_BAND_2GHZ, \ 47bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .center_freq = (_freq), \ 48bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .hw_value = (_channel), \ 49bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .flags = (_flags), \ 50bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .max_antenna_gain = 0, \ 51bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .max_power = 30, \ 52bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 53bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 54bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#define CHAN5G(_channel, _flags) { \ 55bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .band = IEEE80211_BAND_5GHZ, \ 56bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .center_freq = 5000 + (5 * (_channel)), \ 57bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .hw_value = (_channel), \ 58bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .flags = (_flags), \ 59bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .max_antenna_gain = 0, \ 60bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .max_power = 30, \ 61bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 62bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 63bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic struct ieee80211_rate iwm_rates[] = { 64bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(10, 0x1, 0), 65bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(20, 0x2, 0), 66bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(55, 0x4, 0), 67bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(110, 0x8, 0), 68bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(60, 0x10, 0), 69bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(90, 0x20, 0), 70bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(120, 0x40, 0), 71bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(180, 0x80, 0), 72bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(240, 0x100, 0), 73bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(360, 0x200, 0), 74bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(480, 0x400, 0), 75bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi RATETAB_ENT(540, 0x800, 0), 76bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi}; 77bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 78bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#define iwm_a_rates (iwm_rates + 4) 79bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#define iwm_a_rates_size 8 80bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#define iwm_g_rates (iwm_rates + 0) 81bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi#define iwm_g_rates_size 12 82bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 83bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic struct ieee80211_channel iwm_2ghz_channels[] = { 84bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(1, 2412, 0), 85bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(2, 2417, 0), 86bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(3, 2422, 0), 87bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(4, 2427, 0), 88bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(5, 2432, 0), 89bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(6, 2437, 0), 90bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(7, 2442, 0), 91bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(8, 2447, 0), 92bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(9, 2452, 0), 93bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(10, 2457, 0), 94bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(11, 2462, 0), 95bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(12, 2467, 0), 96bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(13, 2472, 0), 97bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN2G(14, 2484, 0), 98bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi}; 99bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 100bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic struct ieee80211_channel iwm_5ghz_a_channels[] = { 101bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(34, 0), CHAN5G(36, 0), 102bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(38, 0), CHAN5G(40, 0), 103bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(42, 0), CHAN5G(44, 0), 104bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(46, 0), CHAN5G(48, 0), 105bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(52, 0), CHAN5G(56, 0), 106bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(60, 0), CHAN5G(64, 0), 107bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(100, 0), CHAN5G(104, 0), 108bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(108, 0), CHAN5G(112, 0), 109bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(116, 0), CHAN5G(120, 0), 110bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(124, 0), CHAN5G(128, 0), 111bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(132, 0), CHAN5G(136, 0), 112bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(140, 0), CHAN5G(149, 0), 113bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(153, 0), CHAN5G(157, 0), 114bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(161, 0), CHAN5G(165, 0), 115bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(184, 0), CHAN5G(188, 0), 116bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(192, 0), CHAN5G(196, 0), 117bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(200, 0), CHAN5G(204, 0), 118bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(208, 0), CHAN5G(212, 0), 119bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CHAN5G(216, 0), 120bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi}; 121bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 122bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic struct ieee80211_supported_band iwm_band_2ghz = { 123bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .channels = iwm_2ghz_channels, 124bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .n_channels = ARRAY_SIZE(iwm_2ghz_channels), 125bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .bitrates = iwm_g_rates, 126bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .n_bitrates = iwm_g_rates_size, 127bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi}; 128bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 129bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic struct ieee80211_supported_band iwm_band_5ghz = { 130bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .channels = iwm_5ghz_a_channels, 131bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels), 132bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .bitrates = iwm_a_rates, 133bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .n_bitrates = iwm_a_rates_size, 134bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi}; 135bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 13613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortizstatic int iwm_key_init(struct iwm_key *key, u8 key_index, 13713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz const u8 *mac_addr, struct key_params *params) 13813e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz{ 13913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz key->hdr.key_idx = key_index; 14013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz if (!mac_addr || is_broadcast_ether_addr(mac_addr)) { 14113e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz key->hdr.multicast = 1; 14213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz memset(key->hdr.mac, 0xff, ETH_ALEN); 14313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz } else { 14413e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz key->hdr.multicast = 0; 14513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz memcpy(key->hdr.mac, mac_addr, ETH_ALEN); 14613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz } 14713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 14813e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz if (params) { 14913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz if (params->key_len > WLAN_MAX_KEY_LEN || 15013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz params->seq_len > IW_ENCODE_SEQ_MAX_SIZE) 15113e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz return -EINVAL; 15213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 15313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz key->cipher = params->cipher; 15413e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz key->key_len = params->key_len; 15513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz key->seq_len = params->seq_len; 15613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz memcpy(key->key, params->key, key->key_len); 15713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz memcpy(key->seq, params->seq, key->seq_len); 15813e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz } 15913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 16013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz return 0; 16113e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz} 16213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 16313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortizstatic int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, 164e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg u8 key_index, bool pairwise, const u8 *mac_addr, 16513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz struct key_params *params) 16613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz{ 16713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz struct iwm_priv *iwm = ndev_to_iwm(ndev); 1685a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter struct iwm_key *key; 16913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz int ret; 17013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 17113e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr); 17213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 1735a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter if (key_index >= IWM_NUM_KEYS) 1745a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter return -ENOENT; 1755a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter 1765a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter key = &iwm->keys[key_index]; 17713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz memset(key, 0, sizeof(struct iwm_key)); 17813e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz ret = iwm_key_init(key, key_index, mac_addr, params); 17913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz if (ret < 0) { 18013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz IWM_ERR(iwm, "Invalid key_params\n"); 18113e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz return ret; 18213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz } 18313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 18413e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz return iwm_set_key(iwm, 0, key); 18513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz} 18613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 18713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortizstatic int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, 188e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg u8 key_index, bool pairwise, const u8 *mac_addr, 189e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg void *cookie, 19013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz void (*callback)(void *cookie, 19113e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz struct key_params*)) 19213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz{ 19313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz struct iwm_priv *iwm = ndev_to_iwm(ndev); 194f9a703e173849425079e29e63bf960c2625e0a85Dan Carpenter struct iwm_key *key; 19513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz struct key_params params; 19613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 19713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index); 19813e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 199f9a703e173849425079e29e63bf960c2625e0a85Dan Carpenter if (key_index >= IWM_NUM_KEYS) 200f9a703e173849425079e29e63bf960c2625e0a85Dan Carpenter return -ENOENT; 201f9a703e173849425079e29e63bf960c2625e0a85Dan Carpenter 20213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz memset(¶ms, 0, sizeof(params)); 20313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 204f9a703e173849425079e29e63bf960c2625e0a85Dan Carpenter key = &iwm->keys[key_index]; 20513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz params.cipher = key->cipher; 20613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz params.key_len = key->key_len; 20713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz params.seq_len = key->seq_len; 20813e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz params.seq = key->seq; 20913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz params.key = key->key; 21013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 21113e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz callback(cookie, ¶ms); 21213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 21313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz return key->key_len ? 0 : -ENOENT; 21413e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz} 21513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 21613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 21713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortizstatic int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, 218e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg u8 key_index, bool pairwise, const u8 *mac_addr) 21913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz{ 22013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz struct iwm_priv *iwm = ndev_to_iwm(ndev); 2215a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter struct iwm_key *key; 22213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 2235a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter if (key_index >= IWM_NUM_KEYS) 2245a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter return -ENOENT; 2255a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter 2265a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter key = &iwm->keys[key_index]; 22713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz if (!iwm->keys[key_index].key_len) { 22813e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index); 22913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz return 0; 23013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz } 23113e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 23213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz if (key_index == iwm->default_key) 23313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz iwm->default_key = -1; 23413e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 23513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz return iwm_set_key(iwm, 1, key); 23613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz} 23713e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 23813e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortizstatic int iwm_cfg80211_set_default_key(struct wiphy *wiphy, 23913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz struct net_device *ndev, 240dbd2fd656f2060abfd3a16257f8b51ec60f6d2edJohannes Berg u8 key_index, bool unicast, 241dbd2fd656f2060abfd3a16257f8b51ec60f6d2edJohannes Berg bool multicast) 24213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz{ 24313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz struct iwm_priv *iwm = ndev_to_iwm(ndev); 24413e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 24513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index); 24613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 2475a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter if (key_index >= IWM_NUM_KEYS) 2485a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter return -ENOENT; 2495a5ee76e09b1f5a3a550127aecc2ea4d59f17963Dan Carpenter 25013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz if (!iwm->keys[key_index].key_len) { 25113e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz IWM_ERR(iwm, "Key %d not used\n", key_index); 25213e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz return -EINVAL; 25313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz } 25413e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 2553549716484a95fd16f7fcf8b68699bd4c803b382Samuel Ortiz iwm->default_key = key_index; 2563549716484a95fd16f7fcf8b68699bd4c803b382Samuel Ortiz 2576e5db0a8454b44bf88fa74cf437a507ec08f436dZhu Yi return iwm_set_tx_key(iwm, key_index); 25813e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz} 25913e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 260d041811d931d4f515fd58e222757cbc7d6375db4Samuel Ortizstatic int iwm_cfg80211_get_station(struct wiphy *wiphy, 261d041811d931d4f515fd58e222757cbc7d6375db4Samuel Ortiz struct net_device *ndev, 262d041811d931d4f515fd58e222757cbc7d6375db4Samuel Ortiz u8 *mac, struct station_info *sinfo) 2639967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz{ 2649967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz struct iwm_priv *iwm = ndev_to_iwm(ndev); 2659967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 2669967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (memcmp(mac, iwm->bssid, ETH_ALEN)) 2679967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return -ENOENT; 2689967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 2699967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz sinfo->filled |= STATION_INFO_TX_BITRATE; 2709967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz sinfo->txrate.legacy = iwm->rate * 10; 2719967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 2729967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { 2739967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz sinfo->filled |= STATION_INFO_SIGNAL; 2749967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz sinfo->signal = iwm->wstats.qual.level; 2759967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 2769967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 2779967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return 0; 2789967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz} 2799967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 28013e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz 281bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yiint iwm_cfg80211_inform_bss(struct iwm_priv *iwm) 282bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi{ 283bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct wiphy *wiphy = iwm_to_wiphy(iwm); 28404d1c22761f33ac8f345665e7ef809c875142425Zhu Yi struct iwm_bss_info *bss; 285bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct iwm_umac_notif_bss_info *umac_bss; 286bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct ieee80211_mgmt *mgmt; 287bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct ieee80211_channel *channel; 288bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct ieee80211_supported_band *band; 289bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi s32 signal; 290bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi int freq; 291bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 29204d1c22761f33ac8f345665e7ef809c875142425Zhu Yi list_for_each_entry(bss, &iwm->bss_list, node) { 293bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi umac_bss = bss->bss; 294bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); 295bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 296bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (umac_bss->band == UMAC_BAND_2GHZ) 297bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi band = wiphy->bands[IEEE80211_BAND_2GHZ]; 298bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi else if (umac_bss->band == UMAC_BAND_5GHZ) 299bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi band = wiphy->bands[IEEE80211_BAND_5GHZ]; 300bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi else { 301bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band); 302bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return -EINVAL; 303bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 304bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 30559eb21a6504731fc16db4cf9463065dd61093e08Bruno Randolf freq = ieee80211_channel_to_frequency(umac_bss->channel, 30659eb21a6504731fc16db4cf9463065dd61093e08Bruno Randolf band->band); 307bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi channel = ieee80211_get_channel(wiphy, freq); 308bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi signal = umac_bss->rssi * 100; 309bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 310bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt, 311bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi le16_to_cpu(umac_bss->frame_len), 312bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi signal, GFP_KERNEL)) 313bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return -EINVAL; 314bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 315bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 316bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return 0; 317bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 318bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 319e36d56b64808aec54b68b4e9976180c1da0933b2Johannes Bergstatic int iwm_cfg80211_change_iface(struct wiphy *wiphy, 320e36d56b64808aec54b68b4e9976180c1da0933b2Johannes Berg struct net_device *ndev, 321bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi enum nl80211_iftype type, u32 *flags, 322bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct vif_params *params) 323bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi{ 324bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct wireless_dev *wdev; 325bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct iwm_priv *iwm; 326bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi u32 old_mode; 327bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 328bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wdev = ndev->ieee80211_ptr; 329bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm = ndev_to_iwm(ndev); 330bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi old_mode = iwm->conf.mode; 331bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 332bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi switch (type) { 333bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi case NL80211_IFTYPE_STATION: 334bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->conf.mode = UMAC_MODE_BSS; 335bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi break; 336bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi case NL80211_IFTYPE_ADHOC: 337bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->conf.mode = UMAC_MODE_IBSS; 338bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi break; 339bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi default: 340bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return -EOPNOTSUPP; 341bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 342bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 343bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wdev->iftype = type; 344bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 345bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if ((old_mode == iwm->conf.mode) || !iwm->umac_profile) 346bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return 0; 347bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 348bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode); 349bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 350ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi if (iwm->umac_profile_active) 351ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi iwm_invalidate_mlme_profile(iwm); 352bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 353bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return 0; 354bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 355bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 356bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, 357bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct cfg80211_scan_request *request) 358bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi{ 359bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct iwm_priv *iwm = ndev_to_iwm(ndev); 360bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi int ret; 361bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 362bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (!test_bit(IWM_STATUS_READY, &iwm->status)) { 363bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi IWM_ERR(iwm, "Scan while device is not ready\n"); 364bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return -EIO; 365bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 366bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 367bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) { 368bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi IWM_ERR(iwm, "Scanning already\n"); 369bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return -EAGAIN; 370bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 371bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 372bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) { 373bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi IWM_ERR(iwm, "Scanning being aborted\n"); 374bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return -EAGAIN; 375bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 376bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 377bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi set_bit(IWM_STATUS_SCANNING, &iwm->status); 378bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 379bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids); 380bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (ret) { 381bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi clear_bit(IWM_STATUS_SCANNING, &iwm->status); 382bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return ret; 383bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 384bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 385bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->scan_request = request; 386bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return 0; 387bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 388bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 389bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) 390bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi{ 391bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 392bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 393bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (changed & WIPHY_PARAM_RTS_THRESHOLD && 394bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi (iwm->conf.rts_threshold != wiphy->rts_threshold)) { 395bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi int ret; 396bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 397bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->conf.rts_threshold = wiphy->rts_threshold; 398bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 399bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, 400bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CFG_RTS_THRESHOLD, 401bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->conf.rts_threshold); 402bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (ret < 0) 403bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return ret; 404bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 405bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 406bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (changed & WIPHY_PARAM_FRAG_THRESHOLD && 407bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi (iwm->conf.frag_threshold != wiphy->frag_threshold)) { 408bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi int ret; 409bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 410bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->conf.frag_threshold = wiphy->frag_threshold; 411bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 412b63b0ea2c18bba44c934ec619ba47488553c3aa3Samuel Ortiz ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX, 413bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi CFG_FRAG_THRESHOLD, 414bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->conf.frag_threshold); 415bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (ret < 0) 416bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return ret; 417bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 418bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 419bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return 0; 420bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 421bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 422bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, 423bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct cfg80211_ibss_params *params) 424bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi{ 425bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 426bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct ieee80211_channel *chan = params->channel; 427bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 428bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (!test_bit(IWM_STATUS_READY, &iwm->status)) 429bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return -EIO; 430bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 43103d1a62c1fb10fe00cfc5cb7f4496d8d6d0e7660Zhu Yi /* UMAC doesn't support creating or joining an IBSS network 43203d1a62c1fb10fe00cfc5cb7f4496d8d6d0e7660Zhu Yi * with specified bssid. */ 433bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (params->bssid) 434bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return -EOPNOTSUPP; 435bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 436bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->channel = ieee80211_frequency_to_channel(chan->center_freq); 437bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->umac_profile->ibss.band = chan->band; 438bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->umac_profile->ibss.channel = iwm->channel; 439bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi iwm->umac_profile->ssid.ssid_len = params->ssid_len; 440bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len); 441bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 442bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return iwm_send_mlme_profile(iwm); 443bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 444bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 445bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) 446bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi{ 447bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 448bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 449bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (iwm->umac_profile_active) 450bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return iwm_invalidate_mlme_profile(iwm); 451bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 452bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return 0; 453bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 454bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 4559967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortizstatic int iwm_set_auth_type(struct iwm_priv *iwm, 4569967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz enum nl80211_auth_type sme_auth_type) 4579967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz{ 4589967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz u8 *auth_type = &iwm->umac_profile->sec.auth_type; 4599967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 4609967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz switch (sme_auth_type) { 4619967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz case NL80211_AUTHTYPE_AUTOMATIC: 4629967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz case NL80211_AUTHTYPE_OPEN_SYSTEM: 4639967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n"); 4649967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *auth_type = UMAC_AUTH_TYPE_OPEN; 4659967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz break; 4669967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz case NL80211_AUTHTYPE_SHARED_KEY: 4679967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (iwm->umac_profile->sec.flags & 4689967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { 4699967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n"); 4709967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; 4719967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } else { 4729967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n"); 4739967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; 4749967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 4759967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 4769967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz break; 4779967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz default: 4789967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type); 4799967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return -ENOTSUPP; 4809967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 4819967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 4829967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return 0; 4839967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz} 4849967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 4859967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortizstatic int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) 4869967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz{ 487554503f8c9e11cbea92b7cf1e31f7e4d93ad4492Zhu Yi IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version); 488554503f8c9e11cbea92b7cf1e31f7e4d93ad4492Zhu Yi 4899967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (!wpa_version) { 4909967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; 4919967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return 0; 4929967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 4939967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 4946a79c9f62a87e39a265f9b855911fbc1f094ded0Samuel Ortiz if (wpa_version & NL80211_WPA_VERSION_1) 4956a79c9f62a87e39a265f9b855911fbc1f094ded0Samuel Ortiz iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK; 4966a79c9f62a87e39a265f9b855911fbc1f094ded0Samuel Ortiz 4979967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (wpa_version & NL80211_WPA_VERSION_2) 4989967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; 4999967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5009967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return 0; 5019967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz} 5029967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5039967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortizstatic int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast) 5049967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz{ 5059967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : 5069967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz &iwm->umac_profile->sec.mcast_cipher; 5079967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5089967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (!cipher) { 5099967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *profile_cipher = UMAC_CIPHER_TYPE_NONE; 5109967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return 0; 5119967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 5129967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 513554503f8c9e11cbea92b7cf1e31f7e4d93ad4492Zhu Yi IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm', 514554503f8c9e11cbea92b7cf1e31f7e4d93ad4492Zhu Yi cipher); 515554503f8c9e11cbea92b7cf1e31f7e4d93ad4492Zhu Yi 5169967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz switch (cipher) { 5179967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz case IW_AUTH_CIPHER_NONE: 5189967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *profile_cipher = UMAC_CIPHER_TYPE_NONE; 5199967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz break; 5209967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz case WLAN_CIPHER_SUITE_WEP40: 5219967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; 5229967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz break; 5239967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz case WLAN_CIPHER_SUITE_WEP104: 5249967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; 5259967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz break; 5269967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz case WLAN_CIPHER_SUITE_TKIP: 5279967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *profile_cipher = UMAC_CIPHER_TYPE_TKIP; 5289967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz break; 5299967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz case WLAN_CIPHER_SUITE_CCMP: 5309967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *profile_cipher = UMAC_CIPHER_TYPE_CCMP; 5319967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz break; 5329967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz default: 5339967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); 5349967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return -ENOTSUPP; 5359967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 5369967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5379967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return 0; 5389967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz} 5399967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5409967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortizstatic int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt) 5419967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz{ 5429967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz u8 *auth_type = &iwm->umac_profile->sec.auth_type; 5439967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5449967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); 5459967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5469967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (key_mgt == WLAN_AKM_SUITE_8021X) 5479967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *auth_type = UMAC_AUTH_TYPE_8021X; 5489967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz else if (key_mgt == WLAN_AKM_SUITE_PSK) { 5499967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (iwm->umac_profile->sec.flags & 5509967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) 5519967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; 5529967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz else 5539967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; 5549967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } else { 5559967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); 5569967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return -EINVAL; 5579967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 5589967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5599967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return 0; 5609967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz} 5619967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5629967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5639967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortizstatic int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, 5649967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz struct cfg80211_connect_params *sme) 5659967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz{ 5669967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 5679967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz struct ieee80211_channel *chan = sme->channel; 568b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz struct key_params key_param; 5699967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz int ret; 5709967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5719967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (!test_bit(IWM_STATUS_READY, &iwm->status)) 5729967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return -EIO; 5739967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5749967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (!sme->ssid) 5759967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return -EINVAL; 5769967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 577ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi if (iwm->umac_profile_active) { 578ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi ret = iwm_invalidate_mlme_profile(iwm); 579ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi if (ret) { 580ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi IWM_ERR(iwm, "Couldn't invalidate profile\n"); 581ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi return ret; 582ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi } 583ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi } 584ae73abf2350de7cbfc5c46a936f4d2a532b36679Zhu Yi 5859967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (chan) 5869967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz iwm->channel = 5879967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz ieee80211_frequency_to_channel(chan->center_freq); 5889967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5899967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz iwm->umac_profile->ssid.ssid_len = sme->ssid_len; 5909967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len); 5919967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 5929967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (sme->bssid) { 5939967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid); 5949967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN); 5959967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz iwm->umac_profile->bss_num = 1; 5969967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } else { 5979967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); 5989967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz iwm->umac_profile->bss_num = 0; 5999967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 6009967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 601554503f8c9e11cbea92b7cf1e31f7e4d93ad4492Zhu Yi ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); 6029967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (ret < 0) 6039967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return ret; 6049967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 605554503f8c9e11cbea92b7cf1e31f7e4d93ad4492Zhu Yi ret = iwm_set_auth_type(iwm, sme->auth_type); 6069967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (ret < 0) 6079967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return ret; 6089967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 6099967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (sme->crypto.n_ciphers_pairwise) { 6109967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0], 6119967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz true); 6129967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (ret < 0) 6139967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return ret; 6149967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 6159967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 6169967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false); 6179967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (ret < 0) 6189967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return ret; 6199967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 6209967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (sme->crypto.n_akm_suites) { 6219967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]); 6229967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (ret < 0) 6239967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return ret; 6249967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz } 6259967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 626b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz /* 627b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz * We save the WEP key in case we want to do shared authentication. 628b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz * We have to do it so because UMAC will assert whenever it gets a 629b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz * key before a profile. 630b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz */ 631b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz if (sme->key) { 632b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL); 633b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz if (key_param.key == NULL) 634b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz return -ENOMEM; 635b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz key_param.key_len = sme->key_len; 636b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz key_param.seq_len = 0; 637b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz key_param.cipher = sme->crypto.ciphers_pairwise[0]; 638b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz 639b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx, 640b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz NULL, &key_param); 641b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz kfree(key_param.key); 642b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz if (ret < 0) { 643b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz IWM_ERR(iwm, "Invalid key_params\n"); 644b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz return ret; 645b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz } 646b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz 647b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz iwm->default_key = sme->key_idx; 648b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz } 649b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz 650a82aedbf1b043f7a7474aa9b6d223104ac51827aSamuel Ortiz /* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */ 651a82aedbf1b043f7a7474aa9b6d223104ac51827aSamuel Ortiz if ((iwm->umac_profile->sec.flags & 652a82aedbf1b043f7a7474aa9b6d223104ac51827aSamuel Ortiz (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) && 653a82aedbf1b043f7a7474aa9b6d223104ac51827aSamuel Ortiz iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) { 654a82aedbf1b043f7a7474aa9b6d223104ac51827aSamuel Ortiz iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK; 655a82aedbf1b043f7a7474aa9b6d223104ac51827aSamuel Ortiz } 656a82aedbf1b043f7a7474aa9b6d223104ac51827aSamuel Ortiz 657b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz ret = iwm_send_mlme_profile(iwm); 658b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz 659b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK || 660b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz sme->key == NULL) 661b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz return ret; 662b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz 663b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz /* 664b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz * We want to do shared auth. 665b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz * We need to actually set the key we previously cached, 666b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz * and then tell the UMAC it's the default one. 667b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz * That will trigger the auth+assoc UMAC machinery, and again, 668b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz * this must be done after setting the profile. 669b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz */ 670b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]); 671b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz if (ret < 0) 672b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz return ret; 673b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz 674b90a5c9561d3f75f906a84613cc0071121143fb6Samuel Ortiz return iwm_set_tx_key(iwm, iwm->default_key); 6759967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz} 6769967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 6779967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortizstatic int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, 6789967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz u16 reason_code) 6799967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz{ 6809967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 6819967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 6829967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active); 6839967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 6849967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz if (iwm->umac_profile_active) 685de15fd31fcabb4b81a556736dd67ec4f71462f07Zhu Yi iwm_invalidate_mlme_profile(iwm); 6869967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 6879967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz return 0; 6889967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz} 6899967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz 690257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yistatic int iwm_cfg80211_set_txpower(struct wiphy *wiphy, 691fa61cf70a6ae1089e459e4b59b2e8d8e90d8535eJuuso Oikarinen enum nl80211_tx_power_setting type, int mbm) 692257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi{ 69388e6195a911bce85adcc14e8377aa619e8054ab2Samuel Ortiz struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 69488e6195a911bce85adcc14e8377aa619e8054ab2Samuel Ortiz int ret; 69588e6195a911bce85adcc14e8377aa619e8054ab2Samuel Ortiz 696257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi switch (type) { 697fa61cf70a6ae1089e459e4b59b2e8d8e90d8535eJuuso Oikarinen case NL80211_TX_POWER_AUTOMATIC: 698257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi return 0; 699fa61cf70a6ae1089e459e4b59b2e8d8e90d8535eJuuso Oikarinen case NL80211_TX_POWER_FIXED: 700fa61cf70a6ae1089e459e4b59b2e8d8e90d8535eJuuso Oikarinen if (mbm < 0 || (mbm % 100)) 701fa61cf70a6ae1089e459e4b59b2e8d8e90d8535eJuuso Oikarinen return -EOPNOTSUPP; 702fa61cf70a6ae1089e459e4b59b2e8d8e90d8535eJuuso Oikarinen 703fe19176ea46db572f0dc2df8bfe1dc5d8751ab9eSamuel Ortiz if (!test_bit(IWM_STATUS_READY, &iwm->status)) 704fe19176ea46db572f0dc2df8bfe1dc5d8751ab9eSamuel Ortiz return 0; 705fe19176ea46db572f0dc2df8bfe1dc5d8751ab9eSamuel Ortiz 70688e6195a911bce85adcc14e8377aa619e8054ab2Samuel Ortiz ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, 707fa61cf70a6ae1089e459e4b59b2e8d8e90d8535eJuuso Oikarinen CFG_TX_PWR_LIMIT_USR, 708fa61cf70a6ae1089e459e4b59b2e8d8e90d8535eJuuso Oikarinen MBM_TO_DBM(mbm) * 2); 70988e6195a911bce85adcc14e8377aa619e8054ab2Samuel Ortiz if (ret < 0) 71088e6195a911bce85adcc14e8377aa619e8054ab2Samuel Ortiz return ret; 71188e6195a911bce85adcc14e8377aa619e8054ab2Samuel Ortiz 71288e6195a911bce85adcc14e8377aa619e8054ab2Samuel Ortiz return iwm_tx_power_trigger(iwm); 713257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi default: 714fe19176ea46db572f0dc2df8bfe1dc5d8751ab9eSamuel Ortiz IWM_ERR(iwm, "Unsupported power type: %d\n", type); 715257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi return -EOPNOTSUPP; 716257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi } 717257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi 718257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi return 0; 719257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi} 720257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi 721257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yistatic int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) 722257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi{ 723257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 724257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi 72588e6195a911bce85adcc14e8377aa619e8054ab2Samuel Ortiz *dbm = iwm->txpower >> 1; 726257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi 727257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi return 0; 728257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi} 729257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi 730bc92afd92088ab41223383cc6863ab4792533c54Johannes Bergstatic int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy, 731bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg struct net_device *dev, 732bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg bool enabled, int timeout) 733bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg{ 734bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 735bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg u32 power_index; 736bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg 737bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg if (enabled) 738bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg power_index = IWM_POWER_INDEX_DEFAULT; 739bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg else 740bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg power_index = IWM_POWER_INDEX_MIN; 741bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg 742bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg if (power_index == iwm->conf.power_index) 743bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg return 0; 744bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg 745bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg iwm->conf.power_index = power_index; 746bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg 747bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, 748bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg CFG_POWER_INDEX, iwm->conf.power_index); 749bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg} 750bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg 751d281fd461dcb9b3d0dc46180bf6e90da3913079dZhu Yistatic int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, 752d281fd461dcb9b3d0dc46180bf6e90da3913079dZhu Yi struct net_device *netdev, 753d281fd461dcb9b3d0dc46180bf6e90da3913079dZhu Yi struct cfg80211_pmksa *pmksa) 7549bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz{ 7559bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 7569bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz 7579bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD); 7589bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz} 7599bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz 760d281fd461dcb9b3d0dc46180bf6e90da3913079dZhu Yistatic int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, 761d281fd461dcb9b3d0dc46180bf6e90da3913079dZhu Yi struct net_device *netdev, 762d281fd461dcb9b3d0dc46180bf6e90da3913079dZhu Yi struct cfg80211_pmksa *pmksa) 7639bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz{ 7649bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 7659bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz 7669bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL); 7679bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz} 7689bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz 769d281fd461dcb9b3d0dc46180bf6e90da3913079dZhu Yistatic int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, 770d281fd461dcb9b3d0dc46180bf6e90da3913079dZhu Yi struct net_device *netdev) 7719bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz{ 7729bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 7739bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz struct cfg80211_pmksa pmksa; 7749bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz 7759bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz memset(&pmksa, 0, sizeof(struct cfg80211_pmksa)); 7769bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz 7779bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH); 7789bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz} 7799bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz 7809bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz 781bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistatic struct cfg80211_ops iwm_cfg80211_ops = { 782bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .change_virtual_intf = iwm_cfg80211_change_iface, 78313e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz .add_key = iwm_cfg80211_add_key, 78413e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz .get_key = iwm_cfg80211_get_key, 78513e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz .del_key = iwm_cfg80211_del_key, 78613e0fe70960e95cdea89b71aa3d046ec71efac8cSamuel Ortiz .set_default_key = iwm_cfg80211_set_default_key, 7879967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz .get_station = iwm_cfg80211_get_station, 788bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .scan = iwm_cfg80211_scan, 789bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .set_wiphy_params = iwm_cfg80211_set_wiphy_params, 7909967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz .connect = iwm_cfg80211_connect, 7919967d46aa5ba065650d3352ab5d906f56ba17648Samuel Ortiz .disconnect = iwm_cfg80211_disconnect, 792bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .join_ibss = iwm_cfg80211_join_ibss, 793bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi .leave_ibss = iwm_cfg80211_leave_ibss, 794257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi .set_tx_power = iwm_cfg80211_set_txpower, 795257862f3faef397f1a677ae6a5a1828fa00a97b1Zhu Yi .get_tx_power = iwm_cfg80211_get_txpower, 796bc92afd92088ab41223383cc6863ab4792533c54Johannes Berg .set_power_mgmt = iwm_cfg80211_set_power_mgmt, 7979bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz .set_pmksa = iwm_cfg80211_set_pmksa, 7989bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz .del_pmksa = iwm_cfg80211_del_pmksa, 7999bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz .flush_pmksa = iwm_cfg80211_flush_pmksa, 800bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi}; 801bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 80249b7772776359b8306ce740bfc52d32b344adc83Zhu Yistatic const u32 cipher_suites[] = { 80349b7772776359b8306ce740bfc52d32b344adc83Zhu Yi WLAN_CIPHER_SUITE_WEP40, 80449b7772776359b8306ce740bfc52d32b344adc83Zhu Yi WLAN_CIPHER_SUITE_WEP104, 80549b7772776359b8306ce740bfc52d32b344adc83Zhu Yi WLAN_CIPHER_SUITE_TKIP, 80649b7772776359b8306ce740bfc52d32b344adc83Zhu Yi WLAN_CIPHER_SUITE_CCMP, 80749b7772776359b8306ce740bfc52d32b344adc83Zhu Yi}; 80849b7772776359b8306ce740bfc52d32b344adc83Zhu Yi 809bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yistruct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) 810bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi{ 811bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi int ret = 0; 812bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct wireless_dev *wdev; 813bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 814bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi /* 815bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * We're trying to have the following memory 816bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * layout: 817bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * 818bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * +-------------------------+ 819bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * | struct wiphy | 820bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * +-------------------------+ 821bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * | struct iwm_priv | 822bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * +-------------------------+ 823bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * | bus private data | 824bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * | (e.g. iwm_priv_sdio) | 825bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * +-------------------------+ 826bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi * 827bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi */ 828bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 829bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); 830bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (!wdev) { 831bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi dev_err(dev, "Couldn't allocate wireless device\n"); 832bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return ERR_PTR(-ENOMEM); 833bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 834bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 835bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wdev->wiphy = wiphy_new(&iwm_cfg80211_ops, 836bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi sizeof(struct iwm_priv) + sizeof_bus); 837bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (!wdev->wiphy) { 838bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi dev_err(dev, "Couldn't allocate wiphy device\n"); 839bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi ret = -ENOMEM; 840bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi goto out_err_new; 841bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 842bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 843bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi set_wiphy_dev(wdev->wiphy, dev); 844bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX; 8459bf22f2c4607dbb68beb26153d83fa52b82e2d2fSamuel Ortiz wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS; 846bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 847bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi BIT(NL80211_IFTYPE_ADHOC); 848bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz; 849bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz; 850bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 851bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 85249b7772776359b8306ce740bfc52d32b344adc83Zhu Yi wdev->wiphy->cipher_suites = cipher_suites; 85349b7772776359b8306ce740bfc52d32b344adc83Zhu Yi wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 85449b7772776359b8306ce740bfc52d32b344adc83Zhu Yi 855bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi ret = wiphy_register(wdev->wiphy); 856bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (ret < 0) { 857bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi dev_err(dev, "Couldn't register wiphy device\n"); 858bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi goto out_err_register; 859bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi } 860bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 861bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return wdev; 862bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 863bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi out_err_register: 864bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wiphy_free(wdev->wiphy); 865bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 866bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi out_err_new: 867bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi kfree(wdev); 868bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 869bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return ERR_PTR(ret); 870bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 871bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 872bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yivoid iwm_wdev_free(struct iwm_priv *iwm) 873bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi{ 874bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi struct wireless_dev *wdev = iwm_to_wdev(iwm); 875bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 876bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi if (!wdev) 877bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi return; 878bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi 879bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wiphy_unregister(wdev->wiphy); 880bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi wiphy_free(wdev->wiphy); 881bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi kfree(wdev); 882bb9f8692f5043efef0dcef048cdd1db68299c2cbZhu Yi} 883